diff --git a/package-lock.json b/package-lock.json index c2fdcf9..704139a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,10 +15,14 @@ "@radix-ui/react-accordion": "^1.2.0", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-popover": "1.1.2", "@radix-ui/react-slot": "^1.1.0", + "@react-icons/all-files": "^4.1.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "lucide-react": "^0.439.0", + "react-icons": "^5.4.0", + "react-spinners": "^0.14.1", "tailwind-merge": "^2.5.2", "tailwindcss-animate": "^1.0.7", "zustand": "^4.5.5" @@ -47,6 +51,355 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", + "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", + "dependencies": { + "@babel/types": "^7.25.6", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "dependencies": { + "@babel/types": "^7.25.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", + "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", + "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.6", + "@babel/parser": "^7.25.6", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", + "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==", + "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.2.0", + "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/babel-plugin/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.0", + "@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==" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz", + "integrity": "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==", + "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==" + }, + "node_modules/@emotion/react": { + "version": "11.13.3", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz", + "integrity": "sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/cache": "^11.13.0", + "@emotion/serialize": "^1.3.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0", + "@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.2", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.2.tgz", + "integrity": "sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.1", + "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==" + }, + "node_modules/@emotion/styled": { + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.0.tgz", + "integrity": "sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0" + }, + "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==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", + "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.1.tgz", + "integrity": "sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==" + }, + "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==" + }, "node_modules/@esbuild/android-arm": { "version": "0.17.19", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", @@ -455,6 +808,40 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz", + "integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==", + "dependencies": { + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.11.tgz", + "integrity": "sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", + "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==" + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -574,59 +961,408 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@musinsa/ui": { - "resolved": "src/packages/ui", - "link": true - }, - "node_modules/@musinsa/utils": { - "resolved": "src/packages/utils", - "link": true - }, - "node_modules/@next/env": { - "version": "14.2.12", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.12.tgz", - "integrity": "sha512-3fP29GIetdwVIfIRyLKM7KrvJaqepv+6pVodEbx0P5CaMLYBtx+7eEg8JYO5L9sveJO87z9eCReceZLi0hxO1Q==" + "node_modules/@mui/core-downloads-tracker": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.1.1.tgz", + "integrity": "sha512-VdQC1tPIIcZAnf62L2M1eQif0x2vlKg3YK4kGYbtijSH4niEgI21GnstykW1vQIs+Bc6L+Hua2GATYVjilJ22A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } }, - "node_modules/@next/eslint-plugin-next": { - "version": "14.2.9", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.9.tgz", - "integrity": "sha512-tmLXuDNfPTqoFuSfsd9Q4R96SS/UCKTPtBnnR+cKDcbh8xZU+126vZnRWH1WEpOmS4Vl2Hy/X6SPmgOGZzn+hA==", - "dev": true, + "node_modules/@mui/material": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.1.1.tgz", + "integrity": "sha512-b+eULldTqtqTCbN++2BtBWCir/1LwEYw+2mIlOt2GiEUh1EBBw4/wIukGKKNt3xrCZqRA80yLLkV6tF61Lq3cA==", "dependencies": { - "glob": "10.3.10" + "@babel/runtime": "^7.25.6", + "@mui/core-downloads-tracker": "^6.1.1", + "@mui/system": "^6.1.1", + "@mui/types": "^7.2.17", + "@mui/utils": "^6.1.1", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.11", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^18.3.1", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material-pigment-css": "^6.1.1", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } } }, - "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.12", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.12.tgz", - "integrity": "sha512-crHJ9UoinXeFbHYNok6VZqjKnd8rTd7K3Z2zpyzF1ch7vVNKmhjv/V7EHxep3ILoN8JB9AdRn/EtVVyG9AkCXw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@mui/material/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "node_modules/@mui/private-theming": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.1.1.tgz", + "integrity": "sha512-JlrjIdhyZUtewtdAuUsvi3ZnO0YS49IW4Mfz19ZWTlQ0sDGga6LNPVwHClWr2/zJK2we2BQx9/i8M32rgKuzrg==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/utils": "^6.1.1", + "prop-types": "^15.8.1" + }, "engines": { - "node": ">= 10" + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@next/swc-darwin-x64": { - "version": "14.2.12", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.12.tgz", - "integrity": "sha512-JbEaGbWq18BuNBO+lCtKfxl563Uw9oy2TodnN2ioX00u7V1uzrsSUcg3Ep9ce+P0Z9es+JmsvL2/rLphz+Frcw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@mui/styled-engine": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.1.1.tgz", + "integrity": "sha512-HJyIoMpFb11fnHuRtUILOXgq6vj4LhIlE8maG4SwP/W+E5sa7HFexhnB3vOMT7bKys4UKNxhobC8jwWxYilGsA==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@emotion/cache": "^11.13.1", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, "engines": { - "node": ">= 10" + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } } }, - "node_modules/@next/swc-linux-arm64-gnu": { + "node_modules/@mui/system": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.1.1.tgz", + "integrity": "sha512-PaYsCz2tUOcpu3T0okDEsSuP/yCDIj9JZ4Tox1JovRSKIjltHpXPsXZSGr3RiWdtM1MTQMFMCZzu0+CKbyy+Kw==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/private-theming": "^6.1.1", + "@mui/styled-engine": "^6.1.1", + "@mui/types": "^7.2.17", + "@mui/utils": "^6.1.1", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.2.17", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.17.tgz", + "integrity": "sha512-oyumoJgB6jDV8JFzRqjBo2daUuHpzDjoO/e3IrRhhHo/FxJlaVhET6mcNrKHUq2E+R+q3ql0qAtvQ4rfWHhAeQ==", + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.1.1.tgz", + "integrity": "sha512-HlRrgdJSPbYDXPpoVMWZV8AE7WcFtAk13rWNWAEVWKSanzBBkymjz3km+Th/Srowsh4pf1fTSP1B0L116wQBYw==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/types": "^7.2.17", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "node_modules/@mui/x-charts": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-7.18.0.tgz", + "integrity": "sha512-XvCX6sBj2aRw7MZcOPjKTEIwhj4j+ixw256bArQScSd+Y2BuHxAyfl/L6NPPWamckAPqJwjQ678jFH2s5t1f1w==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/utils": "^5.16.6", + "@mui/x-charts-vendor": "7.18.0", + "@mui/x-internals": "7.18.0", + "@react-spring/rafz": "^9.7.4", + "@react-spring/web": "^9.7.4", + "clsx": "^2.1.1", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14 || ^6.0.0", + "@mui/system": "^5.15.14 || ^6.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/x-charts-vendor": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@mui/x-charts-vendor/-/x-charts-vendor-7.18.0.tgz", + "integrity": "sha512-YPL7SP6W7t9jBIrK8WjmCtW/YoUmgr0BA7j2QE9bKX4VJLEUU498fEKik0ZJZyzyR7ov0MD3m7S+YCw1o5sqkw==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@types/d3-color": "^3.1.3", + "@types/d3-delaunay": "^6.0.4", + "@types/d3-interpolate": "^3.0.4", + "@types/d3-scale": "^4.0.8", + "@types/d3-shape": "^3.1.6", + "@types/d3-time": "^3.0.3", + "d3-color": "^3.1.0", + "d3-delaunay": "^6.0.4", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.2.0", + "d3-time": "^3.1.0", + "delaunator": "^5.0.1", + "robust-predicates": "^3.0.2" + } + }, + "node_modules/@mui/x-charts/node_modules/@mui/utils": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.6.tgz", + "integrity": "sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/types": "^7.2.15", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/x-charts/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "node_modules/@mui/x-internals": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.18.0.tgz", + "integrity": "sha512-lzCHOWIR0cAIY1bGrWSprYerahbnH5C31ql/2OWCEjcngL2NAV1M6oKI2Vp4HheqzJ822c60UyWyapvyjSzY/A==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/utils": "^5.16.6" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0" + } + }, + "node_modules/@mui/x-internals/node_modules/@mui/utils": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.6.tgz", + "integrity": "sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/types": "^7.2.15", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/x-internals/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "node_modules/@musinsa/ui": { + "resolved": "src/packages/ui", + "link": true + }, + "node_modules/@musinsa/utils": { + "resolved": "src/packages/utils", + "link": true + }, + "node_modules/@next/env": { + "version": "14.2.12", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.12.tgz", + "integrity": "sha512-3fP29GIetdwVIfIRyLKM7KrvJaqepv+6pVodEbx0P5CaMLYBtx+7eEg8JYO5L9sveJO87z9eCReceZLi0hxO1Q==" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.9.tgz", + "integrity": "sha512-tmLXuDNfPTqoFuSfsd9Q4R96SS/UCKTPtBnnR+cKDcbh8xZU+126vZnRWH1WEpOmS4Vl2Hy/X6SPmgOGZzn+hA==", + "dev": true, + "dependencies": { + "glob": "10.3.10" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.12.tgz", + "integrity": "sha512-crHJ9UoinXeFbHYNok6VZqjKnd8rTd7K3Z2zpyzF1ch7vVNKmhjv/V7EHxep3ILoN8JB9AdRn/EtVVyG9AkCXw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.12.tgz", + "integrity": "sha512-JbEaGbWq18BuNBO+lCtKfxl563Uw9oy2TodnN2ioX00u7V1uzrsSUcg3Ep9ce+P0Z9es+JmsvL2/rLphz+Frcw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { "version": "14.2.12", "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.12.tgz", "integrity": "sha512-qBy7OiXOqZrdp88QEl2H4fWalMGnSCrr1agT/AVDndlyw2YJQA89f3ttR/AkEIP9EkBXXeGl6cC72/EZT5r6rw==", @@ -781,6 +1517,15 @@ "node": ">=14" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@radix-ui/primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", @@ -816,6 +1561,97 @@ } } }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", + "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "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": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.2.tgz", + "integrity": "sha512-/i0fl686zaJbDQLNKrkCbMyDm6FQMt4jg323k7HuqitoANm9sE23Ql8yOK3Wusk34HSLKDChhMux05FnP6KUkw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-presence": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-use-size": "1.1.0" + }, + "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-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "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-checkbox/node_modules/@radix-ui/react-presence": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", + "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "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-collapsible": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.0.tgz", @@ -973,19 +1809,63 @@ } } }, - "node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz", - "integrity": "sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==", + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.2.tgz", + "integrity": "sha512-GVZMR+eqK8/Kes0a36Qrv+i20bAPXSn8rCBTHx30w+3ECnR5o3xixAlqcVaYvLeyKUsm0aqyhWfmUcqufM8nYA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-menu": "2.1.2", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-controllable-state": "1.1.0" + }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@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-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "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-guards": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz", + "integrity": "sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==", + "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.0", @@ -1036,6 +1916,367 @@ } } }, + "node_modules/@radix-ui/react-menu": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.2.tgz", + "integrity": "sha512-lZ0R4qR2Al6fZ4yCCZzu/ReTFrylHFxIqy7OezIpWF4bL0o9biKo0pFIvkaew3TyZ9Fy5gYVrR5zCGZBVbO1zg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-collection": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.0", + "@radix-ui/react-portal": "1.1.2", + "@radix-ui/react-presence": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-roving-focus": "1.1.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.6.0" + }, + "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-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "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-menu/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", + "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" + }, + "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-focus-guards": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", + "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", + "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-menu/node_modules/@radix-ui/react-portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz", + "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "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-presence": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", + "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "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/react-remove-scroll": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz", + "integrity": "sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.6", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.2.tgz", + "integrity": "sha512-u2HRUyWW+lOiA2g0Le0tMmT55FGOEWHwPFt1EPfbLly7uXQExFo5duNKqG2DzmFXIdqOeNd+TpE8baHWJCyP9w==", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.0", + "@radix-ui/react-portal": "1.1.2", + "@radix-ui/react-presence": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.6.0" + }, + "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-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "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/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", + "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" + }, + "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-focus-guards": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", + "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", + "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/node_modules/@radix-ui/react-portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz", + "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "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-presence": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", + "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "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/react-remove-scroll": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz", + "integrity": "sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.6", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", + "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-rect": "1.1.0", + "@radix-ui/react-use-size": "1.1.0", + "@radix-ui/rect": "1.1.0" + }, + "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": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.1.tgz", @@ -1104,10 +2345,42 @@ } } }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz", + "integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-collection": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0" + }, + "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.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.0" }, @@ -1121,10 +2394,73 @@ } } }, - "node_modules/@radix-ui/react-use-callback-ref": { + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "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.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", + "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "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.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "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.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", - "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz", + "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==", + "license": "MIT", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -1135,12 +2471,12 @@ } } }, - "node_modules/@radix-ui/react-use-controllable-state": { + "node_modules/@radix-ui/react-use-rect": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", - "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", + "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" + "@radix-ui/rect": "1.1.0" }, "peerDependencies": { "@types/react": "*", @@ -1152,12 +2488,12 @@ } } }, - "node_modules/@radix-ui/react-use-escape-keydown": { + "node_modules/@radix-ui/react-use-size": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", - "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", + "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" + "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", @@ -1169,18 +2505,84 @@ } } }, - "node_modules/@radix-ui/react-use-layout-effect": { + "node_modules/@radix-ui/rect": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", - "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", + "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==" + }, + "node_modules/@react-icons/all-files": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@react-icons/all-files/-/all-files-4.1.0.tgz", + "integrity": "sha512-hxBI2UOuVaI3O/BhQfhtb4kcGn9ft12RWAFVMUeNjqqhLsHvFtzIkFaptBJpFDANTKoDfdVoHTKZDlwKCACbMQ==", + "license": "MIT", "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "react": "*" + } + }, + "node_modules/@react-spring/animated": { + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.4.tgz", + "integrity": "sha512-7As+8Pty2QlemJ9O5ecsuPKjmO0NKvmVkRR1n6mEotFgWar8FKuQt2xgxz3RTgxcccghpx1YdS1FCdElQNexmQ==", + "dependencies": { + "@react-spring/shared": "~9.7.4", + "@react-spring/types": "~9.7.4" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/core": { + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.4.tgz", + "integrity": "sha512-GzjA44niEJBFUe9jN3zubRDDDP2E4tBlhNlSIkTChiNf9p4ZQlgXBg50qbXfSXHQPHak/ExYxwhipKVsQ/sUTw==", + "dependencies": { + "@react-spring/animated": "~9.7.4", + "@react-spring/shared": "~9.7.4", + "@react-spring/types": "~9.7.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-spring/donate" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/rafz": { + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.4.tgz", + "integrity": "sha512-mqDI6rW0Ca8IdryOMiXRhMtVGiEGLIO89vIOyFQXRIwwIMX30HLya24g9z4olDvFyeDW3+kibiKwtZnA4xhldA==" + }, + "node_modules/@react-spring/shared": { + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.4.tgz", + "integrity": "sha512-bEPI7cQp94dOtCFSEYpxvLxj0+xQfB5r9Ru1h8OMycsIq7zFZon1G0sHrBLaLQIWeMCllc4tVDYRTLIRv70C8w==", + "dependencies": { + "@react-spring/rafz": "~9.7.4", + "@react-spring/types": "~9.7.4" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/types": { + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.4.tgz", + "integrity": "sha512-iQVztO09ZVfsletMiY+DpT/JRiBntdsdJ4uqk3UJFhrhS8mIC9ZOZbmfGSRs/kdbNPQkVyzucceDicQ/3Mlj9g==" + }, + "node_modules/@react-spring/web": { + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.4.tgz", + "integrity": "sha512-UMvCZp7I5HCVIleSa4BwbNxynqvj+mJjG2m20VO2yPoi2pnCYANy58flvz9v/YcXTAvsmL655FV3pm5fbr6akA==", + "dependencies": { + "@react-spring/animated": "~9.7.4", + "@react-spring/core": "~9.7.4", + "@react-spring/shared": "~9.7.4", + "@react-spring/types": "~9.7.4" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/@rtsao/scc": { @@ -1353,6 +2755,83 @@ "tslib": "^2.4.0" } }, + "node_modules/@tanstack/react-table": { + "version": "8.20.5", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.20.5.tgz", + "integrity": "sha512-WEHopKw3znbUZ61s9i0+i9g8drmDo6asTWbrQh8Us63DAk/M0FkmIqERew6P71HI75ksZ2Pxyuf4vvKh9rAkiA==", + "license": "MIT", + "dependencies": { + "@tanstack/table-core": "8.20.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/@tanstack/table-core": { + "version": "8.20.5", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.20.5.tgz", + "integrity": "sha512-P9dF7XbibHph2PFRz8gfBKEXEY/HJPOhym8CHmjF8y3q5mWpKx9xtZapXQUWCgkqvsK0R46Azuz+VaxD4Xl+Tg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==" + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", + "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", + "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==" + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1374,17 +2853,20 @@ "undici-types": "~6.19.2" } }, + "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==" + }, "node_modules/@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "devOptional": true + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, "node_modules/@types/react": { "version": "18.3.5", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.5.tgz", "integrity": "sha512-WeqMfGJLGuLCqHGYRGHxnKrXcTitc6L/nBUWfWPcTarG3t9PsquqUMuVeXZeca+mglY4Vo5GZjCi0A3Or2lnxA==", - "devOptional": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -1399,6 +2881,14 @@ "@types/react": "*" } }, + "node_modules/@types/react-transition-group": { + "version": "4.4.11", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz", + "integrity": "sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", @@ -1971,6 +3461,20 @@ "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==", + "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", @@ -2154,7 +3658,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -2331,6 +3834,34 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "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==" + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "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/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2358,8 +3889,112 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "devOptional": true + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } }, "node_modules/damerau-levenshtein": { "version": "1.0.8", @@ -2430,7 +4065,6 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, "dependencies": { "ms": "^2.1.3" }, @@ -2526,6 +4160,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, "node_modules/detect-node-es": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", @@ -2565,6 +4207,15 @@ "node": ">=6.0.0" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2594,6 +4245,14 @@ "node": ">=10.13.0" } }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-abstract": { "version": "1.23.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", @@ -2822,7 +4481,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, "engines": { "node": ">=10" }, @@ -3380,6 +5038,11 @@ "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==" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -3806,6 +5469,14 @@ "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==", + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -3847,7 +5518,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -3898,6 +5568,14 @@ "node": ">= 0.4" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -3938,6 +5616,11 @@ "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==" + }, "node_modules/is-async-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", @@ -4404,12 +6087,28 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, + "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==" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -4672,8 +6371,7 @@ "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/mz": { "version": "2.7.0", @@ -5120,7 +6818,6 @@ "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, "dependencies": { "callsites": "^3.0.0" }, @@ -5128,6 +6825,23 @@ "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==", + "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", @@ -5178,7 +6892,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -5396,7 +7109,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, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -5462,11 +7174,19 @@ "react": "^18.3.1" } }, + "node_modules/react-icons": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.4.0.tgz", + "integrity": "sha512-7eltJxgVt7X64oHh6wSWNwwbKTCtMfK35hcjvJS0yxEAhPM8oUKdS3+kqaW1vicIltw+kR2unHaa12S9pPALoQ==", + "license": "MIT", + "peerDependencies": { + "react": "*" + } + }, "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 + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-remove-scroll": { "version": "2.5.7", @@ -5513,6 +7233,15 @@ } } }, + "node_modules/react-spinners": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/react-spinners/-/react-spinners-0.14.1.tgz", + "integrity": "sha512-2Izq+qgQ08HTofCVEdcAQCXFEYfqTDdfeDQJeo/HHQiQJD4imOicNLhkfN2eh1NYEWVOX4D9ok2lhuDB0z3Aag==", + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", @@ -5535,6 +7264,21 @@ } } }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -5588,6 +7332,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", @@ -5626,7 +7375,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, "engines": { "node": ">=4" } @@ -5706,6 +7454,11 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + }, "node_modules/rollup": { "version": "3.29.4", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", @@ -6208,6 +7961,11 @@ } } }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -6339,6 +8097,14 @@ "node": ">=0.8" } }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -7110,7 +8876,15 @@ "src/app/admin": { "version": "0.0.1", "dependencies": { + "@emotion/react": "^11.13.3", + "@emotion/styled": "^11.13.0", + "@mui/material": "^6.1.1", + "@mui/x-charts": "^7.18.0", + "@radix-ui/react-checkbox": "^1.1.2", + "@radix-ui/react-dropdown-menu": "^2.1.2", + "@radix-ui/react-slot": "^1.1.0", "@shadcn/ui": "^0.0.4", + "@tanstack/react-table": "^8.20.5", "next": "^14.2.12", "react": "^18.3.1", "react-daum-postcode": "^3.1.3", diff --git a/package.json b/package.json index 1f3a8f9..79bbbe0 100644 --- a/package.json +++ b/package.json @@ -16,10 +16,14 @@ "@radix-ui/react-accordion": "^1.2.0", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-popover": "1.1.2", "@radix-ui/react-slot": "^1.1.0", + "@react-icons/all-files": "^4.1.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "lucide-react": "^0.439.0", + "react-icons": "^5.4.0", + "react-spinners": "^0.14.1", "tailwind-merge": "^2.5.2", "tailwindcss-animate": "^1.0.7", "zustand": "^4.5.5" diff --git a/src/app/admin/package.json b/src/app/admin/package.json index 0f66da6..54b2d5e 100644 --- a/src/app/admin/package.json +++ b/src/app/admin/package.json @@ -9,7 +9,15 @@ "lint": "next lint" }, "dependencies": { + "@emotion/react": "^11.13.3", + "@emotion/styled": "^11.13.0", + "@mui/material": "^6.1.1", + "@mui/x-charts": "^7.18.0", + "@radix-ui/react-checkbox": "^1.1.2", + "@radix-ui/react-dropdown-menu": "^2.1.2", + "@radix-ui/react-slot": "^1.1.0", "@shadcn/ui": "^0.0.4", + "@tanstack/react-table": "^8.20.5", "next": "^14.2.12", "react": "^18.3.1", "react-daum-postcode": "^3.1.3", diff --git a/src/app/admin/src/api/auth.ts b/src/app/admin/src/api/auth.ts new file mode 100644 index 0000000..412cc93 --- /dev/null +++ b/src/app/admin/src/api/auth.ts @@ -0,0 +1,69 @@ +import { useAuthenticatedFetch } from '../hooks/useAuthenticatedFetch'; + +interface LoginResponse { + code: number; + isSuccess: boolean; + message: string; + data: { + grantType: string; + accessToken: string; + refreshToken: string; + }; +} + +interface KakaoAddressDocument { + address_name: string; + // Add other properties if needed +} + +export const useAuthApi = () => { + const authFetch = useAuthenticatedFetch(); + + const login = async (email: string, password: string): Promise => { + const response = await fetch('http://taegnues.store:12324/admins/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ email, password }), + }); + if (!response.ok) { + throw new Error('Login failed'); + } + return response.json(); + }; + + // const logout = async () => { + // return authFetch('https://your-backend-api.com/logout', { method: 'POST' }); + // }; + + // const searchKakaoAddress = async (query: string): Promise => { + + // console.log("check query", query); + // console.log("check secret key", process.env.NEXT_PUBLIC_KAKAO_REST_API_KEY); + // const url = `https://dapi.kakao.com/v2/local/search/address.json?query=${encodeURIComponent(query)}&analyze_type=similar`; + + // try { + // const response = await fetch(url, { + // headers: { + // 'Authorization': `KakaoAK ${process.env.NEXT_PUBLIC_KAKAO_REST_API_KEY}` + // } + // }); + + // if (!response.ok) { + // throw new Error('Network response was not ok'); + // } + + // const data = await response.json(); + + // console.log("from api check data", data); + // return data.documents.map((doc: KakaoAddressDocument) => doc.address_name); + // } catch (error) { + // console.error('Error fetching address data:', error); + // return []; + // } + // }; + + + + + return { login }; +}; diff --git a/src/app/admin/src/app/(routes)/(landing)/page.tsx b/src/app/admin/src/app/(routes)/(landing)/page.tsx index 3fbeb52..428a899 100644 --- a/src/app/admin/src/app/(routes)/(landing)/page.tsx +++ b/src/app/admin/src/app/(routes)/(landing)/page.tsx @@ -3,13 +3,14 @@ import { useState } from "react"; import { useRouter } from "next/navigation"; import { Button, Input } from "@/packages/ui/src/index"; -import { useAuthApi } from "../../../../../buyer/src/api/auth"; -import { useAuthStore } from "../../../../../buyer/src/lib/store"; +import { useAuthApi } from "../../../api/auth"; +import { useAuthStore } from "../../../lib/store"; +import { AiOutlineMail, AiOutlineLock } from "react-icons/ai"; // 아이콘 추가 -export default function ManagerLoginPage() { +function ManagerLoginPage() { const router = useRouter(); const { login } = useAuthApi(); - const { setAccessToken } = useAuthStore(); + const { setAccessToken, setRefreshToken } = useAuthStore(); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); @@ -18,60 +19,71 @@ export default function ManagerLoginPage() { try { const data = await login(email, password); setAccessToken(data.data.accessToken); - router.push("/home"); + setRefreshToken(data.data.refreshToken); + router.push("/main"); } catch (error) { + window.alert("로그인에 실패했습니다."); console.error("Login error:", error); } }; return ( - <> -
-

로그인

-
-
e.preventDefault()}> -
- - setEmail(e.target.value)} - /> -
+
+
+

로그인

-
- - setPassword(e.target.value)} - /> -
+ e.preventDefault()}> +
+ +
+ {" "} + setEmail(e.target.value)} + /> +
+
+ +
+ +
+ {" "} + setPassword(e.target.value)} + /> +
+
- - - + + +
+
); -} \ No newline at end of file +} + +export default ManagerLoginPage; diff --git a/src/app/admin/src/app/(routes)/brand/[slug]/page.tsx b/src/app/admin/src/app/(routes)/brand/[slug]/page.tsx new file mode 100644 index 0000000..ad04903 --- /dev/null +++ b/src/app/admin/src/app/(routes)/brand/[slug]/page.tsx @@ -0,0 +1,111 @@ +"use client"; + +import { Button } from "@/packages/ui/src/index"; +import { SlArrowLeft } from "react-icons/sl"; +import { IoHomeOutline } from "react-icons/io5"; +import { MdCheckCircle, MdCancel } from "react-icons/md"; // 체크 및 취소 아이콘 추가 +import Image from "next/image"; + +import adidasDetail1 from "@/app/admin/src/assets/adidasDetail.jpg"; +// import adidasDetail2 from ("@/app/admin/src/assets/adidasDetail2.jpg"); +import clothesLogo from "@/app/admin/src/assets/adidasLogo.png"; + +import { useRouter } from "next/navigation"; +import { useEffect, useState } from "react"; + +const BrandDetail: React.FC = () => { + const router = useRouter(); + const [isApproved, setIsApproved] = useState(null); + + useEffect(() => { + if (typeof window !== "undefined") { + const queryParams = new URLSearchParams(window.location.search); + const approvedStatus = queryParams.get("isApproved"); + setIsApproved(approvedStatus); + } + }, []); + + const handleClick = () => { + router.back(); + }; + + const handleHomeClick = () => { + router.push("/main"); + }; + + return ( + <> +
+ + + + +
+ +
+ {/* 스크롤 가능한 영역 */} +
+ shoesImg + + {/* 브랜드 및 로고 */} +
+

