diff --git a/jsconfig.json b/jsconfig.json index b8d6842d7fad0a64e5ffa846e104342233782852..879f8fc5b7d23204d856dd09d330085ff8d61e9a 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,7 +1,9 @@ { "compilerOptions": { "paths": { - "@/*": ["./src/*"] + "@/*": [ + "./src/*" + ] } } -} +} \ No newline at end of file diff --git a/next.config.mjs b/next.config.mjs index 4678774e6d606704bce1897a5dab960cd798bf66..2a39b71d075e0197440120491bcfa37f29d4eb57 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,4 +1,28 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig = { + images: { + domains: ['https://res.cloudinary.com'], + }, + webpack(config) { + const fileLoaderRule = config.module.rules.find((rule) => + rule.test?.test?.('.svg'), + ) + config.module.rules.push( + { + ...fileLoaderRule, + test: /\.svg$/i, + resourceQuery: /url/, // *.svg?url + }, + { + test: /\.svg$/i, + issuer: fileLoaderRule.issuer, + resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] }, // exclude if *.svg?url + use: ['@svgr/webpack'], + }, + ) + fileLoaderRule.exclude = /\.svg$/i + return config + }, +}; export default nextConfig; diff --git a/package-lock.json b/package-lock.json index d4a9662c58821d09ebebe2ef995bf80407e9b29d..617d640ddc81ce717bb379227f12b644b4c8b435 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "react-dom": "^18" }, "devDependencies": { + "@svgr/webpack": "^8.1.0", "eslint": "^8", "eslint-config-next": "14.2.3", "postcss": "^8", @@ -33,6 +34,1942 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/core/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, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", + "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.5", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/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, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.5.tgz", + "integrity": "sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.24.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.24.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.24.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/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, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/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, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.5.tgz", + "integrity": "sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", + "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.24.3", + "@babel/helper-simple-access": "^7.24.5", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", + "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz", + "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", + "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", + "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", + "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.5.tgz", + "integrity": "sha512-/xxzuNvgRl4/HLNKvnFwdhdgN3cpLxgLROeLDl83Yx0AJ1SGvq1ak0OszTOjDfiB8Vx03eJbeDWh9r+jCCWttw==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.23.0", + "@babel/template": "^7.24.0", + "@babel/types": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", + "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", + "dev": true, + "dependencies": { + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz", + "integrity": "sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.5", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", + "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.5.tgz", + "integrity": "sha512-LdXRi1wEMTrHVR4Zc9F8OewC3vdm5h4QB6L71zy6StmYeqGi1b3ttIO8UC+BfZKcH9jdr4aI249rBkm+3+YvHw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz", + "integrity": "sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.1.tgz", + "integrity": "sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.24.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.1.tgz", + "integrity": "sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz", + "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.1.tgz", + "integrity": "sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz", + "integrity": "sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz", + "integrity": "sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz", + "integrity": "sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-remap-async-to-generator": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz", + "integrity": "sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.5.tgz", + "integrity": "sha512-sMfBc3OxghjC95BkYrYocHL3NaOplrcaunblzwXhGmlPwpmfsxr4vK+mBBt49r+S240vahmv+kUxkeKgs+haCw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz", + "integrity": "sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.4.tgz", + "integrity": "sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.4", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.5.tgz", + "integrity": "sha512-gWkLP25DFj2dwe9Ck8uwMOpko4YsqyfZJrOmqqcegeDYEbp7rmn4U6UQZNj08UF6MaX39XenSpKRCvpDRBtZ7Q==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.24.5", + "@babel/helper-replace-supers": "^7.24.1", + "@babel/helper-split-export-declaration": "^7.24.5", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz", + "integrity": "sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/template": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.5.tgz", + "integrity": "sha512-SZuuLyfxvsm+Ah57I/i1HVjveBENYK9ue8MJ7qkc7ndoNjqquJiElzA7f5yaAXjyW2hKojosOTAQQRX50bPSVg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.1.tgz", + "integrity": "sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.1.tgz", + "integrity": "sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.1.tgz", + "integrity": "sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz", + "integrity": "sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.1.tgz", + "integrity": "sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz", + "integrity": "sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz", + "integrity": "sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.1.tgz", + "integrity": "sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz", + "integrity": "sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.1.tgz", + "integrity": "sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz", + "integrity": "sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.1.tgz", + "integrity": "sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", + "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.1.tgz", + "integrity": "sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.1.tgz", + "integrity": "sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.1.tgz", + "integrity": "sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz", + "integrity": "sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.1.tgz", + "integrity": "sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.5.tgz", + "integrity": "sha512-7EauQHszLGM3ay7a161tTQH7fj+3vVM/gThlz5HpFtnygTxjrlvoeq7MPVA1Vy9Q555OB8SnAOsMkLShNkkrHA==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-plugin-utils": "^7.24.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz", + "integrity": "sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-replace-supers": "^7.24.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.1.tgz", + "integrity": "sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.5.tgz", + "integrity": "sha512-xWCkmwKT+ihmA6l7SSTpk8e4qQl/274iNbSKRRS8mpqFR32ksy36+a+LWY8OXCCEefF8WFlnOHVsaDI2231wBg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.5.tgz", + "integrity": "sha512-9Co00MqZ2aoky+4j2jhofErthm6QVLKbpQrvz20c3CH9KQCLHyNB+t2ya4/UrRpQGR+Wrwjg9foopoeSdnHOkA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz", + "integrity": "sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.5.tgz", + "integrity": "sha512-JM4MHZqnWR04jPMujQDTBVRnqxpLLpx2tkn7iPn+Hmsc0Gnb79yvRWOkvqFOx3Z7P7VxiRIR22c4eGSNj87OBQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.5", + "@babel/helper-plugin-utils": "^7.24.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz", + "integrity": "sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.1.tgz", + "integrity": "sha512-QXp1U9x0R7tkiGB0FOk8o74jhnap0FlZ5gNkRIWdG3eP+SvMFg118e1zaWewDzgABb106QSKpVsD3Wgd8t6ifA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.1.tgz", + "integrity": "sha512-mvoQg2f9p2qlpDQRBC7M3c3XTr0k7cp/0+kFKKO/7Gtu0LSw16eKB+Fabe2bDT/UpsyasTBBkAnbdsLrkD5XMw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz", + "integrity": "sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.23.3", + "@babel/types": "^7.23.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", + "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", + "dev": true, + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.1.tgz", + "integrity": "sha512-+pWEAaDJvSm9aFvJNpLiM2+ktl2Sn2U5DdyiWdZBxmLc6+xGt88dvFqsHiAiDS+8WqUwbDfkKz9jRxK3M0k+kA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.1.tgz", + "integrity": "sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.1.tgz", + "integrity": "sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz", + "integrity": "sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz", + "integrity": "sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.1.tgz", + "integrity": "sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz", + "integrity": "sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.5.tgz", + "integrity": "sha512-UTGnhYVZtTAjdwOTzT+sCyXmTn8AhaxOS/MjG9REclZ6ULHWF9KoCZur0HSGU7hk8PdBFKKbYe6+gqdXWz84Jg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.5.tgz", + "integrity": "sha512-E0VWu/hk83BIFUWnsKZ4D81KXjN5L3MobvevOHErASk9IPwKHOkTgvqzvNo1yP/ePJWqqK2SpUR5z+KQbl6NVw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.5", + "@babel/helper-plugin-utils": "^7.24.5", + "@babel/plugin-syntax-typescript": "^7.24.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.1.tgz", + "integrity": "sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.1.tgz", + "integrity": "sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.1.tgz", + "integrity": "sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.1.tgz", + "integrity": "sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.5.tgz", + "integrity": "sha512-UGK2ifKtcC8i5AI4cH+sbLLuLc2ktYSFJgBAXorKAsHUZmrQ1q6aQ6i3BvU24wWs2AAKqQB6kq3N9V9Gw1HiMQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.24.4", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-plugin-utils": "^7.24.5", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.1", + "@babel/plugin-syntax-import-attributes": "^7.24.1", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.1", + "@babel/plugin-transform-async-generator-functions": "^7.24.3", + "@babel/plugin-transform-async-to-generator": "^7.24.1", + "@babel/plugin-transform-block-scoped-functions": "^7.24.1", + "@babel/plugin-transform-block-scoping": "^7.24.5", + "@babel/plugin-transform-class-properties": "^7.24.1", + "@babel/plugin-transform-class-static-block": "^7.24.4", + "@babel/plugin-transform-classes": "^7.24.5", + "@babel/plugin-transform-computed-properties": "^7.24.1", + "@babel/plugin-transform-destructuring": "^7.24.5", + "@babel/plugin-transform-dotall-regex": "^7.24.1", + "@babel/plugin-transform-duplicate-keys": "^7.24.1", + "@babel/plugin-transform-dynamic-import": "^7.24.1", + "@babel/plugin-transform-exponentiation-operator": "^7.24.1", + "@babel/plugin-transform-export-namespace-from": "^7.24.1", + "@babel/plugin-transform-for-of": "^7.24.1", + "@babel/plugin-transform-function-name": "^7.24.1", + "@babel/plugin-transform-json-strings": "^7.24.1", + "@babel/plugin-transform-literals": "^7.24.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.1", + "@babel/plugin-transform-member-expression-literals": "^7.24.1", + "@babel/plugin-transform-modules-amd": "^7.24.1", + "@babel/plugin-transform-modules-commonjs": "^7.24.1", + "@babel/plugin-transform-modules-systemjs": "^7.24.1", + "@babel/plugin-transform-modules-umd": "^7.24.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.24.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", + "@babel/plugin-transform-numeric-separator": "^7.24.1", + "@babel/plugin-transform-object-rest-spread": "^7.24.5", + "@babel/plugin-transform-object-super": "^7.24.1", + "@babel/plugin-transform-optional-catch-binding": "^7.24.1", + "@babel/plugin-transform-optional-chaining": "^7.24.5", + "@babel/plugin-transform-parameters": "^7.24.5", + "@babel/plugin-transform-private-methods": "^7.24.1", + "@babel/plugin-transform-private-property-in-object": "^7.24.5", + "@babel/plugin-transform-property-literals": "^7.24.1", + "@babel/plugin-transform-regenerator": "^7.24.1", + "@babel/plugin-transform-reserved-words": "^7.24.1", + "@babel/plugin-transform-shorthand-properties": "^7.24.1", + "@babel/plugin-transform-spread": "^7.24.1", + "@babel/plugin-transform-sticky-regex": "^7.24.1", + "@babel/plugin-transform-template-literals": "^7.24.1", + "@babel/plugin-transform-typeof-symbol": "^7.24.5", + "@babel/plugin-transform-unicode-escapes": "^7.24.1", + "@babel/plugin-transform-unicode-property-regex": "^7.24.1", + "@babel/plugin-transform-unicode-regex": "^7.24.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.1", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/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, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.1.tgz", + "integrity": "sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-transform-react-display-name": "^7.24.1", + "@babel/plugin-transform-react-jsx": "^7.23.4", + "@babel/plugin-transform-react-jsx-development": "^7.22.5", + "@babel/plugin-transform-react-pure-annotations": "^7.24.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz", + "integrity": "sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-syntax-jsx": "^7.24.1", + "@babel/plugin-transform-modules-commonjs": "^7.24.1", + "@babel/plugin-transform-typescript": "^7.24.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, "node_modules/@babel/runtime": { "version": "7.24.5", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", @@ -45,6 +1982,64 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/template": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", + "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/types": "^7.24.5", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", + "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.24.1", + "@babel/helper-validator-identifier": "^7.24.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -307,112 +2302,369 @@ "node": ">= 10" } }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz", - "integrity": "sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz", + "integrity": "sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz", + "integrity": "sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz", + "integrity": "sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz", + "integrity": "sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==", + "cpu": [ + "x64" + ], + "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==", + "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==", + "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==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "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==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz", + "integrity": "sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==", + "dev": true + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz", - "integrity": "sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "dev": true, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz", - "integrity": "sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, "engines": { - "node": ">= 10" + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz", - "integrity": "sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dev": true, + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dev": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" }, "engines": { - "node": ">= 8" + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "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==", + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, "engines": { - "node": ">= 8" + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "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==", + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dev": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" }, "engines": { - "node": ">= 8" + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" } }, - "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==", - "optional": true, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "dev": true, + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, "engines": { "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" } }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz", - "integrity": "sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==", - "dev": true + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } }, "node_modules/@swc/counter": { "version": "0.1.3", @@ -436,6 +2688,15 @@ "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" } }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -878,6 +3139,54 @@ "dequal": "^2.0.3" } }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/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, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -894,6 +3203,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -915,6 +3230,38 @@ "node": ">=8" } }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "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" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "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", @@ -954,6 +3301,18 @@ "node": ">=6" } }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -1066,17 +3425,103 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/core-js-compat": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" }, "engines": { - "node": ">= 8" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, "node_modules/cssesc": { @@ -1090,6 +3535,39 @@ "node": ">=4" } }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -1170,6 +3648,15 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -1247,11 +3734,82 @@ "node": ">=6.0.0" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, + "node_modules/electron-to-chromium": { + "version": "1.4.779", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.779.tgz", + "integrity": "sha512-oaTiIcszNfySXVJzKcjxd2YjPxziAd+GmXyb2HbidCeFo6Z88ygOT7EimlrEQhM2U08VhSrbKhLOXP0kKUCZ6g==", + "dev": true + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -1270,6 +3828,27 @@ "node": ">=10.13.0" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-abstract": { "version": "1.23.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", @@ -1428,6 +4007,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "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", @@ -2041,6 +4629,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -2377,6 +4974,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, "node_modules/is-async-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", @@ -2804,12 +5407,30 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -2917,6 +5538,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -2934,6 +5561,15 @@ "loose-envify": "cli.js" } }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, "node_modules/lru-cache": { "version": "10.2.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", @@ -2942,6 +5578,12 @@ "node": "14 || >=16.14" } }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3106,6 +5748,22 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -3114,6 +5772,18 @@ "node": ">=0.10.0" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3314,6 +5984,24 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3668,12 +6356,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", "dev": true }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", @@ -3692,6 +6407,44 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -3936,6 +6689,16 @@ "node": ">=8" } }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/source-map-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", @@ -4197,6 +6960,46 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true + }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dev": true, + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/tailwindcss": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz", @@ -4267,6 +7070,15 @@ "node": ">=0.8" } }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4438,6 +7250,76 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "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" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.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", @@ -4647,6 +7529,12 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, "node_modules/yaml": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz", diff --git a/package.json b/package.json index c2cd5f90454007cef6ac16c790d9977ed069a82e..b38ca7e8db3e257f576e9c2638eb9c6d7b2ceb96 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "react-dom": "^18" }, "devDependencies": { + "@svgr/webpack": "^8.1.0", "eslint": "^8", "eslint-config-next": "14.2.3", "postcss": "^8", diff --git a/src/app/auth/change-password/page.jsx b/src/app/auth/change-password/page.jsx new file mode 100644 index 0000000000000000000000000000000000000000..6bc46caa9f1a0aa71d39d43d249f2fb50b0bbafd --- /dev/null +++ b/src/app/auth/change-password/page.jsx @@ -0,0 +1,126 @@ +"use client" +import fetchRequest from '@/app/lib/fetchRequest' +import Image from 'next/image' +import Link from 'next/link' +import React, { useEffect, useState } from 'react' +import { useSearchParams } from 'next/navigation' +import Loader from '@/components/Loader/Loader' +import { PASSWORD_REGEX } from '@/app/lib/constants' +import { useNotification } from '@/context/NotificationContext' + +const ChangePassword = () => { + const [isSuccess, setIsSuccess] = useState(false) + const [formErrors, setFormErrors] = useState([]) + const [password, setPassword] = useState("") + const [confirmPassword, setConfirmPassword] = useState("") + const [isLoading, setIsLoading] = useState(false) + const params = useSearchParams(); + const { toggleNotification } = useNotification() + const handleChangePassword = async (event) => { + event.preventDefault() + setIsLoading(true) + const { isSuccess, data, errors } = await fetchRequest(`/password_reset/confirm/?token=${params.get("token")}`, { + method: "POST", + body: JSON.stringify({ + password, + token: params.get("token") + }) + }) + if (isSuccess) { + setIsSuccess(true) + } + else { + console.log(errors) + setIsLoading(false) + if (errors.type === "ValidationError") { + if (errors.detail.token) { + setFormErrors(["Le lien que vous avez utilisé pour réinitialiser votre mot de passe est invalide"]) + } + else { + setFormErrors(["Le Mot de passe est invalide"]) + } + } else if (errors?.detail?.detail?.startsWith("The OTP password entered is not valid")) { + setFormErrors(["Le lien que vous avez utilisé pour réinitialiser votre mot de passe est déja utilisé"]) + } + else { + toggleNotification({ + type: "error", + message: "Internal Server Error", + visible: true + }) + } + } + } + const isEmptyFields = !password && !confirmPassword + useEffect(() => { + var currentErrors = [] + if (password !== confirmPassword) { + currentErrors.push("Les mots de passe ne sont pas identiques.") + } + if (password.length < 8) { + currentErrors.push("Le mot de passe doit comporter au moins 8 caractères.") + } + if (!PASSWORD_REGEX.test(password)) { + currentErrors.push("Le mot de passe doit contenir au moins une lettre, un chiffre et un caractère spécial.") + } + setFormErrors(currentErrors) + }, [password, confirmPassword]) + return ( +
+
+
+
+ teamwill +
+ {(!isSuccess) &&
+

Change your password. +

+
+
    +
  • Le mot de passe doit contenir au moins 8 caractères
  • +
  • Le mot de passe doit contenir au moins un chiffre
  • +
  • Le mot de passe doit contenir au moins un caractère spécial
  • +
+
+
+
+ + setPassword(event.target.value)} type="password" name="new_password1" id="new_password1" + className="rounded-md px-3 w-full duration-150 delay-75 focus:ring ring-offset-1 ring-sushi-200 border h-10 border-neutral-300 outline-none" /> +
+
+ + setConfirmPassword(event.target.value)} type="password" name="new_password2" id="new_password2" + className="rounded-md px-3 duration-150 delay-75 w-full focus:ring ring-offset-1 ring-sushi-200 border h-10 border-neutral-300 outline-none" /> +
+
    0 && !isEmptyFields ? "bg-red-100 border border-red-300" : ""} min-h-10 px-3 text-xs py-3 rounded relative mt-9 mb-6 list-inside list-disc`} role="alert"> + {!isEmptyFields && formErrors.map((error, index) => { + return
  • {error}
  • + })} +
+
+ +
+
+
} + {(isSuccess) && ( +
+

The password has been changed!

+ log in again? +
+ )} +
+
+
+ ) +} + +export default ChangePassword \ No newline at end of file diff --git a/src/app/auth/forgot-password/page.jsx b/src/app/auth/forgot-password/page.jsx new file mode 100644 index 0000000000000000000000000000000000000000..d74d5db9ab4b3f3bd45be27257ce6fead4b790b3 --- /dev/null +++ b/src/app/auth/forgot-password/page.jsx @@ -0,0 +1,105 @@ +'use client' +import fetchRequest from '@/app/lib/fetchRequest' +import Loader from '@/components/Loader/Loader' +import { useNotification } from '@/context/NotificationContext' +import Image from 'next/image' +import Link from 'next/link' +import React, { useState } from 'react' + +const ForgotPassword = () => { + const [email, setEmail] = useState("") + const [isSuccess, setIsSuccess] = useState(false) + const [isLoading, setIsLoading] = useState(false) + const [requestErrors, setRequestErrors] = useState([]) + const { toggleNotification } = useNotification() + const handleForgetPassword = async (event) => { + event.preventDefault() + setIsLoading(true) + const { isSuccess, errors, data } = await fetchRequest("/password_reset/", { + body: JSON.stringify({ email }), + method: "POST" + }) + if (isSuccess) { + setIsSuccess(true) + } + else { + setIsLoading(false) + if (errors.type === "ValidationError") { + // setRequestErrors(Object.keys(errors.detail).reduce((prev, current) => { + // return [...prev, ...errors.detail[current]] + // }, [])) + toggleNotification + setRequestErrors(["Nous n'avons pas pu trouver de compte associé à cet e-mail. Veuillez essayer une autre adresse e-mail."]) + } else { + console.log(errors) + toggleNotification({ + type: "error", + message: "Internal Server Error" + }) + } + } + } + return ( +
+
+
+ teamwill + {(!isSuccess) &&
+
+

Forgot your password!! No Problem + Reset it here +

+
+
+
+
+
+ setEmail(e.target.value)} autocomplete="off" id="email" name="email" type="text" + className="peer placeholder-transparent h-10 w-full border-b-2 border-gray-300 text-gray-900 focus:outline-none focus:borer-rose-600" + placeholder="Email address" /> + +
+ + + {(requestErrors.length !== 0) && } +
+ Back to log + in +
+ +
+
+
+
} + {(isSuccess) &&
+ + + +
+

Email Sent!

+

Check your email and open the link we sent to continue

+
+
} +
+
+
+ ) +} + +export default ForgotPassword \ No newline at end of file diff --git a/src/app/auth/login/page.jsx b/src/app/auth/login/page.jsx index 33b3f092806c43146c129778fdef8fa71449bd18..e94f196d34238d6f6324f5d3754292a44943a1b0 100644 --- a/src/app/auth/login/page.jsx +++ b/src/app/auth/login/page.jsx @@ -3,7 +3,7 @@ import { useState } from 'react'; import Link from 'next/link'; import Cookies from 'js-cookie'; -import {createSession} from "@/app/lib/session"; +import { createSession } from "@/app/lib/session"; const LoginPage = () => { const [username, setUsername] = useState(''); @@ -18,45 +18,10 @@ const LoginPage = () => { // Add your form submission logic here }; - const secretKey = process.env.NEXT_PUBLIC_SESSION_SECRET; - console.log(secretKey); - - // send login request to the server const login = async (event) => { event.preventDefault(); try { - const response = await fetch('http://localhost:8000/login/', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ username, password }), - }); - const data = await response.json(); - if (data.error) { - setMessages(data.error); - } else { - setMessages('Login successful'); - // Set the cookie - const expiresAt = new Date(new Date().getTime() + 60 * 60 * 1000); // Set cookie to expire in 1 hour - // const session = json strigify it - Cookies.set('session', data.token, { - expires: expiresAt, - secure: true, - sameSite: 'Lax', - }); - // Redirect to the dashboard - // window.location.href = '/auth/verif'; - } - } catch (error) { - setMessages('An error occurred'); - } - }; - - const loginn = async (event) => { - event.preventDefault(); - try { - const response = await fetch('http://localhost:8000/login/', { + const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/login/`, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -64,16 +29,11 @@ const LoginPage = () => { body: JSON.stringify({ username, password }), }); const data = await response.json(); - if (data.error) { - setMessages(data.error); + if (data.non_field_errors) { + setMessages(data.non_field_errors[0]); } else { - setMessages('Login successful'); - // Set the cookie - const expiresAt = new Date(new Date().getTime() + 60 * 60 * 1000); // Set cookie to expire in 1 hour - // const session = json strigify it await createSession(data); - // Redirect to the dashboard - // window.location.href = '/auth/verif'; + window.location.href = '/auth/verif'; } } catch (error) { setMessages('An error occurred'); @@ -91,7 +51,7 @@ const LoginPage = () => {
{
{ />
- -

Mot de passe oublié?

+ +

Mot de passe oublié?

{messages && ( @@ -124,7 +84,7 @@ const LoginPage = () => { )} diff --git a/src/app/auth/verif/page.jsx b/src/app/auth/verif/page.jsx index cfea4df1253203ecab55cdbcb6d5644d8980cac5..15d3d4083be7e343e184e71bde68c51c9ab26e99 100644 --- a/src/app/auth/verif/page.jsx +++ b/src/app/auth/verif/page.jsx @@ -5,7 +5,7 @@ const Verif = () => { // fetch data from the server /example const fetchExampleData = async () => { try { - const data = await fetchRequest('http://localhost:8000/example/', + const data = await fetchRequest(`/example/`, {method: 'POST', body: JSON.stringify({ "name": "jhon", @@ -20,18 +20,18 @@ const Verif = () => { } }; const isAuth = async () => { - isAuthenticated(); + await isAuthenticated(); } return ( - <> +
user is redirected to this page after successful login
{/*test fetchExampleData */} - +
); } export default Verif; \ No newline at end of file diff --git a/src/app/etage/AddEtageComponent.jsx b/src/app/etage/AddEtageComponent.jsx new file mode 100644 index 0000000000000000000000000000000000000000..d84ae41ffbd070751b3decbd867a59fd8fd87ee1 --- /dev/null +++ b/src/app/etage/AddEtageComponent.jsx @@ -0,0 +1,58 @@ +'use client' +import Loader from '@/components/Loader/Loader' +import React, { useState, useRef } from 'react' +import fetchRequest from '../lib/fetchRequest' + + + +const AddEtageComponent = ({ etagesState })=> { + const [ numeroEtage, setNumeroEtage ] = useState("") + const [isLoading, setIsLoading] = useState(false) + const [errorMessage, setErrorMessage] = useState(null) + const inputRef = useRef(null) + + + const handleNewEtage = (e) => { + setErrorMessage(null) + setNumeroEtage(e.target.value) + } + + const handleAddNewEtage = async () => { + setIsLoading(true) + const { data, errors, isSuccess } = await fetchRequest("/zoaning/etages/", { + method: "POST", + body: JSON.stringify({ numero: numeroEtage }) + }) + if (isSuccess) { + setIsLoading(false) + inputRef.current.value = "" + console.log(data) + etagesState((prevEtagesState) => [...prevEtagesState, data]); + } else { + setIsLoading(false) + if(errors.type == "ValidationError") + {setErrorMessage(errors.detail.numero)} + else{ + setErrorMessage(errorMessage.type) + } + console.log(errors) + } + + } + + return( +
+
+ Nouveau étage: +
+ +
+ +
+ {errorMessage && {errorMessage}} +
+ + ) +} + +export default(AddEtageComponent) \ No newline at end of file diff --git a/src/app/etage/page.jsx b/src/app/etage/page.jsx new file mode 100644 index 0000000000000000000000000000000000000000..5177625933b1d8af927834ac9068aa67da4c722f --- /dev/null +++ b/src/app/etage/page.jsx @@ -0,0 +1,83 @@ +"use client" +import React from 'react' +import AddEtageComponent from './AddEtageComponent' +import fetchRequest from '../lib/fetchRequest' +import { useState, useEffect } from 'react'; +import Loader from '@/components/Loader/Loader' + + + +const Etage = ()=> { + const [etages, setEtages] = useState([]) + const [ isLoadingData, setIsLoadingData ] = useState(true) + // Fetch data from external API + useEffect(() => { + const getAllEtages = async () => { + try{ + const {isSuccess, errors, data} = await fetchRequest('/zoaning/etages/', {method: 'GET'}) + setIsLoadingData(false) + if(isSuccess){ + setEtages(data) + }else{ + setEtages([]) + } + }catch(error){ + setIsLoadingData(false) + console.log(error) + } + } + getAllEtages() + }, []) + const handleDeleteEtage = async (etage) => { + try{ + console.log(etage) + const {isSuccess, errors, data} = await fetchRequest(`/zoaning/etages/${etage.id}/`, {method: "DELETE"}) + console.log(isSuccess) + console.log(errors) + console.log(data) + if(isSuccess){ + console.log(etages) + console.log("etage: ", etage) + setEtages((prevEtages) => prevEtages.filter((e) => e.id !== etage.id)); + } + }catch(error){ + console.log(error) + } + } + return( +
+
+
+

Liste des étages

+
+
+ {(!isLoadingData) ? etages && etages?.length ?
    + {etages?.map((etage, index) => + ( +
  • + Etage numéro: {etage.numero} +
    {handleDeleteEtage(etage)}}> + +
    +
  • + ) + )} +
: +
+ Aucun étage n'a été ajouté +
+ : +
+ +
+ } + +
+ +
+
+ + ) +} + +export default Etage \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index 6c139df80533021db2ee61f9f06c23be2eb0a57f..b6ba7d37334c09788aa0026af48f37b048eed1d8 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -2,29 +2,6 @@ @tailwind components; @tailwind utilities; -:root { - --foreground-rgb: 0, 0, 0; - --background-start-rgb: 214, 219, 220; - --background-end-rgb: 255, 255, 255; -} - -@media (prefers-color-scheme: dark) { - :root { - --foreground-rgb: 255, 255, 255; - --background-start-rgb: 0, 0, 0; - --background-end-rgb: 0, 0, 0; - } -} - -body { - color: rgb(var(--foreground-rgb)); - background: linear-gradient( - to bottom, - transparent, - rgb(var(--background-end-rgb)) - ) - rgb(var(--background-start-rgb)); -} @layer utilities { .text-balance { @@ -34,18 +11,23 @@ body { /* Customize the scrollbar */ ::-webkit-scrollbar { - width: 6px; /* Set the width of the scrollbar */ + width: 6px; + /* Set the width of the scrollbar */ } ::-webkit-scrollbar-thumb { - background-color: rgba(0, 0, 0, 0.3); /* Color of the thumb */ - border-radius: 3px; /* Rounded corners of the thumb */ + background-color: rgba(0, 0, 0, 0.3); + /* Color of the thumb */ + border-radius: 3px; + /* Rounded corners of the thumb */ } ::-webkit-scrollbar-thumb:hover { - background-color: rgba(0, 0, 0, 0.5); /* Color of the thumb on hover */ + background-color: rgba(0, 0, 0, 0.5); + /* Color of the thumb on hover */ } ::-webkit-scrollbar-track { - background-color: rgba(0, 0, 0, 0.1); /* Color of the track */ -} + background-color: rgba(0, 0, 0, 0.1); + /* Color of the track */ +} \ No newline at end of file diff --git a/src/app/layout.js b/src/app/layout.js index 9aef1df7d6c3d50515ab62f578c5cc963a1243a7..45c21613310f3980d4975a0ebb436337cd7e5b89 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -1,17 +1,24 @@ import { Inter } from "next/font/google"; import "./globals.css"; +import Header from "@/app/ui/Header"; +import { NotificationProvider } from "@/context/NotificationContext"; const inter = Inter({ subsets: ["latin"] }); export const metadata = { - title: "Create Next App", + title: "TeamBook", description: "Generated by create next app", }; export default function RootLayout({ children }) { return ( - {children} + +
+ + {children} + + ); } diff --git a/src/app/lib/TypesHelper.js b/src/app/lib/TypesHelper.js new file mode 100644 index 0000000000000000000000000000000000000000..8077bc8cdb962a8c84c120e94ded330e19f02a38 --- /dev/null +++ b/src/app/lib/TypesHelper.js @@ -0,0 +1,3 @@ +export const isArray = (arg) => { + return Array.isArray(arg) +} \ No newline at end of file diff --git a/src/app/lib/constants.js b/src/app/lib/constants.js new file mode 100644 index 0000000000000000000000000000000000000000..9d34296b9316dac3c714bc0476dcfa97e05dda4d --- /dev/null +++ b/src/app/lib/constants.js @@ -0,0 +1,3 @@ +export const PASSWORD_REGEX = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[^a-zA-Z\d\s]).*$/; +export const EMAIL_REGEX = /^[a-zA-Z0-9._%+-]+@teamwillgroup\.com$/ +export const PAGINATION_SIZE = 3 \ No newline at end of file diff --git a/src/app/lib/dal.js b/src/app/lib/dal.js deleted file mode 100644 index 74c6293b78f5f50dac5fc7d8a9b11ed8f1b15fbe..0000000000000000000000000000000000000000 --- a/src/app/lib/dal.js +++ /dev/null @@ -1,16 +0,0 @@ -import 'server-only' - -import Cookies from 'js-cookie'; -import { decrypt } from '@/app/lib/session' -import {redirect} from "next/navigation"; - -export const verifySession = cache(async () => { - const cookie = Cookies.get('session').value - const session = await decrypt(cookie) - - if (!session.token) { - redirect('/login') - } - - return { isAuth: true, userName: session.username } -}) \ No newline at end of file diff --git a/src/app/lib/fetchRequest.js b/src/app/lib/fetchRequest.js index 3afb1c3072b662f2ba0461e36390f1f9e0700eed..a47d118550b459a157d8b8878de6a0cb8a859cd5 100644 --- a/src/app/lib/fetchRequest.js +++ b/src/app/lib/fetchRequest.js @@ -1,29 +1,52 @@ -//custom fetch tha have the token in header - import Cookies from 'js-cookie'; import {decrypt} from "@/app/lib/session"; +const BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000" const fetchRequest = async (url, options = {}) => { - const token = Cookies.get('session'); - console.log('token', token) - const jwtDecrypted = decrypt(token); - console.log('jwtDecrypted', jwtDecrypted) + const jwtCookie = Cookies.get('session'); + console.log('jwtCookie', jwtCookie) + const jwtDecrypted = await decrypt(jwtCookie); + console.log('jwtDecrypted', jwtDecrypted.sessionData.token) const headers = { ...options.headers, - 'Authorization': `Token ${token}`, + // add authorization header with token if there is jwtDecrypted.sessionData.token + Authorization: jwtDecrypted?.sessionData.token ? `Token ${jwtDecrypted.sessionData.token}` : undefined, 'Content-Type': 'application/json', }; - const response = await fetch(url, { + const response = await fetch(`${BASE_URL}${url}`, { ...options, headers, }); - + console.log(response.status) if (!response.ok) { - throw new Error('Network response was not ok'); + try { + const errorData = await response.json(); + return {isSuccess: false, errors: errorData, data: null, status: response.status} + } catch (error) { + return {isSuccess: false, errors: error, data: null, status: response.status} + } } - - return response.json(); + console.log('response', response) + // Check if the response has content before parsing it as JSON + const contentType = response.headers.get('content-type'); + if (contentType && contentType.includes('application/json')) { + const data = await response.json(); + return {isSuccess: true, errors: null, data: data, status: response.status}; + } + // If no JSON content, return null for data + return {isSuccess: true, errors: null, data: data, status: response.status}; }; export default fetchRequest; + + + + + + + + + + + diff --git a/src/app/lib/fetchRequestServer.js b/src/app/lib/fetchRequestServer.js new file mode 100644 index 0000000000000000000000000000000000000000..16aafe94dd8d3c9fe65996005f25770a3231b70e --- /dev/null +++ b/src/app/lib/fetchRequestServer.js @@ -0,0 +1,48 @@ +// src/app/lib/fetchRequestServer.js +import {cookies as nextCookies} from 'next/headers'; +import {decrypt} from "@/app/lib/session"; + +const BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000"; + +const fetchRequestServer = async (url, options = {}) => { + const cookieStore = nextCookies(); + const jwtCookie = cookieStore.get('session')?.value; + + if (!jwtCookie) { + return {isSuccess: false, errors: "No session cookie found", data: null}; + } + + const jwtDecrypted = await decrypt(jwtCookie); + + const headers = { + ...options.headers, + Authorization: jwtDecrypted?.sessionData.token ? `Token ${jwtDecrypted.sessionData.token}` : undefined, + 'Content-Type': 'application/json', + }; + + const response = await fetch(`${BASE_URL}${url}`, { + ...options, + headers, + }); + + if (!response.ok) { + try { + const errorData = await response.json(); + return {isSuccess: false, errors: errorData, data: null}; + } catch (error) { + return {isSuccess: false, errors: error, data: null}; + } + } + + // Check if the response has content before parsing it as JSON + const contentType = response.headers.get('content-type'); + if (contentType && contentType.includes('application/json')) { + const data = await response.json(); + return {isSuccess: true, errors: null, data: data}; + } + // If no JSON content, return null for data + return {isSuccess: true, errors: null, data: null}; + +}; + +export default fetchRequestServer; diff --git a/src/app/lib/isAuthenticated.js b/src/app/lib/isAuthenticated.js index 0a880acf5d8ce15ae58da3d0295208ff7a4ca3f6..7c77a5e9fe0c6cb8dff56ea1052bd1b27e4b6f6b 100644 --- a/src/app/lib/isAuthenticated.js +++ b/src/app/lib/isAuthenticated.js @@ -1,16 +1,20 @@ //verify if the user is authenticated import Cookies from "js-cookie"; +import {decrypt} from "@/app/lib/session"; -export default function isAuthenticated() { +export default async function isAuthenticated() { if (!Cookies.get('session')) { console.log('user is not authenticated'); // redirect to auth/login page - window.location.href = '/auth/login'; - + // window.location.href = '/auth/login'; return false; } - else console.log('user is authenticated'); - return true; + + console.log('user is authenticated'); + const session = Cookies.get('session') + const cookieDecoded = await decrypt(session) + return { isAuth: true, sessionData: cookieDecoded.sessionData } + } diff --git a/src/app/lib/isAuthenticatedSSR.js b/src/app/lib/isAuthenticatedSSR.js new file mode 100644 index 0000000000000000000000000000000000000000..b06881511928d746e1963011e32bac21034e96b9 --- /dev/null +++ b/src/app/lib/isAuthenticatedSSR.js @@ -0,0 +1,20 @@ +//verify if the user is authenticated +import { cookies } from 'next/headers' + +import {decrypt} from "@/app/lib/session"; + +export default async function isAuthenticatedSSR() { + if (!cookies().get('session')) { + console.log('user is not authenticated'); + // redirect to auth/login page + // window.location.href = '/auth/login'; + return false; + } + + console.log('user is authenticated'); + const cookie = cookies().get('session')?.value + const session = await decrypt(cookie) + return { isAuth: true, sessionData: session.sessionData } + +} + diff --git a/src/app/lib/session.js b/src/app/lib/session.js index 850ed748db48de63bae014a7fe245ff3a84f3278..1eb509a2e30326ef4e345033f9811c8dc0688513 100644 --- a/src/app/lib/session.js +++ b/src/app/lib/session.js @@ -2,7 +2,8 @@ import Cookies from 'js-cookie'; import { SignJWT, jwtVerify } from 'jose' -const secretKey = "password1234" +const secretKey = process.env.NEXT_PUBLIC_SESSION_SECRET; +console.log(secretKey); const encodedKey = new TextEncoder().encode(secretKey) export async function encrypt(payload) { diff --git a/src/app/page.js b/src/app/page.js index ecfca6f8e5034eb7f60a623d3db202433f6b96b9..87ce7aa74a17bf1ba51f0e9979b2d955634bf8ca 100644 --- a/src/app/page.js +++ b/src/app/page.js @@ -1,149 +1,8 @@ -import Image from "next/image"; export default function Home() { return (
-
-

- Get started by editing  - src/app/page.js -

-
- - By{" "} - Vercel Logo - -
-
- -
- Next.js Logo -
- -
- -

- Docs{" "} - - -> - -

-

- Find in-depth information about Next.js features and API. -

-
- - -

- Learn{" "} - - -> - -

-

- Learn about Next.js in an interactive course with quizzes! -

-
- - -

- Templates{" "} - - -> - -

-

- Explore starter templates for Next.js. -

-
- - -

- Deploy{" "} - - -> - -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-
-
+ Home Page
); } diff --git a/src/app/privilege/CreatePrivilegeForm.jsx b/src/app/privilege/CreatePrivilegeForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..d124e2edfbefad535461e370dcba8910952705f8 --- /dev/null +++ b/src/app/privilege/CreatePrivilegeForm.jsx @@ -0,0 +1,78 @@ +'use client' +import Loader from '@/components/Loader/Loader' +import React, { useRef, useState } from 'react' +import fetchRequest from '../lib/fetchRequest' +import {useNotification} from "@/context/NotificationContext"; + +const CreatePrivilegeForm = ({ appendPrivilege }) => { + const [isLoading, setIsLoading] = useState(false) + const [error, setError] = useState(null) + const [privilegeName, setPrivilegeName] = useState(""); + const { toggleNotification } = useNotification() + const handlePrivilegeNameChange = (event) => { + setError("") + setPrivilegeName(event.target.value) + } + const inputRef = useRef(null) + const handleSubmit = async (event) => { + event.preventDefault() + setIsLoading(true) + const { data, errors, isSuccess } = await fetchRequest("/privileges/", { + method: "POST", + body: JSON.stringify({ name: privilegeName }) + }) + if (isSuccess) { + setIsLoading(false) + appendPrivilege(data) + inputRef.current.value = "" + setPrivilegeName("") + toggleNotification({ + visible: true, + message: "L'habilitation a été créé avec succès", + type: "success" + }) + } else { + setIsLoading(false) + if (errors.type === "ValidationError") { + if (errors.detail.name) { + toggleNotification({ + type: "warning", + message: "Le nom de l'habilitation existe déjà", + visible: true, + }) + } + else { + toggleNotification({ + visible: true, + message: "Erreur de validation de l'habilitation", + type: "warning" + }) + } + } else { + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + } + console.log(errors) + } + } + return ( +
+

Ajout d'habilitation

+
+ + +
+

{error}

+
+ +
+
+ ) +} + +export default CreatePrivilegeForm \ No newline at end of file diff --git a/src/app/privilege/PrivilegeTableRow.jsx b/src/app/privilege/PrivilegeTableRow.jsx new file mode 100644 index 0000000000000000000000000000000000000000..7537e45773778a694de9fbe0655fdb37d9a04980 --- /dev/null +++ b/src/app/privilege/PrivilegeTableRow.jsx @@ -0,0 +1,174 @@ +'use client' +import React, { useEffect, useRef, useState } from 'react' +import fetchRequest from '../lib/fetchRequest' +import Loader from '@/components/Loader/Loader' +import DeleteIcon from "@/static/image/svg/delete.svg" +import EditIcon from "@/static/image/svg/edit.svg" +import CancelIcon from "@/static/image/svg/cancel.svg" +import CheckIcon from "@/static/image/svg/check.svg" +import { useNotification } from '@/context/NotificationContext' +import ConfirmationModal from '../ui/ConfirmationModal' +const PrivilegeTableRow = ({ id, name, setPrivileges }) => { + const [isUpdating, setIsUpdating] = useState(false) + const [privilegeName, setPrivilegeName] = useState(name) + const [loadingStatus, setLoadingStatus] = useState(false) + const { toggleNotification } = useNotification() + const [isModalOpen, setModalOpen] = useState(false) + const showDeletePopup = () => { + setModalOpen(true); + } + useEffect(() => { + setPrivilegeName(name) + inputRef.current.value = name + }, [name]) + const handleUpdatePrivilege = async () => { + setLoadingStatus(true) + const { isSuccess, errors, data, status } = await fetchRequest(`/privileges/${id}/`, { + method: "PATCH", + body: JSON.stringify({ name: privilegeName }) + }) + setLoadingStatus(false) + if (isSuccess) { + setPrivileges((privileges) => privileges.map((element) => element.id === id ? data.data : element)) + setIsUpdating(false) + toggleNotification({ + visible: true, + message: "L'habilitation a été modifiée avec succès.", + type: "success" + }) + } else { + if (errors.type === "ValidationError") { + if (errors.detail.name) { + toggleNotification({ + type: "warning", + message: "Le nom de l'habilitation existe déjà", + visible: true, + }) + } + else { + toggleNotification({ + visible: true, + message: "Erreur de validation de l'habilitation", + type: "warning" + }) + } + } else if (status === 404) { + toggleNotification({ + visible: true, + message: "L'habilitation n'a pas été trouvé", + type: "warning" + }) + } else { + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + } + console.log(errors) + } + + } + const handleDelete = async () => { + const { isSuccess, errors, status } = await fetchRequest(`/privileges/${id}/`, { method: "DELETE" }) + if (isSuccess) { + setPrivileges((privileges) => privileges.filter((element) => element.id !== id)) + toggleNotification({ + visible: true, + message: "L'habilitation a été supprimée avec succès", + type: "success" + }) + } else if (status == 404) { + toggleNotification({ + visible: true, + message: "L'habilitation n'a pas été trouvé", + type: "warning" + }) + } else { + console.log(errors) + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + } + setModalOpen(false) + } + const cancelUpdate = () => { + setIsUpdating(false) + setPrivilegeName(name) + inputRef.current.value = name + } + const inputRef = useRef(null) + const rowRef = useRef(null) + const handleUpdateBlur = (event) => { + const eventTarget = event.target + let isInsideRowRef = false; + let element = eventTarget; + while (element !== null) { + if (element === rowRef.current) { + isInsideRowRef = true; + break; + } + if (element.parentElement === null) { + isInsideRowRef = false; + break; + } + element = element.parentElement; + } + if (!isInsideRowRef && element?.classList.contains("privilegeRowSVG")) return; + if (!isInsideRowRef) { + cancelUpdate(); + document.removeEventListener("click", handleUpdateBlur); + } + } + useEffect(() => { + if (isUpdating && inputRef?.current) { + inputRef.current.focus() + document.addEventListener("click", handleUpdateBlur) + } + return () => { + document.removeEventListener("click", handleUpdateBlur) + } + }, [isUpdating]) + return ( + <> + + + setPrivilegeName(event.target.value)} defaultValue={name} type='text' className='disabled:bg-white w-full border-0 rounded-md px-2 enabled:drop-shadow border-none enabled:bg-gray-100 duration-100 h-10 outline-none' /> + + + {!isUpdating + ?
+ + +
+ :
+ + +
+ } + + + setModalOpen(false)} + onConfirm={handleDelete} + message={`Voulez-vous vraiment supprimer l'habilitation ?`} + /> + + ) + +} + +export default PrivilegeTableRow \ No newline at end of file diff --git a/src/app/privilege/page.jsx b/src/app/privilege/page.jsx new file mode 100644 index 0000000000000000000000000000000000000000..46c9515f8523b64d56f4b60cedc04afaffeaf2fb --- /dev/null +++ b/src/app/privilege/page.jsx @@ -0,0 +1,55 @@ +'use client' +import React, { useEffect, useState } from 'react' +import CreatePrivilegeForm from './CreatePrivilegeForm' +import fetchRequest from '../lib/fetchRequest' +import { isArray } from '../lib/TypesHelper' +import PrivilegeTableRows from './PrivilegeTableRow' +import Loader from '@/components/Loader/Loader' +const Privilege = () => { + const [privileges, setPrivileges] = useState([]) + const [isLoading, setIsLoading] = useState(true) + useEffect(() => { + const getPrivileges = async () => { + const { data, errors, isSuccess } = await fetchRequest("/privileges") + setIsLoading(false) + if (isSuccess) { + setPrivileges(data) + } else { + console.log(errors) + } + } + getPrivileges() + }, []) + const appendPrivilege = (privilege) => { + setPrivileges((data) => [privilege, ...data]) + } + return ( +
+
+
+ +

List des habilitations

+ {isLoading &&
} + {!isLoading && <> {(!isArray(privileges) || privileges?.length === 0) + ?
+

Pas encore des habilitations

+
+ :
+ + + + + + {privileges.map((element) => { + return + })} +
HabilitationAction
+
+ }} +
+
+
+ ) +} + +export default Privilege \ No newline at end of file diff --git a/src/app/projects/ProjectForm.jsx b/src/app/projects/ProjectForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..e8a184e425f1a48ab632b2c13242421776ed4318 --- /dev/null +++ b/src/app/projects/ProjectForm.jsx @@ -0,0 +1,188 @@ +import { useState, useEffect } from 'react'; +import fetchRequest from '@/app/lib/fetchRequest'; + +const ProjectForm = ({ onAddProject, onEditProject, editingProject }) => { + const [projectName, setProjectName] = useState(''); + const [clientName, setClientName] = useState(''); + const [dateDebut, setDateDebut] = useState(''); + const [dateFin, setDateFin] = useState(''); + const [userIds, setUserIds] = useState([]); + const [searchQuery, setSearchQuery] = useState(''); + const [userSuggestions, setUserSuggestions] = useState([]); + const [errors, setErrors] = useState({}); + + useEffect(() => { + if (editingProject) { + setProjectName(editingProject.nom); + setClientName(editingProject.nomClient); + setDateDebut(editingProject.dateDebut); + setDateFin(editingProject.dateFin); + setUserIds(editingProject.users || []); + } else { + setProjectName(''); + setClientName(''); + setDateDebut(''); + setDateFin(''); + setUserIds([]); + } + }, [editingProject]); + + useEffect(() => { + if (searchQuery.length > 1) { + const fetchUsers = async () => { + const { isSuccess, data } = await fetchRequest(`/search-users/?q=${searchQuery}`); + if (isSuccess) { + setUserSuggestions(data); + } + }; + fetchUsers(); + } else { + setUserSuggestions([]); + } + }, [searchQuery]); + + const handleUserSelect = (user) => { + setUserIds([...userIds, user]); + setSearchQuery(''); + setUserSuggestions([]); + }; + + const handleRemoveUserId = (index) => { + setUserIds(userIds.filter((_, i) => i !== index)); + }; + + const validateForm = () => { + const newErrors = {}; + if (!projectName) newErrors.projectName = "Project name is required"; + if (!clientName) newErrors.clientName = "Client name is required"; + if (!dateDebut) newErrors.dateDebut = "Start date is required"; + if (!userIds.length) newErrors.userIds = "At least one user is required"; + + setErrors(newErrors); + return Object.keys(newErrors).length === 0; + }; + + const handleSubmit = (e) => { + e.preventDefault(); + + if (!validateForm()) return; + + const project = { + nom: projectName, + nomClient: clientName, + dateDebut, + dateFin, + user_ids: userIds.map(user => user.id), + }; + + if (editingProject) { + onEditProject(editingProject.id, project); + } else { + onAddProject(project); + } + }; + + const isUserChosen = (user) => { + return userIds.some(chosenUser => chosenUser.id === user.id); + }; + + return ( +
+
+ + setProjectName(e.target.value)} + className="mt-1 block w-full px-3 py-2 bg-white border border-chicago-300 rounded-md" + required + /> + {errors.projectName &&

{errors.projectName}

} +
+
+ + setClientName(e.target.value)} + className="mt-1 block w-full px-3 py-2 bg-white border border-chicago-300 rounded-md" + required + /> + {errors.clientName &&

{errors.clientName}

} +
+
+
+ + setDateDebut(e.target.value)} + className="mt-1 block w-full px-3 py-2 bg-white border border-chicago-300 rounded-md" + required + /> + {errors.dateDebut &&

{errors.dateDebut}

} +
+
+ + setDateFin(e.target.value)} + className="mt-1 block w-full px-3 py-2 bg-white border border-chicago-300 rounded-md" + /> + {errors.dateFin &&

{errors.dateFin}

} +
+
+
+ + setSearchQuery(e.target.value)} + placeholder="Type to search users..." + className="mt-1 block w-full px-3 py-2 bg-white border border-chicago-300 rounded-md" + /> + {userSuggestions.length > 0 && ( +
    + {userSuggestions.map(user => ( +
  • !isUserChosen(user) && handleUserSelect(user)} + className={`px-3 py-2 border-b border-chicago-200 cursor-pointer ${isUserChosen(user) ? 'bg-gray-200 cursor-not-allowed' : 'hover:bg-sushi-200'}`} + > + {/*add tick is chosen*/} + {isUserChosen(user) && '✔ '} + {user.username} ({user.email}) {isUserChosen(user) && '(selectionné)'} +
  • + ))} +
+ )} +
+ {userIds.map((user, index) => ( +
+ + +
+ ))} +
+ {errors.userIds &&

{errors.userIds}

} +
+ +
+ ); +}; + +export default ProjectForm; diff --git a/src/app/projects/ProjectList.jsx b/src/app/projects/ProjectList.jsx new file mode 100644 index 0000000000000000000000000000000000000000..16d3fe3579cd7a07d7b7f1a293c3d0bed6afca85 --- /dev/null +++ b/src/app/projects/ProjectList.jsx @@ -0,0 +1,117 @@ +import ConfirmationModal from "@/app/ui/ConfirmationModal"; +import { useState } from "react"; + +const ProjectList = ({ projects, onEdit, onDelete, onHandlePageUrl }) => { + const [isModalOpen, setModalOpen] = useState(false); + const [projectToDelete, setProjectToDelete] = useState(null); + const handleDeleteClick = (project) => { + setProjectToDelete(project); + setModalOpen(true); + }; + + const handleConfirmDelete = () => { + onDelete(projectToDelete); + setModalOpen(false); + setProjectToDelete(null); + }; + return ( + <> + + + + + + + + + + + {projects + .sort((a, b) => new Date(b.updated_at) - new Date(a.updated_at)) + .map((project, index) => ( + + + + + + + ))} + +
ProjetMembres de léquipeNom du clientActions
{project.nom}{project.users.length}{project.nomClient} + + +
+ {/* Pagination */} + {projects.count && +
+
    +
  1. + +
  2. +
  3. + 1 +
  4. +
  5. + +
  6. +
+
+ } + {/* Confirmation Modal */} + setModalOpen(false)} + onConfirm={handleConfirmDelete} + message={`Are you sure you want to delete the project "${projectToDelete?.nom}"?`} + /> + + ); +}; + +export default ProjectList; diff --git a/src/app/projects/SideBar.jsx b/src/app/projects/SideBar.jsx new file mode 100644 index 0000000000000000000000000000000000000000..35e67e9ef9c957caba4dd59c0a72c688a2920c34 --- /dev/null +++ b/src/app/projects/SideBar.jsx @@ -0,0 +1,183 @@ +const SideBar = () => { + return ( +
+
+
+
+ + L + +
+ +
+
+ +
+
+
+ +
+
+ +
+
+
+
+ + ); +} +export default SideBar; \ No newline at end of file diff --git a/src/app/projects/page.jsx b/src/app/projects/page.jsx new file mode 100644 index 0000000000000000000000000000000000000000..14a694adcd27d49a78664cb97ceb91bbab1580bd --- /dev/null +++ b/src/app/projects/page.jsx @@ -0,0 +1,141 @@ +'use client'; + +import SideBar from "@/app/projects/SideBar"; +import { useEffect, useState } from 'react'; +import ProjectForm from "@/app/projects/ProjectForm"; +import ProjectList from "@/app/projects/ProjectList"; +import fetchRequest from "@/app/lib/fetchRequest"; + +const Projects = () => { + const [pageUrl, setPageUrl] = useState('/projects/'); + const [projects, setProjects] = useState([]); + const [editingProject, setEditingProject] = useState(null); + {/* errors from request*/ } + const [errors, setErrors] = useState(); + const [loading, setLoading] = useState(false); + const fetchProjects = async () => { + const { isSuccess, errors, data } = await fetchRequest(pageUrl); + if (isSuccess) { + setProjects(data); + setErrors(null); + } else { + console.error("Failed to fetch projects"); + setErrors(errors) + } + }; + useEffect(() => { + + fetchProjects(); + }, [pageUrl]); + + // pageURL + + const handleAddProject = async (project) => { + setLoading(true); + const { isSuccess, errors, data } = await fetchRequest('/projects/', { + method: 'POST', + body: JSON.stringify(project), + }); + + if (isSuccess) { + setProjects([...projects, data]); + setEditingProject(null); + setErrors(null); + } else { + console.log(errors); + console.error("Failed to add project"); + setErrors(errors) + } + setLoading(false); + }; + + const handleEditProject = async (id, updatedProject) => { + setLoading(true); + const { isSuccess, errors, data } = await fetchRequest(`/projects/${id}/`, { + method: 'PUT', + body: JSON.stringify(updatedProject), + }); + + if (isSuccess) { + const updatedProjects = projects.map((project) => + project.id === id ? data : project + ); + setProjects(updatedProjects); + setEditingProject(null); + setErrors(null); + } else { + console.error("Failed to edit project"); + setErrors(errors) + } + setLoading(false); + }; + + const handleEditClick = (project) => { + setEditingProject(project); + }; + + const handleDeleteProject = async (project) => { + setLoading(true) + const { isSuccess, errors } = await fetchRequest(`/projects/${project.id}/`, { + method: 'DELETE', + }); + + if (isSuccess) { + // setProjects(projects.filter((p) => p.id !== project.id)); + await fetchProjects(); + setEditingProject(null); + setErrors(null); + } else { + console.error("Failed to delete project"); + setErrors(errors) + } + setLoading(false); + }; + + return ( +
+
+ +
+ +
+
+

Projets + {loading ? ... : null}

+ + {/*errors from request*/} + {errors && errors.detail && Object.keys(errors.detail).map((key) => ( +
+
+ + + + Something went wrong +
+

+ {errors.detail[key]} +

+
+ ))} + + +
+
+
+ ); +} +export default Projects; + diff --git a/src/app/role/CreateRoleForm.jsx b/src/app/role/CreateRoleForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..d7c479d0ba974ae82aebbaddb6c4d8f8ae95cfa8 --- /dev/null +++ b/src/app/role/CreateRoleForm.jsx @@ -0,0 +1,144 @@ +import Loader from '@/components/Loader/Loader' +import React, { useState, useRef, useEffect, useMemo } from 'react' +import fetchRequest from '../lib/fetchRequest' +import { useNotification } from '@/context/NotificationContext' +import CancelIcon from "@/static/image/svg/cancel.svg" +const CreateRoleForm = ({ appendRole, setIsOpen }) => { + const [isLoading, setIsLoading] = useState(false) + const [roleName, setRoleName] = useState("") + const [privileges, setPrivileges] = useState(null) + const [selectedPrivileges, setSelectedPrivileges] = useState([]) + const { toggleNotification } = useNotification() + useEffect(() => { + const getPrivileges = async () => { + const { data, errors, isSuccess } = await fetchRequest("/privileges") + if (isSuccess) { + setPrivileges(data) + } else { + setPrivileges([]) + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + console.log(errors) + } + } + getPrivileges() + }, []) + const handleRoleNameChange = (event) => { + setRoleName(event.target.value) + } + const inputRef = useRef(null) + const handleSubmit = async (event) => { + event.preventDefault() + setIsLoading(true) + const { data, errors, isSuccess, status } = await fetchRequest("/roles/", { + method: "POST", + body: JSON.stringify({ name: roleName, privileges: selectedPrivileges.map((element) => element.id) }) + }) + if (isSuccess) { + setIsLoading(false) + inputRef.current.value = "" + setSelectedPrivileges([]) + setRoleName("") + appendRole(data) + toggleNotification({ + visible: true, + message: "Le rôle a été créé avec succès", + type: "success" + }) + setIsOpen(false) + } else { + setIsLoading(false) + if (errors.type === "ValidationError") { + if (errors.detail.name) { + toggleNotification({ + visible: true, + message: "Le rôle existe déjà", + type: "warning" + }) + } + else { + toggleNotification({ + visible: true, + message: "Erreur de validation de rôle", + type: "warning" + }) + setIsOpen(false) + } + } + else if (status === 409) { + toggleNotification({ + visible: true, + message: "Roles created with 2 or more same privileges", + type: "error" + }) + setIsOpen(false) + } else if (errors.detail === "Privilege matching query does not exist.") { + toggleNotification({ + visible: true, + message: "Des privilèges que vous avez utilisés ont été supprimés.", + type: "warning" + }) + setIsOpen(false) + } else { + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + setIsOpen(false) + } + console.log(errors) + } + } + const handlePrivilegeClick = (privilege) => { + if (selectedPrivileges.find((element) => element.id === privilege.id)) { + setSelectedPrivileges(selectedPrivileges.filter((element) => element.id !== privilege.id)) + } else { + setSelectedPrivileges([...selectedPrivileges, privilege]) + } + } + const selectAll = () => { + if (privileges.every((element) => selectedPrivileges.find((priv) => priv.id === element.id))) + setSelectedPrivileges([]) + else setSelectedPrivileges(privileges) + } + var isAllSelected = useMemo(() => privileges ? privileges.every((element) => selectedPrivileges.find((priv) => priv.id === element.id)) : false, [selectedPrivileges, privileges]) + return ( +
+
+ setIsOpen(false)} className="h-8 w-8 cursor-pointer absolute top-2 right-2 fill-neutral-600" /> + {(privileges) ?
+

Ajout de Rôle

+
+ + +
+
+
+ +
{!isAllSelected ? "Sélectionner tout" : "désélectionner"}
+
+
+ {privileges.length !== 0 ? privileges?.map((privilege) => { + const isSelected = selectedPrivileges.find((element) => element.id === privilege.id) !== undefined + return
handlePrivilegeClick(privilege)} key={privilege.id} className={`${!isSelected ? 'text-neutral-400 hover:border-neutral-400 hover:text-neutral-500 border-neutral-300 bg-neutral-100' : 'text-indigo-500 hover:border-indigo-500 hover:text-indigo-500 border-indigo-400 bg-indigo-100'} will-change-contents h-6 text-sm flex items-center justify-center duration-150 delay-75 cursor-pointer text-semibold leading-[0] border-2 py-0.5 rounded-full w-fit px-2`}>{privilege.name}
+ }) :
+

Pas encore des habilitations

+
} +
+
+
+ +
+
:
} +
+
+ ) +} + +export default CreateRoleForm \ No newline at end of file diff --git a/src/app/role/RoleTableRows.jsx b/src/app/role/RoleTableRows.jsx new file mode 100644 index 0000000000000000000000000000000000000000..c937dc003abaa06eb94bcdebe535b758c83843a7 --- /dev/null +++ b/src/app/role/RoleTableRows.jsx @@ -0,0 +1,84 @@ +import React, { useState } from 'react' +import fetchRequest from '../lib/fetchRequest' +import DeleteIcon from "@/static/image/svg/delete.svg" +import EditIcon from "@/static/image/svg/edit.svg" +import { useNotification } from '@/context/NotificationContext' +import ConfirmationModal from '../ui/ConfirmationModal' + +const RoleTableRows = ({ name, setRoles, id, privileges, setRoleToUpdate }) => { + const { toggleNotification } = useNotification() + const [isModalOpen, setModalOpen] = useState(false); + + const showDeletePopup = () => { + setModalOpen(true); + } + const handleDelete = async () => { + const { isSuccess, errors, status } = await fetchRequest(`/roles/${id}/`, { method: "DELETE" }) + if (isSuccess) { + setRoles((roles) => roles.filter((element) => element.id !== id)) + toggleNotification({ + visible: true, + message: "Le rôle a été supprimée avec succès", + type: "success" + }) + } else if (status == 404) { + toggleNotification({ + visible: true, + message: "Le rôle n'a pas été trouvé", + type: "warning" + }) + } else if (errors.detail?.indexOf("Cannot delete some instances of model 'Role'") !== -1) { + toggleNotification({ + visible: true, + message: "Impossible de supprimer ce rôle car il est attribué à des utilisateurs", + type: "warning" + }) + } + else { + console.log(errors) + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + } + setModalOpen(false) + console.log(errors) + } + + return ( + <> + + +

{name}

+ + +
+ {privileges?.map((element, index) => { + return
{element.name}
+ })} +
+ + +
+ + +
+ + + setModalOpen(false)} + onConfirm={handleDelete} + message={`Voulez-vous vraiment supprimer le rôle ?`} + /> + + + ) +} + +export default RoleTableRows \ No newline at end of file diff --git a/src/app/role/UpdateRoleForm.jsx b/src/app/role/UpdateRoleForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..348ebfce5dc70d57d41f4157b2bb2579c29dafca --- /dev/null +++ b/src/app/role/UpdateRoleForm.jsx @@ -0,0 +1,143 @@ +import { useNotification } from '@/context/NotificationContext' +import React, { useState, useRef, useEffect, useMemo } from 'react' +import fetchRequest from '../lib/fetchRequest' +import Loader from '@/components/Loader/Loader' +import CancelIcon from "@/static/image/svg/cancel.svg" +import { isArray } from '../lib/TypesHelper' +const UpdateRoleForm = ({ setRoleToUpdate, setRoles, roles, privileges: rolePrivileges, name, id }) => { + const { toggleNotification } = useNotification() + const [loadingStatus, setLoadingStatus] = useState(false) + const [roleName, setRoleName] = useState(name) + const [privileges, setPrivileges] = useState(null) + const [selectedPrivileges, setSelectedPrivileges] = useState(isArray(rolePrivileges) ? rolePrivileges : []) + const inputRef = useRef(null) + console.log("les priv de role ", rolePrivileges) + useEffect(() => { + const getPrivileges = async () => { + const { data, errors, isSuccess } = await fetchRequest("/privileges") + if (isSuccess) { + setPrivileges(data) + } else { + setPrivileges([]) + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + console.log(errors) + } + } + getPrivileges() + }, []) + const handleSubmit = async (event) => { + event.preventDefault() + setLoadingStatus(true) + const { isSuccess, errors, data, status } = await fetchRequest(`/roles/${id}/`, { + method: "PATCH", + body: JSON.stringify({ name: roleName, privileges: selectedPrivileges.filter((element) => privileges.find((prvElement) => prvElement.id === element.id)).map((element) => element.id) }) + }) + console.log(data) + setLoadingStatus(false) + if (isSuccess) { + setRoles((roles) => roles.map((element) => element.id === id ? data : element)) + toggleNotification({ + visible: true, + message: "Le rôle a été modifé avec succès", + type: "success" + }) + setRoleToUpdate(null) + } else { + if (errors.type === "ValidationError") { + if (errors.detail.name) { + toggleNotification({ + type: "warning", + message: "Le nom de rôle existe déjà", + visible: true, + }) + } + else { + toggleNotification({ + visible: true, + message: "Erreur de validation de rôle", + type: "warning" + }) + setRoleToUpdate(null) + } + } else if (status === 404) { + toggleNotification({ + visible: true, + message: "Le rôle n'a pas été trouvé", + type: "warning" + }) + setRoleToUpdate(null) + } else if (errors.detail === "Privilege matching query does not exist.") { + toggleNotification({ + visible: true, + message: "Des privilèges que vous avez utilisés ont été supprimés.", + type: "warning" + }) + setRoleToUpdate(null) + } + else { + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + setRoleToUpdate(null) + } + console.log(errors) + } + } + const handleRoleNameChange = (event) => { + setRoleName(event.target.value) + } + const handlePrivilegeClick = (privilege) => { + if (selectedPrivileges.find((element) => element.id === privilege.id)) { + setSelectedPrivileges(selectedPrivileges.filter((element) => element.id !== privilege.id)) + } else { + setSelectedPrivileges([...selectedPrivileges, privilege]) + } + } + const selectAll = () => { + if (privileges.every((element) => selectedPrivileges.find((priv) => priv.id === element.id))) + setSelectedPrivileges([]) + else setSelectedPrivileges(privileges) + } + var isAllSelected = useMemo(() => privileges ? privileges.every((element) => selectedPrivileges.find((priv) => priv.id === element.id)) : false, [selectedPrivileges, privileges]) + return ( +
+
+ setRoleToUpdate(null)} className="h-8 w-8 cursor-pointer absolute top-2 right-2 fill-neutral-600" /> + {(privileges) ?
+

Modification de Rôle

+
+ + +
+
+
+ +
{!isAllSelected ? "Sélectionner tout" : "désélectionner"}
+
+
+ {privileges.length !== 0 ? privileges?.map((privilege) => { + const isSelected = selectedPrivileges.find((element) => element.id === privilege.id) !== undefined + return
handlePrivilegeClick(privilege)} key={privilege.id} className={`${!isSelected ? 'text-neutral-400 hover:border-neutral-400 hover:text-neutral-500 border-neutral-300 bg-neutral-100' : 'text-indigo-500 hover:border-indigo-500 hover:text-indigo-500 border-indigo-400 bg-indigo-100'} will-change-contents h-6 text-sm flex items-center justify-center duration-150 delay-75 cursor-pointer text-semibold leading-[0] border-2 py-0.5 rounded-full w-fit px-2`}>{privilege.name}
+ }) :
+

Pas encore des habilitations

+
} +
+
+
+ +
+
:
} +
+
+ ) +} + +export default UpdateRoleForm \ No newline at end of file diff --git a/src/app/role/page.jsx b/src/app/role/page.jsx new file mode 100644 index 0000000000000000000000000000000000000000..411c32f224b7080f45d8f933a48805edd67ee899 --- /dev/null +++ b/src/app/role/page.jsx @@ -0,0 +1,75 @@ +'use client' +import React, { useState, useEffect } from 'react' +import CreateRoleForm from './CreateRoleForm' +import Loader from '@/components/Loader/Loader' +import RoleTableRows from './RoleTableRows' +import fetchRequest from '../lib/fetchRequest' +import { isArray } from '../lib/TypesHelper' +import AddIcon from "@/static/image/svg/add.svg" +import UpdateRoleForm from './UpdateRoleForm' +import { useNotification } from '@/context/NotificationContext' +const Role = () => { + const [roles, setRoles] = useState([]) + const [isLoading, setIsLoading] = useState(true) + const [openCreatePopup, setOpenCreatePopup] = useState(null) + const [roleToUpdate, setRoleToUpdate] = useState(null) + const { toggleNotification } = useNotification() + useEffect(() => { + const getRoles = async () => { + const { data, errors, isSuccess } = await fetchRequest("/roles") + setIsLoading(false) + if (isSuccess) { + console.log(data) + setRoles(data) + } else { + console.log(errors) + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + } + } + getRoles() + }, []) + const appendRole = (newRole) => { + setRoles([newRole, ...roles]) + } + return ( +
+
+
+ {openCreatePopup && } + {roleToUpdate && } +
+

List des Roles

+ +
+ {isLoading &&
} + {!isLoading && <> {(!isArray(roles) || roles?.length === 0) + ?
+

Pas encore des roles

+
+ :
+ + + + + + + {roles?.map((element) => { + return + })} +
RôleHabilitationsAction
+
+ }} +
+
+
+ ) +} + +export default Role \ No newline at end of file diff --git a/src/app/ui/ConfirmationModal.jsx b/src/app/ui/ConfirmationModal.jsx new file mode 100644 index 0000000000000000000000000000000000000000..1c667ac3e0990319217a3c6136941e21731b095b --- /dev/null +++ b/src/app/ui/ConfirmationModal.jsx @@ -0,0 +1,30 @@ +import React from 'react'; + +const ConfirmationModal = ({ isOpen, onClose, onConfirm, message }) => { + if (!isOpen) return null; + + return ( +
+
+

Confirmation

+

{message}

+
+ + +
+
+
+ ); +}; + +export default ConfirmationModal; diff --git a/src/app/ui/Header.jsx b/src/app/ui/Header.jsx new file mode 100644 index 0000000000000000000000000000000000000000..1137e74f45a87cdbf0d69bd65b5a15668ad8219c --- /dev/null +++ b/src/app/ui/Header.jsx @@ -0,0 +1,54 @@ +// 'use client'; + +// import { useState, useEffect } from 'react'; +import Link from 'next/link'; +// import isAuthenticated from "@/app/lib/isAuthenticated"; +import isAuthenticatedSSR from "@/app/lib/isAuthenticatedSSR"; +import LogoutButton from "@/app/ui/LogoutButton"; +// import fetchRequest from "@/app/lib/fetchRequest"; +// import Cookies from "js-cookie"; + +const Header = async () => { + + const {isAuth, sessionData} = await isAuthenticatedSSR() + console.log('isAuth', isAuth) + console.log('sessionData', sessionData) + return ( +
+
+ +

