@burdenoff/microfe-movethewheels 2026.1031.1 → 2026.1031.3

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.
Files changed (51) hide show
  1. package/dist/MoveTheWheelsRoot.js +144 -136
  2. package/dist/MoveTheWheelsRoutes.js +61 -57
  3. package/dist/components/ShipmentRiskDialog.js +228 -0
  4. package/dist/components/TrackingAlertList.js +149 -0
  5. package/dist/generated/tracking-quality-operations.d.ts +1154 -2
  6. package/dist/generated/wspace-types.d.ts +2895 -50
  7. package/dist/hooks/useEntityImport.js +68 -0
  8. package/dist/hooks/useShipmentRisk.js +72 -0
  9. package/dist/hooks/useTracking.js +96 -82
  10. package/dist/movethewheels/components/ShipmentRiskDialog.d.ts +20 -0
  11. package/dist/movethewheels/components/TrackingAlertList.d.ts +14 -0
  12. package/dist/movethewheels/hooks/useEntityImport.d.ts +19 -0
  13. package/dist/movethewheels/hooks/useShipmentRisk.d.ts +41 -0
  14. package/dist/movethewheels/pages/ImportExportPage.d.ts +9 -0
  15. package/dist/movethewheels/types/index.d.ts +15 -1
  16. package/dist/movethewheels/utils/entityImport.d.ts +109 -0
  17. package/dist/movethewheels/utils/trackingAlerts.d.ts +36 -0
  18. package/dist/node_modules/lucide-react/dist/esm/icons/arrow-down-up.js +22 -0
  19. package/dist/node_modules/lucide-react/dist/esm/icons/file-spreadsheet.js +30 -0
  20. package/dist/node_modules/lucide-react/dist/esm/icons/file-up.js +22 -0
  21. package/dist/pages/CustomersPage.js +88 -79
  22. package/dist/pages/DashboardPage.js +147 -151
  23. package/dist/pages/DriversPage.js +115 -106
  24. package/dist/pages/ImportExportPage.js +435 -0
  25. package/dist/pages/LiveTrackingPage.js +169 -169
  26. package/dist/pages/ProductsPage.js +85 -76
  27. package/dist/pages/VehiclesPage.js +99 -90
  28. package/dist/pages/WarehousesPage.js +97 -88
  29. package/dist/utils/entityImport.js +73 -0
  30. package/dist/utils/trackingAlerts.js +86 -0
  31. package/package.json +4 -2
  32. package/src/generated/tracking-quality-operations.ts +1519 -1
  33. package/src/generated/wspace-types.ts +3248 -51
  34. package/src/movethewheels/MoveTheWheelsRoot.tsx +8 -0
  35. package/src/movethewheels/MoveTheWheelsRoutes.tsx +4 -0
  36. package/src/movethewheels/components/ShipmentRiskDialog.tsx +315 -0
  37. package/src/movethewheels/components/TrackingAlertList.tsx +188 -0
  38. package/src/movethewheels/hooks/useEntityImport.ts +108 -0
  39. package/src/movethewheels/hooks/useShipmentRisk.ts +195 -0
  40. package/src/movethewheels/hooks/useTracking.ts +66 -22
  41. package/src/movethewheels/pages/CustomersPage.tsx +6 -1
  42. package/src/movethewheels/pages/DashboardPage.tsx +10 -20
  43. package/src/movethewheels/pages/DriversPage.tsx +6 -0
  44. package/src/movethewheels/pages/ImportExportPage.tsx +483 -0
  45. package/src/movethewheels/pages/LiveTrackingPage.tsx +20 -22
  46. package/src/movethewheels/pages/ProductsPage.tsx +14 -1
  47. package/src/movethewheels/pages/VehiclesPage.tsx +6 -0
  48. package/src/movethewheels/pages/WarehousesPage.tsx +6 -1
  49. package/src/movethewheels/types/index.ts +16 -1
  50. package/src/movethewheels/utils/entityImport.ts +239 -0
  51. package/src/movethewheels/utils/trackingAlerts.ts +151 -0
