Initial commit

This commit is contained in:
2026-07-01 17:49:49 +05:30
commit c36f2d5b1d
36 changed files with 12284 additions and 0 deletions

585
src/pages/Dashboard.jsx Normal file
View File

@@ -0,0 +1,585 @@
import { useState, useMemo } from 'react';
import {
Grid,
Card,
CardHeader,
CardContent,
Typography,
Box,
Stack,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Paper,
Chip,
LinearProgress,
IconButton,
Avatar,
Button,
Divider,
Popover
} from '@mui/material';
import dayjs from 'dayjs';
import { alpha } from '@mui/material/styles';
import QrCodeScannerIcon from '@mui/icons-material/QrCodeScanner';
import LocalShippingIcon from '@mui/icons-material/LocalShipping';
import AssignmentIcon from '@mui/icons-material/Assignment';
import WarningAmberIcon from '@mui/icons-material/WarningAmber';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import RefreshIcon from '@mui/icons-material/Refresh';
import ElectricBoltIcon from '@mui/icons-material/ElectricBolt';
import DynamicFeedIcon from '@mui/icons-material/DynamicFeed';
import SpeedIcon from '@mui/icons-material/Speed';
import LocalOfferIcon from '@mui/icons-material/LocalOffer';
import DeliveryDiningIcon from '@mui/icons-material/DeliveryDining';
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
import CalendarTodayOutlinedIcon from '@mui/icons-material/CalendarTodayOutlined';
import ChevronLeftRoundedIcon from '@mui/icons-material/ChevronLeftRounded';
import ChevronRightRoundedIcon from '@mui/icons-material/ChevronRightRounded';
import ArrowRightAltRoundedIcon from '@mui/icons-material/ArrowRightAltRounded';
const BRAND = '#C01227';
const DAY_LABELS = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
// ── Doormile-themed range calendar ───────────────────────────────────────────────
// Click a day to set the start, click again to set the end (auto-swaps if reversed).
// In-range days get a soft red wash; the two endpoints are solid brand red.
function RangeCalendar({ from, to, maxDate, onSelect }) {
const [view, setView] = useState(dayjs(to || from || undefined).startOf('month'));
const [anchorDate, setAnchorDate] = useState(null); // first click while picking a new range
const start = from ? dayjs(from) : null;
const end = to ? dayjs(to) : null;
const max = maxDate ? dayjs(maxDate) : null;
const gridStart = view.startOf('month').subtract(view.startOf('month').day(), 'day');
const cells = Array.from({ length: 42 }, (_, i) => gridStart.add(i, 'day'));
const handleDay = (d) => {
if (!anchorDate) {
setAnchorDate(d);
onSelect(d.format(DATE_FMT), d.format(DATE_FMT));
} else {
const a = anchorDate;
const lo = d.isBefore(a) ? d : a;
const hi = d.isBefore(a) ? a : d;
onSelect(lo.format(DATE_FMT), hi.format(DATE_FMT));
setAnchorDate(null);
}
};
return (
<Box sx={{ p: 2, width: 320 }}>
{/* Month header */}
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ mb: 1.5 }}>
<IconButton size="small" onClick={() => setView((v) => v.subtract(1, 'month'))} sx={{ color: '#5F6368' }}>
<ChevronLeftRoundedIcon />
</IconButton>
<Typography sx={{ fontWeight: 800, color: '#212529' }}>{view.format('MMMM YYYY')}</Typography>
<IconButton size="small" onClick={() => setView((v) => v.add(1, 'month'))} sx={{ color: '#5F6368' }}>
<ChevronRightRoundedIcon />
</IconButton>
</Stack>
{/* Weekday labels */}
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', mb: 0.5 }}>
{DAY_LABELS.map((d, i) => (
<Typography key={i} align="center" sx={{ fontSize: '0.72rem', fontWeight: 700, color: '#9AA0A6', py: 0.5 }}>
{d}
</Typography>
))}
</Box>
{/* Days */}
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', rowGap: 0.25 }}>
{cells.map((d) => {
const inMonth = d.month() === view.month();
const isStart = start && d.isSame(start, 'day');
const isEnd = end && d.isSame(end, 'day');
const isEndpoint = isStart || isEnd;
const inRange = start && end && d.isAfter(start, 'day') && d.isBefore(end, 'day');
const isToday = d.isSame(dayjs(), 'day');
const disabled = max && d.isAfter(max, 'day');
return (
<Box key={d.format(DATE_FMT)} sx={{ display: 'flex', justifyContent: 'center', bgcolor: inRange ? alpha(BRAND, 0.08) : 'transparent',
borderTopLeftRadius: isStart ? 8 : 0, borderBottomLeftRadius: isStart ? 8 : 0,
borderTopRightRadius: isEnd ? 8 : 0, borderBottomRightRadius: isEnd ? 8 : 0 }}>
<Box
component="button"
type="button"
disabled={disabled}
onClick={() => handleDay(d)}
sx={{
width: 36, height: 36, m: '2px', border: 'none', cursor: disabled ? 'default' : 'pointer',
borderRadius: 2, fontSize: '0.85rem', fontFamily: 'inherit',
fontWeight: isEndpoint ? 800 : 600,
color: disabled ? '#CED4DA' : isEndpoint ? '#fff' : inMonth ? '#212529' : '#B9BEC4',
bgcolor: isEndpoint ? BRAND : 'transparent',
boxShadow: isToday && !isEndpoint ? `inset 0 0 0 1.5px ${BRAND}` : 'none',
transition: 'background-color .15s',
'&:hover': { bgcolor: disabled ? 'transparent' : isEndpoint ? '#9E0E20' : alpha(BRAND, 0.12) }
}}
>
{d.date()}
</Box>
</Box>
);
})}
</Box>
</Box>
);
}
// Per-day snapshot for a single hub day. `cumulative` metrics add up across the
// selected date range; the rest are "right now" figures that stay as a live count.
const STAT_DEFS = [
{ label: 'Total Parcels', base: 3142, cumulative: true, icon: DynamicFeedIcon, color: '#1A73E8', sub: 'Handled in range' },
{ label: 'Picked Up Locally', base: 1482, cumulative: true, icon: LocalOfferIcon, color: '#1E8E3E', sub: 'Collected by milers' },
{ label: 'From Other Cities', base: 1660, cumulative: true, icon: LocalShippingIcon, color: '#1A73E8', sub: 'Arrived by truck' },
{ label: 'Ready for Delivery', base: 840, cumulative: false, icon: AssignmentIcon, color: '#00A854', sub: 'Sorted for local areas' },
{ label: 'Ready to Transfer', base: 1120, cumulative: false, icon: LocalShippingIcon, color: '#8E24AA', sub: 'Going to other cities' },
{ label: 'Out for Delivery', base: 620, cumulative: false, icon: DeliveryDiningIcon, color: '#F29900', sub: 'With milers right now' },
{ label: 'Needs Checking', base: 48, cumulative: true, icon: WarningAmberIcon, color: '#D93025', sub: 'Damaged or unclear' },
{ label: 'Returns', base: 12, cumulative: true, icon: WarningAmberIcon, color: '#F29900', sub: 'Going back to sender' },
{ label: 'Available Milers', base: 24, cumulative: false, icon: InfoOutlinedIcon, color: '#1A73E8', sub: 'Free or on duty' },
{ label: 'Batches Going Out', base: 8, cumulative: true, icon: LocalShippingIcon, color: '#1E8E3E', sub: 'Sent in range' }
];
const DATE_FMT = 'YYYY-MM-DD';
export default function Dashboard() {
const today = dayjs().format(DATE_FMT);
const weekAgo = dayjs().subtract(6, 'day').format(DATE_FMT);
const [range, setRange] = useState({ from: weekAgo, to: today });
const [calAnchor, setCalAnchor] = useState(null);
// Inclusive day count for the chosen window (min 1); drives cumulative metrics.
const dayCount = useMemo(() => {
const from = dayjs(range.from);
const to = dayjs(range.to);
if (!from.isValid() || !to.isValid() || to.isBefore(from)) return 1;
return to.diff(from, 'day') + 1;
}, [range]);
const invalidRange = dayjs(range.to).isBefore(dayjs(range.from));
const applyPreset = (days) => {
setRange({ from: dayjs().subtract(days - 1, 'day').format(DATE_FMT), to: today });
};
const isPreset = (days) =>
range.to === today && range.from === dayjs().subtract(days - 1, 'day').format(DATE_FMT);
const stats = useMemo(
() =>
STAT_DEFS.map((s) => ({
...s,
value: (s.cumulative ? s.base * dayCount : s.base).toLocaleString('en-IN')
})),
[dayCount]
);
const rangeLabel =
dayCount === 1
? dayjs(range.from).format('DD MMM YYYY')
: `${dayjs(range.from).format('DD MMM')} ${dayjs(range.to).format('DD MMM YYYY')} · ${dayCount} days`;
const incomingVehicles = [
{ id: 'Truck MH-04-8822', origin: 'Mumbai Hub', estTime: 'Arrived (Bay 4)', status: 'Unloading', progress: 85, color: 'success' },
{ id: 'Truck RJ-14-1049', origin: 'Jaipur Hub', estTime: '15 min away', status: 'Expected', progress: 0, color: 'info' },
{ id: 'Truck KA-03-0284', origin: 'Bengaluru Hub', estTime: '1.5 hrs away', status: 'On the way', progress: 0, color: 'default' }
];
const recentActivity = [
{ time: '11:24 AM', type: 'inbound', text: 'Received 142 parcels from the Mumbai truck' },
{ time: '11:15 AM', type: 'dispatch', text: 'Batch BATCH-9281 sent out with miler Deepak (West Delhi)' },
{ time: '10:50 AM', type: 'exception', text: 'Parcel DM-1005 put on hold (damaged label)' },
{ time: '10:30 AM', type: 'sorting', text: 'Cold room temperature checked — all good (4.2°C)' }
];
const activeRoutes = [
{ zone: 'West Delhi (Dwarka)', packages: 145, riders: 4, status: 'Active' },
{ zone: 'South Delhi (Saket)', packages: 210, riders: 6, status: 'Active' },
{ zone: 'East Delhi (Mayur Vihar)', packages: 98, riders: 3, status: 'Need Milers' },
{ zone: 'North Delhi (Rohini)', packages: 122, riders: 4, status: 'Active' }
];
return (
<Box>
{/* Title + date-range filter, all on one line */}
<Stack
direction={{ xs: 'column', md: 'row' }}
justifyContent="space-between"
alignItems={{ xs: 'stretch', md: 'center' }}
sx={{ mb: 2.5 }} // Reduced from mb: 4 to tighten vertical spacing
gap={1.5}
>
{/* Left Title Section */}
<Box sx={{ flexShrink: 0 }}>
<Typography variant="h5" sx={{ fontWeight: 700, color: '#1E293B', letterSpacing: '-0.02em', mb: 0.5 }}>
Delhi Hub
</Typography>
<Typography variant="body2" sx={{ color: '#64748B', fontSize: '0.825rem' }}>
Showing hub activity for{' '}
<Box component="span" sx={{ fontWeight: 600, color: '#0F172A' }}>
{rangeLabel}
</Box>
</Typography>
</Box>
{/* Right Controls Section */}
<Stack
direction="row"
spacing={1}
alignItems="center"
flexWrap="wrap"
useFlexGap
sx={{ flexGrow: 1, minWidth: 0, justifyContent: { xs: 'flex-start', md: 'flex-end' } }}
>
{/* Refresh Button */}
<IconButton
color="primary"
sx={{
border: '1px solid #E2E8F0',
width: 36,
height: 36,
borderRadius: 2,
bgcolor: '#ffffff',
color: '#64748B',
'&:hover': { bgcolor: '#F8FAFC', color: '#0F172A' }
}}
>
<RefreshIcon sx={{ fontSize: 18 }} />
</IconButton>
{/* Quick Presets */}
{[
{ label: 'Today', days: 1 },
{ label: 'Last 7 days', days: 7 },
{ label: 'Last 30 days', days: 30 }
].map((p) => {
const active = isPreset(p.days);
return (
<Chip
key={p.label}
label={p.label}
onClick={() => applyPreset(p.days)}
sx={{
height: 36,
fontSize: '0.825rem',
fontWeight: 600,
borderRadius: 2,
bgcolor: active ? BRAND : '#F1F5F9',
color: active ? '#ffffff' : '#475569',
boxShadow: active ? '0 4px 10px rgba(192,18,39,0.15)' : 'none',
'& .MuiChip-label': { px: 1.5 },
'&:hover': { bgcolor: active ? '#9E0E20' : '#E2E8F0' }
}}
/>
);
})}
{/* Range Trigger */}
<Button
onClick={(e) => setCalAnchor(e.currentTarget)}
variant="outlined"
startIcon={<CalendarTodayOutlinedIcon sx={{ fontSize: 16 }} />}
sx={{
height: 36,
px: 1.5,
borderRadius: 2,
textTransform: 'none',
fontWeight: 600,
fontSize: '0.825rem',
color: '#334155',
borderColor: invalidRange ? '#EF4444' : '#E2E8F0',
bgcolor: '#ffffff',
justifyContent: 'flex-start',
minWidth: 210, // Compressed from 250px to remove dead layout space
'&:hover': { borderColor: BRAND, bgcolor: alpha(BRAND, 0.02) }
}}
>
<Stack direction="row" alignItems="center" spacing={0.75} sx={{ color: '#334155' }}>
<Box component="span">{dayjs(range.from).format('DD MMM YYYY')}</Box>
<ArrowRightAltRoundedIcon sx={{ fontSize: 16, color: '#94A3B8' }} />
<Box component="span">{dayjs(range.to).format('DD MMM YYYY')}</Box>
</Stack>
</Button>
</Stack>
</Stack>
{/* Themed calendar popover */}
<Popover
open={Boolean(calAnchor)}
anchorEl={calAnchor}
onClose={() => setCalAnchor(null)}
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
PaperProps={{ sx: { mt: 1, borderRadius: 3, border: '1px solid #ECEEF1', boxShadow: '0 12px 40px rgba(0,0,0,0.14)', overflow: 'hidden' } }}
>
<Box sx={{ px: 2, pt: 2 }}>
<Typography sx={{ fontWeight: 800, color: '#212529' }}>Select date range</Typography>
<Typography variant="caption" color="text.secondary">
{dayjs(range.from).format('DD MMM')} {dayjs(range.to).format('DD MMM YYYY')} · {dayCount} {dayCount === 1 ? 'day' : 'days'}
</Typography>
</Box>
<RangeCalendar
from={range.from}
to={range.to}
maxDate={today}
onSelect={(from, to) => setRange({ from, to })}
/>
<Divider />
<Stack direction="row" justifyContent="space-between" alignItems="center" sx={{ px: 2, py: 1.25 }}>
<Button size="small" onClick={() => applyPreset(1)} sx={{ textTransform: 'none', color: '#5F6368', fontWeight: 700 }}>
Reset to today
</Button>
<Button size="small" variant="contained" onClick={() => setCalAnchor(null)}
sx={{ textTransform: 'none', fontWeight: 700, bgcolor: BRAND, borderRadius: 2, '&:hover': { bgcolor: '#9E0E20' } }}>
Done
</Button>
</Stack>
</Popover>
{/* Metrics Row — CSS grid with minmax(0,1fr) never overflows on mobile */}
<Box
sx={{
display: 'grid',
gridTemplateColumns: {
xs: 'repeat(2, minmax(0, 1fr))',
sm: 'repeat(3, minmax(0, 1fr))',
md: 'repeat(4, minmax(0, 1fr))',
lg: 'repeat(5, minmax(0, 1fr))'
},
gap: { xs: 1.5, sm: 2, md: 3 },
mb: { xs: 3, md: 5 }
}}
>
{stats.map((s) => {
const Icon = s.icon;
return (
<Card key={s.label} sx={{ height: '100%', position: 'relative', overflow: 'hidden', borderRadius: 2, boxShadow: '0px 2px 14px rgba(38,38,38,0.03)', border: '1px solid #ECEEF1' }}>
<CardContent sx={{ p: { xs: 2, sm: 2.5 }, '&:last-child': { pb: { xs: 2, sm: 2.5 } } }}>
<Stack direction="row" alignItems="center" spacing={1.75} sx={{ mb: 1.75 }}>
<Avatar sx={{ bgcolor: s.color + '15', color: s.color, width: { xs: 40, sm: 46 }, height: { xs: 40, sm: 46 }, borderRadius: 2, flexShrink: 0 }}>
<Icon fontSize="small" />
</Avatar>
<Typography sx={{ color: '#868E96', fontWeight: 700, lineHeight: 1.3, fontSize: { xs: '0.72rem', sm: '0.78rem' }, textTransform: 'uppercase', letterSpacing: 0.6 }}>
{s.label}
</Typography>
</Stack>
<Typography sx={{ fontWeight: 800, color: '#212529', fontSize: { xs: '1.5rem', sm: '1.9rem' }, lineHeight: 1.15, mb: 0.75 }}>
{s.value}
</Typography>
<Typography variant="caption" sx={{ display: 'block', color: '#6c757d', fontWeight: 500 }}>
{s.sub}
</Typography>
</CardContent>
</Card>
);
})}
</Box>
{/* Operations Grid */}
<Grid container spacing={{ xs: 2, md: 3.5 }}>
{/* Sorting Progress & Incoming Vehicles */}
<Grid size={{ xs: 12, md: 7, lg: 8 }} >
<Stack spacing={3.5}>
{/* Sorting Station Overview */}
<Card>
<CardHeader title="Sorting Progress" subheader="How many parcels we've sorted today" />
<Divider />
<CardContent sx={{ pt: 3 }}>
<Box sx={{ mb: 3.5 }}>
<Stack direction="row" justifyContent="space-between" alignItems="center" sx={{ mb: 1 }} gap={1} flexWrap="wrap">
<Typography variant="subtitle2" sx={{ fontWeight: 700 }}>Today's target — 2,000 parcels</Typography>
<Typography variant="body2" color="text.secondary" sx={{ fontWeight: 700, whiteSpace: 'nowrap' }}>74% done</Typography>
</Stack>
<LinearProgress variant="determinate" value={74.1} sx={{ height: 10, borderRadius: 2, bgcolor: 'grey.200' }} />
</Box>
<Typography variant="subtitle2" sx={{ mb: 2, fontWeight: 700 }}>Trucks Arriving</Typography>
<TableContainer component={Paper} variant="outlined" sx={{ overflowX: 'auto' }}>
<Table size="small" sx={{ minWidth: 480 }}>
<TableHead>
<TableRow>
<TableCell>Truck</TableCell>
<TableCell>Coming From</TableCell>
<TableCell>Status</TableCell>
<TableCell>Unloaded</TableCell>
</TableRow>
</TableHead>
<TableBody>
{incomingVehicles.map((v) => (
<TableRow key={v.id}>
<TableCell sx={{ fontWeight: 700 }}>{v.id}</TableCell>
<TableCell>{v.origin}</TableCell>
<TableCell>
<Chip size="small" label={v.status} color={v.color} variant={v.status === 'Expected' ? 'outlined' : 'filled'} />
</TableCell>
<TableCell sx={{ minWidth: 150 }}>
{v.progress > 0 ? (
<Stack direction="row" alignItems="center" spacing={1}>
<LinearProgress variant="determinate" value={v.progress} sx={{ flex: 1, height: 6, borderRadius: 2 }} />
<Typography variant="caption" sx={{ fontWeight: 600 }}>{v.progress}%</Typography>
</Stack>
) : (
<Typography variant="caption" color="text.secondary">—</Typography>
)}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</CardContent>
</Card>
{/* Online Research: Heavy Traffic / Peak Season Control Center */}
<Card sx={{ borderLeft: '1px solid', borderColor: 'primary.main' }}>
<CardHeader
title="Handling Busy Days"
subheader="Simple ways the hub keeps up when parcels pile up"
avatar={
<Avatar sx={{ bgcolor: 'primary.lighter', color: 'primary.main', borderRadius: 2 }}>
<SpeedIcon />
</Avatar>
}
/>
<Divider />
<CardContent sx={{ pt: 3 }}>
<Grid container spacing={3}>
<Grid size={{ xs: 12, sm: 4 }} >
<Box sx={{ p: 2, bgcolor: 'grey.50', borderRadius: 2, border: '1px solid', borderColor: 'divider' }}>
<Stack direction="row" spacing={1} alignItems="center" sx={{ mb: 1 }}>
<ElectricBoltIcon color="success" sx={{ fontSize: 18 }} />
<Typography variant="subtitle2" sx={{ fontWeight: 700 }}>Fast Lane</Typography>
</Stack>
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
Urgent parcels skip the shelves and go straight from arrival to the outgoing trucks.
</Typography>
<Chip label="On" color="success" size="small" variant="outlined" />
</Box>
</Grid>
<Grid size={{ xs: 12, sm: 4 }} >
<Box sx={{ p: 2, bgcolor: 'grey.50', borderRadius: 2, border: '1px solid', borderColor: 'divider' }}>
<Stack direction="row" spacing={1} alignItems="center" sx={{ mb: 1 }}>
<DynamicFeedIcon color="info" sx={{ fontSize: 18 }} />
<Typography variant="subtitle2" sx={{ fontWeight: 700 }}>Separate Lines</Typography>
</Stack>
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
Big, heavy boxes are sorted on a different line from small letters and envelopes.
</Typography>
<Chip label="Using Line 4" color="info" size="small" variant="outlined" />
</Box>
</Grid>
<Grid size={{ xs: 12, sm: 4 }} >
<Box sx={{ p: 2, bgcolor: 'grey.50', borderRadius: 2, border: '1px solid', borderColor: 'divider' }}>
<Stack direction="row" spacing={1} alignItems="center" sx={{ mb: 1 }}>
<QrCodeScannerIcon color="primary" sx={{ fontSize: 18 }} />
<Typography variant="subtitle2" sx={{ fontWeight: 700 }}>Quick Scan</Typography>
</Stack>
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
A scanner reads each parcel automatically as it passes, so nothing is missed.
</Typography>
<Chip label="Working" color="primary" size="small" variant="outlined" />
</Box>
</Grid>
</Grid>
</CardContent>
</Card>
{/* Active Delivery Routes */}
<Card>
<CardHeader title="Delivery Areas Today" subheader="Parcels and milers for each part of the city" />
<Divider />
<CardContent sx={{ pt: 3 }}>
<TableContainer component={Paper} variant="outlined" sx={{ overflowX: 'auto' }}>
<Table size="small" sx={{ minWidth: 420 }}>
<TableHead>
<TableRow>
<TableCell>Area</TableCell>
<TableCell align="center">Parcels</TableCell>
<TableCell align="center">Milers</TableCell>
<TableCell align="center">Status</TableCell>
</TableRow>
</TableHead>
<TableBody>
{activeRoutes.map((r) => (
<TableRow key={r.zone}>
<TableCell sx={{ fontWeight: 600 }}>{r.zone}</TableCell>
<TableCell align="center">{r.packages}</TableCell>
<TableCell align="center">{r.riders}</TableCell>
<TableCell align="center">
<Chip
size="small"
label={r.status}
color={r.status === 'Active' ? 'success' : 'warning'}
variant="outlined"
/>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</CardContent>
</Card>
</Stack>
</Grid>
{/* Sidebar logs / Active updates */}
<Grid size={{ xs: 12, md: 5, lg: 4 }} >
<Card sx={{ height: '100%' }}>
<CardHeader title="Recent Activity" subheader="What's been happening at the hub" />
<Divider />
<CardContent sx={{ pt: 3 }}>
<Stack spacing={3}>
{recentActivity.map((act, i) => (
<Stack direction="row" spacing={2} key={i} alignItems="flex-start">
<Box
sx={{
width: 8,
height: 8,
borderRadius: '50%',
bgcolor: act.type === 'inbound' ? '#C01227' : act.type === 'exception' ? '#F04134' : '#00A854',
mt: 0.75,
flexShrink: 0
}}
/>
<Stack spacing={0.25} sx={{ flex: 1 }}>
<Typography variant="body2" sx={{ fontWeight: 500 }}>
{act.text}
</Typography>
<Typography variant="caption" color="text.secondary">
{act.time}
</Typography>
</Stack>
</Stack>
))}
</Stack>
<Box sx={{ mt: 4, p: 2.5, bgcolor: '#8E1F2A10', borderRadius: 2, border: '1px dashed #8E1F2A30' }}>
<Typography variant="subtitle2" sx={{ fontWeight: 700, color: 'primary.dark', mb: 1 }}>
Not sure where a parcel goes?
</Typography>
<Typography variant="body2" sx={{ mb: 2 }}>
Scan it and we'll tell you exactly what to do next.
</Typography>
<Button size="small" variant="contained" endIcon={<ArrowForwardIcon fontSize="small" />} href="/routing">
Where Does It Go?
</Button>
</Box>
</CardContent>
</Card>
</Grid>
</Grid>
</Box>
);
}