@burdenoff/microfe-movethewheels 2026.1011.1 → 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 +5 -0
- package/dist/MoveTheWheelsRoutes.js +54 -50
- package/dist/generated/shipment-status-authority-operations.d.ts +4473 -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 +43 -17
- 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 +5 -0
- package/dist/movethewheels/pages/ShipmentStatusAuthorityPage.d.ts +1 -0
- package/dist/movethewheels/utils/shipmentStatusDraft.d.ts +45 -0
- package/dist/pages/DeliveryCapturePage.js +181 -116
- package/dist/pages/ShipmentStatusAuthorityPage.js +563 -0
- package/dist/pages/TrackingEventQualityPage.js +6 -1
- package/dist/src/generated/shipment-status-authority-operations.js +86 -0
- package/dist/utils/shipmentStatusDraft.js +41 -0
- package/package.json +5 -4
- package/src/generated/shipment-status-authority-operations.ts +5503 -0
- package/src/movethewheels/MoveTheWheelsRoot.tsx +6 -0
- package/src/movethewheels/MoveTheWheelsRoutes.tsx +2 -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 +42 -0
- package/src/movethewheels/pages/DeliveryCapturePage.tsx +113 -6
- package/src/movethewheels/pages/ShipmentStatusAuthorityPage.tsx +639 -0
- package/src/movethewheels/pages/TrackingEventQualityPage.tsx +13 -2
- package/src/movethewheels/utils/shipmentStatusDraft.ts +118 -0
- package/src/operations/shipment-status-authority/status.graphql +80 -0
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
import { ClipboardList as e } from "../node_modules/lucide-react/dist/esm/icons/clipboard-list.js";
|
|
2
|
+
import { useMoveTheWheels as t } from "../providers/MoveTheWheelsProvider.js";
|
|
3
|
+
import { useShipmentStatusCommand as n, useShipmentStatusQuery as r } from "../hooks/useShipmentStatusAuthority.js";
|
|
4
|
+
import { Button as i, Input as a, Label as o, Textarea as s } from "../components/ui.js";
|
|
5
|
+
import { PageLayout as c } from "../components/PageLayout.js";
|
|
6
|
+
import { ReuseState as l, reuseCard as u } from "../components/ReuseControls.js";
|
|
7
|
+
import { StatusAuthorityConfigureDocument as d, StatusAuthorityDetailDocument as f, StatusAuthorityManualDocument as p, StatusAuthorityShipmentsDocument as m, StatusAuthoritySourcesDocument as h } from "../src/generated/shipment-status-authority-operations.js";
|
|
8
|
+
import { manualStatusAcknowledged as ee, shipmentSourceInput as te, sourceStatusAcknowledged as ne, statusDecisionReason as re } from "../utils/shipmentStatusDraft.js";
|
|
9
|
+
import { useState as g } from "react";
|
|
10
|
+
import { jsx as _, jsxs as v } from "react/jsx-runtime";
|
|
11
|
+
import { PermissionProvider as y, usePermissions as b } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
12
|
+
//#region src/movethewheels/pages/ShipmentStatusAuthorityPage.tsx
|
|
13
|
+
var x = 20, S = [
|
|
14
|
+
"PLANNED",
|
|
15
|
+
"PICKED_UP",
|
|
16
|
+
"IN_TRANSIT",
|
|
17
|
+
"DELIVERED",
|
|
18
|
+
"FAILED",
|
|
19
|
+
"RETURNED"
|
|
20
|
+
], C = {
|
|
21
|
+
integrationId: "",
|
|
22
|
+
basisTrackingEventId: "",
|
|
23
|
+
maxSourceAgeSeconds: "",
|
|
24
|
+
maxFutureSkewSeconds: "",
|
|
25
|
+
reason: ""
|
|
26
|
+
};
|
|
27
|
+
function w(e) {
|
|
28
|
+
return e ? e.toLowerCase().replaceAll("_", " ") : "Not recorded";
|
|
29
|
+
}
|
|
30
|
+
function T(e) {
|
|
31
|
+
if (!e) return "Not recorded";
|
|
32
|
+
let t = new Date(e);
|
|
33
|
+
return Number.isFinite(t.getTime()) ? t.toLocaleString() : "Unverified time";
|
|
34
|
+
}
|
|
35
|
+
function E({ offset: e, length: t, busy: n, change: r }) {
|
|
36
|
+
return /* @__PURE__ */ v("div", {
|
|
37
|
+
className: "flex flex-wrap items-center gap-3",
|
|
38
|
+
children: [
|
|
39
|
+
/* @__PURE__ */ _(i, {
|
|
40
|
+
variant: "outline",
|
|
41
|
+
disabled: n || e === 0,
|
|
42
|
+
onClick: () => r(Math.max(0, e - x)),
|
|
43
|
+
children: "Previous page"
|
|
44
|
+
}),
|
|
45
|
+
/* @__PURE__ */ _("span", { children: t === void 0 ? "Page unavailable" : `${t} records on this page` }),
|
|
46
|
+
/* @__PURE__ */ _(i, {
|
|
47
|
+
variant: "outline",
|
|
48
|
+
disabled: n || t !== x || e >= 9980,
|
|
49
|
+
onClick: () => r(e + x),
|
|
50
|
+
children: "Next page"
|
|
51
|
+
})
|
|
52
|
+
]
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function D() {
|
|
56
|
+
let { workspaceId: n, tenantId: r, currentUser: i, apiGatewayUrl: a } = t();
|
|
57
|
+
return /* @__PURE__ */ _(c, {
|
|
58
|
+
title: "Shipment status authority",
|
|
59
|
+
subtitle: "Keep recorded status separate from incoming tracking evidence.",
|
|
60
|
+
icon: /* @__PURE__ */ _(e, { "aria-hidden": "true" }),
|
|
61
|
+
children: /* @__PURE__ */ _(y, {
|
|
62
|
+
scopeId: n ?? null,
|
|
63
|
+
gateway: "workspace",
|
|
64
|
+
children: /* @__PURE__ */ _(O, {}, `${n}:${r}:${i?.id}:${a}`)
|
|
65
|
+
})
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function O() {
|
|
69
|
+
let e = b(), [t, n] = g(0), [s, c] = g(""), [u, d] = g(""), [f, p] = g(""), h = r(m, e.hasPermission("shipment:read") ? {
|
|
70
|
+
filter: { search: f || void 0 },
|
|
71
|
+
pagination: {
|
|
72
|
+
limit: x,
|
|
73
|
+
offset: t
|
|
74
|
+
}
|
|
75
|
+
} : null);
|
|
76
|
+
return /* @__PURE__ */ v("div", {
|
|
77
|
+
className: "space-y-6",
|
|
78
|
+
children: [
|
|
79
|
+
/* @__PURE__ */ _("p", { children: "Incoming evidence can be accepted while its status change is held. A recorded software status is not physical proof of delivery." }),
|
|
80
|
+
/* @__PURE__ */ _(l, {
|
|
81
|
+
loading: e.isLoading,
|
|
82
|
+
error: e.error?.message ?? null
|
|
83
|
+
}),
|
|
84
|
+
!e.isLoading && !e.hasPermission("shipment:read") && /* @__PURE__ */ _("p", {
|
|
85
|
+
role: "status",
|
|
86
|
+
children: "Shipment read permission is required."
|
|
87
|
+
}),
|
|
88
|
+
e.hasPermission("shipment:read") && /* @__PURE__ */ v("section", {
|
|
89
|
+
className: "space-y-4 rounded-xl border bg-bg-surface p-5",
|
|
90
|
+
"aria-label": "Shipment selection",
|
|
91
|
+
children: [
|
|
92
|
+
/* @__PURE__ */ v("form", {
|
|
93
|
+
className: "flex flex-wrap gap-3",
|
|
94
|
+
onSubmit: (e) => {
|
|
95
|
+
e.preventDefault(), p(u.trim()), n(0), c("");
|
|
96
|
+
},
|
|
97
|
+
children: [
|
|
98
|
+
/* @__PURE__ */ _(o, {
|
|
99
|
+
htmlFor: "status-search",
|
|
100
|
+
children: "Shipment search"
|
|
101
|
+
}),
|
|
102
|
+
/* @__PURE__ */ _(a, {
|
|
103
|
+
id: "status-search",
|
|
104
|
+
value: u,
|
|
105
|
+
onChange: (e) => d(e.target.value),
|
|
106
|
+
maxLength: 200
|
|
107
|
+
}),
|
|
108
|
+
/* @__PURE__ */ _(i, {
|
|
109
|
+
type: "submit",
|
|
110
|
+
children: "Search shipments"
|
|
111
|
+
})
|
|
112
|
+
]
|
|
113
|
+
}),
|
|
114
|
+
/* @__PURE__ */ _(l, {
|
|
115
|
+
loading: h.loading,
|
|
116
|
+
error: h.error
|
|
117
|
+
}),
|
|
118
|
+
/* @__PURE__ */ v("label", {
|
|
119
|
+
className: "block",
|
|
120
|
+
children: ["Shipment", /* @__PURE__ */ v("select", {
|
|
121
|
+
className: "mt-1 w-full rounded-md border bg-bg-surface p-2 text-sm",
|
|
122
|
+
value: s,
|
|
123
|
+
disabled: h.loading || !h.data,
|
|
124
|
+
onChange: (e) => c(e.target.value),
|
|
125
|
+
children: [/* @__PURE__ */ _("option", {
|
|
126
|
+
value: "",
|
|
127
|
+
children: "Choose a shipment"
|
|
128
|
+
}), h.data?.shipments.map((e) => /* @__PURE__ */ v("option", {
|
|
129
|
+
value: e.id,
|
|
130
|
+
children: [
|
|
131
|
+
e.shipmentNumber,
|
|
132
|
+
" · ",
|
|
133
|
+
w(e.status)
|
|
134
|
+
]
|
|
135
|
+
}, e.id))]
|
|
136
|
+
})]
|
|
137
|
+
}),
|
|
138
|
+
h.data?.shipments.length === 0 && /* @__PURE__ */ _("p", { children: "No shipments on this page." }),
|
|
139
|
+
/* @__PURE__ */ _(E, {
|
|
140
|
+
offset: t,
|
|
141
|
+
length: h.data?.shipments.length,
|
|
142
|
+
busy: h.loading,
|
|
143
|
+
change: (e) => {
|
|
144
|
+
n(e), c("");
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
]
|
|
148
|
+
}),
|
|
149
|
+
s && e.hasPermission("shipment:read") && /* @__PURE__ */ _(k, {
|
|
150
|
+
id: s,
|
|
151
|
+
canUpdate: e.hasPermission("shipment:update"),
|
|
152
|
+
canReadSources: e.hasPermission("integration:read")
|
|
153
|
+
}, s)
|
|
154
|
+
]
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
function k({ id: e, canUpdate: t, canReadSources: c }) {
|
|
158
|
+
let [m, y] = g(0), [b, D] = g(0), [O, k] = g(0), [A, ie] = g(0), j = n(), M = r(f, {
|
|
159
|
+
id: e,
|
|
160
|
+
pagination: {
|
|
161
|
+
limit: x,
|
|
162
|
+
offset: b
|
|
163
|
+
},
|
|
164
|
+
evidencePagination: {
|
|
165
|
+
limit: x,
|
|
166
|
+
offset: A
|
|
167
|
+
}
|
|
168
|
+
}, m + j.revision), N = r(h, t && c ? { pagination: {
|
|
169
|
+
limit: x,
|
|
170
|
+
offset: O
|
|
171
|
+
} } : null), P = M.data?.shipment, [F, I] = g(C), [L, R] = g(""), [z, B] = g(""), [V, H] = g(null), [U, W] = g(null), [G, K] = g(!1), [ae, q] = g(0), J = m >= ae && !!P && !M.loading && !M.error, Y = V !== null && P != null && V !== P.statusRevision, X = j.feedback?.kind === "UNKNOWN", Z = j.busy || M.loading || !P || V === null || Y || X || !J, Q = P?.trackingEvents.filter((e) => e.sourceIntegrationId === F.integrationId && e.sourceTimestampProvenance === "PROVIDER_TIME_VALIDATED" && e.providerEventTime && e.eventType !== "CREATED") ?? [], $ = (e, t) => I((n) => ({
|
|
172
|
+
...n,
|
|
173
|
+
[e]: t
|
|
174
|
+
}));
|
|
175
|
+
return /* @__PURE__ */ v("div", {
|
|
176
|
+
className: "space-y-6",
|
|
177
|
+
children: [
|
|
178
|
+
/* @__PURE__ */ v("section", {
|
|
179
|
+
className: u,
|
|
180
|
+
"aria-label": "Recorded shipment status",
|
|
181
|
+
children: [
|
|
182
|
+
/* @__PURE__ */ v("div", {
|
|
183
|
+
className: "flex flex-wrap justify-between gap-3",
|
|
184
|
+
children: [/* @__PURE__ */ _("h2", {
|
|
185
|
+
className: "font-semibold",
|
|
186
|
+
children: "Recorded status"
|
|
187
|
+
}), /* @__PURE__ */ _(i, {
|
|
188
|
+
variant: "outline",
|
|
189
|
+
disabled: M.loading || j.busy,
|
|
190
|
+
onClick: () => {
|
|
191
|
+
K(!1), y((e) => e + 1);
|
|
192
|
+
},
|
|
193
|
+
children: "Refresh recorded status"
|
|
194
|
+
})]
|
|
195
|
+
}),
|
|
196
|
+
/* @__PURE__ */ _(l, {
|
|
197
|
+
loading: M.loading,
|
|
198
|
+
error: M.error
|
|
199
|
+
}),
|
|
200
|
+
P === null && /* @__PURE__ */ _("p", { children: "Shipment unavailable in this workspace." }),
|
|
201
|
+
P && /* @__PURE__ */ v("dl", {
|
|
202
|
+
className: "grid gap-3 sm:grid-cols-2 break-words",
|
|
203
|
+
children: [
|
|
204
|
+
/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("dt", { children: "Shipment" }), /* @__PURE__ */ _("dd", { children: P.shipmentNumber })] }),
|
|
205
|
+
/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("dt", { children: "Status" }), /* @__PURE__ */ _("dd", { children: w(P.status) })] }),
|
|
206
|
+
/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("dt", { children: "Status revision" }), /* @__PURE__ */ _("dd", { children: P.statusRevision })] }),
|
|
207
|
+
/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("dt", { children: "Authority" }), /* @__PURE__ */ _("dd", { children: w(P.statusAuthority) })] }),
|
|
208
|
+
/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("dt", { children: "Chosen integration" }), /* @__PURE__ */ _("dd", {
|
|
209
|
+
className: "break-all",
|
|
210
|
+
children: P.designatedIntegrationId ?? "None selected"
|
|
211
|
+
})] }),
|
|
212
|
+
/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("dt", { children: "Basis source time" }), /* @__PURE__ */ _("dd", { children: T(P.statusBasisSourceTime) })] }),
|
|
213
|
+
/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("dt", { children: "Maximum source age" }), /* @__PURE__ */ _("dd", { children: P.maxSourceAgeSeconds === null ? "No active source policy" : `${P.maxSourceAgeSeconds} seconds` })] }),
|
|
214
|
+
/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("dt", { children: "Allowed future skew" }), /* @__PURE__ */ _("dd", { children: P.maxFutureSkewSeconds === null ? "No active source policy" : `${P.maxFutureSkewSeconds} seconds` })] })
|
|
215
|
+
]
|
|
216
|
+
})
|
|
217
|
+
]
|
|
218
|
+
}),
|
|
219
|
+
j.feedback && /* @__PURE__ */ _("p", {
|
|
220
|
+
role: "status",
|
|
221
|
+
children: j.feedback.message
|
|
222
|
+
}),
|
|
223
|
+
U && /* @__PURE__ */ _("p", {
|
|
224
|
+
role: "alert",
|
|
225
|
+
children: U
|
|
226
|
+
}),
|
|
227
|
+
!t && /* @__PURE__ */ _("p", {
|
|
228
|
+
role: "status",
|
|
229
|
+
children: "Read-only access. Shipment update permission is required to choose a source or record a correction."
|
|
230
|
+
}),
|
|
231
|
+
t && /* @__PURE__ */ v("section", {
|
|
232
|
+
className: "space-y-4 rounded-xl border bg-bg-surface p-5",
|
|
233
|
+
"aria-label": "Status decisions",
|
|
234
|
+
children: [
|
|
235
|
+
/* @__PURE__ */ _("p", { children: "Review the current status, then explicitly use its revision for a new decision. Clock limits are your policy, not carrier certification." }),
|
|
236
|
+
Y && /* @__PURE__ */ _("p", {
|
|
237
|
+
role: "alert",
|
|
238
|
+
children: "Status changed since this form opened. Your input is preserved. Review the current recorded status before applying."
|
|
239
|
+
}),
|
|
240
|
+
!X && /* @__PURE__ */ v(i, {
|
|
241
|
+
variant: "outline",
|
|
242
|
+
disabled: !J || j.busy,
|
|
243
|
+
onClick: () => {
|
|
244
|
+
P && (H(P.statusRevision), W(null), j.beginSeparateAction());
|
|
245
|
+
},
|
|
246
|
+
children: ["Use reviewed revision ", P?.statusRevision ?? "—"]
|
|
247
|
+
}),
|
|
248
|
+
X && /* @__PURE__ */ v("div", {
|
|
249
|
+
className: "space-y-3",
|
|
250
|
+
children: [/* @__PURE__ */ v("label", {
|
|
251
|
+
className: "flex items-start gap-2",
|
|
252
|
+
children: [/* @__PURE__ */ _("input", {
|
|
253
|
+
type: "checkbox",
|
|
254
|
+
disabled: !J,
|
|
255
|
+
checked: G,
|
|
256
|
+
onChange: (e) => K(e.target.checked)
|
|
257
|
+
}), "I reviewed the refreshed recorded status and decision history."]
|
|
258
|
+
}), /* @__PURE__ */ _(i, {
|
|
259
|
+
variant: "outline",
|
|
260
|
+
disabled: !G || !J || j.busy,
|
|
261
|
+
onClick: () => {
|
|
262
|
+
P && (I(C), R(""), B(""), H(P.statusRevision), W(null), K(!1), j.beginSeparateAction());
|
|
263
|
+
},
|
|
264
|
+
children: "Begin a separate new action"
|
|
265
|
+
})]
|
|
266
|
+
}),
|
|
267
|
+
/* @__PURE__ */ _("form", {
|
|
268
|
+
className: "space-y-3",
|
|
269
|
+
onSubmit: async (t) => {
|
|
270
|
+
if (t.preventDefault(), W(null), !(Z || V === null || !P)) try {
|
|
271
|
+
let t = te(F, V);
|
|
272
|
+
await j.run(d, {
|
|
273
|
+
id: e,
|
|
274
|
+
input: t
|
|
275
|
+
}, (n) => ne(n.configureShipmentStatusSource, {
|
|
276
|
+
id: e,
|
|
277
|
+
epoch: P.statusAuthorityEpoch,
|
|
278
|
+
input: t,
|
|
279
|
+
basis: Q.find((e) => e.id === t.basisTrackingEventId)
|
|
280
|
+
})) ? H(null) : (K(!1), q(m + 1));
|
|
281
|
+
} catch (e) {
|
|
282
|
+
W(e instanceof Error ? e.message : "Review the source policy.");
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
children: /* @__PURE__ */ v("fieldset", {
|
|
286
|
+
disabled: Z || !c,
|
|
287
|
+
className: "space-y-3",
|
|
288
|
+
children: [
|
|
289
|
+
/* @__PURE__ */ _("legend", {
|
|
290
|
+
className: "font-semibold",
|
|
291
|
+
children: "Choose a status source"
|
|
292
|
+
}),
|
|
293
|
+
!c && /* @__PURE__ */ _("p", { children: "Integration read permission is required for source selection." }),
|
|
294
|
+
/* @__PURE__ */ _(l, {
|
|
295
|
+
loading: N.loading,
|
|
296
|
+
error: N.error
|
|
297
|
+
}),
|
|
298
|
+
/* @__PURE__ */ v("label", {
|
|
299
|
+
className: "block",
|
|
300
|
+
children: ["Integration", /* @__PURE__ */ v("select", {
|
|
301
|
+
className: "mt-1 w-full rounded-md border bg-bg-surface p-2 text-sm",
|
|
302
|
+
value: F.integrationId,
|
|
303
|
+
onChange: (e) => {
|
|
304
|
+
$("integrationId", e.target.value), $("basisTrackingEventId", "");
|
|
305
|
+
},
|
|
306
|
+
children: [/* @__PURE__ */ _("option", {
|
|
307
|
+
value: "",
|
|
308
|
+
children: "Choose an integration"
|
|
309
|
+
}), N.data?.integrations.filter((e) => e.status === "ACTIVE").map((e) => /* @__PURE__ */ v("option", {
|
|
310
|
+
value: e.id,
|
|
311
|
+
children: [
|
|
312
|
+
e.name,
|
|
313
|
+
" · ",
|
|
314
|
+
e.provider
|
|
315
|
+
]
|
|
316
|
+
}, e.id))]
|
|
317
|
+
})]
|
|
318
|
+
}),
|
|
319
|
+
/* @__PURE__ */ v("label", {
|
|
320
|
+
className: "block",
|
|
321
|
+
children: ["Recorded basis event", /* @__PURE__ */ v("select", {
|
|
322
|
+
className: "mt-1 w-full rounded-md border bg-bg-surface p-2 text-sm",
|
|
323
|
+
value: F.basisTrackingEventId,
|
|
324
|
+
onChange: (e) => $("basisTrackingEventId", e.target.value),
|
|
325
|
+
children: [/* @__PURE__ */ _("option", {
|
|
326
|
+
value: "",
|
|
327
|
+
children: "Choose an existing basis event"
|
|
328
|
+
}), Q.map((e) => /* @__PURE__ */ v("option", {
|
|
329
|
+
value: e.id,
|
|
330
|
+
children: [
|
|
331
|
+
w(e.eventType),
|
|
332
|
+
" · ",
|
|
333
|
+
T(e.providerEventTime),
|
|
334
|
+
" · ",
|
|
335
|
+
e.id
|
|
336
|
+
]
|
|
337
|
+
}, e.id))]
|
|
338
|
+
})]
|
|
339
|
+
}),
|
|
340
|
+
/* @__PURE__ */ _("p", { children: "This page lists evidence from the selected source with validated provider time. The server checks its recorded receipt, source and clock window before applying." }),
|
|
341
|
+
/* @__PURE__ */ _(o, {
|
|
342
|
+
htmlFor: "status-source-age",
|
|
343
|
+
children: "Maximum source age (seconds)"
|
|
344
|
+
}),
|
|
345
|
+
/* @__PURE__ */ _(a, {
|
|
346
|
+
id: "status-source-age",
|
|
347
|
+
inputMode: "numeric",
|
|
348
|
+
value: F.maxSourceAgeSeconds,
|
|
349
|
+
onChange: (e) => $("maxSourceAgeSeconds", e.target.value)
|
|
350
|
+
}),
|
|
351
|
+
/* @__PURE__ */ _(o, {
|
|
352
|
+
htmlFor: "status-source-skew",
|
|
353
|
+
children: "Allowed future skew (seconds)"
|
|
354
|
+
}),
|
|
355
|
+
/* @__PURE__ */ _(a, {
|
|
356
|
+
id: "status-source-skew",
|
|
357
|
+
inputMode: "numeric",
|
|
358
|
+
value: F.maxFutureSkewSeconds,
|
|
359
|
+
onChange: (e) => $("maxFutureSkewSeconds", e.target.value)
|
|
360
|
+
}),
|
|
361
|
+
/* @__PURE__ */ _(o, {
|
|
362
|
+
htmlFor: "status-source-reason",
|
|
363
|
+
children: "Source choice reason"
|
|
364
|
+
}),
|
|
365
|
+
/* @__PURE__ */ _(s, {
|
|
366
|
+
id: "status-source-reason",
|
|
367
|
+
maxLength: 1e3,
|
|
368
|
+
value: F.reason,
|
|
369
|
+
onChange: (e) => $("reason", e.target.value)
|
|
370
|
+
}),
|
|
371
|
+
/* @__PURE__ */ _(i, {
|
|
372
|
+
type: "submit",
|
|
373
|
+
children: "Apply source choice"
|
|
374
|
+
})
|
|
375
|
+
]
|
|
376
|
+
})
|
|
377
|
+
}),
|
|
378
|
+
c && /* @__PURE__ */ _(E, {
|
|
379
|
+
offset: O,
|
|
380
|
+
length: N.data?.integrations.length,
|
|
381
|
+
busy: N.loading || j.busy,
|
|
382
|
+
change: (e) => {
|
|
383
|
+
k(e), $("integrationId", ""), $("basisTrackingEventId", "");
|
|
384
|
+
}
|
|
385
|
+
}),
|
|
386
|
+
/* @__PURE__ */ _("form", {
|
|
387
|
+
className: "space-y-3",
|
|
388
|
+
onSubmit: async (t) => {
|
|
389
|
+
if (t.preventDefault(), W(null), !(Z || V === null || !P)) try {
|
|
390
|
+
if (!L) throw Error("Choose a recorded status for this correction.");
|
|
391
|
+
await j.run(p, {
|
|
392
|
+
id: e,
|
|
393
|
+
input: {
|
|
394
|
+
status: L,
|
|
395
|
+
expectedStatusRevision: V,
|
|
396
|
+
statusReason: re(z)
|
|
397
|
+
}
|
|
398
|
+
}, (t) => ee(t.updateShipment, {
|
|
399
|
+
id: e,
|
|
400
|
+
revision: V,
|
|
401
|
+
epoch: P.statusAuthorityEpoch,
|
|
402
|
+
status: L
|
|
403
|
+
})) ? H(null) : (K(!1), q(m + 1));
|
|
404
|
+
} catch (e) {
|
|
405
|
+
W(e instanceof Error ? e.message : "Review the correction.");
|
|
406
|
+
}
|
|
407
|
+
},
|
|
408
|
+
children: /* @__PURE__ */ v("fieldset", {
|
|
409
|
+
disabled: Z,
|
|
410
|
+
className: "space-y-3",
|
|
411
|
+
children: [
|
|
412
|
+
/* @__PURE__ */ _("legend", {
|
|
413
|
+
className: "font-semibold",
|
|
414
|
+
children: "Record a manual correction"
|
|
415
|
+
}),
|
|
416
|
+
/* @__PURE__ */ _("p", { children: "A manual correction puts automatic tracking projection on hold. Existing evidence remains unchanged." }),
|
|
417
|
+
/* @__PURE__ */ v("label", {
|
|
418
|
+
className: "block",
|
|
419
|
+
children: ["Recorded status", /* @__PURE__ */ v("select", {
|
|
420
|
+
className: "mt-1 w-full rounded-md border bg-bg-surface p-2 text-sm",
|
|
421
|
+
value: L,
|
|
422
|
+
onChange: (e) => {
|
|
423
|
+
R(S.find((t) => t === e.target.value) ?? "");
|
|
424
|
+
},
|
|
425
|
+
children: [/* @__PURE__ */ _("option", {
|
|
426
|
+
value: "",
|
|
427
|
+
children: "Choose a status"
|
|
428
|
+
}), S.map((e) => /* @__PURE__ */ _("option", {
|
|
429
|
+
value: e,
|
|
430
|
+
children: w(e)
|
|
431
|
+
}, e))]
|
|
432
|
+
})]
|
|
433
|
+
}),
|
|
434
|
+
/* @__PURE__ */ _(o, {
|
|
435
|
+
htmlFor: "status-manual-reason",
|
|
436
|
+
children: "Correction reason"
|
|
437
|
+
}),
|
|
438
|
+
/* @__PURE__ */ _(s, {
|
|
439
|
+
id: "status-manual-reason",
|
|
440
|
+
value: z,
|
|
441
|
+
maxLength: 1e3,
|
|
442
|
+
onChange: (e) => B(e.target.value)
|
|
443
|
+
}),
|
|
444
|
+
/* @__PURE__ */ _(i, {
|
|
445
|
+
type: "submit",
|
|
446
|
+
children: "Record correction and hold"
|
|
447
|
+
})
|
|
448
|
+
]
|
|
449
|
+
})
|
|
450
|
+
})
|
|
451
|
+
]
|
|
452
|
+
}),
|
|
453
|
+
/* @__PURE__ */ v("section", {
|
|
454
|
+
className: u,
|
|
455
|
+
"aria-label": "Shipment status decision history",
|
|
456
|
+
children: [
|
|
457
|
+
/* @__PURE__ */ _("h2", {
|
|
458
|
+
className: "font-semibold",
|
|
459
|
+
children: "Decision history"
|
|
460
|
+
}),
|
|
461
|
+
M.data?.shipmentStatusDecisions.length === 0 && /* @__PURE__ */ _("p", { children: "No recorded status decisions on this page. Legacy evidence may have no decision ledger." }),
|
|
462
|
+
/* @__PURE__ */ _("div", {
|
|
463
|
+
className: "space-y-3",
|
|
464
|
+
children: M.data?.shipmentStatusDecisions.map((e) => /* @__PURE__ */ v("article", {
|
|
465
|
+
className: "border rounded-md p-3 break-words",
|
|
466
|
+
children: [
|
|
467
|
+
/* @__PURE__ */ v("p", { children: [
|
|
468
|
+
w(e.origin),
|
|
469
|
+
" · ",
|
|
470
|
+
w(e.outcome),
|
|
471
|
+
e.heldReason ? `: ${w(e.heldReason)}` : ""
|
|
472
|
+
] }),
|
|
473
|
+
/* @__PURE__ */ v("p", { children: [
|
|
474
|
+
w(e.priorStatus),
|
|
475
|
+
" → ",
|
|
476
|
+
w(e.resultStatus),
|
|
477
|
+
" · revision",
|
|
478
|
+
" ",
|
|
479
|
+
e.observedRevision,
|
|
480
|
+
" → ",
|
|
481
|
+
e.resultRevision
|
|
482
|
+
] }),
|
|
483
|
+
/* @__PURE__ */ _("p", { children: T(e.recordedAt) }),
|
|
484
|
+
e.reason && /* @__PURE__ */ _("p", { children: e.reason }),
|
|
485
|
+
e.trackingEventId && /* @__PURE__ */ v("p", {
|
|
486
|
+
className: "break-all",
|
|
487
|
+
children: ["Evidence: ", e.trackingEventId]
|
|
488
|
+
}),
|
|
489
|
+
e.proofId && /* @__PURE__ */ v("p", {
|
|
490
|
+
className: "break-all",
|
|
491
|
+
children: ["Delivery proof: ", e.proofId]
|
|
492
|
+
}),
|
|
493
|
+
e.configuredIntegrationId && /* @__PURE__ */ v("p", {
|
|
494
|
+
className: "break-all",
|
|
495
|
+
children: ["Chosen integration for this decision: ", e.configuredIntegrationId]
|
|
496
|
+
}),
|
|
497
|
+
e.configuredMaxSourceAgeSeconds !== null && /* @__PURE__ */ v("p", { children: [
|
|
498
|
+
"Source age limit for this decision: ",
|
|
499
|
+
e.configuredMaxSourceAgeSeconds,
|
|
500
|
+
" ",
|
|
501
|
+
"seconds"
|
|
502
|
+
] }),
|
|
503
|
+
e.configuredMaxFutureSkewSeconds !== null && /* @__PURE__ */ v("p", { children: [
|
|
504
|
+
"Future skew limit for this decision: ",
|
|
505
|
+
e.configuredMaxFutureSkewSeconds,
|
|
506
|
+
" ",
|
|
507
|
+
"seconds"
|
|
508
|
+
] })
|
|
509
|
+
]
|
|
510
|
+
}, e.id))
|
|
511
|
+
}),
|
|
512
|
+
/* @__PURE__ */ _(E, {
|
|
513
|
+
offset: b,
|
|
514
|
+
length: M.data?.shipmentStatusDecisions.length,
|
|
515
|
+
busy: M.loading || j.busy,
|
|
516
|
+
change: (e) => {
|
|
517
|
+
D(e);
|
|
518
|
+
}
|
|
519
|
+
})
|
|
520
|
+
]
|
|
521
|
+
}),
|
|
522
|
+
/* @__PURE__ */ v("section", {
|
|
523
|
+
className: u,
|
|
524
|
+
"aria-label": "Recorded tracking evidence",
|
|
525
|
+
children: [
|
|
526
|
+
/* @__PURE__ */ _("h2", {
|
|
527
|
+
className: "font-semibold",
|
|
528
|
+
children: "Tracking evidence"
|
|
529
|
+
}),
|
|
530
|
+
/* @__PURE__ */ _("div", {
|
|
531
|
+
className: "space-y-3",
|
|
532
|
+
children: P?.trackingEvents.map((e) => /* @__PURE__ */ v("article", {
|
|
533
|
+
className: "border rounded-md p-3 break-words",
|
|
534
|
+
children: [
|
|
535
|
+
/* @__PURE__ */ v("p", { children: [
|
|
536
|
+
w(e.eventType),
|
|
537
|
+
" · ",
|
|
538
|
+
w(e.sourceTimestampProvenance)
|
|
539
|
+
] }),
|
|
540
|
+
/* @__PURE__ */ v("p", { children: ["Provider time: ", T(e.providerEventTime)] }),
|
|
541
|
+
/* @__PURE__ */ v("p", { children: ["Received: ", T(e.serverReceivedAt)] }),
|
|
542
|
+
/* @__PURE__ */ v("p", {
|
|
543
|
+
className: "break-all",
|
|
544
|
+
children: ["Evidence: ", e.id]
|
|
545
|
+
})
|
|
546
|
+
]
|
|
547
|
+
}, e.id))
|
|
548
|
+
}),
|
|
549
|
+
/* @__PURE__ */ _(E, {
|
|
550
|
+
offset: A,
|
|
551
|
+
length: P?.trackingEvents.length,
|
|
552
|
+
busy: M.loading || j.busy,
|
|
553
|
+
change: (e) => {
|
|
554
|
+
ie(e), $("basisTrackingEventId", "");
|
|
555
|
+
}
|
|
556
|
+
})
|
|
557
|
+
]
|
|
558
|
+
})
|
|
559
|
+
]
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
//#endregion
|
|
563
|
+
export { D as default };
|
|
@@ -148,6 +148,11 @@ function y() {
|
|
|
148
148
|
/* @__PURE__ */ h("p", { children: ["Event key: ", e.externalEventId ?? "Missing — not deduplicated"] }),
|
|
149
149
|
/* @__PURE__ */ h("p", { children: ["Shipment reference: ", e.shipmentReference || "Not recorded"] }),
|
|
150
150
|
e.errorCode && /* @__PURE__ */ h("p", { children: ["Reason: ", e.errorCode.replaceAll("_", " ").toLowerCase()] }),
|
|
151
|
+
(e.status === "ACCEPTED" || e.status === "DUPLICATE") && /* @__PURE__ */ h("p", { children: [
|
|
152
|
+
"Status decision:",
|
|
153
|
+
" ",
|
|
154
|
+
e.projection?.status === "APPLIED" ? "Applied to the recorded shipment status" : e.projection?.status === "HELD" ? `Held — ${e.projection.heldReason?.replaceAll("_", " ").toLowerCase()}` : "No status decision recorded in this legacy result"
|
|
155
|
+
] }),
|
|
151
156
|
e.status === "CONFLICT" && /* @__PURE__ */ m("p", { children: "The earlier receipt stays unchanged; this update adds no event." }),
|
|
152
157
|
e.shipmentId && /* @__PURE__ */ m(n, {
|
|
153
158
|
variant: "outline",
|
|
@@ -173,7 +178,7 @@ function y() {
|
|
|
173
178
|
}, S),
|
|
174
179
|
/* @__PURE__ */ m("p", {
|
|
175
180
|
className: "text-sm text-text-secondary",
|
|
176
|
-
children: "These results describe recorded ingestion, not physical shipment truth.
|
|
181
|
+
children: "These results describe recorded ingestion, not physical shipment truth. The chosen-source clock policy and manual corrections control recorded shipment status. Provider corrections and replay need separate reviewed policies."
|
|
177
182
|
})
|
|
178
183
|
]
|
|
179
184
|
});
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { gql as e } from "@apollo/client";
|
|
2
|
+
//#region src/generated/shipment-status-authority-operations.ts
|
|
3
|
+
var t = e`
|
|
4
|
+
fragment ShipmentStatusAuthorityFields on MtwShipment {
|
|
5
|
+
id
|
|
6
|
+
shipmentNumber
|
|
7
|
+
status
|
|
8
|
+
statusRevision
|
|
9
|
+
statusAuthority
|
|
10
|
+
statusAuthorityEpoch
|
|
11
|
+
designatedIntegrationId
|
|
12
|
+
statusBasisEventId
|
|
13
|
+
statusBasisSourceTime
|
|
14
|
+
maxSourceAgeSeconds
|
|
15
|
+
maxFutureSkewSeconds
|
|
16
|
+
}
|
|
17
|
+
`, n = e`
|
|
18
|
+
query StatusAuthorityShipments($filter: ShipmentFilterInput, $pagination: PaginationInput!) {
|
|
19
|
+
shipments(filter: $filter, pagination: $pagination) {
|
|
20
|
+
...ShipmentStatusAuthorityFields
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
${t}`, r = e`
|
|
24
|
+
query StatusAuthorityDetail($id: ID!, $pagination: PaginationInput!, $evidencePagination: PaginationInput!) {
|
|
25
|
+
shipment(id: $id) {
|
|
26
|
+
...ShipmentStatusAuthorityFields
|
|
27
|
+
trackingEvents(pagination: $evidencePagination) {
|
|
28
|
+
id
|
|
29
|
+
eventType
|
|
30
|
+
sourceIntegrationId
|
|
31
|
+
sourceTimestampProvenance
|
|
32
|
+
providerEventTime
|
|
33
|
+
serverReceivedAt
|
|
34
|
+
timestamp
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
shipmentStatusDecisions(shipmentId: $id, pagination: $pagination) {
|
|
38
|
+
id
|
|
39
|
+
origin
|
|
40
|
+
outcome
|
|
41
|
+
heldReason
|
|
42
|
+
observedRevision
|
|
43
|
+
resultRevision
|
|
44
|
+
priorStatus
|
|
45
|
+
resultStatus
|
|
46
|
+
trackingEventId
|
|
47
|
+
proofId
|
|
48
|
+
reason
|
|
49
|
+
recordedAt
|
|
50
|
+
configuredIntegrationId
|
|
51
|
+
configuredMaxSourceAgeSeconds
|
|
52
|
+
configuredMaxFutureSkewSeconds
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
${t}`, i = e`
|
|
56
|
+
query StatusAuthoritySources($pagination: PaginationInput!) {
|
|
57
|
+
integrations(pagination: $pagination) {
|
|
58
|
+
id
|
|
59
|
+
name
|
|
60
|
+
provider
|
|
61
|
+
status
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
`, a = e`
|
|
65
|
+
mutation StatusAuthorityConfigure($id: ID!, $input: ConfigureShipmentStatusSourceInput!) {
|
|
66
|
+
configureShipmentStatusSource(id: $id, input: $input) {
|
|
67
|
+
...ShipmentStatusAuthorityFields
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
${t}`, o = e`
|
|
71
|
+
mutation StatusAuthorityManual($id: ID!, $input: UpdateShipmentInput!) {
|
|
72
|
+
updateShipment(id: $id, input: $input) {
|
|
73
|
+
...ShipmentStatusAuthorityFields
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
${t}`, s = e`
|
|
77
|
+
query StatusAuthorityOwnedDelivery($deliveryJobId: ID!) {
|
|
78
|
+
myEpodShipmentStatus(deliveryJobId: $deliveryJobId) {
|
|
79
|
+
id
|
|
80
|
+
status
|
|
81
|
+
statusRevision
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
`;
|
|
85
|
+
//#endregion
|
|
86
|
+
export { a as StatusAuthorityConfigureDocument, r as StatusAuthorityDetailDocument, o as StatusAuthorityManualDocument, s as StatusAuthorityOwnedDeliveryDocument, n as StatusAuthorityShipmentsDocument, i as StatusAuthoritySourcesDocument };
|