'use client'; import { useState, use } from 'react'; import Link from 'next/link'; import { useRouter, useSearchParams } from 'next/navigation'; import { Wrench, ArrowLeft, Bike, AlertTriangle, Calendar, DollarSign, Clock, CheckCircle, XCircle, Search, RefreshCw, ChevronLeft, ChevronRight, Eye, User, FileText, ArrowRight, ShieldAlert, Sparkles } from 'lucide-react'; interface HistoryRecord { id: string; date: string; type: 'damage' | 'maintenance' | 'service' | 'repair' | 'inspection'; severity: 'critical' | 'major' | 'minor' | 'cosmetic'; status: 'reported' | 'in_progress' | 'parts_ordered' | 'completed' | 'cancelled'; description: string; cost: number; reporter: string; resolvedAt?: string; partsUsed?: string[]; } export default function BikeMaintenanceHistoryPage({ params }: { params: Promise<{ id: string }> }) { const router = useRouter(); const searchParams = useSearchParams(); const bikeId = use(params).id; const fromRecord = searchParams.get('from'); // Realistic mock data for a specific bike's maintenance and damage history const [historyList] = useState(() => { return [ { id: 'MNT-001', date: '2024-03-21', type: 'damage', severity: 'major', status: 'in_progress', description: 'Front fender damaged in minor collision at Gulshan signal.', cost: 3200, reporter: 'Sofiq Rahman (Biker)', partsUsed: ['Front fender', 'Mounting brackets'] }, { id: 'MNT-005', date: '2024-03-17', type: 'inspection', severity: 'minor', status: 'completed', description: 'Monthly scheduled routine vehicle inspection.', cost: 250, reporter: 'Gulshan Hub Staff', resolvedAt: '2024-03-17', partsUsed: [] }, { id: 'MNT-012', date: '2024-02-10', type: 'repair', severity: 'critical', status: 'completed', description: 'Motor controller overheating check & throttle replacement.', cost: 7500, reporter: 'System Alert', resolvedAt: '2024-02-12', partsUsed: ['Throttle Assembly', 'Controller Fan'] }, { id: 'MNT-018', date: '2024-01-15', type: 'service', severity: 'minor', status: 'completed', description: 'Chain lubrication, brake shoe calibration, and mirror tightening.', cost: 600, reporter: 'Kamal Ahmed (Biker)', resolvedAt: '2024-01-15', partsUsed: ['Brake Shoe Set'] }, { id: 'MNT-022', date: '2023-12-05', type: 'damage', severity: 'cosmetic', status: 'completed', description: 'Side mirror cracked due to parking slip.', cost: 800, reporter: 'Kamal Ahmed (Biker)', resolvedAt: '2023-12-06', partsUsed: ['Left Side Mirror'] } ]; }); // Client Side Filter & Sorting States const [searchQuery, setSearchQuery] = useState(''); const [typeFilter, setTypeFilter] = useState('all'); const [statusFilter, setStatusFilter] = useState('all'); const [dateFrom, setDateFrom] = useState(''); const [dateTo, setDateTo] = useState(''); const [sortBy, setSortBy] = useState<'date' | 'cost' | 'severity'>('date'); const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc'); const [page, setPage] = useState(1); const pageSize = 5; const handleSort = (field: 'date' | 'cost' | 'severity') => { if (sortBy === field) { setSortOrder(prev => (prev === 'asc' ? 'desc' : 'asc')); } else { setSortBy(field); setSortOrder('desc'); } setPage(1); }; // Logic const filteredList = historyList.filter(item => { if (typeFilter !== 'all') { if (typeFilter === 'damage_all') { if (item.type !== 'damage') return false; } else if (typeFilter === 'damage_cosmetic') { if (item.type !== 'damage' || item.severity !== 'cosmetic') return false; } else if (typeFilter === 'damage_minor') { if (item.type !== 'damage' || item.severity !== 'minor') return false; } else if (typeFilter === 'damage_major') { if (item.type !== 'damage' || item.severity !== 'major') return false; } else if (typeFilter === 'damage_critical') { if (item.type !== 'damage' || item.severity !== 'critical') return false; } else if (typeFilter === 'maintenance_all') { if (item.type === 'damage') return false; } else if (typeFilter === 'maintenance_service') { if (item.type !== 'service') return false; } else if (typeFilter === 'maintenance_repair') { if (item.type !== 'repair') return false; } else if (typeFilter === 'maintenance_inspection') { if (item.type !== 'inspection') return false; } } if (statusFilter !== 'all' && item.status !== statusFilter) return false; if (searchQuery && !item.description.toLowerCase().includes(searchQuery.toLowerCase()) && !item.id.toLowerCase().includes(searchQuery.toLowerCase())) return false; if (dateFrom && new Date(item.date) < new Date(dateFrom)) return false; if (dateTo && new Date(item.date) > new Date(dateTo)) return false; return true; }); const sortedList = [...filteredList].sort((a, b) => { let comp = 0; if (sortBy === 'date') { comp = new Date(a.date).getTime() - new Date(b.date).getTime(); } else if (sortBy === 'cost') { comp = a.cost - b.cost; } else if (sortBy === 'severity') { const ranks = { critical: 4, major: 3, minor: 2, cosmetic: 1 }; comp = ranks[a.severity] - ranks[b.severity]; } return sortOrder === 'desc' ? -comp : comp; }); // Pagination const totalPages = Math.ceil(sortedList.length / pageSize); const paginatedList = sortedList.slice((page - 1) * pageSize, page * pageSize); // Status/Severity Badge Colors const severityColors = { critical: 'bg-red-100 text-red-700', major: 'bg-orange-100 text-orange-700', minor: 'bg-amber-100 text-amber-700', cosmetic: 'bg-slate-100 text-slate-700', }; const statusColors = { reported: 'bg-amber-50 text-amber-700 border border-amber-200', in_progress: 'bg-blue-50 text-blue-700 border border-blue-200', parts_ordered: 'bg-purple-50 text-purple-700 border border-purple-200', completed: 'bg-green-50 text-green-700 border border-green-200', cancelled: 'bg-red-50 text-red-700 border border-red-200', }; const totalCost = filteredList.reduce((sum, item) => sum + item.cost, 0); const criticalCount = filteredList.filter(item => item.severity === 'critical' || item.severity === 'major').length; return (
{/* Back navigation links */}

History Ledger

Viewing comprehensive damage & maintenance history for Bike {bikeId}

{/* Top Metrics Row */}

Total Events

{filteredList.length}

Major / Critical

{criticalCount}

Accumulated Cost

৳{totalCost.toLocaleString()}

Service Status

Healthy

{/* Main Ledger Content */}
{/* Advanced Filters */}
{ setSearchQuery(e.target.value); setPage(1); }} className="pl-9 pr-4 py-2 border border-slate-200 rounded-lg text-sm w-48 sm:w-64 bg-white focus:outline-none focus:border-slate-400 transition-colors" />
{ setDateFrom(e.target.value); setPage(1); }} className="px-3 py-2 border border-slate-200 rounded-lg text-sm bg-white" /> to { setDateTo(e.target.value); setPage(1); }} className="px-3 py-2 border border-slate-200 rounded-lg text-sm bg-white" />
{(dateFrom || dateTo || searchQuery || typeFilter !== 'all' || statusFilter !== 'all') && ( )}
{/* Desktop View */}
{paginatedList.length > 0 ? ( paginatedList.map(item => ( )) ) : ( )}
handleSort('date')} className="px-4 py-3 text-xs font-semibold text-slate-500 uppercase tracking-wider cursor-pointer hover:bg-slate-100 transition-colors" > Date {sortBy === 'date' && {sortOrder === 'asc' ? '↑' : '↓'}} Reference ID Type handleSort('severity')} className="px-4 py-3 text-xs font-semibold text-slate-500 uppercase tracking-wider cursor-pointer hover:bg-slate-100 transition-colors" > Severity {sortBy === 'severity' && {sortOrder === 'asc' ? '↑' : '↓'}} Description handleSort('cost')} className="px-4 py-3 text-xs font-semibold text-slate-500 uppercase tracking-wider cursor-pointer hover:bg-slate-100 transition-colors text-right" > Cost {sortBy === 'cost' && {sortOrder === 'asc' ? '↑' : '↓'}} Status Action
{item.date} {item.id} {item.type.replace('_', ' ')} {item.severity}

{item.description}

{item.partsUsed && item.partsUsed.length > 0 && (
{item.partsUsed.map(p => ( {p} ))}
)}
৳{item.cost.toLocaleString()} {item.status.replace('_', ' ')}

No maintenance logs found

{/* Mobile View */}
{paginatedList.length > 0 ? ( paginatedList.map(item => (
{item.id}

{item.type.replace('_', ' ')}

৳{item.cost.toLocaleString()} {item.status.replace('_', ' ')}

{item.description}

{item.date} Details
)) ) : (

No maintenance logs found

)}
{/* Footer Pagination */} {sortedList.length > pageSize && (

Showing {((page - 1) * pageSize) + 1} to {Math.min(page * pageSize, sortedList.length)} of {sortedList.length} records

{Array.from({ length: totalPages }, (_, i) => i + 1).map(pageNum => ( ))}
)}
); }