@@ -0,0 +1,68 @@
1
+ import { useMoveTheWheels as e } from "../providers/MoveTheWheelsProvider.js";
2
+ import { executeGraphQL as t } from "../utils/graphqlClient.js";
3
+ import { MTW_IMPORT_SPEC_QUERY as n, importEntity as r, importMutation as i } from "../utils/entityImport.js";
4
+ import { useCallback as a, useEffect as o, useMemo as s, useState as c } from "react";
5
+ //#region src/movethewheels/hooks/useEntityImport.ts
6
+ function l() {
7
+ let { apiGatewayUrl: t, authToken: n, workspaceToken: r, workspaceId: i, tenantId: a, currentUser: o } = e();
8
+ return s(() => ({
9
+ apiGatewayUrl: t,
10
+ authToken: n,
11
+ workspaceToken: r,
12
+ workspaceId: i,
13
+ tenantId: a,
14
+ actorId: o?.id
15
+ }), [
16
+ t,
17
+ n,
18
+ r,
19
+ i,
20
+ a,
21
+ o?.id
22
+ ]);
23
+ }
24
+ function u() {
25
+ let e = l(), [r, i] = c([]), [a, s] = c(!0), [u, d] = c(null);
26
+ return o(() => {
27
+ if (!e.workspaceId) return;
28
+ let r = !1;
29
+ return s(!0), t(e, n).then((e) => {
30
+ r || (i(e.mtwImportSpec), d(null));
31
+ }).catch((e) => {
32
+ r || d(e instanceof Error ? e : /* @__PURE__ */ Error("Could not load import columns"));
33
+ }).finally(() => {
34
+ r || s(!1);
35
+ }), () => {
36
+ r = !0;
37
+ };
38
+ }, [e]), {
39
+ specs: r,
40
+ isLoading: a,
41
+ error: u
42
+ };
43
+ }
44
+ function d() {
45
+ let e = l(), [n, o] = c(!1);
46
+ return {
47
+ run: a(async (n) => {
48
+ if (new Blob([n.content]).size > 2097152) throw Error("The file is larger than 2 MB. Split it into smaller files.");
49
+ let { field: a } = r(n.entityType);
50
+ o(!0);
51
+ try {
52
+ let r = (await t(e, i(n.entityType), { input: {
53
+ format: n.format,
54
+ content: n.content,
55
+ dryRun: n.dryRun,
56
+ allowPartial: n.allowPartial
57
+ } }, n.dryRun ? "RETRY_TRANSIENT" : "SINGLE_ATTEMPT"))[a];
58
+ if (!r) throw Error("The import returned no result");
59
+ return r;
60
+ } finally {
61
+ o(!1);
62
+ }
63
+ }, [e]),
64
+ isRunning: n
65
+ };
66
+ }
67
+ //#endregion
68
+ export { d as useEntityImport, u as useImportSpec };
@@ -0,0 +1,72 @@
1
+ import { useMoveTheWheels as e } from "../providers/MoveTheWheelsProvider.js";
2
+ import { executeGraphQL as t } from "../utils/graphqlClient.js";
3
+ import { useCallback as n, useEffect as r, useMemo as i, useState as a } from "react";
4
+ //#region src/movethewheels/hooks/useShipmentRisk.ts
5
+ var o = "\n query ShipmentRiskForecast($shipmentId: ID!) {\n mtwShipmentRiskForecast(shipmentId: $shipmentId) {\n shipmentId\n shipmentNumber\n status\n method\n promisedDelivery\n predictedDeliveryEarliest\n predictedDeliveryLatest\n predictedSlipMinutes\n riskScore\n riskLevel\n atRisk\n breached\n signals {\n code\n weight\n minutes\n ratio\n }\n recommendedAction\n recommendedMutation\n evaluatedAt\n }\n shipment(id: $shipmentId) {\n id\n deliveryJobId\n estimatedDelivery\n }\n }\n", s = "\n mutation RepromiseShipment($id: ID!, $input: UpdateShipmentInput!) {\n updateShipment(id: $id, input: $input) {\n id\n estimatedDelivery\n }\n }\n", c = "\n mutation RecordTrackingUpdate($input: AddTrackingEventInput!) {\n addTrackingEvent(input: $input) {\n id\n timestamp\n }\n }\n";
6
+ function l() {
7
+ let { apiGatewayUrl: t, authToken: n, workspaceToken: r, workspaceId: a, tenantId: o, currentUser: s } = e();
8
+ return i(() => ({
9
+ apiGatewayUrl: t,
10
+ authToken: n,
11
+ workspaceToken: r,
12
+ workspaceId: a,
13
+ tenantId: o,
14
+ actorId: s?.id
15
+ }), [
16
+ t,
17
+ n,
18
+ r,
19
+ a,
20
+ o,
21
+ s?.id
22
+ ]);
23
+ }
24
+ function u(e) {
25
+ let i = l(), [u, d] = a(null), [f, p] = a(null), [m, h] = a(!1), [g, _] = a(null), v = n(async () => {
26
+ if (!e) {
27
+ d(null), p(null);
28
+ return;
29
+ }
30
+ h(!0), _(null);
31
+ try {
32
+ let n = await t(i, o, { shipmentId: e });
33
+ d(n.mtwShipmentRiskForecast), p(n.shipment);
34
+ } catch (e) {
35
+ _(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load the risk forecast"));
36
+ } finally {
37
+ h(!1);
38
+ }
39
+ }, [i, e]);
40
+ return r(() => {
41
+ v();
42
+ }, [v]), {
43
+ forecast: u,
44
+ shipment: f,
45
+ isLoading: m,
46
+ error: g,
47
+ refetch: () => void v(),
48
+ repromise: n(async (n) => {
49
+ e && (await t(i, s, {
50
+ id: e,
51
+ input: { estimatedDelivery: n }
52
+ }, "SINGLE_ATTEMPT"), await v());
53
+ }, [
54
+ i,
55
+ v,
56
+ e
57
+ ]),
58
+ recordTrackingUpdate: n(async (n) => {
59
+ e && (await t(i, c, { input: {
60
+ shipmentId: e,
61
+ eventType: "IN_TRANSIT",
62
+ details: n
63
+ } }, "SINGLE_ATTEMPT"), await v());
64
+ }, [
65
+ i,
66
+ v,
67
+ e
68
+ ])
69
+ };
70
+ }
71
+ //#endregion
72
+ export { u as useShipmentRisk };
@@ -2,10 +2,11 @@ import { useMoveTheWheels as e } from "../providers/MoveTheWheelsProvider.js";
2
2
  import { executeGraphQL as t } from "../utils/graphqlClient.js";
3
3
  import { mapOrder as n, useOrder as r } from "./useOrders.js";
4
4
  import { mapDriver as i, mapVehicle as a, useDriver as o, useDrivers as s, useVehicle as c, useVehicles as l } from "./useFleet.js";
5
- import { useCallback as u, useEffect as d, useMemo as f, useState as p } from "react";
5
+ import { mapTrackingAlert as u, sortTrackingAlerts as d } from "../utils/trackingAlerts.js";
6
+ import { useCallback as f, useEffect as p, useMemo as m, useState as h } from "react";
6
7
  //#region src/movethewheels/hooks/useTracking.ts
7
- var m = "\n query ListShipments($filter: ShipmentFilterInput, $pagination: PaginationInput) {\n shipments(filter: $filter, pagination: $pagination) {\n id\n shipmentNumber\n deliveryJobId\n status\n trackingNumber\n estimatedDelivery\n }\n }\n", h = "\n query LookupDeliveryJob($id: ID!) {\n deliveryJob(id: $id) {\n id\n }\n }\n", g = "\n query LookupDeliveryJobs($filter: DeliveryJobFilterInput, $pagination: PaginationInput) {\n deliveryJobs(filter: $filter, pagination: $pagination) {\n id\n deliveryJobNumber\n trackingNumber\n }\n }\n", _ = "\n query GetDeliveryJobTracking($deliveryJobId: ID!, $pagination: PaginationInput) {\n shipments(filter: { deliveryJobId: $deliveryJobId }, pagination: { limit: 2, offset: 0 }) {\n id\n status\n }\n deliveryJobTracking(deliveryJobId: $deliveryJobId, pagination: $pagination) {\n id\n shipmentId\n eventType\n location\n details\n timestamp\n }\n }\n", v = "\n query GetActiveDeliveries($pagination: PaginationInput) {\n activeDeliveries(pagination: $pagination) {\n id\n shipmentNumber\n deliveryJobId\n status\n estimatedDelivery\n trackingEvents(pagination: { limit: 1, offset: 0 }) {\n id\n shipmentId\n eventType\n location\n details\n timestamp\n }\n deliveryJob {\n id\n deliveryJobNumber\n customerId\n status\n priority\n pickupAddress\n deliveryAddress\n cargoItems\n pricing\n trackingNumber\n specialInstructions\n scheduledDelivery\n vehicleId\n driverId\n createdAt\n updatedAt\n customer {\n name\n email\n phone\n company\n }\n vehicle {\n id\n vehicleNumber\n type\n make\n model\n licensePlate\n ownershipType\n year\n capacity\n status\n currentLocation\n fuelLevel\n mileage\n lastServiceDate\n nextServiceDueDate\n nextServiceDueMileage\n createdAt\n }\n driver {\n id\n userId\n firstName\n lastName\n email\n phone\n employeeId\n licenseNumber\n licenseClass\n licenseExpiry\n status\n currentLocation\n rating\n vehicleId\n createdAt\n }\n }\n }\n }\n", y = "\n query GetTrackingAlerts {\n trackingAlerts {\n shipmentId\n shipmentNumber\n alertType\n message\n }\n }\n";
8
- function b(e) {
8
+ var g = "\n query ListShipments($filter: ShipmentFilterInput, $pagination: PaginationInput) {\n shipments(filter: $filter, pagination: $pagination) {\n id\n shipmentNumber\n deliveryJobId\n status\n trackingNumber\n estimatedDelivery\n }\n }\n", _ = "\n query LookupDeliveryJob($id: ID!) {\n deliveryJob(id: $id) {\n id\n }\n }\n", v = "\n query LookupDeliveryJobs($filter: DeliveryJobFilterInput, $pagination: PaginationInput) {\n deliveryJobs(filter: $filter, pagination: $pagination) {\n id\n deliveryJobNumber\n trackingNumber\n }\n }\n", y = "\n query GetDeliveryJobTracking($deliveryJobId: ID!, $pagination: PaginationInput) {\n shipments(filter: { deliveryJobId: $deliveryJobId }, pagination: { limit: 2, offset: 0 }) {\n id\n status\n }\n deliveryJobTracking(deliveryJobId: $deliveryJobId, pagination: $pagination) {\n id\n shipmentId\n eventType\n location\n details\n timestamp\n }\n }\n", b = "\n query GetActiveDeliveries($pagination: PaginationInput) {\n activeDeliveries(pagination: $pagination) {\n id\n shipmentNumber\n deliveryJobId\n status\n estimatedDelivery\n trackingEvents(pagination: { limit: 1, offset: 0 }) {\n id\n shipmentId\n eventType\n location\n details\n timestamp\n }\n deliveryJob {\n id\n deliveryJobNumber\n customerId\n status\n priority\n pickupAddress\n deliveryAddress\n cargoItems\n pricing\n trackingNumber\n specialInstructions\n scheduledDelivery\n vehicleId\n driverId\n createdAt\n updatedAt\n customer {\n name\n email\n phone\n company\n }\n vehicle {\n id\n vehicleNumber\n type\n make\n model\n licensePlate\n ownershipType\n year\n capacity\n status\n currentLocation\n fuelLevel\n mileage\n lastServiceDate\n nextServiceDueDate\n nextServiceDueMileage\n createdAt\n }\n driver {\n id\n userId\n firstName\n lastName\n email\n phone\n employeeId\n licenseNumber\n licenseClass\n licenseExpiry\n status\n currentLocation\n rating\n vehicleId\n createdAt\n }\n }\n }\n }\n", x = "\n query GetTrackingAlerts {\n trackingAlerts {\n id\n shipmentId\n shipmentNumber\n alertType\n message\n riskScore\n promisedDelivery\n predictedDelivery\n signals\n acknowledged\n acknowledgedAt\n }\n }\n", S = "\n mutation AcknowledgeMtwTrackingAlert($shipmentId: ID!, $alertType: MtwTrackingAlertType!) {\n acknowledgeMtwTrackingAlert(shipmentId: $shipmentId, alertType: $alertType) {\n id\n acknowledged\n acknowledgedAt\n }\n }\n";
9
+ function C(e) {
9
10
  let t = e.location;
10
11
  if (!t) return null;
11
12
  let n = t.latitude ?? t.lat, r = t.longitude ?? t.lng;
@@ -16,10 +17,10 @@ function b(e) {
16
17
  timestamp: new Date(e.timestamp)
17
18
  };
18
19
  }
19
- function x(e, t, n) {
20
+ function w(e, t, n) {
20
21
  let r = e[0];
21
22
  if (!r) return null;
22
- let i = e.map(b).filter((e) => e !== null), a = i[0];
23
+ let i = e.map(C).filter((e) => e !== null), a = i[0];
23
24
  return {
24
25
  id: r.id,
25
26
  entityId: t,
@@ -33,9 +34,9 @@ function x(e, t, n) {
33
34
  lastUpdated: new Date(r.timestamp)
34
35
  };
35
36
  }
36
- function S() {
37
+ function T() {
37
38
  let { apiGatewayUrl: t, authToken: n, workspaceToken: r, workspaceId: i, tenantId: a, currentUser: o } = e();
38
- return f(() => ({
39
+ return m(() => ({
39
40
  apiGatewayUrl: t,
40
41
  authToken: n,
41
42
  workspaceToken: r,
@@ -51,23 +52,23 @@ function S() {
51
52
  o?.id
52
53
  ]);
53
54
  }
54
- var C = 3e4;
55
- function w(e, t) {
56
- d(() => {
55
+ var E = 3e4;
56
+ function D(e, t) {
57
+ p(() => {
57
58
  if (!t || typeof document > "u") return;
58
59
  let n = () => {
59
60
  document.visibilityState === "visible" && e();
60
- }, r = window.setInterval(n, C);
61
+ }, r = window.setInterval(n, E);
61
62
  return document.addEventListener("visibilitychange", n), () => {
62
63
  window.clearInterval(r), document.removeEventListener("visibilitychange", n);
63
64
  };
64
65
  }, [t, e]);
65
66
  }
66
- function T(e = {}) {
67
- let { entityId: n, entityType: r, realtime: i = !1 } = e, a = S(), [o, s] = p([]), [c, l] = p(!1), [f, h] = p(null), g = u(async () => {
68
- l(!0), h(null);
67
+ function O(e = {}) {
68
+ let { entityId: n, entityType: r, realtime: i = !1 } = e, a = T(), [o, s] = h([]), [c, l] = h(!1), [u, d] = h(null), m = f(async () => {
69
+ l(!0), d(null);
69
70
  try {
70
- s((await t(a, m, {
71
+ s((await t(a, g, {
71
72
  filter: n ? {
72
73
  ...r === "order" ? { deliveryJobId: n } : {},
73
74
  ...r === "vehicle" ? { vehicleId: n } : {},
@@ -90,7 +91,7 @@ function T(e = {}) {
90
91
  lastUpdated: void 0
91
92
  })));
92
93
  } catch (e) {
93
- h(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load tracking data"));
94
+ d(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load tracking data"));
94
95
  } finally {
95
96
  l(!1);
96
97
  }
@@ -99,19 +100,19 @@ function T(e = {}) {
99
100
  r,
100
101
  a
101
102
  ]);
102
- return d(() => {
103
- g();
104
- }, [g]), w(g, i), {
103
+ return p(() => {
104
+ m();
105
+ }, [m]), D(m, i), {
105
106
  tracking: o,
106
107
  isLoading: c,
107
- error: f,
108
- refetch: () => void g()
108
+ error: u,
109
+ refetch: () => void m()
109
110
  };
110
111
  }
111
- async function E(e, n) {
112
- let r = n.trim(), i = await t(e, h, { id: r });
112
+ async function k(e, n) {
113
+ let r = n.trim(), i = await t(e, _, { id: r });
113
114
  if (i.deliveryJob?.id) return i.deliveryJob.id;
114
- let a = await t(e, g, {
115
+ let a = await t(e, v, {
115
116
  filter: { search: r },
116
117
  pagination: {
117
118
  limit: 50,
@@ -124,7 +125,7 @@ async function E(e, n) {
124
125
  ].filter((e) => !!e).some((e) => e.toLocaleLowerCase() === o));
125
126
  if (s.length > 1) throw Error("Multiple deliveries match that reference. Enter the full tracking number.");
126
127
  if (s[0]) return s[0].id;
127
- let c = (await t(e, m, {
128
+ let c = (await t(e, g, {
128
129
  filter: { search: r },
129
130
  pagination: {
130
131
  limit: 50,
@@ -134,11 +135,11 @@ async function E(e, n) {
134
135
  if (l.length > 1) throw Error("Multiple shipments match that reference. Enter the full tracking number.");
135
136
  return l[0] ?? null;
136
137
  }
137
- function D(e) {
138
- let n = S(), [i, a] = p(), [o, s] = p(!1), [c, l] = p(null), [f, m] = p(0), { order: h, isLoading: g, error: v, refetch: y } = r(i), [b, C] = p(null), [T, D] = p(!1), [O, k] = p(null);
139
- d(() => {
138
+ function A(e) {
139
+ let n = T(), [i, a] = h(), [o, s] = h(!1), [c, l] = h(null), [u, d] = h(0), { order: m, isLoading: g, error: _, refetch: v } = r(i), [b, x] = h(null), [S, C] = h(!1), [E, O] = h(null);
140
+ p(() => {
140
141
  let t = !1, r = e?.trim() ?? "";
141
- return a(void 0), C(null), l(null), r ? (s(!0), E(n, r).then((e) => {
142
+ return a(void 0), x(null), l(null), r ? (s(!0), k(n, r).then((e) => {
142
143
  t || a(e ?? void 0);
143
144
  }).catch((e) => {
144
145
  t || l(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to find the delivery"));
@@ -151,46 +152,46 @@ function D(e) {
151
152
  });
152
153
  }, [
153
154
  n,
154
- f,
155
+ u,
155
156
  e
156
157
  ]);
157
- let A = u(async () => {
158
+ let A = f(async () => {
158
159
  if (!i) {
159
- C(null), D(!1);
160
+ x(null), C(!1);
160
161
  return;
161
162
  }
162
- D(!0), k(null);
163
+ C(!0), O(null);
163
164
  try {
164
- let e = await t(n, _, {
165
+ let e = await t(n, y, {
165
166
  deliveryJobId: i,
166
167
  pagination: {
167
168
  limit: 50,
168
169
  offset: 0
169
170
  }
170
171
  });
171
- C(x([...e.deliveryJobTracking].sort((e, t) => Date.parse(t.timestamp) - Date.parse(e.timestamp)), i, e.shipments.length === 1 ? e.shipments[0]?.status : void 0));
172
+ x(w([...e.deliveryJobTracking].sort((e, t) => Date.parse(t.timestamp) - Date.parse(e.timestamp)), i, e.shipments.length === 1 ? e.shipments[0]?.status : void 0));
172
173
  } catch (e) {
173
- k(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load order tracking"));
174
+ O(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load order tracking"));
174
175
  } finally {
175
- D(!1);
176
+ C(!1);
176
177
  }
177
178
  }, [n, i]);
178
- return d(() => {
179
+ return p(() => {
179
180
  A();
180
- }, [A]), w(A, !!i), {
181
+ }, [A]), D(A, !!i), {
181
182
  tracking: b,
182
- order: i ? h : null,
183
- isLoading: o || g || T,
184
- error: c ?? (i ? v ?? O : null),
183
+ order: i ? m : null,
184
+ isLoading: o || g || S,
185
+ error: c ?? (i ? _ ?? E : null),
185
186
  refetch: () => {
186
- m((e) => e + 1), i && (y(), A());
187
+ d((e) => e + 1), i && (v(), A());
187
188
  }
188
189
  };
189
190
  }
190
- function O(e) {
191
+ function j(e) {
191
192
  let { vehicle: t, isLoading: n, error: r, refetch: i } = c(e);
192
193
  return {
193
- tracking: f(() => !t || !t.currentLocation ? null : {
194
+ tracking: m(() => !t || !t.currentLocation ? null : {
194
195
  id: `vehicle-track-${t.id}`,
195
196
  entityId: t.id,
196
197
  entityType: "vehicle",
@@ -206,10 +207,10 @@ function O(e) {
206
207
  refetch: i
207
208
  };
208
209
  }
209
- function k(e) {
210
+ function M(e) {
210
211
  let { driver: t, isLoading: n, error: r, refetch: i } = o(e);
211
212
  return {
212
- tracking: f(() => !t || !t.currentLocation ? null : {
213
+ tracking: m(() => !t || !t.currentLocation ? null : {
213
214
  id: `driver-track-${t.id}`,
214
215
  entityId: t.id,
215
216
  entityType: "driver",
@@ -225,11 +226,11 @@ function k(e) {
225
226
  refetch: i
226
227
  };
227
228
  }
228
- function A() {
229
- let e = S(), [r, o] = p([]), [s, c] = p(!1), [l, f] = p(null), m = u(async () => {
230
- c(!0), f(null);
229
+ function N() {
230
+ let e = T(), [r, o] = h([]), [s, c] = h(!1), [l, u] = h(null), d = f(async () => {
231
+ c(!0), u(null);
231
232
  try {
232
- o(((await t(e, v, { pagination: {
233
+ o(((await t(e, b, { pagination: {
233
234
  limit: 100,
234
235
  offset: 0
235
236
  } })).activeDeliveries ?? []).map((e) => {
@@ -238,66 +239,79 @@ function A() {
238
239
  order: n(t),
239
240
  driver: t.driver ? i(t.driver) : null,
240
241
  vehicle: t.vehicle ? a(t.vehicle) : null,
241
- tracking: x(e.trackingEvents ?? [], t.id, e.status),
242
+ tracking: w(e.trackingEvents ?? [], t.id, e.status),
242
243
  estimatedArrival: e.estimatedDelivery ? new Date(e.estimatedDelivery) : void 0
243
244
  } : null;
244
245
  }).filter((e) => e !== null));
245
246
  } catch (e) {
246
- f(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load live tracking"));
247
+ u(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load live tracking"));
247
248
  } finally {
248
249
  c(!1);
249
250
  }
250
251
  }, [e]);
251
- return d(() => {
252
- m();
253
- }, [m]), w(m, !0), {
252
+ return p(() => {
253
+ d();
254
+ }, [d]), D(d, !0), {
254
255
  activeDeliveries: r,
255
256
  isLoading: s,
256
257
  error: l,
257
- refetch: () => void m()
258
+ refetch: () => void d()
258
259
  };
259
260
  }
260
- function j() {
261
- let e = S(), [n, r] = p([]), [i, a] = p(!1), [o, s] = p(null), c = u(async () => {
261
+ function P() {
262
+ let e = T(), [n, r] = h([]), [i, a] = h(!1), [o, s] = h(null), c = f(async () => {
262
263
  a(!0), s(null);
263
264
  try {
264
- r((await t(e, y)).trackingAlerts.map((e) => ({
265
- id: `${e.shipmentId}-${e.alertType}`,
266
- type: "delay",
267
- severity: "medium",
268
- message: `${e.shipmentNumber}: ${e.message}`,
269
- acknowledged: !1
270
- })));
265
+ r(d((await t(e, x)).trackingAlerts.map(u)));
271
266
  } catch (e) {
272
267
  s(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load tracking alerts"));
273
268
  } finally {
274
269
  a(!1);
275
270
  }
276
271
  }, [e]);
277
- return d(() => {
272
+ return p(() => {
278
273
  c();
279
274
  }, [c]), {
280
275
  alerts: n,
281
- unacknowledgedAlerts: f(() => n.filter((e) => !e.acknowledged), [n]),
282
- acknowledgeAlert: u(async (e) => {
283
- r((t) => t.map((t) => t.id === e ? {
284
- ...t,
285
- acknowledged: !0
286
- } : t));
287
- }, []),
276
+ unacknowledgedAlerts: m(() => n.filter((e) => !e.acknowledged), [n]),
277
+ acknowledgeAlert: f(async (i) => {
278
+ let a = n.find((e) => e.id === i);
279
+ if (!(!a?.shipmentId || !a.kind)) {
280
+ r((e) => e.map((e) => e.id === i ? {
281
+ ...e,
282
+ acknowledged: !0
283
+ } : e));
284
+ try {
285
+ let n = await t(e, S, {
286
+ shipmentId: a.shipmentId,
287
+ alertType: a.kind
288
+ }), o = new Date(n.acknowledgeMtwTrackingAlert.acknowledgedAt);
289
+ r((e) => e.map((e) => e.id === i ? {
290
+ ...e,
291
+ acknowledged: !0,
292
+ acknowledgedAt: o
293
+ } : e));
294
+ } catch (e) {
295
+ throw r((e) => e.map((e) => e.id === i ? {
296
+ ...e,
297
+ acknowledged: !1
298
+ } : e)), e instanceof Error ? e : /* @__PURE__ */ Error("Failed to acknowledge alert");
299
+ }
300
+ }
301
+ }, [n, e]),
288
302
  isLoading: i,
289
303
  error: o,
290
304
  refetch: () => void c()
291
305
  };
292
306
  }
293
- function M(e, t) {
307
+ function F(e, t) {
294
308
  let { vehicles: n } = l(), { drivers: r } = s();
295
309
  return {
296
- entitiesInRange: f(() => {
310
+ entitiesInRange: m(() => {
297
311
  let i = [];
298
312
  return n.forEach((n) => {
299
313
  if (!n.currentLocation) return;
300
- let r = N(e.latitude, e.longitude, n.currentLocation.latitude, n.currentLocation.longitude);
314
+ let r = I(e.latitude, e.longitude, n.currentLocation.latitude, n.currentLocation.longitude);
301
315
  r <= t && i.push({
302
316
  type: "vehicle",
303
317
  entity: n,
@@ -305,7 +319,7 @@ function M(e, t) {
305
319
  });
306
320
  }), r.forEach((n) => {
307
321
  if (!n.currentLocation) return;
308
- let r = N(e.latitude, e.longitude, n.currentLocation.latitude, n.currentLocation.longitude);
322
+ let r = I(e.latitude, e.longitude, n.currentLocation.latitude, n.currentLocation.longitude);
309
323
  r <= t && i.push({
310
324
  type: "driver",
311
325
  entity: n,
@@ -323,12 +337,12 @@ function M(e, t) {
323
337
  error: null
324
338
  };
325
339
  }
326
- function N(e, t, n, r) {
327
- let i = P(n - e), a = P(r - t), o = Math.sin(i / 2) * Math.sin(i / 2) + Math.cos(P(e)) * Math.cos(P(n)) * Math.sin(a / 2) * Math.sin(a / 2);
340
+ function I(e, t, n, r) {
341
+ let i = L(n - e), a = L(r - t), o = Math.sin(i / 2) * Math.sin(i / 2) + Math.cos(L(e)) * Math.cos(L(n)) * Math.sin(a / 2) * Math.sin(a / 2);
328
342
  return 6371 * (2 * Math.atan2(Math.sqrt(o), Math.sqrt(1 - o)));
329
343
  }
330
- function P(e) {
344
+ function L(e) {
331
345
  return Math.PI / 180 * e;
332
346
  }
333
347
  //#endregion
334
- export { k as useDriverTracking, M as useGeofence, A as useLiveTracking, D as useOrderTracking, T as useTracking, j as useTrackingAlerts, O as useVehicleTracking };
348
+ export { M as useDriverTracking, F as useGeofence, N as useLiveTracking, A as useOrderTracking, O as useTracking, P as useTrackingAlerts, j as useVehicleTracking };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * ShipmentRiskDialog (BOFF-10397)
3
+ *
4
+ * The risk panel for one shipment, backed by `mtwShipmentRiskForecast`: risk
5
+ * score and level, promised vs predicted delivery window, the contributing
6
+ * signals with their weights, and the recommended action wired to the
7
+ * mutation the forecast names.
8
+ */
9
+ type Translate = (key: string, fallback: string) => string;
10
+ interface ShipmentRiskDialogProps {
11
+ shipmentId: string | undefined;
12
+ shipmentNumber: string | undefined;
13
+ open: boolean;
14
+ onOpenChange: (open: boolean) => void;
15
+ t: Translate;
16
+ onOpenOrder: (deliveryJobId: string) => void;
17
+ onChanged: () => void;
18
+ }
19
+ export declare function ShipmentRiskDialog({ shipmentId, shipmentNumber, open, onOpenChange, t, onOpenOrder, onChanged, }: ShipmentRiskDialogProps): import('react').JSX.Element;
20
+ export {};
@@ -0,0 +1,14 @@
1
+ import { TrackingAlert } from '../types';
2
+ type Translate = (key: string, fallback: string) => string;
3
+ interface TrackingAlertListProps {
4
+ alerts: TrackingAlert[];
5
+ limit: number;
6
+ t: Translate;
7
+ onAcknowledge: (alertId: string) => Promise<void>;
8
+ /** Opens the order (delivery job) page, where a vehicle can be reassigned. */
9
+ onOpenOrder: (deliveryJobId: string) => void;
10
+ /** Called after a risk action changed the shipment, so callers can reload alerts. */
11
+ onChanged: () => void;
12
+ }
13
+ export declare function TrackingAlertList({ alerts, limit, t, onAcknowledge, onOpenOrder, onChanged, }: TrackingAlertListProps): import('react').JSX.Element;
14
+ export {};
@@ -0,0 +1,19 @@
1
+ import { MtwImportEntitySpec, MtwImportEntityType, MtwImportFormat, MtwImportResult } from '../utils/entityImport';
2
+ /** Column specification for every importable entity. */
3
+ export declare function useImportSpec(): {
4
+ specs: MtwImportEntitySpec[];
5
+ isLoading: boolean;
6
+ error: Error | null;
7
+ };
8
+ export interface ImportRequest {
9
+ entityType: MtwImportEntityType;
10
+ format: MtwImportFormat;
11
+ content: string;
12
+ dryRun: boolean;
13
+ allowPartial: boolean;
14
+ }
15
+ /** Runs a validation or an import. Writes are sent once: a retry could create rows twice. */
16
+ export declare function useEntityImport(): {
17
+ run: (request: ImportRequest) => Promise<MtwImportResult>;
18
+ isRunning: boolean;
19
+ };
@@ -0,0 +1,41 @@
1
+ import { RiskSignalCode } from '../utils/trackingAlerts';
2
+ export type RiskLevel = 'NONE' | 'LOW' | 'MEDIUM' | 'HIGH';
3
+ export type RiskRecommendedAction = 'NONE' | 'MONITOR' | 'REPROMISE_DELIVERY' | 'REQUEST_TRACKING_UPDATE' | 'REASSIGN_VEHICLE';
4
+ export interface RiskSignal {
5
+ code: RiskSignalCode;
6
+ weight: number;
7
+ minutes: number | null;
8
+ ratio: number | null;
9
+ }
10
+ export interface ShipmentRiskForecast {
11
+ shipmentId: string;
12
+ shipmentNumber: string;
13
+ status: string;
14
+ method: string;
15
+ promisedDelivery: string | null;
16
+ predictedDeliveryEarliest: string | null;
17
+ predictedDeliveryLatest: string | null;
18
+ predictedSlipMinutes: number;
19
+ riskScore: number;
20
+ riskLevel: RiskLevel;
21
+ atRisk: boolean;
22
+ breached: boolean;
23
+ signals: RiskSignal[];
24
+ recommendedAction: RiskRecommendedAction;
25
+ recommendedMutation: string | null;
26
+ evaluatedAt: string;
27
+ }
28
+ export interface RiskShipment {
29
+ id: string;
30
+ deliveryJobId: string | null;
31
+ estimatedDelivery: string | null;
32
+ }
33
+ export declare function useShipmentRisk(shipmentId: string | undefined): {
34
+ forecast: ShipmentRiskForecast | null;
35
+ shipment: RiskShipment | null;
36
+ isLoading: boolean;
37
+ error: Error | null;
38
+ refetch: () => undefined;
39
+ repromise: (estimatedDelivery: string) => Promise<void>;
40
+ recordTrackingUpdate: (details: string) => Promise<void>;
41
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Import / Export Page (BOFF-3990)
3
+ *
4
+ * Bulk data in and out of MoveTheWheels. Import validates a CSV or JSON file
5
+ * row by row on the server (dry run first, then import) for customers,
6
+ * vehicles, drivers, warehouses and products. Export starts the same
7
+ * `exportMtwEntities` job the list pages use and downloads the archive.
8
+ */
9
+ export default function ImportExportPage(): import('react').JSX.Element;
@@ -415,14 +415,28 @@ export interface Route {
415
415
  optimized?: boolean;
416
416
  createdAt: Date;
417
417
  }
418
+ export type TrackingAlertSeverity = 'low' | 'medium' | 'high' | 'critical';
418
419
  export interface TrackingAlert {
419
420
  id: string;
420
421
  type: 'delay' | 'deviation' | 'temperature' | 'damage' | 'security';
421
- severity: 'low' | 'medium' | 'high' | 'critical';
422
+ severity: TrackingAlertSeverity;
422
423
  message: string;
423
424
  timestamp?: Date;
424
425
  acknowledged: boolean;
425
426
  resolvedAt?: Date;
427
+ /** Server alert kind for shipment alerts (BOFF-10397). */
428
+ kind?: 'DELAYED' | 'AT_RISK';
429
+ shipmentId?: string;
430
+ shipmentNumber?: string;
431
+ /** 0–100 forecast risk score; AT_RISK alerts only. */
432
+ riskScore?: number;
433
+ /** The shipment's promised delivery the alert was raised against. */
434
+ promisedDelivery?: Date;
435
+ /** Earliest forecast delivery time; AT_RISK alerts only. */
436
+ predictedDelivery?: Date;
437
+ /** Contributing risk signal codes; AT_RISK alerts only. */
438
+ signals?: string[];
439
+ acknowledgedAt?: Date;
426
440
  }
427
441
  export interface Tracking {
428
442
  id: string;