+ 아디다스 +

+
+ + {/* 사업자 정보 */} +
+ brandLogo +

아디다스

+

독일 since 1949

+

+ 스포츠 라이프스타일은 라커룸 밖에서도 계속됩니다. 1920년부터 + 독일의 헤르초게나우라흐에서 스포츠 슈즈를 만들던 + 아디다스(ADIDAS)는 이러한 철학을 토대로 경기장에서부터 거리에 + 이르기까지 모두가 즐길 수 있는 '스포츠 라이프스타일'의 개념을 + 처음으로 도입한 브랜드입니다. 스포츠 영역의 다양한 요소를 일상의 + 영역으로 가져오는 아디다스는 이를 통해 전 세계의 트렌드를 주도하고 + 있으며, 지금도 여전히 자신의 다양한 모습을 보여주고 싶어하는 + 소비자와 직접 소통하며 함께 혁신적인 트렌드를 만들고 있습니다. +

+
+ + {/* 승인/거부 버튼 */} +
+ {isApproved === "PENDING" && ( + <> + + + + )} +
+
+
+ + ); +}; + +export default BrandDetail; diff --git a/src/app/admin/src/app/(routes)/brand/detail/page.tsx b/src/app/admin/src/app/(routes)/brand/detail/page.tsx deleted file mode 100644 index dbbe1de..0000000 --- a/src/app/admin/src/app/(routes)/brand/detail/page.tsx +++ /dev/null @@ -1,42 +0,0 @@ -'use client'; - -import { Button } from "@/packages/ui/src/index"; -import Image from "next/image"; -import Logo from "@/app/admin/src/assets/smallLogo.png"; - -import { useRouter } from "next/navigation"; - -const BrandDetail: React.FC = () => { - const router = useRouter(); - - return ( - <> -
- logo router.push('/main')} - /> -
-
-
- 브랜드 이미지 -
-
- -
-
-
-

브랜드명

-
- - - ); -}; - -export default BrandDetail; diff --git a/src/app/admin/src/app/(routes)/brand/page.tsx b/src/app/admin/src/app/(routes)/brand/page.tsx index 3d7a05d..ddf4b37 100644 --- a/src/app/admin/src/app/(routes)/brand/page.tsx +++ b/src/app/admin/src/app/(routes)/brand/page.tsx @@ -1,105 +1,148 @@ -'use client'; -import { Button } from "@/packages/ui/src/index"; -import Image from "next/image"; -import Logo from "@/app/admin/src/assets/smallLogo.png"; +"use client"; -import { useRouter } from "next/navigation"; +import LogoBar from "../../../components/LogoBar"; +import MultiItem from "../../../components/MultiItem"; +import FooterBar from "../../../components/FooterBar"; +import { useState, useEffect, useRef } from "react"; +import { useAuthenticatedFetch } from "../../../hooks/useAuthenticatedFetch"; +import { useAuthStore } from "../../../lib/store"; + +interface brandsDataType { + brandId: number; + brandName: string; + authorityStatus: string; +} const BrandEnrollmentRequestPage: React.FC = () => { - const router = useRouter(); + const [scope, setScope] = useState("all"); + const [pageNo, setPageNo] = useState(0); + const [isLastPage, setIsLastPage] = useState(false); + const [brandsData, setBrandsData] = useState([]); + const [isLoading, setIsLoading] = useState(true); // 로딩 상태 추가 + const { authFetch } = useAuthenticatedFetch(); + const accessToken = useAuthStore((state) => state.accessToken); + const trigger = useRef(null); + const [isReHydrated, setIsRehydrated] = useState(false); + + useEffect(() => { + const checkRehydration = async () => { + const storedState = localStorage.getItem("auth-storage"); + if (storedState) { + setIsRehydrated(true); + } + }; + checkRehydration(); + }, []); + + useEffect(() => { + if (!isReHydrated || !accessToken) { + return; + } + const fetchInitialData = async () => { + setPageNo(0); + setIsLastPage(false); + setIsLoading(true); + + let baseUrl = `http://taegnues.store:12324/admins/brand-requests?authorityStatus`; + if (scope === "true") baseUrl += "=APPROVED"; + else if (scope === "wait") baseUrl += "=PENDING"; + else if (scope === "false") baseUrl += "=DENIED"; + + const fetchUrl = baseUrl + `&pageNo=0`; + + const response = await authFetch(fetchUrl, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + throw new Error("Failed to fetch data"); + } + + const resultData = await response.json(); + setBrandsData(resultData.data || []); + setIsLoading(false); + }; + + fetchInitialData(); + }, [isReHydrated, scope, accessToken]); + + useEffect(() => { + if (!isReHydrated || !accessToken || !trigger.current) return; + + const observer = new IntersectionObserver( + async (entries) => { + const element = entries[0]; + if ( + element.isIntersecting && + !isLoading && + !isLastPage && + trigger.current + ) { + setIsLoading(true); + + let baseUrl = `http://taegnues.store:12324/admins/brand-requests?authorityStatus`; + if (scope === "true") baseUrl += "=APPROVED"; + else if (scope === "wait") baseUrl += "=PENDING"; + else if (scope === "true") baseUrl += "=DENIED"; + const fetchUrl = baseUrl + `&pageNo=${pageNo + 1}`; + + const response = await authFetch(fetchUrl, { method: "GET" }); + + if (!response.ok) throw new Error("Failed to fetch data..."); + + const resultData = await response.json(); + const newBrandList = resultData.data; + + if (newBrandList.length > 0) { + setBrandsData((prevState) => [...prevState, ...newBrandList]); + setPageNo((prev) => prev + 1); + } else { + setIsLastPage(true); + } + + setIsLoading(false); + } + }, + { + threshold: 1.0, + } + ); + + observer.observe(trigger.current); + + return () => { + if (trigger.current) observer.disconnect(); + }; + }, [isReHydrated, accessToken, pageNo, scope, isLoading, isLastPage]); return ( <> -
- logo router.push('/main')} - /> -
-
-
-
- 등록 -
허가됨 -
-

