@burdenoff/microfe-movethewheels 2026.1101.3 → 2026.1102.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/components/CustomerDeliveryUpdatesFields.js +57 -0
- package/dist/components/CustomerNotificationSettingsCard.js +368 -0
- package/dist/components/UpcomingDemandPanel.js +75 -77
- package/dist/generated/tracking-quality-operations.d.ts +275 -0
- package/dist/generated/wspace-operations.d.ts +3 -0
- package/dist/hooks/useCustomers.js +9 -3
- package/dist/hooks/useDemandForecast.js +1 -1
- package/dist/movethewheels/components/CustomerDeliveryUpdatesFields.d.ts +12 -0
- package/dist/movethewheels/components/CustomerNotificationSettingsCard.d.ts +3 -0
- package/dist/movethewheels/hooks/useDemandForecast.d.ts +3 -0
- package/dist/movethewheels/types/index.d.ts +4 -0
- package/dist/movethewheels/utils/customerNotifications.d.ts +66 -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/SettingsPage.js +242 -238
- package/dist/utils/customerNotifications.js +83 -0
- package/package.json +3 -2
- package/src/generated/tracking-quality-operations.ts +304 -0
- package/src/generated/wspace-operations.ts +6 -6
- package/src/movethewheels/components/CustomerDeliveryUpdatesFields.tsx +67 -0
- package/src/movethewheels/components/CustomerNotificationSettingsCard.tsx +465 -0
- package/src/movethewheels/components/UpcomingDemandPanel.tsx +71 -29
- package/src/movethewheels/hooks/useCustomers.ts +17 -0
- package/src/movethewheels/hooks/useDemandForecast.ts +7 -0
- package/src/movethewheels/pages/CustomerDetailsPage.tsx +39 -0
- 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/operations/wspace/movethewheels/queries/forecast.graphql +3 -0
|
@@ -2,178 +2,176 @@ import { Calendar as e } from "../node_modules/lucide-react/dist/esm/icons/calen
|
|
|
2
2
|
import { CircleAlert as t } from "../node_modules/lucide-react/dist/esm/icons/circle-alert.js";
|
|
3
3
|
import { TrendingDown as n } from "../node_modules/lucide-react/dist/esm/icons/trending-down.js";
|
|
4
4
|
import { TrendingUp as r } from "../node_modules/lucide-react/dist/esm/icons/trending-up.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { formatCurrency as i } from "../utils/formatters.js";
|
|
6
|
+
import { Card as a, CardContent as o, CardHeader as s, CardTitle as c, Skeleton as l } from "./ui.js";
|
|
7
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
7
8
|
//#region src/movethewheels/components/UpcomingDemandPanel.tsx
|
|
8
|
-
var
|
|
9
|
+
var f = (e) => {
|
|
9
10
|
let t = new Date(e);
|
|
10
11
|
return Number.isNaN(t.getTime()) ? e : t.toLocaleDateString(void 0, {
|
|
11
12
|
month: "short",
|
|
12
13
|
day: "numeric"
|
|
13
14
|
});
|
|
14
|
-
},
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
}, p = (e, t) => e.filter((e) => e.periodStart === t && e.confidence > 0), m = (e, t) => [...p(e, t)].sort((e, t) => t.predictedVolume - e.predictedVolume || t.predictedRevenue - e.predictedRevenue).slice(0, 3), h = (e, t) => [...p(e, t)].sort((e, t) => t.predictedRevenue - e.predictedRevenue).slice(0, 3), g = (e, t) => p(e, t).reduce((e, t) => e + t.predictedVolume, 0), _ = (e, t = /* @__PURE__ */ new Date()) => {
|
|
16
|
+
let n = [...new Set(e.map((e) => e.periodStart))].sort((e, t) => new Date(e).getTime() - new Date(t).getTime());
|
|
17
|
+
return n.find((e) => new Date(e).getTime() > t.getTime()) ?? n.at(-1) ?? null;
|
|
18
|
+
}, v = (e, t) => e === 0 && t > 0 ? "<1 job" : e === 1 ? "1 job" : `${e} jobs`, y = (e) => e <= 0 ? "Not enough history" : `${Math.round(e * 100)}% confidence`;
|
|
19
|
+
function b({ laneForecast: n, customerForecast: r, laneVariance: i, customerVariance: v, isLoading: b, error: C, onRetry: w }) {
|
|
20
|
+
if (C && !b) return /* @__PURE__ */ u(a, {
|
|
17
21
|
className: "border-status-error-border",
|
|
18
|
-
children: /* @__PURE__ */
|
|
22
|
+
children: /* @__PURE__ */ d(o, {
|
|
19
23
|
className: "p-6 text-center space-y-3",
|
|
20
24
|
children: [
|
|
21
|
-
/* @__PURE__ */
|
|
25
|
+
/* @__PURE__ */ u("p", {
|
|
22
26
|
className: "text-status-error-text font-medium",
|
|
23
27
|
children: "Couldn't load demand forecast"
|
|
24
28
|
}),
|
|
25
|
-
/* @__PURE__ */
|
|
29
|
+
/* @__PURE__ */ u("p", {
|
|
26
30
|
className: "text-sm text-text-secondary",
|
|
27
|
-
children:
|
|
31
|
+
children: C.message
|
|
28
32
|
}),
|
|
29
|
-
/* @__PURE__ */
|
|
33
|
+
/* @__PURE__ */ u("button", {
|
|
30
34
|
type: "button",
|
|
31
|
-
onClick:
|
|
35
|
+
onClick: w,
|
|
32
36
|
className: "text-sm font-medium text-primary hover:underline",
|
|
33
37
|
children: "Retry"
|
|
34
38
|
})
|
|
35
39
|
]
|
|
36
40
|
})
|
|
37
41
|
});
|
|
38
|
-
if (b) return /* @__PURE__ */
|
|
42
|
+
if (b) return /* @__PURE__ */ d(a, { children: [/* @__PURE__ */ u(s, { children: /* @__PURE__ */ u(c, { children: "Upcoming demand" }) }), /* @__PURE__ */ d(o, {
|
|
39
43
|
className: "space-y-4",
|
|
40
44
|
children: [
|
|
41
|
-
/* @__PURE__ */ l
|
|
42
|
-
/* @__PURE__ */ l
|
|
43
|
-
/* @__PURE__ */ l
|
|
45
|
+
/* @__PURE__ */ u(l, { className: "h-16 w-full" }),
|
|
46
|
+
/* @__PURE__ */ u(l, { className: "h-16 w-full" }),
|
|
47
|
+
/* @__PURE__ */ u(l, { className: "h-16 w-full" })
|
|
44
48
|
]
|
|
45
49
|
})] });
|
|
46
|
-
let
|
|
47
|
-
if (!
|
|
50
|
+
let T = _([...n, ...r]), E = T !== null && (p(n, T).length > 0 || p(r, T).length > 0);
|
|
51
|
+
if (!T || !E) return /* @__PURE__ */ d(a, { children: [/* @__PURE__ */ u(s, { children: /* @__PURE__ */ d(c, {
|
|
48
52
|
className: "flex items-center gap-2",
|
|
49
|
-
children: [/* @__PURE__ */
|
|
53
|
+
children: [/* @__PURE__ */ u(e, {
|
|
50
54
|
size: 18,
|
|
51
55
|
"aria-hidden": "true"
|
|
52
56
|
}), "Upcoming demand"]
|
|
53
|
-
}) }), /* @__PURE__ */
|
|
57
|
+
}) }), /* @__PURE__ */ u(o, { children: /* @__PURE__ */ d("div", {
|
|
54
58
|
className: "flex items-start gap-2 rounded-lg border border-border/60 bg-muted/40 p-4 text-sm text-text-secondary",
|
|
55
|
-
children: [/* @__PURE__ */
|
|
59
|
+
children: [/* @__PURE__ */ u(t, {
|
|
56
60
|
size: 16,
|
|
57
61
|
"aria-hidden": "true",
|
|
58
62
|
className: "mt-0.5 shrink-0"
|
|
59
|
-
}), /* @__PURE__ */
|
|
63
|
+
}), /* @__PURE__ */ u("p", { children: "Not enough history to forecast next week yet. Once a lane or customer has at least 4 weeks of delivery jobs, this panel will surface its demand." })]
|
|
60
64
|
}) })] });
|
|
61
|
-
let
|
|
62
|
-
return /* @__PURE__ */
|
|
65
|
+
let D = m(n, T), O = h(n, T), k = m(r, T), A = p(n, T).length > 0, j = g(A ? n : r, T), M = A ? "Predicted jobs (all lanes)" : "Predicted jobs (all customers)", N = A ? D[0] : k[0], P = [...i, ...v].sort((e, t) => Math.abs(t.volumeVariance) - Math.abs(e.volumeVariance)).slice(0, 3);
|
|
66
|
+
return /* @__PURE__ */ d(a, { children: [/* @__PURE__ */ u(s, { children: /* @__PURE__ */ d(c, {
|
|
63
67
|
className: "flex items-center gap-2",
|
|
64
68
|
children: [
|
|
65
|
-
/* @__PURE__ */
|
|
69
|
+
/* @__PURE__ */ u(e, {
|
|
66
70
|
size: 18,
|
|
67
71
|
"aria-hidden": "true"
|
|
68
72
|
}),
|
|
69
73
|
"Upcoming demand — week of ",
|
|
70
|
-
|
|
74
|
+
f(T)
|
|
71
75
|
]
|
|
72
|
-
}) }), /* @__PURE__ */
|
|
76
|
+
}) }), /* @__PURE__ */ d(o, {
|
|
73
77
|
className: "space-y-4",
|
|
74
|
-
children: [/* @__PURE__ */
|
|
78
|
+
children: [/* @__PURE__ */ d("div", {
|
|
75
79
|
className: "flex items-baseline justify-between rounded-lg border border-border/60 bg-muted/40 px-4 py-3",
|
|
76
|
-
children: [/* @__PURE__ */
|
|
80
|
+
children: [/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("p", {
|
|
77
81
|
className: "text-xs uppercase tracking-wide text-text-secondary",
|
|
78
|
-
children:
|
|
79
|
-
}), /* @__PURE__ */
|
|
82
|
+
children: M
|
|
83
|
+
}), /* @__PURE__ */ u("p", {
|
|
80
84
|
className: "text-2xl font-bold",
|
|
81
|
-
children:
|
|
82
|
-
})] }), /* @__PURE__ */
|
|
85
|
+
children: j
|
|
86
|
+
})] }), /* @__PURE__ */ u("p", {
|
|
83
87
|
className: "text-xs text-text-secondary",
|
|
84
|
-
children:
|
|
88
|
+
children: N ? y(N.confidence) : ""
|
|
85
89
|
})]
|
|
86
|
-
}), /* @__PURE__ */
|
|
90
|
+
}), /* @__PURE__ */ d("div", {
|
|
87
91
|
className: "grid grid-cols-1 md:grid-cols-2 gap-4",
|
|
88
92
|
children: [
|
|
89
|
-
/* @__PURE__ */
|
|
93
|
+
/* @__PURE__ */ u(x, {
|
|
90
94
|
title: "Top lanes (volume)",
|
|
91
|
-
rows:
|
|
95
|
+
rows: D
|
|
92
96
|
}),
|
|
93
|
-
/* @__PURE__ */
|
|
97
|
+
/* @__PURE__ */ u(x, {
|
|
94
98
|
title: "Top lanes (revenue)",
|
|
95
|
-
rows:
|
|
99
|
+
rows: O
|
|
96
100
|
}),
|
|
97
|
-
/* @__PURE__ */
|
|
101
|
+
/* @__PURE__ */ u(x, {
|
|
98
102
|
title: "Top customers (volume)",
|
|
99
|
-
rows:
|
|
103
|
+
rows: k
|
|
100
104
|
}),
|
|
101
|
-
/* @__PURE__ */
|
|
105
|
+
/* @__PURE__ */ u(S, { rows: P })
|
|
102
106
|
]
|
|
103
107
|
})]
|
|
104
108
|
})] });
|
|
105
109
|
}
|
|
106
|
-
function
|
|
107
|
-
return t.length === 0 ? /* @__PURE__ */
|
|
110
|
+
function x({ title: e, rows: t }) {
|
|
111
|
+
return t.length === 0 ? /* @__PURE__ */ d("div", {
|
|
108
112
|
className: "rounded-lg border border-border/60 p-4",
|
|
109
|
-
children: [/* @__PURE__ */
|
|
113
|
+
children: [/* @__PURE__ */ u("p", {
|
|
110
114
|
className: "text-sm font-medium mb-2",
|
|
111
115
|
children: e
|
|
112
|
-
}), /* @__PURE__ */
|
|
116
|
+
}), /* @__PURE__ */ u("p", {
|
|
113
117
|
className: "text-xs text-text-secondary",
|
|
114
118
|
children: "No forecasts yet for this week."
|
|
115
119
|
})]
|
|
116
|
-
}) : /* @__PURE__ */
|
|
120
|
+
}) : /* @__PURE__ */ d("div", {
|
|
117
121
|
className: "rounded-lg border border-border/60 p-4",
|
|
118
|
-
children: [/* @__PURE__ */
|
|
122
|
+
children: [/* @__PURE__ */ u("p", {
|
|
119
123
|
className: "text-sm font-medium mb-3",
|
|
120
124
|
children: e
|
|
121
|
-
}), /* @__PURE__ */
|
|
125
|
+
}), /* @__PURE__ */ u("ul", {
|
|
122
126
|
className: "space-y-2",
|
|
123
|
-
children: t.map((e) => /* @__PURE__ */
|
|
127
|
+
children: t.map((e) => /* @__PURE__ */ d("li", {
|
|
124
128
|
className: "flex items-center justify-between text-sm",
|
|
125
|
-
children: [/* @__PURE__ */
|
|
129
|
+
children: [/* @__PURE__ */ u("span", {
|
|
126
130
|
className: "truncate font-medium",
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
title: e.scopeLabel,
|
|
132
|
+
children: e.scopeLabel
|
|
133
|
+
}), /* @__PURE__ */ d("span", {
|
|
129
134
|
className: "ml-2 shrink-0 text-text-secondary",
|
|
130
135
|
children: [
|
|
131
|
-
e.predictedVolume,
|
|
132
|
-
"
|
|
136
|
+
v(e.predictedVolume, e.predictedRevenue),
|
|
137
|
+
" ·",
|
|
133
138
|
" ",
|
|
134
|
-
|
|
135
|
-
style: "currency",
|
|
136
|
-
currency: "USD",
|
|
137
|
-
maximumFractionDigits: 0
|
|
138
|
-
}).format(e.predictedRevenue)
|
|
139
|
+
i(e.predictedRevenue)
|
|
139
140
|
]
|
|
140
141
|
})]
|
|
141
142
|
}, `${e.scopeType}-${e.scopeKey}`))
|
|
142
143
|
})]
|
|
143
144
|
});
|
|
144
145
|
}
|
|
145
|
-
function
|
|
146
|
-
return /* @__PURE__ */
|
|
146
|
+
function S({ rows: e }) {
|
|
147
|
+
return /* @__PURE__ */ d("div", {
|
|
147
148
|
className: "rounded-lg border border-border/60 p-4",
|
|
148
|
-
children: [/* @__PURE__ */
|
|
149
|
+
children: [/* @__PURE__ */ u("p", {
|
|
149
150
|
className: "text-sm font-medium mb-3",
|
|
150
151
|
children: "Recent forecast variance"
|
|
151
|
-
}), e.length === 0 ? /* @__PURE__ */
|
|
152
|
+
}), e.length === 0 ? /* @__PURE__ */ u("p", {
|
|
152
153
|
className: "text-xs text-text-secondary",
|
|
153
154
|
children: "No closed periods to compare yet."
|
|
154
|
-
}) : /* @__PURE__ */
|
|
155
|
+
}) : /* @__PURE__ */ u("ul", {
|
|
155
156
|
className: "space-y-2",
|
|
156
157
|
children: e.map((e) => {
|
|
157
158
|
let t = e.volumeVariance > 0, i = t ? r : n, a = t ? "text-status-success-text" : "text-status-error-text";
|
|
158
|
-
return /* @__PURE__ */
|
|
159
|
+
return /* @__PURE__ */ d("li", {
|
|
159
160
|
className: "flex items-center justify-between text-sm",
|
|
160
|
-
children: [/* @__PURE__ */
|
|
161
|
+
children: [/* @__PURE__ */ d("span", {
|
|
161
162
|
className: "flex items-center gap-2 truncate",
|
|
162
|
-
children: [/* @__PURE__ */
|
|
163
|
+
children: [/* @__PURE__ */ u(i, {
|
|
163
164
|
size: 14,
|
|
164
165
|
className: a,
|
|
165
166
|
"aria-hidden": "true"
|
|
166
|
-
}), /* @__PURE__ */
|
|
167
|
+
}), /* @__PURE__ */ u("span", {
|
|
167
168
|
className: "truncate font-medium",
|
|
168
|
-
|
|
169
|
+
title: e.scopeLabel,
|
|
170
|
+
children: e.scopeLabel
|
|
169
171
|
})]
|
|
170
|
-
}), /* @__PURE__ */
|
|
172
|
+
}), /* @__PURE__ */ d("span", {
|
|
171
173
|
className: `ml-2 shrink-0 ${a}`,
|
|
172
|
-
children: [
|
|
173
|
-
t ? "+" : "",
|
|
174
|
-
e.volumeVariance,
|
|
175
|
-
" jobs"
|
|
176
|
-
]
|
|
174
|
+
children: [t ? "+" : "", Math.abs(e.volumeVariance) === 1 ? `${e.volumeVariance} job` : `${e.volumeVariance} jobs`]
|
|
177
175
|
})]
|
|
178
176
|
}, `${e.scopeType}-${e.scopeKey}-${e.periodStart}`);
|
|
179
177
|
})
|
|
@@ -181,4 +179,4 @@ function v({ rows: e }) {
|
|
|
181
179
|
});
|
|
182
180
|
}
|
|
183
181
|
//#endregion
|
|
184
|
-
export {
|
|
182
|
+
export { b as UpcomingDemandPanel };
|