@burdenoff/microfe-movethewheels 2026.725.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.
- package/dist/MoveTheWheelsRoutes.js +7 -3
- package/dist/components/ProofOfDeliveryCard.js +155 -0
- package/dist/components/SignaturePad.js +82 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useEntityDocuments.js +4 -4
- package/dist/hooks/useEpod.js +208 -0
- package/dist/index.js +22 -21
- package/dist/movethewheels/components/ProofOfDeliveryCard.d.ts +5 -0
- package/dist/movethewheels/components/SignaturePad.d.ts +11 -0
- package/dist/movethewheels/hooks/index.d.ts +1 -0
- package/dist/movethewheels/hooks/useEntityDocuments.d.ts +17 -1
- package/dist/movethewheels/hooks/useEpod.d.ts +59 -0
- package/dist/movethewheels/pages/DeliveryCapturePage.d.ts +1 -0
- package/dist/movethewheels/types/index.d.ts +18 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/loader-circle.js +8 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/pen-line.js +11 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/type.js +24 -0
- package/dist/pages/DeliveryCapturePage.js +245 -0
- package/dist/pages/OrderDetailsPage.js +14 -12
- package/dist/pages/TrackingPage.js +156 -154
- package/dist/utils/formatters.js +13 -2
- package/package.json +4 -3
- package/src/movethewheels/MoveTheWheelsRoutes.tsx +4 -0
- package/src/movethewheels/components/ProofOfDeliveryCard.tsx +149 -0
- package/src/movethewheels/components/SignaturePad.tsx +157 -0
- package/src/movethewheels/hooks/index.ts +12 -0
- package/src/movethewheels/hooks/useEntityDocuments.ts +30 -12
- package/src/movethewheels/hooks/useEpod.ts +410 -0
- package/src/movethewheels/pages/DeliveryCapturePage.tsx +297 -0
- package/src/movethewheels/pages/OrderDetailsPage.tsx +4 -0
- package/src/movethewheels/pages/TrackingPage.tsx +4 -0
- package/src/movethewheels/types/index.ts +21 -0
|
@@ -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;
|
|
@@ -230,6 +230,24 @@ export interface Order {
|
|
|
230
230
|
createdAt: Date;
|
|
231
231
|
updatedAt: Date;
|
|
232
232
|
}
|
|
233
|
+
export type SignatureType = 'drawn' | 'typed';
|
|
234
|
+
export interface ProofOfDelivery {
|
|
235
|
+
id: string;
|
|
236
|
+
deliveryJobId: string;
|
|
237
|
+
shipmentId?: string;
|
|
238
|
+
recipientName: string;
|
|
239
|
+
signatureType: SignatureType;
|
|
240
|
+
/** Drawn: a `data:image/png;base64,...` capture. Typed: the typed full name. */
|
|
241
|
+
signatureData: string;
|
|
242
|
+
/** wspace-files-svc File ids for any attached delivery photos. */
|
|
243
|
+
photoFileIds: string[];
|
|
244
|
+
latitude?: number;
|
|
245
|
+
longitude?: number;
|
|
246
|
+
locationAccuracy?: number;
|
|
247
|
+
deliveredAt: Date;
|
|
248
|
+
capturedByDriverId: string;
|
|
249
|
+
notes?: string;
|
|
250
|
+
}
|
|
233
251
|
export type VehicleType = 'van' | 'truck' | 'motorcycle' | 'bicycle' | 'car';
|
|
234
252
|
export type VehicleStatus = 'available' | 'assigned' | 'maintenance' | 'out_of_service';
|
|
235
253
|
export interface VehicleDocument {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createLucideIcon as e } from "../createLucideIcon.js";
|
|
2
|
+
//#region node_modules/lucide-react/dist/esm/icons/loader-circle.js
|
|
3
|
+
var t = e("LoaderCircle", [["path", {
|
|
4
|
+
d: "M21 12a9 9 0 1 1-6.219-8.56",
|
|
5
|
+
key: "13zald"
|
|
6
|
+
}]]);
|
|
7
|
+
//#endregion
|
|
8
|
+
export { t as LoaderCircle };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createLucideIcon as e } from "../createLucideIcon.js";
|
|
2
|
+
//#region node_modules/lucide-react/dist/esm/icons/pen-line.js
|
|
3
|
+
var t = e("PenLine", [["path", {
|
|
4
|
+
d: "M12 20h9",
|
|
5
|
+
key: "t2du7b"
|
|
6
|
+
}], ["path", {
|
|
7
|
+
d: "M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z",
|
|
8
|
+
key: "1ykcvy"
|
|
9
|
+
}]]);
|
|
10
|
+
//#endregion
|
|
11
|
+
export { t as PenLine };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createLucideIcon as e } from "../createLucideIcon.js";
|
|
2
|
+
//#region node_modules/lucide-react/dist/esm/icons/type.js
|
|
3
|
+
var t = e("Type", [
|
|
4
|
+
["polyline", {
|
|
5
|
+
points: "4 7 4 4 20 4 20 7",
|
|
6
|
+
key: "1nosan"
|
|
7
|
+
}],
|
|
8
|
+
["line", {
|
|
9
|
+
x1: "9",
|
|
10
|
+
x2: "15",
|
|
11
|
+
y1: "20",
|
|
12
|
+
y2: "20",
|
|
13
|
+
key: "swin9y"
|
|
14
|
+
}],
|
|
15
|
+
["line", {
|
|
16
|
+
x1: "12",
|
|
17
|
+
x2: "12",
|
|
18
|
+
y1: "4",
|
|
19
|
+
y2: "20",
|
|
20
|
+
key: "1tx1rr"
|
|
21
|
+
}]
|
|
22
|
+
]);
|
|
23
|
+
//#endregion
|
|
24
|
+
export { t as Type };
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { CircleCheck as e } from "../node_modules/lucide-react/dist/esm/icons/circle-check.js";
|
|
2
|
+
import { LoaderCircle as t } from "../node_modules/lucide-react/dist/esm/icons/loader-circle.js";
|
|
3
|
+
import { MapPin as n } from "../node_modules/lucide-react/dist/esm/icons/map-pin.js";
|
|
4
|
+
import { Package as r } from "../node_modules/lucide-react/dist/esm/icons/package.js";
|
|
5
|
+
import { PenLine as i } from "../node_modules/lucide-react/dist/esm/icons/pen-line.js";
|
|
6
|
+
import { Truck as a } from "../node_modules/lucide-react/dist/esm/icons/truck.js";
|
|
7
|
+
import { Type as o } from "../node_modules/lucide-react/dist/esm/icons/type.js";
|
|
8
|
+
import { Upload as s } from "../node_modules/lucide-react/dist/esm/icons/upload.js";
|
|
9
|
+
import { useCaptureEpod as c, useEpodPhotoUpload as l, useMyPendingEpodDeliveryJobs as u } from "../hooks/useEpod.js";
|
|
10
|
+
import { Button as d, Card as f, CardContent as p, CardHeader as m, CardTitle as h, Input as g, Label as _, Textarea as v } from "../components/ui.js";
|
|
11
|
+
import { PageLayout as y } from "../components/PageLayout.js";
|
|
12
|
+
import { FormError as b } from "../components/FormError.js";
|
|
13
|
+
import { Notice as x, useNotice as S } from "../components/Notice.js";
|
|
14
|
+
import { formatAddress as C, formatDate as w } from "../utils/formatters.js";
|
|
15
|
+
import { SignaturePad as T } from "../components/SignaturePad.js";
|
|
16
|
+
import { useRef as E, useState as D } from "react";
|
|
17
|
+
import { Fragment as O, jsx as k, jsxs as A } from "react/jsx-runtime";
|
|
18
|
+
//#region src/movethewheels/pages/DeliveryCapturePage.tsx
|
|
19
|
+
function j() {
|
|
20
|
+
return new Promise((e) => {
|
|
21
|
+
if (!navigator.geolocation) {
|
|
22
|
+
e(null);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
navigator.geolocation.getCurrentPosition((t) => e(t), () => e(null), {
|
|
26
|
+
enableHighAccuracy: !0,
|
|
27
|
+
timeout: 8e3,
|
|
28
|
+
maximumAge: 3e4
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function M({ job: r, onCaptured: u, onCancel: y }) {
|
|
33
|
+
let { captureEpod: x, isSubmitting: S, error: w } = c(), { upload: M, isUploading: N, error: P } = l(), F = E(null), [I, L] = D(""), [R, z] = D("drawn"), [B, V] = D(""), [H, U] = D(null), [W, G] = D(""), [K, q] = D(null), J = async () => {
|
|
34
|
+
q(null);
|
|
35
|
+
let e = I.trim();
|
|
36
|
+
if (!e) {
|
|
37
|
+
q("Recipient name is required.");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
let t = R === "typed" ? B.trim() : F.current?.toDataUrl() ?? null;
|
|
41
|
+
if (!t) {
|
|
42
|
+
q(R === "typed" ? "Type the recipient full name as their signature." : "A signature is required.");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
let n;
|
|
47
|
+
H && (n = [(await M(H)).fileId]);
|
|
48
|
+
let i = await j();
|
|
49
|
+
await x({
|
|
50
|
+
deliveryJobId: r.id,
|
|
51
|
+
recipientName: e,
|
|
52
|
+
signatureType: R,
|
|
53
|
+
signatureData: t,
|
|
54
|
+
photoFileIds: n,
|
|
55
|
+
latitude: i?.coords.latitude,
|
|
56
|
+
longitude: i?.coords.longitude,
|
|
57
|
+
locationAccuracy: i?.coords.accuracy,
|
|
58
|
+
notes: W.trim() || void 0
|
|
59
|
+
}), u();
|
|
60
|
+
} catch {}
|
|
61
|
+
}, Y = S || N;
|
|
62
|
+
return /* @__PURE__ */ A(f, { children: [/* @__PURE__ */ k(m, { children: /* @__PURE__ */ A(h, {
|
|
63
|
+
className: "flex items-center gap-2",
|
|
64
|
+
children: [
|
|
65
|
+
/* @__PURE__ */ k(a, { size: 18 }),
|
|
66
|
+
" Capture delivery for ",
|
|
67
|
+
r.deliveryJobNumber
|
|
68
|
+
]
|
|
69
|
+
}) }), /* @__PURE__ */ A(p, {
|
|
70
|
+
className: "space-y-4",
|
|
71
|
+
children: [
|
|
72
|
+
/* @__PURE__ */ A("div", {
|
|
73
|
+
className: "text-sm text-text-secondary space-y-1",
|
|
74
|
+
children: [r.customerName && /* @__PURE__ */ A("p", { children: ["Recipient on file: ", r.customerName] }), r.deliveryAddress && /* @__PURE__ */ k("p", { children: C(r.deliveryAddress) })]
|
|
75
|
+
}),
|
|
76
|
+
/* @__PURE__ */ A("div", {
|
|
77
|
+
className: "space-y-1.5",
|
|
78
|
+
children: [/* @__PURE__ */ k(_, {
|
|
79
|
+
htmlFor: "epod-recipient-name",
|
|
80
|
+
children: "Recipient name"
|
|
81
|
+
}), /* @__PURE__ */ k(g, {
|
|
82
|
+
id: "epod-recipient-name",
|
|
83
|
+
value: I,
|
|
84
|
+
onChange: (e) => L(e.target.value),
|
|
85
|
+
placeholder: "Who received the delivery?"
|
|
86
|
+
})]
|
|
87
|
+
}),
|
|
88
|
+
/* @__PURE__ */ A("div", {
|
|
89
|
+
className: "space-y-1.5",
|
|
90
|
+
children: [
|
|
91
|
+
/* @__PURE__ */ k(_, { children: "Signature" }),
|
|
92
|
+
/* @__PURE__ */ A("div", {
|
|
93
|
+
className: "flex gap-2",
|
|
94
|
+
children: [/* @__PURE__ */ A(d, {
|
|
95
|
+
type: "button",
|
|
96
|
+
variant: R === "drawn" ? "default" : "outline",
|
|
97
|
+
size: "sm",
|
|
98
|
+
onClick: () => z("drawn"),
|
|
99
|
+
children: [/* @__PURE__ */ k(i, { size: 14 }), " Draw"]
|
|
100
|
+
}), /* @__PURE__ */ A(d, {
|
|
101
|
+
type: "button",
|
|
102
|
+
variant: R === "typed" ? "default" : "outline",
|
|
103
|
+
size: "sm",
|
|
104
|
+
onClick: () => z("typed"),
|
|
105
|
+
children: [/* @__PURE__ */ k(o, { size: 14 }), " Type name instead"]
|
|
106
|
+
})]
|
|
107
|
+
}),
|
|
108
|
+
R === "drawn" ? /* @__PURE__ */ k(T, { ref: F }) : /* @__PURE__ */ k(g, {
|
|
109
|
+
value: B,
|
|
110
|
+
onChange: (e) => V(e.target.value),
|
|
111
|
+
placeholder: "Type full name as signature"
|
|
112
|
+
})
|
|
113
|
+
]
|
|
114
|
+
}),
|
|
115
|
+
/* @__PURE__ */ A("div", {
|
|
116
|
+
className: "space-y-1.5",
|
|
117
|
+
children: [
|
|
118
|
+
/* @__PURE__ */ k(_, {
|
|
119
|
+
htmlFor: "epod-photo",
|
|
120
|
+
children: "Delivery photo (optional)"
|
|
121
|
+
}),
|
|
122
|
+
/* @__PURE__ */ A("div", {
|
|
123
|
+
className: "flex items-center gap-2",
|
|
124
|
+
children: [/* @__PURE__ */ k("input", {
|
|
125
|
+
id: "epod-photo",
|
|
126
|
+
type: "file",
|
|
127
|
+
accept: "image/*",
|
|
128
|
+
capture: "environment",
|
|
129
|
+
onChange: (e) => U(e.target.files?.[0] ?? null),
|
|
130
|
+
className: "text-sm"
|
|
131
|
+
}), H && /* @__PURE__ */ k(s, {
|
|
132
|
+
size: 14,
|
|
133
|
+
className: "text-text-secondary"
|
|
134
|
+
})]
|
|
135
|
+
}),
|
|
136
|
+
H && /* @__PURE__ */ k("p", {
|
|
137
|
+
className: "text-xs text-text-secondary",
|
|
138
|
+
children: H.name
|
|
139
|
+
})
|
|
140
|
+
]
|
|
141
|
+
}),
|
|
142
|
+
/* @__PURE__ */ A("div", {
|
|
143
|
+
className: "space-y-1.5",
|
|
144
|
+
children: [/* @__PURE__ */ k(_, {
|
|
145
|
+
htmlFor: "epod-notes",
|
|
146
|
+
children: "Notes (optional)"
|
|
147
|
+
}), /* @__PURE__ */ k(v, {
|
|
148
|
+
id: "epod-notes",
|
|
149
|
+
value: W,
|
|
150
|
+
onChange: (e) => G(e.target.value),
|
|
151
|
+
placeholder: "e.g. Left with front desk, gate code used, etc.",
|
|
152
|
+
rows: 2
|
|
153
|
+
})]
|
|
154
|
+
}),
|
|
155
|
+
/* @__PURE__ */ A("p", {
|
|
156
|
+
className: "flex items-center gap-1.5 text-xs text-text-secondary",
|
|
157
|
+
children: [/* @__PURE__ */ k(n, { size: 12 }), " Device GPS is captured automatically when permitted by the browser."]
|
|
158
|
+
}),
|
|
159
|
+
K && /* @__PURE__ */ k(b, { message: K }),
|
|
160
|
+
w && /* @__PURE__ */ k(b, { message: w.message }),
|
|
161
|
+
P && /* @__PURE__ */ k(b, { message: P.message }),
|
|
162
|
+
/* @__PURE__ */ A("div", {
|
|
163
|
+
className: "flex gap-2 justify-end",
|
|
164
|
+
children: [/* @__PURE__ */ k(d, {
|
|
165
|
+
type: "button",
|
|
166
|
+
variant: "outline",
|
|
167
|
+
onClick: y,
|
|
168
|
+
disabled: Y,
|
|
169
|
+
children: "Cancel"
|
|
170
|
+
}), /* @__PURE__ */ k(d, {
|
|
171
|
+
type: "button",
|
|
172
|
+
onClick: () => void J(),
|
|
173
|
+
disabled: Y,
|
|
174
|
+
children: Y ? /* @__PURE__ */ A(O, { children: [/* @__PURE__ */ k(t, {
|
|
175
|
+
size: 14,
|
|
176
|
+
className: "animate-spin"
|
|
177
|
+
}), " Submitting…"] }) : /* @__PURE__ */ A(O, { children: [/* @__PURE__ */ k(e, { size: 14 }), " Confirm delivery"] })
|
|
178
|
+
})]
|
|
179
|
+
})
|
|
180
|
+
]
|
|
181
|
+
})] });
|
|
182
|
+
}
|
|
183
|
+
function N() {
|
|
184
|
+
let { jobs: t, isLoading: n, error: i, refetch: o } = u(), [s, c] = D(null), { message: l, notify: m } = S();
|
|
185
|
+
return /* @__PURE__ */ k(y, {
|
|
186
|
+
title: "My Deliveries",
|
|
187
|
+
subtitle: "Capture proof of delivery for your assigned stops",
|
|
188
|
+
icon: /* @__PURE__ */ k(a, { size: 24 }),
|
|
189
|
+
children: /* @__PURE__ */ A("div", {
|
|
190
|
+
className: "space-y-4",
|
|
191
|
+
children: [/* @__PURE__ */ k(x, { message: l }), s ? /* @__PURE__ */ k(M, {
|
|
192
|
+
job: s,
|
|
193
|
+
onCaptured: () => {
|
|
194
|
+
m("Proof of delivery captured — delivery marked complete."), c(null), o();
|
|
195
|
+
},
|
|
196
|
+
onCancel: () => c(null)
|
|
197
|
+
}) : n ? /* @__PURE__ */ k("p", {
|
|
198
|
+
className: "text-text-secondary text-center py-8",
|
|
199
|
+
children: "Loading your deliveries…"
|
|
200
|
+
}) : i ? /* @__PURE__ */ k(b, { message: i.message }) : t.length > 0 ? /* @__PURE__ */ k("div", {
|
|
201
|
+
className: "space-y-3",
|
|
202
|
+
children: t.map((e) => /* @__PURE__ */ k(f, { children: /* @__PURE__ */ A(p, {
|
|
203
|
+
className: "flex items-center justify-between gap-3 py-4",
|
|
204
|
+
children: [/* @__PURE__ */ A("div", {
|
|
205
|
+
className: "min-w-0",
|
|
206
|
+
children: [
|
|
207
|
+
/* @__PURE__ */ A("p", {
|
|
208
|
+
className: "font-medium flex items-center gap-2",
|
|
209
|
+
children: [
|
|
210
|
+
/* @__PURE__ */ k(r, { size: 16 }),
|
|
211
|
+
" ",
|
|
212
|
+
e.deliveryJobNumber
|
|
213
|
+
]
|
|
214
|
+
}),
|
|
215
|
+
e.deliveryAddress && /* @__PURE__ */ k("p", {
|
|
216
|
+
className: "text-sm text-text-secondary truncate",
|
|
217
|
+
children: C(e.deliveryAddress)
|
|
218
|
+
}),
|
|
219
|
+
e.scheduledDelivery && /* @__PURE__ */ A("p", {
|
|
220
|
+
className: "text-xs text-text-secondary",
|
|
221
|
+
children: ["Scheduled ", w(e.scheduledDelivery, "short")]
|
|
222
|
+
})
|
|
223
|
+
]
|
|
224
|
+
}), /* @__PURE__ */ k(d, {
|
|
225
|
+
type: "button",
|
|
226
|
+
size: "sm",
|
|
227
|
+
onClick: () => c(e),
|
|
228
|
+
children: "Capture"
|
|
229
|
+
})]
|
|
230
|
+
}) }, e.id))
|
|
231
|
+
}) : /* @__PURE__ */ A("div", {
|
|
232
|
+
className: "text-center py-12",
|
|
233
|
+
children: [/* @__PURE__ */ k(e, {
|
|
234
|
+
size: 40,
|
|
235
|
+
className: "mx-auto mb-3 text-text-secondary opacity-50"
|
|
236
|
+
}), /* @__PURE__ */ k("p", {
|
|
237
|
+
className: "text-text-secondary",
|
|
238
|
+
children: "No deliveries awaiting proof of delivery."
|
|
239
|
+
})]
|
|
240
|
+
})]
|
|
241
|
+
})
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
//#endregion
|
|
245
|
+
export { N as default };
|
|
@@ -25,10 +25,11 @@ import { FormError as xe } from "../components/FormError.js";
|
|
|
25
25
|
import { Notice as Se, useNotice as T } from "../components/Notice.js";
|
|
26
26
|
import { formatAddress as E, formatCurrency as D, formatDate as O } from "../utils/formatters.js";
|
|
27
27
|
import { DocumentsCard as Ce } from "../components/DocumentsCard.js";
|
|
28
|
+
import { ProofOfDeliveryCard as we } from "../components/ProofOfDeliveryCard.js";
|
|
28
29
|
import { useState as k } from "react";
|
|
29
|
-
import { useParams as
|
|
30
|
+
import { useParams as Te } from "react-router-dom";
|
|
30
31
|
import { jsx as A, jsxs as j } from "react/jsx-runtime";
|
|
31
|
-
import { EmphasisPanel as
|
|
32
|
+
import { EmphasisPanel as Ee, NextSteps as De, PagePurpose as Oe } from "@burdenoff/fe-libs/ui";
|
|
32
33
|
//#region src/movethewheels/pages/OrderDetailsPage.tsx
|
|
33
34
|
var M = [
|
|
34
35
|
"pending",
|
|
@@ -49,19 +50,19 @@ var M = [
|
|
|
49
50
|
cancelled: "Cancelled",
|
|
50
51
|
failed: "Failed"
|
|
51
52
|
};
|
|
52
|
-
function
|
|
53
|
+
function ke(e) {
|
|
53
54
|
let t = M.indexOf(e);
|
|
54
55
|
return t === -1 || t >= M.length - 1 ? null : M[t + 1];
|
|
55
56
|
}
|
|
56
57
|
function P() {
|
|
57
|
-
let { orderId: M } =
|
|
58
|
+
let { orderId: M } = Te(), { basePath: P, navigate: F } = le(), { order: I, isLoading: Ae, error: je, refetch: L } = ue(M), { updateOrder: Me, updateOrderStatus: Ne } = de(), { vehicles: Pe, drivers: Fe } = fe(), { message: R, notify: z } = T(), [B, V] = k(""), [H, U] = k(""), [W, G] = k(!1), [K, q] = k(!1), [J, Y] = k(null), X = Pe.filter((e) => e.status === "available" || e.id === I?.vehicleId), Z = Fe.filter((e) => e.status === "available" || e.id === I?.driverId), Ie = async () => {
|
|
58
59
|
if (!M || !B && !H) {
|
|
59
60
|
Y("Pick a vehicle and/or a driver to assign.");
|
|
60
61
|
return;
|
|
61
62
|
}
|
|
62
63
|
G(!0), Y(null);
|
|
63
64
|
try {
|
|
64
|
-
await
|
|
65
|
+
await Me(M, {
|
|
65
66
|
vehicleId: B || void 0,
|
|
66
67
|
driverId: H || void 0
|
|
67
68
|
}), z("Assignment updated."), V(""), U(""), L();
|
|
@@ -74,7 +75,7 @@ function P() {
|
|
|
74
75
|
if (M) {
|
|
75
76
|
q(!0), Y(null);
|
|
76
77
|
try {
|
|
77
|
-
await
|
|
78
|
+
await Ne(M, e), z(t), L();
|
|
78
79
|
} catch (e) {
|
|
79
80
|
Y(e instanceof Error ? e.message : "Failed to update status.");
|
|
80
81
|
} finally {
|
|
@@ -84,7 +85,7 @@ function P() {
|
|
|
84
85
|
}, $ = (e) => {
|
|
85
86
|
F && F(s(P, e));
|
|
86
87
|
};
|
|
87
|
-
return
|
|
88
|
+
return Ae ? /* @__PURE__ */ A(_e, { message: "Loading order details..." }) : je || !I ? /* @__PURE__ */ A(ge, {
|
|
88
89
|
title: "Order not found",
|
|
89
90
|
message: "The order you're looking for doesn't exist or has been removed.",
|
|
90
91
|
onRetry: L
|
|
@@ -124,11 +125,11 @@ function P() {
|
|
|
124
125
|
]
|
|
125
126
|
}),
|
|
126
127
|
children: [
|
|
127
|
-
/* @__PURE__ */ A(
|
|
128
|
+
/* @__PURE__ */ A(Oe, {
|
|
128
129
|
icon: /* @__PURE__ */ A(i, { size: 18 }),
|
|
129
130
|
children: "Everything about this one delivery in a single place — who it's for, where it's going, what's inside, the running cost and the full status history. Use this page to review the order, hand it to a driver, print the docket, or jump into live tracking."
|
|
130
131
|
}),
|
|
131
|
-
/* @__PURE__ */ A(
|
|
132
|
+
/* @__PURE__ */ A(De, {
|
|
132
133
|
storageKey: "movethewheels-order-details",
|
|
133
134
|
steps: [
|
|
134
135
|
{
|
|
@@ -358,7 +359,7 @@ function P() {
|
|
|
358
359
|
}), /* @__PURE__ */ j("div", {
|
|
359
360
|
className: "space-y-6",
|
|
360
361
|
children: [
|
|
361
|
-
/* @__PURE__ */ j(
|
|
362
|
+
/* @__PURE__ */ j(Ee, { children: [/* @__PURE__ */ j("h2", {
|
|
362
363
|
className: "flex items-center gap-2 text-base font-semibold text-text-primary mb-4",
|
|
363
364
|
children: [/* @__PURE__ */ A(ne, { size: 18 }), "Order Summary"]
|
|
364
365
|
}), /* @__PURE__ */ j("div", {
|
|
@@ -492,7 +493,7 @@ function P() {
|
|
|
492
493
|
}),
|
|
493
494
|
/* @__PURE__ */ j(l, {
|
|
494
495
|
className: "w-full",
|
|
495
|
-
onClick:
|
|
496
|
+
onClick: Ie,
|
|
496
497
|
disabled: W || !B && !H,
|
|
497
498
|
children: [/* @__PURE__ */ A(se, { size: 16 }), W ? "Assigning…" : "Assign driver & vehicle"]
|
|
498
499
|
})
|
|
@@ -514,7 +515,7 @@ function P() {
|
|
|
514
515
|
]
|
|
515
516
|
}),
|
|
516
517
|
(() => {
|
|
517
|
-
let e =
|
|
518
|
+
let e = ke(I.status);
|
|
518
519
|
return e ? /* @__PURE__ */ j(l, {
|
|
519
520
|
variant: "outline",
|
|
520
521
|
className: "w-full",
|
|
@@ -544,6 +545,7 @@ function P() {
|
|
|
544
545
|
entityType: "order",
|
|
545
546
|
entityId: I.id
|
|
546
547
|
}),
|
|
548
|
+
/* @__PURE__ */ A(we, { deliveryJobId: I.id }),
|
|
547
549
|
I.specialInstructions && /* @__PURE__ */ j(u, { children: [/* @__PURE__ */ A(f, { children: /* @__PURE__ */ j(p, {
|
|
548
550
|
className: "flex items-center gap-2",
|
|
549
551
|
children: [/* @__PURE__ */ A(re, { size: 18 }), "Special Instructions"]
|