commit c36f2d5b1dbd8e3ea46c60944ac855416c043625 Author: Thiru-tenext Date: Wed Jul 1 17:49:49 2026 +0530 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/README.md b/README.md new file mode 100644 index 0000000..f768e33 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# React + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..964a299 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,38 @@ +import js from '@eslint/js' +import globals from 'globals' +import react from 'eslint-plugin-react' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' + +export default [ + { + files: ['**/*.{js,jsx}'], + ignores: ['dist'], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + parserOptions: { + ecmaVersion: 'latest', + ecmaFeatures: { jsx: true }, + sourceType: 'module', + }, + }, + settings: { react: { version: '18.3' } }, + plugins: { + react, + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...js.configs.recommended.rules, + ...react.configs.recommended.rules, + ...react.configs['jsx-runtime'].rules, + ...reactHooks.configs.recommended.rules, + 'react/jsx-no-target-blank': 'off', + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, + }, +] diff --git a/index.html b/index.html new file mode 100644 index 0000000..011eee2 --- /dev/null +++ b/index.html @@ -0,0 +1,21 @@ + + + + + + + + + + + + Doormile Hub Console + + +
+ + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..af33834 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5459 @@ +{ + "name": "doormile-hub", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "doormile-hub", + "version": "0.0.0", + "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@mui/icons-material": "^9.1.1", + "@mui/material": "^9.1.1", + "dayjs": "^1.11.21", + "leaflet": "^1.9.4", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-leaflet": "^4.2.1", + "react-router-dom": "^6.30.4" + }, + "devDependencies": { + "@eslint/js": "^9.8.0", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", + "eslint": "^9.8.0", + "eslint-plugin-react": "^7.35.0", + "eslint-plugin-react-hooks": "^5.1.0-rc.0", + "eslint-plugin-react-refresh": "^0.4.9", + "globals": "^15.9.0", + "postcss": "^8.5.15", + "vite": "^5.4.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz", + "integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/styled": { + "version": "11.14.1", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", + "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mui/core-downloads-tracker": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-9.1.1.tgz", + "integrity": "sha512-AupmMICbdJHqAh6FfOMaaiiIr7dfEgZJn5DFfiPuGNrbs+ZZy9cD1APwO0TSVBz5j08MJEEY6n7iC76/2wjMEA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-9.1.1.tgz", + "integrity": "sha512-OXhm9DajemStb58AumM06DuPhHTa3XD36TFD4yf6WtJyNRO5DfEZbbnHlBg/US2Y2oOXwM/XurMTBOD6L/YYZw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^9.1.1", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-9.1.1.tgz", + "integrity": "sha512-Wv+gInjrpf99l1Q0oHe0eOWGTnlbkzs5nowClX65KCT/2fyPMwcbFEEkUsOHdpcHhB5UAbz/d7jlwt5ajWVvlA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@mui/core-downloads-tracker": "^9.1.1", + "@mui/system": "^9.1.1", + "@mui/types": "^9.1.1", + "@mui/utils": "^9.1.1", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "csstype": "^3.2.3", + "prop-types": "^15.8.1", + "react-is": "^19.2.6", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material-pigment-css": "^9.1.1", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/private-theming": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-9.1.1.tgz", + "integrity": "sha512-oH6c+d6sJ1CZT0Vg2/fHdUQ5zvo9Pn+f+WWk0tlQliHqqIRdN32DZ7UxjalW3LUj4OkHbdWR31biWuLxK9i7Cg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@mui/utils": "^9.1.1", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-9.1.1.tgz", + "integrity": "sha512-neaYKdJfvEG54q8efHLJR7swpHG/gfSv9xGqW5iTSMsubD7yPCPFrhVBt284j1DOF3uZaaDJSHQL7gz6jGF21Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.2.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-9.1.1.tgz", + "integrity": "sha512-q+aqNa58QZUwmmyUvJKKrStrej+4BcWFw4M0Ug+zRylPIQgR64cqvBnE3QTfLZm4OXulydp8Hl3zwKxMayrdsA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@mui/private-theming": "^9.1.1", + "@mui/styled-engine": "^9.1.1", + "@mui/types": "^9.1.1", + "@mui/utils": "^9.1.1", + "clsx": "^2.1.1", + "csstype": "^3.2.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-9.1.1.tgz", + "integrity": "sha512-Zjt7u8wNvDg40rPTGoL+TnfkpuSKjwubsNSFRH1KAVZLcaV4I3AFNHIFbvH7p4F3alEibSbdd90xAgn5Rnfndg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-9.1.1.tgz", + "integrity": "sha512-qSNfnkzZMptaaWFFklpDf4NPJztgwsMDVfM/sSDt+wq4ssYSBhLYwwjuB6eS/+p2IUYbeRzHluzXbw0Zn7aI4A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@mui/types": "^9.1.1", + "@types/prop-types": "^15.7.15", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.2.6" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@react-leaflet/core": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz", + "integrity": "sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==", + "license": "Hippocratic-2.1", + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@remix-run/router": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.3.tgz", + "integrity": "sha512-4An71tdz9X8+3sI4Qqqd2LWd9vS39J7sqd9EU4Scw7TJE/qB10Flv/UuqbPVgfQV9XoK8Np6jNquZitnZq5i+Q==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", + "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.31", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.31.tgz", + "integrity": "sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==", + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.38", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.38.tgz", + "integrity": "sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.28.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz", + "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.38", + "caniuse-lite": "^1.0.30001799", + "electron-to-chromium": "^1.5.376", + "node-releases": "^2.0.48", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001799", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dayjs": { + "version": "1.11.21", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz", + "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.377", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.377.tgz", + "integrity": "sha512-cH1jZgJHoezfTnKfKwnScpHywTFVnJUNITDPREFdhNjiuD502+QFpG0Qk7G8jhsV/f+CEAFlIrzP1fT+IMb92g==", + "dev": true, + "license": "ISC" + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract-get": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", + "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "is-callable": "^1.2.7", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.3.tgz", + "integrity": "sha512-0PuBxFi+4uPanB97iDxCLWuHeYud2FALrw5HFZGtAF38UpJDbDC8frwp2cnDyae692CQ0dou60UwWfhgsa4U/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.1.tgz", + "integrity": "sha512-CxN9N56HYfd2m/acc/NOFrZQsN9kU4eh+2kk6A707Kz1krH8tKmfrs5RnftB8WNX80T0NS7vSQsDOlg23diR2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-abstract-get": "^1.0.0", + "es-errors": "^1.3.0", + "is-callable": "^1.2.7", + "is-date-object": "^1.1.0", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.26", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz", + "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/leaflet": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", + "license": "BSD-2-Clause" + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", + "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-exports-info": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz", + "integrity": "sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-releases": { + "version": "2.0.48", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.48.tgz", + "integrity": "sha512-1uz8041X6LoI6ZSdZacM9lVY28vuzDlSKitnpbSNK0RfKoIJkX29NBPVEFXhnuSuEOA9Ww0xnPJ+ILWbGAv8DA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.7.tgz", + "integrity": "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==", + "license": "MIT" + }, + "node_modules/react-leaflet": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.2.1.tgz", + "integrity": "sha512-p9chkvhcKrWn/H/1FFeVSqLdReGwn2qmiobOQGO3BifX+/vV/39qhY8dGqbdcPh1e6jxh/QHriLXr7a4eLFK4Q==", + "license": "Hippocratic-2.1", + "dependencies": { + "@react-leaflet/core": "^2.1.0" + }, + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "6.30.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.4.tgz", + "integrity": "sha512-SVUsDe+DybHM/WmYKIVYhZh1o5Dcuf16yM6WjG02Q9XVFMZIJyHYhwrr6bFBXZkVP6z69kNkMyBCujt8FaFLJA==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.30.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.4.tgz", + "integrity": "sha512-q4HvNl+mmDdkS0g+MqiBZNteQJCuimWoOyHMy4T/RQLAn9Z29+E91QXRaxOujeMl2HTzRSS0KFPd7lxX3PjV0Q==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.3", + "react-router": "6.30.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/rollup": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", + "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..7a70a8b --- /dev/null +++ b/package.json @@ -0,0 +1,37 @@ +{ + "name": "doormile-hub", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@mui/icons-material": "^9.1.1", + "@mui/material": "^9.1.1", + "dayjs": "^1.11.21", + "leaflet": "^1.9.4", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-leaflet": "^4.2.1", + "react-router-dom": "^6.30.4" + }, + "devDependencies": { + "@eslint/js": "^9.8.0", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", + "eslint": "^9.8.0", + "eslint-plugin-react": "^7.35.0", + "eslint-plugin-react-hooks": "^5.1.0-rc.0", + "eslint-plugin-react-refresh": "^0.4.9", + "globals": "^15.9.0", + "postcss": "^8.5.15", + "vite": "^5.4.0" + } +} diff --git a/public/Doormile-logo.png b/public/Doormile-logo.png new file mode 100644 index 0000000..1cbe324 Binary files /dev/null and b/public/Doormile-logo.png differ diff --git a/public/preloader.png b/public/preloader.png new file mode 100644 index 0000000..92cb60e Binary files /dev/null and b/public/preloader.png differ diff --git a/public/vite.svg b/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 0000000..6eea70c --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,49 @@ +import { Suspense, lazy } from 'react'; +import { Routes, Route, Navigate } from 'react-router-dom'; +import { Box, CircularProgress } from '@mui/material'; + +import MainLayout from '@/layout/MainLayout'; +import MinimalLayout from '@/layout/MinimalLayout'; + +const load = (factory) => { + const C = lazy(factory); + return ( + + + + } + > + + + ); +}; + +export default function App() { + return ( + + {/* Shell pages */} + }> + import('@/pages/Dashboard'))} /> + import('@/pages/operations/Inbound'))} /> + import('@/pages/operations/Routing'))} /> + import('@/pages/operations/Dispatch'))} /> + import('@/pages/operations/Inventory'))} /> + import('@/pages/operations/TrackingMap'))} /> + import('@/pages/operations/OrderAssignment'))} /> + import('@/pages/operations/Riders'))} /> + import('@/pages/operations/RiderRoutes'))} /> + + + {/* Full-bleed pages */} + }> + import('@/pages/auth/Login'))} /> + import('@/pages/auth/Signup'))} /> + + + } /> + } /> + + ); +} diff --git a/src/assets/react.svg b/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/Logo.jsx b/src/components/Logo.jsx new file mode 100644 index 0000000..98d00da --- /dev/null +++ b/src/components/Logo.jsx @@ -0,0 +1,51 @@ +import { Box, Typography } from '@mui/material'; + +// ==============================|| DOORMILE WORDMARK LOGO ||============================== // +// Uses the brand wordmark asset (white PNG). `onDark` shows it as-is on dark/red +// surfaces; on light surfaces it is recoloured to near-black. `compact` (e.g. the +// collapsed sidebar) renders just the square "D" badge, since the wordmark won't fit. + +const LOGO_SRC = '/Doormile-logo.png'; + +export default function Logo({ onDark = false, compact = false, height = 26, sx }) { + if (compact) { + const mark = onDark ? '#FFFFFF' : '#C01227'; + const markText = onDark ? '#C01227' : '#FFFFFF'; + return ( + + + D + + + ); + } + + return ( + + + + ); +} diff --git a/src/components/PageHeader.jsx b/src/components/PageHeader.jsx new file mode 100644 index 0000000..85ea55a --- /dev/null +++ b/src/components/PageHeader.jsx @@ -0,0 +1,81 @@ +import { Box, Stack, Typography, Avatar } from '@mui/material'; + +// ==============================|| SHARED PAGE HEADER ||============================== // + +export default function PageHeader({ icon: Icon, title, subtitle, action }) { + return ( + + + {Icon && ( + + + + )} + + + + {title} + + + {subtitle && ( + + {subtitle} + + )} + + + + {action && ( + + {action} + + )} + + ); +} \ No newline at end of file diff --git a/src/layout/MainLayout/Header.jsx b/src/layout/MainLayout/Header.jsx new file mode 100644 index 0000000..671a137 --- /dev/null +++ b/src/layout/MainLayout/Header.jsx @@ -0,0 +1,516 @@ +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { + AppBar, + Toolbar, + IconButton, + Box, + InputBase, + Badge, + Avatar, + Typography, + Menu, + MenuItem, + Divider, + ListItemIcon, + ListItemText, + Tooltip, + Button, + Stack, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + TextField, + Grid, + alpha, + InputAdornment +} from '@mui/material'; +import MenuIcon from '@mui/icons-material/Menu'; +import SearchIcon from '@mui/icons-material/Search'; +import NotificationsNoneIcon from '@mui/icons-material/NotificationsNone'; +import ChatIcon from '@mui/icons-material/Chat'; +import LogoutIcon from '@mui/icons-material/Logout'; +import LocalShippingOutlinedIcon from '@mui/icons-material/LocalShippingOutlined'; +import QrCodeScannerIcon from '@mui/icons-material/QrCodeScanner'; +import AcUnitIcon from '@mui/icons-material/AcUnit'; +import TwoWheelerIcon from '@mui/icons-material/TwoWheeler'; +import DoneAllIcon from '@mui/icons-material/DoneAll'; +import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; +import SendIcon from '@mui/icons-material/Send'; + +import Logo from '@/components/Logo'; + +const RED = '#C01227'; + +const INITIAL_NOTIFICATIONS = [ + { id: 1, icon: LocalShippingOutlinedIcon, title: 'Linehaul MH-04-AX-8822 from Mumbai Hub arrived', time: '5 min ago', to: '/inbound', read: false }, + { id: 2, icon: QrCodeScannerIcon, title: 'Manifest #MNF-2940 sorted & sealed', time: '15 min ago', to: '/dispatch', read: false }, + { id: 3, icon: TwoWheelerIcon, title: 'Last-mile Miler Deepak went online', time: '30 min ago', to: '/dispatch', read: false }, + { id: 4, icon: AcUnitIcon, title: 'Cold Storage Zone C temperature stabilized at 4.2°C', time: '1 hr ago', to: '/inventory', read: true } +]; + +const MESSAGES = [ + { id: 1, name: 'Devendra (Gate Supervisor)', text: 'Jaipur vehicle is backing into Bay 4 now.', time: '3 min ago', initials: 'DS' }, + { id: 2, name: 'Suresh (Sorter Zone A)', text: 'Completed sorting for South Delhi batch. Ready to verify.', time: '12 min ago', initials: 'SS' }, + { id: 3, name: 'Neha (Last-mile Dispatcher)', text: 'We need 2 more milers for South Delhi route.', time: '45 min ago', initials: 'ND' } +]; + +const NOTIFICATION_DETAILS = { + 1: { + title: 'Linehaul Arrival: Mumbai Hub', + desc: 'Linehaul vehicle MH-04-AX-8822 has checked in at gate terminal Bay 4. Manifest includes 480 mixed corporate shipments.', + stats: [ + { label: 'Carrier Plate', value: 'MH-04-AX-8822' }, + { label: 'Origin Node', value: 'Mumbai Hub (BOM-02)' }, + { label: 'Inbound Sorters', value: 'Allocated (Zone A & C)' }, + { label: 'Cold Chain items', value: '18 items binned' } + ], + actionText: 'Go to Inbound Station', + to: '/inbound' + }, + 2: { + title: 'Sealed Outbound Manifest #MNF-2940', + desc: 'Sorting manifest #MNF-2940 has been closed, sealed, and audited by supervisor Suresh. Packages are loaded in transit cart.', + stats: [ + { label: 'Manifest ID', value: 'MNF-2940' }, + { label: 'Route Zone', value: 'West Delhi (Dwarka)' }, + { label: 'Packages Count', value: '42 items loaded' }, + { label: 'Seal ID Code', value: 'SEAL-DEL-98402' } + ], + actionText: 'Go to Outbound Dispatch', + to: '/dispatch' + }, + 3: { + title: 'Miler Deepak Sharma Online', + desc: 'Last-mile EV miler Deepak Sharma logged into transit terminal app. Courier battery capacity 98% (Fully Charged).', + stats: [ + { label: 'Miler Name', value: 'Deepak Sharma' }, + { label: 'Vehicle Class', value: 'EV Two-wheeler' }, + { label: 'Capacity Limit', value: '35 kg' }, + { label: 'Assigned Route', value: 'South Delhi (Saket)' } + ], + actionText: 'Go to Outbound Dispatch', + to: '/dispatch' + }, + 4: { + title: 'Cold Storage Compliance Logged', + desc: 'Sensor Zone C logged audit snapshot at 12:00 PM. Climate check parameters successfully verified at 4.2°C.', + stats: [ + { label: 'Chamber Area', value: 'Cold Zone Chamber C' }, + { label: 'Sensor Reading', value: '4.2°C (Target: 2-8°C)' }, + { label: 'Log ID', value: 'LOG-C-98248102' }, + { label: 'Status', value: 'Optimal Compliance' } + ], + actionText: 'Go to Storage & Bins', + to: '/inventory' + } +}; + +const INITIAL_CHATS = { + 1: { + name: 'Devendra (Gate Supervisor)', + initials: 'DS', + chat: [ + { sender: 'them', text: 'Jaipur vehicle is backing into Bay 4 now. Sorters are ready.', time: '11:20 AM' }, + { sender: 'me', text: 'Excellent. Please verify temperature logs for the cold container immediately upon opening.', time: '11:21 AM' }, + { sender: 'them', text: 'Got it, Rajesh. Handled by sorter Devendra.', time: '11:22 AM' } + ] + }, + 2: { + name: 'Suresh (Sorter Zone A)', + initials: 'SS', + chat: [ + { sender: 'them', text: 'Completed sorting for South Delhi batch. Ready to verify.', time: '11:10 AM' }, + { sender: 'me', text: 'Have all exceptions been routed to Zone D?', time: '11:12 AM' }, + { sender: 'them', text: 'Yes, 3 damaged boxes are in Zone D. Rest are loaded in the manifest bags.', time: '11:15 AM' } + ] + }, + 3: { + name: 'Neha (Last-mile Dispatcher)', + initials: 'ND', + chat: [ + { sender: 'them', text: 'We need 2 more milers for South Delhi route. Surge in fashion orders.', time: '10:40 AM' }, + { sender: 'me', text: 'Let me ping Deepak and Yashpal to see if they can start early shift.', time: '10:45 AM' }, + { sender: 'them', text: 'Deepak just logged online. Still need one more.', time: '11:05 AM' } + ] + } +}; + +export default function Header({ onToggle }) { + const navigate = useNavigate(); + const [account, setAccount] = useState(null); + const [notifAnchor, setNotifAnchor] = useState(null); + const [msgAnchor, setMsgAnchor] = useState(null); + + // Dialog State + const [selectedNotif, setSelectedNotif] = useState(null); + const [selectedChatId, setSelectedChatId] = useState(null); + const [chats, setChats] = useState(INITIAL_CHATS); + const [typedMessage, setTypedMessage] = useState(''); + + const [notifications, setNotifications] = useState(INITIAL_NOTIFICATIONS); + const [search, setSearch] = useState(''); + + const unread = notifications.filter((n) => !n.read).length; + + const openNotif = (e) => setNotifAnchor(e.currentTarget); + const closeNotif = () => setNotifAnchor(null); + const markAllRead = () => setNotifications((prev) => prev.map((n) => ({ ...n, read: true }))); + + const onNotifClick = (n) => { + setNotifications((prev) => prev.map((x) => (x.id === n.id ? { ...x, read: true } : x))); + closeNotif(); + if (NOTIFICATION_DETAILS[n.id]) { + setSelectedNotif(NOTIFICATION_DETAILS[n.id]); + } else { + navigate(n.to); + } + }; + + const onMessageClick = (mId) => { + setMsgAnchor(null); + setSelectedChatId(mId); + }; + + const handleSendMessage = () => { + if (!typedMessage.trim() || !selectedChatId) return; + const now = new Date(); + const timeStr = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); + + setChats((prev) => { + const activeChat = prev[selectedChatId]; + return { + ...prev, + [selectedChatId]: { + ...activeChat, + chat: [ + ...activeChat.chat, + { sender: 'me', text: typedMessage, time: timeStr } + ] + } + }; + }); + setTypedMessage(''); + }; + + const submitSearch = (e) => { + e.preventDefault(); + const q = search.trim(); + if (q) navigate(`/routing?q=${encodeURIComponent(q)}`); + }; + + return ( + t.zIndex.drawer + 1, + borderBottom: '1px solid', + borderColor: 'grey.200' + }} + > + + + + + + {/* Brand wordmark — left side */} + navigate('/dashboard')} + sx={{ display: 'flex', alignItems: 'center', cursor: 'pointer' }} + > + + + + + + {/* Search */} + + + setSearch(e.target.value)} + placeholder="Scan package, check destination…" + sx={{ fontSize: '0.875rem', flex: 1 }} + inputProps={{ 'aria-label': 'search' }} + /> + + + + setMsgAnchor(e.currentTarget)}> + + + + + + + + + + + + + + setAccount(e.currentTarget)} + sx={{ + display: 'flex', + alignItems: 'center', + gap: 1, + ml: 0.5, + cursor: 'pointer', + py: 0.5, + px: 1, + borderRadius: 2, + '&:hover': { bgcolor: 'grey.100' } + }} + > + RK + + + Rajesh Kumar + + + Delhi Hub Manager + + + + + {/* Notifications dropdown */} + + + + Notifications + + + + + {notifications.length === 0 && ( + + + + )} + {notifications.map((n) => { + const Icon = n.icon; + return ( + onNotifClick(n)} sx={{ py: 1.25, whiteSpace: 'normal', alignItems: 'flex-start' }}> + + + + + + + {!n.read && } + + ); + })} + + + {/* Messages dropdown */} + setMsgAnchor(null)} + transformOrigin={{ horizontal: 'right', vertical: 'top' }} + anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }} + PaperProps={{ sx: { mt: 1, width: 340, maxWidth: '90vw' } }} + > + + Messages + + + {MESSAGES.map((m) => ( + onMessageClick(m.id)} sx={{ py: 1.25, whiteSpace: 'normal', alignItems: 'flex-start' }}> + + + {m.initials} + + + + + {m.time} + + + ))} + + + {/* Account dropdown */} + setAccount(null)} + transformOrigin={{ horizontal: 'right', vertical: 'top' }} + anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }} + PaperProps={{ sx: { mt: 1, minWidth: 200 } }} + > + { setAccount(null); navigate('/login'); }} sx={{ color: 'error.main' }}> + + Logout + + + + + {/* High Fidelity Notification Detail Dialog */} + setSelectedNotif(null)} fullWidth maxWidth="sm"> + {selectedNotif && ( + <> + + {selectedNotif.title} + + + + + {selectedNotif.desc} + + + Operational Details + + + {selectedNotif.stats.map((stat, index) => ( + + + + {stat.label} + + + {stat.value} + + + + ))} + + + + + + + + + )} + + + {/* High Fidelity Chat Message Dialog */} + setSelectedChatId(null)} fullWidth maxWidth="xs"> + {selectedChatId && chats[selectedChatId] && ( + <> + + + {chats[selectedChatId].initials} + + + {chats[selectedChatId].name} + + + + + + {chats[selectedChatId].chat.map((msg, idx) => ( + + + + {msg.text} + + + + {msg.time} + + + ))} + + + + + setTypedMessage(e.target.value)} + onKeyDown={(e) => e.key === 'Enter' && handleSendMessage()} + InputProps={{ + endAdornment: ( + + + + + + ) + }} + /> + + + )} + + + ); +} diff --git a/src/layout/MainLayout/Sidebar.jsx b/src/layout/MainLayout/Sidebar.jsx new file mode 100644 index 0000000..743cea1 --- /dev/null +++ b/src/layout/MainLayout/Sidebar.jsx @@ -0,0 +1,310 @@ +import { useState, useMemo } from 'react'; +import { useLocation, useNavigate } from 'react-router-dom'; +import { + Drawer, + Box, + List, + ListItemButton, + ListItemIcon, + ListItemText, + Typography, + Collapse, + Tooltip, + Toolbar +} from '@mui/material'; +import { alpha } from '@mui/material/styles'; +import ExpandLess from '@mui/icons-material/ExpandLess'; +import ExpandMore from '@mui/icons-material/ExpandMore'; +import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord'; + +import navItems from '@/menu/navItems'; +import Logo from '@/components/Logo'; + +export const DRAWER_WIDTH = 240; +export const MINI_WIDTH = 72; + +const BRAND_RED = '#C01227'; + +function NavLeaf({ item, open, active, depth = 0, onClick }) { + const Icon = item.icon; + + const button = ( + theme.transitions.create(['background-color', 'color', 'padding'], { + duration: theme.transitions.duration.shorter, + }), + '& .MuiListItemIcon-root': { + color: active ? BRAND_RED : 'text.secondary', + minWidth: open ? 32 : 0, + justifyContent: 'center' + }, + '&:hover': { + bgcolor: 'action.hover', + color: 'text.primary', + '& .MuiListItemIcon-root': { color: 'text.primary' } + }, + '&.Mui-selected': { + bgcolor: alpha(BRAND_RED, 0.08), + color: BRAND_RED, + '& .MuiListItemIcon-root': { color: BRAND_RED }, + '&:hover': { bgcolor: alpha(BRAND_RED, 0.12) } + } + }} + > + + {depth > 0 && !Icon ? ( + + ) : Icon ? ( + + ) : null} + + + {open && ( + + )} + + ); + + if (!open) { + return ( + + {button} + + ); + } + + return button; +} + +export default function Sidebar({ open, mobileOpen, onMobileClose, isMobile }) { + const location = useLocation(); + const navigate = useNavigate(); + const expanded = open || isMobile; + + const isActive = (url) => !!(url && location.pathname.startsWith(url)); + + // Memoize initial open state to prevent recalculation on every drawer toggle + const initialOpen = useMemo(() => { + return navItems + .flatMap((g) => g.items) + .filter((i) => i.children && i.children.some((c) => isActive(c.url))) + .map((i) => i.id); + }, [location.pathname]); + + const [collapse, setCollapse] = useState(initialOpen); + + const handleToggleCollapse = (id) => { + setCollapse((prev) => + prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id] + ); + }; + + const go = (url) => { + navigate(url); + if (isMobile) onMobileClose(); + }; + + const sidebarContent = ( + + {/* Top Branding Section */} + + + + + {/* Navigation Scroll Area */} + + {navItems.map((grp) => ( + + {expanded && ( + + {grp.group} + + )} + + + {grp.items.map((item) => { + if (item.children) { + const opened = collapse.includes(item.id); + const childActive = item.children.some((c) => isActive(c.url)); + const Icon = item.icon; + + const headerButton = ( + expanded ? handleToggleCollapse(item.id) : go(item.children[0].url)} + sx={{ + minHeight: 44, + my: 0.25, + mx: 1.25, + px: expanded ? 1.5 : 0, + justifyContent: expanded ? 'flex-start' : 'center', + borderRadius: '8px', + color: 'text.primary', + bgcolor: childActive && !opened ? alpha(BRAND_RED, 0.04) : 'transparent', + '& .MuiListItemIcon-root': { + color: childActive ? BRAND_RED : 'text.secondary', + minWidth: expanded ? 32 : 0, + justifyContent: 'center' + }, + '&:hover': { + bgcolor: 'action.hover', + '& .MuiListItemIcon-root': { color: 'text.primary' } + } + }} + > + + + + {expanded && ( + <> + + {opened ? : } + + )} + + ); + + return ( + + {expanded ? headerButton : {headerButton}} + {expanded && ( + + + {item.children.map((c) => ( + go(c.url)} + /> + ))} + + + )} + + ); + } + + return ( + go(item.url)} + /> + ); + })} + + + ))} + + + {/* Bottom Footer Branding */} + {expanded && ( + + + Hub Control Panel + + + Doormile Logistics · v1.0 + + + )} + + ); + + if (isMobile) { + return ( + + {sidebarContent} + + ); + } + + return ( + theme.transitions.create('width', { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.standard, + }), + }, + }} + open={open} + > + {sidebarContent} + + ); +} \ No newline at end of file diff --git a/src/layout/MainLayout/index.jsx b/src/layout/MainLayout/index.jsx new file mode 100644 index 0000000..2cd1c1d --- /dev/null +++ b/src/layout/MainLayout/index.jsx @@ -0,0 +1,56 @@ +import { useState } from 'react'; +import { Outlet } from 'react-router-dom'; +import { Box, useMediaQuery } from '@mui/material'; +import { useTheme } from '@mui/material/styles'; + +import Header from './Header'; +import Sidebar from './Sidebar'; + +export default function MainLayout() { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('lg')); + const [open, setOpen] = useState(false); + const [mobileOpen, setMobileOpen] = useState(false); + + const toggle = () => { + if (isMobile) setMobileOpen((p) => !p); + else setOpen((p) => !p); + }; + + return ( + +
+ setMobileOpen(false)} + /> + + + + + + + + ); +} diff --git a/src/layout/MinimalLayout.jsx b/src/layout/MinimalLayout.jsx new file mode 100644 index 0000000..d1357cf --- /dev/null +++ b/src/layout/MinimalLayout.jsx @@ -0,0 +1,11 @@ +import { Outlet } from 'react-router-dom'; +import { Box } from '@mui/material'; + +// Used by auth + maintenance pages — full-bleed, no shell. +export default function MinimalLayout() { + return ( + + + + ); +} diff --git a/src/main.jsx b/src/main.jsx new file mode 100644 index 0000000..99c21ec --- /dev/null +++ b/src/main.jsx @@ -0,0 +1,18 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import { BrowserRouter } from 'react-router-dom'; +import { ThemeProvider, CssBaseline } from '@mui/material'; + +import theme from '@/theme'; +import App from '@/App'; + +ReactDOM.createRoot(document.getElementById('root')).render( + + + + + + + + +); diff --git a/src/menu/navItems.jsx b/src/menu/navItems.jsx new file mode 100644 index 0000000..40728c9 --- /dev/null +++ b/src/menu/navItems.jsx @@ -0,0 +1,56 @@ +import SpaceDashboardRoundedIcon from '@mui/icons-material/SpaceDashboardRounded'; +import MapRoundedIcon from '@mui/icons-material/MapRounded'; +import HailRoundedIcon from '@mui/icons-material/HailRounded'; +import MoveToInboxRoundedIcon from '@mui/icons-material/MoveToInboxRounded'; +import AltRouteRoundedIcon from '@mui/icons-material/AltRouteRounded'; +import WarehouseRoundedIcon from '@mui/icons-material/WarehouseRounded'; +import LocalShippingRoundedIcon from '@mui/icons-material/LocalShippingRounded'; +import DeliveryDiningRoundedIcon from '@mui/icons-material/DeliveryDiningRounded'; + +// ==============================|| DOORMILE HUB NAVIGATION ITEMS ||============================== // +// Menu follows the parcel's real journey in plain language so any hub staff member +// can follow it top-to-bottom: Pick up → Receive → Sort & Store → Send out. + +const navItems = [ + { + group: 'Overview', + items: [ + { id: 'dashboard', title: 'Dashboard', url: '/dashboard', icon: SpaceDashboardRoundedIcon }, + { id: 'tracking', title: 'Live Map', url: '/tracking', icon: MapRoundedIcon } + ] + }, + { + group: '1. Pick Up', + items: [ + { id: 'assignments', title: 'Pickup Requests', url: '/assignments', icon: HailRoundedIcon } + ] + }, + { + group: '2. Receive at Hub', + items: [ + { id: 'inbound', title: 'Receive Parcels', url: '/inbound', icon: MoveToInboxRoundedIcon } + ] + }, + { + group: '3. Sort & Store', + items: [ + { id: 'routing', title: 'Where Does It Go?', url: '/routing', icon: AltRouteRoundedIcon }, + { id: 'inventory', title: 'Storage Shelves', url: '/inventory', icon: WarehouseRoundedIcon } + ] + }, + { + group: '4. Send Out', + items: [ + { id: 'dispatch', title: 'Dispatch & Transfer', url: '/dispatch', icon: LocalShippingRoundedIcon } + ] + }, + { + group: 'Team', + items: [ + { id: 'riders', title: 'Milers', url: '/riders', icon: DeliveryDiningRoundedIcon }, + { id: 'rider-routes', title: 'Rider Routes', url: '/rider-routes', icon: AltRouteRoundedIcon } + ] + } +]; + +export default navItems; diff --git a/src/pages/Dashboard.jsx b/src/pages/Dashboard.jsx new file mode 100644 index 0000000..a0db701 --- /dev/null +++ b/src/pages/Dashboard.jsx @@ -0,0 +1,585 @@ +import { useState, useMemo } from 'react'; +import { + Grid, + Card, + CardHeader, + CardContent, + Typography, + Box, + Stack, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Paper, + Chip, + LinearProgress, + IconButton, + Avatar, + Button, + Divider, + Popover +} from '@mui/material'; +import dayjs from 'dayjs'; +import { alpha } from '@mui/material/styles'; +import QrCodeScannerIcon from '@mui/icons-material/QrCodeScanner'; +import LocalShippingIcon from '@mui/icons-material/LocalShipping'; +import AssignmentIcon from '@mui/icons-material/Assignment'; +import WarningAmberIcon from '@mui/icons-material/WarningAmber'; +import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; +import RefreshIcon from '@mui/icons-material/Refresh'; +import ElectricBoltIcon from '@mui/icons-material/ElectricBolt'; +import DynamicFeedIcon from '@mui/icons-material/DynamicFeed'; +import SpeedIcon from '@mui/icons-material/Speed'; +import LocalOfferIcon from '@mui/icons-material/LocalOffer'; +import DeliveryDiningIcon from '@mui/icons-material/DeliveryDining'; +import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'; +import CalendarTodayOutlinedIcon from '@mui/icons-material/CalendarTodayOutlined'; +import ChevronLeftRoundedIcon from '@mui/icons-material/ChevronLeftRounded'; +import ChevronRightRoundedIcon from '@mui/icons-material/ChevronRightRounded'; +import ArrowRightAltRoundedIcon from '@mui/icons-material/ArrowRightAltRounded'; + +const BRAND = '#C01227'; +const DAY_LABELS = ['S', 'M', 'T', 'W', 'T', 'F', 'S']; + +// ── Doormile-themed range calendar ─────────────────────────────────────────────── +// Click a day to set the start, click again to set the end (auto-swaps if reversed). +// In-range days get a soft red wash; the two endpoints are solid brand red. +function RangeCalendar({ from, to, maxDate, onSelect }) { + const [view, setView] = useState(dayjs(to || from || undefined).startOf('month')); + const [anchorDate, setAnchorDate] = useState(null); // first click while picking a new range + + const start = from ? dayjs(from) : null; + const end = to ? dayjs(to) : null; + const max = maxDate ? dayjs(maxDate) : null; + + const gridStart = view.startOf('month').subtract(view.startOf('month').day(), 'day'); + const cells = Array.from({ length: 42 }, (_, i) => gridStart.add(i, 'day')); + + const handleDay = (d) => { + if (!anchorDate) { + setAnchorDate(d); + onSelect(d.format(DATE_FMT), d.format(DATE_FMT)); + } else { + const a = anchorDate; + const lo = d.isBefore(a) ? d : a; + const hi = d.isBefore(a) ? a : d; + onSelect(lo.format(DATE_FMT), hi.format(DATE_FMT)); + setAnchorDate(null); + } + }; + + return ( + + {/* Month header */} + + setView((v) => v.subtract(1, 'month'))} sx={{ color: '#5F6368' }}> + + + {view.format('MMMM YYYY')} + setView((v) => v.add(1, 'month'))} sx={{ color: '#5F6368' }}> + + + + + {/* Weekday labels */} + + {DAY_LABELS.map((d, i) => ( + + {d} + + ))} + + + {/* Days */} + + {cells.map((d) => { + const inMonth = d.month() === view.month(); + const isStart = start && d.isSame(start, 'day'); + const isEnd = end && d.isSame(end, 'day'); + const isEndpoint = isStart || isEnd; + const inRange = start && end && d.isAfter(start, 'day') && d.isBefore(end, 'day'); + const isToday = d.isSame(dayjs(), 'day'); + const disabled = max && d.isAfter(max, 'day'); + return ( + + handleDay(d)} + sx={{ + width: 36, height: 36, m: '2px', border: 'none', cursor: disabled ? 'default' : 'pointer', + borderRadius: 2, fontSize: '0.85rem', fontFamily: 'inherit', + fontWeight: isEndpoint ? 800 : 600, + color: disabled ? '#CED4DA' : isEndpoint ? '#fff' : inMonth ? '#212529' : '#B9BEC4', + bgcolor: isEndpoint ? BRAND : 'transparent', + boxShadow: isToday && !isEndpoint ? `inset 0 0 0 1.5px ${BRAND}` : 'none', + transition: 'background-color .15s', + '&:hover': { bgcolor: disabled ? 'transparent' : isEndpoint ? '#9E0E20' : alpha(BRAND, 0.12) } + }} + > + {d.date()} + + + ); + })} + + + ); +} + +// Per-day snapshot for a single hub day. `cumulative` metrics add up across the +// selected date range; the rest are "right now" figures that stay as a live count. +const STAT_DEFS = [ + { label: 'Total Parcels', base: 3142, cumulative: true, icon: DynamicFeedIcon, color: '#1A73E8', sub: 'Handled in range' }, + { label: 'Picked Up Locally', base: 1482, cumulative: true, icon: LocalOfferIcon, color: '#1E8E3E', sub: 'Collected by milers' }, + { label: 'From Other Cities', base: 1660, cumulative: true, icon: LocalShippingIcon, color: '#1A73E8', sub: 'Arrived by truck' }, + { label: 'Ready for Delivery', base: 840, cumulative: false, icon: AssignmentIcon, color: '#00A854', sub: 'Sorted for local areas' }, + { label: 'Ready to Transfer', base: 1120, cumulative: false, icon: LocalShippingIcon, color: '#8E24AA', sub: 'Going to other cities' }, + { label: 'Out for Delivery', base: 620, cumulative: false, icon: DeliveryDiningIcon, color: '#F29900', sub: 'With milers right now' }, + { label: 'Needs Checking', base: 48, cumulative: true, icon: WarningAmberIcon, color: '#D93025', sub: 'Damaged or unclear' }, + { label: 'Returns', base: 12, cumulative: true, icon: WarningAmberIcon, color: '#F29900', sub: 'Going back to sender' }, + { label: 'Available Milers', base: 24, cumulative: false, icon: InfoOutlinedIcon, color: '#1A73E8', sub: 'Free or on duty' }, + { label: 'Batches Going Out', base: 8, cumulative: true, icon: LocalShippingIcon, color: '#1E8E3E', sub: 'Sent in range' } +]; + +const DATE_FMT = 'YYYY-MM-DD'; + +export default function Dashboard() { + const today = dayjs().format(DATE_FMT); + const weekAgo = dayjs().subtract(6, 'day').format(DATE_FMT); + const [range, setRange] = useState({ from: weekAgo, to: today }); + const [calAnchor, setCalAnchor] = useState(null); + + // Inclusive day count for the chosen window (min 1); drives cumulative metrics. + const dayCount = useMemo(() => { + const from = dayjs(range.from); + const to = dayjs(range.to); + if (!from.isValid() || !to.isValid() || to.isBefore(from)) return 1; + return to.diff(from, 'day') + 1; + }, [range]); + + const invalidRange = dayjs(range.to).isBefore(dayjs(range.from)); + + const applyPreset = (days) => { + setRange({ from: dayjs().subtract(days - 1, 'day').format(DATE_FMT), to: today }); + }; + const isPreset = (days) => + range.to === today && range.from === dayjs().subtract(days - 1, 'day').format(DATE_FMT); + + const stats = useMemo( + () => + STAT_DEFS.map((s) => ({ + ...s, + value: (s.cumulative ? s.base * dayCount : s.base).toLocaleString('en-IN') + })), + [dayCount] + ); + + const rangeLabel = + dayCount === 1 + ? dayjs(range.from).format('DD MMM YYYY') + : `${dayjs(range.from).format('DD MMM')} – ${dayjs(range.to).format('DD MMM YYYY')} · ${dayCount} days`; + + const incomingVehicles = [ + { id: 'Truck MH-04-8822', origin: 'Mumbai Hub', estTime: 'Arrived (Bay 4)', status: 'Unloading', progress: 85, color: 'success' }, + { id: 'Truck RJ-14-1049', origin: 'Jaipur Hub', estTime: '15 min away', status: 'Expected', progress: 0, color: 'info' }, + { id: 'Truck KA-03-0284', origin: 'Bengaluru Hub', estTime: '1.5 hrs away', status: 'On the way', progress: 0, color: 'default' } + ]; + + const recentActivity = [ + { time: '11:24 AM', type: 'inbound', text: 'Received 142 parcels from the Mumbai truck' }, + { time: '11:15 AM', type: 'dispatch', text: 'Batch BATCH-9281 sent out with miler Deepak (West Delhi)' }, + { time: '10:50 AM', type: 'exception', text: 'Parcel DM-1005 put on hold (damaged label)' }, + { time: '10:30 AM', type: 'sorting', text: 'Cold room temperature checked — all good (4.2°C)' } + ]; + + const activeRoutes = [ + { zone: 'West Delhi (Dwarka)', packages: 145, riders: 4, status: 'Active' }, + { zone: 'South Delhi (Saket)', packages: 210, riders: 6, status: 'Active' }, + { zone: 'East Delhi (Mayur Vihar)', packages: 98, riders: 3, status: 'Need Milers' }, + { zone: 'North Delhi (Rohini)', packages: 122, riders: 4, status: 'Active' } + ]; + + return ( + + {/* Title + date-range filter, all on one line */} + + {/* Left Title Section */} + + + Delhi Hub + + + Showing hub activity for{' '} + + {rangeLabel} + + + + + {/* Right Controls Section */} + + {/* Refresh Button */} + + + + + {/* Quick Presets */} + {[ + { label: 'Today', days: 1 }, + { label: 'Last 7 days', days: 7 }, + { label: 'Last 30 days', days: 30 } + ].map((p) => { + const active = isPreset(p.days); + return ( + applyPreset(p.days)} + sx={{ + height: 36, + fontSize: '0.825rem', + fontWeight: 600, + borderRadius: 2, + bgcolor: active ? BRAND : '#F1F5F9', + color: active ? '#ffffff' : '#475569', + boxShadow: active ? '0 4px 10px rgba(192,18,39,0.15)' : 'none', + '& .MuiChip-label': { px: 1.5 }, + '&:hover': { bgcolor: active ? '#9E0E20' : '#E2E8F0' } + }} + /> + ); + })} + + {/* Range Trigger */} + + + + + {/* Themed calendar popover */} + setCalAnchor(null)} + anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} + transformOrigin={{ vertical: 'top', horizontal: 'right' }} + PaperProps={{ sx: { mt: 1, borderRadius: 3, border: '1px solid #ECEEF1', boxShadow: '0 12px 40px rgba(0,0,0,0.14)', overflow: 'hidden' } }} + > + + Select date range + + {dayjs(range.from).format('DD MMM')} – {dayjs(range.to).format('DD MMM YYYY')} · {dayCount} {dayCount === 1 ? 'day' : 'days'} + + + setRange({ from, to })} + /> + + + + + + + + {/* Metrics Row — CSS grid with minmax(0,1fr) never overflows on mobile */} + + {stats.map((s) => { + const Icon = s.icon; + return ( + + + + + + + + {s.label} + + + + {s.value} + + + {s.sub} + + + + ); + })} + + + {/* Operations Grid */} + + + {/* Sorting Progress & Incoming Vehicles */} + + + + {/* Sorting Station Overview */} + + + + + + + Today's target — 2,000 parcels + 74% done + + + + + Trucks Arriving + + + + + Truck + Coming From + Status + Unloaded + + + + {incomingVehicles.map((v) => ( + + {v.id} + {v.origin} + + + + + {v.progress > 0 ? ( + + + {v.progress}% + + ) : ( + + )} + + + ))} + +
+
+
+
+ + {/* Online Research: Heavy Traffic / Peak Season Control Center */} + + + + + } + /> + + + + + + + + Fast Lane + + + Urgent parcels skip the shelves and go straight from arrival to the outgoing trucks. + + + + + + + + + + Separate Lines + + + Big, heavy boxes are sorted on a different line from small letters and envelopes. + + + + + + + + + + Quick Scan + + + A scanner reads each parcel automatically as it passes, so nothing is missed. + + + + + + + + + {/* Active Delivery Routes */} + + + + + + + + + Area + Parcels + Milers + Status + + + + {activeRoutes.map((r) => ( + + {r.zone} + {r.packages} + {r.riders} + + + + + ))} + +
+
+
+
+
+
+ + {/* Sidebar logs / Active updates */} + + + + + + + {recentActivity.map((act, i) => ( + + + + + {act.text} + + + {act.time} + + + + ))} + + + + + Not sure where a parcel goes? + + + Scan it and we'll tell you exactly what to do next. + + + + + + +
+
+ ); +} diff --git a/src/pages/auth/Login.jsx b/src/pages/auth/Login.jsx new file mode 100644 index 0000000..6face46 --- /dev/null +++ b/src/pages/auth/Login.jsx @@ -0,0 +1,212 @@ +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { + Box, + Card, + Stack, + Typography, + TextField, + InputAdornment, + IconButton, + Button, + Checkbox, + FormControlLabel, + Link +} from '@mui/material'; +import Visibility from '@mui/icons-material/Visibility'; +import VisibilityOff from '@mui/icons-material/VisibilityOff'; +import BoltIcon from '@mui/icons-material/Bolt'; +import LocalShippingOutlinedIcon from '@mui/icons-material/LocalShippingOutlined'; +import VerifiedOutlinedIcon from '@mui/icons-material/VerifiedOutlined'; + +import Logo from '@/components/Logo'; + +export default function Login() { + const navigate = useNavigate(); + const [show, setShow] = useState(false); + const [auth, setAuth] = useState('hub.delhi@doormile.in'); + const [pwd, setPwd] = useState('password123'); + + const handleSignIn = () => { + navigate('/dashboard'); + }; + + return ( + + + {/* Brand Side Panel */} + + {/* Background Decorative Circles */} + + + + {/* BLACK LOGO REPLACEMENT (Sidebar) */} + + + + + + + Doormile Hub Console + + + Every parcel, +
handled with ease. +
+ + Receive parcels, sort them, and send them out for delivery or transfer to another city — all from one simple screen. + + + + {[ + { icon: BoltIcon, t: 'We tell you which shelf each parcel goes on' }, + { icon: LocalShippingOutlinedIcon, t: 'Scan parcels in as trucks arrive' }, + { icon: VerifiedOutlinedIcon, t: 'Keep an eye on cold-storage parcels' } + ].map((f) => ( + + + + + {f.t} + + ))} + +
+ + + © 2026 Doormile Logistics Pvt. Ltd. + +
+ + {/* Form Panel */} + + + {/* BLACK LOGO REPLACEMENT (Mobile View) */} + + + + + Hub Sign In + + Sign in to your Doormile Hub operations account. + + + + + + Username / Email + + setAuth(e.target.value)} + /> + + + + + Password + + setPwd(e.target.value)} + InputProps={{ + endAdornment: ( + + setShow((s) => !s)} edge="end" size="small"> + {show ? : } + + + ) + }} + /> + + + + } + label={Remember me} + /> + + Forgot password? + + + + + + + + New to Hub Operations?{' '} + { e.preventDefault(); navigate('/signup'); }} + underline="hover" + sx={{ color: '#C01227', fontWeight: 600 }} + > + Create an account + + + + + + +
+ ); +} \ No newline at end of file diff --git a/src/pages/auth/Signup.jsx b/src/pages/auth/Signup.jsx new file mode 100644 index 0000000..4061191 --- /dev/null +++ b/src/pages/auth/Signup.jsx @@ -0,0 +1,261 @@ +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { + Box, + Card, + Grid, + Stack, + Typography, + TextField, + InputAdornment, + IconButton, + Button, + Link, + MenuItem, + FormControl, + Select, + Checkbox, + FormControlLabel +} from '@mui/material'; +import Visibility from '@mui/icons-material/Visibility'; +import VisibilityOff from '@mui/icons-material/VisibilityOff'; +import HubIcon from '@mui/icons-material/Hub'; +import AssignmentIndIcon from '@mui/icons-material/AssignmentInd'; +import VerifiedUserIcon from '@mui/icons-material/VerifiedUser'; + +import Logo from '@/components/Logo'; + +const HUBS = [ + { value: 'delhi', label: 'Delhi Hub (DEL-01)' }, + { value: 'mumbai', label: 'Mumbai Hub (BOM-02)' }, + { value: 'bangalore', label: 'Bengaluru Hub (BLR-03)' }, + { value: 'chennai', label: 'Chennai Hub (MAA-04)' }, + { value: 'kolkata', label: 'Kolkata Hub (CCU-05)' } +]; + +const ROLES = [ + { value: 'manager', label: 'Hub Manager / Supervisor' }, + { value: 'sorter', label: 'Sorting Station Operator' }, + { value: 'inbound', label: 'Inbound Associate' }, + { value: 'dispatch', label: 'Outbound Dispatch Coordinator' } +]; + +export default function Signup() { + const navigate = useNavigate(); + const [show, setShow] = useState(false); + + // Fields + const [name, setName] = useState(''); + const [email, setEmail] = useState(''); + const [hub, setHub] = useState('delhi'); + const [role, setRole] = useState('manager'); + const [pwd, setPwd] = useState(''); + const [agree, setAgree] = useState(true); + + const handleSignUp = (e) => { + e.preventDefault(); + navigate('/login'); + }; + + return ( + + + {/* Brand Side Panel */} + + {/* Background Decorative Circles */} + + + + {/* BLACK LOGO REPLACEMENT (Sidebar) */} + + + + + + + Hub Registration Gateway + + + Join the Connected +
Logistics Network. +
+ + Create an operational profile to access state-of-the-art sorting stations, live manifest creations, and miler optimization modules. + + + + {[ + { icon: HubIcon, t: 'Connect to any of the 15+ nationwide hubs' }, + { icon: AssignmentIndIcon, t: 'Role-based access controls for security' }, + { icon: VerifiedUserIcon, t: 'Activity logging and dispatch compliance verification' } + ].map((f) => ( + + + + + {f.t} + + ))} + +
+ + + © 2026 Doormile Logistics Pvt. Ltd. + +
+ + {/* Form Panel */} + + + {/* BLACK LOGO REPLACEMENT (Mobile View) */} + + + + + Request Access + + Register your credentials to join hub operations. + + + + + + Full Name + setName(e.target.value)} /> + + + + Work Email + setEmail(e.target.value)} /> + + + + + Assign Hub + + + + + + Select Role + + + + + + + + Password + setPwd(e.target.value)} + InputProps={{ + endAdornment: ( + + setShow((s) => !s)} edge="end" size="small"> + {show ? : } + + + ) + }} + /> + + + setAgree(e.target.checked)} size="small" sx={{ color: '#C01227', '&.Mui-checked': { color: '#C01227' } }} required />} + label={ + + I agree to the{' '} + Terms of Service and{' '} + Operations Guidelines. + + } + /> + + + + + + Already have an account?{' '} + { e.preventDefault(); navigate('/login'); }} + underline="hover" + sx={{ color: '#C01227', fontWeight: 600 }} + > + Sign In + + + + + + + +
+ ); +} \ No newline at end of file diff --git a/src/pages/operations/Dispatch.jsx b/src/pages/operations/Dispatch.jsx new file mode 100644 index 0000000..9b4a90d --- /dev/null +++ b/src/pages/operations/Dispatch.jsx @@ -0,0 +1,326 @@ +import { useState } from 'react'; +import { + Box, + Typography, + Card, + CardContent, + CardHeader, + Grid, + Button, + Stack, + TextField, + MenuItem, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Chip, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Snackbar, + Alert, + Avatar, + Divider, + useMediaQuery +} from '@mui/material'; +import { useTheme } from '@mui/material/styles'; +import LocalShippingIcon from '@mui/icons-material/LocalShipping'; +import AddIcon from '@mui/icons-material/Add'; +import SendIcon from '@mui/icons-material/Send'; +import CheckCircleIcon from '@mui/icons-material/CheckCircle'; +import EastRoundedIcon from '@mui/icons-material/EastRounded'; +import Inventory2OutlinedIcon from '@mui/icons-material/Inventory2Outlined'; +import TwoWheelerOutlinedIcon from '@mui/icons-material/TwoWheelerOutlined'; +import SwapHorizOutlinedIcon from '@mui/icons-material/SwapHorizOutlined'; + +import PageHeader from '@/components/PageHeader'; + +const INITIAL_MANIFESTS = [ + { id: 'BATCH-9281', route: 'Transfer to Mumbai Hub', vehicle: 'Transfer Truck: DL-01-BZ-8055', packagesCount: 154, status: 'Preparing', time: 'Created 1 hr ago', origin: 'Delhi Hub', currentLoc: 'Delhi Hub (Dispatch Dock)', destination: 'Mumbai Hub', kind: 'transfer' }, + { id: 'BATCH-9282', route: 'Local Delivery: Dwarka', vehicle: 'Miler: Deepak Sharma (Two-wheeler)', packagesCount: 12, status: 'Sent', time: 'Sent out 20 min ago', origin: 'Delhi Hub', currentLoc: 'On the way', destination: 'Dwarka, Delhi', kind: 'local' }, + { id: 'BATCH-9283', route: 'Local Delivery: Saket', vehicle: 'Miler: Karthik S. (EV)', packagesCount: 5, status: 'Ready', time: 'Ready 45 min ago', origin: 'Delhi Hub', currentLoc: 'Delhi Hub (Dispatch Dock)', destination: 'Saket, Delhi', kind: 'local' } +]; + +const STATUS_META = { + Preparing: { color: '#B06000', bg: '#FEF7E0', label: 'Preparing' }, + Ready: { color: '#1A73E8', bg: '#E8F0FE', label: 'Ready to send' }, + Sent: { color: '#1E8E3E', bg: '#E6F4EA', label: 'Sent' } +}; + +export default function Dispatch() { + const theme = useTheme(); + const isMdDown = useMediaQuery(theme.breakpoints.down('md')); + + const [manifests, setManifests] = useState(INITIAL_MANIFESTS); + const [openModal, setOpenModal] = useState(false); + + // Create form state + const [newRoute, setNewRoute] = useState('Transfer to Mumbai Hub'); + const [newDestination, setNewDestination] = useState(''); + const [newVehicle, setNewVehicle] = useState(''); + const [newPkgsCount, setNewPkgsCount] = useState('5'); + + // Toast state + const [toast, setToast] = useState({ open: false, msg: '', severity: 'success' }); + + const handleCreateManifest = (e) => { + e.preventDefault(); + if (!newVehicle) { + setToast({ open: true, msg: 'Please input Miler or Vehicle info', severity: 'warning' }); + return; + } + + const randomNum = Math.floor(1000 + Math.random() * 9000); + const newManifest = { + id: `BATCH-${randomNum}`, + route: newRoute, + vehicle: newVehicle, + packagesCount: parseInt(newPkgsCount, 10), + status: 'Preparing', + time: 'Created just now', + origin: 'Delhi Hub', + currentLoc: 'Delhi Hub (Dispatch Dock)', + destination: newDestination || newRoute + }; + + setManifests([newManifest, ...manifests]); + setOpenModal(false); + setNewVehicle(''); + setNewDestination(''); + setToast({ open: true, msg: `Batch ${newManifest.id} created successfully`, severity: 'success' }); + }; + + const handleSeal = (id) => { + setManifests((prev) => + prev.map((m) => (m.id === id ? { ...m, status: 'Ready', time: 'Checked & ready just now' } : m)) + ); + setToast({ open: true, msg: `Batch ${id} checked and ready to send.`, severity: 'success' }); + }; + + const handleDispatch = (id) => { + setManifests((prev) => + prev.map((m) => (m.id === id ? { ...m, status: 'Sent', time: 'Sent out just now', currentLoc: 'On the way' } : m)) + ); + setToast({ open: true, msg: `Batch ${id} sent out! The miler/driver has been notified.`, severity: 'success' }); + }; + + // Action button shown for each batch based on its status + const BatchAction = ({ m, fullWidth }) => { + if (m.status === 'Preparing') { + return ( + + ); + } + if (m.status === 'Ready') { + return ( + + ); + } + return } label="Sent" color="success" variant="outlined" sx={{ fontWeight: 700 }} />; + }; + + // Origin → destination journey, reused in cards and table + const Journey = ({ m }) => { + const meta = STATUS_META[m.status] || STATUS_META.Preparing; + return ( + + + {m.origin} + + {m.destination} + + {m.currentLoc} + + ); + }; + + return ( + + + + + {/* Manifest Actions & List */} + + + } onClick={() => setOpenModal(true)}> + New Batch + + } + /> + + + {isMdDown ? ( + /* ── MOBILE / TABLET: spacious cards ── */ + + {manifests.map((m) => { + const meta = STATUS_META[m.status] || STATUS_META.Preparing; + const KindIcon = m.kind === 'transfer' ? SwapHorizOutlinedIcon : TwoWheelerOutlinedIcon; + return ( + + + + + + + + + {m.id} + {m.time} + + + + + + + + + + + } label={m.vehicle} + sx={{ bgcolor: '#F1F3F5', color: '#495057', fontWeight: 600, maxWidth: '100%', '& .MuiChip-icon': { color: '#9AA0A6' } }} /> + } label={`${m.packagesCount} parcels`} + sx={{ bgcolor: '#F1F3F5', color: '#495057', fontWeight: 600, '& .MuiChip-icon': { color: '#9AA0A6' } }} /> + + + + + + ); + })} + + ) : ( + /* ── DESKTOP: spacious table ── */ + + + + + {['Batch', 'Journey', 'Miler / Vehicle', 'Parcels', 'Status', 'Action'].map((h, i) => ( + + {h} + + ))} + + + + {manifests.map((m) => { + const meta = STATUS_META[m.status] || STATUS_META.Preparing; + const KindIcon = m.kind === 'transfer' ? SwapHorizOutlinedIcon : TwoWheelerOutlinedIcon; + return ( + + + + + + + + {m.id} + {m.time} + + + + + {m.vehicle} + {m.packagesCount} + + + + + + ); + })} + +
+
+ )} +
+
+
+ + {/* Creation Modal */} + setOpenModal(false)} fullWidth maxWidth="xs"> + Create a New Batch + + + + setNewRoute(e.target.value)} + > + Transfer to another city — Mumbai Hub + Transfer to another city — Bengaluru Hub + Local Delivery — Dwarka + Local Delivery — Saket + Local Delivery — Rohini + + + setNewDestination(e.target.value)} + required + /> + + setNewVehicle(e.target.value)} + required + /> + + setNewPkgsCount(e.target.value)} + inputProps={{ min: 1 }} + required + /> + + + + + + + + + + setToast({ ...toast, open: false })} + anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} + > + setToast({ ...toast, open: false })} sx={{ width: '100%' }}> + {toast.msg} + + +
+ ); +} diff --git a/src/pages/operations/Inbound.jsx b/src/pages/operations/Inbound.jsx new file mode 100644 index 0000000..8ed99ce --- /dev/null +++ b/src/pages/operations/Inbound.jsx @@ -0,0 +1,367 @@ +import { useState, useMemo } from 'react'; +import { + Box, Typography, Card, CardContent, Grid, TextField, Button, Stack, + MenuItem, Table, TableBody, TableCell, TableContainer, TableHead, + TableRow, Chip, Alert, Snackbar, InputAdornment, Avatar, Divider, + useMediaQuery +} from '@mui/material'; +import { useTheme } from '@mui/material/styles'; +import QrCodeScannerOutlinedIcon from '@mui/icons-material/QrCodeScannerOutlined'; +import LocalShippingOutlinedIcon from '@mui/icons-material/LocalShippingOutlined'; +import CheckCircleOutlinedIcon from '@mui/icons-material/CheckCircleOutlined'; +import EastOutlinedIcon from '@mui/icons-material/EastOutlined'; +import BoltOutlinedIcon from '@mui/icons-material/BoltOutlined'; +import MoveToInboxOutlinedIcon from '@mui/icons-material/MoveToInboxOutlined'; +import Inventory2OutlinedIcon from '@mui/icons-material/Inventory2Outlined'; +import WarningAmberOutlinedIcon from '@mui/icons-material/WarningAmberOutlined'; +import AcUnitOutlinedIcon from '@mui/icons-material/AcUnitOutlined'; +import ScaleOutlinedIcon from '@mui/icons-material/ScaleOutlined'; +import ThermostatOutlinedIcon from '@mui/icons-material/ThermostatOutlined'; +import WarehouseOutlinedIcon from '@mui/icons-material/WarehouseOutlined'; +import HomeWorkOutlinedIcon from '@mui/icons-material/HomeWorkOutlined'; +import PlaceOutlinedIcon from '@mui/icons-material/PlaceOutlined'; +import AccessTimeOutlinedIcon from '@mui/icons-material/AccessTimeOutlined'; + +import PageHeader from '@/components/PageHeader'; + +const SHELVES = ['Zone A (Shelf 1)', 'Zone A (Shelf 2)', 'Zone B (Shelf 1)', 'Zone C (Cold Room)', 'Exception Area']; + +const INITIAL_INBOUND = [ + { trackingId: 'DM-882201', sender: 'Acme Corp, Mumbai', origin: 'Mumbai Hub', currentLoc: 'Delhi Hub', destination: 'Dwarka, Sec 12, Delhi', weight: '2.4 kg', condition: 'Good', temp: 'N/A', shelf: 'Zone A (Shelf 1)', time: '10 min ago' }, + { trackingId: 'DM-882202', sender: 'Tech Ltd, Mumbai', origin: 'Mumbai Hub', currentLoc: 'Delhi Hub', destination: 'Saket, Block J, Delhi', weight: '1.2 kg', condition: 'Good', temp: '4.1°C', shelf: 'Zone C (Cold Room)', time: '12 min ago' }, + { trackingId: 'DM-882203', sender: 'Crafts India, Jaipur', origin: 'Jaipur Hub', currentLoc: 'Delhi Hub', destination: 'Mayur Vihar Ph 1, Delhi', weight: '8.5 kg', condition: 'Damaged Box', temp: 'N/A', shelf: 'Exception Area', time: '20 min ago' } +]; + +const ORIGINS = [ + { value: 'Mumbai Hub', label: 'Mumbai Hub (BOM-02)' }, + { value: 'Jaipur Hub', label: 'Jaipur Hub (JAI-08)' }, + { value: 'Bengaluru Hub', label: 'Bengaluru Hub (BLR-03)' }, + { value: 'Client Pickup', label: 'Direct Client Pickup (Delhi Local)' } +]; + +const shelfStyle = (shelf) => { + if (shelf === 'Exception Area') return { color: '#D93025', bg: '#FCE8E6' }; + if (shelf.includes('Cold')) return { color: '#00838F', bg: '#E0F7FA' }; + return { color: '#1A73E8', bg: '#E8F0FE' }; +}; +const isGood = (c) => c === 'Good'; + +export default function Inbound() { + const theme = useTheme(); + const isMdDown = useMediaQuery(theme.breakpoints.down('md')); + + const [trackingId, setTrackingId] = useState(''); + const [origin, setOrigin] = useState('Mumbai Hub'); + const [customer, setCustomer] = useState(''); + const [senderAddress, setSenderAddress] = useState(''); + const [destination, setDestination] = useState(''); + const [weight, setWeight] = useState(''); + const [condition, setCondition] = useState('Good'); + const [temp, setTemp] = useState(''); + + const [inboundLogs, setInboundLogs] = useState(INITIAL_INBOUND); + const [toast, setToast] = useState({ open: false, msg: '', severity: 'success' }); + + const stats = useMemo(() => { + const received = inboundLogs.length; + const exceptions = inboundLogs.filter(l => l.condition !== 'Good' || l.shelf === 'Exception Area').length; + const coldChain = inboundLogs.filter(l => l.temp && l.temp !== 'N/A').length; + const pendingSort = inboundLogs.filter(l => l.shelf !== 'Exception Area').length; + return { received, exceptions, coldChain, pendingSort }; + }, [inboundLogs]); + + const handleRandomScan = () => { + const randomNum = Math.floor(100000 + Math.random() * 900000); + setTrackingId(`DM-${randomNum}`); + const customers = ['Acme Electronics', 'Delhi Medicos', 'Urban Fashion', 'Astro Retail', 'Fresho Foods']; + const senderAddresses = ['Andheri East, Mumbai', 'Malviya Nagar, Jaipur', 'Koramangala, Bengaluru', 'Lajpat Nagar, Delhi']; + const destinations = ['Dwarka Sec 4, Delhi', 'Saket Marg, Delhi', 'Karol Bagh, Delhi', 'Connaught Place, Delhi', 'Vasant Kunj, Delhi']; + const weights = ['1.5 kg', '0.8 kg', '5.2 kg', '12.0 kg', '3.1 kg']; + const origins = ['Mumbai Hub', 'Jaipur Hub', 'Bengaluru Hub', 'Client Pickup']; + setCustomer(customers[Math.floor(Math.random() * customers.length)]); + setSenderAddress(senderAddresses[Math.floor(Math.random() * senderAddresses.length)]); + setDestination(destinations[Math.floor(Math.random() * destinations.length)]); + setWeight(weights[Math.floor(Math.random() * weights.length)]); + setCondition(Math.random() > 0.85 ? 'Damaged Box' : 'Good'); + setTemp(Math.random() > 0.8 ? '3.8°C' : 'N/A'); + setOrigin(origins[Math.floor(Math.random() * origins.length)]); + }; + + const handleSubmit = (e) => { + e.preventDefault(); + if (!trackingId || !destination) { + setToast({ open: true, msg: 'Please scan or fill tracking details', severity: 'warning' }); + return; + } + let recommendedShelf = SHELVES[0]; + if (condition.includes('Damaged') || condition.includes('Wet') || condition.includes('Missing')) recommendedShelf = 'Exception Area'; + else if (temp !== 'N/A' && temp !== '') recommendedShelf = 'Zone C (Cold Room)'; + else recommendedShelf = SHELVES[Math.floor(Math.random() * 3)]; + + const newLog = { + trackingId, sender: customer || 'Unknown Sender', origin, currentLoc: 'Delhi Hub', + destination, weight: weight || '1.0 kg', condition, temp: temp || 'N/A', + shelf: recommendedShelf, time: 'Just now' + }; + setInboundLogs([newLog, ...inboundLogs]); + setToast({ open: true, msg: `${trackingId} received · routed to ${recommendedShelf}`, severity: 'success' }); + setTrackingId(''); setCustomer(''); setSenderAddress(''); setDestination(''); setWeight(''); setCondition('Good'); setTemp(''); + }; + + const fieldSx = { '& .MuiOutlinedInput-root': { borderRadius: 2 } }; + + // Reusable journey block + const Journey = ({ log }) => ( + + + {log.origin} + + {log.currentLoc} + + {log.destination.split(',')[0]} + + + + {log.destination} + + + ); + + return ( + + + {/* ── Header ── */} + + + {/* ── KPI strip ── */} + + {[ + { icon: MoveToInboxOutlinedIcon, label: 'Received Today', value: stats.received, color: '#1A73E8', bg: '#E8F0FE' }, + { icon: Inventory2OutlinedIcon, label: 'To Sort', value: stats.pendingSort, color: '#B06000', bg: '#FEF7E0' }, + { icon: WarningAmberOutlinedIcon, label: 'Needs Checking', value: stats.exceptions, color: '#D93025', bg: '#FCE8E6' }, + { icon: AcUnitOutlinedIcon, label: 'Cold Items', value: stats.coldChain, color: '#00838F', bg: '#E0F7FA' }, + ].map((s, i) => ( + + + + + + + + {s.label} + + {s.value} + + + + ))} + + + {/* ── Main ── */} + + + {/* Scanner Panel */} + + + + + + + + + + + Add a Parcel + + + + Record a parcel arriving at Delhi Hub + + + + + + + + + setTrackingId(e.target.value)} sx={fieldSx} + InputProps={{ + startAdornment: , + endAdornment: ( + + + + ) + }} /> + + setOrigin(e.target.value)} sx={fieldSx} + InputProps={{ startAdornment: }}> + {ORIGINS.map((o) => {o.label})} + + + setSenderAddress(e.target.value)} sx={fieldSx} /> + + setDestination(e.target.value)} required sx={fieldSx} + InputProps={{ startAdornment: }} /> + + + setWeight(e.target.value)} sx={fieldSx} + InputProps={{ startAdornment: }} /> + setCondition(e.target.value)} sx={fieldSx}> + Good + Damaged Box + Wet / Crushed + Missing Label + + + + setTemp(e.target.value)} sx={fieldSx} + InputProps={{ startAdornment: }} /> + + + + + + + + + {/* Ledger Panel */} + + + + + + + + + + Recently Received + Parcels logged at the hub today + + + + + + + + {/* ── MOBILE: card list ── */} + {isMdDown ? ( + + {inboundLogs.map((log, i) => { + const ss = shelfStyle(log.shelf); + return ( + + + + {log.trackingId} + + + {log.time} + + + + + } label={log.weight} + sx={{ bgcolor: '#F1F3F5', color: '#495057', fontWeight: 600, '& .MuiChip-icon': { color: '#9AA0A6' } }} /> + + {log.temp !== 'N/A' && ( + } label={log.temp} + sx={{ bgcolor: '#E0F7FA', color: '#00838F', fontWeight: 600, '& .MuiChip-icon': { color: '#00838F' } }} /> + )} + } label={log.shelf} + sx={{ bgcolor: ss.bg, color: ss.color, fontWeight: 600, '& .MuiChip-icon': { color: ss.color } }} /> + + + + ); + })} + + ) : ( + /* ── DESKTOP: table with horizontal scroll guard ── */ + + + + + {['Parcel No.', 'Journey', 'Weight', 'Condition', 'Temp', 'Goes On Shelf', 'Time'].map((h, i) => ( + = 2 && i <= 4 ? 'center' : i === 6 ? 'right' : 'left'} + sx={{ fontWeight: 700, fontSize: '0.7rem', color: '#6C757D', textTransform: 'uppercase', letterSpacing: 0.5, borderBottom: '1px solid #ECEEF1', py: 1.5, whiteSpace: 'nowrap' }}> + {h} + + ))} + + + + {inboundLogs.map((log, index) => { + const ss = shelfStyle(log.shelf); + return ( + + {log.trackingId} + + {log.weight} + + + + {log.temp} + + } label={log.shelf} + sx={{ fontWeight: 600, whiteSpace: 'nowrap', bgcolor: ss.bg, color: ss.color, '& .MuiChip-icon': { color: ss.color } }} /> + + {log.time} + + ); + })} + +
+
+ )} +
+
+
+ + setToast({ ...toast, open: false })} + anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}> + setToast({ ...toast, open: false })} + sx={{ borderRadius: 2, fontWeight: 600, boxShadow: '0 8px 24px rgba(0,0,0,0.18)' }}> + {toast.msg} + + +
+ ); +} diff --git a/src/pages/operations/Inventory.jsx b/src/pages/operations/Inventory.jsx new file mode 100644 index 0000000..591c578 --- /dev/null +++ b/src/pages/operations/Inventory.jsx @@ -0,0 +1,285 @@ +import { useState } from 'react'; +import { + Box, + Typography, + Card, + CardContent, + CardHeader, + Grid, + TextField, + Button, + Stack, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Chip, + MenuItem, + Select, + FormControl, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Avatar, + Divider, + InputAdornment, + useMediaQuery +} from '@mui/material'; +import { useTheme } from '@mui/material/styles'; +import ViewModuleIcon from '@mui/icons-material/ViewModule'; +import AcUnitIcon from '@mui/icons-material/AcUnit'; +import LocalOfferIcon from '@mui/icons-material/LocalOffer'; +import StorageIcon from '@mui/icons-material/Storage'; +import SearchOutlinedIcon from '@mui/icons-material/SearchOutlined'; +import ScaleOutlinedIcon from '@mui/icons-material/ScaleOutlined'; +import WarehouseOutlinedIcon from '@mui/icons-material/WarehouseOutlined'; +import OpenWithRoundedIcon from '@mui/icons-material/OpenWithRounded'; + +import PageHeader from '@/components/PageHeader'; + +const zoneColor = (zone) => { + if (zone === 'C') return { color: '#00838F', bg: '#E0F7FA' }; + if (zone === 'D') return { color: '#D93025', bg: '#FCE8E6' }; + if (zone === 'B') return { color: '#8E24AA', bg: '#F3E5F5' }; + return { color: '#1A73E8', bg: '#E8F0FE' }; +}; +const onShelf = (s) => s === 'On Shelf'; + +const SHELVES = ['Zone A (Shelf 1)', 'Zone A (Shelf 2)', 'Zone B (Shelf 1)', 'Zone B (Shelf 2)', 'Zone C (Cold Room)', 'Exception Area']; + +const INITIAL_INVENTORY = [ + { id: 'DM-882201', customer: 'Acme Corp', weight: '2.4 kg', shelf: 'Zone A (Shelf 1)', zone: 'A', status: 'On Shelf' }, + { id: 'DM-882202', customer: 'BioPharma India', weight: '1.2 kg', shelf: 'Zone C (Cold Room)', zone: 'C', status: 'On Shelf' }, + { id: 'DM-882203', customer: 'Rajesh Textiles', weight: '8.5 kg', shelf: 'Exception Area', zone: 'D', status: 'Under Review' }, + { id: 'DM-109241', customer: 'Urban Fashion', weight: '3.1 kg', shelf: 'Zone B (Shelf 1)', zone: 'B', status: 'On Shelf' }, + { id: 'DM-402941', customer: 'Astro Retail', weight: '0.5 kg', shelf: 'Zone A (Shelf 2)', zone: 'A', status: 'On Shelf' } +]; + +export default function Inventory() { + const theme = useTheme(); + const isMdDown = useMediaQuery(theme.breakpoints.down('md')); + + const [inventory, setInventory] = useState(INITIAL_INVENTORY); + const [search, setSearch] = useState(''); + + // Relocation modal state + const [editItem, setEditItem] = useState(null); + const [newShelf, setNewShelf] = useState(''); + + const handleOpenRelocate = (item) => { + setEditItem(item); + setNewShelf(item.shelf); + }; + + const handleConfirmRelocate = () => { + if (!editItem) return; + + // Determine new zone label + let zoneLabel = 'A'; + if (newShelf.includes('Zone B')) zoneLabel = 'B'; + else if (newShelf.includes('Zone C') || newShelf.includes('Cold')) zoneLabel = 'C'; + else if (newShelf.includes('Exception')) zoneLabel = 'D'; + + setInventory((prev) => + prev.map((item) => + item.id === editItem.id ? { ...item, shelf: newShelf, zone: zoneLabel } : item + ) + ); + + setEditItem(null); + }; + + // Filter inventory list + const filteredInventory = inventory.filter( + (item) => + item.id.toLowerCase().includes(search.toLowerCase()) || + item.customer.toLowerCase().includes(search.toLowerCase()) || + item.shelf.toLowerCase().includes(search.toLowerCase()) + ); + + return ( + + + + + + {/* Environmental Sensors for Cold-Chain Zone C */} + + {[ + { label: 'Cold Room Temperature', value: '4.2°C', icon: AcUnitIcon, color: '#00838F', bg: '#E0F7FA', chip: 'All good · Within safe range', chipColor: 'success' }, + { label: 'Storage Space', value: '120 Shelves', icon: ViewModuleIcon, color: '#1A73E8', bg: '#E8F0FE', chip: '28% full', chipColor: 'primary' }, + { label: 'Needs Attention', value: '1 Parcel', icon: LocalOfferIcon, color: '#D93025', bg: '#FCE8E6', chip: 'Waiting to be checked', chipColor: 'error' }, + ].map((s, i) => ( + + + + + + + + + {s.label} + + + {s.value} + + + + + ))} + + + {/* Main Inventory Board */} + + setSearch(e.target.value)} + sx={{ width: { xs: 160, sm: 220, md: 280 }, '& .MuiOutlinedInput-root': { borderRadius: 2 } }} + InputProps={{ startAdornment: }} + /> + } + sx={{ flexWrap: 'wrap', gap: 1, '& .MuiCardHeader-action': { m: 0, alignSelf: 'center' } }} + /> + + + {isMdDown ? ( + /* ── MOBILE / TABLET: cards ── */ + + {filteredInventory.map((item) => { + const zc = zoneColor(item.zone); + return ( + + + + + + + + + {item.id} + {item.customer} + + + + + + + } label={item.shelf} + sx={{ bgcolor: zc.bg, color: zc.color, fontWeight: 700, '& .MuiChip-icon': { color: zc.color } }} /> + } label={item.weight} + sx={{ bgcolor: '#F1F3F5', color: '#495057', fontWeight: 600, '& .MuiChip-icon': { color: '#9AA0A6' } }} /> + + + + + + ); + })} + {filteredInventory.length === 0 && ( + No parcels found. Try a different search. + )} + + ) : ( + /* ── DESKTOP: spacious table ── */ + + + + + {['Parcel', 'On Shelf', 'Weight', 'Status', 'Action'].map((h, i) => ( + + {h} + + ))} + + + + {filteredInventory.map((item) => { + const zc = zoneColor(item.zone); + return ( + + + + + + + + {item.id} + {item.customer} + + + + + } label={item.shelf} + sx={{ bgcolor: zc.bg, color: zc.color, fontWeight: 700, whiteSpace: 'nowrap', '& .MuiChip-icon': { color: zc.color } }} /> + + {item.weight} + + + + + + + + ); + })} + {filteredInventory.length === 0 && ( + + + No parcels found. Try a different search. + + + )} + +
+
+ )} +
+ + {/* Relocate Dialog */} + setEditItem(null)} fullWidth maxWidth="xs"> + Move Parcel {editItem?.id} + + + + Choose a new shelf for {editItem?.id} (from {editItem?.customer}). + + + + + + + + + + + +
+ ); +} diff --git a/src/pages/operations/OrderAssignment.jsx b/src/pages/operations/OrderAssignment.jsx new file mode 100644 index 0000000..31fca05 --- /dev/null +++ b/src/pages/operations/OrderAssignment.jsx @@ -0,0 +1,317 @@ +import { useState } from 'react'; +import { + Box, + Typography, + Card, + CardContent, + CardHeader, + Button, + Divider, + Avatar, + Stack, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Chip, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + List, + ListItemButton, + ListItemText, + ListItemAvatar, + Radio, + Badge, + Checkbox, + useMediaQuery +} from '@mui/material'; +import { useTheme } from '@mui/material/styles'; +import AssignmentIndIcon from '@mui/icons-material/AssignmentInd'; +import CheckCircleIcon from '@mui/icons-material/CheckCircle'; +import TwoWheelerIcon from '@mui/icons-material/TwoWheeler'; +import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome'; +import PlaceOutlinedIcon from '@mui/icons-material/PlaceOutlined'; +import FlagOutlinedIcon from '@mui/icons-material/FlagOutlined'; +import Inventory2OutlinedIcon from '@mui/icons-material/Inventory2Outlined'; +import PersonOutlineRoundedIcon from '@mui/icons-material/PersonOutlineRounded'; + +import PageHeader from '@/components/PageHeader'; + +const UNASSIGNED_ORDERS = [ + { id: 'PICK-991', customer: 'Ramesh K.', pickup: 'Dwarka Sec 12, Delhi', drop: 'Mumbai', package: 'Small Box, 2kg', time: '10 mins ago', status: 'Pending Assignment' }, + { id: 'PICK-992', customer: 'Anita P.', pickup: 'Saket, Delhi', drop: 'Hyderabad', package: 'Document, 0.5kg', time: '15 mins ago', status: 'Pending Assignment' }, + { id: 'PICK-993', customer: 'Suresh V.', pickup: 'Rohini, Delhi', drop: 'Bengaluru', package: 'Large Box, 12kg', time: '1 hour ago', status: 'Pending Assignment' } +]; + +const AVAILABLE_MILERS = [ + { id: 'M-101', name: 'Deepak Sharma', vehicle: 'Two-Wheeler', area: 'Dwarka', distance: '1.2 km away' }, + { id: 'M-102', name: 'Karthik S.', vehicle: 'EV-Rickshaw', area: 'Saket', distance: '2.5 km away' }, + { id: 'M-103', name: 'Sanjay R.', vehicle: 'Mini Truck', area: 'Rohini', distance: '0.8 km away' } +]; + +export default function OrderAssignment() { + const theme = useTheme(); + const isMdDown = useMediaQuery(theme.breakpoints.down('md')); + + const [orders, setOrders] = useState(UNASSIGNED_ORDERS); + const [selectedOrders, setSelectedOrders] = useState([]); + + // Single Assign Dialog State + const [selectedOrderForAssign, setSelectedOrderForAssign] = useState(null); + const [assignDialogOpen, setAssignDialogOpen] = useState(false); + const [selectedMiler, setSelectedMiler] = useState(''); + + const handleSelectAll = (event) => { + if (event.target.checked) { + const pendingIds = orders.filter(o => o.status === 'Pending Assignment').map(o => o.id); + setSelectedOrders(pendingIds); + } else { + setSelectedOrders([]); + } + }; + + const handleSelectOne = (id) => { + if (selectedOrders.includes(id)) { + setSelectedOrders(selectedOrders.filter(selectedId => selectedId !== id)); + } else { + setSelectedOrders([...selectedOrders, id]); + } + }; + + const handleOpenAssign = (order) => { + setSelectedOrderForAssign(order); + setSelectedMiler(''); + setAssignDialogOpen(true); + }; + + const handleAssign = () => { + if (!selectedMiler) return; + const miler = AVAILABLE_MILERS.find(m => m.id === selectedMiler); + + setOrders(orders.map(o => { + if (o.id === selectedOrderForAssign.id) { + return { ...o, status: `Assigned to ${miler.name}`, assignedMiler: miler }; + } + return o; + })); + + // Remove from selection if it was selected + setSelectedOrders(prev => prev.filter(id => id !== selectedOrderForAssign.id)); + setAssignDialogOpen(false); + }; + + const handleAutoAssignAll = () => { + if (selectedOrders.length === 0) return; + + setOrders(orders.map(o => { + if (selectedOrders.includes(o.id) && o.status === 'Pending Assignment') { + // Just pick a random miler for auto-assign simulation + const randomMiler = AVAILABLE_MILERS[Math.floor(Math.random() * AVAILABLE_MILERS.length)]; + return { ...o, status: `Assigned to ${randomMiler.name}`, assignedMiler: randomMiler }; + } + return o; + })); + + // Clear selection + setSelectedOrders([]); + }; + + const pendingCount = orders.filter(o => o.status === 'Pending Assignment').length; + const isAllSelected = selectedOrders.length > 0 && selectedOrders.length === pendingCount; + + return ( + + + + + } + action={ + + } + sx={{ flexWrap: 'wrap', gap: 1, '& .MuiCardHeader-action': { m: 0, alignSelf: 'center' } }} + /> + + + {isMdDown ? ( + /* ── MOBILE / TABLET: cards ── */ + + {orders.map((row) => { + const isSelected = selectedOrders.includes(row.id); + const isAssigned = row.status !== 'Pending Assignment'; + return ( + + + + + {!isAssigned && ( + handleSelectOne(row.id)} /> + )} + + {row.id} + {row.time} + + + {!isAssigned + ? + : } label="Assigned" sx={{ fontWeight: 700, flexShrink: 0, bgcolor: '#E6F4EA', color: '#1E8E3E', '& .MuiChip-icon': { color: '#1E8E3E' } }} />} + + + + + + {row.customer} + + + + Pick up: {row.pickup} + + + + Going to: {row.drop} + + + + {row.package} + + + + {!isAssigned ? ( + + ) : ( + {row.status} + )} + + + ); + })} + + ) : ( + /* ── DESKTOP: spacious table ── */ + + + + + + 0 && selectedOrders.length < pendingCount} + checked={isAllSelected && pendingCount > 0} + onChange={handleSelectAll} + disabled={pendingCount === 0} + /> + + {['Request', 'Pick Up From', 'Going To', 'Parcel', 'Status', 'Action'].map((h, i) => ( + + {h} + + ))} + + + + {orders.map((row) => { + const isSelected = selectedOrders.includes(row.id); + const isAssigned = row.status !== 'Pending Assignment'; + return ( + + + handleSelectOne(row.id)} disabled={isAssigned} /> + + {row.id} + + {row.customer} + + + {row.pickup} + + + {row.drop} + {row.package} + + {!isAssigned + ? + : } label="Assigned" sx={{ fontWeight: 700, whiteSpace: 'nowrap', bgcolor: '#E6F4EA', color: '#1E8E3E', '& .MuiChip-icon': { color: '#1E8E3E' } }} />} + + + {!isAssigned ? ( + + ) : ( + {row.status} + )} + + + ); + })} + +
+
+ )} +
+ + setAssignDialogOpen(false)} maxWidth="sm" fullWidth> + Choose a Miler for {selectedOrderForAssign?.id} + + Available milers near {selectedOrderForAssign?.pickup}: + + {AVAILABLE_MILERS.map((miler) => ( + setSelectedMiler(miler.id)} + sx={{ + border: '1px solid', + borderColor: selectedMiler === miler.id ? 'primary.main' : 'divider', + borderRadius: 2, + mb: 1, + bgcolor: selectedMiler === miler.id ? 'primary.lighter' : 'transparent' + }} + > + + + + + + + setSelectedMiler(miler.id)} /> + + ))} + + + + + + + +
+ ); +} diff --git a/src/pages/operations/RiderRoutes.jsx b/src/pages/operations/RiderRoutes.jsx new file mode 100644 index 0000000..10a900b --- /dev/null +++ b/src/pages/operations/RiderRoutes.jsx @@ -0,0 +1,844 @@ +import React, { useEffect, useMemo, useRef, useState, useCallback } from 'react'; +import { + Box, Typography, Card, CardContent, Avatar, Chip, Stack, Button, Grid, + IconButton, List, ListItemButton, ListItemText, Collapse, Tooltip, Divider, + LinearProgress, Menu, MenuItem, Drawer, Paper +} from '@mui/material'; +import { alpha } from '@mui/material/styles'; +import { MapContainer, TileLayer, Marker, Popup, Polyline, Tooltip as LTooltip, useMap } from 'react-leaflet'; +import L from 'leaflet'; +import 'leaflet/dist/leaflet.css'; + +import RouteOutlinedIcon from '@mui/icons-material/RouteOutlined'; +import PlayArrowRoundedIcon from '@mui/icons-material/PlayArrowRounded'; +import PauseRoundedIcon from '@mui/icons-material/PauseRounded'; +import ReplayRoundedIcon from '@mui/icons-material/ReplayRounded'; +import SpeedRoundedIcon from '@mui/icons-material/SpeedRounded'; +import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined'; +import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined'; +import ExpandMoreRoundedIcon from '@mui/icons-material/ExpandMoreRounded'; +import ExpandLessRoundedIcon from '@mui/icons-material/ExpandLessRounded'; +import WarehouseRoundedIcon from '@mui/icons-material/WarehouseRounded'; +import FlagRoundedIcon from '@mui/icons-material/FlagRounded'; +import Inventory2OutlinedIcon from '@mui/icons-material/Inventory2Outlined'; +import CheckCircleRoundedIcon from '@mui/icons-material/CheckCircleRounded'; +import CancelRoundedIcon from '@mui/icons-material/CancelRounded'; +import DeliveryDiningRoundedIcon from '@mui/icons-material/DeliveryDiningRounded'; +import StorefrontOutlinedIcon from '@mui/icons-material/StorefrontOutlined'; +import GroupsOutlinedIcon from '@mui/icons-material/GroupsOutlined'; +import StraightenRoundedIcon from '@mui/icons-material/StraightenRounded'; +import PaymentsOutlinedIcon from '@mui/icons-material/PaymentsOutlined'; +import PhoneOutlinedIcon from '@mui/icons-material/PhoneOutlined'; +import PlaceOutlinedIcon from '@mui/icons-material/PlaceOutlined'; +import AccessTimeOutlinedIcon from '@mui/icons-material/AccessTimeOutlined'; +import PersonOutlineOutlinedIcon from '@mui/icons-material/PersonOutlineOutlined'; +import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded'; +import ScaleOutlinedIcon from '@mui/icons-material/ScaleOutlined'; +import ScheduleOutlinedIcon from '@mui/icons-material/ScheduleOutlined'; +import NotesOutlinedIcon from '@mui/icons-material/NotesOutlined'; +import CallOutlinedIcon from '@mui/icons-material/CallOutlined'; +import MyLocationOutlinedIcon from '@mui/icons-material/MyLocationOutlined'; + +// ════════════════════════════════════════════════════════════════════════════════ +// Leaflet base-icon fix (same approach as TrackingMap.jsx) +// ════════════════════════════════════════════════════════════════════════════════ +delete L.Icon.Default.prototype._getIconUrl; +L.Icon.Default.mergeOptions({ + iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon-2x.png', + iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png', + shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png', +}); + +// Keeps Leaflet's canvas sized correctly inside a flex layout / on sidebar toggle. +function MapResizeHandler() { + const map = useMap(); + useEffect(() => { + const fix = () => map.invalidateSize(); + const t = setTimeout(fix, 250); + window.addEventListener('resize', fix); + const ro = new ResizeObserver(fix); + ro.observe(map.getContainer()); + return () => { clearTimeout(t); window.removeEventListener('resize', fix); ro.disconnect(); }; + }, [map]); + return null; +} + +// Imperatively fits the map to a set of latlng points whenever they change. +function FitBounds({ points }) { + const map = useMap(); + useEffect(() => { + if (!points || points.length === 0) return; + const bounds = L.latLngBounds(points.map((p) => [p.lat, p.lng])); + if (bounds.isValid()) map.fitBounds(bounds, { padding: [60, 60], maxZoom: 15 }); + }, [points, map]); + return null; +} + +// Pans/zooms to a single point when an order is focused (clicked). +function FlyTo({ target }) { + const map = useMap(); + useEffect(() => { + if (target) map.flyTo([target.lat, target.lng], Math.max(map.getZoom(), 14), { duration: 0.6 }); + }, [target, map]); + return null; +} + +// ════════════════════════════════════════════════════════════════════════════════ +// Leaflet DivIcons +// ════════════════════════════════════════════════════════════════════════════════ +const hubIcon = new L.DivIcon({ + className: 'rr-icon', + html: `
+ +
`, + iconSize: [34, 34], + iconAnchor: [17, 17], +}); + +const flagIcon = new L.DivIcon({ + className: 'rr-icon', + html: `
+ +
`, + iconSize: [30, 30], + iconAnchor: [15, 15], +}); + +// Numbered stop pin in the rider's colour. Pickups get a square pin, deliveries a +// round one — so the two journey types are distinguishable at a glance on the map. +const stopIcon = (n, color, focused, isPickup) => new L.DivIcon({ + className: 'rr-icon', + html: `
${n}
`, + iconSize: focused ? [30, 30] : [24, 24], + iconAnchor: focused ? [15, 15] : [12, 12], +}); + +// The animated "moving rider" puck in the rider's colour. +const moverIcon = (color) => new L.DivIcon({ + className: 'rr-icon rr-mover', + html: `
+ +
`, + iconSize: [30, 30], + iconAnchor: [15, 15], +}); + +// ════════════════════════════════════════════════════════════════════════════════ +// Mock data — every rider has a DELIVERY trip and a PICKUP trip for the day, each +// with its own ordered stops, timings and distance. Every order stop carries the +// full detail shown in the side drawer when clicked. +// +// Delivery: hub → customer drops. Pickup: merchant collections → hub. +// ════════════════════════════════════════════════════════════════════════════════ +const HUB = { lat: 28.6139, lng: 77.2090, label: 'Delhi Operations Hub' }; +const hubStop = (time) => ({ kind: 'hub', label: HUB.label, lat: HUB.lat, lng: HUB.lng, time }); + +const RIDERS = [ + { + id: 'RDR-8012', name: 'Muthu Kumar', color: '#1A73E8', vehicle: 'Electric Bike', vehicleNo: 'DL-04-EB-1234', phone: '+91 98765 43210', + delivery: { + startTime: '08:12', endTime: '13:40', distanceKm: 18.4, + stops: [ + hubStop('08:12'), + { kind: 'order', orderId: 'ORD-100231', customer: 'Aarav Mehta', phone: '+91 90011 22334', address: 'Flat 402, Dwarka Sector 12, New Delhi', lat: 28.5921, lng: 77.0460, time: '08:48', status: 'Picked', items: 2, weight: '1.4 kg', slot: '08:00–10:00', cod: 0, payment: 'Prepaid', legKm: 5.2, instructions: 'Leave at reception if not home.' }, + { kind: 'order', orderId: 'ORD-100244', customer: 'Priya Nair', phone: '+91 90022 33445', address: 'House 18, Janakpuri B-Block, New Delhi', lat: 28.6219, lng: 77.0878, time: '09:36', status: 'Picked', items: 1, weight: '0.6 kg', slot: '09:00–11:00', cod: 1200, payment: 'COP', legKm: 4.1, instructions: 'Call on arrival.' }, + { kind: 'order', orderId: 'ORD-100258', customer: 'Rohit Sethi', phone: '+91 90033 44556', address: 'Shop 7, Rajouri Garden Market, New Delhi', lat: 28.6492, lng: 77.1207, time: '10:25', status: 'Failed', items: 3, weight: '2.8 kg', slot: '10:00–12:00', cod: 0, payment: 'Prepaid', legKm: 4.6, instructions: 'Customer unreachable — reattempt tomorrow.' }, + { kind: 'order', orderId: 'ORD-100269', customer: 'Sana Kapoor', phone: '+91 90044 55667', address: 'A-22, Karol Bagh, New Delhi', lat: 28.6512, lng: 77.1907, time: '11:30', status: 'Picked', items: 1, weight: '0.9 kg', slot: '11:00–13:00', cod: 850, payment: 'COP', legKm: 4.5, instructions: '' }, + ], + }, + pickup: { + startTime: '14:10', endTime: '16:50', distanceKm: 11.2, + stops: [ + { kind: 'order', orderId: 'PCK-50118', customer: 'TrendKart Store', phone: '+91 98801 11222', address: 'Tilak Nagar Main Rd, New Delhi', lat: 28.6363, lng: 77.0945, time: '14:35', status: 'Picked', items: 6, weight: '4.2 kg', slot: '14:00–16:00', cod: 0, payment: 'Merchant', legKm: 6.0, instructions: 'Collect from back gate.' }, + { kind: 'order', orderId: 'PCK-50126', customer: 'FreshLeaf Organics', phone: '+91 98802 22333', address: 'Subhash Nagar, New Delhi', lat: 28.6404, lng: 77.1199, time: '15:30', status: 'Picked', items: 3, weight: '5.5 kg', slot: '15:00–17:00', cod: 0, payment: 'Merchant', legKm: 3.0, instructions: '' }, + { kind: 'order', orderId: 'PCK-50131', customer: 'GadgetHub', phone: '+91 98803 33444', address: 'Moti Nagar, New Delhi', lat: 28.6580, lng: 77.1450, time: '16:15', status: 'Missed', items: 2, weight: '1.1 kg', slot: '16:00–18:00', cod: 0, payment: 'Merchant', legKm: 2.2, instructions: 'Shop was closed at pickup time.' }, + hubStop('16:50'), + ], + }, + }, + { + id: 'RDR-8041', name: 'Sana Sheikh', color: '#8E24AA', vehicle: 'Motorcycle', vehicleNo: 'DL-02-MC-1199', phone: '+91 98765 43214', + delivery: { + startTime: '08:00', endTime: '14:05', distanceKm: 22.9, + stops: [ + hubStop('08:00'), + { kind: 'order', orderId: 'ORD-100277', customer: 'Imran Qureshi', phone: '+91 90055 66778', address: 'N-Block, Connaught Place, New Delhi', lat: 28.6315, lng: 77.2167, time: '08:30', status: 'Picked', items: 1, weight: '0.4 kg', slot: '08:00–10:00', cod: 0, payment: 'Prepaid', legKm: 2.1, instructions: '' }, + { kind: 'order', orderId: 'ORD-100283', customer: 'Neha Gupta', phone: '+91 90066 77889', address: 'C-44, Lajpat Nagar II, New Delhi', lat: 28.5677, lng: 77.2433, time: '09:20', status: 'Picked', items: 2, weight: '1.7 kg', slot: '09:00–11:00', cod: 1450, payment: 'COP', legKm: 7.4, instructions: 'Ring twice.' }, + { kind: 'order', orderId: 'ORD-100291', customer: 'Vikas Rao', phone: '+91 90077 88990', address: 'J-Block, Saket, New Delhi', lat: 28.5245, lng: 77.2066, time: '10:40', status: 'Picked', items: 1, weight: '0.8 kg', slot: '10:00–12:00', cod: 0, payment: 'Prepaid', legKm: 6.2, instructions: '' }, + { kind: 'order', orderId: 'ORD-100305', customer: 'Diya Shah', phone: '+91 90088 99001', address: 'Malviya Nagar Main Market, New Delhi', lat: 28.5355, lng: 77.2110, time: '11:55', status: 'Picked', items: 4, weight: '3.1 kg', slot: '11:00–13:00', cod: 2300, payment: 'COP', legKm: 1.4, instructions: 'Heavy parcel — handle with care.' }, + ], + }, + pickup: { + startTime: '14:30', endTime: '17:20', distanceKm: 14.6, + stops: [ + { kind: 'order', orderId: 'PCK-50140', customer: 'Bloom & Co Florists', phone: '+91 98804 44555', address: 'Greater Kailash I, New Delhi', lat: 28.5494, lng: 77.2426, time: '15:00', status: 'Picked', items: 4, weight: '2.0 kg', slot: '14:30–16:30', cod: 0, payment: 'Merchant', legKm: 8.1, instructions: '' }, + { kind: 'order', orderId: 'PCK-50147', customer: 'BookNook', phone: '+91 98805 55666', address: 'Hauz Khas Village, New Delhi', lat: 28.5535, lng: 77.1944, time: '16:05', status: 'Picked', items: 9, weight: '7.8 kg', slot: '15:30–17:30', cod: 0, payment: 'Merchant', legKm: 4.5, instructions: 'Multiple boxes.' }, + hubStop('17:20'), + ], + }, + }, + { + id: 'RDR-8015', name: 'Rajesh Sharma', color: '#1E8E3E', vehicle: 'Cargo Van', vehicleNo: 'DL-01-CV-9876', phone: '+91 98765 43211', + delivery: { + startTime: '07:50', endTime: '15:10', distanceKm: 31.2, + stops: [ + hubStop('07:50'), + { kind: 'order', orderId: 'ORD-100312', customer: 'Anil Verma', phone: '+91 90099 00112', address: 'Sector 7, Rohini, New Delhi', lat: 28.7042, lng: 77.1025, time: '08:55', status: 'Picked', items: 5, weight: '6.2 kg', slot: '08:00–10:00', cod: 0, payment: 'Prepaid', legKm: 12.4, instructions: '' }, + { kind: 'order', orderId: 'ORD-100320', customer: 'Meera Iyer', phone: '+91 90100 11223', address: 'NSP, Pitampura, New Delhi', lat: 28.6996, lng: 77.1314, time: '09:50', status: 'Picked', items: 2, weight: '2.0 kg', slot: '09:00–11:00', cod: 990, payment: 'COP', legKm: 3.2, instructions: '' }, + { kind: 'order', orderId: 'ORD-100334', customer: 'Sahil Khan', phone: '+91 90111 22334', address: 'Model Town III, New Delhi', lat: 28.7158, lng: 77.1910, time: '11:10', status: 'Failed', items: 1, weight: '0.7 kg', slot: '10:00–12:00', cod: 0, payment: 'Prepaid', legKm: 6.1, instructions: 'Wrong address provided.' }, + { kind: 'order', orderId: 'ORD-100349', customer: 'Tara Bose', phone: '+91 90122 33445', address: 'Civil Lines, New Delhi', lat: 28.6796, lng: 77.2240, time: '12:30', status: 'Picked', items: 3, weight: '4.4 kg', slot: '12:00–14:00', cod: 3100, payment: 'COP', legKm: 5.0, instructions: '' }, + ], + }, + pickup: { + startTime: '15:40', endTime: '18:30', distanceKm: 19.8, + stops: [ + { kind: 'order', orderId: 'PCK-50155', customer: 'MegaMart Warehouse', phone: '+91 98806 66777', address: 'Wazirpur Industrial Area, New Delhi', lat: 28.6991, lng: 77.1612, time: '16:20', status: 'Picked', items: 24, weight: '38.0 kg', slot: '16:00–18:00', cod: 0, payment: 'Merchant', legKm: 11.0, instructions: 'Use loading dock 4.' }, + { kind: 'order', orderId: 'PCK-50163', customer: 'HomeStyle Furnishings', phone: '+91 98807 77888', address: 'Ashok Vihar, New Delhi', lat: 28.6924, lng: 77.1760, time: '17:25', status: 'Picked', items: 8, weight: '22.5 kg', slot: '17:00–19:00', cod: 0, payment: 'Merchant', legKm: 3.0, instructions: '' }, + hubStop('18:30'), + ], + }, + }, + { + id: 'RDR-8044', name: 'Harpreet Gill', color: '#E8710A', vehicle: 'Cycle', vehicleNo: '—', phone: '+91 98765 43215', + delivery: { + startTime: '09:20', endTime: '13:15', distanceKm: 9.7, + stops: [ + hubStop('09:20'), + { kind: 'order', orderId: 'ORD-100356', customer: 'Kabir Anand', phone: '+91 90133 44556', address: 'Mayur Vihar Phase I, New Delhi', lat: 28.6090, lng: 77.2920, time: '10:05', status: 'Picked', items: 1, weight: '0.5 kg', slot: '10:00–12:00', cod: 600, payment: 'COP', legKm: 9.0, instructions: '' }, + { kind: 'order', orderId: 'ORD-100361', customer: 'Ritu Saxena', phone: '+91 90144 55667', address: 'Mayur Vihar Phase III, New Delhi', lat: 28.6135, lng: 77.3215, time: '11:10', status: 'Picked', items: 2, weight: '1.2 kg', slot: '11:00–13:00', cod: 0, payment: 'Prepaid', legKm: 3.0, instructions: '' }, + { kind: 'order', orderId: 'ORD-100370', customer: 'Farhan Ali', phone: '+91 90155 66778', address: 'Patparganj, New Delhi', lat: 28.6280, lng: 77.2960, time: '12:20', status: 'Picked', items: 1, weight: '0.8 kg', slot: '12:00–14:00', cod: 450, payment: 'COP', legKm: 2.9, instructions: '' }, + ], + }, + pickup: { + startTime: '13:40', endTime: '15:30', distanceKm: 6.4, + stops: [ + { kind: 'order', orderId: 'PCK-50170', customer: 'Cafe Mosaic', phone: '+91 98808 88999', address: 'Mayur Vihar Phase I Market, New Delhi', lat: 28.6055, lng: 77.2985, time: '14:10', status: 'Picked', items: 2, weight: '1.5 kg', slot: '14:00–16:00', cod: 0, payment: 'Merchant', legKm: 4.0, instructions: '' }, + hubStop('15:30'), + ], + }, + }, +]; + +// ── helpers ──────────────────────────────────────────────────────────────────── +const initials = (n) => n.split(' ').map((w) => w[0]).slice(0, 2).join('').toUpperCase(); +const inr = (n) => `₹${(Number(n) || 0).toLocaleString('en-IN')}`; +const lerpPoint = (a, b, t) => ({ lat: a.lat + (b.lat - a.lat) * t, lng: a.lng + (b.lng - a.lng) * t }); + +const STATUS_META = { + Picked: { color: '#1A73E8', icon: CheckCircleRoundedIcon, label: 'Picked up' }, + Missed: { color: '#D93025', icon: CancelRoundedIcon, label: 'Missed' }, +}; + +const MODES = { + pickup: { label: 'Pickups', icon: StorefrontOutlinedIcon, doneLabel: 'Picked up', doneStatus: 'Picked', failStatus: 'Missed', pointLabel: 'Pickup', dash: '8 8' }, +}; + +// ════════════════════════════════════════════════════════════════════════════════ +// Route resolution — OSRM road geometry (free, no API key); straight-line fallback. +// ════════════════════════════════════════════════════════════════════════════════ +async function fetchRoadRoute(stops) { + const coords = stops.map((s) => `${s.lng},${s.lat}`).join(';'); + const url = `https://router.project-osrm.org/route/v1/driving/${coords}?overview=full&geometries=geojson`; + const res = await fetch(url); + const json = await res.json(); + if (json.routes && json.routes[0]) { + return json.routes[0].geometry.coordinates.map(([lng, lat]) => ({ lat, lng })); + } + throw new Error('No route'); +} + +// ════════════════════════════════════════════════════════════════════════════════ +// Small presentational pieces +// ════════════════════════════════════════════════════════════════════════════════ +function KpiCard({ icon: Icon, label, value, sub, color, bg }) { + return ( + + + + + + + + {label} + + + {value} + {sub && {sub}} + + + ); +} + +function DetailRow({ icon: Icon, label, value, valueColor }) { + if (value === undefined || value === null || value === '') return null; + return ( + + + + {label} + {value} + + + ); +} + +// Full order/pickup detail panel — rendered INLINE in the left column (not a modal) +// so the map stays visible and zoomed to the stop while these details are read. +function OrderDetailPanel({ data, onBack }) { + const { order, rider, mode, index } = data; + const meta = STATUS_META[order.status] || {}; + const StatusIcon = meta.icon || CheckCircleRoundedIcon; + const isPickup = mode === 'pickup'; + + return ( + + {/* Header */} + + + + : )} label={isPickup ? 'Pickup' : 'Delivery'} + sx={{ bgcolor: 'rgba(255,255,255,0.18)', color: '#fff', fontWeight: 700, '& .MuiChip-icon': { color: '#fff' } }} /> + } label={meta.label || order.status} + sx={{ bgcolor: 'rgba(255,255,255,0.18)', color: '#fff', fontWeight: 700 }} /> + + {order.customer} + #{order.orderId} + + + {/* Body */} + + + + {/* Contact */} + + + {isPickup ? 'MERCHANT / SENDER' : 'CUSTOMER'} + + + + + + + + + {/* Pickup summary */} + + + PICKUP SUMMARY + + + + + + + + + + + + {order.cod > 0 && ( + + + + + CASH ON PICKUP + {inr(order.cod)} + + + + )} + + {/* Route & location */} + + + ROUTE & LOCATION + + + + + {order.instructions && } + + + + {/* Assigned miler */} + + + ASSIGNED MILER + + + {initials(rider.name)} + + {rider.name} + {rider.vehicle} · {rider.vehicleNo} · Stop {index} + + + + + + + + {/* Footer */} + + + + + + ); +} + +// ════════════════════════════════════════════════════════════════════════════════ +// MAIN COMPONENT +// ════════════════════════════════════════════════════════════════════════════════ +export default function RiderRoutes() { + const [mode] = useState('pickup'); // pickups only + const [visible, setVisible] = useState(() => Object.fromEntries(RIDERS.map((r) => [r.id, true]))); + const [routes, setRoutes] = useState({}); // keyed `${id}__${mode}` + const [expanded, setExpanded] = useState(RIDERS[0].id); + const [focusedStop, setFocusedStop] = useState(null); // `${riderId}-${index}` + const [detail, setDetail] = useState(null); // { order, rider, mode, index } + const [flyTarget, setFlyTarget] = useState(null); + + // Animation state. + const [playing, setPlaying] = useState(null); + const [progress, setProgress] = useState(0); + const [speed, setSpeed] = useState(1); + const [speedAnchor, setSpeedAnchor] = useState(null); + const rafRef = useRef(null); + const lastTsRef = useRef(0); + const resolvedRef = useRef({}); // keys we've already fetched/attempted + + const modeCfg = MODES[mode]; + + // Resolve road routes for the active mode (cached per id+mode). A ref guards + // against re-fetching keys we've already resolved when the tab is revisited. + useEffect(() => { + let cancelled = false; + (async () => { + await Promise.all( + RIDERS.map(async (r) => { + const key = `${r.id}__${mode}`; + if (resolvedRef.current[key]) return; + resolvedRef.current[key] = true; + const stops = r[mode].stops; + let path; + try { path = await fetchRoadRoute(stops); } + catch { path = stops.map((s) => ({ lat: s.lat, lng: s.lng })); } + if (!cancelled) setRoutes((prev) => ({ ...prev, [key]: path })); + }) + ); + })(); + return () => { cancelled = true; }; + }, [mode]); + + const pathFor = useCallback( + (r) => routes[`${r.id}__${mode}`] || r[mode].stops.map((s) => ({ lat: s.lat, lng: s.lng })), + [routes, mode] + ); + + const stopsOf = useCallback((r) => r[mode].stops, [mode]); + + // Auto-fit points = visible riders' stops for the active mode. + const fitPoints = useMemo(() => { + const pts = []; + RIDERS.forEach((r) => { if (visible[r.id]) stopsOf(r).forEach((s) => pts.push(s)); }); + return pts; + }, [visible, stopsOf]); + + // ── Analysis KPIs for the active mode ───────────────────────────────────────── + const kpi = useMemo(() => { + let orders = 0, done = 0, fail = 0, km = 0, cod = 0, activeRiders = 0; + RIDERS.forEach((r) => { + const trip = r[mode]; + const orderStops = trip.stops.filter((s) => s.kind === 'order'); + if (orderStops.length) activeRiders += 1; + orders += orderStops.length; + done += orderStops.filter((s) => s.status === modeCfg.doneStatus).length; + fail += orderStops.filter((s) => s.status === modeCfg.failStatus).length; + km += trip.distanceKm; + cod += orderStops.reduce((s, o) => s + (o.cod || 0), 0); + }); + return { orders, done, fail, km: km.toFixed(1), cod, activeRiders }; + }, [mode, modeCfg]); + + // ── Animation driver ────────────────────────────────────────────────────────── + useEffect(() => { + if (!playing) { if (rafRef.current) cancelAnimationFrame(rafRef.current); return; } + lastTsRef.current = 0; + const DURATION = 14000; + const tick = (ts) => { + if (!lastTsRef.current) lastTsRef.current = ts; + const dt = ts - lastTsRef.current; + lastTsRef.current = ts; + setProgress((p) => { + const nextP = p + (dt * speed) / DURATION; + if (nextP >= 1) { setPlaying(null); return 1; } + return nextP; + }); + rafRef.current = requestAnimationFrame(tick); + }; + rafRef.current = requestAnimationFrame(tick); + return () => { if (rafRef.current) cancelAnimationFrame(rafRef.current); }; + }, [playing, speed]); + + // Stop any animation when switching tabs. + useEffect(() => { setPlaying(null); setProgress(0); }, [mode]); + + const startAnim = (riderId) => { + setVisible((v) => ({ ...v, [riderId]: true })); + if (playing === riderId) { setPlaying(null); return; } + if (playing !== riderId) setProgress(0); + setPlaying(riderId); + }; + const resetAnim = () => { setPlaying(null); setProgress(0); }; + const toggleVisible = (id) => setVisible((v) => ({ ...v, [id]: !v[id] })); + + const openDetail = (rider, order, index) => { + setDetail({ order, rider, mode, index }); + setExpanded(rider.id); + setFocusedStop(`${rider.id}-${index}`); + setFlyTarget({ lat: order.lat, lng: order.lng }); + }; + const closeDetail = () => { setDetail(null); setFlyTarget(null); setFocusedStop(null); }; + + const playState = useMemo(() => { + if (!playing) return null; + const rider = RIDERS.find((r) => r.id === playing); + const path = pathFor(rider); + if (path.length < 2) return null; + const totalSegs = path.length - 1; + const exact = progress * totalSegs; + const i = Math.min(Math.floor(exact), totalSegs - 1); + const frac = exact - i; + const pos = lerpPoint(path[i], path[i + 1], frac); + const travelled = [...path.slice(0, i + 1), pos]; + return { rider, path, travelled, pos }; + }, [playing, progress, pathFor]); + + return ( + + {/* ── Header ── */} + + + + + + + Rider Routes + + Pickups each miler covered today — open any order for full details, or press play to replay the trip. + + + + + + + {/* ── Analysis KPI strip ── */} + + {[ + { icon: GroupsOutlinedIcon, label: 'Active Milers', value: kpi.activeRiders, sub: `of ${RIDERS.length}`, color: '#1A73E8', bg: '#E8F0FE' }, + { icon: modeCfg.icon, label: modeCfg.label, value: kpi.orders, sub: 'pickups covered', color: '#C01227', bg: alpha('#C01227', 0.1) }, + { icon: CheckCircleRoundedIcon, label: modeCfg.doneLabel, value: kpi.done, sub: `${kpi.fail} missed`, color: '#1E8E3E', bg: '#E6F4EA' }, + { icon: StraightenRoundedIcon, label: 'Distance', value: `${kpi.km} km`, sub: 'fleet total today', color: '#8E24AA', bg: '#F3E5F5' }, + ].map((k, i) => ( + + ))} + + + + {/* ── Left control panel — the milers list; clicking an order opens the + full detail in a right-side drawer (below). ── */} + + + + Milers & their {modeCfg.label.toLowerCase()} + {(playing || progress > 0) && ( + + )} + + + + {RIDERS.map((rider) => { + const trip = rider[mode]; + const orders = trip.stops.filter((s) => s.kind === 'order'); + const done = orders.filter((o) => o.status === modeCfg.doneStatus).length; + const isOpen = expanded === rider.id; + const isPlaying = playing === rider.id; + const isVisible = visible[rider.id]; + return ( + + + + {initials(rider.name)} + setExpanded(isOpen ? null : rider.id)} sx={{ flex: 1, borderRadius: 2, px: 1, py: 0.5, minWidth: 0 }}> + {rider.name}} + secondary={{done}/{orders.length} {modeCfg.doneLabel.toLowerCase()} · {trip.distanceKm} km} + /> + {isOpen ? : } + + + + {/* per-rider stat chips (analysis) */} + + } label={`${orders.length} ${modeCfg.label.toLowerCase()}`} sx={{ height: 24, fontWeight: 600, bgcolor: '#F1F3F5' }} /> + } label={done} sx={{ height: 24, fontWeight: 600, bgcolor: alpha('#1E8E3E', 0.1), color: '#1E8E3E' }} /> + } label={`${trip.distanceKm} km`} sx={{ height: 24, fontWeight: 600, bgcolor: '#F1F3F5' }} /> + } label={`${trip.startTime}–${trip.endTime}`} sx={{ height: 24, fontWeight: 600, bgcolor: '#F1F3F5' }} /> + + + {/* action row */} + + + + toggleVisible(rider.id)} sx={{ border: '1px solid #E9ECEF', borderRadius: 2 }}> + {isVisible ? : } + + + + + {isPlaying && ( + + + + )} + + {/* expandable stops — rich order cards; click to open detail */} + + + + {trip.stops.map((s, i) => { + const key = `${rider.id}-${i}`; + const isHub = s.kind === 'hub'; + const meta = STATUS_META[s.status]; + const StatusIcon = meta?.icon; + + // Hub return — compact row, not a card. + if (isHub) { + return ( + + + + + + {s.label} + Back to hub · {s.time} + + + ); + } + + return ( + setFocusedStop(key)} + onMouseLeave={() => setFocusedStop((f) => (f === key ? null : f))} + onClick={() => openDetail(rider, s, i)} + sx={{ + p: 1.5, borderRadius: 2, cursor: 'pointer', transition: 'all .15s', + border: '1px solid', borderColor: focusedStop === key ? alpha(rider.color, 0.55) : '#ECEEF1', + bgcolor: focusedStop === key ? alpha(rider.color, 0.04) : '#fff', + boxShadow: '0 1px 3px rgba(0,0,0,0.03)', + '&:hover': { borderColor: alpha(rider.color, 0.55), boxShadow: '0 4px 14px rgba(0,0,0,0.07)' }, + }} + > + {/* order id + status */} + + + {i} + + Order #{s.orderId} + + + {meta && ( + } label={meta.label} + sx={{ height: 22, fontSize: '0.68rem', fontWeight: 700, color: meta.color, bgcolor: alpha(meta.color, 0.1), flexShrink: 0 }} /> + )} + + + {/* rider + time */} + + + + {rider.name} + + + + {s.time} + + + + + + {/* merchant + address */} + + + {s.customer} + + + + {s.address} + + + {/* metric chips */} + + } label={`${s.legKm} km`} sx={{ height: 22, fontSize: '0.68rem', fontWeight: 600, bgcolor: '#F1F3F5' }} /> + } label={s.weight} sx={{ height: 22, fontSize: '0.68rem', fontWeight: 600, bgcolor: '#F1F3F5' }} /> + } label={`${s.items} ${s.items === 1 ? 'parcel' : 'parcels'}`} sx={{ height: 22, fontSize: '0.68rem', fontWeight: 600, bgcolor: '#F1F3F5' }} /> + + + ); + })} + + + + + ); + })} + + + + + {/* ── Map ── */} + + + {playState && ( + + + {initials(playState.rider.name)} + + {playState.rider.name} + Replaying {modeCfg.label.toLowerCase().replace(/s$/, '')} · {Math.round(progress * 100)}% + + setPlaying(null)}> + setSpeedAnchor(e.currentTarget)}> + + + + )} + setSpeedAnchor(null)}> + {[0.5, 1, 2, 4].map((s) => ( { setSpeed(s); setSpeedAnchor(null); }}>{s}× speed))} + + + + + {!playing && !flyTarget && } + + + + + {HUB.label}
Pickups return here
+
+ + {RIDERS.map((rider) => { + if (!visible[rider.id]) return null; + const path = pathFor(rider); + const stops = stopsOf(rider); + const dimmed = playing && playing !== rider.id; + const endStop = stops[stops.length - 1]; + return ( + + [p.lat, p.lng])} pathOptions={{ color: rider.color, weight: 5, opacity: dimmed ? 0.15 : 0.85, dashArray: modeCfg.dash }} /> + {stops.map((s, i) => { + if (s.kind === 'hub') return null; + const key = `${rider.id}-${i}`; + return ( + openDetail(rider, s, i) }} + > + + {modeCfg.pointLabel} {i} · {s.customer} + {s.address} + #{s.orderId} · {s.time} · {STATUS_META[s.status]?.label} + openDetail(rider, s, i)}>View full details → + + + ); + })} + {!dimmed && ( + + {mode === 'pickup' ? 'Returned to hub' : 'Trip end'} · {rider[mode].endTime} + + )} + + ); + })} + + {playState && ( + <> + [p.lat, p.lng])} pathOptions={{ color: playState.rider.color, weight: 7, opacity: 1 }} /> + + {playState.rider.name} + + + )} +
+
+ + {/* Legend */} + + {RIDERS.map((r) => ( + toggleVisible(r.id)}> + + {r.name} + + ))} + + + + {mode === 'pickup' ? 'Hub return' : 'Trip end'} + + + + Hub + + +
+
+ + {/* ── Order detail — right-side drawer ── */} + + {detail && } + +
+ ); +} diff --git a/src/pages/operations/Riders.jsx b/src/pages/operations/Riders.jsx new file mode 100644 index 0000000..cacbb2c --- /dev/null +++ b/src/pages/operations/Riders.jsx @@ -0,0 +1,1373 @@ +import React, { useState, useMemo, useEffect } from 'react'; +import { + Box, Typography, Card, CardContent, Avatar, Chip, Table, TableBody, + TableCell, TableContainer, TableHead, TableRow, IconButton, Button, + Stack, Tooltip, LinearProgress, Dialog, DialogContent, DialogActions, Drawer, + TextField, MenuItem, Divider, InputAdornment, Menu, ListItemIcon, + Snackbar, Alert, useMediaQuery, Grid, Select, FormControl, InputLabel, + Autocomplete, Switch, FormControlLabel, Paper, ToggleButtonGroup, + ToggleButton, Stepper, Step, StepLabel +} from '@mui/material'; +import { useTheme, alpha } from '@mui/material/styles'; + +// ── Professional outlined icon set ────────────────────────────────────────────── +import AddOutlinedIcon from '@mui/icons-material/AddOutlined'; +import SearchOutlinedIcon from '@mui/icons-material/SearchOutlined'; +import EditOutlinedIcon from '@mui/icons-material/EditOutlined'; +import DeleteOutlineIcon from '@mui/icons-material/DeleteOutlineOutlined'; +import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined'; +import MoreVertOutlinedIcon from '@mui/icons-material/MoreVertOutlined'; +import CloseOutlinedIcon from '@mui/icons-material/CloseOutlined'; +import VerifiedOutlinedIcon from '@mui/icons-material/VerifiedOutlined'; +import CircleRoundedIcon from '@mui/icons-material/CircleRounded'; +import StarRoundedIcon from '@mui/icons-material/StarRounded'; +import PhoneOutlinedIcon from '@mui/icons-material/PhoneOutlined'; +import CallOutlinedIcon from '@mui/icons-material/CallOutlined'; +import PlaceOutlinedIcon from '@mui/icons-material/PlaceOutlined'; +import BadgeOutlinedIcon from '@mui/icons-material/BadgeOutlined'; +import PersonOutlineOutlinedIcon from '@mui/icons-material/PersonOutlineOutlined'; +import PersonAddAlt1OutlinedIcon from '@mui/icons-material/PersonAddAlt1Outlined'; +import GroupsOutlinedIcon from '@mui/icons-material/GroupsOutlined'; +import TwoWheelerOutlinedIcon from '@mui/icons-material/TwoWheelerOutlined'; +import ElectricBikeOutlinedIcon from '@mui/icons-material/ElectricBikeOutlined'; +import PedalBikeOutlinedIcon from '@mui/icons-material/PedalBikeOutlined'; +import LocalShippingOutlinedIcon from '@mui/icons-material/LocalShippingOutlined'; +import AirportShuttleOutlinedIcon from '@mui/icons-material/AirportShuttleOutlined'; +import InventoryOutlinedIcon from '@mui/icons-material/Inventory2Outlined'; +import TrendingUpOutlinedIcon from '@mui/icons-material/TrendingUpOutlined'; +import PaymentsOutlinedIcon from '@mui/icons-material/PaymentsOutlined'; +import AccessTimeOutlinedIcon from '@mui/icons-material/AccessTimeOutlined'; +import WarningAmberOutlinedIcon from '@mui/icons-material/WarningAmberOutlined'; +import CheckCircleOutlinedIcon from '@mui/icons-material/CheckCircleOutlined'; +import RouteOutlinedIcon from '@mui/icons-material/RouteOutlined'; +import GppGoodOutlinedIcon from '@mui/icons-material/GppGoodOutlined'; +import ApartmentOutlinedIcon from '@mui/icons-material/ApartmentOutlined'; +import TableRowsOutlinedIcon from '@mui/icons-material/TableRowsOutlined'; +import GridViewOutlinedIcon from '@mui/icons-material/GridViewOutlined'; +import DownloadOutlinedIcon from '@mui/icons-material/DownloadOutlined'; +import HomeWorkOutlinedIcon from '@mui/icons-material/HomeWorkOutlined'; +import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded'; + +// ── Reference data ────────────────────────────────────────────────────────────── +const VEHICLES = { + 'Electric Bike': { capacity: 30, icon: ElectricBikeOutlinedIcon }, + 'Motorcycle': { capacity: 25, icon: TwoWheelerOutlinedIcon }, + 'Cycle': { capacity: 15, icon: PedalBikeOutlinedIcon }, + 'Cargo Van': { capacity: 120, icon: AirportShuttleOutlinedIcon }, + 'Mini Truck': { capacity: 200, icon: LocalShippingOutlinedIcon }, +}; +const VEHICLE_TYPES = Object.keys(VEHICLES); + +const ALL_ZONES = ['Dwarka', 'Janakpuri', 'Saket', 'Malviya Nagar', 'Rohini', 'Vasant Kunj', 'Central Delhi', 'Lajpat Nagar', 'Karol Bagh', 'Connaught Place', 'Mayur Vihar']; +const HUB_OPTIONS = ['Delhi Operations Hub', 'Mumbai Hub (BOM-02)', 'Bengaluru Hub (BLR-03)', 'Jaipur Hub (JAI-08)']; +const STATUS_OPTIONS = ['On Pickup', 'Idle', 'On Break', 'Returning to Hub', 'Offline', 'Suspended']; + +const STATUS_META = { + 'On Pickup': { color: '#1A73E8', bg: '#E8F0FE', label: 'On Pickup' }, + 'Idle': { color: '#B06000', bg: '#FEF7E0', label: 'Idle / Available' }, + 'On Break': { color: '#8E24AA', bg: '#F3E5F5', label: 'On Break' }, + 'Returning to Hub': { color: '#0B8043', bg: '#E6F4EA', label: 'Returning' }, + 'Offline': { color: '#80868B', bg: '#F1F3F4', label: 'Offline' }, + 'Suspended': { color: '#D93025', bg: '#FCE8E6', label: 'Suspended' }, +}; + +let idSeq = 8060; +const genId = () => `RDR-${idSeq++}`; + +// ── Seed roster ──────────────────────────────────────────────────────────────── +const SEED = [ + { + id: 'RDR-8012', name: 'Muthu Kumar', phone: '+91 98765 43210', hub: 'Delhi Operations Hub', + zones: ['Dwarka', 'Janakpuri'], vehicle: 'Electric Bike', vehicleNo: 'DL-04-EB-1234', + status: 'On Pickup', checkInTime: '08:12', hoursToday: 6.4, + assigned: 24, capacity: 30, pickupsPending: 3, deliveriesPending: 21, + deliveriesDone: 45, deliveriesFailed: 2, codCollected: 4500, codPending: 1200, + rating: 4.8, verified: true, + }, + { + id: 'RDR-8015', name: 'Rajesh Sharma', phone: '+91 98765 43211', hub: 'Delhi Operations Hub', + zones: ['Saket', 'Malviya Nagar'], vehicle: 'Cargo Van', vehicleNo: 'DL-01-CV-9876', + status: 'On Pickup', checkInTime: '07:50', hoursToday: 6.8, + assigned: 88, capacity: 120, pickupsPending: 12, deliveriesPending: 76, + deliveriesDone: 110, deliveriesFailed: 4, codCollected: 12000, codPending: 3400, + rating: 4.9, verified: true, + }, + { + id: 'RDR-8022', name: 'Vikram Singh', phone: '+91 98765 43212', hub: 'Delhi Operations Hub', + zones: ['Rohini'], vehicle: 'Motorcycle', vehicleNo: 'DL-08-MC-4567', + status: 'Idle', checkInTime: '09:05', hoursToday: 5.2, + assigned: 0, capacity: 25, pickupsPending: 0, deliveriesPending: 0, + deliveriesDone: 68, deliveriesFailed: 1, codCollected: 0, codPending: 0, + rating: 4.5, verified: false, + }, + // ... (rest of seed data remains the same) + { + id: 'RDR-8030', name: 'Amit Patel', phone: '+91 98765 43213', hub: 'Delhi Operations Hub', + zones: ['Vasant Kunj'], vehicle: 'Electric Bike', vehicleNo: 'DL-03-EB-7654', + status: 'Returning to Hub', checkInTime: '08:30', hoursToday: 7.1, + assigned: 2, capacity: 30, pickupsPending: 0, deliveriesPending: 2, + deliveriesDone: 55, deliveriesFailed: 6, codCollected: 8500, codPending: 0, + rating: 4.2, verified: true, + }, + { + id: 'RDR-8041', name: 'Sana Sheikh', phone: '+91 98765 43214', hub: 'Delhi Operations Hub', + zones: ['Central Delhi', 'Karol Bagh'], vehicle: 'Motorcycle', vehicleNo: 'DL-02-MC-1199', + status: 'On Pickup', checkInTime: '08:00', hoursToday: 6.6, + assigned: 19, capacity: 25, pickupsPending: 2, deliveriesPending: 17, + deliveriesDone: 73, deliveriesFailed: 0, codCollected: 6200, codPending: 900, + rating: 5.0, verified: true, + }, + { + id: 'RDR-8044', name: 'Harpreet Gill', phone: '+91 98765 43215', hub: 'Delhi Operations Hub', + zones: ['Mayur Vihar'], vehicle: 'Cycle', vehicleNo: '—', + status: 'On Break', checkInTime: '09:20', hoursToday: 3.9, + assigned: 8, capacity: 15, pickupsPending: 1, deliveriesPending: 7, + deliveriesDone: 22, deliveriesFailed: 1, codCollected: 1500, codPending: 300, + rating: 4.6, verified: true, + }, + { + id: 'RDR-8050', name: 'Deepak Yadav', phone: '+91 98765 43216', hub: 'Delhi Operations Hub', + zones: ['Lajpat Nagar'], vehicle: 'Mini Truck', vehicleNo: 'DL-09-MT-3321', + status: 'Offline', checkInTime: '—', hoursToday: 0, + assigned: 0, capacity: 200, pickupsPending: 0, deliveriesPending: 0, + deliveriesDone: 0, deliveriesFailed: 0, codCollected: 0, codPending: 0, + rating: 4.4, verified: false, + }, + { + id: 'RDR-8055', name: 'Iqbal Ahmed', phone: '+91 98765 43217', hub: 'Delhi Operations Hub', + zones: ['Connaught Place'], vehicle: 'Electric Bike', vehicleNo: 'DL-05-EB-8080', + status: 'Suspended', checkInTime: '—', hoursToday: 0, + assigned: 0, capacity: 30, pickupsPending: 0, deliveriesPending: 0, + deliveriesDone: 0, deliveriesFailed: 9, codCollected: 0, codPending: 5600, + rating: 3.1, verified: true, + }, +]; + +// ── Helpers ───────────────────────────────────────────────────────────── +const successRate = (r) => { + const total = r.deliveriesDone + r.deliveriesFailed; + return total === 0 ? 100 : Math.round((r.deliveriesDone / total) * 100); +}; + +const loadPct = (r) => (r.capacity === 0 ? 0 : Math.round((r.assigned / r.capacity) * 100)); +const initials = (name) => name.split(' ').map(w => w[0]).slice(0, 2).join('').toUpperCase(); +const inr = (n) => `₹${n.toLocaleString('en-IN')}`; + +const EMPTY_FORM = { + name: '', phone: '', hub: 'Delhi Operations Hub', zones: [], + vehicle: '', vehicleNo: '', status: 'Idle', verified: false, +}; + +// ════════════════════════════════════════════════════════════════════════════════ +// Presentational Components (Improved spacing & visuals) +// ════════════════════════════════════════════════════════════════════════════════ + +function StatusPill({ status, size = 'md' }) { + const m = STATUS_META[status] || STATUS_META['Offline']; + const small = size === 'sm'; + return ( + + + + {m.label} + + + ); +} + +function CapacityBar({ rider, showLabel = true }) { + const pct = loadPct(rider); + const color = pct > 85 ? '#D93025' : pct > 60 ? '#F29900' : '#1A73E8'; + return ( + + {showLabel && ( + + {rider.assigned}/{rider.capacity} + · {pct}% + + )} + + + ); +} + +function RiderAvatar({ rider, size = 48 }) { + const m = STATUS_META[rider.status] || STATUS_META['Offline']; + return ( + + + {initials(rider.name)} + + + + ); +} + +function VehicleCell({ vehicle, vehicleNo }) { + const Icon = VEHICLES[vehicle]?.icon || LocalShippingOutlinedIcon; + return ( + + + + + + {vehicle} + {vehicleNo} + + + ); +} + +// KPI Card - More spacious +function KpiCard({ icon: Icon, label, value, sub, color, bg, trend }) { + return ( + + + {/* Icon + label sit together on a clean top row */} + + + + + + {label} + + + + + {value} + + + + {trend && } + {sub} + + + + ); +} + +// ════════════════════════════════════════════════════════════════════════════════ +// Dialogs (Cleaner & Better Spaced) +// ════════════════════════════════════════════════════════════════════════════════ + +const STEPS = ['Personal', 'Assignment', 'Vehicle & KYC']; + +function RiderFormDialog({ open, onClose, onSave, initial, mode }) { + const theme = useTheme(); + const fullScreen = useMediaQuery(theme.breakpoints.down('sm')); + const [activeStep, setActiveStep] = useState(0); + const [form, setForm] = useState(initial || EMPTY_FORM); + const [errors, setErrors] = useState({}); + + React.useEffect(() => { + if (open) { + setForm(initial || EMPTY_FORM); + setErrors({}); + setActiveStep(0); + } + }, [open, initial]); + + const set = (k, v) => { + setForm(p => ({ ...p, [k]: v })); + setErrors(e => ({ ...e, [k]: undefined })); + }; + + const validateStep = (step) => { + const e = {}; + if (step === 0) { + if (!form.name.trim()) e.name = 'Full name is required'; + if (!form.phone.trim()) e.phone = 'Phone number is required'; + else if (!/[0-9]{10}/.test(form.phone.replace(/\D/g, ''))) e.phone = 'Enter a valid 10-digit phone number'; + } + if (step === 1) { + if (form.zones.length === 0) e.zones = 'Assign at least one service zone'; + } + if (step === 2) { + if (!form.vehicle) e.vehicle = 'Select a vehicle type'; + if (!form.vehicleNo.trim() && form.vehicle !== 'Cycle') e.vehicleNo = 'Vehicle number is required'; + } + setErrors(e); + return Object.keys(e).length === 0; + }; + + const next = () => { if (validateStep(activeStep)) setActiveStep(s => s + 1); }; + const back = () => setActiveStep(s => s - 1); + + const submit = () => { + if (!validateStep(2)) return; + const cap = VEHICLES[form.vehicle]?.capacity || 30; + onSave({ + ...form, + vehicleNo: form.vehicleNo.trim() || '—', + id: mode === 'add' ? genId() : form.id, + capacity: cap, + checkInTime: mode === 'add' ? '—' : form.checkInTime, + hoursToday: mode === 'add' ? 0 : form.hoursToday, + assigned: mode === 'add' ? 0 : form.assigned, + pickupsPending: mode === 'add' ? 0 : form.pickupsPending, + deliveriesPending: mode === 'add' ? 0 : form.deliveriesPending, + deliveriesDone: mode === 'add' ? 0 : form.deliveriesDone, + deliveriesFailed: mode === 'add' ? 0 : form.deliveriesFailed, + codCollected: mode === 'add' ? 0 : form.codCollected, + codPending: mode === 'add' ? 0 : form.codPending, + rating: mode === 'add' ? 5.0 : form.rating, + }); + }; + + return ( + + {/* Header */} + + + + + + + + + {mode === 'add' ? 'Onboard New Miler' : 'Edit Miler'} + + + {mode === 'add' ? 'Add delivery agent to the fleet' : `Updating ${form.name}`} + + + + + + + + + + {STEPS.map(label => ( + + {label} + + ))} + + + + + + + {/* STEP 0 */} + {activeStep === 0 && ( + + set('name', e.target.value)} error={!!errors.name} helperText={errors.name} + InputProps={{ startAdornment: }} /> + + set('phone', e.target.value)} error={!!errors.phone} helperText={errors.phone} + placeholder="+91 XXXXXXXXXX" InputProps={{ startAdornment: }} /> + + + Home Hub + + + + )} + + {/* STEP 1 */} + {activeStep === 1 && ( + + set('zones', v)} + renderInput={(params) => } + renderTags={(value, getTagProps) => value.map((option, i) => )} + /> + + {mode === 'edit' && ( + + Status + + + )} + + )} + + {/* STEP 2 */} + {activeStep === 2 && ( + + + Vehicle Type + + {errors.vehicle && {errors.vehicle}} + + + set('vehicleNo', e.target.value.toUpperCase())} error={!!errors.vehicleNo} + helperText={errors.vehicleNo || (form.vehicle === 'Cycle' ? 'Optional for cycles' : '')} + placeholder="DL-00-AB-0000" sx={{ '& input': { fontFamily: 'monospace' } }} /> + + + set('verified', e.target.checked)} color="success" />} + label={ + + + + KYC Verified + Driving licence & ID proof validated + + + } + /> + + + )} + + + + + + + {activeStep > 0 && } + {activeStep < STEPS.length - 1 ? ( + + ) : ( + + )} + + + ); +} + +// Profile Drawer - view + inline edit, in the same right-side sheet +function ProfileDrawer({ rider, onClose, onSave, startInEdit = false }) { + const [editing, setEditing] = useState(startInEdit); + const [form, setForm] = useState(rider || {}); + + // Reset the editable copy + mode whenever a different miler is opened. + useEffect(() => { + setForm(rider || {}); + setEditing(startInEdit); + }, [rider, startInEdit]); + + if (!rider) return null; + const sr = successRate(rider); + + const setField = (key) => (e) => setForm((f) => ({ ...f, [key]: e.target.value })); + + const cancelEdit = () => { setForm(rider); setEditing(false); }; + const saveEdit = () => { + const updated = { ...rider, ...form, capacity: VEHICLES[form.vehicle]?.capacity ?? rider.capacity }; + onSave(updated); + setEditing(false); + }; + + return ( + + {/* Header */} + + + {form.name || rider.name} + {rider.id} + + + {rider.verified && ( + } label="Verified" + sx={{ bgcolor: 'rgba(255,255,255,0.18)', color: '#fff', fontWeight: 700 }} /> + )} + + + + + + {/* Content */} + + {editing ? ( + /* ── Inline edit form (same sheet) ── */ + + + EDIT MILER DETAILS + + + + + + Status + + + + Vehicle + + + + + Hub + + + setForm((f) => ({ ...f, zones: v }))} + renderInput={(params) => } + /> + + + ) : ( + + + {/* Today's Performance */} + + + TODAY'S PERFORMANCE + + + {[ + { label: "Picked up", value: rider.deliveriesDone, icon: CheckCircleOutlinedIcon, color: "#16A34A", bg: "#DCFCE7" }, + { label: "Failed", value: rider.deliveriesFailed, icon: WarningAmberOutlinedIcon, color: "#DC2626", bg: "#FEE2E2" }, + { label: "COP", value: inr(rider.codCollected), icon: PaymentsOutlinedIcon, color: "#D97706", bg: "#FEF3C7" }, + ].map((stat, i) => ( + + + + + + {stat.label} + {stat.value} + + + ))} + + + + {/* Live Load Panel */} + + + + LIVE LOAD + + + + + Pending pickups + {rider.pickupsPending} + + + + + {/* Miler Details Panel */} + + + + MILER DETAILS + + + {[ + { icon: PhoneOutlinedIcon, label: "Phone", value: rider.phone }, + { icon: HomeWorkOutlinedIcon, label: "Hub", value: rider.hub }, + { icon: PlaceOutlinedIcon, label: "Zones", value: rider.zones?.join(', ') || 'N/A' }, + { icon: BadgeOutlinedIcon, label: "Vehicle", value: `${rider.vehicle} • ${rider.vehicleNo}` }, + { icon: AccessTimeOutlinedIcon, label: "Check-in", value: `${rider.checkInTime} (${rider.hoursToday}h)` }, + ].map((detail, idx) => ( + + + + + {detail.label} + {detail.value} + + + + ))} + + + + + + )} + + + {/* Footer */} + + {editing ? ( + <> + + + + ) : ( + <> + + + + )} + + + ); +} + +// Delete Dialog +function DeleteDialog({ rider, onClose, onConfirm }) { + return ( + + + + + + Remove Miler? + + {rider?.name} will be permanently removed from the roster. + + + + + + + + ); +} + +// Miler Card (Grid) +function RiderCard({ rider, onView, onMenu }) { + const pct = loadPct(rider); + const pctColor = + pct > 85 ? "#D93025" : pct > 60 ? "#F29900" : "#1A73E8"; + + return ( + onView(rider)} + sx={{ + height: "100%", + borderRadius: 2, + border: "1px solid #E8EAED", + cursor: "pointer", + transition: "all .25s ease", + bgcolor: "#fff", + "&:hover": { + transform: "translateY(-4px)", + borderColor: "#C01227", + boxShadow: "0 16px 40px rgba(0,0,0,.08)", + }, + }} + > + + {/* Header */} + + + + + + + {rider.name} + + + {rider.verified && ( + + )} + + + + {rider.id} + + + + { + e.stopPropagation(); + onMenu(e, rider); + }} + > + + + + + {/* Status */} + + + + + + + {/* Load */} + + + + Today's Load + + + + {rider.assigned}/{rider.capacity} + + + {pct}% + + + + + + + + {/* Zones */} + + + SERVICE ZONES + + + + {rider.zones.slice(0, 3).map((z) => ( + + ))} + + {rider.zones.length > 3 && ( + + )} + + + + + ); +} + +// ════════════════════════════════════════════════════════════════════════════════ +// MAIN COMPONENT +// ════════════════════════════════════════════════════════════════════════════════ +export default function Riders() { + const theme = useTheme(); + const isMdDown = useMediaQuery(theme.breakpoints.down('md')); + const isLgDown = useMediaQuery(theme.breakpoints.down('lg')); + + const [riders, setRiders] = useState(SEED); + const [search, setSearch] = useState(''); + const [statusFilter, setStatusFilter] = useState('All'); + const [vehicleFilter, setVehicleFilter] = useState('All'); + const [view, setView] = useState('table'); + + const [formDialog, setFormDialog] = useState({ open: false, mode: 'add', initial: null }); + const [profile, setProfile] = useState(null); + const [profileEdit, setProfileEdit] = useState(false); + const [deleteTarget, setDeleteTarget] = useState(null); + const [menuAnchor, setMenuAnchor] = useState(null); + const [menuRider, setMenuRider] = useState(null); + const [snack, setSnack] = useState({ open: false, msg: '', severity: 'success' }); + + const toast = (msg, severity = 'success') => setSnack({ open: true, msg, severity }); + + const effectiveView = isLgDown ? 'grid' : view; + + const kpi = useMemo(() => { + const onDuty = riders.filter(r => !['Offline', 'Suspended'].includes(r.status)).length; + const onField = riders.filter(r => ['On Pickup', 'Returning to Hub'].includes(r.status)).length; + const idle = riders.filter(r => r.status === 'Idle').length; + const slaRisk = riders.filter(r => loadPct(r) > 85 || r.deliveriesFailed >= 5).length; + const codToCollect = riders.reduce((s, r) => s + r.codPending, 0); + return { onDuty, onField, idle, slaRisk, codToCollect, total: riders.length }; + }, [riders]); + + const filtered = useMemo(() => { + const q = search.trim().toLowerCase(); + return riders.filter(r => { + const matchSearch = !q || + r.name.toLowerCase().includes(q) || + r.id.toLowerCase().includes(q) || + r.phone.includes(q) || + r.zones.some(z => z.toLowerCase().includes(q)); + const matchStatus = statusFilter === 'All' || r.status === statusFilter; + const matchVehicle = vehicleFilter === 'All' || r.vehicle === vehicleFilter; + return matchSearch && matchStatus && matchVehicle; + }); + }, [riders, search, statusFilter, vehicleFilter]); + + const handleSave = (rider) => { + if (formDialog.mode === 'add') { + setRiders(p => [rider, ...p]); + toast(`${rider.name} onboarded successfully`); + } else { + setRiders(p => p.map(r => r.id === rider.id ? rider : r)); + toast(`${rider.name} updated`); + } + setFormDialog({ open: false, mode: 'add', initial: null }); + }; + + const handleDelete = () => { + setRiders(p => p.filter(r => r.id !== deleteTarget.id)); + toast(`${deleteTarget.name} removed`, 'info'); + setDeleteTarget(null); + setProfile(null); + }; + + const openAdd = () => setFormDialog({ open: true, mode: 'add', initial: null }); + // Edit now opens the same right-side sheet in edit mode (no separate modal). + const openEdit = (r) => { + setMenuAnchor(null); + setProfile(r); + setProfileEdit(true); + }; + const openView = (r) => { + setMenuAnchor(null); + setProfile(r); + setProfileEdit(false); + }; + const saveProfileEdit = (updated) => { + setRiders(p => p.map(r => (r.id === updated.id ? updated : r))); + setProfile(updated); + setProfileEdit(false); + toast(`${updated.name} updated`); + }; + const openMenu = (e, r) => { + setMenuAnchor(e.currentTarget); + setMenuRider(r); + }; + + const STATUS_CHIPS = ['All', 'On Pickup', 'Idle', 'On Break', 'Offline', 'Suspended']; + + return ( + + {/* Header */} + {/* ── Improved Header with better gaps ── */} + + {/* Title & Avatar Branding Group */} + + + + + + + + Milers + + + + {kpi.total} milers • who's working and where + + + + + {/* Actions Group - pushed to the far right with clear spacing between buttons */} + + + + + + + + {/* KPIs */} + + {[ + { icon: GroupsOutlinedIcon, label: 'On Duty', value: kpi.onDuty, sub: `of ${kpi.total}`, color: '#1A73E8', bg: '#E8F0FE', trend: true }, + { icon: RouteOutlinedIcon, label: 'In Field', value: kpi.onField, sub: 'Active pickups', color: '#1E8E3E', bg: '#E6F4EA' }, + { icon: AccessTimeOutlinedIcon, label: 'Available', value: kpi.idle, sub: 'Ready for assignment', color: '#B06000', bg: '#FEF7E0' }, + { icon: WarningAmberOutlinedIcon, label: 'SLA Risk', value: kpi.slaRisk, sub: 'Overloaded milers', color: '#D93025', bg: '#FCE8E6' }, + { icon: PaymentsOutlinedIcon, label: 'COP Pending', value: inr(kpi.codToCollect), sub: 'To be collected', color: '#8E24AA', bg: '#F3E5F5' }, + ].map((k, i) => ( + + + + ))} + + + {/* Main Card */} + + {/* Toolbar */} + + + setSearch(e.target.value)} + InputProps={{ + startAdornment: ( + + + + ), + sx: { borderRadius: 2 }, + }} + sx={{ + maxWidth: { lg: 420 }, + }} + /> + + + + + + + + {!isLgDown && ( + v && setView(v)} + sx={{ borderRadius: 2 }} + > + + + + + + + + )} + + + {/* Status Chips */} + + {STATUS_CHIPS.map(s => { + const active = statusFilter === s; + const meta = STATUS_META[s] || {}; + return ( + setStatusFilter(s)} + icon={meta.color ? : undefined} + sx={{ + height: 38, + px: 1, + borderRadius: 2, + fontSize: '0.82rem', + fontWeight: active ? 700 : 500, + bgcolor: active ? '#1A1A2E' : '#F8F9FB', + color: active ? '#fff' : '#5F6368', + border: active ? 'none' : '1px solid #ECEEF1', + '& .MuiChip-label': { px: 1.25 }, + '&:hover': { bgcolor: active ? '#1A1A2E' : '#F1F3F5' } + }} + /> + ); + })} + + + + {/* Content Area */} + {filtered.length === 0 ? ( + + + No milers match your filters + + + ) : effectiveView === 'table' ? ( + + + + + Miler + Status + Zones + Vehicle + Load + Today + + + + + {filtered.map(rider => ( + openView(rider)}> + + + + + + + + {rider.name} + {rider.id} + + + + + + + {rider.zones.map(z => )} + + + + + + + + Done + {rider.deliveriesDone} + + + COP + {inr(rider.codCollected)} + + + + + + { e.stopPropagation(); openView(rider); }}> + { e.stopPropagation(); openEdit(rider); }}> + { e.stopPropagation(); openMenu(e, rider); }}> + + + + ))} + +
+
+ ) : ( + + + {filtered.map(r => ( + + + + ))} + + + )} + + {filtered.length > 0 && ( + + + Showing {filtered.length} of {riders.length} milers + + + )} +
+ + {/* Context Menu */} + setMenuAnchor(null)} PaperProps={{ sx: { borderRadius: 2 } }}> + openView(menuRider)}>View Profile + openEdit(menuRider)}>Edit + Call + + { setDeleteTarget(menuRider); setMenuAnchor(null); }} sx={{ color: '#D93025' }}> + Remove Miler + + + + {/* Dialogs */} + setFormDialog({ open: false, mode: 'add', initial: null })} onSave={handleSave} /> + { setProfile(null); setProfileEdit(false); }} + onSave={saveProfileEdit} + /> + setDeleteTarget(null)} onConfirm={handleDelete} /> + + {/* Toast */} + setSnack(s => ({ ...s, open: false }))}> + {snack.msg} + +
+ ); +} \ No newline at end of file diff --git a/src/pages/operations/Routing.jsx b/src/pages/operations/Routing.jsx new file mode 100644 index 0000000..a2a1e81 --- /dev/null +++ b/src/pages/operations/Routing.jsx @@ -0,0 +1,342 @@ +import { useState, useEffect } from 'react'; +import { useSearchParams } from 'react-router-dom'; +import { + Box, Typography, Card, CardContent, CardHeader, Grid, TextField, Button, + Stack, Divider, Alert, AlertTitle, Avatar, List, ListItemButton, ListItemText, Chip +} from '@mui/material'; +import QrCodeScannerIcon from '@mui/icons-material/QrCodeScanner'; +import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; +import HelpIcon from '@mui/icons-material/Help'; +import WarningAmberIcon from '@mui/icons-material/WarningAmber'; +import LocalShippingIcon from '@mui/icons-material/LocalShipping'; +import HubIcon from '@mui/icons-material/Hub'; +import LocalOfferIcon from '@mui/icons-material/LocalOffer'; + +// Mock DB with Advanced Logistics Scenarios +const HUB_NAME = 'Delhi Hub (DEL-01)'; +const LOCAL_ZONES = ['Dwarka', 'Janakpuri', 'Saket', 'Malviya Nagar', 'Rohini', 'Vasant Kunj', 'Central Delhi']; + +const PACKAGES_DB = { + 'DM-1001': { + id: 'DM-1001', + source: 'Local Pickup', + origin: 'Customer - Dwarka', + destHub: 'Delhi Hub (DEL-01)', + destZone: 'Janakpuri', + weight: '1.2 kg', + status: 'Arrived at Hub' + }, + 'DM-1002': { + id: 'DM-1002', + source: 'Local Pickup', + origin: 'Merchant - Saket', + destHub: 'Mumbai Hub (BOM-02)', + destZone: 'Andheri West', + weight: '3.5 kg', + status: 'Arrived at Hub' + }, + 'DM-1003': { + id: 'DM-1003', + source: 'Arrived from another city', + origin: 'Bengaluru Hub (BLR-02)', + destHub: 'Delhi Hub (DEL-01)', + destZone: 'Rohini', + weight: '0.5 kg', + status: 'Arrived at Hub' + }, + 'DM-1004': { + id: 'DM-1004', + source: 'Local Pickup', + origin: 'Customer - Vasant Kunj', + destHub: 'Delhi Hub (DEL-01)', + destZone: 'Central Delhi', + weight: '2.0 kg', + status: 'Arrived at Hub' + }, + 'DM-1005': { + id: 'DM-1005', + source: 'Arrived from another city', + origin: 'Chennai Hub (MAA-05)', + destHub: 'Delhi Hub (DEL-01)', + destZone: 'Dwarka', + weight: '15.0 kg', + status: 'Damaged Packaging', + exception: 'Box crushed during transit.' + }, + 'DM-1006': { + id: 'DM-1006', + source: 'Arrived from another city', + origin: 'Pune Hub (PNQ-03)', + destHub: 'Pune Hub (PNQ-03)', + destZone: 'Koregaon Park', + weight: '1.0 kg', + status: 'RTS (Return to Sender)', + exception: 'Customer rejected delivery at destination.' + } +}; + +export default function Routing() { + const [searchParams] = useSearchParams(); + const [searchId, setSearchId] = useState(''); + const [matchedPkg, setMatchedPkg] = useState(null); + const [searched, setSearched] = useState(false); + + useEffect(() => { + const query = searchParams.get('q'); + if (query) { + setSearchId(query); + handleSearch(query); + } + }, [searchParams]); + + const handleSearch = (idToSearch) => { + const id = typeof idToSearch === 'string' ? idToSearch : searchId; + setSearched(true); + if (id && PACKAGES_DB[id]) { + setMatchedPkg(PACKAGES_DB[id]); + } else { + setMatchedPkg(null); + } + }; + + // Advanced Sorting Logic: Classify by Next Action + const determineNextAction = (pkg) => { + if (pkg.status.includes('Exception') || pkg.status === 'Damaged Packaging') { + return { + queue: 'Needs Checking', + action: 'Set aside for a supervisor', + color: '#D93025', bg: '#FCE8E6', icon: + }; + } + if (pkg.status === 'RTS (Return to Sender)') { + return { + queue: 'Send Back', + action: 'Return to the sender', + color: '#F29900', bg: '#FEF7E0', icon: + }; + } + if (pkg.destHub !== HUB_NAME) { + return { + queue: 'Transfer to Another City', + action: `Send to ${pkg.destHub}`, + color: '#8E24AA', bg: '#F3E5F5', icon: + }; + } + // If destHub IS this hub, it's local delivery + if (LOCAL_ZONES.includes(pkg.destZone)) { + // If it was picked up locally but is going to a different area, it's a cross-area delivery. + if (pkg.source === 'Local Pickup' && !pkg.origin.includes(pkg.destZone)) { + return { + queue: 'Local Delivery (Other Area)', + action: `Send to ${pkg.destZone}`, + color: '#1A73E8', bg: '#E8F0FE', icon: + }; + } + return { + queue: 'Local Delivery', + action: `Give to a ${pkg.destZone} miler`, + color: '#1E8E3E', bg: '#E6F4EA', icon: + }; + } + return { queue: 'Unknown', action: 'Check the address', color: '#5F6368', bg: '#F1F3F4', icon: }; + }; + + return ( + + + Where Does It Go? + + Scan a parcel and we'll tell you exactly what to do with it next — deliver locally, transfer to another city, or set it aside. + + + + + {/* Search Panel */} + + + + Scan a Parcel} + avatar={} + /> + + + + setSearchId(e.target.value)} + onKeyDown={(e) => e.key === 'Enter' && handleSearch()} + InputProps={{ + sx: { borderRadius: 2, bgcolor: '#fff' } + }} + /> + + + + + + + Parcels Waiting} + subheader={Tap a parcel to check it} + avatar={} + /> + + + + {Object.keys(PACKAGES_DB).map((key) => { + const pkg = PACKAGES_DB[key]; + return ( + { + setSearchId(key); + handleSearch(key); + }} + selected={searchId === key} + sx={{ + borderRadius: 2, mb: 1, p: 2, + border: '1px solid', + borderColor: searchId === key ? '#C01227' : '#eaeaea', + bgcolor: searchId === key ? '#C0122708' : '#fff', + '&:hover': { bgcolor: '#f8f9fa' } + }} + > + + + ); + })} + + + + + + + {/* Visual Route Guideline Panel */} + + {!searched ? ( + + + + + + + Scan a parcel to begin + We'll show you where it needs to go. + + + + ) : matchedPkg ? ( + + {matchedPkg.id}} + subheader={Source: {matchedPkg.source}} + action={ + + } + sx={{ px: { xs: 2.5, sm: 4 }, pt: { xs: 3, sm: 4 }, pb: 2 }} + /> + + + + {/* Action Banner */} + + + {determineNextAction(matchedPkg).icon} + + + + {determineNextAction(matchedPkg).queue} + + + {determineNextAction(matchedPkg).action} + + + + + {/* Parcel Journey */} + + + The Parcel's Journey + + + + Came From + {matchedPkg.origin} + + + + Right Now (Here) + {HUB_NAME} + + + + Going To + {matchedPkg.destHub === HUB_NAME ? matchedPkg.destZone : matchedPkg.destHub} + + + + + {/* Handling Alerts */} + {matchedPkg.exception && ( + + Something's Wrong + {matchedPkg.exception} + + )} + + {determineNextAction(matchedPkg).queue === 'Transfer to Another City' && ( + + Put in the transfer bin + Place this parcel in the bin for {matchedPkg.destHub}. It will go out with the next city transfer. + + )} + + {determineNextAction(matchedPkg).queue === 'Local Delivery' && ( + + Ready for local delivery + Place this parcel in the {matchedPkg.destZone} lane so a miler can take it out. + + )} + + + + ) : ( + + + + Package Not Found + The package code {searchId} is not registered in the system. + + + + )} + + + + ); +} diff --git a/src/pages/operations/TrackingMap.jsx b/src/pages/operations/TrackingMap.jsx new file mode 100644 index 0000000..14e3d35 --- /dev/null +++ b/src/pages/operations/TrackingMap.jsx @@ -0,0 +1,256 @@ +import React, { useState, useEffect } from 'react'; +import { + Box, Typography, Card, CardHeader, Avatar, Stack, Chip, List, ListItem, + ListItemAvatar, ListItemText, Badge, Divider +} from '@mui/material'; +import DeliveryDiningIcon from '@mui/icons-material/DeliveryDining'; +import HubIcon from '@mui/icons-material/Hub'; +import LocalShippingIcon from '@mui/icons-material/LocalShipping'; +import { MapContainer, TileLayer, Marker, Popup, Polyline, useMap } from 'react-leaflet'; +import L from 'leaflet'; +import 'leaflet/dist/leaflet.css'; + +// Keeps Leaflet's canvas sized correctly when the container resizes (sidebar +// toggle, window resize, first paint inside a flex box). Without this the map +// renders grey/blank tiles — the #1 reason a real map "doesn't show". +function MapResizeHandler() { + const map = useMap(); + useEffect(() => { + const fix = () => map.invalidateSize(); + const t = setTimeout(fix, 250); + window.addEventListener('resize', fix); + const ro = new ResizeObserver(fix); + ro.observe(map.getContainer()); + return () => { clearTimeout(t); window.removeEventListener('resize', fix); ro.disconnect(); }; + }, [map]); + return null; +} + +// Fix leaflet default marker icons issue +delete L.Icon.Default.prototype._getIconUrl; +L.Icon.Default.mergeOptions({ + iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon-2x.png', + iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png', + shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png', +}); + +// Custom HTML Icons for Leaflet +const createHubIcon = () => new L.DivIcon({ + className: 'custom-leaflet-icon', + html: `
`, + iconSize: [36, 36], + iconAnchor: [18, 18], +}); + +const createRiderIcon = () => new L.DivIcon({ + className: 'custom-leaflet-icon', + html: `
`, + iconSize: [30, 30], + iconAnchor: [15, 15], +}); + +const createLinehaulIcon = () => new L.DivIcon({ + className: 'custom-leaflet-icon', + html: `
`, + iconSize: [34, 34], + iconAnchor: [17, 17], +}); + +// Mock Coordinates (Real Lat/Lng) +const HUBS = [ + { id: 'HB-DEL', name: 'Delhi Hub (DEL-01)', position: [28.6139, 77.2090], type: 'Main Hub' }, + { id: 'HB-BOM', name: 'Mumbai Hub (BOM-02)', position: [19.0760, 72.8777], type: 'City Hub' }, + { id: 'HB-BLR', name: 'Bengaluru Hub (BLR-03)', position: [12.9716, 77.5946], type: 'City Hub' } +]; + +const INIT_RIDERS = [ + { id: 'R-102', name: 'Deepak Sharma', area: 'Dwarka, Delhi', status: 'Out for delivery', progress: 0.0, start: [28.5921, 77.0460], end: [28.6139, 77.2090], type: 'Miler' }, + { id: 'R-105', name: 'Karthik S.', area: 'Saket, Delhi', status: 'Picking up', progress: 0.3, start: [28.5245, 77.2066], end: [28.6139, 77.2090], type: 'Miler' } +]; + +const INIT_LINEHAUL = [ + { id: 'LH-DEL-BOM', name: 'Transfer: Delhi → Mumbai', status: 'On the way', progress: 0.1, start: [28.6139, 77.2090], end: [19.0760, 72.8777], type: 'Truck' } +]; + +export default function TrackingMap() { + const [riders, setRiders] = useState(INIT_RIDERS); + const [linehauls, setLinehauls] = useState(INIT_LINEHAUL); + + // Smooth operational tracking loop iteration updates + useEffect(() => { + const interval = setInterval(() => { + setRiders((prev) => + prev.map(r => ({ + ...r, + progress: r.progress >= 1 ? 0 : parseFloat((r.progress + 0.005).toFixed(3)) + })) + ); + + setLinehauls((prev) => + prev.map(l => ({ + ...l, + progress: l.progress >= 1 ? 0 : parseFloat((l.progress + 0.001).toFixed(3)) + })) + ); + }, 150); + return () => clearInterval(interval); + }, []); + + const getInterpolatedPosition = (start, end, progress) => { + return [ + start[0] + (end[0] - start[0]) * progress, + start[1] + (end[1] - start[1]) * progress + ]; + }; + + const mapCenter = [22.0, 76.0]; // Centered across the Delhi → Mumbai / Bengaluru network + + return ( + + + Live Map + See where your milers and transfer trucks are right now, on the map. + + + + {/* Map Canvas Frame */} + + + + + + + {/* Plot Hubs */} + {HUBS.map(hub => ( + + + {hub.name} + {hub.type} + + + ))} + + {/* Plot Milers */} + {riders.map(rider => { + const pos = getInterpolatedPosition(rider.start, rider.end, rider.progress); + return ( + + + + + {rider.name} + {rider.area} + + + + ); + })} + + {/* Plot Linehaul */} + {linehauls.map(lh => { + const pos = getInterpolatedPosition(lh.start, lh.end, lh.progress); + return ( + + + + + {lh.name} + Progress: {Math.round(lh.progress * 100)}% + + + + ); + })} + + + + + {/* Sidebar Status Trackers */} + + + + {/* Active Network Hub Nodes Summary */} + + Active Hub Nodes} + avatar={} + /> + + + {HUBS.map(hub => ( + + + + + ))} + + + + {/* Real-time Last Mile Miler Logs */} + + Milers Out Now (Delhi)} + avatar={} + /> + + + {riders.map(r => ( + + + + {r.name.charAt(0)} + + + + + {Math.round(r.progress * 100)}% + + + ))} + + + + {/* Linehaul Fleet Shipments Tracker */} + + City Transfers} + avatar={} + /> + + + {linehauls.map(lh => ( + + + + {Math.round(lh.progress * 100)}% route + + + ))} + + + + + + + + ); +} + diff --git a/src/theme/componentsOverride.js b/src/theme/componentsOverride.js new file mode 100644 index 0000000..2d625bf --- /dev/null +++ b/src/theme/componentsOverride.js @@ -0,0 +1,191 @@ +import customShadows from './shadows'; + +// ==============================|| DOORMILE THEME - COMPONENT OVERRIDES ||============================== // +// Clean, corporate Material Design tuning for the whole console. + +export default function componentsOverride(theme) { + const { palette } = theme; + + return { + MuiCssBaseline: { + styleOverrides: { + html: { WebkitFontSmoothing: 'antialiased', MozOsxFontSmoothing: 'grayscale', textRendering: 'optimizeLegibility' }, + body: { backgroundColor: palette.background.default }, + '*::-webkit-scrollbar': { width: 8, height: 8 }, + '*::-webkit-scrollbar-thumb': { background: palette.grey[300], borderRadius: 8 }, + '*::-webkit-scrollbar-thumb:hover': { background: palette.grey[400] } + } + }, + MuiButton: { + defaultProps: { disableElevation: true, disableRipple: false }, + styleOverrides: { + root: { + borderRadius: 8, + fontWeight: 600, + padding: '8px 18px', + transition: 'background-color .2s ease, box-shadow .2s ease, transform .12s ease, border-color .2s ease', + '&:active': { transform: 'translateY(0.5px)' }, + '&.Mui-focusVisible': { boxShadow: `0 0 0 3px ${palette.primary.lighter}` } + }, + containedPrimary: { + boxShadow: customShadows.primaryGlow, + '&:hover': { boxShadow: customShadows.primaryGlowHover, backgroundColor: palette.primary.dark } + }, + outlined: { + borderColor: palette.grey[300], + '&:hover': { borderColor: palette.grey[400], backgroundColor: palette.grey[50] } + }, + text: { '&:hover': { backgroundColor: palette.grey[100] } }, + sizeLarge: { padding: '11px 24px', fontSize: '0.9375rem' }, + sizeSmall: { padding: '5px 14px' }, + // Give every button clear breathing room between its icon and label + startIcon: { marginRight: 10 }, + endIcon: { marginLeft: 10 } + } + }, + MuiIconButton: { + styleOverrides: { root: { borderRadius: 8 } } + }, + MuiCard: { + styleOverrides: { + root: { + borderRadius: 14, + border: `1px solid ${palette.grey[200]}`, + boxShadow: customShadows.card, + backgroundImage: 'none', + transition: 'box-shadow .22s ease, border-color .22s ease, transform .22s ease' + } + } + }, + MuiCardHeader: { + defaultProps: { titleTypographyProps: { variant: 'h5' }, subheaderTypographyProps: { variant: 'caption' } }, + styleOverrides: { root: { padding: 20 } } + }, + MuiCardContent: { + styleOverrides: { root: { padding: 20, '&:last-child': { paddingBottom: 20 } } } + }, + MuiPaper: { + defaultProps: { elevation: 0 }, + styleOverrides: { rounded: { borderRadius: 14 } } + }, + MuiToggleButtonGroup: { + styleOverrides: { + root: { backgroundColor: palette.grey[100], borderRadius: 10, padding: 4, gap: 4 }, + grouped: { + border: 0, + borderRadius: '8px !important', + margin: 0 + } + } + }, + MuiToggleButton: { + styleOverrides: { + root: { + border: 0, + borderRadius: 8, + padding: '6px 12px', + color: palette.grey[600], + transition: 'all .18s ease', + '&:hover': { backgroundColor: palette.grey[200] }, + '&.Mui-selected': { + backgroundColor: palette.background.paper, + color: palette.primary.main, + boxShadow: customShadows.card, + '&:hover': { backgroundColor: palette.background.paper } + } + } + } + }, + MuiChip: { + styleOverrides: { + root: { borderRadius: 6, fontWeight: 600, fontSize: '0.75rem' }, + sizeSmall: { height: 22 }, + label: { paddingLeft: 8, paddingRight: 8 } + } + }, + MuiTableCell: { + styleOverrides: { + root: { borderColor: palette.grey[200], padding: '12px 16px', fontSize: '0.8125rem' }, + head: { + fontWeight: 600, + color: palette.grey[600], + backgroundColor: palette.grey[50], + textTransform: 'none', + whiteSpace: 'nowrap' + } + } + }, + MuiTableRow: { + styleOverrides: { + root: { transition: 'background-color .15s ease', '&:hover': { backgroundColor: palette.grey[50] } } + } + }, + MuiOutlinedInput: { + styleOverrides: { + root: { + borderRadius: 8, + backgroundColor: palette.background.paper, + transition: 'box-shadow .2s ease, border-color .2s ease', + '& .MuiOutlinedInput-notchedOutline': { borderColor: palette.grey[300], transition: 'border-color .2s ease' }, + '&:hover .MuiOutlinedInput-notchedOutline': { borderColor: palette.grey[400] }, + '&.Mui-focused': { boxShadow: `0 0 0 3px ${palette.primary.lighter}` }, + '&.Mui-focused .MuiOutlinedInput-notchedOutline': { borderColor: palette.primary.main, borderWidth: 1 } + }, + input: { padding: '11px 14px' } + } + }, + MuiSelect: { + styleOverrides: { + select: { + paddingTop: '11px', + paddingBottom: '11px', + paddingLeft: '14px', + display: 'flex', + alignItems: 'center' + } + } + }, + MuiInputLabel: { + styleOverrides: { root: { color: palette.grey[600], fontSize: '0.875rem' } } + }, + MuiTab: { + styleOverrides: { + root: { textTransform: 'none', fontWeight: 600, minHeight: 46, fontSize: '0.875rem' } + } + }, + MuiTabs: { + styleOverrides: { indicator: { height: 3, borderRadius: 3 } } + }, + MuiTooltip: { + styleOverrides: { + tooltip: { backgroundColor: palette.grey[800], borderRadius: 6, fontSize: '0.75rem', padding: '6px 10px' } + } + }, + MuiDialog: { + styleOverrides: { paper: { borderRadius: 16 } } + }, + MuiAvatar: { + styleOverrides: { root: { fontWeight: 600, fontSize: '0.875rem' } } + }, + MuiListItemButton: { + styleOverrides: { root: { borderRadius: 8 } } + }, + MuiLinearProgress: { + styleOverrides: { root: { borderRadius: 8, height: 6, backgroundColor: palette.grey[200] } } + }, + MuiMenu: { + styleOverrides: { paper: { borderRadius: 12, boxShadow: customShadows.dropdown, marginTop: 6, border: `1px solid ${palette.grey[200]}` } } + }, + MuiMenuItem: { + styleOverrides: { + root: { + borderRadius: 8, + margin: '2px 6px', + padding: '8px 10px', + fontSize: '0.875rem', + '&:hover': { backgroundColor: palette.grey[100] } + } + } + } + }; +} diff --git a/src/theme/index.js b/src/theme/index.js new file mode 100644 index 0000000..53e9cb8 --- /dev/null +++ b/src/theme/index.js @@ -0,0 +1,20 @@ +import { createTheme } from '@mui/material/styles'; + +import palette from './palette'; +import typography from './typography'; +import customShadows from './shadows'; +import componentsOverride from './componentsOverride'; + +// ==============================|| DOORMILE THEME - ENTRY ||============================== // + +let theme = createTheme({ + palette, + typography, + shape: { borderRadius: 6 }, + customShadows, + mixins: { toolbar: { minHeight: 64 } } +}); + +theme.components = componentsOverride(theme); + +export default theme; diff --git a/src/theme/palette.js b/src/theme/palette.js new file mode 100644 index 0000000..c43e390 --- /dev/null +++ b/src/theme/palette.js @@ -0,0 +1,102 @@ +// ==============================|| DOORMILE THEME - PALETTE ||============================== // +// Corporate red brand palette. Brand red #C01227. + +export const grey = { + 0: '#FFFFFF', + 50: '#F8F9FA', + 100: '#F1F3F5', + 200: '#E9ECEF', + 300: '#DEE2E6', + 400: '#CED4DA', + 500: '#ADB5BD', + 600: '#868E96', + 700: '#495057', + 800: '#343A40', // Slate + 900: '#212529', // Graphite + A50: '#F8F9FA', + A100: '#E9ECEF' +}; + +const palette = { + mode: 'light', + common: { black: '#000000', white: '#FFFFFF' }, + primary: { + lighter: '#F8E0E3', + 100: '#EFBBC1', + 200: '#E08A92', + light: '#D6515C', + 400: '#CC2E3C', + main: '#C01227', + dark: '#9E0E20', + 700: '#870C1B', + darker: '#7E0B17', + 900: '#520710', + contrastText: '#FFFFFF' + }, + secondary: { + lighter: grey[100], + 100: grey[100], + 200: grey[200], + light: grey[300], + 400: grey[400], + main: grey[500], + 600: grey[600], + dark: grey[700], + 800: grey[800], + darker: grey[900], + A100: grey[0], + A200: grey[400], + A300: grey[700], + contrastText: grey[0] + }, + error: { + lighter: '#FEEAE9', + light: '#F88078', + main: '#F04134', + dark: '#A82216', + darker: '#7A150C', + contrastText: '#FFFFFF' + }, + warning: { + lighter: '#FFF7E0', + light: '#FFD666', + main: '#FFBF00', + dark: '#B38600', + darker: '#805F00', + contrastText: '#262626' + }, + info: { + lighter: '#E0F7F8', + light: '#66CBD2', + main: '#00A2AE', + dark: '#00727B', + darker: '#005159', + contrastText: '#FFFFFF' + }, + success: { + lighter: '#E3F6EC', + light: '#5CC98C', + main: '#00A854', + dark: '#00773B', + darker: '#00552A', + contrastText: '#FFFFFF' + }, + grey, + text: { + primary: grey[800], + secondary: grey[600], + disabled: grey[400] + }, + action: { + disabled: grey[300], + hover: 'rgba(192, 18, 39, 0.04)', + selected: 'rgba(192, 18, 39, 0.08)' + }, + divider: grey[200], + background: { + paper: '#FFFFFF', + default: grey.A50 + } +}; + +export default palette; diff --git a/src/theme/shadows.js b/src/theme/shadows.js new file mode 100644 index 0000000..bb08a1d --- /dev/null +++ b/src/theme/shadows.js @@ -0,0 +1,15 @@ +// ==============================|| DOORMILE THEME - CUSTOM SHADOWS ||============================== // +// Layered elevation (a tight contact shadow + a soft ambient shadow) reads far more +// premium than a single blurry drop shadow. Brand glow on CTAs is kept restrained. + +const customShadows = { + card: '0 1px 2px rgba(16, 24, 40, 0.04), 0 1px 3px rgba(16, 24, 40, 0.06)', + cardHover: '0 10px 28px -6px rgba(16, 24, 40, 0.12), 0 2px 6px rgba(16, 24, 40, 0.05)', + widget: '0 1px 3px rgba(16, 24, 40, 0.06)', + dropdown: '0 12px 32px -8px rgba(16, 24, 40, 0.18), 0 4px 10px rgba(16, 24, 40, 0.06)', + primaryGlow: '0 4px 12px -2px rgba(192, 18, 39, 0.22)', + primaryGlowHover: '0 6px 16px -2px rgba(192, 18, 39, 0.30)', + header: '0 1px 0 rgba(16, 24, 40, 0.06)' +}; + +export default customShadows; diff --git a/src/theme/typography.js b/src/theme/typography.js new file mode 100644 index 0000000..a958335 --- /dev/null +++ b/src/theme/typography.js @@ -0,0 +1,28 @@ +// ==============================|| DOORMILE THEME - TYPOGRAPHY ||============================== // +// A deliberate type scale with optical tracking: large display text gets tighter +// negative letter-spacing, small UI text stays legible. Optical tracking like this +// is what separates a designed interface from a default Material build. + +const typography = { + fontFamily: '"Public Sans", "Inter", "Helvetica", "Arial", sans-serif', + htmlFontSize: 16, + fontWeightLight: 300, + fontWeightRegular: 400, + fontWeightMedium: 500, + fontWeightBold: 700, + h1: { fontWeight: 800, fontSize: '2.375rem', lineHeight: 1.15, letterSpacing: '-0.022em' }, + h2: { fontWeight: 800, fontSize: '1.875rem', lineHeight: 1.2, letterSpacing: '-0.02em' }, + h3: { fontWeight: 700, fontSize: '1.5rem', lineHeight: 1.28, letterSpacing: '-0.018em' }, + h4: { fontWeight: 700, fontSize: '1.25rem', lineHeight: 1.35, letterSpacing: '-0.014em' }, + h5: { fontWeight: 700, fontSize: '1rem', lineHeight: 1.5, letterSpacing: '-0.01em' }, + h6: { fontWeight: 600, fontSize: '0.875rem', lineHeight: 1.57, letterSpacing: '-0.006em' }, + caption: { fontWeight: 400, fontSize: '0.75rem', lineHeight: 1.66 }, + body1: { fontSize: '0.875rem', lineHeight: 1.6, letterSpacing: '-0.003em' }, + body2: { fontSize: '0.75rem', lineHeight: 1.66 }, + subtitle1: { fontSize: '0.875rem', fontWeight: 600, lineHeight: 1.57, letterSpacing: '-0.006em' }, + subtitle2: { fontSize: '0.75rem', fontWeight: 600, lineHeight: 1.66 }, + overline: { fontSize: '0.6875rem', fontWeight: 700, letterSpacing: '0.08em', textTransform: 'uppercase' }, + button: { textTransform: 'none', fontWeight: 600, letterSpacing: '-0.006em' } +}; + +export default typography; diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..23252ab --- /dev/null +++ b/vite.config.js @@ -0,0 +1,23 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import { fileURLToPath, URL } from 'node:url'; + +export default defineConfig({ + plugins: [react()], + css: { + // Inline postcss config avoids dynamic package resolution issues + postcss: { plugins: [] } + }, + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + }, + server: { + port: 3001, + strictPort: true, + host: true, + open: true + } +}); +