@burdenoff/microfe-movethewheels 2026.726.1 → 2026.728.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/MoveTheWheelsRoutes.js +7 -3
  2. package/dist/components/ProofOfDeliveryCard.js +155 -0
  3. package/dist/components/SignaturePad.js +82 -0
  4. package/dist/hooks/index.js +1 -0
  5. package/dist/hooks/useEpod.js +208 -0
  6. package/dist/index.js +22 -21
  7. package/dist/movethewheels/components/ProofOfDeliveryCard.d.ts +5 -0
  8. package/dist/movethewheels/components/SignaturePad.d.ts +11 -0
  9. package/dist/movethewheels/hooks/index.d.ts +1 -0
  10. package/dist/movethewheels/hooks/useEpod.d.ts +59 -0
  11. package/dist/movethewheels/pages/DeliveryCapturePage.d.ts +1 -0
  12. package/dist/movethewheels/types/index.d.ts +18 -0
  13. package/dist/node_modules/lucide-react/dist/esm/icons/loader-circle.js +8 -0
  14. package/dist/node_modules/lucide-react/dist/esm/icons/pen-line.js +11 -0
  15. package/dist/node_modules/lucide-react/dist/esm/icons/type.js +24 -0
  16. package/dist/pages/DeliveryCapturePage.js +245 -0
  17. package/dist/pages/OrderDetailsPage.js +14 -12
  18. package/dist/pages/TrackingPage.js +156 -154
  19. package/dist/utils/formatters.js +13 -2
  20. package/package.json +1 -1
  21. package/src/movethewheels/MoveTheWheelsRoutes.tsx +4 -0
  22. package/src/movethewheels/components/ProofOfDeliveryCard.tsx +149 -0
  23. package/src/movethewheels/components/SignaturePad.tsx +157 -0
  24. package/src/movethewheels/hooks/index.ts +12 -0
  25. package/src/movethewheels/hooks/useEpod.ts +410 -0
  26. package/src/movethewheels/pages/DeliveryCapturePage.tsx +297 -0
  27. package/src/movethewheels/pages/OrderDetailsPage.tsx +4 -0
  28. package/src/movethewheels/pages/TrackingPage.tsx +4 -0
  29. package/src/movethewheels/types/index.ts +21 -0
@@ -25,8 +25,8 @@ function u() {
25
25
  })
26
26
  });
27
27
  }
