updates on the deliveries page added the steps in the tabular format and updated the comparison map
This commit is contained in:
@@ -923,6 +923,7 @@ const Deliveries = () => {
|
|||||||
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}> Kms</TableCell>
|
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}> Kms</TableCell>
|
||||||
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Amount </TableCell>
|
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Amount </TableCell>
|
||||||
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Notes </TableCell>
|
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Notes </TableCell>
|
||||||
|
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Steps</TableCell>
|
||||||
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Qty</TableCell>
|
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Qty</TableCell>
|
||||||
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>COD </TableCell>
|
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>COD </TableCell>
|
||||||
{tabstatus !== 'Cancelled' && tabstatus !== 'Delivered' && (
|
{tabstatus !== 'Cancelled' && tabstatus !== 'Delivered' && (
|
||||||
@@ -944,7 +945,7 @@ const Deliveries = () => {
|
|||||||
<TableBody>
|
<TableBody>
|
||||||
{rows.length == 0 && !loading1 && (
|
{rows.length == 0 && !loading1 && (
|
||||||
<>
|
<>
|
||||||
<TableCell colSpan={13}>
|
<TableCell colSpan={14}>
|
||||||
{/* <Stack width={'100%'} direction={'row'} justifyContent={'center'}> */}
|
{/* <Stack width={'100%'} direction={'row'} justifyContent={'center'}> */}
|
||||||
<Empty description={`No ${tabstatus} Orders`} styles={{ description: { color: theme.palette.error.main } }} />
|
<Empty description={`No ${tabstatus} Orders`} styles={{ description: { color: theme.palette.error.main } }} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
@@ -1125,10 +1126,27 @@ const Deliveries = () => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Stack>
|
</Stack>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
{/* {qty} */}
|
{/* notes */}
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Typography>{row.notes}</Typography>
|
<Typography>{row.notes}</Typography>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
{/* step */}
|
||||||
|
<TableCell align="center">
|
||||||
|
{row.step ? (
|
||||||
|
<Chip
|
||||||
|
label={row.step}
|
||||||
|
size="small"
|
||||||
|
color="primary"
|
||||||
|
variant="light"
|
||||||
|
sx={{ fontWeight: 700, minWidth: 28 }}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Typography variant="subtitle2" color="text.disabled">
|
||||||
|
—
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
{/* qty */}
|
||||||
<TableCell>
|
<TableCell>
|
||||||
{row.Quantity ? (
|
{row.Quantity ? (
|
||||||
<Typography variant="subtitle1" color={'error'} sx={{ whiteSpace: 'nowrap' }}>
|
<Typography variant="subtitle1" color={'error'} sx={{ whiteSpace: 'nowrap' }}>
|
||||||
|
|||||||
@@ -13,7 +13,11 @@ import {
|
|||||||
MdFormatListBulleted,
|
MdFormatListBulleted,
|
||||||
MdTimer,
|
MdTimer,
|
||||||
MdWarning,
|
MdWarning,
|
||||||
MdClose
|
MdClose,
|
||||||
|
MdSpeed,
|
||||||
|
MdStar,
|
||||||
|
MdFlag,
|
||||||
|
MdHourglassBottom
|
||||||
} from 'react-icons/md';
|
} from 'react-icons/md';
|
||||||
import {
|
import {
|
||||||
stepColor,
|
stepColor,
|
||||||
@@ -513,48 +517,126 @@ function CompareDataPanel({
|
|||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Timing KPIs */}
|
{/* Timing — clock-style timeline. First/last delivery render as
|
||||||
|
digital clock faces flanking a duration centerpiece. Tiny
|
||||||
|
"Started" / "Finished" captions give the row a narrative.
|
||||||
|
Below: avg-per-stop with a dotted stops-row visualization,
|
||||||
|
and avg speed with a 0-60 gauge bar. */}
|
||||||
{(firstDelivery || lastDelivery) && (
|
{(firstDelivery || lastDelivery) && (
|
||||||
<section className="cdp-section">
|
<section className="cdp-section cdp-timing-section">
|
||||||
<div className="cdp-section-head">
|
<div className="cdp-section-head">
|
||||||
<span className="cdp-section-icon"><MdTimer /></span>
|
<span className="cdp-section-icon"><MdTimer /></span>
|
||||||
<span className="cdp-section-title">Timing KPIs</span>
|
<span className="cdp-section-title">Timing</span>
|
||||||
|
{activeMin > 0 && (
|
||||||
|
<span className="cdp-timing-active-tag">
|
||||||
|
<span className="cdp-timing-active-pulse" />
|
||||||
|
Day window
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="cdp-kpi-row">
|
<div className="cdp-timing-clock">
|
||||||
<div className="cdp-kpi">
|
<div className="cdp-clock-card is-start">
|
||||||
<div className="cdp-kpi-label">First delivery</div>
|
<div className="cdp-clock-label">
|
||||||
<div className="cdp-kpi-value">
|
<MdFlag /> First delivery
|
||||||
{firstDelivery ? firstDelivery.format('hh:mm A') : '—'}
|
</div>
|
||||||
|
<div className="cdp-clock-face">
|
||||||
|
<span className="cdp-clock-time">
|
||||||
|
{firstDelivery ? firstDelivery.format('hh:mm') : '—'}
|
||||||
|
</span>
|
||||||
|
<span className="cdp-clock-period">
|
||||||
|
{firstDelivery ? firstDelivery.format('A') : ''}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="cdp-clock-caption">Started</div>
|
||||||
|
</div>
|
||||||
|
<div className="cdp-clock-track" aria-hidden="true">
|
||||||
|
<span className="cdp-clock-track-line" />
|
||||||
|
<span className="cdp-clock-track-dot is-start" />
|
||||||
|
<span className="cdp-clock-track-dot is-end" />
|
||||||
|
<div className="cdp-clock-duration">
|
||||||
|
<span className="cdp-clock-duration-icon">
|
||||||
|
<MdHourglassBottom />
|
||||||
|
</span>
|
||||||
|
<span className="cdp-clock-duration-val">
|
||||||
|
{activeMin > 0
|
||||||
|
? activeMin >= 60
|
||||||
|
? `${Math.floor(activeMin / 60)}h ${activeMin % 60}m`
|
||||||
|
: `${activeMin}m`
|
||||||
|
: '—'}
|
||||||
|
</span>
|
||||||
|
<span className="cdp-clock-duration-sub">active</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="cdp-kpi">
|
<div className="cdp-clock-card is-end">
|
||||||
<div className="cdp-kpi-label">Last delivery</div>
|
<div className="cdp-clock-label">
|
||||||
<div className="cdp-kpi-value">
|
<MdCheckCircle /> Last delivery
|
||||||
{lastDelivery ? lastDelivery.format('hh:mm A') : '—'}
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className="cdp-clock-face">
|
||||||
|
<span className="cdp-clock-time">
|
||||||
|
{lastDelivery ? lastDelivery.format('hh:mm') : '—'}
|
||||||
|
</span>
|
||||||
|
<span className="cdp-clock-period">
|
||||||
|
{lastDelivery ? lastDelivery.format('A') : ''}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="cdp-clock-caption">Finished</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="cdp-kpi">
|
</div>
|
||||||
<div className="cdp-kpi-label">Active time</div>
|
<div className="cdp-timing-stats">
|
||||||
<div className="cdp-kpi-value">
|
<div className="cdp-timing-stat">
|
||||||
{activeMin > 0
|
<div className="cdp-timing-stat-head">
|
||||||
? activeMin >= 60
|
<div className="cdp-timing-stat-icon">
|
||||||
? `${Math.floor(activeMin / 60)}h ${activeMin % 60}m`
|
<MdAccessTime />
|
||||||
: `${activeMin}m`
|
</div>
|
||||||
: '—'}
|
<div className="cdp-timing-stat-body">
|
||||||
</div>
|
<div className="cdp-timing-stat-value">
|
||||||
</div>
|
{avgPerStop > 0 ? `${avgPerStop}` : '—'}
|
||||||
<div className="cdp-kpi">
|
{avgPerStop > 0 && (
|
||||||
<div className="cdp-kpi-label">Avg / stop</div>
|
<span className="cdp-timing-stat-unit">min</span>
|
||||||
<div className="cdp-kpi-value">
|
)}
|
||||||
{avgPerStop > 0 ? `${avgPerStop}m` : '—'}
|
</div>
|
||||||
|
<div className="cdp-timing-stat-label">Avg / stop</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{compareDeltas.length > 0 && (
|
||||||
|
<div className="cdp-timing-stat-viz cdp-stops-dots" aria-hidden="true">
|
||||||
|
{Array.from({ length: Math.min(compareDeltas.length, 12) }).map((_, i) => (
|
||||||
|
<span key={`dot-${i}`} className="cdp-stop-dot" />
|
||||||
|
))}
|
||||||
|
<span className="cdp-timing-stat-viz-label">
|
||||||
|
{compareDeltas.length} stop{compareDeltas.length === 1 ? '' : 's'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{avgSpeed != null && (
|
{avgSpeed != null && (
|
||||||
<div className="cdp-kpi">
|
<div className="cdp-timing-stat">
|
||||||
<div className="cdp-kpi-label">Avg speed</div>
|
<div className="cdp-timing-stat-head">
|
||||||
<div className="cdp-kpi-value">
|
<div className="cdp-timing-stat-icon">
|
||||||
{avgSpeed}
|
<MdSpeed />
|
||||||
<span className="cdp-kpi-unit">km/h</span>
|
</div>
|
||||||
|
<div className="cdp-timing-stat-body">
|
||||||
|
<div className="cdp-timing-stat-value">
|
||||||
|
{avgSpeed}
|
||||||
|
<span className="cdp-timing-stat-unit">km/h</span>
|
||||||
|
</div>
|
||||||
|
<div className="cdp-timing-stat-label">Avg speed</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="cdp-timing-stat-viz cdp-speed-gauge" aria-hidden="true">
|
||||||
|
<div className="cdp-speed-gauge-track">
|
||||||
|
<div
|
||||||
|
className="cdp-speed-gauge-fill"
|
||||||
|
style={{
|
||||||
|
width: `${Math.min(100, (parseFloat(avgSpeed) / 60) * 100)}%`
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="cdp-speed-gauge-scale">
|
||||||
|
<span>0</span>
|
||||||
|
<span>30</span>
|
||||||
|
<span>60 km/h</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -562,11 +644,14 @@ function CompareDataPanel({
|
|||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Highlights — best/worst step quick-pick. */}
|
{/* Highlights — best/worst step quick-pick. Full-width cards stacked
|
||||||
|
vertically: a colored rail on the left side encodes good/bad,
|
||||||
|
the customer name is the headline, the step number sits as a
|
||||||
|
right-aligned chip, and the metric line uses bold pills. */}
|
||||||
{(bestStep || worstStep) && (
|
{(bestStep || worstStep) && (
|
||||||
<section className="cdp-section">
|
<section className="cdp-section">
|
||||||
<div className="cdp-section-head">
|
<div className="cdp-section-head">
|
||||||
<span className="cdp-section-icon"><MdTrendingUp /></span>
|
<span className="cdp-section-icon"><MdStar /></span>
|
||||||
<span className="cdp-section-title">Highlights</span>
|
<span className="cdp-section-title">Highlights</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="cdp-highlights">
|
<div className="cdp-highlights">
|
||||||
@@ -577,23 +662,35 @@ function CompareDataPanel({
|
|||||||
role="button"
|
role="button"
|
||||||
title="Focus this step"
|
title="Focus this step"
|
||||||
>
|
>
|
||||||
<span
|
<span className="cdp-highlight-rail" aria-hidden="true" />
|
||||||
className="cdp-highlight-num"
|
<div className="cdp-highlight-content">
|
||||||
style={{ background: stepColor(bestStep.sequenceStep - 1) }}
|
<div className="cdp-highlight-top">
|
||||||
>
|
<span className="cdp-highlight-label">
|
||||||
{bestStep.sequenceStep}
|
<span className="cdp-highlight-chip">
|
||||||
</span>
|
<MdCheckCircle />
|
||||||
<div className="cdp-highlight-body">
|
</span>
|
||||||
<div className="cdp-highlight-label">
|
Fastest stop
|
||||||
<MdCheckCircle /> Fastest stop
|
</span>
|
||||||
|
<span
|
||||||
|
className="cdp-highlight-step-chip"
|
||||||
|
style={{
|
||||||
|
background: stepColor(bestStep.sequenceStep - 1)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Step {bestStep.sequenceStep}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="cdp-highlight-title">
|
<div className="cdp-highlight-title">
|
||||||
{bestStep.deliverycustomer || `Step ${bestStep.sequenceStep}`}
|
{bestStep.deliverycustomer || `Step ${bestStep.sequenceStep}`}
|
||||||
</div>
|
</div>
|
||||||
<div className="cdp-highlight-meta">
|
<div className="cdp-highlight-meta">
|
||||||
{bestStep.timeDeltaMin != null
|
<span className="cdp-highlight-pill is-good">
|
||||||
? `${bestStep.timeDeltaMin > 0 ? '+' : ''}${bestStep.timeDeltaMin} min vs plan`
|
{bestStep.timeDeltaMin != null
|
||||||
: 'on schedule'}
|
? bestStep.timeDeltaMin === 0
|
||||||
|
? 'On schedule'
|
||||||
|
: `${bestStep.timeDeltaMin > 0 ? '+' : ''}${bestStep.timeDeltaMin} min vs plan`
|
||||||
|
: 'On schedule'}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -605,26 +702,39 @@ function CompareDataPanel({
|
|||||||
role="button"
|
role="button"
|
||||||
title="Focus this step"
|
title="Focus this step"
|
||||||
>
|
>
|
||||||
<span
|
<span className="cdp-highlight-rail" aria-hidden="true" />
|
||||||
className="cdp-highlight-num"
|
<div className="cdp-highlight-content">
|
||||||
style={{ background: stepColor(worstStep.sequenceStep - 1) }}
|
<div className="cdp-highlight-top">
|
||||||
>
|
<span className="cdp-highlight-label">
|
||||||
{worstStep.sequenceStep}
|
<span className="cdp-highlight-chip">
|
||||||
</span>
|
<MdWarning />
|
||||||
<div className="cdp-highlight-body">
|
</span>
|
||||||
<div className="cdp-highlight-label">
|
Biggest deviation
|
||||||
<MdWarning /> Biggest deviation
|
</span>
|
||||||
|
<span
|
||||||
|
className="cdp-highlight-step-chip"
|
||||||
|
style={{
|
||||||
|
background: stepColor(worstStep.sequenceStep - 1)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Step {worstStep.sequenceStep}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="cdp-highlight-title">
|
<div className="cdp-highlight-title">
|
||||||
{worstStep.deliverycustomer || `Step ${worstStep.sequenceStep}`}
|
{worstStep.deliverycustomer || `Step ${worstStep.sequenceStep}`}
|
||||||
</div>
|
</div>
|
||||||
<div className="cdp-highlight-meta">
|
<div className="cdp-highlight-meta">
|
||||||
{worstStep.kmDeltaPct != null
|
{worstStep.kmDeltaPct != null && (
|
||||||
? `${worstStep.kmDeltaPct > 0 ? '+' : ''}${worstStep.kmDeltaPct.toFixed(0)}% route`
|
<span className="cdp-highlight-pill is-bad">
|
||||||
: ''}
|
{worstStep.kmDeltaPct > 0 ? '+' : ''}
|
||||||
{worstStep.timeDeltaMin != null && worstStep.timeDeltaMin > 0
|
{worstStep.kmDeltaPct.toFixed(0)}% route
|
||||||
? ` · +${worstStep.timeDeltaMin}m late`
|
</span>
|
||||||
: ''}
|
)}
|
||||||
|
{worstStep.timeDeltaMin != null && worstStep.timeDeltaMin > 0 && (
|
||||||
|
<span className="cdp-highlight-pill is-bad">
|
||||||
|
+{worstStep.timeDeltaMin}m late
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user