@burdenoff/microfe-movethewheels 2026.1101.4 → 2026.1102.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/CustomerDeliveryUpdatesFields.js +57 -0
- package/dist/components/CustomerNotificationSettingsCard.js +368 -0
- package/dist/components/freight-cost/FreightCommercialFactEditor.js +46 -46
- package/dist/components/freight-cost/FreightCommercialHistory.js +7 -7
- package/dist/components/freight-cost/FreightDraftForm.js +20 -20
- package/dist/components/freight-invoice/InvoiceReviewPanel.js +255 -0
- package/dist/components/freight-invoice/InvoiceReviewQueue.js +93 -0
- package/dist/generated/freight-invoice-operations.d.ts +461 -0
- package/dist/generated/tracking-quality-operations.d.ts +275 -0
- package/dist/hooks/useCustomers.js +9 -3
- package/dist/hooks/useInvoiceComparisonRecovery.js +26 -26
- package/dist/hooks/useInvoiceReviewPermissions.js +14 -0
- package/dist/movethewheels/components/CustomerDeliveryUpdatesFields.d.ts +12 -0
- package/dist/movethewheels/components/CustomerNotificationSettingsCard.d.ts +3 -0
- package/dist/movethewheels/components/freight-invoice/InvoiceReviewPanel.d.ts +11 -0
- package/dist/movethewheels/components/freight-invoice/InvoiceReviewQueue.d.ts +22 -0
- package/dist/movethewheels/hooks/useInvoiceReviewPermissions.d.ts +5 -0
- package/dist/movethewheels/pages/FinancePage.d.ts +3 -1
- package/dist/movethewheels/types/index.d.ts +4 -0
- package/dist/movethewheels/utils/customerNotifications.d.ts +66 -0
- package/dist/movethewheels/utils/invoiceReview.d.ts +26 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/bell-ring.js +22 -0
- package/dist/pages/CustomerDetailsPage.js +279 -231
- package/dist/pages/FinancePage.js +109 -67
- package/dist/pages/FreightEstimatePage.js +89 -89
- package/dist/pages/FreightInvoicePage.js +138 -120
- package/dist/pages/SettingsPage.js +242 -238
- package/dist/src/generated/freight-invoice-operations.js +2100 -1
- package/dist/utils/customerNotifications.js +83 -0
- package/dist/utils/invoiceReview.js +84 -0
- package/package.json +4 -3
- package/src/generated/freight-invoice-operations.ts +245 -1
- package/src/generated/tracking-quality-operations.ts +304 -0
- package/src/movethewheels/components/CustomerDeliveryUpdatesFields.tsx +67 -0
- package/src/movethewheels/components/CustomerNotificationSettingsCard.tsx +465 -0
- package/src/movethewheels/components/freight-invoice/InvoiceReviewPanel.tsx +319 -0
- package/src/movethewheels/components/freight-invoice/InvoiceReviewQueue.tsx +96 -0
- package/src/movethewheels/hooks/useCustomers.ts +17 -0
- package/src/movethewheels/hooks/useInvoiceReviewPermissions.ts +25 -0
- package/src/movethewheels/pages/CustomerDetailsPage.tsx +39 -0
- package/src/movethewheels/pages/FinancePage.tsx +34 -2
- package/src/movethewheels/pages/FreightInvoicePage.tsx +44 -3
- package/src/movethewheels/pages/SettingsPage.tsx +221 -208
- package/src/movethewheels/types/index.ts +4 -0
- package/src/movethewheels/utils/customerNotifications.ts +209 -0
- package/src/movethewheels/utils/invoiceReview.ts +146 -0
- package/src/operations/freight-invoice/review.graphql +26 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Checkbox as e, Label as t } from "./ui.js";
|
|
2
|
+
import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
3
|
+
//#region src/movethewheels/components/CustomerDeliveryUpdatesFields.tsx
|
|
4
|
+
function i({ idPrefix: i, value: a, onChange: o, disabled: s }) {
|
|
5
|
+
return /* @__PURE__ */ r("fieldset", {
|
|
6
|
+
className: "space-y-3",
|
|
7
|
+
disabled: s,
|
|
8
|
+
"data-testid": `${i}-delivery-updates`,
|
|
9
|
+
children: [
|
|
10
|
+
/* @__PURE__ */ n("legend", {
|
|
11
|
+
className: "text-sm font-medium text-text-primary",
|
|
12
|
+
children: "Delivery updates"
|
|
13
|
+
}),
|
|
14
|
+
/* @__PURE__ */ r("div", {
|
|
15
|
+
className: "flex items-start gap-2",
|
|
16
|
+
children: [/* @__PURE__ */ n(e, {
|
|
17
|
+
id: `${i}-notify-email`,
|
|
18
|
+
checked: a.notifyByEmail,
|
|
19
|
+
disabled: s,
|
|
20
|
+
onCheckedChange: (e) => o({
|
|
21
|
+
...a,
|
|
22
|
+
notifyByEmail: e === !0
|
|
23
|
+
})
|
|
24
|
+
}), /* @__PURE__ */ n(t, {
|
|
25
|
+
htmlFor: `${i}-notify-email`,
|
|
26
|
+
className: "text-sm font-normal leading-snug",
|
|
27
|
+
children: "Email this customer about their shipments"
|
|
28
|
+
})]
|
|
29
|
+
}),
|
|
30
|
+
/* @__PURE__ */ r("div", {
|
|
31
|
+
className: "flex items-start gap-2",
|
|
32
|
+
children: [/* @__PURE__ */ n(e, {
|
|
33
|
+
id: `${i}-notify-sms`,
|
|
34
|
+
checked: a.notifyBySms,
|
|
35
|
+
disabled: s,
|
|
36
|
+
onCheckedChange: (e) => o({
|
|
37
|
+
...a,
|
|
38
|
+
notifyBySms: e === !0
|
|
39
|
+
})
|
|
40
|
+
}), /* @__PURE__ */ n(t, {
|
|
41
|
+
htmlFor: `${i}-notify-sms`,
|
|
42
|
+
className: "text-sm font-normal leading-snug",
|
|
43
|
+
children: "Text this customer about their shipments (only with their consent; the phone number needs its country code, e.g. +91…)"
|
|
44
|
+
})]
|
|
45
|
+
}),
|
|
46
|
+
/* @__PURE__ */ n("p", {
|
|
47
|
+
className: "text-xs text-text-secondary",
|
|
48
|
+
children: "Sent only while customer delivery notifications are on in Settings."
|
|
49
|
+
})
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function a(e) {
|
|
54
|
+
return e.notifyByEmail && e.notifyBySms ? "Email and SMS" : e.notifyByEmail ? "Email" : e.notifyBySms ? "SMS" : "Off";
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
export { i as CustomerDeliveryUpdatesFields, a as deliveryUpdatesSummary };
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { BellRing as e } from "../node_modules/lucide-react/dist/esm/icons/bell-ring.js";
|
|
2
|
+
import { LoaderCircle as t } from "../node_modules/lucide-react/dist/esm/icons/loader-circle.js";
|
|
3
|
+
import { RefreshCw as n } from "../node_modules/lucide-react/dist/esm/icons/refresh-cw.js";
|
|
4
|
+
import { RotateCcw as ee } from "../node_modules/lucide-react/dist/esm/icons/rotate-ccw.js";
|
|
5
|
+
import { Save as te } from "../node_modules/lucide-react/dist/esm/icons/save.js";
|
|
6
|
+
import { useMoveTheWheels as ne } from "../providers/MoveTheWheelsProvider.js";
|
|
7
|
+
import { executeGraphQL as r } from "../utils/graphqlClient.js";
|
|
8
|
+
import { formatDateTime as i } from "../utils/formatters.js";
|
|
9
|
+
import { Badge as a, Button as o, Card as re, CardContent as ie, CardDescription as ae, CardHeader as oe, CardTitle as se, Checkbox as s, Label as c, Skeleton as l, Switch as ce } from "./ui.js";
|
|
10
|
+
import { FormError as u } from "./FormError.js";
|
|
11
|
+
import { Notice as le, useNotice as ue } from "./Notice.js";
|
|
12
|
+
import { CUSTOMER_NOTIFICATION_EVENTS as d, MTW_CUSTOMER_NOTIFICATIONS_QUERY as de, MTW_CUSTOMER_NOTIFICATION_PREVIEWS_QUERY as fe, MTW_CUSTOMER_NOTIFICATION_SETTINGS_QUERY as pe, STATUS_LABELS as me, UPDATE_MTW_CUSTOMER_NOTIFICATION_SETTINGS_MUTATION as he, changedNotificationSettings as ge, defaultNotificationSettings as _e, eventLabel as ve, notificationDraftError as ye, toggleEvent as be } from "../utils/customerNotifications.js";
|
|
13
|
+
import { useCallback as xe, useEffect as f, useMemo as p, useRef as Se, useState as m } from "react";
|
|
14
|
+
import { jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
15
|
+
//#region src/movethewheels/components/CustomerNotificationSettingsCard.tsx
|
|
16
|
+
var Ce = 10, _ = (e) => ({
|
|
17
|
+
enabled: e.enabled,
|
|
18
|
+
emailEnabled: e.emailEnabled,
|
|
19
|
+
smsEnabled: e.smsEnabled,
|
|
20
|
+
events: [...e.events]
|
|
21
|
+
}), we = {
|
|
22
|
+
SENT: "default",
|
|
23
|
+
PENDING: "secondary",
|
|
24
|
+
SKIPPED: "outline",
|
|
25
|
+
FAILED: "destructive"
|
|
26
|
+
};
|
|
27
|
+
function v({ readOnly: v }) {
|
|
28
|
+
let { apiGatewayUrl: y, authToken: b, workspaceToken: x, workspaceId: S, tenantId: C, currentUser: w } = ne(), T = p(() => ({
|
|
29
|
+
apiGatewayUrl: y,
|
|
30
|
+
authToken: b,
|
|
31
|
+
workspaceToken: x,
|
|
32
|
+
workspaceId: S,
|
|
33
|
+
tenantId: C,
|
|
34
|
+
actorId: w?.id
|
|
35
|
+
}), [
|
|
36
|
+
y,
|
|
37
|
+
b,
|
|
38
|
+
x,
|
|
39
|
+
S,
|
|
40
|
+
C,
|
|
41
|
+
w?.id
|
|
42
|
+
]), [E, D] = m(() => _e(S ?? "")), [O, k] = m(() => _(E)), [A, j] = m(!1), [M, N] = m(null), [P, F] = m(!1), [Te, I] = m(null), { message: Ee, notify: De } = ue(), [L, Oe] = m([]), [R, ke] = m(0), [z, B] = m(null), [V, H] = m(!0), [U, Ae] = m([]), [W, je] = m("BOOKED"), [Me, Ne] = m(0), G = Se(0);
|
|
43
|
+
f(() => {
|
|
44
|
+
if (!T.workspaceId) return;
|
|
45
|
+
let e = !1;
|
|
46
|
+
return j(!1), r(T, pe).then((t) => {
|
|
47
|
+
e || (D(t.mtwCustomerNotificationSettings), k(_(t.mtwCustomerNotificationSettings)), N(null), j(!0));
|
|
48
|
+
}).catch((t) => {
|
|
49
|
+
e || N(t instanceof Error ? t.message : "Could not load the settings");
|
|
50
|
+
}), r(T, fe).then((t) => {
|
|
51
|
+
e || Ae(t.mtwCustomerNotificationPreviews);
|
|
52
|
+
}).catch(() => {}), () => {
|
|
53
|
+
e = !0;
|
|
54
|
+
};
|
|
55
|
+
}, [T, Me]);
|
|
56
|
+
let K = xe(async () => {
|
|
57
|
+
if (!T.workspaceId) {
|
|
58
|
+
H(!1);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
let e = ++G.current;
|
|
62
|
+
H(!0);
|
|
63
|
+
try {
|
|
64
|
+
let t = await r(T, de, { pagination: {
|
|
65
|
+
limit: Ce,
|
|
66
|
+
offset: 0
|
|
67
|
+
} });
|
|
68
|
+
if (e !== G.current) return;
|
|
69
|
+
Oe(t.mtwCustomerNotifications.items), ke(t.mtwCustomerNotifications.total), B(null);
|
|
70
|
+
} catch (t) {
|
|
71
|
+
if (e !== G.current) return;
|
|
72
|
+
B(t instanceof Error ? t.message : "Could not load notifications");
|
|
73
|
+
} finally {
|
|
74
|
+
e === G.current && H(!1);
|
|
75
|
+
}
|
|
76
|
+
}, [T]);
|
|
77
|
+
f(() => (K(), () => {
|
|
78
|
+
G.current += 1;
|
|
79
|
+
}), [K]);
|
|
80
|
+
let q = p(() => ge(E, O), [E, O]), J = ye(O), Y = Object.keys(q).length > 0, X = A && !v && !P && Y && !J, Z = v || P || !A, Q = (e) => {
|
|
81
|
+
I(null), k((t) => ({
|
|
82
|
+
...t,
|
|
83
|
+
...e
|
|
84
|
+
}));
|
|
85
|
+
}, Pe = async (e) => {
|
|
86
|
+
if (e.preventDefault(), X) {
|
|
87
|
+
F(!0), I(null);
|
|
88
|
+
try {
|
|
89
|
+
let e = (await r(T, he, { input: q }, "SINGLE_ATTEMPT")).updateMtwCustomerNotificationSettings;
|
|
90
|
+
D(e), k(_(e)), De(e.enabled ? "Customer notifications are on. Customers hear about shipment changes from now on." : "Customer notifications are off.");
|
|
91
|
+
} catch (e) {
|
|
92
|
+
I(e instanceof Error ? e.message : "Could not save the settings");
|
|
93
|
+
} finally {
|
|
94
|
+
F(!1);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}, $ = U.find((e) => e.event === W);
|
|
98
|
+
return /* @__PURE__ */ g(re, {
|
|
99
|
+
"data-testid": "mtw-customer-notifications",
|
|
100
|
+
children: [/* @__PURE__ */ g(oe, { children: [/* @__PURE__ */ g("div", {
|
|
101
|
+
className: "flex flex-wrap items-center justify-between gap-3",
|
|
102
|
+
children: [/* @__PURE__ */ g(se, {
|
|
103
|
+
className: "flex items-center gap-2 text-base",
|
|
104
|
+
children: [/* @__PURE__ */ h(e, { size: 18 }), " Customer delivery notifications"]
|
|
105
|
+
}), A && /* @__PURE__ */ h(a, {
|
|
106
|
+
variant: E.enabled ? "default" : "outline",
|
|
107
|
+
children: E.enabled ? "On" : "Off"
|
|
108
|
+
})]
|
|
109
|
+
}), /* @__PURE__ */ h(ae, { children: "Email or text your customers when their shipment is booked, picked up, out for delivery, delivered, running late or could not be delivered. Each customer can opt out on their customer record; SMS goes only to customers who agreed to texts." })] }), /* @__PURE__ */ g(ie, {
|
|
110
|
+
className: "space-y-6",
|
|
111
|
+
children: [
|
|
112
|
+
M && /* @__PURE__ */ g("div", {
|
|
113
|
+
className: "space-y-3",
|
|
114
|
+
children: [/* @__PURE__ */ h(u, { message: `Could not load the customer notification settings (${M}). They cannot be changed until they load.` }), /* @__PURE__ */ g(o, {
|
|
115
|
+
type: "button",
|
|
116
|
+
variant: "outline",
|
|
117
|
+
size: "sm",
|
|
118
|
+
onClick: () => {
|
|
119
|
+
N(null), Ne((e) => e + 1);
|
|
120
|
+
},
|
|
121
|
+
children: [/* @__PURE__ */ h(n, {
|
|
122
|
+
size: 14,
|
|
123
|
+
className: "mr-2"
|
|
124
|
+
}), " Try again"]
|
|
125
|
+
})]
|
|
126
|
+
}),
|
|
127
|
+
/* @__PURE__ */ h(le, { message: Ee }),
|
|
128
|
+
A ? /* @__PURE__ */ g("form", {
|
|
129
|
+
className: "space-y-6",
|
|
130
|
+
onSubmit: (e) => void Pe(e),
|
|
131
|
+
"aria-label": "Customer notification settings",
|
|
132
|
+
children: [
|
|
133
|
+
v && /* @__PURE__ */ h("p", {
|
|
134
|
+
className: "rounded-lg border border-border-default bg-surface-secondary px-4 py-3 text-sm text-text-secondary",
|
|
135
|
+
children: "You can view these settings. Ask a workspace admin or the Logistics Director to change them."
|
|
136
|
+
}),
|
|
137
|
+
/* @__PURE__ */ g("div", {
|
|
138
|
+
className: "flex items-start justify-between gap-4 rounded-lg border border-border-default px-4 py-3",
|
|
139
|
+
children: [/* @__PURE__ */ g("div", {
|
|
140
|
+
className: "min-w-0",
|
|
141
|
+
children: [/* @__PURE__ */ h(c, {
|
|
142
|
+
htmlFor: "mtw-customer-notify-enabled",
|
|
143
|
+
className: "text-sm font-medium",
|
|
144
|
+
children: "Notify customers about their shipments"
|
|
145
|
+
}), /* @__PURE__ */ g("p", {
|
|
146
|
+
className: "text-xs text-text-secondary",
|
|
147
|
+
children: ["Only changes made after you switch this on notify; customers are never mailed about shipments that already happened.", E.enabledAt && E.enabled ? ` On since ${i(E.enabledAt)}.` : ""]
|
|
148
|
+
})]
|
|
149
|
+
}), /* @__PURE__ */ h(ce, {
|
|
150
|
+
id: "mtw-customer-notify-enabled",
|
|
151
|
+
checked: O.enabled,
|
|
152
|
+
disabled: Z,
|
|
153
|
+
onCheckedChange: (e) => Q({ enabled: e })
|
|
154
|
+
})]
|
|
155
|
+
}),
|
|
156
|
+
/* @__PURE__ */ g("fieldset", {
|
|
157
|
+
className: "space-y-3",
|
|
158
|
+
disabled: Z,
|
|
159
|
+
children: [
|
|
160
|
+
/* @__PURE__ */ h("legend", {
|
|
161
|
+
className: "text-sm font-semibold text-text-primary",
|
|
162
|
+
children: "Channels"
|
|
163
|
+
}),
|
|
164
|
+
/* @__PURE__ */ g("div", {
|
|
165
|
+
className: "flex flex-wrap gap-6",
|
|
166
|
+
children: [/* @__PURE__ */ g("div", {
|
|
167
|
+
className: "flex items-center gap-2",
|
|
168
|
+
children: [/* @__PURE__ */ h(s, {
|
|
169
|
+
id: "mtw-customer-notify-email",
|
|
170
|
+
checked: O.emailEnabled,
|
|
171
|
+
disabled: Z,
|
|
172
|
+
onCheckedChange: (e) => Q({ emailEnabled: e === !0 })
|
|
173
|
+
}), /* @__PURE__ */ h(c, {
|
|
174
|
+
htmlFor: "mtw-customer-notify-email",
|
|
175
|
+
className: "text-sm font-normal",
|
|
176
|
+
children: "Email"
|
|
177
|
+
})]
|
|
178
|
+
}), /* @__PURE__ */ g("div", {
|
|
179
|
+
className: "flex items-center gap-2",
|
|
180
|
+
children: [/* @__PURE__ */ h(s, {
|
|
181
|
+
id: "mtw-customer-notify-sms",
|
|
182
|
+
checked: O.smsEnabled,
|
|
183
|
+
disabled: Z,
|
|
184
|
+
onCheckedChange: (e) => Q({ smsEnabled: e === !0 })
|
|
185
|
+
}), /* @__PURE__ */ h(c, {
|
|
186
|
+
htmlFor: "mtw-customer-notify-sms",
|
|
187
|
+
className: "text-sm font-normal",
|
|
188
|
+
children: "SMS (phone numbers with a country code, e.g. +91…)"
|
|
189
|
+
})]
|
|
190
|
+
})]
|
|
191
|
+
}),
|
|
192
|
+
/* @__PURE__ */ h("p", {
|
|
193
|
+
className: "text-xs text-text-secondary",
|
|
194
|
+
children: "Texts are sent through the SMS channel configured for your organization. Without one, SMS sends are recorded as failed in the recent notifications below."
|
|
195
|
+
})
|
|
196
|
+
]
|
|
197
|
+
}),
|
|
198
|
+
/* @__PURE__ */ g("fieldset", {
|
|
199
|
+
className: "space-y-3",
|
|
200
|
+
disabled: Z,
|
|
201
|
+
children: [/* @__PURE__ */ h("legend", {
|
|
202
|
+
className: "text-sm font-semibold text-text-primary",
|
|
203
|
+
children: "Events"
|
|
204
|
+
}), /* @__PURE__ */ h("div", {
|
|
205
|
+
className: "grid grid-cols-1 gap-3 md:grid-cols-2",
|
|
206
|
+
children: d.map((e) => {
|
|
207
|
+
let t = `mtw-customer-notify-event-${e.value}`;
|
|
208
|
+
return /* @__PURE__ */ g("div", {
|
|
209
|
+
className: "flex items-start gap-2",
|
|
210
|
+
children: [/* @__PURE__ */ h(s, {
|
|
211
|
+
id: t,
|
|
212
|
+
checked: O.events.includes(e.value),
|
|
213
|
+
disabled: Z,
|
|
214
|
+
onCheckedChange: (t) => Q({ events: be(O.events, e.value, t === !0) })
|
|
215
|
+
}), /* @__PURE__ */ g(c, {
|
|
216
|
+
htmlFor: t,
|
|
217
|
+
className: "text-sm font-normal leading-snug",
|
|
218
|
+
children: [/* @__PURE__ */ h("span", {
|
|
219
|
+
className: "block font-medium text-text-primary",
|
|
220
|
+
children: e.label
|
|
221
|
+
}), /* @__PURE__ */ h("span", {
|
|
222
|
+
className: "block text-xs text-text-secondary",
|
|
223
|
+
children: e.description
|
|
224
|
+
})]
|
|
225
|
+
})]
|
|
226
|
+
}, e.value);
|
|
227
|
+
})
|
|
228
|
+
})]
|
|
229
|
+
}),
|
|
230
|
+
J && /* @__PURE__ */ h("p", {
|
|
231
|
+
className: "text-xs text-status-error-text",
|
|
232
|
+
children: J
|
|
233
|
+
}),
|
|
234
|
+
/* @__PURE__ */ h(u, { message: Te }),
|
|
235
|
+
/* @__PURE__ */ g("div", {
|
|
236
|
+
className: "flex flex-wrap items-center justify-end gap-3",
|
|
237
|
+
children: [/* @__PURE__ */ g(o, {
|
|
238
|
+
type: "button",
|
|
239
|
+
variant: "outline",
|
|
240
|
+
disabled: !Y || P,
|
|
241
|
+
onClick: () => {
|
|
242
|
+
I(null), k(_(E));
|
|
243
|
+
},
|
|
244
|
+
children: [/* @__PURE__ */ h(ee, {
|
|
245
|
+
size: 16,
|
|
246
|
+
className: "mr-2"
|
|
247
|
+
}), " Discard changes"]
|
|
248
|
+
}), /* @__PURE__ */ g(o, {
|
|
249
|
+
type: "submit",
|
|
250
|
+
disabled: !X,
|
|
251
|
+
children: [P ? /* @__PURE__ */ h(t, {
|
|
252
|
+
size: 16,
|
|
253
|
+
className: "mr-2 animate-spin"
|
|
254
|
+
}) : /* @__PURE__ */ h(te, {
|
|
255
|
+
size: 16,
|
|
256
|
+
className: "mr-2"
|
|
257
|
+
}), "Save notification settings"]
|
|
258
|
+
})]
|
|
259
|
+
})
|
|
260
|
+
]
|
|
261
|
+
}) : M ? null : /* @__PURE__ */ g("div", {
|
|
262
|
+
className: "space-y-3",
|
|
263
|
+
"aria-busy": "true",
|
|
264
|
+
children: [/* @__PURE__ */ h(l, { className: "h-8 w-full" }), /* @__PURE__ */ h(l, { className: "h-24 w-full" })]
|
|
265
|
+
}),
|
|
266
|
+
U.length > 0 && /* @__PURE__ */ g("div", {
|
|
267
|
+
className: "space-y-3 border-t border-border-default pt-4",
|
|
268
|
+
children: [/* @__PURE__ */ g("div", {
|
|
269
|
+
className: "flex flex-wrap items-center gap-2",
|
|
270
|
+
children: [/* @__PURE__ */ h("span", {
|
|
271
|
+
className: "text-sm font-semibold text-text-primary",
|
|
272
|
+
children: "Preview"
|
|
273
|
+
}), d.map((e) => /* @__PURE__ */ h(o, {
|
|
274
|
+
type: "button",
|
|
275
|
+
size: "sm",
|
|
276
|
+
variant: W === e.value ? "default" : "outline",
|
|
277
|
+
onClick: () => je(e.value),
|
|
278
|
+
children: e.label
|
|
279
|
+
}, e.value))]
|
|
280
|
+
}), $ && /* @__PURE__ */ g("div", {
|
|
281
|
+
className: "space-y-2 rounded-lg bg-surface-secondary px-4 py-3 text-sm",
|
|
282
|
+
"data-testid": "mtw-customer-notify-preview",
|
|
283
|
+
children: [
|
|
284
|
+
/* @__PURE__ */ h("p", {
|
|
285
|
+
className: "font-medium text-text-primary",
|
|
286
|
+
children: $.subject
|
|
287
|
+
}),
|
|
288
|
+
/* @__PURE__ */ h("p", {
|
|
289
|
+
className: "whitespace-pre-line text-text-secondary",
|
|
290
|
+
children: $.emailText
|
|
291
|
+
}),
|
|
292
|
+
/* @__PURE__ */ g("p", {
|
|
293
|
+
className: "text-xs text-text-tertiary",
|
|
294
|
+
children: ["SMS: ", $.smsText]
|
|
295
|
+
})
|
|
296
|
+
]
|
|
297
|
+
})]
|
|
298
|
+
}),
|
|
299
|
+
/* @__PURE__ */ g("div", {
|
|
300
|
+
className: "space-y-3 border-t border-border-default pt-4",
|
|
301
|
+
children: [
|
|
302
|
+
/* @__PURE__ */ g("div", {
|
|
303
|
+
className: "flex flex-wrap items-center justify-between gap-2",
|
|
304
|
+
children: [/* @__PURE__ */ g("span", {
|
|
305
|
+
className: "text-sm font-semibold text-text-primary",
|
|
306
|
+
children: ["Recent notifications", R > 0 ? ` (${R})` : ""]
|
|
307
|
+
}), /* @__PURE__ */ g(o, {
|
|
308
|
+
type: "button",
|
|
309
|
+
size: "sm",
|
|
310
|
+
variant: "outline",
|
|
311
|
+
disabled: V,
|
|
312
|
+
onClick: () => void K(),
|
|
313
|
+
children: [/* @__PURE__ */ h(n, {
|
|
314
|
+
size: 14,
|
|
315
|
+
className: "mr-2"
|
|
316
|
+
}), " Refresh"]
|
|
317
|
+
})]
|
|
318
|
+
}),
|
|
319
|
+
z && /* @__PURE__ */ h(u, { message: z }),
|
|
320
|
+
!z && L.length === 0 && !V && /* @__PURE__ */ h("p", {
|
|
321
|
+
className: "text-sm text-text-secondary",
|
|
322
|
+
children: "No customer notifications yet. They appear here as shipments change."
|
|
323
|
+
}),
|
|
324
|
+
L.length > 0 && /* @__PURE__ */ h("ul", {
|
|
325
|
+
className: "divide-y divide-border-default",
|
|
326
|
+
"data-testid": "mtw-customer-notify-recent",
|
|
327
|
+
children: L.map((e) => /* @__PURE__ */ g("li", {
|
|
328
|
+
className: "flex flex-wrap items-start justify-between gap-2 py-2",
|
|
329
|
+
children: [/* @__PURE__ */ g("div", {
|
|
330
|
+
className: "min-w-0",
|
|
331
|
+
children: [
|
|
332
|
+
/* @__PURE__ */ g("p", {
|
|
333
|
+
className: "text-sm font-medium text-text-primary",
|
|
334
|
+
children: [
|
|
335
|
+
ve(e.event),
|
|
336
|
+
" · ",
|
|
337
|
+
e.shipmentNumber ?? e.shipmentId
|
|
338
|
+
]
|
|
339
|
+
}),
|
|
340
|
+
/* @__PURE__ */ g("p", {
|
|
341
|
+
className: "text-xs text-text-secondary",
|
|
342
|
+
children: [
|
|
343
|
+
e.channel === "EMAIL" ? "Email" : "SMS",
|
|
344
|
+
e.recipient ? ` to ${e.recipient}` : "",
|
|
345
|
+
" ·",
|
|
346
|
+
" ",
|
|
347
|
+
i(e.sentAt ?? e.createdAt)
|
|
348
|
+
]
|
|
349
|
+
}),
|
|
350
|
+
e.lastError && e.status !== "SENT" && /* @__PURE__ */ h("p", {
|
|
351
|
+
className: "text-xs text-text-tertiary",
|
|
352
|
+
children: e.lastError
|
|
353
|
+
})
|
|
354
|
+
]
|
|
355
|
+
}), /* @__PURE__ */ h(a, {
|
|
356
|
+
variant: we[e.status],
|
|
357
|
+
children: me[e.status]
|
|
358
|
+
})]
|
|
359
|
+
}, e.id))
|
|
360
|
+
})
|
|
361
|
+
]
|
|
362
|
+
})
|
|
363
|
+
]
|
|
364
|
+
})]
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
//#endregion
|
|
368
|
+
export { v as CustomerNotificationSettingsCard };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Button as e } from "../ui.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { FreightSelect as t, FreightText as n } from "./FreightFields.js";
|
|
3
|
+
import { freightInstant as r, freightLocalTime as i } from "../../utils/freightDraft.js";
|
|
4
|
+
import { newCommercialFact as a } from "../../utils/freightCommercial.js";
|
|
5
5
|
import { useState as o } from "react";
|
|
6
6
|
import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
7
7
|
//#region src/movethewheels/components/freight-cost/FreightCommercialFactEditor.tsx
|
|
8
|
-
function u({ slot:
|
|
9
|
-
let [p, m] = o(!1), h =
|
|
10
|
-
...
|
|
8
|
+
function u({ slot: r, value: i, onChange: s, evidence: u }) {
|
|
9
|
+
let [p, m] = o(!1), h = r[0].toUpperCase() + r.slice(1), g = (e) => s({
|
|
10
|
+
...i,
|
|
11
11
|
...e
|
|
12
12
|
});
|
|
13
13
|
return /* @__PURE__ */ l("fieldset", {
|
|
@@ -17,11 +17,11 @@ function u({ slot: i, value: a, onChange: s, evidence: u }) {
|
|
|
17
17
|
className: "px-1 font-semibold",
|
|
18
18
|
children: h
|
|
19
19
|
}),
|
|
20
|
-
/* @__PURE__ */ l(
|
|
20
|
+
/* @__PURE__ */ l(t, {
|
|
21
21
|
label: `${h} status`,
|
|
22
|
-
value:
|
|
22
|
+
value: i.status,
|
|
23
23
|
onChange: (e) => {
|
|
24
|
-
(e === "UNKNOWN" || e === "SOURCED" || e === "NOT_APPLICABLE") && (m(!1), s(
|
|
24
|
+
(e === "UNKNOWN" || e === "SOURCED" || e === "NOT_APPLICABLE") && (m(!1), s(a(e)));
|
|
25
25
|
},
|
|
26
26
|
children: [
|
|
27
27
|
/* @__PURE__ */ c("option", {
|
|
@@ -38,9 +38,9 @@ function u({ slot: i, value: a, onChange: s, evidence: u }) {
|
|
|
38
38
|
})
|
|
39
39
|
]
|
|
40
40
|
}),
|
|
41
|
-
|
|
41
|
+
i.status === "UNKNOWN" && !p && /* @__PURE__ */ l("div", {
|
|
42
42
|
className: "flex flex-wrap items-center gap-2",
|
|
43
|
-
children: [/* @__PURE__ */ c("p", { children:
|
|
43
|
+
children: [/* @__PURE__ */ c("p", { children: i.reason }), /* @__PURE__ */ l(e, {
|
|
44
44
|
type: "button",
|
|
45
45
|
variant: "outline",
|
|
46
46
|
onClick: () => m(!0),
|
|
@@ -51,31 +51,31 @@ function u({ slot: i, value: a, onChange: s, evidence: u }) {
|
|
|
51
51
|
]
|
|
52
52
|
})]
|
|
53
53
|
}),
|
|
54
|
-
(
|
|
54
|
+
(i.status === "NOT_APPLICABLE" || i.status === "UNKNOWN" && p) && /* @__PURE__ */ c(n, {
|
|
55
55
|
label: `${h} reason`,
|
|
56
|
-
value:
|
|
56
|
+
value: i.reason,
|
|
57
57
|
required: !0,
|
|
58
58
|
onChange: (e) => g({ reason: e })
|
|
59
59
|
}),
|
|
60
|
-
|
|
61
|
-
slot:
|
|
60
|
+
i.status === "SOURCED" && /* @__PURE__ */ c(d, {
|
|
61
|
+
slot: r,
|
|
62
62
|
label: h,
|
|
63
|
-
value:
|
|
63
|
+
value: i,
|
|
64
64
|
patch: g
|
|
65
65
|
}),
|
|
66
|
-
|
|
66
|
+
i.status !== "UNKNOWN" && /* @__PURE__ */ c(f, {
|
|
67
67
|
label: h,
|
|
68
|
-
value:
|
|
68
|
+
value: i,
|
|
69
69
|
patch: g,
|
|
70
70
|
evidence: u
|
|
71
71
|
})
|
|
72
72
|
]
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
|
-
function d({ slot: e, label:
|
|
75
|
+
function d({ slot: e, label: r, value: i, patch: a }) {
|
|
76
76
|
return /* @__PURE__ */ l(s, { children: [
|
|
77
|
-
(e === "origin" || e === "destination") && /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ l(
|
|
78
|
-
label: `${
|
|
77
|
+
(e === "origin" || e === "destination") && /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ l(t, {
|
|
78
|
+
label: `${r} label kind`,
|
|
79
79
|
value: i.kind,
|
|
80
80
|
onChange: (e) => a({ kind: e }),
|
|
81
81
|
children: [/* @__PURE__ */ c("option", {
|
|
@@ -91,32 +91,32 @@ function d({ slot: e, label: t, value: i, patch: a }) {
|
|
|
91
91
|
value: e,
|
|
92
92
|
children: e.replaceAll("_", " ").toLowerCase()
|
|
93
93
|
}, e))]
|
|
94
|
-
}), /* @__PURE__ */ c(
|
|
95
|
-
label: `${
|
|
94
|
+
}), /* @__PURE__ */ c(n, {
|
|
95
|
+
label: `${r} jurisdiction label (optional)`,
|
|
96
96
|
value: i.jurisdiction,
|
|
97
97
|
onChange: (e) => a({ jurisdiction: e })
|
|
98
98
|
})] }),
|
|
99
|
-
e === "carrier" && /* @__PURE__ */ c(
|
|
99
|
+
e === "carrier" && /* @__PURE__ */ c(n, {
|
|
100
100
|
label: "Carrier reference",
|
|
101
101
|
value: i.reference,
|
|
102
102
|
required: !0,
|
|
103
103
|
onChange: (e) => a({ reference: e })
|
|
104
104
|
}),
|
|
105
|
-
e !== "weight" && e !== "volume" && /* @__PURE__ */ c(
|
|
106
|
-
label: e === "cargo" ? "Cargo classification label" : e === "equipment" ? "Equipment type label" : `${
|
|
105
|
+
e !== "weight" && e !== "volume" && /* @__PURE__ */ c(n, {
|
|
106
|
+
label: e === "cargo" ? "Cargo classification label" : e === "equipment" ? "Equipment type label" : `${r} label`,
|
|
107
107
|
value: i.label,
|
|
108
108
|
required: !0,
|
|
109
109
|
onChange: (e) => a({ label: e })
|
|
110
110
|
}),
|
|
111
|
-
e === "cargo" && /* @__PURE__ */ c(
|
|
111
|
+
e === "cargo" && /* @__PURE__ */ c(n, {
|
|
112
112
|
label: "Cargo description",
|
|
113
113
|
value: i.description,
|
|
114
114
|
required: !0,
|
|
115
115
|
onChange: (e) => a({ description: e })
|
|
116
116
|
}),
|
|
117
117
|
(e === "weight" || e === "volume") && /* @__PURE__ */ l(s, { children: [
|
|
118
|
-
/* @__PURE__ */ c(
|
|
119
|
-
label: `${
|
|
118
|
+
/* @__PURE__ */ c(n, {
|
|
119
|
+
label: `${r} amount`,
|
|
120
120
|
value: i.amount,
|
|
121
121
|
required: !0,
|
|
122
122
|
onChange: (e) => a({
|
|
@@ -124,8 +124,8 @@ function d({ slot: e, label: t, value: i, patch: a }) {
|
|
|
124
124
|
zeroReason: e === "0" ? i.zeroReason : ""
|
|
125
125
|
})
|
|
126
126
|
}),
|
|
127
|
-
/* @__PURE__ */ l(
|
|
128
|
-
label: `${
|
|
127
|
+
/* @__PURE__ */ l(t, {
|
|
128
|
+
label: `${r} recorded unit`,
|
|
129
129
|
value: i.unit,
|
|
130
130
|
onChange: (e) => a({ unit: e }),
|
|
131
131
|
children: [/* @__PURE__ */ c("option", {
|
|
@@ -140,8 +140,8 @@ function d({ slot: e, label: t, value: i, patch: a }) {
|
|
|
140
140
|
children: e
|
|
141
141
|
}, e))]
|
|
142
142
|
}),
|
|
143
|
-
i.amount === "0" && /* @__PURE__ */ c(
|
|
144
|
-
label: `${
|
|
143
|
+
i.amount === "0" && /* @__PURE__ */ c(n, {
|
|
144
|
+
label: `${r} recorded zero reason`,
|
|
145
145
|
value: i.zeroReason,
|
|
146
146
|
required: !0,
|
|
147
147
|
onChange: (e) => a({ zeroReason: e })
|
|
@@ -151,7 +151,7 @@ function d({ slot: e, label: t, value: i, patch: a }) {
|
|
|
151
151
|
children: "Record the source unit. No conversion is inferred."
|
|
152
152
|
})
|
|
153
153
|
] }),
|
|
154
|
-
e === "equipment" && /* @__PURE__ */ c(
|
|
154
|
+
e === "equipment" && /* @__PURE__ */ c(n, {
|
|
155
155
|
label: "Equipment count",
|
|
156
156
|
value: i.count,
|
|
157
157
|
required: !0,
|
|
@@ -159,29 +159,29 @@ function d({ slot: e, label: t, value: i, patch: a }) {
|
|
|
159
159
|
})
|
|
160
160
|
] });
|
|
161
161
|
}
|
|
162
|
-
function f({ label: e, value: t, patch:
|
|
162
|
+
function f({ label: e, value: t, patch: a, evidence: o }) {
|
|
163
163
|
return /* @__PURE__ */ l(s, { children: [
|
|
164
164
|
/* @__PURE__ */ l("h4", {
|
|
165
165
|
className: "font-medium",
|
|
166
166
|
children: [e, " source declaration"]
|
|
167
167
|
}),
|
|
168
|
-
/* @__PURE__ */ c(
|
|
168
|
+
/* @__PURE__ */ c(n, {
|
|
169
169
|
label: `${e} source reference`,
|
|
170
170
|
value: t.sourceReference,
|
|
171
171
|
required: !0,
|
|
172
|
-
onChange: (e) =>
|
|
172
|
+
onChange: (e) => a({ sourceReference: e })
|
|
173
173
|
}),
|
|
174
|
-
/* @__PURE__ */ c(
|
|
174
|
+
/* @__PURE__ */ c(n, {
|
|
175
175
|
label: `${e} source revision`,
|
|
176
176
|
value: t.sourceRevision,
|
|
177
177
|
required: !0,
|
|
178
|
-
onChange: (e) =>
|
|
178
|
+
onChange: (e) => a({ sourceRevision: e })
|
|
179
179
|
}),
|
|
180
|
-
/* @__PURE__ */ c(
|
|
180
|
+
/* @__PURE__ */ c(n, {
|
|
181
181
|
label: `${e} observed at (local time, optional)`,
|
|
182
182
|
type: "datetime-local",
|
|
183
|
-
value: t.observedAt ?
|
|
184
|
-
onChange: (e) =>
|
|
183
|
+
value: t.observedAt ? i(t.observedAt) : "",
|
|
184
|
+
onChange: (e) => a({ observedAt: e ? r(e) : "" })
|
|
185
185
|
}),
|
|
186
186
|
/* @__PURE__ */ c("p", {
|
|
187
187
|
className: "text-sm",
|
|
@@ -192,14 +192,14 @@ function f({ label: e, value: t, patch: n, evidence: o }) {
|
|
|
192
192
|
children: "Choose 1–2 versions from the evidence selected below for this record. This declares the source; it does not verify its authority."
|
|
193
193
|
}),
|
|
194
194
|
o.map((e) => {
|
|
195
|
-
let
|
|
195
|
+
let n = t.evidenceLinks.some((t) => t.fileId === e.fileId && t.versionId === e.versionId);
|
|
196
196
|
return /* @__PURE__ */ l("label", {
|
|
197
197
|
className: "flex min-h-11 items-center gap-2 break-words text-sm",
|
|
198
198
|
children: [/* @__PURE__ */ c("input", {
|
|
199
199
|
type: "checkbox",
|
|
200
|
-
checked:
|
|
201
|
-
disabled: !
|
|
202
|
-
onChange: () =>
|
|
200
|
+
checked: n,
|
|
201
|
+
disabled: !n && t.evidenceLinks.length >= 2,
|
|
202
|
+
onChange: () => a({ evidenceLinks: n ? t.evidenceLinks.filter((t) => !(t.fileId === e.fileId && t.versionId === e.versionId)) : [...t.evidenceLinks, {
|
|
203
203
|
fileId: e.fileId,
|
|
204
204
|
versionId: e.versionId
|
|
205
205
|
}] })
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { freightLabel as e } from "../../utils/freightDraft.js";
|
|
2
|
+
import { commercialSlots as t } from "../../utils/freightCommercial.js";
|
|
3
3
|
import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
4
4
|
//#region src/movethewheels/components/freight-cost/FreightCommercialHistory.tsx
|
|
5
5
|
function i({ capture: i }) {
|
|
@@ -19,17 +19,17 @@ function i({ capture: i }) {
|
|
|
19
19
|
}),
|
|
20
20
|
/* @__PURE__ */ n("div", {
|
|
21
21
|
className: "grid min-w-0 gap-3 md:grid-cols-2",
|
|
22
|
-
children:
|
|
23
|
-
let a = i[
|
|
22
|
+
children: t.map((t) => {
|
|
23
|
+
let a = i[t];
|
|
24
24
|
return /* @__PURE__ */ r("article", {
|
|
25
25
|
className: "space-y-2 rounded border p-3",
|
|
26
26
|
children: [
|
|
27
27
|
/* @__PURE__ */ r("h4", {
|
|
28
28
|
className: "font-medium",
|
|
29
29
|
children: [
|
|
30
|
-
t
|
|
30
|
+
e(t),
|
|
31
31
|
" — ",
|
|
32
|
-
|
|
32
|
+
e(a.status)
|
|
33
33
|
]
|
|
34
34
|
}),
|
|
35
35
|
a.reason && /* @__PURE__ */ n("p", { children: a.reason }),
|
|
@@ -61,7 +61,7 @@ function i({ capture: i }) {
|
|
|
61
61
|
] }, JSON.stringify([e.fileId, e.versionId])))]
|
|
62
62
|
})
|
|
63
63
|
]
|
|
64
|
-
},
|
|
64
|
+
}, t);
|
|
65
65
|
})
|
|
66
66
|
}),
|
|
67
67
|
/* @__PURE__ */ r("section", {
|