Files
JML/src/app/admin/rentals/[id]/page.tsx

1229 lines
59 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { useState, useEffect } from 'react';
import { useParams } from 'next/navigation';
import Link from 'next/link';
import {
ArrowLeft, Bike, User, Calendar, DollarSign, Wallet, Shield, CheckCircle, XCircle,
Clock, Edit, Save, Plus, Trash2, Image, Upload, Lock, Unlock, AlertTriangle, MessageSquare, MapPin,
Phone, MessageCircle, Play, Check, X, FileText, Download
} from 'lucide-react';
import {
canRentalAccept, canRentalReject, canRentalCancel, canRentalEdit,
canRentalImageApprove, canRentalLock, canRentalUnlock
} from '../../../../lib/auth';
type RentalStatus = 'pending' | 'accepted' | 'active' | 'completed' | 'cancelled' | 'locked' | 'disputed';
type RentalType = 'single' | 'shared' | 'rent-to-own';
type PaymentMethod = 'cash' | 'bank' | 'wallet';
type PaymentStatus = 'paid' | 'partial' | 'overdue' | 'unpaid';
type PenaltyLevel = 'none' | 'day1' | 'day2' | 'day3';
interface BikeImage {
id: string;
url: string;
type: 'front' | 'back' | 'left' | 'right' | 'battery';
approved?: boolean;
}
interface Note {
id: string;
text: string;
createdAt: string;
}
interface Rental {
id: string;
bikeId: string;
userId: string;
userName: string;
userPhone: string;
bikeModel: string;
bikePlate: string;
bikeBattery: number;
type: RentalType;
status: RentalStatus;
startDate: string;
endDate?: string;
contractMonths?: number;
subscriptionType: 'daily' | 'weekly' | 'monthly';
deposit: number;
depositPaymentMethod: PaymentMethod;
depositPaid: boolean;
dailyRate: number;
weeklyRate: number;
monthlyRate: number;
totalPaid: number;
dueRental: number;
pendingRent?: number;
pendingRentDays?: number;
paymentStatus: PaymentStatus;
penaltyLevel: PenaltyLevel;
penaltyAmount: number;
lockedAt?: string;
lockedReason?: string;
hubId: string;
hubName: string;
initialImages?: BikeImage[];
imagesApproved: boolean;
bikerNote?: string;
rejectNote?: string;
createdAt: string;
acceptedAt?: string;
activatedAt?: string;
lockHistory?: LockEvent[];
paymentHistory?: PaymentHistory[];
}
interface LockEvent {
id: string;
action: 'locked' | 'unlocked';
reason?: string;
performedBy: string;
performedAt: string;
}
interface PaymentHistory {
id: string;
amount: number;
type: 'daily' | 'weekly' | 'monthly' | 'deposit' | 'penalty';
date: string;
method: 'cash' | 'bank' | 'wallet' | 'bkash' | 'nagad';
status: 'paid' | 'pending' | 'failed';
note?: string;
}
const mockRentals: Rental[] = [
{
id: 'RNT-001',
bikeId: 'BIKE-001',
userId: 'USR-003',
userName: 'Jamal Uddin',
userPhone: '+8801912345678',
bikeModel: 'AIMA Lightning',
bikePlate: 'Dhaka Metro Cha-9012',
bikeBattery: 87,
type: 'single',
status: 'active',
startDate: '2024-01-15',
contractMonths: 12,
subscriptionType: 'monthly',
deposit: 3000,
depositPaymentMethod: 'cash',
depositPaid: true,
dailyRate: 150,
weeklyRate: 900,
monthlyRate: 3500,
totalPaid: 38500,
dueRental: 0,
pendingRent: 0,
pendingRentDays: 0,
paymentStatus: 'paid',
penaltyLevel: 'none',
penaltyAmount: 0,
hubId: 'HUB-001',
hubName: 'Gulshan Hub',
imagesApproved: true,
initialImages: [
{ id: 'img1', type: 'front', url: 'https://picsum.photos/seed/bike-front/400/300', approved: true },
{ id: 'img2', type: 'back', url: 'https://picsum.photos/seed/bike-back/400/300', approved: true },
{ id: 'img3', type: 'left', url: 'https://picsum.photos/seed/bike-left/400/300', approved: true },
{ id: 'img4', type: 'right', url: 'https://picsum.photos/seed/bike-right/400/300', approved: true },
{ id: 'img5', type: 'battery', url: 'https://picsum.photos/seed/bike-battery/400/300', approved: true },
],
createdAt: '2024-01-15',
acceptedAt: '2024-01-15',
activatedAt: '2024-01-16',
paymentHistory: [
{ id: 'PAY-001', amount: 3000, type: 'deposit', date: '2024-01-15', method: 'bkash', status: 'paid', note: 'Deposit payment' },
{ id: 'PAY-002', amount: 12000, type: 'monthly', date: '2024-02-15', method: 'bank', status: 'paid', note: 'February rent' },
{ id: 'PAY-003', amount: 12000, type: 'monthly', date: '2024-03-15', method: 'bank', status: 'paid', note: 'March rent' },
{ id: 'PAY-004', amount: 12000, type: 'monthly', date: '2024-04-15', method: 'bank', status: 'pending', note: 'April rent - pending' },
],
lockHistory: [
{ id: 'lh1', action: 'locked', reason: 'First payment overdue - Day 1 penalty', performedBy: 'System', performedAt: '2024-02-01' },
{ id: 'lh2', action: 'unlocked', reason: 'Payment received', performedBy: 'Admin Manager', performedAt: '2024-02-03' },
{ id: 'lh3', action: 'locked', reason: 'Second payment overdue - Day 2 penalty', performedBy: 'System', performedAt: '2024-03-01' },
{ id: 'lh4', action: 'unlocked', reason: 'Payment cleared', performedBy: 'Admin Manager', performedAt: '2024-03-02' },
],
},
{
id: 'RNT-002',
bikeId: 'BIKE-002',
userId: 'USR-002',
userName: 'Karim Hasan',
userPhone: '+8801812345678',
bikeModel: 'Yadea DT3',
bikePlate: 'Dhaka Metro Ba-5521',
bikeBattery: 65,
type: 'single',
status: 'pending',
startDate: '2024-02-10',
contractMonths: 3,
subscriptionType: 'monthly',
deposit: 3000,
depositPaymentMethod: 'bank',
depositPaid: true,
dailyRate: 150,
weeklyRate: 900,
monthlyRate: 3500,
totalPaid: 3000,
dueRental: 3500,
pendingRent: 3500,
pendingRentDays: 5,
paymentStatus: 'partial',
penaltyLevel: 'none',
penaltyAmount: 0,
hubId: 'HUB-002',
hubName: 'Banani Hub',
imagesApproved: false,
initialImages: [
{ id: 'img1', type: 'front', url: '', approved: false },
{ id: 'img2', type: 'back', url: '', approved: false },
{ id: 'img3', type: 'left', url: '', approved: false },
{ id: 'img4', type: 'right', url: '', approved: false },
{ id: 'img5', type: 'battery', url: '', approved: false },
],
createdAt: '2024-02-10',
},
{
id: 'RNT-003',
bikeId: 'BIKE-003',
userId: 'USR-001',
userName: 'Rahim Ahmed',
userPhone: '+8801712345678',
bikeModel: 'AIMA EM5',
bikePlate: 'Dhaka Metro Ko-1234',
bikeBattery: 92,
type: 'rent-to-own',
status: 'completed',
startDate: '2023-06-01',
endDate: '2023-12-01',
contractMonths: 6,
subscriptionType: 'monthly',
deposit: 10000,
depositPaymentMethod: 'wallet',
depositPaid: true,
dailyRate: 500,
weeklyRate: 3000,
monthlyRate: 12000,
totalPaid: 82000,
dueRental: 0,
pendingRent: 0,
pendingRentDays: 0,
paymentStatus: 'paid',
penaltyLevel: 'none',
penaltyAmount: 0,
hubId: 'HUB-001',
hubName: 'Gulshan Hub',
imagesApproved: true,
createdAt: '2023-06-01',
acceptedAt: '2023-06-01',
activatedAt: '2023-06-02',
},
{
id: 'RNT-004',
bikeId: 'BIKE-005',
userId: 'USR-005',
userName: 'Farid Ahmed',
userPhone: '+8801612345678',
bikeModel: 'Yadea G5',
bikePlate: 'Dhaka Metro Ha-5678',
bikeBattery: 45,
type: 'shared',
status: 'locked',
startDate: '2024-01-20',
contractMonths: 1,
subscriptionType: 'weekly',
deposit: 2000,
depositPaymentMethod: 'cash',
depositPaid: true,
dailyRate: 100,
weeklyRate: 600,
monthlyRate: 2200,
totalPaid: 2600,
dueRental: 600,
pendingRent: 600,
pendingRentDays: 3,
paymentStatus: 'overdue',
penaltyLevel: 'day3',
penaltyAmount: 1000,
lockedAt: '2024-02-05',
lockedReason: 'Payment overdue - bike locked',
hubId: 'HUB-003',
hubName: 'Uttara Hub',
imagesApproved: true,
createdAt: '2024-01-20',
acceptedAt: '2024-01-20',
activatedAt: '2024-01-21',
lockHistory: [
{ id: 'lh1', action: 'locked', reason: 'Weekly payment overdue', performedBy: 'System', performedAt: '2024-02-05' },
],
},
];
const mockHubs = [
{ id: 'HUB-001', name: 'Gulshan Hub' },
{ id: 'HUB-002', name: 'Banani Hub' },
{ id: 'HUB-003', name: 'Uttara Hub' },
{ id: 'HUB-004', name: 'Mirpur Hub' },
];
const mockDamageHistory = [
{ id: 'DMG-001', date: '2024-02-10', description: 'Minor scratch on left mirror', severity: 'minor', status: 'resolved' },
{ id: 'DMG-002', date: '2024-03-05', description: 'Front fender dented', severity: 'moderate', status: 'reported' },
{ id: 'DMG-003', date: '2024-03-15', description: 'Rear tire puncture', severity: 'minor', status: 'resolved' },
];
const mockDocuments = [
{ id: 'DOC-001', name: 'Rental Agreement', type: 'agreement', uploadedAt: '2024-01-15', downloaded: true },
{ id: 'DOC-002', name: 'Bike Delivery Form', type: 'form', uploadedAt: '2024-01-16', downloaded: true },
{ id: 'DOC-003', name: 'KYC Documents', type: 'kyc', uploadedAt: '2024-01-14', downloaded: true },
{ id: 'DOC-004', name: 'Insurance Policy', type: 'insurance', uploadedAt: '2024-01-15', downloaded: false },
];
const mockMessages = [
{ id: 'MSG-001', date: '2024-03-15', text: 'Payment reminder sent', type: 'system' },
{ id: 'MSG-002', date: '2024-03-10', text: 'Bike inspection scheduled', type: 'system' },
{ id: 'MSG-003', date: '2024-02-20', text: 'User requested repair', type: 'user' },
];
export default function RentalDetailPage() {
const params = useParams();
const id = params.id as string;
const [rental, setRental] = useState<Rental | null>(null);
const [editMode, setEditMode] = useState(false);
const [notes, setNotes] = useState<Note[]>([
{ id: 'n1', text: 'Rental started successfully. Bike in good condition.', createdAt: '2024-01-15' },
{ id: 'n2', text: 'First monthly payment received.', createdAt: '2024-02-15' },
]);
const [newNote, setNewNote] = useState('');
const [paymentPage, setPaymentPage] = useState(0);
const [editForm, setEditForm] = useState<Partial<Rental>>({});
const [showLockModal, setShowLockModal] = useState(false);
const [showUnlockModal, setShowUnlockModal] = useState(false);
const [showCancelModal, setShowCancelModal] = useState(false);
const [lockReason, setLockReason] = useState('');
const [rejectNote, setRejectNote] = useState('');
const [showRejectModal, setShowRejectModal] = useState(false);
const [showDamageModal, setShowDamageModal] = useState(false);
const [showSmsModal, setShowSmsModal] = useState(false);
const [damageDesc, setDamageDesc] = useState('');
const [damageSeverity, setDamageSeverity] = useState<'minor' | 'moderate' | 'severe'>('minor');
const [smsText, setSmsText] = useState('');
const [damages, setDamages] = useState(mockDamageHistory);
const [documents, setDocuments] = useState(mockDocuments);
const [showUploadModal, setShowUploadModal] = useState(false);
const [uploadDocName, setUploadDocName] = useState('');
const [acceptPermission, setAcceptPermission] = useState(false);
const [rejectPermission, setRejectPermission] = useState(false);
const [cancelPermission, setCancelPermission] = useState(false);
const [editPermission, setEditPermission] = useState(false);
const [imageApprovePermission, setImageApprovePermission] = useState(false);
const [lockPermission, setLockPermission] = useState(false);
const [unlockPermission, setUnlockPermission] = useState(false);
useEffect(() => {
setAcceptPermission(canRentalAccept());
setRejectPermission(canRentalReject());
setCancelPermission(canRentalCancel());
setEditPermission(canRentalEdit());
setImageApprovePermission(canRentalImageApprove());
setLockPermission(canRentalLock());
setUnlockPermission(canRentalUnlock());
}, []);
useEffect(() => {
const found = mockRentals.find(r => r.id === id);
if (found) {
setRental(found);
setEditForm(found);
}
}, [id]);
if (!rental) {
return (
<div className="p-6 flex items-center justify-center min-h-[50vh]">
<div className="text-center">
<Bike className="w-16 h-16 text-slate-300 mx-auto mb-4" />
<p className="text-slate-500">Rental not found</p>
<Link href="/admin/rentals" className="mt-4 px-4 py-2 bg-emerald-600 text-white rounded-lg text-sm inline-block">
Back to Rentals
</Link>
</div>
</div>
);
}
const getStatusBadge = (status: RentalStatus) => {
const styles: Record<RentalStatus, string> = {
active: 'bg-green-100 text-green-700',
pending: 'bg-amber-100 text-amber-700',
accepted: 'bg-blue-100 text-blue-700',
completed: 'bg-indigo-100 text-indigo-700',
cancelled: 'bg-slate-100 text-slate-600',
locked: 'bg-red-100 text-red-700',
disputed: 'bg-orange-100 text-orange-700',
};
const labels: Record<RentalStatus, string> = {
active: 'Active',
pending: 'Pending',
accepted: 'Accepted',
completed: 'Completed',
cancelled: 'Cancelled',
locked: 'Locked',
disputed: 'Disputed',
};
return { style: styles[status], label: labels[status] || status };
};
const getTypeBadge = (type: RentalType) => {
const styles: Record<RentalType, string> = {
single: 'bg-blue-100 text-blue-700',
shared: 'bg-purple-100 text-purple-700',
'rent-to-own': 'bg-emerald-100 text-emerald-700',
};
const labels: Record<RentalType, string> = {
single: 'Single Rent',
shared: 'Share EV',
'rent-to-own': 'Rent to Own',
};
return { style: styles[type], label: labels[type] || type };
};
const getPaymentStatusBadge = (status: PaymentStatus) => {
const styles: Record<PaymentStatus, string> = {
paid: 'bg-green-100 text-green-700',
partial: 'bg-amber-100 text-amber-700',
overdue: 'bg-red-100 text-red-700',
unpaid: 'bg-slate-100 text-slate-600',
};
const labels: Record<PaymentStatus, string> = {
paid: 'Paid',
partial: 'Partial',
overdue: 'Overdue',
unpaid: 'Unpaid',
};
return { style: styles[status], label: labels[status] || status };
};
const getPenaltyBadge = (level: PenaltyLevel) => {
const styles: Record<PenaltyLevel, string> = {
none: 'bg-slate-100 text-slate-500',
day1: 'bg-amber-100 text-amber-700',
day2: 'bg-orange-100 text-orange-700',
day3: 'bg-red-100 text-red-700',
};
const labels: Record<PenaltyLevel, string> = {
none: 'None',
day1: '1st Day',
day2: '2nd Day',
day3: 'Bike Lock',
};
return { style: styles[level], label: labels[level] || level };
};
const handleSaveEdit = () => {
setRental(prev => prev ? { ...prev, ...editForm } : null);
setEditMode(false);
};
const handleLockRental = () => {
if (!lockReason.trim()) return;
const newEvent: LockEvent = { id: `lh${Date.now()}`, action: 'locked', reason: lockReason, performedBy: 'Admin', performedAt: new Date().toISOString().split('T')[0] };
setRental(prev => prev ? { ...prev, status: 'locked', lockedAt: new Date().toISOString().split('T')[0], lockedReason: lockReason, lockHistory: [...(prev.lockHistory || []), newEvent] } : null);
setShowLockModal(false);
setLockReason('');
};
const handleUnlockRental = () => {
const newEvent: LockEvent = { id: `lh${Date.now()}`, action: 'unlocked', performedBy: 'Admin', performedAt: new Date().toISOString().split('T')[0] };
setRental(prev => prev ? { ...prev, status: 'active', lockedAt: undefined, lockedReason: undefined, lockHistory: [...(prev.lockHistory || []), newEvent] } : null);
setShowUnlockModal(false);
};
const handleCancelRental = () => {
setRental(prev => prev ? { ...prev, status: 'cancelled', endDate: new Date().toISOString().split('T')[0] } : null);
setShowCancelModal(false);
};
const handleAcceptRental = () => {
setRental(prev => prev ? { ...prev, status: 'accepted', acceptedAt: new Date().toISOString().split('T')[0] } : null);
};
const handleRejectRental = () => {
if (!rejectNote.trim()) return;
setRental(prev => prev ? { ...prev, status: 'cancelled', rejectNote } : null);
setShowRejectModal(false);
setRejectNote('');
};
const handleApproveImages = () => {
setRental(prev => prev ? { ...prev, imagesApproved: true } : null);
};
const handleActivateRental = () => {
setRental(prev => prev ? { ...prev, status: 'active', activatedAt: new Date().toISOString().split('T')[0] } : null);
};
const handleAddNote = () => {
if (!newNote.trim()) return;
setNotes(prev => [...prev, { id: `n${Date.now()}`, text: newNote, createdAt: new Date().toISOString().split('T')[0] }]);
setNewNote('');
};
const handleReportDamage = () => {
if (!damageDesc.trim()) return;
setDamages(prev => [...prev, { id: `DMG-${Date.now()}`, date: new Date().toISOString().split('T')[0], description: damageDesc, severity: damageSeverity, status: 'reported' }]);
setDamageDesc('');
setDamageSeverity('minor');
setShowDamageModal(false);
};
const handleUploadDocument = () => {
if (!uploadDocName.trim()) return;
setDocuments(prev => [...prev, { id: `DOC-${Date.now()}`, name: uploadDocName, type: 'other', uploadedAt: new Date().toISOString().split('T')[0], downloaded: false }]);
setUploadDocName('');
setShowUploadModal(false);
};
const handleSendSms = () => {
if (!smsText.trim()) return;
alert(`SMS sent to ${rental.userPhone}: ${smsText}`);
setSmsText('');
setShowSmsModal(false);
};
const statusBadge = getStatusBadge(rental.status);
const typeBadge = getTypeBadge(rental.type);
const paymentBadge = getPaymentStatusBadge(rental.paymentStatus);
const penaltyBadge = getPenaltyBadge(rental.penaltyLevel);
const getBatteryColor = (level: number) => {
if (level > 70) return 'text-green-600';
if (level > 40) return 'text-amber-600';
return 'text-red-600';
};
const timelineSteps = [
{ key: 'created', label: 'Created', date: rental.createdAt, completed: true },
{ key: 'accepted', label: 'Accepted', date: rental.acceptedAt, completed: !!rental.acceptedAt },
{ key: 'imagesApproved', label: 'Images Approved', date: rental.imagesApproved ? rental.acceptedAt : undefined, completed: rental.imagesApproved },
{ key: 'activated', label: 'Activated', date: rental.activatedAt, completed: !!rental.activatedAt },
];
return (
<div className="p-4 lg:p-6 max-w-8xl mx-auto">
<Link href="/admin/rentals" className="flex items-center gap-2 text-slate-600 hover:text-slate-800 mb-4">
<ArrowLeft className="w-4 h-4" /> Back to Rentals
</Link>
<div className="bg-white rounded-xl shadow-sm border border-slate-100 overflow-hidden">
<div className="p-6 bg-gradient-to-r from-emerald-600 to-emerald-700 text-white">
<div className="flex flex-col lg:flex-row lg:items-start lg:justify-between gap-4">
<div>
<div className="flex items-center gap-3 flex-wrap">
<h1 className="text-2xl font-extrabold">{rental.id}</h1>
<span className={`inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full ${statusBadge.style}`}>
{statusBadge.label}
</span>
<span className={`inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full ${typeBadge.style}`}>
{typeBadge.label}
</span>
</div>
<p className="text-emerald-100 mt-1">Created: {rental.createdAt}</p>
</div>
<div className="flex gap-2 flex-wrap">
{editMode ? (
<>
<button onClick={handleSaveEdit} className="px-4 py-2 bg-white text-emerald-700 rounded-lg text-sm hover:bg-emerald-50 flex items-center gap-2">
<Save className="w-4 h-4" /> Save
</button>
<button onClick={() => { setEditForm(rental); setEditMode(false); }} className="px-4 py-2 border border-white/30 text-white rounded-lg text-sm hover:bg-white/10">
Cancel
</button>
</>
) : (
<>
{/* {editPermission && (
<button onClick={() => setEditMode(true)} className="px-4 py-2 bg-white text-emerald-700 rounded-lg text-sm hover:bg-emerald-50 flex items-center gap-2">
<Edit className="w-4 h-4" /> Edit
</button>
)} */}
{cancelPermission && rental.status !== 'cancelled' && rental.status !== 'completed' && (
<button onClick={() => setShowCancelModal(true)} className="px-4 py-2 bg-red-500 text-white rounded-lg text-sm hover:bg-red-600 flex items-center gap-2">
<XCircle className="w-4 h-4" /> Cancel
</button>
)}
{lockPermission && rental.status === 'active' && (
<button onClick={() => setShowLockModal(true)} className="px-4 py-2 bg-red-600 text-white rounded-lg text-sm hover:bg-red-700 flex items-center gap-2">
<Lock className="w-4 h-4" /> Lock
</button>
)}
{unlockPermission && rental.status === 'locked' && (
<button onClick={() => setShowUnlockModal(true)} className="px-4 py-2 bg-green-500 text-white rounded-lg text-sm hover:bg-green-600 flex items-center gap-2">
<Unlock className="w-4 h-4" /> Unlock
</button>
)}
{rental.status === 'accepted' && (
<button onClick={handleActivateRental} className="px-4 py-2 bg-blue-500 text-white rounded-lg text-sm hover:bg-blue-600 flex items-center gap-2">
<Play className="w-4 h-4" /> Activate
</button>
)}
</>
)}
</div>
</div>
</div>
<div className="p-6 grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2 space-y-6">
<div className="grid grid-cols-2 lg:grid-cols-3 gap-4">
<div className="bg-blue-50 p-4 rounded-xl border border-blue-100">
<p className="text-sm text-blue-600 font-medium">Total Paid</p>
<p className="text-xl font-bold text-blue-800">{rental.totalPaid.toLocaleString()}</p>
</div>
<div className="bg-amber-50 p-4 rounded-xl border border-amber-100">
<p className="text-sm text-amber-600 font-medium">Due Rental</p>
<p className="text-xl font-bold text-amber-800">{rental.dueRental.toLocaleString()}</p>
</div>
<div className="bg-purple-50 p-4 rounded-xl border border-purple-100">
<p className="text-sm text-purple-600 font-medium">Payment Status</p>
<span className={`inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full ${paymentBadge.style}`}>
{paymentBadge.label}
</span>
</div>
</div>
{rental.penaltyLevel !== 'none' && (
<div className="bg-red-50 p-4 rounded-xl border border-red-100">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-red-600 font-medium">Penalty</p>
<p className="text-lg font-bold text-red-800">{rental.penaltyAmount.toLocaleString()}</p>
</div>
<span className={`inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full ${penaltyBadge.style}`}>
{penaltyBadge.label}
</span>
</div>
</div>
)}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="bg-white p-4 rounded-xl border border-slate-200">
<h3 className="font-semibold text-slate-700 mb-3 flex items-center gap-2">
<Bike className="w-5 h-5 text-blue-500" /> Bike Info
</h3>
<div className="space-y-2">
{editMode ? (
<input
type="text"
value={editForm.bikeModel || ''}
onChange={(e) => setEditForm({ ...editForm, bikeModel: e.target.value })}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
placeholder="Bike Model"
/>
) : (
<div className="flex justify-between"><span className="text-sm text-slate-600">Model</span><span className="text-sm font-medium text-slate-800">{rental.bikeModel}</span></div>
)}
<div className="flex justify-between"><span className="text-sm text-slate-600">Plate</span><span className="text-sm font-medium text-slate-800">{rental.bikePlate}</span></div>
<div className="flex justify-between">
<span className="text-sm text-slate-600">Battery</span>
<span className={`text-sm font-medium ${getBatteryColor(rental.bikeBattery)}`}>{rental.bikeBattery}%</span>
</div>
</div>
</div>
<div className="bg-white p-4 rounded-xl border border-slate-200">
<h3 className="font-semibold text-slate-700 mb-3 flex items-center gap-2">
<User className="w-5 h-5 text-green-500" /> User Info
</h3>
<div className="space-y-2">
<div className="flex justify-between"><span className="text-sm text-slate-600">Name</span><span className="text-sm font-medium text-slate-800">{rental.userName}</span></div>
<div className="flex justify-between items-center"><span className="text-sm text-slate-600">Phone</span><a href={`tel:${rental.userPhone}`} className="text-sm font-medium text-emerald-600 hover:text-emerald-700">{rental.userPhone}</a></div>
<div className="flex gap-2 mt-2 pt-2 border-t border-slate-100">
<a href={`tel:${rental.userPhone}`} className="flex-1 py-1.5 bg-green-500 text-white rounded-lg text-xs text-center hover:bg-green-600 flex items-center justify-center gap-1">
<Phone className="w-3 h-3" /> Call
</a>
<a href={`sms:${rental.userPhone}`} className="flex-1 py-1.5 bg-blue-500 text-white rounded-lg text-xs text-center hover:bg-blue-600 flex items-center justify-center gap-1">
<MessageCircle className="w-3 h-3" /> SMS
</a>
<button onClick={() => setShowSmsModal(true)} className="flex-1 py-1.5 bg-indigo-500 text-white rounded-lg text-xs text-center hover:bg-indigo-600 flex items-center justify-center gap-1">
<MessageSquare className="w-3 h-3" /> In-App SMS
</button>
</div>
</div>
</div>
<div className="bg-white p-4 rounded-xl border border-slate-200">
<h3 className="font-semibold text-slate-700 mb-3 flex items-center gap-2">
<MapPin className="w-5 h-5 text-purple-500" /> Hub Info
</h3>
<div className="space-y-2">
<div className="flex justify-between"><span className="text-sm text-slate-600">Hub</span><span className="text-sm font-medium text-slate-800">{rental.hubName}</span></div>
</div>
</div>
<div className="bg-white p-4 rounded-xl border border-slate-200">
<h3 className="font-semibold text-slate-700 mb-3 flex items-center gap-2">
<Calendar className="w-5 h-5 text-amber-500" /> Duration
</h3>
<div className="space-y-2">
<div className="flex justify-between"><span className="text-sm text-slate-600">Start Date</span><span className="text-sm font-medium text-slate-800">{rental.startDate}</span></div>
{rental.endDate && <div className="flex justify-between"><span className="text-sm text-slate-600">End Date</span><span className="text-sm font-medium text-slate-800">{rental.endDate}</span></div>}
{rental.contractMonths && <div className="flex justify-between"><span className="text-sm text-slate-600">Contract</span><span className="text-sm font-medium text-slate-800">{rental.contractMonths} Months</span></div>}
</div>
</div>
<div className="bg-white p-4 rounded-xl border border-slate-200">
<h3 className="font-semibold text-slate-700 mb-3 flex items-center gap-2">
<Clock className="w-5 h-5 text-indigo-500" /> Subscription
</h3>
<div className="space-y-2">
<div className="flex justify-between"><span className="text-sm text-slate-600">Type</span><span className="text-sm font-medium text-slate-800 capitalize">{rental.subscriptionType}</span></div>
<div className="flex justify-between">
<span className="text-sm text-slate-600">Rate</span>
<span className="text-sm font-medium text-slate-800">
{rental.subscriptionType === 'daily' ? rental.dailyRate : rental.subscriptionType === 'weekly' ? rental.weeklyRate : rental.monthlyRate}/
{rental.subscriptionType === 'daily' ? 'day' : rental.subscriptionType === 'weekly' ? 'week' : 'month'}
</span>
</div>
</div>
</div>
<div className="bg-white p-4 rounded-xl border border-slate-200">
<h3 className="font-semibold text-slate-700 mb-3 flex items-center gap-2">
<Wallet className="w-5 h-5 text-emerald-500" /> Deposit
</h3>
<div className="space-y-2">
<div className="flex justify-between"><span className="text-sm text-slate-600">Amount</span><span className="text-sm font-medium text-slate-800">{rental.deposit.toLocaleString()}</span></div>
<div className="flex justify-between"><span className="text-sm text-slate-600">Method</span><span className="text-sm font-medium text-slate-800 capitalize">{rental.depositPaymentMethod}</span></div>
<div className="flex justify-between">
<span className="text-sm text-slate-600">Status</span>
<span className={`text-xs px-2 py-0.5 rounded ${rental.depositPaid ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'}`}>
{rental.depositPaid ? 'Paid' : 'Unpaid'}
</span>
</div>
</div>
</div>
</div>
{/* Initial Condition Images */}
{/* {(rental.status === 'pending' || rental.status === 'accepted') && rental.initialImages && ( */}
{rental.initialImages && (
<div className="bg-white p-4 rounded-xl border border-slate-200">
<div className="flex items-center justify-between mb-4">
<h3 className="font-semibold text-slate-700 flex items-center gap-2">
<Image className="w-5 h-5 text-purple-500" /> Initial Condition Images
</h3>
{imageApprovePermission && !rental.imagesApproved && (
<button onClick={handleApproveImages} className="px-3 py-1.5 bg-emerald-600 text-white rounded-lg text-sm hover:bg-emerald-700 flex items-center gap-2">
<Check className="w-4 h-4" /> Approve Images
</button>
)}
{rental.imagesApproved && (
<span className="inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full bg-green-100 text-green-700">
<CheckCircle className="w-3 h-3" /> Approved
</span>
)}
</div>
<div className="grid grid-cols-2 sm:grid-cols-5 gap-2">
{(['front', 'back', 'left', 'right', 'battery'] as const).map(type => {
const img = rental.initialImages?.find(i => i.type === type);
return (
<div key={type} className="aspect-video bg-slate-50 rounded-lg border border-slate-200 flex items-center justify-center overflow-hidden">
{img?.url ? (
<img src={img.url} alt={type} className="w-full h-full object-cover" />
) : (
<div className="text-center p-2">
<Image className="w-6 h-6 text-slate-300 mx-auto" />
<p className="text-xs text-slate-500 capitalize mt-1">{type}</p>
</div>
)}
</div>
);
})}
</div>
</div>
)}
{/* Notes */}
<div className="bg-slate-50 p-4 rounded-xl border border-slate-100">
<h3 className="font-semibold text-slate-700 mb-3 flex items-center gap-2">
<MessageSquare className="w-5 h-5" /> Notes ({notes.length})
</h3>
{notes.length > 0 ? (
<div className="space-y-2 mb-3">
{notes.map(note => (
<div key={note.id} className="bg-white p-3 rounded-lg">
<p className="text-sm text-slate-700">{note.text}</p>
<p className="text-xs text-slate-400 mt-1">{note.createdAt}</p>
</div>
))}
</div>
) : (
<p className="text-sm text-slate-500 mb-3">No notes yet.</p>
)}
<div className="flex gap-2">
<input
type="text"
value={newNote}
onChange={(e) => setNewNote(e.target.value)}
placeholder="Add a note..."
className="flex-1 px-3 py-2 border border-slate-200 rounded-lg text-sm"
/>
<button onClick={handleAddNote} disabled={!newNote.trim()} className="px-4 py-2 bg-emerald-600 text-white rounded-lg text-sm disabled:opacity-50">
<Plus className="w-4 h-4" />
</button>
</div>
</div>
{/* Rental Payment History */}
{rental.paymentHistory && rental.paymentHistory.length > 0 && (
<div className="bg-white p-4 rounded-xl border border-slate-200">
<div className="flex items-center justify-between mb-4">
<h3 className="font-semibold text-slate-700 flex items-center gap-2">
<DollarSign className="w-5 h-5 text-emerald-500" /> Rental Payment History
</h3>
<span className="text-xs text-slate-500">{rental.paymentHistory.length} payments</span>
</div>
<div className="space-y-3">
{rental.paymentHistory.slice(paymentPage, paymentPage + 10).map(payment => (
<div key={payment.id} className="p-3 bg-slate-50 rounded-lg border border-slate-100">
<div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-2">
<span className={`text-xs font-semibold px-2 py-1 rounded-full ${payment.type === 'deposit' ? 'bg-purple-100 text-purple-700' : payment.type === 'penalty' ? 'bg-red-100 text-red-700' : 'bg-emerald-100 text-emerald-700'}`}>
{payment.type.charAt(0).toUpperCase() + payment.type.slice(1)}
</span>
<span className={`text-xs font-medium px-2 py-1 rounded-full ${payment.status === 'paid' ? 'bg-green-100 text-green-700' : payment.status === 'pending' ? 'bg-amber-100 text-amber-700' : 'bg-red-100 text-red-700'}`}>
{payment.status.charAt(0).toUpperCase() + payment.status.slice(1)}
</span>
</div>
<span className="text-lg font-bold text-slate-800">{payment.amount.toLocaleString()}</span>
</div>
<div className="flex items-center gap-4 text-xs text-slate-500">
<span>{payment.date}</span>
<span className="capitalize">{payment.method}</span>
</div>
{payment.note && <p className="text-xs text-slate-500 mt-1">{payment.note}</p>}
</div>
))}
</div>
{rental.paymentHistory.length > 1 && (
<div className="flex items-center justify-between mt-4 pt-3 border-t border-slate-100">
<button
onClick={() => setPaymentPage(p => Math.max(0, p - 1))}
disabled={paymentPage === 0}
className="px-3 py-1.5 text-sm border border-slate-200 rounded-lg disabled:opacity-40 hover:bg-slate-50"
>
Prev
</button>
<span className="text-sm text-slate-500">
Showing {paymentPage + 1}-{Math.min(paymentPage + 10, rental.paymentHistory.length)} of {rental.paymentHistory.length}
</span>
<button
onClick={() => setPaymentPage(p => Math.min(Math.ceil((rental.paymentHistory?.length ?? 1) / 10) * 10 - 10, p + 10))}
disabled={paymentPage + 10 >= (rental.paymentHistory?.length ?? 1)}
className="px-3 py-1.5 text-sm border border-slate-200 rounded-lg disabled:opacity-40 hover:bg-slate-50"
>
Next
</button>
</div>
)}
</div>
)}
</div>
<div className="space-y-4">
{rental.status === 'locked' && (
<div className="bg-red-50 p-4 rounded-xl border border-red-100">
<h3 className="font-semibold text-red-800 mb-3 flex items-center gap-2">
<Lock className="w-5 h-5" /> Locked Info
</h3>
<div className="space-y-2">
<div className="flex justify-between"><span className="text-sm text-red-600">Locked At</span><span className="text-sm font-medium text-red-800">{rental.lockedAt}</span></div>
<div className="flex justify-between"><span className="text-sm text-red-600">Reason</span><span className="text-sm font-medium text-red-800">{rental.lockedReason}</span></div>
</div>
</div>
)}
<div className="bg-white p-4 rounded-xl border border-slate-200">
<h3 className="font-semibold text-slate-700 mb-4 flex items-center gap-2">
<Lock className="w-5 h-5 text-red-500" /> Lock History
</h3>
{rental.lockHistory && rental.lockHistory.length > 0 ? (
<div className="space-y-2">
{rental.lockHistory.map(event => (
<div key={event.id} className="flex items-start gap-3 p-3 bg-slate-50 rounded-lg">
<div className={`p-1.5 rounded-full ${event.action === 'locked' ? 'bg-red-100' : 'bg-green-100'}`}>
{event.action === 'locked' ? (
<Lock className="w-4 h-4 text-red-600" />
) : (
<Unlock className="w-4 h-4 text-green-600" />
)}
</div>
<div className="flex-1">
<div className="flex items-center gap-2">
<span className={`text-xs font-medium px-2 py-0.5 rounded-full ${event.action === 'locked' ? 'bg-red-100 text-red-700' : 'bg-green-100 text-green-700'}`}>
{event.action === 'locked' ? 'Locked' : 'Unlocked'}
</span>
<span className="text-xs text-slate-400">{event.performedAt}</span>
</div>
{event.reason && (
<p className="text-sm text-slate-600 mt-1">{event.reason}</p>
)}
<p className="text-xs text-slate-400 mt-1">By: {event.performedBy}</p>
</div>
</div>
))}
</div>
) : (
<p className="text-sm text-slate-400 text-center py-4">No lock history available.</p>
)}
</div>
<div className="bg-white p-4 rounded-xl border border-slate-200">
<div className="flex items-center justify-between mb-4">
<h3 className="font-semibold text-slate-700 flex items-center gap-2">
<AlertTriangle className="w-5 h-5 text-red-500" /> Damage History
</h3>
<button onClick={() => setShowDamageModal(true)} className="px-3 py-1.5 bg-red-500 text-white rounded-lg text-sm hover:bg-red-600 flex items-center gap-2">
<Plus className="w-4 h-4" /> Report Damage
</button>
</div>
<div className="space-y-2">
{damages.map(damage => (
<div key={damage.id} className="p-3 bg-slate-50 rounded-lg flex items-center justify-between">
<div>
<p className="text-sm font-medium text-slate-700">{damage.description}</p>
<p className="text-xs text-slate-500">{damage.date}</p>
</div>
<div className="flex items-center gap-2">
<span className={`text-xs px-2 py-1 rounded-full ${damage.severity === 'minor' ? 'bg-yellow-100 text-yellow-700' :
damage.severity === 'moderate' ? 'bg-orange-100 text-orange-700' :
'bg-red-100 text-red-700'
}`}>
{damage.severity}
</span>
<span className={`text-xs px-2 py-1 rounded-full ${damage.status === 'resolved' ? 'bg-green-100 text-green-700' : 'bg-amber-100 text-amber-700'
}`}>
{damage.status}
</span>
</div>
</div>
))}
</div>
</div>
<div className="bg-white p-4 rounded-xl border border-slate-200">
<div className="flex items-center justify-between mb-4">
<h3 className="font-semibold text-slate-700 flex items-center gap-2">
<FileText className="w-5 h-5 text-blue-500" /> Rental Documents
</h3>
<button onClick={() => setShowUploadModal(true)} className="px-3 py-1.5 bg-blue-500 text-white rounded-lg text-sm hover:bg-blue-600 flex items-center gap-2">
<Upload className="w-4 h-4" /> Upload Document
</button>
</div>
<div className="space-y-2">
{mockDocuments.map(doc => (
<div key={doc.id} className="p-3 bg-slate-50 rounded-lg flex items-center justify-between">
<div className="flex items-center gap-3">
<FileText className="w-5 h-5 text-slate-400" />
<div>
<p className="text-sm font-medium text-slate-700">{doc.name}</p>
<p className="text-xs text-slate-500">{doc.uploadedAt}</p>
</div>
</div>
<button onClick={() => {
const link = document.createElement('a');
link.href = '#';
link.download = doc.name;
alert(`Downloading: ${doc.name}`);
}} className="px-3 py-1.5 text-blue-600 hover:bg-blue-50 rounded-lg text-sm flex items-center gap-1">
<Download className="w-4 h-4" /> Download
</button>
<button onClick={() => alert(`Viewing: ${doc.name}`)} className="px-3 py-1.5 text-slate-600 hover:bg-slate-100 rounded-lg text-sm flex items-center gap-1">
<FileText className="w-4 h-4" /> View
</button>
</div>
))}
</div>
</div>
{rental.status === 'pending' && (
<div className="bg-white p-4 rounded-xl border border-slate-200">
<h3 className="font-semibold text-slate-700 mb-4">Biker Response</h3>
<div className="flex gap-2">
{acceptPermission && (
<button onClick={handleAcceptRental} className="px-4 py-2 bg-green-600 text-white rounded-lg text-sm hover:bg-green-700 flex items-center gap-2">
<CheckCircle className="w-4 h-4" /> Accept
</button>
)}
{rejectPermission && (
<button onClick={() => setShowRejectModal(true)} className="px-4 py-2 bg-red-500 text-white rounded-lg text-sm hover:bg-red-600 flex items-center gap-2">
<XCircle className="w-4 h-4" /> Reject
</button>
)}
</div>
</div>
)}
{rental.status === 'accepted' && (
<div className="bg-green-50 p-4 rounded-xl border border-green-100">
<div className="flex items-center gap-2 text-green-700">
<CheckCircle className="w-5 h-5" />
<span className="font-medium">Accepted on {rental.acceptedAt}</span>
</div>
</div>
)}
{rental.status === 'cancelled' && rental.rejectNote && (
<div className="bg-red-50 p-4 rounded-xl border border-red-100">
<div className="flex items-center gap-2 text-red-700 mb-2">
<XCircle className="w-5 h-5" />
<span className="font-medium">Rejected</span>
</div>
<p className="text-sm text-red-600">Reason: {rental.rejectNote}</p>
</div>
)}
<div className="bg-white p-4 rounded-xl border border-slate-200">
<h3 className="font-semibold text-slate-700 mb-4 flex items-center gap-2">
<Clock className="w-5 h-5 text-slate-500" /> Activity Timeline
</h3>
<div className="space-y-3">
{timelineSteps.map((step, idx) => (
<div key={step.key} className="flex items-center gap-3">
<div className={`w-8 h-8 rounded-full flex items-center justify-center ${step.completed ? 'bg-emerald-100 text-emerald-600' : 'bg-slate-100 text-slate-400'}`}>
{step.completed ? <Check className="w-4 h-4" /> : <span className="text-xs font-medium">{idx + 1}</span>}
</div>
<div className="flex-1">
<p className={`text-sm font-medium ${step.completed ? 'text-slate-800' : 'text-slate-400'}`}>{step.label}</p>
{step.date && <p className="text-xs text-slate-500">{step.date}</p>}
</div>
</div>
))}
</div>
</div>
</div>
</div>
</div>
{showLockModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-md">
<div className="p-4 border-b border-slate-100 flex justify-between items-center">
<h3 className="font-semibold text-slate-800 flex items-center gap-2">
<Lock className="w-5 h-5" /> Lock Rental
</h3>
<button onClick={() => setShowLockModal(false)} className="text-slate-400 hover:text-slate-600">×</button>
</div>
<div className="p-4">
<label className="text-sm text-slate-600">Reason for locking</label>
<textarea
value={lockReason}
onChange={(e) => setLockReason(e.target.value)}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1"
rows={3}
placeholder="Enter reason..."
/>
</div>
<div className="p-4 border-t border-slate-100 flex justify-end gap-2">
<button onClick={() => setShowLockModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg">Cancel</button>
<button onClick={handleLockRental} disabled={!lockReason.trim()} className="px-4 py-2 bg-red-600 text-white rounded-lg disabled:opacity-50">Lock Rental</button>
</div>
</div>
</div>
)}
{showUnlockModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-md">
<div className="p-4 border-b border-slate-100 flex justify-between items-center">
<h3 className="font-semibold text-slate-800 flex items-center gap-2">
<Unlock className="w-5 h-5" /> Unlock Rental
</h3>
<button onClick={() => setShowUnlockModal(false)} className="text-slate-400 hover:text-slate-600">×</button>
</div>
<div className="p-4">
<p className="text-sm text-slate-600">Are you sure you want to unlock this rental? The bike will become active again.</p>
</div>
<div className="p-4 border-t border-slate-100 flex justify-end gap-2">
<button onClick={() => setShowUnlockModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg">Cancel</button>
<button onClick={handleUnlockRental} className="px-4 py-2 bg-green-600 text-white rounded-lg">Unlock Rental</button>
</div>
</div>
</div>
)}
{showCancelModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-md">
<div className="p-4 border-b border-slate-100 flex justify-between items-center">
<h3 className="font-semibold text-slate-800 flex items-center gap-2">
<XCircle className="w-5 h-5" /> Cancel Rental
</h3>
<button onClick={() => setShowCancelModal(false)} className="text-slate-400 hover:text-slate-600">×</button>
</div>
<div className="p-4">
<p className="text-sm text-slate-600">Are you sure you want to cancel this rental? This action cannot be undone.</p>
</div>
<div className="p-4 border-t border-slate-100 flex justify-end gap-2">
<button onClick={() => setShowCancelModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg">Cancel</button>
<button onClick={handleCancelRental} className="px-4 py-2 bg-red-600 text-white rounded-lg">Confirm Cancel</button>
</div>
</div>
</div>
)}
{showRejectModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-md">
<div className="p-4 border-b border-slate-100 flex justify-between items-center">
<h3 className="font-semibold text-slate-800 flex items-center gap-2">
<XCircle className="w-5 h-5" /> Reject Rental
</h3>
<button onClick={() => setShowRejectModal(false)} className="text-slate-400 hover:text-slate-600">×</button>
</div>
<div className="p-4">
<label className="text-sm text-slate-600">Rejection Reason</label>
<textarea
value={rejectNote}
onChange={(e) => setRejectNote(e.target.value)}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1"
rows={3}
placeholder="Enter reason for rejection..."
/>
</div>
<div className="p-4 border-t border-slate-100 flex justify-end gap-2">
<button onClick={() => setShowRejectModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg">Cancel</button>
<button onClick={handleRejectRental} disabled={!rejectNote.trim()} className="px-4 py-2 bg-red-600 text-white rounded-lg disabled:opacity-50">Reject Rental</button>
</div>
</div>
</div>
)}
{showDamageModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-md">
<div className="p-4 border-b border-slate-100 flex justify-between items-center">
<h3 className="font-semibold text-slate-800 flex items-center gap-2">
<AlertTriangle className="w-5 h-5 text-red-500" /> Report Damage
</h3>
<button onClick={() => setShowDamageModal(false)} className="text-slate-400 hover:text-slate-600 text-2xl">&times;</button>
</div>
<div className="p-4 space-y-4">
<div>
<label className="text-sm text-slate-600 block mb-1">Description</label>
<textarea
value={damageDesc}
onChange={(e) => setDamageDesc(e.target.value)}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
rows={3}
placeholder="Describe the damage..."
/>
</div>
<div>
<label className="text-sm text-slate-600 block mb-1">Severity</label>
<div className="flex gap-2">
{(['minor', 'moderate', 'severe'] as const).map(sev => (
<button
key={sev}
onClick={() => setDamageSeverity(sev)}
className={`flex-1 py-2 rounded-lg text-sm border ${damageSeverity === sev
? sev === 'minor' ? 'bg-yellow-100 border-yellow-300 text-yellow-700'
: sev === 'moderate' ? 'bg-orange-100 border-orange-300 text-orange-700'
: 'bg-red-100 border-red-300 text-red-700'
: 'border-slate-200 text-slate-600'
}`}
>
{sev.charAt(0).toUpperCase() + sev.slice(1)}
</button>
))}
</div>
</div>
</div>
<div className="p-4 border-t border-slate-100 flex justify-end gap-2">
<button onClick={() => setShowDamageModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg">Cancel</button>
<button onClick={handleReportDamage} disabled={!damageDesc.trim()} className="px-4 py-2 bg-red-600 text-white rounded-lg disabled:opacity-50">Report Damage</button>
</div>
</div>
</div>
)}
{showSmsModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-md">
<div className="p-4 border-b border-slate-100 flex justify-between items-center">
<h3 className="font-semibold text-slate-800 flex items-center gap-2">
<MessageCircle className="w-5 h-5 text-blue-500" /> Send SMS
</h3>
<button onClick={() => setShowSmsModal(false)} className="text-slate-400 hover:text-slate-600 text-2xl">&times;</button>
</div>
<div className="p-4 space-y-3">
<div className="bg-slate-50 p-3 rounded-lg text-sm">
<p className="text-slate-500">To:</p>
<p className="font-medium text-slate-800">{rental.userName} ({rental.userPhone})</p>
</div>
<div>
<label className="text-sm text-slate-600 block mb-1">Message</label>
<textarea
value={smsText}
onChange={(e) => setSmsText(e.target.value)}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
rows={4}
placeholder="Type your message..."
/>
</div>
</div>
<div className="p-4 border-t border-slate-100 flex justify-end gap-2">
<button onClick={() => setShowSmsModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg">Cancel</button>
<button onClick={handleSendSms} disabled={!smsText.trim()} className="px-4 py-2 bg-blue-600 text-white rounded-lg disabled:opacity-50">Send SMS</button>
</div>
</div>
</div>
)}
{showUploadModal && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl w-full max-w-md">
<div className="p-4 border-b border-slate-100 flex justify-between items-center">
<h3 className="font-semibold text-slate-800 flex items-center gap-2">
<Upload className="w-5 h-5 text-blue-500" /> Upload Document
</h3>
<button onClick={() => setShowUploadModal(false)} className="text-slate-400 hover:text-slate-600 text-2xl">&times;</button>
</div>
<div className="p-4 space-y-4">
<div>
<label className="text-sm text-slate-600 block mb-1">Document Name</label>
<input
type="text"
value={uploadDocName}
onChange={(e) => setUploadDocName(e.target.value)}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
placeholder="Enter document name..."
/>
</div>
<div>
<label className="text-sm text-slate-600 block mb-1">Choose File</label>
<div className="border-2 border-dashed border-slate-200 rounded-lg p-6 text-center hover:border-blue-400 cursor-pointer">
<Upload className="w-8 h-8 text-slate-300 mx-auto mb-2" />
<p className="text-sm text-slate-500">Click to upload or drag and drop</p>
<p className="text-xs text-slate-400 mt-1">PDF, PNG, JPG (max 10MB)</p>
<input type="file" className="hidden" accept=".pdf,.png,.jpg,.jpeg" />
</div>
</div>
</div>
<div className="p-4 border-t border-slate-100 flex justify-end gap-2">
<button onClick={() => setShowUploadModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg">Cancel</button>
<button onClick={handleUploadDocument} disabled={!uploadDocName.trim()} className="px-4 py-2 bg-blue-600 text-white rounded-lg disabled:opacity-50">Upload</button>
</div>
</div>
</div>
)}
</div>
);
}