@burdenoff/microfe-movethewheels 2026.804.1 → 2026.822.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/components/CarbonFootprintPanel.js +108 -0
  2. package/dist/components/UpcomingDemandPanel.js +184 -0
  3. package/dist/components/index.js +1 -0
  4. package/dist/generated/wspace-operations.d.ts +147 -0
  5. package/dist/generated/wspace-types.d.ts +63 -0
  6. package/dist/hooks/useAnalytics.js +45 -4
  7. package/dist/hooks/useDemandForecast.js +54 -0
  8. package/dist/index.js +29 -28
  9. package/dist/movethewheels/components/CarbonFootprintPanel.d.ts +7 -0
  10. package/dist/movethewheels/components/UpcomingDemandPanel.d.ts +13 -0
  11. package/dist/movethewheels/components/index.d.ts +1 -0
  12. package/dist/movethewheels/hooks/index.d.ts +1 -1
  13. package/dist/movethewheels/hooks/useAnalytics.d.ts +22 -0
  14. package/dist/movethewheels/hooks/useDemandForecast.d.ts +39 -0
  15. package/dist/node_modules/lucide-react/dist/esm/icons/leaf.js +11 -0
  16. package/dist/node_modules/lucide-react/dist/esm/icons/trending-down.js +11 -0
  17. package/dist/pages/AnalyticsPage.js +82 -69
  18. package/package.json +2 -2
  19. package/src/generated/wspace-operations.ts +177 -0
  20. package/src/generated/wspace-types.ts +74 -0
  21. package/src/movethewheels/components/CarbonFootprintPanel.tsx +133 -0
  22. package/src/movethewheels/components/UpcomingDemandPanel.tsx +237 -0
  23. package/src/movethewheels/components/index.ts +3 -0
  24. package/src/movethewheels/hooks/index.ts +2 -0
  25. package/src/movethewheels/hooks/useAnalytics.ts +86 -0
  26. package/src/movethewheels/hooks/useDemandForecast.ts +161 -0
  27. package/src/movethewheels/pages/AnalyticsPage.tsx +27 -0
  28. package/src/operations/wspace/movethewheels/queries/forecast.graphql +47 -0
