'use client'; import { useState, use } from 'react'; import Link from 'next/link'; import { Bike, Search, Filter, Plus, MoreVertical, MapPin, Battery, User, Wrench, Eye, Edit, Trash2, X, Download, Upload, MoreHorizontal, CheckCircle, XCircle, AlertTriangle, Calendar, DollarSign, Clock, Navigation, Car, LayoutGrid, List, Gauge, FileText, Shield, Zap, GaugeCircle, Map } from 'lucide-react'; interface Bike { id: string; model: string; brand: string; image: string; plateNumber: string; status: 'available' | 'rented' | 'maintenance' | 'retired'; batteryLevel: number; location: string; assignedTo?: string; investorId?: string; purchaseDate?: string; purchasePrice?: number; currentRent?: number; totalRides?: number; totalDistance?: number; lastService?: string; nextService?: string; insuranceExpiry?: string; registrationExpiry?: string; notes?: string; } const mockBikes: Bike[] = [ { id: 'EV001', model: 'Etron ET50', brand: 'Etron', image: '', plateNumber: 'Dhaka Metro Cha-A-1234', status: 'rented', batteryLevel: 78, location: 'Gulshan 1', assignedTo: 'Rahim Ahmed', investorId: 'inv1', purchaseDate: '2024-01-15', purchasePrice: 125000, currentRent: 350, totalRides: 156, totalDistance: 2340, lastService: '2024-03-01', nextService: '2024-04-01', insuranceExpiry: '2025-01-15', registrationExpiry: '2026-01-15' }, { id: 'EV002', model: 'Yadea DT3', brand: 'Yadea', image: '', plateNumber: 'Dhaka Metro Cha-A-5678', status: 'available', batteryLevel: 95, location: 'Banani', purchaseDate: '2024-02-01', purchasePrice: 118000, totalRides: 89, totalDistance: 1567, lastService: '2024-03-15', nextService: '2024-04-15', insuranceExpiry: '2025-02-01', registrationExpiry: '2026-02-01' }, { id: 'EV003', model: 'AIMA Lightning', brand: 'AIMA', image: '', plateNumber: 'Dhaka Metro Cha-A-9012', status: 'rented', batteryLevel: 62, location: 'Uttara', assignedTo: 'Karim Singh', investorId: 'inv1', purchaseDate: '2024-01-20', purchasePrice: 132000, currentRent: 400, totalRides: 203, totalDistance: 3890, lastService: '2024-03-10', nextService: '2024-04-10', insuranceExpiry: '2025-01-20', registrationExpiry: '2026-01-20' }, { id: 'EV004', model: 'TVS iQube', brand: 'TVS', image: '', plateNumber: 'Dhaka Metro Cha-A-3456', status: 'maintenance', batteryLevel: 45, location: 'Workshop - Banani', purchaseDate: '2023-12-10', purchasePrice: 145000, totalRides: 312, totalDistance: 5670, lastService: '2024-03-20', nextService: '2024-03-25', insuranceExpiry: '2024-12-10', registrationExpiry: '2025-12-10', notes: 'Motor issue - awaiting parts' }, { id: 'EV005', model: 'Bajaj Chetak', brand: 'Bajaj', image: '', plateNumber: 'Dhaka Metro Cha-A-7890', status: 'available', batteryLevel: 100, location: 'Dhanmondi', purchaseDate: '2024-02-15', purchasePrice: 138000, totalRides: 67, totalDistance: 890, lastService: '2024-03-18', nextService: '2024-04-18', insuranceExpiry: '2025-02-15', registrationExpiry: '2026-02-15' }, { id: 'EV006', model: 'Hero Eddy', brand: 'Hero', image: '', plateNumber: 'Dhaka Metro Cha-B-1122', status: 'rented', batteryLevel: 88, location: 'Mirpur 1', assignedTo: 'Mahir Khan', investorId: 'inv2', purchaseDate: '2024-01-05', purchasePrice: 115000, currentRent: 320, totalRides: 178, totalDistance: 2890, lastService: '2024-03-05', nextService: '2024-04-05', insuranceExpiry: '2025-01-05', registrationExpiry: '2026-01-05' }, { id: 'EV007', model: 'Okinawa Ridge', brand: 'Okinawa', image: '', plateNumber: 'Dhaka Metro Cha-B-3344', status: 'available', batteryLevel: 92, location: 'Gulshan 2', purchaseDate: '2024-02-20', purchasePrice: 122000, totalRides: 45, totalDistance: 567, lastService: '2024-03-20', nextService: '2024-04-20', insuranceExpiry: '2025-02-20', registrationExpiry: '2026-02-20' }, { id: 'EV008', model: 'Ampere Magnus', brand: 'Ampere', image: '', plateNumber: 'Dhaka Metro Cha-B-5566', status: 'maintenance', batteryLevel: 15, location: 'Workshop - Dhanmondi', purchaseDate: '2023-11-01', purchasePrice: 98000, totalRides: 234, totalDistance: 4120, lastService: '2024-03-22', nextService: '2024-03-27', insuranceExpiry: '2024-11-01', registrationExpiry: '2025-11-01', notes: 'Battery replacement needed' }, { id: 'EV009', model: 'JME Victory', brand: 'JME', image: '', plateNumber: 'Dhaka Metro Cha-B-7788', status: 'retired', batteryLevel: 0, location: 'Warehouse', purchaseDate: '2023-06-15', purchasePrice: 145000, totalRides: 567, totalDistance: 8900, lastService: '2024-01-10', insuranceExpiry: '2024-06-15', registrationExpiry: '2025-06-15', notes: 'Old vehicle - for scrap' }, { id: 'EV010', model: 'Benling Aura', brand: 'Benling', image: '', plateNumber: 'Dhaka Metro Cha-C-9900', status: 'rented', batteryLevel: 71, location: 'Banani', assignedTo: 'Ovi Rahman', investorId: 'inv1', purchaseDate: '2024-02-10', purchasePrice: 128000, currentRent: 380, totalRides: 112, totalDistance: 1890, lastService: '2024-03-12', nextService: '2024-04-12', insuranceExpiry: '2025-02-10', registrationExpiry: '2026-02-10' }, { id: 'EV011', model: 'Lectrix LXS', brand: 'Lectrix', image: '', plateNumber: 'Dhaka Metro Cha-C-1235', status: 'available', batteryLevel: 98, location: 'Uttara 11', purchaseDate: '2024-03-01', purchasePrice: 135000, totalRides: 23, totalDistance: 345, lastService: '2024-03-21', nextService: '2024-04-21', insuranceExpiry: '2025-03-01', registrationExpiry: '2026-03-01' }, { id: 'EV012', model: 'Revolt RV400', brand: 'Revolt', image: '', plateNumber: 'Dhaka Metro Cha-C-5679', status: 'rented', batteryLevel: 55, location: 'Dhanmondi', assignedTo: 'Tashrif Islam', investorId: 'inv2', purchaseDate: '2024-01-25', purchasePrice: 150000, currentRent: 420, totalRides: 198, totalDistance: 3560, lastService: '2024-03-08', nextService: '2024-04-08', insuranceExpiry: '2025-01-25', registrationExpiry: '2026-01-25' }, ]; const statusColors: Record = { available: 'bg-green-100 text-green-700', rented: 'bg-blue-100 text-blue-700', maintenance: 'bg-amber-100 text-amber-700', retired: 'bg-slate-100 text-slate-500', }; export default function FleetPage() { const [bikes, setBikes] = useState(mockBikes); const [searchQuery, setSearchQuery] = useState(''); const [statusFilter, setStatusFilter] = useState('all'); const [locationFilter, setLocationFilter] = useState('all'); const [selectedBike, setSelectedBike] = useState(null); const [showModal, setShowModal] = useState(false); const [showDetailsModal, setShowDetailsModal] = useState(false); const [editingBike, setEditingBike] = useState(null); const [viewMode, setViewMode] = useState<'table' | 'cards' | 'map'>('table'); const [selectedMapBike, setSelectedMapBike] = useState(null); const availableCount = bikes.filter(b => b.status === 'available').length; const rentedCount = bikes.filter(b => b.status === 'rented').length; const maintenanceCount = bikes.filter(b => b.status === 'maintenance').length; const retiredCount = bikes.filter(b => b.status === 'retired').length; const locations = [...new Set(bikes.map(b => b.location))]; const filteredBikes = bikes.filter(bike => { const matchesSearch = bike.model.toLowerCase().includes(searchQuery.toLowerCase()) || bike.brand.toLowerCase().includes(searchQuery.toLowerCase()) || bike.plateNumber.toLowerCase().includes(searchQuery.toLowerCase()) || bike.id.toLowerCase().includes(searchQuery.toLowerCase()); const matchesStatus = statusFilter === 'all' || bike.status === statusFilter; const matchesLocation = locationFilter === 'all' || bike.location === locationFilter; return matchesSearch && matchesStatus && matchesLocation; }); const handleAddBike = () => { setEditingBike(null); setShowModal(true); }; const handleEditBike = (bike: Bike) => { setEditingBike(bike); setShowModal(true); }; const handleViewDetails = (bike: Bike) => { setSelectedBike(bike); setShowDetailsModal(true); }; const handleDeleteBike = (id: string) => { if (confirm('Are you sure you want to delete this bike?')) { setBikes(bikes.filter(b => b.id !== id)); } }; const handleSaveBike = (bike: Bike) => { if (editingBike) { setBikes(bikes.map(b => b.id === editingBike.id ? bike : b)); } else { setBikes([...bikes, { ...bike, id: `EV${String(bikes.length + 1).padStart(3, '0')}` }]); } setShowModal(false); }; return (

Fleet Management

Manage your EV bike inventory

{/*
*/}
Map View
{selectedMapBike && (
setSelectedMapBike(null)}>
e.stopPropagation()}>

{selectedMapBike.model}

{selectedMapBike.brand} • {selectedMapBike.id}

{selectedMapBike.status}
Plate {selectedMapBike.plateNumber}
Location {selectedMapBike.location}
Battery 50 ? 'text-green-600' : selectedMapBike.batteryLevel > 20 ? 'text-amber-600' : 'text-red-600' }`}>{selectedMapBike.batteryLevel}%
Daily Rate ৳{selectedMapBike.currentRent || 0}
View Details
)}

{availableCount}

Available

{rentedCount}

Rented

{maintenanceCount}

Maintenance

{retiredCount}

Retired

setSearchQuery(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent" />
{viewMode === 'table' ? (
{filteredBikes.map(bike => ( ))}
Bike Plate Number Location Battery Metrics Status Actions

{bike.model}

{bike.brand} • {bike.id}

{bike.plateNumber}

{bike.location}

50 ? 'text-green-600' : bike.batteryLevel > 20 ? 'text-amber-600' : 'text-red-600'}`} /> 50 ? 'text-green-600' : bike.batteryLevel > 20 ? 'text-amber-600' : 'text-red-600'}`}>{bike.batteryLevel}%

{bike.totalRides || 0} rides

{(bike.totalDistance || 0).toLocaleString()} km

{bike.status}
) : (
{filteredBikes.map(bike => (

{bike.model}

{bike.brand} • {bike.id}

Plate {bike.plateNumber}
Location {bike.location}
Battery 50 ? 'text-green-600' : bike.batteryLevel > 20 ? 'text-amber-600' : 'text-red-600'}`}>{bike.batteryLevel}%
Total Rides {bike.totalRides || 0}
{bike.status} ))}
)}

