diff --git a/docker-compose.yml b/docker-compose.yml index 0d71335a..9480eb11 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -590,9 +590,8 @@ services: context: ./frontend dockerfile: Dockerfile.${ENVIRONMENT} args: - - NEXT_PUBLIC_API_URL=${FRONTEND_API_URL} - - NEXT_PUBLIC_WS_URL=${FRONTEND_WS_URL} - - NEXT_PUBLIC_ENVIRONMENT=${ENVIRONMENT} + - NODE_ENV=development + - VITE_API_URL=http://localhost:8000 image: bakery/dashboard:${IMAGE_TAG} container_name: bakery-dashboard restart: unless-stopped diff --git a/frontend/Dockerfile.development b/frontend/Dockerfile.development index 1d978b40..767ab5ae 100644 --- a/frontend/Dockerfile.development +++ b/frontend/Dockerfile.development @@ -1,18 +1,32 @@ +# Development Dockerfile FROM node:18-alpine +# Install curl for healthchecks +RUN apk add --no-cache curl + +# Set working directory WORKDIR /app -# Copy package files +# Copy package files first (better caching) COPY package*.json ./ -# Install dependencies +# Install all dependencies (including dev dependencies) RUN npm ci -# Copy application files +# Copy source code COPY . . -# Expose port +# Create non-root user for security +RUN addgroup -g 1001 -S nodejs +RUN adduser -S reactjs -u 1001 +USER reactjs + +# Expose port 3000 (Vite default) EXPOSE 3000 -# Start development server -CMD ["npm", "run", "dev"] \ No newline at end of file +# Add healthcheck +HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ + CMD curl -f http://localhost:3000/ || exit 1 + +# Start development server with host binding +CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"] \ No newline at end of file diff --git a/frontend/next.config.js b/frontend/next.config.js deleted file mode 100644 index e95f1b0e..00000000 --- a/frontend/next.config.js +++ /dev/null @@ -1,14 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = { - reactStrictMode: true, - swcMinify: true, - i18n: { - locales: ['es', 'en'], - defaultLocale: 'es', - }, - images: { - domains: ['bakeryforecast.es'], - }, -} - -module.exports = nextConfig \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json deleted file mode 100644 index 4e4a9996..00000000 --- a/frontend/package-lock.json +++ /dev/null @@ -1,6426 +0,0 @@ -{ - "name": "bakery-dashboard", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "bakery-dashboard", - "version": "1.0.0", - "dependencies": { - "@headlessui/react": "^2.0.0", - "@heroicons/react": "^2.0.18", - "@tailwindcss/forms": "^0.5.7", - "axios": "^1.6.0", - "chart.js": "^4.4.0", - "date-fns": "^2.30.0", - "framer-motion": "^10.16.4", - "jwt-decode": "^4.0.0", - "next": "14.0.0", - "react": "^18.2.0", - "react-chartjs-2": "^5.2.0", - "react-dom": "^18.2.0", - "react-hook-form": "^7.47.0", - "zustand": "^4.4.6" - }, - "devDependencies": { - "@types/node": "^20.8.0", - "@types/react": "^18.2.0", - "@types/react-dom": "^18.2.0", - "autoprefixer": "^10.4.16", - "eslint": "^8.52.0", - "eslint-config-next": "14.0.0", - "postcss": "^8.4.31", - "tailwindcss": "^3.3.5", - "typescript": "^5.2.2" - } - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@babel/runtime": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", - "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@emnapi/core": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz", - "integrity": "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.0.4", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", - "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz", - "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emotion/is-prop-valid": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", - "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", - "license": "MIT", - "optional": true, - "dependencies": { - "@emotion/memoize": "0.7.4" - } - }, - "node_modules/@emotion/memoize": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", - "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", - "license": "MIT", - "optional": true - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@floating-ui/core": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.2.tgz", - "integrity": "sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==", - "license": "MIT", - "dependencies": { - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/dom": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.2.tgz", - "integrity": "sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==", - "license": "MIT", - "dependencies": { - "@floating-ui/core": "^1.7.2", - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/react": { - "version": "0.26.28", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz", - "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==", - "license": "MIT", - "dependencies": { - "@floating-ui/react-dom": "^2.1.2", - "@floating-ui/utils": "^0.2.8", - "tabbable": "^6.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@floating-ui/react-dom": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.4.tgz", - "integrity": "sha512-JbbpPhp38UmXDDAu60RJmbeme37Jbgsm7NrHGgzYYFKmblzRUh6Pa641dII6LsjwF4XlScDrde2UAzDo/b9KPw==", - "license": "MIT", - "dependencies": { - "@floating-ui/dom": "^1.7.2" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@floating-ui/utils": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", - "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", - "license": "MIT" - }, - "node_modules/@headlessui/react": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.4.tgz", - "integrity": "sha512-lz+OGcAH1dK93rgSMzXmm1qKOJkBUqZf1L4M8TWLNplftQD3IkoEDdUFNfAn4ylsN6WOTVtWaLmvmaHOUk1dTA==", - "license": "MIT", - "dependencies": { - "@floating-ui/react": "^0.26.16", - "@react-aria/focus": "^3.20.2", - "@react-aria/interactions": "^3.25.0", - "@tanstack/react-virtual": "^3.13.9", - "use-sync-external-store": "^1.5.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "react": "^18 || ^19 || ^19.0.0-rc", - "react-dom": "^18 || ^19 || ^19.0.0-rc" - } - }, - "node_modules/@heroicons/react": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.2.0.tgz", - "integrity": "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==", - "license": "MIT", - "peerDependencies": { - "react": ">= 16 || ^19.0.0-rc" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", - "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", - "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.29", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", - "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@kurkle/color": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", - "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==", - "license": "MIT" - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", - "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" - } - }, - "node_modules/@next/env": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.0.0.tgz", - "integrity": "sha512-cIKhxkfVELB6hFjYsbtEeTus2mwrTC+JissfZYM0n+8Fv+g8ucUfOlm3VEDtwtwydZ0Nuauv3bl0qF82nnCAqA==", - "license": "MIT" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.0.0.tgz", - "integrity": "sha512-Ye37nNI09V3yt7pzuzSQtwlvuJ2CGzFszHXkcTHHZgNr7EhTMFLipn3VSJChy+e5+ahTdNApPphc3qCPUsn10A==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob": "7.1.7" - } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.0.tgz", - "integrity": "sha512-HQKi159jCz4SRsPesVCiNN6tPSAFUkOuSkpJsqYTIlbHLKr1mD6be/J0TvWV6fwJekj81bZV9V/Tgx3C2HO9lA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.0.tgz", - "integrity": "sha512-4YyQLMSaCgX/kgC1jjF3s3xSoBnwHuDhnF6WA1DWNEYRsbOOPWjcYhv8TKhRe2ApdOam+VfQSffC4ZD+X4u1Cg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.0.tgz", - "integrity": "sha512-io7fMkJ28Glj7SH8yvnlD6naIhRDnDxeE55CmpQkj3+uaA2Hko6WGY2pT5SzpQLTnGGnviK85cy8EJ2qsETj/g==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.0.tgz", - "integrity": "sha512-nC2h0l1Jt8LEzyQeSs/BKpXAMe0mnHIMykYALWaeddTqCv5UEN8nGO3BG8JAqW/Y8iutqJsaMe2A9itS0d/r8w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.0.tgz", - "integrity": "sha512-Wf+WjXibJQ7hHXOdNOmSMW5bxeJHVf46Pwb3eLSD2L76NrytQlif9NH7JpHuFlYKCQGfKfgSYYre5rIfmnSwQw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.0.tgz", - "integrity": "sha512-WTZb2G7B+CTsdigcJVkRxfcAIQj7Lf0ipPNRJ3vlSadU8f0CFGv/ST+sJwF5eSwIe6dxKoX0DG6OljDBaad+rg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.0.tgz", - "integrity": "sha512-7R8/x6oQODmNpnWVW00rlWX90sIlwluJwcvMT6GXNIBOvEf01t3fBg0AGURNKdTJg2xNuP7TyLchCL7Lh2DTiw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.0.tgz", - "integrity": "sha512-RLK1nELvhCnxaWPF07jGU4x3tjbyx2319q43loZELqF0+iJtKutZ+Lk8SVmf/KiJkYBc7Cragadz7hb3uQvz4g==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.0.tgz", - "integrity": "sha512-g6hLf1SUko+hnnaywQQZzzb3BRecQsoKkF3o/C+F+dOA4w/noVAJngUVkfwF0+2/8FzNznM7ofM6TGZO9svn7w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nolyfill/is-core-module": { - "version": "1.0.39", - "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", - "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.4.0" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@react-aria/focus": { - "version": "3.20.5", - "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.20.5.tgz", - "integrity": "sha512-JpFtXmWQ0Oca7FcvkqgjSyo6xEP7v3oQOLUId6o0xTvm4AD5W0mU2r3lYrbhsJ+XxdUUX4AVR5473sZZ85kU4A==", - "license": "Apache-2.0", - "dependencies": { - "@react-aria/interactions": "^3.25.3", - "@react-aria/utils": "^3.29.1", - "@react-types/shared": "^3.30.0", - "@swc/helpers": "^0.5.0", - "clsx": "^2.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", - "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" - } - }, - "node_modules/@react-aria/interactions": { - "version": "3.25.3", - "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.25.3.tgz", - "integrity": "sha512-J1bhlrNtjPS/fe5uJQ+0c7/jiXniwa4RQlP+Emjfc/iuqpW2RhbF9ou5vROcLzWIyaW8tVMZ468J68rAs/aZ5A==", - "license": "Apache-2.0", - "dependencies": { - "@react-aria/ssr": "^3.9.9", - "@react-aria/utils": "^3.29.1", - "@react-stately/flags": "^3.1.2", - "@react-types/shared": "^3.30.0", - "@swc/helpers": "^0.5.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", - "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" - } - }, - "node_modules/@react-aria/ssr": { - "version": "3.9.9", - "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.9.tgz", - "integrity": "sha512-2P5thfjfPy/np18e5wD4WPt8ydNXhij1jwA8oehxZTFqlgVMGXzcWKxTb4RtJrLFsqPO7RUQTiY8QJk0M4Vy2g==", - "license": "Apache-2.0", - "dependencies": { - "@swc/helpers": "^0.5.0" - }, - "engines": { - "node": ">= 12" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" - } - }, - "node_modules/@react-aria/utils": { - "version": "3.29.1", - "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.29.1.tgz", - "integrity": "sha512-yXMFVJ73rbQ/yYE/49n5Uidjw7kh192WNN9PNQGV0Xoc7EJUlSOxqhnpHmYTyO0EotJ8fdM1fMH8durHjUSI8g==", - "license": "Apache-2.0", - "dependencies": { - "@react-aria/ssr": "^3.9.9", - "@react-stately/flags": "^3.1.2", - "@react-stately/utils": "^3.10.7", - "@react-types/shared": "^3.30.0", - "@swc/helpers": "^0.5.0", - "clsx": "^2.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", - "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" - } - }, - "node_modules/@react-stately/flags": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.2.tgz", - "integrity": "sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==", - "license": "Apache-2.0", - "dependencies": { - "@swc/helpers": "^0.5.0" - } - }, - "node_modules/@react-stately/utils": { - "version": "3.10.7", - "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.7.tgz", - "integrity": "sha512-cWvjGAocvy4abO9zbr6PW6taHgF24Mwy/LbQ4TC4Aq3tKdKDntxyD+sh7AkSRfJRT2ccMVaHVv2+FfHThd3PKQ==", - "license": "Apache-2.0", - "dependencies": { - "@swc/helpers": "^0.5.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" - } - }, - "node_modules/@react-types/shared": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.30.0.tgz", - "integrity": "sha512-COIazDAx1ncDg046cTJ8SFYsX8aS3lB/08LDnbkH/SkdYrFPWDlXMrO/sUam8j1WWM+PJ+4d1mj7tODIKNiFog==", - "license": "Apache-2.0", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" - } - }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", - "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.12.0.tgz", - "integrity": "sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@swc/helpers": { - "version": "0.5.17", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", - "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" - } - }, - "node_modules/@tailwindcss/forms": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.10.tgz", - "integrity": "sha512-utI1ONF6uf/pPNO68kmN1b8rEwNXv3czukalo8VtJH8ksIkZXr3Q3VYudZLkCsDd4Wku120uF02hYK25XGPorw==", - "license": "MIT", - "dependencies": { - "mini-svg-data-uri": "^1.2.3" - }, - "peerDependencies": { - "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1" - } - }, - "node_modules/@tanstack/react-virtual": { - "version": "3.13.12", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.12.tgz", - "integrity": "sha512-Gd13QdxPSukP8ZrkbgS2RwoZseTTbQPLnQEn7HY/rqtM+8Zt95f7xKC7N0EsKs7aoz0WzZ+fditZux+F8EzYxA==", - "license": "MIT", - "dependencies": { - "@tanstack/virtual-core": "3.13.12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/@tanstack/virtual-core": { - "version": "3.13.12", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.12.tgz", - "integrity": "sha512-1YBOJfRHV4sXUmWsFSf5rQor4Ss82G8dQWLRbnk3GA4jeP8hQt1hxXh0tmflpC0dz3VgEv/1+qwPyLeWkQuPFA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", - "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.19.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz", - "integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/prop-types": { - "version": "15.7.15", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", - "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "18.3.23", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz", - "integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.7", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", - "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^18.0.0" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", - "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "dev": true, - "license": "ISC" - }, - "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", - "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", - "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", - "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", - "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", - "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", - "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", - "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", - "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", - "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", - "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", - "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", - "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", - "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", - "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", - "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", - "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.11" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", - "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", - "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", - "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "license": "MIT" - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", - "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.24.0", - "es-object-atoms": "^1.1.1", - "get-intrinsic": "^1.3.0", - "is-string": "^1.1.1", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", - "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-shim-unscopables": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", - "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", - "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/async-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" - }, - "node_modules/autoprefixer": { - "version": "10.4.21", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", - "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "browserslist": "^4.24.4", - "caniuse-lite": "^1.0.30001702", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.1.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.10.3", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.3.tgz", - "integrity": "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==", - "dev": true, - "license": "MPL-2.0", - "engines": { - "node": ">=4" - } - }, - "node_modules/axios": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", - "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/axobject-query": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", - "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.25.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", - "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001726", - "electron-to-chromium": "^1.5.173", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001727", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", - "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chart.js": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.0.tgz", - "integrity": "sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ==", - "license": "MIT", - "dependencies": { - "@kurkle/color": "^0.3.0" - }, - "engines": { - "pnpm": ">=8" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", - "license": "MIT" - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "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, - "license": "MIT" - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "license": "Apache-2.0" - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "license": "MIT" - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.189", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.189.tgz", - "integrity": "sha512-y9D1ntS1ruO/pZ/V2FtLE+JXLQe28XoRpZ7QCCo0T8LdQladzdcOVQZH/IWLVJvCw12OGMb6hYOeOAjntCmJRQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, - "node_modules/es-abstract": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", - "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", - "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.6", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "iterator.prototype": "^1.1.4", - "safe-array-concat": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", - "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-next": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.0.0.tgz", - "integrity": "sha512-jtXeE+/pGQ3h9n11QyyuPN50kO13GO5XvjU5ZRq6W+XTpOMjyobWmK2s7aowy0FtzA49krJzYzEU9s1RMwoJ6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@next/eslint-plugin-next": "14.0.0", - "@rushstack/eslint-patch": "^1.3.3", - "@typescript-eslint/parser": "^5.4.2 || ^6.0.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" - }, - "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0", - "typescript": ">=3.3.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", - "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@nolyfill/is-core-module": "1.0.39", - "debug": "^4.4.0", - "get-tsconfig": "^4.10.0", - "is-bun-module": "^2.0.0", - "stable-hash": "^0.0.5", - "tinyglobby": "^0.2.13", - "unrs-resolver": "^1.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-import-resolver-typescript" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*", - "eslint-plugin-import-x": "*" - }, - "peerDependenciesMeta": { - "eslint-plugin-import": { - "optional": true - }, - "eslint-plugin-import-x": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", - "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.32.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", - "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.9", - "array.prototype.findlastindex": "^1.2.6", - "array.prototype.flat": "^1.3.3", - "array.prototype.flatmap": "^1.3.3", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.1", - "hasown": "^2.0.2", - "is-core-module": "^2.16.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.1", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.9", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", - "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "aria-query": "^5.3.2", - "array-includes": "^3.1.8", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "^4.10.0", - "axobject-query": "^4.1.0", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "hasown": "^2.0.2", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "safe-regex-test": "^1.0.3", - "string.prototype.includes": "^2.0.1" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.37.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", - "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.3", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.2.1", - "estraverse": "^5.3.0", - "hasown": "^2.0.2", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.9", - "object.fromentries": "^2.0.8", - "object.values": "^1.2.1", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.12", - "string.prototype.repeat": "^1.0.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "5.0.0-canary-7118f5dd7-20230705", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz", - "integrity": "sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, - "license": "ISC" - }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/framer-motion": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.18.0.tgz", - "integrity": "sha512-oGlDh1Q1XqYPksuTD/usb0I70hq95OUzmL9+6Zd+Hs4XV0oaISBa/UUMSjYiq6m8EUF32132mOJ8xVZS+I0S6w==", - "license": "MIT", - "dependencies": { - "tslib": "^2.4.0" - }, - "optionalDependencies": { - "@emotion/is-prop-valid": "^0.8.2" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", - "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "license": "BSD-2-Clause" - }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-async-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bun-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", - "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.7.1" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-function": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", - "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-proto": "^1.0.0", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" - }, - "node_modules/iterator.prototype": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", - "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "get-proto": "^1.0.0", - "has-symbols": "^1.1.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jiti": { - "version": "1.21.7", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", - "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", - "license": "MIT", - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/jwt-decode": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", - "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", - "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dev": true, - "license": "MIT", - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "license": "MIT" - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mini-svg-data-uri": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", - "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", - "license": "MIT", - "bin": { - "mini-svg-data-uri": "cli.js" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "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, - "license": "MIT" - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-postinstall": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.2.tgz", - "integrity": "sha512-tWVJxJHmBWLy69PvO96TZMZDrzmw5KeiZBz3RHmiM2XZ9grBJ2WgMAFVVg25nqp3ZjTFUs2Ftw1JhscL3Teliw==", - "dev": true, - "license": "MIT", - "bin": { - "napi-postinstall": "lib/cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/napi-postinstall" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/next": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/next/-/next-14.0.0.tgz", - "integrity": "sha512-J0jHKBJpB9zd4+c153sair0sz44mbaCHxggs8ryVXSFBuBqJ8XdE9/ozoV85xGh2VnSjahwntBZZgsihL9QznA==", - "license": "MIT", - "dependencies": { - "@next/env": "14.0.0", - "@swc/helpers": "0.5.2", - "busboy": "1.6.0", - "caniuse-lite": "^1.0.30001406", - "postcss": "8.4.31", - "styled-jsx": "5.1.1", - "watchpack": "2.4.0" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=18.17.0" - }, - "optionalDependencies": { - "@next/swc-darwin-arm64": "14.0.0", - "@next/swc-darwin-x64": "14.0.0", - "@next/swc-linux-arm64-gnu": "14.0.0", - "@next/swc-linux-arm64-musl": "14.0.0", - "@next/swc-linux-x64-gnu": "14.0.0", - "@next/swc-linux-x64-musl": "14.0.0", - "@next/swc-win32-arm64-msvc": "14.0.0", - "@next/swc-win32-ia32-msvc": "14.0.0", - "@next/swc-win32-x64-msvc": "14.0.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "node_modules/next/node_modules/@swc/helpers": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz", - "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/next/node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, - "license": "MIT" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", - "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", - "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/own-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "license": "BlueOak-1.0.0" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "license": "MIT" - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "license": "MIT", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "license": "MIT", - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-load-config": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", - "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-nested": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", - "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "postcss-selector-parser": "^6.1.1" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "license": "MIT" - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-chartjs-2": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.0.tgz", - "integrity": "sha512-UfZZFnDsERI3c3CZGxzvNJd02SHjaSJ8kgW1djn65H1KK8rehwTjyrRKOG3VTMG8wtHZ5rgAO5oTHtHi9GCCmw==", - "license": "MIT", - "peerDependencies": { - "chart.js": "^4.1.1", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-hook-form": { - "version": "7.60.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.60.0.tgz", - "integrity": "sha512-SBrYOvMbDB7cV8ZfNpaiLcgjH/a1c7aK0lK+aNigpf4xWLO8q+o4tcvVurv3c4EOyzn/3dCsYt4GKD42VvJ/+A==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/react-hook-form" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17 || ^18 || ^19" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "license": "MIT", - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-push-apply": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stable-hash": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", - "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", - "dev": true, - "license": "MIT" - }, - "node_modules/stop-iteration-iterator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", - "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/string.prototype.includes": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", - "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", - "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "regexp.prototype.flags": "^1.5.3", - "set-function-name": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.repeat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", - "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", - "license": "MIT", - "dependencies": { - "client-only": "0.0.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/sucrase": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", - "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "^10.3.10", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/sucrase/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/sucrase/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sucrase/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tabbable": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", - "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", - "license": "MIT" - }, - "node_modules/tailwindcss": { - "version": "3.4.17", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", - "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.6.0", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.2", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.21.6", - "lilconfig": "^3.1.3", - "micromatch": "^4.0.8", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.4.47", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.2", - "postcss-nested": "^6.2.0", - "postcss-selector-parser": "^6.1.2", - "resolve": "^1.22.8", - "sucrase": "^3.35.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", - "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "license": "Apache-2.0" - }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/unrs-resolver": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", - "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "napi-postinstall": "^0.3.0" - }, - "funding": { - "url": "https://opencollective.com/unrs-resolver" - }, - "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.11.1", - "@unrs/resolver-binding-android-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-x64": "1.11.1", - "@unrs/resolver-binding-freebsd-x64": "1.11.1", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", - "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-musl": "1.11.1", - "@unrs/resolver-binding-wasm32-wasi": "1.11.1", - "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", - "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", - "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/use-sync-external-store": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", - "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "license": "MIT" - }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "license": "MIT", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "for-each": "^0.3.5", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/yaml": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", - "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zustand": { - "version": "4.5.7", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", - "integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==", - "license": "MIT", - "dependencies": { - "use-sync-external-store": "^1.2.2" - }, - "engines": { - "node": ">=12.7.0" - }, - "peerDependencies": { - "@types/react": ">=16.8", - "immer": ">=9.0.6", - "react": ">=16.8" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "immer": { - "optional": true - }, - "react": { - "optional": true - } - } - } - } -} diff --git a/frontend/package.json b/frontend/package.json index 1f248b69..1169cd2a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,39 +1,71 @@ { - "name": "bakery-dashboard", + "name": "pania-frontend", "version": "1.0.0", - "private": true, + "description": "AI-powered bakery demand forecasting platform for Madrid", + "type": "module", "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint", - "type-check": "tsc --noEmit" + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview", + "test": "vitest", + "test:ui": "vitest --ui", + "test:coverage": "vitest --coverage", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "lint:fix": "eslint . --ext ts,tsx --fix" }, "dependencies": { - "next": "14.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", - "chart.js": "^4.4.0", - "react-chartjs-2": "^5.2.0", - "axios": "^1.6.0", - "@tailwindcss/forms": "^0.5.7", + "react-router-dom": "^6.15.0", + "@reduxjs/toolkit": "^1.9.5", + "react-redux": "^8.1.2", + "i18next": "^23.4.4", + "react-i18next": "^13.1.2", + "i18next-browser-languagedetector": "^7.1.0", + "react-hook-form": "^7.45.4", + "@hookform/resolvers": "^3.3.1", + "zod": "^3.22.2", + "recharts": "^2.8.0", "date-fns": "^2.30.0", - "react-hook-form": "^7.47.0", - "zustand": "^4.4.6", - "@headlessui/react": "^2.0.0", - "@heroicons/react": "^2.0.18", - "framer-motion": "^10.16.4", - "jwt-decode": "^4.0.0" + "date-fns-tz": "^2.0.0", + "react-hot-toast": "^2.4.1", + "lucide-react": "^0.263.1", + "clsx": "^2.0.0", + "tailwind-merge": "^1.14.0" }, "devDependencies": { - "@types/node": "^20.8.0", - "@types/react": "^18.2.0", - "@types/react-dom": "^18.2.0", - "autoprefixer": "^10.4.16", - "eslint": "^8.52.0", - "eslint-config-next": "14.0.0", - "postcss": "^8.4.31", - "tailwindcss": "^3.3.5", - "typescript": "^5.2.2" - } + "@types/react": "^18.2.15", + "@types/react-dom": "^18.2.7", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "@vitejs/plugin-react": "^4.0.3", + "autoprefixer": "^10.4.14", + "eslint": "^8.45.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.3", + "postcss": "^8.4.27", + "tailwindcss": "^3.3.0", + "typescript": "^5.0.2", + "vite": "^4.4.5", + "vitest": "^0.34.1", + "@vitest/ui": "^0.34.1", + "@testing-library/react": "^13.4.0", + "@testing-library/jest-dom": "^5.17.0", + "@testing-library/user-event": "^14.4.3" + }, + "keywords": [ + "bakery", + "forecasting", + "ai", + "madrid", + "react", + "typescript", + "tailwind" + ], + "repository": { + "type": "git", + "url": "https://github.com/pania-es/frontend" + }, + "author": "PanIA Team", + "license": "MIT" } \ No newline at end of file diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js deleted file mode 100644 index 32cece0c..00000000 --- a/frontend/postcss.config.js +++ /dev/null @@ -1,7 +0,0 @@ -// postcss.config.js -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -}; \ No newline at end of file diff --git a/frontend/public/index.html b/frontend/public/index.html new file mode 100644 index 00000000..66ef8f1b --- /dev/null +++ b/frontend/public/index.html @@ -0,0 +1,170 @@ + + + + + + + + PanIA - Inteligencia Artificial para tu Panadería en Madrid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
🥖
+
Cargando PanIA...
+
+
+ + +
+ + + + + + + + \ No newline at end of file diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx new file mode 100644 index 00000000..5a1e12fc --- /dev/null +++ b/frontend/src/App.tsx @@ -0,0 +1,246 @@ +const [appState, setAppState] = useState({ + isAuthenticated: false, + isLoading: true, + user: null, + currentPage: 'landing' // 👈 Startimport React, { useState, useEffect } from 'react'; +import { Toaster } from 'react-hot-toast'; + +// Components +import LoadingSpinner from './components/ui/LoadingSpinner'; +import ErrorBoundary from './components/ErrorBoundary'; +import LandingPage from './pages/landing/LandingPage'; +import LoginPage from './pages/auth/LoginPage'; +import RegisterPage from './pages/auth/RegisterPage'; +import OnboardingPage from './pages/onboarding/OnboardingPage'; +import DashboardPage from './pages/dashboard/DashboardPage'; +import ForecastPage from './pages/forecast/ForecastPage'; +import OrdersPage from './pages/orders/OrdersPage'; +import SettingsPage from './pages/settings/SettingsPage'; +import Layout from './components/layout/Layout'; + +// Store and types +import { store } from './store'; +import { Provider } from 'react-redux'; + +// i18n +import './i18n'; + +// Global styles +import './styles/globals.css'; + +type CurrentPage = 'landing' | 'login' | 'register' | 'onboarding' | 'dashboard' | 'forecast' | 'orders' | 'settings'; + +interface User { + id: string; + email: string; + fullName: string; + role: string; + isOnboardingComplete: boolean; +} + +interface AppState { + isAuthenticated: boolean; + isLoading: boolean; + user: User | null; + currentPage: CurrentPage; +} + +const LoadingFallback = () => ( +
+
+ +

Cargando PanIA...

+
+
+); + +const App: React.FC = () => { + const [appState, setAppState] = useState({ + isAuthenticated: false, + isLoading: true, + user: null, + currentPage: 'landing' // 👈 Start with landing page + }); + + // Initialize app and check authentication + useEffect(() => { + const initializeApp = async () => { + try { + // Check for stored auth token + const token = localStorage.getItem('auth_token'); + const userData = localStorage.getItem('user_data'); + + if (token && userData) { + const user = JSON.parse(userData); + setAppState({ + isAuthenticated: true, + isLoading: false, + user, + currentPage: user.isOnboardingComplete ? 'dashboard' : 'onboarding' + }); + } else { + setAppState(prev => ({ + ...prev, + isLoading: false, + currentPage: 'landing' // 👈 Show landing page for non-authenticated users + })); + } + } catch (error) { + console.error('App initialization error:', error); + setAppState(prev => ({ + ...prev, + isLoading: false, + currentPage: 'landing' // 👈 Fallback to landing page + })); + } + }; + + initializeApp(); + }, []); + + const handleLogin = (user: User, token: string) => { + localStorage.setItem('auth_token', token); + localStorage.setItem('user_data', JSON.stringify(user)); + + setAppState({ + isAuthenticated: true, + isLoading: false, + user, + currentPage: user.isOnboardingComplete ? 'dashboard' : 'onboarding' + }); + }; + + const handleLogout = () => { + localStorage.removeItem('auth_token'); + localStorage.removeItem('user_data'); + + setAppState({ + isAuthenticated: false, + isLoading: false, + user: null, + currentPage: 'landing' // 👈 Return to landing page after logout + }); + }; + + const handleOnboardingComplete = () => { + const updatedUser = { ...appState.user!, isOnboardingComplete: true }; + localStorage.setItem('user_data', JSON.stringify(updatedUser)); + + setAppState(prev => ({ + ...prev, + user: updatedUser, + currentPage: 'dashboard' + })); + }; + + const navigateTo = (page: CurrentPage) => { + setAppState(prev => ({ ...prev, currentPage: page })); + }; + + if (appState.isLoading) { + return ; + } + + const renderCurrentPage = () => { + // Public pages (non-authenticated) + if (!appState.isAuthenticated) { + switch (appState.currentPage) { + case 'login': + return ( + navigateTo('register')} + /> + ); + case 'register': + return ( + navigateTo('login')} + /> + ); + default: + return ( + navigateTo('login')} + onNavigateToRegister={() => navigateTo('register')} + /> + ); + } + } + + // Authenticated pages + if (!appState.user?.isOnboardingComplete && appState.currentPage !== 'settings') { + return ( + + ); + } + + // Main app pages with layout + const pageComponent = () => { + switch (appState.currentPage) { + case 'forecast': + return ; + case 'orders': + return ; + case 'settings': + return ; + default: + return ; + } + }; + + return ( + + {pageComponent()} + + ); + }; + + return ( + + +
+ {renderCurrentPage()} + + {/* Global Toast Notifications */} + +
+
+
+ ); +}; + +export default App; \ No newline at end of file diff --git a/frontend/src/components/ErrorBoundary.tsx b/frontend/src/components/ErrorBoundary.tsx new file mode 100644 index 00000000..af21fc2b --- /dev/null +++ b/frontend/src/components/ErrorBoundary.tsx @@ -0,0 +1,68 @@ +// src/components/ErrorBoundary.tsx +import React, { Component, ErrorInfo, ReactNode } from 'react'; +import { AlertTriangle } from 'lucide-react'; + +interface Props { + children: ReactNode; +} + +interface State { + hasError: boolean; + error?: Error; +} + +class ErrorBoundary extends Component { + public state: State = { + hasError: false + }; + + public static getDerivedStateFromError(error: Error): State { + return { hasError: true, error }; + } + + public componentDidCatch(error: Error, errorInfo: ErrorInfo) { + console.error('ErrorBoundary caught an error:', error, errorInfo); + } + + public render() { + if (this.state.hasError) { + return ( +
+
+
+
+ +
+

+ ¡Oops! Algo salió mal +

+

+ Ha ocurrido un error inesperado. Por favor, recarga la página. +

+ + {process.env.NODE_ENV === 'development' && ( +
+ + Detalles del error + +
+                    {this.state.error?.stack}
+                  
+
+ )} +
+
+
+ ); + } + + return this.props.children; + } +} + +export default ErrorBoundary; \ No newline at end of file diff --git a/frontend/src/components/auth/ProtectedRoute.tsx b/frontend/src/components/auth/ProtectedRoute.tsx deleted file mode 100644 index 574d22c6..00000000 --- a/frontend/src/components/auth/ProtectedRoute.tsx +++ /dev/null @@ -1,33 +0,0 @@ -// src/components/auth/ProtectedRoute.tsx -import React from 'react'; -import { Navigate, useLocation } from 'react-router-dom'; -import { useAuth } from '../../contexts/AuthContext'; - -interface ProtectedRouteProps { - children: React.ReactNode; - requireAuth?: boolean; - redirectTo?: string; -} - -export const ProtectedRoute: React.FC = ({ - children, - requireAuth = true, - redirectTo = '/login' -}) => { - const { isAuthenticated, isLoading } = useAuth(); - const location = useLocation(); - - if (isLoading) { - return ( -
-
-
- ); - } - - if (requireAuth && !isAuthenticated) { - return ; - } - - return <>{children}; -}; \ No newline at end of file diff --git a/frontend/src/components/charts/ForecastChart.tsx b/frontend/src/components/charts/ForecastChart.tsx deleted file mode 100644 index 0b89e6c9..00000000 --- a/frontend/src/components/charts/ForecastChart.tsx +++ /dev/null @@ -1,166 +0,0 @@ -// ForecastChart.tsx (Modified) -import React from 'react'; -import { - Chart as ChartJS, - CategoryScale, - LinearScale, - PointElement, - LineElement, - Title, - Tooltip, - Legend, - Filler, -} from 'chart.js'; -import { Line } from 'react-chartjs-2'; -import { format } from 'date-fns'; -import { es } from 'date-fns/locale'; - -ChartJS.register( - CategoryScale, - LinearScale, - PointElement, - LineElement, - Title, - Tooltip, - Legend, - Filler -); - -interface ForecastData { - date: string; - predicted_quantity: number; - confidence_lower: number; - confidence_upper: number; - actual_quantity?: number; -} - -interface ForecastChartProps { - data: ForecastData[]; - productName: string; - // height?: number; // Removed fixed height prop -} - -const ForecastChart: React.FC = ({ data, productName /*, height = 400*/ }) => { // Removed height from props - const chartData = { - labels: data.map(d => format(new Date(d.date), 'dd MMM', { locale: es })), - datasets: [ - { - label: 'Predicción', - data: data.map(d => d.predicted_quantity), - borderColor: 'rgb(59, 130, 246)', - backgroundColor: 'rgba(59, 130, 246, 0.1)', - borderWidth: 2, - tension: 0.1, - pointRadius: 4, - pointHoverRadius: 6, - fill: true, - }, - { - label: 'Intervalo Inferior', - data: data.map(d => d.confidence_lower), - borderColor: 'rgba(59, 130, 246, 0.3)', - backgroundColor: 'transparent', - borderDash: [5, 5], - pointRadius: 0, - tension: 0.1, - }, - { - label: 'Intervalo Superior', - data: data.map(d => d.confidence_upper), - borderColor: 'rgba(59, 130, 246, 0.3)', - backgroundColor: 'transparent', - borderDash: [5, 5], - pointRadius: 0, - tension: 0.1, - }, - // Optional: Actual quantity if available - ...(data[0]?.actual_quantity !== undefined && data.some(d => d.actual_quantity !== undefined) ? [{ - label: 'Real', - data: data.map(d => d.actual_quantity), - borderColor: 'rgb(255, 99, 132)', - backgroundColor: 'rgba(255, 99, 132, 0.1)', - borderWidth: 2, - tension: 0.1, - pointRadius: 4, - pointHoverRadius: 6, - hidden: true, // Initially hidden, can be toggled - }] : []), - ], - }; - - const chartOptions = { - responsive: true, - maintainAspectRatio: false, // Ensures the chart fills its parent container's dimensions - plugins: { - legend: { - position: 'top' as const, - labels: { - font: { - size: 12, - }, - }, - }, - title: { - display: true, - text: `Predicción de Demanda - ${productName}`, - font: { - size: 16, - weight: 'bold' as const, - }, - padding: { - bottom: 20, - }, - }, - tooltip: { - mode: 'index' as const, - intersect: false, - callbacks: { - label: function(context: any) { - const label = context.dataset.label || ''; - const value = context.parsed.y; - if (value !== null && value !== undefined) { - return `${label}: ${Math.round(value)} unidades`; - } - return ''; - }, - }, - }, - }, - scales: { - x: { - grid: { - display: false, - }, - title: { - display: true, - text: 'Fecha', - font: { - size: 14, - }, - }, - }, - y: { - beginAtZero: true, - grid: { - color: 'rgba(0, 0, 0, 0.05)', - }, - title: { - display: true, - text: 'Cantidad (unidades)', - font: { - size: 14, - }, - }, - }, - }, - interaction: { - mode: 'nearest' as const, - axis: 'x' as const, - intersect: false, - }, - }; - - return ; -}; - -export default ForecastChart; \ No newline at end of file diff --git a/frontend/src/components/common/ErrorBoundary.tsx b/frontend/src/components/common/ErrorBoundary.tsx deleted file mode 100644 index 53ad41a3..00000000 --- a/frontend/src/components/common/ErrorBoundary.tsx +++ /dev/null @@ -1,57 +0,0 @@ -// src/components/common/ErrorBoundary.tsx -import React, { Component, ErrorInfo, ReactNode } from 'react'; - -interface Props { - children: ReactNode; - fallback?: ReactNode; -} - -interface State { - hasError: boolean; - error: Error | null; -} - -export class ErrorBoundary extends Component { - state: State = { - hasError: false, - error: null - }; - - static getDerivedStateFromError(error: Error): State { - return { hasError: true, error }; - } - - componentDidCatch(error: Error, errorInfo: ErrorInfo) { - console.error('ErrorBoundary caught:', error, errorInfo); - - // Send error to monitoring service - if (process.env.NODE_ENV === 'production') { - // logErrorToService(error, errorInfo); - } - } - - render() { - if (this.state.hasError) { - return this.props.fallback || ( -
-
-

