updates on the dispatch page and redesigned the maximum pages

This commit is contained in:
2026-06-02 13:09:29 +05:30
parent c882dbdcdd
commit 8d0c796ba5
25 changed files with 24405 additions and 4133 deletions

View File

@@ -97,7 +97,91 @@ import {
// DeleteTwoTone
} from '@ant-design/icons';
import { enqueueSnackbar } from 'notistack';
import {
MdLocalShipping,
MdHourglassEmpty,
MdCheckCircle,
MdCancel,
MdAccessTime,
MdHistoryToggleOff,
MdAssignmentTurnedIn,
MdEdit,
MdArrowBack,
MdReceiptLong
} from 'react-icons/md';
import { Paper, Box } from '@mui/material';
// ============================================================================
// Design tokens — shared with the rest of the redesigned operator pages.
// ============================================================================
const DT = {
radiusPill: 999,
radiusCard: 16,
shadowSoft: '0 14px 40px rgba(15, 23, 42, 0.10)',
shadowMd: '0 8px 24px rgba(15, 23, 42, 0.08)',
shadowPop: '0 18px 50px rgba(15, 23, 42, 0.18)',
textPrimary: '#0f172a',
textSecondary: '#64748b',
textMuted: '#94a3b8',
borderSubtle: '#e2e8f0',
divider: '#f1f5f9',
surface: '#ffffff',
surfaceAlt: '#f8fafc'
};
const dtA = (c, suffix) => `${c}${suffix}`;
const tint = (c) => dtA(c, '08');
const soft = (c) => dtA(c, '18');
const ring = (c) => dtA(c, '26');
const edge = (c) => dtA(c, '55');
const BRAND = '#662582';
const BRAND_LIGHT = '#9255AB';
// Semantic per-status palette — also drives StatusBadge.
const STATUS_META = {
pending: { label: 'Pending', color: '#f59e0b', icon: MdHourglassEmpty },
assigned: { label: 'Assigned', color: '#0ea5e9', icon: MdAssignmentTurnedIn },
confirmed: { label: 'Confirmed', color: '#10b981', icon: MdCheckCircle },
modified: { label: 'Modified', color: '#06b6d4', icon: MdHistoryToggleOff },
processing: { label: 'Processing', color: BRAND, icon: MdAccessTime },
active: { label: 'Active', color: '#8b5cf6', icon: MdLocalShipping },
closed: { label: 'Closed', color: '#06b6d4', icon: MdCheckCircle },
completed: { label: 'Completed', color: '#10b981', icon: MdCheckCircle },
cancelled: { label: 'Cancelled', color: '#ef4444', icon: MdCancel }
};
const StatusBadge = ({ status, size = 'md' }) => {
if (!status) return null;
const meta = STATUS_META[String(status).toLowerCase()] || {
label: status,
color: DT.textMuted,
icon: MdHistoryToggleOff
};
const Icon = meta.icon;
const px = size === 'lg' ? 1.25 : 1;
const py = size === 'lg' ? 0.5 : 0.375;
const fs = size === 'lg' ? 12 : 11;
return (
<Box
sx={{
display: 'inline-flex',
alignItems: 'center',
gap: 0.5,
px,
py,
borderRadius: 999,
bgcolor: tint(meta.color),
border: `1px solid ${edge(meta.color)}`,
color: meta.color,
fontSize: fs,
fontWeight: 800,
whiteSpace: 'nowrap'
}}
>
<Icon size={12} /> {meta.label}
</Box>
);
};
const Details = () => {
// const [searchParams] = useSearchParams();
@@ -854,59 +938,105 @@ const Details = () => {
open={open}
onClose={() => handleClose(false)}
maxWidth="xs"
PaperProps={{ sx: { borderRadius: 3 } }}
>
<DialogContent sx={{ mt: 2, my: 1 }}>
<Stack alignItems="center" spacing={3.5}>
<Avatar color="error" sx={{ width: 72, height: 72, fontSize: '1.75rem' }}>
<Box
sx={{
p: 2.5,
background: `linear-gradient(135deg, ${tint('#ef4444')} 0%, ${tint('#f59e0b')} 100%)`,
borderBottom: `1px solid ${DT.borderSubtle}`
}}
>
<Stack direction="row" alignItems="center" spacing={1.5}>
<Avatar sx={{ bgcolor: '#ef4444', color: '#fff', width: 40, height: 40 }}>
<DeleteFilled />
</Avatar>
<Grid >
<Chip label={orderid.slice(4)} variant="combined" color='warning' size='small' />
</Grid>
<Stack spacing={2}>
{/* <Typography variant="h4" align="center">
Are you sure you want to cancel this order?
</Typography> */}
{(invoiceeligible) &&
<Alert color="warning" variant="border" icon={<WarningFilled />}>
<AlertTitle>Order is within 24Hrs time frame. The order will be invoiced with standard pricing as agreed.</AlertTitle>
{/* <Typography variant="h6"> This is an warning alert.</Typography> */}
<Link href='https://thelegendarystaff.com/' target='_blank' >Terms & Condition link</Link>
</Alert>
}
<Typography variant="h4" align="center">
Please type in the order number to confirm.
<Stack>
<Typography variant="h5" sx={{ fontWeight: 800, color: DT.textPrimary }}>
Cancel Order
</Typography>
<Typography variant="caption" sx={{ color: DT.textSecondary, fontWeight: 600 }}>
Confirm to permanently cancel this order
</Typography>
<TextField
type='text'
onChange={(e) => {
console.log(e.target.value)
setDeletepassword(e.target.value)
}}
error={deletepassword !== orderid.slice(4)}
// error={true}
value={deletepassword}
/>
</Stack>
</Stack>
</Box>
<DialogContent sx={{ pt: 3 }}>
<Stack alignItems="center" spacing={2.5}>
<Box
sx={{
display: 'inline-flex',
alignItems: 'center',
gap: 0.5,
px: 1.25,
py: 0.5,
borderRadius: 999,
bgcolor: tint('#f59e0b'),
border: `1px solid ${edge('#f59e0b')}`,
color: '#f59e0b',
fontSize: 12,
fontWeight: 800
}}
>
<MdReceiptLong size={12} /> {orderid.slice(4)}
</Box>
<Stack direction="row" spacing={2} sx={{ width: 1 }}>
<Button fullWidth color="error" variant="contained" onClick={() => {
if (deletepassword === orderid.slice(4)) {
cancelorder();
handleClose(true);
}
{(invoiceeligible) &&
<Alert color="warning" variant="border" icon={<WarningFilled />}>
<AlertTitle>Order is within 24Hrs time frame. The order will be invoiced with standard pricing as agreed.</AlertTitle>
<Link href='https://thelegendarystaff.com/' target='_blank' >Terms & Condition link</Link>
</Alert>
}
}} autoFocus>
Yes, Cancel
</Button>
<Button fullWidth onClick={() => handleClose(false)} color="secondary" variant="outlined">
<Typography variant="body1" align="center" sx={{ color: DT.textSecondary, fontWeight: 600 }}>
Please type in the order number to confirm.
</Typography>
<TextField
type="text"
fullWidth
onChange={(e) => setDeletepassword(e.target.value)}
error={deletepassword !== orderid.slice(4)}
value={deletepassword}
placeholder={orderid.slice(4)}
/>
<Stack direction="row" spacing={1.5} sx={{ width: 1 }}>
<Button
fullWidth
onClick={() => handleClose(false)}
variant="outlined"
sx={{
borderRadius: 999,
py: 1,
borderColor: DT.borderSubtle,
color: DT.textSecondary,
fontWeight: 700,
'&:hover': { borderColor: DT.textSecondary, bgcolor: DT.surfaceAlt }
}}
>
No
</Button>
<Button
fullWidth
variant="contained"
autoFocus
onClick={() => {
if (deletepassword === orderid.slice(4)) {
cancelorder();
handleClose(true);
}
}}
sx={{
borderRadius: 999,
py: 1,
bgcolor: '#ef4444',
fontWeight: 700,
boxShadow: `0 6px 18px ${ring('#ef4444')}`,
'&:hover': { bgcolor: '#dc2626' }
}}
>
Yes, Cancel
</Button>
</Stack>
</Stack>
</DialogContent>
@@ -925,40 +1055,116 @@ const Details = () => {
// fullScreen
TransitionComponent={PopupTransition}>
<DialogTitle>
<Stack direction={'row'} justifyContent={'space-between'}>
<Stack direction={{ sm: 'row', xs: 'column' }} spacing={2} alignItems={'center'}>
<Typography variant='h3'>Assign Roles</Typography>
<Chip label={clientname} variant="light" color="primary" />
<DialogTitle
sx={{
background: `linear-gradient(135deg, ${tint(BRAND)} 0%, ${tint(BRAND_LIGHT)} 100%)`,
borderBottom: `1px solid ${DT.borderSubtle}`,
p: { xs: 2, sm: 2.5 }
}}
>
<Stack direction={{ xs: 'column', sm: 'row' }} justifyContent="space-between" alignItems={{ xs: 'flex-start', sm: 'center' }} spacing={1.5}>
<Stack direction="row" alignItems="center" spacing={1.5}>
<Avatar sx={{ bgcolor: BRAND, color: '#fff', width: 40, height: 40, boxShadow: `0 6px 18px ${ring(BRAND)}` }}>
<MdAssignmentTurnedIn size={20} />
</Avatar>
<Stack>
<Typography variant="h4" sx={{ fontWeight: 800, color: DT.textPrimary, lineHeight: 1.1 }}>
Assign Roles
</Typography>
<Typography variant="caption" sx={{ color: DT.textSecondary, fontWeight: 600 }}>
{clientname} · {currentrole}
</Typography>
</Stack>
</Stack>
<Chip label={orderid} variant="combined" color='warning' size={'large'} />
<Box
sx={{
display: 'inline-flex',
alignItems: 'center',
gap: 0.5,
px: 1.25,
py: 0.5,
borderRadius: 999,
bgcolor: tint('#f59e0b'),
border: `1px solid ${edge('#f59e0b')}`,
color: '#f59e0b',
fontSize: 12,
fontWeight: 800
}}
>
<MdReceiptLong size={12} /> {orderid}
</Box>
</Stack>
<Grid container sx={{ p: 1 }} spacing={2}>
<Grid container sx={{ pt: 2 }} spacing={1.5}>
<Grid item sm={6} xs={12}>
{/* <Chip label={currentrole} variant="combined" color="primary" size='normal' /> */}
<Tabs
value={tabstatus}
// onChange={handleChangetab}
onChange={() => setTabstatus((e) => (e === 0) ? 1 : 0)}
variant="scrollable" scrollButtons="auto" >
{/* <Tab label="All" /> */}
<Tab label={currentrole} />
</Tabs>
<Box
onClick={() => setTabstatus((e) => (e === 0 ? 1 : 0))}
sx={{
display: 'inline-flex',
alignItems: 'center',
gap: 0.75,
px: 1.25,
py: 0.625,
borderRadius: 999,
cursor: 'pointer',
bgcolor: BRAND,
color: '#fff',
fontWeight: 800,
fontSize: 12,
boxShadow: `0 6px 18px ${ring(BRAND)}`
}}
>
<Avatar sx={{ width: 22, height: 22, bgcolor: 'rgba(255,255,255,0.22)', color: '#fff' }}>
<MdAssignmentTurnedIn size={12} />
</Avatar>
{currentrole || 'Role'}
</Box>
</Grid>
<Grid item sm={6} xs={12}>
<Stack direction={'row'} justifyContent={{ xs: 'flex-start', sm: 'flex-end' }}
// alignItems={{xs:'flex-end',sm:'center'}}
sx={{ height: '100%' }} spacing={2}>
<Chip sx={{ width: '130px' }} label={`Required:${currentshiftobj.shifts}`} variant="combined" color='primary' size='normal' />
<Chip sx={{ width: '130px' }} label={`Assigned: ${currentshiftobj.assigned}`} variant="combined" color='success' size='normal' />
<Chip sx={{ width: '130px' }} label={`Remaining: ${currentshiftobj.remaining}`} variant="combined" color='error' size='normal' />
<Stack direction="row" justifyContent={{ xs: 'flex-start', sm: 'flex-end' }} spacing={1} flexWrap="wrap" useFlexGap>
{[
{ label: 'Required', value: currentshiftobj.shifts, color: BRAND },
{ label: 'Assigned', value: currentshiftobj.assigned, color: '#10b981' },
{ label: 'Remaining', value: currentshiftobj.remaining, color: '#ef4444' }
].map((c) => (
<Box
key={c.label}
sx={{
display: 'inline-flex',
alignItems: 'center',
gap: 0.625,
px: 1,
py: 0.5,
borderRadius: 999,
bgcolor: tint(c.color),
border: `1px solid ${edge(c.color)}`,
color: c.color,
fontSize: 11.5,
fontWeight: 800
}}
>
{c.label}
<Box
sx={{
minWidth: 22,
height: 18,
px: 0.5,
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 999,
fontSize: 11,
fontWeight: 800,
bgcolor: '#fff',
color: c.color,
border: `1px solid ${edge(c.color)}`
}}
>
{c.value ?? 0}
</Box>
</Box>
))}
</Stack>
</Grid>
</Grid>
</DialogTitle>
@@ -1256,215 +1462,194 @@ const Details = () => {
<Typography variant="h3">Details</Typography>
</Grid> */}
<CardActions
<Paper
elevation={0}
sx={{
position: 'sticky',
top: '60px',
// top:0,
bgcolor: theme.palette.background.default,
zIndex: 1,
// borderBottom: `1px solid ${theme.palette.divider}`,
width: '100%'
zIndex: 5,
mb: 2,
p: { xs: 1.5, sm: 2, md: 2.5 },
borderRadius: DT.radiusCard / 8,
border: '1px solid',
borderColor: DT.borderSubtle,
background: `linear-gradient(135deg, ${tint(BRAND)} 0%, ${tint(BRAND_LIGHT)} 100%)`,
boxShadow: DT.shadowMd
}}
>
<Grid item xs={12} >
<Stack direction={{ md: 'row', xs: 'column' }} justifyContent="space-between" alignItems="flex-end"
sx={{ width: '100%', p: 1 }}
>
<Stack direction='row' spacing={2} alignItems='center'
justifyContent='flex-start'
sx={{ width: { xs: '100%', md: '0' } }}
<Stack
direction={{ xs: 'column', md: 'row' }}
alignItems={{ xs: 'flex-start', md: 'center' }}
justifyContent="space-between"
spacing={{ xs: 1.5, md: 2 }}
>
<Stack direction="row" alignItems="center" spacing={{ xs: 1.25, sm: 1.75 }}>
<IconButton
onClick={() => history.back()}
sx={{
bgcolor: '#fff',
border: `1px solid ${DT.borderSubtle}`,
borderRadius: 999,
color: DT.textPrimary,
'&:hover': { bgcolor: tint(BRAND), borderColor: edge(BRAND), color: BRAND }
}}
>
<IconButton
onClick={() => history.back()}
// onClick={()=>}
<MdArrowBack size={18} />
</IconButton>
<Avatar
sx={{
width: { xs: 40, sm: 48 },
height: { xs: 40, sm: 48 },
bgcolor: BRAND,
color: '#fff',
boxShadow: `0 6px 18px ${ring(BRAND)}`
}}
>
<MdReceiptLong size={22} />
</Avatar>
<Stack>
<Typography
variant="h3"
sx={{
fontWeight: 800,
color: DT.textPrimary,
lineHeight: 1.1,
fontSize: { xs: '1.25rem', sm: '1.5rem', md: '1.75rem' }
}}
>
<ArrowBackIcon />
</IconButton>
{/* <Link to="/dashboard">Test me</Link> */}
<Stack direction='column' alignItems='flex-start'>
<Typography variant="h3">Details</Typography>
<Stack direction="row" spacing={1}>
{/* <Typography noWrap color="secondary"></Typography> */}
<Chip label={(orderid === '') ? <Skeleton sx={{ width: '80px', bgcolor: '#fff9c4' }} animation="wave" /> : orderid} variant="combined" color='warning' size='small' />
{/* <Typography variant="subtitle1">Date</Typography> */}
{/* <Typography color="secondary">{orderdate}</Typography> */}
<Chip label={(orderdate === '') ? <Skeleton sx={{ width: '80px', bgcolor: '#b3e5fc' }} animation="wave" /> : orderdate} variant="combined" color="primary" size='small' />
{(orderstatus === 'pending') &&
<Chip label="Pending" color="error" size="small" />
}
{(orderstatus === 'cancelled') &&
<Chip label="Cancelled" color="secondary" size="small" />
}
{(orderstatus === 'completed') &&
<Chip label="Completed" color="primary" size="small" />
}
{(orderstatus === 'processing') &&
<Chip label="Processing" color="primary" size="small" />
}
{(orderstatus === 'assigned') &&
<Chip label="Assigned" color="warning" size="small" />
}
{(orderstatus === 'confirmed') &&
<Chip label="Confirmed" color="success" size="small" />
}
{(orderstatus === 'active') &&
<Chip label="Active" color="info" size="small" />
}
{(orderstatus === 'closed') &&
<Chip label="Closed" color="info" size="small" />
}
{(orderstatus === 'modified') &&
<Chip label="Modified"
color='secondary' size="small" variant='contained' />
}
</Stack>
</Stack>
</Stack>
<Stack direction="row" spacing={2}
sx={{ mt: { md: 0, xs: 2 } }}
>
{/* <Typography>{dayjs(startdate).$d.toString()}</Typography> */}
{/* <Typography>{startdate}</Typography> */}
{/* <Typography> {dayjs().$d.toString()}</Typography> */}
{(((orderstatus === 'pending')
|| (orderstatus === 'assigned')
|| (orderstatus === 'confirmed')
|| (orderstatus === 'modified'))
// && (dayjs(startdate).$d > dayjs().$d)
) &&
<Tooltip title='Edit'>
<Button1
variant="outlined"
color="info"
sx={{ borderRadius: '40px' }}
startIcon={<BorderColorIcon color='info' />}
onClick={(e) => {
e.stopPropagation();
// if (dayjs(startdate).$d > dayjs().$d) {
if (dayjs(dayjs().format('MM-DD-YYYY')).isBefore(dayjs(dayjs(startdate).format('MM-DD-YYYY')))) {
navigate(`/editorder`
, {
state: {
orderheaderid: orderheaderid,
tenantid: tenantid
}
}
)
} else {
enqueueSnackbar('Order cannot be edited.\n Order date is not valid at this time',
{
variant: 'error', anchorOrigin: { vertical: 'top', horizontal: 'right' },
autoHideDuration: 4000,
style: { whiteSpace: "pre-line" }
})
}
}}
>
Edit Order
</Button1>
</Tooltip>
}
{/* {(((orderstatus === 'pending')
|| (orderstatus === 'modified'))
&& assignedpendingcount === 0) &&
<>
<Button1
variant="outlined"
color="primary"
sx={{ borderRadius: '40px' }}
startIcon={<SendIcon />}
onClick={() => {
fetchassignedstaffs();
}}
>
Notify Staff
</Button1>
</>
} */}
{(orderstatus !== 'cancelled' && orderstatus !== '' && orderstatus !== 'completed' && orderstatus !== 'closed') &&
<>
<Button1
variant="outlined"
color="error"
onClick={() => {
console.log(dayjs(startdate).diff(dayjs(), 'm') / 60)
if ((dayjs(startdate).diff(dayjs(), 'm') / 60) > 24) {
setInvoiceeligible(false)
setOpen(true)
} else {
setInvoiceeligible(true)
setOpen(true)
}
}}
sx={{ borderRadius: '40px', mt: { xs: 2, sm: 0 } }}
startIcon={<CancelOutlinedIcon />}
>
Cancel Order
</Button1>
</>
}
{(orderstatus === 'cancelled') &&
<>
<Chip label={`Order Cancelled on ${cancelleddate}`} variant="combined" color='error' />
</>
}
{/* {(orderstatus === 'completed') &&
<Button
variant="outlined"
color="error"
onClick={() => {
navigate(`/invoice/create`, {
state: {
orderheaderid: orderheaderid,
tenantid: tenantid
}
})
}
}
sx={{ borderRadius: '40px', mt: { xs: 2, sm: 0 } }}
Order Details
</Typography>
<Stack direction="row" alignItems="center" spacing={0.75} flexWrap="wrap" useFlexGap sx={{ mt: 0.75 }}>
<Box
sx={{
display: 'inline-flex',
alignItems: 'center',
gap: 0.5,
px: 1,
py: 0.375,
borderRadius: 999,
bgcolor: tint('#f59e0b'),
border: `1px solid ${edge('#f59e0b')}`,
color: '#f59e0b',
fontSize: 11,
fontWeight: 800
}}
>
Raise Invoice
</Button>
} */}
<MdReceiptLong size={11} />
{orderid === '' ? <Skeleton sx={{ width: 80 }} animation="wave" /> : orderid}
</Box>
<Box
sx={{
display: 'inline-flex',
alignItems: 'center',
gap: 0.5,
px: 1,
py: 0.375,
borderRadius: 999,
bgcolor: tint(BRAND),
border: `1px solid ${edge(BRAND)}`,
color: BRAND,
fontSize: 11,
fontWeight: 800
}}
>
<MdAccessTime size={11} />
{orderdate === '' ? <Skeleton sx={{ width: 80 }} animation="wave" /> : orderdate}
</Box>
<StatusBadge status={orderstatus} />
</Stack>
</Stack>
</Stack>
</Grid>
</CardActions>
<Stack direction="row" spacing={1.5} alignItems="center" flexWrap="wrap" useFlexGap>
{((orderstatus === 'pending') ||
(orderstatus === 'assigned') ||
(orderstatus === 'confirmed') ||
(orderstatus === 'modified')) && (
<Tooltip title="Edit">
<Button1
variant="outlined"
sx={{
borderRadius: 999,
borderColor: edge(BRAND),
color: BRAND,
fontWeight: 700,
px: 2,
'&:hover': { borderColor: BRAND, bgcolor: tint(BRAND), boxShadow: `0 0 0 3px ${ring(BRAND)}` }
}}
startIcon={<MdEdit size={16} />}
onClick={(e) => {
e.stopPropagation();
if (dayjs(dayjs().format('MM-DD-YYYY')).isBefore(dayjs(dayjs(startdate).format('MM-DD-YYYY')))) {
navigate(`/editorder`, {
state: {
orderheaderid: orderheaderid,
tenantid: tenantid
}
});
} else {
enqueueSnackbar('Order cannot be edited.\n Order date is not valid at this time', {
variant: 'error',
anchorOrigin: { vertical: 'top', horizontal: 'right' },
autoHideDuration: 4000,
style: { whiteSpace: 'pre-line' }
});
}
}}
>
Edit Order
</Button1>
</Tooltip>
)}
{orderstatus !== 'cancelled' && orderstatus !== '' && orderstatus !== 'completed' && orderstatus !== 'closed' && (
<Button1
variant="outlined"
sx={{
borderRadius: 999,
borderColor: edge('#ef4444'),
color: '#ef4444',
fontWeight: 700,
px: 2,
'&:hover': { borderColor: '#ef4444', bgcolor: tint('#ef4444'), boxShadow: `0 0 0 3px ${ring('#ef4444')}` }
}}
onClick={() => {
if ((dayjs(startdate).diff(dayjs(), 'm') / 60) > 24) {
setInvoiceeligible(false);
setOpen(true);
} else {
setInvoiceeligible(true);
setOpen(true);
}
}}
startIcon={<CancelOutlinedIcon />}
>
Cancel Order
</Button1>
)}
{orderstatus === 'cancelled' && (
<Box
sx={{
display: 'inline-flex',
alignItems: 'center',
gap: 0.5,
px: 1.25,
py: 0.5,
borderRadius: 999,
bgcolor: tint('#ef4444'),
border: `1px solid ${edge('#ef4444')}`,
color: '#ef4444',
fontSize: 12,
fontWeight: 800
}}
>
<MdCancel size={12} /> Cancelled on {cancelleddate}
</Box>
)}
</Stack>
</Stack>
</Paper>
{/* Dialog window */}