Compare commits

...

2 Commits

3 changed files with 586 additions and 282 deletions

View File

@@ -862,7 +862,7 @@ export default function BikerDetailPage() {
<ArrowLeft className="w-4 h-4" /> Back to Bikers <ArrowLeft className="w-4 h-4" /> Back to Bikers
</button> </button>
<div className="bg-white rounded-xl shadow-sm border border-slate-100 overflow-hidden mb-4"> <div className="bg-white rounded-xl shadow-sm border border-slate-100 overflow-hidden mb-8">
<div className="p-4 lg:p-6 flex flex-col lg:flex-row lg:items-center gap-4"> <div className="p-4 lg:p-6 flex flex-col lg:flex-row lg:items-center gap-4">
<div className="relative group"> <div className="relative group">
{biker.profileImage ? ( {biker.profileImage ? (

View File

@@ -7,7 +7,7 @@ import {
MapPin, FileText, Image, DollarSign, Wrench, Battery, Key, MapPin, FileText, Image, DollarSign, Wrench, Battery, Key,
CheckCircle, XCircle, ChevronLeft, Save, Printer, Send, QrCode, CheckCircle, XCircle, ChevronLeft, Save, Printer, Send, QrCode,
Wallet, Building, Edit, MessageSquare, Calendar, ArrowLeft, Trash2, Wallet, Building, Edit, MessageSquare, Calendar, ArrowLeft, Trash2,
Package, Settings Package, Settings, History, ArrowRight
} from 'lucide-react'; } from 'lucide-react';
import Link from 'next/link'; import Link from 'next/link';
@@ -284,7 +284,6 @@ export default function MaintenanceDetailPage() {
const [showInvoiceModal, setShowInvoiceModal] = useState(false); const [showInvoiceModal, setShowInvoiceModal] = useState(false);
const [showAddNoteModal, setShowAddNoteModal] = useState(false); const [showAddNoteModal, setShowAddNoteModal] = useState(false);
const [showAddPartModal, setShowAddPartModal] = useState(false); const [showAddPartModal, setShowAddPartModal] = useState(false);
const [showAddServiceCostModal, setShowAddServiceCostModal] = useState(false);
const [partSearch, setPartSearch] = useState(''); const [partSearch, setPartSearch] = useState('');
const [invoiceData, setInvoiceData] = useState({ tips: 0, discount: 0 }); const [invoiceData, setInvoiceData] = useState({ tips: 0, discount: 0 });
const [invoiceCreated, setInvoiceCreated] = useState(false); const [invoiceCreated, setInvoiceCreated] = useState(false);
@@ -295,7 +294,6 @@ export default function MaintenanceDetailPage() {
const [actualCost, setActualCost] = useState(''); const [actualCost, setActualCost] = useState('');
const [selectedPart, setSelectedPart] = useState<EVPart | null>(null); const [selectedPart, setSelectedPart] = useState<EVPart | null>(null);
const [partQuantity, setPartQuantity] = useState(1); const [partQuantity, setPartQuantity] = useState(1);
const [serviceCostInput, setServiceCostInput] = useState('');
useEffect(() => { useEffect(() => {
const found = mockMaintenance.find(r => r.id === id); const found = mockMaintenance.find(r => r.id === id);
@@ -457,12 +455,12 @@ export default function MaintenanceDetailPage() {
<ArrowLeft className="w-4 h-4" /> Back to Maintenance <ArrowLeft className="w-4 h-4" /> Back to Maintenance
</button> </button>
<div className="bg-white rounded-xl shadow-sm border border-slate-100 overflow-hidden"> <div className="bg-white rounded-xl shadow-sm border border-slate-100 overflow-hidden mb-12 lg:mb-0">
<div className="p-6 border-b border-slate-100"> <div className="p-6 border-b border-slate-100">
<div className="flex flex-col lg:flex-row lg:items-start lg:justify-between gap-4"> <div className="flex flex-col lg:flex-row lg:items-start lg:justify-between gap-4">
<div> <div className="min-w-0">
<div className="flex items-center gap-3"> <div className="flex flex-wrap items-center gap-2">
<h1 className="text-2xl font-extrabold text-slate-800">{record.id}</h1> <h1 className="text-xl lg:text-2xl font-extrabold text-slate-800">{record.id}</h1>
<span className={`inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full ${severityColors[record.severity]}`}> <span className={`inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full ${severityColors[record.severity]}`}>
{record.severity} {record.severity}
</span> </span>
@@ -475,7 +473,7 @@ export default function MaintenanceDetailPage() {
</div> </div>
<p className="text-slate-500 mt-1">{typeLabels[record.type]} {record.date}</p> <p className="text-slate-500 mt-1">{typeLabels[record.type]} {record.date}</p>
</div> </div>
<div className="flex gap-2"> <div className="flex flex-wrap gap-2">
{editMode ? ( {editMode ? (
<> <>
<button onClick={handleSaveEdit} className="px-4 py-2 bg-green-600 text-white rounded-lg text-sm hover:bg-green-700 flex items-center gap-2"> <button onClick={handleSaveEdit} className="px-4 py-2 bg-green-600 text-white rounded-lg text-sm hover:bg-green-700 flex items-center gap-2">
@@ -619,6 +617,48 @@ export default function MaintenanceDetailPage() {
)} )}
</div> </div>
<div className="bg-orange-50 p-4 rounded-xl border border-orange-100">
<h3 className="font-semibold text-orange-800 mb-3 flex items-center gap-2">
<History className="w-5 h-5" /> Issue History
</h3>
<div className="space-y-2">
{record.batteryId && (
<Link
href={`/admin/batteries/${record.batteryId}`}
className="flex items-center justify-between p-2 bg-white rounded-lg hover:bg-orange-50 transition-colors"
>
<div className="flex items-center gap-2">
<Battery className="w-4 h-4 text-green-600" />
<span className="text-sm text-slate-700">Battery History</span>
</div>
<ArrowRight className="w-4 h-4 text-orange-400" />
</Link>
)}
{record.bikeId && (
<Link
href={`/admin/fleet/${record.bikeId}`}
className="flex items-center justify-between p-2 bg-white rounded-lg hover:bg-orange-50 transition-colors"
>
<div className="flex items-center gap-2">
<Bike className="w-4 h-4 text-purple-600" />
<span className="text-sm text-slate-700">Fleet History</span>
</div>
<ArrowRight className="w-4 h-4 text-orange-400" />
</Link>
)}
<Link
href="/admin/maintenance"
className="flex items-center justify-between p-2 bg-white rounded-lg hover:bg-orange-50 transition-colors"
>
<div className="flex items-center gap-2">
<Wrench className="w-4 h-4 text-blue-600" />
<span className="text-sm text-slate-700">All Maintenance</span>
</div>
<ArrowRight className="w-4 h-4 text-orange-400" />
</Link>
</div>
</div>
<div className="bg-green-50 p-4 rounded-xl border border-green-100"> <div className="bg-green-50 p-4 rounded-xl border border-green-100">
<h3 className="font-semibold text-green-800 mb-3 flex items-center gap-2"> <h3 className="font-semibold text-green-800 mb-3 flex items-center gap-2">
<User className="w-5 h-5" /> Reporter <User className="w-5 h-5" /> Reporter
@@ -790,8 +830,10 @@ export default function MaintenanceDetailPage() {
</button> </button>
)} )}
</div> </div>
<div className="space-y-2"> <div className="space-y-3">
{(record.partsUsed || []).length > 0 ? ( {record.partsUsed && record.partsUsed.length > 0 ? (
<>
<div className="hidden lg:block overflow-x-auto">
<table className="w-full text-sm"> <table className="w-full text-sm">
<thead className="bg-orange-100"> <thead className="bg-orange-100">
<tr> <tr>
@@ -843,19 +885,67 @@ export default function MaintenanceDetailPage() {
</tr> </tr>
))} ))}
</tbody> </tbody>
<tfoot className="bg-orange-50">
<tr>
<td colSpan={3} className="px-3 py-2 text-right font-semibold text-orange-800">Parts Total:</td>
<td className="px-3 py-2 text-right font-bold text-orange-700">
{record.partsUsed?.reduce((sum, p) => sum + p.totalPrice, 0).toLocaleString()}
</td>
<td></td>
</tr>
</tfoot>
</table> </table>
</div>
<div className="lg:hidden grid grid-cols-1 sm:grid-cols-2 gap-3">
{record.partsUsed.map((part) => (
<div key={part.id} className="bg-white rounded-lg border border-orange-200 p-3">
<div className="flex items-start justify-between mb-2">
<span className="font-medium text-slate-800">{part.partName}</span>
<button
onClick={() => {
setRecord(prev => prev ? {
...prev,
partsUsed: prev.partsUsed?.filter(p => p.id !== part.id)
} : null);
}}
className="text-red-400 hover:text-red-600 p-1"
>
<Trash2 className="w-4 h-4" />
</button>
</div>
<div className="flex items-center justify-between text-sm mb-2">
<div className="flex items-center gap-2">
<span className="text-slate-500">Qty:</span>
<input
type="number"
min="1"
value={part.quantity}
onChange={(e) => {
const newQty = Math.max(1, parseInt(e.target.value) || 1);
setRecord(prev => prev ? {
...prev,
partsUsed: prev.partsUsed?.map(p =>
p.id === part.id
? { ...p, quantity: newQty, totalPrice: newQty * p.unitPrice }
: p
)
} : null);
}}
className="w-16 px-2 py-1 border border-orange-200 rounded text-center text-sm"
/>
</div>
<span className="text-slate-600">{part.unitPrice.toLocaleString()}/unit</span>
</div>
<div className="pt-2 border-t border-orange-100 flex justify-between">
<span className="text-xs text-slate-500">Total</span>
<span className="font-bold text-orange-700">{part.totalPrice.toLocaleString()}</span>
</div>
</div>
))}
</div>
</>
) : ( ) : (
<p className="text-sm text-orange-400">No parts added</p> <p className="text-sm text-orange-400">No parts added</p>
)} )}
{record.partsUsed && record.partsUsed.length > 0 && (
<div className="bg-orange-50 rounded-lg p-3 flex justify-between items-center">
<span className="font-semibold text-orange-800">Parts Total:</span>
<span className="text-lg font-bold text-orange-700">
{record.partsUsed.reduce((sum, p) => sum + p.totalPrice, 0).toLocaleString()}
</span>
</div>
)}
</div> </div>
@@ -922,17 +1012,22 @@ export default function MaintenanceDetailPage() {
</div> </div>
<div className="p-4 space-y-4"> <div className="p-4 space-y-4">
<div className="bg-slate-50 p-3 rounded-lg"> <div className="bg-slate-50 p-3 rounded-lg">
<div className="flex justify-between text-sm mb-2">
<span className="text-slate-500">Estimated Cost:</span>
<span className="font-medium text-slate-600">{record.estimatedCost.toLocaleString()}</span>
</div>
<div className="flex justify-between text-sm mb-2"> <div className="flex justify-between text-sm mb-2">
<span className="text-slate-500">Parts Total:</span> <span className="text-slate-500">Parts Total:</span>
<span className="font-medium text-orange-600">{record.partsUsed?.reduce((s, p) => s + p.totalPrice, 0).toLocaleString()}</span> <span className="font-medium text-orange-600">{record.partsUsed?.reduce((s, p) => s + p.totalPrice, 0).toLocaleString()}</span>
</div> </div>
<div className="flex justify-between text-sm mb-2"> <div>
<span className="text-slate-500">Service Cost (Labor):</span> <label className="text-xs font-medium text-blue-600 mb-1 block">Service Cost (Labor)</label>
<span className="font-medium text-blue-600">{(record.serviceCost || 0).toLocaleString()}</span> <div className="flex gap-2">
<input
type="number"
min="0"
value={record.serviceCost || ''}
onChange={(e) => setRecord(prev => prev ? { ...prev, serviceCost: parseInt(e.target.value) || 0 } : null)}
className="flex-1 px-3 py-2 border border-blue-200 rounded-lg text-sm"
placeholder="Enter labor cost"
/>
</div>
</div> </div>
</div> </div>
@@ -1256,59 +1351,6 @@ export default function MaintenanceDetailPage() {
</div> </div>
)} )}
<div className="fixed bottom-4 right-4 z-40">
<button
onClick={() => setShowAddServiceCostModal(true)}
className="px-4 py-3 bg-blue-600 text-white rounded-full shadow-lg hover:bg-blue-700 flex items-center gap-2"
>
<DollarSign className="w-5 h-5" /> Add Service Cost
</button>
</div>
{showAddServiceCostModal && (
<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-sm">
<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">
<Wrench className="w-5 h-5 text-blue-600" /> Add Service Cost
</h3>
<button onClick={() => setShowAddServiceCostModal(false)} className="text-slate-400 hover:text-slate-600">
<X className="w-5 h-5" />
</button>
</div>
<div className="p-4 space-y-4">
<div>
<label className="text-sm font-medium text-slate-600 mb-1 block">Service Cost (Labor charge)</label>
<input
type="number"
value={serviceCostInput}
onChange={(e) => setServiceCostInput(e.target.value)}
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-lg"
placeholder="Enter service cost"
/>
</div>
<div className="bg-slate-50 p-3 rounded-lg">
<p className="text-sm text-slate-600">Current Service Cost: <span className="font-bold text-blue-600">{record?.serviceCost || 0}</span></p>
</div>
</div>
<div className="p-4 border-t border-slate-100 flex justify-end gap-2">
<button onClick={() => setShowAddServiceCostModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg">Cancel</button>
<button
onClick={() => {
const cost = parseFloat(serviceCostInput) || 0;
setRecord(prev => prev ? { ...prev, serviceCost: cost } : null);
setShowAddServiceCostModal(false);
setServiceCostInput('');
}}
className="px-4 py-2 bg-blue-600 text-white rounded-lg flex items-center gap-2"
>
<Plus className="w-4 h-4" /> Add Cost
</button>
</div>
</div>
</div>
)}
{showPaymentSuccess && ( {showPaymentSuccess && (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4"> <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="bg-white rounded-xl shadow-xl w-full max-w-md">

View File

@@ -1,13 +1,14 @@
'use client'; 'use client';
import Link from 'next/link'; import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { useState } from 'react'; import { useState } from 'react';
import { import {
AlertTriangle, Search, Plus, X, Check, Clock, Bike, User, Phone, AlertTriangle, Search, Plus, X, Check, Clock, Bike, User, Phone,
MapPin, FileText, Image, DollarSign, Wrench, Battery, Key, MapPin, FileText, Image as ImageIcon, DollarSign, Wrench, Battery, Key,
CheckCircle, XCircle, ChevronDown, ChevronUp, Download, Eye, Edit, CheckCircle, XCircle, ChevronDown, ChevronUp, Download, Eye, Edit,
MessageSquare, Filter, Calendar, Save, Printer, Send MessageSquare, Filter, Calendar, Save, Printer, Send, Activity
} from 'lucide-react'; } from 'lucide-react';
type TransactionType = 'deposit' | 'rent_income' | 'investor_funding' | 'investor_withdraw' | 'salary' | 'rent_expense' | 'utility' | 'maintenance' | 'bike_purchase' | 'bike_sale' | 'other_income' | 'other_expense'; type TransactionType = 'deposit' | 'rent_income' | 'investor_funding' | 'investor_withdraw' | 'salary' | 'rent_expense' | 'utility' | 'maintenance' | 'bike_purchase' | 'bike_sale' | 'other_income' | 'other_expense';
@@ -245,7 +246,9 @@ const typeIcons: Record<string, any> = {
}; };
export default function MaintenancePage() { export default function MaintenancePage() {
const [activeTab, setActiveTab] = useState<'all' | MaintenanceType>('all'); const router = useRouter();
const [mainCategory, setMainCategory] = useState<'damage' | 'maintenance'>('damage');
const [targetType, setTargetType] = useState<'all' | 'battery' | 'fleet'>('all');
const [records, setRecords] = useState<MaintenanceRecord[]>(mockMaintenance); const [records, setRecords] = useState<MaintenanceRecord[]>(mockMaintenance);
const [searchQuery, setSearchQuery] = useState(''); const [searchQuery, setSearchQuery] = useState('');
const [statusFilter, setStatusFilter] = useState('all'); const [statusFilter, setStatusFilter] = useState('all');
@@ -259,20 +262,45 @@ export default function MaintenancePage() {
const [expandedNotes, setExpandedNotes] = useState<string[]>([]); const [expandedNotes, setExpandedNotes] = useState<string[]>([]);
const [newNoteText, setNewNoteText] = useState(''); const [newNoteText, setNewNoteText] = useState('');
const [editForm, setEditForm] = useState<Partial<MaintenanceRecord>>({}); const [editForm, setEditForm] = useState<Partial<MaintenanceRecord>>({});
const [reportType, setReportType] = useState<'damage' | 'maintenance'>('damage');
const [showSuccessModal, setShowSuccessModal] = useState(false);
const filteredRecords = records.filter(r => { const filteredRecords = records.filter(r => {
const matchesTab = activeTab === 'all' || r.type === activeTab; const isDamage = r.type === 'damage';
const matchesCategory = mainCategory === 'damage' ? isDamage : !isDamage;
const matchesTarget = targetType === 'all' ||
(targetType === 'battery' && r.batteryId) ||
(targetType === 'fleet' && r.bikeId && !r.batteryId);
const matchesSearch = !searchQuery || const matchesSearch = !searchQuery ||
r.bikeId.toLowerCase().includes(searchQuery.toLowerCase()) || r.bikeId.toLowerCase().includes(searchQuery.toLowerCase()) ||
r.bikeModel.toLowerCase().includes(searchQuery.toLowerCase()) || r.bikeModel.toLowerCase().includes(searchQuery.toLowerCase()) ||
r.bikePlate.toLowerCase().includes(searchQuery.toLowerCase()) || r.bikePlate.toLowerCase().includes(searchQuery.toLowerCase()) ||
r.reporterName.toLowerCase().includes(searchQuery.toLowerCase()) || r.reporterName.toLowerCase().includes(searchQuery.toLowerCase()) ||
r.id.toLowerCase().includes(searchQuery.toLowerCase()); r.id.toLowerCase().includes(searchQuery.toLowerCase()) ||
(r.batteryId && r.batteryId.toLowerCase().includes(searchQuery.toLowerCase()));
const matchesStatus = statusFilter === 'all' || r.status === statusFilter; const matchesStatus = statusFilter === 'all' || r.status === statusFilter;
return matchesTab && matchesSearch && matchesStatus; return matchesCategory && matchesTarget && matchesSearch && matchesStatus;
}); });
const damageRecords = records.filter(r => r.type === 'damage');
const maintenanceRecords = records.filter(r => r.type !== 'damage');
const currentMonth = new Date().toISOString().slice(0, 7);
const stats = { const stats = {
damageCount: damageRecords.length,
maintenanceCount: maintenanceRecords.length,
damageThisMonth: damageRecords.filter(r => r.date?.slice(0, 7) === currentMonth).length,
maintenanceThisMonth: maintenanceRecords.filter(r => r.date?.slice(0, 7) === currentMonth).length,
completedThisMonth: records.filter(r => r.status === 'completed' && r.resolvedAt?.slice(0, 7) === currentMonth).length,
batteryDamage: damageRecords.filter(r => r.batteryId).length,
fleetDamage: damageRecords.filter(r => r.bikeId && !r.batteryId).length,
batteryMaintenance: maintenanceRecords.filter(r => r.batteryId).length,
fleetMaintenance: maintenanceRecords.filter(r => r.bikeId && !r.batteryId).length,
upcomingBattery: maintenanceRecords.filter(r => r.batteryId && r.status === 'reported').length,
upcomingFleet: maintenanceRecords.filter(r => r.bikeId && !r.batteryId && r.status === 'reported').length,
ongoingBattery: maintenanceRecords.filter(r => r.batteryId && r.status === 'in_progress').length,
ongoingFleet: maintenanceRecords.filter(r => r.bikeId && !r.batteryId && r.status === 'in_progress').length,
pendingMaintenance: maintenanceRecords.filter(r => r.status === 'reported' || r.status === 'in_progress').length,
completedMaintenance: maintenanceRecords.filter(r => r.status === 'completed').length,
critical: records.filter(r => r.severity === 'critical' && r.status !== 'completed').length, critical: records.filter(r => r.severity === 'critical' && r.status !== 'completed').length,
inProgress: records.filter(r => r.status === 'in_progress' || r.status === 'parts_ordered').length, inProgress: records.filter(r => r.status === 'in_progress' || r.status === 'parts_ordered').length,
completed: records.filter(r => r.status === 'completed').length, completed: records.filter(r => r.status === 'completed').length,
@@ -397,7 +425,7 @@ export default function MaintenancePage() {
}; };
return ( return (
<div className="p-4 lg:p-6"> <div className="p-4 lg:p-6 mb-6 lg:mb-0">
<div className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4 mb-6"> <div className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4 mb-6">
<div> <div>
<h1 className="text-2xl lg:text-3xl font-extrabold text-slate-800">Damage & Maintenance</h1> <h1 className="text-2xl lg:text-3xl font-extrabold text-slate-800">Damage & Maintenance</h1>
@@ -413,36 +441,45 @@ export default function MaintenancePage() {
</div> </div>
</div> </div>
<div className="grid grid-cols-2 lg:grid-cols-5 gap-4 mb-6"> <div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<div className="bg-white rounded-xl p-5 shadow-sm border border-slate-100"> <div className="bg-white rounded-xl p-5 shadow-sm border border-red-100">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="w-12 h-12 rounded-xl bg-red-50 flex items-center justify-center"> <div className="w-12 h-12 rounded-xl bg-red-50 flex items-center justify-center">
<AlertTriangle className="w-6 h-6 text-red-600" /> <AlertTriangle className="w-6 h-6 text-red-600" />
</div> </div>
<div> <div className="flex-1">
<p className="text-2xl font-extrabold text-slate-800">{stats.critical}</p> <div className="flex items-baseline justify-between gap-2">
<p className="text-sm text-slate-500">Critical</p> <p className="text-2xl font-extrabold text-slate-800">{stats.damageCount}</p>
<span className="text-xs text-red-600 font-medium bg-red-50 px-2 py-0.5 rounded">{stats.damageThisMonth} this month</span>
</div>
<p className="text-sm text-slate-500">Total Damage</p>
</div> </div>
</div> </div>
</div> </div>
<div className="bg-white rounded-xl p-5 shadow-sm border border-slate-100"> <div className="bg-white rounded-xl p-5 shadow-sm border border-blue-100">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="w-12 h-12 rounded-xl bg-blue-50 flex items-center justify-center"> <div className="w-12 h-12 rounded-xl bg-blue-50 flex items-center justify-center">
<Wrench className="w-6 h-6 text-blue-600" /> <Wrench className="w-6 h-6 text-blue-600" />
</div> </div>
<div> <div className="flex-1">
<p className="text-2xl font-extrabold text-slate-800">{stats.inProgress}</p> <div className="flex items-baseline justify-between gap-2">
<p className="text-sm text-slate-500">In Progress</p> <p className="text-2xl font-extrabold text-slate-800">{stats.maintenanceCount}</p>
<span className="text-xs text-blue-600 font-medium bg-blue-50 px-2 py-0.5 rounded">{stats.maintenanceThisMonth} this month</span>
</div>
<p className="text-sm text-slate-500">Total Maintenance</p>
</div> </div>
</div> </div>
</div> </div>
<div className="bg-white rounded-xl p-5 shadow-sm border border-slate-100"> <div className="bg-white rounded-xl p-5 shadow-sm border border-green-100">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="w-12 h-12 rounded-xl bg-green-50 flex items-center justify-center"> <div className="w-12 h-12 rounded-xl bg-green-50 flex items-center justify-center">
<CheckCircle className="w-6 h-6 text-green-600" /> <CheckCircle className="w-6 h-6 text-green-600" />
</div> </div>
<div> <div className="flex-1">
<div className="flex items-baseline justify-between gap-2">
<p className="text-2xl font-extrabold text-slate-800">{stats.completed}</p> <p className="text-2xl font-extrabold text-slate-800">{stats.completed}</p>
<span className="text-xs text-green-600 font-medium bg-green-50 px-2 py-0.5 rounded">{stats.completedThisMonth} this month</span>
</div>
<p className="text-sm text-slate-500">Completed</p> <p className="text-sm text-slate-500">Completed</p>
</div> </div>
</div> </div>
@@ -458,7 +495,7 @@ export default function MaintenancePage() {
</div> </div>
</div> </div>
</div> </div>
<div className="bg-white rounded-xl p-5 shadow-sm border border-slate-100"> {/* <div className="bg-white rounded-xl p-5 shadow-sm border border-slate-100">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="w-12 h-12 rounded-xl bg-purple-50 flex items-center justify-center"> <div className="w-12 h-12 rounded-xl bg-purple-50 flex items-center justify-center">
<DollarSign className="w-6 h-6 text-purple-600" /> <DollarSign className="w-6 h-6 text-purple-600" />
@@ -468,43 +505,145 @@ export default function MaintenancePage() {
<p className="text-sm text-slate-500">Total Cost</p> <p className="text-sm text-slate-500">Total Cost</p>
</div> </div>
</div> </div>
</div> */}
</div>
{mainCategory === 'damage' && (
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<div className="bg-red-50 rounded-xl p-4 border border-red-100 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-lg bg-red-100 flex items-center justify-center">
<AlertTriangle className="w-5 h-5 text-red-600" />
</div>
<div>
<p className="text-lg font-bold text-slate-800">{stats.damageCount}</p>
<p className="text-sm text-slate-500">Total Damage</p>
</div> </div>
</div> </div>
</div>
<div className="bg-green-50 rounded-xl p-4 border border-green-100 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-lg bg-green-100 flex items-center justify-center">
<Battery className="w-5 h-5 text-green-600" />
</div>
<div>
<p className="text-lg font-bold text-slate-800">{stats.batteryDamage}</p>
<p className="text-sm text-slate-500">Battery Damage</p>
</div>
</div>
</div>
<div className="bg-purple-50 rounded-xl p-4 border border-purple-100 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-lg bg-purple-100 flex items-center justify-center">
<Bike className="w-5 h-5 text-purple-600" />
</div>
<div>
<p className="text-lg font-bold text-slate-800">{stats.fleetDamage}</p>
<p className="text-sm text-slate-500">Fleet Damage</p>
</div>
</div>
</div>
<div className="bg-orange-50 rounded-xl p-4 border border-orange-100 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-lg bg-orange-100 flex items-center justify-center">
<Clock className="w-5 h-5 text-orange-600" />
</div>
<div>
<p className="text-lg font-bold text-slate-800">{stats.critical}</p>
<p className="text-sm text-slate-500">Critical Damage</p>
</div>
</div>
</div>
</div>
)}
{mainCategory === 'maintenance' && (
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<div className="bg-blue-50 rounded-xl p-4 border border-blue-100 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-lg bg-blue-100 flex items-center justify-center">
<Wrench className="w-5 h-5 text-blue-600" />
</div>
<div>
<p className="text-lg font-bold text-slate-800">{stats.maintenanceCount}</p>
<p className="text-sm text-slate-500">Total Maintenance</p>
</div>
</div>
</div>
<div className="bg-purple-50 rounded-xl p-4 border border-purple-100 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-lg bg-purple-100 flex items-center justify-center">
<Bike className="w-5 h-5 text-purple-600" />
</div>
<div>
<p className="text-lg font-bold text-slate-800">{stats.upcomingFleet}</p>
<p className="text-sm text-slate-500">Upcoming Fleet</p>
</div>
</div>
</div>
<div className="bg-green-50 rounded-xl p-4 border border-green-100 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-lg bg-green-100 flex items-center justify-center">
<Battery className="w-5 h-5 text-green-600" />
</div>
<div>
<p className="text-lg font-bold text-slate-800">{stats.upcomingBattery}</p>
<p className="text-sm text-slate-500">Upcoming Battery</p>
</div>
</div>
</div>
<div className="bg-orange-50 rounded-xl p-4 border border-orange-100 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-lg bg-orange-100 flex items-center justify-center">
<Activity className="w-5 h-5 text-orange-600" />
</div>
<div>
<p className="text-lg font-bold text-slate-800">{stats.ongoingBattery + stats.ongoingFleet}</p>
<p className="text-sm text-slate-500">Ongoing Maintenance</p>
</div>
</div>
</div>
</div>
)}
<div className="bg-white rounded-xl shadow-sm border border-slate-100 mb-6"> <div className="bg-white rounded-xl shadow-sm border border-slate-100 mb-6">
<div className="p-4 border-b border-slate-100"> <div className="p-4 border-b border-slate-100">
<div className="flex flex-col lg:flex-row lg:items-center gap-4"> <div className="flex flex-col lg:flex-row lg:items-center gap-4">
<div className="flex items-center gap-2 flex-wrap"> <div className="flex flex-col sm:flex-row items-start sm:items-center gap-3">
<div className="flex items-center gap-1 bg-slate-100 p-1 rounded-lg">
<button <button
onClick={() => setActiveTab('all')} onClick={() => setMainCategory('damage')}
className={`px-3 py-1.5 rounded-lg text-sm font-medium ${activeTab === 'all' ? 'bg-slate-800 text-white' : 'border border-slate-200 text-slate-600 hover:bg-slate-50'}`} className={`px-4 py-2 rounded-lg text-sm font-medium flex items-center gap-2 ${mainCategory === 'damage' ? 'bg-red-600 text-white shadow-sm' : 'text-slate-600 hover:bg-white hover:shadow-sm'}`}
>
All
</button>
<button
onClick={() => setActiveTab('damage')}
className={`px-3 py-1.5 rounded-lg text-sm font-medium flex items-center gap-1 ${activeTab === 'damage' ? 'bg-slate-800 text-white' : 'border border-slate-200 text-slate-600 hover:bg-slate-50'}`}
> >
<AlertTriangle className="w-4 h-4" /> Damage <AlertTriangle className="w-4 h-4" /> Damage
</button> </button>
<button <button
onClick={() => setActiveTab('repair')} onClick={() => setMainCategory('maintenance')}
className={`px-3 py-1.5 rounded-lg text-sm font-medium flex items-center gap-1 ${activeTab === 'repair' ? 'bg-slate-800 text-white' : 'border border-slate-200 text-slate-600 hover:bg-slate-50'}`} className={`px-4 py-2 rounded-lg text-sm font-medium flex items-center gap-2 ${mainCategory === 'maintenance' ? 'bg-blue-600 text-white shadow-sm' : 'text-slate-600 hover:bg-white hover:shadow-sm'}`}
> >
<Wrench className="w-4 h-4" /> Repair <Wrench className="w-4 h-4" /> Maintenance
</button>
</div>
<div className="flex items-center gap-1">
<button
onClick={() => setTargetType('all')}
className={`px-3 py-1.5 rounded-lg text-sm font-medium ${targetType === 'all' ? 'bg-slate-800 text-white' : 'border border-slate-200 text-slate-600 hover:bg-slate-50'}`}
>
All
</button> </button>
<button <button
onClick={() => setActiveTab('service')} onClick={() => setTargetType('battery')}
className={`px-3 py-1.5 rounded-lg text-sm font-medium flex items-center gap-1 ${activeTab === 'service' ? 'bg-slate-800 text-white' : 'border border-slate-200 text-slate-600 hover:bg-slate-50'}`} className={`px-3 py-1.5 rounded-lg text-sm font-medium flex items-center gap-1 ${targetType === 'battery' ? 'bg-green-600 text-white' : 'border border-slate-200 text-slate-600 hover:bg-slate-50'}`}
>
<Wrench className="w-4 h-4" /> Service
</button>
<button
onClick={() => setActiveTab('battery_swap')}
className={`px-3 py-1.5 rounded-lg text-sm font-medium flex items-center gap-1 ${activeTab === 'battery_swap' ? 'bg-slate-800 text-white' : 'border border-slate-200 text-slate-600 hover:bg-slate-50'}`}
> >
<Battery className="w-4 h-4" /> Battery <Battery className="w-4 h-4" /> Battery
</button> </button>
<button
onClick={() => setTargetType('fleet')}
className={`px-3 py-1.5 rounded-lg text-sm font-medium flex items-center gap-1 ${targetType === 'fleet' ? 'bg-purple-600 text-white' : 'border border-slate-200 text-slate-600 hover:bg-slate-50'}`}
>
<Bike className="w-4 h-4" /> Fleet
</button>
</div>
</div> </div>
<div className="flex-1"> <div className="flex-1">
<div className="relative"> <div className="relative">
@@ -537,47 +676,59 @@ export default function MaintenancePage() {
{filteredRecords.map(record => { {filteredRecords.map(record => {
const TypeIcon = typeIcons[record.type]; const TypeIcon = typeIcons[record.type];
return ( return (
<Link key={record.id} href={`/admin/maintenance/${record.id}`} className="block p-5 hover:bg-slate-50 transition-colors"> <Link key={record.id} href={`/admin/maintenance/${record.id}`} className="block p-4 lg:p-5 hover:bg-slate-50 transition-colors">
<div className="flex flex-col lg:flex-row lg:items-start gap-4"> <div className="flex flex-col lg:flex-row lg:items-start gap-3 lg:gap-4">
<div className="flex items-center gap-4"> <div className="flex items-start gap-3">
<div className="w-12 h-12 rounded-xl bg-slate-100 flex items-center justify-center"> <div className="w-10 h-10 lg:w-12 lg:h-12 rounded-lg lg:rounded-xl bg-slate-100 flex items-center justify-center flex-shrink-0">
<TypeIcon className="w-6 h-6 text-slate-600" /> <TypeIcon className="w-5 h-5 lg:w-6 lg:h-6 text-slate-600" />
</div> </div>
<div> <div className="min-w-0 flex-1">
<div className="flex items-center gap-2"> <div className="flex flex-wrap items-center gap-1.5 lg:gap-2">
<p className="font-semibold text-slate-800">{record.id}</p> <p className="font-semibold text-slate-800 text-sm lg:text-base">{record.id}</p>
<span className={`inline-flex items-center gap-1 text-xs font-medium px-2 py-0.5 rounded-full ${severityColors[record.severity]}`}> {record.batteryId && (
<span className="inline-flex items-center gap-1 text-xs font-medium px-1.5 py-0.5 rounded-full bg-green-100 text-green-700">
<Battery className="w-3 h-3" /> Battery
</span>
)}
{!record.batteryId && record.bikeId && (
<span className="inline-flex items-center gap-1 text-xs font-medium px-1.5 py-0.5 rounded-full bg-purple-100 text-purple-700">
<Bike className="w-3 h-3" /> Fleet
</span>
)}
<span className={`inline-flex items-center gap-1 text-xs font-medium px-1.5 py-0.5 rounded-full ${severityColors[record.severity]}`}>
{record.severity} {record.severity}
</span> </span>
</div> </div>
<p className="text-sm text-slate-500 flex items-center gap-2"> <p className="text-xs lg:text-sm text-slate-500 flex flex-wrap items-center gap-x-1 lg:gap-x-2">
<Bike className="w-3 h-3" /> {record.bikeModel} ({record.bikePlate}) <span className="flex items-center gap-1"><Bike className="w-3 h-3" /> {record.bikeModel}</span>
<span className="text-slate-300">|</span> <span className="hidden sm:inline text-slate-300">|</span>
<User className="w-3 h-3" /> {record.reporterName} <span className="text-xs">{record.bikePlate}</span>
<span className="hidden lg:inline text-slate-300">|</span>
<span className="flex items-center gap-1"><User className="w-3 h-3" /> {record.reporterName}</span>
</p> </p>
</div> </div>
</div> </div>
<div className="flex-1"> <div className="flex-1 min-w-0">
<p className="text-sm text-slate-700">{record.description}</p> <p className="text-sm text-slate-700 line-clamp-2">{record.description}</p>
<div className="flex flex-wrap gap-4 text-sm text-slate-500 mt-1"> <div className="flex flex-wrap gap-2 lg:gap-4 text-xs lg:text-sm text-slate-500 mt-1.5">
<p className="flex items-center gap-1"> <p className="flex items-center gap-1">
<Clock className="w-3 h-3" /> {record.date} <Clock className="w-3 h-3" /> {record.date}
</p> </p>
<p className="flex items-center gap-1"> <p className="flex items-center gap-1 truncate max-w-[100px] lg:max-w-none">
<MapPin className="w-3 h-3" /> {record.location} <MapPin className="w-3 h-3 flex-shrink-0" /> <span className="truncate">{record.location}</span>
</p> </p>
{record.images.length > 0 && ( {record.images.length > 0 && (
<p className="flex items-center gap-1 text-blue-600"> <p className="flex items-center gap-1 text-blue-600">
<Image className="w-3 h-3" /> {record.images.length} photos <ImageIcon className="w-3 h-3" /> {record.images.length}
</p> </p>
)} )}
{record.notes.length > 0 && ( {record.notes.length > 0 && (
<button <button
onClick={() => toggleNotes(record.id)} onClick={(e) => { e.preventDefault(); toggleNotes(record.id); }}
className="flex items-center gap-1 text-purple-600" className="flex items-center gap-1 text-purple-600"
> >
<MessageSquare className="w-3 h-3" /> {record.notes.length} notes <MessageSquare className="w-3 h-3" /> {record.notes.length}
{expandedNotes.includes(record.id) ? <ChevronUp className="w-3 h-3" /> : <ChevronDown className="w-3 h-3" />} {expandedNotes.includes(record.id) ? <ChevronUp className="w-3 h-3" /> : <ChevronDown className="w-3 h-3" />}
</button> </button>
)} )}
@@ -592,24 +743,24 @@ export default function MaintenancePage() {
)} )}
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center justify-between lg:justify-end gap-2 lg:gap-3 mt-2 lg:mt-0">
<div className="text-right"> <div className="text-left lg:text-right">
<p className="text-sm font-medium text-slate-700">{record.actualCost || record.estimatedCost}</p> <p className="text-sm font-medium text-slate-700">{record.actualCost || record.estimatedCost}</p>
<p className="text-xs text-slate-500">{record.paymentStatus === 'paid' ? 'Paid' : record.paymentStatus === 'approved' ? 'Approved' : 'Payment ' + record.paymentStatus}</p> <p className="text-xs text-slate-500">{record.paymentStatus === 'paid' ? 'Paid' : record.paymentStatus === 'approved' ? 'Approved' : 'Payment ' + record.paymentStatus}</p>
</div> </div>
<span className={`inline-flex items-center gap-1 text-xs font-medium px-2.5 py-1 rounded-full ${statusColors[record.status]}`}> <div className="flex items-center gap-1.5 lg:gap-2">
<span className={`inline-flex items-center gap-1 text-xs font-medium px-2 py-1 rounded-full ${statusColors[record.status]}`}>
{record.status === 'reported' && <Clock className="w-3 h-3" />} {record.status === 'reported' && <Clock className="w-3 h-3" />}
{record.status === 'in_progress' && <Wrench className="w-3 h-3" />} {record.status === 'in_progress' && <Wrench className="w-3 h-3" />}
{record.status === 'parts_ordered' && <AlertTriangle className="w-3 h-3" />} {record.status === 'parts_ordered' && <AlertTriangle className="w-3 h-3" />}
{record.status === 'completed' && <CheckCircle className="w-3 h-3" />} {record.status === 'completed' && <CheckCircle className="w-3 h-3" />}
{record.status === 'cancelled' && <XCircle className="w-3 h-3" />} {record.status === 'cancelled' && <XCircle className="w-3 h-3" />}
{record.status.replace('_', ' ')} <span className="hidden sm:inline">{record.status.replace('_', ' ')}</span>
</span> </span>
<div className="flex gap-1">
<button <button
onClick={(e) => { e.preventDefault(); setSelectedRecord(record); setShowDetailsModal(true); }} onClick={(e) => { e.preventDefault(); router.push(`/admin/maintenance/${record.id}`); }}
className="p-2 hover:bg-slate-100 rounded-lg text-slate-500" className="p-1.5 lg:p-2 hover:bg-slate-100 rounded-lg text-slate-500"
title="View Details" title="View Details"
> >
<Eye className="w-4 h-4" /> <Eye className="w-4 h-4" />
@@ -714,7 +865,7 @@ export default function MaintenancePage() {
<div className="grid grid-cols-4 gap-2"> <div className="grid grid-cols-4 gap-2">
{selectedRecord.images.map((img) => ( {selectedRecord.images.map((img) => (
<div key={img.id} className="aspect-square bg-slate-100 rounded-lg flex flex-col items-center justify-center"> <div key={img.id} className="aspect-square bg-slate-100 rounded-lg flex flex-col items-center justify-center">
<Image className="w-8 h-8 text-slate-400" /> <ImageIcon className="w-8 h-8 text-slate-400" />
<span className="text-xs text-slate-500 mt-1">{img.name}</span> <span className="text-xs text-slate-500 mt-1">{img.name}</span>
</div> </div>
))} ))}
@@ -794,18 +945,71 @@ export default function MaintenancePage() {
</button> </button>
</div> </div>
<div className="p-4 overflow-y-auto max-h-[70vh] space-y-4"> <div className="p-4 overflow-y-auto max-h-[70vh] space-y-4">
<div>
<label className="text-sm font-semibold text-slate-700 mb-2 block">Report Type *</label>
<div className="flex gap-2 mb-4">
<button
type="button"
onClick={() => setReportType('damage')}
className={`flex-1 py-3 px-4 rounded-xl border-2 flex items-center justify-center gap-2 font-medium transition-colors ${reportType === 'damage' ? 'border-red-500 bg-red-50 text-red-700' : 'border-slate-200 text-slate-600 hover:border-red-300'}`}
>
<AlertTriangle className="w-5 h-5" /> Damage
</button>
<button
type="button"
onClick={() => setReportType('maintenance')}
className={`flex-1 py-3 px-4 rounded-xl border-2 flex items-center justify-center gap-2 font-medium transition-colors ${reportType === 'maintenance' ? 'border-blue-500 bg-blue-50 text-blue-700' : 'border-slate-200 text-slate-600 hover:border-blue-300'}`}
>
<Wrench className="w-5 h-5" /> Maintenance
</button>
</div>
</div>
<div>
<label className="text-sm font-semibold text-slate-700 mb-2 block">Select Target *</label>
<div className="grid grid-cols-2 gap-3 mb-4">
<button
type="button"
className="p-4 border-2 rounded-xl flex flex-col items-center gap-2 hover:border-green-500 hover:bg-green-50 transition-colors"
>
<Battery className="w-8 h-8 text-green-600" />
<span className="font-medium text-slate-700">Battery</span>
<span className="text-xs text-slate-500">For battery issues</span>
</button>
<button
type="button"
className="p-4 border-2 rounded-xl flex flex-col items-center gap-2 hover:border-purple-500 hover:bg-purple-50 transition-colors"
>
<Bike className="w-8 h-8 text-purple-600" />
<span className="font-medium text-slate-700">Fleet (Bike)</span>
<span className="text-xs text-slate-500">For bike issues</span>
</button>
</div>
</div>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-2 gap-4">
<div> <div>
<label className="text-xs font-medium text-slate-600 mb-1 block">Issue Type *</label> <label className="text-xs font-medium text-slate-600 mb-1 block">Category *</label>
<select className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"> <select className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm">
<option value="">Select Category</option>
{reportType === 'damage' ? (
<>
<option value="damage">Damage</option> <option value="damage">Damage</option>
<option value="repair">Repair</option> <option value="repair">Repair</option>
<option value="accident">Accident</option>
<option value="theft">Theft</option>
<option value="vandalism">Vandalism</option>
</>
) : (
<>
<option value="service">Service</option> <option value="service">Service</option>
<option value="routine_service">Routine Service</option>
<option value="repair">Repair</option>
<option value="battery_swap">Battery Swap</option> <option value="battery_swap">Battery Swap</option>
<option value="inspection">Inspection</option> <option value="inspection">Inspection</option>
<option value="other">Other</option> </>
)}
</select> </select>
</div> </div>
{reportType === 'damage' ? (
<div> <div>
<label className="text-xs font-medium text-slate-600 mb-1 block">Severity *</label> <label className="text-xs font-medium text-slate-600 mb-1 block">Severity *</label>
<select className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"> <select className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm">
@@ -815,32 +1019,72 @@ export default function MaintenancePage() {
<option value="cosmetic">Cosmetic</option> <option value="cosmetic">Cosmetic</option>
</select> </select>
</div> </div>
) : (
<div> <div>
<label className="text-xs font-medium text-slate-600 mb-1 block">Bike ID *</label> <label className="text-xs font-medium text-slate-600 mb-1 block">Status</label>
<input type="text" placeholder="EV-XXX" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" /> <select className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm">
<option value="pending">Pending</option>
<option value="in_progress">In Progress</option>
<option value="completed">Completed</option>
</select>
</div> </div>
)}
<div> <div>
<label className="text-xs font-medium text-slate-600 mb-1 block">Battery ID</label> <label className="text-xs font-medium text-slate-600 mb-1 block">Battery ID</label>
<input type="text" placeholder="BAT-XXX" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" /> <input type="text" placeholder="BAT-XXX" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div> </div>
<div>
<label className="text-xs font-medium text-slate-600 mb-1 block">Bike ID</label>
<input type="text" placeholder="EV-XXX" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
</div>
<div className="grid grid-cols-2 gap-4">
{reportType === 'damage' ? (
<>
<div>
<label className="text-xs font-medium text-slate-600 mb-1 block">Reporter Name *</label>
<input type="text" placeholder="Enter name" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs font-medium text-slate-600 mb-1 block">Reporter Phone *</label>
<input type="tel" placeholder="01XXXXXXXXX" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
</>
) : (
<>
<div>
<label className="text-xs font-medium text-slate-600 mb-1 block">Performed By</label>
<input type="text" placeholder="Technician name" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
<div>
<label className="text-xs font-medium text-slate-600 mb-1 block">Next Due Date</label>
<input type="date" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div>
</>
)}
</div> </div>
<div> <div>
<label className="text-xs font-medium text-slate-600 mb-1 block">Description *</label> <label className="text-xs font-medium text-slate-600 mb-1 block">Description *</label>
<textarea rows={3} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" placeholder="Describe the issue..." /> <textarea rows={3} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" placeholder="Describe the issue in detail..." />
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-xs font-medium text-slate-600 mb-1 block">Location / Hub *</label>
<input type="text" placeholder="e.g., Gulshan Hub" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div> </div>
<div> <div>
<label className="text-xs font-medium text-slate-600 mb-1 block">Location *</label> <label className="text-xs font-medium text-slate-600 mb-1 block">
<input type="text" placeholder="Where did the issue occur?" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" /> {reportType === 'damage' ? 'Estimated Cost (৳)' : 'Service Cost (৳)'}
</div> </label>
<div>
<label className="text-xs font-medium text-slate-600 mb-1 block">Estimated Cost</label>
<input type="number" placeholder="0" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" /> <input type="number" placeholder="0" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm" />
</div> </div>
</div>
<div> <div>
<label className="text-xs font-medium text-slate-600 mb-1 block">Upload Images</label> <label className="text-xs font-medium text-slate-600 mb-1 block">Upload Images</label>
<div className="border-2 border-dashed border-slate-200 rounded-lg p-6 text-center"> <div className="border-2 border-dashed border-slate-200 rounded-lg p-6 text-center hover:border-accent cursor-pointer">
<Image className="w-8 h-8 text-slate-300 mx-auto mb-2" /> <ImageIcon className="w-8 h-8 text-slate-300 mx-auto mb-2" />
<p className="text-sm text-slate-500">Drag and drop or click to upload</p> <p className="text-sm text-slate-500">Click to upload images</p>
<p className="text-xs text-slate-400">JPG, PNG up to 5MB</p>
</div> </div>
</div> </div>
</div> </div>
@@ -848,7 +1092,7 @@ export default function MaintenancePage() {
<button onClick={() => setShowNewModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50"> <button onClick={() => setShowNewModal(false)} className="px-4 py-2 border border-slate-200 text-slate-600 rounded-lg text-sm hover:bg-slate-50">
Cancel Cancel
</button> </button>
<button onClick={() => { setShowNewModal(false); alert('Issue reported successfully!'); }} className="px-4 py-2 bg-accent text-white rounded-lg text-sm hover:bg-accent-dark"> <button onClick={() => { setShowNewModal(false); setShowSuccessModal(true); }} className="px-4 py-2 bg-accent text-white rounded-lg text-sm hover:bg-accent-dark">
Submit Report Submit Report
</button> </button>
</div> </div>
@@ -953,6 +1197,24 @@ export default function MaintenancePage() {
</div> </div>
</div> </div>
)} )}
{showSuccessModal && (
<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 p-6 text-center">
<div className="w-16 h-16 rounded-full bg-green-100 flex items-center justify-center mx-auto mb-4">
<CheckCircle className="w-8 h-8 text-green-600" />
</div>
<h3 className="text-xl font-bold text-slate-800 mb-2">Issue Reported Successfully!</h3>
<p className="text-slate-500 mb-6">Your issue has been submitted and will be reviewed shortly.</p>
<button
onClick={() => setShowSuccessModal(false)}
className="px-6 py-2 bg-accent text-white rounded-lg hover:bg-accent-dark"
>
OK
</button>
</div>
</div>
)}
</div> </div>
); );
} }