- Algo salió mal -

-

- Ha ocurrido un error inesperado. Por favor, recarga la página. -

- -
-
- ); - } - - return this.props.children; - } -} \ No newline at end of file diff --git a/frontend/src/components/common/NotificationToast.tsx b/frontend/src/components/common/NotificationToast.tsx deleted file mode 100644 index 18ef7e21..00000000 --- a/frontend/src/components/common/NotificationToast.tsx +++ /dev/null @@ -1,64 +0,0 @@ -// src/components/common/NotificationToast.tsx -import React, { useEffect } from 'react'; -import { XMarkIcon } from '@heroicons/react/24/outline'; -import { - CheckCircleIcon, - ExclamationCircleIcon, - ExclamationTriangleIcon, - InformationCircleIcon -} from '@heroicons/react/24/solid'; - -interface NotificationToastProps { - id: string; - type: 'success' | 'error' | 'warning' | 'info'; - title: string; - message: string; - onClose: () => void; -} - -export const NotificationToast: React.FC = ({ - type, - title, - message, - onClose -}) => { - const icons = { - success: CheckCircleIcon, - error: ExclamationCircleIcon, - warning: ExclamationTriangleIcon, - info: InformationCircleIcon - }; - - const colors = { - success: 'text-green-400', - error: 'text-red-400', - warning: 'text-yellow-400', - info: 'text-blue-400' - }; - - const Icon = icons[type]; - - return ( -
-
-
-
- -
-
-

{title}

-

{message}

