reports update

This commit is contained in:
joshikannan
2025-11-14 18:42:26 +05:30
parent b27c27a444
commit 12df2e9dc4
15 changed files with 2159 additions and 633 deletions

View File

@@ -5,7 +5,7 @@ export const facebookColor = '#3b5998';
export const linkedInColor = '#0e76a8'; export const linkedInColor = '#0e76a8';
// export const APP_DEFAULT_PATH = '/sample-page'; // export const APP_DEFAULT_PATH = '/sample-page';
export const APP_DEFAULT_PATH = '/orders'; export const APP_DEFAULT_PATH = '/nearle/orders';
export const HORIZONTAL_MAX_ITEM = 6; export const HORIZONTAL_MAX_ITEM = 6;
export const DRAWER_WIDTH = 260; export const DRAWER_WIDTH = 260;

View File

@@ -156,10 +156,10 @@ const HeaderContent = () => {
}} }}
> >
<ListItemButton <ListItemButton
selected={location.pathname === '/orders/create'} selected={location.pathname === 'nearle/orders/create'}
onClick={() => { onClick={() => {
// console.log(const location = useLocation();) // console.log(const location = useLocation();)
navigate('/orders/create'); navigate('nearle/orders/create');
handleClickAway(); handleClickAway();
}} }}
> >
@@ -175,10 +175,10 @@ const HeaderContent = () => {
/> />
</ListItemButton> </ListItemButton>
<ListItemButton <ListItemButton
selected={location.pathname === '/orders/create'} selected={location.pathname === 'nearle/orders/create'}
onClick={() => { onClick={() => {
// console.log(const location = useLocation();) // console.log(const location = useLocation();)
navigate('/orders/createorders'); navigate('nearle/orders/createorders');
handleClickAway(); handleClickAway();
}} }}
> >
@@ -201,7 +201,7 @@ const HeaderContent = () => {
}} > }} >
<ListItemText <ListItemText
primary={ primary={
<Grid container>  <Grid container>
<ListItemIcon sx={{ mr: 1, fontSize: '20px' }}> <ListItemIcon sx={{ mr: 1, fontSize: '20px' }}>
<CustomerServiceOutlined /> <CustomerServiceOutlined />
</ListItemIcon> </ListItemIcon>
@@ -212,9 +212,9 @@ const HeaderContent = () => {
/> />
</ListItemButton> */} </ListItemButton> */}
<ListItemButton <ListItemButton
selected={location.pathname === '/customers/create'} selected={location.pathname === 'nearle/customers/create'}
onClick={() => { onClick={() => {
navigate('/customers/create'); navigate('nearle/customers/create');
handleClickAway(); handleClickAway();
}} }}
> >

View File

@@ -1,13 +1,13 @@
// project import // project import
// import nearle from './nearle'; import nearle from './nearle';
import other from './other'; // import other from './other';
// ==============================|| MENU ITEMS ||============================== // // ==============================|| MENU ITEMS ||============================== //
const menuItems = { const menuItems = {
items: [ items: [
other // other,
// nearle nearle
] ]
}; };

View File

@@ -4,6 +4,7 @@ import { AiOutlineBarChart } from 'react-icons/ai';
import { AiOutlineDashboard } from 'react-icons/ai'; import { AiOutlineDashboard } from 'react-icons/ai';
import { TbListDetails } from 'react-icons/tb'; import { TbListDetails } from 'react-icons/tb';
import { LiaFileInvoiceSolid } from 'react-icons/lia'; import { LiaFileInvoiceSolid } from 'react-icons/lia';
import DirectionsBikeOutlinedIcon from '@mui/icons-material/DirectionsBikeOutlined';
// assets // assets
import { import {
@@ -21,6 +22,7 @@ import {
UserOutlined, UserOutlined,
SettingOutlined SettingOutlined
} from '@ant-design/icons'; } from '@ant-design/icons';
import { Path } from 'leaflet';
// icons // icons
const icons = { const icons = {
@@ -66,20 +68,41 @@ const nearle = {
type: 'collapse', type: 'collapse',
icon: AiOutlineBarChart, icon: AiOutlineBarChart,
children: [ children: [
{
id: 'OrderSummary',
title: <FormattedMessage id="OrderSummary" />,
type: 'item',
url: '/nearle/reports/ordersummary',
icon: TbListDetails
},
{ {
id: 'OrdersDetails', id: 'OrdersDetails',
title: <FormattedMessage id="OrdersDetails" />, title: <FormattedMessage id="OrdersDetails" />,
type: 'item', type: 'item',
url: '/nearle/ordersdetails', url: '/nearle/reports/ordersdetails',
icon: TbListDetails icon: AiOutlineDashboard
},
{
id: 'RiderSummary',
title: <FormattedMessage id="RiderSummary" />,
type: 'item',
url: '/nearle/reports/ridersummary',
icon: DirectionsBikeOutlinedIcon
} }
// {
// id: 'RiderLogs',
// title: <FormattedMessage id="RiderLogs" />,
// type: 'item',
// url: '/nearle/reports/riderlogs',
// icon: DirectionsBikeOutlinedIcon
// }
] ]
}, },
{ {
id: 'invoice', id: 'invoice',
title: <FormattedMessage id="Invoice" />, title: <FormattedMessage id="Invoice" />,
type: 'item', type: 'item',
url: '/nearle/invoice', url: 'nearle/invoice',
icon: LiaFileInvoiceSolid icon: LiaFileInvoiceSolid
} }
] ]

View File

@@ -57,14 +57,14 @@ const other = {
id: 'orders', id: 'orders',
title: <FormattedMessage id="Orders" />, title: <FormattedMessage id="Orders" />,
type: 'item', type: 'item',
url: '/orders', url: 'nearle/orders',
icon: AiOutlineDashboard icon: AiOutlineDashboard
}, },
{ {
id: 'customers', id: 'customers',
title: <FormattedMessage id="Customers" />, title: <FormattedMessage id="Customers" />,
type: 'item', type: 'item',
url: '/customers', url: 'nearle/customers',
icon: icons.UserOutlined icon: icons.UserOutlined
}, },
{ {
@@ -73,12 +73,33 @@ const other = {
type: 'collapse', type: 'collapse',
icon: AiOutlineBarChart, icon: AiOutlineBarChart,
children: [ children: [
{
id: 'OrderSummary',
title: <FormattedMessage id="OrderSummary" />,
type: 'item',
url: 'reports/ordersummary',
icon: TbListDetails
},
{ {
id: 'OrdersDetails', id: 'OrdersDetails',
title: <FormattedMessage id="OrdersDetails" />, title: <FormattedMessage id="OrdersDetails" />,
type: 'item', type: 'item',
url: 'reports/ordersdetails', url: 'reports/ordersdetails',
icon: TbListDetails icon: TbListDetails
},
{
id: 'RiderSummary',
title: <FormattedMessage id="RiderSummary" />,
type: 'item',
url: 'reports/ridersummary',
icon: TbListDetails
},
{
id: 'RiderLogs',
title: <FormattedMessage id="RiderLogs" />,
type: 'item',
url: 'reports/riderlogs',
icon: TbListDetails
} }
] ]
}, },

View File

@@ -76,16 +76,25 @@ export const fetchCustomersListBySearch = async ({ queryKey }) => {
// ==============================|| fetchOrdersSummary (orders summary)||============================== // // ==============================|| fetchOrdersSummary (orders summary)||============================== //
export const fetchOrdersSummary = async ({ queryKey }) => { export const fetchOrdersSummary = async ({ queryKey }) => {
console.log('queryKey for fetchOrdersSummary', queryKey); console.log('queryKey for fetchOrdersSummary', queryKey);
const [id, startdate, enddate] = queryKey; const [startdate, enddate] = queryKey;
const response = await axios.get( const response = await axios.get(
id == -1 `${process.env.REACT_APP_URL}/deliveries/getreportsummary/?tenantid=${tenid}&fromdate=${startdate}&todate=${enddate}`
? `${process.env.REACT_APP_URL}/deliveries/getreportsummary/?&fromdate=${startdate}&todate=${enddate}`
: `${process.env.REACT_APP_URL}/deliveries/getreportsummary/?partnerid=${id}&fromdate=${startdate}&todate=${enddate}`
); );
console.log('fetchOrdersSummary', response.data.details); console.log('fetchOrdersSummary', response.data.details);
return response.data.details; return response.data.details;
}; };
// ==============================|| getreportlocationsummary (orders summary)||============================== //
export const getreportlocationsummary = async ({ queryKey }) => {
console.log('queryKey for getreportlocationsummary', queryKey);
const [startdate, enddate, locationId] = queryKey;
const response = await axios.get(
`${process.env.REACT_APP_URL}/deliveries/getreportlocationsummary/?tenantid=${tenid}&locationid=${locationId}&fromdate=${startdate}&todate=${enddate}`
);
console.log('getreportlocationsummary', response.data.details);
return response.data.details;
};
// ==============================|| fetchLocations (orders summary))||============================== // // ==============================|| fetchLocations (orders summary))||============================== //
export const fetchLocations = async () => { export const fetchLocations = async () => {
@@ -100,9 +109,9 @@ export const fetchLocations = async () => {
}; };
// ==============================|| fetchDeliverySummary (orders summary)||============================== // // ==============================|| fetchDeliverySummary (orders summary)||============================== //
export const fetchDeliverySummary = async ({ queryKey }) => { export const fetchDeliverySummary = async ({ queryKey }) => {
const [, startdate, enddate, currentStatus] = queryKey; const [, startdate, enddate, currentStatus, locationId] = queryKey;
const response = await axios.get( const response = await axios.get(
`${process.env.REACT_APP_URL}/deliveries/deliverysummary?tenantid=${tenid}&fromdate=${startdate}&todate=${enddate}` `${process.env.REACT_APP_URL}/deliveries/deliverysummary?tenantid=${tenid}&locationid=${locationId}&fromdate=${startdate}&todate=${enddate}`
); );
console.log('fetchDeliverySummary', response.data.details); console.log('fetchDeliverySummary', response.data.details);
return response.data.details; return response.data.details;
@@ -137,13 +146,15 @@ export const fetchRidersSummary = async ({ queryKey }) => {
// ==============================|| fetchorderdetails (orders detail)||============================== // // ==============================|| fetchorderdetails (orders detail)||============================== //
export const fetchorderdetails = async ({ pageParam = 0, queryKey }) => { export const fetchorderdetails = async ({ pageParam = 0, queryKey }) => {
const [startdate, enddate, currentStatus] = queryKey; const [startdate, enddate, currentStatus, locationId] = queryKey;
const limit = 10; const limit = 10;
const pageno = pageParam + 1; // ✅ increment page by 1 each time const pageno = pageParam + 1; // ✅ increment page by 1 each time
const response = await axios.get( const response = await axios.get(
`${process.env.REACT_APP_URL}/deliveries/getdeliveries/?tenantid=${tenid}&fromdate=${startdate}&todate=${enddate}&status=${ `${
process.env.REACT_APP_URL
}/deliveries/getdeliveries/?tenantid=${tenid}&locationid=${locationId}&fromdate=${startdate}&todate=${enddate}&status=${
currentStatus === 'All' ? '' : currentStatus currentStatus === 'All' ? '' : currentStatus
}&pageno=${pageno}&pagesize=${limit}` }&pageno=${pageno}&pagesize=${limit}`
); );

View File

@@ -1,10 +0,0 @@
const Dashboard=()=>{
return <>
<h1>Dashboard</h1>
</>
}
export default Dashboard;

View File

@@ -47,7 +47,7 @@ const Login = () => {
localStorage.getItem('authname') localStorage.getItem('authname')
// || localStorage.getItem("appuserid") // || localStorage.getItem("appuserid")
) { ) {
navigate('/orders'); navigate('/nearle/orders');
} }
// console.log(alertmessage) // console.log(alertmessage)
@@ -144,7 +144,7 @@ const Login = () => {
localStorage.setItem('moduleid', res.data.details.moduleid); localStorage.setItem('moduleid', res.data.details.moduleid);
localStorage.setItem('userid', res.data.details.userid); localStorage.setItem('userid', res.data.details.userid);
navigate('/orders'); navigate('/nearle/orders');
setSubmitting(false); setSubmitting(false);
} else { } else {
opentoast('Login Error'); opentoast('Login Error');

View File

@@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import Loader from 'components/Loader'; import Loader from 'components/Loader';
import { useEffect, useState, useRef, Fragment } from 'react'; import { useEffect, useState, Fragment } from 'react';
import { useTheme } from '@mui/material/styles'; import { useTheme } from '@mui/material/styles';
import MainCard from 'components/MainCard'; import MainCard from 'components/MainCard';
import axios from 'axios'; import axios from 'axios';

View File

@@ -9,6 +9,8 @@ dayjs.extend(utc);
import axios from 'axios'; import axios from 'axios';
import HoverSocialCard from 'components/cards/statistics/HoverSocialCard'; import HoverSocialCard from 'components/cards/statistics/HoverSocialCard';
import { useTheme } from '@mui/material/styles'; import { useTheme } from '@mui/material/styles';
import MyLocationIcon from '@mui/icons-material/MyLocation';
import { import {
Avatar, Avatar,
Box, Box,
@@ -33,8 +35,8 @@ import {
OutlinedInput, OutlinedInput,
InputAdornment, InputAdornment,
Skeleton, Skeleton,
TextField, Autocomplete,
Autocomplete TextField
} from '@mui/material'; } from '@mui/material';
import { SearchOutlined, CloseOutlined } from '@ant-design/icons'; import { SearchOutlined, CloseOutlined } from '@ant-design/icons';
import ClearIcon from '@mui/icons-material/Clear'; import ClearIcon from '@mui/icons-material/Clear';
@@ -46,12 +48,13 @@ import TableSortLabel from '@mui/material/TableSortLabel';
import { visuallyHidden } from '@mui/utils'; import { visuallyHidden } from '@mui/utils';
import Loader from 'components/Loader'; import Loader from 'components/Loader';
import { FilterList } from '@mui/icons-material'; import { FilterList } from '@mui/icons-material';
import { Outlet } from 'react-router';
const Orders = () => { const Orders = () => {
const tid = localStorage.getItem('tenantid'); const tid = localStorage.getItem('tenantid');
const tenId = localStorage.getItem('tenantid');
const [page, setPage] = React.useState(0); const [page, setPage] = React.useState(0);
const [rowsPerPage, setRowsPerPage] = React.useState(10); const [rowsPerPage, setRowsPerPage] = React.useState(10);
const [pageCountObj, setPageCountObj] = React.useState({});
const [pageCount, setPageCount] = React.useState(); const [pageCount, setPageCount] = React.useState();
const [startdate, setStartdate] = useState(dayjs().format('YYYY-MM-DD')); const [startdate, setStartdate] = useState(dayjs().format('YYYY-MM-DD'));
const [enddate, setEnddate] = useState(dayjs().format('YYYY-MM-DD')); const [enddate, setEnddate] = useState(dayjs().format('YYYY-MM-DD'));
@@ -59,7 +62,7 @@ const Orders = () => {
const [percentage2, setPercentage2] = useState('0'); const [percentage2, setPercentage2] = useState('0');
const [percentage3, setPercentage3] = useState('0'); const [percentage3, setPercentage3] = useState('0');
const [percentage4, setPercentage4] = useState('0'); const [percentage4, setPercentage4] = useState('0');
let [orderarr, setArr] = useState([]); const [tenantLocations, setTenantlocations] = useState([]);
const [coveredorders, setCoveredorders] = useState(''); const [coveredorders, setCoveredorders] = useState('');
const [uncoveredorders, setUncoveredorders] = useState(''); const [uncoveredorders, setUncoveredorders] = useState('');
const [cancelled, setCancelled] = useState(''); const [cancelled, setCancelled] = useState('');
@@ -70,7 +73,6 @@ const Orders = () => {
let [rows, setRows] = useState([]); let [rows, setRows] = useState([]);
const [tabvalue, setTabvalue] = useState(0); const [tabvalue, setTabvalue] = useState(0);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [tabstatus1, setTabstatus1] = useState('Today');
const [datestatus, setDatestatus] = useState('Today'); const [datestatus, setDatestatus] = useState('Today');
const [searchword, setSearchword] = useState(''); const [searchword, setSearchword] = useState('');
const [currentStatus, setCurrentStatus] = useState('created'); const [currentStatus, setCurrentStatus] = useState('created');
@@ -78,6 +80,10 @@ const Orders = () => {
const [pendingLenght, setPendingLenght] = useState(); const [pendingLenght, setPendingLenght] = useState();
const [deliveredlenght, setDeliveredlenght] = useState(); const [deliveredlenght, setDeliveredlenght] = useState();
const [cancelledLenght, setCancelledLenght] = useState(); const [cancelledLenght, setCancelledLenght] = useState();
const [cancelOpen, setCancelOpen] = useState(false);
const [orderheaderid, setOrderheaderid] = useState('');
const [locationId, setLocationId] = useState(0);
const [locoName, setLocoName] = useState('Select Location');
const handleChangetab = (e, i) => { const handleChangetab = (e, i) => {
setTabvalue(i); setTabvalue(i);
@@ -85,22 +91,18 @@ const Orders = () => {
if (i === 0) { if (i === 0) {
setTabstatus('Created'); setTabstatus('Created');
setCurrentStatus('created'); setCurrentStatus('created');
setPageCount(pageCountObj.created);
} }
if (i === 1) { if (i === 1) {
setTabstatus('Pending'); setTabstatus('Pending');
setCurrentStatus('pending'); setCurrentStatus('pending');
setPageCount(pageCountObj.pending);
} }
if (i === 2) { if (i === 2) {
setTabstatus('Delivered'); setTabstatus('Delivered');
setCurrentStatus('delivered'); setCurrentStatus('delivered');
setPageCount(pageCountObj.delivered);
} }
if (i === 3) { if (i === 3) {
setTabstatus('Cancelled'); setTabstatus('Cancelled');
setCurrentStatus('cancelled'); setCurrentStatus('cancelled');
setPageCount(pageCountObj.cancelled);
} }
console.log(i); console.log(i);
}; };
@@ -131,20 +133,39 @@ const Orders = () => {
}; };
}, []); }, []);
useEffect(() => { const handleChangePage = (event, newPage) => {
var day = 60 * 60 * 24 * 1000; setPage(newPage);
var startDate = new Date(); };
if (tabstatus1 === 'Tomorrow') {
setEnddate(new Date(startDate.getTime() + day).toISOString().substring(0, 10)); const handleChangeRowsPerPage = (event) => {
setStartdate(new Date(startDate.getTime() + day).toISOString().substring(0, 10)); setRowsPerPage(parseInt(event.target.value, 10));
} else if (tabstatus1 === 'Today') { setPage(0);
setEnddate(new Date().toISOString().substring(0, 10)); };
setStartdate(new Date().toISOString().substring(0, 10));
} else if (tabstatus1 === 'Week') { const cancelorder = async () => {
setStartdate(new Date(startDate.getTime() - day * 7).toISOString().substring(0, 10)); await axios
setEnddate(new Date().toISOString().substring(0, 10)); .put(`${process.env.REACT_APP_URL}/orders/updateorder`, {
orderheaderid: orderheaderid,
orderstatus: 'cancelled',
cancelled: dayjs().format('YYYY-MM-DD HH:mm:ss')
})
.then((res) => {
console.log(res);
if (res.data.status) {
enqueueSnackbar('Order Cancelled Successfully', {
variant: 'success',
anchorOrigin: { vertical: 'top', horizontal: 'right' },
autoHideDuration: 2000
});
fetchtablecovered();
fetchorderscount();
setCancelOpen(false);
} }
}, [tabstatus1]); })
.catch((err) => {
console.log(err);
});
};
const fetchtablecovered = async () => { const fetchtablecovered = async () => {
try { try {
@@ -152,12 +173,11 @@ const Orders = () => {
.get( .get(
`${ `${
process.env.REACT_APP_URL process.env.REACT_APP_URL
}/orders/tenant/getorders/?tenantid=${tid}&status=${currentStatus}&fromdate=${startdate}&todate=${enddate}&pageno=${ }/orders/tenant/getorders/?tenantid=${tid}&locationid=${locationId}&status=${currentStatus}&fromdate=${startdate}&todate=${enddate}&pageno=${
page + 1 page + 1
}&pagesize=${rowsPerPage}&keyword=${searchword}` }&pagesize=${rowsPerPage}&keyword=${searchword}`
) )
.then((res) => { .then((res) => {
setArr(res.data.details);
setRows(res.data.details); setRows(res.data.details);
}) })
.catch((err) => { .catch((err) => {
@@ -169,7 +189,7 @@ const Orders = () => {
}; };
useEffect(() => { useEffect(() => {
fetchtablecovered(); fetchtablecovered();
}, [tabstatus, startdate, enddate, page, rowsPerPage, searchword]); }, [tabstatus, startdate, enddate, page, rowsPerPage, searchword, locationId]);
const fetchpercentage = async () => { const fetchpercentage = async () => {
setLoading(true); setLoading(true);
@@ -205,7 +225,9 @@ const Orders = () => {
setLoading(true); setLoading(true);
try { try {
await axios await axios
.get(`${process.env.REACT_APP_URL}/orders/getordersummary/?tenantid=${tid}&fromdate=${startdate}&todate=${enddate}`) .get(
`${process.env.REACT_APP_URL}/orders/getordersummary/?tenantid=${tid}&locationid=${locationId}&fromdate=${startdate}&todate=${enddate}`
)
.then((res) => { .then((res) => {
console.log('fetchorderscount', res.data.details); console.log('fetchorderscount', res.data.details);
@@ -230,191 +252,222 @@ const Orders = () => {
}; };
useEffect(() => { useEffect(() => {
fetchorderscount(); fetchorderscount();
}, [tabvalue]); }, [tabvalue, locationId]);
// ============================================= || gettenantlocations (branches) || =============================================
const headCells = [ const gettenantlocations = async (id) => {
{ try {
id: 'sno', const res = await axios.get(`${process.env.REACT_APP_URL}/tenants/gettenantlocations/?tenantid=${id}`);
disablePadding: true, console.log('gettenantlocations', res.data.details);
label: 'S NO' if (res.data.details.length == 1) {
}, setIsLocation(true);
{ setTenantlocations(res.data.details);
id: 'orderid', setPickCust(res.data.details[0]);
numeric: false, } else {
disablePadding: false, setTenantlocations(res.data.details);
label: 'ORDER ID' }
}, } catch (err) {
{ console.log('gettenantlocations', err);
id: 'eventname',
disablePadding: false,
label: 'Pickup'
},
{
id: 'eventname4',
disablePadding: false,
label: 'Delivery'
},
{
id: 'itemcount',
disablePadding: false,
label: 'NOTES'
},
{
id: 'orderstatus',
disablePadding: false,
label: 'STATUS'
},
{
id: 'action',
disablePadding: false,
label: 'ACTION'
} }
];
function EnhancedTableHead(props) {
const { order, orderBy, onRequestSort } = props;
const createSortHandler = (property) => (event) => {
onRequestSort(event, property);
}; };
useEffect(() => {
gettenantlocations(tenId);
}, []);
return ( return (
<TableHead> <>
<TableRow> {loading && <Loader />}
{headCells.map((headCell) => ( <Outlet />
<TableCell <Stack direction={{ xs: 'column', md: 'row' }} justifyContent="space-between" alignItems="center" spacing={2}>
key={headCell.id} <Typography variant="h3">Orders</Typography>
align={headCell.numeric ? 'right' : 'left'} </Stack>
padding={headCell.disablePadding ? 'none' : 'normal'} <Grid container spacing={3} sx={{ mt: 0.1 }}>
sortDirection={orderBy === headCell.id ? order : false} <Grid item xs={12} sm={6} md={3}>
> <HoverSocialCard
<TableSortLabel primary="Created Orders"
active={orderBy === headCell.id} secondary={created === '' ? <Skeleton sx={{ width: '30px' }} animation="wave" /> : created}
direction={orderBy === headCell.id ? order : 'asc'} percentage={percentage1.toString()}
onClick={createSortHandler(headCell.id)} color={theme.palette.primary.main}
> />
{headCell.label} </Grid>
{orderBy === headCell.id ? ( <Grid item xs={12} sm={6} md={3}>
<Box component="span" sx={visuallyHidden}> <HoverSocialCard
{order === 'desc' ? 'sorted descending' : 'sorted ascending'} primary="Pending orders"
</Box> secondary={uncoveredorders == '' ? <Skeleton sx={{ width: '30px' }} animation="wave" /> : uncoveredorders}
) : null} percentage={percentage2.toString()}
</TableSortLabel> color={theme.palette.warning.main}
</TableCell> />
))} </Grid>
</TableRow>
</TableHead> <Grid item xs={12} sm={6} md={3}>
); <HoverSocialCard
primary="Delivered orders"
secondary={coveredorders === '' ? <Skeleton sx={{ width: '30px' }} animation="wave" /> : coveredorders}
percentage={percentage3.toString()}
color={theme.palette.success.main}
/>
</Grid>
<Grid item xs={12} sm={6} md={3}>
<HoverSocialCard
primary="Cancelled Orders"
secondary={cancelled === '' ? <Skeleton sx={{ width: '30px' }} animation="wave" /> : cancelled}
percentage={percentage4.toString()}
color={theme.palette.secondary[600]}
/>
</Grid>
</Grid>
<Stack direction={'row'} justifyContent={'space-between'} alignItems={'center'} sx={{ my: 2 }}>
{startdate && enddate && (
<Stack direction="row" spacing={2}>
<Chip label={`Orders-${datestatus ? datestatus : ''}`} color="primary" variant="light" size="small" />
<Chip
label={
<Typography noWrap color="secondary">
{dayjs(startdate).format('DD/MM/YYYY')} - {dayjs(enddate).format('DD/MM/YYYY')}
</Typography>
} }
variant="combined"
function EnhancedTable() { color="warning"
const [open, setOpen] = useState(false); size="small"
const [orderheaderid, setOrderheaderid] = useState(''); />
</Stack>
const cancelorder = async () => { )}
await axios <Stack display={'flex'} flexDirection={'row'} alignItems={'center'} justifyContent={'space-between'} gap={2}>
.put(`${process.env.REACT_APP_URL}/orders/updateorder`, { <Stack direction={'row'} alignItems={'center'} justifyContent={'space-between'}>
orderheaderid: orderheaderid, {tenantLocations.length == 1 ? (
orderstatus: 'cancelled', <TextField
cancelled: dayjs().format('YYYY-MM-DD HH:mm:ss') // disabled={!isAppLocation || !isClient}
}) variant="outlined"
.then((res) => { fullWidth
console.log(res); label={'Business Location'}
if (res.data.status) { value={tenantLocations[0].locationname}
enqueueSnackbar('Order Cancelled Successfully', { focused
variant: 'success', sx={{ width: '350px' }}
anchorOrigin: { vertical: 'top', horizontal: 'right' }, InputProps={{
autoHideDuration: 2000 style: { color: theme.palette.primary.main },
}); startAdornment: (
handleClose(true); <InputAdornment position="start">
<MyLocationIcon color="primary" />
</InputAdornment>
)
}}
/>
) : (
<Autocomplete
fullWidth
// disabled={!isAppLocation || !isClient}
id="combo-box-demo"
options={tenantLocations || []}
getOptionLabel={(option) => `${option.locationname} (${option.suburb})` || ''}
renderInput={(params) => <TextField {...params} label={'Select Location'} value={locoName} color="primary" />}
sx={{ width: '350px' }}
onChange={(event, value, reason) => {
if (value) {
console.log('Business Locations', value);
setLocationId(value.locationid);
setLocoName(value.locationname);
}
if (reason == 'clear') {
setLocationId(0);
setLocoName('Select Location');
}
}}
/>
)}
</Stack>
<Tooltip title="Order Filter">
<IconButton
color="secondary"
variant="light"
sx={{ color: 'text.primary', bgcolor: 'grey.200' }}
aria-haspopup="true"
onClick={() => setOpen(true)}
>
<FilterList />
</IconButton>
</Tooltip>
</Stack>
</Stack>
<Grid item xs={12}>
<Box sx={{ overflow: 'auto', border: 1, borderColor: 'grey.200', borderRadius: 2, backgroundColor: '#fff', minHeight: 350 }}>
<Stack
alignItems="center"
justifyContent="space-between"
direction="row"
sx={{
p: 2,
width: '100%'
}}
>
<Tabs value={tabvalue} onChange={handleChangetab} variant="scrollable" scrollButtons="auto">
<Tab label="Created" icon={<Chip label={createdLenght} color="primary" variant="light" size="small" />} iconPosition="end" />
<Tab label="Pending" icon={<Chip label={pendingLenght} color="primary" variant="light" size="small" />} iconPosition="end" />
<Tab
label="Delivered"
icon={<Chip label={deliveredlenght} color="primary" variant="light" size="small" />}
iconPosition="end"
/>
<Tab
label="Cancelled"
icon={<Chip label={cancelledLenght} color="primary" variant="light" size="small" />}
iconPosition="end"
/>
</Tabs>
<Stack>
<FormControl sx={{ width: 250 }}>
<OutlinedInput
inputRef={textFieldRef}
id="header-search"
aria-describedby="header-search-text"
inputProps={{
'aria-label': 'weight'
}}
placeholder="Search (ctrl+k)"
value={searchword}
onChange={(e) => {
setSearchword(e.target.value);
}}
autoComplete="off"
startAdornment={
<InputAdornment position="start" sx={{ mr: -0.5 }}>
<SearchOutlined style={{ color: theme.palette.primary.main }} />
</InputAdornment>
}
endAdornment={
<Tooltip title="clear">
<IconButton
sx={{ visibility: searchword ? 'visible' : 'hidden' }}
onClick={() => {
setSearchword('');
fetchtablecovered(); fetchtablecovered();
fetchorderscount(); fetchorderscount();
}
})
.catch((err) => {
console.log(err);
});
};
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
const handleClose = () => {
setOpen(false);
setOrderheaderid('');
};
function AlertCustomerDelete({
// title,
open,
handleClose
}) {
// const [deletepassword, setDeletepassword] = useState('');
return (
<Dialog open={open} onClose={() => handleClose(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>
{/* <Grid >
<Chip label={orderid.slice(4)} variant="combined" color='warning' size='small' />
</Grid> */}
<Stack spacing={2}>
<Typography variant="h4" align="center">
Are you sure you want to cancel this order?
</Typography>
{/* <Typography variant="h4" align="center">
Please type in the order number to confirm.
</Typography> */}
</Stack>
<Stack direction="row" spacing={2} sx={{ width: 1 }}>
<Button
fullWidth
color="error"
variant="contained"
onClick={() => {
// if (deletepassword === orderid.slice(4)) {
cancelorder();
// }
}} }}
autoFocus
> >
Yes, Cancel <ClearIcon fontSize="small" sx={{ color: theme.palette.primary.main }} />
</Button> </IconButton>
<Button </Tooltip>
fullWidth
onClick={() => {
handleClose(false);
}}
color="secondary"
variant="outlined"
>
No
</Button>
</Stack>
</Stack>
</DialogContent>
</Dialog>
);
} }
/>
</FormControl>
</Stack>
</Stack>
return ( <Box sx={{ width: '100%', display: 'table', tableLayout: 'fixed' }}>
<Box sx={{ width: '100%' }}> <Box sx={{ width: '100%' }}>
<AlertCustomerDelete open={open} handleClose={handleClose} />
<TableContainer sx={{ width: '100%', borderBottom: 1, borderColor: 'divider' }}> <TableContainer sx={{ width: '100%', borderBottom: 1, borderColor: 'divider' }}>
<Table sx={{ minWidth: 750 }} aria-label="collapsible table" size={'medium'}> <Table sx={{ minWidth: 750 }} aria-label="collapsible table" size={'medium'}>
<EnhancedTableHead /> <TableHead>
<TableRow>
<TableCell> S.No</TableCell>
<TableCell> Orders</TableCell>
<TableCell> Pickup</TableCell>
<TableCell>Drop </TableCell>
<TableCell> Notes</TableCell>
<TableCell>Status </TableCell>
<TableCell>Action </TableCell>
</TableRow>
</TableHead>
{loading && ( {loading && (
<> <>
<TableBody> <TableBody>
@@ -557,11 +610,10 @@ const Orders = () => {
<> <>
<Tooltip title="Cancel"> <Tooltip title="Cancel">
<IconButton <IconButton
// disabled={(row.orderstatus != 'created')}
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
setOrderheaderid(row.orderheaderid); setOrderheaderid(row.orderheaderid);
setOpen(true); setCancelOpen(true);
}} }}
> >
<CloseOutlined <CloseOutlined
@@ -592,156 +644,48 @@ const Orders = () => {
onRowsPerPageChange={handleChangeRowsPerPage} onRowsPerPageChange={handleChangeRowsPerPage}
/> />
</Box> </Box>
); </Box>
} </Box>
return (
<>
{loading && <Loader />}
<Stack direction={{ xs: 'column', md: 'row' }} justifyContent="space-between" alignItems="center" spacing={2}>
<Typography variant="h3">Orders</Typography>
</Stack>
<Grid container spacing={3} sx={{ mt: 0.1 }}>
<Grid item xs={12} sm={6} md={3}>
<HoverSocialCard
primary="Created Orders"
secondary={created === '' ? <Skeleton sx={{ width: '30px' }} animation="wave" /> : created}
percentage={percentage1.toString()}
color={theme.palette.primary.main}
/>
</Grid> </Grid>
<Grid item xs={12} sm={6} md={3}> {/* ============================================== || cancel order || ============================================== */}
<HoverSocialCard <Dialog open={cancelOpen} onClose={() => setCancelOpen(false)} maxWidth="xs">
primary="Pending orders" <DialogContent sx={{ mt: 2, my: 1 }}>
secondary={uncoveredorders == '' ? <Skeleton sx={{ width: '30px' }} animation="wave" /> : uncoveredorders} <Stack alignItems="center" spacing={3.5}>
percentage={percentage2.toString()} <Avatar color="error" sx={{ width: 72, height: 72, fontSize: '1.75rem' }}>
color={theme.palette.warning.main} <DeleteFilled />
/> </Avatar>
</Grid> <Stack spacing={2}>
<Typography variant="h4" align="center">
<Grid item xs={12} sm={6} md={3}> Are you sure you want to cancel this order?
<HoverSocialCard
primary="Delivered orders"
secondary={coveredorders === '' ? <Skeleton sx={{ width: '30px' }} animation="wave" /> : coveredorders}
percentage={percentage3.toString()}
color={theme.palette.success.main}
/>
</Grid>
<Grid item xs={12} sm={6} md={3}>
<HoverSocialCard
primary="Cancelled Orders"
secondary={cancelled === '' ? <Skeleton sx={{ width: '30px' }} animation="wave" /> : cancelled}
percentage={percentage4.toString()}
color={theme.palette.secondary[600]}
/>
</Grid>
</Grid>
<Stack direction={'row'} justifyContent={'space-between'} alignItems={'center'} sx={{ my: 2 }}>
{startdate && enddate && (
<Stack direction="row" spacing={2}>
<Chip label={`Orders-${datestatus ? datestatus : ''}`} color="primary" variant="light" size="small" />
<Chip
label={
<Typography noWrap color="secondary">
{dayjs(startdate).format('DD/MM/YYYY')} - {dayjs(enddate).format('DD/MM/YYYY')}
</Typography> </Typography>
}
variant="combined"
color="warning"
size="small"
/>
</Stack> </Stack>
)} <Stack direction="row" spacing={2} sx={{ width: 1 }}>
<Button
<Tooltip title="Order Filter"> fullWidth
<IconButton color="error"
color="secondary" variant="contained"
variant="light"
sx={{ color: 'text.primary', bgcolor: 'grey.200', display: { xs: 'none', md: 'flex' } }}
aria-haspopup="true"
onClick={() => setOpen(true)}
>
<FilterList />
</IconButton>
</Tooltip>
</Stack>
<Grid item xs={12}>
<Box sx={{ overflow: 'auto', border: 1, borderColor: 'grey.200', borderRadius: 2, backgroundColor: '#fff', minHeight: 350 }}>
<Stack
alignItems="center"
justifyContent="space-between"
direction="row"
sx={{
p: 2,
width: '100%'
}}
>
<Tabs value={tabvalue} onChange={handleChangetab} variant="scrollable" scrollButtons="auto">
<Tab label="Created" icon={<Chip label={createdLenght} color="primary" variant="light" size="small" />} iconPosition="end" />
<Tab label="Pending" icon={<Chip label={pendingLenght} color="primary" variant="light" size="small" />} iconPosition="end" />
<Tab
label="Delivered"
icon={<Chip label={deliveredlenght} color="primary" variant="light" size="small" />}
iconPosition="end"
/>
<Tab
label="Cancelled"
icon={<Chip label={cancelledLenght} color="primary" variant="light" size="small" />}
iconPosition="end"
/>
</Tabs>
<Stack>
<FormControl sx={{ width: 250, display: { xs: 'none', md: 'flex' } }}>
<OutlinedInput
inputRef={textFieldRef}
size="small"
id="header-search"
aria-describedby="header-search-text"
inputProps={{
'aria-label': 'weight'
}}
placeholder="Search (ctrl+k)"
value={searchword}
onChange={(e) => {
setSearchword(e.target.value);
}}
autoComplete="off"
startAdornment={
<InputAdornment position="start" sx={{ mr: -0.5 }}>
<SearchOutlined style={{ color: theme.palette.primary.main }} />
</InputAdornment>
}
endAdornment={
<Tooltip title="clear">
<IconButton
sx={{ visibility: searchword ? 'visible' : 'hidden' }}
onClick={() => { onClick={() => {
setSearchword(''); cancelorder();
fetchtablecovered();
fetchorderscount();
}} }}
autoFocus
> >
<ClearIcon fontSize="small" sx={{ color: theme.palette.primary.main }} /> Yes, Cancel
</IconButton> </Button>
</Tooltip> <Button
} fullWidth
/> onClick={() => {
</FormControl> setCancelOpen(false);
}}
color="secondary"
variant="outlined"
>
No
</Button>
</Stack> </Stack>
</Stack> </Stack>
</DialogContent>
<Box sx={{ width: '100%', display: 'table', tableLayout: 'fixed' }}> </Dialog>
<EnhancedTable /> {/* ============================================== || Date filter || ============================================== */}
</Box>
</Box>
</Grid>
<Dialog open={open}> <Dialog open={open}>
<DialogTitle align="left"> <DialogTitle align="left">
<Typography variant="h4">Select Filter Options</Typography> <Typography variant="h4">Select Filter Options</Typography>

View File

@@ -0,0 +1,778 @@
import { React, useState, useEffect, useRef, Fragment } from 'react';
import axios from 'axios';
import { useQuery } from '@tanstack/react-query';
import { Empty } from 'antd';
import TaskAltIcon from '@mui/icons-material/TaskAlt';
import MyLocationIcon from '@mui/icons-material/MyLocation';
import HighlightOffIcon from '@mui/icons-material/HighlightOff';
// material-ui
import {
Box,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Dialog,
DialogTitle,
Typography,
DialogContent,
Stack,
Button,
IconButton,
Tooltip,
Chip,
Autocomplete,
TextField,
FormControl,
OutlinedInput,
InputAdornment,
Collapse
} from '@mui/material';
import ClearIcon from '@mui/icons-material/Clear';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
import { SearchOutlined } from '@ant-design/icons';
import dayjs from 'dayjs';
var utc = require('dayjs/plugin/utc');
dayjs.extend(utc);
import { DateRangePicker } from 'mui-daterange-picker';
import {
addDays,
addMonths,
addWeeks,
// addYears,
endOfMonth,
endOfWeek,
// endOfYear,
startOfMonth,
startOfWeek
// startOfYear,
} from 'date-fns';
import { FilterList } from '@mui/icons-material';
// project imports
import MainCard from 'components/MainCard';
import Loader from 'components/Loader';
import { useTheme } from '@mui/material/styles';
import TitleCard from '../titleCard';
import { getreportlocationsummary } from '../api/api';
function formatNumberToRupees(value) {
return new Intl.NumberFormat('en-IN', {
style: 'currency',
currency: 'INR',
minimumFractionDigits: 2
}).format(value);
}
// ==============================|| MUI TABLE - ENHANCED ||============================== //
export default function OrdersReport() {
// const [rows, setRows] = useState([]);
const theme = useTheme();
const bgcolor0 = theme.palette.primary.lighter;
const bgcolor1 = '#ffcdd2';
const bgcolor2 = '#f8bbd0';
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); // Initially no row is open
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 textFieldRef = useRef(null);
const [ridersdata, setRidersdata] = useState(null);
const [tenantLocations, setTenantlocations] = useState([]);
const [selectedLocation, setSelectedLocation] = useState(null);
const [locationId, setLocationId] = useState(0);
useEffect(() => {
console.log('openRow', openRow);
}, [openRow]);
/* ============================================= || handleKeyPress (ctrl+k)| ============================================= */
useEffect(() => {
const handleKeyPress = (event) => {
if (event.key === 'k' && (event.metaKey || event.ctrlKey)) {
event.preventDefault();
textFieldRef.current.focus();
}
if (event.key === 'Escape' && document.activeElement === textFieldRef.current) {
// Remove focus from the TextField
textFieldRef.current.blur();
}
};
document.addEventListener('keydown', handleKeyPress);
return () => {
document.removeEventListener('keydown', handleKeyPress);
};
}, []);
// ============================================= || gettenantlocations (branches) || =============================================
const gettenantlocations = async () => {
try {
const res = await axios.get(`${process.env.REACT_APP_URL}/tenants/gettenantlocations?tenantid=${tenantid}`);
console.log('gettenantlocations', res.data.details);
setTenantlocations(res.data.details);
} catch (err) {
console.log('gettenantlocations', err);
}
};
useEffect(() => {
gettenantlocations();
}, []);
// ==============================|| fetchOrdersSummary (orders summary)||============================== //
const {
isLoading: isLoadingReports,
isError: isErrorReports, //true or false
data: rows,
error: reportsError
} = useQuery({
queryKey: [startdate, enddate, locationId],
queryFn: getreportlocationsummary
});
// ==============================|| getriderlocationsummary by tenid (orders summary)||============================== //
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}`
);
console.log('riderRes', riderRes.data.details);
setRidersdata(riderRes.data.details);
} catch (error) {
console.log('riderRes', error);
}
};
// ==============================|| calculate||============================== //
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;
});
// Update the state after the calculation is done
settotal(calculatedTotal);
settotalOrders(ordersTotal);
setTotalOrderPend(Orderpending);
setTotalOrderComplete(OrderComplete);
setTotalOrderCancel(OrderCancel);
setTotalDeliPend(deliverypending);
setTotalDeliComplete(deliverycomplete);
setTotalDeliCancel(deliverycancel);
};
useEffect(() => {
calculate();
}, [rows]);
// if (isLoadingReports) return <Loader />;
if (isErrorReports) return 'An error has occurred:(isErrorReports) ' + reportsError.message;
return (
<>
{isLoadingReports && <Loader />}
<TitleCard title="Orders Summary" />{' '}
<MainCard
content={false}
title={
<Stack display={'flex'} flexDirection={'row'} alignItems={'center'} justifyContent={'space-between'} flexWrap={'wrap'} gap={1}>
<Stack>
{startdate && enddate && (
<Stack direction="row" spacing={2} flexWrap={'wrap'} gap={1}>
<Chip label={`Orders-${datestatus}`} color="primary" variant="light" size="small" />
<Chip
label={
<Typography noWrap color="secondary">
{dayjs(startdate).format('DD/MM/YYYY')} - {dayjs(enddate).format('DD/MM/YYYY')}
</Typography>
}
variant="combined"
color="warning"
size="small"
/>
</Stack>
)}
{(!startdate || !enddate) && (
<>
<Stack direction="row" spacing={2}>
<Chip label="Orders-All" color="primary" variant="light" size="small" />
</Stack>
</>
)}
</Stack>
<Stack
sx={{
display: 'flex',
flexDirection: 'row',
gap: 2,
flexWrap: 'wrap',
flexGrow: 1,
justifyContent: 'right'
}}
>
<FormControl sx={{ width: 250 }}>
<OutlinedInput
inputRef={textFieldRef}
aria-describedby="header-search-text"
inputProps={{
'aria-label': 'weight'
}}
sx={{ background: 'white' }}
size="large"
id="header-search"
placeholder="Search (ctrl+k)"
value={searchword}
onChange={(e) => {
setSearchword(e.target.value);
}}
autoComplete="off"
startAdornment={
<InputAdornment position="start" sx={{ mr: -0.5 }}>
<SearchOutlined />
</InputAdornment>
}
endAdornment={
<IconButton
sx={{ visibility: searchword ? 'visible' : 'hidden' }}
onClick={() => {
setSearchword('');
}}
>
<ClearIcon style={{ fontSize: 'medium', color: '#65387A' }} />
</IconButton>
}
/>
</FormControl>
<Stack>
{tenantLocations.length == 1 ? (
<TextField
variant="outlined"
fullWidth
label={'Business Location'}
value={tenantLocations[0].locationname}
focused
sx={{ minWidth: 250 }}
InputProps={{
style: { color: theme.palette.primary.main },
startAdornment: (
<InputAdornment position="start">
<MyLocationIcon color="primary" />
</InputAdornment>
)
}}
/>
) : (
<Autocomplete
fullWidth
id="combo-box-demo"
options={tenantLocations || []}
value={selectedLocation}
getOptionLabel={(option) => `${option.locationname} (${option.suburb})` || ''}
sx={{ minWidth: 250 }}
onChange={(event, value, reason) => {
setSelectedLocation(value);
if (value) {
console.log('Business Locations', value);
setLocationId(value.locationid);
}
if (reason == 'clear') {
setLocationId(0);
}
}}
renderInput={(params) => <TextField {...params} label="Choose Location" color="primary" />}
/>
)}
</Stack>
<Tooltip title="Order Filter">
<IconButton
color="secondary"
variant="light"
sx={{
color: 'text.primary',
bgcolor: 'grey.200'
}}
onClick={() => setOpen(true)}
>
<FilterList />
</IconButton>
</Tooltip>
</Stack>
</Stack>
}
>
<TableContainer
sx={{
overflow: 'auto',
'&::-webkit-scrollbar': {
width: '3px',
height: '3px'
},
'&::-webkit-scrollbar-thumb': {
backgroundColor: '#65387A' // Color of the scrollbar thumb
}
}}
>
<Table>
<TableHead>
<TableRow sx={{ bgcolor: bgcolor0 }}>
<TableCell rowSpan={2}># </TableCell>
<TableCell rowSpan={2}> Location</TableCell>
<TableCell rowSpan={2}>All </TableCell>
<TableCell colSpan={3} sx={{ textAlign: 'center', bgcolor: bgcolor1 }}>
Orders{' '}
</TableCell>
<TableCell colSpan={3} sx={{ textAlign: 'center', bgcolor: bgcolor2 }}>
Deliveries{' '}
</TableCell>
<TableCell rowSpan={2}> Kilometer</TableCell>
<TableCell rowSpan={2}>Charges </TableCell>
<TableCell rowSpan={2}>Amount </TableCell>
<TableCell rowSpan={2}> Action</TableCell>
</TableRow>
{/* sx={{ bgcolor: headCell.bgcolor }} */}
<TableRow>
<TableCell sx={{ bgcolor: bgcolor1 }}>Pending</TableCell>
<TableCell sx={{ bgcolor: bgcolor1 }}>Completed</TableCell>
<TableCell sx={{ bgcolor: bgcolor1 }}>Cancelled</TableCell>
<TableCell sx={{ bgcolor: bgcolor2 }}>Pending</TableCell>
<TableCell sx={{ bgcolor: bgcolor2 }}>Completed</TableCell>
<TableCell sx={{ bgcolor: bgcolor2 }}>Cancelled</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows?.length !== 0 ? (
rows?.map((row, index) => (
<>
{/* ============================================ || tablerow 1 || ============================================ */}
<TableRow
key={row.locationid}
sx={{
bgcolor: openRow === row.locationid ? '#e1bee7' : null,
'&:hover': {
bgcolor: openRow === row.locationid ? '#e1bee7!important' : null
},
cursor: openRow === row.locationid ? 'pointer' : null
}}
>
<TableCell scope="row" padding="none">
{index + 1}
</TableCell>
<TableCell align="left">
<Stack direction="row" sx={{ ml: -2 }}>
{row.locationname}
</Stack>
</TableCell>
<TableCell align="center">{row.totalorders}</TableCell>
<TableCell align="center">{row.Orderspending}</TableCell>
<TableCell align="center">{row.orderscompleted}</TableCell>
<TableCell align="center">{row.orderscancelled}</TableCell>
<TableCell align="center"> {row.deliveriespending}</TableCell>
<TableCell align="center"> {row.deliveriescompleted}</TableCell>
<TableCell align="center"> {row.deliveriescancelled}</TableCell>
<TableCell align="left">
<Tooltip title="kms" placement="top">
<Chip
size="small"
label={parseFloat(row.kms).toFixed(2)}
sx={{
color: '#f44336',
bgcolor: '#ffcdd2',
border: '1px solid #f44336',
mb: 1,
cursor: 'pointer',
minWidth: 80
}}
/>
</Tooltip>
<br />
<Tooltip title="Actual kms" placement="bottom">
<Chip
size="small"
label={parseFloat(row.actualkms).toFixed(2)}
sx={{
color: '#43a047',
bgcolor: '#c8e6c9',
border: '1px solid #43a047',
cursor: 'pointer',
minWidth: 80
}}
/>
</Tooltip>
</TableCell>
<TableCell align="left">
<Tooltip title="Pay on Delivery" placement="top">
<Chip
size="small"
label={formatNumberToRupees(row.payondelivery)}
variant="outlined"
color="error"
sx={{
color: '#f44336',
bgcolor: '#ffcdd2',
border: '1px solid #f44336',
mb: 1,
cursor: 'pointer',
minWidth: 80
}}
/>
</Tooltip>
<br />
<Tooltip title="Pay Later" placement="bottom">
<Chip
size="small"
label={formatNumberToRupees(row.paylater)}
variant="outlined"
color="success"
sx={{
color: '#43a047',
bgcolor: '#c8e6c9',
border: '1px solid #43a047',
cursor: 'pointer',
minWidth: 80
}}
/>
</Tooltip>
</TableCell>
<TableCell align="right">
<Tooltip title="Total Charges" placement="top">
<Chip
size="small"
label={formatNumberToRupees(row.charges)}
sx={{
color: 'primary.main',
bgcolor: '#e1bee7',
border: '1px solid #662582 ',
cursor: 'pointer',
minWidth: 100
}}
/>
</Tooltip>
</TableCell>
<TableCell align="center">
<IconButton
aria-label="expand row"
size="small"
onClick={() => {
getriderlocationsummary(row.locationid);
setOpenRow(openRow === row.locationid ? null : row.locationid);
}}
sx={{
bgcolor: openRow === row.locationid ? 'primary.main' : null,
color: openRow === row.locationid ? 'white' : null,
'&:hover': {
bgcolor: openRow === row.locationid ? 'primary.main' : '#e1bee7'
}
}}
>
{openRow === row.locationid ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</IconButton>
</TableCell>
</TableRow>
{/* ============================================ || collapsive row || ============================================ */}
{openRow === row.locationid && (
<TableRow
sx={{
bgcolor: openRow === row.locationid ? '#f3e5f5' : null,
'&:hover': {
bgcolor: openRow === row.locationid ? '#f3e5f5!important' : null
},
cursor: openRow === row.locationid ? 'pointer' : null
}}
>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={15}>
<Collapse in={openRow === row.locationid} timeout="auto" unmountOnExit>
<Box sx={{ margin: 1 }}>
<Typography variant="h5" gutterBottom component="div">
Riders Summary
</Typography>
<Table size="small" aria-label="purchases">
<TableHead
sx={{
bgcolor: '#f3e5f5',
'&:onhover': {
bgcolor: '#f3e5f5!important'
}
}}
>
<TableRow>
<TableCell>#</TableCell>
<TableCell>Rider</TableCell>
<TableCell align="left">Deliveries</TableCell>
<TableCell align="left">Assigned</TableCell>
<TableCell align="left">Accepted</TableCell>
<TableCell align="left">Picked</TableCell>
<TableCell align="left">Delivered</TableCell>
<TableCell align="center">kms/Actualkms</TableCell>
<TableCell align="center">POD/PLA</TableCell>
<TableCell align="center">Charges</TableCell>
</TableRow>
</TableHead>
<TableBody>
{ridersdata?.map((rider, index) => (
<TableRow key={rider?.tenantname}>
<TableCell padding="none">{index + 1}</TableCell>
<TableCell align="left">
<Stack direction="row" sx={{ ml: -2 }}>
{rider?.firstname}
{rider?.status == 'Active' ? (
<TaskAltIcon fontSize="small" color="success" sx={{ ml: 1 }} />
) : (
<HighlightOffIcon fontSize="small" color="error" sx={{ ml: 1 }} />
)}
</Stack>
</TableCell>
<TableCell align="left">{rider?.deliveries}</TableCell>
<TableCell align="left">{rider?.Assigened}</TableCell>
<TableCell align="left">{rider?.Accepted}</TableCell>
<TableCell align="left">{rider?.Picked}</TableCell>
<TableCell align="left">{rider?.delivered}</TableCell>
<TableCell align="center">
<Tooltip title="kms" placement="top">
<Chip
size="small"
label={rider?.kms}
sx={{
color: '#1976d2',
bgcolor: '#e3f2fd',
mr: 1,
border: '1px solid #1976d2',
cursor: 'pointer',
minWidth: 80
}}
/>
</Tooltip>
<Tooltip title="Actual kms" placement="top">
<Chip
size="small"
label={rider?.actualkms}
sx={{
color: '#ff8f00',
bgcolor: '#ffecb3',
border: '1px solid #ff8f00',
cursor: 'pointer',
minWidth: 80
}}
/>
</Tooltip>
</TableCell>
<TableCell align="center">
<Tooltip title="Pay on Delivery" placement="top">
<Chip
size="small"
label={formatNumberToRupees(rider?.payondelivery)}
sx={{
color: '#f44336',
bgcolor: '#ffcdd2',
border: '1px solid #f44336',
mr: 1,
cursor: 'pointer',
minWidth: 80
}}
/>
</Tooltip>
<Tooltip title="Paylater" placement="top">
<Chip
size="small"
label={formatNumberToRupees(rider?.Paylater)}
sx={{
color: '#43a047',
bgcolor: '#c8e6c9',
border: '1px solid #43a047',
cursor: 'pointer',
minWidth: 80
}}
/>
</Tooltip>
</TableCell>
<TableCell align="center">
<Tooltip title="Amount" placement="top">
<Chip
size="small"
label={formatNumberToRupees(rider?.Deliveryamt)}
sx={{
color: 'primary.main',
bgcolor: '#e1bee7',
border: '1px solid #662582 ',
cursor: 'pointer',
minWidth: 100
}}
/>
</Tooltip>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>
)}
</>
))
) : (
<TableRow>
<TableCell colSpan={17} rowSpan={40}>
<Stack width={'100%'} direction={'row'} justifyContent={'center'}>
<Empty />
</Stack>
</TableCell>
</TableRow>
)}
</TableBody>
{/* ============================================ || total - row || ============================================ */}
<TableRow sx={{ bgcolor: '#e0e0e0' }}>
<TableCell colSpan={2}>
<Typography variant="h5">Total</Typography>
</TableCell>
<TableCell align="center">
<Typography variant="h5">{totalOrders}</Typography>{' '}
</TableCell>
<TableCell align="center">
<Typography variant="h5">{totalOrderPend}</Typography>{' '}
</TableCell>
<TableCell align="center">
<Typography variant="h5">{totalOrderComplete}</Typography>{' '}
</TableCell>
<TableCell align="center">
<Typography variant="h5"> {totalOrderCancel}</Typography>
</TableCell>
<TableCell align="center">
<Typography variant="h5">{totalDeliPend}</Typography>{' '}
</TableCell>
<TableCell align="center">
<Typography variant="h5">{totalDeliComplete}</Typography>{' '}
</TableCell>
<TableCell align="center">
<Typography variant="h5"> {totalDeliCancel}</Typography>
</TableCell>
<TableCell></TableCell>
<TableCell></TableCell>
<TableCell align="right" sx={{ pr: -2 }}>
<Typography variant="h5">{formatNumberToRupees(total)}</Typography>
</TableCell>{' '}
<TableCell></TableCell>
</TableRow>
</Table>
</TableContainer>
</MainCard>
{/* ============================================ || 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={() => setOpen(false)}>
ok
</Button>
</Stack>
</Dialog>
</>
);
}

View File

@@ -8,6 +8,7 @@ import { useTheme } from '@mui/material/styles';
import { SlLocationPin } from 'react-icons/sl'; import { SlLocationPin } from 'react-icons/sl';
import MapWithRoute from './mapWithRoute'; import MapWithRoute from './mapWithRoute';
import { enqueueSnackbar } from 'notistack'; import { enqueueSnackbar } from 'notistack';
import MyLocationIcon from '@mui/icons-material/MyLocation';
// material-ui // material-ui
import { import {
@@ -27,7 +28,6 @@ import {
IconButton, IconButton,
Tooltip, Tooltip,
Chip, Chip,
Paper,
FormControl, FormControl,
OutlinedInput, OutlinedInput,
InputAdornment, InputAdornment,
@@ -72,6 +72,7 @@ function formatNumberToRupees(value) {
// ==============================|| MUI TABLE - ENHANCED ||============================== // // ==============================|| MUI TABLE - ENHANCED ||============================== //
export default function OrdersDetails() { export default function OrdersDetails() {
const tenId = localStorage.getItem('tenantid');
const textFieldRef = useRef(null); const textFieldRef = useRef(null);
const loadMoreRef = useRef(); const loadMoreRef = useRef();
const containerRef = useRef(); const containerRef = useRef();
@@ -88,29 +89,42 @@ export default function OrdersDetails() {
const [riderEnd, setRiderEnd] = useState(); const [riderEnd, setRiderEnd] = useState();
const [mapOpen, setMapOpen] = useState(false); const [mapOpen, setMapOpen] = useState(false);
const [mapTenant, setMapTenant] = useState({}); const [mapTenant, setMapTenant] = useState({});
let [total, settotal] = useState(0);
let [coveredLenght, setCoveredLenght] = useState(0);
let [uncoveredLenght, setUncoveredLenght] = useState(0);
let [cancelLenght, setCancelLenght] = useState(0);
let [assignLenght, setAssignLenght] = useState(0);
let [pickedLenght, setPickedLenght] = useState(0);
let [activeLenght, setActiveLenght] = useState(0);
let [arrivesLenght, setArrivedLenght] = useState(0);
const [currentStatus, setCurrentStatus] = useState('All'); const [currentStatus, setCurrentStatus] = useState('All');
const [statusLabel, setStatuslabel] = useState('All');
const [statusCount, setStatusCount] = useState(0); const [statusCount, setStatusCount] = useState(0);
const [tenantLocations, setTenantlocations] = useState([]);
const [locationId, setLocationId] = useState(0);
const [locoName, setLocoName] = useState('Select Location');
const status = [ const status = [
{ id: 0, status: 'All', statusLow: 'All', count: total }, { id: 0, status: 'All', statusLow: 'All' },
{ id: 1, status: 'Pending', statusLow: 'pending', count: assignLenght }, { id: 1, status: 'Pending', statusLow: 'pending' },
{ id: 2, status: 'Accepted', statusLow: 'accepted', count: uncoveredLenght }, { id: 2, status: 'Accepted', statusLow: 'accepted' },
{ id: 3, status: 'Arrived', statusLow: 'arrived', count: arrivesLenght }, { id: 3, status: 'Arrived', statusLow: 'arrived' },
{ id: 4, status: 'Picked', statusLow: 'picked', count: pickedLenght }, { id: 4, status: 'Picked', statusLow: 'picked' },
{ id: 5, status: 'Active', statusLow: 'active', count: activeLenght }, { id: 5, status: 'Active', statusLow: 'active' },
{ id: 6, status: 'Delivered', statusLow: 'delivered', count: coveredLenght }, { id: 6, status: 'Delivered', statusLow: 'delivered' },
{ id: 7, status: 'Cancelled', statusLow: 'cancelled', count: cancelLenght } { id: 7, status: 'Cancelled', statusLow: 'cancelled' }
]; ];
// ============================================= || gettenantlocations (branches) || =============================================
const gettenantlocations = async (id) => {
try {
const res = await axios.get(`${process.env.REACT_APP_URL}/tenants/gettenantlocations/?tenantid=${id}`);
console.log('gettenantlocations', res.data.details);
if (res.data.details.length == 1) {
setIsLocation(true);
setTenantlocations(res.data.details);
setPickCust(res.data.details[0]);
} else {
setTenantlocations(res.data.details);
}
} catch (err) {
console.log('gettenantlocations', err);
}
};
useEffect(() => {
gettenantlocations(tenId);
}, []);
const getdeliverylogs = async (id) => { const getdeliverylogs = async (id) => {
console.log('deliveryid', id); console.log('deliveryid', id);
try { try {
@@ -162,15 +176,6 @@ export default function OrdersDetails() {
// ==============================|| fetchorderdetails (orders)||============================== // // ==============================|| fetchorderdetails (orders)||============================== //
// const {
// isLoading: isLoadingOrderDetails,
// isError: isErrorOrderDetails, //true or false
// data: rows,
// error: orderDetailsError
// } = useQuery({
// queryKey: [startdate, enddate, currentStatus],
// queryFn: fetchorderdetails
// });
const { const {
data: rowdata, data: rowdata,
isError: isErrorOrderDetails, isError: isErrorOrderDetails,
@@ -181,7 +186,7 @@ export default function OrdersDetails() {
isFetchingNextPage isFetchingNextPage
// status: rowdataStatus // status: rowdataStatus
} = useInfiniteQuery({ } = useInfiniteQuery({
queryKey: [startdate, enddate, currentStatus], queryKey: [startdate, enddate, currentStatus, locationId],
queryFn: fetchorderdetails, queryFn: fetchorderdetails,
getNextPageParam: (lastPage) => lastPage.nextPage getNextPageParam: (lastPage) => lastPage.nextPage
}); });
@@ -212,13 +217,8 @@ export default function OrdersDetails() {
// ==================================== || fetchDeliverySummary || ==================================== // ==================================== || fetchDeliverySummary || ====================================
const { const { data: deliverycount } = useQuery({
data: deliverycount, queryKey: ['deliverycount', startdate, enddate, currentStatus, locationId],
isLoading,
isError,
error
} = useQuery({
queryKey: ['deliverycount', startdate, enddate, currentStatus],
queryFn: fetchDeliverySummary queryFn: fetchDeliverySummary
}); });
@@ -266,7 +266,6 @@ export default function OrdersDetails() {
// ==============================|| fetchAppLocations ||============================== // // ==============================|| fetchAppLocations ||============================== //
if (isLoadingOrderDetails) return <Loader />;
if (isErrorOrderDetails) return 'An error has occurred:(isErrorOrderDetails) ' + orderDetailsError.message; if (isErrorOrderDetails) return 'An error has occurred:(isErrorOrderDetails) ' + orderDetailsError.message;
const filteredOrders = rows.filter((row) => const filteredOrders = rows.filter((row) =>
@@ -345,17 +344,14 @@ export default function OrdersDetails() {
}; };
return ( return (
<> <>
{isLoadingOrderDetails && <Loader />}
<TitleCard title="Orders Details" /> <TitleCard title="Orders Details" />
<Paper content={false} sx={{ border: '1px solid #eeeeee', borderBottom: 'none' }}>
<Stack <MainCard
display={'flex'} content={false}
flexDirection={{ xs: 'column', md: 'row' }} title={
alignItems={'center'} <Stack display={'flex'} flexDirection={'row'} alignItems={'center'} justifyContent={'space-between'} flexWrap="wrap">
justifyContent={'space-between'} <Stack alignItems="flex-start" spacing={1}>
sx={{ p: 2 }}
spacing={1}
>
<Stack direction="column" alignItems="flex-start" spacing={1}>
{startdate && enddate && ( {startdate && enddate && (
<Stack direction="row" spacing={2}> <Stack direction="row" spacing={2}>
<Badge <Badge
@@ -383,15 +379,57 @@ export default function OrdersDetails() {
</Stack> </Stack>
)} )}
{(!startdate || !enddate) && ( {(!startdate || !enddate) && (
<> <div>
<Stack direction="row" spacing={2}> <Stack direction="row" spacing={2}>
<Chip label="Orders-All" color="primary" variant="light" size="small" /> <Chip label="Orders-All" color="primary" variant="light" size="small" />
{/* <Chip label={<Typography noWrap color="secondary">ALL</Typography>} variant="combined" color='warning' size='small' /> */} {/* <Chip label={<Typography noWrap color="secondary">ALL</Typography>} variant="combined" color='warning' size='small' /> */}
</Stack> </Stack>
</> </div>
)} )}
</Stack> </Stack>
<Stack sx={{ display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 2 }}> <Stack sx={{ display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 2 }}>
<Stack direction={'row'} alignItems={'center'} justifyContent={'space-between'}>
{tenantLocations.length == 1 ? (
<TextField
// disabled={!isAppLocation || !isClient}
variant="outlined"
fullWidth
label={'Business Location'}
value={tenantLocations[0].locationname}
focused
sx={{ width: '350px' }}
InputProps={{
style: { color: theme.palette.primary.main },
startAdornment: (
<InputAdornment position="start">
<MyLocationIcon color="primary" />
</InputAdornment>
)
}}
/>
) : (
<Autocomplete
fullWidth
// disabled={!isAppLocation || !isClient}
id="combo-box-demo"
options={tenantLocations || []}
getOptionLabel={(option) => `${option.locationname} (${option.suburb})` || ''}
renderInput={(params) => <TextField {...params} label={locoName} color="primary" />}
sx={{ width: '300px' }}
onChange={(event, value, reason) => {
if (value) {
console.log('Business Locations', value);
setLocationId(value.locationid);
setLocoName(value.locationname);
}
if (reason == 'clear') {
setLocationId(0);
setLocoName('Select Location');
}
}}
/>
)}
</Stack>
<Autocomplete <Autocomplete
sx={{ minWidth: 200 }} sx={{ minWidth: 200 }}
disablePortal disablePortal
@@ -406,7 +444,7 @@ export default function OrdersDetails() {
setCurrentStatus(value.statusLow); setCurrentStatus(value.statusLow);
} }
}} }}
renderInput={(params) => <TextField {...params} label={statusLabel || 'Select Status'} />} renderInput={(params) => <TextField {...params} label={'Select Status'} />}
/> />
<FormControl sx={{ width: 250 }}> <FormControl sx={{ width: 250 }}>
<OutlinedInput <OutlinedInput
@@ -463,9 +501,8 @@ export default function OrdersDetails() {
<CSVExport data={csvData} filename={`Orders_Detail_${dayjs().format('YYYY-MM-DD_HHmmss')}.csv`} /> <CSVExport data={csvData} filename={`Orders_Detail_${dayjs().format('YYYY-MM-DD_HHmmss')}.csv`} />
</Stack> </Stack>
</Stack> </Stack>
</Paper> }
>
<MainCard content={false}>
<TableContainer <TableContainer
onScroll={handleScroll} onScroll={handleScroll}
ref={containerRef} ref={containerRef}

View File

@@ -0,0 +1,7 @@
import React from 'react';
const riderLogs = () => {
return <div>riderLogs</div>;
};
export default riderLogs;

View File

@@ -0,0 +1,679 @@
import { React, useState, useEffect, useRef } from 'react';
import axios from 'axios';
import { useQuery } from '@tanstack/react-query';
import TaskAltIcon from '@mui/icons-material/TaskAlt';
import HighlightOffIcon from '@mui/icons-material/HighlightOff';
import { Empty } from 'antd';
// material-ui
import {
Box,
Divider,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Dialog,
DialogTitle,
Typography,
DialogContent,
Stack,
Button,
IconButton,
Tooltip,
Chip,
Autocomplete,
TextField,
Collapse
} from '@mui/material';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
import dayjs from 'dayjs';
var utc = require('dayjs/plugin/utc');
dayjs.extend(utc);
import { DateRangePicker } from 'mui-daterange-picker';
import {
addDays,
addMonths,
addWeeks,
// addYears,
endOfMonth,
endOfWeek,
// endOfYear,
startOfMonth,
startOfWeek
// startOfYear,
} from 'date-fns';
import { FilterList } from '@mui/icons-material';
// project imports
import MainCard from 'components/MainCard';
import Loader from 'components/Loader';
import TitleCard from '../titleCard';
import { fetchRidersSummary } from '../api/api';
// table filter
function descendingComparator(a, b, orderBy) {
if (b[orderBy] < a[orderBy]) {
return -1;
}
if (b[orderBy] > a[orderBy]) {
return 1;
}
return 0;
}
function getComparator(order, orderBy) {
return order === 'desc' ? (a, b) => descendingComparator(a, b, orderBy) : (a, b) => -descendingComparator(a, b, orderBy);
}
function stableSort(array, comparator) {
const stabilizedThis = array.map((el, index) => [el, index]);
stabilizedThis.sort((a, b) => {
const order = comparator(a[0], b[0]);
if (order !== 0) return order;
return a[1] - b[1];
});
return stabilizedThis.map((el) => el[0]);
}
function formatNumberToRupees(value) {
return new Intl.NumberFormat('en-IN', {
style: 'currency',
currency: 'INR',
minimumFractionDigits: 2
}).format(value);
}
// ==============================|| MUI TABLE - ENHANCED ||============================== //
export default function RidersSummary() {
// const [rows, setRows] = useState([]);
const [order, setOrder] = useState('asc');
const [orderBy, setOrderBy] = useState('calories');
const [selected, setSelected] = useState([]);
const [page, setPage] = useState(0);
const [dense] = useState(false);
const [rowsPerPage, setRowsPerPage] = useState(10);
const [selectedValue, setSelectedValue] = useState([]);
const [startdate, setStartdate] = useState(dayjs().format('YYYY-MM-DD'));
const [enddate, setEnddate] = useState(dayjs().format('YYYY-MM-DD'));
const [locaName, setLocoName] = useState('All');
const [open, setOpen] = useState(false);
const [dateselect, setDateselect] = useState('select');
const [tabstatus1, setTabstatus1] = useState('Today');
const [datestatus, setDatestatus] = useState('Today');
const [total, settotal] = useState(0);
const [id, setid] = useState(-1);
const [tenantData, setTenantData] = useState([]);
const [openRow, setOpenRow] = useState(null); // Initially no row is open
const [searchword, setSearchword] = useState('');
const textFieldRef = useRef(null);
const [appId, setAppId] = useState(localStorage.getItem('applocationid'));
const [locations, setLocations] = useState('Select Location');
const userid = localStorage.getItem('userid');
/* ============================================= || handleKeyPress (ctrl+k)| ============================================= */
useEffect(() => {
const handleKeyPress = (event) => {
if (event.key === 'k' && (event.metaKey || event.ctrlKey)) {
event.preventDefault();
textFieldRef.current.focus();
}
if (event.key === 'Escape' && document.activeElement === textFieldRef.current) {
// Remove focus from the TextField
textFieldRef.current.blur();
}
};
document.addEventListener('keydown', handleKeyPress);
return () => {
document.removeEventListener('keydown', handleKeyPress);
};
}, []);
// ==============================|| fetchRidersSummary (riders summary)||============================== //
const {
isLoading: isLoadingReports,
isError: isErrorReports, //true or false
data: rows,
error: reportsError
} = useQuery({
queryKey: [appId, startdate, enddate],
queryFn: fetchRidersSummary
});
// ==============================|| calculate||============================== //
const calculate = async () => {
let calculatedTotal = 0;
rows &&
rows.forEach((row, index) => {
console.log(index, row.Deliveryamt);
calculatedTotal += row.Deliveryamt;
});
// Update the state after the calculation is done
settotal(calculatedTotal);
console.log('calculatedTotal', calculatedTotal);
};
useEffect(() => {
calculate();
}, [rows]);
if (isLoadingReports) return <Loader />;
if (isErrorReports) return 'An error has occurred:(isErrorReports) ' + reportsError.message;
// ==============================|| fetchTenantSummary by rider (rider summary)||============================== //
const fetchTenantSummary = async (riderUserid) => {
try {
const tenantRes = await axios.get(
`${process.env.REACT_APP_URL}/deliveries/getreportsummary/?&fromdate=${startdate}&todate=${enddate}&userid=${riderUserid}`
);
console.log('tenantRes', tenantRes.data.details);
setTenantData(tenantRes.data.details);
} catch (error) {
console.log('tenantRes', error);
}
};
const handleClick = (event, name) => {
const selectedIndex = selected.indexOf(name);
let newSelected = [];
if (selectedIndex === -1) {
newSelected = newSelected.concat(selected, name);
} else if (selectedIndex === 0) {
newSelected = newSelected.concat(selected.slice(1));
} else if (selectedIndex === selected.length - 1) {
newSelected = newSelected.concat(selected.slice(0, -1));
} else if (selectedIndex > 0) {
newSelected = newSelected.concat(selected.slice(0, selectedIndex), selected.slice(selectedIndex + 1));
}
const selectedRowData = rows.filter((row) => newSelected.includes(row.name));
setSelectedValue(selectedRowData);
setSelected(newSelected);
};
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event?.target.value, 10));
setPage(0);
};
const isSelected = (name) => selected.indexOf(name) !== -1;
// Avoid a layout jump when reaching the last page with empty rows.
const emptyRows = page > 0 ? Math.max(0, (1 + page) * rowsPerPage - rows.length) : 0;
return (
<>
<TitleCard title="Riders Summary" />
<MainCard
content={false}
title={
<Stack display={'flex'} flexDirection={'row'} alignItems={'center'} justifyContent={'space-between'} flexWrap={'wrap'} gap={1}>
<Stack direction="column" alignItems="flex-start" spacing={1} sx={{}}>
{startdate && enddate && (
<Stack direction="row" spacing={2} flexWrap={'wrap'} gap={1}>
<Chip label={`Orders-${datestatus}`} color="primary" variant="light" size="small" />
<Chip
label={
<Typography noWrap color="secondary">
{dayjs(startdate).format('DD/MM/YYYY')} - {dayjs(enddate).format('DD/MM/YYYY')}
</Typography>
}
variant="combined"
color="warning"
size="small"
/>
</Stack>
)}
{(!startdate || !enddate) && (
<>
<Stack direction="row" spacing={2}>
<Chip label="Orders-All" color="primary" variant="light" size="small" />
{/* <Chip label={<Typography noWrap color="secondary">ALL</Typography>} variant="combined" color='warning' size='small' /> */}
</Stack>
</>
)}
</Stack>
</Stack>
}
>
{/* table */}
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell>S.No </TableCell>
<TableCell> Rider</TableCell>
<TableCell> Deliveries</TableCell>
<TableCell> Assigned</TableCell>
<TableCell> Accepted</TableCell>
<TableCell>Picked </TableCell>
<TableCell>Delivered </TableCell>
<TableCell>KMS/Actualkms </TableCell>
<TableCell> POD/PLA</TableCell>
<TableCell> Charges</TableCell>
<TableCell>Action </TableCell>
</TableRow>
</TableHead>
{/* ============================================ || TableBody || ============================================ */}
<TableBody>
{rows.length === 0 && (
<TableRow>
<TableCell colSpan={11}>
<Stack width={'100%'} direction={'row'} justifyContent={'center'}>
<Empty />
</Stack>
</TableCell>
</TableRow>
)}
{stableSort(rows, getComparator(order, orderBy))
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row, index) => {
if (typeof row === 'number') return null;
const isItemSelected = isSelected(row.name);
const labelId = `enhanced-table-checkbox-${index}`;
return (
rows.length !== 0 && (
<>
{/* // ============================================ || tablerow 1 || ============================================ */}
<TableRow
hover
onClick={(event) => handleClick(event, row.name)}
role="checkbox"
aria-checked={isItemSelected}
tabIndex={-1}
key={row.tenantname}
selected={isItemSelected}
sx={{
bgcolor: openRow === row.userid ? '#e1bee7' : null,
'&:hover': {
bgcolor: openRow === row.userid ? '#e1bee7!important' : null
},
cursor: openRow === row.userid ? 'pointer' : null
}}
>
<TableCell component="th" id={labelId} scope="row" padding="none">
{index + 1}
</TableCell>
<TableCell align="left">
<Stack direction="row" sx={{ ml: -2 }}>
{row.firstname}
{row.status == 'Active' ? (
<TaskAltIcon fontSize="small" color="success" sx={{ ml: 1 }} />
) : (
<HighlightOffIcon fontSize="small" color="error" sx={{ ml: 1 }} />
)}
</Stack>
</TableCell>
<TableCell align="left">{row.deliveries}</TableCell>
<TableCell align="left">{row.Assigened}</TableCell>
<TableCell align="left">{row.Accepted}</TableCell>
<TableCell align="left">{row.Picked}</TableCell>
<TableCell align="left">{row.delivered}</TableCell>
<TableCell align="left">
<Stack direction={'row'}>
<Tooltip title="kms" placement="top">
<Chip
size="small"
label={row.kms}
sx={{
color: '#1976d2',
bgcolor: '#e3f2fd',
mr: 1,
border: '1px solid #1976d2',
cursor: 'pointer',
minWidth: 80
}}
/>
</Tooltip>
<Tooltip title="Actual kms" placement="bottom">
<Chip
size="small"
label={row.actualkms}
sx={{
color: '#ff8f00',
bgcolor: '#ffecb3',
border: '1px solid #ff8f00',
cursor: 'pointer',
minWidth: 80
}}
/>
</Tooltip>
</Stack>
</TableCell>
<TableCell align="right">
<Stack direction={'row'}>
<Tooltip title="Pay on Delivery" placement="top">
<Chip
size="small"
label={formatNumberToRupees(row.payondelivery)}
sx={{
color: '#f44336',
bgcolor: '#ffcdd2',
border: '1px solid #f44336',
cursor: 'pointer',
minWidth: 80,
mr: 1
}}
/>
</Tooltip>
<Tooltip title="Pay Later" placement="bottom">
<Chip
size="small"
label={formatNumberToRupees(row.Paylater)}
sx={{
color: '#43a047',
bgcolor: '#c8e6c9',
border: '1px solid #43a047',
cursor: 'pointer',
minWidth: 80
}}
/>
</Tooltip>
</Stack>
</TableCell>
<TableCell align="right">
<Tooltip title="Total Charges" placement="top">
<Chip
size="small"
label={formatNumberToRupees(row.Deliveryamt)}
sx={{
color: 'primary.main',
bgcolor: '#e1bee7',
border: '1px solid #662582 ',
cursor: 'pointer',
minWidth: 100
}}
/>
</Tooltip>
</TableCell>
<TableCell align="center">
<IconButton
aria-label="expand row"
size="small"
onClick={() => {
fetchTenantSummary(row.userid);
setOpenRow(openRow === row.userid ? null : row.userid);
}}
sx={{
bgcolor: openRow === row.userid ? 'primary.main' : null,
color: openRow === row.userid ? 'white' : null,
'&:hover': {
bgcolor: openRow === row.userid ? 'primary.main' : '#e1bee7'
}
}}
>
{openRow === row.userid ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</IconButton>
</TableCell>
</TableRow>
{/* // ============================================ || collapsive row || ============================================ */}
{openRow === row.userid && (
<TableRow
sx={{
bgcolor: openRow === row.userid ? '#f3e5f5' : null,
'&:hover': {
bgcolor: openRow === row.userid ? '#f3e5f5!important' : null
},
cursor: openRow === row.userid ? 'pointer' : null
}}
>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={15}>
<Collapse
// in={openRow[row.tenantname]}
in={true}
timeout="auto"
unmountOnExit
>
<Box sx={{ margin: 1 }}>
<Typography variant="h5" gutterBottom component="div">
Tenant Summary
</Typography>
<Table size="small" aria-label="purchases">
<TableHead
sx={{
bgcolor: '#f3e5f5',
'&:onhover': {
bgcolor: '#f3e5f5!important'
}
}}
>
<TableRow>
<TableCell>#</TableCell>
<TableCell>Client</TableCell>
<TableCell align="left">All</TableCell>
<TableCell align="left">Pending</TableCell>
<TableCell align="left">Completed</TableCell>
<TableCell align="left">Cancelled</TableCell>
<TableCell align="center">Kms/Actual Kms</TableCell>
<TableCell align="center">POD / PLA</TableCell>
<TableCell align="center">Amount</TableCell>
</TableRow>
</TableHead>
<TableBody>
{tenantData.map((row, index) => (
<TableRow
hover
onClick={(event) => handleClick(event, row.name)}
role="checkbox"
aria-checked={isItemSelected}
tabIndex={-1}
key={row.tenantname}
selected={isItemSelected}
>
{/* <TableCell sx={{ pl: 3 }} padding="checkbox">
<Checkbox
color="primary"
checked={isItemSelected}
inputProps={{
"aria-labelledby": labelId,
}}
/>
</TableCell> */}
<TableCell component="th" id={labelId} scope="row" padding="none">
{index + 1}
</TableCell>
<TableCell align="left">
<Stack direction="row" sx={{ ml: -2 }}>
{row.tenantname}
</Stack>
</TableCell>
<TableCell align="left">{row.totalorders}</TableCell>
<TableCell align="left">{row.deliveriespending}</TableCell>
<TableCell align="left">{row.deliveriescompleted}</TableCell>
<TableCell align="left">{row.deliveriescancelled}</TableCell>
<TableCell align="center">
<Chip
size="small"
label={row.kms}
sx={{
color: '#1976d2',
bgcolor: '#e3f2fd',
mr: 1,
border: '1px solid #1976d2',
minWidth: 80
}}
/>
<Chip
size="small"
label={row.actualkms}
sx={{
color: '#ff8f00',
bgcolor: '#ffecb3',
border: '1px solid #ff8f00',
minWidth: 80
}}
/>
</TableCell>
<TableCell align="center">
<Chip
size="small"
label={formatNumberToRupees(row.payondelivery)}
sx={{
color: '#f44336',
bgcolor: '#ffcdd2',
border: '1px solid #f44336',
minWidth: 80
}}
/>{' '}
<Chip
size="small"
label={formatNumberToRupees(row.paylater)}
sx={{
color: '#43a047',
bgcolor: '#c8e6c9',
border: '1px solid #43a047',
minWidth: 80
}}
/>
</TableCell>
<TableCell align="center">
<Chip
size="small"
label={formatNumberToRupees(row.charges)}
sx={{
color: 'primary.main',
bgcolor: '#e1bee7',
border: '1px solid #662582 ',
minWidth: 100
}}
/>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>
)}
</>
)
);
})}
{emptyRows > 0 && (
<TableRow sx={{ height: (dense ? 33 : 53) * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
</Table>
</TableContainer>
<Divider />
<Stack direction={'row'} sx={{ display: 'flex', justifyContent: 'end', px: 1, py: 2 }}>
<Typography variant="h5">Total :</Typography>
<Typography variant="h5" sx={{ ml: 5, mr: 1.5 }}>
{formatNumberToRupees(total)}
</Typography>
</Stack>
{/* table pagination */}
{/* <TablePagination
rowsPerPageOptions={[10, 25, 50]}
component="div"
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/> */}
</MainCard>
<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') {
setDateselect('all');
setStartdate('');
setEnddate('');
setOpen(false);
} else {
setDateselect('select');
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={() => setOpen(false)}>
ok
</Button>
</Stack>
</Dialog>
</>
);
}

View File

@@ -4,7 +4,8 @@ import { lazy } from 'react';
import MainLayout from 'layout/MainLayout'; import MainLayout from 'layout/MainLayout';
import CommonLayout from 'layout/CommonLayout'; import CommonLayout from 'layout/CommonLayout';
import Loadable from 'components/Loadable'; import Loadable from 'components/Loadable';
// import AuthGuard from 'utils/route-guard/AuthGuard'; import AuthGuard from 'utils/route-guard/AuthGuard';
import { element } from 'prop-types';
// pages routing // pages routing
const MaintenanceError = Loadable(lazy(() => import('pages/maintenance/404'))); const MaintenanceError = Loadable(lazy(() => import('pages/maintenance/404')));
@@ -15,7 +16,6 @@ const MaintenanceComingSoon = Loadable(lazy(() => import('pages/maintenance/comi
// render - sample page // render - sample page
const SamplePage = Loadable(lazy(() => import('pages/extra-pages/sample-page'))); const SamplePage = Loadable(lazy(() => import('pages/extra-pages/sample-page')));
const Login = Loadable(lazy(() => import('pages/nearle/login'))); const Login = Loadable(lazy(() => import('pages/nearle/login')));
const Dashboard = Loadable(lazy(() => import('pages/nearle/dashboard')));
const Customers = Loadable(lazy(() => import('pages/nearle/clients/customers'))); const Customers = Loadable(lazy(() => import('pages/nearle/clients/customers')));
@@ -25,12 +25,15 @@ const Details = Loadable(lazy(() => import('pages/nearle/orders/details')));
const Accountsettings = Loadable(lazy(() => import('pages/nearle/accountsettings'))); const Accountsettings = Loadable(lazy(() => import('pages/nearle/accountsettings')));
// const Createorder = Loadable(lazy(() => import('pages/nearle/orders/createorder'))); // const Createorder = Loadable(lazy(() => import('pages/nearle/orders/createorder')));
const Createclient = Loadable(lazy(() => import('pages/nearle/clients/createCustomer'))); const CreateCustomer = Loadable(lazy(() => import('pages/nearle/clients/createCustomer')));
const Createorder1 = Loadable(lazy(() => import('pages/nearle/orders/createorder1'))); const Createorder1 = Loadable(lazy(() => import('pages/nearle/orders/createorder1')));
const MultipleOrders = Loadable(lazy(() => import('pages/nearle/orders/multipleOrders'))); const MultipleOrders = Loadable(lazy(() => import('pages/nearle/orders/multipleOrders')));
const OrderSummary = Loadable(lazy(() => import('pages/nearle/reports/orderSummary')));
const OrdersDetails = Loadable(lazy(() => import('pages/nearle/reports/ordersDetails'))); const OrdersDetails = Loadable(lazy(() => import('pages/nearle/reports/ordersDetails')));
const RiderSummary = Loadable(lazy(() => import('pages/nearle/reports/ridersummary')));
const RiderLogs = Loadable(lazy(() => import('pages/nearle/reports/riderLogs')));
const Invoice = Loadable(lazy(() => import('pages/nearle/invoice/invoice'))); const Invoice = Loadable(lazy(() => import('pages/nearle/invoice/invoice')));
const InvoicePreview = Loadable(lazy(() => import('../pages/nearle/invoice/invoicePreview'))); const InvoicePreview = Loadable(lazy(() => import('../pages/nearle/invoice/invoicePreview')));
@@ -49,48 +52,81 @@ const MainRoutes = {
), ),
children: [ children: [
{ {
path: 'dashboard', path: 'nearle',
element: <Dashboard /> children: [
{
path: 'orders',
element: <Orders />,
children: [
// use Outlet in orders page to render the child, because order render in app, but chidren createorder, multipleorder have nowhere, outlet make parent as to render
{
path: 'create',
element: <Createorder1 />
},
{
path: 'createorders',
element: <MultipleOrders />
}
]
}, },
{ {
path: 'customers', path: 'customers',
children: [
{
path: '',
element: <Customers /> element: <Customers />
}, },
{ {
path: 'orders', path: 'create',
element: <Orders /> element: <CreateCustomer />
}
]
}, },
{
path: 'reports',
children: [
{
path: 'ordersummary',
element: <OrderSummary />
},
{
path: 'ordersdetails',
element: <OrdersDetails />
},
{
path: 'ridersummary',
element: <RiderSummary />
},
{
path: 'riderlogs',
element: <RiderLogs />
}
]
},
{
path: 'invoice',
children: [
{
path: '',
element: <Invoice />
},
{
path: 'preview',
element: <InvoicePreview />
}
]
}
]
},
{ {
path: 'accountsettings', path: 'accountsettings',
element: <Accountsettings /> element: <Accountsettings />
}, },
{
path: 'orders/create',
element: <Createorder1 />
},
{
path: 'orders/createorders',
element: <MultipleOrders />
},
{ {
path: 'orders/details', path: 'orders/details',
element: <Details /> element: <Details />
},
{
path: 'customers/create',
element: <Createclient />
},
{
path: 'reports/ordersdetails',
element: <OrdersDetails />
},
{
path: 'invoice',
element: <Invoice />
},
{
path: 'invoice/preview',
element: <InvoicePreview />
} }
] ]
}, },