Enhance dashboard API to support date range filtering and update KPI definitions for improved clarity
This commit is contained in:
@@ -171,13 +171,15 @@ function RangeCalendar({ from, to, maxDate, onSelect }) {
|
||||
}
|
||||
|
||||
// Live KPI cards — each maps to one field of GET /api/v1/hub/dashboard.
|
||||
// `ranged: true` → the metric aggregates over the selected date range, so its
|
||||
// subtitle shows the window. The rest are live "right now" figures.
|
||||
const KPI_DEFS = [
|
||||
{ key: 'parcels_received_today', label: 'Total Parcels Received', icon: DynamicFeedIcon, color: '#1A73E8', sub: 'Received today' },
|
||||
{ key: 'parcels_received_today', label: 'Total Parcels Received', icon: DynamicFeedIcon, color: '#1A73E8', sub: 'Received', ranged: true },
|
||||
{ key: 'milers_available', label: 'Available Milers', icon: DeliveryDiningIcon, color: '#1E8E3E', sub: 'Free right now' },
|
||||
{ key: 'milers_on_duty', label: 'Milers on Duty', icon: InfoOutlinedIcon, color: '#1A73E8', sub: 'Currently working' },
|
||||
{ key: 'pending_pickups', label: 'Pending Pickups', icon: AssignmentIcon, color: '#F29900', sub: 'Awaiting a miler' },
|
||||
{ key: 'batches_sent_today', label: 'Batches Sent Today', icon: LocalShippingIcon, color: '#8E24AA', sub: 'Dispatched today' },
|
||||
{ key: 'exceptions', label: 'Needs Checking', icon: WarningAmberIcon, color: '#D93025', sub: 'Damaged or unclear' }
|
||||
{ key: 'batches_sent_today', label: 'Batches Sent', icon: LocalShippingIcon, color: '#8E24AA', sub: 'Dispatched', ranged: true },
|
||||
{ key: 'exceptions', label: 'Needs Checking', icon: WarningAmberIcon, color: '#D93025', sub: 'Damaged or unclear', ranged: true }
|
||||
];
|
||||
|
||||
const DATE_FMT = 'YYYY-MM-DD';
|
||||
@@ -219,7 +221,7 @@ export default function Dashboard() {
|
||||
setError('');
|
||||
try {
|
||||
const [dash, vehicles, activity, zones] = await Promise.all([
|
||||
getDashboard(),
|
||||
getDashboard(range.from, range.to),
|
||||
getInboundVehicles().catch(() => null),
|
||||
getActivity(8).catch(() => null),
|
||||
getZones().catch(() => null)
|
||||
@@ -251,10 +253,14 @@ export default function Dashboard() {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
}, [range.from, range.to]);
|
||||
|
||||
// Re-fetch whenever the range (or loadDashboard) changes. Debounced so picking a
|
||||
// start-then-end date in the calendar fires one request for the final range,
|
||||
// not an extra one for the transient single-day selection.
|
||||
useEffect(() => {
|
||||
loadDashboard();
|
||||
const t = setTimeout(loadDashboard, 250);
|
||||
return () => clearTimeout(t);
|
||||
}, [loadDashboard]);
|
||||
|
||||
// Pull the full report for the selected range and download it as an Excel file.
|
||||
@@ -287,8 +293,16 @@ export default function Dashboard() {
|
||||
}
|
||||
}, [exporting, range.from, range.to, hub.hubname]);
|
||||
|
||||
// Short label for the selected window, appended to range-scoped KPI subtitles.
|
||||
const rangeLabel = useMemo(() => {
|
||||
if (range.from === today && range.to === today) return 'today';
|
||||
if (range.from === range.to) return `on ${dayjs(range.from).format('DD MMM')}`;
|
||||
return `${dayjs(range.from).format('DD MMM')} – ${dayjs(range.to).format('DD MMM')}`;
|
||||
}, [range, today]);
|
||||
|
||||
const kpiCards = KPI_DEFS.map((d) => ({
|
||||
...d,
|
||||
sub: d.ranged ? `${d.sub} ${rangeLabel}` : d.sub,
|
||||
value: kpis && kpis[d.key] != null ? Number(kpis[d.key]).toLocaleString('en-IN') : '—'
|
||||
}));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user