-
-
- -
-
-
-
- ); -}; \ No newline at end of file diff --git a/frontend/src/components/common/ProductSelector.tsx b/frontend/src/components/common/ProductSelector.tsx deleted file mode 100644 index ba2859e4..00000000 --- a/frontend/src/components/common/ProductSelector.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import React from 'react'; -import { Fragment } from 'react'; -import { Listbox, Transition } from '@headlessui/react'; -import { CheckIcon, ChevronUpDownIcon } from '@heroicons/react/20/solid'; - -interface Product { - id: string; - name: string; - displayName: string; - icon?: string; -} - -interface ProductSelectorProps { - products: Product[]; - selected: Product; - onChange: (product: Product) => void; - label?: string; -} - -const ProductSelector: React.FC = ({ - products, - selected, - onChange, - label = 'Seleccionar Producto', -}) => { - return ( -
- {label && ( - - )} - -
- - - {selected.icon && ( - {selected.icon} - )} - {selected.displayName} - - - - - - - {products.map((product) => ( - - `relative cursor-default select-none py-2 pl-10 pr-4 ${ - active ? 'bg-orange-100 text-orange-900' : 'text-gray-900' - }` - } - value={product} - > - {({ selected }) => ( - <> - - {product.icon && ( - {product.icon} - )} - - {product.displayName} - - - {selected ? ( - - - ) : null} - - )} - - ))} - - -
-
-
- ); -}; - -// Export default products list -export const defaultProducts: Product[] = [ - { id: 'pan', name: 'pan', displayName: 'Pan', icon: '🍞' }, - { id: 'croissant', name: 'croissant', displayName: 'Croissant', icon: '🥐' }, - { id: 'napolitana', name: 'napolitana', displayName: 'Napolitana', icon: '🥮' }, - { id: 'palmera', name: 'palmera', displayName: 'Palmera', icon: '🍪' }, - { id: 'cafe', name: 'cafe', displayName: 'Café', icon: '☕' }, - { id: 'bocadillo', name: 'bocadillo', displayName: 'Bocadillo', icon: '🥖' }, - { id: 'tarta', name: 'tarta', displayName: 'Tarta', icon: '🎂' }, - { id: 'donut', name: 'donut', displayName: 'Donut', icon: '🍩' }, -]; - -export default ProductSelector; \ No newline at end of file diff --git a/frontend/src/components/data/SalesUploader.tsx b/frontend/src/components/data/SalesUploader.tsx deleted file mode 100644 index 43f78533..00000000 --- a/frontend/src/components/data/SalesUploader.tsx +++ /dev/null @@ -1,47 +0,0 @@ -// src/components/data/SalesUploader.tsx -import React, { useRef, useState } from 'react'; -import { CloudArrowUpIcon } from '@heroicons/react/24/outline'; - -interface SalesUploaderProps { - onUpload: (file: File) => Promise; -} - -export const SalesUploader: React.FC = ({ onUpload }) => { - const fileInputRef = useRef(null); - const [isUploading, setIsUploading] = useState(false); - - const handleFileSelect = async (event: React.ChangeEvent) => { - const file = event.target.files?.[0]; - if (!file) return; - - setIsUploading(true); - try { - await onUpload(file); - } finally { - setIsUploading(false); - if (fileInputRef.current) { - fileInputRef.current.value = ''; - } - } - }; - - return ( - <> - - - - ); -}; \ No newline at end of file diff --git a/frontend/src/components/layout/Layout.tsx b/frontend/src/components/layout/Layout.tsx new file mode 100644 index 00000000..facc29e4 --- /dev/null +++ b/frontend/src/components/layout/Layout.tsx @@ -0,0 +1,215 @@ +import React, { useState } from 'react'; +import { + Home, + TrendingUp, + Package, + Settings, + Menu, + X, + LogOut, + User, + Bell, + ChevronDown +} from 'lucide-react'; + +interface LayoutProps { + children: React.ReactNode; + user: any; + currentPage: string; + onNavigate: (page: string) => void; + onLogout: () => void; +} + +interface NavigationItem { + id: string; + label: string; + icon: React.ComponentType<{ className?: string }>; + href: string; +} + +const Layout: React.FC = ({ + children, + user, + currentPage, + onNavigate, + onLogout +}) => { + const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); + const [isUserMenuOpen, setIsUserMenuOpen] = useState(false); + + const navigation: NavigationItem[] = [ + { id: 'dashboard', label: 'Panel Principal', icon: Home, href: '/dashboard' }, + { id: 'forecast', label: 'Predicciones', icon: TrendingUp, href: '/forecast' }, + { id: 'orders', label: 'Pedidos', icon: Package, href: '/orders' }, + { id: 'settings', label: 'Configuración', icon: Settings, href: '/settings' }, + ]; + + const handleNavigate = (pageId: string) => { + onNavigate(pageId); + setIsMobileMenuOpen(false); + }; + + return ( +
+ {/* Top Navigation Bar */} + + + {/* Main Content */} +
+
+ {children} +
+
+ + {/* Click outside handler for dropdowns */} + {(isUserMenuOpen || isMobileMenuOpen) && ( +
{ + setIsUserMenuOpen(false); + setIsMobileMenuOpen(false); + }} + /> + )} +
+ ); +}; + +export default Layout; \ No newline at end of file diff --git a/frontend/src/components/training/TrainingProgressCard.tsx b/frontend/src/components/training/TrainingProgressCard.tsx deleted file mode 100644 index 3adf3243..00000000 --- a/frontend/src/components/training/TrainingProgressCard.tsx +++ /dev/null @@ -1,113 +0,0 @@ -// src/components/training/TrainingProgressCard.tsx -import React from 'react'; -import { useTrainingProgress } from '../../api/hooks/useTrainingProgress'; -import { CheckCircleIcon, XCircleIcon } from '@heroicons/react/24/outline'; - -interface TrainingProgressCardProps { - jobId: string; - onComplete?: () => void; -} - -export const TrainingProgressCard: React.FC = ({ - jobId, - onComplete -}) => { - const { progress, error, isComplete, isConnected } = useTrainingProgress(jobId); - - React.useEffect(() => { - if (isComplete && onComplete) { - onComplete(); - } - }, [isComplete, onComplete]); - - if (!progress) { - return ( -
-
-
-
-
-
- ); - } - - return ( -
-
-

Training Progress

-
- {isConnected && ( - - - Live - - )} - {progress.status === 'completed' && ( - - )} - {progress.status === 'failed' && ( - - )} -
-
- - {error && ( -
- {error} -
- )} - -
-
-
- {progress.current_step} - {Math.round(progress.progress)}% -
-
-
-
-
- - {progress.estimated_time_remaining && ( -

- Tiempo estimado: {formatTime(progress.estimated_time_remaining)} -

- )} - - {progress.metrics && ( -
- {Object.entries(progress.metrics).map(([key, value]) => ( -
- {formatMetricName(key)}: - {formatMetricValue(value)} -
- ))} -
- )} -
-
- ); -}; - -// Utility functions -const formatTime = (seconds: number): string => { - if (seconds < 60) return `${seconds}s`; - const minutes = Math.floor(seconds / 60); - if (minutes < 60) return `${minutes}m`; - const hours = Math.floor(minutes / 60); - return `${hours}h ${minutes % 60}m`; -}; - -const formatMetricName = (name: string): string => { - return name.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()); -}; - -const formatMetricValue = (value: any): string => { - if (typeof value === 'number') { - return value.toFixed(2); - } - return String(value); -}; \ No newline at end of file diff --git a/frontend/src/components/ui/Button.tsx b/frontend/src/components/ui/Button.tsx new file mode 100644 index 00000000..e5c8489a --- /dev/null +++ b/frontend/src/components/ui/Button.tsx @@ -0,0 +1,57 @@ +// src/components/ui/Button.tsx +import React from 'react'; +import { clsx } from 'clsx'; +import LoadingSpinner from './LoadingSpinner'; + +interface ButtonProps extends React.ButtonHTMLAttributes { + variant?: 'primary' | 'secondary' | 'outline' | 'danger'; + size?: 'sm' | 'md' | 'lg'; + isLoading?: boolean; + children: React.ReactNode; +} + +const Button: React.FC = ({ + variant = 'primary', + size = 'md', + isLoading = false, + className, + children, + disabled, + ...props +}) => { + const baseClasses = 'inline-flex items-center justify-center font-medium rounded-xl transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2'; + + const variantClasses = { + primary: 'bg-primary-500 text-white hover:bg-primary-600 focus:ring-primary-500 shadow-soft hover:shadow-medium', + secondary: 'bg-gray-500 text-white hover:bg-gray-600 focus:ring-gray-500 shadow-soft hover:shadow-medium', + outline: 'border border-gray-300 text-gray-700 hover:bg-gray-50 focus:ring-primary-500', + danger: 'bg-red-500 text-white hover:bg-red-600 focus:ring-red-500 shadow-soft hover:shadow-medium', + }; + + const sizeClasses = { + sm: 'px-3 py-1.5 text-sm', + md: 'px-4 py-2.5 text-sm', + lg: 'px-6 py-3 text-base', + }; + + const isDisabled = disabled || isLoading; + + return ( + + ); +}; + +export default Button; diff --git a/frontend/src/components/ui/Card.tsx b/frontend/src/components/ui/Card.tsx new file mode 100644 index 00000000..7ffc6bc2 --- /dev/null +++ b/frontend/src/components/ui/Card.tsx @@ -0,0 +1,34 @@ +// src/components/ui/Card.tsx +import React from 'react'; +import { clsx } from 'clsx'; + +interface CardProps { + children: React.ReactNode; + className?: string; + padding?: 'none' | 'sm' | 'md' | 'lg'; +} + +const Card: React.FC = ({ + children, + className, + padding = 'md' +}) => { + const paddingClasses = { + none: '', + sm: 'p-4', + md: 'p-6', + lg: 'p-8' + }; + + return ( +
+ {children} +
+ ); +}; + +export default Card; \ No newline at end of file diff --git a/frontend/src/components/ui/Input.tsx b/frontend/src/components/ui/Input.tsx new file mode 100644 index 00000000..6baaa60f --- /dev/null +++ b/frontend/src/components/ui/Input.tsx @@ -0,0 +1,54 @@ +// src/components/ui/Input.tsx +import React from 'react'; +import { clsx } from 'clsx'; + +interface InputProps extends React.InputHTMLAttributes { + label?: string; + error?: string; + helperText?: string; +} + +const Input: React.FC = ({ + label, + error, + helperText, + className, + id, + ...props +}) => { + const inputId = id || `input-${Math.random().toString(36).substr(2, 9)}`; + + return ( +
+ {label && ( + + )} + + {error && ( +

{error}

+ )} + {helperText && !error && ( +

{helperText}

+ )} +
+ ); +}; + +export default Input; \ No newline at end of file diff --git a/frontend/src/components/ui/LoadingSpinner.tsx b/frontend/src/components/ui/LoadingSpinner.tsx new file mode 100644 index 00000000..b37ab2a9 --- /dev/null +++ b/frontend/src/components/ui/LoadingSpinner.tsx @@ -0,0 +1,27 @@ +// src/components/ui/LoadingSpinner.tsx +import React from 'react'; +import { Loader2 } from 'lucide-react'; + +interface LoadingSpinnerProps { + size?: 'sm' | 'md' | 'lg'; + className?: string; +} + +const LoadingSpinner: React.FC = ({ + size = 'md', + className = '' +}) => { + const sizeClasses = { + sm: 'h-4 w-4', + md: 'h-6 w-6', + lg: 'h-8 w-8' + }; + + return ( + + ); +}; + +export default LoadingSpinner; diff --git a/frontend/src/contexts/AuthContext.tsx b/frontend/src/contexts/AuthContext.tsx deleted file mode 100644 index b25a7aa7..00000000 --- a/frontend/src/contexts/AuthContext.tsx +++ /dev/null @@ -1,222 +0,0 @@ -// frontend/src/contexts/AuthContext.tsx - FIXED VERSION -import React, { createContext, useContext, useEffect, useState, useCallback } from 'react'; -// FIXED: Import authService directly, not through the index -import { authService } from '../api/services/authService'; -import { tokenManager } from '../api/auth/tokenManager'; -import { - UserProfile, - RegisterRequest, -} from '../api/types/api'; - -interface AuthContextType { - user: UserProfile | null; - isAuthenticated: boolean; - isLoading: boolean; - login: (email: string, password: string) => Promise; - register: (data: RegisterRequest) => Promise; - logout: () => Promise; - updateProfile: (updates: Partial) => Promise; - refreshUser: () => Promise; -} - -const AuthContext = createContext(null); - -export const useAuth = () => { - const context = useContext(AuthContext); - if (!context) { - throw new Error('useAuth must be used within an AuthProvider'); - } - return context; -}; - -export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { - const [user, setUser] = useState(null); - const [isLoading, setIsLoading] = useState(true); - - // Initialize auth state - useEffect(() => { - const initAuth = async () => { - try { - await tokenManager.initialize(); - - if (authService.isAuthenticated()) { - // Get user from token first (faster), then validate with API - const tokenUser = tokenManager.getUserFromToken(); - if (tokenUser) { - setUser({ - id: tokenUser.user_id, - email: tokenUser.email, - full_name: tokenUser.full_name, - is_active: true, - is_verified: tokenUser.is_verified, - role: 'user', // Default role - language: 'es', - timezone: 'Europe/Madrid', - created_at: '', // Will be filled by API call - }); - } - - // Validate with API and get complete profile - try { - const profile = await authService.getCurrentUser(); - setUser(profile); - } catch (error) { - console.error('Failed to fetch user profile:', error); - // Keep token-based user data if API fails - } - } - } catch (error) { - console.error('Auth initialization failed:', error); - // Clear potentially corrupted tokens - tokenManager.clearTokens(); - } finally { - setIsLoading(false); - } - }; - - initAuth(); - }, []); - - const login = useCallback(async (email: string, password: string) => { - setIsLoading(true); - try { - // Login and store tokens - const tokenResponse = await authService.login({ email, password }); - - // After login, get user profile - const profile = await authService.getCurrentUser(); - setUser(profile); - } catch (error) { - setIsLoading(false); - throw error; // Re-throw to let components handle the error - } finally { - setIsLoading(false); - } - }, []); - - const register = useCallback(async (data: RegisterRequest) => { - setIsLoading(true); - try { - // ✅ FIX: Handle registration conflicts properly - try { - // Try to register first - const tokenResponse = await authService.register(data); - - // After successful registration, get user profile - const profile = await authService.getCurrentUser(); - setUser(profile); - } catch (registrationError: any) { - // ✅ FIX: If user already exists (409), try to login instead - if (registrationError.response?.status === 409 || - registrationError.message?.includes('already exists')) { - - console.log('User already exists'); - - } else { - // If it's not a "user exists" error, re-throw it - throw registrationError; - } - } - } catch (error) { - setIsLoading(false); - throw error; // Re-throw to let components handle the error - } finally { - setIsLoading(false); - } - }, []); - - const logout = useCallback(async () => { - setIsLoading(true); - try { - await authService.logout(); - setUser(null); - } catch (error) { - console.error('Logout error:', error); - // Clear local state even if API call fails - setUser(null); - tokenManager.clearTokens(); - } finally { - setIsLoading(false); - } - }, []); - - const updateProfile = useCallback(async (updates: Partial) => { - if (!user) return; - - try { - const updated = await authService.updateProfile(updates); - setUser(updated); - } catch (error) { - console.error('Profile update error:', error); - throw error; - } - }, [user]); - - const refreshUser = useCallback(async () => { - if (!authService.isAuthenticated()) return; - - try { - const profile = await authService.getCurrentUser(); - setUser(profile); - } catch (error) { - console.error('User refresh error:', error); - // If refresh fails with 401, user might need to re-login - if (error.status === 401) { - await logout(); - } - } - }, [logout]); - - // Set up token refresh interval - useEffect(() => { - if (!user) return; - - const interval = setInterval(async () => { - try { - await tokenManager.refreshAccessToken(); - } catch (error) { - console.error('Scheduled token refresh failed:', error); - // If token refresh fails, user needs to re-login - await logout(); - } - }, 60000); // Check every 1 minute - - return () => clearInterval(interval); - }, [user, logout]); - - // Monitor token expiration - useEffect(() => { - if (!user) return; - - const checkTokenValidity = () => { - if (!authService.isAuthenticated()) { - console.warn('Token became invalid, logging out user'); - logout(); - } - }; - - // Check token validity every 30 seconds - const interval = setInterval(checkTokenValidity, 30000); - return () => clearInterval(interval); - }, [user, logout]); - - const contextValue = { - user, - isAuthenticated: !!user && authService.isAuthenticated(), - isLoading, - login, - register, - logout, - updateProfile, - refreshUser, - }; - - return ( - - {children} - - ); -}; - -// Export the RegisterRequest type for use in components -export type { RegisterRequest }; \ No newline at end of file diff --git a/frontend/src/i18n/index.ts b/frontend/src/i18n/index.ts new file mode 100644 index 00000000..6c2f59cd --- /dev/null +++ b/frontend/src/i18n/index.ts @@ -0,0 +1,137 @@ +// src/i18n/index.ts +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import LanguageDetector from 'i18next-browser-languagedetector'; + +const resources = { + es: { + translation: { + // Common + "loading": "Cargando...", + "save": "Guardar", + "cancel": "Cancelar", + "delete": "Eliminar", + "edit": "Editar", + "close": "Cerrar", + "yes": "Sí", + "no": "No", + + // Navigation + "dashboard": "Panel Principal", + "forecasts": "Predicciones", + "orders": "Pedidos", + "settings": "Configuración", + "logout": "Cerrar Sesión", + + // Auth + "login": "Iniciar Sesión", + "register": "Registrarse", + "email": "Correo electrónico", + "password": "Contraseña", + "confirmPassword": "Confirmar contraseña", + "fullName": "Nombre completo", + "welcomeBack": "¡Bienvenido de vuelta!", + "createAccount": "Crear cuenta", + + // Dashboard + "todaySales": "Ventas de Hoy", + "wasteReduction": "Reducción Desperdicio", + "aiAccuracy": "Precisión IA", + "stockouts": "Roturas Stock", + + // Forecasts + "highConfidence": "Alta confianza", + "mediumConfidence": "Confianza media", + "lowConfidence": "Baja confianza", + "predictionsForToday": "Predicciones para Hoy", + "weatherImpact": "Impacto del clima", + + // Orders + "newOrder": "Nuevo Pedido", + "pending": "Pendiente", + "confirmed": "Confirmado", + "delivered": "Entregado", + "cancelled": "Cancelado", + + // Products + "croissants": "Croissants", + "bread": "Pan de molde", + "baguettes": "Baguettes", + "coffee": "Café", + "pastries": "Napolitanas", + "muffins": "Magdalenas", + "donuts": "Donuts", + "sandwiches": "Bocadillos" + } + }, + en: { + translation: { + // Common + "loading": "Loading...", + "save": "Save", + "cancel": "Cancel", + "delete": "Delete", + "edit": "Edit", + "close": "Close", + "yes": "Yes", + "no": "No", + + // Navigation + "dashboard": "Dashboard", + "forecasts": "Forecasts", + "orders": "Orders", + "settings": "Settings", + "logout": "Logout", + + // Auth + "login": "Login", + "register": "Register", + "email": "Email", + "password": "Password", + "confirmPassword": "Confirm password", + "fullName": "Full name", + "welcomeBack": "Welcome back!", + "createAccount": "Create account", + + // Dashboard + "todaySales": "Today's Sales", + "wasteReduction": "Waste Reduction", + "aiAccuracy": "AI Accuracy", + "stockouts": "Stockouts", + + // Forecasts + "highConfidence": "High confidence", + "mediumConfidence": "Medium confidence", + "lowConfidence": "Low confidence", + "predictionsForToday": "Today's Predictions", + "weatherImpact": "Weather impact", + + // Orders + "newOrder": "New Order", + "pending": "Pending", + "confirmed": "Confirmed", + "delivered": "Delivered", + "cancelled": "Cancelled" + } + } +}; + +i18n + .use(LanguageDetector) + .use(initReactI18next) + .init({ + resources, + fallbackLng: 'es', + debug: process.env.NODE_ENV === 'development', + + interpolation: { + escapeValue: false, + }, + + detection: { + order: ['localStorage', 'navigator', 'htmlTag'], + caches: ['localStorage'], + }, + }); + +export default i18n; \ No newline at end of file diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx new file mode 100644 index 00000000..825a0c6e --- /dev/null +++ b/frontend/src/main.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.tsx' 👈 Imports from ./App.tsx +import './index.css' + +ReactDOM.createRoot(document.getElementById('root')!).render( + + 👈 Renders the App component + , +) \ No newline at end of file diff --git a/frontend/src/pages/_app.tsx b/frontend/src/pages/_app.tsx deleted file mode 100644 index f949c3dc..00000000 --- a/frontend/src/pages/_app.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { AuthProvider } from '../contexts/AuthContext'; -import '../styles/globals.css'; - -function App({ Component, pageProps }: any) { - return ( - - - - ); -} - -export default App; \ No newline at end of file diff --git a/frontend/src/pages/auth/LoginPage.tsx b/frontend/src/pages/auth/LoginPage.tsx new file mode 100644 index 00000000..e825d4a6 --- /dev/null +++ b/frontend/src/pages/auth/LoginPage.tsx @@ -0,0 +1,278 @@ +import React, { useState } from 'react'; +import { Eye, EyeOff, Loader2 } from 'lucide-react'; +import toast from 'react-hot-toast'; + +interface LoginPageProps { + onLogin: (user: any, token: string) => void; + onNavigateToRegister: () => void; +} + +interface LoginForm { + email: string; + password: string; +} + +const LoginPage: React.FC = ({ onLogin, onNavigateToRegister }) => { + const [formData, setFormData] = useState({ + email: '', + password: '' + }); + + const [showPassword, setShowPassword] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const [errors, setErrors] = useState>({}); + + const validateForm = (): boolean => { + const newErrors: Partial = {}; + + if (!formData.email) { + newErrors.email = 'El email es obligatorio'; + } else if (!/\S+@\S+\.\S+/.test(formData.email)) { + newErrors.email = 'El email no es válido'; + } + + if (!formData.password) { + newErrors.password = 'La contraseña es obligatoria'; + } else if (formData.password.length < 6) { + newErrors.password = 'La contraseña debe tener al menos 6 caracteres'; + } + + setErrors(newErrors); + return Object.keys(newErrors).length === 0; + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + if (!validateForm()) return; + + setIsLoading(true); + + try { + const response = await fetch('/api/v1/auth/login', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(formData), + }); + + const data = await response.json(); + + if (!response.ok) { + throw new Error(data.message || 'Error al iniciar sesión'); + } + + toast.success('¡Bienvenido a PanIA!'); + onLogin(data.user, data.access_token); + + } catch (error: any) { + console.error('Login error:', error); + toast.error(error.message || 'Error al iniciar sesión'); + } finally { + setIsLoading(false); + } + }; + + const handleInputChange = (e: React.ChangeEvent) => { + const { name, value } = e.target; + setFormData(prev => ({ + ...prev, + [name]: value + })); + + // Clear error when user starts typing + if (errors[name as keyof LoginForm]) { + setErrors(prev => ({ + ...prev, + [name]: undefined + })); + } + }; + + return ( +
+
+ {/* Logo and Header */} +
+
+ 🥖 +
+

