@@ -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' ) : '—'
} ) ) ;