@burdenoff/microfe-movethewheels 2026.1101.2 → 2026.1101.4
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/UpcomingDemandPanel.js +75 -77
- package/dist/generated/wspace-operations.d.ts +3 -0
- package/dist/hooks/useDemandForecast.js +1 -1
- package/dist/movethewheels/hooks/useDemandForecast.d.ts +3 -0
- package/dist/movethewheels/utils/driverNavigation.d.ts +6 -0
- package/dist/pages/DeliveryCapturePage.js +71 -71
- package/dist/utils/driverNavigation.js +11 -1
- package/package.json +1 -1
- package/src/generated/wspace-operations.ts +6 -6
- package/src/movethewheels/components/UpcomingDemandPanel.tsx +71 -29
- package/src/movethewheels/hooks/useDemandForecast.ts +7 -0
- package/src/movethewheels/pages/DeliveryCapturePage.tsx +2 -3
- package/src/movethewheels/utils/driverNavigation.ts +16 -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 };
|
|
@@ -1141,6 +1141,7 @@ export type GetMovethewheelsDemandForecastByLaneQuery = {
|
|
|
1141
1141
|
demandForecastByLane: Array<{
|
|
1142
1142
|
scopeType: Types.DemandForecastScope;
|
|
1143
1143
|
scopeKey: string;
|
|
1144
|
+
scopeLabel: string;
|
|
1144
1145
|
periodStart: string;
|
|
1145
1146
|
periodEnd: string;
|
|
1146
1147
|
predictedVolume: number;
|
|
@@ -1157,6 +1158,7 @@ export type GetMovethewheelsDemandForecastByCustomerQuery = {
|
|
|
1157
1158
|
demandForecastByCustomer: Array<{
|
|
1158
1159
|
scopeType: Types.DemandForecastScope;
|
|
1159
1160
|
scopeKey: string;
|
|
1161
|
+
scopeLabel: string;
|
|
1160
1162
|
periodStart: string;
|
|
1161
1163
|
periodEnd: string;
|
|
1162
1164
|
predictedVolume: number;
|
|
@@ -1174,6 +1176,7 @@ export type GetMovethewheelsDemandForecastVarianceQuery = {
|
|
|
1174
1176
|
demandForecastVariance: Array<{
|
|
1175
1177
|
scopeType: Types.DemandForecastScope;
|
|
1176
1178
|
scopeKey: string;
|
|
1179
|
+
scopeLabel: string;
|
|
1177
1180
|
periodStart: string;
|
|
1178
1181
|
periodEnd: string;
|
|
1179
1182
|
predictedVolume: number;
|
|
@@ -2,7 +2,7 @@ import { useMoveTheWheels as e } from "../providers/MoveTheWheelsProvider.js";
|
|
|
2
2
|
import { executeGraphQL as t } from "../utils/graphqlClient.js";
|
|
3
3
|
import { useCallback as n, useEffect as r, useMemo as i, useState as a } from "react";
|
|
4
4
|
//#region src/movethewheels/hooks/useDemandForecast.ts
|
|
5
|
-
var o = "\n query GetMovethewheelsDemandForecast($weeks: Int!, $varianceLimit: Int!) {\n demandForecastByLane(weeks: $weeks) {\n scopeType\n scopeKey\n periodStart\n periodEnd\n predictedVolume\n predictedRevenue\n actualVolume\n actualRevenue\n confidence\n }\n demandForecastByCustomer(weeks: $weeks) {\n scopeType\n scopeKey\n periodStart\n periodEnd\n predictedVolume\n predictedRevenue\n actualVolume\n actualRevenue\n confidence\n }\n laneVariance: demandForecastVariance(scopeType: LANE, limit: $varianceLimit) {\n scopeType\n scopeKey\n periodStart\n periodEnd\n predictedVolume\n actualVolume\n volumeVariance\n predictedRevenue\n actualRevenue\n revenueVariance\n }\n customerVariance: demandForecastVariance(scopeType: CUSTOMER, limit: $varianceLimit) {\n scopeType\n scopeKey\n periodStart\n periodEnd\n predictedVolume\n actualVolume\n volumeVariance\n predictedRevenue\n actualRevenue\n revenueVariance\n }\n }\n";
|
|
5
|
+
var o = "\n query GetMovethewheelsDemandForecast($weeks: Int!, $varianceLimit: Int!) {\n demandForecastByLane(weeks: $weeks) {\n scopeType\n scopeKey\n scopeLabel\n periodStart\n periodEnd\n predictedVolume\n predictedRevenue\n actualVolume\n actualRevenue\n confidence\n }\n demandForecastByCustomer(weeks: $weeks) {\n scopeType\n scopeKey\n scopeLabel\n periodStart\n periodEnd\n predictedVolume\n predictedRevenue\n actualVolume\n actualRevenue\n confidence\n }\n laneVariance: demandForecastVariance(scopeType: LANE, limit: $varianceLimit) {\n scopeType\n scopeKey\n scopeLabel\n periodStart\n periodEnd\n predictedVolume\n actualVolume\n volumeVariance\n predictedRevenue\n actualRevenue\n revenueVariance\n }\n customerVariance: demandForecastVariance(scopeType: CUSTOMER, limit: $varianceLimit) {\n scopeType\n scopeKey\n scopeLabel\n periodStart\n periodEnd\n predictedVolume\n actualVolume\n volumeVariance\n predictedRevenue\n actualRevenue\n revenueVariance\n }\n }\n";
|
|
6
6
|
function s(s = 4, c = 8) {
|
|
7
7
|
let { apiGatewayUrl: l, authToken: u, workspaceToken: d, workspaceId: f, tenantId: p, currentUser: m } = e(), [h, g] = a([]), [_, v] = a([]), [y, b] = a([]), [x, S] = a([]), [C, w] = a(!1), [T, E] = a(null), D = i(() => ({
|
|
8
8
|
apiGatewayUrl: l,
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
export interface ForecastPoint {
|
|
7
7
|
scopeType: 'LANE' | 'CUSTOMER';
|
|
8
8
|
scopeKey: string;
|
|
9
|
+
/** Customer name or `Origin → Destination`; falls back to the key. */
|
|
10
|
+
scopeLabel: string;
|
|
9
11
|
periodStart: string;
|
|
10
12
|
periodEnd: string;
|
|
11
13
|
predictedVolume: number;
|
|
@@ -17,6 +19,7 @@ export interface ForecastPoint {
|
|
|
17
19
|
export interface ForecastVariance {
|
|
18
20
|
scopeType: 'LANE' | 'CUSTOMER';
|
|
19
21
|
scopeKey: string;
|
|
22
|
+
scopeLabel: string;
|
|
20
23
|
periodStart: string;
|
|
21
24
|
periodEnd: string;
|
|
22
25
|
predictedVolume: number;
|
|
@@ -29,3 +29,9 @@ export declare function timezoneOffsetFor(date: string): number;
|
|
|
29
29
|
* days. Null when the runtime cannot report one; the fixed offset is then used.
|
|
30
30
|
*/
|
|
31
31
|
export declare function deviceTimeZone(): string | null;
|
|
32
|
+
/**
|
|
33
|
+
* A calendar label for a YYYY-MM-DD day, e.g. "Sunday, November 1, 2026".
|
|
34
|
+
* Formatted as a pure calendar date (no time, no zone shift) so the header
|
|
35
|
+
* always names the day the driver picked.
|
|
36
|
+
*/
|
|
37
|
+
export declare function formatLocalDay(date: string): string;
|
|
@@ -10,20 +10,20 @@ import { Phone as c } from "../node_modules/lucide-react/dist/esm/icons/phone.js
|
|
|
10
10
|
import { RefreshCw as l } from "../node_modules/lucide-react/dist/esm/icons/refresh-cw.js";
|
|
11
11
|
import { Route as u } from "../node_modules/lucide-react/dist/esm/icons/route.js";
|
|
12
12
|
import { TriangleAlert as d } from "../node_modules/lucide-react/dist/esm/icons/triangle-alert.js";
|
|
13
|
-
import { Truck as
|
|
14
|
-
import { WifiOff as
|
|
15
|
-
import { useMoveTheWheels as
|
|
16
|
-
import { formatAddress as
|
|
17
|
-
import { mapOrderPriority as
|
|
18
|
-
import { localDateString as
|
|
19
|
-
import { useMyDeliveryDay as re, useOnlineStatus as
|
|
20
|
-
import { Badge as S, Button as C, Card as w, CardContent as T, Input as
|
|
21
|
-
import { PageLayout as
|
|
22
|
-
import { PriorityBadge as
|
|
23
|
-
import { FormError as
|
|
24
|
-
import { Notice as
|
|
13
|
+
import { Truck as f } from "../node_modules/lucide-react/dist/esm/icons/truck.js";
|
|
14
|
+
import { WifiOff as ee } from "../node_modules/lucide-react/dist/esm/icons/wifi-off.js";
|
|
15
|
+
import { useMoveTheWheels as te } from "../providers/MoveTheWheelsProvider.js";
|
|
16
|
+
import { formatAddress as p, formatDate as m, formatTime as h } from "../utils/formatters.js";
|
|
17
|
+
import { mapOrderPriority as g } from "../hooks/useOrders.js";
|
|
18
|
+
import { formatLocalDay as _, localDateString as v, phoneHref as y, routeNavigationUrl as ne, shiftLocalDate as b, stopNavigationUrl as x } from "../utils/driverNavigation.js";
|
|
19
|
+
import { useMyDeliveryDay as re, useOnlineStatus as ie } from "../hooks/useDriverDay.js";
|
|
20
|
+
import { Badge as S, Button as C, Card as w, CardContent as T, Input as E, Progress as D } from "../components/ui.js";
|
|
21
|
+
import { PageLayout as O } from "../components/PageLayout.js";
|
|
22
|
+
import { PriorityBadge as k } from "../components/StatusBadge.js";
|
|
23
|
+
import { FormError as A } from "../components/FormError.js";
|
|
24
|
+
import { Notice as j, useNotice as ae } from "../components/Notice.js";
|
|
25
25
|
import { EpodCaptureForm as oe } from "../components/EpodCaptureForm.js";
|
|
26
|
-
import { useEffect as se, useMemo as
|
|
26
|
+
import { useEffect as se, useMemo as M, useRef as ce, useState as N } from "react";
|
|
27
27
|
import { Fragment as P, jsx as F, jsxs as I } from "react/jsx-runtime";
|
|
28
28
|
//#region src/movethewheels/pages/DeliveryCapturePage.tsx
|
|
29
29
|
var L = {
|
|
@@ -96,7 +96,7 @@ function W({ stop: e, onOpen: t, onCapture: n, offline: r }) {
|
|
|
96
96
|
}),
|
|
97
97
|
e.deliveryAddress && /* @__PURE__ */ F("p", {
|
|
98
98
|
className: "mt-1 text-sm text-text-secondary",
|
|
99
|
-
children:
|
|
99
|
+
children: p(e.deliveryAddress)
|
|
100
100
|
}),
|
|
101
101
|
/* @__PURE__ */ I("p", {
|
|
102
102
|
className: "mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-xs text-text-secondary",
|
|
@@ -106,7 +106,7 @@ function W({ stop: e, onOpen: t, onCapture: n, offline: r }) {
|
|
|
106
106
|
children: [
|
|
107
107
|
/* @__PURE__ */ F(a, { size: 12 }),
|
|
108
108
|
" ",
|
|
109
|
-
|
|
109
|
+
h(e.scheduledDelivery)
|
|
110
110
|
]
|
|
111
111
|
}),
|
|
112
112
|
/* @__PURE__ */ I("span", {
|
|
@@ -139,8 +139,8 @@ function W({ stop: e, onOpen: t, onCapture: n, offline: r }) {
|
|
|
139
139
|
]
|
|
140
140
|
}) });
|
|
141
141
|
}
|
|
142
|
-
function
|
|
143
|
-
let s =
|
|
142
|
+
function le({ stop: t, onBack: n, onCapture: r, offline: a }) {
|
|
143
|
+
let s = x(t.deliveryAddress), l = y(t.customerPhone);
|
|
144
144
|
return /* @__PURE__ */ I("div", {
|
|
145
145
|
className: "space-y-4",
|
|
146
146
|
children: [/* @__PURE__ */ I(C, {
|
|
@@ -161,8 +161,8 @@ function G({ stop: t, onBack: n, onCapture: r, offline: a }) {
|
|
|
161
161
|
children: ["Stop ", t.sequence]
|
|
162
162
|
}),
|
|
163
163
|
/* @__PURE__ */ F(H, { state: t.state }),
|
|
164
|
-
/* @__PURE__ */ F(
|
|
165
|
-
priority:
|
|
164
|
+
/* @__PURE__ */ F(k, {
|
|
165
|
+
priority: g(t.priority),
|
|
166
166
|
size: "sm"
|
|
167
167
|
}),
|
|
168
168
|
t.overdue && /* @__PURE__ */ F(S, {
|
|
@@ -179,7 +179,7 @@ function G({ stop: t, onBack: n, onCapture: r, offline: a }) {
|
|
|
179
179
|
children: "Deliver to"
|
|
180
180
|
}), /* @__PURE__ */ F("dd", {
|
|
181
181
|
className: "font-medium",
|
|
182
|
-
children: t.deliveryAddress ?
|
|
182
|
+
children: t.deliveryAddress ? p(t.deliveryAddress) : "No address on file"
|
|
183
183
|
})] }),
|
|
184
184
|
t.customerName && /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("dt", {
|
|
185
185
|
className: "text-text-secondary",
|
|
@@ -200,7 +200,7 @@ function G({ stop: t, onBack: n, onCapture: r, offline: a }) {
|
|
|
200
200
|
children: "Scheduled"
|
|
201
201
|
}), /* @__PURE__ */ F("dd", {
|
|
202
202
|
className: "font-medium",
|
|
203
|
-
children:
|
|
203
|
+
children: m(t.scheduledDelivery, "full")
|
|
204
204
|
})] }),
|
|
205
205
|
t.routeName && /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("dt", {
|
|
206
206
|
className: "text-text-secondary",
|
|
@@ -221,7 +221,7 @@ function G({ stop: t, onBack: n, onCapture: r, offline: a }) {
|
|
|
221
221
|
children: "Proof of delivery captured"
|
|
222
222
|
}), /* @__PURE__ */ F("dd", {
|
|
223
223
|
className: "font-medium",
|
|
224
|
-
children:
|
|
224
|
+
children: m(t.deliveredAt, "full")
|
|
225
225
|
})] })
|
|
226
226
|
]
|
|
227
227
|
}),
|
|
@@ -257,46 +257,46 @@ function G({ stop: t, onBack: n, onCapture: r, offline: a }) {
|
|
|
257
257
|
}) })]
|
|
258
258
|
});
|
|
259
259
|
}
|
|
260
|
-
function
|
|
261
|
-
let { workspaceId: e, tenantId: a, currentUser: o, apiGatewayUrl: s } =
|
|
260
|
+
function G() {
|
|
261
|
+
let { workspaceId: e, tenantId: a, currentUser: o, apiGatewayUrl: s } = te(), c = ie(), m = !c, [h, g] = N(() => v(/* @__PURE__ */ new Date())), [y, x] = N("all"), [S, k] = N({ kind: "list" }), { day: L, isLoading: R, error: H, refetch: U, markCaptured: G } = re(h), { message: ue, notify: K } = ae(), q = v(/* @__PURE__ */ new Date()), J = ce(!1);
|
|
262
262
|
se(() => {
|
|
263
|
-
c ? J.current && (J.current = !1,
|
|
264
|
-
}, [c,
|
|
265
|
-
let Y =
|
|
266
|
-
|
|
263
|
+
c ? J.current && (J.current = !1, U()) : J.current = !0;
|
|
264
|
+
}, [c, U]);
|
|
265
|
+
let Y = M(() => L?.stops ?? [], [L]), X = M(() => Y.filter((e) => y === "all" ? !0 : y === "completed" ? z(e) : !z(e)), [Y, y]), Z = M(() => ne(Y.filter((e) => !z(e)).map((e) => e.deliveryAddress)), [Y]), Q = S.kind === "list" ? null : Y.find((e) => e.jobId === S.jobId) ?? null, de = (e) => {
|
|
266
|
+
G(e), K("Proof of delivery captured — delivery marked complete."), k({ kind: "list" }), U();
|
|
267
267
|
}, $ = (e) => {
|
|
268
|
-
/^\d{4}-\d{2}-\d{2}$/.test(e) && (
|
|
269
|
-
}, fe =
|
|
270
|
-
return /* @__PURE__ */ F(
|
|
268
|
+
/^\d{4}-\d{2}-\d{2}$/.test(e) && (g(e), k({ kind: "list" }));
|
|
269
|
+
}, fe = L && L.totalStops > 0 ? L.completedStops / L.totalStops * 100 : 0;
|
|
270
|
+
return /* @__PURE__ */ F(O, {
|
|
271
271
|
title: "My Deliveries",
|
|
272
272
|
subtitle: "Your stops for the day, in order — navigate, then capture proof of delivery",
|
|
273
|
-
icon: /* @__PURE__ */ F(
|
|
273
|
+
icon: /* @__PURE__ */ F(f, { size: 24 }),
|
|
274
274
|
maxWidth: "2xl",
|
|
275
275
|
children: /* @__PURE__ */ I("div", {
|
|
276
276
|
className: "space-y-4",
|
|
277
277
|
children: [
|
|
278
|
-
/* @__PURE__ */ F(
|
|
278
|
+
/* @__PURE__ */ F(j, { message: ue }),
|
|
279
279
|
m && /* @__PURE__ */ I("div", {
|
|
280
280
|
role: "status",
|
|
281
281
|
className: "flex items-start gap-2 rounded-md border border-border bg-surface-secondary p-3 text-sm",
|
|
282
|
-
children: [/* @__PURE__ */ F(
|
|
282
|
+
children: [/* @__PURE__ */ F(ee, {
|
|
283
283
|
size: 16,
|
|
284
284
|
className: "mt-0.5 shrink-0"
|
|
285
285
|
}), /* @__PURE__ */ F("span", { children: "You are offline. Your last loaded stops stay available; reconnect to capture proof of delivery." })]
|
|
286
286
|
}),
|
|
287
|
-
Q &&
|
|
287
|
+
Q && S.kind === "capture" && Q.awaitingCapture ? /* @__PURE__ */ F(oe, {
|
|
288
288
|
job: B(Q),
|
|
289
289
|
offline: m,
|
|
290
290
|
onCaptured: de,
|
|
291
|
-
onCancel: () =>
|
|
291
|
+
onCancel: () => k({
|
|
292
292
|
kind: "stop",
|
|
293
293
|
jobId: Q.jobId
|
|
294
294
|
})
|
|
295
|
-
}, `${e}:${a}:${o?.id}:${s}:${Q.jobId}`) : Q ? /* @__PURE__ */ F(
|
|
295
|
+
}, `${e}:${a}:${o?.id}:${s}:${Q.jobId}`) : Q ? /* @__PURE__ */ F(le, {
|
|
296
296
|
stop: Q,
|
|
297
297
|
offline: m,
|
|
298
|
-
onBack: () =>
|
|
299
|
-
onCapture: () =>
|
|
298
|
+
onBack: () => k({ kind: "list" }),
|
|
299
|
+
onCapture: () => k({
|
|
300
300
|
kind: "capture",
|
|
301
301
|
jobId: Q.jobId
|
|
302
302
|
})
|
|
@@ -309,7 +309,7 @@ function K() {
|
|
|
309
309
|
variant: "outline",
|
|
310
310
|
size: "sm",
|
|
311
311
|
"aria-label": "Previous day",
|
|
312
|
-
onClick: () => $(
|
|
312
|
+
onClick: () => $(b(h, -1)),
|
|
313
313
|
children: /* @__PURE__ */ F(n, { size: 16 })
|
|
314
314
|
}),
|
|
315
315
|
/* @__PURE__ */ I(C, {
|
|
@@ -324,10 +324,10 @@ function K() {
|
|
|
324
324
|
variant: "outline",
|
|
325
325
|
size: "sm",
|
|
326
326
|
"aria-label": "Next day",
|
|
327
|
-
onClick: () => $(
|
|
327
|
+
onClick: () => $(b(h, 1)),
|
|
328
328
|
children: /* @__PURE__ */ F(r, { size: 16 })
|
|
329
329
|
}),
|
|
330
|
-
/* @__PURE__ */ F(
|
|
330
|
+
/* @__PURE__ */ F(E, {
|
|
331
331
|
type: "date",
|
|
332
332
|
"aria-label": "Delivery date",
|
|
333
333
|
value: h,
|
|
@@ -339,20 +339,20 @@ function K() {
|
|
|
339
339
|
variant: "ghost",
|
|
340
340
|
size: "sm",
|
|
341
341
|
"aria-label": "Refresh stops",
|
|
342
|
-
disabled:
|
|
343
|
-
onClick: () => void
|
|
342
|
+
disabled: R || m,
|
|
343
|
+
onClick: () => void U(),
|
|
344
344
|
children: /* @__PURE__ */ F(l, {
|
|
345
345
|
size: 16,
|
|
346
|
-
className:
|
|
346
|
+
className: R ? "animate-spin" : void 0
|
|
347
347
|
})
|
|
348
348
|
})
|
|
349
349
|
]
|
|
350
350
|
}),
|
|
351
|
-
|
|
352
|
-
|
|
351
|
+
H && /* @__PURE__ */ F(A, { message: H.message }),
|
|
352
|
+
R && !L ? /* @__PURE__ */ F("p", {
|
|
353
353
|
className: "py-8 text-center text-text-secondary",
|
|
354
354
|
children: "Loading your deliveries…"
|
|
355
|
-
}) :
|
|
355
|
+
}) : L && L.driverId === null ? /* @__PURE__ */ I("div", {
|
|
356
356
|
className: "py-12 text-center",
|
|
357
357
|
children: [/* @__PURE__ */ F(d, {
|
|
358
358
|
size: 40,
|
|
@@ -361,7 +361,7 @@ function K() {
|
|
|
361
361
|
className: "text-text-secondary",
|
|
362
362
|
children: "Your account is not linked to a driver in this workspace. Ask your dispatcher to link your user on the driver profile."
|
|
363
363
|
})]
|
|
364
|
-
}) :
|
|
364
|
+
}) : L ? /* @__PURE__ */ I(P, { children: [
|
|
365
365
|
/* @__PURE__ */ F(w, { children: /* @__PURE__ */ I(T, {
|
|
366
366
|
className: "space-y-3 py-4",
|
|
367
367
|
children: [
|
|
@@ -370,35 +370,35 @@ function K() {
|
|
|
370
370
|
children: [/* @__PURE__ */ I("p", {
|
|
371
371
|
className: "font-medium",
|
|
372
372
|
children: [
|
|
373
|
-
|
|
373
|
+
L.completedStops,
|
|
374
374
|
" of ",
|
|
375
|
-
|
|
375
|
+
L.totalStops,
|
|
376
376
|
" stops done",
|
|
377
|
-
|
|
377
|
+
L.driverName ? ` · ${L.driverName}` : ""
|
|
378
378
|
]
|
|
379
379
|
}), /* @__PURE__ */ F("p", {
|
|
380
380
|
className: "text-sm text-text-secondary",
|
|
381
|
-
children:
|
|
381
|
+
children: _(h)
|
|
382
382
|
})]
|
|
383
383
|
}),
|
|
384
|
-
/* @__PURE__ */ F(
|
|
384
|
+
/* @__PURE__ */ F(D, {
|
|
385
385
|
value: fe,
|
|
386
386
|
"aria-label": "Stops completed"
|
|
387
387
|
}),
|
|
388
|
-
|
|
388
|
+
L.nextStop && /* @__PURE__ */ I("div", {
|
|
389
389
|
className: "rounded-md border border-border p-3",
|
|
390
390
|
children: [
|
|
391
391
|
/* @__PURE__ */ I("p", {
|
|
392
392
|
className: "text-xs uppercase tracking-wide text-text-secondary",
|
|
393
|
-
children: ["Next stop · Stop ",
|
|
393
|
+
children: ["Next stop · Stop ", L.nextStop.sequence]
|
|
394
394
|
}),
|
|
395
395
|
/* @__PURE__ */ F("p", {
|
|
396
396
|
className: "mt-1 font-medium",
|
|
397
|
-
children:
|
|
397
|
+
children: L.nextStop.deliveryAddress ? p(L.nextStop.deliveryAddress) : L.nextStop.deliveryJobNumber
|
|
398
398
|
}),
|
|
399
|
-
|
|
399
|
+
L.nextStop.customerName && /* @__PURE__ */ I("p", {
|
|
400
400
|
className: "text-sm text-text-secondary",
|
|
401
|
-
children: ["Recipient: ",
|
|
401
|
+
children: ["Recipient: ", L.nextStop.customerName]
|
|
402
402
|
}),
|
|
403
403
|
/* @__PURE__ */ I("div", {
|
|
404
404
|
className: "mt-3 grid gap-2 sm:grid-cols-2",
|
|
@@ -411,8 +411,8 @@ function K() {
|
|
|
411
411
|
type: "button",
|
|
412
412
|
variant: "outline",
|
|
413
413
|
onClick: () => {
|
|
414
|
-
let e =
|
|
415
|
-
e &&
|
|
414
|
+
let e = L.nextStop;
|
|
415
|
+
e && k({
|
|
416
416
|
kind: "stop",
|
|
417
417
|
jobId: e.jobId
|
|
418
418
|
});
|
|
@@ -429,16 +429,16 @@ function K() {
|
|
|
429
429
|
"aria-label": "Filter stops",
|
|
430
430
|
className: "flex gap-2",
|
|
431
431
|
children: [
|
|
432
|
-
["all", `All stops (${
|
|
433
|
-
["remaining", `Remaining (${
|
|
434
|
-
["completed", `Done (${
|
|
432
|
+
["all", `All stops (${L.totalStops})`],
|
|
433
|
+
["remaining", `Remaining (${L.remainingStops})`],
|
|
434
|
+
["completed", `Done (${L.completedStops})`]
|
|
435
435
|
].map(([e, t]) => /* @__PURE__ */ F(C, {
|
|
436
436
|
type: "button",
|
|
437
437
|
role: "tab",
|
|
438
|
-
"aria-selected":
|
|
438
|
+
"aria-selected": y === e,
|
|
439
439
|
size: "sm",
|
|
440
|
-
variant:
|
|
441
|
-
onClick: () =>
|
|
440
|
+
variant: y === e ? "default" : "outline",
|
|
441
|
+
onClick: () => x(e),
|
|
442
442
|
children: t
|
|
443
443
|
}, e))
|
|
444
444
|
}),
|
|
@@ -447,11 +447,11 @@ function K() {
|
|
|
447
447
|
children: X.map((e) => /* @__PURE__ */ F(W, {
|
|
448
448
|
stop: e,
|
|
449
449
|
offline: m,
|
|
450
|
-
onOpen: () =>
|
|
450
|
+
onOpen: () => k({
|
|
451
451
|
kind: "stop",
|
|
452
452
|
jobId: e.jobId
|
|
453
453
|
}),
|
|
454
|
-
onCapture: () =>
|
|
454
|
+
onCapture: () => k({
|
|
455
455
|
kind: "capture",
|
|
456
456
|
jobId: e.jobId
|
|
457
457
|
})
|
|
@@ -463,7 +463,7 @@ function K() {
|
|
|
463
463
|
className: "mx-auto mb-3 text-text-secondary opacity-50"
|
|
464
464
|
}), /* @__PURE__ */ F("p", {
|
|
465
465
|
className: "text-text-secondary",
|
|
466
|
-
children:
|
|
466
|
+
children: L.totalStops === 0 ? "No deliveries scheduled for this day." : y === "completed" ? "No stops completed yet." : "All stops done for this day."
|
|
467
467
|
})]
|
|
468
468
|
})
|
|
469
469
|
] }) : null
|
|
@@ -473,4 +473,4 @@ function K() {
|
|
|
473
473
|
});
|
|
474
474
|
}
|
|
475
475
|
//#endregion
|
|
476
|
-
export {
|
|
476
|
+
export { G as default };
|
|
@@ -47,5 +47,15 @@ function l() {
|
|
|
47
47
|
return null;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
+
function u(e) {
|
|
51
|
+
let [t, n, r] = e.split("-").map(Number);
|
|
52
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
53
|
+
weekday: "long",
|
|
54
|
+
year: "numeric",
|
|
55
|
+
month: "long",
|
|
56
|
+
day: "numeric",
|
|
57
|
+
timeZone: "UTC"
|
|
58
|
+
}).format(new Date(Date.UTC(t, n - 1, r)));
|
|
59
|
+
}
|
|
50
60
|
//#endregion
|
|
51
|
-
export { l as deviceTimeZone, o as localDateString, a as phoneHref, i as routeNavigationUrl, s as shiftLocalDate, r as stopNavigationUrl, c as timezoneOffsetFor };
|
|
61
|
+
export { l as deviceTimeZone, u as formatLocalDay, o as localDateString, a as phoneHref, i as routeNavigationUrl, s as shiftLocalDate, r as stopNavigationUrl, c as timezoneOffsetFor };
|
package/package.json
CHANGED
|
@@ -397,14 +397,14 @@ export type GetMovethewheelsDemandForecastByLaneQueryVariables = Exact<{
|
|
|
397
397
|
}>;
|
|
398
398
|
|
|
399
399
|
|
|
400
|
-
export type GetMovethewheelsDemandForecastByLaneQuery = { demandForecastByLane: Array<{ scopeType: Types.DemandForecastScope, scopeKey: string, periodStart: string, periodEnd: string, predictedVolume: number, predictedRevenue: number, actualVolume: number | null, actualRevenue: number | null, confidence: number }> };
|
|
400
|
+
export type GetMovethewheelsDemandForecastByLaneQuery = { demandForecastByLane: Array<{ scopeType: Types.DemandForecastScope, scopeKey: string, scopeLabel: string, periodStart: string, periodEnd: string, predictedVolume: number, predictedRevenue: number, actualVolume: number | null, actualRevenue: number | null, confidence: number }> };
|
|
401
401
|
|
|
402
402
|
export type GetMovethewheelsDemandForecastByCustomerQueryVariables = Exact<{
|
|
403
403
|
weeks: number;
|
|
404
404
|
}>;
|
|
405
405
|
|
|
406
406
|
|
|
407
|
-
export type GetMovethewheelsDemandForecastByCustomerQuery = { demandForecastByCustomer: Array<{ scopeType: Types.DemandForecastScope, scopeKey: string, periodStart: string, periodEnd: string, predictedVolume: number, predictedRevenue: number, actualVolume: number | null, actualRevenue: number | null, confidence: number }> };
|
|
407
|
+
export type GetMovethewheelsDemandForecastByCustomerQuery = { demandForecastByCustomer: Array<{ scopeType: Types.DemandForecastScope, scopeKey: string, scopeLabel: string, periodStart: string, periodEnd: string, predictedVolume: number, predictedRevenue: number, actualVolume: number | null, actualRevenue: number | null, confidence: number }> };
|
|
408
408
|
|
|
409
409
|
export type GetMovethewheelsDemandForecastVarianceQueryVariables = Exact<{
|
|
410
410
|
scopeType: Types.DemandForecastScope;
|
|
@@ -412,7 +412,7 @@ export type GetMovethewheelsDemandForecastVarianceQueryVariables = Exact<{
|
|
|
412
412
|
}>;
|
|
413
413
|
|
|
414
414
|
|
|
415
|
-
export type GetMovethewheelsDemandForecastVarianceQuery = { demandForecastVariance: Array<{ scopeType: Types.DemandForecastScope, scopeKey: string, periodStart: string, periodEnd: string, predictedVolume: number, actualVolume: number, volumeVariance: number, predictedRevenue: number, actualRevenue: number, revenueVariance: number }> };
|
|
415
|
+
export type GetMovethewheelsDemandForecastVarianceQuery = { demandForecastVariance: Array<{ scopeType: Types.DemandForecastScope, scopeKey: string, scopeLabel: string, periodStart: string, periodEnd: string, predictedVolume: number, actualVolume: number, volumeVariance: number, predictedRevenue: number, actualRevenue: number, revenueVariance: number }> };
|
|
416
416
|
|
|
417
417
|
export type ListInventoryItemsQueryVariables = Exact<{
|
|
418
418
|
filter?: Types.InventoryFilterInput | null | undefined;
|
|
@@ -549,9 +549,9 @@ export const ListDriversDocument = {"kind":"Document","definitions":[{"kind":"Op
|
|
|
549
549
|
export const GetDriverDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetDriver"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"driver"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"DriverCore"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"DriverCore"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"MtwDriver"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"employeeId"}},{"kind":"Field","name":{"kind":"Name","value":"firstName"}},{"kind":"Field","name":{"kind":"Name","value":"lastName"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"licenseNumber"}},{"kind":"Field","name":{"kind":"Name","value":"licenseClass"}},{"kind":"Field","name":{"kind":"Name","value":"licenseExpiry"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"currentLocation"}},{"kind":"Field","name":{"kind":"Name","value":"rating"}},{"kind":"Field","name":{"kind":"Name","value":"userId"}},{"kind":"Field","name":{"kind":"Name","value":"vehicleId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<GetDriverQuery, GetDriverQueryVariables>;
|
|
550
550
|
export const ListWarehousesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ListWarehouses"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"WarehouseFilterInput"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"PaginationInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"warehouses"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}},{"kind":"Argument","name":{"kind":"Name","value":"pagination"},"value":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WarehouseCore"}},{"kind":"Field","name":{"kind":"Name","value":"locations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"locationCode"}},{"kind":"Field","name":{"kind":"Name","value":"zone"}},{"kind":"Field","name":{"kind":"Name","value":"aisle"}},{"kind":"Field","name":{"kind":"Name","value":"rack"}},{"kind":"Field","name":{"kind":"Name","value":"shelf"}},{"kind":"Field","name":{"kind":"Name","value":"bin"}},{"kind":"Field","name":{"kind":"Name","value":"locationType"}},{"kind":"Field","name":{"kind":"Name","value":"capacity"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WarehouseCore"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"MtwWarehouse"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"address"}},{"kind":"Field","name":{"kind":"Name","value":"contactInfo"}},{"kind":"Field","name":{"kind":"Name","value":"operatingHours"}},{"kind":"Field","name":{"kind":"Name","value":"capabilities"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"totalCapacity"}},{"kind":"Field","name":{"kind":"Name","value":"usedCapacity"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<ListWarehousesQuery, ListWarehousesQueryVariables>;
|
|
551
551
|
export const GetWarehouseDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetWarehouse"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"warehouse"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WarehouseCore"}},{"kind":"Field","name":{"kind":"Name","value":"locations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"locationCode"}},{"kind":"Field","name":{"kind":"Name","value":"zone"}},{"kind":"Field","name":{"kind":"Name","value":"aisle"}},{"kind":"Field","name":{"kind":"Name","value":"rack"}},{"kind":"Field","name":{"kind":"Name","value":"shelf"}},{"kind":"Field","name":{"kind":"Name","value":"bin"}},{"kind":"Field","name":{"kind":"Name","value":"locationType"}},{"kind":"Field","name":{"kind":"Name","value":"capacity"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WarehouseCore"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"MtwWarehouse"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"address"}},{"kind":"Field","name":{"kind":"Name","value":"contactInfo"}},{"kind":"Field","name":{"kind":"Name","value":"operatingHours"}},{"kind":"Field","name":{"kind":"Name","value":"capabilities"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"totalCapacity"}},{"kind":"Field","name":{"kind":"Name","value":"usedCapacity"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<GetWarehouseQuery, GetWarehouseQueryVariables>;
|
|
552
|
-
export const GetMovethewheelsDemandForecastByLaneDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetMovethewheelsDemandForecastByLane"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"weeks"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"demandForecastByLane"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"weeks"},"value":{"kind":"Variable","name":{"kind":"Name","value":"weeks"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"scopeType"}},{"kind":"Field","name":{"kind":"Name","value":"scopeKey"}},{"kind":"Field","name":{"kind":"Name","value":"periodStart"}},{"kind":"Field","name":{"kind":"Name","value":"periodEnd"}},{"kind":"Field","name":{"kind":"Name","value":"predictedVolume"}},{"kind":"Field","name":{"kind":"Name","value":"predictedRevenue"}},{"kind":"Field","name":{"kind":"Name","value":"actualVolume"}},{"kind":"Field","name":{"kind":"Name","value":"actualRevenue"}},{"kind":"Field","name":{"kind":"Name","value":"confidence"}}]}}]}}]} as unknown as DocumentNode<GetMovethewheelsDemandForecastByLaneQuery, GetMovethewheelsDemandForecastByLaneQueryVariables>;
|
|
553
|
-
export const GetMovethewheelsDemandForecastByCustomerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetMovethewheelsDemandForecastByCustomer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"weeks"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"demandForecastByCustomer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"weeks"},"value":{"kind":"Variable","name":{"kind":"Name","value":"weeks"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"scopeType"}},{"kind":"Field","name":{"kind":"Name","value":"scopeKey"}},{"kind":"Field","name":{"kind":"Name","value":"periodStart"}},{"kind":"Field","name":{"kind":"Name","value":"periodEnd"}},{"kind":"Field","name":{"kind":"Name","value":"predictedVolume"}},{"kind":"Field","name":{"kind":"Name","value":"predictedRevenue"}},{"kind":"Field","name":{"kind":"Name","value":"actualVolume"}},{"kind":"Field","name":{"kind":"Name","value":"actualRevenue"}},{"kind":"Field","name":{"kind":"Name","value":"confidence"}}]}}]}}]} as unknown as DocumentNode<GetMovethewheelsDemandForecastByCustomerQuery, GetMovethewheelsDemandForecastByCustomerQueryVariables>;
|
|
554
|
-
export const GetMovethewheelsDemandForecastVarianceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetMovethewheelsDemandForecastVariance"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"scopeType"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DemandForecastScope"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"demandForecastVariance"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"scopeType"},"value":{"kind":"Variable","name":{"kind":"Name","value":"scopeType"}}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"scopeType"}},{"kind":"Field","name":{"kind":"Name","value":"scopeKey"}},{"kind":"Field","name":{"kind":"Name","value":"periodStart"}},{"kind":"Field","name":{"kind":"Name","value":"periodEnd"}},{"kind":"Field","name":{"kind":"Name","value":"predictedVolume"}},{"kind":"Field","name":{"kind":"Name","value":"actualVolume"}},{"kind":"Field","name":{"kind":"Name","value":"volumeVariance"}},{"kind":"Field","name":{"kind":"Name","value":"predictedRevenue"}},{"kind":"Field","name":{"kind":"Name","value":"actualRevenue"}},{"kind":"Field","name":{"kind":"Name","value":"revenueVariance"}}]}}]}}]} as unknown as DocumentNode<GetMovethewheelsDemandForecastVarianceQuery, GetMovethewheelsDemandForecastVarianceQueryVariables>;
|
|
552
|
+
export const GetMovethewheelsDemandForecastByLaneDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetMovethewheelsDemandForecastByLane"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"weeks"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"demandForecastByLane"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"weeks"},"value":{"kind":"Variable","name":{"kind":"Name","value":"weeks"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"scopeType"}},{"kind":"Field","name":{"kind":"Name","value":"scopeKey"}},{"kind":"Field","name":{"kind":"Name","value":"scopeLabel"}},{"kind":"Field","name":{"kind":"Name","value":"periodStart"}},{"kind":"Field","name":{"kind":"Name","value":"periodEnd"}},{"kind":"Field","name":{"kind":"Name","value":"predictedVolume"}},{"kind":"Field","name":{"kind":"Name","value":"predictedRevenue"}},{"kind":"Field","name":{"kind":"Name","value":"actualVolume"}},{"kind":"Field","name":{"kind":"Name","value":"actualRevenue"}},{"kind":"Field","name":{"kind":"Name","value":"confidence"}}]}}]}}]} as unknown as DocumentNode<GetMovethewheelsDemandForecastByLaneQuery, GetMovethewheelsDemandForecastByLaneQueryVariables>;
|
|
553
|
+
export const GetMovethewheelsDemandForecastByCustomerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetMovethewheelsDemandForecastByCustomer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"weeks"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"demandForecastByCustomer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"weeks"},"value":{"kind":"Variable","name":{"kind":"Name","value":"weeks"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"scopeType"}},{"kind":"Field","name":{"kind":"Name","value":"scopeKey"}},{"kind":"Field","name":{"kind":"Name","value":"scopeLabel"}},{"kind":"Field","name":{"kind":"Name","value":"periodStart"}},{"kind":"Field","name":{"kind":"Name","value":"periodEnd"}},{"kind":"Field","name":{"kind":"Name","value":"predictedVolume"}},{"kind":"Field","name":{"kind":"Name","value":"predictedRevenue"}},{"kind":"Field","name":{"kind":"Name","value":"actualVolume"}},{"kind":"Field","name":{"kind":"Name","value":"actualRevenue"}},{"kind":"Field","name":{"kind":"Name","value":"confidence"}}]}}]}}]} as unknown as DocumentNode<GetMovethewheelsDemandForecastByCustomerQuery, GetMovethewheelsDemandForecastByCustomerQueryVariables>;
|
|
554
|
+
export const GetMovethewheelsDemandForecastVarianceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetMovethewheelsDemandForecastVariance"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"scopeType"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DemandForecastScope"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"demandForecastVariance"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"scopeType"},"value":{"kind":"Variable","name":{"kind":"Name","value":"scopeType"}}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"scopeType"}},{"kind":"Field","name":{"kind":"Name","value":"scopeKey"}},{"kind":"Field","name":{"kind":"Name","value":"scopeLabel"}},{"kind":"Field","name":{"kind":"Name","value":"periodStart"}},{"kind":"Field","name":{"kind":"Name","value":"periodEnd"}},{"kind":"Field","name":{"kind":"Name","value":"predictedVolume"}},{"kind":"Field","name":{"kind":"Name","value":"actualVolume"}},{"kind":"Field","name":{"kind":"Name","value":"volumeVariance"}},{"kind":"Field","name":{"kind":"Name","value":"predictedRevenue"}},{"kind":"Field","name":{"kind":"Name","value":"actualRevenue"}},{"kind":"Field","name":{"kind":"Name","value":"revenueVariance"}}]}}]}}]} as unknown as DocumentNode<GetMovethewheelsDemandForecastVarianceQuery, GetMovethewheelsDemandForecastVarianceQueryVariables>;
|
|
555
555
|
export const ListInventoryItemsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ListInventoryItems"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"InventoryFilterInput"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"PaginationInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"inventoryItems"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}},{"kind":"Argument","name":{"kind":"Name","value":"pagination"},"value":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"InventoryItemCore"}},{"kind":"Field","name":{"kind":"Name","value":"cargoItem"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"sku"}},{"kind":"Field","name":{"kind":"Name","value":"category"}}]}},{"kind":"Field","name":{"kind":"Name","value":"warehouse"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"type"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"InventoryItemCore"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"MtwInventoryItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"cargoItemId"}},{"kind":"Field","name":{"kind":"Name","value":"warehouseId"}},{"kind":"Field","name":{"kind":"Name","value":"locationId"}},{"kind":"Field","name":{"kind":"Name","value":"onHand"}},{"kind":"Field","name":{"kind":"Name","value":"available"}},{"kind":"Field","name":{"kind":"Name","value":"allocated"}},{"kind":"Field","name":{"kind":"Name","value":"damaged"}},{"kind":"Field","name":{"kind":"Name","value":"unitCost"}},{"kind":"Field","name":{"kind":"Name","value":"reorderPoint"}},{"kind":"Field","name":{"kind":"Name","value":"safetyStock"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<ListInventoryItemsQuery, ListInventoryItemsQueryVariables>;
|
|
556
556
|
export const GetInventoryStatsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetInventoryStats"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"inventoryStats"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalOnHand"}},{"kind":"Field","name":{"kind":"Name","value":"totalAvailable"}},{"kind":"Field","name":{"kind":"Name","value":"totalAllocated"}},{"kind":"Field","name":{"kind":"Name","value":"totalDamaged"}},{"kind":"Field","name":{"kind":"Name","value":"lowStockCount"}}]}}]}}]} as unknown as DocumentNode<GetInventoryStatsQuery, GetInventoryStatsQueryVariables>;
|
|
557
557
|
export const ListRoutesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ListRoutes"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"RouteFilterInput"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"PaginationInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"routes"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}},{"kind":"Argument","name":{"kind":"Name","value":"pagination"},"value":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"RouteCore"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RouteCore"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"MtwRoute"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"shipmentId"}},{"kind":"Field","name":{"kind":"Name","value":"vehicleId"}},{"kind":"Field","name":{"kind":"Name","value":"driverId"}},{"kind":"Field","name":{"kind":"Name","value":"waypoints"}},{"kind":"Field","name":{"kind":"Name","value":"estimatedDistance"}},{"kind":"Field","name":{"kind":"Name","value":"estimatedDuration"}},{"kind":"Field","name":{"kind":"Name","value":"actualDistance"}},{"kind":"Field","name":{"kind":"Name","value":"actualDuration"}},{"kind":"Field","name":{"kind":"Name","value":"fuelCost"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode<ListRoutesQuery, ListRoutesQueryVariables>;
|
|
@@ -4,11 +4,17 @@
|
|
|
4
4
|
* Surfaces next-week demand forecasts by lane / customer alongside the
|
|
5
5
|
* most recent closed-period variance (BOFF-4393). Pure read-side view
|
|
6
6
|
* over `wspace-movethewheels-svc`'s DemandForecast surface.
|
|
7
|
+
*
|
|
8
|
+
* "Next week" is the first forecast week that has not begun yet: the current
|
|
9
|
+
* week's rows are kept server-side for the closed-period variance, but they
|
|
10
|
+
* are not upcoming demand. Cold-start rows (confidence 0, fewer than 4 weeks
|
|
11
|
+
* of history for that lane or customer) are not shown as forecasts.
|
|
7
12
|
*/
|
|
8
13
|
|
|
9
14
|
import { Calendar, TrendingUp, TrendingDown, AlertCircle } from 'lucide-react';
|
|
10
15
|
|
|
11
16
|
import { Card, CardContent, CardHeader, CardTitle, Skeleton } from './ui';
|
|
17
|
+
import { formatCurrency } from '../utils/formatters';
|
|
12
18
|
|
|
13
19
|
import type { ForecastPoint, ForecastVariance } from '../hooks/useDemandForecast';
|
|
14
20
|
|
|
@@ -28,20 +34,41 @@ const formatWeek = (iso: string): string => {
|
|
|
28
34
|
return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
|
|
29
35
|
};
|
|
30
36
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
};
|
|
37
|
+
/** Rows for one week that rest on enough history to be a forecast. */
|
|
38
|
+
const forecastsFor = (rows: ForecastPoint[], weekStart: string): ForecastPoint[] =>
|
|
39
|
+
rows.filter((row) => row.periodStart === weekStart && row.confidence > 0);
|
|
35
40
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
const topByVolume = (rows: ForecastPoint[], weekStart: string): ForecastPoint[] =>
|
|
42
|
+
[...forecastsFor(rows, weekStart)]
|
|
43
|
+
.sort(
|
|
44
|
+
(a, b) => b.predictedVolume - a.predictedVolume || b.predictedRevenue - a.predictedRevenue
|
|
45
|
+
)
|
|
46
|
+
.slice(0, 3);
|
|
47
|
+
|
|
48
|
+
const topByRevenue = (rows: ForecastPoint[], weekStart: string): ForecastPoint[] =>
|
|
49
|
+
[...forecastsFor(rows, weekStart)]
|
|
50
|
+
.sort((a, b) => b.predictedRevenue - a.predictedRevenue)
|
|
51
|
+
.slice(0, 3);
|
|
40
52
|
|
|
41
53
|
const totalVolume = (rows: ForecastPoint[], weekStart: string): number =>
|
|
42
|
-
rows
|
|
43
|
-
|
|
44
|
-
|
|
54
|
+
forecastsFor(rows, weekStart).reduce((sum, row) => sum + row.predictedVolume, 0);
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The first forecast week that has not started yet, else the latest week on
|
|
58
|
+
* offer (rows arrive sorted by period).
|
|
59
|
+
*/
|
|
60
|
+
const upcomingWeekStart = (rows: ForecastPoint[], now: Date = new Date()): string | null => {
|
|
61
|
+
const starts = [...new Set(rows.map((row) => row.periodStart))].sort(
|
|
62
|
+
(a, b) => new Date(a).getTime() - new Date(b).getTime()
|
|
63
|
+
);
|
|
64
|
+
return starts.find((start) => new Date(start).getTime() > now.getTime()) ?? starts.at(-1) ?? null;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/** `3 jobs`, `1 job`, or `<1 job` when demand is real but under one a week. */
|
|
68
|
+
const formatJobs = (volume: number, revenue: number): string => {
|
|
69
|
+
if (volume === 0 && revenue > 0) return '<1 job';
|
|
70
|
+
return volume === 1 ? '1 job' : `${volume} jobs`;
|
|
71
|
+
};
|
|
45
72
|
|
|
46
73
|
const formatConfidence = (confidence: number): string => {
|
|
47
74
|
if (confidence <= 0) return 'Not enough history';
|
|
@@ -90,9 +117,13 @@ export function UpcomingDemandPanel({
|
|
|
90
117
|
);
|
|
91
118
|
}
|
|
92
119
|
|
|
93
|
-
const nextWeekStart = laneForecast
|
|
120
|
+
const nextWeekStart = upcomingWeekStart([...laneForecast, ...customerForecast]);
|
|
121
|
+
const hasForecast =
|
|
122
|
+
nextWeekStart !== null &&
|
|
123
|
+
(forecastsFor(laneForecast, nextWeekStart).length > 0 ||
|
|
124
|
+
forecastsFor(customerForecast, nextWeekStart).length > 0);
|
|
94
125
|
|
|
95
|
-
if (!nextWeekStart ||
|
|
126
|
+
if (!nextWeekStart || !hasForecast) {
|
|
96
127
|
return (
|
|
97
128
|
<Card>
|
|
98
129
|
<CardHeader>
|
|
@@ -105,8 +136,8 @@ export function UpcomingDemandPanel({
|
|
|
105
136
|
<div className="flex items-start gap-2 rounded-lg border border-border/60 bg-muted/40 p-4 text-sm text-text-secondary">
|
|
106
137
|
<AlertCircle size={16} aria-hidden="true" className="mt-0.5 shrink-0" />
|
|
107
138
|
<p>
|
|
108
|
-
Not enough history to forecast next week yet. Once
|
|
109
|
-
|
|
139
|
+
Not enough history to forecast next week yet. Once a lane or customer has at least 4
|
|
140
|
+
weeks of delivery jobs, this panel will surface its demand.
|
|
110
141
|
</p>
|
|
111
142
|
</div>
|
|
112
143
|
</CardContent>
|
|
@@ -117,7 +148,18 @@ export function UpcomingDemandPanel({
|
|
|
117
148
|
const topLanes = topByVolume(laneForecast, nextWeekStart);
|
|
118
149
|
const topLanesByRevenue = topByRevenue(laneForecast, nextWeekStart);
|
|
119
150
|
const topCustomers = topByVolume(customerForecast, nextWeekStart);
|
|
120
|
-
|
|
151
|
+
// The headline total comes from lane forecasts when any lane clears the
|
|
152
|
+
// history threshold. A customer can have enough history while each of its
|
|
153
|
+
// lanes does not, so fall back to the customer total rather than show a
|
|
154
|
+
// lane total of 0 beside valid customer forecasts.
|
|
155
|
+
const hasLaneForecast = forecastsFor(laneForecast, nextWeekStart).length > 0;
|
|
156
|
+
const total = hasLaneForecast
|
|
157
|
+
? totalVolume(laneForecast, nextWeekStart)
|
|
158
|
+
: totalVolume(customerForecast, nextWeekStart);
|
|
159
|
+
const totalLabel = hasLaneForecast
|
|
160
|
+
? 'Predicted jobs (all lanes)'
|
|
161
|
+
: 'Predicted jobs (all customers)';
|
|
162
|
+
const headlineRow = hasLaneForecast ? topLanes[0] : topCustomers[0];
|
|
121
163
|
|
|
122
164
|
// Most-recent variance row per scope key — show the lane that overshot /
|
|
123
165
|
// undershot the most in absolute volume terms.
|
|
@@ -136,13 +178,11 @@ export function UpcomingDemandPanel({
|
|
|
136
178
|
<CardContent className="space-y-4">
|
|
137
179
|
<div className="flex items-baseline justify-between rounded-lg border border-border/60 bg-muted/40 px-4 py-3">
|
|
138
180
|
<div>
|
|
139
|
-
<p className="text-xs uppercase tracking-wide text-text-secondary">
|
|
140
|
-
Predicted jobs (all lanes)
|
|
141
|
-
</p>
|
|
181
|
+
<p className="text-xs uppercase tracking-wide text-text-secondary">{totalLabel}</p>
|
|
142
182
|
<p className="text-2xl font-bold">{total}</p>
|
|
143
183
|
</div>
|
|
144
184
|
<p className="text-xs text-text-secondary">
|
|
145
|
-
{
|
|
185
|
+
{headlineRow ? formatConfidence(headlineRow.confidence) : ''}
|
|
146
186
|
</p>
|
|
147
187
|
</div>
|
|
148
188
|
|
|
@@ -180,14 +220,12 @@ function ForecastList({ title, rows }: ForecastListProps) {
|
|
|
180
220
|
key={`${row.scopeType}-${row.scopeKey}`}
|
|
181
221
|
className="flex items-center justify-between text-sm"
|
|
182
222
|
>
|
|
183
|
-
<span className="truncate font-medium"
|
|
223
|
+
<span className="truncate font-medium" title={row.scopeLabel}>
|
|
224
|
+
{row.scopeLabel}
|
|
225
|
+
</span>
|
|
184
226
|
<span className="ml-2 shrink-0 text-text-secondary">
|
|
185
|
-
{row.predictedVolume}
|
|
186
|
-
{
|
|
187
|
-
style: 'currency',
|
|
188
|
-
currency: 'USD',
|
|
189
|
-
maximumFractionDigits: 0,
|
|
190
|
-
}).format(row.predictedRevenue)}
|
|
227
|
+
{formatJobs(row.predictedVolume, row.predictedRevenue)} ·{' '}
|
|
228
|
+
{formatCurrency(row.predictedRevenue)}
|
|
191
229
|
</span>
|
|
192
230
|
</li>
|
|
193
231
|
))}
|
|
@@ -219,11 +257,15 @@ function VarianceList({ rows }: VarianceListProps) {
|
|
|
219
257
|
>
|
|
220
258
|
<span className="flex items-center gap-2 truncate">
|
|
221
259
|
<Icon size={14} className={tone} aria-hidden="true" />
|
|
222
|
-
<span className="truncate font-medium"
|
|
260
|
+
<span className="truncate font-medium" title={row.scopeLabel}>
|
|
261
|
+
{row.scopeLabel}
|
|
262
|
+
</span>
|
|
223
263
|
</span>
|
|
224
264
|
<span className={`ml-2 shrink-0 ${tone}`}>
|
|
225
265
|
{isOvershoot ? '+' : ''}
|
|
226
|
-
{row.volumeVariance
|
|
266
|
+
{Math.abs(row.volumeVariance) === 1
|
|
267
|
+
? `${row.volumeVariance} job`
|
|
268
|
+
: `${row.volumeVariance} jobs`}
|
|
227
269
|
</span>
|
|
228
270
|
</li>
|
|
229
271
|
);
|
|
@@ -12,6 +12,8 @@ import { executeGraphQL } from '../utils/graphqlClient';
|
|
|
12
12
|
export interface ForecastPoint {
|
|
13
13
|
scopeType: 'LANE' | 'CUSTOMER';
|
|
14
14
|
scopeKey: string;
|
|
15
|
+
/** Customer name or `Origin → Destination`; falls back to the key. */
|
|
16
|
+
scopeLabel: string;
|
|
15
17
|
periodStart: string;
|
|
16
18
|
periodEnd: string;
|
|
17
19
|
predictedVolume: number;
|
|
@@ -24,6 +26,7 @@ export interface ForecastPoint {
|
|
|
24
26
|
export interface ForecastVariance {
|
|
25
27
|
scopeType: 'LANE' | 'CUSTOMER';
|
|
26
28
|
scopeKey: string;
|
|
29
|
+
scopeLabel: string;
|
|
27
30
|
periodStart: string;
|
|
28
31
|
periodEnd: string;
|
|
29
32
|
predictedVolume: number;
|
|
@@ -49,6 +52,7 @@ const FORECAST_QUERY = `
|
|
|
49
52
|
demandForecastByLane(weeks: $weeks) {
|
|
50
53
|
scopeType
|
|
51
54
|
scopeKey
|
|
55
|
+
scopeLabel
|
|
52
56
|
periodStart
|
|
53
57
|
periodEnd
|
|
54
58
|
predictedVolume
|
|
@@ -60,6 +64,7 @@ const FORECAST_QUERY = `
|
|
|
60
64
|
demandForecastByCustomer(weeks: $weeks) {
|
|
61
65
|
scopeType
|
|
62
66
|
scopeKey
|
|
67
|
+
scopeLabel
|
|
63
68
|
periodStart
|
|
64
69
|
periodEnd
|
|
65
70
|
predictedVolume
|
|
@@ -71,6 +76,7 @@ const FORECAST_QUERY = `
|
|
|
71
76
|
laneVariance: demandForecastVariance(scopeType: LANE, limit: $varianceLimit) {
|
|
72
77
|
scopeType
|
|
73
78
|
scopeKey
|
|
79
|
+
scopeLabel
|
|
74
80
|
periodStart
|
|
75
81
|
periodEnd
|
|
76
82
|
predictedVolume
|
|
@@ -83,6 +89,7 @@ const FORECAST_QUERY = `
|
|
|
83
89
|
customerVariance: demandForecastVariance(scopeType: CUSTOMER, limit: $varianceLimit) {
|
|
84
90
|
scopeType
|
|
85
91
|
scopeKey
|
|
92
|
+
scopeLabel
|
|
86
93
|
periodStart
|
|
87
94
|
periodEnd
|
|
88
95
|
predictedVolume
|
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
type DriverStopState,
|
|
49
49
|
} from '../hooks/useDriverDay';
|
|
50
50
|
import {
|
|
51
|
+
formatLocalDay,
|
|
51
52
|
localDateString,
|
|
52
53
|
phoneHref,
|
|
53
54
|
routeNavigationUrl,
|
|
@@ -445,9 +446,7 @@ export default function DeliveryCapturePage() {
|
|
|
445
446
|
{day.completedStops} of {day.totalStops} stops done
|
|
446
447
|
{day.driverName ? ` · ${day.driverName}` : ''}
|
|
447
448
|
</p>
|
|
448
|
-
<p className="text-sm text-text-secondary">
|
|
449
|
-
{formatDate(new Date(`${date}T12:00:00`), 'full')}
|
|
450
|
-
</p>
|
|
449
|
+
<p className="text-sm text-text-secondary">{formatLocalDay(date)}</p>
|
|
451
450
|
</div>
|
|
452
451
|
<Progress value={progress} aria-label="Stops completed" />
|
|
453
452
|
{day.nextStop && (
|
|
@@ -101,3 +101,19 @@ export function deviceTimeZone(): string | null {
|
|
|
101
101
|
return null;
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* A calendar label for a YYYY-MM-DD day, e.g. "Sunday, November 1, 2026".
|
|
107
|
+
* Formatted as a pure calendar date (no time, no zone shift) so the header
|
|
108
|
+
* always names the day the driver picked.
|
|
109
|
+
*/
|
|
110
|
+
export function formatLocalDay(date: string): string {
|
|
111
|
+
const [year, month, day] = date.split('-').map(Number);
|
|
112
|
+
return new Intl.DateTimeFormat('en-US', {
|
|
113
|
+
weekday: 'long',
|
|
114
|
+
year: 'numeric',
|
|
115
|
+
month: 'long',
|
|
116
|
+
day: 'numeric',
|
|
117
|
+
timeZone: 'UTC',
|
|
118
|
+
}).format(new Date(Date.UTC(year, month - 1, day)));
|
|
119
|
+
}
|
|
@@ -7,6 +7,7 @@ query GetMovethewheelsDemandForecastByLane($weeks: Int!) {
|
|
|
7
7
|
demandForecastByLane(weeks: $weeks) {
|
|
8
8
|
scopeType
|
|
9
9
|
scopeKey
|
|
10
|
+
scopeLabel
|
|
10
11
|
periodStart
|
|
11
12
|
periodEnd
|
|
12
13
|
predictedVolume
|
|
@@ -21,6 +22,7 @@ query GetMovethewheelsDemandForecastByCustomer($weeks: Int!) {
|
|
|
21
22
|
demandForecastByCustomer(weeks: $weeks) {
|
|
22
23
|
scopeType
|
|
23
24
|
scopeKey
|
|
25
|
+
scopeLabel
|
|
24
26
|
periodStart
|
|
25
27
|
periodEnd
|
|
26
28
|
predictedVolume
|
|
@@ -35,6 +37,7 @@ query GetMovethewheelsDemandForecastVariance($scopeType: DemandForecastScope!, $
|
|
|
35
37
|
demandForecastVariance(scopeType: $scopeType, limit: $limit) {
|
|
36
38
|
scopeType
|
|
37
39
|
scopeKey
|
|
40
|
+
scopeLabel
|
|
38
41
|
periodStart
|
|
39
42
|
periodEnd
|
|
40
43
|
predictedVolume
|