Showing 1 to {filteredBikes.length} of {bikes.length} bikes

{/* Add/Edit Modal */} {showModal && (

{editingBike ? 'Edit Bike' : 'Register New Bike'}

setShowModal(false)} />
)} {/* Details Modal */} {showDetailsModal && selectedBike && (

Bike Details

)}
); } function BikeForm({ bike, onSave, onCancel }: { bike: Bike | null; onSave: (bike: Bike) => void; onCancel: () => void }) { const [formData, setFormData] = useState(bike || { id: '', model: '', brand: '', image: '', plateNumber: '', status: 'available', batteryLevel: 100, location: '', assignedTo: undefined, investorId: undefined, purchaseDate: new Date().toISOString().split('T')[0], purchasePrice: 0, totalRides: 0, totalDistance: 0, insuranceExpiry: '', registrationExpiry: '', }); const handleChange = (field: keyof Bike, value: any) => { setFormData({ ...formData, [field]: value }); }; return (
handleChange('id', e.target.value)} placeholder="EV001" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-accent" disabled={!!bike} />
handleChange('brand', e.target.value)} placeholder="Etron" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-accent" />
handleChange('model', e.target.value)} placeholder="ET50" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-accent" />
handleChange('plateNumber', e.target.value)} placeholder="Dhaka Metro Cha-A-1234" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-accent" />
handleChange('batteryLevel', parseInt(e.target.value))} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-accent" />
handleChange('location', e.target.value)} placeholder="Gulshan 1" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-accent" />
handleChange('assignedTo', e.target.value)} placeholder="Biker Name" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-accent" />
handleChange('purchaseDate', e.target.value)} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-accent" />
handleChange('purchasePrice', parseInt(e.target.value))} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-accent" />
handleChange('insuranceExpiry', e.target.value)} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-accent" />
handleChange('registrationExpiry', e.target.value)} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-accent" />
); } function BikeDetails({ bike }: { bike: Bike }) { return (

{bike.model}

{bike.brand} • {bike.id}

{bike.status}

Plate Number

{bike.plateNumber}

Battery Level

50 ? 'text-green-600' : bike.batteryLevel > 20 ? 'text-amber-600' : 'text-red-600'}`}>{bike.batteryLevel}%

Location

{bike.location}

Assigned To

{bike.assignedTo || 'Unassigned'}

Performance Metrics

Total Rides

{bike.totalRides || 0}

Distance

{(bike.totalDistance || 0).toLocaleString()} km

Daily Rent

৳{bike.currentRent || 0}

Purchase Price

৳{bike.purchasePrice?.toLocaleString() || 0}

Maintenance Info

Last Service

{bike.lastService || 'N/A'}

Next Service

{bike.nextService || 'N/A'}

Insurance Expiry

{bike.insuranceExpiry || 'N/A'}

Registration Expiry

{bike.registrationExpiry || 'N/A'}

{bike.notes && (

Notes

{bike.notes}

)}
); } function FleetMap({ bikes, onSelectBike, selectedBike, large }: { bikes: Bike[]; onSelectBike: (bike: Bike) => void; selectedBike: Bike | null, large?: boolean }) { const locationCounts: Record = {}; bikes.forEach(bike => { const loc = bike.location; if (!locationCounts[loc]) { const locations: Record = { 'Gulshan 1': { lat: 23.7936, lng: 90.4061 }, 'Banani': { lat: 23.7983, lng: 90.4071 }, 'Uttara': { lat: 23.8304, lng: 90.4034 }, 'Uttara 11': { lat: 23.8547, lng: 90.4016 }, 'Dhanmondi': { lat: 23.7465, lng: 90.3762 }, 'Mirpur 1': { lat: 23.8090, lng: 90.3706 }, 'Gulshan 2': { lat: 23.7917, lng: 90.4175 }, 'Workshop - Banani': { lat: 23.7965, lng: 90.4050 }, 'Workshop - Dhanmondi': { lat: 23.7438, lng: 90.3738 }, 'Warehouse': { lat: 23.7880, lng: 90.3900 }, }; locationCounts[loc] = { bikes: [], lat: locations[loc]?.lat || 23.7936, lng: locations[loc]?.lng || 90.4061 }; } locationCounts[loc].bikes.push(bike); }); // Simple coordinate mapper for Dhaka-ish area const getCoords = (lat: number, lng: number) => { // Zoom factor based on whether it's the large view const xMultiplier = large ? 700 : 500; const yMultiplier = large ? 600 : 400; const x = (lng - 90.35) * xMultiplier; const y = (23.88 - lat) * yMultiplier; return { x, y }; }; return (
{/* Subtle map pattern */} {/* Simple river-like shapes for "map" look */} {(Object.entries(locationCounts) as [string, { bikes: Bike[]; lat: number; lng: number }][]).map(([loc, data]) => { const { x, y } = getCoords(data.lat, data.lng); const isSelected = data.bikes.some(b => b.id === selectedBike?.id); return ( onSelectBike(data.bikes[0])} className="cursor-pointer"> {/* Glow for selected/multiple */} {/* Marker body */} {/* Center dot or number */} {data.bikes.length > 1 && ( {data.bikes.length} )} {large && ( {loc} )} ); })}
{!large && (
{bikes.filter(b => b.status === 'available').length}
{bikes.filter(b => b.status === 'rented').length}
)} {large && (
)}
); }