- 브랜드 -
- 요청 1 -

-
-
-
- 등록 -
허가됨 -
-

- 브랜드 -
- 요청 2 -

-
-
-
- 등록 -
허가됨 -
-

- 브랜드 -
- 요청 3 -

-
-
-
- 등록 -
허가됨 -
-

- 브랜드 -
- 요청 4 -

-
-
-
- 등록 -
대기 중 -
-

- 브랜드 -
- 요청 5 -

- - -
-
-
- 등록 -
거부됨 + +
+ {isLoading ? ( +
+

Loading...

-

- 브랜드 -
- 요청 6 -

-
+ ) : ( + <> +
+ {brandsData.map((item, index) => ( + + ))} +
+ + + )}
-
-
    -
  • 전체 상품
  • -
  • 허가 상품
  • -
  • 허가 대기 상품
  • -
  • 미허가 상품
  • -
-
); }; diff --git a/src/app/admin/src/app/(routes)/layout.tsx b/src/app/admin/src/app/(routes)/layout.tsx index b0168d9..3b40915 100644 --- a/src/app/admin/src/app/(routes)/layout.tsx +++ b/src/app/admin/src/app/(routes)/layout.tsx @@ -1,16 +1,19 @@ -import { cn } from "@/packages/utils/src/index"; +"use client"; // 이 파일도 클라이언트 컴포넌트로 설정 + +import { useLoading } from "../../hooks/useLoading"; // 올바른 경로로 수정 +import LoadingPage from "../Loading"; // 로딩 페이지 컴포넌트 가져오기 export default function RootLayout({ children, -}: Readonly<{ +}: { children: React.ReactNode; -}>) { +}) { + const nowLoading = useLoading(); + return ( <> -
- {children} +
+ {nowLoading ? : children}
); diff --git a/src/app/admin/src/app/(routes)/main/page.tsx b/src/app/admin/src/app/(routes)/main/page.tsx index bcdbb92..b3a395a 100644 --- a/src/app/admin/src/app/(routes)/main/page.tsx +++ b/src/app/admin/src/app/(routes)/main/page.tsx @@ -1,8 +1,6 @@ -'use client'; +"use client"; import { Button } from "@/packages/ui/src/index"; -import Image from "next/image"; -import Logo from "@/app/admin/src/assets/smallLogo.png"; import { ChartNoAxesCombined } from "lucide-react"; import { PackageSearch } from "lucide-react"; import { Store } from "lucide-react"; @@ -10,50 +8,57 @@ import { Monitor } from "lucide-react"; import { useRouter } from "next/navigation"; +import LogoBar from "../../../components/LogoBar"; + const managerMainPage: React.FC = () => { const router = useRouter(); return ( <> -
- logo router.push('/main')} - /> -
+
-
-
-
-
diff --git a/src/app/admin/src/app/(routes)/mallStatus/page.tsx b/src/app/admin/src/app/(routes)/mallStatus/page.tsx index 0f6f5a2..6b88a09 100644 --- a/src/app/admin/src/app/(routes)/mallStatus/page.tsx +++ b/src/app/admin/src/app/(routes)/mallStatus/page.tsx @@ -1,62 +1,81 @@ -'use client'; +"use client"; -import React from "react"; -import Image from "next/image"; -import Logo from "@/app/admin/src/assets/smallLogo.png"; -import { useRouter } from "next/navigation"; +import React, { useState } from "react"; -const shoppingMallStatusPage: React.FC = () => { - const router = useRouter(); +import LogoBar from "../../../components/LogoBar"; +import DataFilterButton from "../../../components/DataFilterButton"; +import TickPlacementBars from "../../../components/Chart"; +import { DataTableDemo } from "../../../components/DataTable"; + +type filterCategory = "count" | "money"; + +const ShoppingMallStatusPage: React.FC = () => { + const [category, setCategory] = useState("money"); return ( <> -
- logo router.push("/main")} - /> -
-
-
-
- chart -
-
-

- 판매자 판매 현황 -

-
-
-
-
- chart -
-
-

- 쇼핑몰 영업이익 현황 -

-
-
-
-
- chart -
-
-

- 쇼핑몰 보유 자산 -

-
-
-
-
+ +
-

데이터 필터링

+ {category === "money" && ( + <> +
+ {/* 판매자 판매 현황 섹션 */} +
+
+

+ 판매자 판매 현황 +

+ +
+
+ + {/* 쇼핑몰 영업이익 현황 섹션 */} +
+
+

+ 쇼핑몰 영업이익 현황 +

+ +
+
+ + {/* 쇼핑몰 보유 자산 섹션 */} +
+
+

+ 쇼핑몰 보유 자산 +

+ +
+
+
+ + )} + + {category === "count" && ( + <> +
+
+

+ 쇼핑몰 전체 영업 건수 현황 +

+ +
+
+
+ +
+ + )} +
+ {/* 데이터 필터링 섹션 */} +
+
); }; -export default shoppingMallStatusPage; +export default ShoppingMallStatusPage; diff --git a/src/app/admin/src/app/(routes)/product/[slug]/page.tsx b/src/app/admin/src/app/(routes)/product/[slug]/page.tsx new file mode 100644 index 0000000..adab6ad --- /dev/null +++ b/src/app/admin/src/app/(routes)/product/[slug]/page.tsx @@ -0,0 +1,157 @@ +"use client"; + +import { Button } from "@/packages/ui/src/index"; +import { useParams } from "next/navigation"; +import { useEffect, useState } from "react"; +import { useRouter } from "next/navigation"; + +import { SlArrowLeft } from "react-icons/sl"; +import { SlArrowDown } from "react-icons/sl"; +import { SlArrowUp } from "react-icons/sl"; +import { IoHomeOutline } from "react-icons/io5"; +import { MdCheckCircle, MdCancel } from "react-icons/md"; // 체크 및 취소 아이콘 추가 +import Image from "next/image"; + +import shoesImg from "@/app/admin/src/assets/shoes.jpg"; +import clothesLogo from "@/app/admin/src/assets/adidasLogo.png"; +import backShoes1 from "@/app/admin/src/assets/backShoes1.jpg"; +import backShoes2 from "@/app/admin/src/assets/backShoes2.jpg"; + +const ProductDetailPage: React.FC = () => { + const { params } = useParams(); + const [isApproved, setIsApproved] = useState(null); + const [showMore, setShowMore] = useState(false); + + const router = useRouter(); + + useEffect(() => { + if (typeof window !== "undefined") { + const queryParams = new URLSearchParams(window.location.search); + const approvedStatus = queryParams.get("isApproved"); + setIsApproved(approvedStatus); + } + }, []); + + const handleClick = () => { + router.back(); + }; + + const handleHomeClick = () => { + router.push("/main"); + }; + + const handleShowMore = () => { + setShowMore(!showMore); + }; + + const arrowComponent = showMore ? : ; + + return ( + <> +
+ + + + +
+
+ {/* 스크롤 가능한 영역 */} +
+ shoesImg + + {/* 브랜드 및 로고 */} +
+
+ clothesLogo +
+

+ 아디다스 +

+
+ + {/* 상품명 및 가격 */} +
+

+ 러닝슈즈 Runner 5A13 +

+

+ 129,000원 +

+
+ +
+ +
+ + {showMore && ( +
+ backShoes1 + backShoes2 +
+ )} + + {/* 사업자 정보 */} +
+

사업자 정보

+
+

(주) 아디다스 | 대표자 : 홍길동

+

주소 : 서울특별시 성동구 아차산로 13길

+

사업자 등록 번호 : 000-11-22222(사업자 정보 확인)

+
+

+ 당사는 고객님이 현금 결제한 금액에 대해 우리은행과 채무지급보증 + 계약을 체결하여 안전거래를 보장하고 있습니다 +

+
+ + {/* 승인/거부 버튼 */} +
+ {isApproved === "PENDING" && ( + <> + + + + )} +
+
+
+ + ); +}; + +export default ProductDetailPage; diff --git a/src/app/admin/src/app/(routes)/product/detail/page.tsx b/src/app/admin/src/app/(routes)/product/detail/page.tsx deleted file mode 100644 index cd11185..0000000 --- a/src/app/admin/src/app/(routes)/product/detail/page.tsx +++ /dev/null @@ -1,35 +0,0 @@ -'use client'; - -import { Button } from "@/packages/ui/src/index"; -import Image from "next/image"; -import Logo from "@/app/admin/src/assets/smallLogo.png"; - -import { useRouter } from "next/navigation"; - -const ProductDetailPage: React.FC = () => { - const router = useRouter(); - - return ( - <> -
- logo router.push('/main')} - /> -
-
- 상품 1에 대한 분석 화면 - - -
- - ); -}; - -export default ProductDetailPage; diff --git a/src/app/admin/src/app/(routes)/product/page.tsx b/src/app/admin/src/app/(routes)/product/page.tsx index 68dfb25..dbe6f45 100644 --- a/src/app/admin/src/app/(routes)/product/page.tsx +++ b/src/app/admin/src/app/(routes)/product/page.tsx @@ -1,94 +1,148 @@ -'use client'; +"use client"; -import { Button } from "@/packages/ui/src/index"; -import Image from "next/image"; -import Logo from "@/app/admin/src/assets/smallLogo.png"; +import LogoBar from "../../../components/LogoBar"; +import FooterBar from "../../../components/FooterBar"; +import MultiItem from "../../../components/MultiItem"; +import { useEffect, useRef, useState } from "react"; +import { useAuthenticatedFetch } from "../../../hooks/useAuthenticatedFetch"; +import { useAuthStore } from "../../../lib/store"; -import { useRouter } from "next/navigation"; +interface productsDataType { + productId: number; + productName: string; + authorityStatus: string; +} const ProductEnrollmentRequestPage: React.FC = () => { - const router = useRouter(); + const [scope, setScope] = useState("all"); + const [pageNo, setPageNo] = useState(0); + const [isLastPage, setIsLastPage] = useState(false); + const [productsData, setProductsData] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [isRehydrated, setIsRehydrated] = useState(false); // 상태 복원 여부 + const { authFetch } = useAuthenticatedFetch(); + const accessToken = useAuthStore((state) => state.accessToken); + const trigger = useRef(null); + + // zustand 상태 복원 여부 확인 + useEffect(() => { + const checkRehydration = async () => { + const storedState = localStorage.getItem("auth-storage"); + if (storedState) { + setIsRehydrated(true); + } + }; + checkRehydration(); + }, []); + + // 초기 데이터 로드 + useEffect(() => { + if (!isRehydrated || !accessToken) return; // 상태 복원이 완료되지 않으면 요청 X + + const fetchInitialData = async () => { + setPageNo(0); + setIsLastPage(false); + setIsLoading(true); + + let baseUrl = `http://taegnues.store:12324/admins/product-requests`; + if (scope === "true") baseUrl += `/approved`; + else if (scope === "wait") baseUrl += `/pending`; + else if (scope === "false") baseUrl += `/denied`; + + const fetchUrl = baseUrl + `?pageNo=0`; + const response = await authFetch(fetchUrl, { + method: "GET", + headers: { "Content-Type": "application/json" }, + }); + + if (!response.ok) throw new Error("Failed to fetch initial data..."); + + const resultData = await response.json(); + setProductsData(resultData.data || []); + setIsLoading(false); + }; + + fetchInitialData(); + }, [isRehydrated, scope, accessToken]); + + // 무한 스크롤 데이터 로드 + useEffect(() => { + if (!isRehydrated || !accessToken || !trigger.current) return; + + const observer = new IntersectionObserver( + async (entries) => { + const element = entries[0]; + if ( + element.isIntersecting && + !isLoading && + !isLastPage && + trigger.current + ) { + setIsLoading(true); + + let baseUrl = `http://taegnues.store:12324/admins/product-requests`; + if (scope === "true") baseUrl += `/approved`; + else if (scope === "wait") baseUrl += `/pending`; + else if (scope === "false") baseUrl += `/denied`; + + const fetchUrl = baseUrl + `?pageNo=${pageNo + 1}`; + const response = await authFetch(fetchUrl, { method: "GET" }); + + if (!response.ok) throw new Error("Failed to fetch data..."); + + const resultData = await response.json(); + const newProductList = resultData.data; + + if (newProductList.length > 0) { + setProductsData((prev) => [...prev, ...newProductList]); + setPageNo((prev) => prev + 1); + } else { + setIsLastPage(true); + } + + setIsLoading(false); + } + }, + { threshold: 1.0 } + ); + + observer.observe(trigger.current); + + return () => { + if (trigger.current) observer.disconnect(); + }; + }, [isRehydrated, accessToken, pageNo, scope, isLoading, isLastPage]); return ( <> -
- logo router.push('/main')} - /> -
-
-
-
- 등록 -
허가됨 -
-