+ PanIA +

+

+ Inteligencia Artificial para tu Panadería +

+

+ Inicia sesión para acceder a tus predicciones +

+
+ + {/* Login Form */} +
+
+ {/* Email Field */} +
+ + + {errors.email && ( +

{errors.email}

+ )} +
+ + {/* Password Field */} +
+ +
+ + +
+ {errors.password && ( +

{errors.password}

+ )} +
+ + {/* Remember Me & Forgot Password */} +
+
+ + +
+ + +
+ + {/* Submit Button */} +
+ +
+
+ + {/* Register Link */} +
+

+ ¿No tienes una cuenta?{' '} + +

+
+
+ + {/* Features Preview */} +
+

+ Más de 500 panaderías en Madrid confían en PanIA +

+
+
+ + Predicciones precisas +
+
+ + Reduce desperdicios +
+
+ + Fácil de usar +
+
+
+
+
+ ); +}; + +export default LoginPage; \ No newline at end of file diff --git a/frontend/src/pages/auth/RegisterPage.tsx b/frontend/src/pages/auth/RegisterPage.tsx new file mode 100644 index 00000000..943c86b5 --- /dev/null +++ b/frontend/src/pages/auth/RegisterPage.tsx @@ -0,0 +1,686 @@ +{/* Register Form */} +
+
+ {/* Full Name Field */} +
+ + + {errors.fullName && ( +

{errors.fullName}

+ )} +
+ + {/* Email Field */} +
+ + + {errors.email && ( +

{errors.email}

+ )} +
+ + {/* Password Field */} +
+ +
+ + +
+ + {/* Password Strength Indicator */} + {formData.password && ( +
+
+ {[...Array(5)].map((_, i) => ( +
+ ))} +
+

+ Seguridad: {strengthLabels[passwordStrength - 1] || 'Muy débil'} +

+
+ )} + + {errors.password && ( +

{errors.password}

+ )} +
+ + {/* Confirm Password Field */} +
+ +
+ + + {formData.confirmPassword && formData.password === formData.confirmPassword && ( +
+ +
+ )} +
+ {errors.confirmPassword && ( +

{errors.confirmPassword}

+ )} +
+ + {/* Terms and Conditions */} +
+
+ + +
+ {errors.acceptTerms && ( +

{errors.acceptTerms}

+ )} +
+ + {/* Submit Button */} +
+ +
+
+ + {/* Login Link */} +
+

+ ¿Ya tienes una cuenta?{' '} + +

