1234 lines
52 KiB
JavaScript
1234 lines
52 KiB
JavaScript
import React, { useState, useEffect, useRef, Fragment } from 'react';
|
||
|
||
import axios from 'axios';
|
||
import { useQuery } from '@tanstack/react-query';
|
||
import { enqueueSnackbar } from 'notistack';
|
||
|
||
import {
|
||
Avatar,
|
||
Box,
|
||
Table,
|
||
TableBody,
|
||
TableCell,
|
||
TableContainer,
|
||
TableHead,
|
||
TableRow,
|
||
Dialog,
|
||
DialogContent,
|
||
Typography,
|
||
Stack,
|
||
Button,
|
||
IconButton,
|
||
Tooltip,
|
||
Autocomplete,
|
||
TextField,
|
||
Collapse,
|
||
Skeleton,
|
||
Paper,
|
||
Grid,
|
||
InputBase
|
||
} from '@mui/material';
|
||
import {
|
||
MdLocalShipping,
|
||
MdHourglassEmpty,
|
||
MdCheckCircle,
|
||
MdCancel,
|
||
MdMyLocation,
|
||
MdPlace,
|
||
MdSearch,
|
||
MdClear,
|
||
MdCalendarMonth,
|
||
MdReceiptLong,
|
||
MdStraighten,
|
||
MdCurrencyRupee,
|
||
MdInventory2,
|
||
MdKeyboardArrowDown,
|
||
MdKeyboardArrowUp,
|
||
MdTaskAlt,
|
||
MdHighlightOff,
|
||
MdInsights,
|
||
MdLocalOffer
|
||
} from 'react-icons/md';
|
||
|
||
import dayjs from 'dayjs';
|
||
var utc = require('dayjs/plugin/utc');
|
||
dayjs.extend(utc);
|
||
import { DateRangePicker } from 'mui-daterange-picker';
|
||
import { addDays, addMonths, addWeeks, endOfMonth, endOfWeek, startOfMonth, startOfWeek } from 'date-fns';
|
||
|
||
import Loader from 'components/Loader';
|
||
import { useTheme } from '@mui/material/styles';
|
||
import { getreportlocationsummary, gettenantlocations } from '../api/api';
|
||
import CircularLoader from 'components/nearle_components/CircularLoader';
|
||
|
||
// ============================================================================
|
||
// 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 palette per metric column.
|
||
const C_ORDERS = '#0ea5e9';
|
||
const C_DELIVERIES = BRAND;
|
||
const C_PENDING = '#f59e0b';
|
||
const C_COMPLETED = '#10b981';
|
||
const C_CANCELLED = '#ef4444';
|
||
const C_ACCEPTED = '#6366f1';
|
||
const C_PICKED = '#8b5cf6';
|
||
const C_ARRIVED = '#06b6d4';
|
||
const C_SKIPPED = '#f97316';
|
||
const C_KMS = '#f59e0b';
|
||
|
||
const SoftPaper = (props) => (
|
||
<Paper
|
||
{...props}
|
||
sx={{
|
||
mt: 0.75,
|
||
borderRadius: 2,
|
||
boxShadow: DT.shadowPop,
|
||
border: '1px solid',
|
||
borderColor: 'divider',
|
||
overflow: 'hidden'
|
||
}}
|
||
/>
|
||
);
|
||
|
||
const AccentAvatar = ({ color, selected, size = 24, children }) => (
|
||
<Avatar
|
||
sx={{
|
||
width: size,
|
||
height: size,
|
||
bgcolor: selected ? color : soft(color),
|
||
color: selected ? '#fff' : color,
|
||
transition: 'background-color 0.15s, color 0.15s'
|
||
}}
|
||
>
|
||
{children}
|
||
</Avatar>
|
||
);
|
||
|
||
const pillFieldSx = (color) => ({
|
||
'& .MuiOutlinedInput-root': {
|
||
borderRadius: DT.radiusPill + 'px',
|
||
bgcolor: tint(color),
|
||
fontWeight: 600,
|
||
'& fieldset': { borderColor: edge(color), borderWidth: 1.5 },
|
||
'&:hover fieldset': { borderColor: color },
|
||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(color)}` },
|
||
'&.Mui-focused fieldset': { borderColor: color, borderWidth: 2 }
|
||
}
|
||
});
|
||
|
||
// Inline metric pill used in cells; faded slate when zero.
|
||
const MetricPill = ({ value, color, icon, isMoney = false }) => {
|
||
const n = Number(value);
|
||
const display = isMoney ? formatNumberToRupees(n) : Number.isFinite(n) ? n : value || 0;
|
||
const isZero = !Number.isFinite(n) || n === 0;
|
||
if (isZero) {
|
||
return (
|
||
<Typography variant="caption" sx={{ color: DT.textMuted, fontWeight: 700 }}>
|
||
{display}
|
||
</Typography>
|
||
);
|
||
}
|
||
return (
|
||
<Box
|
||
sx={{
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 0.5,
|
||
px: 0.875,
|
||
py: 0.25,
|
||
borderRadius: 999,
|
||
bgcolor: tint(color),
|
||
border: `1px solid ${edge(color)}`,
|
||
color,
|
||
fontSize: 12,
|
||
fontWeight: 800,
|
||
whiteSpace: 'nowrap'
|
||
}}
|
||
>
|
||
{icon}
|
||
{display}
|
||
</Box>
|
||
);
|
||
};
|
||
|
||
function formatNumberToRupees(value) {
|
||
return new Intl.NumberFormat('en-IN', {
|
||
style: 'currency',
|
||
currency: 'INR',
|
||
minimumFractionDigits: 2
|
||
}).format(value || 0);
|
||
}
|
||
|
||
const opentoast = (message, variant, time) => {
|
||
enqueueSnackbar(message, {
|
||
variant: variant,
|
||
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
||
autoHideDuration: time ? time : 1500
|
||
});
|
||
};
|
||
|
||
// ==============================|| OrdersReport ||============================== //
|
||
|
||
export default function OrdersReport() {
|
||
const theme = useTheme();
|
||
const tenantid = localStorage.getItem('tenantid');
|
||
|
||
const [startdate, setStartdate] = useState(dayjs().format('YYYY-MM-DD'));
|
||
const [enddate, setEnddate] = useState(dayjs().format('YYYY-MM-DD'));
|
||
const [open, setOpen] = useState(false);
|
||
const [openRow, setOpenRow] = useState(null);
|
||
const [datestatus, setDatestatus] = useState('Today');
|
||
const [total, settotal] = useState(0);
|
||
const [totalOrders, settotalOrders] = useState(0);
|
||
const [totalOrderPend, setTotalOrderPend] = useState(0);
|
||
const [totalOrderComplete, setTotalOrderComplete] = useState(0);
|
||
const [totalOrderCancel, setTotalOrderCancel] = useState(0);
|
||
const [totalDeliPend, setTotalDeliPend] = useState(0);
|
||
const [totalDeliComplete, setTotalDeliComplete] = useState(0);
|
||
const [totalDeliCancel, setTotalDeliCancel] = useState(0);
|
||
const [searchword, setSearchword] = useState('');
|
||
const [debouncedSearch, setDebouncedSearch] = useState('');
|
||
const textFieldRef = useRef(null);
|
||
const [ridersdata, setRidersdata] = useState(null);
|
||
const [selectedLocation, setSelectedLocation] = useState(null);
|
||
const [locationId, setLocationId] = useState(0);
|
||
const [locoName, setLocoName] = useState('All Locations');
|
||
const [searchLocation] = useState('');
|
||
|
||
// Debounce search.
|
||
useEffect(() => {
|
||
const handler = setTimeout(() => {
|
||
setDebouncedSearch(searchword);
|
||
}, 400);
|
||
return () => clearTimeout(handler);
|
||
}, [searchword]);
|
||
|
||
// Ctrl/Cmd+K to focus the search.
|
||
useEffect(() => {
|
||
const handleKeyPress = (event) => {
|
||
if (event.key === 'k' && (event.metaKey || event.ctrlKey)) {
|
||
event.preventDefault();
|
||
textFieldRef.current && textFieldRef.current.focus();
|
||
}
|
||
if (event.key === 'Escape' && document.activeElement === textFieldRef.current) {
|
||
textFieldRef.current.blur();
|
||
}
|
||
};
|
||
document.addEventListener('keydown', handleKeyPress);
|
||
return () => document.removeEventListener('keydown', handleKeyPress);
|
||
}, []);
|
||
|
||
// ============================================= || gettenantlocations || =============================================
|
||
const {
|
||
data: tenantLocations,
|
||
isLoading: tenantLocationsIsLoading,
|
||
isError: tenantLocationsIsError,
|
||
error: tenantLocationsError
|
||
} = useQuery({
|
||
queryKey: ['tenantlocations', searchLocation],
|
||
queryFn: gettenantlocations
|
||
});
|
||
|
||
// ============================================= || getreportlocationsummary || =============================================
|
||
const {
|
||
isLoading: isLoadingReports,
|
||
isError: isErrorReports,
|
||
data: rows,
|
||
error: reportsError
|
||
} = useQuery({
|
||
queryKey: [startdate, enddate, locationId, debouncedSearch],
|
||
queryFn: getreportlocationsummary
|
||
});
|
||
|
||
// ============================================= || getriderlocationsummary || =============================================
|
||
const getriderlocationsummary = async (id) => {
|
||
try {
|
||
const riderRes = await axios.get(
|
||
`${process.env.REACT_APP_URL}/deliveries/getriderlocationsummary/?&tenantid=${tenantid}&locationid=${id}&fromdate=${startdate}&todate=${enddate}`
|
||
);
|
||
setRidersdata(riderRes.data.details);
|
||
} catch (error) {
|
||
console.log('riderRes', error);
|
||
}
|
||
};
|
||
|
||
// ============================================= || calculate totals || =============================================
|
||
const calculate = () => {
|
||
let calculatedTotal = 0;
|
||
let ordersTotal = 0;
|
||
let Orderpending = 0;
|
||
let OrderComplete = 0;
|
||
let OrderCancel = 0;
|
||
let deliverypending = 0;
|
||
let deliverycomplete = 0;
|
||
let deliverycancel = 0;
|
||
rows &&
|
||
rows.forEach((row) => {
|
||
calculatedTotal += row.charges;
|
||
ordersTotal += row.totalorders;
|
||
Orderpending += row.Orderspending;
|
||
OrderComplete += row.orderscompleted;
|
||
OrderCancel += row.orderscancelled;
|
||
deliverypending += row.deliveriespending;
|
||
deliverycomplete += row.deliveriescompleted;
|
||
deliverycancel += row.deliveriescancelled;
|
||
});
|
||
settotal(calculatedTotal);
|
||
settotalOrders(ordersTotal);
|
||
setTotalOrderPend(Orderpending);
|
||
setTotalOrderComplete(OrderComplete);
|
||
setTotalOrderCancel(OrderCancel);
|
||
setTotalDeliPend(deliverypending);
|
||
setTotalDeliComplete(deliverycomplete);
|
||
setTotalDeliCancel(deliverycancel);
|
||
};
|
||
useEffect(() => {
|
||
calculate();
|
||
}, [rows]);
|
||
|
||
let errormessage = '';
|
||
if (isErrorReports && reportsError?.message) {
|
||
errormessage = `An error has occurred: (isErrorReports) ${reportsError.message}`;
|
||
} else if (tenantLocationsIsError && tenantLocationsError?.message) {
|
||
errormessage = `An error has occurred: (tenantLocationsIsError) ${tenantLocationsError.message}`;
|
||
}
|
||
useEffect(() => {
|
||
if (errormessage) opentoast(errormessage, 'warning', 2000);
|
||
}, [errormessage]);
|
||
|
||
// KPI tiles — derived from the calculated totals.
|
||
const kpiCards = [
|
||
{ key: 'total', label: 'Total Orders', color: BRAND, icon: MdLocalShipping, value: totalOrders },
|
||
{ key: 'pending', label: 'Pending', color: C_PENDING, icon: MdHourglassEmpty, value: totalOrderPend },
|
||
{ key: 'completed', label: 'Completed', color: C_COMPLETED, icon: MdCheckCircle, value: totalOrderComplete },
|
||
{ key: 'cancelled', label: 'Cancelled', color: C_CANCELLED, icon: MdCancel, value: totalOrderCancel },
|
||
{ key: 'charges', label: 'Total Charges', color: C_ACCEPTED, icon: MdLocalOffer, value: total, isMoney: true }
|
||
];
|
||
|
||
return (
|
||
<>
|
||
{(isLoadingReports || tenantLocationsIsLoading) && <Loader />}
|
||
{(isLoadingReports || tenantLocationsIsLoading) && <CircularLoader />}
|
||
|
||
{/* ============================================= || Header || ============================================= */}
|
||
<Paper
|
||
elevation={0}
|
||
sx={{
|
||
mb: { xs: 1.5, md: 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
|
||
}}
|
||
>
|
||
<Stack
|
||
direction={{ xs: 'column', sm: 'row' }}
|
||
alignItems={{ xs: 'flex-start', sm: 'center' }}
|
||
justifyContent="space-between"
|
||
spacing={{ xs: 1.5, sm: 2 }}
|
||
>
|
||
<Stack direction="row" alignItems="center" spacing={{ xs: 1.25, sm: 1.75 }}>
|
||
<Avatar
|
||
sx={{
|
||
width: { xs: 40, sm: 48 },
|
||
height: { xs: 40, sm: 48 },
|
||
bgcolor: BRAND,
|
||
color: '#fff',
|
||
boxShadow: `0 6px 18px ${ring(BRAND)}`
|
||
}}
|
||
>
|
||
<MdInsights 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' }
|
||
}}
|
||
>
|
||
Orders Summary
|
||
</Typography>
|
||
<Stack direction="row" alignItems="center" spacing={0.75} sx={{ mt: 0.5 }}>
|
||
<Box
|
||
sx={{
|
||
width: 8,
|
||
height: 8,
|
||
borderRadius: '50%',
|
||
bgcolor: '#10b981',
|
||
boxShadow: '0 0 0 4px rgba(16,185,129,0.18)'
|
||
}}
|
||
/>
|
||
<Typography variant="caption" sx={{ color: DT.textSecondary, fontWeight: 600 }}>
|
||
Live · {locoName} · {datestatus}
|
||
</Typography>
|
||
</Stack>
|
||
</Stack>
|
||
</Stack>
|
||
|
||
<Tooltip title="Date Filter">
|
||
<Box
|
||
onClick={() => setOpen(true)}
|
||
sx={{
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 0.75,
|
||
px: 1.5,
|
||
py: 0.875,
|
||
borderRadius: 999,
|
||
cursor: 'pointer',
|
||
bgcolor: '#fff',
|
||
border: `1.5px solid ${edge('#f59e0b')}`,
|
||
color: '#f59e0b',
|
||
fontWeight: 800,
|
||
fontSize: 12,
|
||
transition: 'all 0.18s',
|
||
'&:hover': { borderColor: '#f59e0b', boxShadow: `0 0 0 3px ${ring('#f59e0b')}` }
|
||
}}
|
||
>
|
||
<MdCalendarMonth size={14} />
|
||
{startdate && enddate
|
||
? `${dayjs(startdate).format('DD/MM/YY')} – ${dayjs(enddate).format('DD/MM/YY')}`
|
||
: 'All time'}
|
||
</Box>
|
||
</Tooltip>
|
||
</Stack>
|
||
</Paper>
|
||
|
||
{/* ============================================= || KPI Cards || ============================================= */}
|
||
<Grid container spacing={{ xs: 1.25, sm: 1.5, md: 2 }}>
|
||
{kpiCards.map((item) => {
|
||
const Icon = item.icon;
|
||
return (
|
||
<Grid item key={item.key} xs={6} sm={6} md={item.key === 'charges' ? 4 : 2}>
|
||
<Paper
|
||
elevation={0}
|
||
sx={{
|
||
position: 'relative',
|
||
overflow: 'hidden',
|
||
p: { xs: 1.25, sm: 1.75, md: 2.25 },
|
||
borderRadius: DT.radiusCard / 8,
|
||
border: '1px solid',
|
||
borderColor: DT.borderSubtle,
|
||
background: '#fff',
|
||
transition: 'transform 0.2s, box-shadow 0.2s, border-color 0.2s',
|
||
'&:hover': {
|
||
transform: 'translateY(-3px)',
|
||
boxShadow: DT.shadowMd,
|
||
borderColor: edge(item.color)
|
||
}
|
||
}}
|
||
>
|
||
<Box
|
||
sx={{
|
||
position: 'absolute',
|
||
top: 0,
|
||
left: 0,
|
||
right: 0,
|
||
height: 3,
|
||
background: `linear-gradient(90deg, ${item.color} 0%, ${soft(item.color)} 100%)`
|
||
}}
|
||
/>
|
||
<Stack direction="row" alignItems="flex-start" justifyContent="space-between" spacing={1}>
|
||
<Stack spacing={0.5} sx={{ minWidth: 0, flex: 1 }}>
|
||
<Typography
|
||
variant="caption"
|
||
sx={{
|
||
color: DT.textSecondary,
|
||
fontWeight: 700,
|
||
letterSpacing: 0.4,
|
||
textTransform: 'uppercase',
|
||
fontSize: { xs: 10, sm: 11 },
|
||
whiteSpace: 'nowrap',
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis'
|
||
}}
|
||
>
|
||
{item.label}
|
||
</Typography>
|
||
<Typography
|
||
sx={{
|
||
fontWeight: 800,
|
||
color: DT.textPrimary,
|
||
lineHeight: 1.1,
|
||
fontSize: { xs: '1.1rem', sm: '1.35rem', md: '1.55rem' }
|
||
}}
|
||
>
|
||
{isLoadingReports ? (
|
||
<Skeleton sx={{ width: 40 }} animation="wave" />
|
||
) : item.isMoney ? (
|
||
formatNumberToRupees(item.value)
|
||
) : (
|
||
item.value
|
||
)}
|
||
</Typography>
|
||
</Stack>
|
||
<Avatar
|
||
sx={{
|
||
width: { xs: 32, sm: 38, md: 44 },
|
||
height: { xs: 32, sm: 38, md: 44 },
|
||
bgcolor: soft(item.color),
|
||
color: item.color,
|
||
boxShadow: `inset 0 0 0 1px ${edge(item.color)}`,
|
||
flexShrink: 0
|
||
}}
|
||
>
|
||
<Icon size={18} />
|
||
</Avatar>
|
||
</Stack>
|
||
</Paper>
|
||
</Grid>
|
||
);
|
||
})}
|
||
</Grid>
|
||
|
||
{/* ============================================= || Filter Bar || ============================================= */}
|
||
<Paper
|
||
elevation={0}
|
||
sx={{
|
||
mt: { xs: 1.5, md: 2 },
|
||
p: { xs: 1.25, md: 1.75 },
|
||
borderRadius: DT.radiusCard / 8,
|
||
border: '1px solid',
|
||
borderColor: DT.borderSubtle,
|
||
background: '#fff',
|
||
boxShadow: DT.shadowSoft
|
||
}}
|
||
>
|
||
<Stack
|
||
direction={{ xs: 'column', md: 'row' }}
|
||
spacing={1.25}
|
||
alignItems={{ xs: 'stretch', md: 'center' }}
|
||
justifyContent="space-between"
|
||
>
|
||
{/* Search */}
|
||
<Box sx={{ width: { xs: '100%', md: 320 } }}>
|
||
<Box
|
||
sx={{
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: 0.75,
|
||
px: 1.25,
|
||
py: 0.5,
|
||
borderRadius: 999,
|
||
bgcolor: tint(BRAND),
|
||
border: `1.5px solid ${edge(BRAND)}`,
|
||
transition: 'all 0.18s',
|
||
'&:focus-within': {
|
||
borderColor: BRAND,
|
||
boxShadow: `0 0 0 3px ${ring(BRAND)}`
|
||
}
|
||
}}
|
||
>
|
||
<MdSearch size={16} style={{ color: BRAND, flexShrink: 0 }} />
|
||
<InputBase
|
||
inputRef={textFieldRef}
|
||
placeholder="Search location (ctrl+k)"
|
||
value={searchword}
|
||
onChange={(e) => setSearchword(e.target.value)}
|
||
autoComplete="off"
|
||
sx={{
|
||
flex: 1,
|
||
fontSize: 13,
|
||
fontWeight: 600,
|
||
color: DT.textPrimary,
|
||
'& input::placeholder': { color: DT.textMuted, opacity: 1 }
|
||
}}
|
||
/>
|
||
{searchword && (
|
||
<IconButton size="small" onClick={() => setSearchword('')} sx={{ p: 0.25, color: BRAND }}>
|
||
<MdClear size={14} />
|
||
</IconButton>
|
||
)}
|
||
</Box>
|
||
</Box>
|
||
|
||
{/* Location filter */}
|
||
{tenantLocations?.length === 1 ? (
|
||
<Box
|
||
sx={{
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
gap: 0.75,
|
||
px: 1.5,
|
||
py: 0.875,
|
||
borderRadius: 999,
|
||
bgcolor: tint(BRAND),
|
||
border: `1.5px solid ${edge(BRAND)}`,
|
||
color: BRAND,
|
||
fontWeight: 800,
|
||
fontSize: 13
|
||
}}
|
||
>
|
||
<MdMyLocation size={14} /> {tenantLocations[0]?.locationname}
|
||
</Box>
|
||
) : (
|
||
<Autocomplete
|
||
options={tenantLocations || []}
|
||
value={selectedLocation}
|
||
getOptionLabel={(o) => (o ? `${o.locationname} (${o.suburb || ''})` : '')}
|
||
PaperComponent={SoftPaper}
|
||
onChange={(event, value) => {
|
||
setSelectedLocation(value);
|
||
setLocationId(value ? value.locationid : 0);
|
||
setLocoName(value ? value.locationname : 'All Locations');
|
||
}}
|
||
renderInput={(params) => (
|
||
<TextField
|
||
{...params}
|
||
placeholder="All Locations"
|
||
size="small"
|
||
sx={pillFieldSx('#10b981')}
|
||
InputProps={{
|
||
...params.InputProps,
|
||
startAdornment: (
|
||
<Stack direction="row" alignItems="center" spacing={0.75} sx={{ pl: 0.5 }}>
|
||
<AccentAvatar color="#10b981" size={22} selected>
|
||
<MdPlace size={13} />
|
||
</AccentAvatar>
|
||
</Stack>
|
||
)
|
||
}}
|
||
/>
|
||
)}
|
||
sx={{ width: { xs: '100%', md: 320 } }}
|
||
/>
|
||
)}
|
||
</Stack>
|
||
</Paper>
|
||
|
||
{/* ============================================= || Table || ============================================= */}
|
||
<Paper
|
||
elevation={0}
|
||
sx={{
|
||
mt: { xs: 1.5, md: 2 },
|
||
borderRadius: DT.radiusCard / 8,
|
||
border: '1px solid',
|
||
borderColor: DT.borderSubtle,
|
||
overflow: 'hidden',
|
||
background: '#fff'
|
||
}}
|
||
>
|
||
<TableContainer
|
||
sx={{
|
||
overflow: 'auto',
|
||
'&::-webkit-scrollbar': { width: 10, height: 10 },
|
||
'&::-webkit-scrollbar-thumb': {
|
||
backgroundColor: edge(BRAND),
|
||
borderRadius: 8,
|
||
'&:hover': { backgroundColor: BRAND }
|
||
},
|
||
'&::-webkit-scrollbar-track': { backgroundColor: DT.surfaceAlt }
|
||
}}
|
||
>
|
||
<Table sx={{ minWidth: 1100 }}>
|
||
<TableHead>
|
||
<TableRow
|
||
sx={{
|
||
'& th': {
|
||
backgroundColor: DT.surfaceAlt,
|
||
color: DT.textSecondary,
|
||
fontSize: { xs: 10, md: 11 },
|
||
fontWeight: 800,
|
||
letterSpacing: 0.6,
|
||
textTransform: 'uppercase',
|
||
whiteSpace: 'nowrap',
|
||
borderBottom: `1px solid ${DT.borderSubtle}`,
|
||
py: { xs: 1, md: 1.25 },
|
||
px: { xs: 1, md: 1.5 }
|
||
}
|
||
}}
|
||
>
|
||
<TableCell rowSpan={2}>#</TableCell>
|
||
<TableCell rowSpan={2}>Location</TableCell>
|
||
<TableCell rowSpan={2} align="center">All</TableCell>
|
||
<TableCell
|
||
colSpan={3}
|
||
align="center"
|
||
sx={{
|
||
bgcolor: `${soft(C_ORDERS)} !important`,
|
||
borderLeft: `2px solid ${edge(C_ORDERS)} !important`,
|
||
borderRight: `2px solid ${edge(C_ORDERS)} !important`,
|
||
py: '6px !important'
|
||
}}
|
||
>
|
||
<Stack direction="row" alignItems="center" justifyContent="center" spacing={0.75}>
|
||
<Box
|
||
sx={{
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
width: 20,
|
||
height: 20,
|
||
borderRadius: 999,
|
||
bgcolor: C_ORDERS,
|
||
color: '#fff',
|
||
boxShadow: `0 4px 10px ${ring(C_ORDERS)}`
|
||
}}
|
||
>
|
||
<MdInventory2 size={12} />
|
||
</Box>
|
||
<Typography sx={{ fontWeight: 900, fontSize: 12, letterSpacing: 1, color: C_ORDERS }}>
|
||
Orders
|
||
</Typography>
|
||
</Stack>
|
||
</TableCell>
|
||
<TableCell
|
||
colSpan={3}
|
||
align="center"
|
||
sx={{
|
||
bgcolor: `${soft(C_DELIVERIES)} !important`,
|
||
borderLeft: `2px solid ${edge(C_DELIVERIES)} !important`,
|
||
borderRight: `2px solid ${edge(C_DELIVERIES)} !important`,
|
||
py: '6px !important'
|
||
}}
|
||
>
|
||
<Stack direction="row" alignItems="center" justifyContent="center" spacing={0.75}>
|
||
<Box
|
||
sx={{
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
width: 20,
|
||
height: 20,
|
||
borderRadius: 999,
|
||
bgcolor: C_DELIVERIES,
|
||
color: '#fff',
|
||
boxShadow: `0 4px 10px ${ring(C_DELIVERIES)}`
|
||
}}
|
||
>
|
||
<MdLocalShipping size={12} />
|
||
</Box>
|
||
<Typography sx={{ fontWeight: 900, fontSize: 12, letterSpacing: 1, color: C_DELIVERIES }}>
|
||
Deliveries
|
||
</Typography>
|
||
</Stack>
|
||
</TableCell>
|
||
<TableCell rowSpan={2} align="center">Kms</TableCell>
|
||
<TableCell rowSpan={2} align="right">Amount</TableCell>
|
||
<TableCell rowSpan={2} align="center">Action</TableCell>
|
||
</TableRow>
|
||
<TableRow
|
||
sx={{
|
||
'& th': {
|
||
backgroundColor: DT.surfaceAlt,
|
||
color: DT.textSecondary,
|
||
fontSize: { xs: 9.5, md: 10.5 },
|
||
fontWeight: 800,
|
||
letterSpacing: 0.6,
|
||
textTransform: 'uppercase',
|
||
whiteSpace: 'nowrap',
|
||
borderBottom: `1px solid ${DT.borderSubtle}`,
|
||
py: { xs: 0.75, md: 1 },
|
||
px: { xs: 1, md: 1.5 }
|
||
}
|
||
}}
|
||
>
|
||
<TableCell
|
||
align="center"
|
||
sx={{
|
||
color: `${C_PENDING} !important`,
|
||
bgcolor: `${tint(C_ORDERS)} !important`,
|
||
borderLeft: `2px solid ${edge(C_ORDERS)} !important`
|
||
}}
|
||
>
|
||
Pending
|
||
</TableCell>
|
||
<TableCell align="center" sx={{ color: `${C_COMPLETED} !important`, bgcolor: `${tint(C_ORDERS)} !important` }}>
|
||
Completed
|
||
</TableCell>
|
||
<TableCell
|
||
align="center"
|
||
sx={{
|
||
color: `${C_CANCELLED} !important`,
|
||
bgcolor: `${tint(C_ORDERS)} !important`,
|
||
borderRight: `2px solid ${edge(C_ORDERS)} !important`
|
||
}}
|
||
>
|
||
Cancelled
|
||
</TableCell>
|
||
<TableCell
|
||
align="center"
|
||
sx={{
|
||
color: `${C_PENDING} !important`,
|
||
bgcolor: `${tint(C_DELIVERIES)} !important`,
|
||
borderLeft: `2px solid ${edge(C_DELIVERIES)} !important`
|
||
}}
|
||
>
|
||
Pending
|
||
</TableCell>
|
||
<TableCell align="center" sx={{ color: `${C_COMPLETED} !important`, bgcolor: `${tint(C_DELIVERIES)} !important` }}>
|
||
Completed
|
||
</TableCell>
|
||
<TableCell
|
||
align="center"
|
||
sx={{
|
||
color: `${C_CANCELLED} !important`,
|
||
bgcolor: `${tint(C_DELIVERIES)} !important`,
|
||
borderRight: `2px solid ${edge(C_DELIVERIES)} !important`
|
||
}}
|
||
>
|
||
Cancelled
|
||
</TableCell>
|
||
</TableRow>
|
||
</TableHead>
|
||
|
||
<TableBody>
|
||
{rows && rows.length !== 0 ? (
|
||
rows.map((row, index) => (
|
||
<React.Fragment key={row.locationid}>
|
||
{/* ===================== || Main row || ===================== */}
|
||
<TableRow
|
||
sx={{
|
||
cursor: 'pointer',
|
||
transition: 'background-color 0.15s',
|
||
'& td': {
|
||
borderBottom: `1px solid ${DT.divider}`,
|
||
py: { xs: 1, md: 1.25 },
|
||
px: { xs: 1, md: 1.5 }
|
||
},
|
||
'& td.band-o': { backgroundColor: tint(C_ORDERS) },
|
||
'& td.band-d': { backgroundColor: tint(C_DELIVERIES) },
|
||
'& td.band-o-first': { borderLeft: `2px solid ${edge(C_ORDERS)}` },
|
||
'& td.band-o-last': { borderRight: `2px solid ${edge(C_ORDERS)}` },
|
||
'& td.band-d-first': { borderLeft: `2px solid ${edge(C_DELIVERIES)}` },
|
||
'& td.band-d-last': { borderRight: `2px solid ${edge(C_DELIVERIES)}` },
|
||
backgroundColor: openRow === row.locationid ? tint(BRAND) : 'transparent',
|
||
'&:hover': { backgroundColor: openRow === row.locationid ? soft(BRAND) : DT.surfaceAlt },
|
||
'&:hover td.band-o': { backgroundColor: soft(C_ORDERS) },
|
||
'&:hover td.band-d': { backgroundColor: soft(C_DELIVERIES) }
|
||
}}
|
||
>
|
||
<TableCell>
|
||
<Typography sx={{ fontWeight: 700, color: DT.textSecondary }}>{index + 1}</Typography>
|
||
</TableCell>
|
||
|
||
<TableCell>
|
||
<Stack>
|
||
<Typography variant="subtitle2" sx={{ fontWeight: 700, color: DT.textPrimary }} noWrap>
|
||
{row.locationname}
|
||
</Typography>
|
||
<Typography variant="caption" sx={{ color: DT.textMuted }}>
|
||
Id : {row.locationid}
|
||
</Typography>
|
||
</Stack>
|
||
</TableCell>
|
||
|
||
<TableCell align="center">
|
||
<MetricPill value={row.totalorders} color={BRAND} icon={<MdInventory2 size={11} />} />
|
||
</TableCell>
|
||
|
||
<TableCell align="center" className="band-o band-o-first">
|
||
<MetricPill value={row.Orderspending} color={C_PENDING} icon={<MdHourglassEmpty size={11} />} />
|
||
</TableCell>
|
||
<TableCell align="center" className="band-o">
|
||
<MetricPill value={row.orderscompleted} color={C_COMPLETED} icon={<MdCheckCircle size={11} />} />
|
||
</TableCell>
|
||
<TableCell align="center" className="band-o band-o-last">
|
||
<MetricPill value={row.orderscancelled} color={C_CANCELLED} icon={<MdCancel size={11} />} />
|
||
</TableCell>
|
||
|
||
<TableCell align="center" className="band-d band-d-first">
|
||
<MetricPill value={row.deliveriespending} color={C_PENDING} icon={<MdHourglassEmpty size={11} />} />
|
||
</TableCell>
|
||
<TableCell align="center" className="band-d">
|
||
<MetricPill value={row.deliveriescompleted} color={C_COMPLETED} icon={<MdCheckCircle size={11} />} />
|
||
</TableCell>
|
||
<TableCell align="center" className="band-d band-d-last">
|
||
<MetricPill value={row.deliveriescancelled} color={C_CANCELLED} icon={<MdCancel size={11} />} />
|
||
</TableCell>
|
||
|
||
<TableCell align="center">
|
||
<Tooltip title="Cumulative Kms" placement="top">
|
||
<Box sx={{ display: 'inline-block' }}>
|
||
<MetricPill
|
||
value={parseFloat(row.cumulativekms).toFixed(2)}
|
||
color={C_KMS}
|
||
icon={<MdStraighten size={11} />}
|
||
/>
|
||
</Box>
|
||
</Tooltip>
|
||
</TableCell>
|
||
|
||
<TableCell align="right">
|
||
<Tooltip title="Total Charges" placement="top">
|
||
<Box sx={{ display: 'inline-block' }}>
|
||
<MetricPill value={row.charges} color={BRAND} icon={<MdCurrencyRupee size={11} />} isMoney />
|
||
</Box>
|
||
</Tooltip>
|
||
</TableCell>
|
||
|
||
<TableCell align="center">
|
||
<Tooltip title={openRow === row.locationid ? 'Collapse riders' : 'View riders'}>
|
||
<IconButton
|
||
size="small"
|
||
onClick={() => {
|
||
getriderlocationsummary(row.locationid);
|
||
setOpenRow(openRow === row.locationid ? null : row.locationid);
|
||
}}
|
||
sx={{
|
||
bgcolor: openRow === row.locationid ? BRAND : tint(BRAND),
|
||
border: `1px solid ${openRow === row.locationid ? BRAND : edge(BRAND)}`,
|
||
color: openRow === row.locationid ? '#fff' : BRAND,
|
||
borderRadius: 999,
|
||
p: 0.75,
|
||
transition: 'all 0.18s',
|
||
'&:hover': {
|
||
bgcolor: openRow === row.locationid ? BRAND : soft(BRAND),
|
||
borderColor: BRAND,
|
||
boxShadow: `0 0 0 3px ${ring(BRAND)}`
|
||
}
|
||
}}
|
||
>
|
||
{openRow === row.locationid ? <MdKeyboardArrowUp size={14} /> : <MdKeyboardArrowDown size={14} />}
|
||
</IconButton>
|
||
</Tooltip>
|
||
</TableCell>
|
||
</TableRow>
|
||
|
||
{/* ===================== || Collapsible riders row || ===================== */}
|
||
{openRow === row.locationid && (
|
||
<TableRow>
|
||
<TableCell colSpan={13} sx={{ p: 0, borderBottom: `1px solid ${DT.divider}`, bgcolor: DT.surfaceAlt }}>
|
||
<Collapse in={openRow === row.locationid} timeout="auto" unmountOnExit>
|
||
<Box sx={{ p: { xs: 1.5, md: 2 } }}>
|
||
<Stack direction="row" alignItems="center" spacing={1} sx={{ mb: 1.25 }}>
|
||
<AccentAvatar color={BRAND} size={22} selected>
|
||
<MdLocalShipping size={12} />
|
||
</AccentAvatar>
|
||
<Typography variant="subtitle2" sx={{ fontWeight: 800, color: DT.textPrimary }}>
|
||
Riders Summary · {row.locationname}
|
||
</Typography>
|
||
</Stack>
|
||
|
||
<Paper
|
||
elevation={0}
|
||
sx={{
|
||
borderRadius: 2,
|
||
border: '1px solid',
|
||
borderColor: DT.borderSubtle,
|
||
overflow: 'hidden',
|
||
background: '#fff'
|
||
}}
|
||
>
|
||
<Table size="small">
|
||
<TableHead>
|
||
<TableRow
|
||
sx={{
|
||
'& th': {
|
||
backgroundColor: tint(BRAND),
|
||
color: BRAND,
|
||
fontSize: 10.5,
|
||
fontWeight: 800,
|
||
letterSpacing: 0.6,
|
||
textTransform: 'uppercase',
|
||
whiteSpace: 'nowrap',
|
||
borderBottom: `1px solid ${edge(BRAND)}`,
|
||
py: 0.75
|
||
}
|
||
}}
|
||
>
|
||
<TableCell align="center">#</TableCell>
|
||
<TableCell>Rider</TableCell>
|
||
<TableCell align="center">Deliveries</TableCell>
|
||
<TableCell align="center">Pending</TableCell>
|
||
<TableCell align="center">Assigned</TableCell>
|
||
<TableCell align="center">Accepted</TableCell>
|
||
<TableCell align="center">Arrived</TableCell>
|
||
<TableCell align="center">Picked</TableCell>
|
||
<TableCell align="center">Skipped</TableCell>
|
||
<TableCell align="center">Delivered</TableCell>
|
||
<TableCell align="center">Kms</TableCell>
|
||
<TableCell align="center">Charges</TableCell>
|
||
</TableRow>
|
||
</TableHead>
|
||
<TableBody>
|
||
{ridersdata && ridersdata.length > 0 ? (
|
||
ridersdata.map((rider, ri) => (
|
||
<TableRow
|
||
key={`${rider?.firstname}-${ri}`}
|
||
sx={{
|
||
'& td': { borderBottom: `1px solid ${DT.divider}`, py: 0.875, px: 1 },
|
||
'&:hover': { backgroundColor: DT.surfaceAlt }
|
||
}}
|
||
>
|
||
<TableCell align="center">
|
||
<Typography sx={{ fontWeight: 700, color: DT.textSecondary, fontSize: 12 }}>
|
||
{ri + 1}
|
||
</Typography>
|
||
</TableCell>
|
||
<TableCell>
|
||
<Stack direction="row" alignItems="center" spacing={0.75}>
|
||
<Typography
|
||
variant="caption"
|
||
sx={{ fontWeight: 700, color: DT.textPrimary }}
|
||
noWrap
|
||
>
|
||
{rider?.firstname}
|
||
</Typography>
|
||
{rider?.status == 'Active' ? (
|
||
<Tooltip title="Active">
|
||
<span style={{ display: 'inline-flex', color: C_COMPLETED }}>
|
||
<MdTaskAlt size={14} />
|
||
</span>
|
||
</Tooltip>
|
||
) : (
|
||
<Tooltip title="Inactive">
|
||
<span style={{ display: 'inline-flex', color: C_CANCELLED }}>
|
||
<MdHighlightOff size={14} />
|
||
</span>
|
||
</Tooltip>
|
||
)}
|
||
</Stack>
|
||
</TableCell>
|
||
<TableCell align="center">
|
||
<MetricPill value={rider?.totalorders} color={BRAND} icon={<MdInventory2 size={10} />} />
|
||
</TableCell>
|
||
<TableCell align="center">
|
||
<MetricPill value={rider?.pending} color={C_PENDING} icon={<MdHourglassEmpty size={10} />} />
|
||
</TableCell>
|
||
<TableCell align="center">
|
||
<MetricPill value={rider?.assigned} color={C_ORDERS} icon={<MdCheckCircle size={10} />} />
|
||
</TableCell>
|
||
<TableCell align="center">
|
||
<MetricPill value={rider?.accepted} color={C_ACCEPTED} icon={<MdCheckCircle size={10} />} />
|
||
</TableCell>
|
||
<TableCell align="center">
|
||
<MetricPill value={rider?.arrived} color={C_ARRIVED} icon={<MdCheckCircle size={10} />} />
|
||
</TableCell>
|
||
<TableCell align="center">
|
||
<MetricPill value={rider?.picked} color={C_PICKED} icon={<MdLocalShipping size={10} />} />
|
||
</TableCell>
|
||
<TableCell align="center">
|
||
<MetricPill value={rider?.skipped} color={C_SKIPPED} icon={<MdCancel size={10} />} />
|
||
</TableCell>
|
||
<TableCell align="center">
|
||
<MetricPill value={rider?.delivered} color={C_COMPLETED} icon={<MdCheckCircle size={10} />} />
|
||
</TableCell>
|
||
<TableCell align="center">
|
||
<MetricPill value={rider?.cumulativekms} color={C_KMS} icon={<MdStraighten size={10} />} />
|
||
</TableCell>
|
||
<TableCell align="center">
|
||
<MetricPill value={rider?.deliveryamt} color={BRAND} icon={<MdCurrencyRupee size={10} />} isMoney />
|
||
</TableCell>
|
||
</TableRow>
|
||
))
|
||
) : (
|
||
<TableRow>
|
||
<TableCell colSpan={12} sx={{ py: 3, borderBottom: 'none' }}>
|
||
<Stack alignItems="center" spacing={1}>
|
||
<Avatar sx={{ width: 40, height: 40, bgcolor: soft('#94a3b8'), color: DT.textMuted }}>
|
||
<MdLocalShipping size={18} />
|
||
</Avatar>
|
||
<Typography variant="caption" sx={{ color: DT.textSecondary, fontWeight: 700 }}>
|
||
No rider data for this location
|
||
</Typography>
|
||
</Stack>
|
||
</TableCell>
|
||
</TableRow>
|
||
)}
|
||
</TableBody>
|
||
</Table>
|
||
</Paper>
|
||
</Box>
|
||
</Collapse>
|
||
</TableCell>
|
||
</TableRow>
|
||
)}
|
||
</React.Fragment>
|
||
))
|
||
) : (
|
||
<TableRow>
|
||
<TableCell colSpan={13} sx={{ py: 6, borderBottom: 'none' }}>
|
||
<Stack alignItems="center" spacing={1.5}>
|
||
<Avatar sx={{ width: 64, height: 64, bgcolor: soft('#94a3b8'), color: DT.textMuted }}>
|
||
<MdInsights size={28} />
|
||
</Avatar>
|
||
<Typography variant="subtitle1" sx={{ fontWeight: 700, color: DT.textPrimary }}>
|
||
No summary data
|
||
</Typography>
|
||
<Typography variant="caption" sx={{ color: DT.textSecondary }}>
|
||
Adjust the date range or location filter above.
|
||
</Typography>
|
||
</Stack>
|
||
</TableCell>
|
||
</TableRow>
|
||
)}
|
||
|
||
{/* ===================== || Totals row || ===================== */}
|
||
{rows && rows.length !== 0 && (
|
||
<TableRow
|
||
sx={{
|
||
'& td': {
|
||
backgroundColor: tint(BRAND),
|
||
borderTop: `2px solid ${edge(BRAND)}`,
|
||
borderBottom: 'none',
|
||
py: 1.25,
|
||
px: 1.5
|
||
},
|
||
'& td.band-o': { backgroundColor: soft(C_ORDERS) },
|
||
'& td.band-d': { backgroundColor: soft(C_DELIVERIES) },
|
||
'& td.band-o-first': { borderLeft: `2px solid ${edge(C_ORDERS)}` },
|
||
'& td.band-o-last': { borderRight: `2px solid ${edge(C_ORDERS)}` },
|
||
'& td.band-d-first': { borderLeft: `2px solid ${edge(C_DELIVERIES)}` },
|
||
'& td.band-d-last': { borderRight: `2px solid ${edge(C_DELIVERIES)}` }
|
||
}}
|
||
>
|
||
<TableCell colSpan={2}>
|
||
<Stack direction="row" alignItems="center" spacing={1}>
|
||
<AccentAvatar color={BRAND} size={24} selected>
|
||
<MdReceiptLong size={13} />
|
||
</AccentAvatar>
|
||
<Typography sx={{ fontWeight: 800, color: BRAND, fontSize: 13 }}>Total</Typography>
|
||
</Stack>
|
||
</TableCell>
|
||
<TableCell align="center">
|
||
<Typography sx={{ fontWeight: 800, color: DT.textPrimary }}>{totalOrders}</Typography>
|
||
</TableCell>
|
||
<TableCell align="center" className="band-o band-o-first">
|
||
<Typography sx={{ fontWeight: 800, color: C_PENDING }}>{totalOrderPend}</Typography>
|
||
</TableCell>
|
||
<TableCell align="center" className="band-o">
|
||
<Typography sx={{ fontWeight: 800, color: C_COMPLETED }}>{totalOrderComplete}</Typography>
|
||
</TableCell>
|
||
<TableCell align="center" className="band-o band-o-last">
|
||
<Typography sx={{ fontWeight: 800, color: C_CANCELLED }}>{totalOrderCancel}</Typography>
|
||
</TableCell>
|
||
<TableCell align="center" className="band-d band-d-first">
|
||
<Typography sx={{ fontWeight: 800, color: C_PENDING }}>{totalDeliPend}</Typography>
|
||
</TableCell>
|
||
<TableCell align="center" className="band-d">
|
||
<Typography sx={{ fontWeight: 800, color: C_COMPLETED }}>{totalDeliComplete}</Typography>
|
||
</TableCell>
|
||
<TableCell align="center" className="band-d band-d-last">
|
||
<Typography sx={{ fontWeight: 800, color: C_CANCELLED }}>{totalDeliCancel}</Typography>
|
||
</TableCell>
|
||
<TableCell />
|
||
<TableCell align="right">
|
||
<Typography sx={{ fontWeight: 800, color: BRAND, fontSize: 14 }}>
|
||
{formatNumberToRupees(total)}
|
||
</Typography>
|
||
</TableCell>
|
||
<TableCell />
|
||
</TableRow>
|
||
)}
|
||
</TableBody>
|
||
</Table>
|
||
</TableContainer>
|
||
</Paper>
|
||
|
||
{/* ============================================= || Date Filter Dialog || ============================================= */}
|
||
<Dialog open={open} onClose={() => setOpen(false)} PaperProps={{ sx: { borderRadius: 3 } }}>
|
||
<Box
|
||
sx={{
|
||
p: 2.5,
|
||
background: `linear-gradient(135deg, ${tint(BRAND)} 0%, ${tint(BRAND_LIGHT)} 100%)`,
|
||
borderBottom: `1px solid ${DT.borderSubtle}`
|
||
}}
|
||
>
|
||
<Stack direction="row" alignItems="center" spacing={1.5}>
|
||
<Avatar sx={{ bgcolor: BRAND, color: '#fff', width: 40, height: 40, boxShadow: `0 6px 18px ${ring(BRAND)}` }}>
|
||
<MdCalendarMonth size={20} />
|
||
</Avatar>
|
||
<Stack>
|
||
<Typography variant="h5" sx={{ fontWeight: 800, color: DT.textPrimary }}>
|
||
Select Date Range
|
||
</Typography>
|
||
<Typography variant="caption" sx={{ color: DT.textSecondary, fontWeight: 600 }}>
|
||
Filter the summary by a date range or preset
|
||
</Typography>
|
||
</Stack>
|
||
</Stack>
|
||
</Box>
|
||
<DialogContent sx={{ width: '100%' }} className="datedialog">
|
||
<DateRangePicker
|
||
open={open}
|
||
toggle={() => setOpen(!open)}
|
||
id="daterange1"
|
||
onChange={(range) => {
|
||
if (range.label === 'All') {
|
||
setStartdate('');
|
||
setEnddate('');
|
||
setDatestatus('All');
|
||
setOpen(false);
|
||
} else {
|
||
setStartdate(dayjs(range.startDate).format('YYYY-MM-DD'));
|
||
setEnddate(dayjs(range.endDate).format('YYYY-MM-DD'));
|
||
setDatestatus(range.label || '');
|
||
}
|
||
}}
|
||
definedRanges={[
|
||
{ label: 'Today', startDate: new Date(), endDate: new Date() },
|
||
{ label: 'Yesterday', startDate: addDays(new Date(), -1), endDate: addDays(new Date(), -1) },
|
||
{ label: 'Tomorrow', startDate: addDays(new Date(), +1), endDate: addDays(new Date(), +1) },
|
||
{ label: 'This Week', startDate: startOfWeek(new Date()), endDate: endOfWeek(new Date()) },
|
||
{ label: 'Last Week', startDate: startOfWeek(addWeeks(new Date(), -1)), endDate: endOfWeek(addWeeks(new Date(), -1)) },
|
||
{ label: 'Last 7 Days', startDate: addWeeks(new Date(), -1), endDate: new Date() },
|
||
{ label: 'This Month', startDate: startOfMonth(new Date()), endDate: endOfMonth(new Date()) },
|
||
{ label: 'Last Month', startDate: startOfMonth(addMonths(new Date(), -1)), endDate: endOfMonth(addMonths(new Date(), -1)) },
|
||
{ label: 'All', startDate: new Date(), endDate: addDays(new Date(), -1) }
|
||
]}
|
||
/>
|
||
</DialogContent>
|
||
<Stack direction="row" justifyContent="flex-end" spacing={1} sx={{ width: '100%', p: 2, borderTop: `1px solid ${DT.divider}` }}>
|
||
<Button
|
||
variant="outlined"
|
||
onClick={() => setOpen(false)}
|
||
sx={{
|
||
borderRadius: 999,
|
||
px: 2.5,
|
||
borderColor: DT.borderSubtle,
|
||
color: DT.textSecondary,
|
||
fontWeight: 700,
|
||
'&:hover': { borderColor: DT.textSecondary, bgcolor: DT.surfaceAlt }
|
||
}}
|
||
>
|
||
Cancel
|
||
</Button>
|
||
<Button
|
||
variant="contained"
|
||
onClick={() => setOpen(false)}
|
||
sx={{
|
||
borderRadius: 999,
|
||
px: 3,
|
||
bgcolor: BRAND,
|
||
fontWeight: 700,
|
||
boxShadow: `0 6px 18px ${ring(BRAND)}`,
|
||
'&:hover': { bgcolor: '#4D1C61' }
|
||
}}
|
||
>
|
||
Apply
|
||
</Button>
|
||
</Stack>
|
||
</Dialog>
|
||
</>
|
||
);
|
||
}
|