@burdenoff/microfe-movethewheels 2026.1012.1 → 2026.1012.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.
@@ -1,26 +1,26 @@
1
1
  import { useMoveTheWheels as e } from "../providers/MoveTheWheelsProvider.js";
2
2
  import { executeGraphQL as t } from "../utils/graphqlClient.js";
3
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
+ import { useCallback as r, useEffect as i, useMemo as a, useRef as o, useState as s } from "react";
5
+ import { parse as c } from "graphql";
6
6
  //#region src/movethewheels/hooks/useEpod.ts
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 = `
7
+ var l = "\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", u = `
8
8
  query GetEpod($deliveryJobId: ID!) {
9
9
  epod(deliveryJobId: $deliveryJobId) {
10
- ${c}
10
+ ${l}
11
11
  }
12
12
  }
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(`
13
+ `, d = "\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", f = c(`
14
14
  mutation CaptureEpod($input: CaptureEpodInput!) {
15
15
  captureEpod(input: $input) {
16
- ${c}
16
+ ${l}
17
17
  }
18
18
  }
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
+ `), p = "\n mutation EpodInitiateUpload($input: InitiateUploadInput!) {\n initiateUpload(input: $input) {\n uploadUrl\n session { id }\n }\n }\n", m = "\n mutation EpodCompleteUpload($input: CompleteUploadInput!) {\n completeUpload(input: $input) {\n fileId\n }\n }\n", h = "\n query EpodFileUrl($id: ID!, $expiresIn: Int) {\n getFileDownloadUrl(id: $id, expiresIn: $expiresIn)\n }\n", g = 21600;
20
+ function _(e) {
21
21
  return e === "typed" ? "TYPED" : "DRAWN";
22
22
  }
23
- function _(e) {
23
+ function v(e) {
24
24
  return {
25
25
  id: e.id,
26
26
  deliveryJobId: e.deliveryJobId,
@@ -37,7 +37,7 @@ function _(e) {
37
37
  notes: e.notes ?? void 0
38
38
  };
39
39
  }
40
- function v() {
40
+ function y() {
41
41
  let { apiGatewayUrl: t, authToken: n, workspaceToken: r, workspaceId: i, tenantId: o, currentUser: s } = e();
42
42
  return a(() => ({
43
43
  apiGatewayUrl: t,
@@ -55,20 +55,20 @@ function v() {
55
55
  s?.id
56
56
  ]);
57
57
  }
58
- function y(e) {
59
- let n = v(), [a, s] = o(null), [c, u] = o(!1), [d, f] = o(null), p = r(async () => {
58
+ function b(e) {
59
+ let n = y(), [a, o] = s(null), [c, l] = s(!1), [d, f] = s(null), p = r(async () => {
60
60
  if (!e) {
61
- s(null);
61
+ o(null);
62
62
  return;
63
63
  }
64
- u(!0), f(null);
64
+ l(!0), f(null);
65
65
  try {
66
- let r = await t(n, l, { deliveryJobId: e });
67
- s(r.epod ? _(r.epod) : null);
66
+ let r = await t(n, u, { deliveryJobId: e });
67
+ o(r.epod ? v(r.epod) : null);
68
68
  } catch (e) {
69
- f(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load proof of delivery")), s(null);
69
+ f(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load proof of delivery")), o(null);
70
70
  } finally {
71
- u(!1);
71
+ l(!1);
72
72
  }
73
73
  }, [e, n]);
74
74
  return i(() => {
@@ -80,69 +80,133 @@ function y(e) {
80
80
  refetch: p
81
81
  };
82
82
  }
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);
83
+ function x(e = {}) {
84
+ let { limit: n = 20, offset: a = 0 } = e, c = y(), l = JSON.stringify([
85
+ c.apiGatewayUrl,
86
+ c.workspaceId,
87
+ c.tenantId,
88
+ c.actorId
89
+ ]), u = JSON.stringify([
90
+ l,
91
+ n,
92
+ a
93
+ ]), f = o({
94
+ scopeKey: l,
95
+ ids: /* @__PURE__ */ new Set()
96
+ }), p = o(0), [m, h] = s({
97
+ scopeKey: l,
98
+ readKey: u,
99
+ jobs: [],
100
+ totalJobs: 0,
101
+ hasMore: !1,
102
+ isLoading: !0,
103
+ error: null
104
+ }), g = r(async () => {
105
+ let e = ++p.current;
106
+ f.current.scopeKey !== l && (f.current = {
107
+ scopeKey: l,
108
+ ids: /* @__PURE__ */ new Set()
109
+ }), h((e) => ({
110
+ scopeKey: l,
111
+ readKey: u,
112
+ jobs: e.readKey === u ? e.jobs : [],
113
+ totalJobs: e.readKey === u ? e.totalJobs : 0,
114
+ hasMore: e.readKey === u ? e.hasMore : !1,
115
+ isLoading: !0,
116
+ error: null
117
+ }));
86
118
  try {
87
- let e = await t(s, u, { pagination: {
119
+ let r = await t(c, d, { pagination: {
88
120
  limit: n,
89
121
  offset: a
90
122
  } });
91
- f(e.myPendingEpodDeliveryJobsCount ?? 0), m(a + e.myPendingEpodDeliveryJobs.length < e.myPendingEpodDeliveryJobsCount), l(e.myPendingEpodDeliveryJobs.map((e) => ({
92
- id: e.id,
93
- deliveryJobNumber: e.deliveryJobNumber,
94
- status: e.status,
95
- priority: e.priority,
96
- deliveryAddress: e.deliveryAddress,
97
- scheduledDelivery: e.scheduledDelivery ? new Date(e.scheduledDelivery) : void 0,
98
- customerName: e.customer?.name ?? void 0,
99
- customerPhone: e.customer?.phone ?? void 0
100
- })));
101
- } catch (e) {
102
- y(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load pending deliveries")), l([]);
103
- } finally {
104
- g(!1);
123
+ if (e !== p.current) return;
124
+ let i = r.myPendingEpodDeliveryJobs, o = r.myPendingEpodDeliveryJobsCount ?? 0, s = i.filter((e) => f.current.ids.has(e.id)).length;
125
+ h({
126
+ scopeKey: l,
127
+ readKey: u,
128
+ totalJobs: Math.max(0, o - s),
129
+ hasMore: a + i.length < o,
130
+ jobs: i.filter((e) => !f.current.ids.has(e.id)).map((e) => ({
131
+ id: e.id,
132
+ deliveryJobNumber: e.deliveryJobNumber,
133
+ status: e.status,
134
+ priority: e.priority,
135
+ deliveryAddress: e.deliveryAddress,
136
+ scheduledDelivery: e.scheduledDelivery ? new Date(e.scheduledDelivery) : void 0,
137
+ customerName: e.customer?.name ?? void 0,
138
+ customerPhone: e.customer?.phone ?? void 0
139
+ })),
140
+ isLoading: !1,
141
+ error: null
142
+ });
143
+ } catch (t) {
144
+ if (e !== p.current) return;
145
+ h({
146
+ scopeKey: l,
147
+ readKey: u,
148
+ jobs: [],
149
+ totalJobs: 0,
150
+ hasMore: !1,
151
+ isLoading: !1,
152
+ error: t instanceof Error ? t : /* @__PURE__ */ Error("Failed to load pending deliveries")
153
+ });
105
154
  }
106
155
  }, [
107
- s,
156
+ c,
108
157
  n,
109
- a
110
- ]);
111
- return i(() => {
112
- b();
113
- }, [b]), {
114
- jobs: c,
115
- totalJobs: d,
116
- hasMore: p,
117
- isLoading: h,
118
- error: _,
119
- refetch: b
158
+ a,
159
+ l,
160
+ u
161
+ ]), _ = r(() => {
162
+ p.current++;
163
+ }, []);
164
+ i(() => (g(), _), [g, _]);
165
+ let v = r((e) => {
166
+ f.current.scopeKey !== l || f.current.ids.has(e) || (f.current.ids.add(e), h((t) => {
167
+ if (t.scopeKey !== l) return t;
168
+ let n = t.jobs.some((t) => t.id === e);
169
+ return {
170
+ ...t,
171
+ jobs: t.jobs.filter((t) => t.id !== e),
172
+ totalJobs: Math.max(0, t.totalJobs - +!!n)
173
+ };
174
+ }));
175
+ }, [l]), b = m.readKey === u;
176
+ return {
177
+ jobs: b ? m.jobs : [],
178
+ totalJobs: b ? m.totalJobs : 0,
179
+ hasMore: b && m.hasMore,
180
+ isLoading: !b || m.isLoading,
181
+ error: b ? m.error : null,
182
+ refetch: g,
183
+ retireAcknowledgedJob: v
120
184
  };
121
185
  }
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)) && (e.photoFileIds === null ? (t.photoFileIds ?? []).length === 0 : 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);
186
+ function S(e, t) {
187
+ 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 === _(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)) && (e.photoFileIds === null ? (t.photoFileIds ?? []).length === 0 : 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
188
  }
125
- function S() {
126
- let e = n(), [t, i] = o(null);
189
+ function C() {
190
+ let e = n(), [t, i] = s(null);
127
191
  return {
128
192
  captureEpod: r(async (t) => {
129
193
  i(null);
130
194
  try {
131
- let n = await e.run(d, { input: {
195
+ let n = await e.run(f, { input: {
132
196
  expectedShipmentStatusRevision: t.expectedShipmentStatusRevision,
133
197
  completionAttestation: t.completionAttestation,
134
198
  deliveryJobId: t.deliveryJobId,
135
199
  recipientName: t.recipientName,
136
- signatureType: g(t.signatureType),
200
+ signatureType: _(t.signatureType),
137
201
  signatureData: t.signatureData,
138
202
  photoFileIds: t.photoFileIds,
139
203
  latitude: t.latitude,
140
204
  longitude: t.longitude,
141
205
  locationAccuracy: t.locationAccuracy,
142
206
  notes: t.notes
143
- } }, (e) => x(e.captureEpod, t));
207
+ } }, (e) => S(e.captureEpod, t));
144
208
  if (!n) throw Error("Capture was not acknowledged. Review the recorded status and the capture message before taking further action.");
145
- return _(n.captureEpod);
209
+ return v(n.captureEpod);
146
210
  } catch (e) {
147
211
  let t = e instanceof Error ? e : /* @__PURE__ */ Error("Failed to capture proof of delivery");
148
212
  throw i(t), t;
@@ -153,32 +217,32 @@ function S() {
153
217
  captureFeedback: e.feedback
154
218
  };
155
219
  }
156
- function C() {
157
- let e = v(), [n, i] = o(!1), [a, s] = o(0), [c, l] = o(null);
220
+ function w() {
221
+ let e = y(), [n, i] = s(!1), [a, o] = s(0), [c, l] = s(null);
158
222
  return {
159
223
  upload: r(async (n) => {
160
- i(!0), s(0), l(null);
224
+ i(!0), o(0), l(null);
161
225
  try {
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: {
226
+ let r = n.name.lastIndexOf("."), i = r > -1 ? n.name.slice(r + 1) : "", a = n.type || "application/octet-stream", s = await t(e, p, { input: {
163
227
  fileName: n.name,
164
228
  extension: i,
165
229
  mimeType: a,
166
230
  fileSize: String(n.size),
167
231
  visibility: "WORKSPACE"
168
- } }), { uploadUrl: c } = o.initiateUpload, l = o.initiateUpload.session.id;
232
+ } }), { uploadUrl: c } = s.initiateUpload, l = s.initiateUpload.session.id;
169
233
  if (!c) throw Error("The file service did not return an upload URL.");
170
- s(50);
234
+ o(50);
171
235
  let u = await fetch(c, {
172
236
  method: "PUT",
173
237
  headers: { "Content-Type": a },
174
238
  body: n
175
239
  });
176
240
  if (!u.ok) throw Error(`File storage rejected the upload (HTTP ${u.status}).`);
177
- let d = await t(e, p, { input: {
241
+ let d = await t(e, m, { input: {
178
242
  sessionId: l,
179
243
  fileSize: String(n.size)
180
244
  } });
181
- return s(100), {
245
+ return o(100), {
182
246
  fileId: d.completeUpload.fileId,
183
247
  fileName: n.name
184
248
  };
@@ -194,17 +258,17 @@ function C() {
194
258
  error: c
195
259
  };
196
260
  }
197
- function w(e) {
198
- let n = v(), [r, a] = o(null), [s, c] = o(!1);
261
+ function T(e) {
262
+ let n = y(), [r, a] = s(null), [o, c] = s(!1);
199
263
  return i(() => {
200
264
  if (!e) {
201
265
  a(null);
202
266
  return;
203
267
  }
204
268
  let r = !1;
205
- return c(!0), t(n, m, {
269
+ return c(!0), t(n, h, {
206
270
  id: e,
207
- expiresIn: h
271
+ expiresIn: g
208
272
  }).then((e) => {
209
273
  r || a(e.getFileDownloadUrl ?? null);
210
274
  }).catch(() => {
@@ -216,8 +280,8 @@ function w(e) {
216
280
  };
217
281
  }, [e, n]), {
218
282
  url: r,
219
- isLoading: s
283
+ isLoading: o
220
284
  };
221
285
  }
222
286
  //#endregion
223
- export { S as useCaptureEpod, y as useEpod, C as useEpodPhotoUpload, w as useEpodPhotoUrl, b as useMyPendingEpodDeliveryJobs };
287
+ export { C as useCaptureEpod, b as useEpod, w as useEpodPhotoUpload, T as useEpodPhotoUrl, x as useMyPendingEpodDeliveryJobs };
@@ -43,6 +43,7 @@ export declare function useMyPendingEpodDeliveryJobs(options?: {
43
43
  isLoading: boolean;
44
44
  error: Error | null;
45
45
  refetch: () => Promise<void>;
46
+ retireAcknowledgedJob: (deliveryJobId: string) => void;
46
47
  };
47
48
  export interface CaptureEpodArgs {
48
49
  expectedShipmentId: string | null;
@@ -6,21 +6,21 @@ import { MapPin as i } from "../node_modules/lucide-react/dist/esm/icons/map-pin
6
6
  import { Package as a } from "../node_modules/lucide-react/dist/esm/icons/package.js";
7
7
  import { PenLine as o } from "../node_modules/lucide-react/dist/esm/icons/pen-line.js";
8
8
  import { Truck as s } from "../node_modules/lucide-react/dist/esm/icons/truck.js";
9
- import { Type as c } from "../node_modules/lucide-react/dist/esm/icons/type.js";
10
- import { Upload as l } from "../node_modules/lucide-react/dist/esm/icons/upload.js";
11
- import { useMoveTheWheels as u } from "../providers/MoveTheWheelsProvider.js";
12
- import { mapOrderPriority as d, mapOrderStatus as f } from "../hooks/useOrders.js";
13
- import { useShipmentStatusQuery as p } from "../hooks/useShipmentStatusAuthority.js";
14
- import { useCaptureEpod as m, useEpodPhotoUpload as h, useMyPendingEpodDeliveryJobs as g } from "../hooks/useEpod.js";
15
- import { Button as _, Card as v, CardContent as y, CardHeader as b, CardTitle as x, Input as S, Label as C, Textarea as w } from "../components/ui.js";
16
- import { PageLayout as T } from "../components/PageLayout.js";
17
- import { PriorityBadge as E, StatusBadge as D } from "../components/StatusBadge.js";
18
- import { FormError as O } from "../components/FormError.js";
19
- import { Notice as k, useNotice as A } from "../components/Notice.js";
20
- import { formatAddress as j, formatDate as M } from "../utils/formatters.js";
21
- import { SignaturePad as N } from "../components/SignaturePad.js";
22
- import { StatusAuthorityOwnedDeliveryDocument as P } from "../src/generated/shipment-status-authority-operations.js";
23
- import { useEffect as ee, useRef as F, useState as I } from "react";
9
+ import { Type as ee } from "../node_modules/lucide-react/dist/esm/icons/type.js";
10
+ import { Upload as c } from "../node_modules/lucide-react/dist/esm/icons/upload.js";
11
+ import { useMoveTheWheels as l } from "../providers/MoveTheWheelsProvider.js";
12
+ import { mapOrderPriority as u, mapOrderStatus as d } from "../hooks/useOrders.js";
13
+ import { useShipmentStatusQuery as f } from "../hooks/useShipmentStatusAuthority.js";
14
+ import { useCaptureEpod as p, useEpodPhotoUpload as m, useMyPendingEpodDeliveryJobs as h } from "../hooks/useEpod.js";
15
+ import { Button as g, Card as _, CardContent as v, CardHeader as y, CardTitle as b, Input as x, Label as S, Textarea as C } from "../components/ui.js";
16
+ import { PageLayout as w } from "../components/PageLayout.js";
17
+ import { PriorityBadge as T, StatusBadge as E } from "../components/StatusBadge.js";
18
+ import { FormError as D } from "../components/FormError.js";
19
+ import { Notice as O, useNotice as k } from "../components/Notice.js";
20
+ import { formatAddress as A, formatDate as j } from "../utils/formatters.js";
21
+ import { SignaturePad as M } from "../components/SignaturePad.js";
22
+ import { StatusAuthorityOwnedDeliveryDocument as N } from "../src/generated/shipment-status-authority-operations.js";
23
+ import { useEffect as P, useRef as F, useState as I } from "react";
24
24
  import { Fragment as te, jsx as L, jsxs as R } from "react/jsx-runtime";
25
25
  //#region src/movethewheels/pages/DeliveryCapturePage.tsx
26
26
  function ne() {
@@ -37,13 +37,13 @@ function ne() {
37
37
  });
38
38
  }
39
39
  function z({ job: e, onCaptured: t, onCancel: a }) {
40
- let { captureEpod: u, isSubmitting: d, error: f, captureFeedback: g } = m(), [T, E] = I(0), D = p(P, { deliveryJobId: e.id }, T), [k, A] = I(!1), M = F(null), z = F(!1), B = F(!0);
41
- ee(() => (B.current = !0, () => {
40
+ let { captureEpod: l, isSubmitting: u, error: d, captureFeedback: h } = p(), [w, T] = I(0), E = f(N, { deliveryJobId: e.id }, w), [O, k] = I(!1), j = F(null), z = F(!1), B = F(!0);
41
+ P(() => (B.current = !0, () => {
42
42
  B.current = !1;
43
43
  }), []);
44
- let [re, V] = I(!1), [H, ie] = I(0), { upload: ae, isUploading: oe, error: U } = h(), W = F(null), [G, se] = I(""), [K, q] = I("drawn"), [J, ce] = I(""), [Y, le] = I(null), [X, ue] = I(""), [Z, Q] = I(null), de = async () => {
44
+ let [re, V] = I(!1), [H, ie] = I(0), { upload: ae, isUploading: oe, error: U } = m(), W = F(null), [G, se] = I(""), [K, q] = I("drawn"), [J, ce] = I(""), [Y, le] = I(null), [X, ue] = I(""), [Z, Q] = I(null), de = async () => {
45
45
  if (z.current) return;
46
- if (Q(null), D.loading || D.error || !D.data || T < H || !k || g?.kind === "UNKNOWN") {
46
+ if (Q(null), E.loading || E.error || !E.data || w < H || !O || h?.kind === "UNKNOWN") {
47
47
  Q("Review the current linked shipment status and confirm completion before capture. Do not resend an uncertain capture.");
48
48
  return;
49
49
  }
@@ -60,10 +60,10 @@ function z({ job: e, onCaptured: t, onCancel: a }) {
60
60
  z.current = !0, V(!0);
61
61
  try {
62
62
  let i;
63
- if (Y) if (M.current?.file === Y) i = [M.current.id];
63
+ if (Y) if (j.current?.file === Y) i = [j.current.id];
64
64
  else {
65
65
  let e = await ae(Y);
66
- M.current = {
66
+ j.current = {
67
67
  file: Y,
68
68
  id: e.fileId
69
69
  }, i = [e.fileId];
@@ -71,10 +71,10 @@ function z({ job: e, onCaptured: t, onCancel: a }) {
71
71
  if (!B.current) return;
72
72
  let a = await ne();
73
73
  if (!B.current) return;
74
- await u({
75
- expectedShipmentId: D.data.myEpodShipmentStatus?.id ?? null,
76
- expectedShipmentStatusRevision: D.data.myEpodShipmentStatus?.statusRevision,
77
- completionAttestation: k,
74
+ let o = await l({
75
+ expectedShipmentId: E.data.myEpodShipmentStatus?.id ?? null,
76
+ expectedShipmentStatusRevision: E.data.myEpodShipmentStatus?.statusRevision,
77
+ completionAttestation: O,
78
78
  deliveryJobId: e.id,
79
79
  recipientName: n,
80
80
  signatureType: K,
@@ -84,26 +84,28 @@ function z({ job: e, onCaptured: t, onCancel: a }) {
84
84
  longitude: a?.coords.longitude,
85
85
  locationAccuracy: a?.coords.accuracy,
86
86
  notes: X.trim() || void 0
87
- }), t();
87
+ });
88
+ if (!B.current) return;
89
+ t(o.deliveryJobId);
88
90
  } catch {
89
- A(!1), ie(T + 1);
91
+ k(!1), ie(w + 1);
90
92
  } finally {
91
93
  z.current = !1, V(!1);
92
94
  }
93
- }, $ = d || oe || re;
94
- return /* @__PURE__ */ R(v, { children: [/* @__PURE__ */ L(b, { children: /* @__PURE__ */ R(x, {
95
+ }, $ = u || oe || re;
96
+ return /* @__PURE__ */ R(_, { children: [/* @__PURE__ */ L(y, { children: /* @__PURE__ */ R(b, {
95
97
  className: "flex items-center gap-2",
96
98
  children: [
97
99
  /* @__PURE__ */ L(s, { size: 18 }),
98
100
  " Capture delivery for ",
99
101
  e.deliveryJobNumber
100
102
  ]
101
- }) }), /* @__PURE__ */ R(y, {
103
+ }) }), /* @__PURE__ */ R(v, {
102
104
  className: "space-y-4",
103
105
  children: [
104
106
  /* @__PURE__ */ R("div", {
105
107
  className: "text-sm text-text-secondary space-y-1",
106
- children: [e.customerName && /* @__PURE__ */ R("p", { children: ["Recipient on file: ", e.customerName] }), e.deliveryAddress && /* @__PURE__ */ L("p", { children: j(e.deliveryAddress) })]
108
+ children: [e.customerName && /* @__PURE__ */ R("p", { children: ["Recipient on file: ", e.customerName] }), e.deliveryAddress && /* @__PURE__ */ L("p", { children: A(e.deliveryAddress) })]
107
109
  }),
108
110
  /* @__PURE__ */ R("section", {
109
111
  "aria-label": "Linked shipment status",
@@ -112,17 +114,17 @@ function z({ job: e, onCaptured: t, onCancel: a }) {
112
114
  /* @__PURE__ */ R("p", { children: [
113
115
  "Recorded shipment:",
114
116
  " ",
115
- D.data?.myEpodShipmentStatus ? `${D.data.myEpodShipmentStatus.status.toLowerCase().replaceAll("_", " ")} · revision ${D.data.myEpodShipmentStatus.statusRevision}` : D.data ? "No linked shipment" : "Loading current record"
117
+ E.data?.myEpodShipmentStatus ? `${E.data.myEpodShipmentStatus.status.toLowerCase().replaceAll("_", " ")} · revision ${E.data.myEpodShipmentStatus.statusRevision}` : E.data ? "No linked shipment" : "Loading current record"
116
118
  ] }),
117
- D.error && /* @__PURE__ */ L("p", {
119
+ E.error && /* @__PURE__ */ L("p", {
118
120
  role: "alert",
119
- children: D.error
121
+ children: E.error
120
122
  }),
121
- /* @__PURE__ */ L(_, {
123
+ /* @__PURE__ */ L(g, {
122
124
  variant: "outline",
123
- disabled: D.loading || $,
125
+ disabled: E.loading || $,
124
126
  onClick: () => {
125
- A(!1), E((e) => e + 1);
127
+ k(!1), T((e) => e + 1);
126
128
  },
127
129
  children: "Refresh linked status"
128
130
  }),
@@ -130,24 +132,24 @@ function z({ job: e, onCaptured: t, onCancel: a }) {
130
132
  className: "flex items-start gap-2",
131
133
  children: [/* @__PURE__ */ L("input", {
132
134
  type: "checkbox",
133
- checked: k,
134
- disabled: D.loading || !!D.error || $ || T < H || g?.kind === "UNKNOWN",
135
- onChange: (e) => A(e.target.checked)
135
+ checked: O,
136
+ disabled: E.loading || !!E.error || $ || w < H || h?.kind === "UNKNOWN",
137
+ onChange: (e) => k(e.target.checked)
136
138
  }), "I reviewed the recorded linked status and attest to this delivery completion."]
137
139
  }),
138
140
  /* @__PURE__ */ L("p", { children: "This records an assigned driver's attestation; it does not independently verify physical freight movement." }),
139
- g && /* @__PURE__ */ L("p", {
141
+ h && /* @__PURE__ */ L("p", {
140
142
  role: "status",
141
- children: g.message
143
+ children: h.message
142
144
  })
143
145
  ]
144
146
  }),
145
147
  /* @__PURE__ */ R("div", {
146
148
  className: "space-y-1.5",
147
- children: [/* @__PURE__ */ L(C, {
149
+ children: [/* @__PURE__ */ L(S, {
148
150
  htmlFor: "epod-recipient-name",
149
151
  children: "Recipient name"
150
- }), /* @__PURE__ */ L(S, {
152
+ }), /* @__PURE__ */ L(x, {
151
153
  id: "epod-recipient-name",
152
154
  value: G,
153
155
  onChange: (e) => se(e.target.value),
@@ -157,24 +159,24 @@ function z({ job: e, onCaptured: t, onCancel: a }) {
157
159
  /* @__PURE__ */ R("div", {
158
160
  className: "space-y-1.5",
159
161
  children: [
160
- /* @__PURE__ */ L(C, { children: "Signature" }),
162
+ /* @__PURE__ */ L(S, { children: "Signature" }),
161
163
  /* @__PURE__ */ R("div", {
162
164
  className: "flex gap-2",
163
- children: [/* @__PURE__ */ R(_, {
165
+ children: [/* @__PURE__ */ R(g, {
164
166
  type: "button",
165
167
  variant: K === "drawn" ? "default" : "outline",
166
168
  size: "sm",
167
169
  onClick: () => q("drawn"),
168
170
  children: [/* @__PURE__ */ L(o, { size: 14 }), " Draw"]
169
- }), /* @__PURE__ */ R(_, {
171
+ }), /* @__PURE__ */ R(g, {
170
172
  type: "button",
171
173
  variant: K === "typed" ? "default" : "outline",
172
174
  size: "sm",
173
175
  onClick: () => q("typed"),
174
- children: [/* @__PURE__ */ L(c, { size: 14 }), " Type name instead"]
176
+ children: [/* @__PURE__ */ L(ee, { size: 14 }), " Type name instead"]
175
177
  })]
176
178
  }),
177
- K === "drawn" ? /* @__PURE__ */ L(N, { ref: W }) : /* @__PURE__ */ L(S, {
179
+ K === "drawn" ? /* @__PURE__ */ L(M, { ref: W }) : /* @__PURE__ */ L(x, {
178
180
  value: J,
179
181
  onChange: (e) => ce(e.target.value),
180
182
  placeholder: "Type full name as signature"
@@ -184,7 +186,7 @@ function z({ job: e, onCaptured: t, onCancel: a }) {
184
186
  /* @__PURE__ */ R("div", {
185
187
  className: "space-y-1.5",
186
188
  children: [
187
- /* @__PURE__ */ L(C, {
189
+ /* @__PURE__ */ L(S, {
188
190
  htmlFor: "epod-photo",
189
191
  children: "Delivery photo (optional)"
190
192
  }),
@@ -197,7 +199,7 @@ function z({ job: e, onCaptured: t, onCancel: a }) {
197
199
  capture: "environment",
198
200
  onChange: (e) => le(e.target.files?.[0] ?? null),
199
201
  className: "text-sm"
200
- }), Y && /* @__PURE__ */ L(l, {
202
+ }), Y && /* @__PURE__ */ L(c, {
201
203
  size: 14,
202
204
  className: "text-text-secondary"
203
205
  })]
@@ -210,10 +212,10 @@ function z({ job: e, onCaptured: t, onCancel: a }) {
210
212
  }),
211
213
  /* @__PURE__ */ R("div", {
212
214
  className: "space-y-1.5",
213
- children: [/* @__PURE__ */ L(C, {
215
+ children: [/* @__PURE__ */ L(S, {
214
216
  htmlFor: "epod-notes",
215
217
  children: "Notes (optional)"
216
- }), /* @__PURE__ */ L(w, {
218
+ }), /* @__PURE__ */ L(C, {
217
219
  id: "epod-notes",
218
220
  value: X,
219
221
  onChange: (e) => ue(e.target.value),
@@ -225,21 +227,21 @@ function z({ job: e, onCaptured: t, onCancel: a }) {
225
227
  className: "flex items-center gap-1.5 text-xs text-text-secondary",
226
228
  children: [/* @__PURE__ */ L(i, { size: 12 }), " Device GPS is captured automatically when permitted by the browser."]
227
229
  }),
228
- Z && /* @__PURE__ */ L(O, { message: Z }),
229
- f && /* @__PURE__ */ L(O, { message: f.message }),
230
- U && /* @__PURE__ */ L(O, { message: U.message }),
230
+ Z && /* @__PURE__ */ L(D, { message: Z }),
231
+ d && /* @__PURE__ */ L(D, { message: d.message }),
232
+ U && /* @__PURE__ */ L(D, { message: U.message }),
231
233
  /* @__PURE__ */ R("div", {
232
234
  className: "flex gap-2 justify-end",
233
- children: [/* @__PURE__ */ L(_, {
235
+ children: [/* @__PURE__ */ L(g, {
234
236
  type: "button",
235
237
  variant: "outline",
236
238
  onClick: a,
237
239
  disabled: $,
238
240
  children: "Cancel"
239
- }), /* @__PURE__ */ L(_, {
241
+ }), /* @__PURE__ */ L(g, {
240
242
  type: "button",
241
243
  onClick: () => void de(),
242
- disabled: $ || D.loading || !!D.error || !D.data || T < H || !k || g?.kind === "UNKNOWN",
244
+ disabled: $ || E.loading || !!E.error || !E.data || w < H || !O || h?.kind === "UNKNOWN",
243
245
  children: $ ? /* @__PURE__ */ R(te, { children: [/* @__PURE__ */ L(r, {
244
246
  size: 14,
245
247
  className: "animate-spin"
@@ -250,28 +252,28 @@ function z({ job: e, onCaptured: t, onCancel: a }) {
250
252
  })] });
251
253
  }
252
254
  function B() {
253
- let { workspaceId: r, tenantId: i, currentUser: o, apiGatewayUrl: c } = u(), [l, p] = I(0), { jobs: m, hasMore: h, isLoading: b, error: x, refetch: S } = g({
255
+ let { workspaceId: r, tenantId: i, currentUser: o, apiGatewayUrl: ee } = l(), [c, f] = I(0), { jobs: p, hasMore: m, isLoading: y, error: b, refetch: x, retireAcknowledgedJob: S } = h({
254
256
  limit: 20,
255
- offset: l * 20
256
- }), [C, w] = I(null), { message: N, notify: P } = A();
257
- return /* @__PURE__ */ L(T, {
257
+ offset: c * 20
258
+ }), [C, M] = I(null), { message: N, notify: P } = k();
259
+ return /* @__PURE__ */ L(w, {
258
260
  title: "My Deliveries",
259
261
  subtitle: "Capture proof of delivery for your assigned stops",
260
262
  icon: /* @__PURE__ */ L(s, { size: 24 }),
261
263
  children: /* @__PURE__ */ R("div", {
262
264
  className: "space-y-4",
263
- children: [/* @__PURE__ */ L(k, { message: N }), C ? /* @__PURE__ */ L(z, {
265
+ children: [/* @__PURE__ */ L(O, { message: N }), C ? /* @__PURE__ */ L(z, {
264
266
  job: C,
265
- onCaptured: () => {
266
- P("Proof of delivery captured — delivery marked complete."), w(null), p(0), S();
267
+ onCaptured: (e) => {
268
+ S(e), P("Proof of delivery captured — delivery marked complete."), M(null), f(0), x();
267
269
  },
268
- onCancel: () => w(null)
269
- }, `${r}:${i}:${o?.id}:${c}:${C.id}`) : b ? /* @__PURE__ */ L("p", {
270
+ onCancel: () => M(null)
271
+ }, `${r}:${i}:${o?.id}:${ee}:${C.id}`) : y ? /* @__PURE__ */ L("p", {
270
272
  className: "text-text-secondary text-center py-8",
271
273
  children: "Loading your deliveries…"
272
- }) : x ? /* @__PURE__ */ L(O, { message: x.message }) : m.length > 0 ? /* @__PURE__ */ R("div", {
274
+ }) : b ? /* @__PURE__ */ L(D, { message: b.message }) : p.length > 0 ? /* @__PURE__ */ R("div", {
273
275
  className: "space-y-3",
274
- children: [m.map((e) => /* @__PURE__ */ L(v, { children: /* @__PURE__ */ R(y, {
276
+ children: [p.map((e) => /* @__PURE__ */ L(_, { children: /* @__PURE__ */ R(v, {
275
277
  className: "flex items-center justify-between gap-3 py-4",
276
278
  children: [/* @__PURE__ */ R("div", {
277
279
  className: "min-w-0",
@@ -286,45 +288,45 @@ function B() {
286
288
  }),
287
289
  /* @__PURE__ */ R("div", {
288
290
  className: "flex flex-wrap items-center gap-1.5 py-1",
289
- children: [/* @__PURE__ */ L(D, {
290
- status: f(e.status),
291
+ children: [/* @__PURE__ */ L(E, {
292
+ status: d(e.status),
291
293
  type: "order",
292
294
  size: "sm"
293
- }), /* @__PURE__ */ L(E, {
294
- priority: d(e.priority),
295
+ }), /* @__PURE__ */ L(T, {
296
+ priority: u(e.priority),
295
297
  size: "sm"
296
298
  })]
297
299
  }),
298
300
  e.deliveryAddress && /* @__PURE__ */ L("p", {
299
301
  className: "text-sm text-text-secondary truncate",
300
- children: j(e.deliveryAddress)
302
+ children: A(e.deliveryAddress)
301
303
  }),
302
304
  e.scheduledDelivery && /* @__PURE__ */ R("p", {
303
305
  className: "text-xs text-text-secondary",
304
- children: ["Scheduled ", M(e.scheduledDelivery, "short")]
306
+ children: ["Scheduled ", j(e.scheduledDelivery, "short")]
305
307
  })
306
308
  ]
307
- }), /* @__PURE__ */ L(_, {
309
+ }), /* @__PURE__ */ L(g, {
308
310
  type: "button",
309
311
  size: "sm",
310
- onClick: () => w(e),
312
+ onClick: () => M(e),
311
313
  children: "Capture"
312
314
  })]
313
- }) }, e.id)), (l > 0 || h) && /* @__PURE__ */ R("div", {
315
+ }) }, e.id)), (c > 0 || m) && /* @__PURE__ */ R("div", {
314
316
  className: "flex justify-end gap-2 pt-2",
315
- children: [/* @__PURE__ */ R(_, {
317
+ children: [/* @__PURE__ */ R(g, {
316
318
  type: "button",
317
319
  variant: "outline",
318
320
  size: "sm",
319
- disabled: l === 0 || b,
320
- onClick: () => p((e) => Math.max(0, e - 1)),
321
+ disabled: c === 0 || y,
322
+ onClick: () => f((e) => Math.max(0, e - 1)),
321
323
  children: [/* @__PURE__ */ L(e, { size: 16 }), " Previous"]
322
- }), /* @__PURE__ */ R(_, {
324
+ }), /* @__PURE__ */ R(g, {
323
325
  type: "button",
324
326
  variant: "outline",
325
327
  size: "sm",
326
- disabled: !h || b,
327
- onClick: () => p((e) => e + 1),
328
+ disabled: !m || y,
329
+ onClick: () => f((e) => e + 1),
328
330
  children: ["Next ", /* @__PURE__ */ L(t, { size: 16 })]
329
331
  })]
330
332
  })]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-movethewheels",
3
- "version": "2026.1012.1",
3
+ "version": "2026.1012.2",
4
4
  "description": "Burdenoff MoveTheWheels Microfrontend - Logistics & Supply Chain Management Platform",
5
5
  "type": "module",
6
6
  "files": [
@@ -11,7 +11,7 @@
11
11
  * Deferred (see BOFF-4399 follow-up notes): barcode/RFID capture and
12
12
  * multi-language delivery instructions.
13
13
  */
14
- import { useCallback, useEffect, useMemo, useState } from 'react';
14
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
15
15
  import { parse } from 'graphql';
16
16
  import { useShipmentStatusCommand } from './useShipmentStatusAuthority';
17
17
  import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
@@ -212,51 +212,127 @@ interface ApiPendingJob {
212
212
  export function useMyPendingEpodDeliveryJobs(options: { limit?: number; offset?: number } = {}) {
213
213
  const { limit = 20, offset = 0 } = options;
214
214
  const graphQLOptions = useGraphQLOptions();
215
- const [jobs, setJobs] = useState<PendingEpodDeliveryJob[]>([]);
216
- const [totalJobs, setTotalJobs] = useState(0);
217
- const [hasMore, setHasMore] = useState(false);
218
- const [isLoading, setIsLoading] = useState(false);
219
- const [error, setError] = useState<Error | null>(null);
215
+ const scopeKey = JSON.stringify([
216
+ graphQLOptions.apiGatewayUrl,
217
+ graphQLOptions.workspaceId,
218
+ graphQLOptions.tenantId,
219
+ graphQLOptions.actorId,
220
+ ]);
221
+ const readKey = JSON.stringify([scopeKey, limit, offset]);
222
+ // A validated capture ACK makes this stop ineligible for capture immediately.
223
+ // Keep that fact for this actor/scope while a pending-list refresh is delayed.
224
+ // This is an in-memory UI exclusion, never a fabricated server job update.
225
+ const acknowledgedJobs = useRef({ scopeKey, ids: new Set<string>() });
226
+ const requestId = useRef(0);
227
+ const [snapshot, setSnapshot] = useState<{
228
+ scopeKey: string;
229
+ readKey: string;
230
+ jobs: PendingEpodDeliveryJob[];
231
+ totalJobs: number;
232
+ hasMore: boolean;
233
+ isLoading: boolean;
234
+ error: Error | null;
235
+ }>({ scopeKey, readKey, jobs: [], totalJobs: 0, hasMore: false, isLoading: true, error: null });
220
236
 
221
237
  const load = useCallback(async () => {
222
- setIsLoading(true);
223
- setError(null);
238
+ const request = ++requestId.current;
239
+ if (acknowledgedJobs.current.scopeKey !== scopeKey) {
240
+ acknowledgedJobs.current = { scopeKey, ids: new Set<string>() };
241
+ }
242
+ setSnapshot((previous) => ({
243
+ scopeKey,
244
+ readKey,
245
+ jobs: previous.readKey === readKey ? previous.jobs : [],
246
+ totalJobs: previous.readKey === readKey ? previous.totalJobs : 0,
247
+ hasMore: previous.readKey === readKey ? previous.hasMore : false,
248
+ isLoading: true,
249
+ error: null,
250
+ }));
224
251
  try {
225
252
  const data = await executeGraphQL<{
226
253
  myPendingEpodDeliveryJobs: ApiPendingJob[];
227
254
  myPendingEpodDeliveryJobsCount: number;
228
255
  }>(graphQLOptions, MY_PENDING_EPOD_JOBS_QUERY, { pagination: { limit, offset } });
229
- setTotalJobs(data.myPendingEpodDeliveryJobsCount ?? 0);
230
- setHasMore(
231
- offset + data.myPendingEpodDeliveryJobs.length < data.myPendingEpodDeliveryJobsCount
232
- );
233
- setJobs(
234
- data.myPendingEpodDeliveryJobs.map((job) => ({
235
- id: job.id,
236
- deliveryJobNumber: job.deliveryJobNumber,
237
- status: job.status,
238
- priority: job.priority,
239
- deliveryAddress: job.deliveryAddress,
240
- scheduledDelivery: job.scheduledDelivery ? new Date(job.scheduledDelivery) : undefined,
241
- customerName: job.customer?.name ?? undefined,
242
- customerPhone: job.customer?.phone ?? undefined,
243
- }))
244
- );
256
+ if (request !== requestId.current) return;
257
+ const rows = data.myPendingEpodDeliveryJobs;
258
+ const total = data.myPendingEpodDeliveryJobsCount ?? 0;
259
+ const excluded = rows.filter((job) => acknowledgedJobs.current.ids.has(job.id)).length;
260
+ setSnapshot({
261
+ scopeKey,
262
+ readKey,
263
+ totalJobs: Math.max(0, total - excluded),
264
+ // Pagination still follows the server page, including any excluded row.
265
+ hasMore: offset + rows.length < total,
266
+ jobs: rows
267
+ .filter((job) => !acknowledgedJobs.current.ids.has(job.id))
268
+ .map((job) => ({
269
+ id: job.id,
270
+ deliveryJobNumber: job.deliveryJobNumber,
271
+ status: job.status,
272
+ priority: job.priority,
273
+ deliveryAddress: job.deliveryAddress,
274
+ scheduledDelivery: job.scheduledDelivery ? new Date(job.scheduledDelivery) : undefined,
275
+ customerName: job.customer?.name ?? undefined,
276
+ customerPhone: job.customer?.phone ?? undefined,
277
+ })),
278
+ isLoading: false,
279
+ error: null,
280
+ });
245
281
  } catch (fetchError) {
246
- setError(
247
- fetchError instanceof Error ? fetchError : new Error('Failed to load pending deliveries')
248
- );
249
- setJobs([]);
250
- } finally {
251
- setIsLoading(false);
282
+ if (request !== requestId.current) return;
283
+ setSnapshot({
284
+ scopeKey,
285
+ readKey,
286
+ jobs: [],
287
+ totalJobs: 0,
288
+ hasMore: false,
289
+ isLoading: false,
290
+ error:
291
+ fetchError instanceof Error ? fetchError : new Error('Failed to load pending deliveries'),
292
+ });
252
293
  }
253
- }, [graphQLOptions, limit, offset]);
294
+ }, [graphQLOptions, limit, offset, scopeKey, readKey]);
295
+
296
+ const cancelPendingRead = useCallback(() => {
297
+ requestId.current++;
298
+ }, []);
254
299
 
255
300
  useEffect(() => {
256
301
  void load();
257
- }, [load]);
302
+ return cancelPendingRead;
303
+ }, [load, cancelPendingRead]);
304
+
305
+ const retireAcknowledgedJob = useCallback(
306
+ (deliveryJobId: string) => {
307
+ if (
308
+ acknowledgedJobs.current.scopeKey !== scopeKey ||
309
+ acknowledgedJobs.current.ids.has(deliveryJobId)
310
+ )
311
+ return;
312
+ acknowledgedJobs.current.ids.add(deliveryJobId);
313
+ setSnapshot((previous) => {
314
+ if (previous.scopeKey !== scopeKey) return previous;
315
+ const removed = previous.jobs.some((job) => job.id === deliveryJobId);
316
+ return {
317
+ ...previous,
318
+ jobs: previous.jobs.filter((job) => job.id !== deliveryJobId),
319
+ totalJobs: Math.max(0, previous.totalJobs - (removed ? 1 : 0)),
320
+ };
321
+ });
322
+ },
323
+ [scopeKey]
324
+ );
258
325
 
259
- return { jobs, totalJobs, hasMore, isLoading, error, refetch: load };
326
+ const current = snapshot.readKey === readKey;
327
+ return {
328
+ jobs: current ? snapshot.jobs : [],
329
+ totalJobs: current ? snapshot.totalJobs : 0,
330
+ hasMore: current && snapshot.hasMore,
331
+ isLoading: !current || snapshot.isLoading,
332
+ error: current ? snapshot.error : null,
333
+ refetch: load,
334
+ retireAcknowledgedJob,
335
+ };
260
336
  }
261
337
 
262
338
  export interface CaptureEpodArgs {
@@ -78,7 +78,7 @@ function CaptureForm({
78
78
  onCancel,
79
79
  }: {
80
80
  job: PendingEpodDeliveryJob;
81
- onCaptured: () => void;
81
+ onCaptured: (deliveryJobId: string) => void;
82
82
  onCancel: () => void;
83
83
  }) {
84
84
  const { captureEpod, isSubmitting, error: captureError, captureFeedback } = useCaptureEpod();
@@ -163,7 +163,7 @@ function CaptureForm({
163
163
  const position = await getCurrentPosition();
164
164
  if (!active.current) return;
165
165
 
166
- await captureEpod({
166
+ const proof = await captureEpod({
167
167
  expectedShipmentId: ownedStatus.data.myEpodShipmentStatus?.id ?? null,
168
168
  expectedShipmentStatusRevision: ownedStatus.data.myEpodShipmentStatus?.statusRevision,
169
169
  completionAttestation,
@@ -178,7 +178,8 @@ function CaptureForm({
178
178
  notes: notes.trim() || undefined,
179
179
  });
180
180
 
181
- onCaptured();
181
+ if (!active.current) return;
182
+ onCaptured(proof.deliveryJobId);
182
183
  } catch {
183
184
  setCompletionAttestation(false);
184
185
  setRequiredStatusRefresh(statusRefresh + 1);
@@ -358,14 +359,16 @@ export default function DeliveryCapturePage() {
358
359
  const { workspaceId, tenantId, currentUser, apiGatewayUrl } = useMoveTheWheels();
359
360
  const [pageIndex, setPageIndex] = useState(0);
360
361
  const pageSize = 20;
361
- const { jobs, hasMore, isLoading, error, refetch } = useMyPendingEpodDeliveryJobs({
362
- limit: pageSize,
363
- offset: pageIndex * pageSize,
364
- });
362
+ const { jobs, hasMore, isLoading, error, refetch, retireAcknowledgedJob } =
363
+ useMyPendingEpodDeliveryJobs({
364
+ limit: pageSize,
365
+ offset: pageIndex * pageSize,
366
+ });
365
367
  const [selectedJob, setSelectedJob] = useState<PendingEpodDeliveryJob | null>(null);
366
368
  const { message, notify } = useNotice();
367
369
 
368
- const handleCaptured = () => {
370
+ const handleCaptured = (deliveryJobId: string) => {
371
+ retireAcknowledgedJob(deliveryJobId);
369
372
  notify('Proof of delivery captured — delivery marked complete.');
370
373
  setSelectedJob(null);
371
374
  setPageIndex(0);