28
- var d = n(() => import("./pages/DashboardPage.js")), f = n(() => import("./pages/OrdersListPage.js")), p = n(() => import("./pages/OrderDetailsPage.js")), m = n(() => import("./pages/CreateOrderPage.js")), h = n(() => import("./pages/TrackingPage.js")), g = n(() => import("./pages/LiveTrackingPage.js")), _ = n(() => import("./pages/FleetPage.js")), v = n(() => import("./pages/VehiclesPage.js")), y = n(() => import("./pages/VehicleDetailsPage.js")), b = n(() => import("./pages/DriversPage.js")), x = n(() => import("./pages/DriverDetailsPage.js")), S = n(() => import("./pages/InventoryPage.js")), C = n(() => import("./pages/ProductsPage.js")), w = n(() => import("./pages/ProductDetailsPage.js")), T = n(() => import("./pages/WarehousesPage.js")), E = n(() => import("./pages/WarehouseDetailsPage.js")), D = n(() => import("./pages/CustomersPage.js")), O = n(() => import("./pages/CustomerDetailsPage.js")), k = n(() => import("./pages/RoutesPage.js")), A = n(() => import("./pages/RouteDetailsPage.js")), j = n(() => import("./pages/AnalyticsPage.js")), M = n(() => import("./pages/FinancePage.js")), N = n(() => import("./pages/MarketplacePage.js")), P = n(() => import("./pages/ImportExportPage.js")), F = n(() => import("./pages/ReportsPage.js")), I = n(() => import("./pages/SettingsPage.js")), L = n(() => import("./pages/AIAssistantPage.js"));
29
- function R() {
28
+ var d = n(() => import("./pages/DashboardPage.js")), f = n(() => import("./pages/OrdersListPage.js")), p = n(() => import("./pages/OrderDetailsPage.js")), m = n(() => import("./pages/CreateOrderPage.js")), h = n(() => import("./pages/TrackingPage.js")), g = n(() => import("./pages/LiveTrackingPage.js")), _ = n(() => import("./pages/FleetPage.js")), v = n(() => import("./pages/VehiclesPage.js")), y = n(() => import("./pages/VehicleDetailsPage.js")), b = n(() => import("./pages/DriversPage.js")), x = n(() => import("./pages/DriverDetailsPage.js")), S = n(() => import("./pages/InventoryPage.js")), C = n(() => import("./pages/ProductsPage.js")), w = n(() => import("./pages/ProductDetailsPage.js")), T = n(() => import("./pages/WarehousesPage.js")), E = n(() => import("./pages/WarehouseDetailsPage.js")), D = n(() => import("./pages/CustomersPage.js")), O = n(() => import("./pages/CustomerDetailsPage.js")), k = n(() => import("./pages/RoutesPage.js")), A = n(() => import("./pages/RouteDetailsPage.js")), j = n(() => import("./pages/AnalyticsPage.js")), M = n(() => import("./pages/FinancePage.js")), N = n(() => import("./pages/MarketplacePage.js")), P = n(() => import("./pages/ImportExportPage.js")), F = n(() => import("./pages/ReportsPage.js")), I = n(() => import("./pages/SettingsPage.js")), L = n(() => import("./pages/AIAssistantPage.js")), R = n(() => import("./pages/DeliveryCapturePage.js"));
29
+ function z() {
30
30
  return /* @__PURE__ */ o(t, {
31
31
  fallback: /* @__PURE__ */ o(u, {}),
32
32
  children: /* @__PURE__ */ s(i, { children: [
@@ -58,6 +58,10 @@ function R() {
58
58
  path: "tracking/live",
59
59
  element: /* @__PURE__ */ o(g, {})
60
60
  }),
61
+ /* @__PURE__ */ o(r, {
62
+ path: "deliveries/mine",
63
+ element: /* @__PURE__ */ o(R, {})
64
+ }),
61
65
  /* @__PURE__ */ o(r, {
62
66
  path: "fleet",
63
67
  element: /* @__PURE__ */ o(_, {})
@@ -194,4 +198,4 @@ function R() {
194
198
  });
195
199
  }
196
200
  //#endregion
197
- export { R as MoveTheWheelsRoutes };
201
+ export { z as MoveTheWheelsRoutes };
@@ -0,0 +1,155 @@
1
+ import { CircleCheck as e } from "../node_modules/lucide-react/dist/esm/icons/circle-check.js";
2
+ import { Clock as t } from "../node_modules/lucide-react/dist/esm/icons/clock.js";
3
+ import { Download as n } from "../node_modules/lucide-react/dist/esm/icons/download.js";
4
+ import { MapPin as r } from "../node_modules/lucide-react/dist/esm/icons/map-pin.js";
5
+ import { User as i } from "../node_modules/lucide-react/dist/esm/icons/user.js";
6
+ import { useEpod as a, useEpodPhotoUrl as o } from "../hooks/useEpod.js";
7
+ import { Badge as s, Card as c, CardContent as l, CardHeader as u, CardTitle as d } from "./ui.js";
8
+ import { formatDateTime as f } from "../utils/formatters.js";
9
+ import { jsx as p, jsxs as m } from "react/jsx-runtime";
10
+ //#region src/movethewheels/components/ProofOfDeliveryCard.tsx
11
+ function h({ fileId: e }) {
12
+ let { url: t, isLoading: n } = o(e);
13
+ return n ? /* @__PURE__ */ p("div", { className: "h-20 w-20 rounded-lg bg-bg-sunken animate-pulse" }) : t ? /* @__PURE__ */ p("a", {
14
+ href: t,
15
+ target: "_blank",
16
+ rel: "noopener noreferrer",
17
+ className: "shrink-0",
18
+ children: /* @__PURE__ */ p("img", {
19
+ src: t,
20
+ alt: "Delivery photo",
21
+ className: "h-20 w-20 rounded-lg object-cover border border-border"
22
+ })
23
+ }) : null;
24
+ }
25
+ function g({ deliveryJobId: o }) {
26
+ let { epod: g, isLoading: _, error: v } = a(o);
27
+ return /* @__PURE__ */ m(c, { children: [/* @__PURE__ */ m(u, {
28
+ className: "flex flex-row items-center justify-between",
29
+ children: [/* @__PURE__ */ m(d, {
30
+ className: "flex items-center gap-2",
31
+ children: [/* @__PURE__ */ p(e, { size: 18 }), " Proof of Delivery"]
32
+ }), g && /* @__PURE__ */ p(s, {
33
+ variant: "success",
34
+ children: "Captured"
35
+ })]
36
+ }), /* @__PURE__ */ p(l, { children: _ ? /* @__PURE__ */ p("p", {
37
+ className: "text-text-secondary text-center py-4",
38
+ children: "Loading proof of delivery…"
39
+ }) : v ? /* @__PURE__ */ p("p", {
40
+ className: "text-sm text-status-error-text text-center py-4",
41
+ children: "Failed to load proof of delivery."
42
+ }) : g ? /* @__PURE__ */ m("div", {
43
+ className: "space-y-4",
44
+ children: [
45
+ /* @__PURE__ */ m("div", {
46
+ className: "grid grid-cols-1 sm:grid-cols-2 gap-4",
47
+ children: [
48
+ /* @__PURE__ */ m("div", {
49
+ className: "flex items-start gap-2",
50
+ children: [/* @__PURE__ */ p(i, {
51
+ size: 16,
52
+ className: "mt-0.5 text-text-secondary shrink-0"
53
+ }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
54
+ className: "text-xs text-text-secondary",
55
+ children: "Received by"
56
+ }), /* @__PURE__ */ p("p", {
57
+ className: "font-medium",
58
+ children: g.recipientName
59
+ })] })]
60
+ }),
61
+ /* @__PURE__ */ m("div", {
62
+ className: "flex items-start gap-2",
63
+ children: [/* @__PURE__ */ p(t, {
64
+ size: 16,
65
+ className: "mt-0.5 text-text-secondary shrink-0"
66
+ }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
67
+ className: "text-xs text-text-secondary",
68
+ children: "Delivered at"
69
+ }), /* @__PURE__ */ p("p", {
70
+ className: "font-medium",
71
+ children: f(g.deliveredAt)
72
+ })] })]
73
+ }),
74
+ g.latitude != null && g.longitude != null && /* @__PURE__ */ m("div", {
75
+ className: "flex items-start gap-2 sm:col-span-2",
76
+ children: [/* @__PURE__ */ p(r, {
77
+ size: 16,
78
+ className: "mt-0.5 text-text-secondary shrink-0"
79
+ }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
80
+ className: "text-xs text-text-secondary",
81
+ children: "Delivery location"
82
+ }), /* @__PURE__ */ m("p", {
83
+ className: "font-medium",
84
+ children: [
85
+ g.latitude.toFixed(5),
86
+ ", ",
87
+ g.longitude.toFixed(5),
88
+ g.locationAccuracy != null && /* @__PURE__ */ m("span", {
89
+ className: "text-text-secondary",
90
+ children: [
91
+ " (±",
92
+ Math.round(g.locationAccuracy),
93
+ "m)"
94
+ ]
95
+ })
96
+ ]
97
+ })] })]
98
+ })
99
+ ]
100
+ }),
101
+ g.notes && /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
102
+ className: "text-xs text-text-secondary mb-1",
103
+ children: "Notes"
104
+ }), /* @__PURE__ */ p("p", {
105
+ className: "text-sm",
106
+ children: g.notes
107
+ })] }),
108
+ /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ m("p", {
109
+ className: "text-xs text-text-secondary mb-1",
110
+ children: ["Signature ", g.signatureType === "typed" ? "(typed)" : "(drawn)"]
111
+ }), g.signatureType === "drawn" ? /* @__PURE__ */ p("div", {
112
+ className: "border rounded-lg p-2 inline-block bg-white",
113
+ children: /* @__PURE__ */ p("img", {
114
+ src: g.signatureData,
115
+ alt: "Recipient signature",
116
+ className: "h-16"
117
+ })
118
+ }) : /* @__PURE__ */ p("p", {
119
+ className: "text-lg italic font-medium border-b border-border inline-block pb-1",
120
+ children: g.signatureData
121
+ })] }),
122
+ g.photoFileIds.length > 0 && /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
123
+ className: "text-xs text-text-secondary mb-2",
124
+ children: "Delivery photos"
125
+ }), /* @__PURE__ */ p("div", {
126
+ className: "flex flex-wrap gap-2",
127
+ children: g.photoFileIds.map((e) => /* @__PURE__ */ p(h, { fileId: e }, e))
128
+ })] }),
129
+ /* @__PURE__ */ m("a", {
130
+ href: `data:text/plain;charset=utf-8,${encodeURIComponent(`Proof of Delivery\nRecipient: ${g.recipientName}\nDelivered at: ${f(g.deliveredAt)}${g.latitude != null && g.longitude != null ? `\nLocation: ${g.latitude}, ${g.longitude}` : ""}${g.notes ? `\nNotes: ${g.notes}` : ""}`)}`,
131
+ download: `pod-${o}.txt`,
132
+ className: "inline-flex items-center gap-1 text-sm text-primary hover:underline",
133
+ children: [/* @__PURE__ */ p(n, { size: 14 }), " Download record"]
134
+ })
135
+ ]
136
+ }) : /* @__PURE__ */ m("div", {
137
+ className: "text-center py-6",
138
+ children: [
139
+ /* @__PURE__ */ p(e, {
140
+ size: 32,
141
+ className: "mx-auto mb-2 text-text-secondary opacity-50"
142
+ }),
143
+ /* @__PURE__ */ p("p", {
144
+ className: "text-text-secondary",
145
+ children: "Not yet delivered"
146
+ }),
147
+ /* @__PURE__ */ p("p", {
148
+ className: "text-xs text-text-secondary mt-1",
149
+ children: "Proof of delivery will appear here once the driver completes capture."
150
+ })
151
+ ]
152
+ }) })] });
153
+ }
154
+ //#endregion
155
+ export { g as ProofOfDeliveryCard };
@@ -0,0 +1,82 @@
1
+ import { cn as e } from "../utils/cn.js";
2
+ import { Button as t } from "./ui.js";
3
+ import { forwardRef as n, useCallback as r, useEffect as i, useImperativeHandle as a, useRef as o, useState as s } from "react";
4
+ import { jsx as c, jsxs as l } from "react/jsx-runtime";
5
+ //#region src/movethewheels/components/SignaturePad.tsx
6
+ var u = n(({ className: n, onChange: u }, d) => {
7
+ let f = o(null), p = o(!1), m = o(!1), h = o(null), [g, _] = s(!1), v = r(() => {
8
+ let e = f.current;
9
+ return e ? e.getContext("2d") : null;
10
+ }, []);
11
+ i(() => {
12
+ let e = f.current, t = v();
13
+ if (!e || !t) return;
14
+ let n = window.devicePixelRatio || 1, r = e.getBoundingClientRect();
15
+ e.width = r.width * n, e.height = r.height * n, t.scale(n, n), t.lineWidth = 2, t.lineCap = "round", t.lineJoin = "round", t.strokeStyle = getComputedStyle(e).color || "currentColor";
16
+ }, [v]);
17
+ let y = r((e) => {
18
+ let t = f.current;
19
+ if (!t) return {
20
+ x: 0,
21
+ y: 0
22
+ };
23
+ let n = t.getBoundingClientRect();
24
+ return {
25
+ x: e.clientX - n.left,
26
+ y: e.clientY - n.top
27
+ };
28
+ }, []), b = r((e) => {
29
+ let t = f.current, n = v();
30
+ !t || !n || (t.setPointerCapture(e.pointerId), p.current = !0, h.current = y(e));
31
+ }, [v, y]), x = r((e) => {
32
+ if (!p.current) return;
33
+ let t = v(), n = h.current;
34
+ if (!t || !n) return;
35
+ let r = y(e);
36
+ t.beginPath(), t.moveTo(n.x, n.y), t.lineTo(r.x, r.y), t.stroke(), h.current = r, m.current || (m.current = !0, _(!0), u?.(!0));
37
+ }, [
38
+ v,
39
+ u,
40
+ y
41
+ ]), S = r((e) => {
42
+ p.current = !1, h.current = null;
43
+ let t = f.current;
44
+ t?.hasPointerCapture(e.pointerId) && t.releasePointerCapture(e.pointerId);
45
+ }, []), C = r(() => {
46
+ let e = f.current, t = v();
47
+ !e || !t || (t.clearRect(0, 0, e.width, e.height), m.current = !1, _(!1), u?.(!1));
48
+ }, [v, u]), w = r(() => m.current ? f.current?.toDataURL("image/png") ?? null : null, []);
49
+ return a(d, () => ({
50
+ clear: C,
51
+ isEmpty: () => !m.current,
52
+ toDataUrl: w
53
+ }), [C, w]), /* @__PURE__ */ l("div", {
54
+ className: e("space-y-2", n),
55
+ children: [/* @__PURE__ */ c("canvas", {
56
+ ref: f,
57
+ className: "w-full h-40 rounded-lg border-2 border-dashed border-border bg-bg-surface text-text-primary touch-none cursor-crosshair",
58
+ onPointerDown: b,
59
+ onPointerMove: x,
60
+ onPointerUp: S,
61
+ onPointerLeave: S,
62
+ role: "img",
63
+ "aria-label": "Signature capture pad"
64
+ }), /* @__PURE__ */ l("div", {
65
+ className: "flex items-center justify-between",
66
+ children: [/* @__PURE__ */ c("p", {
67
+ className: "text-xs text-text-secondary",
68
+ children: g ? "Signature captured" : "Sign above with your finger or mouse"
69
+ }), /* @__PURE__ */ c(t, {
70
+ type: "button",
71
+ variant: "ghost",
72
+ size: "sm",
73
+ onClick: C,
74
+ disabled: !g,
75
+ children: "Clear"
76
+ })]
77
+ })]
78
+ });
79
+ });
80
+ u.displayName = "SignaturePad";
81
+ //#endregion
82
+ export { u as SignaturePad };
@@ -9,3 +9,4 @@ import "./useReports.js";
9
9
  import "./useImportExport.js";
