From e71e44319ccba5c8984d35afda8e7a0c24da205e Mon Sep 17 00:00:00 2001 From: joshikannan Date: Wed, 26 Nov 2025 18:24:03 +0530 Subject: [PATCH] overall updates --- package-lock.json | 156 +++ package.json | 2 + src/App.js | 4 +- .../cards/statistics/HoverSocialCard.js | 39 +- .../nearle_components/DateFilterDialog.js | 55 + src/components/nearle_components/SearchBar.js | 58 + .../nearle_components/updateNetworkStatus.js | 96 ++ .../nearle_components/useDebounce.js | 15 + .../nearle_components/useHotkeyFocus.js | 26 + src/index.js | 2 +- .../DrawerContent/Navigation/NavCollapse.js | 41 +- .../DrawerContent/Navigation/NavItem.js | 22 +- .../HeaderContent/Profile/ProfileTab.js | 29 +- .../MainLayout/Header/HeaderContent/index.js | 12 +- src/menu-items/nearle.js | 16 +- src/pages/nearle/api/api.js | 84 +- src/pages/nearle/clients/customers.js | 850 +-------------- src/pages/nearle/locations/Locations.js | 24 + .../locations/ResponsiveLocationDrawer.js | 596 +++++++++++ src/pages/nearle/login.js | 1 + src/pages/nearle/orders/RidersPinPointOSM.js | 78 ++ src/pages/nearle/orders/createorder1.js | 2 +- src/pages/nearle/orders/multipleOrders.js | 465 +++++---- src/pages/nearle/orders/orders.js | 987 +++++++++--------- src/pages/nearle/orders/ridersPinPoint.js | 53 + src/pages/nearle/orders/rough.js | 4 +- src/pages/nearle/reports/orderSummary.js | 461 ++++---- src/pages/nearle/reports/ordersDetails.js | 418 ++++---- src/pages/nearle/reports/riderLogs.js | 212 +++- src/pages/nearle/reports/ridersummary.js | 588 +++++------ src/pages/nearle/titleCard.js | 8 +- src/routes/MainRoutes.js | 20 +- src/themes/index.js | 29 +- src/themes/theme/default.js | 26 +- yarn.lock | 70 +- 35 files changed, 3145 insertions(+), 2404 deletions(-) create mode 100644 src/components/nearle_components/DateFilterDialog.js create mode 100644 src/components/nearle_components/SearchBar.js create mode 100644 src/components/nearle_components/updateNetworkStatus.js create mode 100644 src/components/nearle_components/useDebounce.js create mode 100644 src/components/nearle_components/useHotkeyFocus.js create mode 100644 src/pages/nearle/locations/Locations.js create mode 100644 src/pages/nearle/locations/ResponsiveLocationDrawer.js create mode 100644 src/pages/nearle/orders/RidersPinPointOSM.js create mode 100644 src/pages/nearle/orders/ridersPinPoint.js diff --git a/package-lock.json b/package-lock.json index 27475a8..baeedbd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@ant-design/colors": "^7.0.0", "@ant-design/icons": "^5.0.1", + "@custom-react-hooks/use-network": "^1.0.1", "@emotion/cache": "^11.10.7", "@emotion/react": "^11.10.6", "@emotion/styled": "^11.10.6", @@ -18,6 +19,7 @@ "@mui/lab": "^5.0.0-alpha.127", "@mui/material": "^5.12.1", "@mui/x-date-pickers": "^6.18.2", + "@react-google-maps/api": "^2.20.7", "@reduxjs/toolkit": "^1.9.5", "@svgr/webpack": "^7.0.0", "@tanstack/react-query": "^5.22.2", @@ -2267,6 +2269,15 @@ "node": ">=10" } }, + "node_modules/@custom-react-hooks/use-network": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@custom-react-hooks/use-network/-/use-network-1.0.1.tgz", + "integrity": "sha512-WbFVxsC18hjJiVIONAExVORlJlrOeYwzKsiYUCzrt5zCP0u9eLUPJuftF3DvEpoaQdjufazllWCPWKXT+dTY2g==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/@emotion/babel-plugin": { "version": "11.10.6", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz", @@ -2624,6 +2635,22 @@ "tslib": "^2.4.0" } }, + "node_modules/@googlemaps/js-api-loader": { + "version": "1.16.8", + "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.16.8.tgz", + "integrity": "sha512-CROqqwfKotdO6EBjZO/gQGVTbeDps5V7Mt9+8+5Q+jTg5CRMi3Ii/L9PmV3USROrt2uWxtGzJHORmByxyo9pSQ==", + "license": "Apache-2.0" + }, + "node_modules/@googlemaps/markerclusterer": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@googlemaps/markerclusterer/-/markerclusterer-2.5.3.tgz", + "integrity": "sha512-x7lX0R5yYOoiNectr10wLgCBasNcXFHiADIBdmn7jQllF2B5ENQw5XtZK+hIw4xnV0Df0xhN4LN98XqA5jaiOw==", + "license": "Apache-2.0", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "supercluster": "^8.0.1" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", @@ -4111,6 +4138,36 @@ "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" }, + "node_modules/@react-google-maps/api": { + "version": "2.20.7", + "resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-2.20.7.tgz", + "integrity": "sha512-ys7uri3V6gjhYZUI43srHzSKDC6/jiKTwHNlwXFTvjeaJE3M3OaYBt9FZKvJs8qnOhL6i6nD1BKJoi1KrnkCkg==", + "license": "MIT", + "dependencies": { + "@googlemaps/js-api-loader": "1.16.8", + "@googlemaps/markerclusterer": "2.5.3", + "@react-google-maps/infobox": "2.20.0", + "@react-google-maps/marker-clusterer": "2.20.0", + "@types/google.maps": "3.58.1", + "invariant": "2.2.4" + }, + "peerDependencies": { + "react": "^16.8 || ^17 || ^18 || ^19", + "react-dom": "^16.8 || ^17 || ^18 || ^19" + } + }, + "node_modules/@react-google-maps/infobox": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/@react-google-maps/infobox/-/infobox-2.20.0.tgz", + "integrity": "sha512-03PJHjohhaVLkX6+NHhlr8CIlvUxWaXhryqDjyaZ8iIqqix/nV8GFdz9O3m5OsjtxtNho09F/15j14yV0nuyLQ==", + "license": "MIT" + }, + "node_modules/@react-google-maps/marker-clusterer": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/@react-google-maps/marker-clusterer/-/marker-clusterer-2.20.0.tgz", + "integrity": "sha512-tieX9Va5w1yP88vMgfH1pHTacDQ9TgDTjox3tLlisKDXRQWdjw+QeVVghhf5XqqIxXHgPdcGwBvKY6UP+SIvLw==", + "license": "MIT" + }, "node_modules/@react-leaflet/core": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz", @@ -4905,6 +4962,12 @@ "@types/range-parser": "*" } }, + "node_modules/@types/google.maps": { + "version": "3.58.1", + "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.58.1.tgz", + "integrity": "sha512-X9QTSvGJ0nCfMzYOnaVs/k6/4L+7F5uCS+4iUmkLEls6J9S/Phv+m/i3mDeyc49ZBgwab3EFO1HEoBY7k98EGQ==", + "license": "MIT" + }, "node_modules/@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -10699,6 +10762,15 @@ "tslib": "^2.4.0" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/ipaddr.js": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", @@ -13433,6 +13505,12 @@ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" }, + "node_modules/kdbush": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz", + "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==", + "license": "ISC" + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -18872,6 +18950,15 @@ "stylis": "4.x" } }, + "node_modules/supercluster": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz", + "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==", + "license": "ISC", + "dependencies": { + "kdbush": "^4.0.2" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -22001,6 +22088,12 @@ "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==" }, + "@custom-react-hooks/use-network": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@custom-react-hooks/use-network/-/use-network-1.0.1.tgz", + "integrity": "sha512-WbFVxsC18hjJiVIONAExVORlJlrOeYwzKsiYUCzrt5zCP0u9eLUPJuftF3DvEpoaQdjufazllWCPWKXT+dTY2g==", + "requires": {} + }, "@emotion/babel-plugin": { "version": "11.10.6", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz", @@ -22292,6 +22385,20 @@ "tslib": "^2.4.0" } }, + "@googlemaps/js-api-loader": { + "version": "1.16.8", + "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.16.8.tgz", + "integrity": "sha512-CROqqwfKotdO6EBjZO/gQGVTbeDps5V7Mt9+8+5Q+jTg5CRMi3Ii/L9PmV3USROrt2uWxtGzJHORmByxyo9pSQ==" + }, + "@googlemaps/markerclusterer": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@googlemaps/markerclusterer/-/markerclusterer-2.5.3.tgz", + "integrity": "sha512-x7lX0R5yYOoiNectr10wLgCBasNcXFHiADIBdmn7jQllF2B5ENQw5XtZK+hIw4xnV0Df0xhN4LN98XqA5jaiOw==", + "requires": { + "fast-deep-equal": "^3.1.3", + "supercluster": "^8.0.1" + } + }, "@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", @@ -23231,6 +23338,29 @@ "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" }, + "@react-google-maps/api": { + "version": "2.20.7", + "resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-2.20.7.tgz", + "integrity": "sha512-ys7uri3V6gjhYZUI43srHzSKDC6/jiKTwHNlwXFTvjeaJE3M3OaYBt9FZKvJs8qnOhL6i6nD1BKJoi1KrnkCkg==", + "requires": { + "@googlemaps/js-api-loader": "1.16.8", + "@googlemaps/markerclusterer": "2.5.3", + "@react-google-maps/infobox": "2.20.0", + "@react-google-maps/marker-clusterer": "2.20.0", + "@types/google.maps": "3.58.1", + "invariant": "2.2.4" + } + }, + "@react-google-maps/infobox": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/@react-google-maps/infobox/-/infobox-2.20.0.tgz", + "integrity": "sha512-03PJHjohhaVLkX6+NHhlr8CIlvUxWaXhryqDjyaZ8iIqqix/nV8GFdz9O3m5OsjtxtNho09F/15j14yV0nuyLQ==" + }, + "@react-google-maps/marker-clusterer": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/@react-google-maps/marker-clusterer/-/marker-clusterer-2.20.0.tgz", + "integrity": "sha512-tieX9Va5w1yP88vMgfH1pHTacDQ9TgDTjox3tLlisKDXRQWdjw+QeVVghhf5XqqIxXHgPdcGwBvKY6UP+SIvLw==" + }, "@react-leaflet/core": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz", @@ -23772,6 +23902,11 @@ "@types/range-parser": "*" } }, + "@types/google.maps": { + "version": "3.58.1", + "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.58.1.tgz", + "integrity": "sha512-X9QTSvGJ0nCfMzYOnaVs/k6/4L+7F5uCS+4iUmkLEls6J9S/Phv+m/i3mDeyc49ZBgwab3EFO1HEoBY7k98EGQ==" + }, "@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -28074,6 +28209,14 @@ "tslib": "^2.4.0" } }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "ipaddr.js": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", @@ -30040,6 +30183,11 @@ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" }, + "kdbush": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz", + "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==" + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -33782,6 +33930,14 @@ "cssjanus": "^2.0.1" } }, + "supercluster": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz", + "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==", + "requires": { + "kdbush": "^4.0.2" + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", diff --git a/package.json b/package.json index f69a7ab..b63ef17 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "dependencies": { "@ant-design/colors": "^7.0.0", "@ant-design/icons": "^5.0.1", + "@custom-react-hooks/use-network": "^1.0.1", "@emotion/cache": "^11.10.7", "@emotion/react": "^11.10.6", "@emotion/styled": "^11.10.6", @@ -13,6 +14,7 @@ "@mui/lab": "^5.0.0-alpha.127", "@mui/material": "^5.12.1", "@mui/x-date-pickers": "^6.18.2", + "@react-google-maps/api": "^2.20.7", "@reduxjs/toolkit": "^1.9.5", "@svgr/webpack": "^7.0.0", "@tanstack/react-query": "^5.22.2", diff --git a/src/App.js b/src/App.js index b12661a..68d567f 100644 --- a/src/App.js +++ b/src/App.js @@ -8,6 +8,7 @@ import Snackbar from 'components/@extended/Snackbar'; import Notistack from 'components/third-party/Notistack'; import { useNavigate } from 'react-router'; import { useEffect } from 'react'; +import InternetStatus from 'components/nearle_components/updateNetworkStatus'; // auth-provider // import { JWTProvider as AuthProvider } from 'contexts/JWTContext'; @@ -15,16 +16,15 @@ import { useEffect } from 'react'; const App = () => { let navigate = useNavigate(); - useEffect(() => { if (!localStorage.getItem('authname')) { navigate('/login'); } }, []); - return ( <> + {/* */} diff --git a/src/components/cards/statistics/HoverSocialCard.js b/src/components/cards/statistics/HoverSocialCard.js index cca986e..936c35e 100644 --- a/src/components/cards/statistics/HoverSocialCard.js +++ b/src/components/cards/statistics/HoverSocialCard.js @@ -5,11 +5,13 @@ import { Box, Card, CardContent, Grid, Typography } from '@mui/material'; // ===========================|| HOVER SOCIAL CARD ||=========================== // -const HoverSocialCard = ({ primary, secondary, - percentage, +const HoverSocialCard = ({ + primary, + secondary, + percentage, // iconPrimary, - color - }) => { + color +}) => { // const IconPrimary = iconPrimary; // const primaryIcon = iconPrimary ? : null; @@ -20,10 +22,10 @@ const HoverSocialCard = ({ primary, secondary, background: color, position: 'relative', color: '#fff', - // '&:hover svg': { - // opacity: 1, - // transform: 'scale(1.1)' - // } + '&:hover svg': { + opacity: 1, + transform: 'scale(1.1)' + } }} > @@ -33,19 +35,18 @@ const HoverSocialCard = ({ primary, secondary, right: 15, top: 25, color: '#fff', - // '& svg': { - // width: 36, - // height: 36, - // opacity: 0.5, - // transition: 'all .3s ease-in-out' - // } + '& svg': { + width: 36, + height: 36, + opacity: 0.5, + transition: 'all .3s ease-in-out' + } }} > - {/* {percentage.toString()} % */} - {(percentage)? `${percentage.toString()} %`:''} - - + {/* {percentage.toString()} % */} + {percentage ? `${percentage.toString()} %` : ''} + {/* {primaryIcon} */} @@ -69,7 +70,7 @@ HoverSocialCard.propTypes = { primary: PropTypes.string, secondary: PropTypes.string, // iconPrimary: PropTypes.object, - percentage:PropTypes.string, + percentage: PropTypes.string, color: PropTypes.string }; diff --git a/src/components/nearle_components/DateFilterDialog.js b/src/components/nearle_components/DateFilterDialog.js new file mode 100644 index 0000000..c1fd795 --- /dev/null +++ b/src/components/nearle_components/DateFilterDialog.js @@ -0,0 +1,55 @@ +import { Dialog, DialogTitle, DialogContent, Typography, Stack, Button, DialogActions, Paper } from '@mui/material'; + +import { DateRangePicker } from 'mui-daterange-picker'; +import dayjs from 'dayjs'; + +import { addDays, addWeeks, addMonths, startOfWeek, endOfWeek, startOfMonth, endOfMonth } from 'date-fns'; + +export default function DateFilterDialog({ open, onClose, onApply }) { + const 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: addDays(new Date(), -7), 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)) } + ]; + + const handleSelect = (range) => { + if (!range?.startDate || !range?.endDate) return; + + onApply({ + startDate: dayjs(range.startDate).format('YYYY-MM-DD'), + endDate: dayjs(range.endDate).format('YYYY-MM-DD'), + label: range.label || '' + }); + + onClose(); + }; + + return ( + + + + Select Date Range + + + + + + + + + + ); +} diff --git a/src/components/nearle_components/SearchBar.js b/src/components/nearle_components/SearchBar.js new file mode 100644 index 0000000..a62702e --- /dev/null +++ b/src/components/nearle_components/SearchBar.js @@ -0,0 +1,58 @@ +// SearchBar.jsx +import React, { useEffect, useRef } from 'react'; +import { FormControl, OutlinedInput, InputAdornment, IconButton, useTheme } from '@mui/material'; +import SearchOutlined from '@mui/icons-material/SearchOutlined'; +import ClearIcon from '@mui/icons-material/Clear'; + +const SearchBar = ({ value, onChange, sx, placeholder = 'Search (Ctrl + K)' }) => { + const theme = useTheme(); + const inputRef = useRef(null); + + /* ============================================= || handleKeyPress (CTRL + K) and ESC ||============================================= */ + useEffect(() => { + const handleKeyPress = (event) => { + // Focus input with CTRL + K / CMD + K + if (event.key === 'k' && (event.metaKey || event.ctrlKey)) { + event.preventDefault(); + inputRef.current?.focus(); + } + + // ESC removes focus + if (event.key === 'Escape' && document.activeElement === inputRef.current) { + inputRef.current.blur(); + } + }; + + document.addEventListener('keydown', handleKeyPress); + return () => document.removeEventListener('keydown', handleKeyPress); + }, []); + + return ( + + + + + } + endAdornment={ + onChange({ target: { value: '' } })}> + + + } + /> + + ); +}; + +export default SearchBar; diff --git a/src/components/nearle_components/updateNetworkStatus.js b/src/components/nearle_components/updateNetworkStatus.js new file mode 100644 index 0000000..b5f9e15 --- /dev/null +++ b/src/components/nearle_components/updateNetworkStatus.js @@ -0,0 +1,96 @@ +import { useEffect, useState, useRef } from 'react'; +import { useTheme } from '@mui/material/styles'; +import WifiOffIcon from '@mui/icons-material/WifiOff'; +import WifiIcon from '@mui/icons-material/Wifi'; + +const NOTIFICATION_STYLE = { + position: 'fixed', + top: '10px', // Keep top spacing + left: '50%', // Center horizontally + transform: 'translateX(-50%)', // Offset to truly center + padding: '12px 40px', + borderRadius: '8px', + color: 'white', + fontWeight: '500', + fontSize: '14px', + boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)', + zIndex: 9999, + maxWidth: '90%', + minWidth: 'auto', + textAlign: 'center' +}; + +const InternetStatus = () => { + const theme = useTheme(); + const [isOnline, setIsOnline] = useState(navigator.onLine); + const [showBackOnline, setShowBackOnline] = useState(false); + const wasOffline = useRef(!navigator.onLine); + + useEffect(() => { + const handleNetworkChange = () => { + const online = navigator.onLine; + setIsOnline(online); + + if (online && wasOffline.current) { + console.log('✅ Back online'); + setShowBackOnline(true); + wasOffline.current = false; + // window.location.reload(); + + setTimeout(() => { + setShowBackOnline(false); + }, 2000); + } + + if (!online) { + console.log('❌ No internet connection'); + wasOffline.current = true; + setShowBackOnline(false); + } + }; + + window.addEventListener('online', handleNetworkChange); + window.addEventListener('offline', handleNetworkChange); + + return () => { + window.removeEventListener('online', handleNetworkChange); + window.removeEventListener('offline', handleNetworkChange); + }; + }, []); + + return ( + <> + {!isOnline && ( +
+ + No Internet Connection +
+ )} + + {showBackOnline && ( +
+ + Back Online +
+ )} + + ); +}; + +export default InternetStatus; diff --git a/src/components/nearle_components/useDebounce.js b/src/components/nearle_components/useDebounce.js new file mode 100644 index 0000000..ae15a3b --- /dev/null +++ b/src/components/nearle_components/useDebounce.js @@ -0,0 +1,15 @@ +import { useEffect, useState } from 'react'; + +export const useDebounce = (value, delay = 500) => { + const [debouncedValue, setDebouncedValue] = useState(value); + + useEffect(() => { + const handler = setTimeout(() => { + setDebouncedValue(value); + }, delay); + + return () => clearTimeout(handler); // cleanup on every value change + }, [value, delay]); + + return debouncedValue; +}; diff --git a/src/components/nearle_components/useHotkeyFocus.js b/src/components/nearle_components/useHotkeyFocus.js new file mode 100644 index 0000000..9235b53 --- /dev/null +++ b/src/components/nearle_components/useHotkeyFocus.js @@ -0,0 +1,26 @@ +import { useEffect } from 'react'; + +export const useHotkeyFocus = (ref, hotkey = 'k') => { + useEffect(() => { + if (!ref?.current) return; + + const handleKeyPress = (event) => { + const isHotkey = event.key.toLowerCase() === hotkey.toLowerCase(); + + // CTRL + Hotkey + if (isHotkey && (event.metaKey || event.ctrlKey)) { + event.preventDefault(); + ref.current?.focus(); + } + + // ESC to blur + if (event.key === 'Escape' && document.activeElement === ref.current) { + ref.current.blur(); + } + }; + + document.addEventListener('keydown', handleKeyPress); + + return () => document.removeEventListener('keydown', handleKeyPress); + }, [ref, hotkey]); +}; diff --git a/src/index.js b/src/index.js index 5acfc60..0faf8f8 100644 --- a/src/index.js +++ b/src/index.js @@ -11,7 +11,7 @@ import 'simplebar/dist/simplebar.css'; import 'assets/third-party/apex-chart.css'; import 'assets/third-party/react-table.css'; -import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; // project import import App from './App'; diff --git a/src/layout/MainLayout/Drawer/DrawerContent/Navigation/NavCollapse.js b/src/layout/MainLayout/Drawer/DrawerContent/Navigation/NavCollapse.js index 6d24c1c..f1d4ac0 100644 --- a/src/layout/MainLayout/Drawer/DrawerContent/Navigation/NavCollapse.js +++ b/src/layout/MainLayout/Drawer/DrawerContent/Navigation/NavCollapse.js @@ -211,7 +211,16 @@ const NavCollapse = ({ menu, level, parentId, setSelectedItems, selectedItems, s const isSelected = selected === menu.id; const borderIcon = level === 1 ? : false; const Icon = menu.icon; - const menuIcon = menu.icon ? : borderIcon; + const menuIcon = menu.icon ? ( + + ) : ( + borderIcon + ); // const textColor = theme.palette.mode === ThemeMode.DARK ? 'grey.400' : 'text.primary'; // const iconSelectedColor = theme.palette.mode === ThemeMode.DARK && drawerOpen ? theme.palette.text.primary : theme.palette.primary.main; const popperId = miniMenuOpened ? `collapse-pop-${menu.id}` : undefined; @@ -237,11 +246,10 @@ const NavCollapse = ({ menu, level, parentId, setSelectedItems, selectedItems, s sx={{ pl: drawerOpen ? `${level * 28}px` : 1.5, py: !drawerOpen && level === 1 ? 1.25 : 1, - ...(drawerOpen && { '&:hover': { - // bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter' - bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : '#7b1fa2' + // bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter', + bgcolor: '#7b1fa2' }, '&.Mui-selected': { bgcolor: 'transparent', @@ -250,14 +258,14 @@ const NavCollapse = ({ menu, level, parentId, setSelectedItems, selectedItems, s } }), ...(!drawerOpen && { + bgcolor: theme.palette.primary.main, '&:hover': { - bgcolor: 'transparent' + bgcolor: theme.palette.primary.light }, '&.Mui-selected': { '&:hover': { - bgcolor: 'transparent' - }, - bgcolor: 'transparent' + bgcolor: theme.palette.primary.light + } } }) }} @@ -269,30 +277,25 @@ const NavCollapse = ({ menu, level, parentId, setSelectedItems, selectedItems, s minWidth: 28, // color: selected === menu.id ? 'primary.main' : textColor, // color: selected === menu.id ? textColor : textColor, - // bgcolor:'white', - // color:'white', + color: 'white', ...(!drawerOpen && { borderRadius: 1.5, width: 36, height: 36, alignItems: 'center', justifyContent: 'center', + color: 'white', '&:hover': { - // bgcolor: theme.palette.mode === ThemeMode.DARK ? 'secondary.light' : 'secondary.lighter' - bgcolor: '#7b1fa2', - color: 'white' + bgcolor: theme.palette.primary.light } }), ...(!drawerOpen && selected === menu.id && { - // bgcolor: theme.palette.mode === ThemeMode.DARK ? 'primary.900' : 'primary.lighter', - // bgcolor:'white', - bgcolor: '#7b1fa2', + bgcolor: theme.palette.primary.lighter, + color: theme.palette.primary.main, '&:hover': { - // bgcolor: theme.palette.mode === ThemeMode.DARK ? 'primary.darker' : 'primary.lighter' - bgcolor: '#7b1fa2' - // color:'white' + bgcolor: theme.palette.primary.lighter } }) }} diff --git a/src/layout/MainLayout/Drawer/DrawerContent/Navigation/NavItem.js b/src/layout/MainLayout/Drawer/DrawerContent/Navigation/NavItem.js index 6d6e2f5..3c1a74a 100644 --- a/src/layout/MainLayout/Drawer/DrawerContent/Navigation/NavItem.js +++ b/src/layout/MainLayout/Drawer/DrawerContent/Navigation/NavItem.js @@ -78,7 +78,7 @@ const NavItem = ({ item, level }) => { {...listItemProps} disabled={item.disabled} selected={isSelected} - onMouseEnter={(e, val) => { + onMouseEnter={(e) => { console.log(e); }} onMouseLeave={() => { @@ -104,18 +104,15 @@ const NavItem = ({ item, level }) => { } }), ...(!drawerOpen && { - bgcolor: '#662582', + bgcolor: theme.palette.primary.main, '&:hover': { - // bgcolor: 'transparent', - // bgcolor:'#7b1fa2' - bgcolor: '#662582' + bgcolor: theme.palette.primary.light }, '&.Mui-selected': { '&:hover': { - bgcolor: 'transparent' + bgcolor: 'white' }, - bgcolor: 'transparent' - // bgcolor:'#7b1fa2' + bgcolor: 'white' } }) }} @@ -133,15 +130,13 @@ const NavItem = ({ item, level }) => { color: isSelected ? iconSelectedColor : textColor, ...(!drawerOpen && { - borderRadius: 1.5, width: 36, height: 36, alignItems: 'center', justifyContent: 'center', - '&:hover': { // bgcolor: theme.palette.mode === ThemeMode.DARK ? 'secondary.light' : 'secondary.lighter' - bgcolor: '#7b1fa2' + // bgcolor: theme.palette.primary.light } }), ...(!drawerOpen && @@ -149,7 +144,8 @@ const NavItem = ({ item, level }) => { bgcolor: theme.palette.mode === ThemeMode.DARK ? 'primary.900' : 'primary.lighter', '&:hover': { bgcolor: theme.palette.mode === ThemeMode.DARK ? 'primary.darker' : 'primary.lighter' - } + }, + borderRadius: 2 }) }} > @@ -164,7 +160,7 @@ const NavItem = ({ item, level }) => { // sx={{ color: isSelected ? iconSelectedColor : textColor }} sx={{ color: isSelected && !drawerOpen ? theme.palette.primary.main : !isSelected ? 'white' : theme.palette.primary.main, - bgcolor: isSelected && !drawerOpen ? theme.palette.primary.lighter : 'none', + bgcolor: isSelected && theme.palette.primary.lighter, padding: isSelected && !drawerOpen ? 0.8 : 'none', borderRadius: isSelected && !drawerOpen ? 2 : 'none', ml: isSelected && !drawerOpen ? 0.5 : 'none' diff --git a/src/layout/MainLayout/Header/HeaderContent/Profile/ProfileTab.js b/src/layout/MainLayout/Header/HeaderContent/Profile/ProfileTab.js index 62f22c1..afd12ff 100644 --- a/src/layout/MainLayout/Header/HeaderContent/Profile/ProfileTab.js +++ b/src/layout/MainLayout/Header/HeaderContent/Profile/ProfileTab.js @@ -5,53 +5,54 @@ import { useState } from 'react'; import { List, ListItemButton, ListItemIcon, ListItemText } from '@mui/material'; // assets -import { EditOutlined, ProfileOutlined, LogoutOutlined, UserOutlined, WalletOutlined,CommentOutlined } from '@ant-design/icons'; +import { EditOutlined, ProfileOutlined, LogoutOutlined, UserOutlined, WalletOutlined, CommentOutlined } from '@ant-design/icons'; import { useNavigate } from 'react-router'; // ==============================|| HEADER PROFILE - PROFILE TAB ||============================== // const ProfileTab = ({ handleLogout }) => { const [selectedIndex, setSelectedIndex] = useState(0); - const navigate=useNavigate(); + const navigate = useNavigate(); const handleListItemClick = (event, index) => { setSelectedIndex(index); - if(index == 1){ + if (index == 1) { navigate('/accountsettings'); } }; return ( - handleListItemClick(event, 0)}> + {/* handleListItemClick(event, 0)}> - - handleListItemClick(event, 1)}> + */} + handleListItemClick(event, 1)}> - handleListItemClick(event, 2)}> + {/* handleListItemClick(event, 2)}> - + - + */} {/* handleListItemClick(event, 4)}> */} - { - // navigate('/login') - // }} + { + // navigate('/login') + // }} > diff --git a/src/layout/MainLayout/Header/HeaderContent/index.js b/src/layout/MainLayout/Header/HeaderContent/index.js index 7919477..64e72e8 100644 --- a/src/layout/MainLayout/Header/HeaderContent/index.js +++ b/src/layout/MainLayout/Header/HeaderContent/index.js @@ -71,7 +71,7 @@ const HeaderContent = () => { {/* {!matchesXs && megaMenu} */} - {localStorage.getItem('fullname') || ''} + {localStorage.getItem('tenantname') || ''} {matchesXs && } @@ -169,7 +169,7 @@ const HeaderContent = () => { - Create Order + Orders
} /> @@ -178,7 +178,7 @@ const HeaderContent = () => { selected={location.pathname === 'nearle/orders/create'} onClick={() => { // console.log(const location = useLocation();) - navigate('nearle/orders/createorders'); + navigate('nearle/orders/create/grouporders'); handleClickAway(); }} > @@ -188,7 +188,7 @@ const HeaderContent = () => { - Create Group Order + Group Orders } /> @@ -224,7 +224,7 @@ const HeaderContent = () => { - Create Customer + Customers } /> @@ -273,7 +273,7 @@ const HeaderContent = () => { - + {/* */} {/* */} {/* {!matchesXs && } diff --git a/src/menu-items/nearle.js b/src/menu-items/nearle.js index 396b10e..f24712b 100644 --- a/src/menu-items/nearle.js +++ b/src/menu-items/nearle.js @@ -23,6 +23,7 @@ import { SettingOutlined } from '@ant-design/icons'; import { Path } from 'leaflet'; +import { LocationOnOutlined } from '@mui/icons-material'; // icons const icons = { @@ -56,12 +57,19 @@ const nearle = { icon: AiOutlineDashboard }, { - id: 'customers', - title: , + id: 'locations', + title: , type: 'item', - url: '/nearle/customers', - icon: icons.UserOutlined + url: '/nearle/locations', + icon: LocationOnOutlined }, + // { + // id: 'customers', + // title: , + // type: 'item', + // url: '/nearle/customers', + // icon: icons.UserOutlined + // }, { id: 'reports', title: , diff --git a/src/pages/nearle/api/api.js b/src/pages/nearle/api/api.js index 365c5e4..b37bf74 100644 --- a/src/pages/nearle/api/api.js +++ b/src/pages/nearle/api/api.js @@ -1,6 +1,28 @@ import axios from 'axios'; const tenid = localStorage.getItem('tenantid'); +export const fetchOrders = async ({ pageParam = 1, queryKey }) => { + const [, { tenantId, locationId, status, startdate, enddate, searchword, rowsPerPage }] = queryKey; + + const url = + `${process.env.REACT_APP_URL}/orders/tenant/getorders/` + + `?tenantid=${tenantId}` + + `&locationid=${locationId}` + + `&status=${status}` + + `&fromdate=${startdate}` + + `&todate=${enddate}` + + `&pageno=${pageParam}` + // 👈 pageParam comes from TanStack + `&pagesize=${rowsPerPage}` + + `&keyword=${searchword}`; + + const res = await axios.get(url); + return { + details: res.data.details, + nextPage: res.data.details.length === rowsPerPage ? pageParam + 1 : undefined + // 👈 API must return this flag + }; +}; + // ==============================|| fetchOrderSummary (orders)||============================== // export const fetchOrderSummary = async () => { const response = await axios.get(`${process.env.REACT_APP_URL}/orders/getordersummary`); @@ -38,6 +60,21 @@ export const fetchDeliveryLocationSummary = async () => { return response.data.details; }; +// ==============================|| getorders (Locations)||============================== // +// fetchOrders.js + +export const fetchOrders1 = async ({ pageParam = 1, queryKey }) => { + const [_key, tenantid, locationid, status, startdate, enddate, searchword, rowsPerPage] = queryKey; + + const res = await axios.get( + `${process.env.REACT_APP_URL}/orders/tenant/getorders/?tenantid=${tenantid}&locationid=${locationid}&status=${status}&fromdate=${startdate}&todate=${enddate}&pageno=${pageParam}&pagesize=${rowsPerPage}&keyword=${searchword}` + ); + + return { + details: res.data.details, + nextPage: res.data.details.length === rowsPerPage ? pageParam + 1 : undefined + }; +}; // ==============================|| fetchAllTenants (clients)||============================== // @@ -73,7 +110,7 @@ export const fetchCustomersListBySearch = async ({ queryKey }) => { console.log('fetchCustomersListBySearch', response.data.details); return response.data.details; }; -// ==============================|| fetchOrdersSummary (orders summary)||============================== // +// ==============================|| fetchOrdersSummary (rider summary)||============================== // export const fetchOrdersSummary = async ({ queryKey }) => { console.log('queryKey for fetchOrdersSummary', queryKey); const [startdate, enddate] = queryKey; @@ -95,6 +132,17 @@ export const getreportlocationsummary = async ({ queryKey }) => { return response.data.details; }; +// ==============================|| getriderlocationreportsummary (orders summary)||============================== // +export const getriderlocationreportsummary = async ({ queryKey }) => { + console.log('queryKey for getriderlocationreportsummary', queryKey); + const [startdate, enddate, locationId] = queryKey; + const response = await axios.get( + `${process.env.REACT_APP_URL}/deliveries/getriderlocationreportsummary/?tenantid=${tenid}&locationid=${locationId}&fromdate=${startdate}&todate=${enddate}` + ); + console.log('getriderlocationreportsummary', response.data.details); + + return response.data.details; +}; // ==============================|| fetchLocations (orders summary))||============================== // export const fetchLocations = async () => { @@ -107,6 +155,19 @@ export const fetchLocations = async () => { return updatedLocations; }; +// ==============================|| gettenantlocations (orders summary))||============================== // + +export const gettenantlocations = async ({ queryKey }) => { + const [, searchLocation] = queryKey; + try { + const response = await axios.get(`${process.env.REACT_APP_URL}/tenants/gettenantlocations?tenantid=${tenid}&keyword=${searchLocation}`); + return response.data?.details || []; // safe fallback + } catch (error) { + console.error('Error fetching tenant locations:', error); + return error.message; + } +}; + // ==============================|| fetchDeliverySummary (orders summary)||============================== // export const fetchDeliverySummary = async ({ queryKey }) => { const [, startdate, enddate, currentStatus, locationId] = queryKey; @@ -133,11 +194,9 @@ export const fetchAppLocations = async () => { export const fetchRidersSummary = async ({ queryKey }) => { console.log('queryKey for fetchRidersSummary', queryKey); - const [id, startdate, enddate] = queryKey; + const [tenantid, startdate, enddate] = queryKey; const response = await axios.get( - id == -1 - ? `${process.env.REACT_APP_URL}/deliveries/getridersummary/?&fromdate=${startdate}&todate=${enddate}` - : `${process.env.REACT_APP_URL}/deliveries/getridersummary/?applocationid=${id}&fromdate=${startdate}&todate=${enddate}` + `${process.env.REACT_APP_URL}/deliveries/getridersummary/?tenantid=${tenantid}&fromdate=${startdate}&todate=${enddate}` ); console.log('fetchRidersSummary', response.data.details); @@ -146,7 +205,7 @@ export const fetchRidersSummary = async ({ queryKey }) => { // ==============================|| fetchorderdetails (orders detail)||============================== // export const fetchorderdetails = async ({ pageParam = 0, queryKey }) => { - const [startdate, enddate, currentStatus, locationId] = queryKey; + const [startdate, enddate, currentStatus, locationId, searchword] = queryKey; const limit = 10; const pageno = pageParam + 1; // ✅ increment page by 1 each time @@ -156,7 +215,7 @@ export const fetchorderdetails = async ({ pageParam = 0, queryKey }) => { process.env.REACT_APP_URL }/deliveries/getdeliveries/?tenantid=${tenid}&locationid=${locationId}&fromdate=${startdate}&todate=${enddate}&status=${ currentStatus === 'All' ? '' : currentStatus - }&pageno=${pageno}&pagesize=${limit}` + }&pageno=${pageno}&pagesize=${limit}&keyword=${searchword}` ); const details = response.data.details || []; @@ -206,3 +265,14 @@ export const fetchCount = async ({ queryKey }) => { return calculateOrderCounts(); }; + +// ==============================|| fetchRidersLogs (RiderLogs)||============================== // + +export const fetchRidersLogs = async ({ queryKey }) => { + const [tenantid, startdate] = queryKey; + const riderLogsResponse = await axios.get( + `${process.env.REACT_APP_URL}/partners/getriderlogs/?tenantid=${tenantid}&fromdate=${startdate || ''}` + ); + console.log('fetchRidersLogs', riderLogsResponse.data.details); + return riderLogsResponse.data.details; +}; diff --git a/src/pages/nearle/clients/customers.js b/src/pages/nearle/clients/customers.js index b363657..9ab7dee 100644 --- a/src/pages/nearle/clients/customers.js +++ b/src/pages/nearle/clients/customers.js @@ -1,12 +1,9 @@ import React from 'react'; -import { Avatar, Pagination, Tooltip, stepContentClasses } from '@mui/material'; +import { Avatar, Tooltip } from '@mui/material'; import { useEffect, useRef, useState, Fragment, useMemo } from 'react'; import { useTheme } from '@mui/material/styles'; import Skeleton from '@mui/material/Skeleton'; -import HeartFilled from '@mui/icons-material/Favorite'; -// import dayjs from "dayjs"; import Loader from 'components/Loader'; -import CloseIcon from '@mui/icons-material/Close'; import { FilterList } from '@mui/icons-material'; import { FaRegEdit } from 'react-icons/fa'; import { RiEdit2Fill } from 'react-icons/ri'; @@ -16,17 +13,13 @@ import { Box, Button, IconButton, - ClickAwayListener, - Collapse, Dialog, Grid, Menu, MenuItem, - Popper, Stack, TextField, Typography, - useMediaQuery, Chip, OutlinedInput, InputAdornment, @@ -38,7 +31,6 @@ import { DialogTitle, DialogContent, DialogActions, - InputLabel, Table, TableContainer, TableHead, @@ -52,31 +44,11 @@ import LocationOnIcon from '@mui/icons-material/LocationOn'; import parse from 'autosuggest-highlight/parse'; import { debounce } from '@mui/material/utils'; import ClearIcon from '@mui/icons-material/Clear'; -import { MdPersonAdd } from 'react-icons/md'; -// import { MdAccountCircle } from "react-icons/md"; -import { MdPersonAddDisabled } from 'react-icons/md'; -// 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 { ThemeMode } from 'config'; -// import { FaUserLarge } from "react-icons/fa6"; import { MoreOutlined, SearchOutlined, DeleteFilled } from '@ant-design/icons'; -// import ChatDrawer from "sections/apps/chat/ChatDrawer"; -// import ChatHistory from "sections/apps/chat/ChatHistory"; -// import UserAvatar from "sections/apps/chat/UserAvatar"; -// import UserDetails from "sections/apps/chat/UserDetails"; import MainCard from 'components/MainCard'; -// import IconButton from "components/@extended/IconButton"; -// import SimpleBar from "components/third-party/SimpleBar"; -import { PopupTransition } from 'components/@extended/Transitions'; import axios from 'axios'; -// import HoverSocialCard from "../../pages/reports/HoverSocialCard"; import HoverSocialCard from 'components/cards/statistics/HoverSocialCard'; -// import TasksCard from "sections/widget/data/TasksCard"; -// import ApplicationSales from "sections/widget/data/ApplicationSales"; -// import Button from "themes/overrides/Button"; -import { styled } from '@mui/material/styles'; -// import TableRow from "themes/overrides/TableRow"; import dayjs from 'dayjs'; var utc = require('dayjs/plugin/utc'); dayjs.extend(utc); @@ -94,28 +66,6 @@ import { startOfWeek // startOfYear, } from 'date-fns'; -const drawerWidth = 320; -// const Main = styled("main", { shouldForwardProp: (prop) => prop !== "open" })( -// ({ theme, open }) => ({ -// flexGrow: 1, -// transition: theme.transitions.create("margin", { -// easing: theme.transitions.easing.sharp, -// duration: theme.transitions.duration.shorter, -// }), -// marginLeft: `-${drawerWidth}px`, -// [theme.breakpoints.down("lg")]: { -// paddingLeft: 0, -// marginLeft: 0, -// }, -// ...(open && { -// transition: theme.transitions.create("margin", { -// easing: theme.transitions.easing.easeOut, -// duration: theme.transitions.duration.shorter, -// }), -// marginLeft: 0, -// }), -// }) -// ); // ==============================|| google address ||============================== // const GOOGLE_MAPS_API_KEY = process.env.REACT_APP_GOOGLE_MAPS_API_KEY; @@ -134,47 +84,18 @@ function loadScript(src, position, id) { const autocompleteService = { current: null }; -const BootstrapDialog = styled(Dialog)(({ theme }) => ({ - '& .MuiDialog-paperWidthSm': { - maxWidth: '60%', - width: '100%', - margin: 0 - }, - '& .MuiDialogContent-root': { - padding: theme.spacing(2) - }, - '& .MuiDialogActions-root': { - padding: theme.spacing(1) - } -})); - const Customers = () => { const theme = useTheme(); const [search, setSearch] = useState(''); const [loading, setLoading] = useState(false); - const [data, setData] = useState([]); const [users, setUsers] = useState([]); const [userName, setUserName] = useState(''); - const [usernameload, setUsernameload] = useState(false); - const [customerId, setCustomerId] = useState(''); - const [custVisits, setCustVisits] = useState([]); - const [custService, setCustService] = useState([]); - const [custMembership, setCustMembership] = useState({}); - const [visits, setvisits] = useState(0); - const [billAmount, setBillAmount] = useState(0); - const [promotions, setPromotions] = useState(0); - const [discount, setDiscount] = useState(0); const [pageno, setPageno] = useState(1); const [contactno, setContactno] = useState(''); - const ref = useRef(null); const [open, setOpen] = React.useState(false); const [open3, setOpen3] = React.useState(false); const [open4, setOpen4] = React.useState(false); - const [selectedCustomer, setSelectedCustomer] = useState({}); // to edit - - const [packDays, setPackDays] = useState(0); - const [startDate, setStartDate] = useState(''); - const [validDate, setValidDate] = useState(''); + const [selectedCustomer, setSelectedCustomer] = useState({}); const [orderlist, setOrderlist] = useState([]); const [allorders, setAllorders] = useState(''); const [coveredorders, setCoveredorders] = useState(''); @@ -338,31 +259,17 @@ const Customers = () => { document.removeEventListener('keydown', handleKeyPress); }; }, []); - const handleClickOpen = () => { - setOpen(true); - }; + const handleClose = () => { setOpen3(false); }; - const handleClose3 = () => { - setOpen3(false); - }; - // const [anchorEl]=useState(null) - // const tenid = window.localStorage.getItem("tenantid"); useEffect(() => { - // setUsernameload(false); console.log('username', userName); }, [userName]); const [anchorEl, setAnchorEl] = useState(); - const handleClickRightMenu = (event) => { - setAnchorEl(event?.currentTarget); - }; - const handleCloseRightMenu = () => { - setAnchorEl(null); - }; const handleClickSort = (event) => { setAnchorEl(event?.currentTarget); }; @@ -379,58 +286,9 @@ const Customers = () => { useEffect(() => { if (tenid && !search) { - // fetchData1(); } }, [pageno]); - useEffect(() => { - const fetchsearch = async () => { - setLoading(true); - try { - await axios - .get(`${process.env.REACT_APP_URL}/customers/search?tenantid=${tenid}&keyword=${search}`) - .then((response) => { - if (response.data.status) { - setUsers(response.data.details || []); - setLoading(false); - } - }) - .catch((err) => { - console.log(err); - setLoading(false); - }); - } catch (error) { - console.error('Error fetching data:', error); - setLoading(false); - } - }; - if (search.length > 2) { - // fetchsearch(); - } else if (!search) { - // fetchData1(); - setPageno(1); - } - }, [search]); - - useEffect(() => { - if (search) { - let arr = tempusers.filter((val) => { - return ( - val.firstname.toLowerCase().includes(search.toLowerCase()) || - // || val.deliveryaddress.toLowerCase().includes(searchword.toLowerCase()) - // || val.customername.toLowerCase().includes(searchword.toLowerCase()) - // || val.pickupaddress.toString().toLowerCase().includes(searchword.toLowerCase()) - // || val.ordernotes.toString().toLowerCase().includes(searchword.toLowerCase()) - val.contactno.toString().toLowerCase().includes(search.toLowerCase()) - ); - }); - console.log(arr); - setUsers([...arr]); - } else { - setUsers([...tempusers]); - } - }, [search]); - useEffect(() => { if (tenid) { fetchData(tenid); @@ -440,24 +298,15 @@ const Customers = () => { const fetchpercentage = async (tid) => { setLoading(true); try { - // await axios.get(`${process.env.REACT_APP_URL}/orders/getordersummary/?tenantid=${tid}&fromdate=${startdate}&todate=${enddate}`) await axios .get(`${process.env.REACT_APP_URL}/orders/getordersummary/?customerid=${tid}`) .then((res) => { console.log(res); - // setConfirmed(res.data.details.confirmed.toString()); - // setModified(res.data.details.modified.toString()); setAllorders(res.data.details.total.toString()); setCoveredorders(res.data.details.delivered.toString()); - setCancelled(res.data.details.cancelled.toString()); setUncoveredorders(res.data.details.pending.toString()); - // setActiveorders(res.data.details.assigned.toString()); - // setAssigned(res.data.details.accepted.toString()); - // setCreated(res.data.details.created.toString()) - // setClosed(res.data.details.delivered.toString()); - // setPicked(res.data.details.picked.toString()) setPercentage1((Math.round((res.data.details.total / res.data.details.total) * 100) || 0).toString()); setPercentage3((Math.round((res.data.details.delivered / res.data.details.total) * 100) || 0).toString()); @@ -470,10 +319,6 @@ const Customers = () => { .catch((err) => { console.log(err); setLoading(false); - // enqueueSnackbar(err.message, { - // variant: 'error', anchorOrigin: { vertical: 'top', horizontal: 'right' }, - // autoHideDuration: 2000 - // }) }); } catch (err) { console.log(err); @@ -495,7 +340,6 @@ const Customers = () => { autoHideDuration: 2000 }); setCurrentcustomerid(''); - // fetchtable(localStorage.getItem('tenantid')) } else { enqueueSnackbar(res.data.message, { variant: 'error', @@ -523,31 +367,22 @@ const Customers = () => { const fetchtable = async (tid) => { setLoading1(true); try { - // await axios.get(`${process.env.REACT_APP_URL}/tenants/gettenants/?partnerid=${tid}&status=active`) await axios - // .get(`${process.env.REACT_APP_URL}/customers/gettenantcustomers/?tenantid=${tid}`) .get(`${process.env.REACT_APP_URL}/customers/gettenantcustomers/?tenantid=${tid}&pageno=1&pagesize=20`) - .then((res) => { if (res.data.message === 'Success') { let arr = []; res.data.details.map((val, i) => { arr = [...arr, { ...val, sno: i + 1 }]; }); - // setArr(arr) - // setRows([...arr]) - // setStafflist([...arr]) setSelectedCustomer(arr[0]); setUsers([...arr]); setTempusers([...arr]); - // if(arr[0].customerid){ setTenid(arr[0].customerid); setUserName(arr[0].firstname || ''); setContactno(arr[0].contactno || ''); fetchpercentage(arr[0].customerid); fetchData(arr[0].customerid); - // } - console.log(res.data.Details); console.log(arr); setLoading1(false); @@ -575,15 +410,10 @@ const Customers = () => { .get(`${process.env.REACT_APP_URL}/customers/getbytid?tenantid=${tenid}&pageno=${pageno}&pagesize=20`) .then((response) => { if (response.data.status) { - setUsers( - response.data.details - // .slice(0, 10) - ); + setUsers(response.data.details); setUserName(response.data.details[0].firstname || ''); setContactno(response.data.details[0].contactno || ''); fetchData(response.data.details[0].customerid); - - // fetchData(user.customerid); } setLoading(false); }) @@ -609,7 +439,6 @@ const Customers = () => { res.data.details.map((val, i) => { arr = [...arr, { ...val, sno: i + 1 }]; }); - // setArruncovered(arr) setOrderlist([...arr]); } }) @@ -620,20 +449,12 @@ const Customers = () => { console.log(err); } }; - useEffect(() => { - console.log('packDays', packDays); - console.log('startDate', startDate); - const formattedDate = dayjs(startDate, 'DD/MM/YYYY').add(packDays, 'day').format('DD/MM/YYYY'); - setValidDate(formattedDate); - }, [packDays, startDate]); function AlertCustomerDelete({ // title, open, handleClose }) { - // const [deletepassword, setDeletepassword] = useState(''); - return ( handleClose(false)} maxWidth="xs"> @@ -641,26 +462,11 @@ const Customers = () => { - {/* - - */} + Are you sure you want to Remove this Customer? - - {/* - Please type in the order number to confirm. - */} - {/* { - console.log(e.target.value) - setDeletepassword(e.target.value) - }} - error={deletepassword !== orderid.slice(4)} - value={deletepassword} - /> */} @@ -669,11 +475,8 @@ const Customers = () => { color="error" variant="contained" onClick={() => { - // if (deletepassword === orderid.slice(4)) { - // cancelorder(); removeclient(); handleClose(true); - // } }} autoFocus > @@ -759,7 +562,7 @@ const Customers = () => { return ( <> - {(loading || usernameload) && } + {loading && } @@ -773,55 +576,21 @@ const Customers = () => { sx={{ display: 'flex', width: '100%', - // height: "580px", - // bgcolor: "red", + height: '100%' }} > - {/* - - Customers - - - */} - { placeholder="Search (ctrl+k)" value={search} onChange={(e) => setSearch(e.target.value)} - // onChange={handleSearch} sx={{ '& .MuiOutlinedInput-input': { p: '10.5px 0px 12px' @@ -856,19 +624,9 @@ const Customers = () => { - {/* */} { pt: 0 }} > - {/* */} {loading1 ? ( <> {[1, 2, 3, 4, 5, 6, 7, 8, 9].map((val1) => { @@ -898,54 +655,11 @@ const Customers = () => { ); })} - - {/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */} ) : ( {users.map((user, index) => ( - + { @@ -977,9 +691,6 @@ const Customers = () => { > {user.firstname} - - {/* {user.lastMessage} */} - } secondary={ @@ -995,18 +706,6 @@ const Customers = () => { > {user.contactno} - {/* {user.unReadChatCount ? ( - - ) : ( - // chance.bool() - use for last send msg was read or unread - - )} */} } /> @@ -1017,50 +716,7 @@ const Customers = () => { )} - {/* - - - - { - let val = pageno; - if (val > 1) { - val = val - 1; - setPageno(val); - } - }} - > - - - {pageno} - { - let val = pageno; - if (val > 0 && !search) { - val = val + 1; - setPageno(val); - } - }} - > - - - - - - */} - {/* */} {users.length} Customers @@ -1068,38 +724,20 @@ const Customers = () => { - {/* */} - {/*
*/} - @@ -1107,12 +745,7 @@ const Customers = () => { content={false} sx={{ height: '100%', - // marginBottom:'60px' , - bgcolor: theme.palette.mode === ThemeMode.DARK ? 'dark.main' : 'grey.50', - // pt: 2, - // pl: 2, - // borderRadius: emailDetails ? "0" : "0 4px 4px 0", transition: theme.transitions.create('width', { easing: theme.transitions.easing.easeOut, duration: theme.transitions.duration.shorter + 200 @@ -1134,10 +767,7 @@ const Customers = () => { - + {userName ? ( @@ -1156,72 +786,9 @@ const Customers = () => { - {custMembership.membershipid == 0 && custMembership.startdate == '' ? ( - <>{/*

No Membership Found

*/} - ) : ( - <> - {custMembership.membershipid && ( - <> - - - } - variant="caption" - label={custMembership.membershipno || ''} - style={{ - width: 'auto', - height: 'auto', - - color: 'black', - background: 'white' - }} - /> - - - - - - - - {/* - {/* {custMembership.validityperiod || ''} Days */} - {/* {` ${custMembership.string}` || ''} - */} - - - )}{' '} - - )} - { }{' '} Delete - {/* ======================================== || Add Membership dialog|| ======================================== */} - - {/* - - {" "} -
- - - - {" "} - {`${userName} (${contactno})`} - -
-
- - - - - - - Membership Number - - - - - - Select Package - - { - setPackDays(e.target.value); - console.log(e.target.value); - - }} - > - - Trendy (30 days) - - - {" "} - Premiun (60 days) - - - {" "} - Gold (90 days) - - - {" "} - Platinum (365 days) - - - - - - Start Date - - - ( - - )} - onChange={(e) => { - setStartDate( - e.format("DD/MM/YYYY") - ); - console.log( - e.format("DD/MM/YYYY") - ); - }} - /> - - - - - Validity - - - ( - - )} - /> - - - - - - - - -
*/} - {/* - - */} - {/* - - Delete - */}
@@ -1729,32 +1105,10 @@ const Customers = () => { item xs={12} sx={{ - // "&::-webkit-scrollbar": { - // width: "3px", // Customize the width of the scrollbar - // }, - // "&::-webkit-scrollbar-thumb": { - // backgroundColor: "#65387A", // Customize the scrollbar thumb color - // }, height: '100%' - // height: '415px', - // overflowY:'scroll', }} > - {/* */} - {/* */} { item xs={12} sx={{ - // height: '300px', height: '100%' }} > - {/* */} - // 'View all' - // {/* */} - // } secondary={ { > { - {/* # - Sales - Avg. Price - - Total - */} # CUSTOMER ORDER ID @@ -1867,20 +1204,6 @@ const Customers = () => { {orderlist.map((row, index) => ( <> - {/* - - {row.customername} - - - {row.contactno} - - */} - {/* {row.product} - {row.date} - - {row.badgeText} - */} - {row.sno} @@ -1915,7 +1238,6 @@ const Customers = () => { - {/* {row.pickupaddress.slice(0, 20)} */} {row.locationsuburb || row.pickupaddress.slice(0, 20)} @@ -1925,13 +1247,11 @@ const Customers = () => { - {/* {row.deliveryaddress.slice(0, 20)} */} {row.customersuburb || row.deliveryaddress.slice(0, 20)} - {/* {row.ordernotes} */} {row.orderstatus === 'pending' && } @@ -1957,163 +1277,14 @@ const Customers = () => { - {/* -
- - - # - CUSTOMER - ORDER ID - PICKUP - DELIVERY - STATUS - - - - - - {orderlist.map((row)=>{ - - return <> - - {row.sno} - - - - - - - - {row.customername} - - - {row.contactno} - - - - - - {row.orderid} - - {dayjs(row.deliverytime).utc().format('DD/MM/YYYY')} - - - {dayjs(row.deliverytime).utc().format('hh:mm A')} - - - - - - - {row.pickupaddress.slice(0, 20)} - - - - - - - - - - {row.deliveryaddress.slice(0, 20)} - - - - - - {row.ordernotes} - - - - {(row.orderstatus === 'pending') && - - - } - {(row.orderstatus === 'modified') && - - } - {(row.orderstatus === 'cancelled') && - - - - } - {(row.orderstatus === 'delivered') && - - - } - {(row.orderstatus === 'processing') && - - } - {(row.orderstatus === 'ready') && - - } - {(row.orderstatus === 'confirmed') && - - } - - {(row.orderstatus === 'active') && - - } - {(row.orderstatus === 'closed') && - - } - {(row.orderstatus === 'created') && - - } - - - - - - - - - - }) - - } - - -
- */}
- {/*
-
*/}
- {/* */} - {/* - - */} - - {/*
*/} @@ -2129,13 +1300,11 @@ const Customers = () => { 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) { @@ -2199,7 +1368,6 @@ const Customers = () => { + } + > + + + + + S.No + Customer + Address + Kms + Charge + Action + + + + {!dropCust && ( + + + + + + )} + {dropCust?.map((customer, index) => ( + + {index + 1} + {customer.firstname} + {customer.address} + {customer.distance} + {`₹${customer.totalcharge}.00`} + + { + handleCheckboxChange(event, customer)} + /> + } + + + ))} + {dropCust?.length != 0 && ( + + + Total + + + + + {`${totaldist} `} + + + {`₹${totalAmt}.00`} + + + + )} + +
+
+ + + {/* ================================================= || Riders Map || ================================================= */} + + {/* {showMap && dropCust.length >= 1 && } */} + + {/* ================================================= || Notes || ================================================= */} + {dropCust && ( + + + + setOtherinstructions(e.target.value)} + /> + + - } - > - - - - - S.No - Customer - Address - Kms - Charge - Action - - - - {dropCust.map((customer, index) => ( - - {index + 1} - {customer.firstname} - {customer.address} - {customer.distance} - {`₹${customer.totalcharge}.00`} - - { - handleCheckboxChange(event, customer)} - /> - } - - - ))} - {dropCust.length != 0 && ( - - - Total - - - - - {`${totaldist} `} - - - {`₹${totalAmt}.00`} - - - - )} - -
-
-
- + + + + )} - - {/* ================================================= || Notes || ================================================= */} - - - - setOtherinstructions(e.target.value)} - /> - - - - - - - - {/* ============================================= || saved address Dialog || ============================================= */} { {isLoading && } - {`Select Drop Customers (${dropCust.length || 0})`} + {`Select Drop Customers (${dropCust?.length || 0})`} { cust.customerid === customer.customerid)} // Set the checked state of the checkbox based on whether the customer is in `dropCust` + checked={dropCust?.some((cust) => cust.customerid === customer.customerid)} // Set the checked state of the checkbox based on whether the customer is in `dropCust` onChange={(event) => handleCheckboxChange(event, customer)} /> } @@ -866,19 +872,22 @@ const MultipleOrders = () => { diff --git a/src/pages/nearle/orders/orders.js b/src/pages/nearle/orders/orders.js index 75007c0..014376e 100644 --- a/src/pages/nearle/orders/orders.js +++ b/src/pages/nearle/orders/orders.js @@ -10,10 +10,10 @@ import axios from 'axios'; import HoverSocialCard from 'components/cards/statistics/HoverSocialCard'; import { useTheme } from '@mui/material/styles'; import MyLocationIcon from '@mui/icons-material/MyLocation'; +import { CalendarMonth, CancelOutlined, CheckCircleOutline } from '@mui/icons-material'; import { Avatar, - Box, Button, Grid, Tabs, @@ -29,35 +29,37 @@ import { Dialog, TableRow, DialogContent, - DialogTitle, Tooltip, FormControl, OutlinedInput, InputAdornment, Skeleton, Autocomplete, - TextField + TextField, + CircularProgress } from '@mui/material'; import { SearchOutlined, CloseOutlined } from '@ant-design/icons'; import ClearIcon from '@mui/icons-material/Clear'; -import { addDays, addMonths, addWeeks, endOfMonth, endOfWeek, startOfMonth, startOfWeek } from 'date-fns'; -import { DateRangePicker } from 'mui-daterange-picker'; import TableContainer from '@mui/material/TableContainer'; import TablePagination from '@mui/material/TablePagination'; -import TableSortLabel from '@mui/material/TableSortLabel'; -import { visuallyHidden } from '@mui/utils'; import Loader from 'components/Loader'; -import { FilterList } from '@mui/icons-material'; -import { Outlet } from 'react-router'; +// import { FilterList } from '@mui/icons-material'; +import { useHotkeyFocus } from 'components/nearle_components/useHotkeyFocus'; +import DateFilterDialog from 'components/nearle_components/DateFilterDialog'; +import MainCard from 'components/MainCard'; +import AccessTimeIcon from '@mui/icons-material/AccessTime'; +import LocalShippingOutlinedIcon from '@mui/icons-material/LocalShippingOutlined'; +import CircularLoader from 'components/nearle_components/CircularLoader'; +import { useInfiniteQuery } from '@tanstack/react-query'; const Orders = () => { const tid = localStorage.getItem('tenantid'); const tenId = localStorage.getItem('tenantid'); + const loadMoreRef = useRef(); + const containerRef = useRef(); const [page, setPage] = React.useState(0); const [rowsPerPage, setRowsPerPage] = React.useState(10); - const [pageCount, setPageCount] = React.useState(); - const [startdate, setStartdate] = useState(dayjs().format('YYYY-MM-DD')); - const [enddate, setEnddate] = useState(dayjs().format('YYYY-MM-DD')); + const [pageCount, setPageCount] = React.useState(0); const [percentage1, setPercentage1] = useState('0'); const [percentage2, setPercentage2] = useState('0'); const [percentage3, setPercentage3] = useState('0'); @@ -67,14 +69,10 @@ const Orders = () => { const [uncoveredorders, setUncoveredorders] = useState(''); const [cancelled, setCancelled] = useState(''); const [created, setCreated] = useState(''); - const [tabstatus, setTabstatus] = useState('Created'); - const [loading, setLoading] = useState(true); + const [loading, setLoading] = useState(false); const theme = useTheme(); - let [rows, setRows] = useState([]); const [tabvalue, setTabvalue] = useState(0); - const [open, setOpen] = useState(false); - const [datestatus, setDatestatus] = useState('Today'); - const [searchword, setSearchword] = useState(''); + const [tabstatus, setTabstatus] = useState('Created'); const [currentStatus, setCurrentStatus] = useState('created'); const [createdLenght, setCreatedLenght] = useState(); const [pendingLenght, setPendingLenght] = useState(); @@ -84,54 +82,60 @@ const Orders = () => { const [orderheaderid, setOrderheaderid] = useState(''); const [locationId, setLocationId] = useState(0); const [locoName, setLocoName] = useState('Select Location'); + const [dateOpen, setDateOpen] = useState(false); + const [datestatus, setDatestatus] = useState('Today'); + const [startdate, setStartdate] = useState(dayjs().format('YYYY-MM-DD')); + const [enddate, setEnddate] = useState(dayjs().format('YYYY-MM-DD')); - const handleChangetab = (e, i) => { - setTabvalue(i); - - if (i === 0) { - setTabstatus('Created'); - setCurrentStatus('created'); - } - if (i === 1) { - setTabstatus('Pending'); - setCurrentStatus('pending'); - } - if (i === 2) { - setTabstatus('Delivered'); - setCurrentStatus('delivered'); - } - if (i === 3) { - setTabstatus('Cancelled'); - setCurrentStatus('cancelled'); - } - console.log(i); - }; - - const okclicked = () => { - setOpen(false); - }; - const textFieldRef = useRef(null); - - /* ============================================= || handleKeyPress (ctrl+k)| ============================================= */ + const [searchword, setSearchword] = useState(''); + const [debouncedSearch, setDebouncedSearch] = useState(''); useEffect(() => { - const handleKeyPress = (event) => { - if (event.key === 'k' && (event.metaKey || event.ctrlKey)) { - event.preventDefault(); + const handler = setTimeout(() => { + setDebouncedSearch(searchword); + }, 400); - textFieldRef.current.focus(); - } - if (event.key === 'Escape' && document.activeElement === textFieldRef.current) { - // Remove focus from the TextField - textFieldRef.current.blur(); - } - }; - document.addEventListener('keydown', handleKeyPress); + return () => clearTimeout(handler); + }, [searchword]); - return () => { - document.removeEventListener('keydown', handleKeyPress); - }; - }, []); + const statusMap = [ + { + label: 'Created', + value: 'created', + count: createdLenght, + icon: + }, + { + label: 'Pending', + value: 'pending', + count: pendingLenght, + icon: + }, + { + label: 'Delivered', + value: 'delivered', + count: deliveredlenght, + icon: + }, + { + label: 'Cancelled', + value: 'cancelled', + count: cancelledLenght, + icon: + } + ]; + + const handleChangetab = (e, i) => { + setSearchword(''); + setRowsPerPage(10); + setTabvalue(i); + setTabstatus(statusMap[i].label); + setCurrentStatus(statusMap[i].value); + setPage(0); + }; + + const textFieldRef = useRef(null); + useHotkeyFocus(textFieldRef, 'k'); const handleChangePage = (event, newPage) => { setPage(newPage); @@ -143,6 +147,7 @@ const Orders = () => { }; const cancelorder = async () => { + setLoading(true); await axios .put(`${process.env.REACT_APP_URL}/orders/updateorder`, { orderheaderid: orderheaderid, @@ -157,39 +162,97 @@ const Orders = () => { anchorOrigin: { vertical: 'top', horizontal: 'right' }, autoHideDuration: 2000 }); - fetchtablecovered(); + getOrders(); fetchorderscount(); setCancelOpen(false); } + setLoading(false); }) .catch((err) => { console.log(err); + setLoading(false); }); }; - const fetchtablecovered = async () => { - try { - await axios - .get( - `${ - process.env.REACT_APP_URL - }/orders/tenant/getorders/?tenantid=${tid}&locationid=${locationId}&status=${currentStatus}&fromdate=${startdate}&todate=${enddate}&pageno=${ - page + 1 - }&pagesize=${rowsPerPage}&keyword=${searchword}` - ) - .then((res) => { - setRows(res.data.details); - }) - .catch((err) => { - console.log(err); - }); - } catch (err) { - console.log(err); + // const getOrders = async () => { + // try { + // await axios + // .get( + // `${ + // process.env.REACT_APP_URL + // }/orders/tenant/getorders/?tenantid=${tid}&locationid=${locationId}&status=${currentStatus}&fromdate=${startdate}&todate=${enddate}&pageno=${ + // page + 1 + // }&pagesize=${rowsPerPage}&keyword=${debouncedSearch}` + // ) + // .then((res) => { + // setRows(res.data.details); + // }) + // .catch((err) => { + // console.log(err); + // }); + // } catch (err) { + // console.log(err); + // } + // }; + // useEffect(() => { + // getOrders(); + // }, [tabstatus, startdate, enddate, page, rowsPerPage, debouncedSearch, locationId]); + const fetchOrders = async ({ pageParam = 1 }) => { + const res = await axios.get( + `${process.env.REACT_APP_URL}/orders/tenant/getorders/?tenantid=${tid}&locationid=${locationId}&status=${currentStatus}&fromdate=${startdate}&todate=${enddate}&pageno=${pageParam}&pagesize=${rowsPerPage}&keyword=${debouncedSearch}` + ); + + return { + data: res.data.details, + nextPage: res.data.details.length === rowsPerPage ? pageParam + 1 : undefined + }; + }; + + const { + data: rowdata, + isError: isErrorGetOrders, + error: errorGetOrders, + fetchNextPage, + isLoading: isLoadingGeyOrders, + hasNextPage, + isFetchingNextPage + // status: rowdataStatus + } = useInfiniteQuery({ + queryKey: [tabstatus, startdate, enddate, page, rowsPerPage, debouncedSearch, locationId], + queryFn: fetchOrders, + getNextPageParam: (lastPage) => lastPage.nextPage + }); + + const rows = rowdata ? rowdata.pages.flatMap((p) => p.data) : []; + + useEffect(() => { + if (!hasNextPage) return; + const observer = new IntersectionObserver( + (entries) => { + if (entries[0].isIntersecting) { + fetchNextPage(); + } + }, + { + root: document.querySelector('.MuiTableContainer-root'), // 👈 or explicitly TableContainer + rootMargin: '0px', + threshold: 1.0 + } + ); + if (loadMoreRef.current) observer.observe(loadMoreRef.current); + return () => { + if (loadMoreRef.current) observer.unobserve(loadMoreRef.current); + }; + }, [hasNextPage, fetchNextPage]); + + const handleScroll = (event) => { + const { scrollTop, scrollHeight, clientHeight } = event.currentTarget; + if (scrollTop + clientHeight >= scrollHeight - 50) { + if (hasNextPage && !isFetchingNextPage) { + fetchNextPage(); + } } }; - useEffect(() => { - fetchtablecovered(); - }, [tabstatus, startdate, enddate, page, rowsPerPage, searchword, locationId]); const fetchpercentage = async () => { setLoading(true); @@ -197,7 +260,7 @@ const Orders = () => { await axios .get(`${process.env.REACT_APP_URL}/orders/getordersummary/?tenantid=${tid}`) .then((res) => { - console.log(res); + console.log('summary', res.data.details); setCoveredorders(res.data.details.delivered.toString()); setCancelled(res.data.details.cancelled.toString()); setUncoveredorders(res.data.details.pending.toString()); @@ -230,7 +293,6 @@ const Orders = () => { ) .then((res) => { console.log('fetchorderscount', res.data.details); - setCreatedLenght(res.data.details.created); setPendingLenght(res.data.details.pending); setDeliveredlenght(res.data.details.delivered); @@ -252,7 +314,7 @@ const Orders = () => { }; useEffect(() => { fetchorderscount(); - }, [tabvalue, locationId]); + }, [tabvalue, locationId, startdate, enddate]); // ============================================= || gettenantlocations (branches) || ============================================= const gettenantlocations = async (id) => { try { @@ -275,13 +337,20 @@ const Orders = () => { return ( <> - {loading && } - - + {loading && ( + <> + + + + )} + {/* ============================================== || TitleCard || ============================================== */} + Orders - - + {/* ============================================== || HoverSocialCard || ============================================== */} + + + : created} @@ -289,7 +358,7 @@ const Orders = () => { color={theme.palette.primary.main} /> - + : uncoveredorders} @@ -298,7 +367,7 @@ const Orders = () => { /> - + : coveredorders} @@ -307,7 +376,7 @@ const Orders = () => { /> - + : cancelled} @@ -316,10 +385,20 @@ const Orders = () => { /> - + {/* ============================================== || Filters || ============================================== */} + + {startdate && enddate && ( - - + + { {dayjs(startdate).format('DD/MM/YYYY')} - {dayjs(enddate).format('DD/MM/YYYY')} } + sx={{ cursor: 'pointer' }} variant="combined" color="warning" - size="small" + onClick={() => setDateOpen(true)} + deleteIcon={} + onDelete={() => setDateOpen(true)} /> )} - - - {tenantLocations.length == 1 ? ( - - - - ) - }} - /> - ) : ( - `${option.locationname} (${option.suburb})` || ''} - renderInput={(params) => } - 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'); - } - }} - /> - )} - - + + {tenantLocations.length == 1 ? ( + + + + ) + }} + /> + ) : ( + `${option.locationname} (${option.suburb})` || ''} + renderInput={(params) => } + sx={{ + width: { xs: '100%', custom800: 400 } + }} + 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'); + } + }} + /> + )} + {/* setOpen(true)} + onClick={() => setDateOpen(true)} > - + */} - - - + {/* Tabs Wrapper */} + + + {statusMap.map((item, index) => ( + + {item.icon} + {item.label} + + + } + /> + ))} + + + {/* Search Box */} + + + setSearchword(e.target.value)} + autoComplete="off" + startAdornment={ + + + + } + endAdornment={ + + { + setSearchword(''); + getOrders(); + fetchorderscount(); + }} + > + + + + } + /> + + + + + + - - } iconPosition="end" /> - } iconPosition="end" /> - } - iconPosition="end" - /> - } - iconPosition="end" - /> - - - - { - setSearchword(e.target.value); - }} - autoComplete="off" - startAdornment={ - - - - } - endAdornment={ - - { - setSearchword(''); - fetchtablecovered(); - fetchorderscount(); + + + + S.No + Orders + Pickup + Drop + Notes + Status + {currentStatus == 'created' && ( + Action + )} + + + {loading && ( + <> + + {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map((item, index) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ))} + + + )} + + {rows?.length == 0 && ( + <> + + + + + + + )} + + {rows?.map((row, index) => { + return ( + <> + - - - - } - /> - - - + + {page * rowsPerPage + index + 1} + - - - -
- - - S.No - Orders - Pickup - Drop - Notes - Status - Action - - - {loading && ( - <> - - {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map((item, index) => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ))} - - - )} - - {rows?.length == 0 && ( - <> - - - + + + {row.orderid} + + + {dayjs(row.deliverydate).utc().format('DD/MM/YYYY')} + + + {dayjs(row.deliverydate).utc().format('hh:mm A')} + + + + + + + + {row.pickupcustomer} + + {row.pickupcontactno} + + + + {row.pickupsuburb || row.pickupaddress.slice(0, 20)} + + + - - )} - - {rows?.map((row, index) => { - return ( - <> - - - {page * rowsPerPage + index + 1} - - - - - {row.orderid} + + + + + {row.deliverycustomer} + + {row.deliverycontactno} - - {dayjs(row.deliverydate).utc().format('DD/MM/YYYY')} - - - {dayjs(row.deliverydate).utc().format('hh:mm A')} - - + + + {/* {row.pickupaddress.slice(0, 20)} */} + {row.deliverysuburb || row.deliveryaddress.slice(0, 20)} + + + + + + {row.ordernotes} + {/* */} + + + {row.orderstatus === 'pending' && } + {row.orderstatus === 'modified' && } + {row.orderstatus === 'cancelled' && } + {row.orderstatus === 'delivered' && } + {row.orderstatus === 'processing' && } + {row.orderstatus === 'ready' && } + {row.orderstatus === 'confirmed' && } - - - - - {row.pickupcustomer} - - {row.pickupcontactno} - - - - {row.pickupsuburb || row.pickupaddress.slice(0, 20)} - - - - - - - - - - {row.deliverycustomer} - - {row.deliverycontactno} - - - - {/* {row.pickupaddress.slice(0, 20)} */} - {row.deliverysuburb || row.deliveryaddress.slice(0, 20)} - - - - - - {row.ordernotes} - {/* */} - - - {row.orderstatus === 'pending' && } - {row.orderstatus === 'modified' && } - {row.orderstatus === 'cancelled' && } - {row.orderstatus === 'delivered' && } - {row.orderstatus === 'processing' && } - {row.orderstatus === 'ready' && } - {row.orderstatus === 'confirmed' && } + {row.orderstatus === 'active' && } + {row.orderstatus === 'closed' && } + {row.orderstatus === 'created' && } + + - {row.orderstatus === 'active' && } - {row.orderstatus === 'closed' && } - {row.orderstatus === 'created' && } - - - - - {row.orderstatus == 'created' && ( - <> - - { - e.stopPropagation(); - setOrderheaderid(row.orderheaderid); - setCancelOpen(true); + {currentStatus == 'created' && ( + + {row.orderstatus == 'created' && ( + <> + + { + e.stopPropagation(); + setOrderheaderid(row.orderheaderid); + setCancelOpen(true); + }} + > + - - - - - )} - - - - ); - })} - -
-
- - - - -
+ // twoToneColor={theme.palette.primary.main} + /> + + + + )} + + )} + + + ); + })} + {rows?.length != 0 && ( + + +
+ {isFetchingNextPage ? : hasNextPage ? : 'No More Orders'} +
+
+
+ )} + + + + + + {/* ============================================== || cancel order || ============================================== */} setCancelOpen(false)} maxWidth="xs"> @@ -686,87 +803,15 @@ const Orders = () => { {/* ============================================== || Date filter || ============================================== */} - - - Select Filter Options - - - 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), - // }, - ]} - /> - - - - - + setDateOpen(false)} + onApply={({ startDate, endDate, label }) => { + setStartdate(startDate); + setEnddate(endDate); + setDatestatus(label); + }} + /> ); }; diff --git a/src/pages/nearle/orders/ridersPinPoint.js b/src/pages/nearle/orders/ridersPinPoint.js new file mode 100644 index 0000000..a7506f7 --- /dev/null +++ b/src/pages/nearle/orders/ridersPinPoint.js @@ -0,0 +1,53 @@ +import { LoadScriptNext, GoogleMap, Marker } from '@react-google-maps/api'; + +// distance function +function distance(lat1, lng1, lat2, lng2) { + const R = 6371; + const dLat = (lat2 - lat1) * (Math.PI / 180); + const dLng = (lng2 - lng1) * (Math.PI / 180); + + const a = Math.sin(dLat / 2) ** 2 + Math.cos(lat1 * (Math.PI / 180)) * Math.cos(lat2 * (Math.PI / 180)) * Math.sin(dLng / 2) ** 2; + + return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); +} + +const containerStyle = { + width: '100%', + height: '300px' +}; + +export default function RidersPinPoint({ pickCust, dropCust }) { + // Ensure valid lat/lng + const center = pickCust?.latitude && pickCust?.longitude ? { lat: Number(pickCust.latitude), lng: Number(pickCust.longitude) } : null; + + // If center missing, don't render map + if (!center) return null; + + const sortedRiders = dropCust + ?.map((r) => ({ + ...r, + distance: distance(center.lat, center.lng, Number(r.latitude), Number(r.longitude)) + })) + .sort((a, b) => a.distance - b.distance); + + return ( + + + + + {sortedRiders?.map((r, index) => ( + + ))} + + + ); +} diff --git a/src/pages/nearle/orders/rough.js b/src/pages/nearle/orders/rough.js index 0bc9698..809335b 100644 --- a/src/pages/nearle/orders/rough.js +++ b/src/pages/nearle/orders/rough.js @@ -740,7 +740,7 @@ const Createorder1 = () => { setLoading(true); await axios - .post(`${process.env.REACT_APP_URL}/orders/createorders`, arr) + .post(`${process.env.REACT_APP_URL}/orders/create/grouporders`, arr) .then((res) => { if (res.data.status) { enqueueSnackbar('Order Created Successfully', { @@ -753,7 +753,7 @@ const Createorder1 = () => { sendnotifications(); } - navigate('/orders'); + navigate('/nearle/orders'); } else { opentoast(res.data.message, 'warning'); } diff --git a/src/pages/nearle/reports/orderSummary.js b/src/pages/nearle/reports/orderSummary.js index 7e97288..96aaf84 100644 --- a/src/pages/nearle/reports/orderSummary.js +++ b/src/pages/nearle/reports/orderSummary.js @@ -6,6 +6,8 @@ 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'; +import { enqueueSnackbar } from 'notistack'; +import { CalendarMonth } from '@mui/icons-material'; // material-ui import { @@ -60,7 +62,8 @@ 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'; +import { getreportlocationsummary, gettenantlocations } from '../api/api'; +import CircularLoader from 'components/nearle_components/CircularLoader'; function formatNumberToRupees(value) { return new Intl.NumberFormat('en-IN', { @@ -70,6 +73,14 @@ function formatNumberToRupees(value) { }).format(value); } +const opentoast = (message, variant, time) => { + enqueueSnackbar(message, { + variant: variant, + anchorOrigin: { vertical: 'top', horizontal: 'right' }, + autoHideDuration: time ? time : 1500 + }); +}; + // ==============================|| MUI TABLE - ENHANCED ||============================== // export default function OrdersReport() { @@ -95,7 +106,6 @@ export default function OrdersReport() { 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); @@ -125,18 +135,16 @@ export default function OrdersReport() { }, []); // ============================================= || 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(); - }, []); + + const { + data: tenantLocations, + isLoading: tenantLocationsIsLoading, + isError: tenantLocationsIsError, + error: tenantLocationsError + } = useQuery({ + queryKey: ['tenantlocations'], + queryFn: gettenantlocations + }); // ==============================|| fetchOrdersSummary (orders summary)||============================== // const { @@ -196,139 +204,153 @@ export default function OrdersReport() { calculate(); }, [rows]); - // if (isLoadingReports) return ; - if (isErrorReports) return 'An error has occurred:(isErrorReports) ' + reportsError.message; + let errormessage = ''; + + if (isErrorReports && reportsError?.message) { + errormessage = `An error has occurred: (isErrorReports) ${reportsError.message}`; + } else if (tenantLocationsIsError && tenantLocationsError?.message) { + errormessage = `An error has occurred: (tenantLocationsIsError) ${tenantLocationsError.message}`; + } + + useEffect(() => { + if (errormessage) { + console.log('errormessage', errormessage); + opentoast(errormessage, 'warning', 2000); + } + }, [errormessage]); return ( <> - {isLoadingReports && } - {' '} + {(isLoadingReports || tenantLocationsIsLoading) && } + {(isLoadingReports || tenantLocationsIsLoading) && } + + {startdate && enddate && ( + + + + {dayjs(startdate).format('DD/MM/YYYY')} - {dayjs(enddate).format('DD/MM/YYYY')} + + } + variant="combined" + color="warning" + size="small" + deleteIcon={} + onDelete={() => { + setOpen(true); + }} + onClick={() => setOpen(true)} + sx={{ cursor: 'pointer' }} + /> + + )} + {(!startdate || !enddate) && ( + <> + + + + + )} +
+ } + />{' '} - - {startdate && enddate && ( - - - - {dayjs(startdate).format('DD/MM/YYYY')} - {dayjs(enddate).format('DD/MM/YYYY')} - - } - variant="combined" - color="warning" - size="small" - /> - - )} - {(!startdate || !enddate) && ( - <> - - - - - )} - - - - { - setSearchword(e.target.value); - }} - autoComplete="off" - startAdornment={ - - - - } - endAdornment={ - { - setSearchword(''); - }} - > - + + {/* Search Input */} + + setSearchword(e.target.value)} + autoComplete="off" + size="medium" + sx={{ + bgcolor: 'white', + borderRadius: 2 + }} + startAdornment={ + + + + } + endAdornment={ + + setSearchword('')}> + - } - /> - - - {tenantLocations.length == 1 ? ( + + } + /> + + + {/* Location Input */} + {tenantLocations?.length === 1 ? ( + + + + ), + sx: { bgcolor: 'white' } + }} + /> + ) : ( + `${o.locationname} (${o.suburb})`} + onChange={(event, value, reason) => { + setSelectedLocation(value); + setLocationId(value ? value.locationid : 0); + }} + sx={{ + minWidth: 250, + maxWidth: 400, + flex: 1 + }} + renderInput={(params) => ( - - - ) + {...params} + label="Choose Location" + color="primary" + sx={{ + bgcolor: 'white', + borderRadius: 2 }} /> - ) : ( - `${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) => } - /> )} - - - - setOpen(true)} - > - - - - + /> + )} } > @@ -336,8 +358,9 @@ export default function OrdersReport() { sx={{ overflow: 'auto', '&::-webkit-scrollbar': { - width: '3px', - height: '3px' + width: '12px', // Width of vertical scrollbar + height: '14px', // Height of horizontal scrollbar, + borderRadius: 10 }, '&::-webkit-scrollbar-thumb': { backgroundColor: '#65387A' // Color of the scrollbar thumb @@ -357,7 +380,7 @@ export default function OrdersReport() { Deliveries{' '} Kilometer - Charges + {/* Charges */} Amount Action @@ -380,10 +403,6 @@ export default function OrdersReport() { @@ -418,7 +437,7 @@ export default function OrdersReport() { /> -
+ {/*
- + */} - - + {/* */} + {/* -
- +
*/} + {/* - -
+
*/} + {/*
*/} - - Riders Summary - - - # + + # Rider - Deliveries - Assigned - Accepted - Picked - Delivered - kms/Actualkms - POD/PLA + Deliveries + Pending + Assigned + Accepted + Arrived + Picked + Skipped + Delivered + kms + {/* POD/PLA */} Charges - + {ridersdata?.map((rider, index) => ( - - {index + 1} + + + {index + 1} + {rider?.firstname} @@ -555,27 +595,30 @@ export default function OrdersReport() { )} - {rider?.deliveries} - {rider?.Assigened} - {rider?.Accepted} - {rider?.Picked} - {rider?.delivered} + {rider?.totalorders} + {rider?.pending} + {rider?.assigned} + {rider?.accepted} + {rider?.picked} + {rider?.arrived} + {rider?.skipped} + {rider?.delivered} - - - - + {/* */} + + {/* */} + {/* - + */} - - + {/* */} + {/* - - - - - + */} + {/* */} + {/* */} + {/* */} + {/* */} lastPage.nextPage }); + const rows = rowdata?.pages.flatMap((page) => page.details) || []; useEffect(() => { if (!hasNextPage) return; - const observer = new IntersectionObserver( (entries) => { if (entries[0].isIntersecting) { @@ -207,9 +209,7 @@ export default function OrdersDetails() { threshold: 1.0 } ); - if (loadMoreRef.current) observer.observe(loadMoreRef.current); - return () => { if (loadMoreRef.current) observer.unobserve(loadMoreRef.current); }; @@ -245,6 +245,7 @@ export default function OrdersDetails() { }, [currentStatus, deliverycount]); // ==============================|| calculate||============================== // + const calculate = () => { let calculatedTotalCharge = 0; let calculatedTotalAmount = 0; @@ -268,23 +269,9 @@ export default function OrdersDetails() { if (isErrorOrderDetails) return 'An error has occurred:(isErrorOrderDetails) ' + orderDetailsError.message; - const filteredOrders = rows.filter((row) => - row.orderstatus == '' - ? row.orderstatus.toLowerCase().includes(searchword.toLowerCase()) - : row.orderstatus.toLowerCase().includes(searchword.toLowerCase()) || - row.ordernotes.toLowerCase().includes(searchword.toLowerCase()) || - row.tenantname.toLowerCase().includes(searchword.toLowerCase()) || - row.orderid.toLowerCase().includes(searchword.toLowerCase()) || - row.pickupcustomer.toLowerCase().includes(searchword.toLowerCase()) || - row.pickupcontactno.toLowerCase().includes(searchword.toLowerCase()) || - row.pickuplocation.toLowerCase().includes(searchword.toLowerCase()) || - row.deliverycustomer.toLowerCase().includes(searchword.toLowerCase()) || - row.deliverycontactno.toLowerCase().includes(searchword.toLowerCase()) || - row.deliverylocation.toLowerCase().includes(searchword.toLowerCase()) || - row.ridername.toLowerCase().includes(searchword.toLowerCase()) - ); // to download ex format filtered data - const csvData = filteredOrders.map((order) => ({ + + const csvData = rows.map((order) => ({ tenantname: order.tenantname, tenantcity: order.tenantcity, tenantcontactno: order.tenantcontactno, @@ -345,161 +332,166 @@ export default function OrdersDetails() { return ( <> {isLoadingOrderDetails && } - + + {startdate && enddate && ( + + {`Orders-${datestatus}`} + + {dayjs(startdate).format('DD/MM/YYYY')} - {dayjs(enddate).format('DD/MM/YYYY')} + + } + variant="combined" + color="warning" + size="small" + deleteIcon={} + onDelete={() => { + setOpen(true); + }} + onClick={() => setOpen(true)} + sx={{ cursor: 'pointer' }} + /> + + )} + {(!startdate || !enddate) && ( +
+ + + {/* ALL} variant="combined" color='warning' size='small' /> */} + +
+ )} + + + } + /> - - {startdate && enddate && ( - - {`Orders-${datestatus}`} - - - {dayjs(startdate).format('DD/MM/YYYY')} - {dayjs(enddate).format('DD/MM/YYYY')} - - } - variant="combined" - color="warning" - size="small" - /> - - )} - {(!startdate || !enddate) && ( -
- - - {/* ALL} variant="combined" color='warning' size='small' /> */} - -
- )} -
- - - {tenantLocations.length == 1 ? ( - - - - ) - }} - /> - ) : ( - `${option.locationname} (${option.suburb})` || ''} - renderInput={(params) => } - 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'); - } - }} - /> - )} - + + {tenantLocations.length == 1 ? ( + + + + ) + }} + /> + ) : ( `${option.status}`} + options={tenantLocations || []} + getOptionLabel={(option) => `${option.locationname} (${option.suburb})` || ''} + renderInput={(params) => } + sx={{ minWidth: 250, maxWidth: 400, flex: 1 }} onChange={(event, value, reason) => { - if (reason === 'clear') { - setCurrentStatus('All'); - } else { - console.log('status', value); - setCurrentStatus(value.statusLow); + if (value) { + console.log('Business Locations', value); + setLocationId(value.locationid); + setLocoName(value.locationname); + } + if (reason == 'clear') { + setLocationId(0); + setLocoName('Select Location'); } }} - renderInput={(params) => } /> - - { - setSearchword(e.target.value); - }} - autoComplete="off" - startAdornment={ - - - - } - endAdornment={ - - { - setSearchword(''); - }} - > - - - - } - /> - + )} - - setOpen(true)} - > - - - + `${option.status}`} + onChange={(event, value, reason) => { + if (reason === 'clear') { + setCurrentStatus('All'); + } else { + console.log('status', value); + setCurrentStatus(value.statusLow); + } + }} + renderInput={(params) => } + /> + + { + setSearchword(e.target.value); + }} + autoComplete="off" + startAdornment={ + + + + } + endAdornment={ + + { + setSearchword(''); + }} + > + + + + } + /> + - - + {/* + setOpen(true)} + > + + + */} } > @@ -531,24 +523,24 @@ export default function OrdersDetails() { > # - Map - Tenant Name + {/* {} */} + Location Pickup Drop Status - Assignes + Assigned Accepted Arrived Picked Delivered Cancelled - Notes + {/* Notes */} Kms Charges - {filteredOrders.length == 0 && ( + {rows?.length == 0 && ( <> @@ -557,12 +549,12 @@ export default function OrdersDetails() { )} - {filteredOrders.map((row, index) => { + {rows?.map((row, index) => { return ( - filteredOrders.length !== 0 && ( + rows?.length !== 0 && ( {index + 1} - { console.log('row', row); @@ -572,13 +564,14 @@ export default function OrdersDetails() { }} > {} - +
*/} - {row.tenantname} + {row.locationname} {row.orderid} @@ -591,7 +584,7 @@ export default function OrdersDetails() { - + {row.pickupcustomer} {row.pickupcontactno} @@ -606,7 +599,7 @@ export default function OrdersDetails() { - + {row.deliverycustomer} {row.deliverycontactno} @@ -695,25 +688,24 @@ export default function OrdersDetails() { - + {/* {row.ordernotes} - + */} - - - - + + + {/* - + */} - - - - + + + {/* - + */}
) ); })} - - -
- {isFetchingNextPage ? : hasNextPage ? : 'No more results'} -
-
-
+ + {rows?.length != 0 && ( + + +
+ {isFetchingNextPage ? : hasNextPage ? : 'No More Orders'} +
+
+
+ )}
diff --git a/src/pages/nearle/reports/riderLogs.js b/src/pages/nearle/reports/riderLogs.js index 798e3d9..6eb49c7 100644 --- a/src/pages/nearle/reports/riderLogs.js +++ b/src/pages/nearle/reports/riderLogs.js @@ -1,7 +1,209 @@ -import React from 'react'; +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 { + Divider, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + FormControl, + OutlinedInput, + InputAdornment, + Chip, + Stack +} from '@mui/material'; -const riderLogs = () => { - return
riderLogs
; -}; +import dayjs from 'dayjs'; +var utc = require('dayjs/plugin/utc'); +dayjs.extend(utc); +import { SearchOutlined, CloseOutlined } from '@ant-design/icons'; +import Loader from 'components/Loader'; +// project imports +import MainCard from 'components/MainCard'; +import { Empty } from 'antd'; +import TitleCard from '../titleCard'; +import { fetchAppLocations, fetchRidersLogs } from '../api/api'; -export default riderLogs; +function formatDate(dateString) { + const date = dayjs(dateString); + const formattedDate = date.format('DD-MM-YYYY '); + return formattedDate; +} + +const formatTime = (timeString) => + new Date('2024-01-01T' + timeString + 'Z').toLocaleTimeString('en-US', { + timeZone: 'UTC', + hour12: true, + hour: '2-digit', + minute: '2-digit' + }); + +// ==============================|| 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 { + data: rows = [], // Default to empty array + isLoading: IsRiderLogsLoading, + isError: IsRiderLogsError, + error: RiderLogsError + } = useQuery({ + queryKey: [tenantid, startdate], // Meaningful query key + queryFn: fetchRidersLogs, + enabled: !!tenantid && !!startdate, // Fetch only if appId & startdate exist + refetchInterval: 300000 // Auto-fetch every 5 minutes + }); + + React.useEffect(() => { + setRowsPerPage(rows?.length + 1); + }, [rows]); + { + IsRiderLogsError && console.log('RiderLogsError', RiderLogsError); + } + + return ( + <> + {IsRiderLogsLoading && } + + + + + + + + } + endAdornment={ + showClose && ( + + { + setSearchword(''); + SetShowClose(false); + }} + /> + + ) + } + aria-describedby="header-search-text" + inputProps={{ + 'aria-label': 'weight' + }} + placeholder="Search" + value={searchword} + onChange={(e) => { + setSearchword(e.target.value); + if (e.target.value == '') { + SetShowClose(false); + } else { + SetShowClose(true); + } + }} + autoComplete="off" + /> + {' '} + + + + { + if (e) { + setStartdate(dayjs(e.$d).format('YYYY-MM-DD')); + } + }} + /> + + + + } + > + + + + + S.No + ID + Rider + LogDate + Shift(HRS) + Login + Logout + WRK(HRS) + Shift(HRS) + BRK(HRS) + Status + + + + {rows.length == 0 ? ( + + + + + + ) : ( + rows.map((row, index) => ( + + {index + 1} + {row.userid} + {row.username} + + {' '} + + + + {row.shifthours} + + {row.login != '' && ( + + )} + + + {row.logout != '' && ( + + )} + + + {row.workhours} + {row.shorthours} + {row.breakhours} + + {row.logstatus == 0 ? ( + + ) : ( + + )} + + + )) + )} + +
+
+
+ + ); +} diff --git a/src/pages/nearle/reports/ridersummary.js b/src/pages/nearle/reports/ridersummary.js index 14ebde0..fcab777 100644 --- a/src/pages/nearle/reports/ridersummary.js +++ b/src/pages/nearle/reports/ridersummary.js @@ -23,8 +23,6 @@ import { IconButton, Tooltip, Chip, - Autocomplete, - TextField, Collapse } from '@mui/material'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; @@ -45,12 +43,12 @@ import { 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'; +import { useTheme } from '@mui/material/styles'; // table filter function descendingComparator(a, b, orderBy) { @@ -88,6 +86,8 @@ function formatNumberToRupees(value) { export default function RidersSummary() { // const [rows, setRows] = useState([]); + const theme = useTheme(); + const tenantid = localStorage.getItem('tenantid'); const [order, setOrder] = useState('asc'); const [orderBy, setOrderBy] = useState('calories'); const [selected, setSelected] = useState([]); @@ -141,9 +141,12 @@ export default function RidersSummary() { data: rows, error: reportsError } = useQuery({ - queryKey: [appId, startdate, enddate], + queryKey: [tenantid, startdate, enddate], queryFn: fetchRidersSummary }); + useEffect(() => { + rows && console.log('rows', rows); + }, [rows]); // ==============================|| calculate||============================== // const calculate = async () => { let calculatedTotal = 0; @@ -157,7 +160,7 @@ export default function RidersSummary() { console.log('calculatedTotal', calculatedTotal); }; useEffect(() => { - calculate(); + rows && calculate(); }, [rows]); if (isLoadingReports) return ; @@ -167,7 +170,8 @@ export default function RidersSummary() { const fetchTenantSummary = async (riderUserid) => { try { const tenantRes = await axios.get( - `${process.env.REACT_APP_URL}/deliveries/getreportsummary/?&fromdate=${startdate}&todate=${enddate}&userid=${riderUserid}` + // `${process.env.REACT_APP_URL}/deliveries/getreportlocationsummary/?&fromdate=${startdate}&todate=${enddate}&userid=${riderUserid}&tenantid=${tenantid}` + `${process.env.REACT_APP_URL}/deliveries/getriderlocationreportsummary/?&fromdate=${startdate}&todate=${enddate}&userid=${riderUserid}&tenantid=${tenantid}` ); console.log('tenantRes', tenantRes.data.details); setTenantData(tenantRes.data.details); @@ -176,42 +180,9 @@ export default function RidersSummary() { } }; - 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 ( <> - - S.No + # Rider - Deliveries + Total + {/* Pending Assigned Accepted + Arrived Picked + Active + Skipped */} Delivered - KMS/Actualkms - POD/PLA + kms + COD/PLA Charges Action @@ -265,7 +240,7 @@ export default function RidersSummary() { {/* ============================================ || TableBody || ============================================ */} - {rows.length === 0 && ( + {/* {rows?.length === 0 && ( @@ -273,57 +248,59 @@ export default function RidersSummary() { - )} + )} */} - {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}`; + {rows?.map((row, index) => ( + <> + {/* // ============================================ || tablerow 1 || ============================================ */} - return ( - rows.length !== 0 && ( - <> - {/* // ============================================ || tablerow 1 || ============================================ */} + + + {index + 1} + + + + {row.firstname} + {row.status == 'Active' ? ( + + ) : ( + + )} + + - 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 - }} - > - - {index + 1} + {row.totalorders} + {/* + {row.pending ? : row.pending} - - {row.firstname} - {row.status == 'Active' ? ( - - ) : ( - - )} - + {row.assigned ? : row.assigned} - {row.deliveries} - {row.Assigened} - {row.Accepted} - {row.Picked} - {row.delivered} - - + {row.accepted ? : row.accepted} + + + {row.arrived ? : row.arrived} + + + {row.picked ? : row.picked} + + + {row.active ? : row.active} + + + {row.skipped ? : row.skipped} + */} + + {row.delivered} + + + + {/* - - - - - - - - - - - - - - - - - - - - - - - { - 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 ? : } - - - - {/* // ============================================ || collapsive row || ============================================ */} - {openRow === row.userid && ( - */} + + - - - - - Tenant Summary - - - - - # - Client - All - Pending - Completed - Cancelled - Kms/Actual Kms - POD / PLA - Amount - - - - {tenantData.map((row, index) => ( - handleClick(event, row.name)} - role="checkbox" - aria-checked={isItemSelected} - tabIndex={-1} - key={row.tenantname} - selected={isItemSelected} - > - {/* - - */} - - {index + 1} - - - - {row.tenantname} - - - {row.totalorders} - {row.deliveriespending} - {row.deliveriescompleted} - {row.deliveriescancelled} - - + + + + + + + + + + + + + + + + + + + + { + 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 ? : } + + + + {/* // ============================================ || collapsive row || ============================================ */} + {openRow === row.userid && ( + + + + +
+ + + # + Location + All + {/* Pending */} + Completed + {/* Cancelled */} + Actual Kms + COD / PLA + Amount + + + + {tenantData?.map((row, index) => ( + + + {index + 1} + + + + {row.locationname} + + + {row.totalorders} + {/* {row.deliveriespending} */} + {row.deliveriescompleted} + {/* {row.deliveriescancelled} */} + + {/* - - + /> */} + + - - {' '} - - + + {' '} + + - - - - - ))} - -
-
-
-
-
- )} - - ) - ); - })} - {emptyRows > 0 && ( - - - - )} + + + +
+ ))} +
+ +
+
+
+
+ )} + + ))} - + {/* Total : {formatNumberToRupees(total)} - - {/* table pagination */} - {/* */} + */}
+ {/* ================================================ || Date Filter || ================================================ */} Select Filter Options @@ -605,7 +550,6 @@ export default function RidersSummary() { setDateselect('all'); setStartdate(''); setEnddate(''); - setOpen(false); } else { setDateselect('select'); diff --git a/src/pages/nearle/titleCard.js b/src/pages/nearle/titleCard.js index 8538e72..762aa8e 100644 --- a/src/pages/nearle/titleCard.js +++ b/src/pages/nearle/titleCard.js @@ -20,7 +20,7 @@ import { Button, List } from '@mui/material'; -const TitleCard = ({ title }) => { +const TitleCard = ({ title, secondary, sx }) => { const theme = useTheme(); return ( @@ -32,12 +32,14 @@ const TitleCard = ({ title }) => { bgcolor: theme.palette.background.default, zIndex: 1, // borderBottom: `1px solid ${theme.palette.divider}`, - width: '100%' + width: '100%', + ...sx }} > - + {title} + {secondary && secondary} diff --git a/src/routes/MainRoutes.js b/src/routes/MainRoutes.js index 5dad05d..3be5961 100644 --- a/src/routes/MainRoutes.js +++ b/src/routes/MainRoutes.js @@ -19,6 +19,8 @@ const Login = Loadable(lazy(() => import('pages/nearle/login'))); const Customers = Loadable(lazy(() => import('pages/nearle/clients/customers'))); +const Locations = Loadable(lazy(() => import('pages/nearle/locations/Locations'))); + const Orders = Loadable(lazy(() => import('pages/nearle/orders/orders'))); const Details = Loadable(lazy(() => import('pages/nearle/orders/details'))); @@ -56,16 +58,18 @@ const MainRoutes = { children: [ { path: 'orders', - element: , 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: '', // /orders + element: + }, + { + path: 'create/grouporders', // /orders/create/grouporders + element: + }, { path: 'create', element: - }, - { - path: 'createorders', - element: } ] }, @@ -115,6 +119,10 @@ const MainRoutes = { element: } ] + }, + { + path: 'locations', + element: } ] }, diff --git a/src/themes/index.js b/src/themes/index.js index c2f2949..316c953 100644 --- a/src/themes/index.js +++ b/src/themes/index.js @@ -27,11 +27,30 @@ export default function ThemeCustomization({ children }) { () => ({ breakpoints: { values: { - xs: 0, - sm: 768, - md: 1024, - lg: 1266, - xl: 1440 + xs: 0, // Extra-small: 0px and up + custom300: 300, // above 350 + custom350: 350, // above 350 + custom400: 400, // above 400 + custom450: 450, // above 450 + custom500: 500, // above 450 + custom550: 550, // above 450 + custom600: 600, // above 450 + custom650: 650, // above 450 + custom700: 700, // above 450 + custom750: 750, // above 450 + sm: 768, // Small: 768px and up + custom800: 800, // above 450, + custom850: 850, // above 450, + custom900: 900, // above 450 + custom950: 950, // above 450 + custom1000: 1000, // above 450 + md: 1024, // Medium: 1024px and up + custom1050: 1050, // + custom1100: 1100, // + lg: 1266, // Large: 1266px and up + custom1300: 1300, // Large: 1266px and up + custom1350: 1350, // Large: 1266px and up + xl: 1440 // Extra-large: 1440px and up } }, direction: themeDirection, diff --git a/src/themes/theme/default.js b/src/themes/theme/default.js index 5e22305..f6a8a00 100644 --- a/src/themes/theme/default.js +++ b/src/themes/theme/default.js @@ -40,17 +40,17 @@ const Default = (colors) => { // contrastText // }, primary: { - lighter: purple[0], - 100: purple[1], - 200: purple[2], - light: purple[3], - 400: purple[4], + lighter: '#E8D9EF', + 100: '#CBA7DA', + 200: '#AE76C4', + light: '#9255AB', + 400: '#9255AB', main: '#662582', - dark: purple[6], - 700: purple[7], - darker: purple[8], - 900: purple[9], - contrastText + dark: '#4D1C61', + 700: '#3A1549', + darker: '#260E30', + 900: '#17081D', + contrastText: '#FFFFFF' }, secondary: { lighter: greyColors[100], @@ -105,7 +105,11 @@ const Default = (colors) => { darker: green[9], contrastText }, - grey: greyColors + grey: greyColors, + bg: { + main: '#E0E0E0', + light: '#fafafb' + } }; }; diff --git a/yarn.lock b/yarn.lock index 6f70c5a..8faa5db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1243,6 +1243,11 @@ resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz" integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA== +"@custom-react-hooks/use-network@^1.0.1": + version "1.0.1" + resolved "https://registry.npmjs.org/@custom-react-hooks/use-network/-/use-network-1.0.1.tgz" + integrity sha512-WbFVxsC18hjJiVIONAExVORlJlrOeYwzKsiYUCzrt5zCP0u9eLUPJuftF3DvEpoaQdjufazllWCPWKXT+dTY2g== + "@emotion/babel-plugin@^11.10.6": version "11.10.6" resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz" @@ -1501,6 +1506,19 @@ intl-messageformat "10.3.4" tslib "^2.4.0" +"@googlemaps/js-api-loader@1.16.8": + version "1.16.8" + resolved "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.16.8.tgz" + integrity sha512-CROqqwfKotdO6EBjZO/gQGVTbeDps5V7Mt9+8+5Q+jTg5CRMi3Ii/L9PmV3USROrt2uWxtGzJHORmByxyo9pSQ== + +"@googlemaps/markerclusterer@2.5.3": + version "2.5.3" + resolved "https://registry.npmjs.org/@googlemaps/markerclusterer/-/markerclusterer-2.5.3.tgz" + integrity sha512-x7lX0R5yYOoiNectr10wLgCBasNcXFHiADIBdmn7jQllF2B5ENQw5XtZK+hIw4xnV0Df0xhN4LN98XqA5jaiOw== + dependencies: + fast-deep-equal "^3.1.3" + supercluster "^8.0.1" + "@humanwhocodes/config-array@^0.11.8": version "0.11.8" resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz" @@ -2069,6 +2087,28 @@ resolved "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz" integrity sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA== +"@react-google-maps/api@^2.20.7": + version "2.20.7" + resolved "https://registry.npmjs.org/@react-google-maps/api/-/api-2.20.7.tgz" + integrity sha512-ys7uri3V6gjhYZUI43srHzSKDC6/jiKTwHNlwXFTvjeaJE3M3OaYBt9FZKvJs8qnOhL6i6nD1BKJoi1KrnkCkg== + dependencies: + "@googlemaps/js-api-loader" "1.16.8" + "@googlemaps/markerclusterer" "2.5.3" + "@react-google-maps/infobox" "2.20.0" + "@react-google-maps/marker-clusterer" "2.20.0" + "@types/google.maps" "3.58.1" + invariant "2.2.4" + +"@react-google-maps/infobox@2.20.0": + version "2.20.0" + resolved "https://registry.npmjs.org/@react-google-maps/infobox/-/infobox-2.20.0.tgz" + integrity sha512-03PJHjohhaVLkX6+NHhlr8CIlvUxWaXhryqDjyaZ8iIqqix/nV8GFdz9O3m5OsjtxtNho09F/15j14yV0nuyLQ== + +"@react-google-maps/marker-clusterer@2.20.0": + version "2.20.0" + resolved "https://registry.npmjs.org/@react-google-maps/marker-clusterer/-/marker-clusterer-2.20.0.tgz" + integrity sha512-tieX9Va5w1yP88vMgfH1pHTacDQ9TgDTjox3tLlisKDXRQWdjw+QeVVghhf5XqqIxXHgPdcGwBvKY6UP+SIvLw== + "@react-leaflet/core@^2.1.0": version "2.1.0" resolved "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz" @@ -2503,6 +2543,11 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/google.maps@3.58.1": + version "3.58.1" + resolved "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.58.1.tgz" + integrity sha512-X9QTSvGJ0nCfMzYOnaVs/k6/4L+7F5uCS+4iUmkLEls6J9S/Phv+m/i3mDeyc49ZBgwab3EFO1HEoBY7k98EGQ== + "@types/graceful-fs@^4.1.2": version "4.1.5" resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz" @@ -6238,6 +6283,13 @@ intl-messageformat@10.3.4: "@formatjs/icu-messageformat-parser" "2.3.1" tslib "^2.4.0" +invariant@2.2.4: + version "2.2.4" + resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + ipaddr.js@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz" @@ -7199,6 +7251,11 @@ jwt-decode@^3.1.2: resolved "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz" integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A== +kdbush@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz" + integrity sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA== + kind-of@^6.0.2: version "6.0.3" resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" @@ -7343,7 +7400,7 @@ lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -loose-envify@^1.1.0, loose-envify@^1.4.0: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -9186,7 +9243,7 @@ react-dnd@^16.0.1: fast-deep-equal "^3.1.3" hoist-non-react-statics "^3.3.2" -react-dom@*, "react-dom@^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.8 || ^17.0 || ^18.0", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom@^17.0.0 || ^18.0.0", react-dom@^17.0.2, react-dom@^18.0.0, react-dom@^18.2.0, "react-dom@>= 0.14.0", "react-dom@>=16 || >=17 || >= 18", react-dom@>=16.0.0, react-dom@>=16.11.0, react-dom@>=16.6.0, react-dom@>=16.8, react-dom@>=16.8.0, react-dom@>=16.9.0, "react-dom@16.2.0 - 18": +react-dom@*, "react-dom@^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.8 || ^17 || ^18 || ^19", "react-dom@^16.8 || ^17.0 || ^18.0", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom@^17.0.0 || ^18.0.0", react-dom@^17.0.2, react-dom@^18.0.0, react-dom@^18.2.0, "react-dom@>= 0.14.0", "react-dom@>=16 || >=17 || >= 18", react-dom@>=16.0.0, react-dom@>=16.11.0, react-dom@>=16.6.0, react-dom@>=16.8, react-dom@>=16.8.0, react-dom@>=16.9.0, "react-dom@16.2.0 - 18": version "18.2.0" resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz" integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== @@ -9400,7 +9457,7 @@ react-virtuoso@^4.7.0: resolved "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.7.0.tgz" integrity sha512-cpgvI1rSOETGDMhqVAVDuH+XHbWO1uIGKv5I6l4CyC71xWYUeGrE5n7sgTZklROB4+Vbv85pcgfWloTlY48HGQ== -react@*, "react@^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react@^16.6.0 || 17 || 18", "react@^16.8 || ^17.0 || ^18.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.9.0 || ^17.0.0 || ^18", "react@^17.0.0 || ^18.0.0", react@^17.0.2, react@^18.0.0, react@^18.2.0, "react@>= 0.14.0", "react@>= 16", "react@>= 16.14", "react@>=16 || >=17 || >= 18", react@>=16.0.0, react@>=16.11.0, react@>=16.6.0, react@>=16.8, react@>=16.8.0, react@>=16.9.0, "react@16.2.0 - 18": +react@*, "react@^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react@^16.6.0 || 17 || 18", "react@^16.8 || ^17 || ^18 || ^19", "react@^16.8 || ^17.0 || ^18.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.9.0 || ^17.0.0 || ^18", "react@^17.0.0 || ^18.0.0", react@^17.0.2, react@^18.0.0, react@^18.2.0, "react@>= 0.14.0", "react@>= 16", "react@>= 16.14", "react@>=16 || >=17 || >= 18", react@>=16.0.0, react@>=16.11.0, react@>=16.6.0, react@>=16.8, react@>=16.8.0, react@>=16.9.0, "react@16.2.0 - 18": version "18.2.0" resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz" integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== @@ -10293,6 +10350,13 @@ stylis@^4.0.13, stylis@4.1.3, stylis@4.x: resolved "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz" integrity sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA== +supercluster@^8.0.1: + version "8.0.1" + resolved "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz" + integrity sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ== + dependencies: + kdbush "^4.0.2" + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"