+
+
import React, { useState } from 'react'; +import { Eye, EyeOff, Loader2, Check } from 'lucide-react'; +import toast from 'react-hot-toast'; + +interface RegisterPageProps { + onLogin: (user: any, token: string) => void; + onNavigateToLogin: () => void; +} + +interface RegisterForm { + fullName: string; + email: string; + password: string; + confirmPassword: string; + acceptTerms: boolean; +} + +const RegisterPage: React.FC = ({ onLogin, onNavigateToLogin }) => { + const [formData, setFormData] = useState({ + fullName: '', + email: '', + password: '', + confirmPassword: '', + acceptTerms: false + }); + + const [showPassword, setShowPassword] = useState(false); + const [showConfirmPassword, setShowConfirmPassword] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const [errors, setErrors] = useState>({}); + + const validateForm = (): boolean => { + const newErrors: Partial = {}; + + if (!formData.fullName.trim()) { + newErrors.fullName = 'El nombre completo es obligatorio'; + } else if (formData.fullName.trim().length < 2) { + newErrors.fullName = 'El nombre debe tener al menos 2 caracteres'; + } + + if (!formData.email) { + newErrors.email = 'El email es obligatorio'; + } else if (!/\S+@\S+\.\S+/.test(formData.email)) { + newErrors.email = 'El email no es válido'; + } + + if (!formData.password) { + newErrors.password = 'La contraseña es obligatoria'; + } else if (formData.password.length < 8) { + newErrors.password = 'La contraseña debe tener al menos 8 caracteres'; + } else if (!/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(formData.password)) { + newErrors.password = 'La contraseña debe incluir mayúsculas, minúsculas y números'; + } + + if (!formData.confirmPassword) { + newErrors.confirmPassword = 'Confirma tu contraseña'; + } else if (formData.password !== formData.confirmPassword) { + newErrors.confirmPassword = 'Las contraseñas no coinciden'; + } + + if (!formData.acceptTerms) { + newErrors.acceptTerms = 'Debes aceptar los términos y condiciones'; + } + + setErrors(newErrors); + return Object.keys(newErrors).length === 0; + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + if (!validateForm()) return; + + setIsLoading(true); + + try { + const response = await fetch('/api/v1/auth/register', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + full_name: formData.fullName, + email: formData.email, + password: formData.password, + role: 'admin' // Default role for bakery owners + }), + }); + + const data = await response.json(); + + if (!response.ok) { + throw new Error(data.message || 'Error al crear la cuenta'); + } + + // Auto-login after successful registration + const loginResponse = await fetch('/api/v1/auth/login', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + email: formData.email, + password: formData.password, + }), + }); + + const loginData = await loginResponse.json(); + + if (!loginResponse.ok) { + throw new Error('Cuenta creada, pero error al iniciar sesión'); + } + + toast.success('¡Cuenta creada exitosamente! Bienvenido a PanIA'); + onLogin(loginData.user, loginData.access_token); + + } catch (error: any) { + console.error('Registration error:', error); + toast.error(error.message || 'Error al crear la cuenta'); + } finally { + setIsLoading(false); + } + }; + + const handleInputChange = (e: React.ChangeEvent) => { + const { name, value, type, checked } = e.target; + setFormData(prev => ({ + ...prev, + [name]: type === 'checkbox' ? checked : value + })); + + // Clear error when user starts typing + if (errors[name as keyof RegisterForm]) { + setErrors(prev => ({ + ...prev, + [name]: undefined + })); + } + }; + + const getPasswordStrength = (password: string) => { + let strength = 0; + if (password.length >= 8) strength++; + if (/[a-z]/.test(password)) strength++; + if (/[A-Z]/.test(password)) strength++; + if (/\d/.test(password)) strength++; + if (/[^A-Za-z0-9]/.test(password)) strength++; + return strength; + }; + + const passwordStrength = getPasswordStrength(formData.password); + const strengthLabels = ['Muy débil', 'Débil', 'Regular', 'Buena', 'Excelente']; + const strengthColors = ['bg-red-500', 'bg-orange-500', 'bg-yellow-500', 'bg-blue-500', 'bg-green-500']; + + return ( +
+
+ {/* Logo and Header */} +
+
+ 🥖 +
+

+ Únete a PanIA +

+

+ Crea tu cuenta y transforma tu panadería +

+

+ Únete a más de 500 panaderías en Madrid +

+
+ + {/* Register Form */} +
+
+ {/* Full Name Field */} +
+ + + {errors.fullName && ( +

{errors.fullName}

+ )} +
+ + {/* Email Field */} +
+ + + {errors.email && ( +

{errors.email}

+ )} +
+ + {/* Password Field */} +
+ +
+ + +
+ + {/* Password Strength Indicator */} + {formData.password && ( +
+
+ {[...Array(5)].map((_, i) => ( +
+ ))} +
+

+ Seguridad: {strengthLabels[passwordStrength - 1] || 'Muy débil'} +

+
+ )} + + {errors.password && ( +

{errors.password}

+ )} +
+ + {/* Confirm Password Field */} +
+ +
+ + + {formData.confirmPassword && formData.password === formData.confirmPassword && ( +
+ +
+ )} +
+ {errors.confirmPassword && ( +

{errors.confirmPassword}

+ )} +
+ + {/* Terms and Conditions */} +
+
+ + +
+ {errors.acceptTerms && ( +

{errors.acceptTerms}

+ )} +
+ + {/* Submit Button */} +
+ +
+ + + {/* Login Link */} +
+

+ ¿Ya tienes una cuenta?{' '} + +

+
+
+ + {/* Benefits */} +
+

+ Al registrarte obtienes acceso completo durante 30 días gratis +

+
+
+ + Predicciones IA +
+
+ + Soporte 24/7 +
+
+ + Sin compromiso +
+
+
+
+
+ ); +}; + +export default RegisterPage; \ No newline at end of file diff --git a/frontend/src/pages/dashboard/DashboardPage.tsx b/frontend/src/pages/dashboard/DashboardPage.tsx new file mode 100644 index 00000000..33134882 --- /dev/null +++ b/frontend/src/pages/dashboard/DashboardPage.tsx @@ -0,0 +1,429 @@ +import React, { useState, useEffect } from 'react'; +import { TrendingUp, TrendingDown, Package, AlertTriangle, Cloud, Users } from 'lucide-react'; +import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, BarChart, Bar } from 'recharts'; + +interface DashboardPageProps { + user: any; +} + +interface WeatherData { + temperature: number; + description: string; + precipitation: number; +} + +interface ForecastData { + product: string; + predicted: number; + confidence: 'high' | 'medium' | 'low'; + change: number; +} + +interface MetricsData { + totalSales: number; + wasteReduction: number; + accuracy: number; + stockouts: number; +} + +const DashboardPage: React.FC = ({ user }) => { + const topProducts = [ + { name: 'Croissants', quantity: 45, trend: 'up' }, + { name: 'Pan de molde', quantity: 32, trend: 'up' }, + { name: 'Baguettes', quantity: 28, trend: 'down' }, + { name: 'Napolitanas', quantity: 23, trend: 'up' }, + { name: 'Café', quantity: 67, trend: 'up' }, + ]; + + useEffect(() => { + const loadDashboardData = async () => { + setIsLoading(true); + + try { + // Simulate API calls - in real implementation, these would be actual API calls + await new Promise(resolve => setTimeout(resolve, 1000)); + + // Mock weather data + setWeather({ + temperature: 18, + description: 'Parcialmente nublado', + precipitation: 0 + }); + + // Mock today's forecasts + setTodayForecasts([ + { product: 'Croissants', predicted: 48, confidence: 'high', change: 8 }, + { product: 'Pan de molde', predicted: 35, confidence: 'high', change: 3 }, + { product: 'Baguettes', predicted: 25, confidence: 'medium', change: -3 }, + { product: 'Café', predicted: 72, confidence: 'high', change: 5 }, + { product: 'Napolitanas', predicted: 26, confidence: 'medium', change: 3 } + ]); + + // Mock metrics + setMetrics({ + totalSales: 1247, + wasteReduction: 15.3, + accuracy: 87.2, + stockouts: 2 + }); + + } catch (error) { + console.error('Error loading dashboard data:', error); + } finally { + setIsLoading(false); + } + }; + + loadDashboardData(); + }, []); + + const getConfidenceColor = (confidence: string) => { + switch (confidence) { + case 'high': + return 'text-success-600 bg-success-100'; + case 'medium': + return 'text-warning-600 bg-warning-100'; + case 'low': + return 'text-danger-600 bg-danger-100'; + default: + return 'text-gray-600 bg-gray-100'; + } + }; + + const getConfidenceLabel = (confidence: string) => { + switch (confidence) { + case 'high': + return 'Alta'; + case 'medium': + return 'Media'; + case 'low': + return 'Baja'; + default: + return 'N/A'; + } + }; + + if (isLoading) { + return ( +
+
+
+
+ {[...Array(4)].map((_, i) => ( +
+ ))} +
+
+
+
+
+
+
+ ); + } + + return ( +
+ {/* Header */} +
+
+

+ ¡Hola, {user.fullName?.split(' ')[0] || 'Usuario'}! 👋 +

+

+ Aquí tienes un resumen de tu panadería para hoy +

+
+ + {weather && ( +
+ + {weather.temperature}°C - {weather.description} +
+ )} +
+ + {/* Key Metrics */} +
+
+
+
+ +
+
+

Ventas de Hoy

+

{metrics.totalSales}

+

+ + +12% vs ayer +

+
+
+
+ +
+
+
+ +
+
+

Reducción Desperdicio

+

{metrics.wasteReduction}%

+

+ + Mejorando +

+
+
+
+ +
+
+
+ +
+
+

Precisión IA

+

{metrics.accuracy}%

+

+ + Excelente +

+
+
+
+ +
+
+
+ +
+
+

Roturas Stock

+

{metrics.stockouts}

+

+ + Reduciendo +

+
+
+
+
+ + {/* Main Content Grid */} +
+ {/* Sales Chart */} +
+

+ Ventas vs Predicciones (Última Semana) +

+
+ + + + { + const date = new Date(value); + return `${date.getDate()}/${date.getMonth() + 1}`; + }} + /> + + { + const date = new Date(value); + return `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`; + }} + /> + + + + +
+
+ + {/* Today's Forecasts */} +
+

+ Predicciones para Hoy +

+
+ {todayForecasts.map((forecast, index) => ( +
+
+
+ {forecast.product} + + {getConfidenceLabel(forecast.confidence)} + +
+
+ + {forecast.predicted} + + = 0 ? 'text-success-600' : 'text-danger-600' + }`}> + {forecast.change >= 0 ? ( + + ) : ( + + )} + {Math.abs(forecast.change)} vs ayer + +
+
+
+ ))} +
+
+
+ + {/* Bottom Section */} +
+ {/* Top Products */} +
+

+ Productos Más Vendidos (Esta Semana) +

+
+ + + + + + + + + +
+
+ + {/* Quick Actions */} +
+

+ Acciones Rápidas +

+
+ + + + + +
+
+
+ + {/* Weather Impact Alert */} + {weather && weather.precipitation > 0 && ( +
+
+ +
+

Impacto del Clima

+

+ Se esperan precipitaciones hoy. Esto puede reducir el tráfico peatonal en un 20-30%. + Considera ajustar la producción de productos frescos. +

+
+
+
+ )} +
+ ); +}; + +export default DashboardPage; [isLoading, setIsLoading] = useState(true); + const [weather, setWeather] = useState(null); + const [todayForecasts, setTodayForecasts] = useState([]); + const [metrics, setMetrics] = useState({ + totalSales: 0, + wasteReduction: 0, + accuracy: 0, + stockouts: 0 + }); + + // Sample historical data for charts + const salesHistory = [ + { date: '2024-10-28', ventas: 145, prediccion: 140 }, + { date: '2024-10-29', ventas: 128, prediccion: 135 }, + { date: '2024-10-30', ventas: 167, prediccion: 160 }, + { date: '2024-10-31', ventas: 143, prediccion: 145 }, + { date: '2024-11-01', ventas: 156, prediccion: 150 }, + { date: '2024-11-02', ventas: 189, prediccion: 185 }, + { date: '2024-11-03', ventas: 134, prediccion: 130 }, + ]; + + const \ No newline at end of file diff --git a/frontend/src/pages/dashboard/index.tsx b/frontend/src/pages/dashboard/index.tsx deleted file mode 100644 index 25e3d3a5..00000000 --- a/frontend/src/pages/dashboard/index.tsx +++ /dev/null @@ -1,384 +0,0 @@ -// src/pages/dashboard/index.tsx -import React, { useState, useEffect, useCallback } from 'react'; -import Head from 'next/head'; -import { - ChartBarIcon, - CloudArrowUpIcon, - CpuChipIcon, - BellIcon, - ArrowPathIcon, - ScaleIcon, // For accuracy - CalendarDaysIcon, // For last training date - CurrencyEuroIcon -} from '@heroicons/react/24/outline'; -import { useAuth } from '../../contexts/AuthContext'; -import { useTrainingProgress } from '../../api/hooks/useTrainingProgress'; // Path corrected -import { TrainingProgressCard } from '../../components/training/TrainingProgressCard'; -import { ForecastChart } from '../../components/charts/ForecastChart'; -import { SalesUploader } from '../../components/data/SalesUploader'; -import { NotificationToast } from '../../components/common/NotificationToast'; -import { ErrorBoundary } from '../../components/common/ErrorBoundary'; -import { defaultProducts } from '../../components/common/ProductSelector'; -import { - ApiResponse, - ForecastRecord, - TrainingRequest, - TrainingJobProgress -} from '@/api/services'; - - -import api from '@/api/services'; - - -// Dashboard specific types -interface DashboardStats { - totalSales: number; - totalRevenue: number; - lastTrainingDate: string | null; - forecastAccuracy: number; // e.g., MAPE or RMSE -} - -interface Notification { - id: string; - type: 'success' | 'error' | 'warning' | 'info'; - title: string; - message: string; - timestamp: Date; -} - -// StatsCard Component (moved here for completeness, or keep in common if reused) -interface StatsCardProps { - title: string; - value: any; - icon: React.ElementType; - format: 'number' | 'currency' | 'percentage' | 'date' | 'string'; // Added 'string' for flexibility - loading?: boolean; -} - -const StatsCard: React.FC = ({ title, value, icon: Icon, format, loading }) => { - const formatValue = () => { - if (loading) return ( -
- ); - if (value === null || value === undefined) return 'N/A'; - - switch (format) { - case 'number': - return value.toLocaleString('es-ES'); - case 'currency': - return new Intl.NumberFormat('es-ES', { - style: 'currency', - currency: 'EUR', - }).format(value); - case 'percentage': - return `${(value * 100).toFixed(1)}%`; - case 'date': - return value === 'Never' ? value : new Date(value).toLocaleDateString('es-ES'); - default: - return value; - } - }; - - return ( -
-
- {/* Changed icon color */} -
-
-
{title}
-
{formatValue()}
-
-
- ); -}; - - -const DashboardPage: React.FC = () => { - const { user, isAuthenticated, isLoading: authLoading } = useAuth(); - const [activeJobId, setActiveJobId] = useState(null); - const [stats, setStats] = useState(null); - const [forecasts, setForecasts] = useState([]); - const [notifications, setNotifications] = useState([]); - const [chartProductName, setChartProductName] = useState(''); // Currently selected product for chart - const [loadingData, setLoadingData] = useState(true); - - // Hook for training progress (if an active job ID is present) - const { - progress: trainingProgress, - error: trainingError, - isComplete: isTrainingComplete, - isConnected: isTrainingWebSocketConnected, - } = useTrainingProgress(activeJobId); - - // Effect to handle training completion - useEffect(() => { - if (isTrainingComplete && activeJobId) { - addNotification('success', 'Entrenamiento Completado', `El modelo para el trabajo ${activeJobId} ha terminado de entrenar.`); - setActiveJobId(null); // Clear active job - fetchDashboardData(); // Refresh dashboard data after training - } - if (trainingError && activeJobId) { - addNotification('error', 'Error de Entrenamiento', `El entrenamiento para el trabajo ${activeJobId} falló: ${trainingError}`); - setActiveJobId(null); - } - }, [isTrainingComplete, trainingError, activeJobId]); // Dependencies - - - // Notification handling - const addNotification = useCallback((type: Notification['type'], title: string, message: string) => { - const newNotification: Notification = { - id: Date.now().toString(), - type, - title, - message, - timestamp: new Date(), - }; - setNotifications((prev) => [...prev, newNotification]); - }, []); - - const removeNotification = useCallback((id: string) => { - setNotifications((prev) => prev.filter((n) => n.id !== id)); - }, []); - - // Fetch initial dashboard data - const fetchDashboardData = useCallback(async () => { - setLoadingData(true); - try { - // Fetch Dashboard Stats - const statsResponse: ApiResponse = await api.data.dataApi.getDashboardStats(); - if (statsResponse.data) { - setStats(statsResponse.data); - } else if (statsResponse.message) { - addNotification('warning', 'Dashboard Stats', statsResponse.message); - } - - // Fetch initial forecasts (e.g., for a default product or the first available product) - const forecastResponse: ApiResponse = await api.forecasting.getForecast({ - forecast_days: 7, // Example: 7 days forecast - product_name: user?.tenant_id ? 'pan' : undefined, // Default to 'pan' or first product - }); - if (forecastResponse.data && forecastResponse.data.length > 0) { - setForecasts(forecastResponse.data); - setChartProductName(forecastResponse.data[0].product_name); // Set the product name for the chart - } else if (forecastResponse.message) { - addNotification('info', 'Previsiones', forecastResponse.message); - } - - } catch (error: any) { - console.error('Failed to fetch dashboard data:', error); - addNotification('error', 'Error de Carga', error.message || 'No se pudieron cargar los datos del dashboard.'); - } finally { - setLoadingData(false); - } - }, [user, addNotification]); - - useEffect(() => { - if (isAuthenticated) { - fetchDashboardData(); - } - }, [isAuthenticated, fetchDashboardData]); - - const handleSalesUpload = async (file: File) => { - try { - addNotification('info', 'Subiendo archivo', 'Cargando historial de ventas...'); - const response = await api.data.dataApi.uploadSalesHistory(file); - addNotification('success', 'Subida Completa', 'Historial de ventas cargado exitosamente.'); - - // After upload, trigger a new training (assuming this is the flow) - const trainingRequest: TrainingRequest = { - force_retrain: true, - // You might want to specify products if the uploader supports it, - // or let the backend determine based on the uploaded data. - }; - const trainingTask: TrainingJobProgress = await api.training.trainingApi.startTraining(trainingRequest); - setActiveJobId(trainingTask.id); - addNotification('info', 'Entrenamiento iniciado', `Un nuevo entrenamiento ha comenzado (ID: ${trainingTask.id}).`); - // No need to fetch dashboard data here, as useEffect for isTrainingComplete will handle it - } catch (error: any) { - console.error('Error uploading sales or starting training:', error); - addNotification('error', 'Error al subir', error.message || 'No se pudo subir el archivo o iniciar el entrenamiento.'); - } - }; - - const handleForecastProductChange = async (productName: string) => { - setLoadingData(true); - try { - const forecastResponse: ApiResponse = await api.forecasting.forecastingApi.getForecast({ - forecast_days: 7, - product_name: productName, - }); - if (forecastResponse.data) { - setForecasts(forecastResponse.data); - setChartProductName(productName); - } - } catch (error: any) { - addNotification('error', 'Error de Previsión', error.message || `No se pudieron cargar las previsiones para ${productName}.`); - } finally { - setLoadingData(false); - } - }; - - - if (authLoading) { - return ( -
-
-
- ); - } - - if (!isAuthenticated) { - // If not authenticated, ProtectedRoute should handle redirect, but a fallback is good - return null; - } - - return ( - -
- - Dashboard - PanIA - - - - {/* Top Notification Area */} -
- {notifications.map(notification => ( - removeNotification(notification.id)} - /> - ))} -
- - {/* Header/Navbar (You might want a dedicated Layout component for this) */} -
- -
- -
- {/* Dashboard Overview Section */} -
-

Resumen del Negocio

-
- - - - -
-
- - {/* Training Section */} -
-

Entrenamiento del Modelo

-
-
-

Subir Nuevos Datos de Ventas

-

- Carga tu último historial de ventas para mantener tus predicciones actualizadas. -

- -
- -
-

Estado del Entrenamiento

- {activeJobId ? ( - - ) : ( -
- -

No hay un entrenamiento activo en este momento.

-

Sube un nuevo archivo de ventas para iniciar un entrenamiento.

-
- )} -
-
-
- - {/* Forecast Chart Section */} -
-

Previsiones de Demanda

-
-
-

Previsión para {chartProductName || 'Productos'}

- {/* Product Selector for Forecast Chart (assuming ProductSelector can be used for single selection) */} - -
- {loadingData ? ( -
-
-
- ) : forecasts.length > 0 ? ( - - ) : ( -
- -

No hay datos de previsión disponibles.

-

Sube tu historial de ventas o selecciona otro producto.

-
- )} -
-
-
- - {/* Footer */} -
-
-

© {new Date().getFullYear()} PanIA. Todos los derechos reservados.

-
-
-
-
- ); -}; - -export default DashboardPage; \ No newline at end of file diff --git a/frontend/src/pages/forecast/ForecastPage.tsx b/frontend/src/pages/forecast/ForecastPage.tsx new file mode 100644 index 00000000..3251f4a2 --- /dev/null +++ b/frontend/src/pages/forecast/ForecastPage.tsx @@ -0,0 +1,411 @@ +import React, { useState, useEffect } from 'react'; +import { TrendingUp, TrendingDown, Calendar, Cloud, AlertTriangle, Info } from 'lucide-react'; +import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts'; + +interface ForecastData { + date: string; + product: string; + predicted: number; + confidence: 'high' | 'medium' | 'low'; + factors: string[]; + weatherImpact?: string; +} + +interface WeatherAlert { + type: 'rain' | 'heat' | 'cold'; + impact: string; + recommendation: string; +} + +const ForecastPage: React.FC = () => { + const [selectedDate, setSelectedDate] = useState(new Date().toISOString().split('T')[0]); + const [selectedProduct, setSelectedProduct] = useState('all'); + const [forecasts, setForecasts] = useState([]); + const [weatherAlert, setWeatherAlert] = useState(null); + const [isLoading, setIsLoading] = useState(true); + + const products = [ + 'Croissants', 'Pan de molde', 'Baguettes', 'Napolitanas', + 'Café', 'Magdalenas', 'Donuts', 'Bocadillos' + ]; + + // Sample forecast data for the next 7 days + const sampleForecastData = [ + { date: '2024-11-04', croissants: 48, pan: 35, cafe: 72 }, + { date: '2024-11-05', croissants: 52, pan: 38, cafe: 78 }, + { date: '2024-11-06', croissants: 45, pan: 32, cafe: 65 }, + { date: '2024-11-07', croissants: 41, pan: 29, cafe: 58 }, + { date: '2024-11-08', croissants: 56, pan: 42, cafe: 82 }, + { date: '2024-11-09', croissants: 61, pan: 45, cafe: 89 }, + { date: '2024-11-10', croissants: 38, pan: 28, cafe: 55 }, + ]; + + useEffect(() => { + const loadForecasts = async () => { + setIsLoading(true); + + try { + // Simulate API call + await new Promise(resolve => setTimeout(resolve, 1000)); + + // Mock weather alert + setWeatherAlert({ + type: 'rain', + impact: 'Se esperan lluvias moderadas mañana', + recommendation: 'Reduce la producción de productos frescos en un 20%' + }); + + // Mock forecast data + const mockForecasts: ForecastData[] = [ + { + date: selectedDate, + product: 'Croissants', + predicted: 48, + confidence: 'high', + factors: ['Día laboral', 'Clima estable', 'Sin eventos especiales'], + weatherImpact: 'Sin impacto significativo' + }, + { + date: selectedDate, + product: 'Pan de molde', + predicted: 35, + confidence: 'high', + factors: ['Demanda constante', 'Histórico estable'], + weatherImpact: 'Sin impacto' + }, + { + date: selectedDate, + product: 'Café', + predicted: 72, + confidence: 'medium', + factors: ['Temperatura fresca', 'Día laboral'], + weatherImpact: 'Aumento del 10% por temperatura' + }, + { + date: selectedDate, + product: 'Baguettes', + predicted: 28, + confidence: 'medium', + factors: ['Día entre semana', 'Demanda normal'], + weatherImpact: 'Sin impacto' + }, + { + date: selectedDate, + product: 'Napolitanas', + predicted: 23, + confidence: 'low', + factors: ['Variabilidad alta', 'Datos limitados'], + weatherImpact: 'Posible reducción del 5%' + } + ]; + + setForecasts(mockForecasts); + } catch (error) { + console.error('Error loading forecasts:', error); + } finally { + setIsLoading(false); + } + }; + + loadForecasts(); + }, [selectedDate]); + + const getConfidenceColor = (confidence: string) => { + switch (confidence) { + case 'high': + return 'bg-success-100 text-success-800 border-success-200'; + case 'medium': + return 'bg-warning-100 text-warning-800 border-warning-200'; + case 'low': + return 'bg-danger-100 text-danger-800 border-danger-200'; + default: + return 'bg-gray-100 text-gray-800 border-gray-200'; + } + }; + + const getConfidenceLabel = (confidence: string) => { + switch (confidence) { + case 'high': + return 'Alta confianza'; + case 'medium': + return 'Confianza media'; + case 'low': + return 'Baja confianza'; + default: + return 'N/A'; + } + }; + + const filteredForecasts = selectedProduct === 'all' + ? forecasts + : forecasts.filter(f => f.product.toLowerCase().includes(selectedProduct.toLowerCase())); + + if (isLoading) { + return ( +
+
+
+
+
+
+
+
+
+
+ ); + } + + return ( +
+ {/* Header */} +
+
+

Predicciones IA

+

+ Predicciones inteligentes para optimizar tu producción +

+
+
+ + {/* Weather Alert */} + {weatherAlert && ( +
+
+ +
+

Alerta Meteorológica

+

{weatherAlert.impact}

+

+ 💡 Recomendación: {weatherAlert.recommendation} +

+
+
+
+ )} + + {/* Controls */} +
+
+
+ +
+ + setSelectedDate(e.target.value)} + min={new Date().toISOString().split('T')[0]} + max={new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0]} + className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-primary-500 focus:border-primary-500" + /> +
+
+ +
+ + +
+
+
+ + {/* Forecast Cards */} +
+ {filteredForecasts.map((forecast, index) => ( +
+
+

{forecast.product}

+ + {getConfidenceLabel(forecast.confidence)} + +
+ +
+
+ {forecast.predicted} + unidades +
+

+ Predicción para {new Date(forecast.date).toLocaleDateString('es-ES', { + weekday: 'long', + year: 'numeric', + month: 'long', + day: 'numeric' + })} +

+
+ +
+
+

+ + Factores considerados +

+
    + {forecast.factors.map((factor, i) => ( +
  • + + {factor} +
  • + ))} +
+
+ + {forecast.weatherImpact && ( +
+

+ + Impacto del clima +

+

{forecast.weatherImpact}

+
+ )} +
+
+ ))} +
+ + {/* Trend Chart */} +
+

+ Tendencia de Predicciones (Próximos 7 Días) +

+
+ + + + { + const date = new Date(value); + return `${date.getDate()}/${date.getMonth() + 1}`; + }} + /> + + { + const date = new Date(value); + return date.toLocaleDateString('es-ES', { + weekday: 'long', + day: 'numeric', + month: 'long' + }); + }} + /> + + + + + +
+
+ + {/* Recommendations */} +
+

+ Recomendaciones Inteligentes +

+
+
+ +
+

Oportunidad de Aumento

+

+ La demanda de café aumentará un 15% esta semana por las bajas temperaturas. + Considera aumentar el stock de café y bebidas calientes. +

+
+
+ +
+ +
+

Ajuste Recomendado

+

+ Las napolitanas muestran alta variabilidad. Considera reducir la producción + inicial y hornear más según demanda en tiempo real. +

+
+
+ +
+ +
+

Optimización de Horarios

+

+ El pico de demanda de croissants será entre 7:30-9:00 AM. + Asegúrate de tener suficiente stock listo para esas horas. +

+
+
+
+
+ + {/* Export Actions */} +
+

+ Acciones Rápidas +

+
+ + + + + +
+
+
+ ); +}; + +export default ForecastPage; \ No newline at end of file diff --git a/frontend/src/pages/index.tsx b/frontend/src/pages/index.tsx deleted file mode 100644 index d9d17b58..00000000 --- a/frontend/src/pages/index.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import Head from 'next/head'; -import Link from 'next/link'; - -const HomePage = () => { - return ( -
{/* Set overall background to PanIA white */} - - PanIA - Inteligencia Artificial para tu Panadería {/* Updated title and tagline */} - {/* Updated meta description */} - - - {/* Navigation Bar */} -
- -
- -
- {/* Hero Section */} -
{/* Warm Golden background */} -
-

- Inteligencia Artificial que Revoluciona tu Panadería -

-

- Reduce desperdicios hasta 25% y aumenta ganancias con predicciones precisas diseñadas para panaderías españolas. -

- - Prueba Gratis 30 Días - -
-
- - {/* Social Proof Section */} -
-
-

- Más de 150 panaderías confían en PanIA -

-
- {/* Placeholder for customer logos */} -
Logo 1
-
Logo 2
-
Logo 3
-
-

- "PanIA ha transformado completamente nuestra gestión de inventario. ¡Menos desperdicio y más beneficios!" - Panadería San Miguel, Madrid -

- {/* Placeholder for star ratings */} -
★★★★★
-
-
- - {/* Features Section - Cómo Funciona PanIA */} -
-
-

- Cómo Funciona PanIA -

-
-
-
📊
{/* Icon placeholder */} -

Conecta tus Datos

-

Sube tus ventas históricas en 5 minutos de forma segura y sencilla.

-
-
-
🧠
{/* Icon placeholder */} -

IA Entrena tu Modelo

-

Nuestra Inteligencia Artificial aprende los patrones únicos de tu negocio y mercado local.

-
-
-
📈
{/* Icon placeholder */} -

Recibe Predicciones

-

Obtén predicciones diarias precisas automáticamente para optimizar tu producción.

-
-
-
💰
{/* Icon placeholder */} -

Reduce Desperdicios

-

Ve resultados inmediatos en tu desperdicio y un aumento significativo en tus ganancias.

-
-
-
-
- - {/* Call to Action Section */} -
{/* Tech Blue background */} -
-

- ¿Listo para transformar tu panadería? -

-

- Únete a las panaderías que ya están viendo el futuro con PanIA. -

- {/* Golden CTA button */} - Comienza tu Prueba Gratis - -
-
- - {/* Trust Signals Section */} -
{/* Charcoal background */} -
-
-

Datos seguros y protegidos

-

(GDPR compliant)

-
-
-

Soporte en español

-

7 días a la semana

-
-
-

Garantía de satisfacción

-

100%

-
-
-
-
- - {/* Footer */} -
-
-

© {new Date().getFullYear()} PanIA. Todos los derechos reservados.

-
- Política de Privacidad - Términos de Servicio - Contacto -
-
-
-
- ); -}; - -export default HomePage; \ No newline at end of file diff --git a/frontend/src/pages/landing/LandingPage.tsx b/frontend/src/pages/landing/LandingPage.tsx new file mode 100644 index 00000000..afabd0ed --- /dev/null +++ b/frontend/src/pages/landing/LandingPage.tsx @@ -0,0 +1,549 @@ +import React, { useState, useEffect } from 'react'; +import { + TrendingUp, + TrendingDown, + Package, + Clock, + Users, + Star, + ChevronRight, + CheckCircle, + BarChart3, + Shield, + Smartphone, + Play, + ArrowRight, + MapPin, + Quote +} from 'lucide-react'; + +interface LandingPageProps { + onNavigateToLogin: () => void; + onNavigateToRegister: () => void; +} + +const LandingPage: React.FC = ({ onNavigateToLogin, onNavigateToRegister }) => { + const [isVideoModalOpen, setIsVideoModalOpen] = useState(false); + const [currentTestimonial, setCurrentTestimonial] = useState(0); + + const features = [ + { + icon: TrendingUp, + title: "Predicciones Precisas", + description: "IA que aprende de tu negocio único para predecir demanda con 87% de precisión", + color: "bg-success-100 text-success-600" + }, + { + icon: TrendingDown, + title: "Reduce Desperdicios", + description: "Disminuye hasta un 25% el desperdicio diario optimizando tu producción", + color: "bg-primary-100 text-primary-600" + }, + { + icon: Clock, + title: "Ahorra Tiempo", + description: "30-45 minutos menos al día en planificación manual de producción", + color: "bg-blue-100 text-blue-600" + }, + { + icon: Package, + title: "Gestión Inteligente", + description: "Pedidos automáticos y alertas de stock basados en predicciones", + color: "bg-purple-100 text-purple-600" + } + ]; + + const testimonials = [ + { + name: "María González", + business: "Panadería San Miguel", + location: "Chamberí, Madrid", + text: "Con PanIA reduje mis desperdicios un 20% en el primer mes. La IA realmente entiende mi negocio.", + rating: 5, + savings: "€280/mes" + }, + { + name: "Carlos Ruiz", + business: "Obrador Central Goya", + location: "Salamanca, Madrid", + text: "Gestiono 4 puntos de venta y PanIA me ahorra 2 horas diarias de planificación. Imprescindible.", + rating: 5, + savings: "€450/mes" + }, + { + name: "Ana Martín", + business: "Café & Pan Malasaña", + location: "Malasaña, Madrid", + text: "Las predicciones son increíblemente precisas. Ya no me quedo sin croissants en el desayuno.", + rating: 5, + savings: "€190/mes" + } + ]; + + const stats = [ + { number: "500+", label: "Panaderías en Madrid" }, + { number: "87%", label: "Precisión en predicciones" }, + { number: "25%", label: "Reducción desperdicios" }, + { number: "€350", label: "Ahorro mensual promedio" } + ]; + + const madridDistricts = [ + "Centro", "Salamanca", "Chamberí", "Retiro", "Arganzuela", + "Moncloa", "Chamartín", "Hortaleza", "Fuencarral", "Tetuán" + ]; + + useEffect(() => { + const interval = setInterval(() => { + setCurrentTestimonial((prev) => (prev + 1) % testimonials.length); + }, 5000); + return () => clearInterval(interval); + }, [testimonials.length]); + + return ( +
+ {/* Header */} +
+
+
+
+
+ 🥖 +
+ PanIA +
+ + + +
+ + +
+
+
+
+ + {/* Hero Section */} +
+
+
+
+
+ + IA líder para panaderías en Madrid +
+ +

+ La primera IA para + tu panadería +

+ +

+ Transforma tus datos de ventas en predicciones precisas. + Reduce desperdicios, maximiza ganancias y optimiza tu producción + con inteligencia artificial diseñada para panaderías madrileñas. +

+ +
+ + + +
+ +
+ + 30 días gratis • Sin tarjeta de crédito • Configuración en 5 minutos +
+
+ +
+
+
+

Predicciones para Hoy

+ + 87% precisión + +
+ +
+ {[ + { product: "Croissants", predicted: 48, confidence: "high", change: 8 }, + { product: "Pan de molde", predicted: 35, confidence: "high", change: 3 }, + { product: "Café", predicted: 72, confidence: "medium", change: -5 } + ].map((item, index) => ( +
+
+
{item.product}
+
+ {item.change > 0 ? ( + + ) : ( + + )} + {Math.abs(item.change)} vs ayer +
+
+
+
{item.predicted}
+
+ {item.confidence === 'high' ? 'Alta confianza' : 'Media confianza'} +
+
+
+ ))} +
+
+ + {/* Floating stats */} +
+
+
-25%
+
Desperdicios
+
+
+ +
+
+
€350
+
Ahorro/mes
+
+
+
+
+
+
+ + {/* Stats Section */} +
+
+
+

+ Resultados que hablan por sí solos +

+

+ Más de 500 panaderías en Madrid ya confían en PanIA para optimizar su producción +

+
+ +
+ {stats.map((stat, index) => ( +
+
+ {stat.number} +
+
{stat.label}
+
+ ))} +
+
+
+ + {/* Features Section */} +
+
+
+

+ IA diseñada para panaderías madrileñas +

+

+ Cada característica está pensada para resolver los desafíos específicos + de las panaderías en Madrid: desde el clima hasta los patrones de consumo locales +

+
+ +
+ {features.map((feature, index) => { + const Icon = feature.icon; + return ( +
+
+ +
+

{feature.title}

+

{feature.description}

+
+ ); + })} +
+ + {/* Madrid-specific features */} +
+
+
+

+ Especializado en Madrid +

+

+ PanIA conoce Madrid como ninguna otra IA. Integra datos del clima, + tráfico, eventos y patrones de consumo específicos de la capital. +

+
+
+ + Integración con datos meteorológicos de AEMET +
+
+ + Análisis de eventos y festividades locales +
+
+ + Patrones de tráfico peatonal por distrito +
+
+ + Horarios de siesta y patrones españoles +
+
+
+ +
+
+ +

Distritos cubiertos

+
+
+ {madridDistricts.map((district, index) => ( +
+ {district} +
+ ))} +
+
+
+
+
+
+ + {/* Testimonials Section */} +
+
+
+

+ Lo que dicen nuestros clientes +

+

+ Panaderías reales, resultados reales en Madrid +

+
+ +
+
+
+
+ + +
+ "{testimonials[currentTestimonial].text}" +
+ +
+ {[...Array(testimonials[currentTestimonial].rating)].map((_, i) => ( + + ))} +
+ +
+
+ {testimonials[currentTestimonial].name} +
+
+ {testimonials[currentTestimonial].business} +
+
+ {testimonials[currentTestimonial].location} +
+
+ Ahorro: {testimonials[currentTestimonial].savings} +
+
+
+
+
+ + {/* Testimonial indicators */} +
+ {testimonials.map((_, index) => ( +
+
+
+
+ + {/* CTA Section */} +
+
+

+ ¿Listo para transformar tu panadería? +

+

+ Únete a más de 500 panaderías en Madrid que ya reducen desperdicios + y maximizan ganancias con PanIA +

+ +
+ + +
+ +
+
+ + 30 días gratis +
+
+ + Sin tarjeta de crédito +
+
+ + Soporte en español +
+
+
+
+ + {/* Footer */} + + + {/* Video Modal */} + {isVideoModalOpen && ( +
+
+
+

Demo de PanIA

+ +
+
+
+ +

Video demo disponible próximamente

+

+ Mientras tanto, puedes comenzar tu prueba gratuita +

+ +
+
+
+
+ )} +
+ ); +}; + +export default LandingPage; \ No newline at end of file diff --git a/frontend/src/pages/login.tsx b/frontend/src/pages/login.tsx deleted file mode 100644 index 60cfe7a7..00000000 --- a/frontend/src/pages/login.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { useState } from 'react'; -import { useRouter } from 'next/router'; -import Head from 'next/head'; -import { useAuth } from '../contexts/AuthContext'; - -const Login = () => { - const [username, setUsername] = useState(''); - const [password, setPassword] = useState(''); - const [error, setError] = useState(''); - const { login } = useAuth(); - const router = useRouter(); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - setError(''); - try { - await login(username, password); - router.push('/dashboard'); // Assuming a dashboard route after login - } catch (err) { - setError('Credenciales inválidas. Inténtalo de nuevo.'); - } - }; - - return ( -
{/* Updated background to PanIA golden */} - - Login - PanIA {/* Updated title with PanIA */} - -
{/* Updated background to PanIA white */} -
-

PanIA

{/* Updated to PanIA brand name and charcoal color */} -

Inteligencia Artificial para tu Panadería

{/* Added tagline and tech blue color */} -
-
-
- - setUsername(e.target.value)} - required - /> -
-
- - setPassword(e.target.value)} - required - /> -
- {error &&

{error}

} -
- -
-
-
-
- ); -}; - -export default Login; \ No newline at end of file diff --git a/frontend/src/pages/onboarding.tsx b/frontend/src/pages/onboarding.tsx deleted file mode 100644 index 66c02055..00000000 --- a/frontend/src/pages/onboarding.tsx +++ /dev/null @@ -1,1255 +0,0 @@ -import React, { useState, useRef, useEffect, useCallback } from 'react'; -import { - CheckIcon, - ArrowRightIcon, - ArrowLeftIcon, - CloudArrowUpIcon, - BuildingStorefrontIcon, - UserCircleIcon, - CpuChipIcon, - SparklesIcon, - ChartBarIcon, - ExclamationTriangleIcon, - XMarkIcon -} from '@heroicons/react/24/outline'; - -// Updated imports in onboarding.tsx -import { - TenantUser, - TenantCreate, - TenantInfo , - DataValidation, - TrainingJobStatus -} from '@/api/services'; - - -import { api } from '@/api/services'; - -import { useAuth } from '../contexts/AuthContext'; - -const OnboardingPage = () => { - const [currentStep, setCurrentStep] = useState(1); - const [completedSteps, setCompletedSteps] = useState([]); - const [loading, setLoading] = useState(false); - const [notification, setNotification] = useState(null); - const [currentTenantId, setCurrentTenantId] = useState(null); - const [formData, setFormData] = useState({ - // User registration fields - full_name: '', - email: '', - password: '', - confirm_password: '', - - // Bakery/Tenant fields - matching ACTUAL BakeryRegistration schema - bakery_name: '', - address: '', - city: 'Madrid', // Default as per backend - postal_code: '', // Required - must match regex ^\d{5}$ - phone: '', // Will use default if empty, validated for Spanish format - business_type: 'bakery', // Must be one of: ['bakery', 'coffee_shop', 'pastry_shop', 'restaurant'] - - // Additional form fields (not part of BakeryRegistration) - has_nearby_schools: false, - has_nearby_offices: false, - selected_products: ['Pan de molde', 'Croissants', 'Magdalenas'], - salesFile: null, - trainingStatus: 'pending', - trainingTaskId: null, - trainingProgress: 0, - }); - const [errors, setErrors] = useState({}); - const [uploadValidation, setUploadValidation] = useState(null); - const [trainingProgress, setTrainingProgress] = useState(null); - - const fileInputRef = useRef(null); - - // Steps configuration - const steps = [ - { - id: 1, - title: 'Crear Cuenta', - subtitle: 'Información personal', - icon: UserCircleIcon, - color: 'bg-blue-500' - }, - { - id: 2, title: 'Datos de Panadería', - subtitle: 'Información del negocio', - icon: BuildingStorefrontIcon, - color: 'bg-purple-500' - }, - { - id: 3, - title: 'Historial de Ventas', - subtitle: 'Subir datos históricos', - icon: CloudArrowUpIcon, - color: 'bg-green-500' - }, - { - id: 4, - title: 'Entrenar Modelos', - subtitle: 'IA analizando datos', - icon: CpuChipIcon, - color: 'bg-orange-500' - }, - { - id: 5, - title: '¡Listo!', - subtitle: 'Sistema configurado', - icon: SparklesIcon, - color: 'bg-pink-500' - } - ]; - - useEffect(() => { - const startTrainingWhenReachingStep4 = async () => { - // Only trigger if we just reached step 4 and haven't started training yet - if (currentStep === 4 && !formData.trainingTaskId && !loading) { - console.log('Auto-starting training for step 4...'); - - setLoading(true); - - try { - // Check if we have required data - if (!formData.selected_products || formData.selected_products.length === 0) { - showNotification('error', 'No hay productos', 'No se han seleccionado productos para entrenar.'); - setLoading(false); - return; - } - - if (!currentTenantId) { - showNotification('error', 'Error de configuración', 'No se ha configurado el tenant ID.'); - setLoading(false); - return; - } - - // Training configuration - const trainingConfig = { - include_weather: true, - include_traffic: true, - products: formData.selected_products, - min_data_points: 30, - forecast_horizon_days: 7, - cross_validation_folds: 3, - hyperparameter_tuning: true - }; - - console.log('Starting training with config:', trainingConfig); - - // Start training via API - const trainingJob: TrainingJobStatus = await api.training.startTraining(currentTenantId, trainingConfig); - - // Update form data with training job ID - setFormData(prev => ({ - ...prev, - trainingTaskId: trainingJob.job_id, - trainingStatus: 'running' - })); - - showNotification('info', 'Entrenamiento iniciado', 'Los modelos se están entrenando...'); - - } catch (error) { - console.error('Error starting training:', error); - - let errorMessage = 'No se pudo iniciar el entrenamiento.'; - let errorTitle = 'Error de entrenamiento'; - - if (error.response?.status === 400) { - errorMessage = error.response.data?.detail || 'Configuración de entrenamiento inválida.'; - } else if (error.response?.status === 401) { - errorMessage = 'No autorizado. Por favor, inicia sesión nuevamente.'; - errorTitle = 'Error de autenticación'; - } else if (error.response?.status === 403) { - errorMessage = 'No tienes permisos para iniciar el entrenamiento.'; - errorTitle = 'Error de permisos'; - } else if (error.response?.status === 500) { - errorMessage = 'Error interno del servidor. Inténtalo más tarde.'; - errorTitle = 'Error del servidor'; - } - - showNotification('error', errorTitle, errorMessage); - - // Optionally go back to previous step on error - // setCurrentStep(3); - } finally { - setLoading(false); - } - } - }; - - startTrainingWhenReachingStep4(); - }, [currentStep, formData.trainingTaskId, formData.selected_products, currentTenantId, loading]); - - const showNotification = (type, title, message) => { - const id = Date.now().toString(); - setNotification({ id, type, title, message }); - setTimeout(() => setNotification(null), 5000); - }; - - const validateStep = (step) => { - const newErrors = {}; - - switch (step) { - case 1: - if (!formData.full_name.trim()) newErrors.full_name = 'Nombre requerido'; - if (!formData.email.trim()) newErrors.email = 'Email requerido'; - if (!formData.password) newErrors.password = 'Contraseña requerida'; - if (formData.password !== formData.confirm_password) { - newErrors.confirm_password = 'Las contraseñas no coinciden'; - } - break; - case 2: - if (!formData.bakery_name.trim()) newErrors.bakery_name = 'Nombre de panadería requerido'; - if (!formData.address.trim()) newErrors.address = 'Dirección requerida'; - if (!formData.postal_code.trim()) { - newErrors.postal_code = 'Código postal requerido'; - } else if (!/^\d{5}$/.test(formData.postal_code)) { - newErrors.postal_code = 'Código postal debe tener 5 dígitos'; - } - - // Validate business_type matches backend expectations - const validBusinessTypes = ['bakery', 'coffee_shop', 'pastry_shop', 'restaurant']; - if (!validBusinessTypes.includes(formData.business_type)) { - newErrors.business_type = 'Tipo de negocio inválido'; - } - - // Optional: Validate phone format if provided (Spanish format as per backend validator) - if (formData.phone && formData.phone.trim()) { - const phoneRegex = /^(\+34|0034|34)?[6789]\d{8}$/; - if (!phoneRegex.test(formData.phone.replace(/[\s\-\(\)]/g, ''))) { - newErrors.phone = 'Formato de teléfono español inválido'; - } - } - break; - case 3: - if (!formData.salesFile) newErrors.salesFile = 'Archivo de ventas requerido'; - break; - } - - setErrors(newErrors); - return Object.keys(newErrors).length === 0; - }; - - const handleNext = async () => { - if (!validateStep(currentStep)) return; - - setLoading(true); - - try { - if (currentStep === 1) { - // Register user using real auth service - const userData = { - email: formData.email, - password: formData.password, - full_name: formData.full_name - }; - - const user = await api.auth.register(userData); - showNotification('success', 'Usuario creado', 'Cuenta registrada exitosamente.'); - - } else if (currentStep === 2) { - // Register bakery using real tenant service with proper TenantCreate interface - const bakeryData: TenantCreate = { - name: formData.bakery_name, - address: formData.address, - city: formData.city || 'Madrid', // Default value as per backend schema - postal_code: formData.postal_code, // Required field - phone: formData.phone || '+34600000000', // Required field with default - business_type: formData.business_type || 'bakery' // Must be one of: ['bakery', 'coffee_shop', 'pastry_shop', 'restaurant'] - }; - - // The response will be typed as TenantInfo - const tenant: TenantInfo = await api.tenant.registerBakery(bakeryData); - setCurrentTenantId(tenant.id); - showNotification('success', 'Panadería registrada', 'Información guardada correctamente.'); - - } else if (currentStep === 3) { - // ✅ UPDATED: Sales upload step with new schema handling - if (formData.salesFile) { - try { - // Validate if not already validated - let validation = uploadValidation; - if (!validation) { - validation = await api.data.validateSalesData(formData.salesFile, currentTenantId); - setUploadValidation(validation); - } - - // ✅ UPDATED: Check validation using new schema - if (!validation.is_valid) { - const errors = validation.errors || []; - const errorMessages = errors.map(error => - `${error.row ? `Fila ${error.row}: ` : ''}${error.message}` - ).join('; '); - - showNotification('error', 'Datos inválidos', - `Se encontraron errores: ${errorMessages.slice(0, 200)}${errorMessages.length > 200 ? '...' : ''}`); - setLoading(false); - return; - } - - // Show warnings if any - const warnings = validation.warnings || []; - if (warnings.length > 0) { - const warningMessages = warnings.map(warning => - `${warning.row ? `Fila ${warning.row}: ` : ''}${warning.message}` - ).join('; '); - - showNotification('warning', 'Advertencias encontradas', - `Advertencias: ${warningMessages.slice(0, 200)}${warningMessages.length > 200 ? '...' : ''}`); - } - - // Proceed with actual upload - const uploadResult = await api.data.uploadSalesHistory( - formData.salesFile, - currentTenantId - ); - - - - showNotification('success', 'Archivo subido', - `${uploadResult.records_processed} registros procesados exitosamente.`); - - } catch (error: any) { - console.error('Sales upload error:', error); - // ... existing error handling - } - } - } else if (currentStep === 4) { - // Training step - const trainingConfig = { - include_weather: true, - include_traffic: true, - products: formData.selected_products, - min_data_points: 30, - forecast_horizon_days: 7, - cross_validation_folds: 3, - hyperparameter_tuning: true - }; - - const trainingJob = await api.training.startTraining(currentTenantId, trainingConfig); - setFormData(prev => ({ - ...prev, - trainingTaskId: trainingJob.id, - trainingStatus: 'running' - })); - showNotification('info', 'Entrenamiento iniciado', 'Los modelos se están entrenando...'); - - setLoading(false); - return; - } - - // Mark step as completed and move to next - setCompletedSteps([...completedSteps, currentStep]); - if (currentStep < 5) { - setCurrentStep(currentStep + 1); - } - - } catch (error) { - console.error('Error in step:', error); - - // Handle specific API errors - let errorMessage = 'Hubo un problema. Inténtalo de nuevo.'; - let errorTitle = 'Error'; - - if (error.response?.status === 400) { - errorMessage = error.response.data?.detail || 'Datos inválidos.'; - errorTitle = 'Error de validación'; - } else if (error.response?.status === 409) { - errorMessage = 'El email ya está registrado.'; - errorTitle = 'Usuario existente'; - } else if (error.response?.status === 422) { - errorMessage = 'Formato de datos incorrecto.'; - errorTitle = 'Error de formato'; - } else if (error.response?.status >= 500) { - errorMessage = 'Error del servidor. Inténtalo más tarde.'; - errorTitle = 'Error del servidor'; - } - - showNotification('error', errorTitle, errorMessage); - } finally { - setLoading(false); - } - }; - - const handleBack = () => { - if (currentStep > 1) { - setCurrentStep(currentStep - 1); - } - }; - - const handleFileUpload = async (event: React.ChangeEvent) => { - const file = event.target.files?.[0]; - if (!file) return; - - setFormData(prev => ({ ...prev, salesFile: file })); - setUploadValidation(null); - - try { - setLoading(true); - console.log('Validating file:', file.name); - - // Pass the current tenant ID to validation - const validation = await api.data.validateSalesData(file, currentTenantId); - - if (!validation) { - throw new Error('No validation response received from server'); - } - - console.log('Validation result:', validation); - setUploadValidation(validation); - - // ✅ FIXED: Use backend's response structure (both "valid" and "is_valid" supported) - const isValid = validation.is_valid !== undefined ? validation.is_valid : validation.valid; - - if (isValid) { - const recordCount = validation.total_records || validation.recordCount || 'Algunos'; - showNotification('success', 'Archivo válido', - `${recordCount} registros detectados.`); - } else if (validation.warnings && validation.warnings.length > 0 && - (!validation.errors || validation.errors.length === 0)) { - showNotification('warning', 'Archivo con advertencias', - 'El archivo es válido pero tiene algunas advertencias.'); - } else { - const errorCount = validation.errors ? validation.errors.length : 0; - showNotification('error', 'Archivo con errores', - `Se encontraron ${errorCount} errores en el archivo.`); - } - - } catch (error: any) { - console.error('Error validating file:', error); - - let errorMessage = 'Error al validar el archivo'; - if (error.response?.status === 422) { - errorMessage = 'Formato de archivo inválido'; - } else if (error.response?.status === 400) { - errorMessage = 'El archivo no se puede procesar'; - } else if (error.response?.status === 500) { - errorMessage = 'Error del servidor. Inténtalo más tarde.'; - } else if (error.message) { - errorMessage = error.message; - } - - showNotification('error', 'Error de validación', errorMessage); - - // ✅ FIXED: Set validation state using a unified structure - setUploadValidation({ - is_valid: false, - valid: false, // Backward compatibility - errors: [{ type: 'client_error', message: errorMessage }], - warnings: [], - total_records: 0, - valid_records: 0, - invalid_records: 0, - summary: { - status: 'error', - suggestions: ['Intenta con un archivo diferente'] - } - }); - } finally { - setLoading(false); - } - }; - - const renderValidationResult = () => { - if (!uploadValidation) return null; - - // ✅ NEW: Use the updated schema fields - const isValid = uploadValidation.is_valid; - const totalRecords = uploadValidation.total_records || 0; - const validRecords = uploadValidation.valid_records || 0; - const invalidRecords = uploadValidation.invalid_records || 0; - const errors = uploadValidation.errors || []; - const warnings = uploadValidation.warnings || []; - const summary = uploadValidation.summary || { suggestions: [] }; - - return ( -
-
- {isValid ? ( - - ) : ( - - )} -
-

- {isValid ? 'Archivo válido' : 'Archivo con problemas'} -

- - {/* ✅ ENHANCED: Display comprehensive record information */} -

- {totalRecords > 0 && ( - <> - {totalRecords} registros encontrados - {validRecords > 0 && ` (${validRecords} válidos`} - {invalidRecords > 0 && `, ${invalidRecords} con errores)`} - {validRecords > 0 && invalidRecords === 0 && ')'} - - )} - {summary.file_size_mb && ( - - • {summary.file_size_mb}MB - - )} -

- - {/* ✅ ENHANCED: Display structured errors */} - {errors.length > 0 && ( -
-

Errores:

-
    - {errors.slice(0, 3).map((error, idx) => ( -
  • - - - {error.row && `Fila ${error.row}: `} - {error.message} - -
  • - ))} - {errors.length > 3 && ( -
  • - ... y {errors.length - 3} errores más -
  • - )} -
-
- )} - - {/* ✅ ENHANCED: Display structured warnings */} - {warnings.length > 0 && ( -
-

Advertencias:

-
    - {warnings.slice(0, 2).map((warning, idx) => ( -
  • - - - {warning.row && `Fila ${warning.row}: `} - {warning.message} - -
  • - ))} - {warnings.length > 2 && ( -
  • - ... y {warnings.length - 2} advertencias más -
  • - )} -
-
- )} - - {/* ✅ ENHANCED: Display suggestions from summary */} - {summary.suggestions && summary.suggestions.length > 0 && ( -
-

Sugerencias:

-
    - {summary.suggestions.map((suggestion, idx) => ( -
  • - - {suggestion} -
  • - ))} -
-
- )} -
-
-
- ); - }; - - const renderStepIndicator = () => ( -
-
- {steps.map((step, index) => ( -
-
-
- {completedSteps.includes(step.id) ? ( - - ) : ( - - )} -
-
-
{step.title}
-
{step.subtitle}
-
-
- {index < steps.length - 1 && ( -
- )} -
- ))} -
-
- ); - - const renderStep1 = () => ( -
-
-

Crear tu cuenta

-

Empecemos con tu información personal

-
- -
-
- - setFormData(prev => ({ ...prev, full_name: e.target.value }))} - className={`w-full px-4 py-3 border rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all ${ - errors.full_name ? 'border-red-500' : 'border-gray-300' - }`} - placeholder="Tu nombre completo" - /> - {errors.full_name &&

{errors.full_name}

} -
- -
- - setFormData(prev => ({ ...prev, email: e.target.value }))} - className={`w-full px-4 py-3 border rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all ${ - errors.email ? 'border-red-500' : 'border-gray-300' - }`} - placeholder="tu@email.com" - /> - {errors.email &&

{errors.email}

} -
- -
-
- - setFormData(prev => ({ ...prev, password: e.target.value }))} - className={`w-full px-4 py-3 border rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all ${ - errors.password ? 'border-red-500' : 'border-gray-300' - }`} - placeholder="Mínimo 8 caracteres" - /> - {errors.password &&

{errors.password}

} -
- -
- - setFormData(prev => ({ ...prev, confirm_password: e.target.value }))} - className={`w-full px-4 py-3 border rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all ${ - errors.confirm_password ? 'border-red-500' : 'border-gray-300' - }`} - placeholder="Confirma tu contraseña" - /> - {errors.confirm_password &&

{errors.confirm_password}

} -
-
-
-
- ); - - const renderStep2 = () => ( -
-
-

Datos de tu panadería

-

Información sobre tu negocio

-
- -
-
- - setFormData(prev => ({ ...prev, bakery_name: e.target.value }))} - className={`w-full px-4 py-3 border rounded-xl focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all ${ - errors.bakery_name ? 'border-red-500' : 'border-gray-300' - }`} - placeholder="Panadería El Buen Pan" - /> - {errors.bakery_name &&

{errors.bakery_name}

} -
- -
- - setFormData(prev => ({ ...prev, address: e.target.value }))} - className={`w-full px-4 py-3 border rounded-xl focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all ${ - errors.address ? 'border-red-500' : 'border-gray-300' - }`} - placeholder="Calle Mayor 123" - /> - {errors.address &&

{errors.address}

} -
- -
-
- - setFormData(prev => ({ ...prev, city: e.target.value }))} - className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all" - placeholder="Madrid" - /> -
- -
- - setFormData(prev => ({ ...prev, postal_code: e.target.value }))} - className={`w-full px-4 py-3 border rounded-xl focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all ${ - errors.postal_code ? 'border-red-500' : 'border-gray-300' - }`} - placeholder="28001" - /> - {errors.postal_code &&

{errors.postal_code}

} -
-
- -
-

Ubicación del negocio

-
- - -
-
- -
-

Productos principales

-
- {['Pan de molde', 'Baguettes', 'Croissants', 'Magdalenas', 'Donuts', 'Empanadas'].map((product) => ( - - ))} -
-
-
-
- ); - - const renderStep3 = () => ( -
-
-

Historial de ventas

-

Sube tus datos históricos para entrenar la IA

-
- -
-
- - - {formData.salesFile ? ( -
- -
-

{formData.salesFile.name}

-

- {(formData.salesFile.size / 1024 / 1024).toFixed(2)} MB -

-
- -
- ) : ( -
- -
-

Arrastra tu archivo aquí

-

o haz clic para seleccionar

-
- -
- )} -
- - {errors.salesFile && ( -
-

{errors.salesFile}

-
- )} - - {uploadValidation && ( -
0 - ? 'bg-red-50 border-red-200' - : 'bg-yellow-50 border-yellow-200' - }`}> -
- {uploadValidation.valid ? ( - - ) : uploadValidation.errors.length > 0 ? ( - - ) : ( - - )} -
-

0 - ? 'text-red-800' - : 'text-yellow-800' - }`}> - {uploadValidation.valid - ? 'Datos válidos' - : uploadValidation.errors.length > 0 - ? 'Errores encontrados' - : 'Advertencias encontradas' - } -

-

0 - ? 'text-red-700' - : 'text-yellow-700' - }`}> - {uploadValidation.recordCount} registros encontrados - {uploadValidation.duplicates > 0 && `, ${uploadValidation.duplicates} duplicados`} -

- - {uploadValidation.errors.length > 0 && ( -
-

Errores:

-
    - {validation.errors.map((error, idx) => ( -
  • - • {typeof error === 'string' ? error : (error?.message || 'Error no especificado')} -
  • - ))} -
-
- )} - - {uploadValidation.warnings.length > 0 && ( -
-

Advertencias:

-
    - {uploadValidation.warnings.map((warning, idx) => ( -
  • • {warning}
  • - ))} -
-
- )} -
-
-
- )} - -
-