10
10
  import "./useSettings.js";
11
11
  import "./useEntityDocuments.js";
12
+ import "./useEpod.js";
@@ -0,0 +1,208 @@
1
+ import { useMoveTheWheels as e } from "../providers/MoveTheWheelsProvider.js";
2
+ import { executeGraphQL as t } from "../utils/graphqlClient.js";
3
+ import { useCallback as n, useEffect as r, useMemo as i, useState as a } from "react";
4
+ //#region src/movethewheels/hooks/useEpod.ts
5
+ var o = "\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", s = `
6
+ query GetEpod($deliveryJobId: ID!) {
7
+ epod(deliveryJobId: $deliveryJobId) {
8
+ ${o}
9
+ }
10
+ }
11
+ `, c = "\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 }\n", l = `
12
+ mutation CaptureEpod($input: CaptureEpodInput!) {
13
+ captureEpod(input: $input) {
14
+ ${o}
15
+ }
16
+ }
17
+ `, u = "\n mutation EpodInitiateUpload($input: InitiateUploadInput!) {\n initiateUpload(input: $input) {\n uploadUrl\n session { id }\n }\n }\n", d = "\n mutation EpodCompleteUpload($input: CompleteUploadInput!) {\n completeUpload(input: $input) {\n fileId\n }\n }\n", f = "\n query EpodFileUrl($id: ID!, $expiresIn: Int) {\n getFileDownloadUrl(id: $id, expiresIn: $expiresIn)\n }\n", p = 21600;
18
+ function m(e) {
19
+ return e === "typed" ? "TYPED" : "DRAWN";
20
+ }
21
+ function h(e) {
22
+ return {
23
+ id: e.id,
24
+ deliveryJobId: e.deliveryJobId,
25
+ shipmentId: e.shipmentId ?? void 0,
26
+ recipientName: e.recipientName,
27
+ signatureType: e.signatureType === "TYPED" ? "typed" : "drawn",
28
+ signatureData: e.signatureData,
29
+ photoFileIds: e.photoFileIds ?? [],
30
+ latitude: e.latitude ?? void 0,
31
+ longitude: e.longitude ?? void 0,
32
+ locationAccuracy: e.locationAccuracy ?? void 0,
33
+ deliveredAt: new Date(e.deliveredAt),
34
+ capturedByDriverId: e.capturedByDriverId,
35
+ notes: e.notes ?? void 0
36
+ };
37
+ }
38
+ function g() {
39
+ let { apiGatewayUrl: t, authToken: n, workspaceToken: r, workspaceId: a, tenantId: o, currentUser: s } = e();
40
+ return i(() => ({
41
+ apiGatewayUrl: t,
42
+ authToken: n,
43
+ workspaceToken: r,
44
+ workspaceId: a,
45
+ tenantId: o,
46
+ actorId: s?.id
47
+ }), [
48
+ t,
49
+ n,
50
+ r,
51
+ a,
52
+ o,
53
+ s?.id
54
+ ]);
55
+ }
56
+ function _(e) {
57
+ let i = g(), [o, c] = a(null), [l, u] = a(!1), [d, f] = a(null), p = n(async () => {
58
+ if (!e) {
59
+ c(null);
60
+ return;
61
+ }
62
+ u(!0), f(null);
63
+ try {
64
+ let n = await t(i, s, { deliveryJobId: e });
65
+ c(n.epod ? h(n.epod) : null);
66
+ } catch (e) {
67
+ f(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load proof of delivery")), c(null);
68
+ } finally {
69
+ u(!1);
70
+ }
71
+ }, [e, i]);
72
+ return r(() => {
73
+ p();
74
+ }, [p]), {
75
+ epod: o,
76
+ isLoading: l,
77
+ error: d,
78
+ refetch: p
79
+ };
80
+ }
81
+ function v() {
82
+ let e = g(), [i, o] = a([]), [s, l] = a(!1), [u, d] = a(null), f = n(async () => {
83
+ l(!0), d(null);
84
+ try {
85
+ o((await t(e, c, { pagination: {
86
+ limit: 50,
87
+ offset: 0
88
+ } })).myPendingEpodDeliveryJobs.map((e) => ({
89
+ id: e.id,
90
+ deliveryJobNumber: e.deliveryJobNumber,
91
+ status: e.status,
92
+ priority: e.priority,
93
+ deliveryAddress: e.deliveryAddress,
94
+ scheduledDelivery: e.scheduledDelivery ? new Date(e.scheduledDelivery) : void 0,
95
+ customerName: e.customer?.name ?? void 0,
96
+ customerPhone: e.customer?.phone ?? void 0
97
+ })));
98
+ } catch (e) {
99
+ d(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load pending deliveries")), o([]);
100
+ } finally {
101
+ l(!1);
102
+ }
103
+ }, [e]);
104
+ return r(() => {
105
+ f();
106
+ }, [f]), {
107
+ jobs: i,
108
+ isLoading: s,
109
+ error: u,
110
+ refetch: f
111
+ };
112
+ }
113
+ function y() {
114
+ let e = g(), [r, i] = a(!1), [o, s] = a(null);
115
+ return {
116
+ captureEpod: n(async (n) => {
117
+ i(!0), s(null);
118
+ try {
119
+ return h((await t(e, l, { input: {
120
+ deliveryJobId: n.deliveryJobId,
121
+ recipientName: n.recipientName,
122
+ signatureType: m(n.signatureType),
123
+ signatureData: n.signatureData,
124
+ photoFileIds: n.photoFileIds,
125
+ latitude: n.latitude,
126
+ longitude: n.longitude,
127
+ locationAccuracy: n.locationAccuracy,
128
+ notes: n.notes
129
+ } })).captureEpod);
130
+ } catch (e) {
131
+ let t = e instanceof Error ? e : /* @__PURE__ */ Error("Failed to capture proof of delivery");
132
+ throw s(t), t;
133
+ } finally {
134
+ i(!1);
135
+ }
136
+ }, [e]),
137
+ isSubmitting: r,
138
+ error: o
139
+ };
140
+ }
141
+ function b() {
142
+ let e = g(), [r, i] = a(!1), [o, s] = a(0), [c, l] = a(null);
143
+ return {
144
+ upload: n(async (n) => {
145
+ i(!0), s(0), l(null);
146
+ try {
147
+ let r = n.name.lastIndexOf("."), i = r > -1 ? n.name.slice(r + 1) : "", a = n.type || "application/octet-stream", o = await t(e, u, { input: {
148
+ fileName: n.name,
149
+ extension: i,
150
+ mimeType: a,
151
+ fileSize: String(n.size),
152
+ visibility: "WORKSPACE"
153
+ } }), { uploadUrl: c } = o.initiateUpload, l = o.initiateUpload.session.id;
154
+ if (!c) throw Error("The file service did not return an upload URL.");
155
+ s(50);
156
+ let f = await fetch(c, {
157
+ method: "PUT",
158
+ headers: { "Content-Type": a },
159
+ body: n
160
+ });
161
+ if (!f.ok) throw Error(`File storage rejected the upload (HTTP ${f.status}).`);
162
+ let p = await t(e, d, { input: {
163
+ sessionId: l,
164
+ fileSize: String(n.size)
165
+ } });
166
+ return s(100), {
167
+ fileId: p.completeUpload.fileId,
168
+ fileName: n.name
169
+ };
170
+ } catch (e) {
171
+ let t = e instanceof Error ? e : /* @__PURE__ */ Error("The photo could not be uploaded.");
172
+ throw l(t), t;
173
+ } finally {
174
+ i(!1);
175
+ }
176
+ }, [e]),
177
+ isUploading: r,
178
+ progress: o,
179
+ error: c
180
+ };
181
+ }
182
+ function x(e) {
183
+ let n = g(), [i, o] = a(null), [s, c] = a(!1);
184
+ return r(() => {
185
+ if (!e) {
186
+ o(null);
187
+ return;
188
+ }
189
+ let r = !1;
190
+ return c(!0), t(n, f, {
191
+ id: e,
192
+ expiresIn: p
193
+ }).then((e) => {
194
+ r || o(e.getFileDownloadUrl ?? null);
195
+ }).catch(() => {
196
+ r || o(null);
197
+ }).finally(() => {
198
+ r || c(!1);
199
+ }), () => {
200
+ r = !0;
201
+ };
202
+ }, [e, n]), {
203
+ url: i,
204
+ isLoading: s
205
+ };
206
+ }
207
+ //#endregion
208
+ export { y as useCaptureEpod, _ as useEpod, b as useEpodPhotoUpload, x as useEpodPhotoUrl, v as useMyPendingEpodDeliveryJobs };
package/dist/index.js CHANGED
@@ -13,26 +13,27 @@ import { useReports as B } from "./hooks/useReports.js";
13
13
  import { useImportExport as V } from "./hooks/useImportExport.js";
14
14
  import { useModuleSettings as H } from "./hooks/useSettings.js";
15
15
  import { useEntityDocuments as U } from "./hooks/useEntityDocuments.js";
16
+ import { useCaptureEpod as W, useEpod as G, useEpodPhotoUpload as K, useEpodPhotoUrl as q, useMyPendingEpodDeliveryJobs as J } from "./hooks/useEpod.js";
16
17
  import "./hooks/index.js";
17
- import { Avatar as W, AvatarFallback as G, AvatarImage as K, Badge as q, Button as J, Card as Y, CardContent as X, CardDescription as Z, CardFooter as Q, CardHeader as $, CardTitle as ee, Checkbox as te, Dialog as ne, DialogContent as re, DialogDescription as ie, DialogFooter as ae, DialogHeader as oe, DialogTitle as se, DialogTrigger as ce, DropdownMenu as le, DropdownMenuContent as ue, DropdownMenuItem as de, DropdownMenuSeparator as fe, DropdownMenuTrigger as pe, Input as me, Label as he, Progress as ge, ScrollArea as _e, Select as ve, SelectContent as ye, SelectItem as be, SelectTrigger as xe, SelectValue as Se, Separator as Ce, Skeleton as we, Switch as Te, Table as Ee, TableBody as De, TableCell as Oe, TableHead as ke, TableHeader as Ae, TableRow as je, Tabs as Me, TabsContent as Ne, TabsList as Pe, TabsTrigger as Fe, Textarea as Ie, Tooltip as Le, TooltipContent as Re, TooltipProvider as ze, TooltipTrigger as Be } from "./components/ui.js";
18
- import { EmptyState as Ve, ErrorState as He, LoadingState as Ue, PageLayout as We, PageSection as Ge } from "./components/PageLayout.js";
19
- import { chartTokens as Ke, seriesColor as qe } from "./components/charts/chartTokens.js";
20
- import { Sparkline as Je } from "./components/charts/Sparkline.js";
21
- import { MetricCard as Ye, MetricCardSkeleton as Xe, MetricGrid as Ze } from "./components/MetricCard.js";
22
- import { GlassPanel as Qe } from "./components/GlassPanel.js";
23
- import { ChartEmpty as $e, ChartTooltip as et } from "./components/charts/ChartShell.js";
24
- import { TrendChart as tt } from "./components/charts/TrendChart.js";
25
- import { VolumeBar as nt } from "./components/charts/VolumeBar.js";
26
- import { StatusDonut as rt } from "./components/charts/StatusDonut.js";
27
- import { createCurrentIcon as it, createPinIcon as at, createStopIcon as ot, isRealCoord as st } from "./components/maps/leaflet-setup.js";
28
- import { MapCanvas as ct } from "./components/maps/MapCanvas.js";
29
- import { LogisticsMap as lt } from "./components/maps/LogisticsMap.js";
30
- import { RouteMap as ut } from "./components/maps/RouteMap.js";
31
- import { TrackingMap as dt } from "./components/maps/TrackingMap.js";
32
- import { PaymentStatusBadge as ft, PriorityBadge as pt, StatusBadge as mt, TypeBadge as ht, VehicleTypeBadge as gt } from "./components/StatusBadge.js";
33
- import { DataTable as _t } from "./components/DataTable.js";
34
- import { FormError as vt } from "./components/FormError.js";
35
- import { Notice as yt, useNotice as bt } from "./components/Notice.js";
36
- import { DocumentsCard as xt } from "./components/DocumentsCard.js";
18
+ import { Avatar as Y, AvatarFallback as X, AvatarImage as Z, Badge as Q, Button as $, Card as ee, CardContent as te, CardDescription as ne, CardFooter as re, CardHeader as ie, CardTitle as ae, Checkbox as oe, Dialog as se, DialogContent as ce, DialogDescription as le, DialogFooter as ue, DialogHeader as de, DialogTitle as fe, DialogTrigger as pe, DropdownMenu as me, DropdownMenuContent as he, DropdownMenuItem as ge, DropdownMenuSeparator as _e, DropdownMenuTrigger as ve, Input as ye, Label as be, Progress as xe, ScrollArea as Se, Select as Ce, SelectContent as we, SelectItem as Te, SelectTrigger as Ee, SelectValue as De, Separator as Oe, Skeleton as ke, Switch as Ae, Table as je, TableBody as Me, TableCell as Ne, TableHead as Pe, TableHeader as Fe, TableRow as Ie, Tabs as Le, TabsContent as Re, TabsList as ze, TabsTrigger as Be, Textarea as Ve, Tooltip as He, TooltipContent as Ue, TooltipProvider as We, TooltipTrigger as Ge } from "./components/ui.js";
19
+ import { EmptyState as Ke, ErrorState as qe, LoadingState as Je, PageLayout as Ye, PageSection as Xe } from "./components/PageLayout.js";
20
+ import { chartTokens as Ze, seriesColor as Qe } from "./components/charts/chartTokens.js";
21
+ import { Sparkline as $e } from "./components/charts/Sparkline.js";
22
+ import { MetricCard as et, MetricCardSkeleton as tt, MetricGrid as nt } from "./components/MetricCard.js";
23
+ import { GlassPanel as rt } from "./components/GlassPanel.js";
24
+ import { ChartEmpty as it, ChartTooltip as at } from "./components/charts/ChartShell.js";
25
+ import { TrendChart as ot } from "./components/charts/TrendChart.js";
26
+ import { VolumeBar as st } from "./components/charts/VolumeBar.js";
27
+ import { StatusDonut as ct } from "./components/charts/StatusDonut.js";
28
+ import { createCurrentIcon as lt, createPinIcon as ut, createStopIcon as dt, isRealCoord as ft } from "./components/maps/leaflet-setup.js";
29
+ import { MapCanvas as pt } from "./components/maps/MapCanvas.js";
30
+ import { LogisticsMap as mt } from "./components/maps/LogisticsMap.js";
31
+ import { RouteMap as ht } from "./components/maps/RouteMap.js";
32
+ import { TrackingMap as gt } from "./components/maps/TrackingMap.js";
33
+ import { PaymentStatusBadge as _t, PriorityBadge as vt, StatusBadge as yt, TypeBadge as bt, VehicleTypeBadge as xt } from "./components/StatusBadge.js";
34
+ import { DataTable as St } from "./components/DataTable.js";
35
+ import { FormError as Ct } from "./components/FormError.js";
36
+ import { Notice as wt, useNotice as Tt } from "./components/Notice.js";
37
+ import { DocumentsCard as Et } from "./components/DocumentsCard.js";
37
38
  import "./components/index.js";
38
- export { W as Avatar, G as AvatarFallback, K as AvatarImage, q as Badge, J as Button, Y as Card, X as CardContent, Z as CardDescription, Q as CardFooter, $ as CardHeader, ee as CardTitle, $e as ChartEmpty, et as ChartTooltip, te as Checkbox, _t as DataTable, ne as Dialog, re as DialogContent, ie as DialogDescription, ae as DialogFooter, oe as DialogHeader, se as DialogTitle, ce as DialogTrigger, xt as DocumentsCard, le as DropdownMenu, ue as DropdownMenuContent, de as DropdownMenuItem, fe as DropdownMenuSeparator, pe as DropdownMenuTrigger, Ve as EmptyState, He as ErrorState, vt as FormError, Qe as GlassPanel, me as Input, he as Label, Ue as LoadingState, lt as LogisticsMap, ct as MapCanvas, Ye as MetricCard, Xe as MetricCardSkeleton, Ze as MetricGrid, n as MoveTheWheelsRoot, yt as Notice, We as PageLayout, Ge as PageSection, ft as PaymentStatusBadge, pt as PriorityBadge, ge as Progress, ut as RouteMap, _e as ScrollArea, ve as Select, ye as SelectContent, be as SelectItem, xe as SelectTrigger, Se as SelectValue, Ce as Separator, we as Skeleton, Je as Sparkline, mt as StatusBadge, rt as StatusDonut, Te as Switch, Ee as Table, De as TableBody, Oe as TableCell, ke as TableHead, Ae as TableHeader, je as TableRow, Me as Tabs, Ne as TabsContent, Pe as TabsList, Fe as TabsTrigger, Ie as Textarea, Le as Tooltip, Re as TooltipContent, ze as TooltipProvider, Be as TooltipTrigger, dt as TrackingMap, tt as TrendChart, ht as TypeBadge, gt as VehicleTypeBadge, nt as VolumeBar, Ke as chartTokens, it as createCurrentIcon, at as createPinIcon, ot as createStopIcon, st as isRealCoord, qe as seriesColor, E as useAnalytics, b as useCustomer, x as useCustomerStats, S as useCustomers, D as useDashboardMetrics, c as useDriver, N as useDriverTracking, l as useDrivers, U as useEntityDocuments, O as useFinanceMetrics, u as useFleet, k as useFleetAnalytics, d as useFleetStats, P as useGeofence, V as useImportExport, m as useInventory, h as useInventoryStats, F as useLiveTracking, H as useModuleSettings, e as useMoveTheWheels, t as useMoveTheWheelsNavigate, r as useMoveTheWheelsStore, bt as useNotice, a as useOrder, A as useOrderAnalytics, o as useOrderStats, I as useOrderTracking, s as useOrders, j as usePerformanceAnalytics, g as useProduct, _ as useProducts, B as useReports, M as useRevenueAnalytics, C as useRoute, w as useRouteStats, T as useRoutes, i as useSandboxAssistantTransport, L as useTracking, R as useTrackingAlerts, f as useVehicle, z as useVehicleTracking, p as useVehicles, v as useWarehouse, y as useWarehouses };
39
+ export { Y as Avatar, X as AvatarFallback, Z as AvatarImage, Q as Badge, $ as Button, ee as Card, te as CardContent, ne as CardDescription, re as CardFooter, ie as CardHeader, ae as CardTitle, it as ChartEmpty, at as ChartTooltip, oe as Checkbox, St as DataTable, se as Dialog, ce as DialogContent, le as DialogDescription, ue as DialogFooter, de as DialogHeader, fe as DialogTitle, pe as DialogTrigger, Et as DocumentsCard, me as DropdownMenu, he as DropdownMenuContent, ge as DropdownMenuItem, _e as DropdownMenuSeparator, ve as DropdownMenuTrigger, Ke as EmptyState, qe as ErrorState, Ct as FormError, rt as GlassPanel, ye as Input, be as Label, Je as LoadingState, mt as LogisticsMap, pt as MapCanvas, et as MetricCard, tt as MetricCardSkeleton, nt as MetricGrid, n as MoveTheWheelsRoot, wt as Notice, Ye as PageLayout, Xe as PageSection, _t as PaymentStatusBadge, vt as PriorityBadge, xe as Progress, ht as RouteMap, Se as ScrollArea, Ce as Select, we as SelectContent, Te as SelectItem, Ee as SelectTrigger, De as SelectValue, Oe as Separator, ke as Skeleton, $e as Sparkline, yt as StatusBadge, ct as StatusDonut, Ae as Switch, je as Table, Me as TableBody, Ne as TableCell, Pe as TableHead, Fe as TableHeader, Ie as TableRow, Le as Tabs, Re as TabsContent, ze as TabsList, Be as TabsTrigger, Ve as Textarea, He as Tooltip, Ue as TooltipContent, We as TooltipProvider, Ge as TooltipTrigger, gt as TrackingMap, ot as TrendChart, bt as TypeBadge, xt as VehicleTypeBadge, st as VolumeBar, Ze as chartTokens, lt as createCurrentIcon, ut as createPinIcon, dt as createStopIcon, ft as isRealCoord, Qe as seriesColor, E as useAnalytics, W as useCaptureEpod, b as useCustomer, x as useCustomerStats, S as useCustomers, D as useDashboardMetrics, c as useDriver, N as useDriverTracking, l as useDrivers, U as useEntityDocuments, G as useEpod, K as useEpodPhotoUpload, q as useEpodPhotoUrl, O as useFinanceMetrics, u as useFleet, k as useFleetAnalytics, d as useFleetStats, P as useGeofence, V as useImportExport, m as useInventory, h as useInventoryStats, F as useLiveTracking, H as useModuleSettings, e as useMoveTheWheels, t as useMoveTheWheelsNavigate, r as useMoveTheWheelsStore, J as useMyPendingEpodDeliveryJobs, Tt as useNotice, a as useOrder, A as useOrderAnalytics, o as useOrderStats, I as useOrderTracking, s as useOrders, j as usePerformanceAnalytics, g as useProduct, _ as useProducts, B as useReports, M as useRevenueAnalytics, C as useRoute, w as useRouteStats, T as useRoutes, i as useSandboxAssistantTransport, L as useTracking, R as useTrackingAlerts, f as useVehicle, z as useVehicleTracking, p as useVehicles, v as useWarehouse, y as useWarehouses };
@@ -0,0 +1,5 @@
1
+ interface ProofOfDeliveryCardProps {
2
+ deliveryJobId: string;
3
+ }
4
+ export declare function ProofOfDeliveryCard({ deliveryJobId }: ProofOfDeliveryCardProps): import("react").JSX.Element;
5
+ export {};
@@ -0,0 +1,11 @@
1
+ export interface SignaturePadHandle {
2
+ clear: () => void;
3
+ isEmpty: () => boolean;
4
+ toDataUrl: () => string | null;
5
+ }
6
+ interface SignaturePadProps {
7
+ className?: string;
8
+ onChange?: (hasSignature: boolean) => void;
9
+ }
10
+ export declare const SignaturePad: import('react').ForwardRefExoticComponent<SignaturePadProps & import('react').RefAttributes<SignaturePadHandle>>;
11
+ export {};
@@ -14,3 +14,4 @@ export { useReports } from './useReports';
14
14
  export { useImportExport } from './useImportExport';
15
15
  export { useModuleSettings } from './useSettings';
16
16
  export { useEntityDocuments, type EntityDocument, type EntityDocumentType, } from './useEntityDocuments';
17
+ export { useEpod, useMyPendingEpodDeliveryJobs, useCaptureEpod, useEpodPhotoUpload, useEpodPhotoUrl, type PendingEpodDeliveryJob, type CaptureEpodArgs, type UploadedEpodPhoto, } from './useEpod';
@@ -0,0 +1,59 @@
1
+ import { Order, ProofOfDelivery, SignatureType } from '../types';
2
+
3
+ /** The shipper/customer-facing view: the completed ePOD record for a delivery job (or null if not yet captured). */
4
+ export declare function useEpod(deliveryJobId: string | undefined): {
5
+ epod: ProofOfDelivery | null;
6
+ isLoading: boolean;
7
+ error: Error | null;
8
+ refetch: () => Promise<void>;
9
+ };
10
+ export interface PendingEpodDeliveryJob {
11
+ id: string;
12
+ deliveryJobNumber: string;
13
+ status: string;
14
+ priority: string;
15
+ deliveryAddress: Order['deliveryAddress'] | null;
16
+ scheduledDelivery?: Date;
17
+ customerName?: string;
18
+ customerPhone?: string;
19
+ }
20
+ /** Type C self-list: the CALLING driver's own jobs still awaiting ePOD capture — feeds the capture flow's job picker. */
21
+ export declare function useMyPendingEpodDeliveryJobs(): {
22
+ jobs: PendingEpodDeliveryJob[];
23
+ isLoading: boolean;
24
+ error: Error | null;
25
+ refetch: () => Promise<void>;
26
+ };
27
+ export interface CaptureEpodArgs {
28
+ deliveryJobId: string;
29
+ recipientName: string;
30
+ signatureType: SignatureType;
31
+ signatureData: string;
32
+ photoFileIds?: string[];
33
+ latitude?: number;
34
+ longitude?: number;
35
+ locationAccuracy?: number;
36
+ notes?: string;
37
+ }
38
+ /** Driver-facing capture mutation. Identity/ownership is enforced server-side — this never sends a driver id. */
39
+ export declare function useCaptureEpod(): {
40
+ captureEpod: (args: CaptureEpodArgs) => Promise<ProofOfDelivery>;
41
+ isSubmitting: boolean;
42
+ error: Error | null;
43
+ };
44
+ export interface UploadedEpodPhoto {
45
+ fileId: string;
46
+ fileName: string;
47
+ }
48
+ /** Uploads a delivery photo via the platform 3-step file flow and resolves to its `fileId`. */
49
+ export declare function useEpodPhotoUpload(): {
50
+ upload: (file: File) => Promise<UploadedEpodPhoto>;
51
+ isUploading: boolean;
52
+ progress: number;
53
+ error: Error | null;
54
+ };
55
+ /** Resolves a TTL-safe download URL for a captured delivery photo, for display/download. */
56
+ export declare function useEpodPhotoUrl(fileId: string | null | undefined): {
57
+ url: string | null;
58
+ isLoading: boolean;
59
+ };
@@ -0,0 +1 @@
1
+ export default function DeliveryCapturePage(): import("react").JSX.Element;