TeamBook

+ +
+ +
+ ); +}; + +export default Header; \ No newline at end of file diff --git a/src/app/ui/LogoutButton.js b/src/app/ui/LogoutButton.js new file mode 100644 index 0000000000000000000000000000000000000000..b219fc4381e545d6cd4e3facfe37c20696fbe65b --- /dev/null +++ b/src/app/ui/LogoutButton.js @@ -0,0 +1,26 @@ +'use client'; + +import Cookies from 'js-cookie'; +import fetchRequest from "@/app/lib/fetchRequest"; + +const LogoutButton = () => { + const logout = async () => { + const response = await fetchRequest(`/logout`, { + method: 'GET'}); + console.log(response); + if (response.isSuccess) { + console.log('logout successful'); + Cookies.remove('session'); + window.location.href = '/'; + } + + }; + + return ( + + ); +}; + +export default LogoutButton; diff --git a/src/app/user/CreateUserForm.jsx b/src/app/user/CreateUserForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..1b4540dded96560ea804cbd0e84475a0e820fc27 --- /dev/null +++ b/src/app/user/CreateUserForm.jsx @@ -0,0 +1,236 @@ +import React, { useState, useEffect } from 'react' +import Loader from '@/components/Loader/Loader' +import fetchRequest from '../lib/fetchRequest' +import { useNotification } from '@/context/NotificationContext' +import CancelIcon from "@/static/image/svg/cancel.svg" +import { EMAIL_REGEX } from '../lib/constants' + + + + +function generateRandomPassword() { + const length = Math.floor(Math.random() * 3) + 8; // Length between 8 and 10 + const uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + const lowercase = 'abcdefghijklmnopqrstuvwxyz'; + const numbers = '0123456789'; + const symbols = '!@#$%^&*()_+[]{}|;:,.<>?'; + + let password = ''; + + password += uppercase[Math.floor(Math.random() * uppercase.length)]; + password += numbers[Math.floor(Math.random() * numbers.length)]; + password += symbols[Math.floor(Math.random() * symbols.length)]; + + const allCharacters = uppercase + lowercase + numbers + symbols; + + for (let i = 3; i < length; i++) { + const randomIndex = Math.floor(Math.random() * allCharacters.length); + password += allCharacters[randomIndex]; + } + + password = password.split('').sort(() => 0.5 - Math.random()).join(''); + + return password; +} +const CreateUserForm = ({ setIsOpen, appendUser }) => { + const [isLoading, setIsLoading] = useState(false) + const [selectedRole, setSelectedRole] = useState(null) + const { toggleNotification } = useNotification() + const [selectedProject, setSelectedProject] = useState([]) + + const [roles, setRoles] = useState(null) + const [projects, setProjects] = useState(null) + useEffect(() => { + const getRoles = async () => { + const { data, errors, isSuccess } = await fetchRequest("/roles/") + if (isSuccess) { + setRoles(data) + } else { + setRoles([]) + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + console.log(errors) + } + } + const getProjects = async () => { + const { isSuccess, errors, data } = await fetchRequest("/projects/"); + if (isSuccess) { + setProjects(data); + } else { + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + console.log(errors) + } + } + getRoles() + getProjects() + }, []) + const handleFieldChange = (event) => { + setUserData({ ...userData, [event.target.name]: event.target.value }) + setErrors({ ...errors, [event.target.name]: "" }) + } + const [errors, setErrors] = useState({ first_name: "", last_name: "", email: "", role: "" }) + const [userData, setUserData] = useState({ email: "", password: generateRandomPassword(), first_name: "", last_name: "" }) + + const isValidFields = () => { + const localErrors = { first_name: "", last_name: "", email: "", role: "" } + if (userData.first_name === "") localErrors.first_name = "Le prénom doit être spécifier." + if (userData.last_name === "") localErrors.last_name = "Le nom doit être spécifier." + if (!selectedRole) localErrors.role = "Le rôle doit être spécifier." + if (!userData.email) localErrors.email = "L'email doit être spécifier." + else if (!EMAIL_REGEX.test(userData.email)) localErrors.email = "Votre adresse email n'est pas valide." + setErrors({ ...localErrors }) + return Object.values(localErrors).find((element) => element !== "") === undefined + } + const handleSubmit = async (event) => { + event.preventDefault() + if (isValidFields()) { + setIsLoading(true) + const { data, errors: requestErrors, isSuccess, status } = await fetchRequest("/users/", { + method: "POST", + body: JSON.stringify({ ...userData, username: userData.email, role: selectedRole, projects: selectedProject }) + }) + if (isSuccess) { + setIsLoading(false) + setSelectedRole(null) + appendUser(data) + toggleNotification({ + visible: true, + message: "L'utilisateur a été créé avec succès", + type: "success" + }) + setIsOpen(false) + } else { + setIsLoading(false) + if (requestErrors.type === "ValidationError") { + if (requestErrors.detail.email) { + setErrors({ ...errors, email: "Cette adresse email est déjà utilisée." }) + } + else if (requestErrors.detail.role) { + toggleNotification({ + visible: true, + message: "Erreur de validation de rôle (le rôle peut être supprimé)", + type: "warning" + }) + } + else { + toggleNotification({ + visible: true, + message: "Erreur de validation de utilisateur", + type: "warning" + }) + setIsOpen(false) + } + } + else { + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + setIsOpen(false) + } + console.log(requestErrors) + } + } + + } + const handleRoleChange = (event) => { + setErrors({ ...errors, role: "" }) + if (event.target.value) + setSelectedRole(event.target.value) + else setSelectedRole(null) + } + const handleProjectChange = (event) => { + if (event.target.value) + setSelectedProject([event.target.value]) + else setSelectedProject([]) + } + return ( +
+
+ setIsOpen(false)} className="h-8 w-8 cursor-pointer absolute top-2 right-2 fill-neutral-600" /> + {(roles && projects) ?
+

Ajout d'utilisateur

+
+
+ + +

{errors.last_name}

+
+
+ + +

{errors.first_name}

+
+
+
+ + +

{errors.email}

+
+
+ + +
+
+
+ +
+
+ {roles.length !== 0 ? +
+ +

{errors.role}

+
+ :
+

Pas encore des rôles

+
} +
+
+
+
+ +
+
+ {projects.length !== 0 ? +
+ +
+ :
+

Pas encore des projets

+
} +
+
+
+ +
+
:
} +
+
+ ) +} + +export default CreateUserForm \ No newline at end of file diff --git a/src/app/user/UpdateUserForm.jsx b/src/app/user/UpdateUserForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..1e62cce821677d104112efa6e1185d54b24774b0 --- /dev/null +++ b/src/app/user/UpdateUserForm.jsx @@ -0,0 +1,206 @@ +import React, { useState, useEffect } from 'react' +import Loader from '@/components/Loader/Loader' +import fetchRequest from '../lib/fetchRequest' +import { useNotification } from '@/context/NotificationContext' +import CancelIcon from "@/static/image/svg/cancel.svg" +import { EMAIL_REGEX } from '../lib/constants' + + +const UpdateUserForm = ({ setUserToUpdate, userToUpdate, setUsers }) => { + const [isLoading, setIsLoading] = useState(false) + const [selectedRole, setSelectedRole] = useState(userToUpdate.role?.id || null) + const { toggleNotification } = useNotification() + const [selectedProject, setSelectedProject] = useState(userToUpdate.projects?.length ? [userToUpdate.projects[0].id] : []) + + const [roles, setRoles] = useState(null) + const [projects, setProjects] = useState(null) + useEffect(() => { + const getRoles = async () => { + const { data, errors, isSuccess } = await fetchRequest("/roles/") + if (isSuccess) { + setRoles(data) + } else { + setRoles([]) + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + console.log(errors) + } + } + const getProjects = async () => { + const { isSuccess, errors, data } = await fetchRequest("/projects/"); + if (isSuccess) { + setProjects(data); + } else { + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + console.log(errors) + } + } + getRoles() + getProjects() + }, []) + const handleFieldChange = (event) => { + setUserData({ ...userData, [event.target.name]: event.target.value }) + setErrors({ ...errors, [event.target.name]: "" }) + } + const [errors, setErrors] = useState({ first_name: "", last_name: "", email: "", role: "" }) + const [userData, setUserData] = useState({ email: userToUpdate.email, first_name: userToUpdate.first_name, last_name: userToUpdate.last_name }) + + const isValidFields = () => { + const localErrors = { first_name: "", last_name: "", email: "", role: "" } + if (userData.first_name === "") localErrors.first_name = "Le prénom doit être spécifier." + if (userData.last_name === "") localErrors.last_name = "Le nom doit être spécifier." + if (!selectedRole) localErrors.role = "Le rôle doit être spécifier." + if (!userData.email) localErrors.email = "L'email doit être spécifier." + else if (!EMAIL_REGEX.test(userData.email)) localErrors.email = "Votre adresse email n'est pas valide." + setErrors({ ...localErrors }) + return Object.values(localErrors).find((element) => element !== "") === undefined + } + const handleSubmit = async (event) => { + event.preventDefault() + if (isValidFields()) { + setIsLoading(true) + const { data, errors: requestErrors, isSuccess, status } = await fetchRequest(`/users/${userToUpdate.id}/`, { + method: "PATCH", + body: JSON.stringify({ ...userData, username: userData.email, role: selectedRole, projects: selectedProject }) + }) + if (isSuccess) { + setUsers((users) => users.map((element) => element.id === userToUpdate.id ? data : element)) + setIsLoading(false) + setSelectedRole(null) + toggleNotification({ + visible: true, + message: "L'utilisateur a été modifié avec succès", + type: "success" + }) + setUserToUpdate(null) + } else { + setIsLoading(false) + if (requestErrors.type === "ValidationError") { + if (requestErrors.detail.email) { + setErrors({ ...errors, email: "Cette adresse email est déjà utilisée." }) + } + else if (requestErrors.detail.role) { + toggleNotification({ + visible: true, + message: "Erreur de validation de rôle (le rôle peut être supprimé)", + type: "warning" + }) + } + else { + toggleNotification({ + visible: true, + message: "Erreur de validation de utilisateur", + type: "warning" + }) + setUserToUpdate(null) + } + } + else { + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + setUserToUpdate(null) + } + console.log(requestErrors) + } + } + + } + const handleRoleChange = (event) => { + setErrors({ ...errors, role: "" }) + if (event.target.value) + setSelectedRole(event.target.value) + else setSelectedRole(null) + } + const handleProjectChange = (event) => { + if (event.target.value) + setSelectedProject([event.target.value]) + else setSelectedProject([]) + } + return ( +
+
+ setUserToUpdate(null)} className="h-8 w-8 cursor-pointer absolute top-2 right-2 fill-neutral-600" /> + {(roles && projects) ?
+

Modification d'utilisateur

+
+
+ + +

{errors.last_name}

+
+
+ + +

{errors.first_name}

+
+
+
+ + +

{errors.email}

+
+
+
+ +
+
+ {roles.length !== 0 ? +
+ +

{errors.role}

+
+ :
+

Pas encore des rôles

+
} +
+
+
+
+ +
+
+ {projects.length !== 0 ? +
+ +
+ :
+

Pas encore des projets

+
} +
+
+
+ +
+
:
} +
+
+ ) +} + +export default UpdateUserForm \ No newline at end of file diff --git a/src/app/user/UserTableRow.jsx b/src/app/user/UserTableRow.jsx new file mode 100644 index 0000000000000000000000000000000000000000..e0575321e03509d921e81fa70d03b2846fa3073a --- /dev/null +++ b/src/app/user/UserTableRow.jsx @@ -0,0 +1,88 @@ +import React, { useState } from 'react' +import DeleteIcon from "@/static/image/svg/delete.svg" +import EditIcon from "@/static/image/svg/edit.svg" +import ConfirmationModal from '../ui/ConfirmationModal' +import { useNotification } from '@/context/NotificationContext' +import fetchRequest from '../lib/fetchRequest' + +const UserTableRow = ({ email, last_name, first_name, id, setUsers, role, projects, setUserToUpdate }) => { + const { toggleNotification } = useNotification() + const [isModalOpen, setModalOpen] = useState(false); + const showDeletePopup = () => { + setModalOpen(true); + } + const handleDelete = async () => { + const { isSuccess, errors, status } = await fetchRequest(`/users/${id}/`, { method: "DELETE" }) + if (isSuccess) { + setUsers((users) => users.filter((element) => element.id !== id)) + toggleNotification({ + visible: true, + message: "L'utilisateur a été supprimé avec succès", + type: "success" + }) + } else if (status == 404) { + toggleNotification({ + visible: true, + message: "L'utilisateur n'a pas été trouvé", + type: "warning" + }) + } else if (errors.detail?.indexOf("Cannot delete some instances of model") !== -1) { + toggleNotification({ + visible: true, + message: "Impossible de supprimer cet utilisateur car il est attribué à d'autre objets", + type: "warning" + }) + } + else { + console.log(errors) + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + } + setModalOpen(false) + console.log(errors) + } + return ( + <> + + +

{first_name} {last_name}

+ + +

{email}

+ + +

{role?.name || ""}

+ + +
    + {(!projects || projects.length === 0) &&

    -

    } + {projects?.map((project) => { + return
  • {project.nom}
  • + })} +
+ + +
+ + +
+ + + setModalOpen(false)} + onConfirm={handleDelete} + message={`Voulez-vous vraiment supprimer le rôle ?`} + /> + + ) +} + +export default UserTableRow \ No newline at end of file diff --git a/src/app/user/page.jsx b/src/app/user/page.jsx new file mode 100644 index 0000000000000000000000000000000000000000..de82ec7b2e39c034cebdb294b46644b769a81f0a --- /dev/null +++ b/src/app/user/page.jsx @@ -0,0 +1,119 @@ +'use client'; +import React, { useEffect, useState, useDeferredValue } from 'react' +import CreateUserForm from './CreateUserForm' +import UpdateUserForm from './UpdateUserForm' +import AddIcon from "@/static/image/svg/add.svg" +import Loader from '@/components/Loader/Loader' +import fetchRequest from '../lib/fetchRequest'; +import { isArray } from '../lib/TypesHelper'; +import { useNotification } from '@/context/NotificationContext'; +import UserTableRow from './UserTableRow'; +import { PAGINATION_SIZE } from '../lib/constants'; +import ArrowRightIcon from "@/static/image/svg/chevron-right.svg" +import ArrowLeftIcon from "@/static/image/svg/chevron-left.svg" +const UserPage = () => { + const [users, setUsers] = useState([]) + const [paginationData, setPaginationData] = useState(null) + const [isLoading, setIsLoading] = useState(true) + const [openCreatePopup, setOpenCreatePopup] = useState(null) + const [userToUpdate, setUserToUpdate] = useState(null) + const { toggleNotification } = useNotification() + const [query, setQuery] = useState(''); + const getUsers = async (pageNumber = 1, signal) => { + setIsLoading(true) + if (search) var { data, errors, isSuccess } = await fetchRequest(`/users/?page=${pageNumber}&search=${query}`, { signal: signal }) + else var { data, errors, isSuccess } = await fetchRequest(`/users/?page=${pageNumber}`) + setIsLoading(false) + if (isSuccess) { + console.log(data) + setUsers(data.results) + setPaginationData({ pagesNumber: Math.ceil((data.count || 0) / PAGINATION_SIZE), currentPage: pageNumber }) + } else { + toggleNotification({ + visible: true, + message: "Internal Server Error", + type: "error" + }) + } + } + useEffect(() => { + const controller = new AbortController() + const signal = controller.signal + getUsers(1, signal) + return () => { + controller.abort("fetching another users") + } + }, [query]) + const appendUser = (newUser) => { + setUsers([newUser, ...users]) + } + + const handleSearchChange = (event) => { + setQuery(event.target.value) + } + return (
+
+
+ {openCreatePopup && } + {userToUpdate && } +
+

List des Utilisateurs

+ +
+
+ +
+ {(isLoading) &&
} + {(!isLoading) && <> {(!isArray(users) || users?.length === 0) + ?
+

Pas encore des utilisateurs

+
+ : +
+ + + + + + + + + {users?.map((element) => { + return + })} +
NomEmailRôleProjectsAction
+
} + + } +
+ {(paginationData) &&
+ {(paginationData.currentPage > 1) &&
getUsers(paginationData.currentPage - 1)} className='flex cursor-pointer hover:bg-neutral-200 duration-150 delay-75 h-8 w-9 items-center justify-center'> + +
} + {paginationData && Array.from({ length: paginationData.pagesNumber }, (_, index) => index).map((element, index) => { + if (element + 1 === paginationData.currentPage + 3) return

+ ... +

+ else if (paginationData.currentPage === element + 1) return

+ {element + 1} +

+ else if (paginationData.currentPage < element + 3 && element - paginationData.currentPage < 3) return

getUsers(element + 1)} key={element} className='h-8 w-9 hover:bg-neutral-200 cursor-pointer duration-150 delay-75 font-bold text-neutral-700 text-sm flex items-center justify-center' > + {element + 1} +

+ else return <> + })} + {(paginationData.currentPage !== paginationData.pagesNumber) &&
getUsers(paginationData.currentPage + 1)} className='flex h-8 w-9 items-center hover:bg-neutral-200 duration-150 delay-75 cursor-pointer justify-center'> + +
} +
} +
+
+
+
+ ) +} + +export default UserPage \ No newline at end of file diff --git a/src/app/zone/CreateNewZone.jsx b/src/app/zone/CreateNewZone.jsx new file mode 100644 index 0000000000000000000000000000000000000000..cdfb8cb47bc60185bfd6a5f51a28aac26f481075 --- /dev/null +++ b/src/app/zone/CreateNewZone.jsx @@ -0,0 +1,103 @@ +"use client" +import React, { useState, useEffect, useRef } from 'react' +import fetchRequest from '../lib/fetchRequest' +import Loader from '@/components/Loader/Loader' +import { Island_Moments } from 'next/font/google' + +const CreateNewZone = () => { + const [etages, setEtages] = useState([]) + const [error, setError] = useState(null) + const [isLoadingEtages, setIsLoadingEtages] = useState(true) + const [isLoadingAction, setIsLoadingAction] = useState(false) + const [nomZone, setNomZone] = useState("") + const [selectedEtage, setSelectedEtage] = useState(null) + + const inputRef = useRef(null) + const selectRef = useRef(null) + + useEffect(() => { + const getAllEtages = async () => { + try{ + const {isSuccess, errors, data} = await fetchRequest('/zoaning/etages/', {method: 'GET'}) + setIsLoadingEtages(false) + if(isSuccess){ + setEtages(data) + }else{ + setEtages([]) + } + }catch(error){ + setIsLoadingEtages(false) + console.log(error) + } + } + getAllEtages() + }, []) + + const handleSubmit = async (event) => { + event.preventDefault() + isLoadingAction(true) + const { data, errors, isSuccess } = await fetchRequest("/zoning/zones/", { + method: "POST", + body: JSON.stringify({ name: nomZone }) + }) + if (isSuccess) { + isLoadingAction(false) + appendPrivilege(data) + inputRef.current.value = "" + setPrivilegeName("") + } else { + isLoadingAction(false) + if (errors.type === "ValidationError") { + if (errors.detail.name) { + setError("Le privilège existe déjà") + } + } + console.log(errors) + } + } + + // Handle the name of zone change + const handleChangeZone = (event) => { + setError("") + setNomZone(event.target.value) + } + + const handleChangeEtage = (event) => { + setError("") + setSelectedEtage(event.target.value) + } + + + + return( +
+

Ajout d'une zone

+
+
+ + +
+
+ + +
+
+

+
+ +
+
+ ) +} + + +export default CreateNewZone \ No newline at end of file diff --git a/src/app/zone/RowZone.jsx b/src/app/zone/RowZone.jsx new file mode 100644 index 0000000000000000000000000000000000000000..1d71ca2b41bd1fb68e5dda4303226ade197b38c9 --- /dev/null +++ b/src/app/zone/RowZone.jsx @@ -0,0 +1,50 @@ +"use client" +import React from 'react' +import fetchRequest from '../lib/fetchRequest' +import { useState, useEffect } from 'react'; +import Loader from '@/components/Loader/Loader' +import CreateNewZone from './CreateNewZone' +import DeleteIcon from "@/static/image/svg/delete.svg" +import EditIcon from "@/static/image/svg/edit.svg" +import CancelIcon from "@/static/image/svg/cancel.svg" +import CheckIcon from "@/static/image/svg/check.svg" + + +const RowZone = ({ id, nom, etage }) => { + return( + + + + + + + + +
+ + +
+
+ + +
+ + + ) +} + + +export default RowZone \ No newline at end of file diff --git a/src/app/zone/page.jsx b/src/app/zone/page.jsx new file mode 100644 index 0000000000000000000000000000000000000000..a1c067effa3ea3e661e1e37ec94322ca0c992fd8 --- /dev/null +++ b/src/app/zone/page.jsx @@ -0,0 +1,66 @@ +"use client" +import React from 'react' +import fetchRequest from '../lib/fetchRequest' +import { useState, useEffect } from 'react'; +import Loader from '@/components/Loader/Loader' +import CreateNewZone from './CreateNewZone' +import DeleteIcon from "@/static/image/svg/delete.svg" +import EditIcon from "@/static/image/svg/edit.svg" +import CancelIcon from "@/static/image/svg/cancel.svg" +import CheckIcon from "@/static/image/svg/check.svg" +import RowZone from './RowZone' + + +const Zone = ()=> { + const [zones, setZones] = useState([]) + const [ isLoadingData, setIsLoadingData ] = useState(true) + // Fetch data from external API + useEffect(() => { + const getAllZones = async () => { + try{ + const {isSuccess, errors, data} = await fetchRequest('/zoaning/zones/', {method: 'GET'}) + setIsLoadingData(false) + if(isSuccess){ + setZones(data) + }else{ + setZones([]) + } + }catch(error){ + setIsLoadingData(false) + console.log(error) + } + } + getAllZones() + }, []) + return( +
+
+
+ +

List des Zones

+ {zones ? +
+

Pas encore des habilitations

+
+ : +
+ + + + + + + {zones.map((element) => { + return + })} +
ZoneEtageAction
+
+ } +
+
+
+ + ) +} + +export default Zone \ No newline at end of file diff --git a/src/components/Loader/Loader.css b/src/components/Loader/Loader.css new file mode 100644 index 0000000000000000000000000000000000000000..1e1ca65608312aa3c0c9ecfbed194e5cee0cbf75 --- /dev/null +++ b/src/components/Loader/Loader.css @@ -0,0 +1,46 @@ +@keyframes ldio-gcsicpsikdq { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + +.ldio-gcsicpsikdq div { + width: 50px; + height: 50px; + border-top-color: transparent; + border: 5px solid transparent; + border-radius: 50%; +} + +.ldio-gcsicpsikdq div { + animation: ldio-gcsicpsikdq 1s linear infinite; +} + +.loadingio-spinner-rolling-daoiuzlm498 { + width: min-content; + height: 70px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + background: transparent; +} + +.ldio-gcsicpsikdq { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + transform: translateZ(0) scale(1); + backface-visibility: hidden; + transform-origin: 0 0; + /* see note above */ +} + +.ldio-gcsicpsikdq div { + box-sizing: content-box; +} \ No newline at end of file diff --git a/src/components/Loader/Loader.jsx b/src/components/Loader/Loader.jsx new file mode 100644 index 0000000000000000000000000000000000000000..2430f19a7bd30aade3569d38228bdc38b43b5288 --- /dev/null +++ b/src/components/Loader/Loader.jsx @@ -0,0 +1,13 @@ +import React from 'react' +import "./Loader.css" +const Loader = ({ size, border, className, color }) => { + return ( +
+
+
+
+
+ ) +} + +export default Loader \ No newline at end of file diff --git a/src/components/Notification/Error.jsx b/src/components/Notification/Error.jsx new file mode 100644 index 0000000000000000000000000000000000000000..6329a934072ae8e2b30be32c6703019794afd7f4 --- /dev/null +++ b/src/components/Notification/Error.jsx @@ -0,0 +1,39 @@ +import React, { useEffect, useRef } from 'react' +import WarningIcon from "@/static/image/svg/WarningIcon.svg" +import CrossIcon from "@/static/image/svg/cross.svg" +import "./Notification.css" + +const Error = ({ displayNotification, message, closeNotification }) => { + const container = useRef(null) + useEffect(() => { + if (!displayNotification) { + container.current.style.transform = "translateX(110%)" + } + }, [displayNotification]) + const hideNotification = () => { + container.current.style.transform = "translateX(110%)" + setTimeout(() => { + closeNotification() + }, 800) + } + return ( +
+
+
+ +
+
+ +
+
+
+

Erreur

+

{message}

+
+
+
+
+
+ ) +} +export default Error \ No newline at end of file diff --git a/src/components/Notification/Notification.css b/src/components/Notification/Notification.css new file mode 100644 index 0000000000000000000000000000000000000000..6f8e680fdc982b32ba35c4305423d202660d0f24 --- /dev/null +++ b/src/components/Notification/Notification.css @@ -0,0 +1,277 @@ +@keyframes timerAnimation { + 0% { + width: 0%; + } + + 100% { + width: 100%; + } +} + +@keyframes notificationPopupContainerAnimation { + 0% { + transform: translateX(110%); + } + + 30% { + transform: translateX(-11%); + } + + 40% { + transform: translateX(-1%); + } + + 45% { + transform: translateX(-8%); + } + + 50% { + transform: translateX(-2%); + } + + 100%, + 60% { + transform: translateX(-5%); + } +} + +.notificationPopup { + z-index: 5000000; + position: fixed; + bottom: 10px; + right: 10px; + transform: translateX(-5%); + transition: 800ms; + animation-name: notificationPopupContainerAnimation; + animation-duration: 1700ms; + background-color: white; + height: 70px; + max-width: 450px; + border-radius: 7px; + width: 83.33%; + box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); + --tw-shadow-color: #d4d4d4; +} + +@media screen and (min-width: 768px) { + .notificationPopup { + width: 66.66%; + } +} + +@media screen and (min-width: 1024px) { + .notificationPopup { + width: 33.33%; + } +} + +@media screen and (min-width: 1280px) { + .notificationPopup { + width: 30%; + } +} + +.notificationPopup>div { + display: flex; + align-items: center; + height: 100%; + position: relative; +} + +.notificationPopup .part1 { + width: 20%; + display: flex; + align-items: center; + height: 100%; + border-bottom-left-radius: 7px; + border-top-left-radius: 7px; + background-color: rgb(34 197 94); + justify-content: center; +} + +.notificationPopup .part1Warning { + width: 20%; + display: flex; + align-items: center; + height: 100%; + border-bottom-left-radius: 7px; + border-top-left-radius: 7px; + background-color: #facc15; + justify-content: center; +} + +.notificationPopup .part1Error { + width: 20%; + display: flex; + align-items: center; + height: 100%; + border-bottom-left-radius: 7px; + border-top-left-radius: 7px; + background-color: #ef4444; + justify-content: center; +} + +.notificationPopup .part1 .icon { + height: 40px; + width: 40px; + fill: white; + stroke-width: 10px; +} + +.notificationPopup .part1Warning .icon { + height: 40px; + width: 40px; + fill: white; + stroke-width: 10px; +} + +.notificationPopup .part1Error .icon { + height: 40px; + width: 40px; + fill: white; + stroke-width: 10px; +} + +.notificationPopup .part2 { + position: absolute; + z-index: 50; + right: 4px; + top: 4px; + cursor: pointer; +} + +.notificationPopup .part2 .icon { + height: 12px; + width: 12px; + fill: rgb(23 23 23); +} + +.notificationPopup .part3 { + position: relative; + height: 100%; + flex: 1; +} + +.notificationPopup .part3:nth-child(1) { + display: flex; + justify-content: center; + height: 98%; + flex-direction: column; + display: flex; + margin-left: 8px; +} + +.notificationPopup .part3 h2 { + line-height: 20px; + font-size: 18px; + margin-left: 5px; + position: relative; + top: 4px; +} + +.notificationPopup .part3 p { + line-height: 20px; + font-size: 16px; + width: 91.6%; + line-height: 16px; + color: #78716c; + margin-left: 5px; + margin-top: 7px; +} + +.timerSuccess { + position: absolute; + bottom: 0; + height: 4px; + width: 100%; + background-color: transparent; + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; +} + +.timerWarning { + position: absolute; + bottom: 0; + height: 4px; + width: 100%; + background-color: transparent; + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; +} + +.timerSuccess::before { + height: 4px; + background-color: rgb(34 197 94); +} + +.timerSuccess::before { + height: 4px; + background-color: rgb(34 197 94); +} + +.timerSuccess::before { + content: ""; + position: absolute; + width: 0%; + animation-name: timerAnimation; + animation-duration: 4000ms; + animation-delay: 1700ms; + animation-timing-function: linear; + left: 0; + top: 0; +} + +.timerWarning::before { + height: 4px; + background-color: #facc15; +} + +.timerWarning::before { + height: 4px; + background-color: #facc15; +} + +.timerWarning::before { + content: ""; + position: absolute; + width: 0%; + animation-name: timerAnimation; + animation-duration: 4000ms; + animation-delay: 1700ms; + animation-timing-function: linear; + left: 0; + top: 0; +} + + +.timerError::before { + height: 4px; + background-color: #ef4444; +} + +.timerError::before { + height: 4px; + background-color: #ef4444; +} + +.timerError::before { + content: ""; + position: absolute; + width: 0%; + animation-name: timerAnimation; + animation-duration: 4000ms; + animation-delay: 1700ms; + animation-timing-function: linear; + left: 0; + top: 0; +} + +.timerError { + position: absolute; + bottom: 0; + height: 4px; + width: 100%; + background-color: transparent; + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; +} \ No newline at end of file diff --git a/src/components/Notification/Notification.jsx b/src/components/Notification/Notification.jsx new file mode 100644 index 0000000000000000000000000000000000000000..4dc60386df416d364c670005ab5fca321f6d45d2 --- /dev/null +++ b/src/components/Notification/Notification.jsx @@ -0,0 +1,66 @@ +import React, { useCallback, useEffect, useState } from 'react' +import Success from './Success' +import Warning from './Warning' +import { useNotification } from '@/context/NotificationContext' +import Error from './Error' +const Notification = () => { + const { toggleNotification, notification } = useNotification() + const [displayNotification, setDisplayNotification] = useState(true) + + var timeOutForwordPropagation + var timeOutBackPropagation + + const closeNotification = useCallback(() => { + clearTimeout(timeOutForwordPropagation) + clearTimeout(timeOutBackPropagation) + toggleNotification({ + visible: false, + type: null, + message: "" + }) + setDisplayNotification(true) + }, [timeOutForwordPropagation, timeOutBackPropagation]) + + + useEffect(() => { + if (notification?.type) { + new Promise((resolve, reject) => { + try { + timeOutForwordPropagation = setTimeout(() => { + setDisplayNotification(false) + resolve() + }, 5700) + } catch (e) { + reject(e) + } + }).then(() => { + timeOutBackPropagation = setTimeout(() => { + toggleNotification({ + visible: false, + type: null, + message: "" + }) + setDisplayNotification(true) + }, 800) + }).catch((error) => { + console.log(error) + }) + + return () => { + clearTimeout(timeOutForwordPropagation) + clearTimeout(timeOutBackPropagation) + } + } + }, [notification?.type]) + + if (notification?.type === "error") + return + if (notification?.type === "success") + return + else if (notification?.type === "warning") + return + else + return
+} + +export default Notification \ No newline at end of file diff --git a/src/components/Notification/Success.jsx b/src/components/Notification/Success.jsx new file mode 100644 index 0000000000000000000000000000000000000000..943570acd9bd6dbab70f4dd9793cb5a0a670f3d9 --- /dev/null +++ b/src/components/Notification/Success.jsx @@ -0,0 +1,39 @@ +import React, { useEffect, useRef } from 'react' +import SuccessIcon from "@/static/image/svg/successIcon.svg" +import CrossIcon from "@/static/image/svg/cross.svg" +import "./Notification.css" + +const Success = ({ displayNotification, message, closeNotification }) => { + const container = useRef(null) + useEffect(() => { + if (!displayNotification) { + container.current.style.transform = "translateX(110%)" + } + }, [displayNotification]) + const hideNotification = () => { + container.current.style.transform = "translateX(110%)" + setTimeout(() => { + closeNotification() + }, 800) + } + return ( +
+
+
+ +
+
+ +
+
+
+

Succès

+

{message}

+
+
+
+
+
+ ) +} +export default Success \ No newline at end of file diff --git a/src/components/Notification/Warning.jsx b/src/components/Notification/Warning.jsx new file mode 100644 index 0000000000000000000000000000000000000000..31eff42865f46e461f28dab4e06a9e6e846b8906 --- /dev/null +++ b/src/components/Notification/Warning.jsx @@ -0,0 +1,39 @@ +import React, { useEffect, useRef } from 'react' +import CrossIcon from "@/static/image/svg/cross.svg" +import WarningIcon from "@/static/image/svg/warningIcon.svg" + +const Warning = ({ displayNotification, message, closeNotification }) => { + const container = useRef(null) + useEffect(() => { + if (!displayNotification) { + container.current.style.transform = "translateX(110%)" + } + }, [displayNotification]) + const hideNotification = () => { + container.current.style.transform = "translateX(110%)" + setTimeout(() => { + closeNotification() + }, 800) + } + return ( +
+
+
+ +
+
+ +
+
+
+

Avertissement

+

{message}

+
+
+
+
+
+ ) +} + +export default Warning \ No newline at end of file diff --git a/src/context/NotificationContext.js b/src/context/NotificationContext.js new file mode 100644 index 0000000000000000000000000000000000000000..9d2bb5c823324be91c19741af43e47b6478d1b40 --- /dev/null +++ b/src/context/NotificationContext.js @@ -0,0 +1,25 @@ +"use client" +import Notification from '@/components/Notification/Notification'; +import React, { createContext, useState, useContext } from 'react'; + +const NotificationContext = createContext(); + +export const useNotification = () => { + return useContext(NotificationContext); +}; + + +export const NotificationProvider = ({ children }) => { + const [notification, setNotification] = useState(null); + + const toggleNotification = (payload) => { + setNotification(payload) + } + + return ( + + {children} + + + ); +}; \ No newline at end of file diff --git a/src/middleware.js b/src/middleware.js index 1308f827736c79a423734acb70d0051515d7d5b1..9c10ccd053ceab928edd7da6ffa5da999c49578b 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -1,12 +1,10 @@ -"use client"; - import { NextResponse } from 'next/server' import { decrypt } from '@/app/lib/session' -import Cookies from 'js-cookie'; +import { cookies } from 'next/headers' // 1. Specify protected and public routes -const protectedRoutes = ['/dashboard'] -const publicRoutes = ['/login', '/signup', '/'] +const protectedRoutes = ['/dashboard', '/auth/verif'] +const publicRoutes = ['/auth/login', '/auth/signup'] export default async function middleware(req) { // 2. Check if the current route is protected or public @@ -15,22 +13,21 @@ export default async function middleware(req) { const isPublicRoute = publicRoutes.includes(path) // 3. Decrypt the session from the cookie - const cookie = Cookies.get('session'); - console.log('cookie', cookie) + const cookie = cookies().get('session')?.value const session = await decrypt(cookie) - + // console.log('session dfdf', session) // 5. Redirect to /login if the user is not authenticated - if (isProtectedRoute && !session?.token) { - return NextResponse.redirect(new URL('/login', req.nextUrl)) + if (isProtectedRoute && !session?.sessionData.token) { + return NextResponse.redirect(new URL('/auth/login', req.nextUrl)) } // 6. Redirect to /dashboard if the user is authenticated if ( isPublicRoute && - session?.token && - !req.nextUrl.pathname.startsWith('/auth') + session?.sessionData.token && + !req.nextUrl.pathname.startsWith('/auth/verif') ) { - return NextResponse.redirect(new URL('/auth', req.nextUrl)) + return NextResponse.redirect(new URL('/auth/verif', req.nextUrl)) } return NextResponse.next() diff --git a/src/static/image/svg/add.svg b/src/static/image/svg/add.svg new file mode 100644 index 0000000000000000000000000000000000000000..37eaf783c6b70ff9297a84dfff632105ad288efe --- /dev/null +++ b/src/static/image/svg/add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/static/image/svg/cancel.svg b/src/static/image/svg/cancel.svg new file mode 100644 index 0000000000000000000000000000000000000000..1a52a76615e2ee52c46822777d48a7b04b1f8113 --- /dev/null +++ b/src/static/image/svg/cancel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/static/image/svg/check.svg b/src/static/image/svg/check.svg new file mode 100644 index 0000000000000000000000000000000000000000..f169344e257f6f1c7aacb4d33fc3fb1f790d3119 --- /dev/null +++ b/src/static/image/svg/check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/static/image/svg/chevron-left.svg b/src/static/image/svg/chevron-left.svg new file mode 100644 index 0000000000000000000000000000000000000000..bfbeddaec4e6e4a0ae5f8210efcc1f2044fca927 --- /dev/null +++ b/src/static/image/svg/chevron-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/static/image/svg/chevron-right.svg b/src/static/image/svg/chevron-right.svg new file mode 100644 index 0000000000000000000000000000000000000000..49c8a53fcd0352ccbec6886ee77927dd10244b18 --- /dev/null +++ b/src/static/image/svg/chevron-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/static/image/svg/cross.svg b/src/static/image/svg/cross.svg new file mode 100644 index 0000000000000000000000000000000000000000..f0c90d5047732e14d0693dfab195fb9d352cf075 --- /dev/null +++ b/src/static/image/svg/cross.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/static/image/svg/delete.svg b/src/static/image/svg/delete.svg new file mode 100644 index 0000000000000000000000000000000000000000..37a3374c3a00ed9249b891340e143a0304ef189f --- /dev/null +++ b/src/static/image/svg/delete.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/static/image/svg/edit.svg b/src/static/image/svg/edit.svg new file mode 100644 index 0000000000000000000000000000000000000000..9f6730fd01232372fc31d62cf49a68627c09ccb3 --- /dev/null +++ b/src/static/image/svg/edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/static/image/svg/successIcon.svg b/src/static/image/svg/successIcon.svg new file mode 100644 index 0000000000000000000000000000000000000000..57199b67460a6e381793e902fa51c699449090b1 --- /dev/null +++ b/src/static/image/svg/successIcon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/static/image/svg/warningIcon.svg b/src/static/image/svg/warningIcon.svg new file mode 100644 index 0000000000000000000000000000000000000000..8fdac5d1bf288ebf1fb6cb63992ec1488da89d64 --- /dev/null +++ b/src/static/image/svg/warningIcon.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + \ No newline at end of file