Formato requerido

-
-

• Archivo CSV o Excel (.csv, .xlsx, .xls)

-

• Columnas: Fecha, Producto, Cantidad, Precio

-

• Mínimo 30 días de datos históricos

-

• Fechas en formato DD/MM/YYYY

-
-
-
-
- ); - - const renderStep4 = () => ( -
-
-

Entrenando modelos IA

-

Nuestros algoritmos están analizando tus datos

-
- -
- {/* Main Progress Card */} -
-
-
- -
-

Entrenamiento en progreso

-

- {trainingProgress ? trainingProgress.current_step : 'Iniciando...'} -

-
-
-
-

- {trainingProgress ? trainingProgress.progress : 0}% -

-

Completado

-
-
- -
-
-
-
- - {/* Training Steps */} -
- {[ - { title: 'Validación de datos', icon: CheckIcon, completed: trainingProgress?.progress > 10 }, - { title: 'Procesamiento', icon: CpuChipIcon, completed: trainingProgress?.progress > 30 }, - { title: 'Entrenamiento', icon: ChartBarIcon, completed: trainingProgress?.progress > 60 }, - { title: 'Validación final', icon: SparklesIcon, completed: trainingProgress?.progress > 90 } - ].map((step, idx) => ( -
(idx * 25) - ? 'bg-blue-50 border-blue-200' - : 'bg-gray-50 border-gray-200' - } - `}> -
- - - {step.title} - -
-
- ))} -
- - {/* Products Progress */} - {trainingProgress && ( -
-

Productos entrenados

-
- {formData.selected_products.map((product, idx) => ( -
- {product} -
- {idx < (trainingProgress.products_completed || 0) ? ( - - ) : idx === (trainingProgress.products_completed || 0) ? ( -
- ) : ( -
- )} -
-
- ))} -
-
- {trainingProgress.products_completed || 0} de {trainingProgress.products_total || formData.selected_products.length} productos completados -
-
- )} - - {/* Estimated Time */} - {trainingProgress && trainingProgress.progress < 100 && ( -
-
-
- - Tiempo estimado restante: ~{Math.max(1, Math.round((100 - trainingProgress.progress) / 10))} minutos - -
-
- )} -
-
- ); - - const renderStep5 = () => ( -
-
-
- -
-

¡Todo listo!

-

Tu sistema de predicción está configurado y funcionando

-
- -
-
- -

Modelos Entrenados

-

{formData.selected_products.length} productos configurados

-
- -
- -

IA Activa

-

Predicciones en tiempo real

-
- -
- -

Panadería Lista

-

Sistema completamente configurado

-
-
- -
-

¿Qué puedes hacer ahora?

-
-
- - Ver predicciones de demanda para los próximos 7 días -
-
- - Configurar alertas automáticas -
-
- - Analizar tendencias históricas -
-
- - Optimizar tu producción diaria -
-
-
- -
- -
-
- ); - - const renderCurrentStep = () => { - switch (currentStep) { - case 1: return renderStep1(); - case 2: return renderStep2(); - case 3: return renderStep3(); - case 4: return renderStep4(); - case 5: return renderStep5(); - default: return renderStep1(); - } - }; - - return ( -
- {/* Header */} -
-
-
-
- -
-
-

BakeryForecast

-

Configuración inicial

-
-
-
-
- - {/* Main Content */} -
- {renderStepIndicator()} - -
-
- {renderCurrentStep()} -
- - {/* Navigation */} -
- {currentStep > 1 && currentStep < 5 ? ( - - ) : ( -
- )} - - {currentStep < 4 && ( - - )} - - {currentStep === 4 && trainingProgress?.status !== 'completed' && ( - - )} - - {currentStep === 4 && trainingProgress?.status === 'completed' && ( - - )} -
-
-
- - {/* Notification Toast */} - {notification && ( -
-
-
-
-
- {notification.type === 'success' && } - {notification.type === 'error' && } - {notification.type === 'warning' && } - {notification.type === 'info' && } -
-
-

{notification.title}

-

{notification.message}

-
-
- -
-
-
- )} -
- ); -}; - -export default OnboardingPage; \ No newline at end of file diff --git a/frontend/src/pages/onboarding/OnboardingPage.tsx b/frontend/src/pages/onboarding/OnboardingPage.tsx new file mode 100644 index 00000000..6e5828fd --- /dev/null +++ b/frontend/src/pages/onboarding/OnboardingPage.tsx @@ -0,0 +1,516 @@ +import React, { useState } from 'react'; +import { ChevronLeft, ChevronRight, Upload, MapPin, Store, Factory, Check } from 'lucide-react'; +import toast from 'react-hot-toast'; + +interface OnboardingPageProps { + user: any; + onComplete: () => void; +} + +interface BakeryData { + name: string; + address: string; + businessType: 'individual' | 'central_workshop'; + coordinates?: { lat: number; lng: number }; + products: string[]; + hasHistoricalData: boolean; + csvFile?: File; +} + +const MADRID_PRODUCTS = [ + 'Croissants', 'Pan de molde', 'Baguettes', 'Panecillos', 'Ensaimadas', + 'Napolitanas', 'Magdalenas', 'Donuts', 'Palmeras', 'Café', + 'Chocolate caliente', 'Zumos', 'Bocadillos', 'Empanadas', 'Tartas' +]; + +const OnboardingPage: React.FC = ({ user, onComplete }) => { + const [currentStep, setCurrentStep] = useState(1); + const [isLoading, setIsLoading] = useState(false); + const [bakeryData, setBakeryData] = useState({ + name: '', + address: '', + businessType: 'individual', + products: [], + hasHistoricalData: false + }); + + const steps = [ + { id: 1, title: 'Datos de Panadería', icon: Store }, + { id: 2, title: 'Productos y Servicios', icon: Factory }, + { id: 3, title: 'Datos Históricos', icon: Upload }, + { id: 4, title: 'Configuración Final', icon: Check } + ]; + + const handleNext = () => { + if (validateCurrentStep()) { + setCurrentStep(prev => Math.min(prev + 1, steps.length)); + } + }; + + const handlePrevious = () => { + setCurrentStep(prev => Math.max(prev - 1, 1)); + }; + + const validateCurrentStep = (): boolean => { + switch (currentStep) { + case 1: + if (!bakeryData.name.trim()) { + toast.error('El nombre de la panadería es obligatorio'); + return false; + } + if (!bakeryData.address.trim()) { + toast.error('La dirección es obligatoria'); + return false; + } + return true; + case 2: + if (bakeryData.products.length === 0) { + toast.error('Selecciona al menos un producto'); + return false; + } + return true; + case 3: + if (bakeryData.hasHistoricalData && !bakeryData.csvFile) { + toast.error('Por favor, sube tu archivo CSV con datos históricos'); + return false; + } + return true; + default: + return true; + } + }; + + const handleComplete = async () => { + setIsLoading(true); + + try { + // Step 1: Register tenant/bakery + const tenantResponse = await fetch('/api/v1/tenants/register', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${localStorage.getItem('auth_token')}` + }, + body: JSON.stringify({ + name: bakeryData.name, + address: bakeryData.address, + business_type: bakeryData.businessType, + coordinates: bakeryData.coordinates, + products: bakeryData.products + }) + }); + + if (!tenantResponse.ok) { + throw new Error('Error al registrar la panadería'); + } + + const tenantData = await tenantResponse.json(); + const tenantId = tenantData.tenant.id; + + // Step 2: Upload CSV data if provided + if (bakeryData.hasHistoricalData && bakeryData.csvFile) { + const formData = new FormData(); + formData.append('file', bakeryData.csvFile); + + const uploadResponse = await fetch(`/api/v1/tenants/${tenantId}/data/upload`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${localStorage.getItem('auth_token')}` + }, + body: formData + }); + + if (!uploadResponse.ok) { + throw new Error('Error al subir los datos históricos'); + } + + // Step 3: Start training process + const trainingResponse = await fetch(`/api/v1/tenants/${tenantId}/training/start`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${localStorage.getItem('auth_token')}` + }, + body: JSON.stringify({ + products: bakeryData.products + }) + }); + + if (!trainingResponse.ok) { + throw new Error('Error al iniciar el entrenamiento del modelo'); + } + + toast.success('¡Datos subidos! El entrenamiento del modelo comenzará pronto.'); + } + + toast.success('¡Configuración completada! Bienvenido a PanIA'); + onComplete(); + + } catch (error: any) { + console.error('Onboarding completion error:', error); + toast.error(error.message || 'Error al completar la configuración'); + } finally { + setIsLoading(false); + } + }; + + const renderStep = () => { + switch (currentStep) { + case 1: + return ( +
+
+

