overall commit
This commit is contained in:
76
src/pages/nearle/reports/RiderLocationMap.js
Normal file
76
src/pages/nearle/reports/RiderLocationMap.js
Normal file
@@ -0,0 +1,76 @@
|
||||
import { Button } from '@mui/material';
|
||||
import { LoadScriptNext, GoogleMap, Marker, OverlayView } from '@react-google-maps/api';
|
||||
|
||||
const containerStyle = {
|
||||
width: '100%',
|
||||
height: 'calc(100vh - 150px)'
|
||||
};
|
||||
|
||||
export default function RiderLocationMap({ riderLocations }) {
|
||||
console.log('riderLocations', riderLocations);
|
||||
|
||||
const center = {
|
||||
lat: Number(riderLocations?.[0]?.latitude || 11.0056),
|
||||
lng: Number(riderLocations?.[0]?.longitude || 76.9661)
|
||||
};
|
||||
const GreenIcon = {
|
||||
url: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png',
|
||||
scaledSize: new window.google.maps.Size(25, 41),
|
||||
anchor: new window.google.maps.Point(12, 41)
|
||||
};
|
||||
|
||||
const RedIcon = {
|
||||
url: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png',
|
||||
scaledSize: new window.google.maps.Size(25, 41),
|
||||
anchor: new window.google.maps.Point(12, 41)
|
||||
};
|
||||
|
||||
return (
|
||||
<LoadScriptNext googleMapsApiKey={process.env.REACT_APP_GOOGLE_MAPS_API_KEY}>
|
||||
<GoogleMap mapContainerStyle={containerStyle} zoom={12} center={center}>
|
||||
{riderLocations &&
|
||||
riderLocations?.map((r, index) => {
|
||||
const lat = Number(r.latitude);
|
||||
const lng = Number(r.longitude);
|
||||
return (
|
||||
<div key={index}>
|
||||
{/* Marker */}
|
||||
<Marker
|
||||
position={{ lat, lng }}
|
||||
icon={r.status == 'active' ? GreenIcon : RedIcon}
|
||||
label={{
|
||||
fontSize: '14px',
|
||||
fontWeight: 'bold'
|
||||
}}
|
||||
/>
|
||||
<OverlayView position={{ lat, lng }} mapPaneName={OverlayView.OVERLAY_LAYER}>
|
||||
<div
|
||||
style={{
|
||||
background: 'none',
|
||||
color: 'green',
|
||||
padding: '2px 8px',
|
||||
borderRadius: '4px',
|
||||
fontSize: '12px',
|
||||
fontWeight: 600,
|
||||
whiteSpace: 'nowrap',
|
||||
transform: 'translate(-50%, -140%)',
|
||||
pointerEvents: 'none',
|
||||
ml: 20
|
||||
}}
|
||||
>
|
||||
<Button variant="contained" color="primary" size="small">
|
||||
{` ${r.username} `}
|
||||
{/* <br /> */}
|
||||
{/* {`${r.contactno || '##### ##### '} `} */}
|
||||
<br />
|
||||
{`(${r.orderid || ''}) `}
|
||||
</Button>
|
||||
</div>
|
||||
</OverlayView>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</GoogleMap>
|
||||
</LoadScriptNext>
|
||||
);
|
||||
}
|
||||
@@ -32,7 +32,8 @@ import {
|
||||
FormControl,
|
||||
OutlinedInput,
|
||||
InputAdornment,
|
||||
Collapse
|
||||
Collapse,
|
||||
Badge
|
||||
} from '@mui/material';
|
||||
import ClearIcon from '@mui/icons-material/Clear';
|
||||
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
|
||||
@@ -64,6 +65,7 @@ import { useTheme } from '@mui/material/styles';
|
||||
import TitleCard from '../titleCard';
|
||||
import { getreportlocationsummary, gettenantlocations } from '../api/api';
|
||||
import CircularLoader from 'components/nearle_components/CircularLoader';
|
||||
import { getValueColor } from 'components/nearle_components/getValueColor';
|
||||
|
||||
function formatNumberToRupees(value) {
|
||||
return new Intl.NumberFormat('en-IN', {
|
||||
@@ -104,12 +106,20 @@ export default function OrdersReport() {
|
||||
const [totalDeliComplete, setTotalDeliComplete] = useState(0);
|
||||
const [totalDeliCancel, setTotalDeliCancel] = useState(0);
|
||||
const [searchword, setSearchword] = useState('');
|
||||
const [debouncedSearch, setDebouncedSearch] = useState('');
|
||||
const textFieldRef = useRef(null);
|
||||
const [ridersdata, setRidersdata] = useState(null);
|
||||
const [selectedLocation, setSelectedLocation] = useState(null);
|
||||
const [locationId, setLocationId] = useState(0);
|
||||
const [searchLocation, setSearchLocation] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedSearch(searchword);
|
||||
}, 400);
|
||||
|
||||
return () => clearTimeout(handler);
|
||||
}, [searchword]);
|
||||
useEffect(() => {
|
||||
console.log('openRow', openRow);
|
||||
}, [openRow]);
|
||||
@@ -154,7 +164,7 @@ export default function OrdersReport() {
|
||||
data: rows,
|
||||
error: reportsError
|
||||
} = useQuery({
|
||||
queryKey: [startdate, enddate, locationId],
|
||||
queryKey: [startdate, enddate, locationId, debouncedSearch],
|
||||
queryFn: getreportlocationsummary
|
||||
});
|
||||
// ==============================|| getriderlocationsummary by tenid (orders summary)||============================== //
|
||||
@@ -230,7 +240,9 @@ export default function OrdersReport() {
|
||||
<Stack>
|
||||
{startdate && enddate && (
|
||||
<Stack direction="row" spacing={2} flexWrap={'wrap'} gap={1}>
|
||||
<Chip label={`Orders-${datestatus}`} color="primary" variant="light" size="small" />
|
||||
<Badge badgeContent={rows?.length || 0} color="primary">
|
||||
<Chip label={`Location-${datestatus}`} color="primary" variant="light" size="small" />
|
||||
</Badge>
|
||||
<Chip
|
||||
label={
|
||||
<Typography noWrap color="secondary">
|
||||
@@ -411,22 +423,40 @@ export default function OrdersReport() {
|
||||
{index + 1}
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
<Stack direction="row" sx={{ ml: -2 }}>
|
||||
{row.locationname}
|
||||
<Stack sx={{ ml: -2 }}>
|
||||
<Typography> {row.locationname}</Typography>
|
||||
<Typography variant="body2">Id : {row.locationid}</Typography>
|
||||
</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="center" sx={{ color: getValueColor(row.totalorders) }}>
|
||||
{row.totalorders}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(row.Orderspending) }}>
|
||||
{row.Orderspending}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(row.orderscompleted) }}>
|
||||
{row.orderscompleted}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(row.orderscancelled) }}>
|
||||
{row.orderscancelled}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(row.deliveriespending) }}>
|
||||
{' '}
|
||||
{row.deliveriespending}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(row.deliveriescompleted) }}>
|
||||
{' '}
|
||||
{row.deliveriescompleted}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(row.deliveriescancelled) }}>
|
||||
{' '}
|
||||
{row.deliveriescancelled}
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
<Tooltip title="kms" placement="top">
|
||||
<Tooltip title="Cumulative Kms" placement="top">
|
||||
<Chip
|
||||
size="small"
|
||||
label={parseFloat(row.kms).toFixed(2)}
|
||||
label={parseFloat(row.cumulativekms).toFixed(2)}
|
||||
sx={{
|
||||
color: '#f44336',
|
||||
bgcolor: '#ffcdd2',
|
||||
@@ -596,19 +626,35 @@ export default function OrdersReport() {
|
||||
)}
|
||||
</Stack>
|
||||
</TableCell>
|
||||
<TableCell align="center">{rider?.totalorders}</TableCell>
|
||||
<TableCell align="center">{rider?.pending}</TableCell>
|
||||
<TableCell align="center">{rider?.assigned}</TableCell>
|
||||
<TableCell align="center">{rider?.accepted}</TableCell>
|
||||
<TableCell align="center">{rider?.picked}</TableCell>
|
||||
<TableCell align="center">{rider?.arrived}</TableCell>
|
||||
<TableCell align="center">{rider?.skipped}</TableCell>
|
||||
<TableCell align="center">{rider?.delivered}</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(rider.totalorders) }}>
|
||||
{rider?.totalorders}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(rider.pending) }}>
|
||||
{rider?.pending}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(rider.assigned) }}>
|
||||
{rider?.assigned}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(rider.accepted) }}>
|
||||
{rider?.accepted}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(rider.picked) }}>
|
||||
{rider?.picked}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(rider.arrived) }}>
|
||||
{rider?.arrived}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(rider.skipped) }}>
|
||||
{rider?.skipped}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(rider.delivered) }}>
|
||||
{rider?.delivered}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
{/* <Tooltip title="kms" placement="top"> */}
|
||||
<Chip
|
||||
size="small"
|
||||
label={rider?.kms}
|
||||
label={rider?.cumulativekms}
|
||||
sx={{
|
||||
color: '#1976d2',
|
||||
bgcolor: '#e3f2fd',
|
||||
|
||||
@@ -1,209 +1,322 @@
|
||||
import * as React from 'react';
|
||||
import { useState } from 'react';
|
||||
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
||||
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
|
||||
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
// material-ui
|
||||
import React, { useState, useEffect, Fragment } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Drawer,
|
||||
IconButton,
|
||||
Toolbar,
|
||||
Typography,
|
||||
AppBar,
|
||||
useMediaQuery,
|
||||
Divider,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
FormControl,
|
||||
OutlinedInput,
|
||||
InputAdornment,
|
||||
Chip,
|
||||
Stack
|
||||
List,
|
||||
ListItem,
|
||||
ListItemText,
|
||||
useTheme,
|
||||
ListItemAvatar,
|
||||
Stack,
|
||||
Button,
|
||||
Checkbox,
|
||||
Skeleton,
|
||||
Backdrop,
|
||||
Chip
|
||||
} from '@mui/material';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
var utc = require('dayjs/plugin/utc');
|
||||
dayjs.extend(utc);
|
||||
import { SearchOutlined, CloseOutlined } from '@ant-design/icons';
|
||||
import MenuIcon from '@mui/icons-material/Menu';
|
||||
import SearchBar from 'components/nearle_components/SearchBar';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import Loader from 'components/Loader';
|
||||
// project imports
|
||||
|
||||
import RiderLocationMap from './RiderLocationMap';
|
||||
import MainCard from 'components/MainCard';
|
||||
import { Empty } from 'antd';
|
||||
import TitleCard from '../titleCard';
|
||||
import { fetchAppLocations, fetchRidersLogs } from '../api/api';
|
||||
import dayjs from 'dayjs';
|
||||
import TaskAltIcon from '@mui/icons-material/TaskAlt';
|
||||
|
||||
function formatDate(dateString) {
|
||||
const date = dayjs(dateString);
|
||||
const formattedDate = date.format('DD-MM-YYYY ');
|
||||
return formattedDate;
|
||||
}
|
||||
import error500 from 'assets/images/maintenance/Error500.png';
|
||||
import { fetchRidersLogs } from '../api/api';
|
||||
import CircularLoader from 'components/nearle_components/CircularLoader';
|
||||
|
||||
const formatTime = (timeString) =>
|
||||
new Date('2024-01-01T' + timeString + 'Z').toLocaleTimeString('en-US', {
|
||||
timeZone: 'UTC',
|
||||
hour12: true,
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
const drawerWidth = 350;
|
||||
|
||||
// ==============================|| RidersLogs ||============================== //
|
||||
|
||||
export default function RidersLogs() {
|
||||
const tenantid = localStorage.getItem('tenantid');
|
||||
const [rowsPerPage, setRowsPerPage] = useState(10);
|
||||
const [startdate, setStartdate] = useState(dayjs().format('YYYY-MM-DD'));
|
||||
const [searchword, setSearchword] = useState('');
|
||||
const [showClose, SetShowClose] = useState(false);
|
||||
|
||||
/* ============================================= || fetchRidersLogs| ============================================= */
|
||||
const RidersLogs = () => {
|
||||
const theme = useTheme();
|
||||
const isDesktop = useMediaQuery('(min-width:900px)');
|
||||
const [open, setOpen] = useState(false);
|
||||
const [selectedRiders, setSelectedRiders] = useState([]);
|
||||
const [riderSearch, setRiderSearch] = useState('');
|
||||
const appId = 1;
|
||||
const {
|
||||
data: rows = [], // Default to empty array
|
||||
isLoading: IsRiderLogsLoading,
|
||||
isError: IsRiderLogsError,
|
||||
error: RiderLogsError
|
||||
data: riders,
|
||||
isLoading: ridersIsLoading,
|
||||
isFetching: riderIsFetching,
|
||||
refetch: riderLogsRefetch,
|
||||
error: riderLogsError
|
||||
} = useQuery({
|
||||
queryKey: [tenantid, startdate], // Meaningful query key
|
||||
queryKey: [appId, dayjs().format('YYYY-MM-DD'), riderSearch],
|
||||
queryFn: fetchRidersLogs,
|
||||
enabled: !!tenantid && !!startdate, // Fetch only if appId & startdate exist
|
||||
refetchInterval: 300000 // Auto-fetch every 5 minutes
|
||||
refetchInterval: 5 * 60 * 1000
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
setRowsPerPage(rows?.length + 1);
|
||||
}, [rows]);
|
||||
{
|
||||
IsRiderLogsError && console.log('RiderLogsError', RiderLogsError);
|
||||
}
|
||||
useEffect(() => {
|
||||
console.log('riders', riders);
|
||||
// const sortedRiders = riders?.sort((a, b) => a.firstname.localeCompare(b.firstname));
|
||||
setSelectedRiders(riders);
|
||||
}, [riders]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('selectedRiders', selectedRiders);
|
||||
}, [selectedRiders]);
|
||||
|
||||
useEffect(() => {
|
||||
setOpen(isDesktop);
|
||||
}, [isDesktop]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{IsRiderLogsLoading && <Loader />}
|
||||
<TitleCard title="Riders Logs" />
|
||||
<MainCard
|
||||
content={false}
|
||||
title={
|
||||
<Stack display={'flex'} flexDirection={'row'} alignItems={'center'} justifyContent={'space-between'} flexWrap={'wrap'} gap={1}>
|
||||
<Stack>
|
||||
<FormControl sx={{ width: 250 }}>
|
||||
<OutlinedInput
|
||||
sx={{ background: 'white' }}
|
||||
size="medium"
|
||||
id="header-search"
|
||||
startAdornment={
|
||||
<InputAdornment position="start" sx={{ mr: -0.5 }}>
|
||||
<SearchOutlined />
|
||||
</InputAdornment>
|
||||
<Fragment>
|
||||
{
|
||||
<Backdrop
|
||||
sx={{
|
||||
color: '#fff',
|
||||
zIndex: (theme) => theme.zIndex.drawer + 1
|
||||
}}
|
||||
open={ridersIsLoading || riderIsFetching} // when loader = true, backdrop covers the page
|
||||
>
|
||||
<CircularLoader color="inherit" />
|
||||
</Backdrop>
|
||||
}
|
||||
<MainCard content={false}>
|
||||
<Box sx={{ display: 'flex', width: '100%', height: '100%', position: 'relative' }}>
|
||||
{/* Drawer */}
|
||||
<Drawer
|
||||
variant={isDesktop ? 'persistent' : 'temporary'}
|
||||
open={open}
|
||||
onClose={() => !isDesktop && setOpen(false)}
|
||||
ModalProps={{ keepMounted: true }}
|
||||
sx={{
|
||||
'& .MuiDrawer-paper': {
|
||||
width: drawerWidth,
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
top: 0,
|
||||
height: '100%',
|
||||
overflowY: 'auto',
|
||||
transition: 'transform 0.35s ease-in-out',
|
||||
zIndex: 13
|
||||
}
|
||||
}}
|
||||
>
|
||||
{/* Search */}
|
||||
<Box sx={{ position: 'sticky', top: 0, zIndex: 1 }}>
|
||||
<SearchBar
|
||||
value={riderSearch}
|
||||
placeholder="Search Rider"
|
||||
onChange={(e) => setRiderSearch(e.target.value)}
|
||||
sx={{
|
||||
height: 60,
|
||||
bgcolor: 'white',
|
||||
'& .MuiOutlinedInput-notchedOutline': {
|
||||
borderBottom: '1px solid',
|
||||
borderColor: theme.palette.secondary.light
|
||||
}
|
||||
endAdornment={
|
||||
showClose && (
|
||||
<InputAdornment position="end" sx={{ mr: -0.5 }}>
|
||||
<CloseOutlined
|
||||
onClick={() => {
|
||||
setSearchword('');
|
||||
SetShowClose(false);
|
||||
}}
|
||||
}}
|
||||
/>
|
||||
<List>
|
||||
<ListItem sx={{ cursor: 'pointer', '&:hover': { bgcolor: theme.palette.secondary.lighter }, bgcolor: 'white', mt: -1 }}>
|
||||
<ListItemAvatar>
|
||||
<Checkbox
|
||||
checked={riders?.length == selectedRiders?.length}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
setSelectedRiders(riders);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary="All" />
|
||||
</ListItem>
|
||||
<Divider />
|
||||
</List>
|
||||
</Box>
|
||||
{/* Rider List */}
|
||||
<List>
|
||||
{/* Individuals */}
|
||||
{ridersIsLoading || riderIsFetching
|
||||
? Array.from({ length: 10 }).map((_, index) => (
|
||||
<Fragment key={index}>
|
||||
<ListItem sx={{ py: 1.5, px: 2 }}>
|
||||
<ListItemAvatar>
|
||||
<Skeleton variant="circular" width={24} height={24} />
|
||||
</ListItemAvatar>
|
||||
|
||||
<ListItemText
|
||||
primary={<Skeleton variant="text" width="60%" height={22} />}
|
||||
secondary={<Skeleton variant="text" width="40%" height={18} />}
|
||||
/>
|
||||
</InputAdornment>
|
||||
)
|
||||
}
|
||||
aria-describedby="header-search-text"
|
||||
inputProps={{
|
||||
'aria-label': 'weight'
|
||||
|
||||
<Stack spacing={0.5} textAlign="right">
|
||||
<Skeleton variant="text" width={50} height={18} />
|
||||
<Skeleton variant="text" width={80} height={16} />
|
||||
</Stack>
|
||||
</ListItem>
|
||||
|
||||
<Divider />
|
||||
</Fragment>
|
||||
))
|
||||
: riders?.map((row) => {
|
||||
return (
|
||||
<Fragment key={row.userid}>
|
||||
<ListItem
|
||||
sx={{
|
||||
cursor: 'pointer',
|
||||
py: 1,
|
||||
px: 2,
|
||||
borderRadius: 1,
|
||||
'&:hover': { bgcolor: theme.palette.secondary.lighter }
|
||||
}}
|
||||
secondaryAction={
|
||||
<Stack textAlign="right" spacing={0.5}>
|
||||
<Typography variant="body2" noWrap sx={{ color: row.status == 'active' ? 'success.main' : 'error.main' }}>
|
||||
{row.userid}
|
||||
</Typography>
|
||||
<Typography variant="caption" color="text.secondary" noWrap>
|
||||
{dayjs(row.logdate).format('DD/MM/YYYY hh:mm A')}
|
||||
</Typography>
|
||||
</Stack>
|
||||
}
|
||||
>
|
||||
<ListItemAvatar>
|
||||
<Checkbox
|
||||
sx={{
|
||||
color: row.status == 'active' ? 'green' : 'red',
|
||||
'&.Mui-checked': {
|
||||
color: row.status == 'active' ? 'green' : 'red'
|
||||
}
|
||||
}}
|
||||
checked={
|
||||
// INDIVIDUAL CHECKED CONDITION
|
||||
selectedRiders?.length === 1 && selectedRiders[0]?.userid === row?.userid
|
||||
}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
// SELECT ONE RIDER
|
||||
setSelectedRiders([row]);
|
||||
} else {
|
||||
// UNCHECK -> SELECT ALL
|
||||
setSelectedRiders(riders);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</ListItemAvatar>
|
||||
|
||||
<ListItemText
|
||||
primary={
|
||||
row.username ? (
|
||||
<Typography noWrap>
|
||||
{row.username?.slice(0, 25) || ''}
|
||||
{row.username?.length > 25 && '...'}
|
||||
{/* {row.status === 'active' && <TaskAltIcon fontSize="small" color="success" sx={{ ml: 1 }} />} */}
|
||||
</Typography>
|
||||
) : (
|
||||
<Typography noWrap>
|
||||
{row.firstname || ''}
|
||||
{row.lastname ? ` ${row.lastname}` : ''}
|
||||
</Typography>
|
||||
)
|
||||
}
|
||||
secondary={
|
||||
<Typography variant="caption" color="text.secondary" noWrap>
|
||||
{row.contactno || '##########'}
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<Divider />
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
</Drawer>
|
||||
|
||||
{/* AppBar */}
|
||||
<AppBar
|
||||
elevation={0}
|
||||
position="absolute"
|
||||
sx={{
|
||||
top: 0,
|
||||
left: open && isDesktop ? `${drawerWidth}px` : 0,
|
||||
width: open && isDesktop ? `calc(100% - ${drawerWidth}px)` : '100%',
|
||||
transition: 'left 0.3s ease, width 0.3s ease',
|
||||
backgroundColor: 'white',
|
||||
borderBottom: '1px solid',
|
||||
borderColor: theme.palette.secondary.light
|
||||
}}
|
||||
>
|
||||
<Toolbar>
|
||||
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ width: '100%' }}>
|
||||
<Stack direction="row" alignItems="center">
|
||||
<IconButton color="primary" onClick={() => setOpen(!open)}>
|
||||
<MenuIcon />
|
||||
</IconButton>
|
||||
|
||||
<Typography variant="h5" color="primary" sx={{ ml: 2 }}>
|
||||
Riders Locations
|
||||
</Typography>
|
||||
</Stack>
|
||||
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
riderLogsRefetch();
|
||||
}}
|
||||
placeholder="Search"
|
||||
value={searchword}
|
||||
onChange={(e) => {
|
||||
setSearchword(e.target.value);
|
||||
if (e.target.value == '') {
|
||||
SetShowClose(false);
|
||||
} else {
|
||||
SetShowClose(true);
|
||||
}
|
||||
}}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</FormControl>{' '}
|
||||
</Stack>
|
||||
<Stack flexDirection="row" alignItems="center" gap={2}>
|
||||
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
||||
<DatePicker
|
||||
label="Choose Date"
|
||||
value={dayjs(startdate)}
|
||||
format="DD-MM-YYYY"
|
||||
onChange={(e) => {
|
||||
if (e) {
|
||||
setStartdate(dayjs(e.$d).format('YYYY-MM-DD'));
|
||||
}
|
||||
>
|
||||
Refresh
|
||||
</Button>
|
||||
</Stack>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
|
||||
{/* Map */}
|
||||
<Box
|
||||
sx={{
|
||||
flexGrow: 1,
|
||||
overflow: 'auto',
|
||||
pt: '64px',
|
||||
pl: open && isDesktop ? `${drawerWidth}px` : 0,
|
||||
transition: 'padding-left 0.3s ease',
|
||||
minHeight: '80vh'
|
||||
}}
|
||||
>
|
||||
{(ridersIsLoading || riderIsFetching) && (
|
||||
<Box position="relative" width="100%" height="80vh" display="grid" placeItems="center">
|
||||
{/* <CircularLoader /> */}
|
||||
<Skeleton
|
||||
variant="rectangular"
|
||||
width="100%"
|
||||
height="100%"
|
||||
animation="wave"
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
borderRadius: 1,
|
||||
zIndex: 1
|
||||
}}
|
||||
/>
|
||||
</LocalizationProvider>
|
||||
</Stack>
|
||||
</Stack>
|
||||
}
|
||||
>
|
||||
<TableContainer>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>S.No</TableCell>
|
||||
<TableCell>ID</TableCell>
|
||||
<TableCell>Rider</TableCell>
|
||||
<TableCell>LogDate</TableCell>
|
||||
<TableCell>Shift(HRS)</TableCell>
|
||||
<TableCell>Login</TableCell>
|
||||
<TableCell>Logout</TableCell>
|
||||
<TableCell>WRK(HRS)</TableCell>
|
||||
<TableCell>Shift(HRS)</TableCell>
|
||||
<TableCell>BRK(HRS)</TableCell>
|
||||
<TableCell>Status</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{rows.length == 0 ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={11}>
|
||||
<Empty />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : (
|
||||
rows.map((row, index) => (
|
||||
<TableRow key={index + 1}>
|
||||
<TableCell align="left">{index + 1}</TableCell>
|
||||
<TableCell align="left">{row.userid}</TableCell>
|
||||
<TableCell align="left">{row.username}</TableCell>
|
||||
<TableCell align="left">
|
||||
{' '}
|
||||
<Chip label={formatDate(row.logdate)} color="warning" variant="outlined" size="small" sx={{ bgcolor: '#fffde7' }} />
|
||||
</TableCell>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<TableCell align="left">{row.shifthours}</TableCell>
|
||||
<TableCell align="left">
|
||||
{row.login != '' && (
|
||||
<Chip label={formatTime(row.login)} color="info" variant="outlined" size="small" sx={{ bgcolor: '#e0f7fa' }} />
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
{row.logout != '' && (
|
||||
<Chip label={formatTime(row.logout)} color="info" variant="outlined" size="small" sx={{ bgcolor: '#e0f7fa' }} />
|
||||
)}
|
||||
</TableCell>
|
||||
|
||||
<TableCell align="left">{row.workhours}</TableCell>
|
||||
<TableCell align="left">{row.shorthours}</TableCell>
|
||||
<TableCell align="left">{row.breakhours}</TableCell>
|
||||
<TableCell align="left">
|
||||
{row.logstatus == 0 ? (
|
||||
<Chip label="Active" color="success" variant="outlined" size="small" sx={{ bgcolor: '#e8f5e9' }} />
|
||||
) : (
|
||||
<Chip label="Inactive" color="error" variant="outlined" size="small" sx={{ bgcolor: '#fce4ec' }} />
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
{selectedRiders?.length > 0 && <RiderLocationMap riderLocations={selectedRiders} />}
|
||||
{riderLogsError && (
|
||||
<Box sx={{ width: '100% ', height: '100%' }}>
|
||||
<img src={error500} alt="mantis" style={{ height: '100%', width: '100%' }} />
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</MainCard>
|
||||
</>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default RidersLogs;
|
||||
|
||||
@@ -49,6 +49,7 @@ import Loader from 'components/Loader';
|
||||
import TitleCard from '../titleCard';
|
||||
import { fetchRidersSummary } from '../api/api';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { getValueColor } from 'components/nearle_components/getValueColor';
|
||||
|
||||
// table filter
|
||||
function descendingComparator(a, b, orderBy) {
|
||||
@@ -222,14 +223,15 @@ export default function RidersSummary() {
|
||||
<TableRow>
|
||||
<TableCell># </TableCell>
|
||||
<TableCell> Rider</TableCell>
|
||||
<TableCell>Total </TableCell>
|
||||
{/* <TableCell> Pending</TableCell>
|
||||
<TableCell>Deliveries </TableCell>
|
||||
<TableCell> Pending</TableCell>
|
||||
<TableCell> Assigned</TableCell>
|
||||
<TableCell> Accepted</TableCell>
|
||||
<TableCell>Arrived </TableCell>
|
||||
<TableCell>Picked </TableCell>
|
||||
<TableCell>Active </TableCell>
|
||||
<TableCell>Skipped </TableCell> */}
|
||||
<TableCell>Skipped </TableCell>
|
||||
<TableCell>Cancelled </TableCell>
|
||||
<TableCell>Delivered </TableCell>
|
||||
<TableCell>kms </TableCell>
|
||||
<TableCell> COD/PLA</TableCell>
|
||||
@@ -263,40 +265,45 @@ export default function RidersSummary() {
|
||||
{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 sx={{ ml: -2, wrap: 'nowrap' }}>
|
||||
<Typography>
|
||||
{row.firstname} {row.lastname}
|
||||
</Typography>
|
||||
<Typography variant="body2">Id : {row.userid}</Typography>
|
||||
</Stack>
|
||||
</TableCell>
|
||||
|
||||
<TableCell align="left">{row.totalorders}</TableCell>
|
||||
{/* <TableCell align="left">
|
||||
{row.pending ? <Chip color="primary" variant="light" label={row.pending} /> : row.pending}
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
{row.assigned ? <Chip color="primary" variant="light" label={row.assigned} /> : row.assigned}
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
{row.accepted ? <Chip color="primary" variant="light" label={row.accepted} /> : row.accepted}
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
{row.arrived ? <Chip color="primary" variant="light" label={row.arrived} /> : row.arrived}
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
{row.picked ? <Chip color="primary" variant="light" label={row.picked} /> : row.picked}
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
{row.active ? <Chip color="primary" variant="light" label={row.active} /> : row.active}
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
{row.skipped ? <Chip color="primary" variant="light" label={row.skipped} /> : row.skipped}
|
||||
</TableCell> */}
|
||||
<TableCell align="center" sx={{ color: getValueColor(row.totalorders) }}>
|
||||
{row.totalorders}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
{row.pending ? <Chip color="primary" variant="light" label={row.pending} /> : row.pending}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
{row.assigned ? <Chip color="primary" variant="light" label={row.assigned} /> : row.assigned}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
{row.accepted ? <Chip color="primary" variant="light" label={row.accepted} /> : row.accepted}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
{row.arrived ? <Chip color="primary" variant="light" label={row.arrived} /> : row.arrived}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
{row.picked ? <Chip color="primary" variant="light" label={row.picked} /> : row.picked}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
{row.active ? <Chip color="primary" variant="light" label={row.active} /> : row.active}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
{row.skipped ? <Chip color="primary" variant="light" label={row.skipped} /> : row.skipped}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
{row.cancelled ? <Chip color="primary" variant="light" label={row.cancelled} /> : row.cancelled}
|
||||
</TableCell>
|
||||
|
||||
<TableCell align="left">{row.delivered}</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(row.totalorders) }}>
|
||||
{row.delivered}
|
||||
</TableCell>
|
||||
|
||||
<TableCell align="left">
|
||||
<Stack direction={'row'}>
|
||||
@@ -314,10 +321,10 @@ export default function RidersSummary() {
|
||||
}}
|
||||
/>
|
||||
</Tooltip> */}
|
||||
<Tooltip title="Actual kms" placement="bottom">
|
||||
<Tooltip title="Cumulative Kms" placement="top">
|
||||
<Chip
|
||||
size="small"
|
||||
label={row.actualkms}
|
||||
label={row.cumulativekms ? parseFloat(row.cumulativekms).toFixed(2) : 0}
|
||||
sx={{
|
||||
color: '#ff8f00',
|
||||
bgcolor: '#ffecb3',
|
||||
@@ -423,10 +430,10 @@ export default function RidersSummary() {
|
||||
<TableCell>#</TableCell>
|
||||
<TableCell>Location</TableCell>
|
||||
<TableCell align="left">All</TableCell>
|
||||
{/* <TableCell align="left">Pending</TableCell> */}
|
||||
<TableCell align="left">Pending</TableCell>
|
||||
<TableCell align="left">Completed</TableCell>
|
||||
{/* <TableCell align="left">Cancelled</TableCell> */}
|
||||
<TableCell align="left">Actual Kms</TableCell>
|
||||
<TableCell align="left">Cancelled</TableCell>
|
||||
<TableCell align="left"> Kms</TableCell>
|
||||
<TableCell align="left">COD / PLA</TableCell>
|
||||
<TableCell align="left">Amount</TableCell>
|
||||
</TableRow>
|
||||
@@ -446,14 +453,23 @@ export default function RidersSummary() {
|
||||
{index + 1}
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
<Stack direction="row" sx={{ ml: -2 }}>
|
||||
{row.locationname}
|
||||
<Stack sx={{ ml: -2 }}>
|
||||
<Typography> {row.locationname}</Typography>
|
||||
<Typography variant="body2"> Id: {row.locationid}</Typography>
|
||||
</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" sx={{ color: getValueColor(row.totalorders) }}>
|
||||
{row.totalorders}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(row.deliveriespending) }}>
|
||||
{row.deliveriespending}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(row.deliveriescompleted) }}>
|
||||
{row.deliveriescompleted}
|
||||
</TableCell>
|
||||
<TableCell align="center" sx={{ color: getValueColor(row.deliveriescancelled) }}>
|
||||
{row.deliveriescancelled}
|
||||
</TableCell>
|
||||
<TableCell align="left">
|
||||
{/* <Chip
|
||||
size="small"
|
||||
@@ -466,16 +482,18 @@ export default function RidersSummary() {
|
||||
minWidth: 80
|
||||
}}
|
||||
/> */}
|
||||
<Chip
|
||||
size="small"
|
||||
label={row.actualkms}
|
||||
sx={{
|
||||
color: '#ff8f00',
|
||||
bgcolor: '#ffecb3',
|
||||
border: '1px solid #ff8f00',
|
||||
minWidth: 80
|
||||
}}
|
||||
/>
|
||||
<Tooltip title="Cumulative Kms" placement="top">
|
||||
<Chip
|
||||
size="small"
|
||||
label={row.cumulativekms ? parseFloat(row.cumulativekms).toFixed(2) : 0}
|
||||
sx={{
|
||||
color: '#ff8f00',
|
||||
bgcolor: '#ffecb3',
|
||||
border: '1px solid #ff8f00',
|
||||
minWidth: 80
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</TableCell>
|
||||
|
||||
<TableCell align="left">
|
||||
|
||||
Reference in New Issue
Block a user