@burdenoff/microfe-movethewheels 2026.1010.2 → 2026.1011.2
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 +12 -1
- package/dist/MoveTheWheelsRoutes.js +57 -49
- package/dist/generated/shipment-status-authority-operations.d.ts +4473 -0
- package/dist/generated/tracking-quality-operations.d.ts +4302 -0
- package/dist/hooks/useEpod.js +85 -77
- package/dist/hooks/useShipmentStatusAuthority.js +127 -0
- package/dist/hooks/useTracking.js +15 -14
- package/dist/hooks/useTrackingEventQuality.js +60 -0
- package/dist/movethewheels/hooks/useEpod.d.ts +23 -0
- package/dist/movethewheels/hooks/useShipmentStatusAuthority.d.ts +23 -0
- package/dist/movethewheels/hooks/useTrackingEventQuality.d.ts +18 -0
- package/dist/movethewheels/pages/ShipmentStatusAuthorityPage.d.ts +1 -0
- package/dist/movethewheels/pages/TrackingEventQualityPage.d.ts +1 -0
- package/dist/movethewheels/utils/shipmentStatusDraft.d.ts +45 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/radio-tower.js +36 -0
- package/dist/pages/DeliveryCapturePage.js +181 -116
- package/dist/pages/ShipmentStatusAuthorityPage.js +563 -0
- package/dist/pages/TrackingEventQualityPage.js +224 -0
- package/dist/src/generated/shipment-status-authority-operations.js +86 -0
- package/dist/src/generated/tracking-quality-operations.js +44 -0
- package/dist/utils/shipmentStatusDraft.js +41 -0
- package/package.json +16 -7
- package/patches/README.md +25 -0
- package/patches/braces@3.0.3.patch +87 -0
- package/src/generated/shipment-status-authority-operations.ts +5503 -0
- package/src/generated/tracking-quality-operations.ts +5323 -0
- package/src/movethewheels/MoveTheWheelsRoot.tsx +14 -0
- package/src/movethewheels/MoveTheWheelsRoutes.tsx +4 -0
- package/src/movethewheels/hooks/useEpod.ts +47 -12
- package/src/movethewheels/hooks/useShipmentStatusAuthority.ts +179 -0
- package/src/movethewheels/hooks/useTracking.ts +27 -12
- package/src/movethewheels/hooks/useTrackingEventQuality.ts +110 -0
- package/src/movethewheels/pages/DeliveryCapturePage.tsx +113 -6
- package/src/movethewheels/pages/ShipmentStatusAuthorityPage.tsx +639 -0
- package/src/movethewheels/pages/TrackingEventQualityPage.tsx +250 -0
- package/src/movethewheels/utils/shipmentStatusDraft.ts +118 -0
- package/src/operations/shipment-status-authority/status.graphql +80 -0
- package/src/operations/tracking-quality/quality.graphql +15 -0
package/dist/hooks/useEpod.js
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import { useMoveTheWheels as e } from "../providers/MoveTheWheelsProvider.js";
|
|
2
2
|
import { executeGraphQL as t } from "../utils/graphqlClient.js";
|
|
3
|
-
import {
|
|
3
|
+
import { useShipmentStatusCommand as n } from "./useShipmentStatusAuthority.js";
|
|
4
|
+
import { useCallback as r, useEffect as i, useMemo as a, useState as o } from "react";
|
|
5
|
+
import { parse as s } from "graphql";
|
|
4
6
|
//#region src/movethewheels/hooks/useEpod.ts
|
|
5
|
-
var
|
|
7
|
+
var c = "\n id\n deliveryJobId\n shipmentId\n recipientName\n signatureType\n signatureData\n photoFileIds\n latitude\n longitude\n locationAccuracy\n deliveredAt\n capturedByDriverId\n notes\n", l = `
|
|
6
8
|
query GetEpod($deliveryJobId: ID!) {
|
|
7
9
|
epod(deliveryJobId: $deliveryJobId) {
|
|
8
|
-
${
|
|
10
|
+
${c}
|
|
9
11
|
}
|
|
10
12
|
}
|
|
11
|
-
`,
|
|
13
|
+
`, u = "\n query MyPendingEpodDeliveryJobs($pagination: PaginationInput) {\n myPendingEpodDeliveryJobs(pagination: $pagination) {\n id\n deliveryJobNumber\n status\n priority\n deliveryAddress\n scheduledDelivery\n customer {\n name\n phone\n }\n }\n myPendingEpodDeliveryJobsCount\n }\n", d = s(`
|
|
12
14
|
mutation CaptureEpod($input: CaptureEpodInput!) {
|
|
13
15
|
captureEpod(input: $input) {
|
|
14
|
-
${
|
|
16
|
+
${c}
|
|
15
17
|
}
|
|
16
18
|
}
|
|
17
|
-
|
|
18
|
-
function
|
|
19
|
+
`), f = "\n mutation EpodInitiateUpload($input: InitiateUploadInput!) {\n initiateUpload(input: $input) {\n uploadUrl\n session { id }\n }\n }\n", p = "\n mutation EpodCompleteUpload($input: CompleteUploadInput!) {\n completeUpload(input: $input) {\n fileId\n }\n }\n", m = "\n query EpodFileUrl($id: ID!, $expiresIn: Int) {\n getFileDownloadUrl(id: $id, expiresIn: $expiresIn)\n }\n", h = 21600;
|
|
20
|
+
function g(e) {
|
|
19
21
|
return e === "typed" ? "TYPED" : "DRAWN";
|
|
20
22
|
}
|
|
21
|
-
function
|
|
23
|
+
function _(e) {
|
|
22
24
|
return {
|
|
23
25
|
id: e.id,
|
|
24
26
|
deliveryJobId: e.deliveryJobId,
|
|
@@ -35,58 +37,58 @@ function h(e) {
|
|
|
35
37
|
notes: e.notes ?? void 0
|
|
36
38
|
};
|
|
37
39
|
}
|
|
38
|
-
function
|
|
39
|
-
let { apiGatewayUrl: t, authToken: n, workspaceToken: r, workspaceId:
|
|
40
|
-
return
|
|
40
|
+
function v() {
|
|
41
|
+
let { apiGatewayUrl: t, authToken: n, workspaceToken: r, workspaceId: i, tenantId: o, currentUser: s } = e();
|
|
42
|
+
return a(() => ({
|
|
41
43
|
apiGatewayUrl: t,
|
|
42
44
|
authToken: n,
|
|
43
45
|
workspaceToken: r,
|
|
44
|
-
workspaceId:
|
|
46
|
+
workspaceId: i,
|
|
45
47
|
tenantId: o,
|
|
46
48
|
actorId: s?.id
|
|
47
49
|
}), [
|
|
48
50
|
t,
|
|
49
51
|
n,
|
|
50
52
|
r,
|
|
51
|
-
|
|
53
|
+
i,
|
|
52
54
|
o,
|
|
53
55
|
s?.id
|
|
54
56
|
]);
|
|
55
57
|
}
|
|
56
|
-
function
|
|
57
|
-
let
|
|
58
|
+
function y(e) {
|
|
59
|
+
let n = v(), [a, s] = o(null), [c, u] = o(!1), [d, f] = o(null), p = r(async () => {
|
|
58
60
|
if (!e) {
|
|
59
|
-
|
|
61
|
+
s(null);
|
|
60
62
|
return;
|
|
61
63
|
}
|
|
62
64
|
u(!0), f(null);
|
|
63
65
|
try {
|
|
64
|
-
let
|
|
65
|
-
|
|
66
|
+
let r = await t(n, l, { deliveryJobId: e });
|
|
67
|
+
s(r.epod ? _(r.epod) : null);
|
|
66
68
|
} catch (e) {
|
|
67
|
-
f(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load proof of delivery")),
|
|
69
|
+
f(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load proof of delivery")), s(null);
|
|
68
70
|
} finally {
|
|
69
71
|
u(!1);
|
|
70
72
|
}
|
|
71
|
-
}, [e,
|
|
72
|
-
return
|
|
73
|
+
}, [e, n]);
|
|
74
|
+
return i(() => {
|
|
73
75
|
p();
|
|
74
76
|
}, [p]), {
|
|
75
|
-
epod:
|
|
76
|
-
isLoading:
|
|
77
|
+
epod: a,
|
|
78
|
+
isLoading: c,
|
|
77
79
|
error: d,
|
|
78
80
|
refetch: p
|
|
79
81
|
};
|
|
80
82
|
}
|
|
81
|
-
function
|
|
82
|
-
let { limit:
|
|
83
|
-
|
|
83
|
+
function b(e = {}) {
|
|
84
|
+
let { limit: n = 20, offset: a = 0 } = e, s = v(), [c, l] = o([]), [d, f] = o(0), [p, m] = o(!1), [h, g] = o(!1), [_, y] = o(null), b = r(async () => {
|
|
85
|
+
g(!0), y(null);
|
|
84
86
|
try {
|
|
85
|
-
let e = await t(s,
|
|
86
|
-
limit:
|
|
87
|
-
offset:
|
|
87
|
+
let e = await t(s, u, { pagination: {
|
|
88
|
+
limit: n,
|
|
89
|
+
offset: a
|
|
88
90
|
} });
|
|
89
|
-
f(e.myPendingEpodDeliveryJobsCount ?? 0), m(
|
|
91
|
+
f(e.myPendingEpodDeliveryJobsCount ?? 0), m(a + e.myPendingEpodDeliveryJobs.length < e.myPendingEpodDeliveryJobsCount), l(e.myPendingEpodDeliveryJobs.map((e) => ({
|
|
90
92
|
id: e.id,
|
|
91
93
|
deliveryJobNumber: e.deliveryJobNumber,
|
|
92
94
|
status: e.status,
|
|
@@ -97,61 +99,67 @@ function v(e = {}) {
|
|
|
97
99
|
customerPhone: e.customer?.phone ?? void 0
|
|
98
100
|
})));
|
|
99
101
|
} catch (e) {
|
|
100
|
-
y(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load pending deliveries")),
|
|
102
|
+
y(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load pending deliveries")), l([]);
|
|
101
103
|
} finally {
|
|
102
|
-
|
|
104
|
+
g(!1);
|
|
103
105
|
}
|
|
104
106
|
}, [
|
|
105
107
|
s,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
+
n,
|
|
109
|
+
a
|
|
108
110
|
]);
|
|
109
|
-
return
|
|
111
|
+
return i(() => {
|
|
110
112
|
b();
|
|
111
113
|
}, [b]), {
|
|
112
|
-
jobs:
|
|
114
|
+
jobs: c,
|
|
113
115
|
totalJobs: d,
|
|
114
116
|
hasMore: p,
|
|
115
117
|
isLoading: h,
|
|
116
|
-
error:
|
|
118
|
+
error: _,
|
|
117
119
|
refetch: b
|
|
118
120
|
};
|
|
119
121
|
}
|
|
120
|
-
function
|
|
121
|
-
|
|
122
|
+
function x(e, t) {
|
|
123
|
+
return !!e && typeof e.id == "string" && e.id.trim().length > 0 && e.deliveryJobId === t.deliveryJobId && e.shipmentId === t.expectedShipmentId && e.recipientName === t.recipientName && e.signatureType === g(t.signatureType) && e.signatureData === t.signatureData && typeof e.capturedByDriverId == "string" && e.capturedByDriverId.trim().length > 0 && typeof e.deliveredAt == "string" && Number.isFinite(Date.parse(e.deliveredAt)) && Array.isArray(e.photoFileIds) && e.photoFileIds.length === (t.photoFileIds ?? []).length && e.photoFileIds.every((e, n) => e === (t.photoFileIds ?? [])[n]) && e.latitude === (t.latitude ?? null) && e.longitude === (t.longitude ?? null) && e.locationAccuracy === (t.locationAccuracy ?? null) && e.notes === (t.notes ?? null);
|
|
124
|
+
}
|
|
125
|
+
function S() {
|
|
126
|
+
let e = n(), [t, i] = o(null);
|
|
122
127
|
return {
|
|
123
|
-
captureEpod:
|
|
124
|
-
i(
|
|
128
|
+
captureEpod: r(async (t) => {
|
|
129
|
+
i(null);
|
|
125
130
|
try {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
131
|
+
let n = await e.run(d, { input: {
|
|
132
|
+
expectedShipmentStatusRevision: t.expectedShipmentStatusRevision,
|
|
133
|
+
completionAttestation: t.completionAttestation,
|
|
134
|
+
deliveryJobId: t.deliveryJobId,
|
|
135
|
+
recipientName: t.recipientName,
|
|
136
|
+
signatureType: g(t.signatureType),
|
|
137
|
+
signatureData: t.signatureData,
|
|
138
|
+
photoFileIds: t.photoFileIds,
|
|
139
|
+
latitude: t.latitude,
|
|
140
|
+
longitude: t.longitude,
|
|
141
|
+
locationAccuracy: t.locationAccuracy,
|
|
142
|
+
notes: t.notes
|
|
143
|
+
} }, (e) => x(e.captureEpod, t));
|
|
144
|
+
if (!n) throw Error("Capture was not acknowledged. Review the recorded status and the capture message before taking further action.");
|
|
145
|
+
return _(n.captureEpod);
|
|
137
146
|
} catch (e) {
|
|
138
147
|
let t = e instanceof Error ? e : /* @__PURE__ */ Error("Failed to capture proof of delivery");
|
|
139
|
-
throw
|
|
140
|
-
} finally {
|
|
141
|
-
i(!1);
|
|
148
|
+
throw i(t), t;
|
|
142
149
|
}
|
|
143
150
|
}, [e]),
|
|
144
|
-
isSubmitting:
|
|
145
|
-
error:
|
|
151
|
+
isSubmitting: e.busy,
|
|
152
|
+
error: t,
|
|
153
|
+
captureFeedback: e.feedback
|
|
146
154
|
};
|
|
147
155
|
}
|
|
148
|
-
function
|
|
149
|
-
let e =
|
|
156
|
+
function C() {
|
|
157
|
+
let e = v(), [n, i] = o(!1), [a, s] = o(0), [c, l] = o(null);
|
|
150
158
|
return {
|
|
151
|
-
upload:
|
|
159
|
+
upload: r(async (n) => {
|
|
152
160
|
i(!0), s(0), l(null);
|
|
153
161
|
try {
|
|
154
|
-
let r = n.name.lastIndexOf("."), i = r > -1 ? n.name.slice(r + 1) : "", a = n.type || "application/octet-stream", o = await t(e,
|
|
162
|
+
let r = n.name.lastIndexOf("."), i = r > -1 ? n.name.slice(r + 1) : "", a = n.type || "application/octet-stream", o = await t(e, f, { input: {
|
|
155
163
|
fileName: n.name,
|
|
156
164
|
extension: i,
|
|
157
165
|
mimeType: a,
|
|
@@ -160,18 +168,18 @@ function b() {
|
|
|
160
168
|
} }), { uploadUrl: c } = o.initiateUpload, l = o.initiateUpload.session.id;
|
|
161
169
|
if (!c) throw Error("The file service did not return an upload URL.");
|
|
162
170
|
s(50);
|
|
163
|
-
let
|
|
171
|
+
let u = await fetch(c, {
|
|
164
172
|
method: "PUT",
|
|
165
173
|
headers: { "Content-Type": a },
|
|
166
174
|
body: n
|
|
167
175
|
});
|
|
168
|
-
if (!
|
|
169
|
-
let
|
|
176
|
+
if (!u.ok) throw Error(`File storage rejected the upload (HTTP ${u.status}).`);
|
|
177
|
+
let d = await t(e, p, { input: {
|
|
170
178
|
sessionId: l,
|
|
171
179
|
fileSize: String(n.size)
|
|
172
180
|
} });
|
|
173
181
|
return s(100), {
|
|
174
|
-
fileId:
|
|
182
|
+
fileId: d.completeUpload.fileId,
|
|
175
183
|
fileName: n.name
|
|
176
184
|
};
|
|
177
185
|
} catch (e) {
|
|
@@ -181,35 +189,35 @@ function b() {
|
|
|
181
189
|
i(!1);
|
|
182
190
|
}
|
|
183
191
|
}, [e]),
|
|
184
|
-
isUploading:
|
|
185
|
-
progress:
|
|
192
|
+
isUploading: n,
|
|
193
|
+
progress: a,
|
|
186
194
|
error: c
|
|
187
195
|
};
|
|
188
196
|
}
|
|
189
|
-
function
|
|
190
|
-
let n =
|
|
191
|
-
return
|
|
197
|
+
function w(e) {
|
|
198
|
+
let n = v(), [r, a] = o(null), [s, c] = o(!1);
|
|
199
|
+
return i(() => {
|
|
192
200
|
if (!e) {
|
|
193
|
-
|
|
201
|
+
a(null);
|
|
194
202
|
return;
|
|
195
203
|
}
|
|
196
204
|
let r = !1;
|
|
197
|
-
return c(!0), t(n,
|
|
205
|
+
return c(!0), t(n, m, {
|
|
198
206
|
id: e,
|
|
199
|
-
expiresIn:
|
|
207
|
+
expiresIn: h
|
|
200
208
|
}).then((e) => {
|
|
201
|
-
r ||
|
|
209
|
+
r || a(e.getFileDownloadUrl ?? null);
|
|
202
210
|
}).catch(() => {
|
|
203
|
-
r ||
|
|
211
|
+
r || a(null);
|
|
204
212
|
}).finally(() => {
|
|
205
213
|
r || c(!1);
|
|
206
214
|
}), () => {
|
|
207
215
|
r = !0;
|
|
208
216
|
};
|
|
209
217
|
}, [e, n]), {
|
|
210
|
-
url:
|
|
218
|
+
url: r,
|
|
211
219
|
isLoading: s
|
|
212
220
|
};
|
|
213
221
|
}
|
|
214
222
|
//#endregion
|
|
215
|
-
export {
|
|
223
|
+
export { S as useCaptureEpod, y as useEpod, C as useEpodPhotoUpload, w as useEpodPhotoUrl, b as useMyPendingEpodDeliveryJobs };
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { useMoveTheWheels as e } from "../providers/MoveTheWheelsProvider.js";
|
|
2
|
+
import { useCallback as t, useEffect as n, useMemo as r, useRef as i, useState as a } from "react";
|
|
3
|
+
import { print as o } from "graphql";
|
|
4
|
+
import { clearGraphqlFetchResponseCache as s, graphqlFetch as c } from "@burdenoff/fe-libs/shared/graphql";
|
|
5
|
+
//#region src/movethewheels/hooks/useShipmentStatusAuthority.ts
|
|
6
|
+
var l = new Set([
|
|
7
|
+
"STATUS_REVISION_CONFLICT",
|
|
8
|
+
"BAD_USER_INPUT",
|
|
9
|
+
"FORBIDDEN",
|
|
10
|
+
"UNAUTHENTICATED",
|
|
11
|
+
"NOT_FOUND"
|
|
12
|
+
]), u = class extends Error {
|
|
13
|
+
code;
|
|
14
|
+
constructor(e, t) {
|
|
15
|
+
super(e), this.code = t, this.name = "ShipmentStatusRequestError";
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
function d() {
|
|
19
|
+
let { apiGatewayUrl: n, authToken: i, workspaceToken: a, workspaceId: s, tenantId: l } = e(), d = r(() => ({
|
|
20
|
+
apiGatewayUrl: n,
|
|
21
|
+
authToken: i,
|
|
22
|
+
workspaceToken: a,
|
|
23
|
+
workspaceId: s,
|
|
24
|
+
tenantId: l
|
|
25
|
+
}), [
|
|
26
|
+
n,
|
|
27
|
+
i,
|
|
28
|
+
a,
|
|
29
|
+
s,
|
|
30
|
+
l
|
|
31
|
+
]);
|
|
32
|
+
return t(async (e, t, n = !1, r) => {
|
|
33
|
+
let i = await c({
|
|
34
|
+
gateway: "workspace",
|
|
35
|
+
query: o(e),
|
|
36
|
+
variables: t,
|
|
37
|
+
baseUrl: d.apiGatewayUrl,
|
|
38
|
+
authToken: d.authToken,
|
|
39
|
+
workspaceToken: d.workspaceToken || !0,
|
|
40
|
+
workspaceId: d.workspaceId || !0,
|
|
41
|
+
tenantId: d.tenantId || !0,
|
|
42
|
+
organizationId: !0,
|
|
43
|
+
signal: r,
|
|
44
|
+
skipAuthRetry: n
|
|
45
|
+
});
|
|
46
|
+
if (i.errors?.length) {
|
|
47
|
+
let e = i.errors[0], t = i.data === null && i.errors.length === 1 && typeof e?.extensions?.code == "string" ? e.extensions.code : null;
|
|
48
|
+
throw new u(e?.message ?? "Unable to load the recorded status.", t);
|
|
49
|
+
}
|
|
50
|
+
if (i.data == null) throw new u("No acknowledgement was received.", null);
|
|
51
|
+
return i.data;
|
|
52
|
+
}, [d]);
|
|
53
|
+
}
|
|
54
|
+
function f(e, t, r = 0) {
|
|
55
|
+
let i = d(), o = JSON.stringify(t), [c, l] = a(null);
|
|
56
|
+
n(() => {
|
|
57
|
+
let t = new AbortController(), n = {
|
|
58
|
+
request: i,
|
|
59
|
+
key: o,
|
|
60
|
+
revision: r
|
|
61
|
+
};
|
|
62
|
+
if (l({
|
|
63
|
+
...n,
|
|
64
|
+
data: null,
|
|
65
|
+
error: null,
|
|
66
|
+
loading: o !== "null"
|
|
67
|
+
}), o !== "null") return r > 0 && s(), i(e, JSON.parse(o), !1, t.signal).then((e) => {
|
|
68
|
+
t.signal.aborted || l({
|
|
69
|
+
...n,
|
|
70
|
+
data: e,
|
|
71
|
+
error: null,
|
|
72
|
+
loading: !1
|
|
73
|
+
});
|
|
74
|
+
}).catch((e) => {
|
|
75
|
+
t.signal.aborted || l({
|
|
76
|
+
...n,
|
|
77
|
+
data: null,
|
|
78
|
+
error: e instanceof Error ? e.message : "Unable to load recorded status.",
|
|
79
|
+
loading: !1
|
|
80
|
+
});
|
|
81
|
+
}), () => t.abort();
|
|
82
|
+
}, [
|
|
83
|
+
e,
|
|
84
|
+
i,
|
|
85
|
+
o,
|
|
86
|
+
r
|
|
87
|
+
]);
|
|
88
|
+
let u = c?.request === i && c.key === o && c.revision === r;
|
|
89
|
+
return {
|
|
90
|
+
data: u ? c.data : null,
|
|
91
|
+
error: u ? c.error : null,
|
|
92
|
+
loading: u ? c.loading : o !== "null"
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function p() {
|
|
96
|
+
let e = d(), t = i(!1), n = i(!1), [r, o] = a(!1), [s, c] = a(null), [f, p] = a(0);
|
|
97
|
+
return {
|
|
98
|
+
run: async (r, i, a) => {
|
|
99
|
+
if (t.current || n.current) return null;
|
|
100
|
+
t.current = !0, o(!0), c(null);
|
|
101
|
+
try {
|
|
102
|
+
let t = await e(r, i, !0);
|
|
103
|
+
if (!a(t)) throw new u("The returned acknowledgement does not identify this decision.", null);
|
|
104
|
+
return c({
|
|
105
|
+
kind: "APPLIED",
|
|
106
|
+
message: "Decision recorded. Review the refreshed status and history."
|
|
107
|
+
}), p((e) => e + 1), t;
|
|
108
|
+
} catch (e) {
|
|
109
|
+
let t = e instanceof u && e.code !== null && l.has(e.code);
|
|
110
|
+
return n.current = !t, c({
|
|
111
|
+
kind: t ? "REJECTED" : "UNKNOWN",
|
|
112
|
+
message: t ? `${e.message} Your input is preserved; refresh and review the recorded status before another action.` : "Acknowledgement is uncertain. Do not resend this action. Refresh the recorded status and review its decisions before beginning a separate new action."
|
|
113
|
+
}), null;
|
|
114
|
+
} finally {
|
|
115
|
+
t.current = !1, o(!1);
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
busy: r,
|
|
119
|
+
feedback: s,
|
|
120
|
+
revision: f,
|
|
121
|
+
beginSeparateAction: () => {
|
|
122
|
+
n.current = !1, c(null);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
export { p as useShipmentStatusCommand, f as useShipmentStatusQuery };
|
|
@@ -4,7 +4,7 @@ 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
5
|
import { useCallback as u, useEffect as d, useMemo as f, useState as p } from "react";
|
|
6
6
|
//#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 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";
|
|
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
8
|
function b(e) {
|
|
9
9
|
let t = e.location;
|
|
10
10
|
if (!t) return null;
|
|
@@ -16,21 +16,21 @@ function b(e) {
|
|
|
16
16
|
timestamp: new Date(e.timestamp)
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
|
-
function x(e, t) {
|
|
20
|
-
let
|
|
21
|
-
if (!
|
|
22
|
-
let
|
|
19
|
+
function x(e, t, n) {
|
|
20
|
+
let r = e[0];
|
|
21
|
+
if (!r) return null;
|
|
22
|
+
let i = e.map(b).filter((e) => e !== null), a = i[0];
|
|
23
23
|
return {
|
|
24
|
-
id:
|
|
24
|
+
id: r.id,
|
|
25
25
|
entityId: t,
|
|
26
26
|
entityType: "order",
|
|
27
|
-
currentLocation:
|
|
28
|
-
locationHistory:
|
|
29
|
-
status: n
|
|
27
|
+
currentLocation: a,
|
|
28
|
+
locationHistory: i,
|
|
29
|
+
status: n?.toLowerCase() ?? "unknown",
|
|
30
30
|
estimatedArrival: void 0,
|
|
31
|
-
nextCheckpoint:
|
|
31
|
+
nextCheckpoint: r.details ?? void 0,
|
|
32
32
|
alerts: [],
|
|
33
|
-
lastUpdated: new Date(
|
|
33
|
+
lastUpdated: new Date(r.timestamp)
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
function S() {
|
|
@@ -161,13 +161,14 @@ function D(e) {
|
|
|
161
161
|
}
|
|
162
162
|
D(!0), k(null);
|
|
163
163
|
try {
|
|
164
|
-
|
|
164
|
+
let e = await t(n, _, {
|
|
165
165
|
deliveryJobId: i,
|
|
166
166
|
pagination: {
|
|
167
167
|
limit: 50,
|
|
168
168
|
offset: 0
|
|
169
169
|
}
|
|
170
|
-
})
|
|
170
|
+
});
|
|
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));
|
|
171
172
|
} catch (e) {
|
|
172
173
|
k(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load order tracking"));
|
|
173
174
|
} finally {
|
|
@@ -237,7 +238,7 @@ function A() {
|
|
|
237
238
|
order: n(t),
|
|
238
239
|
driver: t.driver ? i(t.driver) : null,
|
|
239
240
|
vehicle: t.vehicle ? a(t.vehicle) : null,
|
|
240
|
-
tracking: x(e.trackingEvents ?? [], t.id),
|
|
241
|
+
tracking: x(e.trackingEvents ?? [], t.id, e.status),
|
|
241
242
|
estimatedArrival: e.estimatedDelivery ? new Date(e.estimatedDelivery) : void 0
|
|
242
243
|
} : null;
|
|
243
244
|
}).filter((e) => e !== null));
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import "../src/generated/tracking-quality-operations.js";
|
|
2
|
+
//#region src/movethewheels/hooks/useTrackingEventQuality.ts
|
|
3
|
+
var e = new Set([
|
|
4
|
+
"ACCEPTED",
|
|
5
|
+
"DUPLICATE",
|
|
6
|
+
"CONFLICT",
|
|
7
|
+
"REJECTED"
|
|
8
|
+
]), t = new Set([
|
|
9
|
+
"LEGACY_AUTHORITY",
|
|
10
|
+
"MANUAL_AUTHORITY",
|
|
11
|
+
"NON_DESIGNATED_SOURCE",
|
|
12
|
+
"UNKNOWN_SOURCE_TIME",
|
|
13
|
+
"OLDER_SOURCE_TIME",
|
|
14
|
+
"EQUAL_SOURCE_TIME",
|
|
15
|
+
"SOURCE_TIME_TOO_OLD",
|
|
16
|
+
"SOURCE_TIME_IN_FUTURE",
|
|
17
|
+
"UNMAPPED_EVENT_TYPE",
|
|
18
|
+
"UNRECEIPTED_EVIDENCE"
|
|
19
|
+
]), n = new Set([
|
|
20
|
+
"KEY_CONFLICT",
|
|
21
|
+
"BUDGET_EXHAUSTED",
|
|
22
|
+
"INTEGRATION_UNAVAILABLE",
|
|
23
|
+
"SHIPMENT_UNAVAILABLE",
|
|
24
|
+
"UPDATE_REJECTED"
|
|
25
|
+
]), r = (e, t) => typeof e == "string" && e.length <= t, i = (e, t) => e === null || r(e, t);
|
|
26
|
+
function a(a) {
|
|
27
|
+
if (!Array.isArray(a) || a.length > 5) return null;
|
|
28
|
+
let o = [];
|
|
29
|
+
for (let s of a) {
|
|
30
|
+
if (typeof s != "object" || !s || Array.isArray(s)) return null;
|
|
31
|
+
let a = s;
|
|
32
|
+
if (!Number.isInteger(a.index) || typeof a.index != "number" || a.index !== o.length || a.index < 0 || a.index > 4 || !i(a.externalEventId, 255) || !r(a.shipmentReference, 255) || !i(a.shipmentId, 255) || typeof a.status != "string" || !e.has(a.status) || a.status === "CONFLICT" && a.shipmentId !== null || !(a.errorCode === null || typeof a.errorCode == "string" && n.has(a.errorCode))) return null;
|
|
33
|
+
let c = null, l = a.projectionStatus, u = a.projectionDecisionId ?? null, d = a.projectionHeldReason ?? null;
|
|
34
|
+
if (l != null) {
|
|
35
|
+
if (a.status !== "ACCEPTED" && a.status !== "DUPLICATE") return null;
|
|
36
|
+
if (l === "LEGACY_NO_DECISION") {
|
|
37
|
+
if (a.status !== "DUPLICATE" || u !== null || d !== null) return null;
|
|
38
|
+
} else if (l === "APPLIED" || l === "HELD") {
|
|
39
|
+
if (!r(u, 255) || !u || (l === "APPLIED" ? d !== null : typeof d != "string" || !t.has(d))) return null;
|
|
40
|
+
} else return null;
|
|
41
|
+
c = {
|
|
42
|
+
status: l,
|
|
43
|
+
decisionId: u,
|
|
44
|
+
heldReason: d
|
|
45
|
+
};
|
|
46
|
+
} else if (u !== null || d !== null) return null;
|
|
47
|
+
o.push({
|
|
48
|
+
index: a.index,
|
|
49
|
+
externalEventId: a.externalEventId,
|
|
50
|
+
shipmentReference: a.shipmentReference,
|
|
51
|
+
shipmentId: a.shipmentId,
|
|
52
|
+
status: a.status,
|
|
53
|
+
errorCode: a.errorCode,
|
|
54
|
+
projection: c
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return o;
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
export { a as trackingOutcomes };
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import { Order, ProofOfDelivery, SignatureType } from '../types';
|
|
2
2
|
|
|
3
|
+
export interface ApiProofOfDelivery {
|
|
4
|
+
id: string;
|
|
5
|
+
deliveryJobId: string;
|
|
6
|
+
shipmentId?: string | null;
|
|
7
|
+
recipientName: string;
|
|
8
|
+
signatureType: 'DRAWN' | 'TYPED';
|
|
9
|
+
signatureData: string;
|
|
10
|
+
photoFileIds?: string[] | null;
|
|
11
|
+
latitude?: number | null;
|
|
12
|
+
longitude?: number | null;
|
|
13
|
+
locationAccuracy?: number | null;
|
|
14
|
+
deliveredAt: string;
|
|
15
|
+
capturedByDriverId: string;
|
|
16
|
+
notes?: string | null;
|
|
17
|
+
}
|
|
3
18
|
/** The shipper/customer-facing view: the completed ePOD record for a delivery job (or null if not yet captured). */
|
|
4
19
|
export declare function useEpod(deliveryJobId: string | undefined): {
|
|
5
20
|
epod: ProofOfDelivery | null;
|
|
@@ -30,6 +45,9 @@ export declare function useMyPendingEpodDeliveryJobs(options?: {
|
|
|
30
45
|
refetch: () => Promise<void>;
|
|
31
46
|
};
|
|
32
47
|
export interface CaptureEpodArgs {
|
|
48
|
+
expectedShipmentId: string | null;
|
|
49
|
+
expectedShipmentStatusRevision?: number;
|
|
50
|
+
completionAttestation: boolean;
|
|
33
51
|
deliveryJobId: string;
|
|
34
52
|
recipientName: string;
|
|
35
53
|
signatureType: SignatureType;
|
|
@@ -40,11 +58,16 @@ export interface CaptureEpodArgs {
|
|
|
40
58
|
locationAccuracy?: number;
|
|
41
59
|
notes?: string;
|
|
42
60
|
}
|
|
61
|
+
export declare function epodAcknowledged(actual: ApiProofOfDelivery | null | undefined, expected: CaptureEpodArgs): boolean;
|
|
43
62
|
/** Driver-facing capture mutation. Identity/ownership is enforced server-side — this never sends a driver id. */
|
|
44
63
|
export declare function useCaptureEpod(): {
|
|
45
64
|
captureEpod: (args: CaptureEpodArgs) => Promise<ProofOfDelivery>;
|
|
46
65
|
isSubmitting: boolean;
|
|
47
66
|
error: Error | null;
|
|
67
|
+
captureFeedback: {
|
|
68
|
+
kind: "APPLIED" | "REJECTED" | "UNKNOWN";
|
|
69
|
+
message: string;
|
|
70
|
+
} | null;
|
|
48
71
|
};
|
|
49
72
|
export interface UploadedEpodPhoto {
|
|
50
73
|
fileId: string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DocumentNode } from 'graphql';
|
|
2
|
+
|
|
3
|
+
export declare class ShipmentStatusRequestError extends Error {
|
|
4
|
+
readonly code: string | null;
|
|
5
|
+
constructor(message: string, code: string | null);
|
|
6
|
+
}
|
|
7
|
+
/** Normal shared gateway transport; mutation acknowledgements are never automatically retried. */
|
|
8
|
+
export declare function useShipmentStatusApi(): <T>(document: DocumentNode, variables: Record<string, unknown>, mutation?: boolean, signal?: AbortSignal) => Promise<T>;
|
|
9
|
+
export declare function useShipmentStatusQuery<T>(document: DocumentNode, variables: Record<string, unknown> | null, revision?: number): {
|
|
10
|
+
data: T | null;
|
|
11
|
+
error: string | null;
|
|
12
|
+
loading: boolean;
|
|
13
|
+
};
|
|
14
|
+
export declare function useShipmentStatusCommand(): {
|
|
15
|
+
run: <T>(document: DocumentNode, variables: Record<string, unknown>, acknowledged: (result: T) => boolean) => Promise<T | null>;
|
|
16
|
+
busy: boolean;
|
|
17
|
+
feedback: {
|
|
18
|
+
kind: "APPLIED" | "REJECTED" | "UNKNOWN";
|
|
19
|
+
message: string;
|
|
20
|
+
} | null;
|
|
21
|
+
revision: number;
|
|
22
|
+
beginSeparateAction: () => void;
|
|
23
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { TrackingQualityIntegrationsDocument, TrackingQualityDeliveriesDocument, TrackingQualityShipmentDocument } from '../../generated/tracking-quality-operations';
|
|
2
|
+
|
|
3
|
+
export { TrackingQualityIntegrationsDocument as QualityIntegrationsDocument, TrackingQualityDeliveriesDocument as QualityDeliveriesDocument, TrackingQualityShipmentDocument as QualityShipmentDocument, };
|
|
4
|
+
export interface TrackingUpdateOutcome {
|
|
5
|
+
index: number;
|
|
6
|
+
externalEventId: string | null;
|
|
7
|
+
shipmentReference: string;
|
|
8
|
+
shipmentId: string | null;
|
|
9
|
+
status: 'ACCEPTED' | 'DUPLICATE' | 'CONFLICT' | 'REJECTED';
|
|
10
|
+
errorCode: string | null;
|
|
11
|
+
projection: {
|
|
12
|
+
status: 'APPLIED' | 'HELD' | 'LEGACY_NO_DECISION';
|
|
13
|
+
decisionId: string | null;
|
|
14
|
+
heldReason: string | null;
|
|
15
|
+
} | null;
|
|
16
|
+
}
|
|
17
|
+
/** JSON scalar decoding fails closed; legacy delivery history has no outcomes. */
|
|
18
|
+
export declare function trackingOutcomes(value: unknown): TrackingUpdateOutcome[] | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function ShipmentStatusAuthorityPage(): import("react").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function TrackingEventQualityPage(): import("react").JSX.Element;
|