Files
nearle_console/src/pages/nearle/deliveries/deliveries.js

1722 lines
66 KiB
JavaScript

import { enqueueSnackbar } from 'notistack';
import { DeleteFilled, EditOutlined } from '@ant-design/icons';
import { useState, useEffect, Fragment, useRef } from 'react';
import { Empty } from 'antd';
import dayjs from 'dayjs';
var utc = require('dayjs/plugin/utc');
dayjs.extend(utc);
import axios from 'axios';
import HoverSocialCard from 'components/cards/statistics/HoverSocialCard';
import { useTheme } from '@mui/material/styles';
import { PiMapPinLineDuotone } from 'react-icons/pi';
import { MdOutlineDateRange } from 'react-icons/md';
import { MdOutlineDeliveryDining } from 'react-icons/md';
import { useQuery, useMutation, useInfiniteQuery } from '@tanstack/react-query';
import {
Avatar,
Box,
Button,
Grid,
Tabs,
Tab,
IconButton,
Stack,
Chip,
Typography,
Table,
TableCell,
TableBody,
TableHead,
Collapse,
Dialog,
TableRow,
DialogContent,
DialogTitle,
Tooltip,
DialogActions,
Popper,
ClickAwayListener,
Checkbox,
Autocomplete,
TextField,
FormLabel,
TablePagination,
TableContainer,
Skeleton,
useMediaQuery,
Divider,
CircularProgress,
Backdrop,
MenuItem,
Menu
} from '@mui/material';
import MainCard from 'components/MainCard';
import {
MoreOutlined,
CloseOutlined
// NotificationOutlined
} from '@ant-design/icons';
import { PopupTransition } from 'components/@extended/Transitions';
import {
addDays,
addMonths,
addWeeks,
// addYears,
endOfMonth,
endOfWeek,
// endOfYear,
startOfMonth,
startOfWeek
// startOfYear,
} from 'date-fns';
import { DateRangePicker } from 'mui-daterange-picker';
import * as React from 'react';
import Loader from 'components/Loader';
import { KeyboardArrowDownOutlined, KeyboardArrowUpOutlined } from '@mui/icons-material';
import CircularLoader from 'components/CircularLoader';
import {
cancelDeliveryAPI,
changeRiderAPI,
fetchCountAPI,
fetchDeliveries,
fetchPercentageAPI,
fetchRidersList,
notifyRider,
updateDeliveryAPI,
getorderdetails,
gettenantlocations,
getTenants
} from 'pages/api/api';
import DebounceSearchBar from 'components/nearle_components/DebounceSearchBar';
import TitleCard from 'components/nearle_components/TitleCard';
import { OpenToast } from 'components/third-party/OpenToast';
import { OrdersTableSkeleton } from '../orders/OrdersTableSkeleton';
import LocationAutocomplete from 'components/nearle_components/LocationAutocomplete';
import LoaderWithImage from 'components/nearle_components/LoaderWithImage';
// ================================================= || deliveries (initial point)|| =================================================
const Deliveries = () => {
const userid = localStorage.getItem('userid');
const theme = useTheme();
const loadMoreRef = useRef();
const containerRef = useRef();
const [deliverylist, setDeliverylist] = useState([]);
const [dialogopen, setDialogopen] = useState(false);
const [locaName, setLocoName] = useState('All');
const [appId, setAppId] = useState(0);
const [startdate, setStartdate] = useState(dayjs().format('YYYY-MM-DD'));
const [enddate, setEnddate] = useState(dayjs().format('YYYY-MM-DD'));
const [tabstatus, setTabstatus] = useState('Pending');
const [tabvalue, setTabvalue] = useState(0);
const [open, setOpen] = useState(false);
const [datestatus, setDatestatus] = useState('Today');
const [kms, setKms] = useState('');
const [cumulativekms, setCumulativeKms] = useState();
const [deliveryamount, setDeliveryamount] = useState();
const [notes, setNotes] = useState('');
const [currentorder, setCurrentorder] = useState({});
const [deliverylat, setDeliverylat] = useState('');
const [deliverylong, setDeliverylong] = useState('');
const [currentStatus, setCurrentStatus] = useState('pending');
const locationRef = useRef(null);
const tenantRef = useRef(null);
const [page, setPage] = React.useState(0);
const [rowsPerPage, setRowsPerPage] = React.useState(50);
const [totalCount, setTotalCount] = React.useState();
const [productCollapse, setProductCollapse] = useState(null);
const [orderHeaderid, setOrderHeaderId] = useState(null);
const [searchword, setSearchword] = useState('');
const [debouncedSearch, setDebouncedSearch] = useState('');
const [menuAnchorEl, setMenuAnchorEl] = React.useState(null);
const [selectedRow, setSelectedRow] = useState(null);
const [loading1, setLoading1] = useState(false);
const [anchorEl, setAnchorEl] = React.useState(null);
const [open2, setOpen2] = useState('');
const [cancelDeliveryOpen, setCancelDeliveryOpen] = useState(false);
const [changeDialogOpen, setChangeDialogOpen] = useState(false);
const [cancelFeed, setCancelFeed] = useState('');
const [selectedRider, setSelectedRider] = useState(null);
const [tenantid, setTenantid] = useState(0);
const [locationid, setLocationid] = useState(0);
const [tenantValue, setTenantValue] = useState(null);
const [locationValue, setLocationValue] = useState(null);
const [riderid, setRiderid] = useState(0);
const roleid = localStorage.getItem('roleid');
useEffect(() => {
setTenantid(0);
setTenantValue(null);
setLocationid(0);
setLocationValue(null);
}, [appId]);
// to clear the location autocomplete
useEffect(() => {
setLocationid(0);
setLocationValue(null);
}, [tenantid]);
const menuOpen = Boolean(menuAnchorEl);
const handleMenuOpen = (event, row) => {
setSelectedRow(row);
console.log('selectedRow', row);
setMenuAnchorEl(event.currentTarget);
};
const handleMenuClose = () => {
setMenuAnchorEl(null);
};
// =========================================== || cancelDelivery || ===========================================
const { mutate: cancelDelivery } = useMutation({
mutationFn: ({ selectedRow, cancelFeed }) => cancelDeliveryAPI(selectedRow, cancelFeed),
onSuccess: () => {
opentoast('Delivery Cancelled Successfully', 'success');
setCancelDeliveryOpen(false);
fetchCountRefetch(); // Refresh count data
fetchDeliveriesRefetch(); // Refresh deliveries
},
onError: (error) => {
opentoast(error.message, 'error');
}
});
// ==============================|| cancelridernotification ||============================== //
const cancelridernotification = async () => {
console.log('cancelridernotification', selectedRow);
try {
const response = await axios.post(`${process.env.REACT_APP_URL}/utils/notifyuser`, {
token: selectedRow.userfcmtoken,
notification: {
title: 'NearleXpress',
body: `${selectedRow.orderid} have been Cancelled`,
sound: 'ring',
image: ''
},
data: {
type: 'cancel'
}
});
return response.data;
} catch (err) {
opentoast(err.message, 'error', 2000);
console.log(err);
}
};
// ==============================|| getTenants ||============================== //
const {
data: tenantlist,
isLoading: fetchtenantsIsLoading,
isError: fetchtenantsIsError,
error: fetchtenantsError
} = useQuery({
queryKey: ['tenantlist', appId],
queryFn: () => getTenants(appId), // Ensure appId is passed
enabled: appId !== 0 // Ensures query runs only when appId is valid
});
// ==============================|| gettenantlocations ||============================== //
const {
data: locationlist,
isLoading: fetchlocationsIsLoading,
isError: fetchlocationsIsError,
error: fetchlocationsError
} = useQuery({
queryKey: ['gettenantlocations', tenantid],
queryFn: () => gettenantlocations(tenantid), // Ensure appId is passed
enabled: tenantid !== 0 // Ensures query runs only when appId is valid
});
// =========================================== || notifyrider || ===========================================
const notifyRiderMutation = useMutation({
mutationFn: notifyRider, // Using the separate function
onSuccess: () => {
enqueueSnackbar('Notification sent Successfully', {
variant: 'success',
anchorOrigin: { vertical: 'top', horizontal: 'right' },
autoHideDuration: 2000
});
},
onError: (error) => {
enqueueSnackbar(error.message, {
variant: 'error',
anchorOrigin: { vertical: 'top', horizontal: 'right' },
autoHideDuration: 2000
});
}
});
// =========================================== || changerider || ===========================================
const changeRiderMutation = useMutation({
mutationFn: ({ selectedRider, selectedRow }) => changeRiderAPI(selectedRider, selectedRow),
onSuccess: (res) => {
setLoading1(false);
setChangeDialogOpen(false);
if (res.data.message === 'Success') {
opentoast('Rider Changed Successfully', 'success');
}
fetchCountRefetch(); // Refresh count data
fetchDeliveriesRefetch(); // Refresh deliveries
notifyRiderMutation.mutate(selectedRider.userfcmtoken);
},
onError: (err) => {
console.log(err);
opentoast(err.message, 'error');
setLoading1(false);
}
});
/* ============================================= || opentoast || ============================================= */
const opentoast = (message, variant) => {
enqueueSnackbar(message, {
variant,
anchorOrigin: { vertical: 'top', horizontal: 'right' },
autoHideDuration: 2000
});
};
// ==============================|| getorderdetails ||============================== //
const { data: orderdetails } = useQuery({
queryKey: ['orderdetails', orderHeaderid],
queryFn: () => getorderdetails(orderHeaderid),
enabled: !!orderHeaderid // ✅ prevent initial fetch when undefined
});
const dialogclose = () => {
setDialogopen(false);
};
const handleChangetab = (e, i) => {
setPage(0);
setTabvalue(i);
setRowsPerPage(50);
if (i === 0) {
setTabstatus('Pending');
setCurrentStatus('pending');
setTotalCount(countData?.uncoveredLength);
}
if (i === 1) {
setTabstatus('Assigned');
setCurrentStatus('accepted');
setTotalCount(countData?.assignedLength);
}
if (i === 2) {
setTabstatus('Arrived');
setCurrentStatus('arrived');
setTotalCount(countData?.arrivedLength);
}
if (i === 3) {
setTabstatus('Picked');
setCurrentStatus('picked');
setTotalCount(countData?.pickedLength);
}
if (i === 4) {
setTabstatus('Active');
setCurrentStatus('active');
setTotalCount(countData?.activeLength);
}
if (i === 5) {
setTabstatus('Skipped');
setCurrentStatus('skipped');
setTotalCount(countData?.skippedLength);
}
if (i === 6) {
setTabstatus('Delivered');
setCurrentStatus('delivered');
setTotalCount(countData?.coveredLength);
}
if (i === 7) {
setTabstatus('Cancelled');
setCurrentStatus('cancelled');
setTotalCount(countData?.cancelLength);
}
console.log(i);
setSearchword('');
};
const okclicked = () => {
setOpen(false);
};
/* ============================================= || fetchDeliveries | ============================================= */
const {
data: deliveriesData,
isLoading: fetchDeliveriesIsLoading,
isError: fetchDeliveriesIsError,
error: fetchDeliveriesError,
fetchNextPage,
hasNextPage,
isFetchingNextPage,
refetch: fetchDeliveriesRefetch
} = useInfiniteQuery({
queryKey: [
'fetchdeliveries',
appId,
userid,
currentStatus,
startdate,
enddate,
rowsPerPage,
debouncedSearch,
tenantid,
locationid,
riderid
],
queryFn: fetchDeliveries,
getNextPageParam: (lastPage) => lastPage.nextPage ?? undefined
});
const rows = deliveriesData?.pages.flatMap((page) => page.rows) || [];
useEffect(() => {
if (!hasNextPage) return;
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
fetchNextPage();
}
},
{
root: document.querySelector('.MuiTableContainer-root'), // 👈 or explicitly TableContainer
rootMargin: '0px',
threshold: 1.0
}
);
if (loadMoreRef.current) observer.observe(loadMoreRef.current);
return () => {
if (loadMoreRef.current) observer.unobserve(loadMoreRef.current);
};
}, [hasNextPage, fetchNextPage]);
const handleScroll = (event) => {
const { scrollTop, scrollHeight, clientHeight } = event.currentTarget;
if (scrollTop + clientHeight >= scrollHeight - 50) {
if (hasNextPage && !isFetchingNextPage) {
fetchNextPage();
}
}
};
/* ============================================= || fetchPercentageAPI | ============================================= */
const {
data: percentageData,
isLoading: fetchPercentageIsLoading,
isError: fetchPercentageIsError,
error: fetchPercentageError
} = useQuery({
queryKey: ['fetchpercentageaPI', appId],
queryFn: () => fetchPercentageAPI(appId)
});
useEffect(() => {
if (percentageData) {
console.log('percentageData', percentageData);
}
}, [percentageData]);
/* ============================================= || fetchcount | ============================================= */
const {
data: countData = {}, // Default to empty object
isLoading: fetchCountIsLoading,
isError: fetchCountIsError,
error: fetchCountError,
refetch: fetchCountRefetch
} = useQuery({
queryKey: ['fetchCountData', appId, userid, startdate, enddate, rowsPerPage, debouncedSearch, tenantid, locationid, riderid, tabstatus],
queryFn: () => fetchCountAPI(appId, userid, startdate, enddate, rowsPerPage, debouncedSearch, tenantid, locationid, riderid)
});
useEffect(() => {
console.log('countData', countData);
if (tabvalue === 0 && countData) {
setTotalCount(countData.uncoveredLength);
}
}, [countData]);
// ==============================|| fetchRidersList ||============================== //
const {
data: ridersList = [],
isLoading: riderListIsLoading,
isError: ridersListIsError,
error: ridersListError
} = useQuery({
queryKey: ['ridersList', appId], // Unique key for caching & re-fetching
queryFn: fetchRidersList,
enabled: Boolean(appId),
onError: (err) => {
OpenToast(err.message, 'error', 2000);
}
});
/* ============================================= || updatedelivery | ============================================= */
const updateDeliveryMutation = useMutation({
mutationFn: (orderData) => updateDeliveryAPI(orderData),
onSuccess: (res) => {
console.log(res);
if (res.data.status) {
opentoast('Updated Successfully', 'success');
setDeliveryamount('');
setNotes('');
setDialogopen(false);
fetchDeliveriesRefetch();
fetchCountRefetch();
}
},
onError: (err) => {
console.log(err);
opentoast(err.message, 'success');
}
});
const errorMessage = fetchDeliveriesIsError
? `Error fetching percentages: ${fetchDeliveriesError?.message}`
: fetchPercentageIsError
? `Error fetching percentages: ${fetchPercentageError?.message}`
: fetchCountIsError
? `Error fetching percentages: ${fetchCountError?.message}`
: ridersListIsError
? `Error fetching percentages: ${ridersListError?.message}`
: fetchtenantsIsError
? `Error tenant list: ${fetchtenantsError?.message}`
: fetchlocationsIsError
? `Error location list: ${fetchlocationsError?.message}`
: null;
if (errorMessage) {
console.log('errorMessage', errorMessage);
OpenToast(errorMessage, 'error', 2000);
return null; // or return <></> if inside a component
}
return (
<>
{(fetchCountIsLoading ||
fetchPercentageIsLoading ||
fetchDeliveriesIsLoading ||
fetchtenantsIsLoading ||
fetchlocationsIsLoading ||
riderListIsLoading) && (
<>
<Loader />
{/* <CircularLoader /> */}
</>
)}
{
<Backdrop
sx={{
color: '#fff',
zIndex: (theme) => theme.zIndex.drawer + 1
}}
open={
fetchCountIsLoading ||
fetchPercentageIsLoading ||
fetchDeliveriesIsLoading ||
fetchtenantsIsLoading ||
fetchlocationsIsLoading ||
riderListIsLoading
}
>
{/* <CircularLoader color="inherit" /> */}
</Backdrop>
}
{/* ============================================= || TitleCard | ============================================= */}
<TitleCard title={'Deliveries'}>
<LocationAutocomplete
ref={locationRef}
locaName={locaName}
setAppId={setAppId}
setLocoName={setLocoName}
setPage={setPage}
sx={{ width: { xs: '100%', custom450: 300 }, zIndex: '100' }}
/>
</TitleCard>
{/* ============================================= || hoverCard | ============================================= */}
<Grid container spacing={2} sx={{ mt: '1px' }}>
{[
{
label: 'Created orders',
value: percentageData?.uncoveredOrders,
percentage: percentageData?.percentage1,
color: theme.palette.info.main
},
{
label: 'Pending orders',
value: percentageData?.assignedOrders,
percentage: percentageData?.percentage2,
color: theme.palette.warning.main
},
{
label: 'Delivered orders',
value: percentageData?.pickedOrders,
percentage: percentageData?.percentage3,
color: theme.palette.success.main
},
{
label: 'Cancelled Orders',
value: percentageData?.coveredOrders,
percentage: percentageData?.percentage4,
color: theme.palette.error.main
}
].map((item, index) => (
<Grid item key={index} xs={12} custom400={6} sm={3} sx={{ cursor: 'pointer' }}>
<HoverSocialCard
primary={item.label}
secondary={fetchPercentageIsLoading ? <Skeleton sx={{ width: '30px' }} animation="wave" /> : item.value}
percentage={item.percentage?.toString()}
color={item.color}
/>
</Grid>
))}
</Grid>
{/* ============================================= || orderFilter | ============================================= */}
<Stack direction="row" justifyContent="space-between" alignItems="center" gap={3} sx={{ flexWrap: 'wrap', my: 2 }}>
{startdate && enddate ? (
<Stack
direction="row"
flexWrap="wrap" // ✅ allow wrapping
gap={1.5} // ✅ space between items when wrapped
alignItems="center" // optional, for vertical alignment
>
<Chip
avatar={
<Avatar sx={{ backgroundColor: 'transparent' }}>
<MdOutlineDeliveryDining fontSize="30px" style={{ color: 'red' }} />
</Avatar>
}
label={`Deliveries-${datestatus}`}
color="error"
variant="combined"
/>
<Chip
avatar={
<Avatar sx={{ backgroundColor: 'transparent' }}>
<MdOutlineDateRange fontSize="30px" style={{ color: '#fbc02d' }} />
</Avatar>
}
label={
<Typography noWrap color="secondary">
{dayjs(startdate).format('DD/MM/YYYY')} - {dayjs(enddate).format('DD/MM/YYYY')}
</Typography>
}
onClick={() => setOpen(true)}
variant="combined"
color="warning"
sx={{ maxWidth: '100%', cursor: 'pointer' }} // to avoid overflow
/>
<Chip
avatar={
<Avatar sx={{ backgroundColor: 'transparent' }}>
<PiMapPinLineDuotone fontSize="30px" style={{ color: '#00bcd4' }} />
</Avatar>
}
label={locaName}
color="info"
variant="combined"
sx={{ maxWidth: '100%' }}
/>
</Stack>
) : (
<Chip label="Orders-All" color="primary" variant="light" size="small" />
)}
<Autocomplete
disablePortal
options={tenantlist || []}
value={tenantValue}
sx={{ minWidth: 200, flex: 1 }}
onOpen={(event) => {
if (!appId) {
event.preventDefault();
OpenToast('Please select a your location first!', 'warning', 3000);
setTimeout(() => {
locationRef.current?.focus();
}, 0);
}
}}
onChange={(e, val, reason) => {
if (reason === 'clear') {
setTenantid(0);
setTenantValue(null);
setLocationid(0);
setLocationValue(null);
} else {
setTenantid(val?.tenantid || 0);
setTenantValue(val);
setLocationid(0);
setLocationValue(null);
}
}}
renderInput={(params) => <TextField {...params} inputRef={tenantRef} label="Select Tenant" />}
/>
<Autocomplete
disablePortal
options={locationlist || []}
getOptionLabel={(option) => `${option.locationname} (${option.suburb})` || ''}
value={locationValue}
sx={{ minWidth: 200, flex: 1 }}
onOpen={(event) => {
if (!appId && !tenantid) {
event.preventDefault();
OpenToast('Please select a your Location and Tenant first!', 'warning', 3000);
setTimeout(() => {
locationRef.current?.focus();
}, 0);
} else if (!tenantid) {
event.preventDefault();
OpenToast('Please select a your Tenant first!', 'warning', 3000);
setTimeout(() => {
tenantRef.current?.focus();
}, 0);
}
}}
onChange={(e, val, reason) => {
if (reason === 'clear') {
setLocationid(0);
setLocationValue(null);
} else {
setLocationid(val.locationid || 0);
setLocationValue(val);
}
}}
renderInput={(params) => <TextField {...params} label="Select Location" />}
/>
<Autocomplete
sx={{ minWidth: 200, flex: 1 }}
fullWidth
disabled={riderListIsLoading}
options={ridersList}
getOptionLabel={(option) => `${option.firstname} ${option.lastname} (${option.contactno})`}
renderInput={(params) => <TextField {...params} label="Choose Rider" />}
onChange={(e, value, reason) => {
if (reason === 'clear') {
setRiderid(0);
} else {
setRiderid(value.userid);
console.log('selected rider', value);
}
}}
onOpen={(event) => {
if (!appId) {
event.preventDefault();
OpenToast('Please select a your location first!', 'warning', 3000);
setTimeout(() => {
locationRef.current?.focus();
}, 0);
}
}}
/>
</Stack>
{/* ============================================= || Tabs || ============================================= */}
<Stack
display={'flex'}
flexDirection={'row'}
justifyContent={'space-between'}
alignItems={'center'}
flexWrap={'wrap-reverse'}
gap={2}
sx={{
border: '1px solid ',
borderBottom: 0,
borderColor: 'bg.main',
p: 1.5
}}
>
<Tabs
value={tabvalue}
onChange={handleChangetab}
variant="scrollable"
// eslint-disable-next-line react-hooks/rules-of-hooks
scrollButtons={useMediaQuery(theme.breakpoints.down('custom1000')) ? true : false}
allowScrollButtonsMobile
>
<Tab
label="Assigned"
icon={
<Chip
label={countData?.uncoveredLength || 0}
color="primary"
variant="light"
size="small"
sx={{ minWidth: 40, justifyContent: 'center' }}
/>
}
iconPosition="end"
/>
<Tab
label="Accepted"
icon={
<Chip
label={countData?.assignedLength || 0}
color="primary"
variant="light"
size="small"
sx={{ minWidth: 40, justifyContent: 'center' }}
/>
}
iconPosition="end"
/>
<Tab
label="Arrived"
icon={
<Chip
label={countData?.arrivedLength || 0}
color="primary"
variant="light"
size="small"
sx={{ minWidth: 40, justifyContent: 'center' }}
/>
}
iconPosition="end"
/>
<Tab
label="Picked"
icon={
<Chip
label={countData?.pickedLength || 0}
color="primary"
variant="light"
size="small"
sx={{ minWidth: 40, justifyContent: 'center' }}
/>
}
iconPosition="end"
/>
<Tab
label="Active"
icon={
<Chip
label={countData?.activeLength || 0}
color="primary"
variant="light"
size="small"
sx={{ minWidth: 40, justifyContent: 'center' }}
/>
}
iconPosition="end"
/>
<Tab
label="Skipped"
icon={
<Chip
label={countData?.skippedLength || 0}
color="primary"
variant="light"
size="small"
sx={{ minWidth: 40, justifyContent: 'center' }}
/>
}
iconPosition="end"
/>
<Tab
label="Delivered"
icon={
<Chip
label={countData?.coveredLength || 0}
color="primary"
variant="light"
size="small"
sx={{ minWidth: 40, justifyContent: 'center' }}
/>
}
iconPosition="end"
/>
<Tab
label="Cancelled"
icon={
<Chip
label={countData?.cancelLength || 0}
color="primary"
variant="light"
size="small"
sx={{ minWidth: 40, justifyContent: 'center' }}
/>
}
iconPosition="end"
/>
</Tabs>
{/* ============================================= || searchOutlined | ============================================= */}
<DebounceSearchBar
value={searchword}
onChange={setSearchword}
onDebouncedChange={setDebouncedSearch}
sx={{ m: 0, width: 280, flex: 1 }}
/>
</Stack>
{/* ============================================= || MainCard || ============================================= */}
<MainCard content={false}>
<TableContainer
ref={containerRef}
onScroll={handleScroll}
sx={{
maxHeight: 'calc(100vh - 190px)',
overflow: 'auto',
overflowX: 'auto',
'&::-webkit-scrollbar': {
width: '12px', // scroll bar width
cursor: 'pointer'
},
'&::-webkit-scrollbar-thumb': {
backgroundColor: theme.palette.primary.main, // thumb color
borderRadius: '8px',
cursor: 'pointer'
},
'&::-webkit-scrollbar-thumb:hover': {
backgroundColor: theme.palette.primary.dark, // hover color
cursor: 'pointer'
},
'&::-webkit-scrollbar-track': {
backgroundColor: theme.palette.primary.lighter,
cursor: 'pointer'
}
}}
>
<Table stickyHeader sx={{ minWidth: 1400 }}>
<TableHead>
<TableRow>
{tabstatus == 'Created' && (
<TableCell sx={{ whiteSpace: 'nowrap' }}>
<Checkbox
indeterminate={deliverylist.length > 0 && deliverylist.length != rows.length}
onChange={(e) => {
if (e.target.checked) {
setDeliverylist([...rows]);
} else {
setDeliverylist([]);
}
}}
checked={deliverylist.length == rows.length}
/>
</TableCell>
)}
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>S.No </TableCell>
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Tenant </TableCell>
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>
Order Location{' '}
</TableCell>
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Pickup </TableCell>
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Drop </TableCell>
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Rider </TableCell>
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Est. Delivery Time</TableCell>
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Transit</TableCell>
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}> Kms</TableCell>
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Amount </TableCell>
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Notes </TableCell>
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Steps</TableCell>
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>Qty</TableCell>
<TableCell sx={{ position: 'sticky !important', backgroundColor: theme.palette.secondary.light, whiteSpace: 'nowrap', border: 'none' }}>COD </TableCell>
{tabstatus !== 'Cancelled' && tabstatus !== 'Delivered' && (
<TableCell
align="right"
sx={{
position: 'sticky !important',
backgroundColor: theme.palette.secondary.light,
whiteSpace: 'nowrap',
border: 'none'
}}
>
Action
</TableCell>
)}
</TableRow>
</TableHead>
{(loading1 || fetchDeliveriesIsLoading) && <OrdersTableSkeleton col={8} />}
<TableBody>
{rows.length == 0 && !loading1 && (
<>
<TableCell colSpan={14}>
{/* <Stack width={'100%'} direction={'row'} justifyContent={'center'}> */}
<Empty description={`No ${tabstatus} Orders`} styles={{ description: { color: theme.palette.error.main } }} />
</TableCell>
</>
)}
{rows.map((row, index) => {
return (
<>
<TableRow
role="checkbox"
tabIndex={-1}
key={row.tenantname}
sx={{
cursor: 'pointer',
backgroundColor: deliverylist.find((res1) => res1.orderheaderid == row.orderheaderid) ? '#e1bee7' : '',
'&:hover': {
backgroundColor: deliverylist.find((res1) => res1.orderheaderid == row.orderheaderid) ? '#e1bee7 !important' : ''
}
}}
>
{tabstatus == 'Created' && (
<TableCell>
<Checkbox
onChange={(e) => {
if (e.target.checked) {
let arr = deliverylist;
arr.push({ ...row, sno: deliverylist.length + 1 });
setDeliverylist([...arr]);
} else {
let res = deliverylist.find((res1) => res1.orderheaderid == row.orderheaderid);
if (res) {
let arr = deliverylist;
let res = deliverylist.find((res1) => res1.orderheaderid == row.orderheaderid);
arr.splice(res.sno - 1, 1);
arr.map((val, i) => {
val.sno = i + 1;
});
setDeliverylist([...arr]);
}
}
console.log('list', deliverylist);
}}
checked={deliverylist.find((res1) => res1.orderheaderid == row.orderheaderid)}
/>
</TableCell>
)}
<TableCell>
{/* <Typography> {row.sno}</Typography> */}
<Typography> {page * rowsPerPage + index + 1}</Typography>
</TableCell>
{/* Tenants */}
<TableCell>
<Tooltip title={row.tenantadress}>
<Typography noWrap variant="subtitle1">
{row.tenantname}
</Typography>
<Typography noWrap variant="body2">
{row.tenantsuburb}
</Typography>
<Typography noWrap variant="body2">
{row.applocation}
</Typography>
</Tooltip>
</TableCell>
{/* order details */}
<TableCell align="left">
<Tooltip title="Location Name-Suburb" placement="top">
<Typography variant="subtitle1" noWrap>
{`${row.locationname}-(${row.locationsuburb})`}
</Typography>
</Tooltip>
<Stack display={'flex'} flexDirection={'row'} gap={3}>
<Stack>
<Tooltip title="Order Id" placement="top">
<Typography variant="body2" noWrap>
{row.orderid}
</Typography>
</Tooltip>
<Tooltip title="Ordered date" placement="top">
<Typography noWrap sx={{ fontSize: '12px' }}>
{dayjs(row.orderdate).utc().format('DD/MM/YYYY')}
</Typography>
<Typography noWrap sx={{ fontSize: '11px' }}>
{dayjs(row.orderdate).utc().format('hh:mm A')}
</Typography>
</Tooltip>
</Stack>
-
<Stack>
<Tooltip title="Delivery Id" placement="top">
<Typography variant="body2" noWrap>
{row.deliveryid}
</Typography>
</Tooltip>
<Tooltip title="Delivery date" placement="top">
<Typography noWrap sx={{ fontSize: '12px' }}>
{dayjs(row.deliverydate).utc().format('DD/MM/YYYY')}
</Typography>
<Typography noWrap sx={{ fontSize: '11px' }}>
{dayjs(row.deliverydate).utc().format('hh:mm A')}
</Typography>
</Tooltip>
</Stack>
</Stack>
</TableCell>
{/* pickup */}
<TableCell align="left">
<Stack direction={'row'} spacing={1}>
<Stack direction="column">
<Typography variant="subtitle1" sx={{ whiteSpace: 'nowrap' }}>
{row.pickupcustomer}
</Typography>
<Typography variant="body2">{row.pickupcontactno}</Typography>
<Tooltip title={row.Pickupaddress} sx={{ whiteSpace: 'nowrap' }}>
<Typography variant="body2">{row.pickuplocation || row.Pickupaddress.slice(0, 12) + '...'}</Typography>
</Tooltip>
</Stack>
</Stack>
</TableCell>
{/* drop */}
<TableCell align="left">
<Stack direction={'row'} spacing={1}>
<Stack direction="column">
<Typography variant="subtitle1" sx={{ whiteSpace: 'nowrap' }}>
{row.deliverycustomer}
</Typography>
<Typography variant="body2">{row.deliverycontactno}</Typography>
<Tooltip title={row.deliveryaddress}>
<Typography variant="body2" sx={{ whiteSpace: 'nowrap' }}>
{`${row.deliverylocation || row.deliveryaddress.slice(0, 12) + '...'}`}
</Typography>
</Tooltip>
</Stack>
</Stack>
</TableCell>
{/* rider */}
<TableCell>
<Typography variant="subtitle1" noWrap>
{row.ridername}
</Typography>
<Typography variant="subtitle2"> {`ID: ${row.userid}`}</Typography>
<Typography variant="subtitle2"> {row.ridercontact}</Typography>
</TableCell>
{/* Estimated Delivery Time */}
<TableCell align="left">
<Typography variant="subtitle1" noWrap>
{row.expecteddeliverytime ? dayjs(row.expecteddeliverytime).format('hh:mm A') : 'N/A'}
</Typography>
</TableCell>
{/* Transit Minutes */}
<TableCell align="left">
<Typography variant="subtitle1" noWrap>
{row.transitminutes || 0} min
</Typography>
</TableCell>
{/* kms */}
<TableCell>
<Stack direction={'column'} spacing={1}>
<Tooltip title=" KMS" placement="top">
<Chip label={row.kms || 0} size="small" variant="light" color="error" />
</Tooltip>
<Tooltip title="Actual KMS">
<Chip label={row.cumulativekms || 0} size="small" color="success" variant="light" />
</Tooltip>
</Stack>
</TableCell>
{/* amount */}
<TableCell align="left">
<Stack direction={'column'} spacing={1}>
<Tooltip title=" Delivery Charge" placement="top">
<Chip label={`${row.deliverycharges?.toFixed(2)}` || 0} size="small" variant="light" color="error" />
</Tooltip>
<Tooltip title="Delivery Amount">
<Chip label={`${row.deliveryamt?.toFixed(2)}` || 0} size="small" color="success" variant="light" />
</Tooltip>
</Stack>
</TableCell>
{/* notes */}
<TableCell>
<Typography>{row.notes}</Typography>
</TableCell>
{/* step */}
<TableCell align="center">
{row.step ? (
<Chip
label={row.step}
size="small"
color="primary"
variant="light"
sx={{ fontWeight: 700, minWidth: 28 }}
/>
) : (
<Typography variant="subtitle2" color="text.disabled">
</Typography>
)}
</TableCell>
{/* qty */}
<TableCell>
{row.Quantity ? (
<Typography variant="subtitle1" color={'error'} sx={{ whiteSpace: 'nowrap' }}>
{row.Quantity}
</Typography>
) : (
<Typography variant="subtitle1" sx={{ whiteSpace: 'nowrap' }}>
{' '}
{row.Quantity}
</Typography>
)}
</TableCell>
{/* {cash} */}
<TableCell>
{row.collectionamt ? (
<Typography variant="subtitle1" color={'error'} sx={{ whiteSpace: 'nowrap' }}>
{' '}
{`${row.collectionamt.toFixed(2)}`}{' '}
</Typography>
) : (
<Typography variant="subtitle1" sx={{ whiteSpace: 'nowrap' }}>
{' '}
{`${row.collectionamt.toFixed(2)}`}{' '}
</Typography>
)}
</TableCell>
{/* Action */}
{tabstatus !== 'Cancelled' && tabstatus !== 'Delivered' && (
<TableCell>
<Stack display={'flex'} flexDirection={'row'} justifyContent={'end'}>
{row.deliverytype == 'C' && (
<Tooltip title="Product details" placement="top">
<IconButton
color="primary"
onClick={() => {
if (productCollapse?.orderid === row.orderid) {
setProductCollapse(null); // Collapse if already open
setOrderHeaderId(null);
} else {
setProductCollapse(row); // Open if different
setOrderHeaderId(row.orderheaderid); // Open if different
}
}}
>
{productCollapse?.orderid === row.orderid ? <KeyboardArrowUpOutlined /> : <KeyboardArrowDownOutlined />}
</IconButton>
</Tooltip>
)}
<IconButton
color="primary"
size="small"
sx={{ bgcolor: 'primary.100' }}
onClick={(e) => handleMenuOpen(e, row)}
>
<EditOutlined />
</IconButton>
<Menu
anchorEl={menuAnchorEl}
open={menuOpen}
onClose={handleMenuClose}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'right'
}}
transformOrigin={{
vertical: 'top',
horizontal: 'right'
}}
PaperProps={{
elevation: 4,
sx: {
minWidth: 200,
borderRadius: 1
}
}}
>
{selectedRow?.orderstatus !== 'delivered' && (
<MenuItem
onClick={() => {
notifyRiderMutation.mutate(selectedRow.userfcmtoken);
handleMenuClose();
}}
>
Notify Rider
</MenuItem>
)}
{['pending', 'accepted', 'arrived'].includes(selectedRow?.orderstatus) && (
<MenuItem
onClick={() => {
if (!appId) {
opentoast('Please select a location first!', 'warning');
locationRef.current?.focus();
return;
}
setChangeDialogOpen(true);
handleMenuClose();
}}
>
Change Rider
</MenuItem>
)}
{(roleid == 1 || roleid == 2) && (
<MenuItem
onClick={() => {
setKms(selectedRow.kms);
setCumulativeKms(selectedRow.cumulativekms);
setDeliverylat(selectedRow.droplat);
setDeliverylong(selectedRow.droplon);
setNotes(selectedRow.notes);
setDeliveryamount(selectedRow.deliveryamount);
setCurrentorder(selectedRow);
setDialogopen(true);
handleMenuClose();
}}
>
Update Delivery Status
</MenuItem>
)}
{selectedRow?.orderstatus !== 'cancelled' && selectedRow?.orderstatus !== 'delivered' && (
<MenuItem
sx={{ color: 'error.main' }}
onClick={() => {
setCancelDeliveryOpen(true);
handleMenuClose();
}}
>
Cancel Delivery
</MenuItem>
)}
</Menu>
</Stack>
</TableCell>
)}
</TableRow>
{productCollapse?.orderid === row?.orderid && (
<TableRow>
<TableCell
colSpan={11}
sx={{
p: 0,
border: 0,
'&:hover': {
backgroundColor: 'white' // or use 'inherit'
}
}}
>
<Collapse in={true} timeout="auto" unmountOnExit>
<Box
sx={{
width: '100%',
px: 2,
py: 2
}}
>
<Table size="small" sx={{ minWidth: 800 }}>
<TableHead>
<TableRow
sx={{
'&:hover': {
backgroundColor: 'transparent !important'
}
}}
>
<TableCell sx={{ fontWeight: 600 }}>S.No</TableCell>
<TableCell sx={{ fontWeight: 600 }}>Product Name</TableCell>
<TableCell sx={{ fontWeight: 600 }}>Description</TableCell>
<TableCell align="right" sx={{ fontWeight: 600 }}>
Quantity
</TableCell>
<TableCell align="right" sx={{ fontWeight: 600 }}>
Cost
</TableCell>
<TableCell align="right" sx={{ fontWeight: 600 }}>
Price
</TableCell>
<TableCell align="right" sx={{ fontWeight: 600 }}>
Tax
</TableCell>
<TableCell align="right" sx={{ fontWeight: 600 }}>
Amount
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{orderdetails?.details?.map((product, index) => (
<TableRow
key={index}
sx={{
'&:hover': {
backgroundColor: 'transparent !important'
}
}}
>
<TableCell>{index + 1}</TableCell>
<TableCell>
<Stack direction="row" spacing={1} alignItems="center">
<img
src={product?.productimage || 'https://via.placeholder.com/40'} // fallback image
alt={product?.productname}
style={{
width: 40,
height: 40,
objectFit: 'cover',
borderRadius: 4
}}
/>
<Typography variant="body2" noWrap>
{product?.productname || 'Unnamed'}
</Typography>
</Stack>
</TableCell>
<TableCell>{product?.productdescription || '-'}</TableCell>
<TableCell align="right">{product?.orderqty || 0}</TableCell>
<TableCell align="right"> {product?.price || 0}</TableCell>
<TableCell align="right"> {(product?.productsumprice ?? 0).toFixed(2)}</TableCell>
<TableCell align="right"> {(product?.taxamount ?? 0).toFixed(2)}</TableCell>
<TableCell align="right">
{(product?.productsumprice + product?.taxamount).toFixed(2) || 0}
</TableCell>
</TableRow>
))}
<TableRow
sx={{
'&:hover': {
backgroundColor: 'transparent !important'
}
}}
>
<TableCell align="right" colSpan={7} sx={{}}>
Total Amount :
</TableCell>
<TableCell align="right" sx={{}}>
{orderdetails?.pricedetails?.orderamount.toFixed(2)}
</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>
)}
</>
);
})}
{rows?.length != 0 && (
<TableRow>
<TableCell colSpan={15} rowSpan={3}>
<div ref={loadMoreRef} style={{ height: 40, textAlign: 'center' }}>
{isFetchingNextPage ? <LoaderWithImage /> : hasNextPage ? <LoaderWithImage /> : 'No More Deliveries'}
</div>
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</TableContainer>
</MainCard>
{/* =============================== || cancel dialog || =============================== */}
<Dialog open={cancelDeliveryOpen} onClose={() => setCancelDeliveryOpen(false)} maxWidth="xs">
<DialogContent sx={{ mt: 2, my: 1 }}>
<Stack alignItems="center" spacing={3.5}>
<Avatar color="error" sx={{ width: 72, height: 72, fontSize: '1.75rem' }}>
<DeleteFilled />
</Avatar>
<Stack spacing={2}>
<Typography variant="h5" align="center">
Are you sure you want to cancel this delivery?
</Typography>
</Stack>
<TextField
fullWidth
label="Enter Feedback"
multiline
maxRows={4}
onChange={(e) => {
setCancelFeed(e.target.value);
}}
/>
<Stack direction="row" spacing={2} sx={{ width: 1 }}>
<Button
// disabled={cancelFeed == '' ? true : false}
fullWidth
color="error"
variant="contained"
onClick={() => {
{
cancelFeed == '' ? opentoast('Enter FeedBack', 'error') : cancelDelivery({ selectedRow, cancelFeed });
}
cancelridernotification();
}}
autoFocus
sx={{ border: '1px solid red' }}
>
Yes, Cancel
</Button>
<Button
fullWidth
onClick={() => {
setCancelDeliveryOpen(false);
}}
color="secondary"
variant="outlined"
>
No
</Button>
</Stack>
</Stack>
</DialogContent>
</Dialog>
{/* =============================== || change dialog || =============================== */}
<Dialog
open={changeDialogOpen}
onClose={() => setChangeDialogOpen(false)}
maxWidth="sm"
fullWidth
TransitionComponent={PopupTransition}
>
<DialogTitle sx={{ bgcolor: theme.palette.primary.main }}>
<Typography variant="h3" sx={{ color: 'white' }}>
Change Rider
</Typography>
</DialogTitle>
<DialogContent dividers>
<Grid container spacing={2}>
<Grid item xs={12} sx={{ m: 2 }}>
<Autocomplete
fullWidth
options={ridersList}
// getOptionLabel={(option) => `${option.firstname} ${option.lastname} | ${option.contactno}`}
renderInput={(params) => <TextField {...params} label="Choose Rider" />}
onChange={(e, value) => {
setSelectedRider(value);
console.log('selected rider', value);
}}
/>
</Grid>
</Grid>
</DialogContent>
<DialogActions>
<Stack direction={'row'} spacing={3}>
<Button
variant="outlined"
color="secondary"
onClick={() => {
setChangeDialogOpen(false);
}}
>
Cancel
</Button>
<Button
variant="contained"
color="primary"
onClick={() => {
setLoading1(true);
changeRiderMutation.mutate({ selectedRider, selectedRow });
}}
>
Change Rider
</Button>
</Stack>
</DialogActions>
</Dialog>
{/* =============================== || Date filter Dialog || =============================== */}
<Dialog open={open}>
<DialogTitle align="left">
<Typography variant="h4">Select Filter Options</Typography>
</DialogTitle>
<DialogContent sx={{ width: '100%' }} className="datedialog">
<DateRangePicker
open={open}
toggle={() => setOpen(!open)}
id="daterange1"
onChange={(range) => {
if (range.label === 'All') {
setStartdate('');
setEnddate('');
setOpen(false);
} else {
setStartdate(dayjs(range.startDate).format('YYYY-MM-DD'));
setEnddate(dayjs(range.endDate).format('YYYY-MM-DD'));
if (range.label) {
setDatestatus(range.label);
} else {
setDatestatus('');
}
}
console.log(range);
}}
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" sx={{ width: '100%', p: 2 }}>
<Button variant="contained" size="small" onClick={okclicked}>
ok
</Button>
</Stack>
</Dialog>
{/* =============================== || Update Delivery Dialog || =============================== */}
<Dialog fullWidth={true} open={dialogopen} onClose={dialogclose} scroll={'paper'} maxWidth="sm" TransitionComponent={PopupTransition}>
<DialogTitle
sx={{
bgcolor: '#662582',
color: '#fff'
}}
>
Update Delivery Status
</DialogTitle>
<DialogContent dividers={true}>
<MainCard sx={{ height: '100%' }}>
<Grid container spacing={2.5}>
<Grid item xs={12} sm={6}>
<FormLabel>Kms</FormLabel>
<TextField
fullWidth
value={kms}
type="number"
onChange={(e) => {
setKms(e.target.value);
console.log(e);
}}
/>
</Grid>
<Grid item xs={12} sm={6}>
<FormLabel>Actual Kms</FormLabel>
<TextField value={cumulativekms} type="number" onChange={(e) => setCumulativeKms(+e.target.value)} fullWidth />
</Grid>
<Grid item xs={12} sm={6}>
<FormLabel>Delivery lat</FormLabel>
<TextField
fullWidth
type="number"
value={deliverylat}
onChange={(e) => {
setDeliverylat(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} sm={6}>
<FormLabel>Delivery Long</FormLabel>
<TextField
value={deliverylong}
type="number"
onChange={(e) => {
setDeliverylong(e.target.value);
}}
fullWidth
/>
</Grid>
<Grid item xs={12}>
<FormLabel>Amount</FormLabel>
<TextField fullWidth type="number" value={deliveryamount} onChange={(e) => setDeliveryamount(+e.target.value)} />
</Grid>
<Grid item xs={12}>
<FormLabel>Notes</FormLabel>
<TextField value={notes} fullWidth onChange={(e) => setNotes(e.target.value)} />
</Grid>
</Grid>
</MainCard>
</DialogContent>
<DialogActions>
<Grid container>
<Grid item xs={12}>
<Stack direction={'row'} justifyContent={'flex-end'} spacing={2} sx={{ p: 2 }}>
<Button
variant="contained"
onClick={() => {
dialogclose();
}}
color="error"
>
Close
</Button>{' '}
<Button
variant="contained"
onClick={() => {
if (!kms) {
opentoast('Fill Kms', 'warning');
} else if (!cumulativekms) {
opentoast('Fill Actual Kms', 'warning');
} else if (!deliverylat) {
opentoast('Fill Delivery Latitude', 'warning');
} else if (!deliverylong) {
opentoast('Fill Delivery Longitude', 'warning');
} else if (!deliveryamount) {
opentoast('Fill Delivery Amount', 'warning');
} else {
updateDeliveryMutation.mutate({
deliveryid: currentorder.deliveryid,
orderheaderid: currentorder.orderheaderid,
orderstatus: 'delivered',
deliverytime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
deliverylat,
deliverylong,
kms,
cumulativekms,
deliveryamt: parseFloat(deliveryamount),
notes,
userid: +selectedRow.userid
});
}
}}
>
Update
</Button>
</Stack>
</Grid>
</Grid>
</DialogActions>
</Dialog>
</>
);
};
export default Deliveries;