@burdenoff/microfe-movethewheels 2026.1031.2 → 2026.1031.4
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/dist/MoveTheWheelsRoot.js +121 -104
- package/dist/MoveTheWheelsRoutes.js +142 -133
- package/dist/components/DocumentsCard.js +11 -11
- package/dist/components/ProofOfDeliveryCard.js +13 -13
- package/dist/components/ShipmentRiskDialog.js +24 -24
- package/dist/components/ShippingQuoteResults.js +46 -46
- package/dist/components/TrackingAlertList.js +17 -17
- package/dist/generated/tracking-quality-operations.d.ts +140 -0
- package/dist/hooks/useEntityImport.js +68 -0
- package/dist/hooks/useOrderDispatch.js +17 -17
- package/dist/movethewheels/hooks/useEntityImport.d.ts +19 -0
- package/dist/movethewheels/pages/ImportExportPage.d.ts +9 -0
- package/dist/movethewheels/pages/SettingsPage.d.ts +1 -0
- package/dist/movethewheels/providers/ModuleSettingsProvider.d.ts +17 -0
- package/dist/movethewheels/utils/entityImport.d.ts +109 -0
- package/dist/movethewheels/utils/formatters.d.ts +23 -3
- package/dist/movethewheels/utils/moduleSettings.d.ts +52 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/arrow-down-up.js +22 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/bell.js +11 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/file-spreadsheet.js +30 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/file-up.js +22 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/key-round.js +14 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/plug.js +22 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/rotate-ccw.js +11 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/settings.js +13 -0
- package/dist/pages/AnalyticsPage.js +27 -27
- package/dist/pages/CreateOrderPage.js +340 -317
- package/dist/pages/CustomerDetailsPage.js +246 -246
- package/dist/pages/CustomersPage.js +88 -79
- package/dist/pages/DashboardPage.js +24 -24
- package/dist/pages/DeliveryCapturePage.js +74 -74
- package/dist/pages/DriverDetailsPage.js +337 -337
- package/dist/pages/DriversPage.js +119 -110
- package/dist/pages/FinancePage.js +26 -26
- package/dist/pages/ImportExportPage.js +435 -0
- package/dist/pages/InventoryPage.js +28 -28
- package/dist/pages/LiveTrackingPage.js +108 -108
- package/dist/pages/MarketplacePage.js +44 -44
- package/dist/pages/OrderDetailsPage.js +306 -306
- package/dist/pages/OrdersListPage.js +27 -27
- package/dist/pages/ProductDetailsPage.js +89 -89
- package/dist/pages/ProductsPage.js +86 -77
- package/dist/pages/RouteDetailsPage.js +282 -285
- package/dist/pages/RoutesPage.js +78 -78
- package/dist/pages/SettingsPage.js +459 -0
- package/dist/pages/TrackingPage.js +41 -41
- package/dist/pages/VehicleDetailsPage.js +207 -207
- package/dist/pages/VehiclesPage.js +100 -90
- package/dist/pages/WarehouseDetailsPage.js +132 -132
- package/dist/pages/WarehousesPage.js +97 -88
- package/dist/providers/ModuleSettingsProvider.js +74 -0
- package/dist/utils/entityImport.js +73 -0
- package/dist/utils/formatters.js +53 -26
- package/dist/utils/moduleSettings.js +132 -0
- package/package.json +4 -2
- package/src/generated/tracking-quality-operations.ts +184 -0
- package/src/movethewheels/MoveTheWheelsRoot.tsx +22 -3
- package/src/movethewheels/MoveTheWheelsRoutes.tsx +13 -0
- package/src/movethewheels/hooks/useEntityImport.ts +108 -0
- package/src/movethewheels/pages/CreateOrderPage.tsx +38 -6
- package/src/movethewheels/pages/CustomersPage.tsx +6 -1
- package/src/movethewheels/pages/DriversPage.tsx +6 -0
- package/src/movethewheels/pages/ImportExportPage.tsx +483 -0
- package/src/movethewheels/pages/ProductsPage.tsx +16 -3
- package/src/movethewheels/pages/RouteDetailsPage.tsx +3 -6
- package/src/movethewheels/pages/RoutesPage.tsx +2 -2
- package/src/movethewheels/pages/SettingsPage.tsx +516 -0
- package/src/movethewheels/pages/VehicleDetailsPage.tsx +4 -2
- package/src/movethewheels/pages/VehiclesPage.tsx +8 -1
- package/src/movethewheels/pages/WarehousesPage.tsx +6 -1
- package/src/movethewheels/providers/ModuleSettingsProvider.tsx +133 -0
- package/src/movethewheels/utils/entityImport.ts +239 -0
- package/src/movethewheels/utils/formatters.ts +69 -10
- package/src/movethewheels/utils/moduleSettings.ts +224 -0
|
@@ -5,172 +5,181 @@ import { Plus as te } from "../node_modules/lucide-react/dist/esm/icons/plus.js"
|
|
|
5
5
|
import { RefreshCw as n } from "../node_modules/lucide-react/dist/esm/icons/refresh-cw.js";
|
|
6
6
|
import { Star as r } from "../node_modules/lucide-react/dist/esm/icons/star.js";
|
|
7
7
|
import { Truck as ne } from "../node_modules/lucide-react/dist/esm/icons/truck.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { Upload as re } from "../node_modules/lucide-react/dist/esm/icons/upload.js";
|
|
9
|
+
import { UserCheck as ie } from "../node_modules/lucide-react/dist/esm/icons/user-check.js";
|
|
10
|
+
import { UserMinus as ae } from "../node_modules/lucide-react/dist/esm/icons/user-minus.js";
|
|
10
11
|
import { Users as i } from "../node_modules/lucide-react/dist/esm/icons/users.js";
|
|
11
|
-
import { joinPath as
|
|
12
|
-
import { useMoveTheWheels as
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { useDebouncedValue as
|
|
22
|
-
import { useEntityExport as
|
|
23
|
-
import { ExportStatusBanner as
|
|
24
|
-
import { useMemo as
|
|
25
|
-
import { jsx as
|
|
26
|
-
import { CTAOverflowMenu as
|
|
12
|
+
import { joinPath as oe } from "../utils/navigation.js";
|
|
13
|
+
import { useMoveTheWheels as a } from "../providers/MoveTheWheelsProvider.js";
|
|
14
|
+
import { formatDate as o } from "../utils/formatters.js";
|
|
15
|
+
import { useDriverStatusCounts as s, useDrivers as c, useFleetStats as l, useVehicles as u } from "../hooks/useFleet.js";
|
|
16
|
+
import { Avatar as d, AvatarFallback as f, Button as se, Card as p, CardContent as m, Select as h, SelectContent as g, SelectItem as _, SelectTrigger as v, SelectValue as y } from "../components/ui.js";
|
|
17
|
+
import { PageLayout as ce } from "../components/PageLayout.js";
|
|
18
|
+
import { MetricCard as b, MetricGrid as le } from "../components/MetricCard.js";
|
|
19
|
+
import { DRIVER_STATUS_LABELS as x } from "../constants/index.js";
|
|
20
|
+
import { StatusBadge as ue } from "../components/StatusBadge.js";
|
|
21
|
+
import { DataTable as de } from "../components/DataTable.js";
|
|
22
|
+
import { useDebouncedValue as fe } from "../hooks/useDebouncedValue.js";
|
|
23
|
+
import { useEntityExport as S } from "../hooks/useEntityExport.js";
|
|
24
|
+
import { ExportStatusBanner as C } from "../components/ExportStatusBanner.js";
|
|
25
|
+
import { useMemo as w, useState as T } from "react";
|
|
26
|
+
import { jsx as E, jsxs as D } from "react/jsx-runtime";
|
|
27
|
+
import { CTAOverflowMenu as O, PagePurpose as k } from "@burdenoff/fe-libs/ui";
|
|
27
28
|
//#region src/movethewheels/pages/DriversPage.tsx
|
|
28
|
-
var
|
|
29
|
+
var A = [{
|
|
29
30
|
value: "all",
|
|
30
31
|
label: "All statuses"
|
|
31
|
-
}, ...Object.entries(
|
|
32
|
+
}, ...Object.entries(x).map(([e, t]) => ({
|
|
32
33
|
value: e,
|
|
33
34
|
label: t
|
|
34
35
|
}))];
|
|
35
|
-
function
|
|
36
|
-
let { basePath:
|
|
37
|
-
limit:
|
|
38
|
-
offset:
|
|
39
|
-
search:
|
|
40
|
-
status:
|
|
41
|
-
licenseClass:
|
|
42
|
-
}), { stats:
|
|
43
|
-
return /* @__PURE__ */
|
|
36
|
+
function j() {
|
|
37
|
+
let { basePath: x, navigate: j } = a(), { state: M, isExporting: N, startExport: P, dismiss: F } = S("drivers", "driver"), [I, L] = T(0), [R, z] = T(25), [B, V] = T(""), pe = fe(B), [H, U] = T("all"), [W, G] = T("all"), { drivers: K, totalDrivers: me, hasMore: he, isLoading: ge, error: _e, refetch: q } = c({
|
|
38
|
+
limit: R,
|
|
39
|
+
offset: I * R,
|
|
40
|
+
search: pe || void 0,
|
|
41
|
+
status: H === "all" ? void 0 : H,
|
|
42
|
+
licenseClass: W === "all" ? void 0 : W
|
|
43
|
+
}), { stats: J } = l(), { counts: Y } = s(), { vehicles: X } = u({ ids: w(() => Array.from(new Set(K.map((e) => e.assignedVehicle).filter(Boolean))), [K]) }), ve = w(() => new Map(X.map((e) => [e.id, e.vehicleNumber])), [X]), Z = J.totalDrivers, ye = w(() => Array.from(new Set(K.map((e) => e.licenseType).filter(Boolean))).sort((e, t) => e.localeCompare(t)), [K]), Q = H !== "all" || W !== "all" || B.length > 0, $ = (e) => j?.(oe(x, e));
|
|
44
|
+
return /* @__PURE__ */ D(ce, {
|
|
44
45
|
title: "Drivers",
|
|
45
|
-
subtitle: `${
|
|
46
|
-
icon: /* @__PURE__ */
|
|
47
|
-
headerActions: /* @__PURE__ */
|
|
46
|
+
subtitle: `${Z} drivers`,
|
|
47
|
+
icon: /* @__PURE__ */ E(i, { size: 24 }),
|
|
48
|
+
headerActions: /* @__PURE__ */ E(O, {
|
|
48
49
|
primary: {
|
|
49
50
|
label: "Add Driver",
|
|
50
|
-
icon: /* @__PURE__ */
|
|
51
|
+
icon: /* @__PURE__ */ E(te, { size: 16 }),
|
|
51
52
|
onSelect: () => $("fleet/drivers/new")
|
|
52
53
|
},
|
|
53
|
-
actions: [
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
actions: [
|
|
55
|
+
{
|
|
56
|
+
label: "Refresh",
|
|
57
|
+
icon: /* @__PURE__ */ E(n, { size: 16 }),
|
|
58
|
+
onSelect: () => q()
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
label: "Import",
|
|
62
|
+
icon: /* @__PURE__ */ E(re, { size: 16 }),
|
|
63
|
+
onSelect: () => $("import-export?entity=DRIVER")
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
label: N ? "Exporting…" : "Export",
|
|
67
|
+
icon: /* @__PURE__ */ E(t, { size: 16 }),
|
|
68
|
+
onSelect: P
|
|
69
|
+
}
|
|
70
|
+
]
|
|
62
71
|
}),
|
|
63
72
|
children: [
|
|
64
|
-
/* @__PURE__ */
|
|
65
|
-
icon: /* @__PURE__ */
|
|
73
|
+
/* @__PURE__ */ E(k, {
|
|
74
|
+
icon: /* @__PURE__ */ E(i, { size: 18 }),
|
|
66
75
|
children: "Your delivery workforce. Track each driver's availability, rating, licence status, contact number and the vehicle they are on — open a driver to review their record before assigning them to an order or route."
|
|
67
76
|
}),
|
|
68
|
-
/* @__PURE__ */
|
|
69
|
-
state:
|
|
70
|
-
onDismiss:
|
|
77
|
+
/* @__PURE__ */ E(C, {
|
|
78
|
+
state: M,
|
|
79
|
+
onDismiss: F
|
|
71
80
|
}),
|
|
72
|
-
/* @__PURE__ */
|
|
81
|
+
/* @__PURE__ */ D("div", { children: [/* @__PURE__ */ E("p", {
|
|
73
82
|
className: "mb-3 text-sm font-medium text-text-secondary",
|
|
74
83
|
children: "Workforce at a glance"
|
|
75
|
-
}), /* @__PURE__ */
|
|
84
|
+
}), /* @__PURE__ */ D(le, {
|
|
76
85
|
columns: 4,
|
|
77
86
|
children: [
|
|
78
|
-
/* @__PURE__ */
|
|
87
|
+
/* @__PURE__ */ E(b, {
|
|
79
88
|
label: "On duty",
|
|
80
|
-
value:
|
|
81
|
-
icon: /* @__PURE__ */
|
|
89
|
+
value: J.driversByStatus.available + J.driversByStatus.busy,
|
|
90
|
+
icon: /* @__PURE__ */ E(ie, { size: 20 }),
|
|
82
91
|
accent: "success",
|
|
83
92
|
subtitle: "Available or delivering"
|
|
84
93
|
}),
|
|
85
|
-
/* @__PURE__ */
|
|
94
|
+
/* @__PURE__ */ E(b, {
|
|
86
95
|
label: "On break",
|
|
87
|
-
value:
|
|
88
|
-
icon: /* @__PURE__ */
|
|
96
|
+
value: Y.onBreak,
|
|
97
|
+
icon: /* @__PURE__ */ E(e, { size: 20 }),
|
|
89
98
|
accent: "warning",
|
|
90
99
|
subtitle: "Back on shift shortly"
|
|
91
100
|
}),
|
|
92
|
-
/* @__PURE__ */
|
|
101
|
+
/* @__PURE__ */ E(b, {
|
|
93
102
|
label: "Off duty",
|
|
94
|
-
value:
|
|
95
|
-
icon: /* @__PURE__ */
|
|
103
|
+
value: Y.offDuty,
|
|
104
|
+
icon: /* @__PURE__ */ E(ae, { size: 20 }),
|
|
96
105
|
accent: "neutral",
|
|
97
|
-
subtitle:
|
|
106
|
+
subtitle: Y.inactive > 0 ? `${Y.inactive} inactive` : void 0
|
|
98
107
|
}),
|
|
99
|
-
/* @__PURE__ */
|
|
108
|
+
/* @__PURE__ */ E(b, {
|
|
100
109
|
label: "Avg rating",
|
|
101
|
-
value:
|
|
102
|
-
icon: /* @__PURE__ */
|
|
110
|
+
value: J.avgDriverRating > 0 ? J.avgDriverRating.toFixed(1) : "—",
|
|
111
|
+
icon: /* @__PURE__ */ E(r, { size: 20 }),
|
|
103
112
|
accent: "brand",
|
|
104
|
-
subtitle: `${
|
|
113
|
+
subtitle: `${Z} drivers`
|
|
105
114
|
})
|
|
106
115
|
]
|
|
107
116
|
})] }),
|
|
108
|
-
/* @__PURE__ */
|
|
117
|
+
/* @__PURE__ */ E(p, { children: /* @__PURE__ */ E(m, {
|
|
109
118
|
className: "p-4",
|
|
110
|
-
children: /* @__PURE__ */
|
|
119
|
+
children: /* @__PURE__ */ D("div", {
|
|
111
120
|
className: "flex flex-wrap items-center gap-4",
|
|
112
121
|
children: [
|
|
113
|
-
/* @__PURE__ */
|
|
122
|
+
/* @__PURE__ */ D("div", {
|
|
114
123
|
className: "flex items-center gap-2",
|
|
115
|
-
children: [/* @__PURE__ */
|
|
124
|
+
children: [/* @__PURE__ */ E(ee, {
|
|
116
125
|
size: 16,
|
|
117
126
|
className: "text-text-secondary"
|
|
118
|
-
}), /* @__PURE__ */
|
|
127
|
+
}), /* @__PURE__ */ E("span", {
|
|
119
128
|
className: "text-sm font-medium",
|
|
120
129
|
children: "Filters:"
|
|
121
130
|
})]
|
|
122
131
|
}),
|
|
123
|
-
/* @__PURE__ */
|
|
124
|
-
value:
|
|
132
|
+
/* @__PURE__ */ D(h, {
|
|
133
|
+
value: H,
|
|
125
134
|
onValueChange: (e) => {
|
|
126
|
-
|
|
135
|
+
U(e), L(0);
|
|
127
136
|
},
|
|
128
|
-
children: [/* @__PURE__ */
|
|
137
|
+
children: [/* @__PURE__ */ E(v, {
|
|
129
138
|
className: "w-[180px]",
|
|
130
|
-
children: /* @__PURE__ */
|
|
131
|
-
}), /* @__PURE__ */
|
|
139
|
+
children: /* @__PURE__ */ E(y, { placeholder: "Status" })
|
|
140
|
+
}), /* @__PURE__ */ E(g, { children: A.map((e) => /* @__PURE__ */ E(_, {
|
|
132
141
|
value: e.value,
|
|
133
142
|
children: e.label
|
|
134
143
|
}, e.value)) })]
|
|
135
144
|
}),
|
|
136
|
-
/* @__PURE__ */
|
|
137
|
-
value:
|
|
145
|
+
/* @__PURE__ */ D(h, {
|
|
146
|
+
value: W,
|
|
138
147
|
onValueChange: (e) => {
|
|
139
|
-
|
|
148
|
+
G(e), L(0);
|
|
140
149
|
},
|
|
141
|
-
children: [/* @__PURE__ */
|
|
150
|
+
children: [/* @__PURE__ */ E(v, {
|
|
142
151
|
className: "w-[180px]",
|
|
143
|
-
children: /* @__PURE__ */
|
|
144
|
-
}), /* @__PURE__ */
|
|
152
|
+
children: /* @__PURE__ */ E(y, { placeholder: "License class" })
|
|
153
|
+
}), /* @__PURE__ */ D(g, { children: [/* @__PURE__ */ E(_, {
|
|
145
154
|
value: "all",
|
|
146
155
|
children: "All licence classes"
|
|
147
|
-
}),
|
|
156
|
+
}), ye.map((e) => /* @__PURE__ */ E(_, {
|
|
148
157
|
value: e,
|
|
149
158
|
children: e
|
|
150
159
|
}, e))] })]
|
|
151
160
|
}),
|
|
152
|
-
Q && /* @__PURE__ */
|
|
161
|
+
Q && /* @__PURE__ */ E(se, {
|
|
153
162
|
variant: "ghost",
|
|
154
163
|
size: "sm",
|
|
155
164
|
onClick: () => {
|
|
156
|
-
|
|
165
|
+
U("all"), G("all"), V(""), L(0);
|
|
157
166
|
},
|
|
158
167
|
children: "Clear filters"
|
|
159
168
|
})
|
|
160
169
|
]
|
|
161
170
|
})
|
|
162
171
|
}) }),
|
|
163
|
-
/* @__PURE__ */
|
|
172
|
+
/* @__PURE__ */ E(de, {
|
|
164
173
|
columns: [
|
|
165
174
|
{
|
|
166
175
|
id: "driver",
|
|
167
176
|
header: "Driver",
|
|
168
|
-
cell: (e) => /* @__PURE__ */
|
|
177
|
+
cell: (e) => /* @__PURE__ */ D("div", {
|
|
169
178
|
className: "flex items-center gap-3",
|
|
170
|
-
children: [/* @__PURE__ */
|
|
179
|
+
children: [/* @__PURE__ */ E(d, { children: /* @__PURE__ */ E(f, { children: e.fullName.split(" ").map((e) => e[0]).join("") }) }), /* @__PURE__ */ D("div", { children: [/* @__PURE__ */ E("p", {
|
|
171
180
|
className: "font-medium",
|
|
172
181
|
children: e.fullName
|
|
173
|
-
}), /* @__PURE__ */
|
|
182
|
+
}), /* @__PURE__ */ E("p", {
|
|
174
183
|
className: "text-sm text-text-secondary",
|
|
175
184
|
children: e.employeeId
|
|
176
185
|
})] })]
|
|
@@ -181,7 +190,7 @@ function A() {
|
|
|
181
190
|
header: "Status",
|
|
182
191
|
accessorKey: "status",
|
|
183
192
|
sortable: !0,
|
|
184
|
-
cell: (e) => /* @__PURE__ */
|
|
193
|
+
cell: (e) => /* @__PURE__ */ E(ue, {
|
|
185
194
|
status: e.status,
|
|
186
195
|
type: "driver"
|
|
187
196
|
})
|
|
@@ -189,11 +198,11 @@ function A() {
|
|
|
189
198
|
{
|
|
190
199
|
id: "license",
|
|
191
200
|
header: "License",
|
|
192
|
-
cell: (e) => /* @__PURE__ */
|
|
201
|
+
cell: (e) => /* @__PURE__ */ D("div", {
|
|
193
202
|
className: "text-sm",
|
|
194
|
-
children: [/* @__PURE__ */
|
|
203
|
+
children: [/* @__PURE__ */ E("p", { children: e.licenseType }), /* @__PURE__ */ E("p", {
|
|
195
204
|
className: "text-text-secondary",
|
|
196
|
-
children: e.licenseExpiry ? `Exp: ${
|
|
205
|
+
children: e.licenseExpiry ? `Exp: ${o(e.licenseExpiry, "short")}` : "Expiry not recorded"
|
|
197
206
|
})]
|
|
198
207
|
})
|
|
199
208
|
},
|
|
@@ -201,12 +210,12 @@ function A() {
|
|
|
201
210
|
id: "phone",
|
|
202
211
|
header: "Phone",
|
|
203
212
|
accessorKey: "phone",
|
|
204
|
-
cell: (e) => e.phone ? /* @__PURE__ */
|
|
213
|
+
cell: (e) => e.phone ? /* @__PURE__ */ E("a", {
|
|
205
214
|
href: `tel:${e.phone}`,
|
|
206
215
|
className: "text-sm hover:underline",
|
|
207
216
|
onClick: (e) => e.stopPropagation(),
|
|
208
217
|
children: e.phone
|
|
209
|
-
}) : /* @__PURE__ */
|
|
218
|
+
}) : /* @__PURE__ */ E("span", {
|
|
210
219
|
className: "text-sm text-text-secondary",
|
|
211
220
|
children: "—"
|
|
212
221
|
})
|
|
@@ -214,15 +223,15 @@ function A() {
|
|
|
214
223
|
{
|
|
215
224
|
id: "rating",
|
|
216
225
|
header: "Rating",
|
|
217
|
-
cell: (e) => e.rating === void 0 ? /* @__PURE__ */
|
|
226
|
+
cell: (e) => e.rating === void 0 ? /* @__PURE__ */ E("span", {
|
|
218
227
|
className: "text-sm text-text-secondary",
|
|
219
228
|
children: "Not rated"
|
|
220
|
-
}) : /* @__PURE__ */
|
|
229
|
+
}) : /* @__PURE__ */ D("div", {
|
|
221
230
|
className: "flex items-center gap-1",
|
|
222
|
-
children: [/* @__PURE__ */
|
|
231
|
+
children: [/* @__PURE__ */ E(r, {
|
|
223
232
|
size: 14,
|
|
224
233
|
className: "text-status-warning-text fill-current"
|
|
225
|
-
}), /* @__PURE__ */
|
|
234
|
+
}), /* @__PURE__ */ E("span", {
|
|
226
235
|
className: "font-medium",
|
|
227
236
|
children: e.rating.toFixed(1)
|
|
228
237
|
})]
|
|
@@ -232,14 +241,14 @@ function A() {
|
|
|
232
241
|
id: "vehicle",
|
|
233
242
|
header: "Assigned vehicle",
|
|
234
243
|
cell: (e) => {
|
|
235
|
-
if (!e.assignedVehicle) return /* @__PURE__ */
|
|
244
|
+
if (!e.assignedVehicle) return /* @__PURE__ */ E("span", {
|
|
236
245
|
className: "text-sm text-text-secondary",
|
|
237
246
|
children: "Unassigned"
|
|
238
247
|
});
|
|
239
248
|
let t = ve.get(e.assignedVehicle);
|
|
240
|
-
return /* @__PURE__ */
|
|
249
|
+
return /* @__PURE__ */ D("span", {
|
|
241
250
|
className: "inline-flex items-center gap-1.5 text-sm font-medium",
|
|
242
|
-
children: [/* @__PURE__ */
|
|
251
|
+
children: [/* @__PURE__ */ E(ne, {
|
|
243
252
|
size: 14,
|
|
244
253
|
className: "text-text-secondary"
|
|
245
254
|
}), t ?? "Assigned"]
|
|
@@ -251,30 +260,30 @@ function A() {
|
|
|
251
260
|
header: "Hire Date",
|
|
252
261
|
accessorKey: "hireDate",
|
|
253
262
|
sortable: !0,
|
|
254
|
-
cell: (e) => e.hireDate ?
|
|
263
|
+
cell: (e) => e.hireDate ? o(e.hireDate, "short") : /* @__PURE__ */ E("span", {
|
|
255
264
|
className: "text-text-secondary",
|
|
256
265
|
children: "Not recorded"
|
|
257
266
|
})
|
|
258
267
|
}
|
|
259
268
|
],
|
|
260
|
-
data:
|
|
269
|
+
data: K,
|
|
261
270
|
isLoading: ge,
|
|
262
271
|
error: _e,
|
|
263
|
-
onRetry:
|
|
272
|
+
onRetry: q,
|
|
264
273
|
searchable: !0,
|
|
265
274
|
searchPlaceholder: "Search drivers...",
|
|
266
275
|
searchFields: ["fullName", "employeeId"],
|
|
267
|
-
searchQuery:
|
|
276
|
+
searchQuery: B,
|
|
268
277
|
onSearchQueryChange: (e) => {
|
|
269
|
-
|
|
278
|
+
V(e), L(0);
|
|
270
279
|
},
|
|
271
280
|
onRowClick: (e) => $(`fleet/drivers/${e.id}`),
|
|
272
281
|
getRowId: (e) => e.id,
|
|
273
|
-
pageIndex:
|
|
274
|
-
pageSize:
|
|
275
|
-
onPageChange:
|
|
282
|
+
pageIndex: I,
|
|
283
|
+
pageSize: R,
|
|
284
|
+
onPageChange: L,
|
|
276
285
|
onPageSizeChange: (e) => {
|
|
277
|
-
|
|
286
|
+
z(e), L(0);
|
|
278
287
|
},
|
|
279
288
|
totalItems: me,
|
|
280
289
|
hasNextPage: he,
|
|
@@ -286,4 +295,4 @@ function A() {
|
|
|
286
295
|
});
|
|
287
296
|
}
|
|
288
297
|
//#endregion
|
|
289
|
-
export {
|
|
298
|
+
export { j as default };
|
|
@@ -5,21 +5,21 @@ import { FileText as r } from "../node_modules/lucide-react/dist/esm/icons/file-
|
|
|
5
5
|
import { Fuel as i } from "../node_modules/lucide-react/dist/esm/icons/fuel.js";
|
|
6
6
|
import { TrendingUp as a } from "../node_modules/lucide-react/dist/esm/icons/trending-up.js";
|
|
7
7
|
import { useMoveTheWheels as o } from "../providers/MoveTheWheelsProvider.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
8
|
+
import { formatCurrency as s } from "../utils/formatters.js";
|
|
9
|
+
import { useAnalytics as c, useFinanceMetrics as l } from "../hooks/useAnalytics.js";
|
|
10
|
+
import { Button as u, Card as d, CardContent as f, CardHeader as p, CardTitle as m } from "../components/ui.js";
|
|
11
|
+
import { PageLayout as h } from "../components/PageLayout.js";
|
|
12
|
+
import { chartTokens as g } from "../components/charts/chartTokens.js";
|
|
13
|
+
import { MetricCard as _, MetricGrid as v } from "../components/MetricCard.js";
|
|
14
|
+
import { TrendChart as y } from "../components/charts/TrendChart.js";
|
|
15
|
+
import { VolumeBar as b } from "../components/charts/VolumeBar.js";
|
|
15
16
|
import "../components/charts/index.js";
|
|
16
|
-
import { formatCurrency as b } from "../utils/formatters.js";
|
|
17
17
|
import { useMemo as x } from "react";
|
|
18
18
|
import { jsx as S, jsxs as C } from "react/jsx-runtime";
|
|
19
19
|
import { EmphasisPanel as w, PagePurpose as T } from "@burdenoff/fe-libs/ui";
|
|
20
20
|
//#region src/movethewheels/pages/FinancePage.tsx
|
|
21
21
|
function E() {
|
|
22
|
-
let { analytics: E } =
|
|
22
|
+
let { analytics: E } = c(), { metrics: D } = l(), { navigate: O } = o(), k = () => O("/billing"), A = x(() => E.trends.revenue.map((e) => ({
|
|
23
23
|
month: e.month,
|
|
24
24
|
revenue: e.revenue
|
|
25
25
|
})), [E.trends.revenue]), j = x(() => [
|
|
@@ -40,11 +40,11 @@ function E() {
|
|
|
40
40
|
D.deliveredRevenue,
|
|
41
41
|
D.fuelCost
|
|
42
42
|
]), M = j.some((e) => e.amount > 0);
|
|
43
|
-
return /* @__PURE__ */ C(
|
|
43
|
+
return /* @__PURE__ */ C(h, {
|
|
44
44
|
title: "Finance",
|
|
45
45
|
subtitle: "Financial overview and reports",
|
|
46
46
|
icon: /* @__PURE__ */ S(n, { size: 24 }),
|
|
47
|
-
headerActions: /* @__PURE__ */ C(
|
|
47
|
+
headerActions: /* @__PURE__ */ C(u, {
|
|
48
48
|
variant: "outline",
|
|
49
49
|
onClick: k,
|
|
50
50
|
children: [/* @__PURE__ */ S(r, { size: 16 }), " Invoices & Billing"]
|
|
@@ -54,30 +54,30 @@ function E() {
|
|
|
54
54
|
icon: /* @__PURE__ */ S(n, { size: 18 }),
|
|
55
55
|
children: "Follow the money behind your deliveries. See total revenue, how much has already been collected on delivered orders, fuel cost and how many invoices are still open — then head to Billing to raise and settle invoices."
|
|
56
56
|
}),
|
|
57
|
-
/* @__PURE__ */ C(
|
|
57
|
+
/* @__PURE__ */ C(v, {
|
|
58
58
|
columns: 4,
|
|
59
59
|
children: [
|
|
60
|
-
/* @__PURE__ */ S(
|
|
60
|
+
/* @__PURE__ */ S(_, {
|
|
61
61
|
treatment: "glass",
|
|
62
62
|
glow: !0,
|
|
63
63
|
label: "Total Revenue",
|
|
64
|
-
value:
|
|
64
|
+
value: s(D.totalRevenue),
|
|
65
65
|
icon: /* @__PURE__ */ S(n, { size: 20 }),
|
|
66
66
|
accent: "success"
|
|
67
67
|
}),
|
|
68
|
-
/* @__PURE__ */ S(
|
|
68
|
+
/* @__PURE__ */ S(_, {
|
|
69
69
|
label: "Collected (Delivered)",
|
|
70
|
-
value:
|
|
70
|
+
value: s(D.deliveredRevenue),
|
|
71
71
|
icon: /* @__PURE__ */ S(a, { size: 20 }),
|
|
72
72
|
accent: "brand"
|
|
73
73
|
}),
|
|
74
|
-
/* @__PURE__ */ S(
|
|
74
|
+
/* @__PURE__ */ S(_, {
|
|
75
75
|
label: "Fuel Cost",
|
|
76
|
-
value:
|
|
76
|
+
value: s(D.fuelCost),
|
|
77
77
|
icon: /* @__PURE__ */ S(i, { size: 20 }),
|
|
78
78
|
accent: "warning"
|
|
79
79
|
}),
|
|
80
|
-
/* @__PURE__ */ S(
|
|
80
|
+
/* @__PURE__ */ S(_, {
|
|
81
81
|
label: "Open Invoices",
|
|
82
82
|
value: String(D.openInvoices),
|
|
83
83
|
icon: /* @__PURE__ */ S(t, { size: 20 }),
|
|
@@ -87,9 +87,9 @@ function E() {
|
|
|
87
87
|
}),
|
|
88
88
|
/* @__PURE__ */ C("div", {
|
|
89
89
|
className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
|
|
90
|
-
children: [/* @__PURE__ */ C(
|
|
90
|
+
children: [/* @__PURE__ */ C(d, {
|
|
91
91
|
className: "lg:col-span-2",
|
|
92
|
-
children: [/* @__PURE__ */ S(
|
|
92
|
+
children: [/* @__PURE__ */ S(p, { children: /* @__PURE__ */ S(m, { children: "Revenue trend" }) }), /* @__PURE__ */ S(f, { children: /* @__PURE__ */ S(y, {
|
|
93
93
|
xKey: "month",
|
|
94
94
|
variant: "area",
|
|
95
95
|
height: 280,
|
|
@@ -98,9 +98,9 @@ function E() {
|
|
|
98
98
|
series: [{
|
|
99
99
|
dataKey: "revenue",
|
|
100
100
|
name: "Revenue",
|
|
101
|
-
color:
|
|
101
|
+
color: g.brandBlue
|
|
102
102
|
}],
|
|
103
|
-
valueFormatter: (e) =>
|
|
103
|
+
valueFormatter: (e) => s(Number(e)),
|
|
104
104
|
emptyMessage: "No revenue recorded yet. Revenue appears here as orders are delivered."
|
|
105
105
|
}) })]
|
|
106
106
|
}), /* @__PURE__ */ C(w, {
|
|
@@ -136,7 +136,7 @@ function E() {
|
|
|
136
136
|
children: D.openInvoices
|
|
137
137
|
})]
|
|
138
138
|
}),
|
|
139
|
-
/* @__PURE__ */ C(
|
|
139
|
+
/* @__PURE__ */ C(u, {
|
|
140
140
|
className: "w-full",
|
|
141
141
|
onClick: k,
|
|
142
142
|
children: ["Open Billing ", /* @__PURE__ */ S(e, { size: 16 })]
|
|
@@ -144,7 +144,7 @@ function E() {
|
|
|
144
144
|
]
|
|
145
145
|
})]
|
|
146
146
|
}),
|
|
147
|
-
/* @__PURE__ */ C(
|
|
147
|
+
/* @__PURE__ */ C(d, { children: [/* @__PURE__ */ S(p, { children: /* @__PURE__ */ S(m, { children: "Revenue vs cost" }) }), /* @__PURE__ */ S(f, { children: M ? /* @__PURE__ */ S(b, {
|
|
148
148
|
xKey: "label",
|
|
149
149
|
height: 260,
|
|
150
150
|
showLegend: !1,
|
|
@@ -153,7 +153,7 @@ function E() {
|
|
|
153
153
|
dataKey: "amount",
|
|
154
154
|
name: "Amount"
|
|
155
155
|
}],
|
|
156
|
-
valueFormatter: (e) =>
|
|
156
|
+
valueFormatter: (e) => s(Number(e))
|
|
157
157
|
}) : /* @__PURE__ */ S("p", {
|
|
158
158
|
className: "py-8 text-center text-sm text-text-secondary",
|
|
159
159
|
children: "Revenue and cost figures appear here as orders are delivered."
|