import { Card, Group, Loader, SimpleGrid, Stack, Text, ThemeIcon } from '@mantine/core'; import { Gauge } from 'lucide-react'; import { Bar, BarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis, } from 'recharts'; import { useOnTimeDispatch, useWarehouseCycleStats } from '@/hooks/useWarehouses'; import { formatDays } from './options'; function onTimeColor(pct: number | null | undefined): string { if (pct == null) return 'edr-text'; if (pct >= 80) return 'teal'; if (pct >= 50) return 'orange'; return 'red'; } /** * Warehouse performance: on-time dispatch rate (items that left before their * storage free-days expired), average dock-to-dispatch, and the per-stage * cycle times that make it up. */ export function CycleTimeCard() { const { data: cycle, isLoading: cycleLoading } = useWarehouseCycleStats(); const { data: onTime, isLoading: onTimeLoading } = useOnTimeDispatch(); const isLoading = cycleLoading || onTimeLoading; const hasStages = (cycle?.sampleSize ?? 0) > 0; const stages = cycle?.stages ?? []; return (
Cycle time & on-time Dispatch performance over the last 90 days
{isLoading ? ( ) : ( On-time dispatch {onTime?.onTimePct == null ? 'N/A' : `${onTime.onTimePct}%`} {onTime?.onTimePct == null ? 'No storage rule / sample' : `${onTime.onTimeCount}/${onTime.sampleSize} left before free-days`} Dock → dispatch {hasStages ? formatDays(cycle?.avgDockToDispatchDays) : '—'} avg over {cycle?.sampleSize ?? 0} dispatched {hasStages ? ( [`${value} days`, 'Avg'] as [string, string]} /> ) : ( Not enough dispatched items yet to chart stage times. )} )}
); }