'use client'; import { useState } from 'react'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { User, Phone, Mail, MapPin, Calendar, Heart, Briefcase, Car, Navigation, FileText, Clock, TrendingUp, CreditCard, Shield, Award, Star, Activity, Eye, ArrowLeft, PhoneCall, MessageCircle, CheckCircle, XCircle, AlertTriangle, DollarSign, Wallet, Bike as BikeIcon, Wrench, Ban, Copy, ExternalLink, Download, Upload, Bell, MessageSquare, Send, RefreshCcw, Image, Plus, X, Check, AlertCircle, Map, Camera, FileCheck, FileX, Users, Bike, AlertOctagon, ShieldAlert, History, Banknote, Building2, ChevronDown, ChevronRight, MapPinHouse, Home, Hash, Globe, PhoneIncoming, Tag, Save, Trash2, EyeOff, LayoutList, Grid3X3, MoreHorizontal, Package, Fuel, Gauge, Timer, Coins, Receipt, ArrowRightLeft, Truck, Battery, Zap, Settings2, Siren, Printer, Clock3, UserCheck, Globe2, Building, HeartPulse, UsersRound, MessageSquareDashed, BellRing, ListTodo, ClipboardList, BugOff, Info, SendHorizontal, PhoneOutgoing, Edit, Pencil } from 'lucide-react'; import toast from 'react-hot-toast'; interface KYCData { fullName: string; phone: string; alternatePhone?: string; email: string; nid: string; dateOfBirth: string; gender: string; bloodGroup: string; maritalStatus: string; religion: string; nationality: string; presentAddress: { houseFlat: string; floor: string; road: string; block: string; area: string; thana: string; district: string; division: string; postalCode: string; landmark?: string; }; permanentAddress: { houseFlat: string; floor: string; road: string; block: string; area: string; thana: string; district: string; division: string; postalCode: string; }; isPermanentSame: boolean; drivingLicense: { number: string; licenseType: string; expiryDate: string; issueDate: string; issuingAuthority: string; frontImage?: string; backImage?: string; }; employment: { status: string; companyName: string; department: string; designation: string; monthlyIncome: string; yearsOfExperience: string; businessAddress: string; }; nominee: { name: string; relationship: string; nid: string; phone: string; email: string; address: string; dateOfBirth: string; bloodGroup: string; sharePercentage: string; photo?: string; nidFront?: string; nidBack?: string; }; emergencyContact: { name: string; relationship: string; phone: string; email: string; address: string; }; nidFrontImage?: string; nidBackImage?: string; kycTimeline: Array<{ stage: string; status: string; timestamp: string; adminName: string; notes?: string; }>; } interface Rental { id: string; planName: string; subscriptionType: string; startDate: string; endDate?: string; dailyRate: number; weeklyRate?: number; monthlyRate?: number; depositAmount: number; depositStatus: string; dueAmount: number; pendingDays: number; rentPaymentStatus: string; evModel: string; batteryPercent: number; currentLocation: string; odometerReading: number; contractEndDate: string; initialConditionImages: string[]; status: string; totalAmount: number; penalty: number; plate: string; } interface Transaction { id: string; date: string; type: string; amount: number; method: string; status: string; description: string; } interface ActivityLog { id: string; type: string; action: string; timestamp: string; adminName?: string; details?: string; icon: any; } interface DamageReport { id: string; date: string; rentalId: string; bike: string; damageType: string; severity: string; estimatedCost: number; actualCost?: number; status: string; resolution?: string; description: string; location: string; images: string[]; } interface MessageHistory { id: string; direction: 'sent' | 'received'; channel: 'sms' | 'push' | 'in_app'; message: string; timestamp: string; status: string; } interface Note { id: string; text: string; createdAt: string; createdBy: string; } interface Biker { id: string; kyc: KYCData; gpsDeviceId: string; gpsStatus: string; lastLocation: string; location?: string; currentRental: Rental; previousRentals: Rental[]; bikeSpecs: { model: string; brand: string; year: string; color: string; vin: string; engineNumber: string; plateNumber: string; batteryCapacity: string; maxRange: string; chargingTime: string; lastServiceDate: string; nextServiceDue: string; totalKmRun: number; }; bikes: { current: { id: string; model: string; brand: string; plate: string; vin: string; color: string; year: string; batteryCapacity: string; maxRange: string; totalKmRun: number; lastService: string; nextService: string; }; batteries: Array<{ id: string; name: string; percent: number; status: 'active' | 'available' | 'charging' | 'swapped'; swappedAt: string; location: string; odometer: number; }>; }; transactions: Transaction[]; activityLog: ActivityLog[]; damageReports: DamageReport[]; messageHistory: MessageHistory[]; notes: Note[]; walletBalance: number; totalPaid: number; totalDue: number; pendingAmount: number; totalPenaltiesPaid: number; bankAccount: { bankName: string; accountNumber: string; routingNumber: string; }; billingAddress: { houseFlat: string; floor: string; road: string; block: string; area: string; thana: string; district: string; division: string; postalCode: string; }; status: string; kycStatus: string; membershipType: string; rating: number; totalRatings: number; depositAmount: number; role: string; totalRentals: number; activeRentals: number; completedRentals: number; cancelledRentals: number; } const mockBiker: Biker = { id: 'B001', status: 'active', role: 'rider', totalRentals: 45, activeRentals: 1, completedRentals: 42, cancelledRentals: 2, location: 'Gulshan 1, Dhaka', kycStatus: 'verified', membershipType: 'Premium', rating: 4.8, totalRatings: 156, depositAmount: 5000, kyc: { fullName: 'Mohammad Rafiqul Islam', phone: '01712345678', alternatePhone: '01987654321', email: 'rafiqul.islam@gmail.com', nid: '19951234567890123', dateOfBirth: '1995-06-15', gender: 'Male', bloodGroup: 'O+', maritalStatus: 'Married', religion: 'Islam', nationality: 'Bangladeshi', presentAddress: { houseFlat: 'House 42', floor: '3rd Floor', road: 'Road 11', block: 'Block D', area: 'Gulshan 1', thana: 'Gulshan', district: 'Dhaka', division: 'Dhaka', postalCode: '1212', landmark: 'Near BIBM', }, permanentAddress: { houseFlat: 'House 42', floor: '3rd Floor', road: 'Road 11', block: 'Block D', area: 'Gulshan 1', thana: 'Gulshan', district: 'Dhaka', division: 'Dhaka', postalCode: '1212', }, isPermanentSame: true, drivingLicense: { number: 'DL-2020-DH-1234567', licenseType: 'Motorcycle', expiryDate: '2030-06-14', issueDate: '2020-06-15', issuingAuthority: 'Bangladesh Road Transport Authority (BRTA), Dhaka', frontImage: 'https://picsum.photos/400/250?random=dl1', backImage: 'https://picsum.photos/400/250?random=dl2', }, employment: { status: 'Self Employed', companyName: 'FoodPanda Bangladesh', department: 'Delivery Operations', designation: 'Delivery Rider', monthlyIncome: '৳35,000', yearsOfExperience: '4 years', businessAddress: 'House 12, Road 5, Gulshan 1, Dhaka', }, nominee: { name: 'Fatema Begum', relationship: 'Wife', nid: '19952345678901234', phone: '01812345678', email: 'fatema.begum@yahoo.com', address: 'House 42, Road 11, Gulshan 1, Dhaka', dateOfBirth: '1998-03-20', bloodGroup: 'A+', sharePercentage: '100', photo: 'https://picsum.photos/200/200?random=nominee', nidFront: 'https://picsum.photos/400/250?random=nf1', nidBack: 'https://picsum.photos/400/250?random=nf2', }, emergencyContact: { name: 'Abdul Karim', relationship: 'Brother', phone: '01798765432', email: 'abdul.karim@outlook.com', address: 'House 15, Road 8, Banani, Dhaka', }, nidFrontImage: 'https://picsum.photos/400/250?random=nid1', nidBackImage: 'https://picsum.photos/400/250?random=nid2', kycTimeline: [ { stage: 'Application Submitted', status: 'completed', timestamp: '2024-01-10 09:30 AM', adminName: 'System' }, { stage: 'ID Verification', status: 'completed', timestamp: '2024-01-11 10:15 AM', adminName: 'Asaduzzaman', notes: 'NID verified successfully' }, { stage: 'Address Verification', status: 'completed', timestamp: '2024-01-12 02:30 PM', adminName: 'Rahima Begum', notes: 'Address confirmed via phone call' }, { stage: 'Interview Scheduled', status: 'completed', timestamp: '2024-01-13 09:00 AM', adminName: 'System' }, { stage: 'Interview Completed', status: 'completed', timestamp: '2024-01-15 11:30 AM', adminName: 'Karim Ahmed', notes: 'All documents verified, approved for onboarding' }, { stage: 'KYC Approved', status: 'completed', timestamp: '2024-01-16 03:45 PM', adminName: 'Supervisor Rahman' }, ], }, gpsDeviceId: 'GPS-DH-2024-001234', gpsStatus: 'Online', lastLocation: '23.8103, 90.4125', currentRental: { id: 'RNT-2024-0045', planName: 'Monthly Rental', subscriptionType: 'Premium', startDate: '2024-03-01', contractEndDate: '2024-04-30', dailyRate: 0, monthlyRate: 4500, depositAmount: 5000, depositStatus: 'Paid', dueAmount: 0, pendingDays: 0, rentPaymentStatus: 'Paid', evModel: 'AIMA Lightning EV', batteryPercent: 78, currentLocation: '23.7521, 90.3756', odometerReading: 2456, initialConditionImages: [ 'https://picsum.photos/400/300?random=cond1', 'https://picsum.photos/400/300?random=cond2', 'https://picsum.photos/400/300?random=cond3', 'https://picsum.photos/400/300?random=cond4', ], status: 'Active', totalAmount: 4500, penalty: 0, plate: 'Dhaka Metro Cha-4521', }, previousRentals: [ { id: 'RNT-2024-0020', planName: 'Weekly Rental', subscriptionType: 'Basic', startDate: '2024-02-01', contractEndDate: '2024-02-07', endDate: '2024-02-28', dailyRate: 0, weeklyRate: 1200, depositAmount: 3000, depositStatus: 'Returned', dueAmount: 0, pendingDays: 0, rentPaymentStatus: 'Paid', evModel: 'Yadea DT3', batteryPercent: 0, currentLocation: '', odometerReading: 1850, initialConditionImages: [], status: 'Completed', totalAmount: 4800, penalty: 0, plate: 'Dhaka Metro Cha-3890', }, { id: 'RNT-2024-0010', planName: 'Monthly Rental', subscriptionType: 'Standard', startDate: '2024-01-01', contractEndDate: '2024-01-31', endDate: '2024-01-31', dailyRate: 0, monthlyRate: 3500, depositAmount: 3000, depositStatus: 'Returned', dueAmount: 500, pendingDays: 0, rentPaymentStatus: 'Paid with Penalty', evModel: 'Etron ET50', batteryPercent: 0, currentLocation: '', odometerReading: 1200, initialConditionImages: [], status: 'Completed', totalAmount: 4000, penalty: 500, plate: 'Dhaka Metro Cha-2156', }, { id: 'RNT-2023-0045', planName: 'Weekly Rental', subscriptionType: 'Basic', startDate: '2023-12-15', contractEndDate: '2023-12-21', endDate: '2023-12-22', dailyRate: 0, weeklyRate: 1200, depositAmount: 3000, depositStatus: 'Returned', dueAmount: 0, pendingDays: 0, rentPaymentStatus: 'Cancelled', evModel: 'AIMA Lightning EV', batteryPercent: 0, currentLocation: '', odometerReading: 180, initialConditionImages: [], status: 'Cancelled', totalAmount: 1200, penalty: 0, plate: 'Dhaka Metro Cha-4521', }, ], bikeSpecs: { model: 'AIMA Lightning EV', brand: 'AIMA', year: '2024', color: 'Matte Black', vin: 'VIN1234567890ABCD', engineNumber: 'ENG-2024-AIMA-5678', plateNumber: 'Dhaka Metro Cha-4521', batteryCapacity: '72V 40Ah', maxRange: '120 km', chargingTime: '4-6 hours', lastServiceDate: '2024-03-15', nextServiceDue: '2024-04-15', totalKmRun: 2456, }, bikes: { current: { id: 'BIKE-001', model: 'AIMA Lightning EV', brand: 'AIMA', plate: 'Dhaka Metro Cha-4521', vin: 'VIN123456789ABCDE', color: 'Black', year: '2023', batteryCapacity: '72V 45Ah', maxRange: '120 km', totalKmRun: 2456, lastService: '2024-03-15', nextService: '2024-06-15', }, batteries: [ { id: 'BAT-DH-001', name: 'Battery A', percent: 78, status: 'active', swappedAt: '2024-04-15 10:30', location: 'Swap Station - Gulshan', odometer: 2456 }, { id: 'BAT-DH-002', name: 'Battery B', percent: 92, status: 'available', swappedAt: '2024-04-10 08:00', location: 'Swap Station - Banani', odometer: 1890 }, { id: 'BAT-DH-003', name: 'Battery C', percent: 15, status: 'charging', swappedAt: '2024-04-05 14:00', location: 'Swap Station - Gulshan', odometer: 1200 }, ], }, transactions: [ { id: 'TXN-001', date: '2024-03-28', type: 'Rent Payment', amount: 4500, method: 'bKash', status: 'Completed', description: 'March 2024 monthly rent' }, { id: 'TXN-002', date: '2024-03-01', type: 'Deposit', amount: 5000, method: 'bKash', status: 'Completed', description: 'Security deposit for new rental' }, { id: 'TXN-003', date: '2024-02-28', type: 'Rent Payment', amount: 1200, method: 'Rocket', status: 'Completed', description: 'Final week rent - February' }, { id: 'TXN-004', date: '2024-02-21', type: 'Rent Payment', amount: 1200, method: 'bKash', status: 'Completed', description: 'Week 4 rent - February' }, { id: 'TXN-005', date: '2024-02-14', type: 'Rent Payment', amount: 1200, method: 'bKash', status: 'Completed', description: 'Week 3 rent - February' }, { id: 'TXN-006', date: '2024-02-07', type: 'Rent Payment', amount: 1200, method: 'Rocket', status: 'Completed', description: 'Week 2 rent - February' }, { id: 'TXN-007', date: '2024-02-01', type: 'Deposit Return', amount: -3000, method: 'Bank Transfer', status: 'Completed', description: 'Deposit returned from previous rental' }, { id: 'TXN-008', date: '2024-01-31', type: 'Penalty', amount: 500, method: 'Wallet', status: 'Completed', description: 'Late payment penalty - January' }, { id: 'TXN-009', date: '2024-01-28', type: 'Rent Payment', amount: 3500, method: 'bKash', status: 'Completed', description: 'January 2024 monthly rent' }, { id: 'TXN-010', date: '2024-01-15', type: 'Wallet Top-up', amount: 5000, method: 'bKash', status: 'Completed', description: 'Wallet recharge' }, { id: 'TXN-011', date: '2024-01-01', type: 'Deposit', amount: 3000, method: 'Cash', status: 'Completed', description: 'Security deposit' }, { id: 'TXN-012', date: '2023-12-28', type: 'Rent Payment', amount: 800, method: 'bKash', status: 'Completed', description: 'Partial rent - December' }, ], activityLog: [ { id: 'ACT-001', type: 'login', action: 'App login from Android device', timestamp: '2024-03-28 08:15 AM', icon: User }, { id: 'ACT-002', type: 'rental', action: 'Battery swap at Gulshan Swap Station', timestamp: '2024-03-28 07:45 AM', icon: Battery, details: 'Swapped from 35% to 92%' }, { id: 'ACT-003', type: 'payment', action: 'Monthly rent payment completed', timestamp: '2024-03-28 07:30 AM', adminName: 'System', icon: DollarSign }, { id: 'ACT-004', type: 'rental', action: 'Rental started - AIMA Lightning EV', timestamp: '2024-03-01 10:00 AM', icon: BikeIcon }, { id: 'ACT-005', type: 'kyc', action: 'KYC verification completed', timestamp: '2024-01-16 03:45 PM', adminName: 'Supervisor Rahman', icon: Shield }, { id: 'ACT-006', type: 'document', action: 'Driving license image uploaded', timestamp: '2024-01-10 11:20 AM', icon: FileText }, { id: 'ACT-007', type: 'penalty', action: 'Late payment penalty applied', timestamp: '2024-01-31 11:59 PM', adminName: 'System', icon: AlertTriangle, details: '৳500 for late rent payment' }, { id: 'ACT-008', type: 'bike', action: 'Bike changed from Etron ET50 to AIMA Lightning', timestamp: '2024-03-01 09:30 AM', adminName: 'Staff: Kamal', icon: ArrowRightLeft }, { id: 'ACT-009', type: 'message', action: 'Received SMS: Rent reminder', timestamp: '2024-02-28 09:00 AM', icon: MessageSquare }, { id: 'ACT-010', type: 'login', action: 'App login from iOS device', timestamp: '2024-02-15 06:30 PM', icon: User }, { id: 'ACT-011', type: 'rental', action: 'Battery swap at Banani Swap Station', timestamp: '2024-02-15 05:45 PM', icon: Battery, details: 'Swapped from 28% to 95%' }, { id: 'ACT-012', type: 'document', action: 'NID image uploaded', timestamp: '2024-01-10 09:45 AM', icon: FileText }, ], damageReports: [ { id: 'DMG-001', date: '2024-02-10', rentalId: 'RNT-2024-0020', bike: 'Yadea DT3', damageType: 'Body Damage', severity: 'Medium', estimatedCost: 2000, actualCost: 1800, status: 'Resolved', resolution: 'Panel repaired and repainted', description: 'Minor scratch on left rear fender noticed during routine inspection', location: 'Gulshan 1, Dhaka', images: ['https://picsum.photos/400/300?random=dm1', 'https://picsum.photos/400/300?random=dm2'], }, { id: 'DMG-002', date: '2024-01-20', rentalId: 'RNT-2024-0010', bike: 'Etron ET50', damageType: 'Tire Damage', severity: 'Low', estimatedCost: 800, actualCost: 750, status: 'Resolved', resolution: 'Rear tire replaced', description: 'Puncture in rear tire caused by sharp object on road', location: 'Dhanmondi 32, Dhaka', images: ['https://picsum.photos/400/300?random=dm3'], }, { id: 'DMG-003', date: '2024-03-25', rentalId: 'RNT-2024-0045', bike: 'AIMA Lightning EV', damageType: 'Battery Damage', severity: 'High', estimatedCost: 5000, status: 'Pending', description: 'Battery not holding charge properly, discharging faster than normal', location: 'Uttara Sector 10, Dhaka', images: ['https://picsum.photos/400/300?random=dm4', 'https://picsum.photos/400/300?random=dm5'], }, ], messageHistory: [ { id: 'MSG-001', direction: 'sent', channel: 'sms', message: 'Your monthly rent of ৳4,500 is due on March 28. Please ensure sufficient balance in your wallet.', timestamp: '2024-03-25 10:00 AM', status: 'Delivered' }, { id: 'MSG-002', direction: 'received', channel: 'sms', message: 'Okay, I will pay today.', timestamp: '2024-03-25 10:15 AM', status: 'Received' }, { id: 'MSG-003', direction: 'sent', channel: 'sms', message: 'Thank you. You can make payment via bKash or Rocket to 01712345678.', timestamp: '2024-03-25 10:20 AM', status: 'Delivered' }, { id: 'MSG-004', direction: 'received', channel: 'sms', message: 'Payment done. Transaction ID: BKP123456789.', timestamp: '2024-03-28 07:25 AM', status: 'Received' }, { id: 'MSG-005', direction: 'sent', channel: 'push', message: 'Your rent payment has been received. Thank you!', timestamp: '2024-03-28 07:30 AM', status: 'Delivered' }, { id: 'MSG-006', direction: 'sent', channel: 'sms', message: 'Reminder: Your bike rental contract ends on April 30. Please renew or return the bike.', timestamp: '2024-03-20 09:00 AM', status: 'Delivered' }, { id: 'MSG-007', direction: 'received', channel: 'sms', message: 'I want to renew the contract. What are the new rates?', timestamp: '2024-03-20 02:30 PM', status: 'Received' }, { id: 'MSG-008', direction: 'sent', channel: 'sms', message: 'Great! Current rates are ৳4,500/month for the same plan. We will send renewal documents soon.', timestamp: '2024-03-20 03:00 PM', status: 'Delivered' }, ], notes: [ { id: 'NOTE-001', text: 'Very reliable biker, always pays rent on time. Low maintenance issues.', createdAt: '2024-03-15 11:30 AM', createdBy: 'Karim (Staff)' }, { id: 'NOTE-002', text: 'Battery performance issue reported on March 25. Needs inspection.', createdAt: '2024-03-25 04:00 PM', createdBy: 'Rahim (Manager)' }, { id: 'NOTE-003', text: 'VIP customer - priority support required.', createdAt: '2024-02-01 09:00 AM', createdBy: 'Supervisor Rahman' }, ], walletBalance: 1250, totalPaid: 27800, totalDue: 0, pendingAmount: 0, totalPenaltiesPaid: 500, bankAccount: { bankName: 'Dutch-Bangla Bank Limited', accountNumber: '1511234567890', routingNumber: '9032612', }, billingAddress: { houseFlat: 'House 42', floor: '3rd Floor', road: 'Road 11', block: 'Block D', area: 'Gulshan 1', thana: 'Gulshan', district: 'Dhaka', division: 'Dhaka', postalCode: '1212', }, }; const tabs = [ { id: 'personal', label: 'Personal', icon: User }, { id: 'license', label: 'License & GPS', icon: Car }, { id: 'documents', label: 'Documents', icon: FileCheck }, { id: 'bikes', label: 'Bikes', icon: BikeIcon }, { id: 'rent', label: 'Rent & Account', icon: CreditCard }, { id: 'messages', label: 'Messages', icon: MessageSquare }, { id: 'notes', label: 'Notes', icon: ClipboardList }, { id: 'activity', label: 'Activity', icon: Activity }, { id: 'damage', label: 'Damage', icon: AlertOctagon }, ]; const statusColors: Record = { active: 'bg-green-100 text-green-700', pending: 'bg-amber-100 text-amber-700', inactive: 'bg-slate-100 text-slate-500', blocked: 'bg-red-100 text-red-700', completed: 'bg-green-100 text-green-700', cancelled: 'bg-red-100 text-red-700', resolved: 'bg-green-100 text-green-700', }; const severityColors: Record = { Low: 'bg-blue-100 text-blue-700', Medium: 'bg-amber-100 text-amber-700', High: 'bg-orange-100 text-orange-700', Critical: 'bg-red-100 text-red-700', }; const activityTypeColors: Record = { login: 'bg-blue-100 text-blue-600', rental: 'bg-green-100 text-green-600', payment: 'bg-purple-100 text-purple-600', kyc: 'bg-cyan-100 text-cyan-600', document: 'bg-amber-100 text-amber-600', penalty: 'bg-red-100 text-red-600', bike: 'bg-indigo-100 text-indigo-600', message: 'bg-pink-100 text-pink-600', }; const damageTypes = [ 'Battery Damage', 'Body Damage', 'Tire Damage', 'Engine Damage', 'Accident', 'Theft', 'Other', ]; const severityLevels = ['Low', 'Medium', 'High', 'Critical']; const smsTemplates = [ { id: 'rent_due', label: 'Monthly rent due', message: 'Monthly rent due. Please pay ৳{amount} within 3 days.' }, { id: 'contract_end', label: 'Contract ending', message: 'Your bike rental contract ends on {date}. Please renew or return.' }, { id: 'kyc_approved', label: 'KYC approved', message: 'Congratulations! Your KYC has been approved. You can now rent bikes.' }, { id: 'penalty', label: 'Penalty warning', message: 'Warning: Your account has a penalty of ৳{amount}. Please clear it to avoid service suspension.' }, { id: 'docs_upload', label: 'Document request', message: 'Please upload your documents for verification. Missing documents: {docs}' }, { id: 'battery_reminder', label: 'Battery swap reminder', message: 'Your battery is running low. Please swap at nearest station.' }, ]; function AddressCard({ title, address, icon: Icon, bgColor }: { title: string; address: any; icon: any; bgColor: string }) { return (

{title}

{address.houseFlat && } {address.floor && } {address.road && } {address.block && } {address.area && } {address.thana && } {address.district && } {address.division && } {address.postalCode && } {address.landmark && }
); } function InfoRow({ label, value }: { label: string; value: string }) { return value ? (
{label} {value}
) : null; } function ProfileField({ label, value, editing, onChange }: { label: string; value: string; editing?: boolean; onChange?: (v: string) => void }) { if (editing) { return (
{label} onChange?.(e.target.value)} className="w-40 px-2 py-1.5 border border-slate-200 rounded text-xs text-slate-800 bg-white" />
); } return (
{label} {value}
); } function SectionCard({ title, icon: Icon, children, headerBg = 'bg-slate-50', editKey, editingSection, setEditingSection, onEdit, editForm, setEditForm, biker }: { title: string; icon: any; children: React.ReactNode; headerBg?: string; editKey?: string; editingSection?: string | null; setEditingSection?: (s: string | null) => void; onEdit?: () => void; editForm?: any; setEditForm?: any; biker?: any }) { return (

{title}

{editKey && setEditingSection ? ( editingSection !== editKey ? ( ) : (
) ) : null}
{children}
); } function TimelineItem({ stage, status, timestamp, adminName, notes, isLast }: { stage: string; status: string; timestamp: string; adminName: string; notes?: string; isLast: boolean }) { return (
{status === 'completed' ? : }
{!isLast &&
}

{stage}

{timestamp} • {adminName}

{notes &&

{notes}

}
); } export default function BikerDetailPage() { const router = useRouter(); const [activeTab, setActiveTab] = useState('personal'); const [showMessageModal, setShowMessageModal] = useState(false); const [showDamageModal, setShowDamageModal] = useState(false); const [showDocumentUpload, setShowDocumentUpload] = useState(false); const [messageTab, setMessageTab] = useState<'sms' | 'push' | 'template'>('sms'); const [messageText, setMessageText] = useState(''); const [selectedTemplate, setSelectedTemplate] = useState(''); const [newNote, setNewNote] = useState(''); const [damageForm, setDamageForm] = useState({ bike: '', damageType: '', description: '', severity: '', estimatedCost: '', location: '', images: [] as string[], }); const [rentPage, setRentPage] = useState(1); const [transactionPage, setTransactionPage] = useState(1); const [editingSection, setEditingSection] = useState(null); const [editForm, setEditForm] = useState({}); const biker = mockBiker; const perPage = 10; const paginatedRentHistory = [...biker.currentRental ? [biker.currentRental] : [], ...biker.previousRentals].slice((rentPage - 1) * perPage, rentPage * perPage); const totalRentPages = Math.ceil((1 + biker.previousRentals.length) / perPage); const paginatedTransactions = biker.transactions.slice((transactionPage - 1) * perPage, transactionPage * perPage); const totalTransactionPages = Math.ceil(biker.transactions.length / perPage); const handleSendMessage = () => { if (!messageText.trim()) return; toast.success(`Message sent to ${biker.kyc.phone}`); setMessageText(''); setShowMessageModal(false); }; const handleAddNote = () => { if (!newNote.trim()) return; toast.success('Note added successfully'); setNewNote(''); }; const handleSendTemplate = (template: typeof smsTemplates[0]) => { let message = template.message; message = message.replace('{amount}', biker.currentRental?.monthlyRate?.toString() || '4500'); message = message.replace('{date}', biker.currentRental?.contractEndDate || '2024-04-30'); message = message.replace('{docs}', 'Driving License, NID'); setMessageText(message); setMessageTab('sms'); }; const handleSubmitDamage = () => { if (!damageForm.damageType || !damageForm.description) { toast.error('Please fill all required fields'); return; } toast.success('Damage report submitted successfully'); setShowDamageModal(false); setDamageForm({ bike: '', damageType: '', description: '', severity: '', estimatedCost: '', location: '', images: [] }); }; const formatAddress = (addr: any) => { return [addr.houseFlat, addr.floor, addr.road, addr.block, addr.area, addr.thana, addr.district, addr.division, addr.postalCode].filter(Boolean).join(', '); }; return (
{biker.kyc.fullName.charAt(0)}

{biker.kyc.fullName}

{biker.status === 'active' && } {biker.status === 'pending' && } {biker.status === 'blocked' && } {biker.status.charAt(0).toUpperCase() + biker.status.slice(1)}

ID: {biker.id} • {biker.location}

{biker.kycStatus === 'verified' && } {biker.kycStatus === 'pending' && } KYC: {biker.kycStatus} {editingSection === 'membership' ? ( <> ) : ( <> {biker.membershipType} )} {biker.rating > 0 && ( {biker.rating} ({biker.totalRatings}) )}
SMS
{/* Stats Grid */}
Total Rentals

{biker.totalRentals}

Active Rentals

{biker.activeRentals}

Completed

{biker.completedRentals}

Cancelled

{biker.cancelledRentals}

{/* Tabs Container */}
{activeTab === 'personal' && (
{/* Application Details */}

Application Details

{editingSection !== 'application' ? ( ) : (
)}
{editingSection === 'application' ? ( <>
setEditForm({ ...editForm, fullName: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, phone: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, alternatePhone: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, email: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, nid: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, dateOfBirth: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, religion: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, nationality: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
) : ( <>

Full Name

{biker.kyc.fullName}

Phone

{biker.kyc.phone}

{biker.kyc.alternatePhone && (

Alternate Phone

{biker.kyc.alternatePhone}

)}

Email

{biker.kyc.email}

NID

{biker.kyc.nid}

Date of Birth

{biker.kyc.dateOfBirth}

Gender

{biker.kyc.gender}

Blood Group

{biker.kyc.bloodGroup}

Marital Status

{biker.kyc.maritalStatus}

Religion

{biker.kyc.religion}

Nationality

{biker.kyc.nationality}

)}
{/* Nominee Details */}

Nominee Details

{editingSection !== 'nominee' ? ( ) : (
)}
{editingSection === 'nominee' ? ( <>
setEditForm({ ...editForm, name: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, relationship: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, nid: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, phone: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, email: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, sharePercentage: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, address: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
) : ( <>

Nominee Name

{biker.kyc.nominee.name}

Relationship

{biker.kyc.nominee.relationship}

NID

{biker.kyc.nominee.nid}

Phone

{biker.kyc.nominee.phone}

Email

{biker.kyc.nominee.email}

Share %

{biker.kyc.nominee.sharePercentage}%

Blood Group

{biker.kyc.nominee.bloodGroup}

Address

{biker.kyc.nominee.address}

)}
{/* Employment Information */}

Employment Information

{editingSection !== 'employment' ? ( ) : (
)}
{editingSection === 'employment' ? ( <>
setEditForm({ ...editForm, companyName: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, department: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, designation: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, monthlyIncome: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, yearsOfExperience: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, businessAddress: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
) : ( <>

Status

{biker.kyc.employment.status}

Monthly Income

{biker.kyc.employment.monthlyIncome}

Company / Business

{biker.kyc.employment.companyName}

Department

{biker.kyc.employment.department}

Designation

{biker.kyc.employment.designation}

Experience

{biker.kyc.employment.yearsOfExperience}

Business Address

{biker.kyc.employment.businessAddress}

)}
{/* Emergency Contact */}

Emergency Contact

{editingSection !== 'emergency' ? ( ) : (
)}
{editingSection === 'emergency' ? ( <>
setEditForm({ ...editForm, name: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, relationship: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, phone: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, email: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, address: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
) : ( <>

Contact Name

{biker.kyc.emergencyContact.name}

Relationship

{biker.kyc.emergencyContact.relationship}

Phone

{biker.kyc.emergencyContact.phone}

Email

{biker.kyc.emergencyContact.email}

Address

{biker.kyc.emergencyContact.address}

)}
{/* Present Address */}

Present Address

{editingSection !== 'presentAddress' ? ( ) : (
)}
{editingSection === 'presentAddress' ? ( <>
setEditForm({ ...editForm, addressLine1: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" placeholder="House No, Road, Area" />
setEditForm({ ...editForm, addressLine2: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" placeholder="Additional info" />
setEditForm({ ...editForm, district: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, thana: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, zip: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, landmark: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" placeholder="Near landmark" />
setEditForm({ ...editForm, country: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
) : ( <>

Address Line 1

{biker.kyc.presentAddress.houseFlat}, {biker.kyc.presentAddress.road}

Address Line 2

{biker.kyc.presentAddress.block ? `${biker.kyc.presentAddress.block}, ` : ''}{biker.kyc.presentAddress.area}

Division

{biker.kyc.presentAddress.division}

District

{biker.kyc.presentAddress.district}

Thana / Upazila

{biker.kyc.presentAddress.thana}

Zip Code

{biker.kyc.presentAddress.postalCode}

{biker.kyc.presentAddress.landmark && (

Landmark

{biker.kyc.presentAddress.landmark}

)}

Country

Bangladesh

)}
{/* Permanent Address */}

Permanent Address

{editingSection !== 'permanentAddress' ? ( ) : (
)}
{editingSection === 'permanentAddress' ? ( <>
setEditForm({ ...editForm, addressLine1: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" placeholder="House No, Road, Area" />
setEditForm({ ...editForm, addressLine2: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" placeholder="Additional info" />
setEditForm({ ...editForm, district: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, thana: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, zip: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, landmark: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" placeholder="Near landmark" />
setEditForm({ ...editForm, country: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
) : ( <>

Address Line 1

{biker.kyc.permanentAddress.houseFlat}, {biker.kyc.permanentAddress.road}

Address Line 2

{biker.kyc.permanentAddress.block ? `${biker.kyc.permanentAddress.block}, ` : ''}{biker.kyc.permanentAddress.area}

Division

{biker.kyc.permanentAddress.division}

District

{biker.kyc.permanentAddress.district}

Thana / Upazila

{biker.kyc.permanentAddress.thana || '-'}

Zip Code

{biker.kyc.permanentAddress.postalCode}

Landmark

{'-'}

Country

Bangladesh

{biker.kyc.isPermanentSame && (
Same as Present Address
)} )}
)} {activeTab === 'license' && (
{ setEditForm({ licenseNumber: biker.kyc.drivingLicense.number, licenseType: biker.kyc.drivingLicense.licenseType, licenseIssueDate: biker.kyc.drivingLicense.issueDate, licenseExpiryDate: biker.kyc.drivingLicense.expiryDate, issuingAuthority: biker.kyc.drivingLicense.issuingAuthority }); }} editForm={editForm} setEditForm={setEditForm} biker={biker}>
{editingSection === 'drivingLicense' ? ( <>
setEditForm({ ...editForm, licenseNumber: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, licenseIssueDate: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, licenseExpiryDate: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, issuingAuthority: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
) : ( <>

License Number

{biker.kyc.drivingLicense.number}

License Type

{biker.kyc.drivingLicense.licenseType}

Issue Date

{biker.kyc.drivingLicense.issueDate}

Expiry Date

{biker.kyc.drivingLicense.expiryDate}

Issuing Authority

{biker.kyc.drivingLicense.issuingAuthority}

Front Image

{biker.kyc.drivingLicense.frontImage ? ( License Front ) : (
)}

Back Image

{biker.kyc.drivingLicense.backImage ? ( License Back ) : (
)}
)}
{ setEditForm({ gpsDeviceId: biker.gpsDeviceId, gpsStatus: biker.gpsStatus, lastLocation: biker.lastLocation }); }} editForm={editForm} setEditForm={setEditForm} biker={biker}>
{editingSection === 'gps' ? ( <>
setEditForm({ ...editForm, gpsDeviceId: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, lastLocation: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
) : ( <>

Device ID

{biker.gpsDeviceId}

Status

{biker.gpsStatus}

Last Location

{biker.lastLocation}

)}
)} {activeTab === 'documents' && (

Documents

National ID

NID Front

Approved
{biker.kyc.nidFrontImage && ( NID Front )}

NID Back

Approved
{biker.kyc.nidBackImage && ( NID Back )}

Driving License

License Front

{biker.kyc.drivingLicense.frontImage ? ( Uploaded ) : ( Missing )}
{biker.kyc.drivingLicense.frontImage && ( License Front )}

License Back

{biker.kyc.drivingLicense.backImage ? ( Uploaded ) : ( Missing )}
{biker.kyc.drivingLicense.backImage && ( License Back )}

Nominee Documents

Nominee Photo

{biker.kyc.nominee.photo ? ( Nominee ) : (
)}

Nominee NID Front

{biker.kyc.nominee.nidFront ? ( NID Front ) : (
)}

Nominee NID Back

{biker.kyc.nominee.nidBack ? ( NID Back ) : (
)}
{biker.kyc.kycTimeline.map((item, idx) => ( ))}
)} {activeTab === 'bikes' && (
{/* Current Bike */}
{/* Bike info row */}

{biker.bikes.current.model}

{biker.bikes.current.brand} • {biker.bikes.current.year} • {biker.bikes.current.color}

{biker.bikes.current.plate}

Active
{/* Battery swap info */}
50 ? 'bg-green-100' : biker.bikes.batteries[0]?.percent > 20 ? 'bg-amber-100' : 'bg-red-100'}`}> 50 ? 'text-green-600' : biker.bikes.batteries[0]?.percent > 20 ? 'text-amber-600' : 'text-red-600'}`} />

Current Battery

50 ? 'text-green-600' : biker.bikes.batteries[0]?.percent > 20 ? 'text-amber-600' : 'text-red-600'}`}>{biker.bikes.batteries[0]?.percent}%

Battery ID

{biker.bikes.batteries[0]?.id}

Location

{biker.bikes.batteries[0]?.location}

{/* Battery info grid */}

Battery Capacity

{biker.bikes.current.batteryCapacity}

Max Range

{biker.bikes.current.maxRange}

Odometer

{biker.bikes.current.totalKmRun.toLocaleString()} km

VIN

{biker.bikes.current.vin}

Last Service

{biker.bikes.current.lastService}

Next Service

{biker.bikes.current.nextService}

{/* Initial Condition Images */} {biker.currentRental.initialConditionImages.length > 0 && (

Initial Condition Photos

{biker.currentRental.initialConditionImages.map((img, idx) => ( {`Condition ))}
)}
{/* Battery History */} { setEditForm({}); }} editForm={editForm} setEditForm={setEditForm} biker={biker}>
{editingSection === 'batteryHistory' ? ( <> {editForm.editingIndex !== undefined ? ( <>

Editing: {biker.bikes.batteries[editForm.editingIndex]?.name}

setEditForm({ ...editForm, batName: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, batId: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, batPercent: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, batLocation: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, batSwappedAt: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, batOdometer: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
) : ( <>

Add New Battery

{biker.bikes.batteries.length > 0 && ( )}
setEditForm({ ...editForm, batId: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" placeholder="BAT-DH-004" />
setEditForm({ ...editForm, batName: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" placeholder="Battery D" />
setEditForm({ ...editForm, batPercent: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" placeholder="0-100" />
setEditForm({ ...editForm, batLocation: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" placeholder="Swap Station" />
setEditForm({ ...editForm, batSwappedAt: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" placeholder="YYYY-MM-DD HH:MM" />
setEditForm({ ...editForm, batOdometer: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
)} ) : ( <>
{biker.bikes.batteries.map((bat, idx) => (
50 ? 'bg-green-100' : bat.percent > 20 ? 'bg-amber-100' : 'bg-red-100'}`}> 50 ? 'text-green-600' : bat.percent > 20 ? 'text-amber-600' : 'text-red-600'}`} />

{bat.name} ({bat.id})

{bat.location} • Swapped: {bat.swappedAt}

50 ? 'text-green-600' : bat.percent > 20 ? 'text-amber-600' : 'text-red-600'}`}>{bat.percent}% {bat.status.charAt(0).toUpperCase() + bat.status.slice(1)}
))} )}
{/* Previous Rentals */}
{biker.previousRentals.length > 0 ? ( <>
{biker.previousRentals.map((rental, idx) => (

{rental.evModel}

{rental.plate} • {rental.id}

{rental.status}
{editingSection === 'previousRentals' && editForm.editingIndex === idx ? ( <>
setEditForm({ ...editForm, rentalEvModel: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, rentalPlate: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, rentalStartDate: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, rentalEndDate: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, rentalTotalAmount: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
setEditForm({ ...editForm, rentalPenalty: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-xs" />
) : (

Plan

{rental.planName}

Start

{rental.startDate}

End

{rental.endDate || '-'}

Total

৳{rental.totalAmount.toLocaleString()}{rental.penalty > 0 ? (+৳{rental.penalty}) : null}

)}
))} ) : (

No previous rentals

)}
)} {activeTab === 'rent' && (
{/* Financial Summary */}

Total Paid

৳{biker.totalPaid.toLocaleString()}

Total Due

৳{biker.totalDue.toLocaleString()}

Pending

৳{biker.pendingAmount.toLocaleString()}

Deposit

৳{biker.depositAmount.toLocaleString()}

Penalties Paid

৳{biker.totalPenaltiesPaid.toLocaleString()}

{/* Wallet */}

Balance

৳{biker.walletBalance.toLocaleString()}

Last updated: March 28, 2024

{/* Payment History */}
{paginatedTransactions.map(txn => ( ))}
Date Type Amount Method Status
{txn.date} {txn.type} ৳{Math.abs(txn.amount).toLocaleString()} {txn.method} {txn.status}

Showing {((transactionPage - 1) * perPage) + 1}-{Math.min(transactionPage * perPage, biker.transactions.length)} of {biker.transactions.length}

{/* Rent History Table */}
{biker.currentRental && ( )} {biker.previousRentals.map(rental => ( ))}
Date Bike Plan Duration Rent Penalty Total Status
{biker.currentRental.startDate}

{biker.currentRental.evModel}

{biker.currentRental.plate}

{biker.currentRental.planName} {biker.currentRental.subscriptionType} ৳{(biker.currentRental.monthlyRate || biker.currentRental.weeklyRate || biker.currentRental.dailyRate).toLocaleString()} - ৳{biker.currentRental.totalAmount.toLocaleString()} Active
{rental.startDate}

{rental.evModel}

{rental.plate}

{rental.planName} {rental.endDate || '-'} ৳{((rental.monthlyRate || rental.weeklyRate) || 0).toLocaleString()} {rental.penalty > 0 ? `৳${rental.penalty.toLocaleString()}` : '-'} ৳{rental.totalAmount.toLocaleString()} {rental.status}

Showing page {rentPage} of {totalRentPages}

)} {activeTab === 'activity' && (
{biker.activityLog.map(log => { const Icon = log.icon; return (

{log.action}

{log.timestamp} {log.adminName && • {log.adminName}}
{log.details &&

{log.details}

}
); })}
)} {activeTab === 'messages' && (
{biker.messageHistory.filter(m => m.channel === 'sms' || m.channel === 'in_app').map(msg => (
{msg.direction === 'sent' ? : } {msg.direction === 'sent' ? 'Sent' : 'Received'} ({msg.channel})
{msg.timestamp}

{msg.message}

{msg.status === 'Delivered' && } {msg.status}
))}
{biker.messageHistory.filter(m => m.channel === 'push').length > 0 ? ( biker.messageHistory.filter(m => m.channel === 'push').map(msg => (
Push Notification {msg.timestamp}

{msg.message}

{msg.status === 'Delivered' && } {msg.status}
)) ) : (

No push notifications sent

)}
)} {activeTab === 'notes' && (
{biker.notes.length > 0 ? ( biker.notes.map(note => (

{note.text}

{note.createdAt} {note.createdBy}
)) ) : (

No notes yet

)}
setNewNote(e.target.value)} placeholder="Add a note..." className="flex-1 px-3 py-2 border border-slate-200 rounded-lg text-sm" />
)} {activeTab === 'damage' && (
{biker.damageReports.length > 0 ? (
{biker.damageReports.map(report => (

{report.damageType}

{report.date} • {report.rentalId}

{report.severity} {report.status === 'Resolved' && } {report.status}

{report.description}

Bike

{report.bike}

Location

{report.location}

Estimated

৳{report.estimatedCost}

Actual

৳{report.actualCost || '-'}

{report.resolution && (

Resolution

{report.resolution}

)} {report.images.length > 0 && (
{report.images.map((img, idx) => ( {`Damage ))}
)}
))}
) : (

No damage reports

)}
{biker.damageReports.filter(r => r.images.length > 0).map(report => (

{report.date} - {report.damageType}

{report.images.map((img, idx) => ( {`Damage ))}
))} {biker.damageReports.filter(r => r.images.length > 0).length === 0 && (

No damage photos

)}
)}
{showMessageModal && (

Send Message to {biker.kyc.fullName}

{messageTab === 'template' ? (

Select a template to use:

{smsTemplates.map(tmpl => ( ))}
) : (