- 상품 1 -

-
-
-
- 등록 -
허가됨 -
-

- 상품 2 -

-
-
-
- 등록 -
허가됨 -
-

- 상품 3 -

-
-
-
- 등록 -
허가됨 -
-

- 상품 4 -

-
-
-
- 등록 -
대기 중 -
-

- 상품 5 -

- - -
-
-
- 등록 -
거부됨 + +
+ {isLoading && productsData.length === 0 ? ( +
+

Loading...

-

- 상품 6 -

-
+ ) : ( + <> +
+ {productsData.map((item, index) => ( + + ))} +
+ {isLoading && ( +
+

Loading...

+
+ )} + + + )}
-
-
    -
  • 전체 상품
  • -
  • 허가 상품
  • -
  • 허가 대기 상품
  • -
  • 미허가 상품
  • -
-
); }; diff --git a/src/app/admin/src/app/(routes)/review/page.tsx b/src/app/admin/src/app/(routes)/review/page.tsx index 852e9d3..94c04c6 100644 --- a/src/app/admin/src/app/(routes)/review/page.tsx +++ b/src/app/admin/src/app/(routes)/review/page.tsx @@ -1,118 +1,99 @@ "use client"; -import React from "react"; - -import { Button } from "@/packages/ui/src/index"; -import Image from "next/image"; -import Logo from "@/app/admin/src/assets/smallLogo.png"; +import React, { useEffect, useState } from "react"; import { useRouter } from "next/navigation"; +import { useAuthStore } from "../../../lib/store"; +import { useAuthenticatedFetch } from "../../../hooks/useAuthenticatedFetch"; + +import ReviewBox from "../../../components/ReviewBox"; + +import LogoBar from "../../../components/LogoBar"; + +interface ReviewData { + reviewId: number; + author: string; + content: string; + rating: number; + likeCount: number; + reviewImageDTO: { + reviewImageId: number; + originalImageName: string; + path: string; + }; + productId: number; + productName: string; +} const ReviewMonitoringPage: React.FC = () => { - const router = useRouter(); + const { authFetch } = useAuthenticatedFetch(); + const { accessToken } = useAuthStore(); + const [isReHydrated, setIsRehydrated] = useState(false); + const [reviewData, setReviewData] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const checkRehydration = async () => { + const storedState = localStorage.getItem("auth-storage"); + if (storedState) { + setIsRehydrated(true); + } + }; + checkRehydration(); + }, []); + + useEffect(() => { + if (!isReHydrated || !accessToken) { + return; + } + const fetchReviews = async () => { + try { + setLoading(true); + const fetchResponse = await authFetch( + "http://taegnues.store:12324/admins/reviews", + { + headers: { + "Content-Type": "application/json", + }, + method: "GET", + } + ); + + if (!fetchResponse.ok) { + throw new Error("Fail to fetch data..."); + } + + const resultData = await fetchResponse.json(); + console.log(resultData); + setReviewData(resultData.data); + } catch (error: any) { + setError(error.message); + } finally { + setLoading(false); + } + }; + fetchReviews(); + }, [isReHydrated, accessToken]); return ( <> -
- logo router.push("/main")} - /> -
-
-
-
-
-

