@burdenoff/microfe-movethewheels 2026.510.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -0
- package/dist/AIAssistantPage-hD0VYJdH.js +210 -0
- package/dist/AnalyticsPage-DHTHCUtr.js +201 -0
- package/dist/CreateOrderPage-Cprg4Y9V.js +471 -0
- package/dist/CustomerDetailsPage-DNDEw7IW.js +239 -0
- package/dist/CustomersPage-CDjjeCEL.js +119 -0
- package/dist/DashboardPage-8iTPXRAG.js +374 -0
- package/dist/DataTable-CRIKfdIN.js +239 -0
- package/dist/DriverDetailsPage-CRyRCno7.js +297 -0
- package/dist/DriversPage-16O8fVmf.js +127 -0
- package/dist/FinancePage-BYUxK5dR.js +154 -0
- package/dist/FleetPage-CHYETCWT.js +293 -0
- package/dist/ImportExportPage-C3MKKxfc.js +232 -0
- package/dist/InventoryPage--822AxZM.js +223 -0
- package/dist/LiveTrackingPage-Dp3rTJDr.js +332 -0
- package/dist/MarketplacePage-DjEqudfM.js +192 -0
- package/dist/MetricCard-GTbxAk1a.js +135 -0
- package/dist/OrderDetailsPage-BIuYG0ub.js +398 -0
- package/dist/OrdersListPage-CW5V0Uvh.js +257 -0
- package/dist/PageLayout-B7b0vl0R.js +1894 -0
- package/dist/ProductDetailsPage-Q3X7AT-7.js +168 -0
- package/dist/ProductsPage-CUj9JpnW.js +131 -0
- package/dist/ReportsPage-DblO5CdJ.js +227 -0
- package/dist/RouteDetailsPage-CLctgk6A.js +240 -0
- package/dist/RoutesPage-8hrv6RWT.js +116 -0
- package/dist/SettingsPage-BJ5BQeqn.js +247 -0
- package/dist/StatusBadge-BrrwraIA.js +206 -0
- package/dist/TrackingPage-BGqHDh-w.js +322 -0
- package/dist/VehicleDetailsPage-XnDH4iQR.js +194 -0
- package/dist/VehiclesPage-Cs4XxHkA.js +127 -0
- package/dist/WarehouseDetailsPage-GemdMvr_.js +215 -0
- package/dist/WarehousesPage-QTiuDuXy.js +121 -0
- package/dist/arrow-left-6CiLhqVp.js +11 -0
- package/dist/box-BunB_4UH.js +18 -0
- package/dist/chart-column-DWwVEVQ-.js +22 -0
- package/dist/chevron-right-DhZVf20o.js +8 -0
- package/dist/circle-alert-D5f6RZxt.js +26 -0
- package/dist/circle-check-big-D-JMHcTe.js +11 -0
- package/dist/clock-CvwBKbQP.js +13 -0
- package/dist/dev/main.d.ts +1 -0
- package/dist/dollar-sign-CP9qeU5d.js +14 -0
- package/dist/download-CIuG04pJ.js +21 -0
- package/dist/file-text-Dd_thxkn.js +26 -0
- package/dist/filter-DyRMX9CU.js +8 -0
- package/dist/formatters-_vJlC-47.js +50 -0
- package/dist/generated/global-operations.d.ts +1 -0
- package/dist/generated/global-types.d.ts +20715 -0
- package/dist/generated/wspace-operations.d.ts +3704 -0
- package/dist/generated/wspace-types.d.ts +53362 -0
- package/dist/graphqlClient-CdJyR_ed.js +55 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +772 -0
- package/dist/map-BqH1cBJi.js +18 -0
- package/dist/map-pin-CFBOmh-A.js +13 -0
- package/dist/movethewheels/MoveTheWheelsRoot.d.ts +25 -0
- package/dist/movethewheels/MoveTheWheelsRoutes.d.ts +7 -0
- package/dist/movethewheels/components/DataTable.d.ts +32 -0
- package/dist/movethewheels/components/MetricCard.d.ts +43 -0
- package/dist/movethewheels/components/PageLayout.d.ts +68 -0
- package/dist/movethewheels/components/StatusBadge.d.ts +49 -0
- package/dist/movethewheels/components/index.d.ts +10 -0
- package/dist/movethewheels/components/ui.d.ts +22 -0
- package/dist/movethewheels/constants/index.d.ts +24 -0
- package/dist/movethewheels/constants/mockData.d.ts +33 -0
- package/dist/movethewheels/hooks/index.d.ts +12 -0
- package/dist/movethewheels/hooks/useAnalytics.d.ts +118 -0
- package/dist/movethewheels/hooks/useCustomers.d.ts +37 -0
- package/dist/movethewheels/hooks/useFleet.d.ts +71 -0
- package/dist/movethewheels/hooks/useInventory.d.ts +60 -0
- package/dist/movethewheels/hooks/useOrders.d.ts +47 -0
- package/dist/movethewheels/hooks/useRoutes.d.ts +41 -0
- package/dist/movethewheels/hooks/useTracking.d.ts +69 -0
- package/dist/movethewheels/index.d.ts +30 -0
- package/dist/movethewheels/pages/AIAssistantPage.d.ts +4 -0
- package/dist/movethewheels/pages/AnalyticsPage.d.ts +4 -0
- package/dist/movethewheels/pages/CreateOrderPage.d.ts +6 -0
- package/dist/movethewheels/pages/CustomerDetailsPage.d.ts +4 -0
- package/dist/movethewheels/pages/CustomersPage.d.ts +4 -0
- package/dist/movethewheels/pages/DashboardPage.d.ts +6 -0
- package/dist/movethewheels/pages/DriverDetailsPage.d.ts +4 -0
- package/dist/movethewheels/pages/DriversPage.d.ts +4 -0
- package/dist/movethewheels/pages/FinancePage.d.ts +4 -0
- package/dist/movethewheels/pages/FleetPage.d.ts +6 -0
- package/dist/movethewheels/pages/ImportExportPage.d.ts +4 -0
- package/dist/movethewheels/pages/InventoryPage.d.ts +4 -0
- package/dist/movethewheels/pages/LiveTrackingPage.d.ts +6 -0
- package/dist/movethewheels/pages/MarketplacePage.d.ts +4 -0
- package/dist/movethewheels/pages/OrderDetailsPage.d.ts +6 -0
- package/dist/movethewheels/pages/OrdersListPage.d.ts +6 -0
- package/dist/movethewheels/pages/ProductDetailsPage.d.ts +4 -0
- package/dist/movethewheels/pages/ProductsPage.d.ts +4 -0
- package/dist/movethewheels/pages/ReportsPage.d.ts +4 -0
- package/dist/movethewheels/pages/RouteDetailsPage.d.ts +4 -0
- package/dist/movethewheels/pages/RoutesPage.d.ts +4 -0
- package/dist/movethewheels/pages/SettingsPage.d.ts +4 -0
- package/dist/movethewheels/pages/TrackingPage.d.ts +6 -0
- package/dist/movethewheels/pages/VehicleDetailsPage.d.ts +4 -0
- package/dist/movethewheels/pages/VehiclesPage.d.ts +4 -0
- package/dist/movethewheels/pages/WarehouseDetailsPage.d.ts +4 -0
- package/dist/movethewheels/pages/WarehousesPage.d.ts +4 -0
- package/dist/movethewheels/providers/MoveTheWheelsProvider.d.ts +16 -0
- package/dist/movethewheels/store/movethewheelsStore.d.ts +73 -0
- package/dist/movethewheels/types/index.d.ts +655 -0
- package/dist/movethewheels/utils/cn.d.ts +6 -0
- package/dist/movethewheels/utils/formatters.d.ts +60 -0
- package/dist/movethewheels/utils/graphqlClient.d.ts +11 -0
- package/dist/movethewheels/utils/index.d.ts +7 -0
- package/dist/movethewheels/utils/navigation.d.ts +23 -0
- package/dist/navigation-BgnOfsVd.js +6 -0
- package/dist/navigation-C2fY_aS9.js +8 -0
- package/dist/package-DVZbDRcV.js +22 -0
- package/dist/phone-KdwpVmC4.js +18 -0
- package/dist/plus-Bl7uX6Ji.js +11 -0
- package/dist/refresh-cw-BYjl3K-8.js +22 -0
- package/dist/route-Ce_poKFi.js +51 -0
- package/dist/save-C-qDVat-.js +18 -0
- package/dist/search-5pdn5eOO.js +13 -0
- package/dist/settings-C4kIDsYg.js +28 -0
- package/dist/square-pen-BwQ67vLE.js +11 -0
- package/dist/star-BlVsC3Ad.js +8 -0
- package/dist/store-DTmQT5M0.js +26 -0
- package/dist/trending-up-C1faflCI.js +11 -0
- package/dist/triangle-alert-CUoVAA4L.js +18 -0
- package/dist/truck-BmDAzu05.js +30 -0
- package/dist/useAnalytics-ph7eTIK6.js +297 -0
- package/dist/useCustomers-bS3a4ytk.js +186 -0
- package/dist/useFleet-BdETplNE.js +398 -0
- package/dist/useInventory-Dwn18FPz.js +323 -0
- package/dist/useOrders-D_3_hGMp.js +324 -0
- package/dist/useRoutes-v4aBaS-E.js +224 -0
- package/dist/useTracking-De2KIUNu.js +261 -0
- package/dist/user-BplzDrLP.js +13 -0
- package/dist/users-i-igmsP4.js +24 -0
- package/dist/warehouse-DewG0PXh.js +25 -0
- package/dist/wrench-CoSDEIC7.js +31 -0
- package/package.json +107 -0
- package/src/dev/main.tsx +110 -0
- package/src/dev/styles.css +139 -0
- package/src/generated/global-operations.ts +2 -0
- package/src/generated/global-types.ts +24048 -0
- package/src/generated/wspace-operations.ts +3734 -0
- package/src/generated/wspace-types.ts +60715 -0
- package/src/index.ts +4 -0
- package/src/movethewheels/MoveTheWheelsRoot.tsx +258 -0
- package/src/movethewheels/MoveTheWheelsRoutes.tsx +119 -0
- package/src/movethewheels/components/DataTable.tsx +367 -0
- package/src/movethewheels/components/MetricCard.tsx +180 -0
- package/src/movethewheels/components/PageLayout.tsx +234 -0
- package/src/movethewheels/components/StatusBadge.tsx +243 -0
- package/src/movethewheels/components/index.ts +26 -0
- package/src/movethewheels/components/ui.tsx +124 -0
- package/src/movethewheels/constants/index.ts +65 -0
- package/src/movethewheels/constants/mockData.ts +1342 -0
- package/src/movethewheels/hooks/index.ts +55 -0
- package/src/movethewheels/hooks/useAnalytics.ts +476 -0
- package/src/movethewheels/hooks/useCustomers.ts +359 -0
- package/src/movethewheels/hooks/useFleet.ts +778 -0
- package/src/movethewheels/hooks/useInventory.ts +632 -0
- package/src/movethewheels/hooks/useOrders.ts +703 -0
- package/src/movethewheels/hooks/useRoutes.ts +453 -0
- package/src/movethewheels/hooks/useTracking.ts +505 -0
- package/src/movethewheels/index.ts +68 -0
- package/src/movethewheels/pages/AIAssistantPage.tsx +160 -0
- package/src/movethewheels/pages/AnalyticsPage.tsx +190 -0
- package/src/movethewheels/pages/CreateOrderPage.tsx +454 -0
- package/src/movethewheels/pages/CustomerDetailsPage.tsx +207 -0
- package/src/movethewheels/pages/CustomersPage.tsx +115 -0
- package/src/movethewheels/pages/DashboardPage.tsx +414 -0
- package/src/movethewheels/pages/DriverDetailsPage.tsx +261 -0
- package/src/movethewheels/pages/DriversPage.tsx +118 -0
- package/src/movethewheels/pages/FinancePage.tsx +141 -0
- package/src/movethewheels/pages/FleetPage.tsx +289 -0
- package/src/movethewheels/pages/ImportExportPage.tsx +165 -0
- package/src/movethewheels/pages/InventoryPage.tsx +212 -0
- package/src/movethewheels/pages/LiveTrackingPage.tsx +325 -0
- package/src/movethewheels/pages/MarketplacePage.tsx +235 -0
- package/src/movethewheels/pages/OrderDetailsPage.tsx +387 -0
- package/src/movethewheels/pages/OrdersListPage.tsx +241 -0
- package/src/movethewheels/pages/ProductDetailsPage.tsx +155 -0
- package/src/movethewheels/pages/ProductsPage.tsx +124 -0
- package/src/movethewheels/pages/ReportsPage.tsx +164 -0
- package/src/movethewheels/pages/RouteDetailsPage.tsx +245 -0
- package/src/movethewheels/pages/RoutesPage.tsx +104 -0
- package/src/movethewheels/pages/SettingsPage.tsx +242 -0
- package/src/movethewheels/pages/TrackingPage.tsx +419 -0
- package/src/movethewheels/pages/VehicleDetailsPage.tsx +218 -0
- package/src/movethewheels/pages/VehiclesPage.tsx +124 -0
- package/src/movethewheels/pages/WarehouseDetailsPage.tsx +216 -0
- package/src/movethewheels/pages/WarehousesPage.tsx +122 -0
- package/src/movethewheels/providers/MoveTheWheelsProvider.tsx +66 -0
- package/src/movethewheels/store/movethewheelsStore.ts +136 -0
- package/src/movethewheels/types/index.ts +744 -0
- package/src/movethewheels/utils/cn.ts +9 -0
- package/src/movethewheels/utils/formatters.ts +215 -0
- package/src/movethewheels/utils/graphqlClient.ts +63 -0
- package/src/movethewheels/utils/index.ts +8 -0
- package/src/movethewheels/utils/navigation.ts +70 -0
- package/src/operations/global/.gitkeep +0 -0
- package/src/operations/wspace/movethewheels/fragments/core.graphql +191 -0
- package/src/operations/wspace/movethewheels/mutations/entities.graphql +87 -0
- package/src/operations/wspace/movethewheels/mutations/logistics.graphql +86 -0
- package/src/operations/wspace/movethewheels/mutations/marketplace-reports.graphql +81 -0
- package/src/operations/wspace/movethewheels/mutations/orders.graphql +21 -0
- package/src/operations/wspace/movethewheels/queries/dashboard.graphql +61 -0
- package/src/operations/wspace/movethewheels/queries/entities.graphql +83 -0
- package/src/operations/wspace/movethewheels/queries/logistics.graphql +84 -0
- package/src/operations/wspace/movethewheels/queries/marketplace-reports.graphql +40 -0
- package/src/operations/wspace/movethewheels/queries/orders.graphql +43 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Driver Details Page
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { useParams } from 'react-router-dom';
|
|
6
|
+
import { Users, ArrowLeft, Star, DollarSign, Clock, FileText, Edit, MapPin } from 'lucide-react';
|
|
7
|
+
import { PageLayout, LoadingState, ErrorState } from '../components/PageLayout';
|
|
8
|
+
import { StatusBadge } from '../components/StatusBadge';
|
|
9
|
+
import {
|
|
10
|
+
Card,
|
|
11
|
+
CardContent,
|
|
12
|
+
CardHeader,
|
|
13
|
+
CardTitle,
|
|
14
|
+
Button,
|
|
15
|
+
Badge,
|
|
16
|
+
Progress,
|
|
17
|
+
} from '../components/ui';
|
|
18
|
+
import { useDriver } from '../hooks/useFleet';
|
|
19
|
+
import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
|
|
20
|
+
import { formatCurrency, formatDate } from '../utils/formatters';
|
|
21
|
+
import { joinPath } from '../utils/navigation';
|
|
22
|
+
|
|
23
|
+
export default function DriverDetailsPage() {
|
|
24
|
+
const { driverId } = useParams<{ driverId: string }>();
|
|
25
|
+
const { basePath, navigate } = useMoveTheWheels();
|
|
26
|
+
const { driver, isLoading, error, refetch } = useDriver(driverId);
|
|
27
|
+
|
|
28
|
+
const goBack = () => navigate?.(joinPath(basePath, 'fleet/drivers'));
|
|
29
|
+
|
|
30
|
+
if (isLoading) return <LoadingState message="Loading driver details..." />;
|
|
31
|
+
if (error || !driver) return <ErrorState title="Driver not found" onRetry={refetch} />;
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<PageLayout
|
|
35
|
+
title={driver.fullName}
|
|
36
|
+
subtitle={`Employee ID: ${driver.employeeId}`}
|
|
37
|
+
icon={<Users size={24} />}
|
|
38
|
+
headerActions={
|
|
39
|
+
<div className="flex gap-2">
|
|
40
|
+
<Button variant="outline" onClick={goBack}>
|
|
41
|
+
<ArrowLeft size={16} /> Back
|
|
42
|
+
</Button>
|
|
43
|
+
<Button>
|
|
44
|
+
<Edit size={16} /> Edit
|
|
45
|
+
</Button>
|
|
46
|
+
</div>
|
|
47
|
+
}
|
|
48
|
+
headerContent={
|
|
49
|
+
<div className="flex items-center gap-4">
|
|
50
|
+
<StatusBadge status={driver.status} type="driver" />
|
|
51
|
+
<div className="flex items-center gap-1">
|
|
52
|
+
<Star size={16} className="text-yellow-500 fill-yellow-500" />
|
|
53
|
+
<span className="font-medium">{driver.ratings.overall.toFixed(1)}</span>
|
|
54
|
+
<span className="text-muted-foreground">({driver.ratings.totalRatings} ratings)</span>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
}
|
|
58
|
+
>
|
|
59
|
+
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
60
|
+
<div className="lg:col-span-2 space-y-6">
|
|
61
|
+
{/* Ratings */}
|
|
62
|
+
<Card>
|
|
63
|
+
<CardHeader>
|
|
64
|
+
<CardTitle className="flex items-center gap-2">
|
|
65
|
+
<Star size={18} /> Ratings
|
|
66
|
+
</CardTitle>
|
|
67
|
+
</CardHeader>
|
|
68
|
+
<CardContent>
|
|
69
|
+
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
|
|
70
|
+
{[
|
|
71
|
+
{ label: 'Punctuality', value: driver.ratings.punctuality },
|
|
72
|
+
{ label: 'Communication', value: driver.ratings.communication },
|
|
73
|
+
{ label: 'Handling', value: driver.ratings.carefulHandling },
|
|
74
|
+
{ label: 'Professionalism', value: driver.ratings.professionalism },
|
|
75
|
+
{ label: 'On-Time Delivery', value: driver.ratings.onTimeDelivery },
|
|
76
|
+
].map((rating) => (
|
|
77
|
+
<div key={rating.label}>
|
|
78
|
+
<p className="text-sm text-muted-foreground">{rating.label}</p>
|
|
79
|
+
<div className="flex items-center gap-2 mt-1">
|
|
80
|
+
<Progress value={rating.value * 20} className="flex-1 h-2" />
|
|
81
|
+
<span className="text-sm font-medium">{rating.value.toFixed(1)}</span>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
))}
|
|
85
|
+
</div>
|
|
86
|
+
</CardContent>
|
|
87
|
+
</Card>
|
|
88
|
+
|
|
89
|
+
{/* Working Hours */}
|
|
90
|
+
<Card>
|
|
91
|
+
<CardHeader>
|
|
92
|
+
<CardTitle className="flex items-center gap-2">
|
|
93
|
+
<Clock size={18} /> Working Hours
|
|
94
|
+
</CardTitle>
|
|
95
|
+
</CardHeader>
|
|
96
|
+
<CardContent>
|
|
97
|
+
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
98
|
+
<div>
|
|
99
|
+
<p className="text-sm text-muted-foreground">Shift</p>
|
|
100
|
+
<p className="font-medium">
|
|
101
|
+
{driver.workingHours.startTime} - {driver.workingHours.endTime}
|
|
102
|
+
</p>
|
|
103
|
+
</div>
|
|
104
|
+
<div>
|
|
105
|
+
<p className="text-sm text-muted-foreground">Working Days</p>
|
|
106
|
+
<p className="font-medium">{driver.workingHours.workingDays.length} days/week</p>
|
|
107
|
+
</div>
|
|
108
|
+
<div>
|
|
109
|
+
<p className="text-sm text-muted-foreground">Hours Today</p>
|
|
110
|
+
<p className="font-medium">
|
|
111
|
+
{driver.workingHours.currentHoursToday}h / {driver.workingHours.maxHoursPerDay}h
|
|
112
|
+
</p>
|
|
113
|
+
</div>
|
|
114
|
+
<div>
|
|
115
|
+
<p className="text-sm text-muted-foreground">Hours This Week</p>
|
|
116
|
+
<p className="font-medium">
|
|
117
|
+
{driver.workingHours.currentHoursThisWeek}h /{' '}
|
|
118
|
+
{driver.workingHours.maxHoursPerWeek}h
|
|
119
|
+
</p>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
</CardContent>
|
|
123
|
+
</Card>
|
|
124
|
+
|
|
125
|
+
{/* Documents */}
|
|
126
|
+
<Card>
|
|
127
|
+
<CardHeader>
|
|
128
|
+
<CardTitle className="flex items-center gap-2">
|
|
129
|
+
<FileText size={18} /> Documents
|
|
130
|
+
</CardTitle>
|
|
131
|
+
</CardHeader>
|
|
132
|
+
<CardContent>
|
|
133
|
+
<div className="space-y-3">
|
|
134
|
+
<div className="flex items-center justify-between p-3 border rounded-lg">
|
|
135
|
+
<div>
|
|
136
|
+
<p className="font-medium">Driver's License</p>
|
|
137
|
+
<p className="text-sm text-muted-foreground">
|
|
138
|
+
{driver.licenseNumber} - {driver.licenseType}
|
|
139
|
+
</p>
|
|
140
|
+
<p className="text-sm text-muted-foreground">
|
|
141
|
+
Expires: {formatDate(driver.licenseExpiry)}
|
|
142
|
+
</p>
|
|
143
|
+
</div>
|
|
144
|
+
<Badge variant="default">Valid</Badge>
|
|
145
|
+
</div>
|
|
146
|
+
{driver.documents.map((doc) => (
|
|
147
|
+
<div
|
|
148
|
+
key={doc.id}
|
|
149
|
+
className="flex items-center justify-between p-3 border rounded-lg"
|
|
150
|
+
>
|
|
151
|
+
<div>
|
|
152
|
+
<p className="font-medium capitalize">{doc.type.replace('_', ' ')}</p>
|
|
153
|
+
<p className="text-sm text-muted-foreground">
|
|
154
|
+
Expires: {formatDate(doc.expiryDate)}
|
|
155
|
+
</p>
|
|
156
|
+
</div>
|
|
157
|
+
<Badge variant={doc.verified ? 'default' : 'secondary'}>
|
|
158
|
+
{doc.verified ? 'Verified' : 'Pending'}
|
|
159
|
+
</Badge>
|
|
160
|
+
</div>
|
|
161
|
+
))}
|
|
162
|
+
</div>
|
|
163
|
+
</CardContent>
|
|
164
|
+
</Card>
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
<div className="space-y-6">
|
|
168
|
+
{/* Stats */}
|
|
169
|
+
<Card>
|
|
170
|
+
<CardHeader>
|
|
171
|
+
<CardTitle>Statistics</CardTitle>
|
|
172
|
+
</CardHeader>
|
|
173
|
+
<CardContent className="space-y-4">
|
|
174
|
+
<div>
|
|
175
|
+
<p className="text-sm text-muted-foreground">Total Deliveries</p>
|
|
176
|
+
<p className="text-2xl font-bold">{driver.completedOrders.toLocaleString()}</p>
|
|
177
|
+
</div>
|
|
178
|
+
<div>
|
|
179
|
+
<p className="text-sm text-muted-foreground">Today's Deliveries</p>
|
|
180
|
+
<p className="text-2xl font-bold">{driver.todayOrders}</p>
|
|
181
|
+
</div>
|
|
182
|
+
<div>
|
|
183
|
+
<p className="text-sm text-muted-foreground">Join Date</p>
|
|
184
|
+
<p className="font-medium">{formatDate(driver.joinDate)}</p>
|
|
185
|
+
</div>
|
|
186
|
+
</CardContent>
|
|
187
|
+
</Card>
|
|
188
|
+
|
|
189
|
+
{/* Earnings */}
|
|
190
|
+
<Card>
|
|
191
|
+
<CardHeader>
|
|
192
|
+
<CardTitle className="flex items-center gap-2">
|
|
193
|
+
<DollarSign size={18} /> Earnings
|
|
194
|
+
</CardTitle>
|
|
195
|
+
</CardHeader>
|
|
196
|
+
<CardContent className="space-y-3">
|
|
197
|
+
<div>
|
|
198
|
+
<p className="text-sm text-muted-foreground">Total Earnings</p>
|
|
199
|
+
<p className="text-2xl font-bold">
|
|
200
|
+
{formatCurrency(driver.earnings.totalEarnings)}
|
|
201
|
+
</p>
|
|
202
|
+
</div>
|
|
203
|
+
<div className="grid grid-cols-2 gap-3">
|
|
204
|
+
<div>
|
|
205
|
+
<p className="text-sm text-muted-foreground">This Week</p>
|
|
206
|
+
<p className="font-medium">{formatCurrency(driver.earnings.weeklyEarnings)}</p>
|
|
207
|
+
</div>
|
|
208
|
+
<div>
|
|
209
|
+
<p className="text-sm text-muted-foreground">This Month</p>
|
|
210
|
+
<p className="font-medium">{formatCurrency(driver.earnings.monthlyEarnings)}</p>
|
|
211
|
+
</div>
|
|
212
|
+
</div>
|
|
213
|
+
<div>
|
|
214
|
+
<p className="text-sm text-muted-foreground">Base Salary</p>
|
|
215
|
+
<p className="font-medium">{formatCurrency(driver.baseSalary)}/year</p>
|
|
216
|
+
</div>
|
|
217
|
+
</CardContent>
|
|
218
|
+
</Card>
|
|
219
|
+
|
|
220
|
+
{/* Location */}
|
|
221
|
+
{driver.currentLocation && (
|
|
222
|
+
<Card>
|
|
223
|
+
<CardHeader>
|
|
224
|
+
<CardTitle className="flex items-center gap-2">
|
|
225
|
+
<MapPin size={18} /> Current Location
|
|
226
|
+
</CardTitle>
|
|
227
|
+
</CardHeader>
|
|
228
|
+
<CardContent>
|
|
229
|
+
<p className="text-sm">
|
|
230
|
+
{driver.currentLocation.address || 'Location updating...'}
|
|
231
|
+
</p>
|
|
232
|
+
<p className="text-xs text-muted-foreground mt-1">
|
|
233
|
+
Updated {formatDate(driver.currentLocation.timestamp || new Date(), 'relative')}
|
|
234
|
+
</p>
|
|
235
|
+
</CardContent>
|
|
236
|
+
</Card>
|
|
237
|
+
)}
|
|
238
|
+
|
|
239
|
+
{/* Compliance */}
|
|
240
|
+
<Card>
|
|
241
|
+
<CardHeader>
|
|
242
|
+
<CardTitle>Compliance Status</CardTitle>
|
|
243
|
+
</CardHeader>
|
|
244
|
+
<CardContent className="space-y-2">
|
|
245
|
+
{Object.entries(driver.compliance)
|
|
246
|
+
.filter(([k]) => k !== 'lastUpdate')
|
|
247
|
+
.map(([key, value]) => (
|
|
248
|
+
<div key={key} className="flex items-center justify-between">
|
|
249
|
+
<span className="text-sm capitalize">{key.replace(/([A-Z])/g, ' $1')}</span>
|
|
250
|
+
<Badge variant={value ? 'default' : 'destructive'}>
|
|
251
|
+
{value ? 'Compliant' : 'Non-compliant'}
|
|
252
|
+
</Badge>
|
|
253
|
+
</div>
|
|
254
|
+
))}
|
|
255
|
+
</CardContent>
|
|
256
|
+
</Card>
|
|
257
|
+
</div>
|
|
258
|
+
</div>
|
|
259
|
+
</PageLayout>
|
|
260
|
+
);
|
|
261
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drivers Page - List of all drivers
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Users, Plus, RefreshCw, Download, Star } from 'lucide-react';
|
|
6
|
+
import { PageLayout } from '../components/PageLayout';
|
|
7
|
+
import { DataTable, type Column } from '../components/DataTable';
|
|
8
|
+
import { StatusBadge } from '../components/StatusBadge';
|
|
9
|
+
import { Button, Avatar, AvatarFallback } from '../components/ui';
|
|
10
|
+
import { useDrivers } from '../hooks/useFleet';
|
|
11
|
+
import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
|
|
12
|
+
import { formatDate } from '../utils/formatters';
|
|
13
|
+
import { joinPath } from '../utils/navigation';
|
|
14
|
+
import type { Driver } from '../types';
|
|
15
|
+
|
|
16
|
+
export default function DriversPage() {
|
|
17
|
+
const { basePath, navigate } = useMoveTheWheels();
|
|
18
|
+
const { drivers, totalDrivers, isLoading, refetch } = useDrivers();
|
|
19
|
+
|
|
20
|
+
const goTo = (path: string) => navigate?.(joinPath(basePath, path));
|
|
21
|
+
|
|
22
|
+
const columns: Column<Driver>[] = [
|
|
23
|
+
{
|
|
24
|
+
id: 'driver',
|
|
25
|
+
header: 'Driver',
|
|
26
|
+
cell: (row) => (
|
|
27
|
+
<div className="flex items-center gap-3">
|
|
28
|
+
<Avatar>
|
|
29
|
+
<AvatarFallback>
|
|
30
|
+
{row.fullName
|
|
31
|
+
.split(' ')
|
|
32
|
+
.map((n) => n[0])
|
|
33
|
+
.join('')}
|
|
34
|
+
</AvatarFallback>
|
|
35
|
+
</Avatar>
|
|
36
|
+
<div>
|
|
37
|
+
<p className="font-medium">{row.fullName}</p>
|
|
38
|
+
<p className="text-sm text-muted-foreground">{row.employeeId}</p>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
),
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: 'status',
|
|
45
|
+
header: 'Status',
|
|
46
|
+
accessorKey: 'status',
|
|
47
|
+
sortable: true,
|
|
48
|
+
cell: (row) => <StatusBadge status={row.status} type="driver" />,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: 'rating',
|
|
52
|
+
header: 'Rating',
|
|
53
|
+
cell: (row) => (
|
|
54
|
+
<div className="flex items-center gap-1">
|
|
55
|
+
<Star size={14} className="text-yellow-500 fill-yellow-500" />
|
|
56
|
+
<span className="font-medium">{row.ratings.overall.toFixed(1)}</span>
|
|
57
|
+
<span className="text-muted-foreground text-sm">({row.ratings.totalRatings})</span>
|
|
58
|
+
</div>
|
|
59
|
+
),
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: 'deliveries',
|
|
63
|
+
header: 'Deliveries',
|
|
64
|
+
accessorKey: 'completedOrders',
|
|
65
|
+
sortable: true,
|
|
66
|
+
cell: (row) => <span className="font-medium">{row.completedOrders.toLocaleString()}</span>,
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: 'license',
|
|
70
|
+
header: 'License',
|
|
71
|
+
cell: (row) => (
|
|
72
|
+
<div className="text-sm">
|
|
73
|
+
<p>{row.licenseType}</p>
|
|
74
|
+
<p className="text-muted-foreground">Exp: {formatDate(row.licenseExpiry, 'short')}</p>
|
|
75
|
+
</div>
|
|
76
|
+
),
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: 'joined',
|
|
80
|
+
header: 'Join Date',
|
|
81
|
+
accessorKey: 'joinDate',
|
|
82
|
+
sortable: true,
|
|
83
|
+
cell: (row) => formatDate(row.joinDate, 'short'),
|
|
84
|
+
},
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<PageLayout
|
|
89
|
+
title="Drivers"
|
|
90
|
+
subtitle={`${totalDrivers} drivers`}
|
|
91
|
+
icon={<Users size={24} />}
|
|
92
|
+
headerActions={
|
|
93
|
+
<div className="flex gap-2">
|
|
94
|
+
<Button variant="outline" onClick={refetch}>
|
|
95
|
+
<RefreshCw size={16} /> Refresh
|
|
96
|
+
</Button>
|
|
97
|
+
<Button variant="outline">
|
|
98
|
+
<Download size={16} /> Export
|
|
99
|
+
</Button>
|
|
100
|
+
<Button>
|
|
101
|
+
<Plus size={16} /> Add Driver
|
|
102
|
+
</Button>
|
|
103
|
+
</div>
|
|
104
|
+
}
|
|
105
|
+
>
|
|
106
|
+
<DataTable
|
|
107
|
+
columns={columns}
|
|
108
|
+
data={drivers}
|
|
109
|
+
isLoading={isLoading}
|
|
110
|
+
searchable
|
|
111
|
+
searchPlaceholder="Search drivers..."
|
|
112
|
+
searchFields={['fullName', 'employeeId'] as (keyof Driver)[]}
|
|
113
|
+
onRowClick={(row) => goTo(`fleet/drivers/${row.id}`)}
|
|
114
|
+
getRowId={(row) => row.id}
|
|
115
|
+
/>
|
|
116
|
+
</PageLayout>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finance Page
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { DollarSign, TrendingUp, CreditCard, FileText, Download } from 'lucide-react';
|
|
6
|
+
import { PageLayout } from '../components/PageLayout';
|
|
7
|
+
import { MetricCard, MetricGrid } from '../components/MetricCard';
|
|
8
|
+
import { Card, CardContent, CardHeader, CardTitle, Button } from '../components/ui';
|
|
9
|
+
import { useAnalytics } from '../hooks/useAnalytics';
|
|
10
|
+
import { useOrderStats } from '../hooks/useOrders';
|
|
11
|
+
import { formatCurrency } from '../utils/formatters';
|
|
12
|
+
|
|
13
|
+
export default function FinancePage() {
|
|
14
|
+
const { analytics } = useAnalytics();
|
|
15
|
+
const { stats } = useOrderStats();
|
|
16
|
+
|
|
17
|
+
const pendingPayments = stats.totalRevenue * 0.15; // Simulated
|
|
18
|
+
const completedPayments = stats.totalRevenue * 0.85;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<PageLayout
|
|
22
|
+
title="Finance"
|
|
23
|
+
subtitle="Financial overview and reports"
|
|
24
|
+
icon={<DollarSign size={24} />}
|
|
25
|
+
headerActions={
|
|
26
|
+
<div className="flex gap-2">
|
|
27
|
+
<Button variant="outline">
|
|
28
|
+
<FileText size={16} /> Invoices
|
|
29
|
+
</Button>
|
|
30
|
+
<Button variant="outline">
|
|
31
|
+
<Download size={16} /> Export
|
|
32
|
+
</Button>
|
|
33
|
+
</div>
|
|
34
|
+
}
|
|
35
|
+
>
|
|
36
|
+
<MetricGrid columns={4}>
|
|
37
|
+
<MetricCard
|
|
38
|
+
label="Total Revenue"
|
|
39
|
+
value={formatCurrency(analytics.overview.totalRevenue)}
|
|
40
|
+
icon={<DollarSign size={20} />}
|
|
41
|
+
change="+12.5%"
|
|
42
|
+
changeType="positive"
|
|
43
|
+
trend="up"
|
|
44
|
+
/>
|
|
45
|
+
<MetricCard
|
|
46
|
+
label="Completed"
|
|
47
|
+
value={formatCurrency(completedPayments)}
|
|
48
|
+
icon={<TrendingUp size={20} />}
|
|
49
|
+
changeType="positive"
|
|
50
|
+
/>
|
|
51
|
+
<MetricCard
|
|
52
|
+
label="Pending"
|
|
53
|
+
value={formatCurrency(pendingPayments)}
|
|
54
|
+
icon={<CreditCard size={20} />}
|
|
55
|
+
changeType="neutral"
|
|
56
|
+
/>
|
|
57
|
+
<MetricCard
|
|
58
|
+
label="Avg Order Value"
|
|
59
|
+
value={formatCurrency(stats.avgOrderValue)}
|
|
60
|
+
icon={<DollarSign size={20} />}
|
|
61
|
+
/>
|
|
62
|
+
</MetricGrid>
|
|
63
|
+
|
|
64
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
65
|
+
<Card>
|
|
66
|
+
<CardHeader>
|
|
67
|
+
<CardTitle>Revenue by Month</CardTitle>
|
|
68
|
+
</CardHeader>
|
|
69
|
+
<CardContent>
|
|
70
|
+
<div className="space-y-4">
|
|
71
|
+
{analytics.trends.revenue.map((r) => (
|
|
72
|
+
<div
|
|
73
|
+
key={r.month}
|
|
74
|
+
className="flex items-center justify-between p-3 bg-muted/50 rounded-lg"
|
|
75
|
+
>
|
|
76
|
+
<span className="font-medium">{r.month} 2024</span>
|
|
77
|
+
<span className="text-lg font-bold">{formatCurrency(r.revenue)}</span>
|
|
78
|
+
</div>
|
|
79
|
+
))}
|
|
80
|
+
</div>
|
|
81
|
+
</CardContent>
|
|
82
|
+
</Card>
|
|
83
|
+
|
|
84
|
+
<Card>
|
|
85
|
+
<CardHeader>
|
|
86
|
+
<CardTitle>Payment Status</CardTitle>
|
|
87
|
+
</CardHeader>
|
|
88
|
+
<CardContent>
|
|
89
|
+
<div className="space-y-4">
|
|
90
|
+
<div className="flex items-center justify-between p-4 bg-green-50 dark:bg-green-900/20 rounded-lg">
|
|
91
|
+
<div className="flex items-center gap-3">
|
|
92
|
+
<div className="w-10 h-10 rounded-full bg-green-100 dark:bg-green-800 flex items-center justify-center">
|
|
93
|
+
<TrendingUp size={20} className="text-green-600" />
|
|
94
|
+
</div>
|
|
95
|
+
<div>
|
|
96
|
+
<p className="font-medium">Paid</p>
|
|
97
|
+
<p className="text-sm text-muted-foreground">
|
|
98
|
+
{stats.byStatus.delivered} orders
|
|
99
|
+
</p>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
<span className="text-xl font-bold text-green-600">
|
|
103
|
+
{formatCurrency(completedPayments)}
|
|
104
|
+
</span>
|
|
105
|
+
</div>
|
|
106
|
+
<div className="flex items-center justify-between p-4 bg-yellow-50 dark:bg-yellow-900/20 rounded-lg">
|
|
107
|
+
<div className="flex items-center gap-3">
|
|
108
|
+
<div className="w-10 h-10 rounded-full bg-yellow-100 dark:bg-yellow-800 flex items-center justify-center">
|
|
109
|
+
<CreditCard size={20} className="text-yellow-600" />
|
|
110
|
+
</div>
|
|
111
|
+
<div>
|
|
112
|
+
<p className="font-medium">Pending</p>
|
|
113
|
+
<p className="text-sm text-muted-foreground">
|
|
114
|
+
{stats.byStatus.pending + stats.byStatus.in_transit} orders
|
|
115
|
+
</p>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
<span className="text-xl font-bold text-yellow-600">
|
|
119
|
+
{formatCurrency(pendingPayments)}
|
|
120
|
+
</span>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
</CardContent>
|
|
124
|
+
</Card>
|
|
125
|
+
</div>
|
|
126
|
+
|
|
127
|
+
<Card>
|
|
128
|
+
<CardHeader>
|
|
129
|
+
<CardTitle>Recent Transactions</CardTitle>
|
|
130
|
+
</CardHeader>
|
|
131
|
+
<CardContent>
|
|
132
|
+
<div className="text-center py-8 text-muted-foreground">
|
|
133
|
+
<FileText size={48} className="mx-auto mb-4 opacity-50" />
|
|
134
|
+
<p>Transaction history would be displayed here</p>
|
|
135
|
+
<p className="text-sm">Integration with payment gateway required</p>
|
|
136
|
+
</div>
|
|
137
|
+
</CardContent>
|
|
138
|
+
</Card>
|
|
139
|
+
</PageLayout>
|
|
140
|
+
);
|
|
141
|
+
}
|