diff --git a/components.json b/components.json new file mode 100644 index 0000000..edcaef2 --- /dev/null +++ b/components.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "iconLibrary": "lucide", + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "registries": {} +} diff --git a/debug.log b/debug.log new file mode 100644 index 0000000..2cbc2a3 --- /dev/null +++ b/debug.log @@ -0,0 +1 @@ +[0212/070717.490:ERROR:third_party\crashpad\crashpad\util\win\registration_protocol_win.cc:108] CreateFile: The system cannot find the file specified. (0x2) diff --git a/next.config.ts b/next.config.ts index e9ffa30..3c6d3aa 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,6 +1,16 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { + images: { + remotePatterns: [ + { + protocol: 'http', + hostname: 'localhost', + port: '4000', + pathname: '/uploads/**', + }, + ], + }, /* config options here */ }; diff --git a/package-lock.json b/package-lock.json index e6de71a..ddaf1ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,19 +8,48 @@ "name": "frontend-panel", "version": "0.1.0", "dependencies": { + "@emotion/styled": "^11.14.1", + "@radix-ui/react-checkbox": "^1.3.3", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-label": "^2.1.8", + "@radix-ui/react-popover": "^1.1.15", + "@radix-ui/react-progress": "^1.1.8", + "@radix-ui/react-select": "^2.2.6", + "@radix-ui/react-separator": "^1.1.8", + "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-switch": "^1.2.6", + "@tanstack/react-query": "^5.90.12", + "axios": "^1.13.2", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "date-fns": "^4.1.0", + "formik": "^2.4.9", + "jsonwebtoken": "^9.0.3", + "jwt-decode": "^4.0.0", + "lucide-react": "^0.561.0", "next": "15.5.7", + "next-nprogress-bar": "^2.4.7", + "quill": "^2.0.3", "react": "19.1.0", - "react-dom": "19.1.0" + "react-day-picker": "^9.13.0", + "react-dom": "19.1.0", + "react-dropzone": "^14.3.8", + "react-toastify": "^11.0.5", + "tailwind-merge": "^3.4.0", + "yup": "^1.7.1" }, "devDependencies": { "@eslint/eslintrc": "^3", "@tailwindcss/postcss": "^4", + "@types/jsonwebtoken": "^9.0.10", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9", "eslint-config-next": "15.5.7", "tailwindcss": "^4", + "tw-animate-css": "^1.4.0", "typescript": "^5" } }, @@ -37,6 +66,151 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@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-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@date-fns/tz": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.4.1.tgz", + "integrity": "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==", + "license": "MIT" + }, "node_modules/@emnapi/core": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", @@ -70,6 +244,153 @@ "tslib": "^2.4.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", + "peer": true, + "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/@eslint-community/eslint-utils": { "version": "4.9.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", @@ -214,6 +535,44 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz", + "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.4" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -736,7 +1095,6 @@ "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==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -758,7 +1116,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -768,14 +1125,12 @@ "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, "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==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -987,6 +1342,1458 @@ "node": ">=12.4.0" } }, + "node_modules/@radix-ui/number": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", + "license": "MIT" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz", + "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", + "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", + "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz", + "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", + "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz", + "integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", + "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz", + "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", + "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.8.tgz", + "integrity": "sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.3", + "@radix-ui/react-primitive": "2.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-context": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz", + "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", + "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", + "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz", + "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", + "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz", + "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "license": "MIT", + "dependencies": { + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", + "license": "MIT" + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -1281,6 +3088,32 @@ "tailwindcss": "4.1.17" } }, + "node_modules/@tanstack/query-core": { + "version": "5.90.12", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.12.tgz", + "integrity": "sha512-T1/8t5DhV/SisWjDnaiU2drl6ySvsHj1bHBCWNXd+/T+Hh1cf6JodyEYMd5sgwm+b/mETT4EV3H+zCVczCU5hg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.90.12", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.12.tgz", + "integrity": "sha512-graRZspg7EoEaw0a8faiUASCyJrqjKPdqJ9EwuDRUF9mEYJ1YPczI9H+/agJ0mOJkPCJDk0lsz5QTrLZ/jQ2rg==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.90.12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", @@ -1299,6 +3132,18 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.7.tgz", + "integrity": "sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g==", + "license": "MIT", + "dependencies": { + "hoist-non-react-statics": "^3.3.0" + }, + "peerDependencies": { + "@types/react": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1313,6 +3158,24 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "20.19.26", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.26.tgz", @@ -1323,11 +3186,16 @@ "undici-types": "~6.21.0" } }, + "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/react": { "version": "19.2.7", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -1338,8 +3206,9 @@ "version": "19.2.3", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", - "dev": true, + "devOptional": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -1934,6 +3803,18 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/aria-query": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", @@ -2121,6 +4002,21 @@ "node": ">= 0.4" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/attr-accept": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz", + "integrity": "sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ==", + "license": "MIT", + "engines": { + "node": ">=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", @@ -2147,6 +4043,17 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/axobject-query": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", @@ -2157,6 +4064,21 @@ "node": ">= 0.4" } }, + "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", @@ -2188,6 +4110,12 @@ "node": ">=8" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -2211,7 +4139,6 @@ "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", @@ -2242,7 +4169,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -2285,12 +4211,33 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, + "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", @@ -2311,6 +4258,18 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2318,6 +4277,28 @@ "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", @@ -2337,7 +4318,6 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, "license": "MIT" }, "node_modules/damerau-levenshtein": { @@ -2401,11 +4381,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/date-fns-jalali": { + "version": "4.1.0-0", + "resolved": "https://registry.npmjs.org/date-fns-jalali/-/date-fns-jalali-4.1.0-0.tgz", + "integrity": "sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==", + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2426,6 +4421,15 @@ "dev": true, "license": "MIT" }, + "node_modules/deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -2462,6 +4466,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -2472,6 +4485,12 @@ "node": ">=8" } }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, "node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -2489,7 +4508,6 @@ "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", @@ -2500,6 +4518,15 @@ "node": ">= 0.4" } }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -2521,6 +4548,15 @@ "node": ">=10.13.0" } }, + "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.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", @@ -2594,7 +4630,6 @@ "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" @@ -2604,7 +4639,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -2642,7 +4676,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -2655,7 +4688,6 @@ "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", @@ -2702,7 +4734,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -2891,6 +4922,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -3137,6 +5169,12 @@ "node": ">=0.10.0" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3144,6 +5182,12 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "license": "Apache-2.0" + }, "node_modules/fast-glob": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", @@ -3211,6 +5255,18 @@ "node": ">=16.0.0" } }, + "node_modules/file-selector": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-2.1.2.tgz", + "integrity": "sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig==", + "license": "MIT", + "dependencies": { + "tslib": "^2.7.0" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -3224,6 +5280,12 @@ "node": ">=8" } }, + "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", @@ -3262,6 +5324,26 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -3278,11 +5360,51 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formik": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.9.tgz", + "integrity": "sha512-5nI94BMnlFDdQRBY4Sz39WkhxajZJ57Fzs8wVbtsQlm5ScKIR1QLYqv/ultBnobObtlUyxpxoLodpixrsf36Og==", + "funding": [ + { + "type": "individual", + "url": "https://opencollective.com/formik" + } + ], + "license": "Apache-2.0", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.1", + "deepmerge": "^2.1.1", + "hoist-non-react-statics": "^3.3.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-fast-compare": "^2.0.1", + "tiny-warning": "^1.0.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.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==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3333,7 +5455,6 @@ "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", @@ -3354,11 +5475,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "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", @@ -3446,7 +5575,6 @@ "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" @@ -3518,7 +5646,6 @@ "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" @@ -3531,7 +5658,6 @@ "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" @@ -3547,7 +5673,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -3556,6 +5681,15 @@ "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/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3570,7 +5704,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -3626,6 +5759,12 @@ "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", @@ -3706,7 +5845,6 @@ "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -4056,7 +6194,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -4072,6 +6209,18 @@ "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", @@ -4079,6 +6228,12 @@ "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", @@ -4106,6 +6261,28 @@ "json5": "lib/cli.js" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=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", @@ -4122,6 +6299,36 @@ "node": ">=4.0" } }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -4427,6 +6634,12 @@ "url": "https://opencollective.com/parcel" } }, + "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", @@ -4443,6 +6656,67 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4450,11 +6724,16 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "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==", - "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -4463,6 +6742,15 @@ "loose-envify": "cli.js" } }, + "node_modules/lucide-react": { + "version": "0.561.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.561.0.tgz", + "integrity": "sha512-Y59gMY38tl4/i0qewcqohPdEbieBy7SovpBL9IFebhc2mDd8x4PZSOsiFRkpPcOq6bj1r/mjH/Rk73gSlIJP2A==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -4477,7 +6765,6 @@ "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" @@ -4507,6 +6794,27 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -4534,7 +6842,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/nanoid": { @@ -4630,6 +6937,15 @@ } } }, + "node_modules/next-nprogress-bar": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/next-nprogress-bar/-/next-nprogress-bar-2.4.7.tgz", + "integrity": "sha512-OeveNQYFBhQhZ+RgrDnvHNUEQfHCmipymmD4AfAVE9pFV4jeWi7/nNK5f0lIk7ODRrtjyyr/n2YpkRbs5kUoMg==", + "license": "MIT", + "dependencies": { + "nprogress-v2": "^1.0.4" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -4658,11 +6974,16 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/nprogress-v2": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/nprogress-v2/-/nprogress-v2-1.1.10.tgz", + "integrity": "sha512-MypWLNIPIM07SS0bAc/oac0vhVFz9vAHm7d1sj//Pnf3J03LQ3CuWrlDteIu6exq0fIvkDJ6tUDRWLaifsIt5w==", + "license": "MIT" + }, "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==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -4849,11 +7170,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parchment": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz", + "integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==", + "license": "BSD-3-Clause" + }, "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==", - "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -4862,6 +7188,24 @@ "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", @@ -4886,9 +7230,17 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, "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", @@ -4961,7 +7313,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -4969,6 +7320,18 @@ "react-is": "^16.13.1" } }, + "node_modules/property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", + "license": "MIT" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -5000,6 +7363,35 @@ ], "license": "MIT" }, + "node_modules/quill": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/quill/-/quill-2.0.3.tgz", + "integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==", + "license": "BSD-3-Clause", + "dependencies": { + "eventemitter3": "^5.0.1", + "lodash-es": "^4.17.21", + "parchment": "^3.0.0", + "quill-delta": "^5.1.0" + }, + "engines": { + "npm": ">=8.2.3" + } + }, + "node_modules/quill-delta": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz", + "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", + "license": "MIT", + "dependencies": { + "fast-diff": "^1.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.isequal": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/react": { "version": "19.1.0", "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", @@ -5010,6 +7402,27 @@ "node": ">=0.10.0" } }, + "node_modules/react-day-picker": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.13.0.tgz", + "integrity": "sha512-euzj5Hlq+lOHqI53NiuNhCP8HWgsPf/bBAVijR50hNaY1XwjKjShAnIe8jm8RD2W9IJUvihDIZ+KrmqfFzNhFQ==", + "license": "MIT", + "dependencies": { + "@date-fns/tz": "^1.4.1", + "date-fns": "^4.1.0", + "date-fns-jalali": "^4.1.0-0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/gpbl" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/react-dom": { "version": "19.1.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", @@ -5023,13 +7436,117 @@ "react": "^19.1.0" } }, + "node_modules/react-dropzone": { + "version": "14.3.8", + "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.3.8.tgz", + "integrity": "sha512-sBgODnq+lcA4P296DY4wacOZz3JFpD99fp+hb//iBO2HHnyeZU3FwWyXJ6salNpqQdsZrgMrotuko/BdJMV8Ug==", + "license": "MIT", + "dependencies": { + "attr-accept": "^2.2.4", + "file-selector": "^2.1.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">= 10.13" + }, + "peerDependencies": { + "react": ">= 16.8 || 18.0.0" + } + }, + "node_modules/react-fast-compare": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", + "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==", + "license": "MIT" + }, "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==", - "dev": true, "license": "MIT" }, + "node_modules/react-remove-scroll": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-toastify": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.5.tgz", + "integrity": "sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA==", + "license": "MIT", + "dependencies": { + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": "^18 || ^19", + "react-dom": "^18 || ^19" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -5078,7 +7595,6 @@ "version": "1.22.11", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", - "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.16.1", @@ -5099,7 +7615,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -5170,6 +7685,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/safe-push-apply": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", @@ -5215,7 +7750,6 @@ "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "devOptional": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -5417,6 +7951,15 @@ "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", @@ -5606,6 +8149,12 @@ } } }, + "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", @@ -5623,7 +8172,6 @@ "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==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -5632,6 +8180,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tailwind-merge": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz", + "integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "4.1.17", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.17.tgz", @@ -5653,6 +8211,18 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/tiny-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", + "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==", + "license": "MIT" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -5715,6 +8285,12 @@ "node": ">=8.0" } }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", + "license": "MIT" + }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -5747,6 +8323,16 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/tw-animate-css": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz", + "integrity": "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Wombosvideo" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -5760,6 +8346,18 @@ "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -5924,6 +8522,49 @@ "punycode": "^2.1.0" } }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6039,6 +8680,15 @@ "node": ">=0.10.0" } }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "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", @@ -6051,6 +8701,18 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/yup": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.7.1.tgz", + "integrity": "sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw==", + "license": "MIT", + "dependencies": { + "property-expr": "^2.0.5", + "tiny-case": "^1.0.3", + "toposort": "^2.0.2", + "type-fest": "^2.19.0" + } } } } diff --git a/package.json b/package.json index dcaec2b..375184f 100644 --- a/package.json +++ b/package.json @@ -9,19 +9,48 @@ "lint": "eslint" }, "dependencies": { + "@emotion/styled": "^11.14.1", + "@radix-ui/react-checkbox": "^1.3.3", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-label": "^2.1.8", + "@radix-ui/react-popover": "^1.1.15", + "@radix-ui/react-progress": "^1.1.8", + "@radix-ui/react-select": "^2.2.6", + "@radix-ui/react-separator": "^1.1.8", + "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-switch": "^1.2.6", + "@tanstack/react-query": "^5.90.12", + "axios": "^1.13.2", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "date-fns": "^4.1.0", + "formik": "^2.4.9", + "jsonwebtoken": "^9.0.3", + "jwt-decode": "^4.0.0", + "lucide-react": "^0.561.0", + "next": "15.5.7", + "next-nprogress-bar": "^2.4.7", + "quill": "^2.0.3", "react": "19.1.0", + "react-day-picker": "^9.13.0", "react-dom": "19.1.0", - "next": "15.5.7" + "react-dropzone": "^14.3.8", + "react-toastify": "^11.0.5", + "tailwind-merge": "^3.4.0", + "yup": "^1.7.1" }, "devDependencies": { - "typescript": "^5", + "@eslint/eslintrc": "^3", + "@tailwindcss/postcss": "^4", + "@types/jsonwebtoken": "^9.0.10", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", - "@tailwindcss/postcss": "^4", - "tailwindcss": "^4", "eslint": "^9", "eslint-config-next": "15.5.7", - "@eslint/eslintrc": "^3" + "tailwindcss": "^4", + "tw-animate-css": "^1.4.0", + "typescript": "^5" } } diff --git a/public/fonts/sogand/SOGAND.ttf b/public/fonts/sogand/SOGAND.ttf new file mode 100644 index 0000000..fdee227 Binary files /dev/null and b/public/fonts/sogand/SOGAND.ttf differ diff --git a/public/fonts/vazir/Vazirmatn-Black.woff2 b/public/fonts/vazir/Vazirmatn-Black.woff2 new file mode 100644 index 0000000..f08cace Binary files /dev/null and b/public/fonts/vazir/Vazirmatn-Black.woff2 differ diff --git a/public/fonts/vazir/Vazirmatn-Bold.woff2 b/public/fonts/vazir/Vazirmatn-Bold.woff2 new file mode 100644 index 0000000..65b427f Binary files /dev/null and b/public/fonts/vazir/Vazirmatn-Bold.woff2 differ diff --git a/public/fonts/vazir/Vazirmatn-ExtraBold.woff2 b/public/fonts/vazir/Vazirmatn-ExtraBold.woff2 new file mode 100644 index 0000000..c074e70 Binary files /dev/null and b/public/fonts/vazir/Vazirmatn-ExtraBold.woff2 differ diff --git a/public/fonts/vazir/Vazirmatn-ExtraLight.woff2 b/public/fonts/vazir/Vazirmatn-ExtraLight.woff2 new file mode 100644 index 0000000..997dea0 Binary files /dev/null and b/public/fonts/vazir/Vazirmatn-ExtraLight.woff2 differ diff --git a/public/fonts/vazir/Vazirmatn-Light.woff2 b/public/fonts/vazir/Vazirmatn-Light.woff2 new file mode 100644 index 0000000..d154722 Binary files /dev/null and b/public/fonts/vazir/Vazirmatn-Light.woff2 differ diff --git a/public/fonts/vazir/Vazirmatn-Medium.woff2 b/public/fonts/vazir/Vazirmatn-Medium.woff2 new file mode 100644 index 0000000..495af75 Binary files /dev/null and b/public/fonts/vazir/Vazirmatn-Medium.woff2 differ diff --git a/public/fonts/vazir/Vazirmatn-Regular.woff2 b/public/fonts/vazir/Vazirmatn-Regular.woff2 new file mode 100644 index 0000000..c9824c8 Binary files /dev/null and b/public/fonts/vazir/Vazirmatn-Regular.woff2 differ diff --git a/public/fonts/vazir/Vazirmatn-SemiBold.woff2 b/public/fonts/vazir/Vazirmatn-SemiBold.woff2 new file mode 100644 index 0000000..5301641 Binary files /dev/null and b/public/fonts/vazir/Vazirmatn-SemiBold.woff2 differ diff --git a/public/fonts/vazir/Vazirmatn-Thin.woff2 b/public/fonts/vazir/Vazirmatn-Thin.woff2 new file mode 100644 index 0000000..b7df278 Binary files /dev/null and b/public/fonts/vazir/Vazirmatn-Thin.woff2 differ diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 0000000..b443044 Binary files /dev/null and b/public/logo.png differ diff --git a/src/app/(auth)/layout.tsx b/src/app/(auth)/layout.tsx new file mode 100644 index 0000000..1abc7ec --- /dev/null +++ b/src/app/(auth)/layout.tsx @@ -0,0 +1,13 @@ +"use client"; +import {QueryClient, QueryClientProvider} from "@tanstack/react-query"; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + const queryClient = new QueryClient(); + return ( + {children} + ); +} diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx new file mode 100644 index 0000000..01b6e69 --- /dev/null +++ b/src/app/(auth)/login/page.tsx @@ -0,0 +1,24 @@ +"use client"; +import LoginForm from "@/components/forms/login/LoginForm"; +import {useUserLogin} from "@/hooks"; +import {useRouter} from "next/navigation"; +import React from "react"; + +export default function Page() { + const router = useRouter(); + const {mutateAsync, isPending} = useUserLogin(); + return ( +
+
+
+ فرم ورود +
+ +
+
+ ); +} diff --git a/src/app/(auth)/reset-password/[token]/page.tsx b/src/app/(auth)/reset-password/[token]/page.tsx new file mode 100644 index 0000000..7072957 --- /dev/null +++ b/src/app/(auth)/reset-password/[token]/page.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +export default function Page() { + return ( +
+ +
+ ) +} diff --git a/src/app/(auth)/reset-password/page.tsx b/src/app/(auth)/reset-password/page.tsx new file mode 100644 index 0000000..9af72a7 --- /dev/null +++ b/src/app/(auth)/reset-password/page.tsx @@ -0,0 +1,18 @@ +"use client" +import ResetPasswordForm from '@/components/forms/reset-password/ResetPasswordForm' +import { useRouter } from 'next/navigation' +import React from 'react' + +export default function Page() { + const router = useRouter(); + return ( +
+
+
+ فرم فراموشی رمز عبور +
+ +
+
+ ) +} diff --git a/src/app/(dashboard)/configs/loading.tsx b/src/app/(dashboard)/configs/loading.tsx new file mode 100644 index 0000000..2b22b07 --- /dev/null +++ b/src/app/(dashboard)/configs/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ); +} diff --git a/src/app/(dashboard)/configs/page.tsx b/src/app/(dashboard)/configs/page.tsx new file mode 100644 index 0000000..d5f4531 --- /dev/null +++ b/src/app/(dashboard)/configs/page.tsx @@ -0,0 +1,26 @@ +"use client"; +import UpdateConfigsForm from "@/components/forms/configs/ConfigsForm"; +import Loader from "@/components/Loader"; +import {useGetAllConfigs, useUpdateConfigs} from "@/hooks/configs"; +import {useRouter} from "next/navigation"; +import React, {Suspense} from "react"; + +export default function Page() { + const router = useRouter(); + const {data} = useGetAllConfigs(); + const {mutateAsync, isPending} = useUpdateConfigs(); + return ( +
+ }> + {data && data?.data?.length && ( + + )} + +
+ ); +} diff --git a/src/app/(dashboard)/dashboard/loading.tsx b/src/app/(dashboard)/dashboard/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/dashboard/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/dashboard/page.tsx b/src/app/(dashboard)/dashboard/page.tsx new file mode 100644 index 0000000..4d81877 --- /dev/null +++ b/src/app/(dashboard)/dashboard/page.tsx @@ -0,0 +1,25 @@ +import DashboardCDNServerStatus from "@/components/DashboardCDNServerStatus"; +import DashboardStatistics from "@/components/DashboardStatistics"; +import Loader from "@/components/Loader"; +import RoleGuard from "@/components/RoleGuard"; + +import React, {Suspense} from "react"; + +export default function Page() { + return ( +
+
+ }> + + +
+
+ }> + + + + +
+
+ ); +} diff --git a/src/app/(dashboard)/default/loading.tsx b/src/app/(dashboard)/default/loading.tsx new file mode 100644 index 0000000..2b22b07 --- /dev/null +++ b/src/app/(dashboard)/default/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ); +} diff --git a/src/app/(dashboard)/default/page.tsx b/src/app/(dashboard)/default/page.tsx new file mode 100644 index 0000000..e18cb7b --- /dev/null +++ b/src/app/(dashboard)/default/page.tsx @@ -0,0 +1,33 @@ +"use client"; +import UpdateDefaultForm from "@/components/forms/default/UpdateDefaultsForm"; +import Loader from "@/components/Loader"; +import {useGetAllDefaults, useUpdateDefaults} from "@/hooks/defaults"; +import { useGetLanguages } from "@/hooks/languages"; +import {useRouter} from "next/navigation"; +import React, {Suspense} from "react"; + +export default function Page() { + const router = useRouter(); + + const {data, isLoading} = useGetAllDefaults(); + const {mutateAsync, isPending} = useUpdateDefaults(); + const { + data: languages, + } = useGetLanguages(); + return ( +
+ }> + {data && languages && ( + + )} + +
+ ); +} diff --git a/src/app/(dashboard)/department/loading.tsx b/src/app/(dashboard)/department/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/department/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/department/members/edit/[id]/page.tsx b/src/app/(dashboard)/department/members/edit/[id]/page.tsx new file mode 100644 index 0000000..56eb0a1 --- /dev/null +++ b/src/app/(dashboard)/department/members/edit/[id]/page.tsx @@ -0,0 +1,64 @@ +"use client"; +import UpdateDoctorForm from "@/components/forms/doctor/update/UpdateDoctorForm"; +import Loader from "@/components/Loader"; +import SectionTitle from "@/components/SectionTitle"; +import { useGetAllExpertiseList } from "@/hooks/expertise"; +import { useGetLanguages } from "@/hooks/languages"; +import {useGetSingleUser, useUpdateUser} from "@/hooks/users"; + +import Link from "next/link"; +import {useParams, useRouter} from "next/navigation"; +import {Suspense, useState} from "react"; + + +export default function Page() { + const params = useParams(); + const id = params?.id; + const router = useRouter(); + const [loading] = useState(false); + const { + data: languages, + } = useGetLanguages(); + const { + data: expertises, + } = useGetAllExpertiseList(); + const { + data: singleUser, + } = useGetSingleUser(id?.toString() ?? ""); + + const {mutateAsync} = useUpdateUser(); + const {data} = singleUser || {}; + return ( +
+
+ +
+ + افزودن عضو جدید + + + مشاهده لیست اعضاء دپارتمان + +
+
+ }> + {data && expertises && languages && !loading && ( + + )} + +
+ ); +} diff --git a/src/app/(dashboard)/department/members/edit/page.tsx b/src/app/(dashboard)/department/members/edit/page.tsx new file mode 100644 index 0000000..6a1fa26 --- /dev/null +++ b/src/app/(dashboard)/department/members/edit/page.tsx @@ -0,0 +1,7 @@ + +"use client" +import { notFound } from 'next/navigation' + +export default function Page() { + return notFound +} diff --git a/src/app/(dashboard)/department/members/new/page.tsx b/src/app/(dashboard)/department/members/new/page.tsx new file mode 100644 index 0000000..149e3ac --- /dev/null +++ b/src/app/(dashboard)/department/members/new/page.tsx @@ -0,0 +1,103 @@ +"use client"; +import DenyAccess from "@/components/DenyAccess"; +import CreateDepartmentMember from "@/components/forms/department/new/CreateDepartmentMember"; +import Loader from "@/components/Loader"; +import SectionTitle from "@/components/SectionTitle"; +import {API_URL} from "@/constants"; +import {Expertise, Language} from "@/types"; +import Link from "next/link"; +import {useRouter} from "next/navigation"; +import {Suspense, useEffect, useState} from "react"; + +async function fetchLanguages() { + const res = await fetch(`${API_URL}/language/get/all`,{cache:"no-cache"}); + + + if (!res.ok && res.status==500) { + throw new Error("Failed to get data"); + } + + if(!res.ok && res.status==404){ + return [] + } + + const data = await res.json(); + + return data; +} +async function fetchExpertise() { + const res = await fetch(`${API_URL}/expertise/fa/get/all/list`,{cache:"no-cache"}); + + + if (!res.ok && res.status==500) { + throw new Error("Failed to get data"); + } + + if(!res.ok && res.status==404){ + return [] + } + + const data = await res.json(); + + return data; +} + +export default function Page() { + const router = useRouter(); + const [loading, setLoading] = useState(false); + const [data, setData] = useState([]); + + const [expertises, setExpertises] = useState([]); + useEffect(() => { + let active = true; + + setLoading(true); + fetchExpertise() + .then((res) => { + if (!active) return; + setExpertises(res.data); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, []); + useEffect(() => { + let active = true; + + setLoading(true); + fetchLanguages() + .then((res) => { + if (!active) return; + setData(res.data); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, []); + + if (loading) { + return ; + } + return ( +
+
+ + مشاهده لیست اعضاء دپارتمان +
+ }> + {data?.length > 0 ? expertises?.length > 0 ? : : } + + +
+ ); +} diff --git a/src/app/(dashboard)/department/members/page.tsx b/src/app/(dashboard)/department/members/page.tsx new file mode 100644 index 0000000..781840a --- /dev/null +++ b/src/app/(dashboard)/department/members/page.tsx @@ -0,0 +1,49 @@ +import DepartmentMembersTable from "@/components/DepartmentMembersTable"; + +import Loader from "@/components/Loader"; +import RoleGuard from "@/components/RoleGuard"; +import SearchBox from "@/components/SearchBox"; +import UsersTableExport from "@/components/usersTableExport"; + +import {Plus} from "lucide-react"; +import Link from "next/link"; +import React, {Suspense} from "react"; + +export default function Page() { + return ( + <> +
+
+
+ +
+
+ + + + افزودن عضو جدید + + + + + +
+
+
+ }> + + +
+
+ + ); +} diff --git a/src/app/(dashboard)/doctors/edit/[id]/page.tsx b/src/app/(dashboard)/doctors/edit/[id]/page.tsx new file mode 100644 index 0000000..d83a36c --- /dev/null +++ b/src/app/(dashboard)/doctors/edit/[id]/page.tsx @@ -0,0 +1,64 @@ +"use client"; +import UpdateDoctorForm from "@/components/forms/doctor/update/UpdateDoctorForm"; +import Loader from "@/components/Loader"; +import SectionTitle from "@/components/SectionTitle"; +import { useGetAllExpertiseList } from "@/hooks/expertise"; +import { useGetLanguages } from "@/hooks/languages"; +import {useGetSingleUser, useUpdateUser} from "@/hooks/users"; + +import Link from "next/link"; +import {useParams, useRouter} from "next/navigation"; +import {Suspense, useState} from "react"; + + +export default function Page() { + const params = useParams(); + const id = params?.id; + const router = useRouter(); + const [loading] = useState(false); + const { + data: languages, + } = useGetLanguages(); + const { + data: expertises, + } = useGetAllExpertiseList(); + const { + data: singleUser, + } = useGetSingleUser(id?.toString() ?? ""); + + const {mutateAsync} = useUpdateUser(); + const {data} = singleUser || {}; + return ( +
+
+ +
+ + افزودن پزشک جدید + + + مشاهده لیست پزشکان + +
+
+ }> + {data && expertises && languages && !loading && ( + + )} + +
+ ); +} diff --git a/src/app/(dashboard)/doctors/edit/page.tsx b/src/app/(dashboard)/doctors/edit/page.tsx new file mode 100644 index 0000000..11355b4 --- /dev/null +++ b/src/app/(dashboard)/doctors/edit/page.tsx @@ -0,0 +1,10 @@ +"use client" +import { notFound } from "next/navigation"; + + + + +export default function Page() { + + return notFound(); +} diff --git a/src/app/(dashboard)/doctors/loading.tsx b/src/app/(dashboard)/doctors/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/doctors/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/doctors/new/page.tsx b/src/app/(dashboard)/doctors/new/page.tsx new file mode 100644 index 0000000..058c01d --- /dev/null +++ b/src/app/(dashboard)/doctors/new/page.tsx @@ -0,0 +1,103 @@ +"use client"; +import DenyAccess from "@/components/DenyAccess"; +import CreateDoctorForm from "@/components/forms/doctor/create/CreateDoctorForm"; +import Loader from "@/components/Loader"; +import SectionTitle from "@/components/SectionTitle"; +import {API_URL} from "@/constants"; +import {Expertise, Language} from "@/types"; +import Link from "next/link"; +import {useRouter} from "next/navigation"; +import {Suspense, useEffect, useState} from "react"; + +async function fetchLanguages() { + const res = await fetch(`${API_URL}/language/get/all`,{cache:"no-cache"}); + + + + if (!res.ok && res.status==500) { + throw new Error("Failed to get data"); + } + + if(!res.ok && res.status==404){ + return [] + } + + const data = await res.json(); + + return data; +} +async function fetchExpertise() { + const res = await fetch(`${API_URL}/expertise/fa/get/all/list`,{cache:"no-cache"}); + + if (!res.ok && res.status==500) { + throw new Error("Failed to get data"); + } + + if(!res.ok && res.status==404){ + return [] + } + + const data = await res.json(); + + return data; +} + +export default function Page() { + const router = useRouter(); + const [loading, setLoading] = useState(false); + const [data, setData] = useState([]); + + const [expertises, setExpertises] = useState([]); + useEffect(() => { + let active = true; + + setLoading(true); + fetchExpertise() + .then((res) => { + if (!active) return; + setExpertises(res.data); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, []); + useEffect(() => { + let active = true; + + setLoading(true); + fetchLanguages() + .then((res) => { + if (!active) return; + setData(res.data); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, []); + + if (loading) { + return ; + } + return ( +
+
+ + مشاهده لیست پزشکان +
+ }> + {data?.length > 0 ? expertises?.length > 0 ? : : } + + +
+ ); +} diff --git a/src/app/(dashboard)/doctors/page.tsx b/src/app/(dashboard)/doctors/page.tsx new file mode 100644 index 0000000..cb64189 --- /dev/null +++ b/src/app/(dashboard)/doctors/page.tsx @@ -0,0 +1,51 @@ +import DoctorsTable from "@/components/DoctorsTable"; +import ExpertiseFilterBox from "@/components/ExpertiseFilterBox"; +import Loader from "@/components/Loader"; +import RoleGuard from "@/components/RoleGuard"; +import SearchBox from "@/components/SearchBox"; +import UsersTableExport from "@/components/usersTableExport"; + +import {Plus} from "lucide-react"; +import Link from "next/link"; +import React, {Suspense} from "react"; + +export default function Page() { + return ( + <> +
+
+
+ + + +
+
+ + + + افزودن پزشک جدید + + + + + +
+
+
+ }> + + +
+
+ + ); +} diff --git a/src/app/(dashboard)/expertise/edit/[id]/page.tsx b/src/app/(dashboard)/expertise/edit/[id]/page.tsx new file mode 100644 index 0000000..f45d5f1 --- /dev/null +++ b/src/app/(dashboard)/expertise/edit/[id]/page.tsx @@ -0,0 +1,62 @@ +"use client"; +import UpdateExpertiseForm from "@/components/forms/expertise/edit/UpdateExpertiseForm"; +import Loader from "@/components/Loader"; +import SectionTitle from "@/components/SectionTitle"; +import {useGetSingleExpertise, useUpdateExpertise} from "@/hooks/expertise"; +import {useGetLanguages} from "@/hooks/languages"; + +import Link from "next/link"; +import {useParams, useRouter} from "next/navigation"; +import {Suspense, useState} from "react"; + +export default function Page() { + const params = useParams(); + const id = params?.id; + const router = useRouter(); + const [loading] = useState(false); + const { + data: languages, + + } = useGetLanguages(); + + const { + data: singleExpertise, + + } = useGetSingleExpertise(id?.toString() ?? ""); + + const {isPending, mutateAsync} = useUpdateExpertise(); + const {data} = singleExpertise || {}; + return ( +
+
+ +
+ + افزودن تخصص جدید + + + مشاهده لیست تخصص ها + +
+
+ }> + {data && languages && !loading && ( + + )} + +
+ ); +} diff --git a/src/app/(dashboard)/expertise/edit/loading.tsx b/src/app/(dashboard)/expertise/edit/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/expertise/edit/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/expertise/edit/page.tsx b/src/app/(dashboard)/expertise/edit/page.tsx new file mode 100644 index 0000000..7072957 --- /dev/null +++ b/src/app/(dashboard)/expertise/edit/page.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +export default function Page() { + return ( +
+ +
+ ) +} diff --git a/src/app/(dashboard)/expertise/loading.tsx b/src/app/(dashboard)/expertise/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/expertise/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/expertise/new/loading.tsx b/src/app/(dashboard)/expertise/new/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/expertise/new/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/expertise/new/page.tsx b/src/app/(dashboard)/expertise/new/page.tsx new file mode 100644 index 0000000..a243e71 --- /dev/null +++ b/src/app/(dashboard)/expertise/new/page.tsx @@ -0,0 +1,40 @@ +"use client"; +import DenyAccess from "@/components/DenyAccess"; +import CreateExpertiseForm from "@/components/forms/expertise/new/CreateExpertiseForm"; +import Loader from "@/components/Loader"; +import SectionTitle from "@/components/SectionTitle"; +import {useCreateExpertise} from "@/hooks/expertise"; +import {useGetLanguages} from "@/hooks/languages"; +import Link from "next/link"; +import {useRouter} from "next/navigation"; +import React, {Suspense} from "react"; + +export default function Page() { + const router = useRouter(); + const {data} = useGetLanguages(); + const {mutateAsync, isPending} = useCreateExpertise(); + return ( +
+
+ + + مشاهده لیست تخصص ها + +
+ }> + { + data?.data ? data?.data?.length > 0 ? : :
خطا در دریافت اطلاعات زبان ها
+ } + +
+
+ ); +} diff --git a/src/app/(dashboard)/expertise/page.tsx b/src/app/(dashboard)/expertise/page.tsx new file mode 100644 index 0000000..465e8fa --- /dev/null +++ b/src/app/(dashboard)/expertise/page.tsx @@ -0,0 +1,52 @@ +"use client"; + +import ExpertiseTable from "@/components/ExpertiseTable"; +import LanguagesFilterBox from "@/components/LanguagesFilterBox"; +import RoleGuard from "@/components/RoleGuard"; +import SearchBox from "@/components/SearchBox"; +import { Spinner } from "@/components/ui/spinner"; + +import {Plus} from "lucide-react"; +import Link from "next/link"; + +import React, { Suspense, useState } from "react"; + +export default function Page() { + const [lang,setLang]=useState("fa"); + return ( + <> +
+
+
+ + +
+
+ + + + افزودن تخصص جدید + + + {/* + + */} +
+
+
+ }> + + +
+
+ + ); +} diff --git a/src/app/(dashboard)/languages/loading.tsx b/src/app/(dashboard)/languages/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/languages/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/languages/page.tsx b/src/app/(dashboard)/languages/page.tsx new file mode 100644 index 0000000..023e363 --- /dev/null +++ b/src/app/(dashboard)/languages/page.tsx @@ -0,0 +1,52 @@ +"use client"; +import CreateLanguageForm from "@/components/forms/languages/new/CreateLanguageForm"; +import LanguagesTable from "@/components/LangaugesTable"; +import Loader from "@/components/Loader"; +import RoleGuard from "@/components/RoleGuard"; +import SearchBox from "@/components/SearchBox"; +import {Dialog} from "@/components/ui/dialog"; +import {useCreateLanguage} from "@/hooks/languages"; +import { useQueryClient } from "@tanstack/react-query"; +import {useRouter} from "next/navigation"; + +import React, {Suspense} from "react"; + +export default function Page() { + const router = useRouter(); +const queryClient = useQueryClient(); + const {mutateAsync, isPending} = useCreateLanguage(); + return ( + <> +
+
+
+ +
+
+ + + + + +
+
+
+ }> + + +
+
+ + ); +} diff --git a/src/app/(dashboard)/layout.tsx b/src/app/(dashboard)/layout.tsx new file mode 100644 index 0000000..1851bb0 --- /dev/null +++ b/src/app/(dashboard)/layout.tsx @@ -0,0 +1,53 @@ +import type {Metadata} from "next"; +import "../globals.css"; +import ProfileDropdown from "@/components/ProfileDropdown"; +import {Button} from "@/components/ui/button"; +import {Bell} from "lucide-react"; +import SideMenu from "@/components/SideMenu"; +import PanelQueryProvider from "@/components/PanelQueryProvider"; +import AuthGuard from "@/components/AuthGuard"; +import { Suspense } from "react"; +import Loader from "@/components/Loader"; +import { Badge } from "@/components/ui/badge"; +export const metadata: Metadata = { + title: "پنل مدیریت سایت ipd", + description: "Generated by create next app", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( +
+ + + +
+
+
+ }> + + + + + {new Date().toLocaleDateString("fa-IR")} + +
+

+ پنل مدیریت بیماران بین الملل بیمارستان شمال +

+
+ +
+ {children} +
+
+
+
+
+ ); +} diff --git a/src/app/(dashboard)/logs/access/loading.tsx b/src/app/(dashboard)/logs/access/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/logs/access/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/logs/audit/loading.tsx b/src/app/(dashboard)/logs/audit/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/logs/audit/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/logs/errors/loading.tsx b/src/app/(dashboard)/logs/errors/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/logs/errors/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/logs/loading.tsx b/src/app/(dashboard)/logs/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/logs/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/logs/performance/loading.tsx b/src/app/(dashboard)/logs/performance/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/logs/performance/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/logs/policy/loading.tsx b/src/app/(dashboard)/logs/policy/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/logs/policy/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/logs/requests/loading.tsx b/src/app/(dashboard)/logs/requests/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/logs/requests/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/logs/upload-server/loading.tsx b/src/app/(dashboard)/logs/upload-server/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/logs/upload-server/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/logs/upload-server/page.tsx b/src/app/(dashboard)/logs/upload-server/page.tsx new file mode 100644 index 0000000..a57611b --- /dev/null +++ b/src/app/(dashboard)/logs/upload-server/page.tsx @@ -0,0 +1,43 @@ +import React from "react"; + +async function fetchData() { + const res = await fetch("http://localhost:4000/logs", { cache: "no-cache" }); + + if (!res.ok && res.status == 500) { + throw new Error("Failed to fetch data"); + } + + if (!res.ok && res.status == 404) { + return ""; + } + + const data = await res.json(); + + return data; +} +interface LogsType { + level: string; + message: { method: string; timestamp: Date; url: string }; +} +export default async function Page() { + const data = await fetchData(); + return ( +
+
+ {data.logs + .map((item: string) => JSON.parse(item)) + .map((log: LogsType, index: number) => ( +
+
Level : {log.level}
+
message method : {log.message.method}
+
+ message timestamp :{" "} + {new Date(log.message.timestamp).toLocaleString("fa-IR")} +
+
url : {log.message.url}
+
+ ))} +
+
+ ); +} diff --git a/src/app/(dashboard)/medical-packages/edit/[id]/page.tsx b/src/app/(dashboard)/medical-packages/edit/[id]/page.tsx new file mode 100644 index 0000000..31fcb81 --- /dev/null +++ b/src/app/(dashboard)/medical-packages/edit/[id]/page.tsx @@ -0,0 +1,73 @@ +"use client"; +import UpdateMedicalPackageForm from "@/components/forms/medical-packages/edit/UpdateMedicalPackageForm"; +import Loader from "@/components/Loader"; +import SectionTitle from "@/components/SectionTitle"; +import {useGetLanguages} from "@/hooks/languages"; +import { + useGetAllMedicalPackagesParent, + useGetSingleMedicalPackage, + useUpdateMedicalPackage, +} from "@/hooks/medical-package"; +import {useQueryClient} from "@tanstack/react-query"; + +import Link from "next/link"; +import {useParams, useRouter} from "next/navigation"; +import {Suspense, useState} from "react"; + +export default function Page() { + const params = useParams(); + const id = params?.id; + const router = useRouter(); + const queryClient = useQueryClient(); + const [lang] = useState("fa"); + const [loading] = useState(false); + const { + data: languages, + } = useGetLanguages(); + + const { + data: singleMedicalPackage, + } = useGetSingleMedicalPackage({id: id?.toString() ?? "", lang}); + const {data: parents} = + useGetAllMedicalPackagesParent("fa"); + + const {isPending, mutateAsync} = useUpdateMedicalPackage(); + const {data} = singleMedicalPackage || {}; + return ( +
+
+
+ +
+
+ + افزودن خدمت پزشکی جدید + + + مشاهده لیست خدمات پزشکی + +
+
+ }> + {data && languages && !loading && ( + + )} + +
+ ); +} diff --git a/src/app/(dashboard)/medical-packages/edit/page.tsx b/src/app/(dashboard)/medical-packages/edit/page.tsx new file mode 100644 index 0000000..7072957 --- /dev/null +++ b/src/app/(dashboard)/medical-packages/edit/page.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +export default function Page() { + return ( +
+ +
+ ) +} diff --git a/src/app/(dashboard)/medical-packages/new/page.tsx b/src/app/(dashboard)/medical-packages/new/page.tsx new file mode 100644 index 0000000..9e41613 --- /dev/null +++ b/src/app/(dashboard)/medical-packages/new/page.tsx @@ -0,0 +1,30 @@ +"use client"; +import DenyAccess from "@/components/DenyAccess"; +import CreateMedicalPackageForm from "@/components/forms/medical-packages/new/CreateMedicalPackageForm"; +import Loader from "@/components/Loader"; +import {useGetLanguages} from "@/hooks/languages"; +import {useCreateMedicalPackage, useGetAllMedicalPackagesParent} from "@/hooks/medical-package"; +import {useQueryClient} from "@tanstack/react-query"; +import React, {Suspense} from "react"; + +export default function Page() { + const {data} = useGetLanguages(); + const {mutateAsync, isPending} = useCreateMedicalPackage(); + const {data:parents}=useGetAllMedicalPackagesParent("fa") + const queryClient = useQueryClient(); + return ( +
+ }> + {data?.data?.length > 0 ? ( + + ) : } + +
+ ); +} diff --git a/src/app/(dashboard)/medical-packages/page.tsx b/src/app/(dashboard)/medical-packages/page.tsx new file mode 100644 index 0000000..13f1834 --- /dev/null +++ b/src/app/(dashboard)/medical-packages/page.tsx @@ -0,0 +1,49 @@ +"use client"; +import LanguagesFilterBox from "@/components/LanguagesFilterBox"; +import Loader from "@/components/Loader"; +import MedicalPackagesTable from "@/components/MedicalPackagesTable"; +import RoleGuard from "@/components/RoleGuard"; +import SearchBox from "@/components/SearchBox"; +import {Plus} from "lucide-react"; +import Link from "next/link"; +import React, {Suspense, useState} from "react"; + +export default function Page() { + const [lang, setLang] = useState("fa"); + + return ( +
+
+
+ + + +
+
+ + + + افزودن پکیج جدید + + + {/* + + */} +
+
+
+ }> + + +
+
+ ); +} diff --git a/src/app/(dashboard)/online-case/new/page.tsx b/src/app/(dashboard)/online-case/new/page.tsx new file mode 100644 index 0000000..e16a123 --- /dev/null +++ b/src/app/(dashboard)/online-case/new/page.tsx @@ -0,0 +1,15 @@ +"use client"; +import CreateOnlineCaseForm from "@/components/forms/online-case/new/CreateOnlineCaseForm"; +import { useGetAllCountries } from "@/hooks/country"; +import {useRouter} from "next/navigation"; +import React from "react"; + +export default function Page() { + const router = useRouter(); + const {data:countries,isLoading:fetchCountriesLoading}=useGetAllCountries() + return ( +
+ +
+ ); +} diff --git a/src/app/(dashboard)/online-case/page.tsx b/src/app/(dashboard)/online-case/page.tsx new file mode 100644 index 0000000..92e378c --- /dev/null +++ b/src/app/(dashboard)/online-case/page.tsx @@ -0,0 +1,46 @@ +import Loader from "@/components/Loader"; +import OnlineCasesTable from "@/components/OnlineCasesTable"; +import RoleGuard from "@/components/RoleGuard"; +import SearchBox from "@/components/SearchBox"; +import {Plus} from "lucide-react"; +import Link from "next/link"; +import React, {Suspense} from "react"; + +export default function Page() { + return ( + <> +
+
+
+ +
+
+ + + + افزودن کیس جدید + + + {/* + + */} +
+
+
+ }> + + +
+
+ + ); +} diff --git a/src/app/(dashboard)/patients/edit/[id]/page.tsx b/src/app/(dashboard)/patients/edit/[id]/page.tsx new file mode 100644 index 0000000..7cc191e --- /dev/null +++ b/src/app/(dashboard)/patients/edit/[id]/page.tsx @@ -0,0 +1,66 @@ +"use client"; +import UpdatePatientForm from "@/components/forms/patients/edit/UpdatePatientForm"; +import Loader from "@/components/Loader"; +import SectionTitle from "@/components/SectionTitle"; +import {useGetAllCountries} from "@/hooks/country"; +import {useGetSinglePatient, useUpdatePatient} from "@/hooks/patients"; +import {useUpdateUser} from "@/hooks/users"; + +import Link from "next/link"; +import {useParams, useRouter} from "next/navigation"; +import {Suspense, useState} from "react"; + +export default function Page() { + const router = useRouter(); + const {data: countries, isLoading: fetchCountriesLoading} = + useGetAllCountries(); + const params = useParams(); + const id = params?.id; + const [loading, setLoading] = useState(false); + + const { + data: singleUser, + isLoading, + error, + } = useGetSinglePatient(id?.toString() ?? ""); + + const {isPending, mutateAsync} = useUpdatePatient(); + const {data} = singleUser || {}; + + + + + return ( +
+
+ +
+ + افزودن بیمار جدید + + + مشاهده لیست بیماران + +
+
+ }> + {data && countries && ( + + )} + +
+ ); +} diff --git a/src/app/(dashboard)/patients/loading.tsx b/src/app/(dashboard)/patients/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/patients/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/patients/new/page.tsx b/src/app/(dashboard)/patients/new/page.tsx new file mode 100644 index 0000000..9ed670f --- /dev/null +++ b/src/app/(dashboard)/patients/new/page.tsx @@ -0,0 +1,32 @@ +"use client"; +import CreatePatientForm from "@/components/forms/patients/new/CreatePatientForm"; +import SectionTitle from "@/components/SectionTitle"; +import {useGetAllCountries} from "@/hooks/country"; +import Link from "next/link"; +import {useRouter} from "next/navigation"; +import React from "react"; + +export default function Page() { + const router = useRouter(); + const {data, isLoading} = useGetAllCountries(); + + return ( +
+
+ + + مشاهده لیست بیماران + +
+ + +
+ ); +} diff --git a/src/app/(dashboard)/patients/page.tsx b/src/app/(dashboard)/patients/page.tsx new file mode 100644 index 0000000..8e4b5a3 --- /dev/null +++ b/src/app/(dashboard)/patients/page.tsx @@ -0,0 +1,108 @@ +import FilterByisDeleted from "@/components/FilterByisDeleted"; +import Loader from "@/components/Loader"; +import PatientsTable from "@/components/PatientsTable"; +import RoleGuard from "@/components/RoleGuard"; +import SearchBox from "@/components/SearchBox"; +import {Field} from "@/components/ui/field"; +import {Label} from "@/components/ui/label"; +import UsersTableExport from "@/components/usersTableExport"; + +import {Plus} from "lucide-react"; +import Link from "next/link"; +import React, {Suspense} from "react"; + +export default function Page() { + return ( + <> +
+
+
+
+

+ جستجوی پیشرفته +

+
+ + + + + + + + + + + + + +
+
+ + {/* */} +
+ +
+ + + + افزودن بیمار جدید + + + + + +
+
+
+ }> + + +
+
+ + ); +} diff --git a/src/app/(dashboard)/patients/restore/page.tsx b/src/app/(dashboard)/patients/restore/page.tsx new file mode 100644 index 0000000..96a1431 --- /dev/null +++ b/src/app/(dashboard)/patients/restore/page.tsx @@ -0,0 +1,10 @@ +import RestorePatientTable from '@/components/RestorePatientTable' +import React from 'react' + +export default function Page() { + return ( +
+ +
+ ) +} diff --git a/src/app/(dashboard)/privacy-policy/page.tsx b/src/app/(dashboard)/privacy-policy/page.tsx new file mode 100644 index 0000000..e0facdb --- /dev/null +++ b/src/app/(dashboard)/privacy-policy/page.tsx @@ -0,0 +1,60 @@ +"use client"; +import Loader from "@/components/Loader"; +import {Button} from "@/components/ui/button"; +import { + useGetPrivacyPolicy, + useUpdatePrivacyPolicy, +} from "@/hooks/privacy-policy"; +import {handleAxiosError} from "@/lib/utils"; +import dynamic from "next/dynamic"; +import React, {Suspense, useEffect, useRef, useState} from "react"; +import {toast} from "react-toastify"; +const RichTextEditor = dynamic(() => import("@/components/TextEditor"), { + ssr: false, +}); + +type RichTextEditorHandle = { + getContent: () => string; +}; + +export default function Page() { + const editorRef = useRef(null); + const [editorContent, setEditorContent] = useState(""); + + const {mutateAsync} = useUpdatePrivacyPolicy(); + const {data, isLoading} = useGetPrivacyPolicy(); + const handleSave = async () => { + if (editorRef.current) { + const content = editorRef.current.getContent(); + setEditorContent(content); + + try { + const {message} = await mutateAsync(content); + toast.success(message); + } catch (error) { + toast.error(handleAxiosError(error)); + } + } + }; + + useEffect(() => { + console.log(data) + setEditorContent(data?.data?.content); + }, [isLoading, data]); + + return ( +
+

متن Privacy Policy

+
+ {(data?.data || !isLoading) && ( + }> + + + )} +
+
+ +
+
+ ); +} diff --git a/src/app/(dashboard)/tos/page.tsx b/src/app/(dashboard)/tos/page.tsx new file mode 100644 index 0000000..10d554a --- /dev/null +++ b/src/app/(dashboard)/tos/page.tsx @@ -0,0 +1,193 @@ +"use client"; +import CreateTosForm from "@/components/forms/tos/create/CreateTosForm"; +import UpdateTosForm from "@/components/forms/tos/update/UpdateTosForm"; +import Loader from "@/components/Loader"; +import SectionTitle from "@/components/SectionTitle"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { + useCreateTos, + useDeleteTos, + useGetAllTos, + useGetSingleTos, + useTosToggleActive, +} from "@/hooks/tos"; +import { handleAxiosError } from "@/lib/utils"; +import { useQueryClient } from "@tanstack/react-query"; +import { Plus, Trash } from "lucide-react"; +import { useRouter } from "next/navigation"; +import React, { Suspense, useState } from "react"; +import { toast } from "react-toastify"; + + + + +export default function Page() { + const router = useRouter(); + const [mode, setMode] = useState<"new" | "edit" | "form">("new"); + const [version, setVersion] = useState(""); + const { mutateAsync: createAsync, isPending: createPending } = useCreateTos(); + const queryClient = useQueryClient(); + + const { data: AllTos} = useGetAllTos(); + const { mutateAsync: toggleAsync, isPending: togglePending } = + useTosToggleActive(); + const { mutateAsync: deleteAsync, isPending: deletePending } = useDeleteTos(); + const { + mutateAsync: updateAsync, + isPending: singleTosPending, + data: preValues, + } = useGetSingleTos(); + + const handleGetSingleTos = async (version: string) => { + try { + await updateAsync(version); + } catch (error) { + toast.error("adassd"); + } + }; + + const handleToggleActive = async (version: string) => { + try { + const { message } = await toggleAsync(version); + await queryClient.invalidateQueries({ queryKey: ["get-all-tos"] }); + toast.success(message); + } catch (error) { + toast.error(handleAxiosError(error)); + } + }; + const handleDeleteTos = async (version: string) => { + try { + const { message } = await deleteAsync(version); + await queryClient.invalidateQueries({ queryKey: ["get-all-tos"] }); + toast.success(message); + } catch (error) { + toast.error(handleAxiosError(error)); + } + }; + return ( +
+
+ {mode === "new" && ( + + )} + {mode === "form" && ( + <> + + + )} + + {mode === "edit" && version && preValues?.data && ( + }> + + + )} +
+
+ +
+
+ {AllTos && + AllTos?.data?.length > 0 && + AllTos?.data?.map((item, index) => ( +
+
+ ردیف : + {index + 1} +
+
+ عنوان : + {item.title} +
+
+ ورژن : + + {item.version} + +
+
+
+ {item.version === version && mode === "edit" ? ( + + ) : ( + + )} +
+
+ {item.isActive ? ( + + فعال است + + ) : ( + + )} +
+
+ +
+
+
+ ))} +
+
+ ); +} diff --git a/src/app/(dashboard)/transfer-packages/new/page.tsx b/src/app/(dashboard)/transfer-packages/new/page.tsx new file mode 100644 index 0000000..3b545d0 --- /dev/null +++ b/src/app/(dashboard)/transfer-packages/new/page.tsx @@ -0,0 +1,28 @@ +"use client"; +import DenyAccess from "@/components/DenyAccess"; +import CreateTransferPackageForm from "@/components/forms/transfer-packages/new/CreateTransferPackageForm"; +import Loader from "@/components/Loader"; +import { useGetLanguages } from "@/hooks/languages"; +import React, { Suspense } from "react"; + +export default function Page() { + const { data } = useGetLanguages(); + return ( +
+ }> + {data ? ( + data?.data?.length > 0 ? ( + + ) : ( + + ) + ) : ( +
خطا در دریافت دیتای زبان ها
+ )} +
+
+ ); +} diff --git a/src/app/(dashboard)/transfer-packages/page.tsx b/src/app/(dashboard)/transfer-packages/page.tsx new file mode 100644 index 0000000..7072957 --- /dev/null +++ b/src/app/(dashboard)/transfer-packages/page.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +export default function Page() { + return ( +
+ +
+ ) +} diff --git a/src/app/(dashboard)/transfer-team/loading.tsx b/src/app/(dashboard)/transfer-team/loading.tsx new file mode 100644 index 0000000..a01d2c1 --- /dev/null +++ b/src/app/(dashboard)/transfer-team/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/(dashboard)/transfer-team/members/edit/[id]/page.tsx b/src/app/(dashboard)/transfer-team/members/edit/[id]/page.tsx new file mode 100644 index 0000000..f66111f --- /dev/null +++ b/src/app/(dashboard)/transfer-team/members/edit/[id]/page.tsx @@ -0,0 +1,67 @@ +"use client"; +import UpdateDoctorForm from "@/components/forms/doctor/update/UpdateDoctorForm"; +import Loader from "@/components/Loader"; +import SectionTitle from "@/components/SectionTitle"; +import { useGetAllExpertiseList } from "@/hooks/expertise"; +import { useGetLanguages } from "@/hooks/languages"; +import {useGetSingleUser, useUpdateUser} from "@/hooks/users"; + +import Link from "next/link"; +import {useParams, useRouter} from "next/navigation"; +import {Suspense, useState} from "react"; + + +export default function Page() { + const params = useParams(); + const id = params?.id; + const router = useRouter(); + const [loading] = useState(false); + const { + data: languages, + + } = useGetLanguages(); + const { + data: expertises, + + } = useGetAllExpertiseList(); + const { + data: singleUser, + + } = useGetSingleUser(id?.toString() ?? ""); + + const {mutateAsync} = useUpdateUser(); + const {data} = singleUser || {}; + return ( +
+
+ +
+ + افزودن عضو جدید + + + مشاهده لیست اعضاء تیم + +
+
+ }> + {data && expertises && languages && !loading && ( + + )} + +
+ ); +} diff --git a/src/app/(dashboard)/transfer-team/members/edit/page.tsx b/src/app/(dashboard)/transfer-team/members/edit/page.tsx new file mode 100644 index 0000000..18ed602 --- /dev/null +++ b/src/app/(dashboard)/transfer-team/members/edit/page.tsx @@ -0,0 +1,6 @@ +"use client"; +import {notFound} from "next/navigation"; + +export default function Page() { + return notFound(); +} diff --git a/src/app/(dashboard)/transfer-team/members/new/page.tsx b/src/app/(dashboard)/transfer-team/members/new/page.tsx new file mode 100644 index 0000000..b5f691a --- /dev/null +++ b/src/app/(dashboard)/transfer-team/members/new/page.tsx @@ -0,0 +1,105 @@ +"use client"; +import DenyAccess from "@/components/DenyAccess"; +import CreateTransferTeamMember from "@/components/forms/transfer-team/member/new/CreateTransferTeamMemberForm"; +import Loader from "@/components/Loader"; +import SectionTitle from "@/components/SectionTitle"; +import {API_URL} from "@/constants"; +import {Expertise, Language} from "@/types"; +import Link from "next/link"; +import {useRouter} from "next/navigation"; +import {Suspense, useEffect, useState} from "react"; + +async function fetchLanguages() { + const res = await fetch(`${API_URL}/language/get/all`,{cache:"no-cache"}); + + if (!res.ok && res.status==500) { + throw new Error("Failed to get data"); + } + + if(!res.ok && res.status==404){ + return [] + } + + const data = await res.json(); + + return data; +} +async function fetchExpertise() { + const res = await fetch(`${API_URL}/expertise/fa/get/all/list`,{cache:"no-cache"}); + + if (!res.ok && res.status==500) { + throw new Error("Failed to get data"); + } + + if(!res.ok && res.status==404){ + return [] + } + const data = await res.json(); + + return data; +} + +export default function Page() { + const router = useRouter(); + const [loading, setLoading] = useState(false); + const [data, setData] = useState([]); + + const [expertises, setExpertises] = useState([]); + useEffect(() => { + let active = true; + + setLoading(true); + fetchExpertise() + .then((res) => { + if (!active) return; + setExpertises(res.data); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, []); + useEffect(() => { + let active = true; + + setLoading(true); + fetchLanguages() + .then((res) => { + if (!active) return; + setData(res.data); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, []); + + if (loading) { + return ; + } + return ( +
+
+ + + مشاهده لیست اعضا + +
+ }> + {data?.length > 0 ? expertises?.length > 0 ? : : } + + +
+ ); +} diff --git a/src/app/(dashboard)/transfer-team/members/page.tsx b/src/app/(dashboard)/transfer-team/members/page.tsx new file mode 100644 index 0000000..e293c92 --- /dev/null +++ b/src/app/(dashboard)/transfer-team/members/page.tsx @@ -0,0 +1,49 @@ + +import Loader from "@/components/Loader"; +import RoleGuard from "@/components/RoleGuard"; +import SearchBox from "@/components/SearchBox"; +import TransferTeamTable from "@/components/TransferTeamTable"; +import UsersTableExport from "@/components/usersTableExport"; + +import {Plus} from "lucide-react"; +import Link from "next/link"; +import React, {Suspense} from "react"; + +export default function Page() { + return ( + <> +
+
+
+ +
+
+ + + + افزودن عضو جدید + + + + + +
+
+
+ }> + + +
+
+ + ); +} diff --git a/src/app/(dashboard)/transfer-team/teams/new/page.tsx b/src/app/(dashboard)/transfer-team/teams/new/page.tsx new file mode 100644 index 0000000..4602537 --- /dev/null +++ b/src/app/(dashboard)/transfer-team/teams/new/page.tsx @@ -0,0 +1,41 @@ +"use client"; +import CreateTransferTeamForm from "@/components/forms/transfer-team/team/new/CreateTransferTeamForm"; +import Loader from "@/components/Loader"; +import SectionTitle from "@/components/SectionTitle"; +import {useCreateTransferTeam, useGetAllTransferTeamAllMembers} from "@/hooks/transfer-team"; +import Link from "next/link"; +import {useRouter} from "next/navigation"; +import React, {Suspense} from "react"; + +export default function Page() { + const {data: members, isLoading: fetchMembersLoading} = + useGetAllTransferTeamAllMembers(); + const {mutateAsync,isPending}=useCreateTransferTeam() + const router = useRouter(); + return ( +
+
+ + + مشاهده لیست تیم ها + +
+ }> + {members && ( + + )} + +
+ ); +} diff --git a/src/app/(dashboard)/transfer-team/teams/page.tsx b/src/app/(dashboard)/transfer-team/teams/page.tsx new file mode 100644 index 0000000..7219257 --- /dev/null +++ b/src/app/(dashboard)/transfer-team/teams/page.tsx @@ -0,0 +1,38 @@ +"use client"; +import CreateTransferTeamForm from "@/components/forms/transfer-team/team/new/CreateTransferTeamForm"; +import Loader from "@/components/Loader"; +import SectionTitle from "@/components/SectionTitle"; +import {useGetAllTransferTeamAllMembers} from "@/hooks/transfer-team"; +import Link from "next/link"; +import {useRouter} from "next/navigation"; +import React, {Suspense} from "react"; + +export default function Page() { + const {data: members, isLoading: fetchMembersLoading} = + useGetAllTransferTeamAllMembers(); + const router = useRouter(); + return ( +
+
+ + + مشاهده لیست تیم ها + +
+ }> + {members && ( + + )} + +
+ ); +} diff --git a/src/app/error.tsx b/src/app/error.tsx new file mode 100644 index 0000000..155024c --- /dev/null +++ b/src/app/error.tsx @@ -0,0 +1,17 @@ +"use client" +import Link from "next/link"; + +export default function ErrorPage() { + return ( +
+

500

+

خطای سرور رخ داده است.

+ + بازگشت به صفحه اصلی + +
+ ); +} diff --git a/src/app/globals.css b/src/app/globals.css index a2dc41e..56f9d95 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,26 +1,147 @@ @import "tailwindcss"; +@import "tw-animate-css"; -:root { - --background: #ffffff; - --foreground: #171717; -} +@custom-variant dark (&:is(.dark *)); @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); --font-sans: var(--font-geist-sans); --font-mono: var(--font-geist-mono); + --color-sidebar-ring: var(--sidebar-ring); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar: var(--sidebar); + --color-chart-5: var(--chart-5); + --color-chart-4: var(--chart-4); + --color-chart-3: var(--chart-3); + --color-chart-2: var(--chart-2); + --color-chart-1: var(--chart-1); + --color-ring: var(--ring); + --color-input: var(--input); + --color-border: var(--border); + --color-destructive: var(--destructive); + --color-accent-foreground: var(--accent-foreground); + --color-accent: var(--accent); + --color-muted-foreground: var(--muted-foreground); + --color-muted: var(--muted); + --color-secondary-foreground: var(--secondary-foreground); + --color-secondary: var(--secondary); + --color-primary-foreground: var(--primary-foreground); + --color-primary: var(--primary); + --color-popover-foreground: var(--popover-foreground); + --color-popover: var(--popover); + --color-card-foreground: var(--card-foreground); + --color-card: var(--card); + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --radius-2xl: calc(var(--radius) + 8px); + --radius-3xl: calc(var(--radius) + 12px); + --radius-4xl: calc(var(--radius) + 16px); + --font-size-content: calc(var(--rem-size-2) * 1rem); } -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; +:root { + --radius: 0.625rem; + --background: #f6f6f6; + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.32 0.16 255); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); + --toastify-font-family: VazirMatn, var(--font-vazir); + --panel-width: 120px; + --panel-width-padding: 140px; +} + +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.205 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.205 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.922 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.556 0 0); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.556 0 0); +} + +@layer base { + * { + @apply border-border outline-ring/50 font-normal; + } + body { + @apply bg-background text-foreground; + } + button:not(:disabled), + [role="button"]:not(:disabled) { + cursor: pointer; } } body { - background: var(--background); - color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; + font-family: VazirMatn, Arial, Helvetica, sans-serif; + scroll-behavior: smooth; +} +.custom-toast { + font-family: VazirMatn, sans-serif; /* فونت فارسی دلخواه */ + font-size: 16px; +} +.ql-editor { + font-family: VazirMatn, sans-serif !important; + font-size: 16px; + line-height: 1.6; } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index f7fa87e..a42ca12 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,19 +1,10 @@ -import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; +import type {Metadata} from "next"; import "./globals.css"; - -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], -}); - -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], -}); +import {FontVazir} from "@/config/font.config"; +import {ToastContainer} from "react-toastify"; export const metadata: Metadata = { - title: "Create Next App", + title: "پنل مدیریت وب سایت بیماران بین الملل", description: "Generated by create next app", }; @@ -23,11 +14,22 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - + {children} + ); diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx new file mode 100644 index 0000000..1b9066c --- /dev/null +++ b/src/app/not-found.tsx @@ -0,0 +1,16 @@ +import Link from "next/link"; + +export default function NotFoundPage() { + return ( +
+

404

+

صفحه‌ای که دنبال آن هستید پیدا نشد.

+ + بازگشت به صفحه اصلی + +
+ ); +} diff --git a/src/app/page.tsx b/src/app/page.tsx index a932894..c946d54 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,103 +1,47 @@ +import { LogIn } from "lucide-react"; import Image from "next/image"; +import Link from "next/link"; export default function Home() { return (
-
+
Next.js logo -
    -
  1. - Get started by editing{" "} - - src/app/page.tsx - - . -
  2. -
  3. - Save and see your changes instantly. -
  4. -
+

+ پنل مدیریت سایت بیماران بین الملل +

+ {/*

+ یکی از دکمه های زیر را فشار دهید +

*/}
- +
); } diff --git a/src/components/AuthGuard.tsx b/src/components/AuthGuard.tsx new file mode 100644 index 0000000..7e0369d --- /dev/null +++ b/src/components/AuthGuard.tsx @@ -0,0 +1,27 @@ +"use client"; + +import {useMe} from "@/hooks"; +import Loader from "./Loader"; + +export default function AuthGuard({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + const {isLoading} = useMe(); + + + + if (isLoading) + return ( +
+
+ لطفا منتظر بمانید + + + +
+
+ ); + return children; +} diff --git a/src/components/CalendarHijri.tsx b/src/components/CalendarHijri.tsx new file mode 100644 index 0000000..d0601d3 --- /dev/null +++ b/src/components/CalendarHijri.tsx @@ -0,0 +1,49 @@ +"use client"; + +import * as React from "react"; +import {ChevronDownIcon} from "lucide-react"; + +import {Button} from "@/components/ui/button"; +import {Popover, PopoverContent, PopoverTrigger} from "@/components/ui/popover"; +import {CalendarHijriBase} from "./ui/calendar-hijri"; + +export function CalendarHijri({ + date, + setDate, +}: { + date: Date | undefined; + setDate: React.Dispatch>; +}) { + const [open, setOpen] = React.useState(false); + + return ( +
+ + + + + + { + setDate(date); + setOpen(false); + }} + /> + + +
+ ); +} diff --git a/src/components/CalendarNormal.tsx b/src/components/CalendarNormal.tsx new file mode 100644 index 0000000..4900033 --- /dev/null +++ b/src/components/CalendarNormal.tsx @@ -0,0 +1,49 @@ +"use client"; + +import * as React from "react"; +import {ChevronDownIcon} from "lucide-react"; + +import {Button} from "@/components/ui/button"; +import {Calendar} from "@/components/ui/calendar"; +import {Popover, PopoverContent, PopoverTrigger} from "@/components/ui/popover"; + +export function CalendarNormal({ + date, + setDate, +}: { + date: Date | undefined; + setDate: React.Dispatch>; +}) { + const [open, setOpen] = React.useState(false); + + return ( +
+ + + + + + { + setDate(date); + setOpen(false); + }} + /> + + +
+ ); +} diff --git a/src/components/DashboardCDNServerStatus.tsx b/src/components/DashboardCDNServerStatus.tsx new file mode 100644 index 0000000..0763202 --- /dev/null +++ b/src/components/DashboardCDNServerStatus.tsx @@ -0,0 +1,184 @@ +import {API_CDN_URL} from "@/constants"; +import {formatSystemForUI} from "@/lib/utils"; +import React from "react"; +import SectionTitle from "./SectionTitle"; +import Link from "next/link"; +import { Logs } from "lucide-react"; + +async function getCDNStatus() { + try { + const res = await fetch(`${API_CDN_URL}/status`, { + method: "GET", + credentials: "include", + }); + + if (!res.ok) { + const errorData = await res.json().catch(() => null); + + return { + status: "SERVICE_ERROR", + message: errorData?.message || "سرویس با خطا پاسخ داد", + system: null, + }; + } + + const data = await res.json(); + return { + status: "OK", + message: data.message, + system: data.system, + }; + } catch { + return { + status: "DOWN", + message: "سرویس پاسخگو نیست", + system: null, + }; + } +} + +export default async function DashboardCDNServerStatus() { + const data = await getCDNStatus(); + + const {status, message, system} = data || {}; + + const uiSystem = system ? formatSystemForUI(system) : null; + return ( +
+ <> +
+ +
+
+ وضعیت +
+ + + + + + {message} ({status}) + +
+
+ + {uiSystem && ( + <> +
+ +
+
+
+ uptime +
+ {uiSystem.uptime} +
+
+ +
+ pid +
+ {uiSystem.pid} +
+
+ +
+ node version +
+ + {uiSystem.nodeVersion} + +
+
+ +
+ heap used +
+ + {uiSystem.heapUsed} + +
+
+ +
+ heap total +
+ + {uiSystem.heapTotal} + +
+
+ +
+ rss +
+ {uiSystem.rss} +
+
+ +
+ cpu user +
+ + {uiSystem.cpuUser} + +
+
+ +
+ cpu system +
+ + {uiSystem.cpuSystem} + +
+
+ +
+ + event loop utilization + +
+ + {uiSystem.eventLoopUtil} + +
+
+ +
+ free memory +
+ + {uiSystem.freeMemory} + +
+
+ +
+ total memory +
+ + {uiSystem.totalMemory} + +
+
+
+
+ + + مشاهده لاگ ها + +
+ + )} +
+ ); +} diff --git a/src/components/DashboardStatistics.tsx b/src/components/DashboardStatistics.tsx new file mode 100644 index 0000000..5c540e2 --- /dev/null +++ b/src/components/DashboardStatistics.tsx @@ -0,0 +1,136 @@ +import React from "react"; +import SectionTitle from "./SectionTitle"; +import {API_URL} from "@/constants"; +import {cookies} from "next/headers"; +export interface DashboardCounts { + department: { + members: number; + }; + patients: number; + onlineCases: { + completed: number; + pending: number; + }; + staff: { + coordinators: number; + admins: number; + doctors: number; + }; +} + +async function getData() { + try { + const res = await fetch(`${API_URL}/statistics/data`, { + method: "GET", + credentials: "include", + cache: "no-cache", + headers: { + Cookie: (await cookies()).toString(), + }, + }); + + const data = await res.json(); + return data; + } catch { + // throw new Error("failed to get data"); + return {} + } +} +export default async function DashboardStatistics() { + const fetchedData = await getData(); + const {data} = fetchedData || {}; + return ( + <> +
+
+ +
+ {data?.department && ( + <> +
+ اعضای دپارتمان + + {Number(data?.department?.members).toLocaleString("fa-IR")} + +
+
+ پزشکان دپارتمان + + {Number(data?.department?.doctors).toLocaleString("fa-IR")} + +
+ + )} + +
+
+
+ +
+ {data?.staff && ( + <> +
+ کارشناسان سایت + + {Number(data?.staff?.coordinators).toLocaleString("fa-IR")} + +
+
+ ادمین های سایت + + {Number(data?.staff?.admins).toLocaleString("fa-IR")} + +
+
+ پزشکان سایت + + {Number(data?.staff?.doctors).toLocaleString("fa-IR")} + +
+ + )} +
+
+
+ +
+ + {data?.patients && ( +
+ تعداد کل بیماران + + {Number(data?.patients?.numbers).toLocaleString("fa-IR")} + +
+ )} + {data?.onlineCases && ( + <> +
+ + {" "} + پذیرش های کامل شده + + + {Number(data?.onlineCases?.completed).toLocaleString( + "fa-IR" + )} + +
+
+ + {" "} + پذیرش های درحال انجام + + + {Number(data?.onlineCases?.pending).toLocaleString("fa-IR")} + +
+ + )} + +
+
+
+ + ); +} diff --git a/src/components/DeleteExpertiseButton.tsx b/src/components/DeleteExpertiseButton.tsx new file mode 100644 index 0000000..dc58167 --- /dev/null +++ b/src/components/DeleteExpertiseButton.tsx @@ -0,0 +1,67 @@ +"use client"; +import React from "react"; +import {Button} from "./ui/button"; +import {Trash} from "lucide-react"; +import privateApi from "@/service/http/privateCall.axios"; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "./ui/dialog"; +import {toast} from "react-toastify"; +import {handleAxiosError} from "@/lib/utils"; +import { ServerResponseObject } from "@/types"; + +async function deleteUser(id: number | string, route: string) { + try { + const {message} = await privateApi.delete(`/${route}/delete/${id}`) as ServerResponseObject; + toast.success(message); + } catch (error) { + toast.error(handleAxiosError(error)); + } +} +export default function DeleteExpertiseButton({ + id, + route, +}: { + id: number | string; + route: string; +}) { + + const handleDelete = async () => { + await deleteUser(id, route); + }; + return ( + <> + + + + + + + حذف آیتم + + آیا از حذف این آیتم اطمینان دارد ؟ + + + + + + + + + + + + + ); +} diff --git a/src/components/DeleteFileButton.tsx b/src/components/DeleteFileButton.tsx new file mode 100644 index 0000000..2d8473d --- /dev/null +++ b/src/components/DeleteFileButton.tsx @@ -0,0 +1,40 @@ +"use client"; +import React from "react"; +import {Button} from "./ui/button"; +import {Trash} from "lucide-react"; +import {useDeleteFile} from "@/hooks"; +import {handleAxiosError} from "@/lib/utils"; +import {toast} from "react-toastify"; + +export default function DeleteFileButton({ + type, + fileKey, + fileUrl, +}: { + type: "image" | "document"; + fileKey: string; + fileUrl: string; +}) { + const {mutateAsync} = useDeleteFile(); + + const handleDeleteThumbnail = async () => { + try { + const {message} = await mutateAsync({fileKey, fileUrl, type}); + toast.success(message); + } catch (error) { + toast.error(handleAxiosError(error)); + } + }; + return ( + <> + + + ); +} diff --git a/src/components/DeleteLanguageButton.tsx b/src/components/DeleteLanguageButton.tsx new file mode 100644 index 0000000..50f1fb8 --- /dev/null +++ b/src/components/DeleteLanguageButton.tsx @@ -0,0 +1,69 @@ +"use client"; +import React from "react"; +import {Button} from "./ui/button"; +import {Trash} from "lucide-react"; +import privateApi from "@/service/http/privateCall.axios"; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "./ui/dialog"; +import {useQueryClient} from "@tanstack/react-query"; +import {toast} from "react-toastify"; +import {handleAxiosError} from "@/lib/utils"; +import { ServerResponseObject } from "@/types"; + +async function deleteUser(id: number | string, route: string) { + try { + const {message} = await privateApi.delete(`/${route}/delete/${id}`) as ServerResponseObject; + toast.success(message); + } catch (error) { + toast.error(handleAxiosError(error)); + } +} +export default function DeleteLanguageButton({ + id, + route, +}: { + id: number | string; + route: string; +}) { + const queryClient = useQueryClient(); + const handleDelete = async () => { + await deleteUser(id, route); + queryClient.invalidateQueries({queryKey: ["get-all-languages"]}); + }; + return ( + <> + + + + + + + حذف آیتم + + آیا از حذف این آیتم اطمینان دارد ؟ + + + + + + + + + + + + + ); +} diff --git a/src/components/DeleteMedicalPackageButton.tsx b/src/components/DeleteMedicalPackageButton.tsx new file mode 100644 index 0000000..2dfe2c2 --- /dev/null +++ b/src/components/DeleteMedicalPackageButton.tsx @@ -0,0 +1,69 @@ +"use client"; +import React from "react"; +import {Button} from "./ui/button"; +import {Trash} from "lucide-react"; +import privateApi from "@/service/http/privateCall.axios"; +import {usePathname} from "next/navigation"; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "./ui/dialog"; +import {toast} from "react-toastify"; +import {handleAxiosError} from "@/lib/utils"; +import { ServerResponseObject } from "@/types"; + +async function deleteMedicalPackage(id: number | string, route: string) { + try { + const {message} = await privateApi.delete(`/${route}/delete/${id}`) as ServerResponseObject; + toast.success(message); + } catch (error) { + toast.error(handleAxiosError(error)); + } +} +export default function DeleteMedicalPackageButton({ + id, + route, +}: { + id: number | string; + route: string; +}) { + const pathname = usePathname(); + const handleDelete = async () => { + await deleteMedicalPackage(id, route); + window.location.pathname = pathname; + }; + return ( + <> + + + + + + + حذف آیتم + + آیا از حذف این آیتم اطمینان دارد ؟ + + + + + + + + + + + + + ); +} diff --git a/src/components/DenyAccess.tsx b/src/components/DenyAccess.tsx new file mode 100644 index 0000000..c927570 --- /dev/null +++ b/src/components/DenyAccess.tsx @@ -0,0 +1,8 @@ +import Link from 'next/link' +import React from 'react' + +export default function DenyAccess({label,link}:{label:string,link:string}) { + return ( +
شما نمیتوانید از این بخش استفاده کنید. ابتدا می بایست حداقل یک {label} ایجاد کنید. برای ایجاد روی   لینک   کلیک کنید
+ ) +} diff --git a/src/components/DepartmentMembersTable.tsx b/src/components/DepartmentMembersTable.tsx new file mode 100644 index 0000000..37a2575 --- /dev/null +++ b/src/components/DepartmentMembersTable.tsx @@ -0,0 +1,260 @@ +"use client"; + +import * as React from "react"; +import { + Pagination, + PaginationContent, + PaginationItem, + PaginationLink, + PaginationNext, + PaginationPrevious, +} from "@/components/ui/pagination"; +import {API_URL} from "@/constants"; +import Loader from "./Loader"; +import {useSearchParams} from "next/navigation"; +import {Pencil} from "lucide-react"; +import DeleteUserButton from "./deleteUserButton"; +import Link from "next/link"; +import RoleGuard from "./RoleGuard"; + +// ===================== +// Types +// ===================== + +export type ApiResponse = { + status: number; + message: string; + data: { + data: T[]; + page: string; + limit: string; + total: number; + totalPages: number; + hasNext: boolean; + hasPrev: boolean; + }; +}; +type Translation = { + displayName: string; + lang: string; +}; + +type Expertise = { + slug: string; + translations: Translation[]; +}; + +type UserTranslation = { + firstName: string; + lastName: string; + lang: string; + position: string; +}; + +export type Data = { + id: number; + email: string; + phone: string; + slug: string; + image: string | null; + translations: UserTranslation[]; + expertise: Expertise; +}; +async function fetchData( + page: number, + pageSize: number, + queries?: string, +): Promise> { + const res = await fetch( + `${API_URL}/user/get/all?t=department&lang=fa&page=${page}&limit=${pageSize}${ + queries ? `&${queries}` : "" + }`, + { + cache: "no-store", + credentials: "include", + }, + ); + + if (!res.ok) { + throw new Error("Failed to fetch data"); + } + + return res.json(); +} +export default function DepartmentMembersTable() { + const [page, setPage] = React.useState(1); + const [pageSize] = React.useState(20); + const [data, setData] = React.useState([]); + const [total, setTotal] = React.useState(0); + const [loading, setLoading] = React.useState(false); + + const searchParams = useSearchParams(); + const totalPages = Math.ceil(total / pageSize); + + React.useEffect(() => { + let active = true; + + setLoading(true); + fetchData(page, pageSize, searchParams.toString()) + .then((res) => { + if (!active) return; + setData(res.data?.data); + setTotal(res.data?.total); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, [page, pageSize, searchParams]); + if (loading) { + return ( +
+ +
+ ); + } + return ( + <> +
+
+ + + + + + + + + + + + + + + {data.map((post) => ( + + + + + + + + + + + + + ))} + +
+ نام + + نام خانوادگی + + سمت + + تخصص + + ایمیل + + موبایل + + اکشن ها +
+ + نام + + {post?.translations[0]?.firstName} + + + نام خانوادگی + + {post?.translations[0]?.lastName} + + + سمت + + {post.translations[0]?.position} + + + تخصص + + {post?.expertise?.translations[0]?.displayName} + + + ایمیل + + {post.email} + + + موبایل + + {post?.phone.toString().toLocaleLowerCase("fa-IR")} + + + اکشن ها + +
+ + + + + + +
+
+
+ {total > 0 && ( + + + + setPage((p) => Math.max(1, p - 1))} + className={ + page === 1 + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + {Array.from({length: totalPages}).map((_, i) => { + const pageNumber = i + 1; + return ( + + setPage(pageNumber)} + className="cursor-pointer" + > + {pageNumber} + + + ); + })} + + + setPage((p) => Math.min(totalPages, p + 1))} + className={ + page === totalPages + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + + )} + + ); +} diff --git a/src/components/DoctorsTable.tsx b/src/components/DoctorsTable.tsx new file mode 100644 index 0000000..daf3272 --- /dev/null +++ b/src/components/DoctorsTable.tsx @@ -0,0 +1,261 @@ +"use client"; + +import * as React from "react"; +import { + Pagination, + PaginationContent, + PaginationItem, + PaginationLink, + PaginationNext, + PaginationPrevious, +} from "@/components/ui/pagination"; +import {API_URL} from "@/constants"; +import Loader from "./Loader"; +import {useRouter, useSearchParams} from "next/navigation"; +import {Pencil} from "lucide-react"; +import DeleteUserButton from "./deleteUserButton"; +import Link from "next/link"; +import RoleGuard from "./RoleGuard"; + +export type ApiResponse = { + status: number; + message: string; + data: { + data: T[]; + page: string; + limit: string; + total: number; + totalPages: number; + hasNext: boolean; + hasPrev: boolean; + }; +}; +type Translation = { + displayName: string; + lang: string; +}; + +type Expertise = { + slug: string; + translations: Translation[]; +}; + +type UserTranslation = { + firstName: string; + lastName: string; + lang: string; + position: string; +}; + +export type Data = { + id: number; + email: string; + phone: string; + slug: string; + image: string | null; + translations: UserTranslation[]; + expertise: Expertise; +}; +async function fetchData( + page: number, + pageSize: number, + queries?: string, +): Promise> { + console.log("doctors table"); + + const res = await fetch( + `${API_URL}/user/get/all?t=doctor&lang=fa&page=${page}&limit=${pageSize}${ + queries ? `&${queries}` : "" + }`, + { + cache: "no-store", + credentials: "include", + }, + ); + + if (!res.ok) { + throw new Error("Failed to fetch data"); + } + + return res.json(); +} +export default function DoctorsTable() { + const [page, setPage] = React.useState(1); + const [pageSize] = React.useState(20); + const [data, setData] = React.useState([]); + const [total, setTotal] = React.useState(0); + const [loading, setLoading] = React.useState(false); + + const searchParams = useSearchParams(); + const totalPages = Math.ceil(total / pageSize); + + const router = useRouter(); + React.useEffect(() => { + let active = true; + + setLoading(true); + fetchData(page, pageSize, searchParams.toString()) + .then((res) => { + if (!active) return; + setData(res.data?.data); + setTotal(res.data?.total); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, [page, pageSize, searchParams]); + if (loading) { + return ( +
+ +
+ ); + } + return ( + <> +
+
+ + + + + + + + + + + + + + + {data.map((post) => ( + + + + + + + + + + + + + ))} + +
+ نام + + نام خانوادگی + + سمت + + تخصص + + ایمیل + + موبایل + + اکشن ها +
+ + نام + + {post?.translations[0]?.firstName} + + + نام خانوادگی + + {post?.translations[0]?.lastName} + + + سمت + + {post.translations[0]?.position} + + + تخصص + + {post?.expertise?.translations[0]?.displayName} + + + ایمیل + + {post.email} + + + موبایل + + {post?.phone.toString().toLocaleLowerCase("fa-IR")} + + + اکشن ها + +
+ + + + + + + + +
+
+
+ {total > 0 && ( + + + + setPage((p) => Math.max(1, p - 1))} + className={ + page === 1 + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + {Array.from({length: totalPages}).map((_, i) => { + const pageNumber = i + 1; + return ( + + setPage(pageNumber)} + className="cursor-pointer" + > + {pageNumber} + + + ); + })} + + + setPage((p) => Math.min(totalPages, p + 1))} + className={ + page === totalPages + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + + )} + + ); +} diff --git a/src/components/ExpertiseFilterBox.tsx b/src/components/ExpertiseFilterBox.tsx new file mode 100644 index 0000000..eadb935 --- /dev/null +++ b/src/components/ExpertiseFilterBox.tsx @@ -0,0 +1,94 @@ +"use client"; +import React from "react"; +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectTrigger, + SelectValue, +} from "./ui/select"; +import {useRouter, useSearchParams} from "next/navigation"; +import {API_URL} from "@/constants"; +import Loader from "./Loader"; + +interface Data { + id: number; + slug: string; + translations: { + id: number; + displayName: string; + lang: string; + }[]; +} +async function fetchData() { + console.log('filters box') + const res = await fetch(`${API_URL}/expertise/fa/get/all/list?lang=fa`, { + cache: "no-store", + credentials: "include", + }); + + if (!res.ok) { + + throw new Error("Failed to fetch data"); + } + + const data = await res.json(); + return data; +} + +export default function ExpertiseFilterBox() { + const urlSearchParams = useSearchParams(); + const [data, setData] = React.useState([]); + const [loading, setLoading] = React.useState(false); + + const searchParams = new URLSearchParams(urlSearchParams); + const router = useRouter(); + + React.useEffect(() => { + let active = true; + + setLoading(true); + fetchData() + .then((res) => { + if (!active) return; + setData(res.data); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, []); + const handleFilter = (value: string) => { + searchParams.set("e", value); + router.push(`/doctors${searchParams ? `?${searchParams.toString()}` : ""}`); + }; + + if (loading) { + return ( +
+ +
+ ); + } + return ( + <> + + + ); +} diff --git a/src/components/ExpertiseTable.tsx b/src/components/ExpertiseTable.tsx new file mode 100644 index 0000000..1b05f34 --- /dev/null +++ b/src/components/ExpertiseTable.tsx @@ -0,0 +1,234 @@ +"use client"; + +import * as React from "react"; +import { + Pagination, + PaginationContent, + PaginationItem, + PaginationLink, + PaginationNext, + PaginationPrevious, +} from "@/components/ui/pagination"; +import {API_URL} from "@/constants"; +import Loader from "./Loader"; +import {useSearchParams} from "next/navigation"; +import {Pencil} from "lucide-react"; +import Link from "next/link"; +import RoleGuard from "./RoleGuard"; +import DeleteExpertiseButton from "./DeleteExpertiseButton"; + +export type ApiResponse = { + status: number; + message: string; + data: { + data: T[]; + page: string; + limit: string; + total: number; + totalPages: number; + hasNext: boolean; + hasPrev: boolean; + }; +}; + + + + + + +export type Data = { + slug: string; + id: number; + translations: { + displayName: string | null; + lang: { + title: string; + } | null; + }[]; +}; +async function fetchData( + lang: string, + page: number, + pageSize: number, + queries?: string, +): Promise> { + console.log("doctors table"); + + const res = await fetch( + `${API_URL}/expertise/${ + lang ?? "fa" + }/get/all?page=${page}&limit=${pageSize}${queries ? `&${queries}` : ""}`, + { + cache: "no-store", + credentials: "include", + }, + ); + + if (!res.ok) { + throw new Error("Failed to fetch data"); + } + + return await res.json(); +} +export default function ExpertiseTable({lang}: {lang: string}) { + const [page, setPage] = React.useState(1); + const [pageSize] = React.useState(20); + const [data, setData] = React.useState([]); + const [total, setTotal] = React.useState(0); + const [loading, setLoading] = React.useState(false); + + const searchParams = useSearchParams(); + const totalPages = Math.ceil(total / pageSize); + + React.useEffect(() => { + let active = true; + + setLoading(true); + fetchData(lang, page, pageSize, searchParams.toString()) + .then((res) => { + if (!active) return; + console.log(res.data); + setData(res.data?.data); + setTotal(res.data?.total); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, [page, pageSize, searchParams, lang]); + if (loading) { + return ( +
+ +
+ ); + } + return ( + <> +
+
+ + + + + + + + + + + + + + {data.map((post, index) => ( + + + + + + + + + + ))} + +
+ ردیف + + اسلاگ + + نام + + نام زبان + + اکشن ها +
+ + ردیف + + {index + 1} + + + اسلاگ + + {post?.slug} + + + نام + + {post?.translations[0]?.displayName} + + + نام زبان + + {post?.translations[0]?.lang?.title} + + + اکشن ها + +
+ + + + + + + + +
+
+
+ {total > 0 && ( + + + + setPage((p) => Math.max(1, p - 1))} + className={ + page === 1 + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + {Array.from({length: totalPages}).map((_, i) => { + const pageNumber = i + 1; + return ( + + setPage(pageNumber)} + className="cursor-pointer" + > + {pageNumber} + + + ); + })} + + + setPage((p) => Math.min(totalPages, p + 1))} + className={ + page === totalPages + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + + )} + + ); +} diff --git a/src/components/FeatureIcon.tsx b/src/components/FeatureIcon.tsx new file mode 100644 index 0000000..ccead37 --- /dev/null +++ b/src/components/FeatureIcon.tsx @@ -0,0 +1,30 @@ +import * as Icons from "lucide-react"; + +interface FeatureIconProps extends Icons.LucideProps { + iconName?: string; + label?: string; + hasLabel:boolean +} + +export const FeatureIcon: React.FC = ({ + iconName, + label, + hasLabel=true, + ...props +}) => { + const LucideIcon = + iconName && iconName in Icons + ? (Icons[ + iconName as keyof typeof Icons + ] as React.ComponentType) + : null; + + return ( +
+ {LucideIcon && } + {hasLabel && {label}} +
+ ); +}; + +export default FeatureIcon; diff --git a/src/components/FilterByisDeleted.tsx b/src/components/FilterByisDeleted.tsx new file mode 100644 index 0000000..4990e38 --- /dev/null +++ b/src/components/FilterByisDeleted.tsx @@ -0,0 +1,45 @@ +"use client"; +import React from "react"; +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectTrigger, + SelectValue, +} from "./ui/select"; +import {useRouter, useSearchParams} from "next/navigation"; + +export default function FilterByisDeleted() { + const urlSearchParams = useSearchParams(); + + const searchParams = new URLSearchParams(urlSearchParams); + const router = useRouter(); + + const handleFilter = (value: string) => { + if (value === "true") { + searchParams.set("is_deleted", value); + }else{ + searchParams.delete("is_deleted"); + } + router.push( + `/patients${searchParams ? `?${searchParams.toString()}` : ""}` + ); + }; + + return ( + <> + + + ); +} diff --git a/src/components/LangaugesTable.tsx b/src/components/LangaugesTable.tsx new file mode 100644 index 0000000..eac20ca --- /dev/null +++ b/src/components/LangaugesTable.tsx @@ -0,0 +1,165 @@ +"use client"; + +import * as React from "react"; +import { + Pagination, + PaginationContent, + PaginationItem, + PaginationLink, + PaginationNext, + PaginationPrevious, +} from "@/components/ui/pagination"; +import Loader from "./Loader"; +import {useRouter} from "next/navigation"; + +import RoleGuard from "./RoleGuard"; +import DeleteLanguageButton from "./DeleteLanguageButton"; +import {useGetLanguages, useUpdateLanguage} from "@/hooks/languages"; +import {Dialog} from "./ui/dialog"; +import UpdateLanguageForm from "./forms/languages/update/UpdateLanguageForm"; +import { useQueryClient } from "@tanstack/react-query"; + +export type ApiResponse = { + status: number; + message: string; + data: T[]; + +}; + +export type Data = { + id: number; + title: string; + slug: string; +}; + +export default function LanguagesTable() { + const [page, setPage] = React.useState(1); + const [pageSize] = React.useState(20); + const {data, isLoading} = useGetLanguages(); + const [total] = React.useState(0); + const {mutateAsync, isPending} = useUpdateLanguage(); + const totalPages = Math.ceil(total / pageSize); + const queryClient = useQueryClient(); + const router = useRouter(); + + const languages = data ? (data?.data as Data[]) : []; + if (isLoading) { + return ( +
+ +
+ ); + } + return ( + <> +
+
+ + + + + + + + + + + + {languages?.map((post) => ( + + + + + + + + ))} + +
+ عنوان + + اسلاگ + + اکشن ها +
+ + عنوان + + {post?.title} + + + اسلاگ + + {post?.slug} + + + اکشن ها + +
+ + + + + + + + +
+
+
+ {total > 0 && ( + + + + setPage((p) => Math.max(1, p - 1))} + className={ + page === 1 + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + {Array.from({length: totalPages}).map((_, i) => { + const pageNumber = i + 1; + return ( + + setPage(pageNumber)} + className="cursor-pointer" + > + {pageNumber} + + + ); + })} + + + setPage((p) => Math.min(totalPages, p + 1))} + className={ + page === totalPages + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + + )} + + ); +} diff --git a/src/components/LanguagesFilterBox.tsx b/src/components/LanguagesFilterBox.tsx new file mode 100644 index 0000000..4e5ad4a --- /dev/null +++ b/src/components/LanguagesFilterBox.tsx @@ -0,0 +1,91 @@ +"use client"; +import React, {SetStateAction} from "react"; +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectTrigger, + SelectValue, +} from "./ui/select"; +import {useRouter, useSearchParams} from "next/navigation"; +import {API_URL} from "@/constants"; +import Loader from "./Loader"; + +interface Data { + id: number; + slug: string; + title:string +} +async function fetchData() { + const res = await fetch(`${API_URL}/language/get/all`, { + cache: "no-store", + credentials: "include", + }); + + if (!res.ok) { + throw new Error("Failed to fetch data"); + } + + const data = await res.json(); + return data; +} + +export default function LanguagesFilterBox({ + lang, + setLang, +}: { + lang: string; + setLang: React.Dispatch>; +}) { + const urlSearchParams = useSearchParams(); + const [data, setData] = React.useState([]); + const [loading, setLoading] = React.useState(false); + + const searchParams = new URLSearchParams(urlSearchParams); + const router = useRouter(); + + React.useEffect(() => { + let active = true; + + setLoading(true); + fetchData() + .then((res) => { + if (!active) return; + console.log(res.data) + setData(res.data); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, []); + + if (loading) { + return ( +
+ +
+ ); + } + return ( + <> + + + ); +} diff --git a/src/components/Loader.tsx b/src/components/Loader.tsx new file mode 100644 index 0000000..04c22b0 --- /dev/null +++ b/src/components/Loader.tsx @@ -0,0 +1,13 @@ +import React from "react"; +import { Spinner } from "./ui/spinner"; + +export default function Loader({size="size-6"}:{size?:string}) { + return ( + <> +
+ + +
+ + ); +} diff --git a/src/components/MedicalPackagesTable.tsx b/src/components/MedicalPackagesTable.tsx new file mode 100644 index 0000000..a1849e0 --- /dev/null +++ b/src/components/MedicalPackagesTable.tsx @@ -0,0 +1,261 @@ +"use client"; + +import * as React from "react"; +import { + Pagination, + PaginationContent, + PaginationItem, + PaginationLink, + PaginationNext, + PaginationPrevious, +} from "@/components/ui/pagination"; +import { API_URL } from "@/constants"; +import Loader from "./Loader"; +import { useSearchParams } from "next/navigation"; +import { Pencil } from "lucide-react"; +import Link from "next/link"; +import RoleGuard from "./RoleGuard"; +import DeleteMedicalPackageButton from "./DeleteMedicalPackageButton"; + +export type ApiResponse = { + status: number; + message: string; + data: { + data: T[]; + page: string; + limit: string; + total: number; + totalPages: number; + hasNext: boolean; + hasPrev: boolean; + }; +}; + +export type Data = { + translations: { + id: number; + title: string; + content: string | null; + lang_id: number | null; + medicalPackageId: number | null; + }[]; + children: { + icon: string | null; + priority: number | null; + id: number; + thumbnail_id: number; + parent_id: number | null; + }[]; +} & { + icon: string | null; + priority: number | null; + id: number; + thumbnail_id: number; + parent_id: number | null; +}; +async function fetchData( + lang: string, + page: number, + pageSize: number, + queries?: string, +): Promise> { + const res = await fetch( + `${API_URL}/medical-packages/${lang}/get/all?page=${page}&limit=${pageSize}${ + queries ? `&${queries}` : "" + }`, + { + cache: "no-store", + credentials: "include", + }, + ); + + if (!res.ok) { + throw new Error("Failed to fetch data"); + } + + return res.json(); +} +export default function MedicalPackagesTable({ lang }: { lang: string }) { + const [page, setPage] = React.useState(1); + const [pageSize] = React.useState(20); + const [data, setData] = React.useState([]); + const [total, setTotal] = React.useState(0); + const [loading, setLoading] = React.useState(false); + + const searchParams = useSearchParams(); + const totalPages = Math.ceil(total / pageSize); + + React.useEffect(() => { + let active = true; + + setLoading(true); + fetchData(lang, page, pageSize, searchParams.toString()) + .then((res) => { + if (!active) return; + setData(res.data?.data); + setTotal(res.data?.total); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, [page, pageSize, searchParams, lang]); + if (loading) { + return ( +
+ +
+ ); + } + return ( + <> +
+
+ + + + + + + + + + + + + + + + {data.map((post) => ( + + + + + + + + + + + + ))} + +
+ شناسه + + عنوان + + تعداد زیرمجموعه + + آیکون + + الویت + + شناسه والد + + اکشن ها +
+ + شناسه + + {post?.id} + + + عنوان + + {post?.translations[0]?.title} + + + تعداد زیر مجموعه + + {post.children.length + ? Number(post.children.length).toLocaleString("fa-IR") + : "-"} + + + آیکون + + {post?.icon ?? "-"} + + + اولویت نمایش + + {post.priority} + + + شناسه والد + + {post?.parent_id} + + + اکشن ها + +
+ + + + + + + + +
+
+
+ {total > 0 && ( + + + + setPage((p) => Math.max(1, p - 1))} + className={ + page === 1 + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + {Array.from({ length: totalPages }).map((_, i) => { + const pageNumber = i + 1; + return ( + + setPage(pageNumber)} + className="cursor-pointer" + > + {pageNumber} + + + ); + })} + + + setPage((p) => Math.min(totalPages, p + 1))} + className={ + page === totalPages + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + + )} + + ); +} diff --git a/src/components/OnlineCasesTable.tsx b/src/components/OnlineCasesTable.tsx new file mode 100644 index 0000000..770c945 --- /dev/null +++ b/src/components/OnlineCasesTable.tsx @@ -0,0 +1,244 @@ +"use client"; + +import * as React from "react"; +import { + Pagination, + PaginationContent, + PaginationItem, + PaginationLink, + PaginationNext, + PaginationPrevious, +} from "@/components/ui/pagination"; +import {API_URL} from "@/constants"; +import Loader from "./Loader"; +import {useRouter, useSearchParams} from "next/navigation"; +import {Pencil} from "lucide-react"; +import Link from "next/link"; +import RoleGuard from "./RoleGuard"; +import DeleteExpertiseButton from "./DeleteExpertiseButton"; + +export type ApiResponse = { + status: number; + message: string; + data: { + data: T[]; + page: string; + limit: string; + total: number; + totalPages: number; + hasNext: boolean; + hasPrev: boolean; + }; +}; +type Translation = { + displayName: string; + lang: string; +}; + +type Expertise = { + slug: string; + translations: Translation[]; +}; + +type UserTranslation = { + firstName: string; + lastName: string; + lang: string; + position: string; +}; + +export type Data = { + slug: string; + id: number; + translations: { + displayName: string | null; + lang: { + title: string; + } | null; + }[]; +}; +async function fetchData( + page: number, + pageSize: number, + queries?: string, +): Promise> { + console.log("doctors table"); + + const res = await fetch( + `${API_URL}/case/get/all?page=${page}&limit=${pageSize}${queries ? `&${queries}` : ""}`, + { + cache: "no-store", + credentials: "include", + }, + ); + + if (!res.ok) { + throw new Error("Failed to fetch data"); + } + + return await res.json(); +} +export default function OnlineCasesTable() { + const [page, setPage] = React.useState(1); + const [pageSize] = React.useState(20); + const [data, setData] = React.useState([]); + const [total, setTotal] = React.useState(0); + const [loading, setLoading] = React.useState(false); + + console.log(data); + const searchParams = useSearchParams(); + const totalPages = Math.ceil(total / pageSize); + + const router = useRouter(); + React.useEffect(() => { + let active = true; + + setLoading(true); + fetchData(page, pageSize, searchParams.toString()) + .then((res) => { + if (!active) return; + console.log(res.data); + setData(res.data?.data); + setTotal(res.data?.total); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, [page, pageSize, searchParams]); + if (loading) { + return ( +
+ +
+ ); + } + return ( + <> +
+
+ + + + + + + + + + + + + + {data.map((post, index) => ( + + + + + + + + + + ))} + +
+ ردیف + + اسلاگ + + نام + + نام زبان + + اکشن ها +
+ + ردیف + + {index + 1} + + + اسلاگ + + {post?.slug} + + + نام + + {post?.translations[0]?.displayName} + + + نام زبان + + {post?.translations[0]?.lang?.title} + + + اکشن ها + +
+ + + + + + + + +
+
+
+ {total > 0 && ( + + + + setPage((p) => Math.max(1, p - 1))} + className={ + page === 1 + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + {Array.from({length: totalPages}).map((_, i) => { + const pageNumber = i + 1; + return ( + + setPage(pageNumber)} + className="cursor-pointer" + > + {pageNumber} + + + ); + })} + + + setPage((p) => Math.min(totalPages, p + 1))} + className={ + page === totalPages + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + + )} + + ); +} diff --git a/src/components/PanelQueryProvider.tsx b/src/components/PanelQueryProvider.tsx new file mode 100644 index 0000000..5ef0b32 --- /dev/null +++ b/src/components/PanelQueryProvider.tsx @@ -0,0 +1,19 @@ +"use client"; +import {QueryClient, QueryClientProvider} from "@tanstack/react-query"; +import React from "react"; + +export default function PanelQueryProvider({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + const queryClient = new QueryClient(); + return ( + <> + + + {children} + + + ); +} diff --git a/src/components/PatientsTable.tsx b/src/components/PatientsTable.tsx new file mode 100644 index 0000000..21fa5a7 --- /dev/null +++ b/src/components/PatientsTable.tsx @@ -0,0 +1,326 @@ +"use client"; + +import * as React from "react"; +import { + Pagination, + PaginationContent, + PaginationItem, + PaginationLink, + PaginationNext, + PaginationPrevious, +} from "@/components/ui/pagination"; +import {API_URL} from "@/constants"; +import Loader from "./Loader"; +import {useSearchParams} from "next/navigation"; +import {Pencil} from "lucide-react"; +import DeleteUserButton from "./deleteUserButton"; +import Link from "next/link"; +import RoleGuard from "./RoleGuard"; +import RestoreUserButton from "./restoreUserButton"; + +export type ApiResponse = { + status: number; + message: string; + data: { + data: T[]; + page: string; + limit: string; + total: number; + totalPages: number; + hasNext: boolean; + hasPrev: boolean; + }; +}; + +export type Data = { + id: string; + pid: string; + firstName: string; + lastName: string; + nationality: { + id: number; + name: string; + callCode: string; + }; + nationalityCode: string | null; + passportCode: string | null; + countryCode: string | null; + phone: string | null; + email: string | null; + preferredLanguage: string | null; + age: number | null; + address: string | null; + birthDate: Date | null; + sex: "male" | "female" | "other" | null; + postalCode: string | null; + createdAt: Date; + documents: { + id: string; + createdAt: Date; + caseId: string | null; + patientId: string | null; + uploadedById: string | null; + type: DocumentType; + }[]; +}; +async function fetchData( + page: number, + pageSize: number, + queries?: string, +): Promise> { + const res = await fetch( + `${API_URL}/patient/get/all?lang=fa&page=${page}&limit=${pageSize}${ + queries ? `&${queries}` : "" + }`, + { + cache: "no-store", + credentials: "include", + }, + ); + + if (!res.ok) { + throw new Error("Failed to fetch data"); + } + + return res.json(); +} +export default function PatientsTable() { + const [page, setPage] = React.useState(1); + const [pageSize] = React.useState(20); + const [data, setData] = React.useState([]); + const [total, setTotal] = React.useState(0); + const [loading, setLoading] = React.useState(false); + + const URLSearch = useSearchParams(); + + const searchParams = new URLSearchParams(URLSearch); + const is_deleted = searchParams.get("is_deleted") ? true : false; + const totalPages = Math.ceil(total / pageSize); + + React.useEffect(() => { + let active = true; + + setLoading(true); + fetchData(page, pageSize, URLSearch.toString()) + .then((res) => { + if (!active) return; + setData(res.data?.data); + setTotal(res.data?.total); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, [page, pageSize, URLSearch]); + if (loading) { + return ( +
+ +
+ ); + } + return ( + <> +
+
+ + + + + + + + + + + + + + + + + + + + + {data.map((post) => ( + + + + + + + + + + + + + + + + + + + ))} + +
+ شناسه + + نام + + نام خانوادگی + + کد ملی / کد پاسپورت + + جنسیت + + تاریخ تولد + + کشور + + شماره تماس + + ایمیل + + آدرس + + زبان ترجیحی + + اکشن ها +
+ + شناسه + + {post?.pid} + + + نام + + {post?.firstName} + + + نام خانوادگی + + {post?.lastName} + + + کد ملی / کدپاسپورت + + {post?.nationalityCode} / {post?.passportCode} + + + جنسیت + + {post?.sex === "male" + ? "مرد" + : post.sex === "female" + ? "زن" + : "سایر"} + + + تاریخ تولد + + {post?.birthDate && + new Date(post?.birthDate).toLocaleDateString()} + + + کشور + + {post?.nationality?.name} + + + شماره تماس + + {post?.phone && + post?.phone.toString().toLocaleLowerCase("fa-IR")} + + + ایمیل + + {post?.email} + + + آدرس + + {post?.address} + + + زبان ترجیحی + + {post?.preferredLanguage} + + + اکشن ها + +
+ + {!is_deleted && ( + + )} + {is_deleted && ( + + )} + + + + + + +
+
+
+ {total > 0 && ( + + + + setPage((p) => Math.max(1, p - 1))} + className={ + page === 1 + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + {Array.from({length: totalPages}).map((_, i) => { + const pageNumber = i + 1; + return ( + + setPage(pageNumber)} + className="cursor-pointer" + > + {pageNumber} + + + ); + })} + + + setPage((p) => Math.min(totalPages, p + 1))} + className={ + page === totalPages + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + + )} + + ); +} diff --git a/src/components/PersianMonthDropdown.tsx b/src/components/PersianMonthDropdown.tsx new file mode 100644 index 0000000..356a9b1 --- /dev/null +++ b/src/components/PersianMonthDropdown.tsx @@ -0,0 +1,32 @@ +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { PERSIAN_MONTHS } from "@/constants"; + +export default function PersianMonthDropdown({ + value, + onChange, +}: { + value: number; + onChange: (month: number) => void; +}) { + return ( + + ); +} diff --git a/src/components/PrivateRoute.tsx b/src/components/PrivateRoute.tsx new file mode 100644 index 0000000..d92e88f --- /dev/null +++ b/src/components/PrivateRoute.tsx @@ -0,0 +1,18 @@ +"use client"; +import { useEffect } from "react"; +import { useRouter } from "next/navigation"; + +export default function PrivateRoute({ children }: { children: React.ReactNode }) { + const router = useRouter(); + const isLoggedIn = Boolean(localStorage.getItem("auth_token")); // یا useSession + + useEffect(() => { + if (!isLoggedIn) { + router.push("/login"); + } + }, [isLoggedIn, router]); + + if (!isLoggedIn) return null; // یا loader + + return <>{children}; +} diff --git a/src/components/ProfileDropdown.tsx b/src/components/ProfileDropdown.tsx new file mode 100644 index 0000000..fee6bcf --- /dev/null +++ b/src/components/ProfileDropdown.tsx @@ -0,0 +1,50 @@ +"use client"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@radix-ui/react-dropdown-menu"; +import React from "react"; +import {Button} from "./ui/button"; + +import ProfileLogoutDropdown from "./ProfileLogoutDropdown"; +import {useQueryClient} from "@tanstack/react-query"; +import {ChevronDown, User} from "lucide-react"; +import { MeResponse } from "@/hooks"; + +export default function ProfileDropdown() { + const qc = useQueryClient(); + const user:MeResponse = qc.getQueryData(["me"])!; + + return ( +
+ + + + + + + ویرایش پروفایل + + + + + +
+ ); +} diff --git a/src/components/ProfileLogoutDropdown.tsx b/src/components/ProfileLogoutDropdown.tsx new file mode 100644 index 0000000..8a1c16e --- /dev/null +++ b/src/components/ProfileLogoutDropdown.tsx @@ -0,0 +1,59 @@ +"use client"; +import React from "react"; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "./ui/dialog"; +import {Button} from "./ui/button"; +import {useLogoutUser} from "@/hooks/users"; +import {toast} from "react-toastify"; +import Loader from "./Loader"; +import {useRouter} from "next/navigation"; + +export default function ProfileLogoutDropdown() { + const {mutateAsync, isPending} = useLogoutUser(); + + const router = useRouter(); + const handleLogout = async () => { + try { + const {message} = await mutateAsync(); + router.push("/login"); + } catch (error) { + toast.error("asdasdsad"); + } + }; + return ( + <> + +
+ + + + + + خروج از حساب + + آیا برای خروج از حساب مطمئن هستید؟ + + + + + + + + + + +
+
+ + ); +} diff --git a/src/components/RefreshCDNStatus.tsx b/src/components/RefreshCDNStatus.tsx new file mode 100644 index 0000000..56409a8 --- /dev/null +++ b/src/components/RefreshCDNStatus.tsx @@ -0,0 +1,21 @@ +"use client"; +import React from "react"; +import {Button} from "./ui/button"; +import {RefreshCw} from "lucide-react"; +import { useRouter } from "next/navigation"; + +export default function RefreshCDNStatus() { + const router = useRouter(); + return ( + <> + + + ); +} diff --git a/src/components/RestorePatientTable.tsx b/src/components/RestorePatientTable.tsx new file mode 100644 index 0000000..51e004a --- /dev/null +++ b/src/components/RestorePatientTable.tsx @@ -0,0 +1,320 @@ +"use client"; + +import * as React from "react"; +import { + Pagination, + PaginationContent, + PaginationItem, + PaginationLink, + PaginationNext, + PaginationPrevious, +} from "@/components/ui/pagination"; +import {API_URL} from "@/constants"; +import Loader from "./Loader"; +import {useSearchParams} from "next/navigation"; +import {Pencil} from "lucide-react"; +import DeleteUserButton from "./deleteUserButton"; +import Link from "next/link"; +import RoleGuard from "./RoleGuard"; +import {Field, FieldLabel} from "./ui/field"; +import {Input} from "./ui/input"; + +export type ApiResponse = { + status: number; + message: string; + data: { + data: T[]; + page: string; + limit: string; + total: number; + totalPages: number; + hasNext: boolean; + hasPrev: boolean; + }; +}; + +export type Data = { + id: string; + firstName: string; + lastName: string; + nationality: { + id: number; + name: string; + callCode: string; + }; + nationalityCode: string | null; + passportCode: string | null; + countryCode: string | null; + phone: string | null; + email: string | null; + preferredLanguage: string | null; + age: number | null; + address: string | null; + birthDate: Date | null; + sex: "male" | "female" | "other" | null; + postalCode: string | null; + createdAt: Date; + documents: { + id: string; + createdAt: Date; + caseId: string | null; + patientId: string | null; + uploadedById: string | null; + type: DocumentType; + }[]; +}; +async function fetchData( + page: number, + pageSize: number, + queries?: string, +): Promise> { + const res = await fetch( + `${API_URL}/patient/get/all?lang=fa&page=${page}&limit=${pageSize}${ + queries ? `&${queries}` : "" + }`, + { + cache: "no-store", + credentials: "include", + }, + ); + + if (!res.ok) { + throw new Error("Failed to fetch data"); + } + + return res.json(); +} +export default function RestorePatientTable() { + const [id, setID] = React.useState(""); + const [page, setPage] = React.useState(1); + const [pageSize] = React.useState(20); + const [data, setData] = React.useState([]); + const [total, setTotal] = React.useState(0); + const [loading, setLoading] = React.useState(false); + + const searchParams = useSearchParams(); + const totalPages = Math.ceil(total / pageSize); + + React.useEffect(() => { + let active = true; + + setLoading(true); + fetchData(page, pageSize, searchParams.toString()) + .then((res) => { + if (!active) return; + setData(res.data?.data); + setTotal(res.data?.total); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, [page, pageSize, searchParams]); + if (loading) { + return ( +
+ +
+ ); + } + return ( + <> +
+ + شناسه بیمار + setID(e.target.value)} + /> + +
+
+ + + + + + + + + + + + + + + + + + + + {data.map((post) => ( + + + + + + + + + + + + + + + + + + ))} + +
+ نام + + نام خانوادگی + + کد ملی / کد پاسپورت + + جنسیت + + تاریخ تولد + + کشور + + شماره تماس + + ایمیل + + آدرس + + زبان ترجیحی + + اکشن ها +
+ + نام + + {post?.firstName} + + + نام خانوادگی + + {post?.lastName} + + + کد ملی / کدپاسپورت + + {post?.nationalityCode} / {post?.passportCode} + + + جنسیت + + {post?.sex === "male" + ? "مرد" + : post.sex === "female" + ? "زن" + : "سایر"} + + + تاریخ تولد + + {post?.birthDate && + new Date(post?.birthDate).toLocaleDateString()} + + + کشور + + {post?.nationality?.name} + + + شماره تماس + + {post?.phone && + post?.phone.toString().toLocaleLowerCase("fa-IR")} + + + ایمیل + + {post?.email} + + + آدرس + + {post?.address} + + + زبان ترجیحی + + {post?.preferredLanguage} + + + اکشن ها + +
+ + + + + + + + +
+
+
+ {total > 0 && ( + + + + setPage((p) => Math.max(1, p - 1))} + className={ + page === 1 + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + {Array.from({length: totalPages}).map((_, i) => { + const pageNumber = i + 1; + return ( + + setPage(pageNumber)} + className="cursor-pointer" + > + {pageNumber} + + + ); + })} + + + setPage((p) => Math.min(totalPages, p + 1))} + className={ + page === totalPages + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + + )} + + ); +} diff --git a/src/components/RoleGuard.tsx b/src/components/RoleGuard.tsx new file mode 100644 index 0000000..77ac9a6 --- /dev/null +++ b/src/components/RoleGuard.tsx @@ -0,0 +1,24 @@ +"use client"; + +import {StaffRoles} from "@/constants"; +import {useMe} from "@/hooks"; + +export default function RoleGuard({ + roles, + children, +}: { + roles: StaffRoles[]; + children: React.ReactNode; +}) { + const {data, isLoading} = useMe(); + + if (isLoading) return null; // یا Skeleton + + if (!data) return null; + + const userRole = data.data.role.toUpperCase() as StaffRoles; + console.log(!roles.includes(userRole)); + if (!roles.includes(userRole)) return null; + + return <>{children}; +} diff --git a/src/components/SearchBox.tsx b/src/components/SearchBox.tsx new file mode 100644 index 0000000..05c7153 --- /dev/null +++ b/src/components/SearchBox.tsx @@ -0,0 +1,63 @@ +"use client"; +import React from "react"; +import {Field} from "./ui/field"; +import {Input} from "./ui/input"; +import {useRouter, useSearchParams} from "next/navigation"; +import {Label} from "./ui/label"; + +export default function SearchBox({ + placeholder, + label, + hasLabel=false, + queryName, + inputName, + route, +}: { + placeholder?: string; + queryName?: string; + inputName: string; + label?:string, + hasLabel?:boolean + route: string; +}) { + const router = useRouter(); + const urlSearchParams = useSearchParams(); + const searchParams = new URLSearchParams(urlSearchParams); + const debounce = (onChange: (v: string) => void) => { + let timeout: ReturnType; + return (e: React.ChangeEvent) => { + const form = e.currentTarget.value; + clearTimeout(timeout); + timeout = setTimeout(() => { + onChange(form); + }, 1000); + }; + }; + const handleSearch = async (value: string) => { + try { + searchParams.set(`${queryName ?? inputName}`, value); + router.push( + `/${route}${searchParams ? `?${searchParams.toString()}` : ""} ` + ); + } catch (error) { + console.error("Error fetching data:", error); + } + }; + + return ( + <> + + {hasLabel && } + { + handleSearch(e); + })} + defaultValue={searchParams.get(`${queryName ?? inputName}`) ?? ""} + name={inputName} + className="bg-white w-[240px] flex-1" + /> + + + ); +} diff --git a/src/components/SectionTitle.tsx b/src/components/SectionTitle.tsx new file mode 100644 index 0000000..4b0ff60 --- /dev/null +++ b/src/components/SectionTitle.tsx @@ -0,0 +1,11 @@ +import React from "react"; + +export default function SectionTitle({label}: {label: string}) { + return ( + <> +

+ {label} +

+ + ); +} diff --git a/src/components/SelectCalendar.tsx b/src/components/SelectCalendar.tsx new file mode 100644 index 0000000..af9a5d0 --- /dev/null +++ b/src/components/SelectCalendar.tsx @@ -0,0 +1,58 @@ +"use client"; +import React from "react"; +import {CalendarNormal} from "./CalendarNormal"; +import {CalendarHijri} from "./CalendarHijri"; +import {Label} from "./ui/label"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "./ui/select"; + +export default function SelectCalendar({ + date, + setDate, +}: { + date: Date | undefined; + setDate: React.Dispatch>; +}) { + const [dropdown, setDropdown] = React.useState<"persian" | "general">( + "general" + ); + + return ( +
+
+ + +
+
+ + + {dropdown === "general" ? : } +
+
+ ); +} diff --git a/src/components/SideMenu.tsx b/src/components/SideMenu.tsx new file mode 100644 index 0000000..e889287 --- /dev/null +++ b/src/components/SideMenu.tsx @@ -0,0 +1,112 @@ +"use client"; +import React, {useEffect, useState} from "react"; +import {Button} from "./ui/button"; +import {ChevronRight} from "lucide-react"; +import Link from "next/link"; +import {SIDE_MENU_TYPE, SIDE_MENUS, STAFF_ROLE_TYPE} from "@/constants"; +import FeatureIcon from "./FeatureIcon"; +import {useRouter} from "next/navigation"; +import {getSideMenusByRole} from "@/lib/utils"; +import {useMe} from "@/hooks"; + +export default function SideMenu() { + const {data} = useMe(); + const [isOpen, setIsOpen] = useState(false); + const router = useRouter(); + const [selected, setSelected] = useState(); + useEffect(() => { + setIsOpen(false); + }, [router]); + const visibleMenus = getSideMenusByRole( + SIDE_MENUS, + data?.data?.role + ? (data?.data?.role.toUpperCase() as STAFF_ROLE_TYPE) + : "COORDINATOR" + ); + return ( + <> +
+
+ +
+
+
+ + + {selected?.label} + +
+ {selected?.sub && + selected.sub.items.length > 0 && + isOpen === true && + selected?.sub?.items.map((item) => { + if (item.show || item.show === undefined) { + return ( +
+ + {item.label} + + {item.hasLine && ( + + )} +
+ ); + } + })} +
+
+ + + ); +} diff --git a/src/components/TextEditor.tsx b/src/components/TextEditor.tsx new file mode 100644 index 0000000..f672341 --- /dev/null +++ b/src/components/TextEditor.tsx @@ -0,0 +1,85 @@ +"use client"; + +import React, { + useEffect, + useRef, + forwardRef, + useImperativeHandle, +} from "react"; +import Quill from "quill"; +import "quill/dist/quill.snow.css"; + +export type RichTextEditorHandle = { + getContent: () => string; +}; + +type Props = { + value?: string; // ✅ مقدار اولیه +}; +const toolbarOptions = [ + ['bold', 'italic', 'underline', 'strike'], // toggled buttons + ['blockquote', 'code-block'], + ['link', 'image', ], + + [{ 'header': 1 }, { 'header': 2 }], // custom button values + [{ 'list': 'ordered'}, { 'list': 'bullet' }, { 'list': 'check' }], + [{ 'indent': '-1'}, { 'indent': '+1' }], // outdent/indent + [{ 'direction': 'rtl' }], // text direction + + [{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown + [{ 'header': [1, 2, 3, 4, 5, 6, false] }], + + [{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme + [{ 'font': [] }], + [{ 'align': [] }], + + ['clean'] // remove formatting button +]; +const RichTextEditor = forwardRef( + ({ value }, ref) => { + const editorRef = useRef(null); + const quillRef = useRef(null); + + // init editor + useEffect(() => { + if (!editorRef.current || quillRef.current) return; + + quillRef.current = new Quill(editorRef.current, { + theme: "snow", + modules: { + toolbar:toolbarOptions, + }, + placeholder: "شروع به نوشتن...", + }); + + const editorEl = + editorRef.current.querySelector(".ql-editor"); + if (editorEl) { + editorEl.setAttribute("dir", "rtl"); + editorEl.style.textAlign = "right"; + } + }, []); + + // ✅ set content when value changes + useEffect(() => { + if (quillRef.current && value !== undefined) { + quillRef.current.clipboard.dangerouslyPasteHTML(value); + } + }, [value]); + + useImperativeHandle(ref, () => ({ + getContent: () => quillRef.current?.root.innerHTML || "", + })); + + return ( +
+ ); + }, +); + +RichTextEditor.displayName = "RichTextEditor"; +export default RichTextEditor; diff --git a/src/components/TransferTeamTable.tsx b/src/components/TransferTeamTable.tsx new file mode 100644 index 0000000..a6153c7 --- /dev/null +++ b/src/components/TransferTeamTable.tsx @@ -0,0 +1,263 @@ +"use client"; + +import * as React from "react"; +import { + Pagination, + PaginationContent, + PaginationItem, + PaginationLink, + PaginationNext, + PaginationPrevious, +} from "@/components/ui/pagination"; +import {API_URL} from "@/constants"; +import Loader from "./Loader"; +import {useRouter, useSearchParams} from "next/navigation"; +import {Pencil, Trash} from "lucide-react"; +import DeleteUserButton from "./deleteUserButton"; +import Link from "next/link"; +import {useMe} from "@/hooks"; +import RoleGuard from "./RoleGuard"; + +// ===================== +// Types +// ===================== + +export type ApiResponse = { + status: number; + message: string; + data: { + data: T[]; + page: string; + limit: string; + total: number; + totalPages: number; + hasNext: boolean; + hasPrev: boolean; + }; +}; +type Translation = { + displayName: string; + lang: string; +}; + +type Expertise = { + slug: string; + translations: Translation[]; +}; + +type UserTranslation = { + firstName: string; + lastName: string; + lang: string; + position: string; +}; + +export type Data = { + id: number; + email: string; + phone: string; + slug: string; + image: string | null; + translations: UserTranslation[]; + expertise: Expertise; +}; +async function fetchData( + page: number, + pageSize: number, + queries?: string, +): Promise> { + const res = await fetch( + `${API_URL}/user/get/all?t=transfer_team&lang=fa&page=${page}&limit=${pageSize}${ + queries ? `&${queries}` : "" + }`, + { + cache: "no-store", + credentials: "include", + }, + ); + + if (!res.ok) { + throw new Error("Failed to fetch data"); + } + + return res.json(); +} +export default function TransferTeamTable() { + const {data: user} = useMe(); + const [page, setPage] = React.useState(1); + const [pageSize] = React.useState(20); + const [data, setData] = React.useState([]); + const [total, setTotal] = React.useState(0); + const [loading, setLoading] = React.useState(false); + + const searchParams = useSearchParams(); + const totalPages = Math.ceil(total / pageSize); + + const router = useRouter(); + React.useEffect(() => { + let active = true; + + setLoading(true); + fetchData(page, pageSize, searchParams.toString()) + .then((res) => { + if (!active) return; + setData(res.data?.data); + setTotal(res.data?.total); + }) + .catch(console.error) + .finally(() => active && setLoading(false)); + + return () => { + active = false; + }; + }, [page, pageSize, searchParams]); + if (loading) { + return ( +
+ +
+ ); + } + return ( + <> +
+
+ + + + + + + + + + + + + + + {data.map((post) => ( + + + + + + + + + + + + + ))} + +
+ نام + + نام خانوادگی + + سمت + + تخصص + + ایمیل + + موبایل + + اکشن ها +
+ + نام + + {post?.translations[0]?.firstName} + + + نام خانوادگی + + {post?.translations[0]?.lastName} + + + سمت + + {post.translations[0]?.position} + + + تخصص + + {post?.expertise?.translations[0]?.displayName} + + + ایمیل + + {post.email} + + + موبایل + + {post?.phone.toString().toLocaleLowerCase("fa-IR")} + + + اکشن ها + +
+ + + + + + +
+
+
+ {total > 0 && ( + + + + setPage((p) => Math.max(1, p - 1))} + className={ + page === 1 + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + {Array.from({length: totalPages}).map((_, i) => { + const pageNumber = i + 1; + return ( + + setPage(pageNumber)} + className="cursor-pointer" + > + {pageNumber} + + + ); + })} + + + setPage((p) => Math.min(totalPages, p + 1))} + className={ + page === totalPages + ? "pointer-events-none opacity-50" + : "cursor-pointer" + } + /> + + + + )} + + ); +} diff --git a/src/components/deleteUserButton.tsx b/src/components/deleteUserButton.tsx new file mode 100644 index 0000000..a2a3ddc --- /dev/null +++ b/src/components/deleteUserButton.tsx @@ -0,0 +1,69 @@ +"use client"; +import React from "react"; +import {Button} from "./ui/button"; +import {Trash} from "lucide-react"; +import privateApi from "@/service/http/privateCall.axios"; +import {usePathname} from "next/navigation"; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "./ui/dialog"; +import {toast} from "react-toastify"; +import {handleAxiosError} from "@/lib/utils"; +import { ServerResponseObject } from "@/types"; + +async function deleteUser(id: number | string, route: string) { + try { + const {message} = await privateApi.delete(`/${route}/delete/${id}`) as ServerResponseObject; + toast.success(message); + } catch (error) { + toast.error(handleAxiosError(error)); + } +} +export default function DeleteUserButton({ + id, + route, +}: { + id: number | string; + route: string; +}) { + const pathname = usePathname(); + const handleDelete = async () => { + await deleteUser(id, route); + window.location.pathname = pathname; + }; + return ( + <> + + + + + + + حذف آیتم + + آیا از حذف این آیتم اطمینان دارد ؟ + + + + + + + + + + + + + ); +} diff --git a/src/components/forms/configs/ConfigsForm.ts b/src/components/forms/configs/ConfigsForm.ts new file mode 100644 index 0000000..6f3550f --- /dev/null +++ b/src/components/forms/configs/ConfigsForm.ts @@ -0,0 +1,45 @@ +"use client"; +import {withFormik} from "formik"; + +import {toast} from "react-toastify"; +import InnerConfigListForm from "./InnerConfigListForm"; +import {AppRouterInstance} from "next/dist/shared/lib/app-router-context.shared-runtime"; +import {UseMutateAsyncFunction} from "@tanstack/react-query"; +import {ServerResponse} from "@/types"; +export interface ConfigFormItem { + key: string; + value: string; + description?: string; +} + +export interface ConfigFormValues { + configs: ConfigFormItem[]; +} +export interface ConfigListFormProps { + router: AppRouterInstance; + initialData: ConfigFormItem[]; // 👈 دیتای ورودی تو + onSubmit: UseMutateAsyncFunction< + ServerResponse, + Error, + ConfigFormItem[], + ServerResponse + >; + updatePending: boolean; +} + +const ConfigListForm = withFormik({ + mapPropsToValues: (props) => ({ + configs: props.initialData, // 👈 اینجاست که فرم پر میشه + }), + + handleSubmit: async (values, {props}) => { + try { + await props.onSubmit(values.configs); + toast.success("تنظیمات ذخیره شد"); + } catch (error) { + toast.error("خطایی رخ داده است"); + } + }, +})(InnerConfigListForm); + +export default ConfigListForm; diff --git a/src/components/forms/configs/InnerConfigListForm.tsx b/src/components/forms/configs/InnerConfigListForm.tsx new file mode 100644 index 0000000..5ed4d80 --- /dev/null +++ b/src/components/forms/configs/InnerConfigListForm.tsx @@ -0,0 +1,61 @@ +"use client"; +import React from "react"; +import { Form, FormikProps } from "formik"; +import { Field, FieldLabel } from "@/components/ui/field"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { Button } from "@/components/ui/button"; +import { ConfigFormValues, ConfigListFormProps } from "./ConfigsForm"; + +export default function InnerConfigListForm( + props: FormikProps & ConfigListFormProps +) { + const { values, setFieldValue } = props; + + console.log(values.configs) + return ( +
+ {values.configs?.length && values?.configs?.map((config, index) => ( +
+ + Key + + + + + Value + + setFieldValue( + `configs.${index}.value`, + e.target.value + ) + } + /> + + + + Description + +
+
+
+ آیا میخواهید زیر مجموعه شود + setIsSub(checked)} + /> +
+ {isSub && ( + + انتخاب خدمت پزشکی والد + + + )} +
+ +
+ ); +} diff --git a/src/components/forms/medical-packages/edit/UpdateMedicalPackageForm.ts b/src/components/forms/medical-packages/edit/UpdateMedicalPackageForm.ts new file mode 100644 index 0000000..710c8fe --- /dev/null +++ b/src/components/forms/medical-packages/edit/UpdateMedicalPackageForm.ts @@ -0,0 +1,92 @@ +"use client"; +import {withFormik} from "formik"; +import InnerUpdateMedicalPackageForm from "./InnerUpdateMedicalPackageForm"; +import {Language, ServerResponse} from "@/types"; +import {QueryClient, UseMutateAsyncFunction} from "@tanstack/react-query"; +import {CreateMedicalPackageTranslation} from "../new/CreateMedicalPackageForm"; +import {toast} from "react-toastify"; +import {handleAxiosError} from "@/lib/utils"; +import {AppRouterInstance} from "next/dist/shared/lib/app-router-context.shared-runtime"; + +export interface UpdateMedicalPackageFormProps { + queryClient: QueryClient; + languages: Language[]; + parents: { + translations: { + id: number; + lang_id: number | null; + title: string; + content: string | null; + medicalPackageId: number | null; + }[]; + id: number; + thumbnail_id: number; + icon: string | null; + priority: number | null; + parent_id: number | null; + }[]; + updateFn: UseMutateAsyncFunction< + ServerResponse, + Error, + {id: string; data: UpdateMedicalPackageFormValues}, + ServerResponse + >; + updatePending: boolean; + preValues: { + translations: { + id: number; + title: string; + content: string | null; + lang_id: number | null; + medicalPackageId: number | null; + }[]; + id: number; + thumbnail_id: number | null; + thumbnail: { + fileKey: string; + filename: string | null; + fileUrl: string | null; + }; + icon: string | null; + priority: number | null; + parent_id: number | null; + }; + id: string; + router: AppRouterInstance; +} +export interface UpdateMedicalPackageFormValues { + translations: { + id: number; + title: string; + content: string | null; + lang_id: number | null; + medicalPackageId: number | null; + }[]; + icon: string; + thumbnail_id: number | null; + priority: number; + parent_id: number | null; +} + +const UpdateMedicalPackageForm = withFormik< + UpdateMedicalPackageFormProps, + UpdateMedicalPackageFormValues +>({ + mapPropsToValues: (props) => ({ + translations: props.preValues.translations, + icon: props.preValues.icon ?? "", + priority: props.preValues.priority ?? 1, + thumbnail_id: props.preValues.thumbnail_id ?? null, + parent_id: props.preValues.parent_id ?? null, + }), + handleSubmit: async (values, {props}) => { + try { + const {message} = await props.updateFn({id: props.id, data: values}); + toast.success(message); + } catch (error) { + toast.error(handleAxiosError(error)); + } + }, +})(InnerUpdateMedicalPackageForm); + +export default UpdateMedicalPackageForm; diff --git a/src/components/forms/medical-packages/new/CreateMedicalPackageForm.ts b/src/components/forms/medical-packages/new/CreateMedicalPackageForm.ts new file mode 100644 index 0000000..2c7cce6 --- /dev/null +++ b/src/components/forms/medical-packages/new/CreateMedicalPackageForm.ts @@ -0,0 +1,83 @@ +import {withFormik} from "formik"; +import InnerCreateMedicalPackageForm from "./InnerCreateMedicalPackageForm"; +import {QueryClient, UseMutateAsyncFunction} from "@tanstack/react-query"; +import {Language, ServerResponse} from "@/types"; +import {toast} from "react-toastify"; +import {handleAxiosError} from "@/lib/utils"; + +export interface CreateMedicalPackageProps { + queryClient: QueryClient; + languages: Language[]; + parents: { + translations: { + id: number; + lang_id: number | null; + title: string; + content: string | null; + medicalPackageId: number | null; + }[]; + id: number; + thumbnail_id: number; + icon: string | null; + priority: number | null; + parent_id: number | null; + }[]; + createFn: UseMutateAsyncFunction< + ServerResponse, + Error, + CreateMedicalPackageValues, + ServerResponse + >; + createPending: boolean; +} +export interface CreateMedicalPackageValues { + translations: CreateMedicalPackageTranslation[]; + icon: string; + thumbnail_id: number | null; + priority: number; + parent_id: number | null; + price:string +} +export interface CreateMedicalPackageTranslation { + lang_id: number; + title: string; + content: string; +} +function buildInitialTranslations( + languages: Language[], +): CreateMedicalPackageTranslation[] { + return languages.map((lang) => ({ + lang_id: lang.id, + title: "", + content: "", + // position: "", + })); +} +const CreateMedicalPackageForm = withFormik< + CreateMedicalPackageProps, + CreateMedicalPackageValues +>({ + mapPropsToValues: (props) => ({ + translations: buildInitialTranslations(props.languages), + icon: "", + price:"", + priority: 1, + thumbnail_id: null, + parent_id: null, + }), + handleSubmit: async (values, {props}) => { + console.log(values) + try { + const {message} = await props.createFn(values); + toast.success(message); + + props.queryClient.invalidateQueries({ + queryKey: ["get-all-medical-packages"], + }); + } catch (error) { + toast.error(handleAxiosError(error)); + } + }, +})(InnerCreateMedicalPackageForm); + +export default CreateMedicalPackageForm; diff --git a/src/components/forms/medical-packages/new/InnerCreateMedicalPackageForm.tsx b/src/components/forms/medical-packages/new/InnerCreateMedicalPackageForm.tsx new file mode 100644 index 0000000..1772e2b --- /dev/null +++ b/src/components/forms/medical-packages/new/InnerCreateMedicalPackageForm.tsx @@ -0,0 +1,172 @@ +import { ErrorMessage, Form, FormikProps } from "formik"; +import React, { useRef, useState } from "react"; +import { + CreateMedicalPackageProps, + CreateMedicalPackageValues, +} from "./CreateMedicalPackageForm"; +import { Field, FieldLabel } from "@/components/ui/field"; +import { Input } from "@/components/ui/input"; +import RichTextEditor, { RichTextEditorHandle } from "@/components/TextEditor"; +import { Button } from "@/components/ui/button"; +import { Switch } from "@/components/ui/switch"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import Loader from "@/components/Loader"; +import { Textarea } from "@/components/ui/textarea"; +import UploadDropzone from "@/components/uploadDropzone"; + +export default function InnerCreateMedicalPackageForm( + props: FormikProps & CreateMedicalPackageProps, +) { + const [isSub, setIsSub] = useState(false); + const [output, setOutput] = useState(""); + const { setFieldValue} = props; + const ref = useRef(null); + + const [refs] = useState( + props.languages.map(() => JSON.parse(JSON.stringify(ref))), + ); + + const handleSave = () => { + refs.forEach((r, i) => { + setFieldValue(`translations.${i}.content`, r.current.getContent()); + }); + setFieldValue("thumbnail_id", output); + props.handleSubmit(); + }; + return ( +
+ + آپلود تصویر شاخص ( تامبنیل ) + + + + قیمت پکیج (به دلار آمریکا) + setFieldValue(`price`, e.target.value)} + /> + + + {props.values.translations.map((tr, index) => { + const lang = props?.languages.find((l) => l.id === tr.lang_id); + + return ( +
+

+ ردیف برای زبان {lang?.title} ({lang?.slug}) +

+ + {/* First Name */} + + + عنوان + + + setFieldValue(`translations.${index}.title`, e.target.value) + } + /> + + + + {/* Last Name */} + + + محتوا + + + + +
+ ); + })} +
+ آیکون (کد svg را در این قسمت قرار دهید) + +
+
+
+ آیا میخواهید زیر مجموعه شود + { + setIsSub(checked); + props.setFieldValue("parent_id", null); + }} + /> +
+ {isSub && ( + + انتخاب خدمت پزشکی والد + + + )} +
+ +
+ ); +} diff --git a/src/components/forms/online-case/new/CreateOnlineCaseForm.ts b/src/components/forms/online-case/new/CreateOnlineCaseForm.ts new file mode 100644 index 0000000..bebd317 --- /dev/null +++ b/src/components/forms/online-case/new/CreateOnlineCaseForm.ts @@ -0,0 +1,55 @@ +"use client" +import {withFormik} from "formik"; +import {AppRouterInstance} from "next/dist/shared/lib/app-router-context.shared-runtime"; +import InnerCreateOnlineCaseForm from "./InnerCreateOnlineCaseForm"; +import {CreatePatientFormValues} from "../../patients/edit/UpdatePatientForm"; +import { CreatePatientFormProps } from "../../patients/new/CreatePatientForm"; + +enum CaseStatus { + NEW, + CONTACTED, + DOCS_PENDING, + REVIEWING, + PRE_APPROVED, + REJECTED, + CLOSED, + CONVERTED_TO_HIS, +} + +export interface CreateOnlineCaseFormProps { + router: AppRouterInstance; + // patients?:any +} +export interface CreateOnlineCaseFormValues { + message?: string; + specialty?: string; + + status?: CaseStatus; +} + +const CreateOnlineCaseForm = withFormik< + CreateOnlineCaseFormProps & CreatePatientFormProps, + CreatePatientFormValues & CreateOnlineCaseFormValues +>({ + mapPropsToValues: () => ({ + firstName: "", + lastName: "", + email: "", + sex: "male", + address: "", + age: null, + birthDate: "", + nationality: "", + nationalityCode: "", + passportCode: "", + postalCode: "", + phone: "", + specialty: "", + preferredLanguage: "", + status: CaseStatus.NEW, + message: "", + }), + handleSubmit: async (values, {props}) => {}, +})(InnerCreateOnlineCaseForm); + +export default CreateOnlineCaseForm; diff --git a/src/components/forms/online-case/new/InnerCreateOnlineCaseForm.tsx b/src/components/forms/online-case/new/InnerCreateOnlineCaseForm.tsx new file mode 100644 index 0000000..8c0184d --- /dev/null +++ b/src/components/forms/online-case/new/InnerCreateOnlineCaseForm.tsx @@ -0,0 +1,399 @@ +"use client"; +import {ErrorMessage, Form, FormikProps} from "formik"; +import React, {useEffect} from "react"; +import {CreatePatientFormValues} from "../../patients/edit/UpdatePatientForm"; +import { + CreateOnlineCaseFormProps, + CreateOnlineCaseFormValues, +} from "./CreateOnlineCaseForm"; +import {Field, FieldLabel} from "@/components/ui/field"; +import {Input} from "@/components/ui/input"; +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import Loader from "@/components/Loader"; +import {CreatePatientFormProps} from "../../patients/new/CreatePatientForm"; +import SelectCalendar from "@/components/SelectCalendar"; +import {Button} from "@/components/ui/button"; +import SectionTitle from "@/components/SectionTitle"; +import UploadDropzone from "@/components/uploadDropzone"; +import {Textarea} from "@/components/ui/textarea"; + +export default function InnerCreateOnlineCaseForm( + props: FormikProps & + CreateOnlineCaseFormProps & + CreatePatientFormProps +) { + const {setFieldValue} = props; + useEffect(() => { + const selectedYear = new Date(props.values.birthDate!).getFullYear(); + const age = selectedYear + ? new Date(Date.now()).getFullYear() - selectedYear + : null; + setFieldValue("age", age); + }, [props.values.birthDate]); + return ( + <> +
+
+
+ + نام + setFieldValue(`firstName`, e.target.value)} + required + /> + + +
+
+ + نام خانوادگی + setFieldValue(`lastName`, e.target.value)} + /> + + +
+
+ + سن + setFieldValue(`age`, e.target.value)} + /> + + +
+
+ + جنسیت + + + +
+
+ + شماره تماس + setFieldValue(`phone`, e.target.value)} + /> + + +
+
+ + + کد پاسپورت (افرادغیرایرانی) + + setFieldValue(`passportCode`, e.target.value)} + /> + + +
+
+ + + کد ملی (افراد ایرانی) + + + setFieldValue(`nationalityCode`, e.target.value) + } + /> + + +
+
+ + ملیت بیمار + + + +
+
+ + ایمیل + setFieldValue(`email`, e.target.value)} + /> + + +
+ +
+ + setFieldValue("birthDate", value)} + /> + + +
+
+ + + زبان ترجیحی بیمار + + + + +
+
+ + خدمت مورد نظر + + + +
+
+ + آدرس + setFieldValue(`address`, e.target.value)} + /> + + +
+
+ + پیام +