updates on the ui changes and frully removed the mui and converted into astryx and color change
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,750 +0,0 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
import {
|
||||
Autocomplete,
|
||||
Button,
|
||||
Chip,
|
||||
Divider,
|
||||
Grid,
|
||||
Stack,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
TextField,
|
||||
Tooltip,
|
||||
Typography,
|
||||
Backdrop,
|
||||
IconButton,
|
||||
Badge,
|
||||
Accordion,
|
||||
AccordionSummary,
|
||||
AccordionActions,
|
||||
AccordionDetails,
|
||||
useMediaQuery
|
||||
} from '@mui/material';
|
||||
import React, { Fragment, useEffect, useMemo, useState } from 'react';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { MobileCard, MobileCardList, MobileField, MobileFieldGrid } from 'components/nearle_components/MobileCard';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import dayjs from 'dayjs';
|
||||
import MainCard from 'components/MainCard';
|
||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||
import { createAutomationDeliveries, fetchPaymentType, fetchRidersList, finalCreatedeliveries, notifyRider } from 'pages/api/api';
|
||||
import { OpenToast } from 'components/third-party/OpenToast';
|
||||
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||
import Loader from 'components/Loader';
|
||||
import CircularLoader from 'components/CircularLoader';
|
||||
import { Empty } from 'antd';
|
||||
import HoverSocialCard from 'components/cards/statistics/HoverSocialCard';
|
||||
import { DashboardFilled, DashboardOutlined, OpenAIFilled } from '@ant-design/icons';
|
||||
import { MdDirectionsBike } from 'react-icons/md';
|
||||
import { FaMapLocationDot } from 'react-icons/fa6';
|
||||
import { HiOutlineArrowLeft } from 'react-icons/hi';
|
||||
import { IoReload } from 'react-icons/io5';
|
||||
import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';
|
||||
import CheckBoxIcon from '@mui/icons-material/CheckBox';
|
||||
import { GiProfit } from 'react-icons/gi';
|
||||
import { ArrowRightAltOutlined } from '@mui/icons-material';
|
||||
import LocalShippingIcon from '@mui/icons-material/LocalShipping';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import BoltIcon from '@mui/icons-material/Bolt';
|
||||
import CurrencyRupeeIcon from '@mui/icons-material/CurrencyRupee';
|
||||
import SavingsIcon from '@mui/icons-material/Savings';
|
||||
import EnergySavingsLeafIcon from '@mui/icons-material/EnergySavingsLeaf';
|
||||
import DirectionsBikeOutlinedIcon from '@mui/icons-material/DirectionsBikeOutlined';
|
||||
import DownloadOutlinedIcon from '@mui/icons-material/DownloadOutlined';
|
||||
import { exportToExcel } from 'components/exportToExcel';
|
||||
import CSVExport from 'components/third-party/ReactTable';
|
||||
|
||||
var utc = require('dayjs/plugin/utc');
|
||||
dayjs.extend(utc);
|
||||
|
||||
const OptimisedOrderPreview = () => {
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
console.log('location.state', location.state);
|
||||
const [rider, setRider] = useState(null);
|
||||
const [payment, setPayment] = useState(null);
|
||||
const [finaldeliveryList, setFinalDeliveryList] = useState([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [deliverylist, setDeliverylist] = useState(location.state?.deliverylist);
|
||||
const [zoneData, setZoneData] = useState(location?.state?.zoneData);
|
||||
const [metaData, setMetaData] = useState(location.state?.metaData);
|
||||
const riderToken = location.state?.riderToken;
|
||||
const appId = location.state?.appId;
|
||||
const aiMode = location.state?.aiMode;
|
||||
const reassignOrders = location.state?.reassignOrders;
|
||||
const [csvExportData, setCsvExportData] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('called');
|
||||
|
||||
console.log('aiMode', aiMode);
|
||||
console.log('riderToken', riderToken);
|
||||
console.log('zoneData', zoneData);
|
||||
console.log('metaData', metaData);
|
||||
console.log('reassignOrders', reassignOrders);
|
||||
}, [zoneData, metaData, deliverylist]);
|
||||
|
||||
useEffect(() => {
|
||||
const filtered = finaldeliveryList.map((item) => ({
|
||||
zone_name: item.zone_name,
|
||||
ordernotes: item.ordernotes,
|
||||
rider: item.rider,
|
||||
step: item.step,
|
||||
ordertype: item.ordertype,
|
||||
orderamount: item.orderamount,
|
||||
riderkms: item.riderkms,
|
||||
cumulativekms: item.cumulativekms,
|
||||
baseprice: item.baseprice,
|
||||
minkm: item.minkm,
|
||||
priceperkm: item.priceperkm,
|
||||
kms: item.kms,
|
||||
actualkms: item.actualkms,
|
||||
rider_charge: item.rider_charge,
|
||||
deliveryamt: item.deliveryamt,
|
||||
deliverycharges: item.deliverycharges,
|
||||
profit: item.profit
|
||||
}));
|
||||
|
||||
setCsvExportData(filtered);
|
||||
|
||||
console.log('csvExportData', filtered);
|
||||
}, [finaldeliveryList]);
|
||||
useEffect(() => {
|
||||
if (!deliverylist?.length) return;
|
||||
const updateDeliveryAmtList = deliverylist.map((list) => {
|
||||
const cumulativeKms = Number(list.cumulativekms || 0);
|
||||
const minKm = Number(list.minkm || 0);
|
||||
const basePrice = Number(list.baseprice || 0);
|
||||
const pricePerKm = Number(list.priceperkm || 0);
|
||||
if (cumulativeKms <= minKm) {
|
||||
return {
|
||||
...list,
|
||||
deliveryamt: basePrice
|
||||
};
|
||||
}
|
||||
return {
|
||||
...list,
|
||||
deliveryamt: (cumulativeKms - minKm) * pricePerKm + basePrice
|
||||
};
|
||||
});
|
||||
|
||||
setFinalDeliveryList(updateDeliveryAmtList);
|
||||
}, [deliverylist]);
|
||||
|
||||
// ==============================|| fetchPaymentType ||============================== //
|
||||
|
||||
const {
|
||||
data: paymentModes = [],
|
||||
isLoading: paymentModesLoading,
|
||||
isError: paymentModesError,
|
||||
error: paymentModesErrorMessage
|
||||
} = useQuery({
|
||||
queryKey: ['paymentmodes'],
|
||||
queryFn: fetchPaymentType
|
||||
});
|
||||
|
||||
// ==============================|| fetchRidersList ||============================== //
|
||||
|
||||
const {
|
||||
data: ridersList = [],
|
||||
isLoading: ridersListLoading,
|
||||
isError: ridersListError,
|
||||
error: ridersListErrorMessage,
|
||||
refetch: ridersListRefetch
|
||||
} = useQuery({
|
||||
queryKey: ['ridersList', appId], // Unique key for caching & re-fetching
|
||||
queryFn: fetchRidersList,
|
||||
enabled: appId !== 0 // Ensures query runs only when appId is valid
|
||||
});
|
||||
|
||||
const getRiderName = async (userid) => {
|
||||
await ridersList.map((rider) => {
|
||||
if (rider.userid == userid) {
|
||||
return rider.firstname;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// ======================================================= || notifyRiderMutation || =======================================================
|
||||
|
||||
const notifyRiderMutation = useMutation({
|
||||
mutationFn: notifyRider, // Using the separate function
|
||||
onSuccess: () => {
|
||||
OpenToast('Notification sent Successfully', 'success', 2000);
|
||||
},
|
||||
onError: (error) => {
|
||||
OpenToast(error.message, 'error', 2000);
|
||||
}
|
||||
});
|
||||
|
||||
const createFinalDeliveryMutation = useMutation({
|
||||
mutationFn: finalCreatedeliveries, // for optimised delivery create
|
||||
|
||||
onSuccess: (data) => {
|
||||
// rider state here is never set (no setRider call anywhere in this
|
||||
// file), so rider.userfcmtoken threw on every success — also the
|
||||
// wrong argument type regardless (notifyRider needs a milerprofileid,
|
||||
// not an FCM token; see dispatch/Preview.js's identical fix). Notify
|
||||
// every rider actually present in the committed deliveries instead.
|
||||
const notifiedRiderIds = new Set();
|
||||
(finaldeliveryList || []).forEach((order) => {
|
||||
const riderId = order.userid;
|
||||
if (riderId == null || notifiedRiderIds.has(String(riderId))) return;
|
||||
notifiedRiderIds.add(String(riderId));
|
||||
notifyRiderMutation.mutate(riderId);
|
||||
});
|
||||
if (data.status == 'accepted') {
|
||||
OpenToast('Delivery Created Successfully', 'success', 2000);
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
OpenToast(error.message, 'error', 4000);
|
||||
},
|
||||
onSettled: () => {
|
||||
setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
navigate('/doormile/deliveries');
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
|
||||
const handleFinalCreateDelivery = async () => {
|
||||
// console.log('Final delivery list:', finaldeliveryList);
|
||||
|
||||
setIsLoading(true);
|
||||
createFinalDeliveryMutation.mutate({
|
||||
deliveries: finaldeliveryList
|
||||
});
|
||||
};
|
||||
const createDeliveryMutation = useMutation({
|
||||
// 0 -> manual rider assign 1 -> ai rider assign
|
||||
mutationFn: createAutomationDeliveries,
|
||||
onSuccess: (data, variables) => {
|
||||
console.log('data', data);
|
||||
console.log('varialbles', variables);
|
||||
OpenToast('Orders Optimised Successfully', 'success', 2000);
|
||||
// notifyRiderMutation.mutate(variables?.riderToken); // Call notifyRider after success
|
||||
setZoneData(data?.zones);
|
||||
setDeliverylist(data?.details);
|
||||
setMetaData(data?.meta);
|
||||
setIsLoading(false);
|
||||
},
|
||||
onError: (error) => {
|
||||
OpenToast(error.message, 'error', 4000);
|
||||
setIsLoading(false);
|
||||
},
|
||||
onSettled: () => {
|
||||
setIsLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
const tuningTypes = [
|
||||
{
|
||||
tuneid: 1,
|
||||
type: 'Rider'
|
||||
},
|
||||
{
|
||||
tuneid: 2,
|
||||
type: 'Pickup'
|
||||
},
|
||||
{
|
||||
tuneid: 3,
|
||||
type: 'Zone'
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{
|
||||
<Backdrop
|
||||
sx={{
|
||||
color: '#fff',
|
||||
zIndex: (theme) => theme.zIndex.drawer + 1
|
||||
}}
|
||||
open={paymentModesLoading || ridersListLoading || isLoading} // when loader = true, backdrop covers the page
|
||||
>
|
||||
<CircularLoader color="inherit" />
|
||||
</Backdrop>
|
||||
}
|
||||
{(paymentModesLoading || ridersListLoading || isLoading) && (
|
||||
<>
|
||||
<Loader />
|
||||
<CircularLoader />
|
||||
</>
|
||||
)}
|
||||
<Stack
|
||||
direction={{ xs: 'column', md: 'row' }}
|
||||
alignItems={{ xs: 'stretch', md: 'center' }}
|
||||
justifyContent="space-between"
|
||||
spacing={{ xs: 1.5, md: 0 }}
|
||||
sx={{}}
|
||||
>
|
||||
<Stack direction="row" alignItems="center" spacing={1}>
|
||||
<Tooltip title="Back to orders" placement="top">
|
||||
<IconButton
|
||||
onClick={() => navigate('/doormile/orders')}
|
||||
sx={{
|
||||
bgcolor: 'action.hover',
|
||||
'&:hover': { bgcolor: 'action.selected' }
|
||||
}}
|
||||
>
|
||||
<HiOutlineArrowLeft size={20} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Typography variant="h3" fontWeight={600}>
|
||||
Assign Orders
|
||||
</Typography>
|
||||
</Stack>
|
||||
|
||||
{/* <Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<IoReload />}
|
||||
onClick={() => {
|
||||
setIsLoading(true);
|
||||
createDeliveryMutation.mutate({ deliveries: reassignOrders });
|
||||
}}
|
||||
>
|
||||
Tuning
|
||||
</Button> */}
|
||||
<Autocomplete
|
||||
multiple
|
||||
id="checkboxes-tags-demo"
|
||||
options={tuningTypes}
|
||||
disableCloseOnSelect
|
||||
getOptionLabel={(option) => option.type}
|
||||
renderOption={(props, option, { selected }) => {
|
||||
const { id, ...optionProps } = props;
|
||||
const SelectionIcon = selected ? CheckBoxIcon : CheckBoxOutlineBlankIcon;
|
||||
|
||||
return (
|
||||
<li key={id} {...optionProps}>
|
||||
<SelectionIcon fontSize="small" style={{ marginRight: 8, padding: 9, boxSizing: 'content-box' }} />
|
||||
{option.type}
|
||||
</li>
|
||||
);
|
||||
}}
|
||||
sx={{ width: { xs: '100%', md: 400 } }}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
sx={{
|
||||
'& .MuiInputBase-input': {
|
||||
lineHeight: '1.5' // 👈 important
|
||||
}
|
||||
}}
|
||||
label="Hyper Tuning"
|
||||
// placeholder="Favorites"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{/* <Button
|
||||
variant="outlined"
|
||||
size="small"
|
||||
startIcon={<DownloadOutlinedIcon />}
|
||||
onClick={() => {
|
||||
exportToExcel(finaldeliveryList, 'users', 'UsersData');
|
||||
}}
|
||||
>
|
||||
Export Report
|
||||
</Button> */}
|
||||
<CSVExport
|
||||
data={csvExportData}
|
||||
filename={`Orders_Detail_${dayjs().format('YYYY-MM-DD_HHmmss')}.csv`}
|
||||
label=" CSV"
|
||||
style={{ m: 1 }}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack sx={{ my: 2 }}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={6} sm={6} md={3}>
|
||||
<HoverSocialCard
|
||||
secondary={metaData?.total_orders}
|
||||
primary={'Orders'}
|
||||
percentage={<DashboardFilled />}
|
||||
color={theme.palette.success.main}
|
||||
sx={{ cursor: 'pointer' }}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={6} sm={6} md={3}>
|
||||
<HoverSocialCard
|
||||
secondary={metaData?.utilized_riders}
|
||||
primary={'Riders'}
|
||||
percentage={<MdDirectionsBike />}
|
||||
color={theme.palette.warning.main}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={6} sm={6} md={3}>
|
||||
<HoverSocialCard
|
||||
secondary={zoneData?.length}
|
||||
primary={'Zones'}
|
||||
percentage={<FaMapLocationDot />}
|
||||
color={theme.palette.info.main}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={6} sm={6} md={3}>
|
||||
<HoverSocialCard
|
||||
secondary={metaData?.total_profit}
|
||||
primary={'Profit'}
|
||||
percentage={<GiProfit />}
|
||||
color={theme.palette.error.main}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Stack>
|
||||
<MainCard content={false}>
|
||||
{zoneData?.map((zone, index) => {
|
||||
const riders = zone?.riders.flatMap((rider) => rider);
|
||||
const orders = zone?.riders?.flatMap((rider) => rider.orders);
|
||||
|
||||
return (
|
||||
<Accordion key={index}>
|
||||
<AccordionSummary>
|
||||
<Stack direction="row" alignItems="center" spacing={2} sx={{ m: 2 }}>
|
||||
<Typography variant="h5" fontWeight={1000}>
|
||||
Zone {index + 1} :
|
||||
</Typography>
|
||||
<Chip label={zone.zone_name} color="primary" variant="light" size="small" sx={{ minWidth: 100 }} />
|
||||
<Tooltip title={`Orders`} placement="top">
|
||||
<Badge badgeContent={zone.total_orders} color="secondary">
|
||||
<DashboardOutlined style={{ fontSize: 20 }} />
|
||||
</Badge>
|
||||
</Tooltip>
|
||||
<Tooltip title={`Riders`} placement="top">
|
||||
<Badge color="secondary" badgeContent={zone.active_riders_count}>
|
||||
<DirectionsBikeOutlinedIcon style={{ fontSize: 20 }} />
|
||||
</Badge>
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails sx={{ p: { xs: 0, md: 1 } }}>
|
||||
{isMobile ? (
|
||||
<MobileCardList>
|
||||
{orders.map((val, i) => {
|
||||
const typeAccent =
|
||||
val.ordertype === 'Economy' ? '#10b981' : val.ordertype === 'Risky' ? '#ef4444' : '#C01227';
|
||||
return (
|
||||
<MobileCard key={i} accent={typeAccent}>
|
||||
<Stack direction="row" alignItems="center" justifyContent="space-between" spacing={1}>
|
||||
<Stack direction="row" alignItems="center" spacing={1} sx={{ minWidth: 0 }}>
|
||||
<Chip size="small" label={`#${i + 1}`} variant="light" color="primary" />
|
||||
<Typography variant="subtitle2" noWrap sx={{ minWidth: 0 }}>
|
||||
{`${val.locationname}-(${val.locationsuburb})`}
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Chip
|
||||
size="small"
|
||||
label={val.ordertype}
|
||||
icon={
|
||||
val.ordertype === 'Economy' ? (
|
||||
<EnergySavingsLeafIcon />
|
||||
) : val.ordertype === 'Risky' ? (
|
||||
<WarningIcon />
|
||||
) : (
|
||||
<BoltIcon />
|
||||
)
|
||||
}
|
||||
color={val.ordertype === 'Economy' ? 'success' : val.ordertype === 'Risky' ? 'error' : 'primary'}
|
||||
variant="light"
|
||||
/>
|
||||
</Stack>
|
||||
<MobileFieldGrid>
|
||||
<MobileField label="Order Id" value={val.orderid} />
|
||||
<MobileField label="Rider">
|
||||
<Typography sx={{ fontSize: 13, fontWeight: 600 }} noWrap>
|
||||
{val.rider}
|
||||
</Typography>
|
||||
<Typography variant="caption">ID : {val.userid}</Typography>
|
||||
</MobileField>
|
||||
<MobileField label="Pickup">
|
||||
<Stack spacing={0.25} sx={{ minWidth: 0 }}>
|
||||
<Typography variant="caption" noWrap>
|
||||
{val.pickupcustomer}
|
||||
</Typography>
|
||||
<Typography variant="caption" noWrap>
|
||||
{val.pickupcontactno}
|
||||
</Typography>
|
||||
<Tooltip title={val.pickupaddress}>
|
||||
<Typography variant="caption" noWrap sx={{ cursor: 'pointer' }}>
|
||||
{val.pickupsuburb || val.pickupaddress.slice(0, 20)}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
<Chip
|
||||
size="small"
|
||||
label={dayjs(val.pickupslot).format('DD/MM/YYYY hh:mm A')}
|
||||
variant="light"
|
||||
sx={{ color: '#0a803b', bgcolor: '#c3f3c7', alignSelf: 'flex-start' }}
|
||||
/>
|
||||
</Stack>
|
||||
</MobileField>
|
||||
<MobileField label="Delivery">
|
||||
<Stack spacing={0.25} sx={{ minWidth: 0 }}>
|
||||
<Typography variant="caption" noWrap>
|
||||
{val.deliverycustomer}
|
||||
</Typography>
|
||||
<Typography variant="caption" noWrap>
|
||||
{val.deliverycontactno}
|
||||
</Typography>
|
||||
<Tooltip title={val.deliveryaddress}>
|
||||
<Typography variant="caption" noWrap sx={{ cursor: 'pointer' }}>
|
||||
{val.deliverysuburb || val.deliveryaddress.slice(0, 20)}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
<Chip
|
||||
size="small"
|
||||
label={dayjs(val.expecteddeliverytime).format('DD/MM/YYYY hh:mm A')}
|
||||
variant="light"
|
||||
sx={{ color: '#DD2C00', background: '#FBE9E7', alignSelf: 'flex-start' }}
|
||||
/>
|
||||
</Stack>
|
||||
</MobileField>
|
||||
{val.ordernotes ? <MobileField full label="Notes" value={val.ordernotes} /> : null}
|
||||
<MobileField label="Profit">
|
||||
<Chip
|
||||
size="small"
|
||||
label={`₹ ${parseFloat(val?.profit).toFixed(2)}`}
|
||||
variant="light"
|
||||
sx={{ color: '#009688', bgcolor: '#b2dfdb' }}
|
||||
/>
|
||||
</MobileField>
|
||||
<MobileField label="Charges">
|
||||
<Chip
|
||||
size="small"
|
||||
label={`₹ ${val.deliverycharge.toFixed(2)} `}
|
||||
variant="light"
|
||||
sx={{ color: '#0074e7', bgcolor: '#cce3fa' }}
|
||||
/>
|
||||
</MobileField>
|
||||
<MobileField label="KMS">
|
||||
<Chip size="small" label={`${val.kms} km`} color="error" variant="light" />
|
||||
</MobileField>
|
||||
<MobileField label="Cumulative KMS">
|
||||
<Chip size="small" label={`${val.cumulativekms} km`} color="success" variant="light" />
|
||||
</MobileField>
|
||||
</MobileFieldGrid>
|
||||
</MobileCard>
|
||||
);
|
||||
})}
|
||||
</MobileCardList>
|
||||
) : (
|
||||
<TableContainer sx={{ p: 0, m: 0 }}>
|
||||
<Table stickyHeader>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>#</TableCell>
|
||||
{/* <TableCell>Tenant</TableCell> */}
|
||||
<TableCell>Order Location</TableCell>
|
||||
<TableCell>Pickup</TableCell>
|
||||
<TableCell>Delivery</TableCell>
|
||||
<TableCell>Notes</TableCell>
|
||||
<TableCell>Rider</TableCell>
|
||||
<TableCell align="center">Type</TableCell>
|
||||
<TableCell align="center">Profit</TableCell>
|
||||
<TableCell align="center">Charges</TableCell>
|
||||
<TableCell align="center">KMS</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
|
||||
<TableBody>
|
||||
{orders.map((val, i) => (
|
||||
<Fragment key={i}>
|
||||
<TableRow sx={{}}>
|
||||
<TableCell>
|
||||
<Typography> {i + 1}</Typography>
|
||||
</TableCell>
|
||||
{/* <TableCell>
|
||||
<Tooltip title={val.tenantaddress}>
|
||||
<Typography variant="body1" noWrap>
|
||||
{val.tenantname}
|
||||
</Typography>
|
||||
<Typography noWrap sx={{ fontSize: '11px' }}>
|
||||
{val.tenantsuburb}
|
||||
<br />
|
||||
</Typography>
|
||||
|
||||
<Typography noWrap variant="body2">
|
||||
{val.applocation}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
</TableCell> */}
|
||||
<TableCell align="left">
|
||||
<Tooltip title={val.locationaddress} placement="top">
|
||||
<Typography variant="body1" noWrap>
|
||||
{`${val.locationname}-(${val.locationsuburb})`}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
<Tooltip title="Order Id">
|
||||
<Typography variant="body2" noWrap>
|
||||
{val.orderid}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
<Stack display={'flex'} flexDirection={'row'} gap={3} sx={{ cursor: 'pointer' }}>
|
||||
<Tooltip title="Pickup Time">
|
||||
<Typography noWrap sx={{ fontSize: '12px' }}>
|
||||
{dayjs(val.pickupslot).format('DD/MM/YYYY')}
|
||||
</Typography>
|
||||
<Chip
|
||||
size="small"
|
||||
label={dayjs(val.pickupslot).format('hh:mm A')}
|
||||
variant="light"
|
||||
sx={{ color: '#0a803b', bgcolor: '#c3f3c7' }}
|
||||
/>
|
||||
</Tooltip>
|
||||
<ArrowRightAltOutlined />
|
||||
<Tooltip title="Estimated Delivery time">
|
||||
<Typography noWrap sx={{ fontSize: '12px' }}>
|
||||
{dayjs(val.expecteddeliverytime).format('DD/MM/YYYY')}
|
||||
</Typography>
|
||||
<Chip
|
||||
size="small"
|
||||
label={dayjs(val.expecteddeliverytime).format('hh:mm A')}
|
||||
variant="light"
|
||||
sx={{ color: '#DD2C00', background: '#FBE9E7' }}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
<Stack direction={'row'} spacing={1}>
|
||||
<Stack direction="column">
|
||||
<Typography variant="caption">{val.pickupcustomer}</Typography>
|
||||
<Typography variant="caption">{val.pickupcontactno}</Typography>
|
||||
<Tooltip title={val.pickupaddress}>
|
||||
<Typography sx={{ cursor: 'pointer' }} variant="caption">
|
||||
{val.pickupsuburb || val.pickupaddress.slice(0, 20)}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
<Stack direction={'row'} spacing={1}>
|
||||
<Stack direction="column">
|
||||
<Typography variant="caption">{val.deliverycustomer}</Typography>
|
||||
<Typography variant="caption">{val.deliverycontactno}</Typography>
|
||||
<Tooltip title={val.deliveryaddress}>
|
||||
<Typography sx={{ cursor: 'pointer' }} variant="caption">
|
||||
{val.deliverysuburb || val.deliveryaddress.slice(0, 20)}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
<Typography variant="caption" sx={{ whiteSpace: 'nowrap' }}>
|
||||
{val.ordernotes}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
|
||||
<TableCell align="left">
|
||||
<Typography variant="caption" sx={{ whiteSpace: 'nowrap' }}>
|
||||
{val.rider}
|
||||
</Typography>
|
||||
<br />
|
||||
<Typography variant="caption">ID : {val.userid}</Typography>
|
||||
</TableCell>
|
||||
|
||||
<TableCell align="center">
|
||||
<Chip
|
||||
size="small"
|
||||
label={val.ordertype}
|
||||
icon={
|
||||
val.ordertype === 'Economy' ? (
|
||||
<EnergySavingsLeafIcon />
|
||||
) : val.ordertype === 'Risky' ? (
|
||||
<WarningIcon />
|
||||
) : (
|
||||
<BoltIcon />
|
||||
)
|
||||
}
|
||||
color={val.ordertype === 'Economy' ? 'success' : val.ordertype === 'Risky' ? 'error' : 'primary'}
|
||||
variant="light"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
<Chip
|
||||
size="small"
|
||||
label={`₹ ${parseFloat(val?.profit).toFixed(2)}`}
|
||||
variant="light"
|
||||
sx={{ color: '#009688', bgcolor: '#b2dfdb' }}
|
||||
/>
|
||||
</TableCell>
|
||||
|
||||
<TableCell align="center">
|
||||
<Stack display={'flex'} flexDirection={'column'} gap={1} sx={{ cursor: 'pointer' }}>
|
||||
<Tooltip title="Charges" placement="top">
|
||||
<Chip
|
||||
size="small"
|
||||
label={`₹ ${val.deliverycharge.toFixed(2)} `}
|
||||
variant="light"
|
||||
sx={{ color: '#0074e7', bgcolor: '#cce3fa' }}
|
||||
/>
|
||||
</Tooltip>
|
||||
{/* <Tooltip title="Amount" placement="left">
|
||||
<Chip size="small" label={`₹ ${val.deliveryamt.toFixed(2)} `} color="success" variant="light" />
|
||||
</Tooltip> */}
|
||||
</Stack>
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
<Stack display={'flex'} flexDirection={'column'} gap={1} sx={{ cursor: 'pointer' }}>
|
||||
<Tooltip title="KMS" placement="top">
|
||||
<Chip size="small" label={`${val.kms} km`} color="error" variant="light" />
|
||||
</Tooltip>
|
||||
<Tooltip title="Cumulative Kms" placement="right">
|
||||
<Chip size="small" label={`${val.cumulativekms} km`} color="success" variant="light" />
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</Fragment>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
)}
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
);
|
||||
})}
|
||||
|
||||
<Divider />
|
||||
<Stack
|
||||
display={'flex'}
|
||||
flexDirection={{ xs: 'column', sm: 'row' }}
|
||||
gap={2}
|
||||
alignItems={{ xs: 'stretch', sm: 'center' }}
|
||||
justifyContent={'end'}
|
||||
sx={{ p: 2 }}
|
||||
>
|
||||
<Button
|
||||
sx={{ width: { xs: '100%', sm: 'auto' } }}
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
startIcon={<ArrowBackIcon />}
|
||||
onClick={() => {
|
||||
navigate('/doormile/orders');
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
<Button
|
||||
sx={{ my: { xs: 0, sm: 2 }, width: { xs: '100%', sm: 'auto' } }}
|
||||
variant="contained"
|
||||
disabled={aiMode === 0 && (!rider || !payment)}
|
||||
onClick={handleFinalCreateDelivery}
|
||||
>
|
||||
Assign Orders
|
||||
</Button>
|
||||
</Stack>
|
||||
</MainCard>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default OptimisedOrderPreview;
|
||||
@@ -67,37 +67,16 @@ import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import { fetchPercentageData, createAutomationDeliveries, getallriders, buildMilerLookup, notifyRider } from '../../api/api';
|
||||
import { getBookings, cancelBooking, getAdminCustomers, getBookingTrack, batchAssignBookings, getMilers } from 'pages/api/doormileApi';
|
||||
import { parseDoormileTimestamp } from 'utils/doormileTimestamp';
|
||||
import { DT, a, tint, soft, ring, edge } from 'themes/dt/tokens';
|
||||
|
||||
// ============================================================================
|
||||
// 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 dtTint = tint;
|
||||
const dtSoft = soft;
|
||||
const dtRing = ring;
|
||||
const dtEdge = edge;
|
||||
|
||||
const BRAND = '#C01227';
|
||||
const BRAND_LIGHT = '#D25463';
|
||||
const BRAND = '#000000';
|
||||
const BRAND_LIGHT = '#3A3A3A';
|
||||
|
||||
// Semantic per-row status palette, keyed by GET /admin/bookings' real `status`
|
||||
// enum (lowercased — StatusBadge lowercases before lookup). pending_pickup,
|
||||
@@ -455,7 +434,9 @@ const Orders = () => {
|
||||
}
|
||||
},
|
||||
{
|
||||
root: null,
|
||||
// MainLayout's AppShell scrolls content inside `.astryx-layout-content`
|
||||
// (height="fill"), not the window — root: null would never intersect.
|
||||
root: document.querySelector('.astryx-layout-content'),
|
||||
rootMargin: '0px 0px 400px 0px',
|
||||
threshold: 0
|
||||
}
|
||||
@@ -830,46 +811,51 @@ const Orders = () => {
|
||||
py: 0.5,
|
||||
flexShrink: 0,
|
||||
cursor: 'pointer',
|
||||
borderRadius: 999,
|
||||
border: `1.5px solid ${active ? t.color : edge(t.color)}`,
|
||||
bgcolor: active ? t.color : tint(t.color),
|
||||
color: active ? '#fff' : t.color,
|
||||
fontWeight: 700,
|
||||
boxShadow: active ? `0 6px 18px ${ring(t.color)}` : 'none',
|
||||
transition: 'all 0.18s',
|
||||
borderRadius: DT.radiusField + 'px',
|
||||
// Selected tab always shows the brand red, not the status's own
|
||||
// semantic color (pending=amber, delivered=emerald, etc.) — the
|
||||
// status color survives on the avatar below, which is where
|
||||
// operators actually read it. Shape/weight/hover match
|
||||
// deliveries.js, the design reference for every list page.
|
||||
border: `1px solid ${active ? BRAND : DT.borderSubtle}`,
|
||||
bgcolor: active ? BRAND : DT.surface,
|
||||
color: active ? '#fff' : DT.textSecondary,
|
||||
fontWeight: 600,
|
||||
boxShadow: 'none',
|
||||
transition: 'background-color 0.15s, border-color 0.15s, color 0.15s',
|
||||
'&:hover': {
|
||||
borderColor: t.color,
|
||||
boxShadow: active ? `0 6px 18px ${ring(t.color)}` : `0 0 0 3px ${ring(t.color)}`
|
||||
borderColor: active ? BRAND : DT.borderHover,
|
||||
bgcolor: active ? BRAND : DT.surfaceAlt
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Avatar
|
||||
sx={{
|
||||
width: { xs: 22, md: 26 },
|
||||
height: { xs: 22, md: 26 },
|
||||
width: { xs: 20, md: 22 },
|
||||
height: { xs: 20, md: 22 },
|
||||
bgcolor: active ? 'rgba(255,255,255,0.22)' : soft(t.color),
|
||||
color: active ? '#fff' : t.color
|
||||
}}
|
||||
>
|
||||
<Icon size={13} />
|
||||
<Icon size={12} />
|
||||
</Avatar>
|
||||
<Typography variant="caption" sx={{ fontWeight: 800, fontSize: { xs: 11.5, md: 13 }, lineHeight: 1 }}>
|
||||
<Typography variant="caption" sx={{ fontWeight: 600, fontSize: { xs: 11.5, md: 13 }, lineHeight: 1 }}>
|
||||
{t.label}
|
||||
</Typography>
|
||||
<Box
|
||||
sx={{
|
||||
minWidth: { xs: 22, md: 26 },
|
||||
height: { xs: 18, md: 22 },
|
||||
minWidth: { xs: 20, md: 24 },
|
||||
height: { xs: 18, md: 20 },
|
||||
px: 0.625,
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
borderRadius: 999,
|
||||
fontSize: { xs: 10, md: 11 },
|
||||
fontWeight: 800,
|
||||
bgcolor: active ? 'rgba(255,255,255,0.22)' : '#fff',
|
||||
color: active ? '#fff' : t.color,
|
||||
border: active ? 'none' : `1px solid ${edge(t.color)}`
|
||||
fontWeight: 700,
|
||||
bgcolor: active ? 'rgba(255,255,255,0.22)' : DT.surfaceAlt,
|
||||
color: active ? '#fff' : DT.textSecondary,
|
||||
border: 'none'
|
||||
}}
|
||||
>
|
||||
{count ?? 0}
|
||||
|
||||
Reference in New Issue
Block a user