@burdenoff/microfe-movethewheels 2026.624.1 → 2026.626.1
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/{AIAssistantPage-BrHX2lQn.js → AIAssistantPage-AvsMbunM.js} +39 -33
- package/dist/{AnalyticsPage-DI6Wcaw5.js → AnalyticsPage-CCLfHgQZ.js} +44 -33
- package/dist/CreateOrderPage-CjlnEtk3.js +510 -0
- package/dist/CustomerDetailsPage-I6cdDHUi.js +265 -0
- package/dist/CustomersPage-CGGfD4ki.js +163 -0
- package/dist/{DashboardPage-3ZOnwg1a.js → DashboardPage-D2HRqwg9.js} +122 -111
- package/dist/DataTable-CD9ZhpLB.js +249 -0
- package/dist/DriverDetailsPage-rg_pGNuP.js +330 -0
- package/dist/DriversPage-DKiynISH.js +167 -0
- package/dist/FinancePage-Vg8WPs38.js +158 -0
- package/dist/{FleetPage-CPS7r4J3.js → FleetPage-DddXt8r8.js} +124 -85
- package/dist/ImportExportPage-BW6qO3kc.js +248 -0
- package/dist/InventoryPage-rMGuaJN-.js +222 -0
- package/dist/LiveTrackingPage-DQ1q4Id3.js +375 -0
- package/dist/MarketplacePage-DKrXAv62.js +219 -0
- package/dist/MetricCard-B7yMyvMX.js +146 -0
- package/dist/OrderDetailsPage-CFASgsYX.js +431 -0
- package/dist/OrdersListPage-BHeT8S5o.js +309 -0
- package/dist/{PageLayout-xDTiBTDS.js → PageLayout-D3N8MCTm.js} +213 -195
- package/dist/ProductDetailsPage-CFGcbaHo.js +195 -0
- package/dist/ProductsPage--xEpbQ8A.js +171 -0
- package/dist/{ReportsPage-B8OyWGzl.js → ReportsPage-Bb7_90rK.js} +57 -49
- package/dist/RouteDetailsPage-CVtDVb1N.js +282 -0
- package/dist/RoutesPage-s57PtgcQ.js +163 -0
- package/dist/SettingsPage-BYNCBOpN.js +298 -0
- package/dist/{StatusBadge-C--7NhoW.js → StatusBadge-CijYQXtb.js} +5 -2
- package/dist/{TrackingPage-BldUm_g7.js → TrackingPage-CcRc_dva.js} +88 -83
- package/dist/VehicleDetailsPage-3YDMPsPs.js +220 -0
- package/dist/VehiclesPage-UlxPWP9K.js +167 -0
- package/dist/WarehouseDetailsPage-Db7KeN-d.js +238 -0
- package/dist/WarehousesPage-CuTO-OPp.js +164 -0
- package/dist/{arrow-left-Bk5GsGNk.js → arrow-left-CBpZKkpq.js} +1 -1
- package/dist/{box-BAMv2-7M.js → box-CAaiElsb.js} +1 -1
- package/dist/{chart-column-CAfkf4o6.js → chart-column-D1Ym15-S.js} +1 -1
- package/dist/{chevron-right-Czrt_Qew.js → chevron-right-BIFGi0UA.js} +1 -1
- package/dist/{circle-alert-CEuV9Pij.js → circle-alert-DjmNo5_L.js} +1 -1
- package/dist/{circle-check-big-Cx8aO6B-.js → circle-check-big-CjuPVo3_.js} +1 -1
- package/dist/{clock-Be95bq7_.js → clock-BjkdnddD.js} +1 -1
- package/dist/{dollar-sign-kJqItPli.js → dollar-sign-IB4O0wuQ.js} +1 -1
- package/dist/{download-caab0D3V.js → download-Dpa9vqoG.js} +1 -1
- package/dist/{file-text-b1qhrJn1.js → file-text-C8Uioy11.js} +1 -1
- package/dist/{filter-BWmLTZB-.js → filter-Da5OZaHI.js} +1 -1
- package/dist/index.js +16 -16
- package/dist/{map-CS2aFgyO.js → map-_Per4sT9.js} +1 -1
- package/dist/{map-pin-96FeqL7H.js → map-pin-BSaf5IDL.js} +1 -1
- package/dist/{navigation-i6UXEjTC.js → navigation-DaTbrhw2.js} +1 -1
- package/dist/{package-KhSi3xaT.js → package-BE7U0wQE.js} +1 -1
- package/dist/{phone-B-h3tbsr.js → phone-DV4StZiA.js} +1 -1
- package/dist/{plus-D2BYAzMn.js → plus-Dl1rLeJR.js} +1 -1
- package/dist/{refresh-cw-D5Sy01s-.js → refresh-cw-CWfERAit.js} +1 -1
- package/dist/{route-CBDXuwH9.js → route-Dp9JiN_E.js} +1 -1
- package/dist/{save-CMc7h-Vi.js → save-XH8vydOn.js} +1 -1
- package/dist/{search-DVrUQbOg.js → search-OxoIiL_C.js} +1 -1
- package/dist/{settings-BwzIRYv3.js → settings-3Rw5NwFF.js} +1 -1
- package/dist/{square-pen-DmW36Bau.js → square-pen-hLIbFQFV.js} +1 -1
- package/dist/{star-Cv2MzxZL.js → star-YsVV3MNQ.js} +1 -1
- package/dist/{store-CLH957vl.js → store-RCBl7HB-.js} +1 -1
- package/dist/{trending-up-l8M0BO_w.js → trending-up-C-85AwGT.js} +1 -1
- package/dist/{triangle-alert-BI45s6bH.js → triangle-alert-BOhfGgmh.js} +1 -1
- package/dist/{truck-DX3lNQkz.js → truck-CtDjNFbi.js} +1 -1
- package/dist/{user-D8EY1uvt.js → user-Dz5TJZFs.js} +1 -1
- package/dist/{users-CfG0J8wP.js → users-g2N0eL-Z.js} +1 -1
- package/dist/{warehouse-Dt_bAr82.js → warehouse-D3WWDeTX.js} +1 -1
- package/dist/{wrench-C50eI_Iy.js → wrench-CmxY1n4I.js} +1 -1
- package/package.json +2 -2
- package/src/movethewheels/components/DataTable.tsx +41 -6
- package/src/movethewheels/components/MetricCard.tsx +51 -20
- package/src/movethewheels/components/PageLayout.tsx +60 -5
- package/src/movethewheels/components/StatusBadge.tsx +2 -1
- package/src/movethewheels/pages/AIAssistantPage.tsx +11 -3
- package/src/movethewheels/pages/AnalyticsPage.tsx +31 -25
- package/src/movethewheels/pages/CreateOrderPage.tsx +56 -17
- package/src/movethewheels/pages/CustomerDetailsPage.tsx +63 -38
- package/src/movethewheels/pages/CustomersPage.tsx +51 -12
- package/src/movethewheels/pages/DashboardPage.tsx +62 -48
- package/src/movethewheels/pages/DriverDetailsPage.tsx +57 -26
- package/src/movethewheels/pages/DriversPage.tsx +45 -12
- package/src/movethewheels/pages/FinancePage.tsx +45 -41
- package/src/movethewheels/pages/FleetPage.tsx +82 -34
- package/src/movethewheels/pages/ImportExportPage.tsx +46 -29
- package/src/movethewheels/pages/InventoryPage.tsx +37 -33
- package/src/movethewheels/pages/LiveTrackingPage.tsx +58 -20
- package/src/movethewheels/pages/MarketplacePage.tsx +37 -3
- package/src/movethewheels/pages/OrderDetailsPage.tsx +74 -46
- package/src/movethewheels/pages/OrdersListPage.tsx +81 -14
- package/src/movethewheels/pages/ProductDetailsPage.tsx +36 -11
- package/src/movethewheels/pages/ProductsPage.tsx +41 -12
- package/src/movethewheels/pages/ReportsPage.tsx +23 -19
- package/src/movethewheels/pages/RouteDetailsPage.tsx +71 -31
- package/src/movethewheels/pages/RoutesPage.tsx +48 -9
- package/src/movethewheels/pages/SettingsPage.tsx +68 -26
- package/src/movethewheels/pages/TrackingPage.tsx +52 -49
- package/src/movethewheels/pages/VehicleDetailsPage.tsx +49 -24
- package/src/movethewheels/pages/VehiclesPage.tsx +41 -15
- package/src/movethewheels/pages/WarehouseDetailsPage.tsx +55 -30
- package/src/movethewheels/pages/WarehousesPage.tsx +46 -9
- package/dist/CreateOrderPage-DfkSi6JF.js +0 -471
- package/dist/CustomerDetailsPage-DzAIu_tH.js +0 -239
- package/dist/CustomersPage-d21ixOYa.js +0 -119
- package/dist/DataTable-CZGz3SJu.js +0 -239
- package/dist/DriverDetailsPage-YuZSlPSV.js +0 -297
- package/dist/DriversPage-BOhqEBTv.js +0 -127
- package/dist/FinancePage-CnjUNXOb.js +0 -154
- package/dist/ImportExportPage-zNjs7xsV.js +0 -232
- package/dist/InventoryPage-C9g5d3SW.js +0 -223
- package/dist/LiveTrackingPage-DoBvtdBG.js +0 -332
- package/dist/MarketplacePage-BEj5hcBF.js +0 -192
- package/dist/MetricCard-DeHVeVwl.js +0 -135
- package/dist/OrderDetailsPage-D-9lDZYU.js +0 -398
- package/dist/OrdersListPage-CJzHbgY3.js +0 -257
- package/dist/ProductDetailsPage-3rKtzXpy.js +0 -168
- package/dist/ProductsPage-B0P_wjBJ.js +0 -131
- package/dist/RouteDetailsPage-DGjKTUMj.js +0 -240
- package/dist/RoutesPage-CpopY8xN.js +0 -116
- package/dist/SettingsPage-BvXSa3gi.js +0 -247
- package/dist/VehicleDetailsPage-Dqv--MVW.js +0 -194
- package/dist/VehiclesPage-CCBHRDHu.js +0 -127
- package/dist/WarehouseDetailsPage-ZObC_c7W.js +0 -215
- package/dist/WarehousesPage-CpgZEVW9.js +0 -121
package/dist/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { $ as e, A as t, B as n, C as r, D as i, E as a, F as o, G as s, H as c, I as l, J as u, K as d, L as f, M as p, N as m, O as h, P as g, Q as ee, R as te, S as ne, T as re, U as ie, V as ae, W as oe, X as se, Y as ce, Z as le, _ as ue, a as de, b as fe, c as pe, d as me, et as he, f as ge, g as _e, h as ve, i as _, it as v, j as y, k as b, l as x, m as S, n as C, nt as w, o as T, p as E, q as D, r as O, s as k, t as A, tt as j, u as M, v as N, w as P, x as F, y as ye, z as be } from "./PageLayout-
|
|
2
|
-
import { t as xe } from "./DataTable-
|
|
3
|
-
import { n as Se, t as Ce } from "./route-
|
|
4
|
-
import { t as we } from "./chart-column-
|
|
5
|
-
import { t as Te } from "./dollar-sign-
|
|
6
|
-
import { t as Ee } from "./file-text-
|
|
7
|
-
import { n as De, t as Oe } from "./settings-
|
|
8
|
-
import { t as ke } from "./map-
|
|
9
|
-
import { t as Ae } from "./package-
|
|
10
|
-
import { t as je } from "./store-
|
|
11
|
-
import { t as I } from "./truck-
|
|
12
|
-
import { t as Me } from "./users-
|
|
13
|
-
import { t as L } from "./warehouse-
|
|
1
|
+
import { $ as e, A as t, B as n, C as r, D as i, E as a, F as o, G as s, H as c, I as l, J as u, K as d, L as f, M as p, N as m, O as h, P as g, Q as ee, R as te, S as ne, T as re, U as ie, V as ae, W as oe, X as se, Y as ce, Z as le, _ as ue, a as de, b as fe, c as pe, d as me, et as he, f as ge, g as _e, h as ve, i as _, it as v, j as y, k as b, l as x, m as S, n as C, nt as w, o as T, p as E, q as D, r as O, s as k, t as A, tt as j, u as M, v as N, w as P, x as F, y as ye, z as be } from "./PageLayout-D3N8MCTm.js";
|
|
2
|
+
import { t as xe } from "./DataTable-CD9ZhpLB.js";
|
|
3
|
+
import { n as Se, t as Ce } from "./route-Dp9JiN_E.js";
|
|
4
|
+
import { t as we } from "./chart-column-D1Ym15-S.js";
|
|
5
|
+
import { t as Te } from "./dollar-sign-IB4O0wuQ.js";
|
|
6
|
+
import { t as Ee } from "./file-text-C8Uioy11.js";
|
|
7
|
+
import { n as De, t as Oe } from "./settings-3Rw5NwFF.js";
|
|
8
|
+
import { t as ke } from "./map-_Per4sT9.js";
|
|
9
|
+
import { t as Ae } from "./package-BE7U0wQE.js";
|
|
10
|
+
import { t as je } from "./store-RCBl7HB-.js";
|
|
11
|
+
import { t as I } from "./truck-CtDjNFbi.js";
|
|
12
|
+
import { t as Me } from "./users-g2N0eL-Z.js";
|
|
13
|
+
import { t as L } from "./warehouse-D3WWDeTX.js";
|
|
14
14
|
import { i as Ne, n as Pe, r as Fe } from "./graphqlClient-CdJyR_ed.js";
|
|
15
15
|
import { n as Ie, r as Le, t as Re } from "./useOrders-D_3_hGMp.js";
|
|
16
16
|
import { a as ze, i as Be, n as Ve, o as He, r as Ue, t as We } from "./useFleet-BdETplNE.js";
|
|
@@ -19,8 +19,8 @@ import { n as Ze, r as Qe, t as $e } from "./useCustomers-bS3a4ytk.js";
|
|
|
19
19
|
import { n as et, r as tt, t as nt } from "./useRoutes-v4aBaS-E.js";
|
|
20
20
|
import { a as rt, i as it, n as at, o as ot, r as st, t as ct } from "./useAnalytics-ph7eTIK6.js";
|
|
21
21
|
import { a as lt, i as ut, n as dt, o as ft, r as pt, s as mt, t as ht } from "./useTracking-De2KIUNu.js";
|
|
22
|
-
import { n as gt, r as _t, t as vt } from "./MetricCard-
|
|
23
|
-
import { a as yt, i as bt, n as xt, r as St, t as Ct } from "./StatusBadge-
|
|
22
|
+
import { n as gt, r as _t, t as vt } from "./MetricCard-B7yMyvMX.js";
|
|
23
|
+
import { a as yt, i as bt, n as xt, r as St, t as Ct } from "./StatusBadge-CijYQXtb.js";
|
|
24
24
|
import { Suspense as wt, lazy as R, useEffect as z } from "react";
|
|
25
25
|
import { Navigate as Tt, Route as B, Routes as Et } from "react-router-dom";
|
|
26
26
|
import { jsx as V, jsxs as H } from "react/jsx-runtime";
|
|
@@ -161,7 +161,7 @@ function Nt() {
|
|
|
161
161
|
})
|
|
162
162
|
});
|
|
163
163
|
}
|
|
164
|
-
var Pt = R(() => import("./DashboardPage-
|
|
164
|
+
var Pt = R(() => import("./DashboardPage-D2HRqwg9.js")), Ft = R(() => import("./OrdersListPage-BHeT8S5o.js")), It = R(() => import("./OrderDetailsPage-CFASgsYX.js")), W = R(() => import("./CreateOrderPage-CjlnEtk3.js")), Lt = R(() => import("./TrackingPage-CcRc_dva.js")), Rt = R(() => import("./LiveTrackingPage-DQ1q4Id3.js")), zt = R(() => import("./FleetPage-DddXt8r8.js")), Bt = R(() => import("./VehiclesPage-UlxPWP9K.js")), Vt = R(() => import("./VehicleDetailsPage-3YDMPsPs.js")), Ht = R(() => import("./DriversPage-DKiynISH.js")), Ut = R(() => import("./DriverDetailsPage-rg_pGNuP.js")), Wt = R(() => import("./InventoryPage-rMGuaJN-.js")), Gt = R(() => import("./ProductsPage--xEpbQ8A.js")), Kt = R(() => import("./ProductDetailsPage-CFGcbaHo.js")), qt = R(() => import("./WarehousesPage-CuTO-OPp.js")), Jt = R(() => import("./WarehouseDetailsPage-Db7KeN-d.js")), Yt = R(() => import("./CustomersPage-CGGfD4ki.js")), G = R(() => import("./CustomerDetailsPage-I6cdDHUi.js")), Xt = R(() => import("./RoutesPage-s57PtgcQ.js")), K = R(() => import("./RouteDetailsPage-CVtDVb1N.js")), Zt = R(() => import("./AnalyticsPage-CCLfHgQZ.js")), Qt = R(() => import("./FinancePage-Vg8WPs38.js")), $t = R(() => import("./MarketplacePage-DKrXAv62.js")), en = R(() => import("./ImportExportPage-BW6qO3kc.js")), tn = R(() => import("./ReportsPage-Bb7_90rK.js")), nn = R(() => import("./SettingsPage-BYNCBOpN.js")), rn = R(() => import("./AIAssistantPage-AvsMbunM.js"));
|
|
165
165
|
function an() {
|
|
166
166
|
return /* @__PURE__ */ V(wt, {
|
|
167
167
|
fallback: /* @__PURE__ */ V(Nt, {}),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { it as e } from "./PageLayout-
|
|
1
|
+
import { it as e } from "./PageLayout-D3N8MCTm.js";
|
|
2
2
|
//#region node_modules/lucide-react/dist/esm/icons/map-pin.js
|
|
3
3
|
var t = e("MapPin", [["path", {
|
|
4
4
|
d: "M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { it as e } from "./PageLayout-
|
|
1
|
+
import { it as e } from "./PageLayout-D3N8MCTm.js";
|
|
2
2
|
//#region node_modules/lucide-react/dist/esm/icons/square-pen.js
|
|
3
3
|
var t = e("SquarePen", [["path", {
|
|
4
4
|
d: "M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { it as e } from "./PageLayout-
|
|
1
|
+
import { it as e } from "./PageLayout-D3N8MCTm.js";
|
|
2
2
|
//#region node_modules/lucide-react/dist/esm/icons/star.js
|
|
3
3
|
var t = e("Star", [["path", {
|
|
4
4
|
d: "M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@burdenoff/microfe-movethewheels",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.626.1",
|
|
4
4
|
"description": "Burdenoff MoveTheWheels Microfrontend - Logistics & Supply Chain Management Platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@apollo/client": "^4.0.11",
|
|
43
|
-
"@burdenoff/fe-libs": "2026.
|
|
43
|
+
"@burdenoff/fe-libs": "2026.625.5",
|
|
44
44
|
"@tanstack/react-query": "^5.90.16",
|
|
45
45
|
"clsx": "^2.1.1",
|
|
46
46
|
"graphql": "^16.12.0",
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
SelectValue,
|
|
16
16
|
Skeleton,
|
|
17
17
|
} from './ui';
|
|
18
|
+
import { IllustratedEmptyState } from '@burdenoff/fe-libs/ui';
|
|
18
19
|
import { cn } from '../utils/cn';
|
|
19
20
|
import {
|
|
20
21
|
ChevronLeft,
|
|
@@ -50,6 +51,19 @@ interface DataTableProps<T> {
|
|
|
50
51
|
onRowClick?: (row: T) => void;
|
|
51
52
|
rowClassName?: string | ((row: T) => string);
|
|
52
53
|
emptyMessage?: string;
|
|
54
|
+
/**
|
|
55
|
+
* Boff UI 2.0 — standard illustration name served by the host at
|
|
56
|
+
* /illustrations/<name>.webp. When provided, the zero/empty state renders an
|
|
57
|
+
* on-brand IllustratedEmptyState instead of bare text. Search-result empties
|
|
58
|
+
* always use the empty-search illustration regardless of this value.
|
|
59
|
+
*/
|
|
60
|
+
emptyIllustration?: string;
|
|
61
|
+
/** Optional title for the illustrated empty state (defaults to emptyMessage). */
|
|
62
|
+
emptyTitle?: string;
|
|
63
|
+
/** Optional description for the illustrated empty state. */
|
|
64
|
+
emptyDescription?: ReactNode;
|
|
65
|
+
/** Optional primary action (e.g. a "Create" button) for the illustrated empty state. */
|
|
66
|
+
emptyAction?: ReactNode;
|
|
53
67
|
className?: string;
|
|
54
68
|
getRowId?: (row: T) => string;
|
|
55
69
|
}
|
|
@@ -72,6 +86,10 @@ export function DataTable<T extends object>({
|
|
|
72
86
|
onRowClick,
|
|
73
87
|
rowClassName,
|
|
74
88
|
emptyMessage = 'No data found',
|
|
89
|
+
emptyIllustration,
|
|
90
|
+
emptyTitle,
|
|
91
|
+
emptyDescription,
|
|
92
|
+
emptyAction,
|
|
75
93
|
className,
|
|
76
94
|
getRowId,
|
|
77
95
|
}: DataTableProps<T>) {
|
|
@@ -188,13 +206,13 @@ export function DataTable<T extends object>({
|
|
|
188
206
|
<Skeleton className="h-10 w-64" />
|
|
189
207
|
</div>
|
|
190
208
|
)}
|
|
191
|
-
<div className="rounded-
|
|
209
|
+
<div className="rounded-card border border-border-seam bg-bg-surface shadow-elevation-1">
|
|
192
210
|
<Table>
|
|
193
211
|
<TableHeader>
|
|
194
212
|
<TableRow>
|
|
195
213
|
{columns.map((column) => (
|
|
196
214
|
<TableHead key={column.id}>
|
|
197
|
-
<Skeleton className="h-4 w-20" />
|
|
215
|
+
<Skeleton className="h-4 w-20 motion-safe:animate-vc-shimmer" />
|
|
198
216
|
</TableHead>
|
|
199
217
|
))}
|
|
200
218
|
</TableRow>
|
|
@@ -204,7 +222,7 @@ export function DataTable<T extends object>({
|
|
|
204
222
|
<TableRow key={i}>
|
|
205
223
|
{columns.map((column) => (
|
|
206
224
|
<TableCell key={column.id}>
|
|
207
|
-
<Skeleton className="h-4 w-full max-w-[100px]" />
|
|
225
|
+
<Skeleton className="h-4 w-full max-w-[100px] motion-safe:animate-vc-shimmer" />
|
|
208
226
|
</TableCell>
|
|
209
227
|
))}
|
|
210
228
|
</TableRow>
|
|
@@ -237,7 +255,7 @@ export function DataTable<T extends object>({
|
|
|
237
255
|
)}
|
|
238
256
|
|
|
239
257
|
{/* Table */}
|
|
240
|
-
<div className="rounded-
|
|
258
|
+
<div className="overflow-x-auto rounded-card border border-border-seam bg-bg-surface shadow-elevation-1">
|
|
241
259
|
<Table>
|
|
242
260
|
<TableHeader>
|
|
243
261
|
<TableRow>
|
|
@@ -261,8 +279,25 @@ export function DataTable<T extends object>({
|
|
|
261
279
|
<TableBody>
|
|
262
280
|
{paginatedData.length === 0 ? (
|
|
263
281
|
<TableRow>
|
|
264
|
-
<TableCell colSpan={columns.length} className="
|
|
265
|
-
|
|
282
|
+
<TableCell colSpan={columns.length} className="py-8 text-center">
|
|
283
|
+
{emptyIllustration ? (
|
|
284
|
+
searchQuery ? (
|
|
285
|
+
<IllustratedEmptyState
|
|
286
|
+
illustration="empty-search"
|
|
287
|
+
title="No matches"
|
|
288
|
+
description={`Nothing matches “${searchQuery}”. Try a different search.`}
|
|
289
|
+
/>
|
|
290
|
+
) : (
|
|
291
|
+
<IllustratedEmptyState
|
|
292
|
+
illustration={emptyIllustration}
|
|
293
|
+
title={emptyTitle ?? emptyMessage}
|
|
294
|
+
description={emptyDescription}
|
|
295
|
+
action={emptyAction}
|
|
296
|
+
/>
|
|
297
|
+
)
|
|
298
|
+
) : (
|
|
299
|
+
<p className="text-text-secondary">{emptyMessage}</p>
|
|
300
|
+
)}
|
|
266
301
|
</TableCell>
|
|
267
302
|
</TableRow>
|
|
268
303
|
) : (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
import { GlassCard } from '@burdenoff/fe-libs/ui';
|
|
2
3
|
import { cn } from '../utils/cn';
|
|
3
|
-
import { Card, CardContent } from './ui';
|
|
4
4
|
|
|
5
5
|
interface MetricCardProps {
|
|
6
6
|
/** Main value to display */
|
|
@@ -23,6 +23,10 @@ interface MetricCardProps {
|
|
|
23
23
|
onClick?: () => void;
|
|
24
24
|
/** Additional CSS classes */
|
|
25
25
|
className?: string;
|
|
26
|
+
/** Boff UI 2.0 surface treatment. Defaults to the soft accent-wash metric surface. */
|
|
27
|
+
treatment?: 'metric' | 'glass';
|
|
28
|
+
/** Featured/active accent glow (used for the single hero metric per page). */
|
|
29
|
+
glow?: boolean;
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
const sizeClasses = {
|
|
@@ -60,12 +64,14 @@ export function MetricCard({
|
|
|
60
64
|
size = 'md',
|
|
61
65
|
onClick,
|
|
62
66
|
className,
|
|
67
|
+
treatment = 'metric',
|
|
68
|
+
glow = false,
|
|
63
69
|
}: MetricCardProps) {
|
|
64
70
|
const styles = sizeClasses[size];
|
|
65
71
|
|
|
66
72
|
const changeColors = {
|
|
67
|
-
positive: 'text-
|
|
68
|
-
negative: 'text-
|
|
73
|
+
positive: 'text-status-success-text',
|
|
74
|
+
negative: 'text-status-error-text',
|
|
69
75
|
neutral: 'text-text-secondary',
|
|
70
76
|
};
|
|
71
77
|
|
|
@@ -98,24 +104,44 @@ export function MetricCard({
|
|
|
98
104
|
};
|
|
99
105
|
|
|
100
106
|
return (
|
|
101
|
-
<
|
|
107
|
+
<GlassCard
|
|
108
|
+
treatment={treatment}
|
|
109
|
+
glow={glow}
|
|
102
110
|
className={cn(
|
|
103
|
-
'overflow-hidden
|
|
104
|
-
onClick &&
|
|
111
|
+
'overflow-hidden border-border-seam',
|
|
112
|
+
onClick &&
|
|
113
|
+
'cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-bg focus-visible:ring-offset-2 focus-visible:ring-offset-bg-base',
|
|
105
114
|
className
|
|
106
115
|
)}
|
|
107
116
|
onClick={onClick}
|
|
117
|
+
{...(onClick
|
|
118
|
+
? {
|
|
119
|
+
role: 'button',
|
|
120
|
+
tabIndex: 0,
|
|
121
|
+
onKeyDown: (e: React.KeyboardEvent<HTMLDivElement>) => {
|
|
122
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
123
|
+
e.preventDefault();
|
|
124
|
+
onClick();
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
}
|
|
128
|
+
: {})}
|
|
108
129
|
>
|
|
109
|
-
<
|
|
130
|
+
<div className={styles.card}>
|
|
110
131
|
<div className="flex items-start justify-between">
|
|
111
132
|
<div className="space-y-1">
|
|
112
133
|
<p className={cn('text-text-secondary', styles.label)}>{label}</p>
|
|
113
|
-
<p className={cn('text-text-primary tracking-tight', styles.value)}>
|
|
134
|
+
<p className={cn('text-text-primary tracking-tight tabular-nums', styles.value)}>
|
|
114
135
|
{typeof value === 'number' ? value.toLocaleString() : value}
|
|
115
136
|
</p>
|
|
116
137
|
{subtitle && <p className="text-xs text-text-secondary">{subtitle}</p>}
|
|
117
138
|
{change && (
|
|
118
|
-
<div
|
|
139
|
+
<div
|
|
140
|
+
className={cn(
|
|
141
|
+
'flex items-center gap-1 text-sm tabular-nums',
|
|
142
|
+
changeColors[changeType]
|
|
143
|
+
)}
|
|
144
|
+
>
|
|
119
145
|
{trend && trendIcons[trend]}
|
|
120
146
|
<span>{change}</span>
|
|
121
147
|
</div>
|
|
@@ -123,14 +149,17 @@ export function MetricCard({
|
|
|
123
149
|
</div>
|
|
124
150
|
{icon && (
|
|
125
151
|
<div
|
|
126
|
-
className={cn(
|
|
152
|
+
className={cn(
|
|
153
|
+
'flex-shrink-0 p-2 rounded-lg bg-action-primary-bg/10 text-action-primary-bg',
|
|
154
|
+
styles.icon
|
|
155
|
+
)}
|
|
127
156
|
>
|
|
128
157
|
{icon}
|
|
129
158
|
</div>
|
|
130
159
|
)}
|
|
131
160
|
</div>
|
|
132
|
-
</
|
|
133
|
-
</
|
|
161
|
+
</div>
|
|
162
|
+
</GlassCard>
|
|
134
163
|
);
|
|
135
164
|
}
|
|
136
165
|
|
|
@@ -141,18 +170,20 @@ export function MetricCardSkeleton({ size = 'md' }: { size?: 'sm' | 'md' | 'lg'
|
|
|
141
170
|
const styles = sizeClasses[size];
|
|
142
171
|
|
|
143
172
|
return (
|
|
144
|
-
<
|
|
145
|
-
<
|
|
173
|
+
<GlassCard treatment="metric" className="overflow-hidden border-border-seam">
|
|
174
|
+
<div className={styles.card}>
|
|
146
175
|
<div className="flex items-start justify-between">
|
|
147
176
|
<div className="space-y-2 flex-1">
|
|
148
|
-
<div className="h-4 w-24 bg-bg-sunken animate-
|
|
149
|
-
<div className="h-8 w-32 bg-bg-sunken animate-
|
|
150
|
-
<div className="h-3 w-20 bg-bg-sunken animate-
|
|
177
|
+
<div className="h-4 w-24 bg-bg-sunken motion-safe:animate-vc-shimmer rounded" />
|
|
178
|
+
<div className="h-8 w-32 bg-bg-sunken motion-safe:animate-vc-shimmer rounded" />
|
|
179
|
+
<div className="h-3 w-20 bg-bg-sunken motion-safe:animate-vc-shimmer rounded" />
|
|
151
180
|
</div>
|
|
152
|
-
<div
|
|
181
|
+
<div
|
|
182
|
+
className={cn('bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg', styles.icon)}
|
|
183
|
+
/>
|
|
153
184
|
</div>
|
|
154
|
-
</
|
|
155
|
-
</
|
|
185
|
+
</div>
|
|
186
|
+
</GlassCard>
|
|
156
187
|
);
|
|
157
188
|
}
|
|
158
189
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
import { AuroraBackground, GradientText, IllustratedEmptyState } from '@burdenoff/fe-libs/ui';
|
|
2
3
|
import { cn } from '../utils/cn';
|
|
3
4
|
|
|
4
5
|
interface PageLayoutProps {
|
|
@@ -21,6 +22,16 @@ interface PageLayoutProps {
|
|
|
21
22
|
className?: string;
|
|
22
23
|
/** Additional CSS classes for the content area */
|
|
23
24
|
contentClassName?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Boff UI 2.0 — render a subtle living aurora backdrop behind the page header.
|
|
27
|
+
* Reserved for the MFE's single primary page (the Dashboard). One per MFE.
|
|
28
|
+
*/
|
|
29
|
+
hero?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Boff UI 2.0 — the slice of the title to emphasise with a brand gradient.
|
|
32
|
+
* When provided, the title renders as `…<GradientText>{titleAccent}</GradientText>`.
|
|
33
|
+
*/
|
|
34
|
+
titleAccent?: string;
|
|
24
35
|
}
|
|
25
36
|
|
|
26
37
|
const maxWidthClasses = {
|
|
@@ -53,7 +64,24 @@ export function PageLayout({
|
|
|
53
64
|
showHeader = true,
|
|
54
65
|
className,
|
|
55
66
|
contentClassName,
|
|
67
|
+
hero = false,
|
|
68
|
+
titleAccent,
|
|
56
69
|
}: PageLayoutProps) {
|
|
70
|
+
// Render the title, optionally clipping a gradient into the accent slice.
|
|
71
|
+
const renderTitle = (value: string) => {
|
|
72
|
+
if (!titleAccent || !value.includes(titleAccent)) {
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
const [before, after] = value.split(titleAccent);
|
|
76
|
+
return (
|
|
77
|
+
<>
|
|
78
|
+
{before}
|
|
79
|
+
<GradientText>{titleAccent}</GradientText>
|
|
80
|
+
{after}
|
|
81
|
+
</>
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
|
|
57
85
|
return (
|
|
58
86
|
<div
|
|
59
87
|
className={cn(
|
|
@@ -72,20 +100,27 @@ export function PageLayout({
|
|
|
72
100
|
<div className={cn('mx-auto w-full', maxWidthClasses[maxWidth], contentClassName)}>
|
|
73
101
|
{/* Page Header */}
|
|
74
102
|
{showHeader && (title || headerActions) && (
|
|
75
|
-
<header
|
|
103
|
+
<header
|
|
104
|
+
className={cn(
|
|
105
|
+
'mb-6 sm:mb-8',
|
|
106
|
+
hero &&
|
|
107
|
+
'relative overflow-hidden rounded-card border border-border-seam bg-hero-mesh px-5 py-6 sm:px-7 sm:py-8'
|
|
108
|
+
)}
|
|
109
|
+
>
|
|
110
|
+
{hero && <AuroraBackground intensity="subtle" />}
|
|
76
111
|
<div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
|
77
112
|
{/* Title Section */}
|
|
78
113
|
<div className="space-y-1">
|
|
79
114
|
{(title || icon) && (
|
|
80
115
|
<div className="flex items-center gap-3">
|
|
81
116
|
{icon && (
|
|
82
|
-
<div className="flex-shrink-0 p-2.5 rounded-xl bg-action-primary-bg/10 text-primary">
|
|
117
|
+
<div className="flex-shrink-0 p-2.5 rounded-xl bg-action-primary-bg/10 text-action-primary-bg">
|
|
83
118
|
{icon}
|
|
84
119
|
</div>
|
|
85
120
|
)}
|
|
86
121
|
{title && (
|
|
87
122
|
<h1 className="text-2xl sm:text-3xl font-bold tracking-tight text-text-primary">
|
|
88
|
-
{title}
|
|
123
|
+
{renderTitle(title)}
|
|
89
124
|
</h1>
|
|
90
125
|
)}
|
|
91
126
|
</div>
|
|
@@ -148,7 +183,13 @@ export function PageSection({
|
|
|
148
183
|
}
|
|
149
184
|
|
|
150
185
|
/**
|
|
151
|
-
* EmptyState - A consistent empty state component
|
|
186
|
+
* EmptyState - A consistent empty/zero state component.
|
|
187
|
+
*
|
|
188
|
+
* Boff UI 2.0: when an `illustration` name is provided (one of the standard
|
|
189
|
+
* host-served names — empty-data, empty-search, empty-files, empty-people,
|
|
190
|
+
* empty-notifications, onboarding, empty-generic), it renders the on-brand
|
|
191
|
+
* IllustratedEmptyState. Otherwise it falls back to the legacy icon layout so
|
|
192
|
+
* existing callers keep working unchanged.
|
|
152
193
|
*/
|
|
153
194
|
export function EmptyState({
|
|
154
195
|
icon,
|
|
@@ -156,13 +197,27 @@ export function EmptyState({
|
|
|
156
197
|
description,
|
|
157
198
|
action,
|
|
158
199
|
className,
|
|
200
|
+
illustration = 'empty-data',
|
|
159
201
|
}: {
|
|
160
202
|
icon?: ReactNode;
|
|
161
203
|
title: string;
|
|
162
204
|
description?: string;
|
|
163
205
|
action?: ReactNode;
|
|
164
206
|
className?: string;
|
|
207
|
+
/** Standard illustration name served by the host at /illustrations/<name>.webp. */
|
|
208
|
+
illustration?: string;
|
|
165
209
|
}) {
|
|
210
|
+
if (!icon) {
|
|
211
|
+
return (
|
|
212
|
+
<IllustratedEmptyState
|
|
213
|
+
illustration={illustration}
|
|
214
|
+
title={title}
|
|
215
|
+
description={description}
|
|
216
|
+
action={action}
|
|
217
|
+
className={cn('animate-in fade-in-0 zoom-in-95 duration-300', className)}
|
|
218
|
+
/>
|
|
219
|
+
);
|
|
220
|
+
}
|
|
166
221
|
return (
|
|
167
222
|
<div
|
|
168
223
|
className={cn(
|
|
@@ -173,7 +228,7 @@ export function EmptyState({
|
|
|
173
228
|
className
|
|
174
229
|
)}
|
|
175
230
|
>
|
|
176
|
-
|
|
231
|
+
<div className="mb-4 p-4 rounded-2xl bg-bg-sunken/50 text-text-secondary">{icon}</div>
|
|
177
232
|
<h3 className="text-lg font-semibold text-text-primary mb-1">{title}</h3>
|
|
178
233
|
{description && <p className="text-sm text-text-secondary max-w-sm mb-4">{description}</p>}
|
|
179
234
|
{action}
|
|
@@ -78,8 +78,9 @@ export function StatusBadge({
|
|
|
78
78
|
>
|
|
79
79
|
{showDot && (
|
|
80
80
|
<span
|
|
81
|
+
aria-hidden="true"
|
|
81
82
|
className={cn(
|
|
82
|
-
'w-1.5 h-1.5 rounded-full mr-1.5 flex-shrink-0',
|
|
83
|
+
'w-1.5 h-1.5 rounded-full mr-1.5 flex-shrink-0 motion-safe:animate-vc-glow-pulse',
|
|
83
84
|
colors.text.replace('text-', 'bg-')
|
|
84
85
|
)}
|
|
85
86
|
/>
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
Badge,
|
|
16
16
|
ScrollArea,
|
|
17
17
|
} from '../components/ui';
|
|
18
|
+
import { GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';
|
|
18
19
|
|
|
19
20
|
export default function AIAssistantPage() {
|
|
20
21
|
const [message, setMessage] = useState('');
|
|
@@ -60,10 +61,17 @@ export default function AIAssistantPage() {
|
|
|
60
61
|
subtitle="Intelligent logistics support"
|
|
61
62
|
icon={<Bot size={24} />}
|
|
62
63
|
>
|
|
64
|
+
<PagePurpose icon={<Bot size={18} />}>
|
|
65
|
+
Ask plain-English questions about your operation and get answers backed by your own data.
|
|
66
|
+
Use it to optimize routes, forecast demand, spot likely delays, and run what-if scenarios
|
|
67
|
+
(e.g. “what if I add two vehicles?”) — like having a logistics analyst on call.
|
|
68
|
+
</PagePurpose>
|
|
69
|
+
|
|
63
70
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
64
71
|
<div className="lg:col-span-2 space-y-4">
|
|
65
|
-
|
|
66
|
-
|
|
72
|
+
{/* Chat — the page's single emphasis zone */}
|
|
73
|
+
<GlassCard treatment="glass" glow className="h-[600px] flex flex-col">
|
|
74
|
+
<CardHeader className="border-b border-border-seam">
|
|
67
75
|
<CardTitle className="flex items-center gap-2">
|
|
68
76
|
<Sparkles size={18} className="text-primary" /> Chat with AI
|
|
69
77
|
</CardTitle>
|
|
@@ -97,7 +105,7 @@ export default function AIAssistantPage() {
|
|
|
97
105
|
</Button>
|
|
98
106
|
</div>
|
|
99
107
|
</div>
|
|
100
|
-
</
|
|
108
|
+
</GlassCard>
|
|
101
109
|
</div>
|
|
102
110
|
|
|
103
111
|
<div className="space-y-6">
|