@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.
- package/dist/MoveTheWheelsRoot.js +144 -136
- package/dist/MoveTheWheelsRoutes.js +61 -57
- package/dist/components/ShipmentRiskDialog.js +228 -0
- package/dist/components/TrackingAlertList.js +149 -0
- package/dist/generated/tracking-quality-operations.d.ts +1154 -2
- package/dist/generated/wspace-types.d.ts +2895 -50
- package/dist/hooks/useEntityImport.js +68 -0
- package/dist/hooks/useShipmentRisk.js +72 -0
- package/dist/hooks/useTracking.js +96 -82
- package/dist/movethewheels/components/ShipmentRiskDialog.d.ts +20 -0
- package/dist/movethewheels/components/TrackingAlertList.d.ts +14 -0
- package/dist/movethewheels/hooks/useEntityImport.d.ts +19 -0
- package/dist/movethewheels/hooks/useShipmentRisk.d.ts +41 -0
- package/dist/movethewheels/pages/ImportExportPage.d.ts +9 -0
- package/dist/movethewheels/types/index.d.ts +15 -1
- package/dist/movethewheels/utils/entityImport.d.ts +109 -0
- package/dist/movethewheels/utils/trackingAlerts.d.ts +36 -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/file-spreadsheet.js +30 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/file-up.js +22 -0
- package/dist/pages/CustomersPage.js +88 -79
- package/dist/pages/DashboardPage.js +147 -151
- package/dist/pages/DriversPage.js +115 -106
- package/dist/pages/ImportExportPage.js +435 -0
- package/dist/pages/LiveTrackingPage.js +169 -169
- package/dist/pages/ProductsPage.js +85 -76
- package/dist/pages/VehiclesPage.js +99 -90
- package/dist/pages/WarehousesPage.js +97 -88
- package/dist/utils/entityImport.js +73 -0
- package/dist/utils/trackingAlerts.js +86 -0
- package/package.json +4 -2
- package/src/generated/tracking-quality-operations.ts +1519 -1
- package/src/generated/wspace-types.ts +3248 -51
- package/src/movethewheels/MoveTheWheelsRoot.tsx +8 -0
- package/src/movethewheels/MoveTheWheelsRoutes.tsx +4 -0
- package/src/movethewheels/components/ShipmentRiskDialog.tsx +315 -0
- package/src/movethewheels/components/TrackingAlertList.tsx +188 -0
- package/src/movethewheels/hooks/useEntityImport.ts +108 -0
- package/src/movethewheels/hooks/useShipmentRisk.ts +195 -0
- package/src/movethewheels/hooks/useTracking.ts +66 -22
- package/src/movethewheels/pages/CustomersPage.tsx +6 -1
- package/src/movethewheels/pages/DashboardPage.tsx +10 -20
- package/src/movethewheels/pages/DriversPage.tsx +6 -0
- package/src/movethewheels/pages/ImportExportPage.tsx +483 -0
- package/src/movethewheels/pages/LiveTrackingPage.tsx +20 -22
- package/src/movethewheels/pages/ProductsPage.tsx +14 -1
- package/src/movethewheels/pages/VehiclesPage.tsx +6 -0
- package/src/movethewheels/pages/WarehousesPage.tsx +6 -1
- package/src/movethewheels/types/index.ts +16 -1
- package/src/movethewheels/utils/entityImport.ts +239 -0
- 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 {
|
|
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
|
|
8
|
-
function
|
|
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
|
|
20
|
+
function w(e, t, n) {
|
|
20
21
|
let r = e[0];
|
|
21
22
|
if (!r) return null;
|
|
22
|
-
let i = e.map(
|
|
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
|
|
37
|
+
function T() {
|
|
37
38
|
let { apiGatewayUrl: t, authToken: n, workspaceToken: r, workspaceId: i, tenantId: a, currentUser: o } = e();
|
|
38
|
-
return
|
|
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
|
|
55
|
-
function
|
|
56
|
-
|
|
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,
|
|
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
|
|
67
|
-
let { entityId: n, entityType: r, realtime: i = !1 } = e, a =
|
|
68
|
-
l(!0),
|
|
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,
|
|
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
|
-
|
|
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
|
|
103
|
-
|
|
104
|
-
}, [
|
|
103
|
+
return p(() => {
|
|
104
|
+
m();
|
|
105
|
+
}, [m]), D(m, i), {
|
|
105
106
|
tracking: o,
|
|
106
107
|
isLoading: c,
|
|
107
|
-
error:
|
|
108
|
-
refetch: () => void
|
|
108
|
+
error: u,
|
|
109
|
+
refetch: () => void m()
|
|
109
110
|
};
|
|
110
111
|
}
|
|
111
|
-
async function
|
|
112
|
-
let r = n.trim(), i = await t(e,
|
|
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,
|
|
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,
|
|
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
|
|
138
|
-
let n =
|
|
139
|
-
|
|
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),
|
|
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
|
-
|
|
155
|
+
u,
|
|
155
156
|
e
|
|
156
157
|
]);
|
|
157
|
-
let A =
|
|
158
|
+
let A = f(async () => {
|
|
158
159
|
if (!i) {
|
|
159
|
-
|
|
160
|
+
x(null), C(!1);
|
|
160
161
|
return;
|
|
161
162
|
}
|
|
162
|
-
|
|
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
|
-
|
|
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
|
-
|
|
174
|
+
O(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load order tracking"));
|
|
174
175
|
} finally {
|
|
175
|
-
|
|
176
|
+
C(!1);
|
|
176
177
|
}
|
|
177
178
|
}, [n, i]);
|
|
178
|
-
return
|
|
179
|
+
return p(() => {
|
|
179
180
|
A();
|
|
180
|
-
}, [A]),
|
|
181
|
+
}, [A]), D(A, !!i), {
|
|
181
182
|
tracking: b,
|
|
182
|
-
order: i ?
|
|
183
|
-
isLoading: o || g ||
|
|
184
|
-
error: c ?? (i ?
|
|
183
|
+
order: i ? m : null,
|
|
184
|
+
isLoading: o || g || S,
|
|
185
|
+
error: c ?? (i ? _ ?? E : null),
|
|
185
186
|
refetch: () => {
|
|
186
|
-
|
|
187
|
+
d((e) => e + 1), i && (v(), A());
|
|
187
188
|
}
|
|
188
189
|
};
|
|
189
190
|
}
|
|
190
|
-
function
|
|
191
|
+
function j(e) {
|
|
191
192
|
let { vehicle: t, isLoading: n, error: r, refetch: i } = c(e);
|
|
192
193
|
return {
|
|
193
|
-
tracking:
|
|
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
|
|
210
|
+
function M(e) {
|
|
210
211
|
let { driver: t, isLoading: n, error: r, refetch: i } = o(e);
|
|
211
212
|
return {
|
|
212
|
-
tracking:
|
|
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
|
|
229
|
-
let e =
|
|
230
|
-
c(!0),
|
|
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,
|
|
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:
|
|
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
|
-
|
|
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
|
|
252
|
-
|
|
253
|
-
}, [
|
|
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
|
|
258
|
+
refetch: () => void d()
|
|
258
259
|
};
|
|
259
260
|
}
|
|
260
|
-
function
|
|
261
|
-
let e =
|
|
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,
|
|
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
|
|
272
|
+
return p(() => {
|
|
278
273
|
c();
|
|
279
274
|
}, [c]), {
|
|
280
275
|
alerts: n,
|
|
281
|
-
unacknowledgedAlerts:
|
|
282
|
-
acknowledgeAlert:
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
|
307
|
+
function F(e, t) {
|
|
294
308
|
let { vehicles: n } = l(), { drivers: r } = s();
|
|
295
309
|
return {
|
|
296
|
-
entitiesInRange:
|
|
310
|
+
entitiesInRange: m(() => {
|
|
297
311
|
let i = [];
|
|
298
312
|
return n.forEach((n) => {
|
|
299
313
|
if (!n.currentLocation) return;
|
|
300
|
-
let r =
|
|
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 =
|
|
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
|
|
327
|
-
let i =
|
|
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
|
|
344
|
+
function L(e) {
|
|
331
345
|
return Math.PI / 180 * e;
|
|
332
346
|
}
|
|
333
347
|
//#endregion
|
|
334
|
-
export {
|
|
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:
|
|
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;
|