+ Información de tu Panadería +

+ +
+
+ + setBakeryData(prev => ({ ...prev, name: e.target.value }))} + className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-primary-500 focus:border-primary-500" + placeholder="Ej: Panadería San Miguel" + /> +
+ +
+ +
+ + setBakeryData(prev => ({ ...prev, address: e.target.value }))} + className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-primary-500 focus:border-primary-500" + placeholder="Calle Mayor, 123, Madrid" + /> +
+
+ +
+ +
+ + + +
+
+
+
+
+ ); + + case 2: + return ( +
+
+

+ ¿Qué productos vendes? +

+

+ Selecciona los productos más comunes en tu panadería +

+ +
+ {MADRID_PRODUCTS.map((product) => ( + + ))} +
+ +
+

+ Productos seleccionados: {bakeryData.products.length} +

+
+
+
+ ); + + case 3: + return ( +
+
+

+ Datos Históricos de Ventas +

+

+ Para obtener mejores predicciones, puedes subir tus datos históricos de ventas +

+ +
+
+ +
+ + {bakeryData.hasHistoricalData && ( +
+
+ + + {bakeryData.csvFile ? ( +
+

+ Archivo seleccionado: +

+

+ {bakeryData.csvFile.name} +

+ +
+ ) : ( +
+

+ Sube tu archivo CSV con las ventas históricas +

+ { + const file = e.target.files?.[0]; + if (file) { + setBakeryData(prev => ({ ...prev, csvFile: file })); + } + }} + className="hidden" + id="csv-upload" + /> + +
+ )} +
+ +
+

Formato esperado del CSV:

+

Fecha, Producto, Cantidad

+

2024-01-01, Croissants, 45

+

2024-01-01, Pan de molde, 12

+
+
+ )} + + {!bakeryData.hasHistoricalData && ( +
+

+ No te preocupes, PanIA puede empezar a funcionar sin datos históricos. + Las predicciones mejorarán automáticamente conforme uses el sistema. +

+
+ )} +
+
+
+ ); + + case 4: + return ( +
+
+
+ +
+

+ ¡Todo listo para comenzar! +

+

+ Revisa los datos de tu panadería antes de continuar +

+
+ +
+
+ Panadería: +

{bakeryData.name}

+
+ +
+ Dirección: +

{bakeryData.address}

+
+ +
+ Tipo de negocio: +

+ {bakeryData.businessType === 'individual' ? 'Panadería Individual' : 'Obrador Central'} +

+
+ +
+ Productos: +

{bakeryData.products.join(', ')}

+
+ +
+ Datos históricos: +

+ {bakeryData.hasHistoricalData ? `Sí (${bakeryData.csvFile?.name})` : 'No'} +

+
+
+
+ ); + + default: + return null; + } + }; + + return ( +
+
+ {/* Header */} +
+
+ 🥖 +
+

+ Configuración inicial +

+

+ Vamos a configurar PanIA para tu panadería +

+
+ + {/* Progress Steps */} +
+
+ {steps.map((step) => ( +
+
= step.id + ? 'bg-primary-500 border-primary-500 text-white' + : 'border-gray-300 text-gray-500' + }`} + > + +
+ + {step.title} + +
+ ))} +
+
+
+
+
+ + {/* Step Content */} +
+ {renderStep()} +
+ + {/* Navigation */} +
+ + + {currentStep < steps.length ? ( + + ) : ( + + )} +
+
+
+ ); +}; + +export default OnboardingPage; \ No newline at end of file diff --git a/frontend/src/pages/orders/OrdersPage.tsx b/frontend/src/pages/orders/OrdersPage.tsx new file mode 100644 index 00000000..511b5518 --- /dev/null +++ b/frontend/src/pages/orders/OrdersPage.tsx @@ -0,0 +1,424 @@ +import React, { useState, useEffect } from 'react'; +import { Package, Plus, Edit, Trash2, Calendar, CheckCircle, AlertCircle, Clock } from 'lucide-react'; + +interface Order { + id: string; + supplier: string; + items: OrderItem[]; + orderDate: string; + deliveryDate: string; + status: 'pending' | 'confirmed' | 'delivered' | 'cancelled'; + total: number; + type: 'ingredients' | 'consumables'; +} + +interface OrderItem { + name: string; + quantity: number; + unit: string; + price: number; + suggested?: boolean; +} + +const OrdersPage: React.FC = () => { + const [orders, setOrders] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [showNewOrder, setShowNewOrder] = useState(false); + const [activeTab, setActiveTab] = useState<'all' | 'pending' | 'delivered'>('all'); + + // Sample orders data + const sampleOrders: Order[] = [ + { + id: '1', + supplier: 'Harinas Castellana', + items: [ + { name: 'Harina de trigo', quantity: 50, unit: 'kg', price: 0.85, suggested: true }, + { name: 'Levadura fresca', quantity: 2, unit: 'kg', price: 3.20 }, + { name: 'Sal marina', quantity: 5, unit: 'kg', price: 1.10 } + ], + orderDate: '2024-11-03', + deliveryDate: '2024-11-05', + status: 'pending', + total: 52.50, + type: 'ingredients' + }, + { + id: '2', + supplier: 'Distribuciones Madrid', + items: [ + { name: 'Vasos de café 250ml', quantity: 1000, unit: 'unidades', price: 0.08 }, + { name: 'Bolsas papel kraft', quantity: 500, unit: 'unidades', price: 0.12, suggested: true }, + { name: 'Servilletas', quantity: 20, unit: 'paquetes', price: 2.50 } + ], + orderDate: '2024-11-02', + deliveryDate: '2024-11-04', + status: 'confirmed', + total: 190.00, + type: 'consumables' + }, + { + id: '3', + supplier: 'Lácteos Frescos SA', + items: [ + { name: 'Leche entera', quantity: 20, unit: 'litros', price: 0.95 }, + { name: 'Mantequilla', quantity: 5, unit: 'kg', price: 4.20 }, + { name: 'Nata para montar', quantity: 3, unit: 'litros', price: 2.80 } + ], + orderDate: '2024-11-01', + deliveryDate: '2024-11-03', + status: 'delivered', + total: 47.40, + type: 'ingredients' + } + ]; + + useEffect(() => { + const loadOrders = async () => { + setIsLoading(true); + + try { + // Simulate API call + await new Promise(resolve => setTimeout(resolve, 800)); + setOrders(sampleOrders); + } catch (error) { + console.error('Error loading orders:', error); + } finally { + setIsLoading(false); + } + }; + + loadOrders(); + }, []); + + const getStatusColor = (status: string) => { + switch (status) { + case 'pending': + return 'bg-warning-100 text-warning-800 border-warning-200'; + case 'confirmed': + return 'bg-blue-100 text-blue-800 border-blue-200'; + case 'delivered': + return 'bg-success-100 text-success-800 border-success-200'; + case 'cancelled': + return 'bg-red-100 text-red-800 border-red-200'; + default: + return 'bg-gray-100 text-gray-800 border-gray-200'; + } + }; + + const getStatusLabel = (status: string) => { + switch (status) { + case 'pending': + return 'Pendiente'; + case 'confirmed': + return 'Confirmado'; + case 'delivered': + return 'Entregado'; + case 'cancelled': + return 'Cancelado'; + default: + return status; + } + }; + + const getStatusIcon = (status: string) => { + switch (status) { + case 'pending': + return ; + case 'confirmed': + return ; + case 'delivered': + return ; + case 'cancelled': + return ; + default: + return ; + } + }; + + const filteredOrders = orders.filter(order => { + if (activeTab === 'all') return true; + if (activeTab === 'pending') return order.status === 'pending' || order.status === 'confirmed'; + if (activeTab === 'delivered') return order.status === 'delivered'; + return true; + }); + + const handleDeleteOrder = (orderId: string) => { + setOrders(prev => prev.filter(order => order.id !== orderId)); + }; + + if (isLoading) { + return ( +
+
+
+
+ {[...Array(3)].map((_, i) => ( +
+ ))} +
+
+
+ ); + } + + return ( +
+ {/* Header */} +
+
+

Gestión de Pedidos

+

+ Administra tus pedidos de ingredientes y consumibles +

+
+ + +
+ + {/* Tabs */} +
+
+ {[ + { id: 'all', label: 'Todos', count: orders.length }, + { id: 'pending', label: 'Pendientes', count: orders.filter(o => o.status === 'pending' || o.status === 'confirmed').length }, + { id: 'delivered', label: 'Entregados', count: orders.filter(o => o.status === 'delivered').length } + ].map((tab) => ( + + ))} +
+
+ + {/* AI Suggestions */} +
+
+
+ +
+
+

Sugerencias Inteligentes de Pedidos

+
+

Harina de trigo: Stock bajo detectado. Recomendamos pedir 50kg para cubrir 2 semanas.

+

Bolsas de papel: Aumento del 15% en takeaway. Considera aumentar el pedido habitual.

+

Café en grano: Predicción de alta demanda por temperaturas bajas. +20% recomendado.

+
+ +
+
+
+ + {/* Orders Grid */} +
+ {filteredOrders.map((order) => ( +
+ {/* Order Header */} +
+
+

{order.supplier}

+ + {getStatusIcon(order.status)} + {getStatusLabel(order.status)} + +
+ +
+ + Entrega: {new Date(order.deliveryDate).toLocaleDateString('es-ES')} +
+ +
+ + {order.type === 'ingredients' ? 'Ingredientes' : 'Consumibles'} + + €{order.total.toFixed(2)} +
+
+ + {/* Order Items */} +
+

Artículos ({order.items.length})

+
+ {order.items.map((item, index) => ( +
+
+ {item.name} + {item.suggested && ( + + IA + + )} +
+ {item.quantity} {item.unit} × €{item.price.toFixed(2)} +
+
+ + €{(item.quantity * item.price).toFixed(2)} + +
+ ))} +
+
+ + {/* Order Actions */} +
+
+ + +
+
+
+ ))} +
+ + {/* Empty State */} + {filteredOrders.length === 0 && ( +
+ +

No hay pedidos

+

+ {activeTab === 'all' + ? 'Aún no has creado ningún pedido' + : `No hay pedidos ${activeTab === 'pending' ? 'pendientes' : 'entregados'}` + } +

+ +
+ )} + + {/* Quick Stats */} +
+
+
+
+ +
+
+

Total Pedidos

+

{orders.length}

+
+
+
+ +
+
+
+ +
+
+

Pendientes

+

+ {orders.filter(o => o.status === 'pending' || o.status === 'confirmed').length} +

+
+
+
+ +
+
+
+ +
+
+

Gasto Mensual

+

+ €{orders.reduce((sum, order) => sum + order.total, 0).toFixed(0)} +

+
+
+
+
+ + {/* Quick Actions */} +
+

+ Acciones Rápidas +

+
+ + + + + + + +
+
+ + {/* New Order Modal Placeholder */} + {showNewOrder && ( +
+
+

Nuevo Pedido

+

+ Esta funcionalidad estará disponible próximamente. PanIA analizará tus necesidades + y creará pedidos automáticos basados en las predicciones de demanda. +

+
+ + +
+
+
+ )} +
+ ); +}; + +export default OrdersPage; \ No newline at end of file diff --git a/frontend/src/pages/settings/SettingsPage.tsx b/frontend/src/pages/settings/SettingsPage.tsx new file mode 100644 index 00000000..fb6aecb0 --- /dev/null +++ b/frontend/src/pages/settings/SettingsPage.tsx @@ -0,0 +1,616 @@ +import React, { useState } from 'react'; +import { + User, + Bell, + Shield, + Globe, + Smartphone, + Mail, + LogOut, + Save, + ChevronRight, + MapPin, + Clock, + DollarSign +} from 'lucide-react'; +import toast from 'react-hot-toast'; + +interface SettingsPageProps { + user: any; + onLogout: () => void; +} + +interface UserSettings { + fullName: string; + email: string; + phone: string; + language: string; + timezone: string; + currency: string; + bakeryName: string; + bakeryAddress: string; + businessType: string; +} + +interface NotificationSettings { + emailNotifications: boolean; + smsNotifications: boolean; + dailyReports: boolean; + weeklyReports: boolean; + forecastAlerts: boolean; + stockAlerts: boolean; + orderReminders: boolean; +} + +const SettingsPage: React.FC = ({ user, onLogout }) => { + const [activeTab, setActiveTab] = useState('profile'); + const [isLoading, setIsLoading] = useState(false); + + const [userSettings, setUserSettings] = useState({ + fullName: user.fullName || '', + email: user.email || '', + phone: '', + language: 'es', + timezone: 'Europe/Madrid', + currency: 'EUR', + bakeryName: 'Mi Panadería', + bakeryAddress: '', + businessType: 'individual' + }); + + const [notificationSettings, setNotificationSettings] = useState({ + emailNotifications: true, + smsNotifications: false, + dailyReports: true, + weeklyReports: true, + forecastAlerts: true, + stockAlerts: true, + orderReminders: true + }); + + const tabs = [ + { id: 'profile', label: 'Perfil', icon: User }, + { id: 'notifications', label: 'Notificaciones', icon: Bell }, + { id: 'security', label: 'Seguridad', icon: Shield }, + { id: 'preferences', label: 'Preferencias', icon: Globe }, + ]; + + const handleSaveSettings = async () => { + setIsLoading(true); + + try { + // Simulate API call + await new Promise(resolve => setTimeout(resolve, 1000)); + + toast.success('Configuración guardada exitosamente'); + } catch (error) { + toast.error('Error al guardar la configuración'); + } finally { + setIsLoading(false); + } + }; + + const handleLogout = () => { + if (window.confirm('¿Estás seguro de que quieres cerrar sesión?')) { + onLogout(); + } + }; + + const renderProfileTab = () => ( +
+
+

Información Personal

+
+
+ + setUserSettings(prev => ({ ...prev, fullName: e.target.value }))} + className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-primary-500 focus:border-primary-500" + /> +
+ +
+ + setUserSettings(prev => ({ ...prev, email: e.target.value }))} + className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-primary-500 focus:border-primary-500" + /> +
+ +
+ + setUserSettings(prev => ({ ...prev, phone: e.target.value }))} + placeholder="+34 600 000 000" + className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-primary-500 focus:border-primary-500" + /> +
+
+
+ +
+

Información del Negocio

+
+
+ + setUserSettings(prev => ({ ...prev, bakeryName: e.target.value }))} + className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-primary-500 focus:border-primary-500" + /> +
+ +
+ +
+ + setUserSettings(prev => ({ ...prev, bakeryAddress: e.target.value }))} + placeholder="Calle Mayor, 123, Madrid" + className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-primary-500 focus:border-primary-500" + /> +
+
+ +
+ + +
+
+
+ +
+

Horarios de Operación

+
+
+
+ + +
+
+ + +
+
+ +
+ +
+ {['L', 'M', 'X', 'J', 'V', 'S', 'D'].map((day, index) => ( + + ))} +
+
+
+
+ +
+

Integración con POS

+
+
+
+
+

Sistema POS Conectado

+

Sincroniza ventas automáticamente

+
+ + Desconectado + +
+ +
+
+
+
+ ); + + const renderNotificationsTab = () => ( +
+
+

Canales de Notificación

+
+
+
+ +
+
Notificaciones por Email
+
Recibe alertas y reportes por correo
+
+
+ +
+ +
+
+ +
+
Notificaciones SMS
+
Alertas urgentes por mensaje de texto
+
+
+ +
+
+
+ +
+

Tipos de Notificación

+
+ {[ + { key: 'dailyReports', label: 'Reportes Diarios', desc: 'Resumen diario de ventas y predicciones' }, + { key: 'weeklyReports', label: 'Reportes Semanales', desc: 'Análisis semanal de rendimiento' }, + { key: 'forecastAlerts', label: 'Alertas de Predicción', desc: 'Cambios significativos en demanda' }, + { key: 'stockAlerts', label: 'Alertas de Stock', desc: 'Inventario bajo o próximos vencimientos' }, + { key: 'orderReminders', label: 'Recordatorios de Pedidos', desc: 'Próximas entregas y fechas límite' } + ].map((item) => ( +
+
+
{item.label}
+
{item.desc}
+
+ +
+ ))} +
+
+
+ ); + + const renderSecurityTab = () => ( +
+
+

Cambiar Contraseña

+
+
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+
+ +
+

Sesiones Activas

+
+
+
+
Navegador actual
+
Chrome en Windows • Madrid, España
+
Sesión actual
+
+
+ +
+
+
Mobile App
+
iPhone • Hace 2 días
+
+ +
+
+
+ +
+

Zona Peligrosa

+
+

Eliminar Cuenta

+

+ Esta acción eliminará permanentemente tu cuenta y todos los datos asociados. + No se puede deshacer. +

+ +
+
+
+ ); + + const renderPreferencesTab = () => ( +
+
+

Configuración Regional

+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ +
+

Exportar Datos

+
+ + + + + +
+
+
+ ); + + const renderTabContent = () => { + switch (activeTab) { + case 'profile': + return renderProfileTab(); + case 'notifications': + return renderNotificationsTab(); + case 'security': + return renderSecurityTab(); + case 'preferences': + return renderPreferencesTab(); + default: + return renderProfileTab(); + } + }; + + return ( +
+ {/* Header */} +
+

Configuración

+

+ Administra tu cuenta y personaliza tu experiencia en PanIA +

+
+ +
+ {/* Sidebar Navigation */} +
+ +
+ + {/* Main Content */} +
+
+ {renderTabContent()} + + {/* Save Button */} + {(activeTab === 'profile' || activeTab === 'notifications' || activeTab === 'preferences') && ( +
+
+

+ Los cambios se guardarán automáticamente +

+ +
+
+ )} +
+
+
+
+ ); +}; + +export default SettingsPage; \ No newline at end of file diff --git a/frontend/src/store/index.ts b/frontend/src/store/index.ts new file mode 100644 index 00000000..3526332a --- /dev/null +++ b/frontend/src/store/index.ts @@ -0,0 +1,22 @@ +/ src/store/index.ts +import { configureStore } from '@reduxjs/toolkit'; +import authSlice from './slices/authSlice'; +import tenantSlice from './slices/tenantSlice'; +import forecastSlice from './slices/forecastSlice'; + +export const store = configureStore({ + reducer: { + auth: authSlice, + tenant: tenantSlice, + forecast: forecastSlice, + }, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware({ + serializableCheck: { + ignoredActions: ['persist/PERSIST'], + }, + }), +}); + +export type RootState = ReturnType; +export type AppDispatch = typeof store.dispatch; \ No newline at end of file diff --git a/frontend/src/store/slices/authSlice.ts b/frontend/src/store/slices/authSlice.ts new file mode 100644 index 00000000..5624b2bf --- /dev/null +++ b/frontend/src/store/slices/authSlice.ts @@ -0,0 +1,64 @@ +// src/store/slices/authSlice.ts +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; + +interface User { + id: string; + email: string; + fullName: string; + role: string; + isOnboardingComplete: boolean; +} + +interface AuthState { + isAuthenticated: boolean; + user: User | null; + token: string | null; + isLoading: boolean; + error: string | null; +} + +const initialState: AuthState = { + isAuthenticated: false, + user: null, + token: null, + isLoading: false, + error: null, +}; + +const authSlice = createSlice({ + name: 'auth', + initialState, + reducers: { + loginStart: (state) => { + state.isLoading = true; + state.error = null; + }, + loginSuccess: (state, action: PayloadAction<{ user: User; token: string }>) => { + state.isAuthenticated = true; + state.user = action.payload.user; + state.token = action.payload.token; + state.isLoading = false; + state.error = null; + }, + loginFailure: (state, action: PayloadAction) => { + state.isAuthenticated = false; + state.user = null; + state.token = null; + state.isLoading = false; + state.error = action.payload; + }, + logout: (state) => { + state.isAuthenticated = false; + state.user = null; + state.token = null; + state.isLoading = false; + state.error = null; + }, + clearError: (state) => { + state.error = null; + }, + }, +}); + +export const { loginStart, loginSuccess, loginFailure, logout, clearError } = authSlice.actions; +export default authSlice.reducer; \ No newline at end of file diff --git a/frontend/src/store/slices/forecastSlice.ts b/frontend/src/store/slices/forecastSlice.ts new file mode 100644 index 00000000..e69de29b diff --git a/frontend/src/store/slices/tenantSlice.ts b/frontend/src/store/slices/tenantSlice.ts new file mode 100644 index 00000000..e69de29b diff --git a/frontend/src/styles/globals.css b/frontend/src/styles/globals.css index d2e25318..ba3a4b6b 100644 --- a/frontend/src/styles/globals.css +++ b/frontend/src/styles/globals.css @@ -1,6 +1,96 @@ -/* src/styles/globals.css */ -@tailwind base; -@tailwind components; -@tailwind utilities; +@import 'tailwindcss/base'; +@import 'tailwindcss/components'; +@import 'tailwindcss/utilities'; -/* You can add any custom global CSS here */ \ No newline at end of file +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Poppins:wght@400;500;600;700&display=swap'); + +/* Base styles */ +* { + box-sizing: border-box; +} + +body { + font-family: 'Inter', system-ui, -apple-system, sans-serif; + line-height: 1.5; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* Custom scrollbar */ +::-webkit-scrollbar { + width: 6px; +} + +::-webkit-scrollbar-track { + background: #f1f5f9; +} + +::-webkit-scrollbar-thumb { + background: #cbd5e1; + border-radius: 3px; +} + +::-webkit-scrollbar-thumb:hover { + background: #94a3b8; +} + +/* Focus styles */ +.focus-ring:focus { + outline: none; + box-shadow: 0 0 0 3px rgba(249, 115, 22, 0.1); + border-color: #f97316; +} + +/* Animation classes */ +.animate-fade-in { + animation: fadeIn 0.5s ease-in-out; +} + +.animate-slide-up { + animation: slideUp 0.3s ease-out; +} + +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Custom components */ +.bakery-card { + @apply bg-white rounded-xl shadow-soft p-6 hover:shadow-medium transition-all duration-200; +} + +.confidence-high { + @apply bg-green-100 text-green-800 border-green-200; +} + +.confidence-medium { + @apply bg-yellow-100 text-yellow-800 border-yellow-200; +} + +.confidence-low { + @apply bg-red-100 text-red-800 border-red-200; +} + +/* Mobile-first responsive design helpers */ +@media (max-width: 640px) { + .mobile-padding { + padding-left: 1rem; + padding-right: 1rem; + } + + .mobile-text-sm { + font-size: 0.875rem; + } +} \ No newline at end of file diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index ec5c4e60..f3714989 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -1,35 +1,133 @@ /** @type {import('tailwindcss').Config} */ -module.exports = { +export default { content: [ - './src/pages/**/*.{js,ts,jsx,tsx,mdx}', - './src/components/**/*.{js,ts,jsx,tsx,mdx}', - './src/app/**/*.{js,ts,jsx,tsx,mdx}', + "./index.html", + "./src/**/*.{js,ts,jsx,tsx}", ], theme: { extend: { colors: { + // PanIA Brand Colors primary: { - 50: '#eff6ff', - 500: '#3b82f6', - 600: '#2563eb', - 700: '#1d4ed8', + 50: '#fff7ed', + 100: '#ffedd5', + 200: '#fed7aa', + 300: '#fdba74', + 400: '#fb923c', + 500: '#f97316', // Main orange + 600: '#ea580c', + 700: '#c2410c', + 800: '#9a3412', + 900: '#7c2d12', + 950: '#431407', }, - bakery: { // Existing bakery colors, can be potentially phased out or used as accents - brown: '#8B4513', - cream: '#FFF8DC', - wheat: '#F5DEB3', + secondary: { + 50: '#f8fafc', + 100: '#f1f5f9', + 200: '#e2e8f0', + 300: '#cbd5e1', + 400: '#94a3b8', + 500: '#64748b', + 600: '#475569', + 700: '#334155', + 800: '#1e293b', + 900: '#0f172a', + 950: '#020617', + }, + // Traffic Light Indicators + success: { + 50: '#f0fdf4', + 100: '#dcfce7', + 500: '#22c55e', + 600: '#16a34a', + 700: '#15803d', + }, + warning: { + 50: '#fffbeb', + 100: '#fef3c7', + 500: '#f59e0b', + 600: '#d97706', + 700: '#b45309', + }, + danger: { + 50: '#fef2f2', + 100: '#fee2e2', + 500: '#ef4444', + 600: '#dc2626', + 700: '#b91c1c', + }, + // Spanish Theme Colors + madrid: { + 50: '#fdf2f8', + 100: '#fce7f3', + 200: '#fbcfe8', + 300: '#f9a8d4', + 400: '#f472b6', + 500: '#ec4899', + 600: '#db2777', + 700: '#be185d', + 800: '#9d174d', + 900: '#831843', + }, + }, + fontFamily: { + 'sans': ['Inter', 'system-ui', 'sans-serif'], + 'display': ['Poppins', 'Inter', 'system-ui', 'sans-serif'], + }, + fontSize: { + 'xs': ['0.75rem', { lineHeight: '1rem' }], + 'sm': ['0.875rem', { lineHeight: '1.25rem' }], + 'base': ['1rem', { lineHeight: '1.5rem' }], + 'lg': ['1.125rem', { lineHeight: '1.75rem' }], + 'xl': ['1.25rem', { lineHeight: '1.75rem' }], + '2xl': ['1.5rem', { lineHeight: '2rem' }], + '3xl': ['1.875rem', { lineHeight: '2.25rem' }], + '4xl': ['2.25rem', { lineHeight: '2.5rem' }], + }, + spacing: { + '18': '4.5rem', + '88': '22rem', + '128': '32rem', + }, + borderRadius: { + 'xl': '0.75rem', + '2xl': '1rem', + '3xl': '1.5rem', + }, + boxShadow: { + 'soft': '0 2px 15px -3px rgba(0, 0, 0, 0.07), 0 10px 20px -2px rgba(0, 0, 0, 0.04)', + 'medium': '0 4px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)', + 'strong': '0 10px 40px -10px rgba(0, 0, 0, 0.15), 0 2px 10px -2px rgba(0, 0, 0, 0.04)', + }, + animation: { + 'fade-in': 'fadeIn 0.5s ease-in-out', + 'slide-up': 'slideUp 0.3s ease-out', + 'slide-down': 'slideDown 0.3s ease-out', + 'scale-in': 'scaleIn 0.2s ease-out', + 'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite', + }, + keyframes: { + fadeIn: { + '0%': { opacity: '0' }, + '100%': { opacity: '1' }, + }, + slideUp: { + '0%': { transform: 'translateY(10px)', opacity: '0' }, + '100%': { transform: 'translateY(0)', opacity: '1' }, + }, + slideDown: { + '0%': { transform: 'translateY(-10px)', opacity: '0' }, + '100%': { transform: 'translateY(0)', opacity: '1' }, + }, + scaleIn: { + '0%': { transform: 'scale(0.95)', opacity: '0' }, + '100%': { transform: 'scale(1)', opacity: '1' }, }, - pania: { // New PanIA brand colors - golden: '#F4A261', // Primary: Warm Golden - representing bread/warmth - blue: '#2A9D8F', // Secondary: Tech Blue - representing AI/innovation - brown: '#8B4513', // Accent: Deep Brown - representing traditional bakery - white: '#FFFFFF', // Neutral: Clean White - charcoal: '#333333', // Neutral: Charcoal - } }, }, }, plugins: [ require('@tailwindcss/forms'), + require('@tailwindcss/typography'), ], } \ No newline at end of file diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json deleted file mode 100644 index 31eebad2..00000000 --- a/frontend/tsconfig.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "compilerOptions": { - "target": "es5", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "paths": { - "@/*": [ - "./src/*" - ] - }, - "plugins": [ - { - "name": "next" - } - ] - }, - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - ".next/types/**/*.ts" - ], - "exclude": [ - "node_modules" - ] -} diff --git a/frontend/vite.config.js b/frontend/vite.config.js new file mode 100644 index 00000000..96d92165 --- /dev/null +++ b/frontend/vite.config.js @@ -0,0 +1,45 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import path from 'path' + +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, + server: { + port: 3000, + host: true, + proxy: { + '/api': { + target: 'http://localhost:8000', + changeOrigin: true, + secure: false, + rewrite: (path) => path.replace(/^\/api/, '/api'), + }, + }, + }, + build: { + outDir: 'dist', + sourcemap: true, + rollupOptions: { + output: { + manualChunks: { + vendor: ['react', 'react-dom'], + router: ['react-router-dom'], + state: ['@reduxjs/toolkit', 'react-redux'], + i18n: ['i18next', 'react-i18next', 'i18next-browser-languagedetector'], + charts: ['recharts'], + utils: ['date-fns', 'date-fns-tz', 'zod', 'clsx', 'tailwind-merge'], + }, + }, + }, + }, + test: { + globals: true, + environment: 'jsdom', + setupFiles: ['./src/test/setup.ts'], + }, +}) \ No newline at end of file