upates on the google map removal
This commit is contained in:
@@ -146,7 +146,7 @@ flowchart TD
|
|||||||
direction LR
|
direction LR
|
||||||
Store["Redux: fcm · login · menu · snackbar · toast · auth"]:::state
|
Store["Redux: fcm · login · menu · snackbar · toast · auth"]:::state
|
||||||
QC["TanStack Query (cache + infinite scroll)"]:::state
|
QC["TanStack Query (cache + infinite scroll)"]:::state
|
||||||
Env["REACT_APP_URL · REACT_APP_URL2 · REACT_APP_GOOGLE_MAPS_API_KEY"]:::state
|
Env["REACT_APP_URL · REACT_APP_URL2"]:::state
|
||||||
LS["localStorage: authname · userid · roleid · userfcmtoken · applocations"]:::state
|
LS["localStorage: authname · userid · roleid · userfcmtoken · applocations"]:::state
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
3
.env
3
.env
@@ -4,13 +4,10 @@ GENERATE_SOURCEMAP = false
|
|||||||
## Backend API URL
|
## Backend API URL
|
||||||
REACT_APP_API_URL=https://mock-data-api-nextjs.vercel.app/
|
REACT_APP_API_URL=https://mock-data-api-nextjs.vercel.app/
|
||||||
|
|
||||||
## Google Map Key
|
|
||||||
|
|
||||||
REACT_APP_URL=https://jupiter.nearle.app/live/api/v1
|
REACT_APP_URL=https://jupiter.nearle.app/live/api/v1
|
||||||
REACT_APP_URL2=https://jupiter.nearle.app/live/api/v2
|
REACT_APP_URL2=https://jupiter.nearle.app/live/api/v2
|
||||||
REACT_APP_URL3=https://jupiter.nearle.app/live/api/v3
|
REACT_APP_URL3=https://jupiter.nearle.app/live/api/v3
|
||||||
REACT_APP_STAFF_TOKEN=
|
REACT_APP_STAFF_TOKEN=
|
||||||
REACT_APP_GOOGLE_MAPS_API_KEY=AIzaSyCF4KatYCI3vqz1_H3kiHeyS3yCMfYToh8
|
|
||||||
REACT_APP_RIDER_ACCESS_ID=AAAAILMpCEU:APA91bEavuOllBI6sFgYtxXAgNmAVwNA-MnCMHLGlR4_t7UqpLajAkdn3T0CZr_zaLBknLyim9ytFLMZgbeXmKqTad_PKCbqlYjHpaizVrLXtecxqyEy4UktIacK2UvHVUATHL-7VQQk
|
REACT_APP_RIDER_ACCESS_ID=AAAAILMpCEU:APA91bEavuOllBI6sFgYtxXAgNmAVwNA-MnCMHLGlR4_t7UqpLajAkdn3T0CZr_zaLBknLyim9ytFLMZgbeXmKqTad_PKCbqlYjHpaizVrLXtecxqyEy4UktIacK2UvHVUATHL-7VQQk
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ REACT_APP_URL=https://jupiter.nearle.app/live/api/v1
|
|||||||
REACT_APP_URL2=https://jupiter.nearle.app/live/api/v2
|
REACT_APP_URL2=https://jupiter.nearle.app/live/api/v2
|
||||||
REACT_APP_URL3=https://jupiter.nearle.app/live/api/v3
|
REACT_APP_URL3=https://jupiter.nearle.app/live/api/v3
|
||||||
REACT_APP_STAFF_TOKEN=
|
REACT_APP_STAFF_TOKEN=
|
||||||
REACT_APP_GOOGLE_MAPS_API_KEY=AIzaSyCF4KatYCI3vqz1_H3kiHeyS3yCMfYToh8
|
|
||||||
REACT_APP_RIDER_ACCESS_ID=AAAAILMpCEU:APA91bEavuOllBI6sFgYtxXAgNmAVwNA-MnCMHLGlR4_t7UqpLajAkdn3T0CZr_zaLBknLyim9ytFLMZgbeXmKqTad_PKCbqlYjHpaizVrLXtecxqyEy4UktIacK2UvHVUATHL-7VQQk
|
REACT_APP_RIDER_ACCESS_ID=AAAAILMpCEU:APA91bEavuOllBI6sFgYtxXAgNmAVwNA-MnCMHLGlR4_t7UqpLajAkdn3T0CZr_zaLBknLyim9ytFLMZgbeXmKqTad_PKCbqlYjHpaizVrLXtecxqyEy4UktIacK2UvHVUATHL-7VQQk
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ For the per-page API map and architectural flow chart, see the project skill **`
|
|||||||
- **Routing**: `react-router-dom 6.10`, lazy-loaded via `components/Loadable`.
|
- **Routing**: `react-router-dom 6.10`, lazy-loaded via `components/Loadable`.
|
||||||
- **Forms**: `formik 2.2` + `yup 1.1` where present; new simple forms can use plain `useState`.
|
- **Forms**: `formik 2.2` + `yup 1.1` where present; new simple forms can use plain `useState`.
|
||||||
- **Dates**: `dayjs 1.11` with `utc` plugin (already extended at the top of `deliveries.js`). Use `dayjs(...).utc()` for backend timestamps and bare `dayjs(...)` for local-time bucketing — see the batch-bucketing comment in `deliveries.js` for the rationale.
|
- **Dates**: `dayjs 1.11` with `utc` plugin (already extended at the top of `deliveries.js`). Use `dayjs(...).utc()` for backend timestamps and bare `dayjs(...)` for local-time bucketing — see the batch-bucketing comment in `deliveries.js` for the rationale.
|
||||||
- **Maps**: `leaflet` + `react-leaflet`, plus `@react-google-maps/api` for Google. Geocoding via `react-geocode`. Maps API key is `process.env.REACT_APP_GOOGLE_MAPS_API_KEY`.
|
- **Maps**: `leaflet` + `react-leaflet` only. Geocoding/address search via free OSM Nominatim (`src/components/nearle_components/AddressAutocomplete.js`) and routing via OSRM — no API key required. Google Maps (`@react-google-maps/api`, `react-geocode`, `react-google-autocomplete`) has been fully removed; do not reintroduce it.
|
||||||
- **Notifications**: `firebase 10.14` (FCM) — see `src/firebase_notification/`. Toasts via `notistack 3`.
|
- **Notifications**: `firebase 10.14` (FCM) — see `src/firebase_notification/`. Toasts via `notistack 3`.
|
||||||
- **Drag-and-drop**: `react-dnd` (used on the Dispatch Preview page).
|
- **Drag-and-drop**: `react-dnd` (used on the Dispatch Preview page).
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ npm run lint
|
|||||||
```
|
```
|
||||||
|
|
||||||
- **Env files at repo root**: `env.staging` is committed; `.env.development` / `.env.production` are typically gitignored. Pull from a teammate when missing.
|
- **Env files at repo root**: `env.staging` is committed; `.env.development` / `.env.production` are typically gitignored. Pull from a teammate when missing.
|
||||||
- **Required env vars**: `REACT_APP_URL` (primary API base), `REACT_APP_URL2` (secondary API base — used for `/users/update`, `/tenants/update`, `/partners/getriderlogs`, archival `/orders/getorders`), `REACT_APP_GOOGLE_MAPS_API_KEY`. The optimiser URLs (`routes.workolik.com`, `routemate.workolik.com`) and the Jupiter auth URL (`jupiter.nearle.app`) are hardcoded — see the `nearlexpress-docs` skill.
|
- **Required env vars**: `REACT_APP_URL` (primary API base), `REACT_APP_URL2` (secondary API base — used for `/users/update`, `/tenants/update`, `/partners/getriderlogs`, archival `/orders/getorders`). No Maps API key is needed — maps and address search run on free Leaflet/OSM services. The optimiser URLs (`routes.workolik.com`, `routemate.workolik.com`) and the Jupiter auth URL (`jupiter.nearle.app`) are hardcoded — see the `nearlexpress-docs` skill.
|
||||||
- **Dev server runs on `http://localhost:3000`**. The user usually has it running already — assume it is up when reporting "reload to see it".
|
- **Dev server runs on `http://localhost:3000`**. The user usually has it running already — assume it is up when reporting "reload to see it".
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -282,7 +282,7 @@ These colour-code lifecycle states. Do **not** swap them for brand red — opera
|
|||||||
- **The `applocationid` query param**: every list endpoint expects this — `0` means "All Zones". Pages default `appId = 0` and update it from `LocationAutocomplete`.
|
- **The `applocationid` query param**: every list endpoint expects this — `0` means "All Zones". Pages default `appId = 0` and update it from `LocationAutocomplete`.
|
||||||
- **`role` gating** uses `localStorage.getItem('roleid')`. Some buttons are conditionally rendered based on it. Do not hide UI based on string equality alone — check existing patterns.
|
- **`role` gating** uses `localStorage.getItem('roleid')`. Some buttons are conditionally rendered based on it. Do not hide UI based on string equality alone — check existing patterns.
|
||||||
- **Skeleton vs Loader vs LoaderWithImage** — these are different. Skeleton = per-row placeholder, Loader = full-screen backdrop blocking interaction, LoaderWithImage = inline branded spinner. Don't swap them.
|
- **Skeleton vs Loader vs LoaderWithImage** — these are different. Skeleton = per-row placeholder, Loader = full-screen backdrop blocking interaction, LoaderWithImage = inline branded spinner. Don't swap them.
|
||||||
- **Maps API key** is read from env on every render in some places — wrapping it in a `useMemo` is fine but unnecessary. Don't add new direct `process.env.REACT_APP_GOOGLE_MAPS_API_KEY` reads outside map-related files.
|
- **No Maps API key exists in this project anymore.** Address search/geocoding goes through `AddressAutocomplete.js` (Nominatim) and routing through OSRM — both free, no key. Do not add `process.env.REACT_APP_GOOGLE_MAPS_API_KEY` or any Google Maps script/dependency back in.
|
||||||
- **`Tenants.js` has known dangling references** (`setClientstatus`, `setState`, `setSuburb`, `setTenanatPricing`, `<Collapse in={open}>`) inherited from legacy code. They are tolerated. Do **not** "fix" them as a drive-by — they are out of scope and removing them risks breaking the row collapse contents.
|
- **`Tenants.js` has known dangling references** (`setClientstatus`, `setState`, `setSuburb`, `setTenanatPricing`, `<Collapse in={open}>`) inherited from legacy code. They are tolerated. Do **not** "fix" them as a drive-by — they are out of scope and removing them risks breaking the row collapse contents.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
2
FLOW.md
2
FLOW.md
@@ -162,7 +162,7 @@ flowchart TD
|
|||||||
Store["Redux Toolkit store<br/>fcmSlice · loginUserSlice<br/>menu · snackbar · toastSlice · auth"]:::state
|
Store["Redux Toolkit store<br/>fcmSlice · loginUserSlice<br/>menu · snackbar · toastSlice · auth"]:::state
|
||||||
QC["@tanstack/react-query<br/>QueryClient (cache + infinite scroll)"]:::state
|
QC["@tanstack/react-query<br/>QueryClient (cache + infinite scroll)"]:::state
|
||||||
AxiosBase["axios (raw) +<br/>utils/axios.js (401 → /login)"]:::state
|
AxiosBase["axios (raw) +<br/>utils/axios.js (401 → /login)"]:::state
|
||||||
Env["env vars: REACT_APP_URL ·<br/>REACT_APP_URL2 · REACT_APP_GOOGLE_MAPS_API_KEY"]:::state
|
Env["env vars: REACT_APP_URL ·<br/>REACT_APP_URL2"]:::state
|
||||||
LS["localStorage:<br/>authname · userid · roleid ·<br/>userfcmtoken · applocations"]:::state
|
LS["localStorage:<br/>authname · userid · roleid ·<br/>userfcmtoken · applocations"]:::state
|
||||||
Toasts["Notistack · OpenToast wrapper"]:::state
|
Toasts["Notistack · OpenToast wrapper"]:::state
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -54,11 +54,10 @@ REACT_APP_API_URL=https://mock-data-api-nextjs.vercel.app/
|
|||||||
REACT_APP_URL=https://jupiter.nearle.app/live/api/v1
|
REACT_APP_URL=https://jupiter.nearle.app/live/api/v1
|
||||||
REACT_APP_URL2=https://jupiter.nearle.app/live/api/v2
|
REACT_APP_URL2=https://jupiter.nearle.app/live/api/v2
|
||||||
REACT_APP_URL3=https://jupiter.nearle.app/live/api/v3
|
REACT_APP_URL3=https://jupiter.nearle.app/live/api/v3
|
||||||
|
|
||||||
# API Credentials
|
|
||||||
REACT_APP_GOOGLE_MAPS_API_KEY=AIzaSyCF...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
No Maps API key is required — maps and address search run on free Leaflet/OpenStreetMap (Nominatim + OSRM), not Google Maps.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🏃 Getting Started & Local Development
|
## 🏃 Getting Started & Local Development
|
||||||
|
|||||||
112
package-lock.json
generated
112
package-lock.json
generated
@@ -20,7 +20,6 @@
|
|||||||
"@mui/lab": "^5.0.0-alpha.127",
|
"@mui/lab": "^5.0.0-alpha.127",
|
||||||
"@mui/material": "^5.12.1",
|
"@mui/material": "^5.12.1",
|
||||||
"@mui/x-date-pickers": "^7.29.4",
|
"@mui/x-date-pickers": "^7.29.4",
|
||||||
"@react-google-maps/api": "^2.20.7",
|
|
||||||
"@reduxjs/toolkit": "^2.12.0",
|
"@reduxjs/toolkit": "^2.12.0",
|
||||||
"@stylexjs/stylex": "^0.19.0",
|
"@stylexjs/stylex": "^0.19.0",
|
||||||
"@svgr/webpack": "^7.0.0",
|
"@svgr/webpack": "^7.0.0",
|
||||||
@@ -52,8 +51,6 @@
|
|||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
"react-dom": "^19.2.8",
|
"react-dom": "^19.2.8",
|
||||||
"react-geocode": "^0.2.3",
|
|
||||||
"react-google-autocomplete": "^2.7.3",
|
|
||||||
"react-icons": "^4.12.0",
|
"react-icons": "^4.12.0",
|
||||||
"react-intl": "^7.1.14",
|
"react-intl": "^7.1.14",
|
||||||
"react-leaflet": "^5.0.0",
|
"react-leaflet": "^5.0.0",
|
||||||
@@ -3586,22 +3583,6 @@
|
|||||||
"tslib": "^2.8.0"
|
"tslib": "^2.8.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/@grpc/grpc-js": {
|
"node_modules/@grpc/grpc-js": {
|
||||||
"version": "1.9.14",
|
"version": "1.9.14",
|
||||||
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.14.tgz",
|
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.14.tgz",
|
||||||
@@ -5106,36 +5087,6 @@
|
|||||||
"integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==",
|
"integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"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": {
|
"node_modules/@react-leaflet/core": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-3.0.0.tgz",
|
||||||
@@ -5767,12 +5718,6 @@
|
|||||||
"@types/range-parser": "*"
|
"@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": {
|
"node_modules/@types/graceful-fs": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz",
|
||||||
@@ -14158,12 +14103,6 @@
|
|||||||
"integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==",
|
"integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"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/keyv": {
|
"node_modules/keyv": {
|
||||||
"version": "4.5.4",
|
"version": "4.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||||
@@ -18142,34 +18081,6 @@
|
|||||||
"integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==",
|
"integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/react-geocode": {
|
|
||||||
"version": "0.2.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-geocode/-/react-geocode-0.2.3.tgz",
|
|
||||||
"integrity": "sha512-sIpbgmn1IUzAxO4haOZ6jeeFnMD8ya9PC38yiNrmJ9vPWbvAO2D/2yfCBzZjGZVUm4PRzKAc0KghXfaEnug0TQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"regenerator-runtime": "^0.13.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-geocode/node_modules/regenerator-runtime": {
|
|
||||||
"version": "0.13.11",
|
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
|
||||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/react-google-autocomplete": {
|
|
||||||
"version": "2.7.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-google-autocomplete/-/react-google-autocomplete-2.7.4.tgz",
|
|
||||||
"integrity": "sha512-BeEk2mjzgJcfiCueuKBofm5+RxHUIr0+POn9Yw8merK4Yd0jcOp9Lk/IGJySbz1GTi2Jqvi7V4dbw/DPLD1HMA==",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"lodash.debounce": "^4.0.8",
|
|
||||||
"prop-types": "^15.5.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": ">=16.8.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-icons": {
|
"node_modules/react-icons": {
|
||||||
"version": "4.12.0",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz",
|
||||||
@@ -20719,15 +20630,6 @@
|
|||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"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": {
|
"node_modules/supports-color": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||||
@@ -21444,20 +21346,6 @@
|
|||||||
"is-typedarray": "^1.0.0"
|
"is-typedarray": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript": {
|
|
||||||
"version": "5.9.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
|
||||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
|
||||||
"tsc": "bin/tsc",
|
|
||||||
"tsserver": "bin/tsserver"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.17"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ua-parser-js": {
|
"node_modules/ua-parser-js": {
|
||||||
"version": "1.0.40",
|
"version": "1.0.40",
|
||||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.40.tgz",
|
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.40.tgz",
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
"@mui/lab": "^5.0.0-alpha.127",
|
"@mui/lab": "^5.0.0-alpha.127",
|
||||||
"@mui/material": "^5.12.1",
|
"@mui/material": "^5.12.1",
|
||||||
"@mui/x-date-pickers": "^7.29.4",
|
"@mui/x-date-pickers": "^7.29.4",
|
||||||
"@react-google-maps/api": "^2.20.7",
|
|
||||||
"@reduxjs/toolkit": "^2.12.0",
|
"@reduxjs/toolkit": "^2.12.0",
|
||||||
"@stylexjs/stylex": "^0.19.0",
|
"@stylexjs/stylex": "^0.19.0",
|
||||||
"@svgr/webpack": "^7.0.0",
|
"@svgr/webpack": "^7.0.0",
|
||||||
@@ -47,8 +46,6 @@
|
|||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
"react-dom": "^19.2.8",
|
"react-dom": "^19.2.8",
|
||||||
"react-geocode": "^0.2.3",
|
|
||||||
"react-google-autocomplete": "^2.7.3",
|
|
||||||
"react-icons": "^4.12.0",
|
"react-icons": "^4.12.0",
|
||||||
"react-intl": "^7.1.14",
|
"react-intl": "^7.1.14",
|
||||||
"react-leaflet": "^5.0.0",
|
"react-leaflet": "^5.0.0",
|
||||||
|
|||||||
@@ -39,10 +39,6 @@
|
|||||||
<!-- this is to resolve issue in old safari browser in tablet -->
|
<!-- this is to resolve issue in old safari browser in tablet -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/resize-observer-polyfill@1.5.1/dist/ResizeObserver.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/resize-observer-polyfill@1.5.1/dist/ResizeObserver.min.js"></script>
|
||||||
|
|
||||||
<!-- google address autocomplete -->
|
|
||||||
<!-- <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDQ2c_pOSOFYSjxGMwkFvCVWKjYOM9siow&libraries=places"></script> -->
|
|
||||||
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBhkGfnq27sN0wV5y_S-M2KojpFTk_by-Q&libraries=places"></script>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.datedialog > div > div > .MuiPaper-root {
|
.datedialog > div > div > .MuiPaper-root {
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
|
|||||||
193
src/components/nearle_components/AddressAutocomplete.js
Normal file
193
src/components/nearle_components/AddressAutocomplete.js
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import { Autocomplete, TextField, CircularProgress } from '@mui/material';
|
||||||
|
import { debounce } from '@mui/material/utils';
|
||||||
|
|
||||||
|
// Free OSM Nominatim geocoder — replaces Google Places Autocomplete /
|
||||||
|
// react-geocode across the console. No API key required. Nominatim's usage
|
||||||
|
// policy caps the public endpoint at ~1 req/sec, so every caller here is
|
||||||
|
// debounced (500ms) and cancels stale in-flight predictions.
|
||||||
|
const NOMINATIM_SEARCH_URL = 'https://nominatim.openstreetmap.org/search';
|
||||||
|
|
||||||
|
// Builds a Google-Places-shaped `address_components` array (each entry
|
||||||
|
// `{ long_name, short_name, types: [] }`) from Nominatim's flat `address`
|
||||||
|
// object, so existing call sites' `place.address_components.forEach(...)`
|
||||||
|
// type-switch parsing keeps working unchanged.
|
||||||
|
const buildAddressComponents = (addr = {}) => {
|
||||||
|
const components = [];
|
||||||
|
const push = (longName, types) => {
|
||||||
|
if (longName) components.push({ long_name: longName, short_name: longName, types });
|
||||||
|
};
|
||||||
|
push(addr.house_number, ['street_number']);
|
||||||
|
push(addr.road || addr.pedestrian, ['route']);
|
||||||
|
push(addr.suburb || addr.neighbourhood || addr.quarter, ['sublocality_level_1', 'sublocality']);
|
||||||
|
push(addr.city_district || addr.county, ['administrative_area_level_3']);
|
||||||
|
push(addr.city || addr.town || addr.village, ['locality']);
|
||||||
|
push(addr.state, ['administrative_area_level_1']);
|
||||||
|
push(addr.country, ['country']);
|
||||||
|
push(addr.postcode, ['postal_code']);
|
||||||
|
return components;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Shapes a Nominatim result close enough to a Google Places `place` object
|
||||||
|
// (formatted_address, geometry.location.lat()/lng(), address_components)
|
||||||
|
// that call sites need only mechanical edits, not rewrites.
|
||||||
|
export const toPlace = (result) => ({
|
||||||
|
formatted_address: result.display_name,
|
||||||
|
name: result.display_name?.split(',')[0] || '',
|
||||||
|
geometry: {
|
||||||
|
location: {
|
||||||
|
lat: () => parseFloat(result.lat),
|
||||||
|
lng: () => parseFloat(result.lon)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
address_components: buildAddressComponents(result.address)
|
||||||
|
});
|
||||||
|
|
||||||
|
const buildParams = (query, bias) => {
|
||||||
|
const params = new URLSearchParams({ q: query, format: 'json', addressdetails: '1', limit: '5' });
|
||||||
|
if (bias?.lat && bias?.lng) {
|
||||||
|
const d = 0.5; // ~55km box around the operator's zone — soft bias, not a hard filter
|
||||||
|
params.set('viewbox', `${bias.lng - d},${bias.lat + d},${bias.lng + d},${bias.lat - d}`);
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Standalone forward-geocode helper — replaces `Geocode.fromAddress(address)`
|
||||||
|
// for call sites that resolve a plain text address without a predictions
|
||||||
|
// dropdown (e.g. re-geocoding on submit). Returns a `toPlace`-shaped object,
|
||||||
|
// or null if nothing matched.
|
||||||
|
export async function geocodeAddress(address, { bias } = {}) {
|
||||||
|
if (!address) return null;
|
||||||
|
try {
|
||||||
|
const params = buildParams(address, bias);
|
||||||
|
params.set('limit', '1');
|
||||||
|
const res = await fetch(`${NOMINATIM_SEARCH_URL}?${params.toString()}`, { headers: { Accept: 'application/json' } });
|
||||||
|
if (!res.ok) return null;
|
||||||
|
const results = await res.json();
|
||||||
|
if (!results?.length) return null;
|
||||||
|
return toPlace(results[0]);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('geocodeAddress error:', err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address search-as-you-type — replaces Google Places Autocomplete
|
||||||
|
// (usePlacesWidget / window.google.maps.places.Autocomplete /
|
||||||
|
// AutocompleteService) across the console. Renders as an MUI Autocomplete
|
||||||
|
// with freeSolo so the operator can still submit free text.
|
||||||
|
//
|
||||||
|
// Props:
|
||||||
|
// value / onChange(text) — controlled free-text input value
|
||||||
|
// onPlaceSelected(place) — fired when a suggestion is chosen; `place`
|
||||||
|
// is shaped like a Google Places `place`
|
||||||
|
// bias { lat, lng } — optional soft bias toward the operator's zone
|
||||||
|
const AddressAutocomplete = ({
|
||||||
|
id,
|
||||||
|
label,
|
||||||
|
placeholder = 'Search address',
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
onPlaceSelected,
|
||||||
|
bias,
|
||||||
|
sx,
|
||||||
|
textFieldSx,
|
||||||
|
fullWidth = true,
|
||||||
|
disabled,
|
||||||
|
inputRef,
|
||||||
|
TextFieldProps = {}
|
||||||
|
}) => {
|
||||||
|
const [inputValue, setInputValue] = useState(value || '');
|
||||||
|
const [options, setOptions] = useState([]);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (value !== undefined && value !== inputValue) setInputValue(value || '');
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
|
const fetchPredictions = useMemo(
|
||||||
|
() =>
|
||||||
|
debounce((query, bias1, callback) => {
|
||||||
|
if (!query) {
|
||||||
|
callback([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const params = buildParams(query, bias1);
|
||||||
|
fetch(`${NOMINATIM_SEARCH_URL}?${params.toString()}`, { headers: { Accept: 'application/json' } })
|
||||||
|
.then((res) => (res.ok ? res.json() : []))
|
||||||
|
.then((results) => callback(results || []))
|
||||||
|
.catch(() => callback([]));
|
||||||
|
}, 500),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let active = true;
|
||||||
|
if (!inputValue) {
|
||||||
|
setOptions([]);
|
||||||
|
setLoading(false);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
setLoading(true);
|
||||||
|
fetchPredictions(inputValue, bias, (results) => {
|
||||||
|
if (!active) return;
|
||||||
|
setLoading(false);
|
||||||
|
setOptions(results);
|
||||||
|
});
|
||||||
|
return () => {
|
||||||
|
active = false;
|
||||||
|
};
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [inputValue, bias?.lat, bias?.lng, fetchPredictions]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Autocomplete
|
||||||
|
id={id}
|
||||||
|
freeSolo
|
||||||
|
fullWidth={fullWidth}
|
||||||
|
disabled={disabled}
|
||||||
|
sx={sx}
|
||||||
|
options={options}
|
||||||
|
filterOptions={(x) => x}
|
||||||
|
getOptionLabel={(option) => (typeof option === 'string' ? option : option.display_name || '')}
|
||||||
|
isOptionEqualToValue={(option, val) => option.place_id === val?.place_id}
|
||||||
|
inputValue={inputValue}
|
||||||
|
onInputChange={(event, newInputValue) => {
|
||||||
|
setInputValue(newInputValue);
|
||||||
|
onChange?.(newInputValue);
|
||||||
|
}}
|
||||||
|
onChange={(event, selected) => {
|
||||||
|
if (selected && typeof selected !== 'string') {
|
||||||
|
setInputValue(selected.display_name || '');
|
||||||
|
onPlaceSelected?.(toPlace(selected));
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
renderInput={(params) => (
|
||||||
|
<TextField
|
||||||
|
{...params}
|
||||||
|
{...TextFieldProps}
|
||||||
|
inputRef={inputRef}
|
||||||
|
label={label}
|
||||||
|
placeholder={placeholder}
|
||||||
|
sx={textFieldSx}
|
||||||
|
autoComplete="off"
|
||||||
|
InputProps={{
|
||||||
|
...params.InputProps,
|
||||||
|
...TextFieldProps.InputProps,
|
||||||
|
startAdornment: TextFieldProps.InputProps?.startAdornment ?? params.InputProps.startAdornment,
|
||||||
|
endAdornment: (
|
||||||
|
<>
|
||||||
|
{loading ? <CircularProgress color="inherit" size={16} /> : null}
|
||||||
|
{TextFieldProps.InputProps?.endAdornment ?? params.InputProps.endAdornment}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddressAutocomplete;
|
||||||
@@ -59,15 +59,14 @@ const AppSideNav = ({ isCollapsed, onCollapsedChange }) => {
|
|||||||
paddingBlock: '12px',
|
paddingBlock: '12px',
|
||||||
paddingInline: '8px',
|
paddingInline: '8px',
|
||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
'--spacing-12': '72px',
|
'--spacing-12': '72px'
|
||||||
// Pages with tall/independently-scrolling content (e.g. deliveries'
|
// Sticky positioning + height/scroll are already handled by
|
||||||
// internal TableContainer scroll region) still let the document
|
// AppShell's own auto-mode side nav wrapper (position: sticky,
|
||||||
// scroll past the header, so pin the nav explicitly rather than
|
// top/height driven by --appshell-header-height, see
|
||||||
// relying only on AppShell's own auto-mode sticky wrapper.
|
// AppTopNav.js). A second nested position: sticky here — inside
|
||||||
position: 'sticky',
|
// that wrapper's own scrollable LayoutPanel — was redundant and
|
||||||
top: 'var(--appshell-header-height, 0px)',
|
// gave the offset two independent calculations to drift apart on,
|
||||||
height: 'calc(100dvh - var(--appshell-header-height, 0px))',
|
// which is what caused the visible jump/scroll-away glitch.
|
||||||
overflowY: 'auto'
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SideNavSection title="Doormile">{nearle.children.map(renderMenuItem)}</SideNavSection>
|
<SideNavSection title="Doormile">{nearle.children.map(renderMenuItem)}</SideNavSection>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useRef, useState } from 'react';
|
import { useLayoutEffect, useRef, useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
@@ -89,14 +89,15 @@ const AppTopNav = () => {
|
|||||||
|
|
||||||
// AppShell (height="auto") pins the sticky side nav below the header using
|
// AppShell (height="auto") pins the sticky side nav below the header using
|
||||||
// a --appshell-header-height CSS var it measures itself via ResizeObserver
|
// a --appshell-header-height CSS var it measures itself via ResizeObserver
|
||||||
// (AppShell.tsx). On some routes that measurement lags/settles wrong, so
|
// (AppShell.tsx), inside a useEffect that only runs (and paints) *after*
|
||||||
// the side nav's sticky offset is off and its bottom-anchored collapse
|
// the first frame. That one-frame gap is what made the side nav's sticky
|
||||||
// button visibly jumps on scroll. Re-measure the header independently here
|
// offset settle wrong and visibly jump/drift on scroll. Re-measure the
|
||||||
// and force the same variable with !important on the shell root — an
|
// header independently here in useLayoutEffect (synchronous, before the
|
||||||
// author-stylesheet !important rule beats AppShell's own non-important
|
// browser paints) and force the same variable with !important on the
|
||||||
// inline style.setProperty() call on that same element, so this always
|
// shell root — an author-stylesheet !important rule beats AppShell's own
|
||||||
// wins regardless of what the internal measurement produced.
|
// non-important inline style.setProperty() call on that same element, so
|
||||||
useEffect(() => {
|
// this always wins regardless of what the internal measurement produced.
|
||||||
|
useLayoutEffect(() => {
|
||||||
const el = topNavRef.current;
|
const el = topNavRef.current;
|
||||||
if (!el) return undefined;
|
if (!el) return undefined;
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ import {
|
|||||||
PartitionOutlined,
|
PartitionOutlined,
|
||||||
CarOutlined,
|
CarOutlined,
|
||||||
UserOutlined,
|
UserOutlined,
|
||||||
ProfileOutlined
|
ProfileOutlined,
|
||||||
|
TeamOutlined,
|
||||||
|
MoneyCollectOutlined
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
|
|
||||||
// icons
|
// icons
|
||||||
@@ -46,7 +48,9 @@ const icons = {
|
|||||||
PartitionOutlined,
|
PartitionOutlined,
|
||||||
CarOutlined,
|
CarOutlined,
|
||||||
UserOutlined,
|
UserOutlined,
|
||||||
ProfileOutlined
|
ProfileOutlined,
|
||||||
|
TeamOutlined,
|
||||||
|
MoneyCollectOutlined
|
||||||
};
|
};
|
||||||
|
|
||||||
// ==============================|| MENU ITEMS - SUPPORT ||============================== //
|
// ==============================|| MENU ITEMS - SUPPORT ||============================== //
|
||||||
@@ -85,6 +89,20 @@ const nearle = {
|
|||||||
url: '/doormile/riders',
|
url: '/doormile/riders',
|
||||||
icon: icons.UserOutlined
|
icon: icons.UserOutlined
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'tenants',
|
||||||
|
title: <FormattedMessage id="tenants" />,
|
||||||
|
type: 'item',
|
||||||
|
url: '/doormile/tenants',
|
||||||
|
icon: icons.TeamOutlined
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'pricing',
|
||||||
|
title: <FormattedMessage id="pricing" />,
|
||||||
|
type: 'item',
|
||||||
|
url: '/doormile/pricing',
|
||||||
|
icon: icons.MoneyCollectOutlined
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'reports',
|
id: 'reports',
|
||||||
title: <FormattedMessage id="reports" />,
|
title: <FormattedMessage id="reports" />,
|
||||||
|
|||||||
@@ -363,6 +363,62 @@ export const updateDeliveryAPI = async (orderData) => {
|
|||||||
return axios.put(`${process.env.REACT_APP_URL}/deliveries/updatedelivery`, orderData);
|
return axios.put(`${process.env.REACT_APP_URL}/deliveries/updatedelivery`, orderData);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ==============================|| getalltenants (tenants) ||============================== //
|
||||||
|
|
||||||
|
export const getalltenants = async ({ queryKey }) => {
|
||||||
|
const [, appId, debouncedSearch, status, page, rowsPerPage] = queryKey;
|
||||||
|
try {
|
||||||
|
let url = `${process.env.REACT_APP_URL
|
||||||
|
}/tenants/getalltenants/?status=${status}&applocationid=${appId}&keyword=${debouncedSearch}&pageno=${page + 1
|
||||||
|
}&pagesize=${rowsPerPage}&moduleid=6`;
|
||||||
|
const response = await axios.get(url);
|
||||||
|
return response.data.details; // return only data, keep it clean
|
||||||
|
} catch (err) {
|
||||||
|
const message = err.response?.data?.message || err.message || 'Something went wrong';
|
||||||
|
OpenToast(message);
|
||||||
|
return null; // return null for failure
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// ==============================|| gettenantsummary (tenants) ||============================== //
|
||||||
|
|
||||||
|
export const gettenantsummary = async ({ queryKey }) => {
|
||||||
|
const [, appId] = queryKey;
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`${process.env.REACT_APP_URL}/tenants/gettenantsummary/?moduleid=6&applocationid=${appId}`);
|
||||||
|
return response.data.summary; // return only data, keep it clean
|
||||||
|
} catch (err) {
|
||||||
|
const message = err.response?.data?.message || err.message || 'Something went wrong';
|
||||||
|
OpenToast(message);
|
||||||
|
return null; // return null for failure
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// ==============================|| getpricinglist (tenants) ||============================== //
|
||||||
|
|
||||||
|
export const getpricinglist = async ({ queryKey }) => {
|
||||||
|
const [, appId] = queryKey;
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`${process.env.REACT_APP_URL}/tenants/getpricinglist/?moduleid=6&applocationid=${appId}`);
|
||||||
|
return response.data.summary; // return only data, keep it clean
|
||||||
|
} catch (err) {
|
||||||
|
const message = err.response?.data?.message || err.message || 'Something went wrong';
|
||||||
|
OpenToast(message);
|
||||||
|
return null; // return null for failure
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// ==============================|| getallpricing (clientPricing) ||============================== //
|
||||||
|
|
||||||
|
export const getallpricing = async ({ queryKey }) => {
|
||||||
|
const [, appId] = queryKey;
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`${process.env.REACT_APP_URL}/utils/getallpricing/?applocationid=${appId}`);
|
||||||
|
return response.data.details || [];
|
||||||
|
} catch (err) {
|
||||||
|
const message = err.response?.data?.message || err.message || 'Something went wrong';
|
||||||
|
OpenToast(message);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// ==============================|| fetchAllRiders (riders) ||============================== //
|
// ==============================|| fetchAllRiders (riders) ||============================== //
|
||||||
export const fetchAllRiders = async ({ pageParam = 1, queryKey }) => {
|
export const fetchAllRiders = async ({ pageParam = 1, queryKey }) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
602
src/pages/nearle/clientPricing/clientPricing.js
Normal file
602
src/pages/nearle/clientPricing/clientPricing.js
Normal file
@@ -0,0 +1,602 @@
|
|||||||
|
import React, { useMemo, useRef, useState } from 'react';
|
||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
Box,
|
||||||
|
Grid,
|
||||||
|
Paper,
|
||||||
|
Stack,
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableContainer,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
Typography,
|
||||||
|
useMediaQuery,
|
||||||
|
useTheme
|
||||||
|
} from '@mui/material';
|
||||||
|
import {
|
||||||
|
MdLocalOffer,
|
||||||
|
MdMyLocation,
|
||||||
|
MdAttachMoney,
|
||||||
|
MdGroups,
|
||||||
|
MdPlace,
|
||||||
|
MdSpeed,
|
||||||
|
MdPriceCheck,
|
||||||
|
MdStraighten,
|
||||||
|
MdReceiptLong,
|
||||||
|
MdOutlineLocalOffer,
|
||||||
|
MdOutlineGroups,
|
||||||
|
MdOutlineAttachMoney,
|
||||||
|
MdOutlinePlace
|
||||||
|
} from 'react-icons/md';
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
import Loader from 'components/Loader';
|
||||||
|
import DebounceSearchBar from 'components/nearle_components/DebounceSearchBar';
|
||||||
|
import LocationAutocomplete from 'components/nearle_components/LocationAutocomplete';
|
||||||
|
import PageHeader from 'components/nearle_components/PageHeader';
|
||||||
|
import StatCard from 'components/nearle_components/StatCard';
|
||||||
|
import { MobileCard, MobileCardList, MobileField, MobileFieldGrid } from 'components/nearle_components/MobileCard';
|
||||||
|
import { OrdersTableSkeleton } from '../orders/OrdersTableSkeleton';
|
||||||
|
import { getallpricing } from 'pages/api/api';
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Design tokens — shared with the deliveries / tenants / customers pages so every
|
||||||
|
// surface (header, KPI tiles, table, badges) speaks the same visual language.
|
||||||
|
// Keep this block in sync with customers.js / deliveries.js.
|
||||||
|
// ============================================================================
|
||||||
|
const DT = {
|
||||||
|
radiusPill: 999,
|
||||||
|
radiusCard: 14,
|
||||||
|
radiusField: 10,
|
||||||
|
shadowSoft: '0 1px 2px rgba(15, 23, 42, 0.04), 0 8px 24px rgba(15, 23, 42, 0.05)',
|
||||||
|
shadowMd: '0 1px 3px rgba(15, 23, 42, 0.06)',
|
||||||
|
shadowPop: '0 12px 32px rgba(15, 23, 42, 0.12)',
|
||||||
|
textPrimary: '#0f172a',
|
||||||
|
textSecondary: '#64748b',
|
||||||
|
textMuted: '#94a3b8',
|
||||||
|
borderSubtle: '#e2e8f0',
|
||||||
|
borderHover: '#cbd5e1',
|
||||||
|
divider: '#f1f5f9',
|
||||||
|
surface: '#ffffff',
|
||||||
|
surfaceAlt: '#f8fafc',
|
||||||
|
brand: '#662582'
|
||||||
|
};
|
||||||
|
const a = (c, suffix) => `${c}${suffix}`;
|
||||||
|
const tint = (c) => a(c, '08');
|
||||||
|
const soft = (c) => a(c, '18');
|
||||||
|
const ring = (c) => a(c, '26');
|
||||||
|
const edge = (c) => a(c, '55');
|
||||||
|
|
||||||
|
const BRAND = '#662582';
|
||||||
|
|
||||||
|
const SoftPaper = (props) => (
|
||||||
|
<Paper
|
||||||
|
{...props}
|
||||||
|
sx={{
|
||||||
|
mt: 0.75,
|
||||||
|
borderRadius: 2,
|
||||||
|
boxShadow: DT.shadowPop,
|
||||||
|
border: '1px solid',
|
||||||
|
borderColor: 'divider',
|
||||||
|
overflow: 'hidden'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const AccentAvatar = ({ color, selected, size = 24, children }) => (
|
||||||
|
<Avatar
|
||||||
|
sx={{
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
bgcolor: selected ? color : soft(color),
|
||||||
|
color: selected ? '#fff' : color,
|
||||||
|
transition: 'background-color 0.15s, color 0.15s'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Avatar>
|
||||||
|
);
|
||||||
|
|
||||||
|
const formatRupees = (value) =>
|
||||||
|
new Intl.NumberFormat('en-IN', {
|
||||||
|
style: 'currency',
|
||||||
|
currency: 'INR',
|
||||||
|
minimumFractionDigits: 2
|
||||||
|
}).format(Number(value) || 0);
|
||||||
|
|
||||||
|
const formatDecimal = (value) =>
|
||||||
|
new Intl.NumberFormat('en-IN', { minimumFractionDigits: 2 }).format(Number(value) || 0);
|
||||||
|
|
||||||
|
// Numeric table value — plain, strong, right-readable text. The old version
|
||||||
|
// wrapped every cell in a coloured bordered pill, which made the table read
|
||||||
|
// like a rainbow; corporate data tables keep figures as quiet typography and
|
||||||
|
// let the column header carry the meaning.
|
||||||
|
const MetricPill = ({ label }) => (
|
||||||
|
<Typography
|
||||||
|
component="span"
|
||||||
|
sx={{ fontSize: 13.5, fontWeight: 700, color: DT.textPrimary, whiteSpace: 'nowrap', fontVariantNumeric: 'tabular-nums' }}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Typography>
|
||||||
|
);
|
||||||
|
|
||||||
|
// Subtle neutral category chip (zone / slab) — one quiet style, muted icon.
|
||||||
|
const CategoryChip = ({ icon, label }) => (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'inline-flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 0.5,
|
||||||
|
px: 1,
|
||||||
|
py: 0.375,
|
||||||
|
borderRadius: 8,
|
||||||
|
bgcolor: DT.surfaceAlt,
|
||||||
|
border: `1px solid ${DT.borderSubtle}`,
|
||||||
|
color: DT.textPrimary,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: 600,
|
||||||
|
whiteSpace: 'nowrap'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box component="span" sx={{ display: 'inline-flex', color: DT.textMuted }}>
|
||||||
|
{icon}
|
||||||
|
</Box>
|
||||||
|
{label}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
|
||||||
|
// ==============================|| Pricing page ||============================== //
|
||||||
|
|
||||||
|
const ClientsPricing = () => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
|
const containerRef = useRef();
|
||||||
|
const [appId, setAppId] = useState(0);
|
||||||
|
const [locaName, setLocoName] = useState('All');
|
||||||
|
const [searchword, setSearchword] = useState('');
|
||||||
|
const [debouncedSearch, setDebouncedSearch] = useState('');
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: pricing = [],
|
||||||
|
isLoading
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ['getallpricing', appId],
|
||||||
|
queryFn: getallpricing,
|
||||||
|
keepPreviousData: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const rows = useMemo(() => {
|
||||||
|
if (!debouncedSearch) return pricing;
|
||||||
|
const q = debouncedSearch.toLowerCase().trim();
|
||||||
|
return pricing.filter((row) =>
|
||||||
|
[row.applocation, row.appname, row.slab, String(row.pricingid)]
|
||||||
|
.filter(Boolean)
|
||||||
|
.some((field) => String(field).toLowerCase().includes(q))
|
||||||
|
);
|
||||||
|
}, [pricing, debouncedSearch]);
|
||||||
|
|
||||||
|
const stats = useMemo(() => {
|
||||||
|
const total = pricing.length;
|
||||||
|
const tenants = new Set(pricing.map((r) => r.appname).filter(Boolean)).size;
|
||||||
|
const avgBase = total
|
||||||
|
? pricing.reduce((sum, r) => sum + (Number(r.baseprice) || 0), 0) / total
|
||||||
|
: 0;
|
||||||
|
return { total, tenants, avgBase };
|
||||||
|
}, [pricing]);
|
||||||
|
|
||||||
|
const KPI_META = [
|
||||||
|
{ key: 'total', label: 'Total Pricing Slabs', color: BRAND, icon: MdOutlineLocalOffer, value: stats.total },
|
||||||
|
{ key: 'tenants', label: 'Tenants Priced', color: '#0ea5e9', icon: MdOutlineGroups, value: stats.tenants },
|
||||||
|
{ key: 'avg', label: 'Avg Base Price', color: '#f59e0b', icon: MdOutlineAttachMoney, value: formatRupees(stats.avgBase) },
|
||||||
|
{ key: 'zone', label: 'Active Zone', color: '#10b981', icon: MdOutlinePlace, value: locaName || 'All Zones' }
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isLoading && <Loader />}
|
||||||
|
|
||||||
|
{/* ============================================= || Header || ============================================= */}
|
||||||
|
<PageHeader
|
||||||
|
title="Pricing"
|
||||||
|
subtitle={`Live · ${locaName || 'All Zones'}`}
|
||||||
|
live
|
||||||
|
action={
|
||||||
|
<LocationAutocomplete
|
||||||
|
locaName={locaName}
|
||||||
|
setAppId={setAppId}
|
||||||
|
setLocoName={setLocoName}
|
||||||
|
pill
|
||||||
|
accentColor={BRAND}
|
||||||
|
icon={<MdMyLocation size={14} />}
|
||||||
|
placeholder="Select Zone"
|
||||||
|
paperComponent={SoftPaper}
|
||||||
|
sx={{ width: { xs: '100%', sm: 280 }, zIndex: 100 }}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* ============================================= || KPI Cards || ============================================= */}
|
||||||
|
<Grid container spacing={{ xs: 2, md: 2.5 }} sx={{ mb: { xs: 1.5, md: 2 } }}>
|
||||||
|
{KPI_META.map((item) => {
|
||||||
|
const Icon = item.icon;
|
||||||
|
return (
|
||||||
|
<Grid item key={item.key} xs={6} sm={6} md={3}>
|
||||||
|
<StatCard title={item.label} value={item.value} icon={<Icon size={20} />} color={item.color} />
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* ============================================= || Search Header || ============================================= */}
|
||||||
|
<Paper
|
||||||
|
elevation={0}
|
||||||
|
sx={{
|
||||||
|
mt: { xs: 1.5, md: 2 },
|
||||||
|
p: { xs: 1, md: 1.5 },
|
||||||
|
borderTopLeftRadius: DT.radiusCard / 8,
|
||||||
|
borderTopRightRadius: DT.radiusCard / 8,
|
||||||
|
borderBottomLeftRadius: 0,
|
||||||
|
borderBottomRightRadius: 0,
|
||||||
|
border: '1px solid',
|
||||||
|
borderColor: DT.borderSubtle,
|
||||||
|
borderBottom: 0,
|
||||||
|
background: '#fff'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack
|
||||||
|
direction={{ xs: 'column', sm: 'row' }}
|
||||||
|
alignItems={{ xs: 'stretch', sm: 'center' }}
|
||||||
|
justifyContent="space-between"
|
||||||
|
spacing={1.25}
|
||||||
|
>
|
||||||
|
<Stack direction="row" alignItems="center" spacing={1.25}>
|
||||||
|
<AccentAvatar color={BRAND} size={32}>
|
||||||
|
<MdLocalOffer size={18} />
|
||||||
|
</AccentAvatar>
|
||||||
|
<Stack>
|
||||||
|
<Typography
|
||||||
|
variant="caption"
|
||||||
|
sx={{ fontWeight: 800, color: DT.textSecondary, letterSpacing: 0.6, textTransform: 'uppercase' }}
|
||||||
|
>
|
||||||
|
Pricing Catalog
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" sx={{ color: DT.textPrimary, fontWeight: 700 }}>
|
||||||
|
{pricing.length} total · {rows.length} shown
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
<Box sx={{ width: { xs: '100%', sm: 280, lg: 340 }, flex: { xs: '1 1 100%', sm: '0 0 auto' } }}>
|
||||||
|
<DebounceSearchBar
|
||||||
|
value={searchword}
|
||||||
|
onChange={setSearchword}
|
||||||
|
onDebouncedChange={setDebouncedSearch}
|
||||||
|
placeholder={`Search pricing (ctrl+k)`}
|
||||||
|
sx={{
|
||||||
|
m: 0,
|
||||||
|
width: '100%',
|
||||||
|
borderRadius: DT.radiusField + 'px',
|
||||||
|
bgcolor: DT.surface,
|
||||||
|
'& fieldset': { borderColor: DT.borderSubtle, borderWidth: 1 },
|
||||||
|
'&:hover fieldset': { borderColor: DT.borderHover },
|
||||||
|
'&.Mui-focused fieldset': { borderColor: BRAND, borderWidth: 1.5 },
|
||||||
|
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` }
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
{/* ============================================= || Table || ============================================= */}
|
||||||
|
<Paper
|
||||||
|
elevation={0}
|
||||||
|
sx={{
|
||||||
|
borderTopLeftRadius: 0,
|
||||||
|
borderTopRightRadius: 0,
|
||||||
|
borderBottomLeftRadius: DT.radiusCard / 8,
|
||||||
|
borderBottomRightRadius: DT.radiusCard / 8,
|
||||||
|
border: '1px solid',
|
||||||
|
borderColor: DT.borderSubtle,
|
||||||
|
overflow: 'hidden',
|
||||||
|
background: '#fff'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isMobile ? (
|
||||||
|
rows.length === 0 && !isLoading ? (
|
||||||
|
<Stack alignItems="center" spacing={1.5} sx={{ py: 6, px: 2 }}>
|
||||||
|
<Avatar sx={{ width: 64, height: 64, bgcolor: soft('#94a3b8'), color: DT.textMuted }}>
|
||||||
|
<MdLocalOffer size={28} />
|
||||||
|
</Avatar>
|
||||||
|
<Typography variant="subtitle1" sx={{ fontWeight: 700, color: DT.textPrimary }}>
|
||||||
|
No pricing to show
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="caption" sx={{ color: DT.textSecondary, textAlign: 'center' }}>
|
||||||
|
{searchword ? 'Try a different keyword.' : 'Pick a zone above to load the catalog.'}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
) : (
|
||||||
|
<MobileCardList scroll>
|
||||||
|
{rows.map((row, index) => (
|
||||||
|
<MobileCard
|
||||||
|
key={row.pricingid || `${row.appname}-${index}`}
|
||||||
|
accent={BRAND}
|
||||||
|
header={
|
||||||
|
<Stack direction="row" alignItems="center" justifyContent="space-between" spacing={1}>
|
||||||
|
<Stack direction="row" alignItems="center" spacing={1} sx={{ minWidth: 0 }}>
|
||||||
|
<AccentAvatar color={BRAND} size={36}>
|
||||||
|
<MdGroups size={18} />
|
||||||
|
</AccentAvatar>
|
||||||
|
<Stack sx={{ minWidth: 0 }}>
|
||||||
|
<Typography
|
||||||
|
variant="subtitle2"
|
||||||
|
sx={{ fontWeight: 700, color: DT.textPrimary }}
|
||||||
|
noWrap
|
||||||
|
>
|
||||||
|
{row.appname || '—'}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="caption" sx={{ color: DT.textSecondary }}>
|
||||||
|
ID #{row.pricingid}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
<Typography variant="caption" sx={{ fontWeight: 700, color: DT.textMuted, flexShrink: 0 }}>
|
||||||
|
{String(index + 1).padStart(2, '0')}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Stack direction="row" spacing={0.75} sx={{ mt: 1, flexWrap: 'wrap', gap: 0.75 }}>
|
||||||
|
{row.applocation ? (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'inline-flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 0.5,
|
||||||
|
px: 1,
|
||||||
|
py: 0.375,
|
||||||
|
borderRadius: 999,
|
||||||
|
bgcolor: tint('#10b981'),
|
||||||
|
border: `1px solid ${edge('#10b981')}`,
|
||||||
|
color: '#10b981',
|
||||||
|
fontSize: 11,
|
||||||
|
fontWeight: 800
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MdPlace size={12} /> {row.applocation}
|
||||||
|
</Box>
|
||||||
|
) : null}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'inline-flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 0.5,
|
||||||
|
px: 1,
|
||||||
|
py: 0.375,
|
||||||
|
borderRadius: 999,
|
||||||
|
bgcolor: tint('#0ea5e9'),
|
||||||
|
border: `1px solid ${edge('#0ea5e9')}`,
|
||||||
|
color: '#0ea5e9',
|
||||||
|
fontSize: 11,
|
||||||
|
fontWeight: 800
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MdSpeed size={12} /> {row.slab || '—'}
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<MobileFieldGrid>
|
||||||
|
<MobileField label="Base Price">
|
||||||
|
<MetricPill
|
||||||
|
color={BRAND}
|
||||||
|
icon={<MdPriceCheck size={12} />}
|
||||||
|
label={formatRupees(row.baseprice)}
|
||||||
|
/>
|
||||||
|
</MobileField>
|
||||||
|
<MobileField label="Price / KM">
|
||||||
|
<MetricPill
|
||||||
|
color="#10b981"
|
||||||
|
icon={<MdAttachMoney size={12} />}
|
||||||
|
label={formatRupees(row.priceperkm)}
|
||||||
|
/>
|
||||||
|
</MobileField>
|
||||||
|
<MobileField label="Min KM">
|
||||||
|
<MetricPill
|
||||||
|
color="#f59e0b"
|
||||||
|
icon={<MdStraighten size={12} />}
|
||||||
|
label={`${formatDecimal(row.minkm)} km`}
|
||||||
|
/>
|
||||||
|
</MobileField>
|
||||||
|
<MobileField label="Max KM">
|
||||||
|
<MetricPill
|
||||||
|
color="#ef4444"
|
||||||
|
icon={<MdStraighten size={12} />}
|
||||||
|
label={`${formatDecimal(row.maxkm)} km`}
|
||||||
|
/>
|
||||||
|
</MobileField>
|
||||||
|
<MobileField label="Min Orders">
|
||||||
|
<Stack direction="row" alignItems="center" spacing={0.5}>
|
||||||
|
<MdReceiptLong size={14} color={DT.textMuted} />
|
||||||
|
<Typography variant="subtitle2" sx={{ fontWeight: 700, color: DT.textPrimary }}>
|
||||||
|
{row.minorder ?? '—'}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
</MobileField>
|
||||||
|
</MobileFieldGrid>
|
||||||
|
</MobileCard>
|
||||||
|
))}
|
||||||
|
</MobileCardList>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<TableContainer
|
||||||
|
ref={containerRef}
|
||||||
|
sx={{
|
||||||
|
maxHeight: { xs: 'calc(100vh - 220px)', md: 'calc(100vh - 190px)' },
|
||||||
|
'&::-webkit-scrollbar': { width: 10, height: 10 },
|
||||||
|
'&::-webkit-scrollbar-thumb': {
|
||||||
|
backgroundColor: edge(BRAND),
|
||||||
|
borderRadius: 8,
|
||||||
|
'&:hover': { backgroundColor: BRAND }
|
||||||
|
},
|
||||||
|
'&::-webkit-scrollbar-track': { backgroundColor: DT.surfaceAlt }
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Table stickyHeader sx={{ minWidth: { xs: 860, md: 1080 } }}>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow
|
||||||
|
sx={{
|
||||||
|
'& th': {
|
||||||
|
backgroundColor: DT.surfaceAlt,
|
||||||
|
color: DT.textSecondary,
|
||||||
|
fontSize: { xs: 10, md: 11 },
|
||||||
|
fontWeight: 800,
|
||||||
|
letterSpacing: 0.6,
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
borderBottom: `1px solid ${DT.borderSubtle}`,
|
||||||
|
py: { xs: 1, md: 1.25 },
|
||||||
|
px: { xs: 1, md: 2 }
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TableCell>#</TableCell>
|
||||||
|
<TableCell>Tenant</TableCell>
|
||||||
|
<TableCell>Zone</TableCell>
|
||||||
|
<TableCell>Slab</TableCell>
|
||||||
|
<TableCell align="center">Base Price</TableCell>
|
||||||
|
<TableCell align="center">Min KM</TableCell>
|
||||||
|
<TableCell align="center">Price / KM</TableCell>
|
||||||
|
<TableCell align="center">Max KM</TableCell>
|
||||||
|
<TableCell align="center">Min Orders</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
|
||||||
|
<TableBody>
|
||||||
|
{isLoading && <OrdersTableSkeleton col={5} />}
|
||||||
|
{rows.length === 0 && !isLoading ? (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={9} sx={{ py: 6 }}>
|
||||||
|
<Stack alignItems="center" spacing={1.5}>
|
||||||
|
<Avatar sx={{ width: 64, height: 64, bgcolor: soft('#94a3b8'), color: DT.textMuted }}>
|
||||||
|
<MdLocalOffer size={28} />
|
||||||
|
</Avatar>
|
||||||
|
<Typography variant="subtitle1" sx={{ fontWeight: 700, color: DT.textPrimary }}>
|
||||||
|
No pricing to show
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="caption" sx={{ color: DT.textSecondary }}>
|
||||||
|
{searchword ? 'Try a different keyword.' : 'Pick a zone above to load the catalog.'}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
) : (
|
||||||
|
rows.map((row, index) => (
|
||||||
|
<TableRow
|
||||||
|
key={row.pricingid || `${row.appname}-${index}`}
|
||||||
|
sx={{
|
||||||
|
transition: 'background-color 0.15s',
|
||||||
|
'& td': {
|
||||||
|
borderBottom: `1px solid ${DT.divider}`,
|
||||||
|
py: { xs: 1, md: 1.5 },
|
||||||
|
px: { xs: 1, md: 2 }
|
||||||
|
},
|
||||||
|
'&:hover': { backgroundColor: DT.surfaceAlt }
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TableCell>
|
||||||
|
<Typography variant="caption" sx={{ fontWeight: 700, color: DT.textMuted }}>
|
||||||
|
{String(index + 1).padStart(2, '0')}
|
||||||
|
</Typography>
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell>
|
||||||
|
<Stack direction="row" alignItems="center" spacing={1}>
|
||||||
|
<AccentAvatar color={BRAND} size={36}>
|
||||||
|
<MdGroups size={18} />
|
||||||
|
</AccentAvatar>
|
||||||
|
<Stack>
|
||||||
|
<Typography
|
||||||
|
variant="subtitle2"
|
||||||
|
sx={{ fontWeight: 700, color: DT.textPrimary, whiteSpace: 'nowrap' }}
|
||||||
|
>
|
||||||
|
{row.appname || '—'}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="caption" sx={{ color: DT.textSecondary }}>
|
||||||
|
ID #{row.pricingid}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell>
|
||||||
|
{row.applocation ? (
|
||||||
|
<CategoryChip icon={<MdPlace size={12} />} label={row.applocation} />
|
||||||
|
) : (
|
||||||
|
<Typography variant="caption" sx={{ color: DT.textMuted }}>—</Typography>
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell>
|
||||||
|
<CategoryChip icon={<MdSpeed size={12} />} label={row.slab || '—'} />
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell align="center">
|
||||||
|
<MetricPill
|
||||||
|
color={BRAND}
|
||||||
|
icon={<MdPriceCheck size={12} />}
|
||||||
|
label={formatRupees(row.baseprice)}
|
||||||
|
width={110}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell align="center">
|
||||||
|
<MetricPill
|
||||||
|
color="#f59e0b"
|
||||||
|
icon={<MdStraighten size={12} />}
|
||||||
|
label={`${formatDecimal(row.minkm)} km`}
|
||||||
|
width={90}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell align="center">
|
||||||
|
<MetricPill
|
||||||
|
color="#10b981"
|
||||||
|
icon={<MdAttachMoney size={12} />}
|
||||||
|
label={formatRupees(row.priceperkm)}
|
||||||
|
width={110}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell align="center">
|
||||||
|
<MetricPill
|
||||||
|
color="#ef4444"
|
||||||
|
icon={<MdStraighten size={12} />}
|
||||||
|
label={`${formatDecimal(row.maxkm)} km`}
|
||||||
|
width={90}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell align="center">
|
||||||
|
<Stack direction="row" alignItems="center" justifyContent="center" spacing={0.5}>
|
||||||
|
<MdReceiptLong size={14} color={DT.textMuted} />
|
||||||
|
<Typography
|
||||||
|
variant="subtitle2"
|
||||||
|
sx={{ fontWeight: 700, color: DT.textPrimary, whiteSpace: 'nowrap' }}
|
||||||
|
>
|
||||||
|
{row.minorder ?? '—'}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
)}
|
||||||
|
</Paper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ClientsPricing;
|
||||||
2100
src/pages/nearle/clients/Tenants.js
Normal file
2100
src/pages/nearle/clients/Tenants.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -11,13 +11,11 @@ import { MdPersonAddAlt1 } from 'react-icons/md';
|
|||||||
// project import
|
// project import
|
||||||
import MainCard from 'components/MainCard';
|
import MainCard from 'components/MainCard';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { usePlacesWidget } from 'react-google-autocomplete';
|
import AddressAutocomplete, { geocodeAddress } from 'components/nearle_components/AddressAutocomplete';
|
||||||
import Loader from 'components/Loader';
|
import Loader from 'components/Loader';
|
||||||
import Geocode from 'react-geocode';
|
|
||||||
import { enqueueSnackbar } from 'notistack';
|
import { enqueueSnackbar } from 'notistack';
|
||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
import { DT, tint } from 'themes/dt/tokens';
|
import { DT, tint } from 'themes/dt/tokens';
|
||||||
// import { setLocationType } from 'react-geocode';
|
|
||||||
|
|
||||||
// const avatarImage = require.context('assets/images/users', true);
|
// const avatarImage = require.context('assets/images/users', true);
|
||||||
|
|
||||||
@@ -51,9 +49,6 @@ const Createclient = () => {
|
|||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
Geocode.setApiKey(process.env.REACT_APP_GOOGLE_MAPS_API_KEY);
|
|
||||||
// Geocode.setApiKey('AIzaSyCF4KatYCI3vqz1_H3kiHeyS3yCMfYToh8');
|
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -65,25 +60,15 @@ const Createclient = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
let active = true;
|
||||||
Geocode.fromAddress(address).then(
|
geocodeAddress(address).then((place) => {
|
||||||
(response) => {
|
if (active && place) {
|
||||||
if (response.status == 'OK') {
|
setLatlong({ lat: place.geometry.location.lat(), lng: place.geometry.location.lng() });
|
||||||
const { lat, lng } = response.results[0].geometry.location;
|
}
|
||||||
setLatlong({
|
|
||||||
lat,
|
|
||||||
lng
|
|
||||||
});
|
});
|
||||||
console.log(response);
|
return () => {
|
||||||
}
|
active = false;
|
||||||
},
|
};
|
||||||
(error) => {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}, [address]);
|
}, [address]);
|
||||||
|
|
||||||
const opentoast = (message) => {
|
const opentoast = (message) => {
|
||||||
@@ -147,11 +132,7 @@ const Createclient = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const { ref: materialRef } = usePlacesWidget({
|
const handleAddressPlaceSelected = (place) => {
|
||||||
apiKey: process.env.REACT_APP_GOOGLE_MAPS_API_KEY,
|
|
||||||
onPlaceSelected: (place) => {
|
|
||||||
console.log(place);
|
|
||||||
|
|
||||||
setAddress(place.formatted_address);
|
setAddress(place.formatted_address);
|
||||||
let city1, zipcode1, state1, suburb1;
|
let city1, zipcode1, state1, suburb1;
|
||||||
for (let i = 0; i < place.address_components.length; i++) {
|
for (let i = 0; i < place.address_components.length; i++) {
|
||||||
@@ -167,6 +148,7 @@ const Createclient = () => {
|
|||||||
zipcode1 = place.address_components[i].long_name;
|
zipcode1 = place.address_components[i].long_name;
|
||||||
break;
|
break;
|
||||||
case 'sublocality':
|
case 'sublocality':
|
||||||
|
case 'sublocality_level_1':
|
||||||
suburb1 = place.address_components[i].long_name;
|
suburb1 = place.address_components[i].long_name;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -176,16 +158,7 @@ const Createclient = () => {
|
|||||||
setState(state1 || '');
|
setState(state1 || '');
|
||||||
setZipcode(zipcode1 || '');
|
setZipcode(zipcode1 || '');
|
||||||
setSuburb(suburb1 || '');
|
setSuburb(suburb1 || '');
|
||||||
|
};
|
||||||
// setAddress(place.formatted_address)
|
|
||||||
},
|
|
||||||
// inputAutocompleteValue: "country",
|
|
||||||
options: {
|
|
||||||
// componentRestrictions: 'us',
|
|
||||||
// types: ["establishment"]
|
|
||||||
types: ['address' || 'geocode']
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const createprofile = async () => {
|
const createprofile = async () => {
|
||||||
console.log('res', businessname, businessno, mobilenumber, emailaddress, address, city, zipcode);
|
console.log('res', businessname, businessno, mobilenumber, emailaddress, address, city, zipcode);
|
||||||
@@ -499,14 +472,13 @@ const Createclient = () => {
|
|||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Stack spacing={1.25}>
|
<Stack spacing={1.25}>
|
||||||
<InputLabel htmlFor="personal-address">Address</InputLabel>
|
<InputLabel htmlFor="personal-address">Address</InputLabel>
|
||||||
<TextField
|
<AddressAutocomplete
|
||||||
fullWidth
|
|
||||||
// defaultValue="Street 110-B Kalians Bag, Dewan, M.P. New York"
|
|
||||||
id="personal-address"
|
id="personal-address"
|
||||||
|
fullWidth
|
||||||
placeholder="Address"
|
placeholder="Address"
|
||||||
value={address}
|
value={address}
|
||||||
onChange={(e) => setAddress(e.target.value)}
|
onChange={setAddress}
|
||||||
inputRef={materialRef}
|
onPlaceSelected={handleAddressPlaceSelected}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ import { TbMapPinCode } from 'react-icons/tb';
|
|||||||
import { FaLocationDot } from 'react-icons/fa6';
|
import { FaLocationDot } from 'react-icons/fa6';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
import Geocode from 'react-geocode';
|
import AddressAutocomplete from 'components/nearle_components/AddressAutocomplete';
|
||||||
import Loader from 'components/Loader';
|
import Loader from 'components/Loader';
|
||||||
import * as geolib from 'geolib';
|
import * as geolib from 'geolib';
|
||||||
import MainCard from 'components/MainCard';
|
import MainCard from 'components/MainCard';
|
||||||
@@ -177,30 +177,14 @@ const SoftPaper = (props) => (
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
function loadScript(src, position, id) {
|
|
||||||
if (!position) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const script = document.createElement('script');
|
|
||||||
script.setAttribute('async', '');
|
|
||||||
script.setAttribute('id', id);
|
|
||||||
script.src = src;
|
|
||||||
position.appendChild(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Createorder1 = () => {
|
const Createorder1 = () => {
|
||||||
Geocode.setApiKey(process.env.REACT_APP_GOOGLE_MAPS_API_KEY);
|
|
||||||
// ================================================= || GoogleMaps (Drawer) || =================================================
|
// ================================================= || GoogleMaps (Drawer) || =================================================
|
||||||
const [value, setValue] = React.useState(null);
|
|
||||||
const [value1, setValue1] = React.useState(null);
|
|
||||||
const [inputValue, setInputValue] = React.useState('');
|
const [inputValue, setInputValue] = React.useState('');
|
||||||
const [inputValue1, setInputValue1] = React.useState('');
|
const [inputValue1, setInputValue1] = React.useState('');
|
||||||
const [inputValue2, setInputValue2] = React.useState('');
|
const [inputValue2, setInputValue2] = React.useState('');
|
||||||
const [inputValue3, setInputValue3] = React.useState('');
|
const [inputValue3, setInputValue3] = React.useState('');
|
||||||
const [options, setOptions] = React.useState([]);
|
const [options, setOptions] = React.useState([]);
|
||||||
const [options1, setOptions1] = React.useState([]);
|
const [options1, setOptions1] = React.useState([]);
|
||||||
const loaded = React.useRef(false);
|
|
||||||
const loaded1 = React.useRef(false);
|
const loaded1 = React.useRef(false);
|
||||||
const [mobilenumber, setMobilenumber] = useState('');
|
const [mobilenumber, setMobilenumber] = useState('');
|
||||||
const [emailaddress, setEmailaddress] = useState('');
|
const [emailaddress, setEmailaddress] = useState('');
|
||||||
@@ -218,8 +202,6 @@ const Createorder1 = () => {
|
|||||||
const [dropDoorno, setDropDoorno] = useState('');
|
const [dropDoorno, setDropDoorno] = useState('');
|
||||||
const [pickLandmark, setPickLandmark] = useState('');
|
const [pickLandmark, setPickLandmark] = useState('');
|
||||||
const [dropLandmark, setDropLandmark] = useState('');
|
const [dropLandmark, setDropLandmark] = useState('');
|
||||||
const [address, setAddress] = useState('');
|
|
||||||
const [address1, setAddress1] = useState('');
|
|
||||||
const [latlong, setLatlong] = useState({});
|
const [latlong, setLatlong] = useState({});
|
||||||
const [latlong1, setLatlong1] = useState({});
|
const [latlong1, setLatlong1] = useState({});
|
||||||
const autocompleteService = useRef(null);
|
const autocompleteService = useRef(null);
|
||||||
@@ -252,225 +234,6 @@ const Createorder1 = () => {
|
|||||||
{ label: '12 Angry Men', year: 1957 }
|
{ label: '12 Angry Men', year: 1957 }
|
||||||
];
|
];
|
||||||
|
|
||||||
// // // ====================================================== || address (pick)|| ======================================================
|
|
||||||
// useEffect(() => {
|
|
||||||
// if (address) {
|
|
||||||
// try {
|
|
||||||
// Geocode.fromAddress(address).then(
|
|
||||||
// (response) => {
|
|
||||||
// if (response.status == 'OK') {
|
|
||||||
// const { lat, lng } = response.results[0].geometry.location;
|
|
||||||
// console.log({ lat, lng });
|
|
||||||
// setLatlong({
|
|
||||||
// lat,
|
|
||||||
// lng
|
|
||||||
// });
|
|
||||||
// console.log(response);
|
|
||||||
// if (response.results[0].address_components) {
|
|
||||||
// let place = response.results[0];
|
|
||||||
// let cityA, zipcodeA, stateA, suburbA;
|
|
||||||
// for (let i = 0; i < place.address_components.length; i++) {
|
|
||||||
// for (let j = 0; j < place.address_components[i].types.length; j++) {
|
|
||||||
// switch (place.address_components[i].types[j]) {
|
|
||||||
// case 'locality':
|
|
||||||
// cityA = place.address_components[i].long_name;
|
|
||||||
// break;
|
|
||||||
// case 'administrative_area_level_1':
|
|
||||||
// stateA = place.address_components[i].long_name;
|
|
||||||
// break;
|
|
||||||
// case 'postal_code':
|
|
||||||
// zipcodeA = place.address_components[i].long_name;
|
|
||||||
// break;
|
|
||||||
// case 'sublocality':
|
|
||||||
// suburbA = place.address_components[i].long_name;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// setCity(cityA || '');
|
|
||||||
// setState(stateA || '');
|
|
||||||
// setZipcode(zipcodeA || '');
|
|
||||||
// setSuburb(suburbA || '');
|
|
||||||
// console.log({ lat, lng, cityA, stateA, zipcodeA, suburbA });
|
|
||||||
// setPickCust({
|
|
||||||
// ...pickCust
|
|
||||||
// // city: cityA,
|
|
||||||
// // state: stateA,
|
|
||||||
// // postcode: zipcodeA,
|
|
||||||
// // suburb: suburbA
|
|
||||||
// // latitude: lat,
|
|
||||||
// // longitude: lng
|
|
||||||
// });
|
|
||||||
// // setStartPoint({ latitude: lat, longitude: lng });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// (error) => {
|
|
||||||
// console.log(error);
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// } catch (err) {
|
|
||||||
// console.log(err);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }, [address]);
|
|
||||||
// // // ====================================================== || address 1 (drop)|| ======================================================
|
|
||||||
// useEffect(() => {
|
|
||||||
// if (address) {
|
|
||||||
// try {
|
|
||||||
// Geocode.fromAddress(address1).then(
|
|
||||||
// (response) => {
|
|
||||||
// if (response.status == 'OK') {
|
|
||||||
// const { lat, lng } = response.results[0].geometry.location;
|
|
||||||
|
|
||||||
// setLatlong1({
|
|
||||||
// lat,
|
|
||||||
// lng
|
|
||||||
// });
|
|
||||||
// console.log(response);
|
|
||||||
// if (response.results[0].address_components) {
|
|
||||||
// let place = response.results[0];
|
|
||||||
// let cityB, zipcodeB, stateB, suburbB;
|
|
||||||
// for (let i = 0; i < place.address_components.length; i++) {
|
|
||||||
// for (let j = 0; j < place.address_components[i].types.length; j++) {
|
|
||||||
// switch (place.address_components[i].types[j]) {
|
|
||||||
// case 'locality':
|
|
||||||
// cityB = place.address_components[i].long_name;
|
|
||||||
// break;
|
|
||||||
// case 'administrative_area_level_1':
|
|
||||||
// stateB = place.address_components[i].long_name;
|
|
||||||
// break;
|
|
||||||
// case 'postal_code':
|
|
||||||
// zipcodeB = place.address_components[i].long_name;
|
|
||||||
// break;
|
|
||||||
// case 'sublocality':
|
|
||||||
// suburbB = place.address_components[i].long_name;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// setCity(cityB || '');
|
|
||||||
// setState(stateB || '');
|
|
||||||
// setZipcode(zipcodeB || '');
|
|
||||||
// setSuburb(suburbB || '');
|
|
||||||
// console.log({ lat, lng, cityB, stateB, zipcodeB, suburbB });
|
|
||||||
// setDropCust({
|
|
||||||
// ...dropCust
|
|
||||||
// // city: cityB,
|
|
||||||
// // state: stateB,
|
|
||||||
// // postcode: zipcodeB,
|
|
||||||
// // suburb: suburbB
|
|
||||||
// // latitude: lat,
|
|
||||||
// // longitude: lng
|
|
||||||
// });
|
|
||||||
// // setEndPoint({ latitude: lat, longitude: lng });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// (error) => {
|
|
||||||
// console.log(error);
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// } catch (err) {
|
|
||||||
// console.log(err);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }, [address1]);
|
|
||||||
|
|
||||||
if (typeof window !== 'undefined' && !loaded.current) {
|
|
||||||
if (!document.querySelector('#google-maps')) {
|
|
||||||
loadScript(
|
|
||||||
`https://maps.googleapis.com/maps/api/js?key=${process.env.REACT_APP_GOOGLE_MAPS_API_KEY}&libraries=places&location=10.3656,77.9690&radius=50000&components=country:IN&strictbounds=true`,
|
|
||||||
document.querySelector('head'),
|
|
||||||
'google-maps'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
loaded.current = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// const fetch = React.useMemo(
|
|
||||||
// () =>
|
|
||||||
// debounce((request, callback) => {
|
|
||||||
// autocompleteService.current.getPlacePredictions(request, callback);
|
|
||||||
// }, 400),
|
|
||||||
// []
|
|
||||||
// );
|
|
||||||
// const fetch1 = React.useMemo(
|
|
||||||
// () =>
|
|
||||||
// debounce((request, callback) => {
|
|
||||||
// autocompleteService.current.getPlacePredictions(request, callback);
|
|
||||||
// }, 400),
|
|
||||||
// []
|
|
||||||
// );
|
|
||||||
|
|
||||||
// ====================================================== || options (pick)|| ======================================================
|
|
||||||
|
|
||||||
// React.useEffect(() => {
|
|
||||||
// let active = true;
|
|
||||||
// if (!autocompleteService.current && window.google) {
|
|
||||||
// autocompleteService.current = new window.google.maps.places.AutocompleteService();
|
|
||||||
// }
|
|
||||||
// if (!autocompleteService.current) {
|
|
||||||
// return undefined;
|
|
||||||
// }
|
|
||||||
// if (inputValue === '') {
|
|
||||||
// setOptions(value ? [value] : []);
|
|
||||||
// return undefined;
|
|
||||||
// }
|
|
||||||
// fetch({ input: inputValue }, (results) => {
|
|
||||||
// if (active) {
|
|
||||||
// let newOptions = [];
|
|
||||||
|
|
||||||
// if (value) {
|
|
||||||
// newOptions = [value];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (results) {
|
|
||||||
// newOptions = [...newOptions, ...results];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// setOptions(newOptions);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return () => {
|
|
||||||
// active = false;
|
|
||||||
// };
|
|
||||||
// }, [value, inputValue, fetch]);
|
|
||||||
|
|
||||||
// // ====================================================== || options1 (drop)|| ======================================================
|
|
||||||
// React.useEffect(() => {
|
|
||||||
// let active = true;
|
|
||||||
// if (!autocompleteService.current && window.google) {
|
|
||||||
// autocompleteService.current = new window.google.maps.places.AutocompleteService();
|
|
||||||
// }
|
|
||||||
// if (!autocompleteService.current) {
|
|
||||||
// return undefined;
|
|
||||||
// }
|
|
||||||
// if (inputValue1 === '') {
|
|
||||||
// setOptions1(value1 ? [value1] : []);
|
|
||||||
// return undefined;
|
|
||||||
// }
|
|
||||||
// fetch1({ input: inputValue1 }, (results) => {
|
|
||||||
// if (active) {
|
|
||||||
// let newOptions = [];
|
|
||||||
|
|
||||||
// if (value1) {
|
|
||||||
// newOptions = [value1];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (results) {
|
|
||||||
// newOptions = [...newOptions, ...results];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// setOptions1(newOptions);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return () => {
|
|
||||||
// active = false;
|
|
||||||
// };
|
|
||||||
// }, [value1, inputValue1, fetch1]);
|
|
||||||
|
|
||||||
const appId = localStorage.getItem('applocationid');
|
const appId = localStorage.getItem('applocationid');
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -687,41 +450,6 @@ const Createorder1 = () => {
|
|||||||
}
|
}
|
||||||
}, [searchword]);
|
}, [searchword]);
|
||||||
|
|
||||||
// const { ref: materialRef } = usePlacesWidget({
|
|
||||||
// apiKey: process.env.REACT_APP_GOOGLE_MAPS_API_KEY,
|
|
||||||
// onPlaceSelected: (place) => {
|
|
||||||
// console.log(place);
|
|
||||||
|
|
||||||
// // setAddress(place.formatted_address)
|
|
||||||
// let city1, zipcode1, state1, suburb1;
|
|
||||||
// for (let i = 0; i < place.address_components.length; i++) {
|
|
||||||
// for (let j = 0; j < place.address_components[i].types.length; j++) {
|
|
||||||
// switch (place.address_components[i].types[j]) {
|
|
||||||
// case 'locality':
|
|
||||||
// city1 = place.address_components[i].long_name;
|
|
||||||
// break;
|
|
||||||
// case 'administrative_area_level_1':
|
|
||||||
// state1 = place.address_components[i].long_name;
|
|
||||||
// break;
|
|
||||||
// case 'postal_code':
|
|
||||||
// zipcode1 = place.address_components[i].long_name;
|
|
||||||
// break;
|
|
||||||
// case 'sublocality':
|
|
||||||
// suburb1 = place.address_components[i].long_name;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // setCity(city1 || '')
|
|
||||||
// // setState(state1 || '');
|
|
||||||
// // setZipcode(zipcode1 || '');
|
|
||||||
// // setSuburb(suburb1 || '')
|
|
||||||
// },
|
|
||||||
|
|
||||||
// options: {
|
|
||||||
// types: ['address' || 'geocode']
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// ==================================================== || fetchtenantinfo || ====================================================
|
// ==================================================== || fetchtenantinfo || ====================================================
|
||||||
const fetchtenantinfo = async () => {
|
const fetchtenantinfo = async () => {
|
||||||
@@ -1161,32 +889,11 @@ const Createorder1 = () => {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
// ============================================= || Google Maps Autocomplete(pick) || =============================================
|
// ============================================= || Address Autocomplete (pick) || =============================================
|
||||||
useEffect(() => {
|
const handlePickPlaceSelected = (place) => {
|
||||||
// Initialize Google Maps Autocomplete
|
|
||||||
if (inputValue2) {
|
|
||||||
const autocompleteInput = document.getElementById('addressAuto1');
|
|
||||||
const autocomplete = new window.google.maps.places.Autocomplete(autocompleteInput, {
|
|
||||||
// types: ['(cities)'], // You can adjust the types parameter based on your requirements
|
|
||||||
strictBounds: true,
|
|
||||||
bounds: new window.google.maps.Circle({
|
|
||||||
// center: new window.google.maps.LatLng(11.0050707, 76.9509083),
|
|
||||||
// radius: 100000
|
|
||||||
center: new window.google.maps.LatLng(appLocaLat, appLocaLng),
|
|
||||||
radius: appLocaRadius * 1000
|
|
||||||
}).getBounds()
|
|
||||||
});
|
|
||||||
let arr = [];
|
|
||||||
// Event listener for autocomplete place changed
|
|
||||||
autocomplete.addListener('place_changed', () => {
|
|
||||||
const place = autocomplete.getPlace();
|
|
||||||
setInputValue2(`${place.name}, ${place.formatted_address}`);
|
setInputValue2(`${place.name}, ${place.formatted_address}`);
|
||||||
console.log('new place', place); // Do something with the selected place
|
|
||||||
console.log(' pick (new place) lat lng', { lat: place.geometry.location.lat(), lng: place.geometry.location.lng() }); // Do something with the selected place
|
|
||||||
// to trigger getDistance
|
// to trigger getDistance
|
||||||
setStartPoint({ latitude: place.geometry.location.lat(), longitude: place.geometry.location.lng() });
|
setStartPoint({ latitude: place.geometry.location.lat(), longitude: place.geometry.location.lng() });
|
||||||
setValue(place);
|
|
||||||
setAddress(`${place.name} ${place.formatted_address}`);
|
|
||||||
setPickCust({ ...pickCust, address: `${place.name} ${place.formatted_address}` });
|
setPickCust({ ...pickCust, address: `${place.name} ${place.formatted_address}` });
|
||||||
const address = {
|
const address = {
|
||||||
address: `${place.name} ${place.formatted_address}`,
|
address: `${place.name} ${place.formatted_address}`,
|
||||||
@@ -1242,36 +949,12 @@ const Createorder1 = () => {
|
|||||||
latitude: place.geometry.location.lat(),
|
latitude: place.geometry.location.lat(),
|
||||||
longitude: place.geometry.location.lng()
|
longitude: place.geometry.location.lng()
|
||||||
});
|
});
|
||||||
console.log('Pick Address:', address);
|
};
|
||||||
});
|
// ============================================= || Address Autocomplete (Drop) || =============================================
|
||||||
}
|
|
||||||
}, [inputValue2]);
|
|
||||||
// ============================================= || Google Maps Autocomplete(Drop) || =============================================
|
|
||||||
|
|
||||||
useEffect(() => {
|
const handleDropPlaceSelected = (place) => {
|
||||||
if (inputValue3) {
|
|
||||||
// Initialize Google Maps Autocomplete
|
|
||||||
const autocompleteInput = document.getElementById('addressAuto2');
|
|
||||||
const autocomplete = new window.google.maps.places.Autocomplete(autocompleteInput, {
|
|
||||||
// types: ['(cities)'], // You can adjust the types parameter based on your requirements
|
|
||||||
strictBounds: true,
|
|
||||||
bounds: new window.google.maps.Circle({
|
|
||||||
// center: new window.google.maps.LatLng(11.0050707, 76.9509083),
|
|
||||||
center: new window.google.maps.LatLng(appLocaLat, appLocaLng),
|
|
||||||
radius: appLocaRadius * 1000 //km to m
|
|
||||||
// radius: 100000 //km to m
|
|
||||||
}).getBounds()
|
|
||||||
});
|
|
||||||
let arr = [];
|
|
||||||
// Event listener for autocomplete place changed
|
|
||||||
autocomplete.addListener('place_changed', () => {
|
|
||||||
const place = autocomplete.getPlace();
|
|
||||||
setInputValue3(`${place.name}, ${place.formatted_address}`);
|
setInputValue3(`${place.name}, ${place.formatted_address}`);
|
||||||
console.log('new place', place); // Do something with the selected place
|
|
||||||
console.log('drop (new place) lat lng', { lat: place.geometry.location.lat(), lng: place.geometry.location.lng() }); // Do something with the selected place
|
|
||||||
setEndPoint({ latitude: place.geometry.location.lat(), longitude: place.geometry.location.lng() });
|
setEndPoint({ latitude: place.geometry.location.lat(), longitude: place.geometry.location.lng() });
|
||||||
setValue1(place);
|
|
||||||
setAddress1(`${place.name} ${place.formatted_address}`);
|
|
||||||
setDropCust({ ...dropCust, address: `${place.name} ${place.formatted_address}` });
|
setDropCust({ ...dropCust, address: `${place.name} ${place.formatted_address}` });
|
||||||
const address = {
|
const address = {
|
||||||
address: `${place.name} ${place.formatted_address}`,
|
address: `${place.name} ${place.formatted_address}`,
|
||||||
@@ -1327,10 +1010,7 @@ const Createorder1 = () => {
|
|||||||
latitude: place.geometry.location.lat(),
|
latitude: place.geometry.location.lat(),
|
||||||
longitude: place.geometry.location.lng()
|
longitude: place.geometry.location.lng()
|
||||||
});
|
});
|
||||||
console.log('Drop Address:', address);
|
};
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [inputValue3]);
|
|
||||||
|
|
||||||
// ============================================= || gettenantlocations (branches) || =============================================
|
// ============================================= || gettenantlocations (branches) || =============================================
|
||||||
const gettenantlocations = async () => {
|
const gettenantlocations = async () => {
|
||||||
@@ -1609,15 +1289,18 @@ const Createorder1 = () => {
|
|||||||
<Stack spacing={1.25} sx={{ mt: 0 }}>
|
<Stack spacing={1.25} sx={{ mt: 0 }}>
|
||||||
{addId1 == 0 ? (
|
{addId1 == 0 ? (
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<AddressAutocomplete
|
||||||
variant="outlined"
|
|
||||||
label="Address"
|
label="Address"
|
||||||
disabled={!isLocation}
|
disabled={!isLocation}
|
||||||
id="addressAuto1"
|
id="addressAuto1"
|
||||||
fullWidth
|
fullWidth
|
||||||
value={inputValue2}
|
value={inputValue2}
|
||||||
onChange={(e) => setInputValue2(e.target.value)}
|
onChange={setInputValue2}
|
||||||
InputProps={{
|
onPlaceSelected={handlePickPlaceSelected}
|
||||||
|
bias={{ lat: appLocaLat, lng: appLocaLng }}
|
||||||
|
TextFieldProps={{
|
||||||
|
variant: 'outlined',
|
||||||
|
InputProps: {
|
||||||
endAdornment: (
|
endAdornment: (
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -1638,6 +1321,7 @@ const Createorder1 = () => {
|
|||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -2021,14 +1705,17 @@ const Createorder1 = () => {
|
|||||||
<Stack spacing={1.25} sx={{ mt: 0 }}>
|
<Stack spacing={1.25} sx={{ mt: 0 }}>
|
||||||
{addId2 == 0 ? (
|
{addId2 == 0 ? (
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<AddressAutocomplete
|
||||||
id="addressAuto2"
|
id="addressAuto2"
|
||||||
disabled={!isLocation}
|
disabled={!isLocation}
|
||||||
label="Address"
|
label="Address"
|
||||||
fullWidth
|
fullWidth
|
||||||
value={inputValue3}
|
value={inputValue3}
|
||||||
onChange={(e) => setInputValue3(e.target.value)}
|
onChange={setInputValue3}
|
||||||
InputProps={{
|
onPlaceSelected={handleDropPlaceSelected}
|
||||||
|
bias={{ lat: appLocaLat, lng: appLocaLng }}
|
||||||
|
TextFieldProps={{
|
||||||
|
InputProps: {
|
||||||
endAdornment: (
|
endAdornment: (
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -2049,6 +1736,7 @@ const Createorder1 = () => {
|
|||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,157 +0,0 @@
|
|||||||
/* eslint-disable no-unused-vars */
|
|
||||||
import * as React from 'react';
|
|
||||||
import Box from '@mui/material/Box';
|
|
||||||
import TextField from '@mui/material/TextField';
|
|
||||||
import Autocomplete from '@mui/material/Autocomplete';
|
|
||||||
import LocationOnIcon from '@mui/icons-material/LocationOn';
|
|
||||||
import Grid from '@mui/material/Grid';
|
|
||||||
import Typography from '@mui/material/Typography';
|
|
||||||
import parse from 'autosuggest-highlight/parse';
|
|
||||||
import { debounce } from '@mui/material/utils';
|
|
||||||
|
|
||||||
// This key was created specifically for the demo in mui.com.
|
|
||||||
// You need to create a new one for your application.
|
|
||||||
const GOOGLE_MAPS_API_KEY ='AIzaSyCF4KatYCI3vqz1_H3kiHeyS3yCMfYToh8';
|
|
||||||
|
|
||||||
function loadScript(src, position, id) {
|
|
||||||
if (!position) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const script = document.createElement('script');
|
|
||||||
script.setAttribute('async', '');
|
|
||||||
script.setAttribute('id', id);
|
|
||||||
script.src = src;
|
|
||||||
position.appendChild(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
const autocompleteService = { current: null };
|
|
||||||
|
|
||||||
export default function GoogleMaps() {
|
|
||||||
const [value, setValue] = React.useState(null);
|
|
||||||
const [inputValue, setInputValue] = React.useState('');
|
|
||||||
const [options, setOptions] = React.useState([]);
|
|
||||||
const loaded = React.useRef(false);
|
|
||||||
|
|
||||||
if (typeof window !== 'undefined' && !loaded.current) {
|
|
||||||
if (!document.querySelector('#google-maps')) {
|
|
||||||
loadScript(
|
|
||||||
`https://maps.googleapis.com/maps/api/js?key=${GOOGLE_MAPS_API_KEY}&libraries=places`,
|
|
||||||
document.querySelector('head'),
|
|
||||||
'google-maps',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
loaded.current = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fetch = React.useMemo(
|
|
||||||
() =>
|
|
||||||
debounce((request, callback) => {
|
|
||||||
autocompleteService.current.getPlacePredictions(request, callback);
|
|
||||||
}, 400),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
let active = true;
|
|
||||||
|
|
||||||
if (!autocompleteService.current && window.google) {
|
|
||||||
autocompleteService.current =
|
|
||||||
new window.google.maps.places.AutocompleteService();
|
|
||||||
}
|
|
||||||
if (!autocompleteService.current) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inputValue === '') {
|
|
||||||
setOptions(value ? [value] : []);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch({ input: inputValue }, (results) => {
|
|
||||||
if (active) {
|
|
||||||
let newOptions = [];
|
|
||||||
|
|
||||||
if (value) {
|
|
||||||
newOptions = [value];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (results) {
|
|
||||||
newOptions = [...newOptions, ...results];
|
|
||||||
}
|
|
||||||
|
|
||||||
setOptions(newOptions);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
active = false;
|
|
||||||
};
|
|
||||||
}, [value, inputValue, fetch]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Autocomplete
|
|
||||||
id="google-map-demo"
|
|
||||||
// sx={{ width: 300 }}
|
|
||||||
fullWidth
|
|
||||||
getOptionLabel={(option) =>
|
|
||||||
typeof option === 'string' ? option : option.description
|
|
||||||
}
|
|
||||||
filterOptions={(x) => x}
|
|
||||||
options={options}
|
|
||||||
autoComplete
|
|
||||||
includeInputInList
|
|
||||||
filterSelectedOptions
|
|
||||||
value={value}
|
|
||||||
noOptionsText="No locations"
|
|
||||||
onChange={(event, newValue) => {
|
|
||||||
setOptions(newValue ? [newValue, ...options] : options);
|
|
||||||
setValue(newValue);
|
|
||||||
}}
|
|
||||||
onInputChange={(event, newInputValue) => {
|
|
||||||
setInputValue(newInputValue);
|
|
||||||
}}
|
|
||||||
renderInput={(params) => (
|
|
||||||
<TextField {...params}
|
|
||||||
// label="Add a location"
|
|
||||||
placeholder='Address'
|
|
||||||
|
|
||||||
fullWidth />
|
|
||||||
)}
|
|
||||||
renderOption={(props, option) => {
|
|
||||||
const matches =
|
|
||||||
option.structured_formatting.main_text_matched_substrings || [];
|
|
||||||
|
|
||||||
const parts = parse(
|
|
||||||
option.structured_formatting.main_text,
|
|
||||||
matches.map((match) => [match.offset, match.offset + match.length]),
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<li {...props}>
|
|
||||||
<Grid container alignItems="center">
|
|
||||||
<Grid item sx={{ display: 'flex', width: 44 }}>
|
|
||||||
<LocationOnIcon sx={{ color: 'text.secondary' }} />
|
|
||||||
</Grid>
|
|
||||||
<Grid item sx={{ width: 'calc(100% - 44px)', wordWrap: 'break-word' }}>
|
|
||||||
{parts.map((part, index) => (
|
|
||||||
<Box
|
|
||||||
key={index}
|
|
||||||
component="span"
|
|
||||||
sx={{ fontWeight: part.highlight ? 'bold' : 'regular' }}
|
|
||||||
>
|
|
||||||
{part.text}
|
|
||||||
</Box>
|
|
||||||
))}
|
|
||||||
<Typography variant="body2" color="text.secondary">
|
|
||||||
{option.structured_formatting.secondary_text}
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,846 +0,0 @@
|
|||||||
/* eslint-disable no-unused-vars */
|
|
||||||
import React from 'react';
|
|
||||||
import Loader from 'components/Loader';
|
|
||||||
import { useEffect, useState, Fragment } from 'react';
|
|
||||||
import { useTheme } from '@mui/material/styles';
|
|
||||||
import MainCard from 'components/MainCard';
|
|
||||||
import axios from 'axios';
|
|
||||||
import ClearIcon from '@mui/icons-material/Clear';
|
|
||||||
import { SearchOutlined, CloseOutlined } from '@ant-design/icons';
|
|
||||||
import { Empty } from 'antd';
|
|
||||||
import MyLocationIcon from '@mui/icons-material/MyLocation';
|
|
||||||
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
|
|
||||||
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
|
|
||||||
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
|
||||||
import dayjs from 'dayjs';
|
|
||||||
var utc = require('dayjs/plugin/utc');
|
|
||||||
dayjs.extend(utc);
|
|
||||||
import { enqueueSnackbar } from 'notistack';
|
|
||||||
import { useNavigate } from 'react-router';
|
|
||||||
import { calculateDrivingDistance, calculateTotalCharge } from '../../../utils/distance';
|
|
||||||
import { GoogleMap, LoadScript, Marker } from '@react-google-maps/api';
|
|
||||||
|
|
||||||
import {
|
|
||||||
FormControl,
|
|
||||||
InputAdornment,
|
|
||||||
Grid,
|
|
||||||
Typography,
|
|
||||||
Stack,
|
|
||||||
Button,
|
|
||||||
TextField,
|
|
||||||
Autocomplete,
|
|
||||||
Divider,
|
|
||||||
Dialog,
|
|
||||||
DialogTitle,
|
|
||||||
DialogContent,
|
|
||||||
Checkbox,
|
|
||||||
DialogActions,
|
|
||||||
CircularProgress,
|
|
||||||
IconButton,
|
|
||||||
OutlinedInput,
|
|
||||||
FormGroup,
|
|
||||||
FormControlLabel,
|
|
||||||
Table,
|
|
||||||
TableContainer,
|
|
||||||
TableCell,
|
|
||||||
TableBody,
|
|
||||||
TableRow,
|
|
||||||
Paper,
|
|
||||||
TableHead,
|
|
||||||
Box
|
|
||||||
} from '@mui/material';
|
|
||||||
import CircularLoader from 'components/nearle_components/CircularLoader';
|
|
||||||
// import RidersPinPointOSM from './RidersPinPointOSM';
|
|
||||||
import RidersPinPoint from './ridersPinPoint';
|
|
||||||
|
|
||||||
const MultipleOrders = () => {
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const theme = useTheme();
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [btnLoading, setBtnLoading] = useState(false);
|
|
||||||
const [appId, setAppId] = useState(0);
|
|
||||||
|
|
||||||
const [tenantLocations, setTenantlocations] = useState([]);
|
|
||||||
const userid = localStorage.getItem('userid');
|
|
||||||
const tenId = localStorage.getItem('tenantid');
|
|
||||||
const [tid, setTid] = useState(0);
|
|
||||||
const [isLocation, setIsLocation] = useState(false);
|
|
||||||
const [basePrice, setBasePrice] = useState(0);
|
|
||||||
const [pricePerKm, setPricePerKm] = useState(0);
|
|
||||||
const [minKm, setMinKm] = useState(0);
|
|
||||||
const [pickCust, setPickCust] = useState(null);
|
|
||||||
const [dropCust, setDropCust] = useState([]);
|
|
||||||
const [isCustomerOpen, setIsCustomerOpen] = useState(false);
|
|
||||||
const [searchCustList, setSearchCustList] = useState('');
|
|
||||||
const [customerlist, setCustomerlist] = useState([]);
|
|
||||||
const [startdate, setStartdate] = useState(dayjs().format('MM-DD-YYYY'));
|
|
||||||
const [timeslotarr, setTimeslotarr] = useState([]);
|
|
||||||
const [starttime, setStatrttime] = useState();
|
|
||||||
const [endtime, setEndtime] = useState();
|
|
||||||
const [alertmessage, setAlertmessage] = useState('');
|
|
||||||
const [otherinstructions, setOtherinstructions] = useState('');
|
|
||||||
const [admintoken, setAdmintoken] = useState();
|
|
||||||
const [totaldist, settotaldist] = useState(0);
|
|
||||||
const [totalAmt, settotalAmt] = useState(0);
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
|
||||||
const [showMap, setShowMap] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
dropCust && console.log('dropCust', dropCust);
|
|
||||||
}, [dropCust]);
|
|
||||||
|
|
||||||
// =============================================== || opentoast || ===============================================
|
|
||||||
const opentoast = (message, variant, time) => {
|
|
||||||
enqueueSnackbar(message, {
|
|
||||||
variant: variant,
|
|
||||||
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
|
||||||
autoHideDuration: time ? time : 1500
|
|
||||||
});
|
|
||||||
console.log(alertmessage);
|
|
||||||
};
|
|
||||||
// ==============================|| fetchAppLocations ||============================== //
|
|
||||||
const fetchAppLocations = async () => {
|
|
||||||
try {
|
|
||||||
const locationRes = await axios.get(`${process.env.REACT_APP_URL}/partners/getlocations/?userid=${userid}`);
|
|
||||||
console.log('fetchAppLocations', locationRes.data.details);
|
|
||||||
} catch (err) {
|
|
||||||
console.log('locationRes', err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
useEffect(() => {
|
|
||||||
fetchAppLocations();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// ============================================= || fetchTenantPricing || =============================================
|
|
||||||
|
|
||||||
const fetchTenantPricing = async (id) => {
|
|
||||||
try {
|
|
||||||
const pricingResponse = await axios.get(`${process.env.REACT_APP_URL}/tenants/gettenantpricing/?tenantid=${tenId}`);
|
|
||||||
console.log('pricingResponse', pricingResponse.data.details);
|
|
||||||
setBasePrice(pricingResponse.data.details.baseprice);
|
|
||||||
setPricePerKm(pricingResponse.data.details.priceperkm);
|
|
||||||
setMinKm(pricingResponse.data.details.minkm);
|
|
||||||
} catch (error) {
|
|
||||||
console.log('fetchTenantPricing error', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
useEffect(() => {
|
|
||||||
fetchTenantPricing();
|
|
||||||
}, []);
|
|
||||||
// ============================================= || gettenantlocations (branches) || =============================================
|
|
||||||
const gettenantlocations = async (id) => {
|
|
||||||
try {
|
|
||||||
const res = await axios.get(`${process.env.REACT_APP_URL}/tenants/gettenantlocations/?tenantid=${id}`);
|
|
||||||
console.log('gettenantlocations', res.data.details);
|
|
||||||
if (res.data.details.length == 1) {
|
|
||||||
setIsLocation(true);
|
|
||||||
setTenantlocations(res.data.details);
|
|
||||||
setPickCust(res.data.details[0]);
|
|
||||||
} else {
|
|
||||||
setTenantlocations(res.data.details);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.log('gettenantlocations', err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
useEffect(() => {
|
|
||||||
gettenantlocations(tenId);
|
|
||||||
}, []);
|
|
||||||
// ========================================================= || clientdetails || =========================================================
|
|
||||||
const clientdetails = async () => {
|
|
||||||
try {
|
|
||||||
let url =
|
|
||||||
searchCustList == ''
|
|
||||||
? `${process.env.REACT_APP_URL}/customers/gettenantcustomers/?tenantid=${tenId}&pageno=1&pagesize=10`
|
|
||||||
: `${process.env.REACT_APP_URL}/customers/search/?tenantid=${tenId}&keyword=${searchCustList}`;
|
|
||||||
await axios
|
|
||||||
.get(url)
|
|
||||||
.then((res) => {
|
|
||||||
if (res.data.status) {
|
|
||||||
console.log('clientdetails', res.data.details);
|
|
||||||
|
|
||||||
setCustomerlist(res.data.details);
|
|
||||||
let arr = [];
|
|
||||||
res.data.details.map((val) => {
|
|
||||||
arr.push({
|
|
||||||
label: `${val.firstname} | ${val.contactno}`,
|
|
||||||
...val
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err);
|
|
||||||
opentoast('server error', 'warning');
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
useEffect(() => {
|
|
||||||
if (tenId) {
|
|
||||||
clientdetails();
|
|
||||||
}
|
|
||||||
}, [searchCustList.length > 3, searchCustList == '', tenId]);
|
|
||||||
|
|
||||||
// ========================================================= || calculateTotal(dist , charge) || =========================================================
|
|
||||||
const calculateTotal = () => {
|
|
||||||
let a1 = 0;
|
|
||||||
let a2 = 0;
|
|
||||||
dropCust?.map((customer) => {
|
|
||||||
a1 += customer.distance;
|
|
||||||
a2 += customer.totalcharge;
|
|
||||||
});
|
|
||||||
settotaldist(a1);
|
|
||||||
settotalAmt(a2);
|
|
||||||
};
|
|
||||||
useEffect(() => {
|
|
||||||
dropCust && calculateTotal();
|
|
||||||
}, [dropCust]);
|
|
||||||
|
|
||||||
// ========================================================= || handleCheckboxChange || =========================================================
|
|
||||||
const handleCheckboxChange = async (event, customer) => {
|
|
||||||
setIsLoading(true);
|
|
||||||
console.log('event', event.target.checked);
|
|
||||||
console.log('customer', customer);
|
|
||||||
if (event.target.checked) {
|
|
||||||
// If the checkbox is checked, calculate the distance and add the customer
|
|
||||||
try {
|
|
||||||
const obj = await calculateDistance(customer);
|
|
||||||
console.log('return of calculateDistance', obj);
|
|
||||||
|
|
||||||
const { roundedDistance, totalcharge } = obj;
|
|
||||||
// Create a new customer object with the distance property
|
|
||||||
const updatedCustomer = {
|
|
||||||
...customer,
|
|
||||||
distance: roundedDistance,
|
|
||||||
totalcharge: totalcharge
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add the updated customer object to dropCust
|
|
||||||
setDropCust((prevDropCust) => [...prevDropCust, updatedCustomer]);
|
|
||||||
|
|
||||||
// Log the rounded distance
|
|
||||||
console.log(`Rounded Distance: ${roundedDistance} km`);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to calculate distance:', error);
|
|
||||||
}
|
|
||||||
setIsLoading(false);
|
|
||||||
} else {
|
|
||||||
// If the checkbox is unchecked, remove the customer from dropCust
|
|
||||||
setDropCust((prevDropCust) => {
|
|
||||||
return prevDropCust.filter((cust) => cust.customerid !== customer.customerid);
|
|
||||||
});
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// ========================================================= || calculateDistance || =========================================================
|
|
||||||
const calculateDistance = async (customer) => {
|
|
||||||
console.log('Distance calculation starts');
|
|
||||||
try {
|
|
||||||
const roundedDistance = await calculateDrivingDistance(pickCust, customer);
|
|
||||||
const totalcharge = calculateTotalCharge(roundedDistance, basePrice, pricePerKm, minKm);
|
|
||||||
return { roundedDistance, totalcharge };
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error calculating distance:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// ==================================================== || fetchTiming || ====================================================
|
|
||||||
const fetchTiming = async () => {
|
|
||||||
setLoading(true);
|
|
||||||
await axios
|
|
||||||
.get(`${process.env.REACT_APP_URL}/utils/getapplocations/?applocationid=${appId}`)
|
|
||||||
.then((res) => {
|
|
||||||
console.log('fetchTiming', res);
|
|
||||||
const { opentime, closetime, latitude, longitude, radius } = res.data.details[0];
|
|
||||||
if (res.data.status) {
|
|
||||||
setStatrttime(`${dayjs().format('MM-DD-YYYY')} ${opentime}`);
|
|
||||||
setEndtime(`${dayjs().format('MM-DD-YYYY')} ${closetime}`);
|
|
||||||
console.log('starttime', `${dayjs().format('MM-DD-YYYY')} ${opentime}`);
|
|
||||||
console.log('endtime', `${dayjs().format('MM-DD-YYYY')} ${closetime} `);
|
|
||||||
let arr = [];
|
|
||||||
for (
|
|
||||||
let i = `${dayjs().format('MM-DD-YYYY')} ${opentime}`, j = 0;
|
|
||||||
dayjs(`${dayjs().format('MM-DD-YYYY')} ${closetime} `).diff(i, 'm') >= 0;
|
|
||||||
j++, i = dayjs(i).add(30, 'm')
|
|
||||||
) {
|
|
||||||
arr.push(i);
|
|
||||||
}
|
|
||||||
console.log('setTimeslotarr', arr);
|
|
||||||
setTimeslotarr(arr);
|
|
||||||
}
|
|
||||||
setLoading(false);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err);
|
|
||||||
setLoading(false);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
useEffect(() => {
|
|
||||||
if (appId) {
|
|
||||||
fetchTiming();
|
|
||||||
}
|
|
||||||
}, [starttime, endtime, appId]);
|
|
||||||
|
|
||||||
const fetchAppAdminTokens = async () => {
|
|
||||||
setLoading(true);
|
|
||||||
await axios
|
|
||||||
.get(`${process.env.REACT_APP_URL}/utils/getapplocationconfig/?applocationid=${appId}`)
|
|
||||||
.then((res) => {
|
|
||||||
const userfcmtokemArray = res.data.details.applocationadmins.map((admin) => admin.userfcmtokem); // fcm => firebase cloud messaging
|
|
||||||
console.log('fetchAppAdminTokens', res);
|
|
||||||
console.log('userfcmtokemArray', userfcmtokemArray);
|
|
||||||
if (res.data.status) {
|
|
||||||
setAdmintoken(userfcmtokemArray);
|
|
||||||
}
|
|
||||||
setLoading(false);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err);
|
|
||||||
setLoading(false);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (starttime && endtime) {
|
|
||||||
fetchAppAdminTokens();
|
|
||||||
}
|
|
||||||
}, [starttime, endtime]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
console.log('pickCust', pickCust);
|
|
||||||
}, [pickCust]);
|
|
||||||
|
|
||||||
// ==================================================== || fetchtenantinfo || ====================================================
|
|
||||||
const fetchtenantinfo = async () => {
|
|
||||||
setLoading(true);
|
|
||||||
console.log('tid', tid);
|
|
||||||
|
|
||||||
await axios
|
|
||||||
.get(`${process.env.REACT_APP_URL}/tenants/gettenantinfo/?tenantid=${tid}`)
|
|
||||||
.then((res) => {
|
|
||||||
console.log('fetchtenantinfo', res);
|
|
||||||
if (res.data.status) {
|
|
||||||
fetchAppAdminTokens();
|
|
||||||
}
|
|
||||||
setLoading(false);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err);
|
|
||||||
setLoading(false);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
useEffect(() => {
|
|
||||||
if (tid) {
|
|
||||||
fetchtenantinfo();
|
|
||||||
}
|
|
||||||
}, [tid]);
|
|
||||||
// ================================================== || sendnotifications || ==================================================
|
|
||||||
const sendnotifications = async () => {
|
|
||||||
setLoading(true);
|
|
||||||
await axios
|
|
||||||
.post(`${process.env.REACT_APP_URL}/utils/sendnotifications`, {
|
|
||||||
priority: 'high',
|
|
||||||
registration_ids: admintoken,
|
|
||||||
data: {
|
|
||||||
accessid: process.env.REACT_APP_RIDER_ACCESS_ID
|
|
||||||
},
|
|
||||||
notification: {
|
|
||||||
title: 'Nearle Merchant',
|
|
||||||
body: 'An Order has been placed successfully,kindly process the same',
|
|
||||||
sound: 'ring'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
if (res.data.message == 'Success') {
|
|
||||||
enqueueSnackbar('Notification sent Successfully', {
|
|
||||||
variant: 'success',
|
|
||||||
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
|
||||||
autoHideDuration: 1000
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setLoading(false);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err);
|
|
||||||
enqueueSnackbar(err.message, {
|
|
||||||
variant: 'error',
|
|
||||||
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
|
||||||
autoHideDuration: 1000
|
|
||||||
});
|
|
||||||
setLoading(false);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// =============================================== || creategrouporders || ===============================================
|
|
||||||
const creategrouporders = async () => {
|
|
||||||
const arr = dropCust?.map((customer) => ({
|
|
||||||
applocationid: pickCust.applocationid,
|
|
||||||
cancellled: '',
|
|
||||||
// categoryid: +tenant.categoryid,
|
|
||||||
configid: 9,
|
|
||||||
customerid: customer.customerid,
|
|
||||||
deliveryaddress: customer.address || '',
|
|
||||||
deliverycharge: +customer.totalcharge || 0,
|
|
||||||
deliverycity: customer.city || '',
|
|
||||||
deliverycontactno: customer.contactno || '',
|
|
||||||
deliverycustomer: customer.firstname || '',
|
|
||||||
deliveryid: +customer.customerid,
|
|
||||||
deliverylandmark: customer.landmark || '',
|
|
||||||
deliverylat: customer.latitude,
|
|
||||||
deliverylocation: customer.suburb || '',
|
|
||||||
deliverylocationid: customer.deliverylocationid || 0,
|
|
||||||
deliverylong: customer.longitude,
|
|
||||||
// deliverytime: `${dayjs(startdate).format('YYYY-MM-DD HH:mm:ss')} `,
|
|
||||||
deliverytime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
||||||
deliverytype: 'B',
|
|
||||||
delivered: '',
|
|
||||||
itemcount: 1,
|
|
||||||
kms: customer.distance.toString() || 0,
|
|
||||||
locationid: +pickCust.locationid,
|
|
||||||
moduleid: +pickCust.moduleid,
|
|
||||||
orderamount: +customer.totalcharge || 0,
|
|
||||||
ordercharges: 0.0,
|
|
||||||
orderdate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
||||||
orderheaderid: 0,
|
|
||||||
orderid: '', //
|
|
||||||
ordernotes: otherinstructions,
|
|
||||||
orderstatus: 'created',
|
|
||||||
ordervalue: +customer.totalcharge || 0,
|
|
||||||
partnerid: pickCust.partnerid,
|
|
||||||
partneruserid: +userid,
|
|
||||||
paymentstatus: 1,
|
|
||||||
paymenttype: 42,
|
|
||||||
pending: '',
|
|
||||||
pickupaddress: pickCust.address || '',
|
|
||||||
pickupcity: pickCust.locationcity || '',
|
|
||||||
pickupcontactno: pickCust.contactno || '',
|
|
||||||
pickupcustomer: pickCust.locationname || '',
|
|
||||||
pickuplandmark: pickCust.landmark || '',
|
|
||||||
pickuplat: pickCust.latitude,
|
|
||||||
pickuplocation: pickCust.suburb || '',
|
|
||||||
pickuplocationid: pickCust.locationid || 0,
|
|
||||||
pickuplong: pickCust.longitude,
|
|
||||||
processing: '',
|
|
||||||
ready: '',
|
|
||||||
remarks: '',
|
|
||||||
taxamount: 0.0,
|
|
||||||
tenantid: pickCust.tenantid,
|
|
||||||
tenantuserid: 0
|
|
||||||
}));
|
|
||||||
console.log('arr', arr);
|
|
||||||
|
|
||||||
if (!tenId) {
|
|
||||||
opentoast('Choose Client ', 'warning');
|
|
||||||
} else {
|
|
||||||
setLoading(true);
|
|
||||||
|
|
||||||
await axios
|
|
||||||
.post(`${process.env.REACT_APP_URL}/orders/createorders`, arr)
|
|
||||||
.then((res) => {
|
|
||||||
if (res.data.status) {
|
|
||||||
enqueueSnackbar('Order Created Successfully', {
|
|
||||||
variant: 'success',
|
|
||||||
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
|
||||||
autoHideDuration: 1000
|
|
||||||
});
|
|
||||||
if (admintoken) {
|
|
||||||
// notifyadmin(admintoken);
|
|
||||||
sendnotifications();
|
|
||||||
}
|
|
||||||
navigate('/nearle/orders');
|
|
||||||
} else {
|
|
||||||
opentoast(res.data.message, 'warning');
|
|
||||||
}
|
|
||||||
setLoading(false);
|
|
||||||
console.log(res);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err);
|
|
||||||
// opentoast(err.data.message, 'warning');
|
|
||||||
setLoading(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
console.log(arr);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{loading && <Loader />}
|
|
||||||
{/* <RidersPinPointOSM /> */}
|
|
||||||
<Grid container sx={{ mb: 2 }}>
|
|
||||||
<Grid item xs={12} sm={3} md={6}>
|
|
||||||
<Stack>
|
|
||||||
<Typography variant="h3" whiteSpace="nowrap">
|
|
||||||
Multiple Orders
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} sm={9} md={6}>
|
|
||||||
<Stack
|
|
||||||
sx={{}}
|
|
||||||
width={'100%'}
|
|
||||||
direction="row"
|
|
||||||
alignItems="center"
|
|
||||||
spacing={2}
|
|
||||||
justifyContent={'flex-end'}
|
|
||||||
flexWrap={{ xs: 'wrap', custom550: 'nowrap' }}
|
|
||||||
gap={2}
|
|
||||||
>
|
|
||||||
{/* Business Location */}
|
|
||||||
<Stack sx={{ width: '100%' }}>
|
|
||||||
{tenantLocations?.length === 1 ? (
|
|
||||||
<TextField
|
|
||||||
label="Business Location"
|
|
||||||
fullWidth
|
|
||||||
focused
|
|
||||||
value={tenantLocations[0]?.locationname}
|
|
||||||
InputProps={{
|
|
||||||
style: { color: theme.palette.primary.main },
|
|
||||||
startAdornment: (
|
|
||||||
<InputAdornment position="start">
|
|
||||||
<MyLocationIcon color="primary" />
|
|
||||||
</InputAdornment>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<Autocomplete
|
|
||||||
fullWidth
|
|
||||||
options={tenantLocations || []}
|
|
||||||
getOptionLabel={(option) => `${option.locationname} (${option.suburb})`}
|
|
||||||
onChange={(event, value, reason) => {
|
|
||||||
if (value) {
|
|
||||||
setTid(value.tenantid);
|
|
||||||
setIsLocation(true);
|
|
||||||
setPickCust(value);
|
|
||||||
}
|
|
||||||
if (reason === 'clear') setIsLocation(false);
|
|
||||||
}}
|
|
||||||
renderInput={(params) => <TextField {...params} label="Select Business Location" color="primary" fullWidth />}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
{/* Date Picker */}
|
|
||||||
<Stack sx={{ display: 'flex', justifyContent: 'flex-end' }}>
|
|
||||||
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
|
||||||
<DatePicker
|
|
||||||
format="DD-MM-YYYY"
|
|
||||||
disablePast
|
|
||||||
value={dayjs(startdate)}
|
|
||||||
sx={{ width: 150 }}
|
|
||||||
onChange={(e) => {
|
|
||||||
let diff = dayjs().diff(dayjs(dayjs(e).format('YYYY-MM-DD')), 'd');
|
|
||||||
|
|
||||||
if (diff <= 0) {
|
|
||||||
setStartdate(e);
|
|
||||||
|
|
||||||
let arr = [];
|
|
||||||
timeslotarr.forEach((val) => {
|
|
||||||
if (dayjs().diff(dayjs(`${dayjs(e).format('MM-DD-YYYY')} ${dayjs(val).format('HH:mm:ss')}`), 'm') <= 0) {
|
|
||||||
arr.push(val);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (arr[0]) {
|
|
||||||
setOrderarr([
|
|
||||||
{
|
|
||||||
sno: 1,
|
|
||||||
address: '',
|
|
||||||
customerid: '',
|
|
||||||
deliverytime: dayjs(arr[0]),
|
|
||||||
deliverylocationid: '',
|
|
||||||
clientname: '',
|
|
||||||
contactno: '',
|
|
||||||
latitude: '',
|
|
||||||
longitude: ''
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
setOrderarr([]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
opentoast('choose Upcoming Date', 'warning');
|
|
||||||
setStartdate(NaN);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</LocalizationProvider>
|
|
||||||
</Stack>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
{/* ===================================================== || Pickup || ===================================================== */}
|
|
||||||
{pickCust && (
|
|
||||||
<TableContainer component={Paper} sx={{ mb: 2 }}>
|
|
||||||
<Table sx={{ minWidth: 650 }} aria-label="simple table">
|
|
||||||
<TableHead>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell>Pickup Location</TableCell>
|
|
||||||
<TableCell>Address</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell>{pickCust?.locationname}</TableCell>
|
|
||||||
<TableCell>{pickCust?.address}</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</TableContainer>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* ===================================================== || Drop || ===================================================== */}
|
|
||||||
|
|
||||||
<MainCard
|
|
||||||
sx={{ height: '100%' }}
|
|
||||||
title={`Drop (${dropCust?.length || 0})`}
|
|
||||||
secondary={
|
|
||||||
<Button
|
|
||||||
variant="outlined"
|
|
||||||
size="small"
|
|
||||||
sx={{
|
|
||||||
'&:hover': {
|
|
||||||
bgcolor: theme.palette.primary.main,
|
|
||||||
color: 'white'
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
if (!isLocation) {
|
|
||||||
opentoast('Select Business Location', 'warning');
|
|
||||||
} else {
|
|
||||||
setIsCustomerOpen(true);
|
|
||||||
setSearchCustList('');
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Select Customers
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<TableContainer component={Paper}>
|
|
||||||
<Table sx={{ minWidth: 650 }} aria-label="simple table">
|
|
||||||
<TableHead>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell>S.No</TableCell>
|
|
||||||
<TableCell>Customer</TableCell>
|
|
||||||
<TableCell>Address</TableCell>
|
|
||||||
<TableCell>Kms</TableCell>
|
|
||||||
<TableCell align="right">Charge</TableCell>
|
|
||||||
<TableCell>Action</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>
|
|
||||||
{!dropCust && (
|
|
||||||
<TableRow>
|
|
||||||
<TableCell colSpan={6}>
|
|
||||||
<Empty description={' Drop Customers Not Selected'} />
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
)}
|
|
||||||
{dropCust?.map((customer, index) => (
|
|
||||||
<TableRow key={index}>
|
|
||||||
<TableCell>{index + 1}</TableCell>
|
|
||||||
<TableCell>{customer.firstname}</TableCell>
|
|
||||||
<TableCell>{customer.address}</TableCell>
|
|
||||||
<TableCell>{customer.distance}</TableCell>
|
|
||||||
<TableCell align="right">{`₹${customer.totalcharge}.00`}</TableCell>
|
|
||||||
<TableCell align="center">
|
|
||||||
{
|
|
||||||
<CloseOutlined
|
|
||||||
style={{ cursor: 'pointer', color: 'red' }}
|
|
||||||
onClick={(event) => handleCheckboxChange(event, customer)}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
{dropCust?.length != 0 && (
|
|
||||||
<TableRow>
|
|
||||||
<TableCell>
|
|
||||||
<Typography variant="h5">Total</Typography>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell></TableCell>
|
|
||||||
<TableCell></TableCell>
|
|
||||||
<TableCell>
|
|
||||||
<Typography variant="h5">{`${totaldist} `}</Typography>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell align="right">
|
|
||||||
<Typography variant="h5"> {`₹${totalAmt}.00`}</Typography>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell></TableCell>
|
|
||||||
</TableRow>
|
|
||||||
)}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</TableContainer>
|
|
||||||
</MainCard>
|
|
||||||
|
|
||||||
{/* ================================================= || Riders Map || ================================================= */}
|
|
||||||
|
|
||||||
{/* {showMap && dropCust.length >= 1 && <RidersPinPoint pickCust={pickCust} dropCust={dropCust} />} */}
|
|
||||||
|
|
||||||
{/* ================================================= || Notes || ================================================= */}
|
|
||||||
{dropCust && (
|
|
||||||
<MainCard sx={{ mt: 2 }} title={'Notes'}>
|
|
||||||
<Grid container>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<TextField
|
|
||||||
focused
|
|
||||||
id="outlined-multiline-static"
|
|
||||||
sx={{ width: '100%', height: '100%', mb: 2 }}
|
|
||||||
multiline
|
|
||||||
rows={1}
|
|
||||||
placeholder="Notes"
|
|
||||||
value={otherinstructions}
|
|
||||||
onChange={(e) => setOtherinstructions(e.target.value)}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Stack direction="row" justifyContent={'end'} sx={{ mt: 2, width: '100%' }}>
|
|
||||||
<Button
|
|
||||||
disabled={dropCust?.length == 0}
|
|
||||||
size="medium"
|
|
||||||
variant="outlined"
|
|
||||||
onClick={() => {
|
|
||||||
setLoading(true);
|
|
||||||
setBtnLoading(true);
|
|
||||||
creategrouporders();
|
|
||||||
setTimeout(() => {
|
|
||||||
setLoading(false);
|
|
||||||
setBtnLoading(false);
|
|
||||||
}, 2000);
|
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
'&:hover': {
|
|
||||||
transform: 'scale(1.05)',
|
|
||||||
transition: 'transform 0.3s ease'
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{btnLoading ? <CircularProgress color="primary" size={20} thickness={10} /> : 'Create'}
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
</MainCard>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* ============================================= || saved address Dialog || ============================================= */}
|
|
||||||
<Dialog
|
|
||||||
open={isCustomerOpen}
|
|
||||||
onClose={() => {
|
|
||||||
setIsCustomerOpen(false);
|
|
||||||
}}
|
|
||||||
fullWidth
|
|
||||||
sx={{ minWidth: 'lg' }}
|
|
||||||
>
|
|
||||||
{isLoading && <CircularLoader />}
|
|
||||||
<DialogTitle sx={{ bgcolor: theme.palette.primary.main, color: 'white' }}>
|
|
||||||
<Stack>
|
|
||||||
<Typography variant="h4"> {`Select Drop Customers (${dropCust?.length || 0})`}</Typography>
|
|
||||||
<FormControl
|
|
||||||
sx={{
|
|
||||||
width: '100%',
|
|
||||||
mt: 1
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Stack spacing={2} sx={{ py: 0.2 }}>
|
|
||||||
<OutlinedInput
|
|
||||||
fullWidth
|
|
||||||
id="input-search-header"
|
|
||||||
placeholder="Search"
|
|
||||||
value={searchCustList}
|
|
||||||
onChange={(e) => setSearchCustList(e.target.value)}
|
|
||||||
sx={{
|
|
||||||
'& .MuiOutlinedInput-input': {
|
|
||||||
p: '10.5px 0px 12px'
|
|
||||||
},
|
|
||||||
bgcolor: 'white'
|
|
||||||
}}
|
|
||||||
startAdornment={
|
|
||||||
<InputAdornment position="start">
|
|
||||||
<SearchOutlined style={{ fontSize: 'small' }} />
|
|
||||||
</InputAdornment>
|
|
||||||
}
|
|
||||||
endAdornment={
|
|
||||||
<IconButton
|
|
||||||
sx={{ visibility: searchCustList ? 'visible' : 'hidden' }}
|
|
||||||
onClick={() => {
|
|
||||||
setSearchCustList('');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ClearIcon />
|
|
||||||
</IconButton>
|
|
||||||
}
|
|
||||||
autoComplete="off"
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
</FormControl>
|
|
||||||
</Stack>
|
|
||||||
</DialogTitle>
|
|
||||||
<Divider />
|
|
||||||
<DialogContent sx={{ p: 2.5 }}>
|
|
||||||
{customerlist.length == 0 ? (
|
|
||||||
<Stack spacing={2} direction={'row'} alignItems={'center'} justifyContent={'center'} sx={{ minHeight: 600, maxHeight: 600 }}>
|
|
||||||
<Empty />
|
|
||||||
</Stack>
|
|
||||||
) : (
|
|
||||||
<Stack spacing={2} sx={{ minHeight: 600, maxHeight: 600 }}>
|
|
||||||
{customerlist &&
|
|
||||||
customerlist.map((customer, index) => (
|
|
||||||
<FormGroup key={index}>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Checkbox
|
|
||||||
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)}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={
|
|
||||||
<div style={{ width: '100%' }}>
|
|
||||||
<Typography variant="subtitle1" sx={{ textAlign: 'left' }}>
|
|
||||||
{`${customer.firstname} (${customer.contactno})`}
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<Typography variant="body2" color="secondary" sx={{ textAlign: 'left' }}>
|
|
||||||
{customer.address}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
))}
|
|
||||||
</Stack>
|
|
||||||
)}
|
|
||||||
</DialogContent>
|
|
||||||
<Divider />
|
|
||||||
<DialogActions sx={{ p: 2.5 }}>
|
|
||||||
<Button
|
|
||||||
color={dropCust?.length !== 0 ? 'primary' : 'error'}
|
|
||||||
variant="outlined"
|
|
||||||
sx={{
|
|
||||||
'&:hover': {
|
|
||||||
bgcolor: dropCust?.length !== 0 ? theme.palette.primary.main : theme.palette.error.main,
|
|
||||||
color: 'white'
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
setIsCustomerOpen(false);
|
|
||||||
{
|
|
||||||
dropCust?.length !== 0 && setShowMap(true);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{dropCust?.length !== 0 ? 'Continue' : 'Close'}
|
|
||||||
</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MultipleOrders;
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,54 +0,0 @@
|
|||||||
/* eslint-disable no-unused-vars */
|
|
||||||
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 (
|
|
||||||
<LoadScriptNext googleMapsApiKey={process.env.REACT_APP_GOOGLE_MAPS_API_KEY}>
|
|
||||||
<GoogleMap mapContainerStyle={containerStyle} zoom={11} center={center}>
|
|
||||||
<Marker position={center} icon={{ url: 'http://maps.google.com/mapfiles/ms/icons/purple-dot.png' }} />
|
|
||||||
|
|
||||||
{sortedRiders?.map((r, index) => (
|
|
||||||
<Marker
|
|
||||||
key={index}
|
|
||||||
position={{ lat: Number(r.latitude), lng: Number(r.longitude) }}
|
|
||||||
label={{
|
|
||||||
text: (index + 1).toString(),
|
|
||||||
color: 'white',
|
|
||||||
fontSize: '14px',
|
|
||||||
fontWeight: 'bold'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</GoogleMap>
|
|
||||||
</LoadScriptNext>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,94 +0,0 @@
|
|||||||
import React, { useEffect, useRef } from 'react';
|
|
||||||
import { LoadScriptNext, GoogleMap } from '@react-google-maps/api';
|
|
||||||
import { DT } from 'themes/dt/tokens';
|
|
||||||
|
|
||||||
const containerStyle = {
|
|
||||||
width: '100%',
|
|
||||||
height: '90vh'
|
|
||||||
};
|
|
||||||
|
|
||||||
const MapWithRouteGoogle = ({ coordinates, additionalProps, setMapOpen }) => {
|
|
||||||
const mapRef = useRef(null);
|
|
||||||
|
|
||||||
/** Convert coordinates to numbers */
|
|
||||||
const numericCoordinates = coordinates
|
|
||||||
.map((c) => {
|
|
||||||
const lat = Number(c.lat);
|
|
||||||
const lng = Number(c.lng);
|
|
||||||
return isNaN(lat) || isNaN(lng) ? null : { lat, lng };
|
|
||||||
})
|
|
||||||
.filter(Boolean);
|
|
||||||
|
|
||||||
if (numericCoordinates.length < 2) {
|
|
||||||
return <div>No route data available</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const start = numericCoordinates[0];
|
|
||||||
const end = numericCoordinates[numericCoordinates.length - 1];
|
|
||||||
|
|
||||||
/** Map loaded callback */
|
|
||||||
const onMapLoad = (map) => {
|
|
||||||
// draw markers
|
|
||||||
new window.google.maps.Marker({
|
|
||||||
position: start,
|
|
||||||
map,
|
|
||||||
label: 'S',
|
|
||||||
title: `Start: ${additionalProps?.riderStart}`
|
|
||||||
});
|
|
||||||
|
|
||||||
new window.google.maps.Marker({
|
|
||||||
position: end,
|
|
||||||
map,
|
|
||||||
label: 'E',
|
|
||||||
title: `End: ${additionalProps?.riderEnd}`
|
|
||||||
});
|
|
||||||
|
|
||||||
// draw rider route (point-to-point)
|
|
||||||
const route = new window.google.maps.Polyline({
|
|
||||||
path: numericCoordinates,
|
|
||||||
geodesic: false,
|
|
||||||
strokeColor: DT.brand,
|
|
||||||
strokeOpacity: 1.0,
|
|
||||||
strokeWeight: 4
|
|
||||||
});
|
|
||||||
|
|
||||||
route.setMap(map);
|
|
||||||
|
|
||||||
// auto fit
|
|
||||||
const bounds = new window.google.maps.LatLngBounds();
|
|
||||||
numericCoordinates.forEach((p) => bounds.extend(p));
|
|
||||||
map.fitBounds(bounds);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<button
|
|
||||||
onClick={() => setMapOpen(false)}
|
|
||||||
style={{
|
|
||||||
position: 'absolute',
|
|
||||||
top: 10,
|
|
||||||
right: 10,
|
|
||||||
zIndex: 999,
|
|
||||||
padding: '6px 12px',
|
|
||||||
background: DT.brand,
|
|
||||||
color: 'white',
|
|
||||||
borderRadius: DT.radiusInner,
|
|
||||||
cursor: 'pointer',
|
|
||||||
border: 'none',
|
|
||||||
fontWeight: 600,
|
|
||||||
boxShadow: DT.shadowMd
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Close
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<LoadScriptNext googleMapsApiKey={process.env.REACT_APP_GOOGLE_MAPS_API_KEY}>
|
|
||||||
<GoogleMap mapContainerStyle={containerStyle} center={start} zoom={14} onLoad={onMapLoad}>
|
|
||||||
{/* Polyline and markers added via onLoad */}
|
|
||||||
</GoogleMap>
|
|
||||||
</LoadScriptNext>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MapWithRouteGoogle;
|
|
||||||
@@ -1,10 +1,46 @@
|
|||||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { GoogleMap, Polyline, Marker, InfoWindow, useJsApiLoader } from '@react-google-maps/api';
|
import { MapContainer, TileLayer, Polyline, Marker, Popup, useMap } from 'react-leaflet';
|
||||||
|
import L from 'leaflet';
|
||||||
|
import 'leaflet/dist/leaflet.css';
|
||||||
import { Box, IconButton, Stack, Typography, CircularProgress } from '@mui/material';
|
import { Box, IconButton, Stack, Typography, CircularProgress } from '@mui/material';
|
||||||
import { MdClose, MdRoute } from 'react-icons/md';
|
import { MdClose, MdRoute } from 'react-icons/md';
|
||||||
|
|
||||||
const containerStyle = { width: '100%', height: '100%' };
|
const containerStyle = { width: '100%', height: '100%' };
|
||||||
|
|
||||||
|
// Numbered step icon — brand red to match the planned-route polyline below.
|
||||||
|
// Drawn fresh per render as a data URL so the step number can be baked into
|
||||||
|
// the SVG without juggling external marker assets.
|
||||||
|
const stepIcon = (n, isFocused) => {
|
||||||
|
const size = isFocused ? 38 : 32;
|
||||||
|
const color = isFocused ? '#910E1D' : '#C01227';
|
||||||
|
const svg = encodeURIComponent(
|
||||||
|
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="${size}" height="${size}">` +
|
||||||
|
`<circle cx="16" cy="16" r="14" fill="${color}" stroke="white" stroke-width="3"/>` +
|
||||||
|
`<text x="16" y="21" text-anchor="middle" font-family="Arial,sans-serif" font-size="14" font-weight="700" fill="white">${n}</text>` +
|
||||||
|
`</svg>`
|
||||||
|
);
|
||||||
|
return new L.Icon({
|
||||||
|
iconUrl: `data:image/svg+xml;charset=UTF-8,${svg}`,
|
||||||
|
iconSize: [size, size],
|
||||||
|
iconAnchor: [size / 2, size / 2]
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fits the map to the planned path once both the map and data are ready.
|
||||||
|
// Re-runs whenever the route changes (different rider / date).
|
||||||
|
const FitBoundsController = ({ dropPath }) => {
|
||||||
|
const map = useMap();
|
||||||
|
useEffect(() => {
|
||||||
|
if (!dropPath.length) return;
|
||||||
|
if (dropPath.length === 1) {
|
||||||
|
map.setView(dropPath[0], 14);
|
||||||
|
} else {
|
||||||
|
map.fitBounds(dropPath, { padding: [48, 48] });
|
||||||
|
}
|
||||||
|
}, [dropPath, map]);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
// Renders a single rider's PLANNED route for the date range chosen on the
|
// Renders a single rider's PLANNED route for the date range chosen on the
|
||||||
// Riders Summary page. `details` is an ordered array of waypoints (sorted by
|
// Riders Summary page. `details` is an ordered array of waypoints (sorted by
|
||||||
// the planning step number) shaped as:
|
// the planning step number) shaped as:
|
||||||
@@ -13,84 +49,38 @@ const containerStyle = { width: '100%', height: '100%' };
|
|||||||
// `dropLat/dropLng` are required; pickup coords are optional and rendered as
|
// `dropLat/dropLng` are required; pickup coords are optional and rendered as
|
||||||
// faded pre-stops if present.
|
// faded pre-stops if present.
|
||||||
export default function RidersRoutes({ details, loading, riderName, dateRange, onClose }) {
|
export default function RidersRoutes({ details, loading, riderName, dateRange, onClose }) {
|
||||||
const mapRef = useRef(null);
|
|
||||||
const [focusedStep, setFocusedStep] = useState(null);
|
const [focusedStep, setFocusedStep] = useState(null);
|
||||||
const [routePath, setRoutePath] = useState([]);
|
const [routePath, setRoutePath] = useState([]);
|
||||||
const [routeLoading, setRouteLoading] = useState(false);
|
const [routeLoading, setRouteLoading] = useState(false);
|
||||||
|
|
||||||
const { isLoaded } = useJsApiLoader({
|
|
||||||
googleMapsApiKey: process.env.REACT_APP_GOOGLE_MAPS_KEY
|
|
||||||
});
|
|
||||||
|
|
||||||
// Step-pin coordinates in planning order — what the polyline connects.
|
// Step-pin coordinates in planning order — what the polyline connects.
|
||||||
const dropPath = useMemo(
|
const dropPath = useMemo(() => (details || []).map((d) => [d.dropLat, d.dropLng]), [details]);
|
||||||
() => (details || []).map((d) => ({ lat: d.dropLat, lng: d.dropLng })),
|
|
||||||
[details]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Auto-fit map bounds to the full planned path once the map and data are
|
|
||||||
// both ready. Re-runs whenever the route changes (different rider / date).
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isLoaded || !mapRef.current || dropPath.length === 0) return;
|
|
||||||
const bounds = new window.google.maps.LatLngBounds();
|
|
||||||
dropPath.forEach((p) => bounds.extend(p));
|
|
||||||
mapRef.current.fitBounds(bounds, 48);
|
|
||||||
}, [isLoaded, dropPath]);
|
|
||||||
|
|
||||||
// Resolve the rider's planned waypoints into an actual road-following path
|
// Resolve the rider's planned waypoints into an actual road-following path
|
||||||
// via the Directions API. Without this, the polyline would cut across
|
// via OSRM. Without this, the polyline would cut across buildings / aerial
|
||||||
// buildings / aerial lines — operators have no way to read the real route.
|
// lines — operators have no way to read the real route.
|
||||||
// Directions has a 25-waypoint limit per request, so we chunk and stitch.
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isLoaded || dropPath.length < 2) {
|
if (dropPath.length < 2) {
|
||||||
setRoutePath([]);
|
setRoutePath([]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
const ds = new window.google.maps.DirectionsService();
|
|
||||||
const MAX_WPS = 23; // origin + 23 waypoints + destination = 25 stops/chunk
|
|
||||||
|
|
||||||
const fetchSegment = (origin, destination, waypoints) =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
ds.route(
|
|
||||||
{
|
|
||||||
origin,
|
|
||||||
destination,
|
|
||||||
waypoints: waypoints.map((p) => ({ location: p, stopover: true })),
|
|
||||||
travelMode: window.google.maps.TravelMode.DRIVING
|
|
||||||
},
|
|
||||||
(result, status) => {
|
|
||||||
if (status === 'OK') resolve(result);
|
|
||||||
else reject(new Error(status));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
setRouteLoading(true);
|
setRouteLoading(true);
|
||||||
try {
|
try {
|
||||||
const points = dropPath;
|
const coords = dropPath.map(([lat, lng]) => `${lng},${lat}`).join(';');
|
||||||
const all = [];
|
const url = `https://router.project-osrm.org/route/v1/driving/${coords}?overview=full&geometries=geojson`;
|
||||||
let i = 0;
|
const res = await fetch(url);
|
||||||
while (i < points.length - 1) {
|
const data = await res.json();
|
||||||
const remaining = points.length - 1 - i;
|
if (!cancelled && data.routes?.length) {
|
||||||
const take = Math.min(remaining, MAX_WPS + 1);
|
const points = data.routes[0].geometry.coordinates.map(([lng, lat]) => [lat, lng]);
|
||||||
const origin = points[i];
|
setRoutePath(points);
|
||||||
const destination = points[i + take];
|
} else if (!cancelled) {
|
||||||
const waypoints = points.slice(i + 1, i + take);
|
setRoutePath([]);
|
||||||
const res = await fetchSegment(origin, destination, waypoints);
|
|
||||||
const seg = res.routes[0].overview_path.map((ll) => ({
|
|
||||||
lat: ll.lat(),
|
|
||||||
lng: ll.lng()
|
|
||||||
}));
|
|
||||||
// Avoid duplicating the join point between adjacent chunks.
|
|
||||||
if (all.length > 0 && seg.length > 0) seg.shift();
|
|
||||||
all.push(...seg);
|
|
||||||
i += take;
|
|
||||||
}
|
}
|
||||||
if (!cancelled) setRoutePath(all);
|
} catch (e) {
|
||||||
} catch {
|
console.warn('OSRM route error:', e);
|
||||||
// Fall back to the straight-line skeleton on failure (quota, no route, etc.).
|
|
||||||
if (!cancelled) setRoutePath([]);
|
if (!cancelled) setRoutePath([]);
|
||||||
} finally {
|
} finally {
|
||||||
if (!cancelled) setRouteLoading(false);
|
if (!cancelled) setRouteLoading(false);
|
||||||
@@ -100,22 +90,7 @@ export default function RidersRoutes({ details, loading, riderName, dateRange, o
|
|||||||
return () => {
|
return () => {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
};
|
};
|
||||||
}, [isLoaded, dropPath]);
|
}, [dropPath]);
|
||||||
|
|
||||||
// Numbered step icon as a data URL — drawn fresh per render so we can pass
|
|
||||||
// the step number into the SVG without juggling external assets. Color is
|
|
||||||
// brand purple to match the planned-route polyline below.
|
|
||||||
const stepIcon = (n, isFocused) => {
|
|
||||||
const size = isFocused ? 38 : 32;
|
|
||||||
const color = isFocused ? '#910E1D' : '#C01227';
|
|
||||||
const svg = encodeURIComponent(
|
|
||||||
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="${size}" height="${size}">` +
|
|
||||||
`<circle cx="16" cy="16" r="14" fill="${color}" stroke="white" stroke-width="3"/>` +
|
|
||||||
`<text x="16" y="21" text-anchor="middle" font-family="Arial,sans-serif" font-size="14" font-weight="700" fill="white">${n}</text>` +
|
|
||||||
`</svg>`
|
|
||||||
);
|
|
||||||
return `data:image/svg+xml;charset=UTF-8,${svg}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const headerBar = (
|
const headerBar = (
|
||||||
<Stack
|
<Stack
|
||||||
@@ -133,12 +108,8 @@ export default function RidersRoutes({ details, loading, riderName, dateRange, o
|
|||||||
>
|
>
|
||||||
<MdRoute size={20} />
|
<MdRoute size={20} />
|
||||||
<Stack sx={{ flex: 1, minWidth: 0 }}>
|
<Stack sx={{ flex: 1, minWidth: 0 }}>
|
||||||
<Typography sx={{ fontWeight: 700, fontSize: 15, lineHeight: 1.2 }}>
|
<Typography sx={{ fontWeight: 700, fontSize: 15, lineHeight: 1.2 }}>Planned route{riderName ? ` — ${riderName}` : ''}</Typography>
|
||||||
Planned route{riderName ? ` — ${riderName}` : ''}
|
{dateRange && <Typography sx={{ fontSize: 12, opacity: 0.85 }}>{dateRange}</Typography>}
|
||||||
</Typography>
|
|
||||||
{dateRange && (
|
|
||||||
<Typography sx={{ fontSize: 12, opacity: 0.85 }}>{dateRange}</Typography>
|
|
||||||
)}
|
|
||||||
</Stack>
|
</Stack>
|
||||||
{details && details.length > 0 && (
|
{details && details.length > 0 && (
|
||||||
<Typography sx={{ fontSize: 12, opacity: 0.9, fontWeight: 600 }}>
|
<Typography sx={{ fontSize: 12, opacity: 0.9, fontWeight: 600 }}>
|
||||||
@@ -154,16 +125,14 @@ export default function RidersRoutes({ details, loading, riderName, dateRange, o
|
|||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|
||||||
// Loading state — route fetch in flight OR Google Maps script not ready yet.
|
// Loading state — parent is still fetching the planned route data.
|
||||||
if (loading || !isLoaded) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
<Box sx={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
||||||
{headerBar}
|
{headerBar}
|
||||||
<Stack alignItems="center" justifyContent="center" sx={{ flex: 1, gap: 1.5 }}>
|
<Stack alignItems="center" justifyContent="center" sx={{ flex: 1, gap: 1.5 }}>
|
||||||
<CircularProgress size={32} />
|
<CircularProgress size={32} />
|
||||||
<Typography sx={{ color: '#64748b', fontSize: 13 }}>
|
<Typography sx={{ color: '#64748b', fontSize: 13 }}>Loading planned route…</Typography>
|
||||||
{loading ? 'Loading planned route…' : 'Loading map…'}
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
@@ -176,9 +145,7 @@ export default function RidersRoutes({ details, loading, riderName, dateRange, o
|
|||||||
<Box sx={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
<Box sx={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
||||||
{headerBar}
|
{headerBar}
|
||||||
<Stack alignItems="center" justifyContent="center" sx={{ flex: 1, gap: 1, p: 3 }}>
|
<Stack alignItems="center" justifyContent="center" sx={{ flex: 1, gap: 1, p: 3 }}>
|
||||||
<Typography sx={{ color: '#1e293b', fontWeight: 700, fontSize: 16 }}>
|
<Typography sx={{ color: '#1e293b', fontWeight: 700, fontSize: 16 }}>No planned route for this rider</Typography>
|
||||||
No planned route for this rider
|
|
||||||
</Typography>
|
|
||||||
<Typography sx={{ color: '#64748b', fontSize: 13, textAlign: 'center', maxWidth: 360 }}>
|
<Typography sx={{ color: '#64748b', fontSize: 13, textAlign: 'center', maxWidth: 360 }}>
|
||||||
There are no deliveries with drop coordinates assigned to this rider for the selected date range.
|
There are no deliveries with drop coordinates assigned to this rider for the selected date range.
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -191,53 +158,21 @@ export default function RidersRoutes({ details, loading, riderName, dateRange, o
|
|||||||
<Box sx={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
<Box sx={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
||||||
{headerBar}
|
{headerBar}
|
||||||
<Box sx={{ flex: 1, minHeight: 0 }}>
|
<Box sx={{ flex: 1, minHeight: 0 }}>
|
||||||
<GoogleMap
|
<MapContainer center={dropPath[0]} zoom={14} style={containerStyle} zoomControl={false}>
|
||||||
mapContainerStyle={containerStyle}
|
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" attribution="© OpenStreetMap contributors" />
|
||||||
onLoad={(map) => (mapRef.current = map)}
|
<FitBoundsController dropPath={dropPath} />
|
||||||
center={dropPath[0]}
|
|
||||||
zoom={14}
|
|
||||||
options={{
|
|
||||||
streetViewControl: false,
|
|
||||||
mapTypeControl: false,
|
|
||||||
fullscreenControl: false
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{routePath.length > 0 ? (
|
{routePath.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
{/* Translucent backdrop so the route stays legible on busy tiles. */}
|
{/* Translucent backdrop so the route stays legible on busy tiles. */}
|
||||||
<Polyline
|
<Polyline positions={routePath} pathOptions={{ color: '#C01227', opacity: 0.25, weight: 8 }} />
|
||||||
path={routePath}
|
{/* Road-following planned route from OSRM. */}
|
||||||
options={{ strokeColor: '#C01227', strokeOpacity: 0.25, strokeWeight: 8 }}
|
<Polyline positions={routePath} pathOptions={{ color: '#C01227', opacity: 0.95, weight: 4 }} />
|
||||||
/>
|
|
||||||
{/* Road-following planned route from the Directions API. */}
|
|
||||||
<Polyline
|
|
||||||
path={routePath}
|
|
||||||
options={{ strokeColor: '#C01227', strokeOpacity: 0.95, strokeWeight: 4 }}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
// Fallback while Directions is in flight (or if it fails) — dashed
|
// Fallback while OSRM is in flight (or if it fails) — dashed
|
||||||
// straight-line skeleton between drop pins in step order.
|
// straight-line skeleton between drop pins in step order.
|
||||||
<Polyline
|
<Polyline positions={dropPath} pathOptions={{ color: '#C01227', opacity: 0.6, weight: 3, dashArray: '2 10', lineCap: 'round' }} />
|
||||||
path={dropPath}
|
|
||||||
options={{
|
|
||||||
strokeColor: '#C01227',
|
|
||||||
strokeOpacity: 0,
|
|
||||||
strokeWeight: 0,
|
|
||||||
icons: [
|
|
||||||
{
|
|
||||||
icon: {
|
|
||||||
path: 'M 0,-1 0,1',
|
|
||||||
strokeOpacity: 0.6,
|
|
||||||
strokeColor: '#C01227',
|
|
||||||
scale: 3
|
|
||||||
},
|
|
||||||
offset: '0',
|
|
||||||
repeat: '14px'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{details.map((d, i) => {
|
{details.map((d, i) => {
|
||||||
@@ -246,39 +181,29 @@ export default function RidersRoutes({ details, loading, riderName, dateRange, o
|
|||||||
return (
|
return (
|
||||||
<Marker
|
<Marker
|
||||||
key={`step-${d.deliveryid || d.orderid || i}`}
|
key={`step-${d.deliveryid || d.orderid || i}`}
|
||||||
position={{ lat: d.dropLat, lng: d.dropLng }}
|
position={[d.dropLat, d.dropLng]}
|
||||||
icon={{ url: stepIcon(stepNum, isFocused) }}
|
icon={stepIcon(stepNum, isFocused)}
|
||||||
onClick={() => setFocusedStep(isFocused ? null : d.deliveryid)}
|
eventHandlers={{
|
||||||
zIndex={isFocused ? 1000 : stepNum}
|
click: () => setFocusedStep(isFocused ? null : d.deliveryid)
|
||||||
|
}}
|
||||||
|
zIndexOffset={isFocused ? 1000 : stepNum}
|
||||||
>
|
>
|
||||||
{isFocused && (
|
<Popup onClose={() => setFocusedStep(null)}>
|
||||||
<InfoWindow onCloseClick={() => setFocusedStep(null)}>
|
|
||||||
<Box sx={{ minWidth: 180, fontFamily: 'inherit' }}>
|
<Box sx={{ minWidth: 180, fontFamily: 'inherit' }}>
|
||||||
<Typography sx={{ fontWeight: 800, fontSize: 13, color: '#0f172a' }}>
|
<Typography sx={{ fontWeight: 800, fontSize: 13, color: '#0f172a' }}>
|
||||||
Step {stepNum} · {d.customer}
|
Step {stepNum} · {d.customer}
|
||||||
</Typography>
|
</Typography>
|
||||||
{d.address && (
|
{d.address && <Typography sx={{ fontSize: 12, color: '#475569', mt: 0.5 }}>{d.address}</Typography>}
|
||||||
<Typography sx={{ fontSize: 12, color: '#475569', mt: 0.5 }}>
|
|
||||||
{d.address}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
{d.expectedTime && (
|
{d.expectedTime && (
|
||||||
<Typography sx={{ fontSize: 12, color: '#64748b', mt: 0.5 }}>
|
<Typography sx={{ fontSize: 12, color: '#64748b', mt: 0.5 }}>ETA {String(d.expectedTime).slice(11, 16) || d.expectedTime}</Typography>
|
||||||
ETA {String(d.expectedTime).slice(11, 16) || d.expectedTime}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
{d.orderid && (
|
|
||||||
<Typography sx={{ fontSize: 11, color: '#94a3b8', mt: 0.5 }}>
|
|
||||||
Order #{d.orderid}
|
|
||||||
</Typography>
|
|
||||||
)}
|
)}
|
||||||
|
{d.orderid && <Typography sx={{ fontSize: 11, color: '#94a3b8', mt: 0.5 }}>Order #{d.orderid}</Typography>}
|
||||||
</Box>
|
</Box>
|
||||||
</InfoWindow>
|
</Popup>
|
||||||
)}
|
|
||||||
</Marker>
|
</Marker>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</GoogleMap>
|
</MapContainer>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ import { useState, useEffect } from 'react';
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import Loader from 'components/Loader';
|
import Loader from 'components/Loader';
|
||||||
import Transitions from 'components/@extended/Transitions';
|
import Transitions from 'components/@extended/Transitions';
|
||||||
import Autocomplete from 'react-google-autocomplete';
|
import AddressAutocomplete from 'components/nearle_components/AddressAutocomplete';
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
@@ -63,8 +63,6 @@ import TablePagination from '@mui/material/TablePagination';
|
|||||||
import TableSortLabel from '@mui/material/TableSortLabel';
|
import TableSortLabel from '@mui/material/TableSortLabel';
|
||||||
import { visuallyHidden } from '@mui/utils';
|
import { visuallyHidden } from '@mui/utils';
|
||||||
|
|
||||||
import Geocode from 'react-geocode';
|
|
||||||
|
|
||||||
const Requests = () => {
|
const Requests = () => {
|
||||||
// let dispatch = useDispatch();
|
// let dispatch = useDispatch();
|
||||||
|
|
||||||
@@ -204,7 +202,6 @@ const Requests = () => {
|
|||||||
const [suburb, setSuburb] = useState('');
|
const [suburb, setSuburb] = useState('');
|
||||||
const [currenttenantid] = useState('');
|
const [currenttenantid] = useState('');
|
||||||
const [latlong, setLatlong] = useState({});
|
const [latlong, setLatlong] = useState({});
|
||||||
Geocode.setApiKey(process.env.REACT_APP_GOOGLE_MAPS_API_KEY);
|
|
||||||
const [alertmessage, setAlertmessage] = useState('');
|
const [alertmessage, setAlertmessage] = useState('');
|
||||||
// const [toast, setToast] = useState(false);
|
// const [toast, setToast] = useState(false);
|
||||||
const [rolesarr, setRolesarr] = useState([]);
|
const [rolesarr, setRolesarr] = useState([]);
|
||||||
@@ -286,27 +283,34 @@ const Requests = () => {
|
|||||||
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
useEffect(() => {
|
const handleAddressPlaceSelected = (place) => {
|
||||||
try {
|
setAddress(place.formatted_address);
|
||||||
Geocode.fromAddress(address).then(
|
setLatlong({ lat: place.geometry.location.lat(), lng: place.geometry.location.lng() });
|
||||||
(response) => {
|
let city1, state, zipcode1, suburb1;
|
||||||
if (response.status == 'OK') {
|
place.address_components.forEach((component) => {
|
||||||
const { lat, lng } = response.results[0].geometry.location;
|
component.types.forEach((type) => {
|
||||||
setLatlong({
|
switch (type) {
|
||||||
lat,
|
case 'locality':
|
||||||
lng
|
city1 = component.long_name;
|
||||||
|
break;
|
||||||
|
case 'administrative_area_level_1':
|
||||||
|
state = component.long_name;
|
||||||
|
break;
|
||||||
|
case 'postal_code':
|
||||||
|
zipcode1 = component.long_name;
|
||||||
|
break;
|
||||||
|
case 'sublocality':
|
||||||
|
case 'sublocality_level_1':
|
||||||
|
suburb1 = component.long_name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
console.log(response);
|
});
|
||||||
}
|
setCity(city1 || '');
|
||||||
},
|
setState1(state || '');
|
||||||
(error) => {
|
setZipcode(zipcode1 || '');
|
||||||
console.log(error);
|
setSuburb(suburb1 || '');
|
||||||
}
|
};
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}, [address]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('rolesarr');
|
console.log('rolesarr');
|
||||||
@@ -1467,53 +1471,22 @@ const Requests = () => {
|
|||||||
|
|
||||||
{/* } */}
|
{/* } */}
|
||||||
|
|
||||||
<Autocomplete
|
<AddressAutocomplete
|
||||||
className="automap"
|
id="request-address-autocomplete"
|
||||||
apiKey={process.env.REACT_APP_GOOGLE_MAPS_API_KEY}
|
fullWidth
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
height: '40px',
|
|
||||||
borderRadius: '5px',
|
|
||||||
border: '1px solid #e0e0e0',
|
|
||||||
textIndent: '10px',
|
|
||||||
outline: 'none'
|
|
||||||
// ':hover': {
|
|
||||||
// border: '1px solid #00b0ff !important',
|
|
||||||
// backgroundColor:'blue'
|
|
||||||
// }
|
|
||||||
}}
|
|
||||||
onPlaceSelected={(place) => {
|
|
||||||
setAddress(place.formatted_address);
|
|
||||||
let city1, state, zipcode1, suburb1;
|
|
||||||
for (let i = 0; i < place.address_components.length; i++) {
|
|
||||||
for (let j = 0; j < place.address_components[i].types.length; j++) {
|
|
||||||
switch (place.address_components[i].types[j]) {
|
|
||||||
case 'locality':
|
|
||||||
city1 = place.address_components[i].long_name;
|
|
||||||
break;
|
|
||||||
case 'administrative_area_level_1':
|
|
||||||
state = place.address_components[i].long_name;
|
|
||||||
break;
|
|
||||||
case 'postal_code':
|
|
||||||
zipcode1 = place.address_components[i].long_name;
|
|
||||||
break;
|
|
||||||
case 'sublocality':
|
|
||||||
suburb1 = place.address_components[i].long_name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCity(city1 || '');
|
|
||||||
setState1(state || '');
|
|
||||||
setZipcode(zipcode1 || '');
|
|
||||||
setSuburb(suburb1 || '');
|
|
||||||
}}
|
|
||||||
options={{
|
|
||||||
types: ['address' || 'geocode']
|
|
||||||
}}
|
|
||||||
placeholder="Address"
|
placeholder="Address"
|
||||||
value={address}
|
value={address}
|
||||||
onChange={(e) => setAddress(e.target.value)}
|
onChange={setAddress}
|
||||||
|
onPlaceSelected={handleAddressPlaceSelected}
|
||||||
|
TextFieldProps={{
|
||||||
|
className: 'automap',
|
||||||
|
InputProps: {
|
||||||
|
style: {
|
||||||
|
borderRadius: '5px',
|
||||||
|
border: '1px solid #e0e0e0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -13,12 +13,10 @@ import { DT, tint } from 'themes/dt/tokens';
|
|||||||
import MainCard from 'components/MainCard';
|
import MainCard from 'components/MainCard';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
// assets
|
// assets
|
||||||
import { usePlacesWidget } from 'react-google-autocomplete';
|
import AddressAutocomplete, { geocodeAddress } from 'components/nearle_components/AddressAutocomplete';
|
||||||
import Loader from 'components/Loader';
|
import Loader from 'components/Loader';
|
||||||
import Geocode from 'react-geocode';
|
|
||||||
import { enqueueSnackbar } from 'notistack';
|
import { enqueueSnackbar } from 'notistack';
|
||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
// import { setLocationType } from 'react-geocode';
|
|
||||||
|
|
||||||
// const avatarImage = require.context('assets/images/users', true);
|
// const avatarImage = require.context('assets/images/users', true);
|
||||||
|
|
||||||
@@ -52,9 +50,6 @@ const Createrider = () => {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
|
|
||||||
Geocode.setApiKey(process.env.REACT_APP_GOOGLE_MAPS_API_KEY);
|
|
||||||
// Geocode.setApiKey('AIzaSyCF4KatYCI3vqz1_H3kiHeyS3yCMfYToh8');
|
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -66,25 +61,15 @@ const Createrider = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
let active = true;
|
||||||
Geocode.fromAddress(address).then(
|
geocodeAddress(address).then((place) => {
|
||||||
(response) => {
|
if (active && place) {
|
||||||
if (response.status == 'OK') {
|
setLatlong({ lat: place.geometry.location.lat(), lng: place.geometry.location.lng() });
|
||||||
const { lat, lng } = response.results[0].geometry.location;
|
}
|
||||||
setLatlong({
|
|
||||||
lat,
|
|
||||||
lng
|
|
||||||
});
|
});
|
||||||
console.log(response);
|
return () => {
|
||||||
}
|
active = false;
|
||||||
},
|
};
|
||||||
(error) => {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}, [address]);
|
}, [address]);
|
||||||
|
|
||||||
const opentoast = (message) => {
|
const opentoast = (message) => {
|
||||||
@@ -115,11 +100,7 @@ const Createrider = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const { ref: materialRef } = usePlacesWidget({
|
const handleAddressPlaceSelected = (place) => {
|
||||||
apiKey: process.env.REACT_APP_GOOGLE_MAPS_API_KEY,
|
|
||||||
onPlaceSelected: (place) => {
|
|
||||||
console.log(place);
|
|
||||||
|
|
||||||
setAddress(place.formatted_address);
|
setAddress(place.formatted_address);
|
||||||
let city1, zipcode1, state1, suburb1;
|
let city1, zipcode1, state1, suburb1;
|
||||||
for (let i = 0; i < place.address_components.length; i++) {
|
for (let i = 0; i < place.address_components.length; i++) {
|
||||||
@@ -135,6 +116,7 @@ const Createrider = () => {
|
|||||||
zipcode1 = place.address_components[i].long_name;
|
zipcode1 = place.address_components[i].long_name;
|
||||||
break;
|
break;
|
||||||
case 'sublocality':
|
case 'sublocality':
|
||||||
|
case 'sublocality_level_1':
|
||||||
suburb1 = place.address_components[i].long_name;
|
suburb1 = place.address_components[i].long_name;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -144,16 +126,7 @@ const Createrider = () => {
|
|||||||
setState(state1 || '');
|
setState(state1 || '');
|
||||||
setZipcode(zipcode1 || '');
|
setZipcode(zipcode1 || '');
|
||||||
setSuburb(suburb1 || '');
|
setSuburb(suburb1 || '');
|
||||||
|
};
|
||||||
// setAddress(place.formatted_address)
|
|
||||||
},
|
|
||||||
// inputAutocompleteValue: "country",
|
|
||||||
options: {
|
|
||||||
// componentRestrictions: 'us',
|
|
||||||
// types: ["establishment"]
|
|
||||||
types: ['address' || 'geocode']
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const createprofile = async () => {
|
const createprofile = async () => {
|
||||||
if (!firstname) {
|
if (!firstname) {
|
||||||
@@ -339,14 +312,13 @@ const Createrider = () => {
|
|||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Stack spacing={1.25}>
|
<Stack spacing={1.25}>
|
||||||
<InputLabel htmlFor="personal-address">Address</InputLabel>
|
<InputLabel htmlFor="personal-address">Address</InputLabel>
|
||||||
<TextField
|
<AddressAutocomplete
|
||||||
fullWidth
|
|
||||||
// defaultValue="Street 110-B Kalians Bag, Dewan, M.P. New York"
|
|
||||||
id="personal-address"
|
id="personal-address"
|
||||||
|
fullWidth
|
||||||
placeholder="Address"
|
placeholder="Address"
|
||||||
value={address}
|
value={address}
|
||||||
onChange={(e) => setAddress(e.target.value)}
|
onChange={setAddress}
|
||||||
inputRef={materialRef}
|
onPlaceSelected={handleAddressPlaceSelected}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -31,9 +31,8 @@ import { DatePicker } from '@mui/x-date-pickers/DatePicker';
|
|||||||
// project import
|
// project import
|
||||||
import MainCard from 'components/MainCard';
|
import MainCard from 'components/MainCard';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { usePlacesWidget } from 'react-google-autocomplete';
|
import AddressAutocomplete from 'components/nearle_components/AddressAutocomplete';
|
||||||
import Loader from 'components/Loader';
|
import Loader from 'components/Loader';
|
||||||
import Geocode from 'react-geocode';
|
|
||||||
import { enqueueSnackbar } from 'notistack';
|
import { enqueueSnackbar } from 'notistack';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import CircularLoader from 'components/CircularLoader';
|
import CircularLoader from 'components/CircularLoader';
|
||||||
@@ -58,8 +57,6 @@ const EditRider = () => {
|
|||||||
const [locaName, setLocoName] = useState();
|
const [locaName, setLocoName] = useState();
|
||||||
const userid = localStorage.getItem('userid');
|
const userid = localStorage.getItem('userid');
|
||||||
|
|
||||||
Geocode.setApiKey(process.env.REACT_APP_GOOGLE_MAPS_API_KEY);
|
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const fetchRiderData = async (id) => {
|
const fetchRiderData = async (id) => {
|
||||||
@@ -231,13 +228,10 @@ const EditRider = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const { ref: materialRef } = usePlacesWidget({
|
const handleAddressPlaceSelected = (place) => {
|
||||||
apiKey: process.env.REACT_APP_GOOGLE_MAPS_API_KEY,
|
|
||||||
onPlaceSelected: (place) => {
|
|
||||||
console.log(place);
|
|
||||||
setAddress(place.formatted_address);
|
setAddress(place.formatted_address);
|
||||||
|
|
||||||
let city1, zipcode1, state1, suburb1;
|
let city1, state1, suburb1;
|
||||||
for (let i = 0; i < place.address_components.length; i++) {
|
for (let i = 0; i < place.address_components.length; i++) {
|
||||||
for (let j = 0; j < place.address_components[i].types.length; j++) {
|
for (let j = 0; j < place.address_components[i].types.length; j++) {
|
||||||
switch (place.address_components[i].types[j]) {
|
switch (place.address_components[i].types[j]) {
|
||||||
@@ -247,29 +241,17 @@ const EditRider = () => {
|
|||||||
case 'administrative_area_level_1':
|
case 'administrative_area_level_1':
|
||||||
state1 = place.address_components[i].long_name;
|
state1 = place.address_components[i].long_name;
|
||||||
break;
|
break;
|
||||||
case 'postal_code':
|
|
||||||
zipcode1 = place.address_components[i].long_name;
|
|
||||||
break;
|
|
||||||
case 'sublocality':
|
case 'sublocality':
|
||||||
|
case 'sublocality_level_1':
|
||||||
suburb1 = place.address_components[i].long_name;
|
suburb1 = place.address_components[i].long_name;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setCity(city1 || '');
|
setCity(city1 || '');
|
||||||
|
|
||||||
setState(state1 || '');
|
setState(state1 || '');
|
||||||
setSuburb(suburb1 || '');
|
setSuburb(suburb1 || '');
|
||||||
|
};
|
||||||
// setAddress(place.formatted_address)
|
|
||||||
},
|
|
||||||
// inputAutocompleteValue: "country",
|
|
||||||
options: {
|
|
||||||
// componentRestrictions: 'us',
|
|
||||||
// types: ["establishment"]
|
|
||||||
types: ['address' || 'geocode']
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const updateRider = async () => {
|
const updateRider = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -487,16 +469,13 @@ const EditRider = () => {
|
|||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Stack spacing={1.25}>
|
<Stack spacing={1.25}>
|
||||||
<InputLabel htmlFor="personal-address">Address</InputLabel>
|
<InputLabel htmlFor="personal-address">Address</InputLabel>
|
||||||
<TextField
|
<AddressAutocomplete
|
||||||
fullWidth
|
|
||||||
// defaultValue="Street 110-B Kalians Bag, Dewan, M.P. New York"
|
|
||||||
id="personal-address"
|
id="personal-address"
|
||||||
|
fullWidth
|
||||||
placeholder="Address"
|
placeholder="Address"
|
||||||
value={address}
|
value={address}
|
||||||
onChange={(e) => {
|
onChange={setAddress}
|
||||||
setAddress(e.target.value);
|
onPlaceSelected={handleAddressPlaceSelected}
|
||||||
}}
|
|
||||||
inputRef={materialRef}
|
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useState, useEffect, useRef, Fragment } from 'react';
|
import { useState, useEffect, useRef, Fragment } from 'react';
|
||||||
import Geocode from 'react-geocode';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import {
|
import {
|
||||||
@@ -491,8 +490,6 @@ const Riders = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Geocode.setApiKey(process.env.REACT_APP_GOOGLE_MAPS_API_KEY);
|
|
||||||
|
|
||||||
const handleChangetab = (i) => {
|
const handleChangetab = (i) => {
|
||||||
setTabvalue(i);
|
setTabvalue(i);
|
||||||
setLogsRow(null);
|
setLogsRow(null);
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ const OrdersPreview = Loadable(lazy(() => import('pages/nearle/orders/OrdersPrev
|
|||||||
|
|
||||||
const Deliveries = Loadable(lazy(() => import('pages/nearle/deliveries/deliveries')));
|
const Deliveries = Loadable(lazy(() => import('pages/nearle/deliveries/deliveries')));
|
||||||
|
|
||||||
|
const Tenants = Loadable(lazy(() => import('pages/nearle/clients/Tenants')));
|
||||||
|
const ClientsPricing = Loadable(lazy(() => import('pages/nearle/clientPricing/clientPricing')));
|
||||||
|
|
||||||
const Details = Loadable(lazy(() => import('pages/nearle/orders/details')));
|
const Details = Loadable(lazy(() => import('pages/nearle/orders/details')));
|
||||||
|
|
||||||
const ViewProfile = Loadable(lazy(() => import('pages/nearle/viewProfile')));
|
const ViewProfile = Loadable(lazy(() => import('pages/nearle/viewProfile')));
|
||||||
@@ -70,6 +73,14 @@ const MainRoutes = {
|
|||||||
path: 'deliveries',
|
path: 'deliveries',
|
||||||
element: <Deliveries />
|
element: <Deliveries />
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'tenants',
|
||||||
|
element: <Tenants />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'pricing',
|
||||||
|
element: <ClientsPricing />
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'requests',
|
path: 'requests',
|
||||||
element: <Requests />
|
element: <Requests />
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
"orderspreview": "Orders Preview",
|
"orderspreview": "Orders Preview",
|
||||||
"deliveries": "Deliveries",
|
"deliveries": "Deliveries",
|
||||||
"riders": "Riders",
|
"riders": "Riders",
|
||||||
|
"tenants": "Tenants",
|
||||||
|
"pricing": "Pricing",
|
||||||
"reports": "Reports",
|
"reports": "Reports",
|
||||||
"ordersummary": "Orders Summary",
|
"ordersummary": "Orders Summary",
|
||||||
"ordersdetails": "Orders Details",
|
"ordersdetails": "Orders Details",
|
||||||
|
|||||||
213
yarn.lock
213
yarn.lock
@@ -79,7 +79,7 @@
|
|||||||
jsonpointer "^5.0.0"
|
jsonpointer "^5.0.0"
|
||||||
leven "^3.1.0"
|
leven "^3.1.0"
|
||||||
|
|
||||||
"@astryxdesign/core@^0.1.9", "@astryxdesign/core@0.1.9":
|
"@astryxdesign/core@^0.1.9":
|
||||||
version "0.1.9"
|
version "0.1.9"
|
||||||
resolved "https://registry.npmjs.org/@astryxdesign/core/-/core-0.1.9.tgz"
|
resolved "https://registry.npmjs.org/@astryxdesign/core/-/core-0.1.9.tgz"
|
||||||
integrity sha512-2ZNypZFfujMPxdU8M9Jbe77vwFPP1FYvA0Pk/3L3OLxEIzi98qLbRJjhDEHLbrflANSFVB4l5+qYpJjYtFFXMQ==
|
integrity sha512-2ZNypZFfujMPxdU8M9Jbe77vwFPP1FYvA0Pk/3L3OLxEIzi98qLbRJjhDEHLbrflANSFVB4l5+qYpJjYtFFXMQ==
|
||||||
@@ -107,7 +107,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz"
|
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz"
|
||||||
integrity sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==
|
integrity sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==
|
||||||
|
|
||||||
"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.0.0-0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.1.0", "@babel/core@^7.11.1", "@babel/core@^7.12.0", "@babel/core@^7.12.3", "@babel/core@^7.13.0", "@babel/core@^7.16.0", "@babel/core@^7.21.3", "@babel/core@^7.21.4", "@babel/core@^7.4.0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.4.0-0", "@babel/core@^7.7.2", "@babel/core@^7.8.0", "@babel/core@>=7.11.0":
|
"@babel/core@^7.1.0", "@babel/core@^7.11.1", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.21.3", "@babel/core@^7.21.4", "@babel/core@^7.7.2", "@babel/core@^7.8.0":
|
||||||
version "7.29.7"
|
version "7.29.7"
|
||||||
resolved "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz"
|
resolved "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz"
|
||||||
integrity sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==
|
integrity sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==
|
||||||
@@ -467,7 +467,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-plugin-utils" "^7.16.7"
|
"@babel/helper-plugin-utils" "^7.16.7"
|
||||||
|
|
||||||
"@babel/plugin-syntax-flow@^7.14.5", "@babel/plugin-syntax-flow@^7.16.7":
|
"@babel/plugin-syntax-flow@^7.16.7":
|
||||||
version "7.26.0"
|
version "7.26.0"
|
||||||
resolved "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz"
|
resolved "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz"
|
||||||
integrity sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==
|
integrity sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==
|
||||||
@@ -917,7 +917,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/plugin-transform-react-jsx" "^7.27.1"
|
"@babel/plugin-transform-react-jsx" "^7.27.1"
|
||||||
|
|
||||||
"@babel/plugin-transform-react-jsx@^7.14.9", "@babel/plugin-transform-react-jsx@^7.27.1":
|
"@babel/plugin-transform-react-jsx@^7.27.1":
|
||||||
version "7.27.1"
|
version "7.27.1"
|
||||||
resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz"
|
resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz"
|
||||||
integrity sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==
|
integrity sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==
|
||||||
@@ -1346,7 +1346,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz"
|
resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz"
|
||||||
integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==
|
integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==
|
||||||
|
|
||||||
"@emotion/is-prop-valid@*", "@emotion/is-prop-valid@^1.2.0":
|
"@emotion/is-prop-valid@^1.2.0":
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz"
|
resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz"
|
||||||
integrity sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==
|
integrity sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==
|
||||||
@@ -1363,7 +1363,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz"
|
resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz"
|
||||||
integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
|
integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
|
||||||
|
|
||||||
"@emotion/react@^11.0.0-rc.0", "@emotion/react@^11.10.6", "@emotion/react@^11.4.1", "@emotion/react@^11.5.0", "@emotion/react@^11.9.0":
|
"@emotion/react@^11.10.6":
|
||||||
version "11.10.6"
|
version "11.10.6"
|
||||||
resolved "https://registry.npmjs.org/@emotion/react/-/react-11.10.6.tgz"
|
resolved "https://registry.npmjs.org/@emotion/react/-/react-11.10.6.tgz"
|
||||||
integrity sha512-6HT8jBmcSkfzO7mc+N1L9uwvOnlcGoix8Zn7srt+9ga0MjREo6lRpuVX0kzo6Jp6oTqDhREOFsygN6Ew4fEQbw==
|
integrity sha512-6HT8jBmcSkfzO7mc+N1L9uwvOnlcGoix8Zn7srt+9ga0MjREo6lRpuVX0kzo6Jp6oTqDhREOFsygN6Ew4fEQbw==
|
||||||
@@ -1393,7 +1393,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz"
|
resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz"
|
||||||
integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
|
integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
|
||||||
|
|
||||||
"@emotion/styled@^11.10.6", "@emotion/styled@^11.3.0", "@emotion/styled@^11.8.1":
|
"@emotion/styled@^11.10.6":
|
||||||
version "11.10.6"
|
version "11.10.6"
|
||||||
resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.10.6.tgz"
|
resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.10.6.tgz"
|
||||||
integrity sha512-OXtBzOmDSJo5Q0AFemHCfl+bUueT8BIcPSxu0EGTpGk6DmI5dnhSzQANm1e1ze0YZL7TDyAyy6s/b/zmGOS3Og==
|
integrity sha512-OXtBzOmDSJo5Q0AFemHCfl+bUueT8BIcPSxu0EGTpGk6DmI5dnhSzQANm1e1ze0YZL7TDyAyy6s/b/zmGOS3Og==
|
||||||
@@ -1526,7 +1526,7 @@
|
|||||||
"@firebase/util" "1.10.0"
|
"@firebase/util" "1.10.0"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@firebase/app-compat@0.2.43", "@firebase/app-compat@0.x":
|
"@firebase/app-compat@0.2.43":
|
||||||
version "0.2.43"
|
version "0.2.43"
|
||||||
resolved "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.43.tgz"
|
resolved "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.43.tgz"
|
||||||
integrity sha512-HM96ZyIblXjAC7TzE8wIk2QhHlSvksYkQ4Ukh1GmEenzkucSNUmUX4QvoKrqeWsLEQ8hdcojABeCV8ybVyZmeg==
|
integrity sha512-HM96ZyIblXjAC7TzE8wIk2QhHlSvksYkQ4Ukh1GmEenzkucSNUmUX4QvoKrqeWsLEQ8hdcojABeCV8ybVyZmeg==
|
||||||
@@ -1537,12 +1537,12 @@
|
|||||||
"@firebase/util" "1.10.0"
|
"@firebase/util" "1.10.0"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@firebase/app-types@0.9.2", "@firebase/app-types@0.x":
|
"@firebase/app-types@0.9.2":
|
||||||
version "0.9.2"
|
version "0.9.2"
|
||||||
resolved "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz"
|
resolved "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz"
|
||||||
integrity sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==
|
integrity sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==
|
||||||
|
|
||||||
"@firebase/app@0.10.13", "@firebase/app@0.x":
|
"@firebase/app@0.10.13":
|
||||||
version "0.10.13"
|
version "0.10.13"
|
||||||
resolved "https://registry.npmjs.org/@firebase/app/-/app-0.10.13.tgz"
|
resolved "https://registry.npmjs.org/@firebase/app/-/app-0.10.13.tgz"
|
||||||
integrity sha512-OZiDAEK/lDB6xy/XzYAyJJkaDqmQ+BCtOEPLqFvxWKUz5JbBmej7IiiRHdtiIOD/twW7O5AxVsfaaGA/V1bNsA==
|
integrity sha512-OZiDAEK/lDB6xy/XzYAyJJkaDqmQ+BCtOEPLqFvxWKUz5JbBmej7IiiRHdtiIOD/twW7O5AxVsfaaGA/V1bNsA==
|
||||||
@@ -1839,7 +1839,7 @@
|
|||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
undici "6.19.7"
|
undici "6.19.7"
|
||||||
|
|
||||||
"@firebase/util@1.10.0", "@firebase/util@1.x":
|
"@firebase/util@1.10.0":
|
||||||
version "1.10.0"
|
version "1.10.0"
|
||||||
resolved "https://registry.npmjs.org/@firebase/util/-/util-1.10.0.tgz"
|
resolved "https://registry.npmjs.org/@firebase/util/-/util-1.10.0.tgz"
|
||||||
integrity sha512-xKtx4A668icQqoANRxyDLBLz51TAbDP9KRfpbKGxiCAW346d0BeJe5vN6/hKxxmWwnZ0mautyv39JxviwwQMOQ==
|
integrity sha512-xKtx4A668icQqoANRxyDLBLz51TAbDP9KRfpbKGxiCAW346d0BeJe5vN6/hKxxmWwnZ0mautyv39JxviwwQMOQ==
|
||||||
@@ -1958,19 +1958,6 @@
|
|||||||
intl-messageformat "10.7.18"
|
intl-messageformat "10.7.18"
|
||||||
tslib "^2.8.0"
|
tslib "^2.8.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"
|
|
||||||
|
|
||||||
"@grpc/grpc-js@~1.9.0":
|
"@grpc/grpc-js@~1.9.0":
|
||||||
version "1.9.14"
|
version "1.9.14"
|
||||||
resolved "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.14.tgz"
|
resolved "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.14.tgz"
|
||||||
@@ -2344,7 +2331,7 @@
|
|||||||
clsx "^2.1.0"
|
clsx "^2.1.0"
|
||||||
prop-types "^15.8.1"
|
prop-types "^15.8.1"
|
||||||
|
|
||||||
"@mui/material@^5.0.0", "@mui/material@^5.12.1", "@mui/material@^5.15.14 || ^6.0.0 || ^7.0.0", "@mui/material@>=5.15.0":
|
"@mui/material@^5.12.1":
|
||||||
version "5.16.14"
|
version "5.16.14"
|
||||||
resolved "https://registry.npmjs.org/@mui/material/-/material-5.16.14.tgz"
|
resolved "https://registry.npmjs.org/@mui/material/-/material-5.16.14.tgz"
|
||||||
integrity sha512-eSXQVCMKU2xc7EcTxe/X/rC9QsV2jUe8eLM3MUCPYbo6V52eCE436akRIvELq/AqZpxx2bwkq7HC0cRhLB+yaw==
|
integrity sha512-eSXQVCMKU2xc7EcTxe/X/rC9QsV2jUe8eLM3MUCPYbo6V52eCE436akRIvELq/AqZpxx2bwkq7HC0cRhLB+yaw==
|
||||||
@@ -2381,7 +2368,7 @@
|
|||||||
csstype "^3.1.3"
|
csstype "^3.1.3"
|
||||||
prop-types "^15.8.1"
|
prop-types "^15.8.1"
|
||||||
|
|
||||||
"@mui/system@^5.15.14 || ^6.0.0 || ^7.0.0", "@mui/system@^5.16.12", "@mui/system@^5.16.14":
|
"@mui/system@^5.16.12", "@mui/system@^5.16.14":
|
||||||
version "5.16.14"
|
version "5.16.14"
|
||||||
resolved "https://registry.npmjs.org/@mui/system/-/system-5.16.14.tgz"
|
resolved "https://registry.npmjs.org/@mui/system/-/system-5.16.14.tgz"
|
||||||
integrity sha512-KBxMwCb8mSIABnKvoGbvM33XHyT+sN0BzEBG+rsSc0lLQGzs7127KWkCA6/H8h6LZ00XpBEME5MAj8mZLiQ1tw==
|
integrity sha512-KBxMwCb8mSIABnKvoGbvM33XHyT+sN0BzEBG+rsSc0lLQGzs7127KWkCA6/H8h6LZ00XpBEME5MAj8mZLiQ1tw==
|
||||||
@@ -2660,28 +2647,6 @@
|
|||||||
resolved "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz"
|
resolved "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz"
|
||||||
integrity sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==
|
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@^3.0.0":
|
"@react-leaflet/core@^3.0.0":
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.npmjs.org/@react-leaflet/core/-/core-3.0.0.tgz"
|
resolved "https://registry.npmjs.org/@react-leaflet/core/-/core-3.0.0.tgz"
|
||||||
@@ -2907,16 +2872,6 @@
|
|||||||
"@svgr/babel-plugin-transform-react-native-svg" "^7.0.0"
|
"@svgr/babel-plugin-transform-react-native-svg" "^7.0.0"
|
||||||
"@svgr/babel-plugin-transform-svg-component" "^7.0.0"
|
"@svgr/babel-plugin-transform-svg-component" "^7.0.0"
|
||||||
|
|
||||||
"@svgr/core@*", "@svgr/core@^7.0.0":
|
|
||||||
version "7.0.0"
|
|
||||||
resolved "https://registry.npmjs.org/@svgr/core/-/core-7.0.0.tgz"
|
|
||||||
integrity sha512-ztAoxkaKhRVloa3XydohgQQCb0/8x9T63yXovpmHzKMkHO6pkjdsIAWKOS4bE95P/2quVh1NtjSKlMRNzSBffw==
|
|
||||||
dependencies:
|
|
||||||
"@babel/core" "^7.21.3"
|
|
||||||
"@svgr/babel-preset" "^7.0.0"
|
|
||||||
camelcase "^6.2.0"
|
|
||||||
cosmiconfig "^8.1.3"
|
|
||||||
|
|
||||||
"@svgr/core@^5.5.0":
|
"@svgr/core@^5.5.0":
|
||||||
version "5.5.0"
|
version "5.5.0"
|
||||||
resolved "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz"
|
resolved "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz"
|
||||||
@@ -2926,6 +2881,16 @@
|
|||||||
camelcase "^6.2.0"
|
camelcase "^6.2.0"
|
||||||
cosmiconfig "^7.0.0"
|
cosmiconfig "^7.0.0"
|
||||||
|
|
||||||
|
"@svgr/core@^7.0.0":
|
||||||
|
version "7.0.0"
|
||||||
|
resolved "https://registry.npmjs.org/@svgr/core/-/core-7.0.0.tgz"
|
||||||
|
integrity sha512-ztAoxkaKhRVloa3XydohgQQCb0/8x9T63yXovpmHzKMkHO6pkjdsIAWKOS4bE95P/2quVh1NtjSKlMRNzSBffw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/core" "^7.21.3"
|
||||||
|
"@svgr/babel-preset" "^7.0.0"
|
||||||
|
camelcase "^6.2.0"
|
||||||
|
cosmiconfig "^8.1.3"
|
||||||
|
|
||||||
"@svgr/hast-util-to-babel-ast@^5.5.0":
|
"@svgr/hast-util-to-babel-ast@^5.5.0":
|
||||||
version "5.5.0"
|
version "5.5.0"
|
||||||
resolved "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz"
|
resolved "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz"
|
||||||
@@ -3029,7 +2994,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz"
|
resolved "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz"
|
||||||
integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==
|
integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==
|
||||||
|
|
||||||
"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14", "@types/babel__core@^7.1.9":
|
"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14":
|
||||||
version "7.1.19"
|
version "7.1.19"
|
||||||
resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz"
|
resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz"
|
||||||
integrity sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==
|
integrity sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==
|
||||||
@@ -3137,11 +3102,6 @@
|
|||||||
"@types/qs" "*"
|
"@types/qs" "*"
|
||||||
"@types/serve-static" "*"
|
"@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":
|
"@types/graceful-fs@^4.1.2":
|
||||||
version "4.1.5"
|
version "4.1.5"
|
||||||
resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz"
|
resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz"
|
||||||
@@ -3149,7 +3109,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/hoist-non-react-statics@^3.3.1", "@types/hoist-non-react-statics@>= 3.3.1":
|
"@types/hoist-non-react-statics@^3.3.1":
|
||||||
version "3.3.1"
|
version "3.3.1"
|
||||||
resolved "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz"
|
resolved "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz"
|
||||||
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
|
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
|
||||||
@@ -3215,7 +3175,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/node@*", "@types/node@>= 12", "@types/node@>=12.12.47", "@types/node@>=13.7.0":
|
"@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0":
|
||||||
version "22.13.5"
|
version "22.13.5"
|
||||||
resolved "https://registry.npmjs.org/@types/node/-/node-22.13.5.tgz"
|
resolved "https://registry.npmjs.org/@types/node/-/node-22.13.5.tgz"
|
||||||
integrity sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==
|
integrity sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==
|
||||||
@@ -3257,7 +3217,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz"
|
resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz"
|
||||||
integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==
|
integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==
|
||||||
|
|
||||||
"@types/react@*", "@types/react@^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react@^18.2.25 || ^19", "@types/react@>= 16", "@types/react@16 || 17 || 18 || 19":
|
"@types/react@*", "@types/react@16 || 17 || 18 || 19":
|
||||||
version "18.3.18"
|
version "18.3.18"
|
||||||
resolved "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz"
|
resolved "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz"
|
||||||
integrity sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==
|
integrity sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==
|
||||||
@@ -3354,7 +3314,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/yargs-parser" "*"
|
"@types/yargs-parser" "*"
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin@^4.0.0 || ^5.0.0", "@typescript-eslint/eslint-plugin@^5.5.0":
|
"@typescript-eslint/eslint-plugin@^5.5.0":
|
||||||
version "5.62.0"
|
version "5.62.0"
|
||||||
resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz"
|
resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz"
|
||||||
integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==
|
integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==
|
||||||
@@ -3377,7 +3337,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/utils" "5.62.0"
|
"@typescript-eslint/utils" "5.62.0"
|
||||||
|
|
||||||
"@typescript-eslint/parser@^5.0.0", "@typescript-eslint/parser@^5.5.0":
|
"@typescript-eslint/parser@^5.5.0":
|
||||||
version "5.62.0"
|
version "5.62.0"
|
||||||
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz"
|
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz"
|
||||||
integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==
|
integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==
|
||||||
@@ -3612,16 +3572,16 @@ acorn-walk@^7.1.1:
|
|||||||
resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz"
|
resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz"
|
||||||
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
|
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
|
||||||
|
|
||||||
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.14.0, acorn@^8.2.4, acorn@^8.8.2, acorn@^8.9.0:
|
|
||||||
version "8.14.0"
|
|
||||||
resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz"
|
|
||||||
integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==
|
|
||||||
|
|
||||||
acorn@^7.1.1:
|
acorn@^7.1.1:
|
||||||
version "7.4.1"
|
version "7.4.1"
|
||||||
resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz"
|
resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz"
|
||||||
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
||||||
|
|
||||||
|
acorn@^8.14.0, acorn@^8.2.4, acorn@^8.8.2, acorn@^8.9.0:
|
||||||
|
version "8.14.0"
|
||||||
|
resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz"
|
||||||
|
integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==
|
||||||
|
|
||||||
address@^1.0.1, address@^1.1.2:
|
address@^1.0.1, address@^1.1.2:
|
||||||
version "1.2.2"
|
version "1.2.2"
|
||||||
resolved "https://registry.npmjs.org/address/-/address-1.2.2.tgz"
|
resolved "https://registry.npmjs.org/address/-/address-1.2.2.tgz"
|
||||||
@@ -3666,7 +3626,7 @@ ajv-keywords@^5.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fast-deep-equal "^3.1.3"
|
fast-deep-equal "^3.1.3"
|
||||||
|
|
||||||
ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.9.1:
|
ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5:
|
||||||
version "6.12.6"
|
version "6.12.6"
|
||||||
resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz"
|
resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz"
|
||||||
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
|
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
|
||||||
@@ -3686,7 +3646,7 @@ ajv@^8.0.0:
|
|||||||
json-schema-traverse "^1.0.0"
|
json-schema-traverse "^1.0.0"
|
||||||
require-from-string "^2.0.2"
|
require-from-string "^2.0.2"
|
||||||
|
|
||||||
ajv@^8.6.0, ajv@>=8:
|
ajv@^8.6.0:
|
||||||
version "8.17.1"
|
version "8.17.1"
|
||||||
resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz"
|
resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz"
|
||||||
integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==
|
integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==
|
||||||
@@ -3696,7 +3656,7 @@ ajv@^8.6.0, ajv@>=8:
|
|||||||
json-schema-traverse "^1.0.0"
|
json-schema-traverse "^1.0.0"
|
||||||
require-from-string "^2.0.2"
|
require-from-string "^2.0.2"
|
||||||
|
|
||||||
ajv@^8.8.2, ajv@^8.9.0:
|
ajv@^8.9.0:
|
||||||
version "8.17.1"
|
version "8.17.1"
|
||||||
resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz"
|
resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz"
|
||||||
integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==
|
integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==
|
||||||
@@ -4381,7 +4341,7 @@ browserify-sign@^4.2.3:
|
|||||||
readable-stream "^2.3.8"
|
readable-stream "^2.3.8"
|
||||||
safe-buffer "^5.2.1"
|
safe-buffer "^5.2.1"
|
||||||
|
|
||||||
browserslist@^4.0.0, browserslist@^4.18.1, browserslist@^4.21.4, browserslist@^4.23.3, browserslist@^4.24.0, browserslist@^4.25.0, "browserslist@>= 4", "browserslist@>= 4.21.0", browserslist@>=4:
|
browserslist@^4.0.0, browserslist@^4.18.1, browserslist@^4.21.4, browserslist@^4.23.3, browserslist@^4.24.0, browserslist@^4.25.0:
|
||||||
version "4.25.1"
|
version "4.25.1"
|
||||||
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz"
|
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz"
|
||||||
integrity sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==
|
integrity sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==
|
||||||
@@ -5170,7 +5130,7 @@ cssstyle@^2.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
cssom "~0.3.6"
|
cssom "~0.3.6"
|
||||||
|
|
||||||
csstype@^3.0.10, csstype@^3.0.2, csstype@^3.1.3:
|
csstype@^3.0.2, csstype@^3.1.3:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
|
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
|
||||||
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
||||||
@@ -5216,14 +5176,14 @@ data-view-byte-offset@^1.0.1:
|
|||||||
es-errors "^1.3.0"
|
es-errors "^1.3.0"
|
||||||
is-data-view "^1.0.1"
|
is-data-view "^1.0.1"
|
||||||
|
|
||||||
"date-fns@^2.25.0 || ^3.2.0 || ^4.0.0", date-fns@^2.30.0, "date-fns@>= 2.x":
|
date-fns@^2.30.0:
|
||||||
version "2.30.0"
|
version "2.30.0"
|
||||||
resolved "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz"
|
resolved "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz"
|
||||||
integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==
|
integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.21.0"
|
"@babel/runtime" "^7.21.0"
|
||||||
|
|
||||||
dayjs@^1.10.7, dayjs@^1.11.10, dayjs@^1.11.11, "dayjs@>= 1.x":
|
dayjs@^1.11.10, dayjs@^1.11.11:
|
||||||
version "1.11.13"
|
version "1.11.13"
|
||||||
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz"
|
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz"
|
||||||
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
|
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
|
||||||
@@ -6037,7 +5997,7 @@ eslint-webpack-plugin@^3.1.1:
|
|||||||
normalize-path "^3.0.0"
|
normalize-path "^3.0.0"
|
||||||
schema-utils "^4.0.0"
|
schema-utils "^4.0.0"
|
||||||
|
|
||||||
eslint@*, "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", "eslint@^6.0.0 || ^7.0.0 || ^8.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^7.0.0 || ^8.0.0", "eslint@^7.5.0 || ^8.0.0", eslint@^8.0.0, eslint@^8.1.0, eslint@^8.3.0, eslint@^8.38.0, "eslint@>= 6", eslint@>=7.0.0, eslint@>=7.28.0:
|
eslint@^8.3.0, eslint@^8.38.0:
|
||||||
version "8.57.1"
|
version "8.57.1"
|
||||||
resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz"
|
resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz"
|
||||||
integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==
|
integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==
|
||||||
@@ -7128,7 +7088,7 @@ intl-messageformat@10.7.18:
|
|||||||
"@formatjs/icu-messageformat-parser" "2.11.4"
|
"@formatjs/icu-messageformat-parser" "2.11.4"
|
||||||
tslib "^2.8.0"
|
tslib "^2.8.0"
|
||||||
|
|
||||||
invariant@^2.2.4, invariant@2.2.4:
|
invariant@^2.2.4:
|
||||||
version "2.2.4"
|
version "2.2.4"
|
||||||
resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz"
|
resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz"
|
||||||
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
|
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
|
||||||
@@ -7760,7 +7720,7 @@ jest-resolve-dependencies@^27.5.1:
|
|||||||
jest-regex-util "^27.5.1"
|
jest-regex-util "^27.5.1"
|
||||||
jest-snapshot "^27.5.1"
|
jest-snapshot "^27.5.1"
|
||||||
|
|
||||||
jest-resolve@*, jest-resolve@^27.4.2, jest-resolve@^27.5.1:
|
jest-resolve@^27.4.2, jest-resolve@^27.5.1:
|
||||||
version "27.5.1"
|
version "27.5.1"
|
||||||
resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz"
|
resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz"
|
||||||
integrity sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==
|
integrity sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==
|
||||||
@@ -7970,7 +7930,7 @@ jest-worker@^28.0.2:
|
|||||||
merge-stream "^2.0.0"
|
merge-stream "^2.0.0"
|
||||||
supports-color "^8.0.0"
|
supports-color "^8.0.0"
|
||||||
|
|
||||||
"jest@^27.0.0 || ^28.0.0", jest@^27.4.3:
|
jest@^27.4.3:
|
||||||
version "27.5.1"
|
version "27.5.1"
|
||||||
resolved "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz"
|
resolved "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz"
|
||||||
integrity sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==
|
integrity sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==
|
||||||
@@ -8167,11 +8127,6 @@ jwt-decode@^3.1.2:
|
|||||||
resolved "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz"
|
resolved "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz"
|
||||||
integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==
|
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==
|
|
||||||
|
|
||||||
keyv@^4.5.3:
|
keyv@^4.5.3:
|
||||||
version "4.5.4"
|
version "4.5.4"
|
||||||
resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz"
|
resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz"
|
||||||
@@ -8214,7 +8169,7 @@ launch-editor@^2.6.0:
|
|||||||
picocolors "^1.0.0"
|
picocolors "^1.0.0"
|
||||||
shell-quote "^1.8.1"
|
shell-quote "^1.8.1"
|
||||||
|
|
||||||
leaflet@^1.9.0, leaflet@^1.9.4:
|
leaflet@^1.9.4:
|
||||||
version "1.9.4"
|
version "1.9.4"
|
||||||
resolved "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz"
|
resolved "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz"
|
||||||
integrity sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==
|
integrity sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==
|
||||||
@@ -9663,15 +9618,6 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^
|
|||||||
resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz"
|
resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz"
|
||||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||||
|
|
||||||
"postcss@^7.0.0 || ^8.0.1", postcss@^8, postcss@^8.0.0, postcss@^8.0.3, postcss@^8.0.9, postcss@^8.1.0, postcss@^8.1.4, postcss@^8.2, postcss@^8.2.14, postcss@^8.2.15, postcss@^8.2.2, postcss@^8.3, postcss@^8.3.5, postcss@^8.4, postcss@^8.4.21, postcss@^8.4.33, postcss@^8.4.4, postcss@^8.4.47, postcss@^8.4.6, "postcss@>= 8", postcss@>=8, postcss@>=8.0.9:
|
|
||||||
version "8.5.3"
|
|
||||||
resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz"
|
|
||||||
integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==
|
|
||||||
dependencies:
|
|
||||||
nanoid "^3.3.8"
|
|
||||||
picocolors "^1.1.1"
|
|
||||||
source-map-js "^1.2.1"
|
|
||||||
|
|
||||||
postcss@^7.0.35:
|
postcss@^7.0.35:
|
||||||
version "7.0.39"
|
version "7.0.39"
|
||||||
resolved "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz"
|
resolved "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz"
|
||||||
@@ -9680,6 +9626,15 @@ postcss@^7.0.35:
|
|||||||
picocolors "^0.2.1"
|
picocolors "^0.2.1"
|
||||||
source-map "^0.6.1"
|
source-map "^0.6.1"
|
||||||
|
|
||||||
|
postcss@^8.3.5, postcss@^8.4.33, postcss@^8.4.4, postcss@^8.4.47:
|
||||||
|
version "8.5.3"
|
||||||
|
resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz"
|
||||||
|
integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==
|
||||||
|
dependencies:
|
||||||
|
nanoid "^3.3.8"
|
||||||
|
picocolors "^1.1.1"
|
||||||
|
source-map-js "^1.2.1"
|
||||||
|
|
||||||
prelude-ls@^1.2.1:
|
prelude-ls@^1.2.1:
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz"
|
resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz"
|
||||||
@@ -9697,7 +9652,7 @@ prettier-linter-helpers@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fast-diff "^1.1.2"
|
fast-diff "^1.1.2"
|
||||||
|
|
||||||
prettier@^2.8.7, prettier@>=2.0.0:
|
prettier@^2.8.7:
|
||||||
version "2.8.8"
|
version "2.8.8"
|
||||||
resolved "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz"
|
resolved "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz"
|
||||||
integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
|
integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
|
||||||
@@ -9759,7 +9714,7 @@ prompts@^2.0.1, prompts@^2.4.2:
|
|||||||
kleur "^3.0.3"
|
kleur "^3.0.3"
|
||||||
sisteransi "^1.0.5"
|
sisteransi "^1.0.5"
|
||||||
|
|
||||||
prop-types@^15.5.0, prop-types@^15.6.2, prop-types@^15.8.1:
|
prop-types@^15.6.2, prop-types@^15.8.1:
|
||||||
version "15.8.1"
|
version "15.8.1"
|
||||||
resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"
|
resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"
|
||||||
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
||||||
@@ -10317,7 +10272,7 @@ react-dnd@^16.0.1:
|
|||||||
fast-deep-equal "^3.1.3"
|
fast-deep-equal "^3.1.3"
|
||||||
hoist-non-react-statics "^3.3.2"
|
hoist-non-react-statics "^3.3.2"
|
||||||
|
|
||||||
react-dom@*, "react-dom@^16.8 || ^17 || ^18 || ^19", "react-dom@^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^18.0.0 || ^19.0.0", react-dom@^19.0.0, react-dom@^19.2.8, "react-dom@>= 0.14.0", 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@>=19.0.0:
|
react-dom@^19.2.8:
|
||||||
version "19.2.8"
|
version "19.2.8"
|
||||||
resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz"
|
resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz"
|
||||||
integrity sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==
|
integrity sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==
|
||||||
@@ -10334,21 +10289,6 @@ react-fast-compare@^2.0.1:
|
|||||||
resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz"
|
resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz"
|
||||||
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
|
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
|
||||||
|
|
||||||
react-geocode@^0.2.3:
|
|
||||||
version "0.2.3"
|
|
||||||
resolved "https://registry.npmjs.org/react-geocode/-/react-geocode-0.2.3.tgz"
|
|
||||||
integrity sha512-sIpbgmn1IUzAxO4haOZ6jeeFnMD8ya9PC38yiNrmJ9vPWbvAO2D/2yfCBzZjGZVUm4PRzKAc0KghXfaEnug0TQ==
|
|
||||||
dependencies:
|
|
||||||
regenerator-runtime "^0.13.3"
|
|
||||||
|
|
||||||
react-google-autocomplete@^2.7.3:
|
|
||||||
version "2.7.4"
|
|
||||||
resolved "https://registry.npmjs.org/react-google-autocomplete/-/react-google-autocomplete-2.7.4.tgz"
|
|
||||||
integrity sha512-BeEk2mjzgJcfiCueuKBofm5+RxHUIr0+POn9Yw8merK4Yd0jcOp9Lk/IGJySbz1GTi2Jqvi7V4dbw/DPLD1HMA==
|
|
||||||
dependencies:
|
|
||||||
lodash.debounce "^4.0.8"
|
|
||||||
prop-types "^15.5.0"
|
|
||||||
|
|
||||||
react-icons@^4.12.0:
|
react-icons@^4.12.0:
|
||||||
version "4.12.0"
|
version "4.12.0"
|
||||||
resolved "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz"
|
resolved "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz"
|
||||||
@@ -10410,7 +10350,7 @@ react-loading-icons@^1.1.0:
|
|||||||
resolved "https://registry.npmjs.org/react-loading-icons/-/react-loading-icons-1.1.0.tgz"
|
resolved "https://registry.npmjs.org/react-loading-icons/-/react-loading-icons-1.1.0.tgz"
|
||||||
integrity sha512-Y9eZ6HAufmUd8DIQd6rFrx5Bt/oDlTM9Nsjvf8YpajTa3dI8cLNU8jUN5z7KTANU+Yd6/KJuBjxVlrU2dMw33g==
|
integrity sha512-Y9eZ6HAufmUd8DIQd6rFrx5Bt/oDlTM9Nsjvf8YpajTa3dI8cLNU8jUN5z7KTANU+Yd6/KJuBjxVlrU2dMw33g==
|
||||||
|
|
||||||
"react-redux@^7.2.1 || ^8.1.3 || ^9.0.0", react-redux@^9.2.0:
|
react-redux@^9.2.0:
|
||||||
version "9.2.0"
|
version "9.2.0"
|
||||||
resolved "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz"
|
resolved "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz"
|
||||||
integrity sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==
|
integrity sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==
|
||||||
@@ -10418,7 +10358,7 @@ react-loading-icons@^1.1.0:
|
|||||||
"@types/use-sync-external-store" "^0.0.6"
|
"@types/use-sync-external-store" "^0.0.6"
|
||||||
use-sync-external-store "^1.4.0"
|
use-sync-external-store "^1.4.0"
|
||||||
|
|
||||||
react-refresh@^0.11.0, "react-refresh@>=0.10.0 <1.0.0":
|
react-refresh@^0.11.0:
|
||||||
version "0.11.0"
|
version "0.11.0"
|
||||||
resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz"
|
resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz"
|
||||||
integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==
|
integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==
|
||||||
@@ -10438,7 +10378,7 @@ react-router@^6.10.0, react-router@6.29.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@remix-run/router" "1.22.0"
|
"@remix-run/router" "1.22.0"
|
||||||
|
|
||||||
react-scripts@^5.0.1, react-scripts@>=2.1.3:
|
react-scripts@^5.0.1:
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz"
|
resolved "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz"
|
||||||
integrity sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==
|
integrity sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==
|
||||||
@@ -10513,7 +10453,7 @@ react-transition-group@^4.4.5:
|
|||||||
loose-envify "^1.4.0"
|
loose-envify "^1.4.0"
|
||||||
prop-types "^15.6.2"
|
prop-types "^15.6.2"
|
||||||
|
|
||||||
react@*, "react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ~19", "react@^16.9.0 || ^17.0.0 || ^18 || ^19", "react@^17.0.0 || ^18.0.0 || ^19.0.0", "react@^18 || ^19", "react@^18.0 || ^19", "react@^18.0.0 || ^19.0.0", react@^19.0.0, react@^19.2.8, "react@>= 0.14.0", "react@>= 16", "react@>= 16.14", react@>=16.0.0, react@>=16.11.0, react@>=16.6.0, react@>=16.8, react@>=16.8.0, react@>=16.9.0, react@>=19, react@>=19.0.0, "react@16 || 17 || 18 || 19":
|
react@^19.2.8:
|
||||||
version "19.2.8"
|
version "19.2.8"
|
||||||
resolved "https://registry.npmjs.org/react/-/react-19.2.8.tgz"
|
resolved "https://registry.npmjs.org/react/-/react-19.2.8.tgz"
|
||||||
integrity sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==
|
integrity sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==
|
||||||
@@ -10582,7 +10522,7 @@ redux@^4.2.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.9.2"
|
"@babel/runtime" "^7.9.2"
|
||||||
|
|
||||||
redux@^5.0.0, redux@^5.0.1:
|
redux@^5.0.1:
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz"
|
resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz"
|
||||||
integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==
|
integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==
|
||||||
@@ -10613,11 +10553,6 @@ regenerate@^1.4.2:
|
|||||||
resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz"
|
resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz"
|
||||||
integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
|
integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
|
||||||
|
|
||||||
regenerator-runtime@^0.13.3:
|
|
||||||
version "0.13.11"
|
|
||||||
resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz"
|
|
||||||
integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
|
|
||||||
|
|
||||||
regenerator-runtime@^0.13.9:
|
regenerator-runtime@^0.13.9:
|
||||||
version "0.13.11"
|
version "0.13.11"
|
||||||
resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz"
|
resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz"
|
||||||
@@ -10801,7 +10736,7 @@ rollup-plugin-terser@^7.0.0:
|
|||||||
serialize-javascript "^4.0.0"
|
serialize-javascript "^4.0.0"
|
||||||
terser "^5.0.0"
|
terser "^5.0.0"
|
||||||
|
|
||||||
"rollup@^1.20.0 || ^2.0.0", rollup@^1.20.0||^2.0.0, rollup@^2.0.0, rollup@^2.43.1:
|
rollup@^2.43.1:
|
||||||
version "2.79.2"
|
version "2.79.2"
|
||||||
resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz"
|
resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz"
|
||||||
integrity sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==
|
integrity sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==
|
||||||
@@ -11566,7 +11501,7 @@ stylis-plugin-rtl@^2.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
cssjanus "^2.0.1"
|
cssjanus "^2.0.1"
|
||||||
|
|
||||||
stylis@^4.3.4, stylis@4.x:
|
stylis@^4.3.4:
|
||||||
version "4.3.6"
|
version "4.3.6"
|
||||||
resolved "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz"
|
resolved "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz"
|
||||||
integrity sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==
|
integrity sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==
|
||||||
@@ -11594,13 +11529,6 @@ sucrase@^3.35.0:
|
|||||||
pirates "^4.0.1"
|
pirates "^4.0.1"
|
||||||
ts-interface-checker "^0.1.9"
|
ts-interface-checker "^0.1.9"
|
||||||
|
|
||||||
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:
|
supports-color@^5.3.0:
|
||||||
version "5.5.0"
|
version "5.5.0"
|
||||||
resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
|
resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
|
||||||
@@ -11942,7 +11870,7 @@ type-fest@^0.20.2:
|
|||||||
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz"
|
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz"
|
||||||
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
|
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
|
||||||
|
|
||||||
type-fest@^0.21.3, "type-fest@>=0.17.0 <4.0.0":
|
type-fest@^0.21.3:
|
||||||
version "0.21.3"
|
version "0.21.3"
|
||||||
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz"
|
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz"
|
||||||
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
|
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
|
||||||
@@ -12012,11 +11940,6 @@ typedarray-to-buffer@^3.1.5:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-typedarray "^1.0.0"
|
is-typedarray "^1.0.0"
|
||||||
|
|
||||||
"typescript@^3.2.1 || ^4", typescript@^5.6.0, "typescript@>= 2.7", "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta", typescript@>=4.9.5:
|
|
||||||
version "5.9.3"
|
|
||||||
resolved "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz"
|
|
||||||
integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==
|
|
||||||
|
|
||||||
ua-parser-js@^1.0.33:
|
ua-parser-js@^1.0.33:
|
||||||
version "1.0.40"
|
version "1.0.40"
|
||||||
resolved "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.40.tgz"
|
resolved "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.40.tgz"
|
||||||
@@ -12257,7 +12180,7 @@ webpack-dev-middleware@^5.3.4:
|
|||||||
range-parser "^1.2.1"
|
range-parser "^1.2.1"
|
||||||
schema-utils "^4.0.0"
|
schema-utils "^4.0.0"
|
||||||
|
|
||||||
webpack-dev-server@^4.6.0, "webpack-dev-server@3.x || 4.x":
|
webpack-dev-server@^4.6.0:
|
||||||
version "4.15.2"
|
version "4.15.2"
|
||||||
resolved "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz"
|
resolved "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz"
|
||||||
integrity sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==
|
integrity sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==
|
||||||
@@ -12322,7 +12245,7 @@ webpack-sources@^3.2.3:
|
|||||||
resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz"
|
resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz"
|
||||||
integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
|
integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
|
||||||
|
|
||||||
"webpack@^4.0.0 || ^5.0.0", "webpack@^4.37.0 || ^5.0.0", "webpack@^4.4.0 || ^5.9.0", "webpack@^4.44.2 || ^5.47.0", webpack@^5.0.0, webpack@^5.1.0, webpack@^5.20.0, webpack@^5.64.4, "webpack@>= 4", webpack@>=2, "webpack@>=4.43.0 <6.0.0":
|
webpack@^5.64.4:
|
||||||
version "5.98.0"
|
version "5.98.0"
|
||||||
resolved "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz"
|
resolved "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz"
|
||||||
integrity sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==
|
integrity sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==
|
||||||
|
|||||||
Reference in New Issue
Block a user