프로필 사진

-
-
-

구매했던 상품

-
-
-
-

- 후기 -

-
-
-
-
-

좋아요 수

-
- -
-
-
-
-

프로필 사진

-
-
-

구매했던 상품

-
-
-
-

- 후기 -

-
-
-
-
-

좋아요 수

-
- -
-
-
-
-

프로필 사진

-
-
-

구매했던 상품

-
-
-
-

- 후기 -

-
-
-
-
-

좋아요 수

-
- -
-
-
-
-

프로필 사진

-
-
-

구매했던 상품

-
-
-
-

- 후기 -

-
-
-
-
-

좋아요 수

-
- + +
+
+ {reviewData?.map((review, index) => ( + + ))}
diff --git a/src/app/admin/src/app/Loading.tsx b/src/app/admin/src/app/Loading.tsx new file mode 100644 index 0000000..72cb410 --- /dev/null +++ b/src/app/admin/src/app/Loading.tsx @@ -0,0 +1,12 @@ +import { FadeLoader } from "react-spinners"; + +const LoadingPage = () => { + return ( +
+

잠시만 기다려주세요.

+ +
+ ); +}; + +export default LoadingPage; diff --git a/src/app/admin/src/app/layout.tsx b/src/app/admin/src/app/layout.tsx index ef63919..615bcc8 100644 --- a/src/app/admin/src/app/layout.tsx +++ b/src/app/admin/src/app/layout.tsx @@ -1,6 +1,6 @@ import type { Metadata } from "next"; import localFont from "next/font/local"; -import { cn } from "@/packages/utils/src/index" +import { cn } from "@/packages/utils/src/index"; import "./globals.css"; const geistSans = localFont({ @@ -15,8 +15,8 @@ const geistMono = localFont({ }); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "Grow Mall", + description: "그로우몰", }; export default function RootLayout({ @@ -27,7 +27,8 @@ export default function RootLayout({ return ( diff --git a/src/app/admin/src/assets/adidasDetail.jpg b/src/app/admin/src/assets/adidasDetail.jpg new file mode 100644 index 0000000..399b10e Binary files /dev/null and b/src/app/admin/src/assets/adidasDetail.jpg differ diff --git a/src/app/admin/src/assets/adidasDetail2.jpg b/src/app/admin/src/assets/adidasDetail2.jpg new file mode 100644 index 0000000..caeaeed Binary files /dev/null and b/src/app/admin/src/assets/adidasDetail2.jpg differ diff --git a/src/app/admin/src/assets/adidasLogo.png b/src/app/admin/src/assets/adidasLogo.png new file mode 100644 index 0000000..1524ad3 Binary files /dev/null and b/src/app/admin/src/assets/adidasLogo.png differ diff --git a/src/app/admin/src/assets/backShoes1.jpg b/src/app/admin/src/assets/backShoes1.jpg new file mode 100644 index 0000000..33662a1 Binary files /dev/null and b/src/app/admin/src/assets/backShoes1.jpg differ diff --git a/src/app/admin/src/assets/backShoes2.jpg b/src/app/admin/src/assets/backShoes2.jpg new file mode 100644 index 0000000..c03ee81 Binary files /dev/null and b/src/app/admin/src/assets/backShoes2.jpg differ diff --git a/src/app/admin/src/assets/clothes.jpg b/src/app/admin/src/assets/clothes.jpg new file mode 100644 index 0000000..31fa3ed Binary files /dev/null and b/src/app/admin/src/assets/clothes.jpg differ diff --git a/src/app/admin/src/assets/shoes.jpg b/src/app/admin/src/assets/shoes.jpg new file mode 100644 index 0000000..f85fbfe Binary files /dev/null and b/src/app/admin/src/assets/shoes.jpg differ diff --git a/src/app/admin/src/assets/smallLogo.webp b/src/app/admin/src/assets/smallLogo.webp new file mode 100644 index 0000000..580f679 Binary files /dev/null and b/src/app/admin/src/assets/smallLogo.webp differ diff --git a/src/app/admin/src/components/Chart.tsx b/src/app/admin/src/components/Chart.tsx new file mode 100644 index 0000000..98c765e --- /dev/null +++ b/src/app/admin/src/components/Chart.tsx @@ -0,0 +1,153 @@ +import * as React from "react"; +import Stack from "@mui/material/Stack"; +import FormControl from "@mui/material/FormControl"; +import FormLabel from "@mui/material/FormLabel"; +import RadioGroup from "@mui/material/RadioGroup"; +import FormControlLabel from "@mui/material/FormControlLabel"; +import Radio from "@mui/material/Radio"; +import { BarChart } from "@mui/x-charts/BarChart"; +import { axisClasses } from "@mui/x-charts/ChartsAxis"; +import { + dataset, + valueFormatter_count, + valueFormatter_money, +} from "../dataset/dummy"; + +type TickParamsSelectorProps = { + tickPlacement: "end" | "start" | "middle" | "extremities"; + tickLabelPlacement: "tick" | "middle"; + setTickPlacement: React.Dispatch< + React.SetStateAction<"end" | "start" | "middle" | "extremities"> + >; + setTickLabelPlacement: React.Dispatch< + React.SetStateAction<"tick" | "middle"> + >; +}; + +function TickParamsSelector({ + tickPlacement, + tickLabelPlacement, + setTickPlacement, + setTickLabelPlacement, +}: TickParamsSelectorProps) { + return ( + + + + tickPlacement + + + setTickPlacement( + event.target.value as "start" | "end" | "middle" | "extremities" + ) + } + > + } label="start" /> + } label="end" /> + } label="middle" /> + } + label="extremities" + /> + + + + + tickLabelPlacement + + + setTickLabelPlacement(event.target.value as "tick" | "middle") + } + > + } label="tick" /> + } label="middle" /> + + + + ); +} + +const chartSetting_money = { + yAxis: [ + { + label: "Sales Volume ($)", + }, + ], + series: [ + { dataKey: "seoul", valueFormatter: valueFormatter_money, color: "black" }, + ], // 바 색상을 검정색으로 지정 + height: 300, + sx: { + [`& .${axisClasses.directionY} .${axisClasses.label}`]: { + transform: "translateX(-10px)", + }, + }, +}; + +const chartSetting_count = { + yAxis: [ + { + label: "Number of Sales", + }, + ], + series: [ + { dataKey: "seoul", valueFormatter: valueFormatter_count, color: "black" }, + ], // 바 색상을 검정색으로 지정 + height: 300, + sx: { + [`& .${axisClasses.directionY} .${axisClasses.label}`]: { + transform: "translateX(-10px)", + }, + }, +}; + +type unitType = "money" | "count"; + +export default function TickPlacementBars({ unit }: { unit: unitType }) { + const [tickPlacement, setTickPlacement] = React.useState< + "start" | "end" | "middle" | "extremities" + >("middle"); + const [tickLabelPlacement, setTickLabelPlacement] = React.useState< + "middle" | "tick" + >("middle"); + + let chartSetting; + + if (unit === "money") { + chartSetting = chartSetting_money; + } else { + chartSetting = chartSetting_count; + } + + return ( +
+ +
+ ); +} diff --git a/src/app/admin/src/components/DataFilterButton.tsx b/src/app/admin/src/components/DataFilterButton.tsx new file mode 100644 index 0000000..919bf3a --- /dev/null +++ b/src/app/admin/src/components/DataFilterButton.tsx @@ -0,0 +1,47 @@ +import React from "react"; +import * as Popover from "@radix-ui/react-popover"; +import { Button } from "@/packages/ui/src"; + +type filterCategory = "count" | "money"; + +interface DataFilterButtonProps { + setCategory: (category: filterCategory) => void; +} + +const DataFilterButton: React.FC = ({ setCategory }) => ( + + + + + + +
+ + + + + + +
+ +
+
+
+); + +export default DataFilterButton; diff --git a/src/app/admin/src/components/DataTable.tsx b/src/app/admin/src/components/DataTable.tsx new file mode 100644 index 0000000..f5a1a83 --- /dev/null +++ b/src/app/admin/src/components/DataTable.tsx @@ -0,0 +1,246 @@ +"use client"; + +import * as React from "react"; +import { + ColumnDef, + ColumnFiltersState, + SortingState, + VisibilityState, + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable, +} from "@tanstack/react-table"; +import { ArrowUpDown, ChevronDown, MoreHorizontal } from "lucide-react"; + +import clothesLogo from "@/app/admin/src/assets/adidasLogo.png"; + +import Image from "next/image"; +import { Button } from "./ui/button"; +import { Checkbox } from "./ui/checkbox"; +import { + DropdownMenu, + DropdownMenuCheckboxItem, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "./ui/dropdown-menu"; +import { Input } from "./ui/input"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "./ui/table"; + +const data: Payment[] = [ + { + id: "m5gr84i9", + amount: 316, + brand: "아디다스", + }, + { + id: "3u1reuv4", + amount: 242, + brand: "나이키", + }, + { + id: "derv1ws0", + amount: 837, + brand: "푸마", + }, + { + id: "5kma53ae", + amount: 874, + brand: "뉴발란스", + }, + { + id: "bhqecj4p", + amount: 721, + brand: "미즈노", + }, +]; + +export type Payment = { + id: string; + amount: number; + brand: string; +}; + +export const columns: ColumnDef[] = [ + { + accessorKey: "brand", + header: ({ column }) => { + return ( + + ); + }, + cell: ({ row }) => ( +
+ +
+ clothesLogo +
+
{" "} + {row.getValue("brand")} +
+ ), + }, + { + accessorKey: "amount", + header: ({ column }) => { + return ( +
+ +
+ ); + }, + cell: ({ row }) => { + const amount = parseFloat(row.getValue("amount")); + + return
{amount}
; + }, + }, +]; + +export function DataTableDemo() { + const [sorting, setSorting] = React.useState([]); + const [columnFilters, setColumnFilters] = React.useState( + [] + ); + const [columnVisibility, setColumnVisibility] = + React.useState({}); + const [rowSelection, setRowSelection] = React.useState({}); + + const table = useReactTable({ + data, + columns, + onSortingChange: setSorting, + onColumnFiltersChange: setColumnFilters, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getSortedRowModel: getSortedRowModel(), + getFilteredRowModel: getFilteredRowModel(), + onColumnVisibilityChange: setColumnVisibility, + onRowSelectionChange: setRowSelection, + state: { + sorting, + columnFilters, + columnVisibility, + rowSelection, + }, + }); + + return ( +
+
+ + table.getColumn("brand")?.setFilterValue(event.target.value) + } + className="max-w-sm" + /> + + + + + + {table + .getAllColumns() + .filter((column) => column.getCanHide()) + .map((column) => { + return ( + + column.toggleVisibility(!!value) + } + > + {column.id} + + ); + })} + + +
+
+ + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => { + return ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext() + )} + + ); + })} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext() + )} + + ))} + + )) + ) : ( + + + No results. + + + )} + +
+
+
+ ); +} diff --git a/src/app/admin/src/components/FooterBar.tsx b/src/app/admin/src/components/FooterBar.tsx new file mode 100644 index 0000000..e158b39 --- /dev/null +++ b/src/app/admin/src/components/FooterBar.tsx @@ -0,0 +1,50 @@ +"use client"; + +import React, { useState } from "react"; + +interface FooterPropsType { + category: string; + scope: string; + setScope: React.Dispatch>; + className?: string; +} + +const FooterBar: React.FC = ({ + category, + scope, + setScope, + className, +}) => { + const categoryName = + category === "product" ? "상품" : category === "brand" ? "브랜드" : ""; + + return ( +
+
    + {["all", "true", "wait", "false"].map((item) => ( +
  • + +
  • + ))} +
+
+ ); +}; + +export default FooterBar; diff --git a/src/app/admin/src/components/LogoBar.tsx b/src/app/admin/src/components/LogoBar.tsx index 4067cc9..55e1bd7 100644 --- a/src/app/admin/src/components/LogoBar.tsx +++ b/src/app/admin/src/components/LogoBar.tsx @@ -1,21 +1,49 @@ "use client"; +import React from "react"; import Image from "next/image"; -import Logo from "@/app/admin/src/assets/smallLogo.png"; +import Logo from "@/app/admin/src/assets/smallLogo.webp"; import { useRouter } from "next/navigation"; +import { MdLogout } from "react-icons/md"; +import { useAuthStore } from "../lib/store"; -const router = useRouter(); +const LogoBar: React.FC = () => { + const router = useRouter(); + const { accessToken, setAccessToken, setRefreshToken, clearStorage } = + useAuthStore(); -const LogoBar = () => { -
- logo router.push("/main")} - /> -
; + const handleLogout = () => { + setAccessToken(null); + setRefreshToken(null); + clearStorage(); + router.push("/"); + }; + return ( +
+ {/* 로고 */} +
+ logo router.push("/main")} + /> +
+ + {/* 메뉴 아이콘 */} + + {accessToken && ( +
  • + +
  • + )} +
    +
    + ); }; -export default LogoBar; +export default React.memo(LogoBar); diff --git a/src/app/admin/src/components/MultiItem.tsx b/src/app/admin/src/components/MultiItem.tsx new file mode 100644 index 0000000..3be6b6f --- /dev/null +++ b/src/app/admin/src/components/MultiItem.tsx @@ -0,0 +1,109 @@ +"use client"; + +import React, { forwardRef } from "react"; +import { Button } from "@/packages/ui/src"; +import { useRouter } from "next/navigation"; +import { useAuthenticatedFetch } from "../hooks/useAuthenticatedFetch"; +import Image from "next/image"; + +import adidasLogo from "@/app/admin/src/assets/adidasLogo.png"; + +interface ItemPropsType { + category: string; + id: number; + isApproved: string | null; + imageUrl?: string; +} + +const MultiItem = forwardRef( + ({ category, id, isApproved, imageUrl }, ref) => { + const router = useRouter(); + const { authFetch } = useAuthenticatedFetch(); + + const backgroundColor = + isApproved === "APPROVED" + ? "bg-gradient-to-r from-green-400 to-green-600" + : isApproved === "DENIED" + ? "bg-gradient-to-r from-red-500 to-red-700" + : "bg-gradient-to-r from-yellow-500 to-yellow-600"; + + const categoryName = + category === "product" ? ( + "상품" + ) : category === "brand" ? ( + <> + 브랜드 +
    + 요청 + + ) : ( + "" + ); + + const approveUrl = `http://taegnues.store:12324/admins/${category}-requests/${id}/approve`; + const denyUrl = `http://taegnues.store:12324/admins/${category}-requests/${id}/deny`; + + const handleChangeStatus = async (url: string) => { + try { + const response = await authFetch(url, { method: "PATCH" }); + + if (!response.ok) { + throw new Error("Failed to update status."); + } + + const data = await response.json(); + console.log("변경 성공:", data); + window.alert("허가 상태를 변경 완료했습니다! 새로고침 시 적용됩니다!"); + } catch (error) { + console.error("Error updating status:", error); + } + }; + + return ( +
    router.push(`/product/${id}`)} + ref={ref} + className="h-36 bg-gray-300 rounded-lg shadow-lg mb-10 transition-transform transform hover:scale-105 flex flex-col relative ml-7 mr-7" + > + {`${categoryName} +
    + 등록 +
    + {isApproved === "APPROVED" && "허가됨"} + {isApproved === "DENIED" && "거부됨"} + {isApproved === "PENDING" && "대기 중"} +
    + {isApproved === "PENDING" && ( +
    + + +
    + )} +
    + ); + } +); + +export default MultiItem; diff --git a/src/app/admin/src/components/ReviewBox.tsx b/src/app/admin/src/components/ReviewBox.tsx new file mode 100644 index 0000000..240657f --- /dev/null +++ b/src/app/admin/src/components/ReviewBox.tsx @@ -0,0 +1,107 @@ +import React, { useState } from "react"; +import { Button } from "@/packages/ui/src"; +import { Heart, Star } from "lucide-react"; +import Image from "next/image"; + +interface ReviewBoxProps { + reviewId: number; + author: string; + content: string; + rating: number; + likeCount: number; + imagePath: string; + imageName: string; + productName: string; +} + +const ReviewBox: React.FC = ({ + author, + content, + imageName, + imagePath, + likeCount, + productName, + rating, + reviewId, +}) => { + const [heartState, setHeartState] = useState(false); + + const DeleteReview = async () => { + try { + const fetchResponse = await fetch( + `http://taegnues.store:12324/admins/reviews/${reviewId}`, + { + method: "DELETE", + } + ); + + if (!fetchResponse.ok) { + throw new Error("Failed to delete review"); + } + + window.alert("리뷰가 성공적으로 삭제되었습니다"); + } catch (error) { + console.error(error); + window.alert("리뷰 삭제에 실패했습니다."); + } + }; + + const handleDeleteClick = async (e: React.MouseEvent) => { + const deleteCheck = window.confirm("리뷰를 삭제할까요?"); + if (deleteCheck) { + await DeleteReview(); + } + }; + + const handleClickHeart = () => { + setHeartState((prevState) => !prevState); + }; + + return ( +
    +
    + {imageName} +
    +
    +

    작성자: {author}

    +

    {productName}

    +

    {content}

    +
    +
    +
    + + {likeCount} +
    +
    + + {rating} +
    + +
    +
    + ); +}; + +export default ReviewBox; diff --git a/src/app/admin/src/components/ui/button.tsx b/src/app/admin/src/components/ui/button.tsx new file mode 100644 index 0000000..d986764 --- /dev/null +++ b/src/app/admin/src/components/ui/button.tsx @@ -0,0 +1,56 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "../../lib/utils"; + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + } +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/src/app/admin/src/components/ui/checkbox.tsx b/src/app/admin/src/components/ui/checkbox.tsx new file mode 100644 index 0000000..b725422 --- /dev/null +++ b/src/app/admin/src/components/ui/checkbox.tsx @@ -0,0 +1,30 @@ +"use client" + +import * as React from "react" +import * as CheckboxPrimitive from "@radix-ui/react-checkbox" +import { Check } from "lucide-react" + +import { cn } from "../../lib/utils"; + +const Checkbox = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + +)) +Checkbox.displayName = CheckboxPrimitive.Root.displayName + +export { Checkbox } diff --git a/src/app/admin/src/components/ui/dropdown-menu.tsx b/src/app/admin/src/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..5061855 --- /dev/null +++ b/src/app/admin/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,200 @@ +"use client"; + +import * as React from "react"; +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; +import { Check, ChevronRight, Circle } from "lucide-react"; + +import { cn } from "../../lib/utils"; + +const DropdownMenu = DropdownMenuPrimitive.Root; + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; + +const DropdownMenuGroup = DropdownMenuPrimitive.Group; + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal; + +const DropdownMenuSub = DropdownMenuPrimitive.Sub; + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup; + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean; + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)); +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName; + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName; + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)); +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName; + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean; + } +>(({ className, inset, ...props }, ref) => ( + +)); +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName; + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)); +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName; + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)); +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName; + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean; + } +>(({ className, inset, ...props }, ref) => ( + +)); +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName; + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName; + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ); +}; +DropdownMenuShortcut.displayName = "DropdownMenuShortcut"; + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +}; diff --git a/src/app/admin/src/components/ui/input.tsx b/src/app/admin/src/components/ui/input.tsx new file mode 100644 index 0000000..fcbee8b --- /dev/null +++ b/src/app/admin/src/components/ui/input.tsx @@ -0,0 +1,25 @@ +import * as React from "react"; + +import { cn } from "../../lib/utils"; + +export interface InputProps + extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ); + } +); +Input.displayName = "Input"; + +export { Input }; diff --git a/src/app/admin/src/components/ui/table.tsx b/src/app/admin/src/components/ui/table.tsx new file mode 100644 index 0000000..e44e0a1 --- /dev/null +++ b/src/app/admin/src/components/ui/table.tsx @@ -0,0 +1,117 @@ +import * as React from "react"; + +import { cn } from "../../lib/utils"; + +const Table = React.forwardRef< + HTMLTableElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
    + + +)); +Table.displayName = "Table"; + +const TableHeader = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableHeader.displayName = "TableHeader"; + +const TableBody = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableBody.displayName = "TableBody"; + +const TableFooter = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + tr]:last:border-b-0", + className + )} + {...props} + /> +)); +TableFooter.displayName = "TableFooter"; + +const TableRow = React.forwardRef< + HTMLTableRowElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableRow.displayName = "TableRow"; + +const TableHead = React.forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( +
    +)); +TableHead.displayName = "TableHead"; + +const TableCell = React.forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableCell.displayName = "TableCell"; + +const TableCaption = React.forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
    +)); +TableCaption.displayName = "TableCaption"; + +export { + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption, +}; diff --git a/src/app/admin/src/dataset/dummy.ts b/src/app/admin/src/dataset/dummy.ts new file mode 100644 index 0000000..332d6a4 --- /dev/null +++ b/src/app/admin/src/dataset/dummy.ts @@ -0,0 +1,93 @@ +export const dataset = [ + { + london: 59, + paris: 57, + newYork: 86, + seoul: 21, + month: 'Jan', + }, + { + london: 50, + paris: 52, + newYork: 78, + seoul: 28, + month: 'Feb', + }, + { + london: 47, + paris: 53, + newYork: 106, + seoul: 41, + month: 'Mar', + }, + { + london: 54, + paris: 56, + newYork: 92, + seoul: 73, + month: 'Apr', + }, + { + london: 57, + paris: 69, + newYork: 92, + seoul: 99, + month: 'May', + }, + { + london: 60, + paris: 63, + newYork: 103, + seoul: 144, + month: 'June', + }, + { + london: 59, + paris: 60, + newYork: 105, + seoul: 319, + month: 'July', + }, + { + london: 65, + paris: 60, + newYork: 106, + seoul: 249, + month: 'Aug', + }, + { + london: 51, + paris: 51, + newYork: 95, + seoul: 131, + month: 'Sept', + }, + { + london: 60, + paris: 65, + newYork: 97, + seoul: 55, + month: 'Oct', + }, + { + london: 67, + paris: 64, + newYork: 76, + seoul: 48, + month: 'Nov', + }, + { + london: 61, + paris: 70, + newYork: 103, + seoul: 25, + month: 'Dec', + }, +]; + +export function valueFormatter_money(value: number | null) { + return `${value} $`; +} +export function valueFormatter_count(value: number | null) { + return `${value}`; +} \ No newline at end of file diff --git a/src/app/admin/src/hooks/useAuthenticatedFetch.ts b/src/app/admin/src/hooks/useAuthenticatedFetch.ts new file mode 100644 index 0000000..04ce594 --- /dev/null +++ b/src/app/admin/src/hooks/useAuthenticatedFetch.ts @@ -0,0 +1,31 @@ +import { useAuthStore } from '../lib/store'; +import { useRouter } from 'next/navigation'; + +export const useAuthenticatedFetch = () => { + const { accessToken, clearStorage } = useAuthStore(); + const router = useRouter(); + + const handleLogout = () => { + // setAccessToken(null); + // setRefreshToken(null); + clearStorage(); // 상태와 로컬스토리지 초기화 + }; + + const authFetch = async (url: string, options: RequestInit = {}) => { + const headers = new Headers(options.headers); + headers.set('Authorization', `Bearer ${accessToken}`); + + const response = await fetch(url, { ...options, headers }); + + if (response.status === 401) { + // useAuthStore.getState().logout(); + handleLogout(); + router.push('/'); + throw new Error('Token expired'); + } + + return response; + }; + + return { authFetch }; +}; \ No newline at end of file diff --git a/src/app/admin/src/hooks/useGetRequest.ts b/src/app/admin/src/hooks/useGetRequest.ts new file mode 100644 index 0000000..f20b667 --- /dev/null +++ b/src/app/admin/src/hooks/useGetRequest.ts @@ -0,0 +1,40 @@ +type statePropType = '' | 'approved' | 'pending' | 'denied'; + +interface GetRequestOptions { + pageNo?: number; +} + +const useGetRequest = (resourceType: string, state?: statePropType, options?: GetRequestOptions) => { // 상품 혹은 브랜드를 상태에 따라 다르게 get 할 수 있는 훅 + const getRequest = async () => { + try { + let url = `http://taegnues.store:12324/admins/${resourceType}`; + + if (resourceType === 'brand') { + const authorityStatus = state ? state.toUpperCase() : ''; + const pageNo = options?.pageNo ?? 0; + url += `?authorityStatus=${authorityStatus}&pageNo=${pageNo}`; + } else { //브랜드가 아닌 경우 + url += state ? `/${state}` : ''; + } + + const response = await fetch(url, { + method: 'GET', + }) + + if (!response.ok) { + throw new Error('Failed to fetch data...'); + } + + const data = await response.json(); + + return data; + } catch (error) { + console.error(error); + return null; + } + } + + return { getRequest }; +} + +export default useGetRequest; diff --git a/src/app/admin/src/hooks/useLoading.ts b/src/app/admin/src/hooks/useLoading.ts new file mode 100644 index 0000000..4803658 --- /dev/null +++ b/src/app/admin/src/hooks/useLoading.ts @@ -0,0 +1,24 @@ +"use client"; // 클라이언트 컴포넌트로 동작하게 설정 +import { useEffect, useState } from "react"; +import { usePathname } from "next/navigation"; + +export const useLoading = () => { + const [nowLoading, setNowLoading] = useState(false); + const pathName = usePathname(); + + useEffect(() => { + const handleStart = () => { + setNowLoading(true); + }; + + const handleEnd = () => { + setNowLoading(false); + }; + + handleStart(); + handleEnd(); + + }, [pathName]); + + return nowLoading; +}; diff --git a/src/app/admin/src/hooks/useRequestAction.ts b/src/app/admin/src/hooks/useRequestAction.ts new file mode 100644 index 0000000..9b8e955 --- /dev/null +++ b/src/app/admin/src/hooks/useRequestAction.ts @@ -0,0 +1,35 @@ +import { useCallback } from "react"; //허가, 거부 버튼 클릭 시 요청하는 훅 + +type ActionType = "approve" | "deny"; // approve와 deny만 허용 + +const useRequestAction = (resourceType: string, id?: string) => { + const handleAction = useCallback( + async (actionType: ActionType): Promise => { // 반환 타입을 Promise로 명시 + try { + const response = await fetch( + `http://taegnues.store:12324/admin/${resourceType}/${id ?? ''}/${actionType}`, + { + method: "PATCH", + } + ); + + if (!response.ok) { + throw new Error("Failed to fetch data..."); + } + + const alertMessage = + actionType === "approve" + ? "허가 상태로 변경하였습니다!" + : "미허가 상태로 변경하였습니다!"; + window.alert(alertMessage); + } catch (error) { + console.error(error); + } + }, + [resourceType, id] + ); + + return { handleAction }; +}; + +export default useRequestAction; diff --git a/src/app/admin/src/lib/store.ts b/src/app/admin/src/lib/store.ts new file mode 100644 index 0000000..fd46c50 --- /dev/null +++ b/src/app/admin/src/lib/store.ts @@ -0,0 +1,30 @@ +import { create } from 'zustand' +import { persist } from 'zustand/middleware' + +interface AuthState { + accessToken: string | null + refreshToken: string | null + setAccessToken: (token: string | null) => void + setRefreshToken: (token: string | null) => void + clearStorage: () => void // clearStorage 추가 +} + +export const useAuthStore = create( + persist( + (set, get) => ({ + accessToken: null, + refreshToken: null, + setAccessToken: (accessToken: string | null) => set(() => ({ accessToken })), + setRefreshToken: (refreshToken: string | null) => set(() => ({ refreshToken })), + clearStorage: () => { + // 상태 초기화 (토큰을 null로 설정) + set(() => ({ accessToken: null, refreshToken: null })) + // 로컬스토리지에서 persist된 상태도 초기화 + localStorage.removeItem('auth-storage') + } + }), + { + name: 'auth-storage' // 로컬스토리지에 저장할 키 + } + ) +) diff --git a/src/app/admin/src/lib/utils.ts b/src/app/admin/src/lib/utils.ts new file mode 100644 index 0000000..bd0c391 --- /dev/null +++ b/src/app/admin/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/src/app/admin/tailwind.config.ts b/src/app/admin/tailwind.config.ts index 70058f3..39d686c 100644 --- a/src/app/admin/tailwind.config.ts +++ b/src/app/admin/tailwind.config.ts @@ -1,84 +1,87 @@ import type { Config } from "tailwindcss"; const config: Config = { - darkMode: ["class"], - content: [ - "./src/**/*.{js,ts,jsx,tsx}", - "../../packages/ui/src/**/*.{js,ts,jsx,tsx}", - ], - theme: { - extend: { - colors: { - background: 'hsl(var(--background))', - foreground: 'hsl(var(--foreground))', - card: { - DEFAULT: 'hsl(var(--card))', - foreground: 'hsl(var(--card-foreground))' - }, - popover: { - DEFAULT: 'hsl(var(--popover))', - foreground: 'hsl(var(--popover-foreground))' - }, - primary: { - DEFAULT: 'hsl(var(--primary))', - foreground: 'hsl(var(--primary-foreground))' - }, - secondary: { - DEFAULT: 'hsl(var(--secondary))', - foreground: 'hsl(var(--secondary-foreground))' - }, - muted: { - DEFAULT: 'hsl(var(--muted))', - foreground: 'hsl(var(--muted-foreground))' - }, - accent: { - DEFAULT: 'hsl(var(--accent))', - foreground: 'hsl(var(--accent-foreground))' - }, - destructive: { - DEFAULT: 'hsl(var(--destructive))', - foreground: 'hsl(var(--destructive-foreground))' - }, - border: 'hsl(var(--border))', - input: 'hsl(var(--input))', - ring: 'hsl(var(--ring))', - chart: { - '1': 'hsl(var(--chart-1))', - '2': 'hsl(var(--chart-2))', - '3': 'hsl(var(--chart-3))', - '4': 'hsl(var(--chart-4))', - '5': 'hsl(var(--chart-5))' - } - }, - borderRadius: { - lg: 'var(--radius)', - md: 'calc(var(--radius) - 2px)', - sm: 'calc(var(--radius) - 4px)' - }, - keyframes: { - 'accordion-down': { - from: { - height: '0' - }, - to: { - height: 'var(--radix-accordion-content-height)' - } - }, - 'accordion-up': { - from: { - height: 'var(--radix-accordion-content-height)' - }, - to: { - height: '0' - } - } - }, - animation: { - 'accordion-down': 'accordion-down 0.2s ease-out', - 'accordion-up': 'accordion-up 0.2s ease-out' - } - } - }, - plugins: [require("tailwindcss-animate")], + darkMode: ["class"], + content: [ + "./src/**/*.{js,ts,jsx,tsx}", + "../../packages/ui/src/**/*.{js,ts,jsx,tsx}", + ], + theme: { + extend: { + fontFamily: { + musinsa: ['"Noto Sans KR", sans-serif'], + }, + colors: { + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))' + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))' + }, + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))' + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))' + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))' + }, + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))' + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))' + }, + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + chart: { + '1': 'hsl(var(--chart-1))', + '2': 'hsl(var(--chart-2))', + '3': 'hsl(var(--chart-3))', + '4': 'hsl(var(--chart-4))', + '5': 'hsl(var(--chart-5))' + } + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)' + }, + keyframes: { + 'accordion-down': { + from: { + height: '0' + }, + to: { + height: 'var(--radix-accordion-content-height)' + } + }, + 'accordion-up': { + from: { + height: 'var(--radix-accordion-content-height)' + }, + to: { + height: '0' + } + } + }, + animation: { + 'accordion-down': 'accordion-down 0.2s ease-out', + 'accordion-up': 'accordion-up 0.2s ease-out' + } + } + }, + plugins: [require("tailwindcss-animate")], }; export default config; diff --git a/src/app/seller/src/app/(routes)/(landing)/page.tsx b/src/app/seller/src/app/(routes)/(landing)/page.tsx index cada2f9..ce466f6 100644 --- a/src/app/seller/src/app/(routes)/(landing)/page.tsx +++ b/src/app/seller/src/app/(routes)/(landing)/page.tsx @@ -1,4 +1,3 @@ -import { Button } from "@/packages/ui/src/index"; import LoginForm from "../../../components/auth/LoginForm"; export default function LoginScreen() { @@ -7,31 +6,6 @@ export default function LoginScreen() {

    로그인

    - -
    - Or sign in with -
    -
    - -
    - - - -
    -
    - -
    ); } diff --git a/src/app/seller/src/app/(routes)/main/page.tsx b/src/app/seller/src/app/(routes)/main/page.tsx index 27a579d..26b0fa6 100644 --- a/src/app/seller/src/app/(routes)/main/page.tsx +++ b/src/app/seller/src/app/(routes)/main/page.tsx @@ -1,11 +1,13 @@ -'use client'; +"use client"; import React from "react"; import { Button } from "@/packages/ui/src/index"; import LogoBar from "../../../components/LogoBar"; - +import { PackageSearch } from "lucide-react"; +import { Store } from "lucide-react"; +import { Monitor } from "lucide-react"; const SellerMain: React.FC = () => { return ( @@ -32,17 +34,20 @@ const SellerMain: React.FC = () => {
    -
    -
    -
    @@ -51,4 +56,4 @@ const SellerMain: React.FC = () => { ); }; -export default SellerMain; \ No newline at end of file +export default SellerMain;