@@ -0,0 +1,54 @@
1
+ import { useMoveTheWheels as e } from "../providers/MoveTheWheelsProvider.js";
2
+ import { executeGraphQL as t } from "../utils/graphqlClient.js";
3
+ import { useCallback as n, useEffect as r, useMemo as i, useState as a } from "react";
4
+ //#region src/movethewheels/hooks/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";
6
+ function s(s = 4, c = 8) {
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
+ apiGatewayUrl: l,
9
+ authToken: u,
10
+ workspaceToken: d,
11
+ workspaceId: f,
12
+ tenantId: p,
13
+ actorId: m?.id
14
+ }), [
15
+ l,
16
+ u,
17
+ d,
18
+ f,
19
+ p,
20
+ m?.id
21
+ ]), O = n(async () => {
22
+ w(!0), E(null);
23
+ try {
24
+ let e = await t(D, o, {
25
+ weeks: s,
26
+ varianceLimit: c
27
+ });
28
+ g(e.demandForecastByLane ?? []), v(e.demandForecastByCustomer ?? []), b(e.laneVariance ?? []), S(e.customerVariance ?? []);
29
+ } catch (e) {
30
+ E(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to load demand forecast"));
31
+ } finally {
32
+ w(!1);
33
+ }
34
+ }, [
35
+ D,
36
+ s,
37
+ c
38
+ ]);
39
+ return r(() => {
40
+ O();
41
+ }, [O]), {
42
+ laneForecast: h,
43
+ customerForecast: _,
44
+ laneVariance: y,
45
+ customerVariance: x,
46
+ isLoading: C,
47
+ error: T,
48
+ refetch: n(() => {
49
+ O();
50
+ }, [O])
51
+ };
52
+ }
53
+ //#endregion
54
+ export { s as useDemandForecast };
package/dist/index.js CHANGED
@@ -7,33 +7,34 @@ import { useDriver as c, useDrivers as l, useFleet as u, useFleetStats as d, use
7
7
  import { useInventory as m, useInventoryStats as h, useProduct as g, useProducts as _, useWarehouse as v, useWarehouses as y } from "./hooks/useInventory.js";
8
8
  import { useCustomer as b, useCustomerStats as x, useCustomers as S } from "./hooks/useCustomers.js";
9
9
  import { useRoute as C, useRouteStats as w, useRoutes as T } from "./hooks/useRoutes.js";
10
- import { useAnalytics as E, useDashboardMetrics as D, useFinanceMetrics as O, useFleetAnalytics as k, useOrderAnalytics as A, usePerformanceAnalytics as j, useRevenueAnalytics as M } from "./hooks/useAnalytics.js";
11
- import { useDriverTracking as N, useGeofence as P, useLiveTracking as F, useOrderTracking as I, useTracking as L, useTrackingAlerts as R, useVehicleTracking as z } from "./hooks/useTracking.js";
12
- import { useReports as B } from "./hooks/useReports.js";
13
- import { useImportExport as V } from "./hooks/useImportExport.js";
14
- import { useModuleSettings as H } from "./hooks/useSettings.js";
15
- import { useEntityDocuments as U } from "./hooks/useEntityDocuments.js";
16
- import { useCaptureEpod as W, useEpod as G, useEpodPhotoUpload as K, useEpodPhotoUrl as q, useMyPendingEpodDeliveryJobs as J } from "./hooks/useEpod.js";
10
+ import { useAnalytics as E, useDashboardMetrics as D, useEmissionsSummary as O, useFinanceMetrics as k, useFleetAnalytics as A, useOrderAnalytics as j, usePerformanceAnalytics as M, useRevenueAnalytics as N } from "./hooks/useAnalytics.js";
11
+ import { useDriverTracking as P, useGeofence as F, useLiveTracking as I, useOrderTracking as L, useTracking as R, useTrackingAlerts as z, useVehicleTracking as B } from "./hooks/useTracking.js";
12
+ import { useReports as V } from "./hooks/useReports.js";
13
+ import { useImportExport as H } from "./hooks/useImportExport.js";
14
+ import { useModuleSettings as U } from "./hooks/useSettings.js";
15
+ import { useEntityDocuments as W } from "./hooks/useEntityDocuments.js";
16
+ import { useCaptureEpod as G, useEpod as K, useEpodPhotoUpload as q, useEpodPhotoUrl as J, useMyPendingEpodDeliveryJobs as Y } from "./hooks/useEpod.js";
17
17
  import "./hooks/index.js";
18
- import { Avatar as Y, AvatarFallback as X, AvatarImage as Z, Badge as Q, Button as $, Card as ee, CardContent as te, CardDescription as ne, CardFooter as re, CardHeader as ie, CardTitle as ae, Checkbox as oe, Dialog as se, DialogContent as ce, DialogDescription as le, DialogFooter as ue, DialogHeader as de, DialogTitle as fe, DialogTrigger as pe, DropdownMenu as me, DropdownMenuContent as he, DropdownMenuItem as ge, DropdownMenuSeparator as _e, DropdownMenuTrigger as ve, Input as ye, Label as be, Progress as xe, ScrollArea as Se, Select as Ce, SelectContent as we, SelectItem as Te, SelectTrigger as Ee, SelectValue as De, Separator as Oe, Skeleton as ke, Switch as Ae, Table as je, TableBody as Me, TableCell as Ne, TableHead as Pe, TableHeader as Fe, TableRow as Ie, Tabs as Le, TabsContent as Re, TabsList as ze, TabsTrigger as Be, Textarea as Ve, Tooltip as He, TooltipContent as Ue, TooltipProvider as We, TooltipTrigger as Ge } from "./components/ui.js";
19
- import { EmptyState as Ke, ErrorState as qe, LoadingState as Je, PageLayout as Ye, PageSection as Xe } from "./components/PageLayout.js";
20
- import { chartTokens as Ze, seriesColor as Qe } from "./components/charts/chartTokens.js";
21
- import { Sparkline as $e } from "./components/charts/Sparkline.js";
22
- import { MetricCard as et, MetricCardSkeleton as tt, MetricGrid as nt } from "./components/MetricCard.js";
23
- import { GlassPanel as rt } from "./components/GlassPanel.js";
24
- import { ChartEmpty as it, ChartTooltip as at } from "./components/charts/ChartShell.js";
25
- import { TrendChart as ot } from "./components/charts/TrendChart.js";
26
- import { VolumeBar as st } from "./components/charts/VolumeBar.js";
27
- import { StatusDonut as ct } from "./components/charts/StatusDonut.js";
28
- import { createCurrentIcon as lt, createPinIcon as ut, createStopIcon as dt, isRealCoord as ft } from "./components/maps/leaflet-setup.js";
29
- import { MapCanvas as pt } from "./components/maps/MapCanvas.js";
30
- import { LogisticsMap as mt } from "./components/maps/LogisticsMap.js";
31
- import { RouteMap as ht } from "./components/maps/RouteMap.js";
32
- import { TrackingMap as gt } from "./components/maps/TrackingMap.js";
33
- import { PaymentStatusBadge as _t, PriorityBadge as vt, StatusBadge as yt, TypeBadge as bt, VehicleTypeBadge as xt } from "./components/StatusBadge.js";
34
- import { DataTable as St } from "./components/DataTable.js";
35
- import { FormError as Ct } from "./components/FormError.js";
36
- import { Notice as wt, useNotice as Tt } from "./components/Notice.js";
37
- import { DocumentsCard as Et } from "./components/DocumentsCard.js";
18
+ import { Avatar as X, AvatarFallback as Z, AvatarImage as Q, Badge as $, Button as ee, Card as te, CardContent as ne, CardDescription as re, CardFooter as ie, CardHeader as ae, CardTitle as oe, Checkbox as se, Dialog as ce, DialogContent as le, DialogDescription as ue, DialogFooter as de, DialogHeader as fe, DialogTitle as pe, DialogTrigger as me, DropdownMenu as he, DropdownMenuContent as ge, DropdownMenuItem as _e, DropdownMenuSeparator as ve, DropdownMenuTrigger as ye, Input as be, Label as xe, Progress as Se, ScrollArea as Ce, Select as we, SelectContent as Te, SelectItem as Ee, SelectTrigger as De, SelectValue as Oe, Separator as ke, Skeleton as Ae, Switch as je, Table as Me, TableBody as Ne, TableCell as Pe, TableHead as Fe, TableHeader as Ie, TableRow as Le, Tabs as Re, TabsContent as ze, TabsList as Be, TabsTrigger as Ve, Textarea as He, Tooltip as Ue, TooltipContent as We, TooltipProvider as Ge, TooltipTrigger as Ke } from "./components/ui.js";
19
+ import { EmptyState as qe, ErrorState as Je, LoadingState as Ye, PageLayout as Xe, PageSection as Ze } from "./components/PageLayout.js";
20
+ import { chartTokens as Qe, seriesColor as $e } from "./components/charts/chartTokens.js";
21
+ import { Sparkline as et } from "./components/charts/Sparkline.js";
22
+ import { MetricCard as tt, MetricCardSkeleton as nt, MetricGrid as rt } from "./components/MetricCard.js";
23
+ import { GlassPanel as it } from "./components/GlassPanel.js";
24
+ import { ChartEmpty as at, ChartTooltip as ot } from "./components/charts/ChartShell.js";
25
+ import { TrendChart as st } from "./components/charts/TrendChart.js";
26
+ import { VolumeBar as ct } from "./components/charts/VolumeBar.js";
27
+ import { StatusDonut as lt } from "./components/charts/StatusDonut.js";
28
+ import { createCurrentIcon as ut, createPinIcon as dt, createStopIcon as ft, isRealCoord as pt } from "./components/maps/leaflet-setup.js";
29
+ import { MapCanvas as mt } from "./components/maps/MapCanvas.js";
30
+ import { LogisticsMap as ht } from "./components/maps/LogisticsMap.js";
31
+ import { RouteMap as gt } from "./components/maps/RouteMap.js";
32
+ import { TrackingMap as _t } from "./components/maps/TrackingMap.js";
33
+ import { PaymentStatusBadge as vt, PriorityBadge as yt, StatusBadge as bt, TypeBadge as xt, VehicleTypeBadge as St } from "./components/StatusBadge.js";
34
+ import { DataTable as Ct } from "./components/DataTable.js";
35
+ import { FormError as wt } from "./components/FormError.js";
36
+ import { Notice as Tt, useNotice as Et } from "./components/Notice.js";
37
+ import { DocumentsCard as Dt } from "./components/DocumentsCard.js";
38
+ import { CarbonFootprintPanel as Ot } from "./components/CarbonFootprintPanel.js";
38
39
  import "./components/index.js";
39
- export { Y as Avatar, X as AvatarFallback, Z as AvatarImage, Q as Badge, $ as Button, ee as Card, te as CardContent, ne as CardDescription, re as CardFooter, ie as CardHeader, ae as CardTitle, it as ChartEmpty, at as ChartTooltip, oe as Checkbox, St as DataTable, se as Dialog, ce as DialogContent, le as DialogDescription, ue as DialogFooter, de as DialogHeader, fe as DialogTitle, pe as DialogTrigger, Et as DocumentsCard, me as DropdownMenu, he as DropdownMenuContent, ge as DropdownMenuItem, _e as DropdownMenuSeparator, ve as DropdownMenuTrigger, Ke as EmptyState, qe as ErrorState, Ct as FormError, rt as GlassPanel, ye as Input, be as Label, Je as LoadingState, mt as LogisticsMap, pt as MapCanvas, et as MetricCard, tt as MetricCardSkeleton, nt as MetricGrid, n as MoveTheWheelsRoot, wt as Notice, Ye as PageLayout, Xe as PageSection, _t as PaymentStatusBadge, vt as PriorityBadge, xe as Progress, ht as RouteMap, Se as ScrollArea, Ce as Select, we as SelectContent, Te as SelectItem, Ee as SelectTrigger, De as SelectValue, Oe as Separator, ke as Skeleton, $e as Sparkline, yt as StatusBadge, ct as StatusDonut, Ae as Switch, je as Table, Me as TableBody, Ne as TableCell, Pe as TableHead, Fe as TableHeader, Ie as TableRow, Le as Tabs, Re as TabsContent, ze as TabsList, Be as TabsTrigger, Ve as Textarea, He as Tooltip, Ue as TooltipContent, We as TooltipProvider, Ge as TooltipTrigger, gt as TrackingMap, ot as TrendChart, bt as TypeBadge, xt as VehicleTypeBadge, st as VolumeBar, Ze as chartTokens, lt as createCurrentIcon, ut as createPinIcon, dt as createStopIcon, ft as isRealCoord, Qe as seriesColor, E as useAnalytics, W as useCaptureEpod, b as useCustomer, x as useCustomerStats, S as useCustomers, D as useDashboardMetrics, c as useDriver, N as useDriverTracking, l as useDrivers, U as useEntityDocuments, G as useEpod, K as useEpodPhotoUpload, q as useEpodPhotoUrl, O as useFinanceMetrics, u as useFleet, k as useFleetAnalytics, d as useFleetStats, P as useGeofence, V as useImportExport, m as useInventory, h as useInventoryStats, F as useLiveTracking, H as useModuleSettings, e as useMoveTheWheels, t as useMoveTheWheelsNavigate, r as useMoveTheWheelsStore, J as useMyPendingEpodDeliveryJobs, Tt as useNotice, a as useOrder, A as useOrderAnalytics, o as useOrderStats, I as useOrderTracking, s as useOrders, j as usePerformanceAnalytics, g as useProduct, _ as useProducts, B as useReports, M as useRevenueAnalytics, C as useRoute, w as useRouteStats, T as useRoutes, i as useSandboxAssistantTransport, L as useTracking, R as useTrackingAlerts, f as useVehicle, z as useVehicleTracking, p as useVehicles, v as useWarehouse, y as useWarehouses };
40
+ export { X as Avatar, Z as AvatarFallback, Q as AvatarImage, $ as Badge, ee as Button, Ot as CarbonFootprintPanel, te as Card, ne as CardContent, re as CardDescription, ie as CardFooter, ae as CardHeader, oe as CardTitle, at as ChartEmpty, ot as ChartTooltip, se as Checkbox, Ct as DataTable, ce as Dialog, le as DialogContent, ue as DialogDescription, de as DialogFooter, fe as DialogHeader, pe as DialogTitle, me as DialogTrigger, Dt as DocumentsCard, he as DropdownMenu, ge as DropdownMenuContent, _e as DropdownMenuItem, ve as DropdownMenuSeparator, ye as DropdownMenuTrigger, qe as EmptyState, Je as ErrorState, wt as FormError, it as GlassPanel, be as Input, xe as Label, Ye as LoadingState, ht as LogisticsMap, mt as MapCanvas, tt as MetricCard, nt as MetricCardSkeleton, rt as MetricGrid, n as MoveTheWheelsRoot, Tt as Notice, Xe as PageLayout, Ze as PageSection, vt as PaymentStatusBadge, yt as PriorityBadge, Se as Progress, gt as RouteMap, Ce as ScrollArea, we as Select, Te as SelectContent, Ee as SelectItem, De as SelectTrigger, Oe as SelectValue, ke as Separator, Ae as Skeleton, et as Sparkline, bt as StatusBadge, lt as StatusDonut, je as Switch, Me as Table, Ne as TableBody, Pe as TableCell, Fe as TableHead, Ie as TableHeader, Le as TableRow, Re as Tabs, ze as TabsContent, Be as TabsList, Ve as TabsTrigger, He as Textarea, Ue as Tooltip, We as TooltipContent, Ge as TooltipProvider, Ke as TooltipTrigger, _t as TrackingMap, st as TrendChart, xt as TypeBadge, St as VehicleTypeBadge, ct as VolumeBar, Qe as chartTokens, ut as createCurrentIcon, dt as createPinIcon, ft as createStopIcon, pt as isRealCoord, $e as seriesColor, E as useAnalytics, G as useCaptureEpod, b as useCustomer, x as useCustomerStats, S as useCustomers, D as useDashboardMetrics, c as useDriver, P as useDriverTracking, l as useDrivers, O as useEmissionsSummary, W as useEntityDocuments, K as useEpod, q as useEpodPhotoUpload, J as useEpodPhotoUrl, k as useFinanceMetrics, u as useFleet, A as useFleetAnalytics, d as useFleetStats, F as useGeofence, H as useImportExport, m as useInventory, h as useInventoryStats, I as useLiveTracking, U as useModuleSettings, e as useMoveTheWheels, t as useMoveTheWheelsNavigate, r as useMoveTheWheelsStore, Y as useMyPendingEpodDeliveryJobs, Et as useNotice, a as useOrder, j as useOrderAnalytics, o as useOrderStats, L as useOrderTracking, s as useOrders, M as usePerformanceAnalytics, g as useProduct, _ as useProducts, V as useReports, N as useRevenueAnalytics, C as useRoute, w as useRouteStats, T as useRoutes, i as useSandboxAssistantTransport, R as useTracking, z as useTrackingAlerts, f as useVehicle, B as useVehicleTracking, p as useVehicles, v as useWarehouse, y as useWarehouses };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Carbon footprint panel (BOFF-4391).
3
+ *
4
+ * Surfaces workspace-level CO2e totals and per-vehicle intensity. Data comes
5
+ * from Query.emissionsSummary via useEmissionsSummary.
6
+ */
7
+ export declare function CarbonFootprintPanel(): import("react").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import { ForecastPoint, ForecastVariance } from '../hooks/useDemandForecast';
2
+
3
+ interface UpcomingDemandPanelProps {
4
+ laneForecast: ForecastPoint[];
5
+ customerForecast: ForecastPoint[];
6
+ laneVariance: ForecastVariance[];
7
+ customerVariance: ForecastVariance[];
8
+ isLoading: boolean;
9
+ error: Error | null;
10
+ onRetry: () => void;
11
+ }
12
+ export declare function UpcomingDemandPanel({ laneForecast, customerForecast, laneVariance, customerVariance, isLoading, error, onRetry, }: UpcomingDemandPanelProps): import("react").JSX.Element;
13
+ export {};
@@ -14,3 +14,4 @@ export { DataTable, type Column } from './DataTable';
14
14
  export { FormError } from './FormError';
15
15
  export { Notice, useNotice } from './Notice';
16
16
  export { DocumentsCard } from './DocumentsCard';
17
+ export { CarbonFootprintPanel } from './CarbonFootprintPanel';
@@ -8,7 +8,7 @@ export { useFleet, useVehicles, useVehicle, useDrivers, useDriver, useFleetStats
8
8
  export { useInventory, useProducts, useProduct, useWarehouses, useWarehouse, useInventoryStats, } from './useInventory';
9
9
  export { useCustomers, useCustomer, useCustomerStats } from './useCustomers';
10
10
  export { useRoutes, useRoute, useRouteStats } from './useRoutes';
11
- export { useAnalytics, useDashboardMetrics, useRevenueAnalytics, useOrderAnalytics, useFleetAnalytics, usePerformanceAnalytics, useFinanceMetrics, type FinanceMetrics, } from './useAnalytics';
11
+ export { useAnalytics, useDashboardMetrics, useRevenueAnalytics, useOrderAnalytics, useFleetAnalytics, usePerformanceAnalytics, useFinanceMetrics, type FinanceMetrics, useEmissionsSummary, type EmissionsSummary, } from './useAnalytics';
12
12
  export { useTracking, useOrderTracking, useVehicleTracking, useDriverTracking, useLiveTracking, useTrackingAlerts, useGeofence, } from './useTracking';
13
13
  export { useReports } from './useReports';
14
14
  export { useImportExport } from './useImportExport';
@@ -133,4 +133,26 @@ export declare function usePerformanceAnalytics(): {
133
133
  isLoading: boolean;
134
134
  error: Error | null;
135
135
  };
136
+ export interface EmissionsSummary {
137
+ totalCo2eKg: number;
138
+ totalDistanceKm: number;
139
+ averageCo2eKgPerKm: number;
140
+ byVehicle: Array<{
141
+ vehicleId: string | null;
142
+ vehicleNumber: string | null;
143
+ totalDistanceKm: number;
144
+ co2eKg: number;
145
+ }>;
146
+ }
147
+ /**
148
+ * Real emissions figures straight from Query.emissionsSummary (BOFF-4391).
149
+ * Returns totals, per-km intensity, and a per-vehicle breakdown sourced from
150
+ * cached route CO2e values and actual/estimated distances.
151
+ */
152
+ export declare function useEmissionsSummary(): {
153
+ summary: EmissionsSummary;
154
+ isLoading: boolean;
155
+ error: Error | null;
156
+ refetch: () => void;
157
+ };
136
158
  export {};
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Demand forecasting hook (BOFF-4393). Pulls next-N-week forecasts by lane
3
+ * and customer plus the recent closed-period variance. Read-side only — the
4
+ * admin console exposes `recalculateDemandForecasts` separately.
5
+ */
6
+ export interface ForecastPoint {
7
+ scopeType: 'LANE' | 'CUSTOMER';
8
+ scopeKey: string;
9
+ periodStart: string;
10
+ periodEnd: string;
11
+ predictedVolume: number;
12
+ predictedRevenue: number;
13
+ actualVolume: number | null;
14
+ actualRevenue: number | null;
15
+ confidence: number;
16
+ }
17
+ export interface ForecastVariance {
18
+ scopeType: 'LANE' | 'CUSTOMER';
19
+ scopeKey: string;
20
+ periodStart: string;
21
+ periodEnd: string;
22
+ predictedVolume: number;
23
+ actualVolume: number;
24
+ volumeVariance: number;
25
+ predictedRevenue: number;
26
+ actualRevenue: number;
27
+ revenueVariance: number;
28
+ }
29
+ interface UseDemandForecastResult {
30
+ laneForecast: ForecastPoint[];
31
+ customerForecast: ForecastPoint[];
32
+ laneVariance: ForecastVariance[];
33
+ customerVariance: ForecastVariance[];
34
+ isLoading: boolean;
35
+ error: Error | null;
36
+ refetch: () => void;
37
+ }
38
+ export declare function useDemandForecast(weeks?: number, varianceLimit?: number): UseDemandForecastResult;
39
+ export {};
@@ -0,0 +1,11 @@
1
+ import { createLucideIcon as e } from "../createLucideIcon.js";
2
+ //#region node_modules/lucide-react/dist/esm/icons/leaf.js
3
+ var t = e("Leaf", [["path", {
4
+ d: "M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 4.18 2 8 0 5.5-4.78 10-10 10Z",
5
+ key: "nnexq3"
6
+ }], ["path", {
7
+ d: "M2 21c0-3 1.85-5.36 5.08-6C9.5 14.52 12 13 13 12",
8
+ key: "mt58a7"
9
+ }]]);
10
+ //#endregion
11
+ export { t as Leaf };
@@ -0,0 +1,11 @@
1
+ import { createLucideIcon as e } from "../createLucideIcon.js";
2
+ //#region node_modules/lucide-react/dist/esm/icons/trending-down.js
3
+ var t = e("TrendingDown", [["polyline", {
4
+ points: "22 17 13.5 8.5 8.5 13.5 2 7",
5
+ key: "1r2t7k"
6
+ }], ["polyline", {
7
+ points: "16 17 22 17 22 11",
8
+ key: "11uiuu"
9
+ }]]);
10
+ //#endregion
11
+ export { t as TrendingDown };
@@ -13,75 +13,78 @@ import { VolumeBar as b } from "../components/charts/VolumeBar.js";
13
13
  import { StatusDonut as x } from "../components/charts/StatusDonut.js";
14
14
  import "../components/charts/index.js";
15
15
  import { formatCurrency as S } from "../utils/formatters.js";
16
- import { useMemo as C } from "react";
17
- import { jsx as w, jsxs as T } from "react/jsx-runtime";
18
- import { EmphasisPanel as E, PagePurpose as D } from "@burdenoff/fe-libs/ui";
16
+ import { CarbonFootprintPanel as C } from "../components/CarbonFootprintPanel.js";
17
+ import { UpcomingDemandPanel as w } from "../components/UpcomingDemandPanel.js";
18
+ import { useDemandForecast as T } from "../hooks/useDemandForecast.js";
19
+ import { useMemo as E } from "react";
20
+ import { jsx as D, jsxs as O } from "react/jsx-runtime";
21
+ import { EmphasisPanel as k, PagePurpose as A } from "@burdenoff/fe-libs/ui";
19
22
  //#region src/movethewheels/pages/AnalyticsPage.tsx
20
- var O = (e) => e.replace(/_/g, " ").replace(/\b\w/g, (e) => e.toUpperCase());
21
- function k() {
22
- let { analytics: k, isLoading: A, error: j, refetch: M } = o(), { orderData: N } = c(), { fleetData: P } = s(), F = C(() => k.trends.dailyOrders.map((e) => e.orders), [k.trends.dailyOrders]), I = C(() => k.trends.revenue.map((e) => ({
23
+ var j = (e) => e.replace(/_/g, " ").replace(/\b\w/g, (e) => e.toUpperCase());
24
+ function M() {
25
+ let { analytics: M, isLoading: N, error: P, refetch: F } = o(), { orderData: I } = c(), { fleetData: L } = s(), { laneForecast: R, customerForecast: z, laneVariance: B, customerVariance: V, isLoading: H, error: U, refetch: W } = T(4, 8), G = E(() => M.trends.dailyOrders.map((e) => e.orders), [M.trends.dailyOrders]), K = E(() => M.trends.revenue.map((e) => ({
23
26
  month: e.month,
24
27
  revenue: e.revenue
25
- })), [k.trends.revenue]), L = C(() => N.byStatus.filter((e) => e.count > 0).map((e) => ({
26
- name: O(e.status),
28
+ })), [M.trends.revenue]), q = E(() => I.byStatus.filter((e) => e.count > 0).map((e) => ({
29
+ name: j(e.status),
27
30
  value: e.count
28
- })), [N.byStatus]), R = L.reduce((e, t) => e + t.value, 0);
29
- return /* @__PURE__ */ T(h, {
31
+ })), [I.byStatus]), J = q.reduce((e, t) => e + t.value, 0);
32
+ return /* @__PURE__ */ O(h, {
30
33
  title: "Analytics",
31
34
  subtitle: "Business performance and insights",
32
- icon: /* @__PURE__ */ w(e, { size: 24 }),
35
+ icon: /* @__PURE__ */ D(e, { size: 24 }),
33
36
  children: [
34
- /* @__PURE__ */ w(D, {
35
- icon: /* @__PURE__ */ w(e, { size: 18 }),
37
+ /* @__PURE__ */ D(A, {
38
+ icon: /* @__PURE__ */ D(e, { size: 18 }),
36
39
  children: "See how the operation is really performing. Track order volume, revenue, on-time rate and customer satisfaction over time so you can spot trends, find bottlenecks, and decide where to invest — whether that's more vehicles, better routes, or new customers."
37
40
  }),
38
- j && !A ? /* @__PURE__ */ w(u, {
41
+ P && !N ? /* @__PURE__ */ D(u, {
39
42
  className: "border-status-error-border",
40
- children: /* @__PURE__ */ T(d, {
43
+ children: /* @__PURE__ */ O(d, {
41
44
  className: "p-6 text-center space-y-3",
42
45
  children: [
43
- /* @__PURE__ */ w("p", {
46
+ /* @__PURE__ */ D("p", {
44
47
  className: "text-status-error-text font-medium",
45
48
  children: "Couldn't load analytics"
46
49
  }),
47
- /* @__PURE__ */ w("p", {
50
+ /* @__PURE__ */ D("p", {
48
51
  className: "text-sm text-text-secondary",
49
- children: j.message
52
+ children: P.message
50
53
  }),
51
- /* @__PURE__ */ w(l, {
54
+ /* @__PURE__ */ D(l, {
52
55
  variant: "outline",
53
- onClick: M,
56
+ onClick: F,
54
57
  children: "Retry"
55
58
  })
56
59
  ]
57
60
  })
58
- }) : A ? /* @__PURE__ */ w(v, {
61
+ }) : N ? /* @__PURE__ */ D(v, {
59
62
  columns: 4,
60
- children: Array.from({ length: 4 }).map((e, t) => /* @__PURE__ */ w(_, {}, t))
61
- }) : /* @__PURE__ */ T(v, {
63
+ children: Array.from({ length: 4 }).map((e, t) => /* @__PURE__ */ D(_, {}, t))
64
+ }) : /* @__PURE__ */ O(v, {
62
65
  columns: 4,
63
66
  children: [
64
- /* @__PURE__ */ w(g, {
67
+ /* @__PURE__ */ D(g, {
65
68
  label: "Order Volume",
66
- value: k.overview.totalOrders.toLocaleString(),
67
- icon: /* @__PURE__ */ w(n, { size: 20 }),
69
+ value: M.overview.totalOrders.toLocaleString(),
70
+ icon: /* @__PURE__ */ D(n, { size: 20 }),
68
71
  accent: "brand",
69
- sparklineData: F.length >= 2 ? F : void 0
72
+ sparklineData: G.length >= 2 ? G : void 0
70
73
  }),
71
- /* @__PURE__ */ w(g, {
74
+ /* @__PURE__ */ D(g, {
72
75
  treatment: "glass",
73
76
  glow: !0,
74
77
  label: "Revenue",
75
- value: S(k.overview.totalRevenue),
76
- icon: /* @__PURE__ */ w(t, { size: 20 }),
78
+ value: S(M.overview.totalRevenue),
79
+ icon: /* @__PURE__ */ D(t, { size: 20 }),
77
80
  accent: "success"
78
81
  }),
79
- /* @__PURE__ */ w(g, {
82
+ /* @__PURE__ */ D(g, {
80
83
  label: "On-Time Delivery",
81
- value: `${k.overview.onTimeDeliveryRate.toFixed(1)}%`,
82
- icon: /* @__PURE__ */ w(i, { size: 20 }),
84
+ value: `${M.overview.onTimeDeliveryRate.toFixed(1)}%`,
85
+ icon: /* @__PURE__ */ D(i, { size: 20 }),
83
86
  accent: "blue",
84
- delta: k.overview.onTimeDeliveryRate >= 90 ? {
87
+ delta: M.overview.onTimeDeliveryRate >= 90 ? {
85
88
  value: "On target",
86
89
  direction: "up"
87
90
  } : {
@@ -89,19 +92,19 @@ function k() {
89
92
  direction: "down"
90
93
  }
91
94
  }),
92
- /* @__PURE__ */ w(g, {
95
+ /* @__PURE__ */ D(g, {
93
96
  label: "Customer Satisfaction",
94
- value: k.overview.customerSatisfaction.toFixed(1),
95
- icon: /* @__PURE__ */ w(r, { size: 20 }),
97
+ value: M.overview.customerSatisfaction.toFixed(1),
98
+ icon: /* @__PURE__ */ D(r, { size: 20 }),
96
99
  accent: "warning",
97
100
  subtitle: "out of 5"
98
101
  })
99
102
  ]
100
103
  }),
101
- /* @__PURE__ */ T(u, { children: [/* @__PURE__ */ w(f, { children: /* @__PURE__ */ w(p, { children: "Order & delivery trend" }) }), /* @__PURE__ */ w(d, { children: /* @__PURE__ */ w(y, {
104
+ /* @__PURE__ */ O(u, { children: [/* @__PURE__ */ D(f, { children: /* @__PURE__ */ D(p, { children: "Order & delivery trend" }) }), /* @__PURE__ */ D(d, { children: /* @__PURE__ */ D(y, {
102
105
  xKey: "date",
103
106
  height: 300,
104
- data: k.trends.dailyOrders,
107
+ data: M.trends.dailyOrders,
105
108
  series: [{
106
109
  dataKey: "orders",
107
110
  name: "Orders"
@@ -111,89 +114,99 @@ function k() {
111
114
  }],
112
115
  emptyMessage: "No order trend recorded yet"
113
116
  }) })] }),
114
- /* @__PURE__ */ T("div", {
117
+ /* @__PURE__ */ D(w, {
118
+ laneForecast: R,
119
+ customerForecast: z,
120
+ laneVariance: B,
121
+ customerVariance: V,
122
+ isLoading: H,
123
+ error: U,
124
+ onRetry: W
125
+ }),
126
+ /* @__PURE__ */ O("div", {
115
127
  className: "grid grid-cols-1 lg:grid-cols-2 gap-6",
116
- children: [/* @__PURE__ */ T(u, { children: [/* @__PURE__ */ w(f, { children: /* @__PURE__ */ w(p, { children: "Revenue by month" }) }), /* @__PURE__ */ w(d, { children: /* @__PURE__ */ w(b, {
128
+ children: [/* @__PURE__ */ O(u, { children: [/* @__PURE__ */ D(f, { children: /* @__PURE__ */ D(p, { children: "Revenue by month" }) }), /* @__PURE__ */ D(d, { children: /* @__PURE__ */ D(b, {
117
129
  xKey: "month",
118
130
  height: 280,
119
131
  showLegend: !1,
120
- data: I,
132
+ data: K,
121
133
  series: [{
122
134
  dataKey: "revenue",
123
135
  name: "Revenue"
124
136
  }],
125
137
  valueFormatter: (e) => S(Number(e)),
126
138
  emptyMessage: "No revenue recorded yet"
127
- }) })] }), /* @__PURE__ */ T(u, { children: [/* @__PURE__ */ w(f, { children: /* @__PURE__ */ w(p, { children: "Orders by status" }) }), /* @__PURE__ */ w(d, { children: /* @__PURE__ */ w(x, {
128
- data: L,
139
+ }) })] }), /* @__PURE__ */ O(u, { children: [/* @__PURE__ */ D(f, { children: /* @__PURE__ */ D(p, { children: "Orders by status" }) }), /* @__PURE__ */ D(d, { children: /* @__PURE__ */ D(x, {
140
+ data: q,
129
141
  height: 240,
130
- centerLabel: R.toLocaleString(),
142
+ centerLabel: J.toLocaleString(),
131
143
  centerSubLabel: "orders",
132
144
  emptyMessage: "No orders to break down yet"
133
145
  }) })] })]
134
146
  }),
135
- /* @__PURE__ */ T("div", {
147
+ /* @__PURE__ */ O("div", {
136
148
  className: "grid grid-cols-1 lg:grid-cols-2 gap-6",
137
- children: [/* @__PURE__ */ T(u, { children: [/* @__PURE__ */ w(f, { children: /* @__PURE__ */ w(p, { children: "Fleet Performance" }) }), /* @__PURE__ */ T(d, {
149
+ children: [/* @__PURE__ */ O(u, { children: [/* @__PURE__ */ D(f, { children: /* @__PURE__ */ D(p, { children: "Fleet Performance" }) }), /* @__PURE__ */ O(d, {
138
150
  className: "space-y-4",
139
- children: [/* @__PURE__ */ T("div", { children: [/* @__PURE__ */ T("div", {
151
+ children: [/* @__PURE__ */ O("div", { children: [/* @__PURE__ */ O("div", {
140
152
  className: "flex justify-between text-sm mb-1",
141
- children: [/* @__PURE__ */ w("span", { children: "Vehicle Utilization" }), /* @__PURE__ */ T("span", { children: [P.vehicleUtilization.toFixed(0), "%"] })]
142
- }), /* @__PURE__ */ w(m, { value: P.vehicleUtilization })] }), P.vehiclesByType.length > 0 && /* @__PURE__ */ T("div", {
153
+ children: [/* @__PURE__ */ D("span", { children: "Vehicle Utilization" }), /* @__PURE__ */ O("span", { children: [L.vehicleUtilization.toFixed(0), "%"] })]
154
+ }), /* @__PURE__ */ D(m, { value: L.vehicleUtilization })] }), L.vehiclesByType.length > 0 && /* @__PURE__ */ O("div", {
143
155
  className: "pt-2",
144
- children: [/* @__PURE__ */ w("p", {
156
+ children: [/* @__PURE__ */ D("p", {
145
157
  className: "text-sm text-text-secondary mb-2",
146
158
  children: "Vehicles by Type"
147
- }), P.vehiclesByType.map(({ type: e, count: t }) => /* @__PURE__ */ T("div", {
159
+ }), L.vehiclesByType.map(({ type: e, count: t }) => /* @__PURE__ */ O("div", {
148
160
  className: "flex justify-between text-sm py-1",
149
- children: [/* @__PURE__ */ w("span", {
161
+ children: [/* @__PURE__ */ D("span", {
150
162
  className: "capitalize",
151
163
  children: e
152
- }), /* @__PURE__ */ w("span", {
164
+ }), /* @__PURE__ */ D("span", {
153
165
  className: "font-medium",
154
166
  children: t
155
167
  })]
156
168
  }, e))]
157
169
  })]
158
- })] }), /* @__PURE__ */ T(E, {
170
+ })] }), /* @__PURE__ */ O(k, {
159
171
  className: "space-y-4",
160
172
  children: [
161
- /* @__PURE__ */ w("h2", {
173
+ /* @__PURE__ */ D("h2", {
162
174
  className: "text-base font-semibold text-text-primary",
163
175
  children: "Performance Metrics"
164
176
  }),
165
- /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("p", {
177
+ /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("p", {
166
178
  className: "text-sm text-text-secondary",
167
179
  children: "On-Time Delivery"
168
- }), /* @__PURE__ */ T("p", {
180
+ }), /* @__PURE__ */ O("p", {
169
181
  className: "text-2xl font-bold",
170
- children: [k.performance.onTimeDelivery.toFixed(1), "%"]
182
+ children: [M.performance.onTimeDelivery.toFixed(1), "%"]
171
183
  })] }),
172
- /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("p", {
184
+ /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("p", {
173
185
  className: "text-sm text-text-secondary",
174
186
  children: "Customer Satisfaction"
175
- }), /* @__PURE__ */ T("p", {
187
+ }), /* @__PURE__ */ O("p", {
176
188
  className: "text-2xl font-bold",
177
- children: [k.overview.customerSatisfaction.toFixed(1), "/5"]
189
+ children: [M.overview.customerSatisfaction.toFixed(1), "/5"]
178
190
  })] }),
179
- /* @__PURE__ */ T("div", {
191
+ /* @__PURE__ */ O("div", {
180
192
  className: "flex items-center gap-2",
181
- children: [/* @__PURE__ */ w(a, {
193
+ children: [/* @__PURE__ */ D(a, {
182
194
  size: 16,
183
195
  className: "text-text-secondary"
184
- }), /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("p", {
196
+ }), /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("p", {
185
197
  className: "text-sm text-text-secondary",
186
198
  children: "Driver Ratings"
187
- }), /* @__PURE__ */ T("p", {
199
+ }), /* @__PURE__ */ O("p", {
188
200
  className: "text-2xl font-bold",
189
- children: [k.performance.driverRatings.toFixed(1), "/5"]
201
+ children: [M.performance.driverRatings.toFixed(1), "/5"]
190
202
  })] })]
191
203
  })
192
204
  ]
193
205
  })]
194
- })
206
+ }),
207
+ /* @__PURE__ */ D(C, {})
195
208
  ]
196
209
  });
197
210
  }
198
211
  //#endregion
199
- export { k as default };
212
+ export { M as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-movethewheels",
3
- "version": "2026.804.1",
3
+ "version": "2026.822.1",
4
4
  "description": "Burdenoff MoveTheWheels Microfrontend - Logistics & Supply Chain Management Platform",
5
5
  "type": "module",
6
6
  "files": [
@@ -106,7 +106,7 @@
106
106
  "zustand": "^5.0.0"
107
107
  },
108
108
  "publishConfig": {
109
- "access": "restricted"
109
+ "access": "public"
110
110
  },
111
111
  "overrides": {
112
112
  "lodash": ">=4.17.21",