diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 93bc564d..66e9d633 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -27,7 +27,10 @@ module.exports = { 'react/self-closing-comp': 0, 'react/jsx-props-no-spreading': 0, '@typescript-eslint/no-explicit-any': 0, + 'jsx-a11y/label-has-associated-control': 0, + 'jsx-a11y/control-has-associated-label': 0, 'react/no-array-index-key': 0, + 'no-nested-ternary': 0, 'no-param-reassign': [ 'error', { props: true, ignorePropertyModificationsFor: ['state'] }, diff --git a/.hintrc b/.hintrc index b7cc97d9..fabba2c1 100644 --- a/.hintrc +++ b/.hintrc @@ -17,6 +17,12 @@ { "button-name": "off" } + ], + "axe/parsing": [ + "default", + { + "duplicate-id-active": "off" + } ] } } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 9467f54e..d60201b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@mui/material": "^5.16.4", "@react-jvectormap/core": "^1.0.4", "@react-jvectormap/world": "^1.1.2", - "@reduxjs/toolkit": "^2.2.5", + "@reduxjs/toolkit": "^2.2.6", "@testing-library/user-event": "^14.5.2", "@types/react-redux": "^7.1.33", "@types/react-router-dom": "^5.3.3", @@ -51,7 +51,7 @@ "yup": "^1.4.0" }, "devDependencies": { - "@testing-library/jest-dom": "^6.4.5", + "@testing-library/jest-dom": "^6.4.8", "@testing-library/react": "^16.0.0", "@types/dotenv": "^8.2.0", "@types/jest": "^29.5.12", @@ -60,7 +60,7 @@ "@types/node": "^20.14.7", "@types/react": "^18.3.3", "@types/react-color": "^3.0.12", - "@types/react-dom": "^18.2.22", + "@types/react-dom": "^18.3.0", "@types/react-simple-maps": "^3.0.4", "@types/react-slider": "^1.3.6", "@types/redux-mock-store": "^1.0.6", @@ -177,6 +177,12 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -375,70 +381,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", @@ -738,6 +680,16 @@ "statuses": "^2.0.1" } }, + "node_modules/@bundled-es-modules/tough-cookie": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz", + "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==", + "dev": true, + "dependencies": { + "@types/tough-cookie": "^4.0.5", + "tough-cookie": "^4.1.4" + } + }, "node_modules/@emotion/babel-plugin": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", @@ -756,33 +708,10 @@ "stylis": "4.2.0" } }, - "node_modules/@emotion/babel-plugin/node_modules/@emotion/memoize": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", - "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" - }, - "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" - }, - "node_modules/@emotion/babel-plugin/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@emotion/babel-plugin/node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" - }, "node_modules/@emotion/cache": { - "version": "11.13.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.0.tgz", - "integrity": "sha512-hPV345J/tH0Cwk2wnU/3PBzORQ9HeX+kQSbwI+jslzpRCHE6fSGTohswksA/Ensr8znPzwfzKZCmAM9Lmlhp7g==", + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", "dependencies": { "@emotion/memoize": "^0.9.0", "@emotion/sheet": "^1.4.0", @@ -791,33 +720,23 @@ "stylis": "4.2.0" } }, - "node_modules/@emotion/cache/node_modules/@emotion/memoize": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", - "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" - }, - "node_modules/@emotion/cache/node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" - }, "node_modules/@emotion/hash": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" }, "node_modules/@emotion/is-prop-valid": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", - "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz", + "integrity": "sha512-SHetuSLvJDzuNbOdtPVbq6yMMMlLoW5Q94uDqJZqy50gcmAjxFkVqmzqSGEFq9gT2iMuIeKV1PXVWmvUhuZLlQ==", "dependencies": { - "@emotion/memoize": "^0.8.1" + "@emotion/memoize": "^0.9.0" } }, "node_modules/@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" }, "node_modules/@emotion/react": { "version": "11.13.0", @@ -855,16 +774,6 @@ "csstype": "^3.0.2" } }, - "node_modules/@emotion/serialize/node_modules/@emotion/memoize": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", - "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" - }, - "node_modules/@emotion/serialize/node_modules/@emotion/unitless": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.9.0.tgz", - "integrity": "sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ==" - }, "node_modules/@emotion/sheet": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", @@ -892,23 +801,10 @@ } } }, - "node_modules/@emotion/styled/node_modules/@emotion/is-prop-valid": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz", - "integrity": "sha512-SHetuSLvJDzuNbOdtPVbq6yMMMlLoW5Q94uDqJZqy50gcmAjxFkVqmzqSGEFq9gT2iMuIeKV1PXVWmvUhuZLlQ==", - "dependencies": { - "@emotion/memoize": "^0.9.0" - } - }, - "node_modules/@emotion/styled/node_modules/@emotion/memoize": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", - "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" - }, "node_modules/@emotion/unitless": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.9.0.tgz", + "integrity": "sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ==" }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { "version": "1.1.0", @@ -1503,6 +1399,39 @@ "node": ">=18" } }, + "node_modules/@inquirer/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@inquirer/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@inquirer/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/@inquirer/core/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -1794,6 +1723,76 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/console/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/console/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@jest/core": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", @@ -1842,36 +1841,100 @@ } }, "node_modules/@jest/core/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/core/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/core/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true + "node_modules/@jest/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/@jest/environment": { "version": "29.7.0", @@ -1988,6 +2051,64 @@ } } }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/@jest/reporters/node_modules/istanbul-lib-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", @@ -2002,6 +2123,27 @@ "node": ">=10" } }, + "node_modules/@jest/reporters/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -2084,116 +2226,253 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=6.0.0" + "node": ">=7.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/transform/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/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=6.0.0" + "node": ">=8" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@kurkle/color": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", - "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" - }, - "node_modules/@mswjs/cookies": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-1.1.1.tgz", - "integrity": "sha512-W68qOHEjx1iD+4VjQudlx26CPIoxmIAtK4ZCexU0/UJBG6jYhcuyzKJx+Iw8uhBIGd9eba64XgWVgo20it1qwA==", + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@mswjs/interceptors": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.29.1.tgz", - "integrity": "sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw==", + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "@open-draft/deferred-promise": "^2.2.0", - "@open-draft/logger": "^0.3.0", - "@open-draft/until": "^2.0.0", - "is-node-process": "^1.2.0", - "outvariant": "^1.2.1", - "strict-event-emitter": "^0.5.1" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=18" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, + "node_modules/@mswjs/interceptors": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.29.1.tgz", + "integrity": "sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw==", + "dev": true, + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" } }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.4.tgz", - "integrity": "sha512-rNdHXhclwjEZnK+//3SR43YRx0VtjdHnUFhMSGYmAMJve+KiwEja/41EYh8V3pZKqF2geKyfcFUenTfDTYUR4w==", + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.5.tgz", + "integrity": "sha512-ziFn1oPm6VjvHQcdGcAO+fXvOQEgieIj0BuSqcltFU+JXIxjPdVYNTdn2HU7/Ak5Gabk6k2u7+9PV7oZ6JT5sA==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" } }, "node_modules/@mui/material": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.4.tgz", - "integrity": "sha512-dBnh3/zRYgEVIS3OE4oTbujse3gifA0qLMmuUk13ywsDCbngJsdgwW5LuYeiT5pfA8PGPGSqM7mxNytYXgiMCw==", + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.5.tgz", + "integrity": "sha512-eQrjjg4JeczXvh/+8yvJkxWIiKNHVptB/AqpsKfZBWp5mUD5U3VsjODMuUl1K2BSq0omV3CiO/mQmWSSMKSmaA==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/core-downloads-tracker": "^5.16.4", - "@mui/system": "^5.16.4", + "@mui/core-downloads-tracker": "^5.16.5", + "@mui/system": "^5.16.5", "@mui/types": "^7.2.15", - "@mui/utils": "^5.16.4", + "@mui/utils": "^5.16.5", "@popperjs/core": "^2.11.8", "@types/react-transition-group": "^4.4.10", "clsx": "^2.1.0", @@ -2228,18 +2507,13 @@ } } }, - "node_modules/@mui/material/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - }, "node_modules/@mui/private-theming": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.4.tgz", - "integrity": "sha512-ZsAm8cq31SJ37SVWLRlu02v9SRthxnfQofaiv14L5Bht51B0dz6yQEoVU/V8UduZDCCIrWkBHuReVfKhE/UuXA==", + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.5.tgz", + "integrity": "sha512-CSLg0YkpDqg0aXOxtjo3oTMd3XWMxvNb5d0v4AYVqwOltU8q6GvnZjhWyCLjGSCrcgfwm6/VDjaKLPlR14wxIA==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/utils": "^5.16.4", + "@mui/utils": "^5.16.5", "prop-types": "^15.8.1" }, "engines": { @@ -2291,15 +2565,15 @@ } }, "node_modules/@mui/system": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.4.tgz", - "integrity": "sha512-ET1Ujl2/8hbsD611/mqUuNArMCGv/fIWO/f8B3ZqF5iyPHM2aS74vhTNyjytncc4i6dYwGxNk+tLa7GwjNS0/w==", + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.5.tgz", + "integrity": "sha512-uzIUGdrWddUx1HPxW4+B2o4vpgKyRxGe/8BxbfXVDPNPHX75c782TseoCnR/VyfnZJfqX87GcxDmnZEE1c031g==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/private-theming": "^5.16.4", + "@mui/private-theming": "^5.16.5", "@mui/styled-engine": "^5.16.4", "@mui/types": "^7.2.15", - "@mui/utils": "^5.16.4", + "@mui/utils": "^5.16.5", "clsx": "^2.1.0", "csstype": "^3.1.3", "prop-types": "^15.8.1" @@ -2343,11 +2617,12 @@ } }, "node_modules/@mui/utils": { - "version": "5.16.4", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.4.tgz", - "integrity": "sha512-nlppYwq10TBIFqp7qxY0SvbACOXeOjeVL3pOcDsK0FT8XjrEXh9/+lkg8AEIzD16z7YfiJDQjaJG2OLkE7BxNg==", + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.5.tgz", + "integrity": "sha512-CwhcA9y44XwK7k2joL3Y29mRUnoBt+gOZZdGyw7YihbEwEErJYBtDwbZwVgH68zAljGe/b+Kd5bzfl63Gi3R2A==", "dependencies": { "@babel/runtime": "^7.23.9", + "@mui/types": "^7.2.15", "@types/prop-types": "^15.7.12", "clsx": "^2.1.1", "prop-types": "^15.8.1", @@ -2370,11 +2645,6 @@ } } }, - "node_modules/@mui/utils/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2780,10 +3050,80 @@ "node": ">=18" } }, + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "peer": true + }, + "node_modules/@testing-library/dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@testing-library/jest-dom": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.7.tgz", - "integrity": "sha512-GaKJ0nijoNf30dWSOOzQEBkWBRk4rG3C/efw8zKrimNuZpnS/6/AEwo0WvZHgJxG84cNCgxt+mtbe1fsvfLp2A==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.8.tgz", + "integrity": "sha512-JD0G+Zc38f5MBHA4NgxQMR5XtO5Jx9g86jqturNTt2WUfRmLDIY7iKkWHDCCTiDuFMre6nxAD5wHw9W5kI4rGw==", "dev": true, "dependencies": { "@adobe/css-tools": "^4.4.0", @@ -2799,30 +3139,21 @@ "node": ">=14", "npm": ">=6", "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" }, - "peerDependencies": { - "@jest/globals": ">= 28", - "@types/bun": "latest", - "@types/jest": ">= 28", - "jest": ">= 28", - "vitest": ">= 0.32" + "engines": { + "node": ">=8" }, - "peerDependenciesMeta": { - "@jest/globals": { - "optional": true - }, - "@types/bun": { - "optional": true - }, - "@types/jest": { - "optional": true - }, - "jest": { - "optional": true - }, - "vitest": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/@testing-library/jest-dom/node_modules/chalk": { @@ -2838,12 +3169,51 @@ "node": ">=8" } }, + "node_modules/@testing-library/jest-dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", "dev": true }, + "node_modules/@testing-library/jest-dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@testing-library/react": { "version": "16.0.0", "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.0.tgz", @@ -3081,12 +3451,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@types/jest/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, "node_modules/@types/jsdom": { "version": "21.1.7", "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz", @@ -3121,9 +3485,9 @@ } }, "node_modules/@types/node": { - "version": "20.14.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", - "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", + "version": "20.14.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz", + "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -3667,12 +4031,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@vitest/snapshot/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, "node_modules/@vitest/spy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", @@ -3726,12 +4084,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@vitest/utils/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", @@ -3817,17 +4169,14 @@ } }, "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { - "color-convert": "^2.0.1" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4" } }, "node_modules/any-promise": { @@ -4165,6 +4514,76 @@ "@babel/core": "^7.8.0" } }, + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/babel-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/babel-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/babel-plugin-istanbul": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", @@ -4443,9 +4862,9 @@ ] }, "node_modules/chai": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", - "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", "dev": true, "dependencies": { "assertion-error": "^1.1.0", @@ -4454,25 +4873,40 @@ "get-func-name": "^2.0.2", "loupe": "^2.3.6", "pathval": "^1.1.1", - "type-detect": "^4.0.8" + "type-detect": "^4.1.0" }, "engines": { "node": ">=4" } }, + "node_modules/chai/node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" } }, "node_modules/char-regex": { @@ -4635,6 +5069,39 @@ "node": ">=12" } }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cliui/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/cliui/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -4682,9 +5149,9 @@ } }, "node_modules/cloudinary": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-2.3.0.tgz", - "integrity": "sha512-QBa/ePVVfVcVOB1Vut236rjAbTZAArzOm0e2IWUkQJSZFS65Sjf+i3DyRGen4QX8GZzrcbzvKI9b8BTHAv1zqQ==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-2.3.1.tgz", + "integrity": "sha512-DW63pfRhN6Ob9czyLSG8G3Vz+m1tijLYyTZMOuFpFWPwtVXZVdFrc2ggDtGrbIBYpvr94tjPOkOdWgYW2ae3rA==", "dependencies": { "lodash": "^4.17.21", "q": "^1.5.1" @@ -4726,20 +5193,17 @@ "dev": true }, "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "color-name": "1.1.3" } }, "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/colorette": { "version": "2.0.20", @@ -4786,10 +5250,9 @@ "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 + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "node_modules/cookie": { "version": "0.5.0", @@ -4815,14 +5278,6 @@ "node": ">=10" } }, - "node_modules/cosmiconfig/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "engines": { - "node": ">= 6" - } - }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -4844,6 +5299,76 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/create-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/create-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/create-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/create-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -5315,9 +5840,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.833", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.833.tgz", - "integrity": "sha512-aVGP9xK70Ysrzip1m5LoJjCp1EDrYzZ7Pg/O3QR1h3PAhmc8SNfSXV3kmmtkg5rNO42EcTYmLX3eFMgqALlGIA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.2.tgz", + "integrity": "sha512-kc4r3U3V3WLaaZqThjYz/Y6z8tJe+7K0bbjUVo3i+LWIypVdMx5nXCkwRe6SWbY6ILqLdc1rKcKmr3HoH7wjSQ==", "dev": true }, "node_modules/emittery": { @@ -6100,6 +6625,21 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -6110,11 +6650,45 @@ "concat-map": "0.0.1" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -6125,6 +6699,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -6137,6 +6720,18 @@ "node": "*" } }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/eslint/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -6817,11 +7412,11 @@ } }, "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/has-property-descriptors": { @@ -6920,6 +7515,11 @@ "react-is": "^16.7.0" } }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", @@ -7606,6 +8206,27 @@ "node": ">=10" } }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/istanbul-lib-source-maps": { "version": "5.0.6", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", @@ -7733,17 +8354,63 @@ } }, "node_modules/jest-circus/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-circus/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-circus/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/jest-circus/node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -7758,11 +8425,29 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-circus/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true + "node_modules/jest-circus/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/jest-cli": { "version": "29.7.0", @@ -7797,6 +8482,76 @@ } } }, + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jest-config": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", @@ -7843,33 +8598,79 @@ } }, "node_modules/jest-config/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-config/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==", + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-config/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "node_modules/jest-config/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-config/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-config/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/jest-config/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -7877,11 +8678,29 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-config/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true + "node_modules/jest-config/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/jest-diff": { "version": "29.7.0", @@ -7899,17 +8718,63 @@ } }, "node_modules/jest-diff/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/jest-diff/node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -7924,11 +8789,29 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-diff/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true + "node_modules/jest-diff/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/jest-docblock": { "version": "29.7.0", @@ -7959,17 +8842,63 @@ } }, "node_modules/jest-each/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-each/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-each/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/jest-each/node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -7984,11 +8913,29 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-each/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true + "node_modules/jest-each/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/jest-environment-node": { "version": "29.7.0", @@ -8080,12 +9027,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-leak-detector/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, "node_modules/jest-matcher-utils": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", @@ -8102,58 +9043,78 @@ } }, "node_modules/jest-matcher-utils/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-matcher-utils/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-matcher-utils/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "node_modules/jest-matcher-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-matcher-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-matcher-utils/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-message-util/node_modules/ansi-styles": { + "node_modules/jest-matcher-utils/node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", @@ -8165,6 +9126,96 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-message-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-message-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/jest-message-util/node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -8179,11 +9230,29 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-message-util/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true + "node_modules/jest-message-util/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/jest-mock": { "version": "29.7.0", @@ -8258,6 +9327,76 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-resolve/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-resolve/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-resolve/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jest-runner": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", @@ -8290,60 +9429,200 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runner/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runner/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runtime/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runtime/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", "jest-message-util": "^29.7.0", "jest-util": "^29.7.0", "natural-compare": "^1.4.0", @@ -8355,17 +9634,63 @@ } }, "node_modules/jest-snapshot/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-snapshot/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/jest-snapshot/node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -8380,11 +9705,29 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-snapshot/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true + "node_modules/jest-snapshot/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/jest-util": { "version": "29.7.0", @@ -8403,6 +9746,76 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jest-validate": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", @@ -8421,6 +9834,90 @@ } }, "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/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/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-validate/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-validate/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", @@ -8432,55 +9929,105 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-validate/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "node_modules/jest-watcher/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=7.0.0" } }, - "node_modules/jest-validate/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "node_modules/jest-watcher/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "node_modules/jest-watcher/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" + "has-flag": "^4.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, "node_modules/jest-worker": { @@ -8498,6 +10045,15 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/jest-worker/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -8903,6 +10459,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lint-staged/node_modules/yaml": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", + "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/listr2": { "version": "8.2.3", "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.3.tgz", @@ -9286,16 +10854,16 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/msw": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/msw/-/msw-2.3.2.tgz", - "integrity": "sha512-vDn6d6a50vxPE+HnaKQfpmZ4SVXlOjF97yD5FJcUT3v2/uZ65qvTYNL25yOmnrfCNWZ4wtAS7EbtXxygMug2Tw==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.3.4.tgz", + "integrity": "sha512-sHMlwrajgmZSA2l1o7qRSe+azm/I+x9lvVVcOxAzi4vCtH8uVPJk1K5BQYDkzGl+tt0RvM9huEXXdeGrgcc79g==", "dev": true, "hasInstallScript": true, "dependencies": { "@bundled-es-modules/cookie": "^2.0.0", "@bundled-es-modules/statuses": "^1.0.1", + "@bundled-es-modules/tough-cookie": "^0.1.6", "@inquirer/confirm": "^3.0.0", - "@mswjs/cookies": "^1.1.0", "@mswjs/interceptors": "^0.29.0", "@open-draft/until": "^2.1.0", "@types/cookie": "^0.6.0", @@ -9328,6 +10896,76 @@ } } }, + "node_modules/msw/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/msw/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/msw/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/msw/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/msw/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/msw/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/msw/node_modules/type-fest": { "version": "4.23.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.23.0.tgz", @@ -9915,9 +11553,9 @@ } }, "node_modules/postcss": { - "version": "8.4.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", - "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "version": "8.4.40", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz", + "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==", "dev": true, "funding": [ { @@ -10013,6 +11651,18 @@ } } }, + "node_modules/postcss-load-config/node_modules/yaml": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", + "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/postcss-nested": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", @@ -10147,6 +11797,11 @@ "react-is": "^16.13.1" } }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/property-expr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", @@ -10295,9 +11950,9 @@ } }, "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, "node_modules/react-loader-spinner": { "version": "6.1.6", @@ -10315,11 +11970,6 @@ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/react-loader-spinner/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - }, "node_modules/react-loading-skeleton": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/react-loading-skeleton/-/react-loading-skeleton-3.4.0.tgz", @@ -10951,10 +12601,9 @@ } }, "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "engines": { "node": ">=0.10.0" } @@ -10977,6 +12626,15 @@ "source-map": "^0.6.0" } }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -11354,6 +13012,24 @@ "react-dom": ">= 16.8.0" } }, + "node_modules/styled-components/node_modules/@emotion/is-prop-valid": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/styled-components/node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/styled-components/node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, "node_modules/styled-components/node_modules/postcss": { "version": "8.4.38", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", @@ -11381,15 +13057,20 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/styled-components/node_modules/stylis": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", + "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==" + }, "node_modules/styled-components/node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/stylis": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", - "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, "node_modules/sucrase": { "version": "3.35.0", @@ -11443,14 +13124,14 @@ } }, "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dependencies": { - "has-flag": "^4.0.0" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -11465,9 +13146,9 @@ } }, "node_modules/swiper": { - "version": "11.1.5", - "resolved": "https://registry.npmjs.org/swiper/-/swiper-11.1.5.tgz", - "integrity": "sha512-JJQWFXdxiMGC2j6ZGTYat5Z7NN9JORJBgHp0/joX9uPod+cRj0wr5H5VnWSNIz9JeAamQvYKaG7aFrGHIF9OEg==", + "version": "11.1.7", + "resolved": "https://registry.npmjs.org/swiper/-/swiper-11.1.7.tgz", + "integrity": "sha512-2EpQvhgKb+DNbi8/i9uRXhddivcMZQxca341t2NZYV1xroCR2p4YtYd3azuqRQ4OEBGcG4nv3aN24O80bMipow==", "funding": [ { "type": "patreon", @@ -11505,9 +13186,9 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.6.tgz", - "integrity": "sha512-1uRHzPB+Vzu57ocybfZ4jh5Q3SdlH7XW23J5sQoM9LhE9eIOlzxer/3XPSsycvih3rboRsvt0QCmzSrqyOYUIA==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.7.tgz", + "integrity": "sha512-rxWZbe87YJb4OcSopb7up2Ba4U82BoiSGUdoDr3Ydrg9ckxFS/YWsvhN323GMcddgU65QRy7JndC7ahhInhvlQ==", "dev": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", @@ -12019,10 +13700,16 @@ "node": ">=10.12.0" } }, + "node_modules/v8-to-istanbul/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/vite": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.4.tgz", - "integrity": "sha512-Cw+7zL3ZG9/NZBB8C+8QbQZmR54GwqIz+WMI4b3JgdYJvX+ny9AjJXqkGQlDXSXRP9rP0B4tbciRMOVEKulVOA==", + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.5.tgz", + "integrity": "sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==", "dev": true, "dependencies": { "esbuild": "^0.21.3", @@ -12518,6 +14205,39 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -12657,15 +14377,11 @@ "dev": true }, "node_modules/yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", - "dev": true, - "bin": { - "yaml": "bin.mjs" - }, + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "engines": { - "node": ">= 14" + "node": ">= 6" } }, "node_modules/yargs": { diff --git a/package.json b/package.json index 99d85d94..d353a0c7 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "@mui/material": "^5.16.4", "@react-jvectormap/core": "^1.0.4", "@react-jvectormap/world": "^1.1.2", - "@reduxjs/toolkit": "^2.2.5", + "@reduxjs/toolkit": "^2.2.6", "@testing-library/user-event": "^14.5.2", "@types/react-redux": "^7.1.33", "@types/react-router-dom": "^5.3.3", @@ -59,7 +59,7 @@ "yup": "^1.4.0" }, "devDependencies": { - "@testing-library/jest-dom": "^6.4.5", + "@testing-library/jest-dom": "^6.4.8", "@testing-library/react": "^16.0.0", "@types/dotenv": "^8.2.0", "@types/jest": "^29.5.12", @@ -68,7 +68,7 @@ "@types/node": "^20.14.7", "@types/react": "^18.3.3", "@types/react-color": "^3.0.12", - "@types/react-dom": "^18.2.22", + "@types/react-dom": "^18.3.0", "@types/react-simple-maps": "^3.0.4", "@types/react-slider": "^1.3.6", "@types/redux-mock-store": "^1.0.6", diff --git a/src/__test__/Checkout/checkout.test.tsx b/src/__test__/Checkout/checkout.test.tsx index 26d52ab3..0c5a3609 100644 --- a/src/__test__/Checkout/checkout.test.tsx +++ b/src/__test__/Checkout/checkout.test.tsx @@ -28,8 +28,8 @@ describe('checkoutSlice', () => { it('should handle initial state', () => { expect(store.getState().checkout).toEqual({ checkout: { - id: 31, - totalAmount: 160, + id: -1, + totalAmount: 0, status: 'Pending', couponCode: '', deliveryInfo: { @@ -91,7 +91,7 @@ describe('checkoutSlice', () => { city: 'Anytown', zip: '12345', }, - id: 31, + id: -1, orderDetails: [ { id: 41, @@ -102,7 +102,7 @@ describe('checkoutSlice', () => { paid: true, paymentInfo: null, status: 'Pending', - totalAmount: 160, + totalAmount: 0, trackingNumber: 'Tr280585', updatedAt: '2024-07-22T11:01:20.291Z', }, diff --git a/src/__test__/Coupons/CouponsFeature.test.ts b/src/__test__/Coupons/CouponsFeature.test.ts new file mode 100644 index 00000000..441e64b7 --- /dev/null +++ b/src/__test__/Coupons/CouponsFeature.test.ts @@ -0,0 +1,185 @@ +import { configureStore } from '@reduxjs/toolkit'; + +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import axios from 'axios'; +import couponsReducer, { + fetchCoupons, + fetchMyCoupons, + createCoupon, + updateCoupon, + deleteCoupon, +} from '@/features/Coupons/CouponsFeature'; + +vi.mock('axios'); + +const createTestStore = () => + configureStore({ reducer: { coupons: couponsReducer } }); +let store: any; + +describe('couponsSlice', () => { + beforeEach(() => { + store = createTestStore(); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it('should handle initial state', () => { + const { coupons } = store.getState(); + expect(coupons).toEqual({ + coupons: [], + loading: false, + error: null, + }); + }); + + describe('fetchCoupons', () => { + it('should handle fetchCoupons.pending', () => { + store.dispatch(fetchCoupons.pending('requestId')); + const { coupons } = store.getState(); + expect(coupons.loading).toBe(true); + }); + + it('should handle fetchCoupons.fulfilled', async () => { + const mockCoupons = [{ id: 1, code: 'TEST' }]; + (axios.get as any).mockResolvedValueOnce({ data: mockCoupons }); + + await store.dispatch(fetchCoupons()); + const { coupons } = store.getState(); + expect(coupons.loading).toBe(false); + expect(coupons.coupons).toEqual(mockCoupons); + }); + + it('should handle fetchCoupons.rejected', async () => { + const error = 'Failed to fetch coupons'; + (axios.get as any).mockRejectedValueOnce(new Error(error)); + + await store.dispatch(fetchCoupons()); + const { coupons } = store.getState(); + expect(coupons.loading).toBe(false); + expect(coupons.error).toBe(error); + }); + }); + + describe('fetchMyCoupons', () => { + it('should handle fetchMyCoupons.pending', () => { + store.dispatch(fetchMyCoupons.pending('requestId')); + const { coupons } = store.getState(); + expect(coupons.loading).toBe(true); + }); + + it('should handle fetchMyCoupons.fulfilled', async () => { + const mockCoupons = [{ id: 1, code: 'MYCOUPON' }]; + (axios.get as any).mockResolvedValueOnce({ data: mockCoupons }); + + await store.dispatch(fetchMyCoupons()); + const { coupons } = store.getState(); + expect(coupons.loading).toBe(false); + expect(coupons.coupons).toEqual(mockCoupons); + }); + + it('should handle fetchMyCoupons.rejected', async () => { + const error = 'Failed to fetch coupons'; + (axios.get as any).mockRejectedValueOnce(new Error(error)); + + await store.dispatch(fetchMyCoupons()); + const { coupons } = store.getState(); + expect(coupons.loading).toBe(false); + expect(coupons.error).toBe(error); + }); + }); + describe('createCoupon', () => { + it('should handle createCoupon.pending', () => { + const dummyRequestId = 'dummyRequestId'; + const dummyArgs = { + newCoupon: { + description: '', + percentage: 0, + expirationDate: '', + applicableProducts: [], + }, + token: 'dummyToken', + }; + + store.dispatch(createCoupon.pending(dummyRequestId, dummyArgs)); + const { coupons } = store.getState(); + expect(coupons.loading).toBe(true); + }); + + it('should handle createCoupon.fulfilled', async () => { + const newCoupon = { + id: 1, + description: 'NEWCOUPON', + percentage: 1, + expirationDate: '2024-02-01', + applicableProducts: [1, 2], + }; + (axios.post as any).mockResolvedValueOnce({ data: newCoupon }); + + await store.dispatch(createCoupon({ newCoupon, token: 'testToken' })); + const { coupons } = store.getState(); + expect(coupons.loading).toBe(false); + expect(coupons.coupons).toContainEqual(newCoupon); + }); + + it('should handle createCoupon.rejected', async () => { + const error = 'Failed to create coupon'; + (axios.post as any).mockRejectedValueOnce(new Error(error)); + const invalidCoupon = { + description: '', + percentage: 0, + expirationDate: '', + applicableProducts: [], + }; + + await store.dispatch( + createCoupon({ newCoupon: invalidCoupon, token: 'testToken' }) + ); + const { coupons } = store.getState(); + expect(coupons.loading).toBe(false); + expect(coupons.error).toBe(error); + }); + }); + + describe('updateCoupon', () => { + it('should handle updateCoupon.rejected', async () => { + const error = 'Failed to update coupon'; + (axios.put as any).mockRejectedValueOnce(new Error(error)); + + const updatedCoupon = { + id: 1, + description: 'UPDATED DESCRIPTION', + percentage: 10, + expirationDate: '2024-12-31', + applicableProducts: [1, 2, 3], + code: 'UPDATEDCOUPON', + }; + + await store.dispatch(updateCoupon(updatedCoupon)); + const { coupons } = store.getState(); + expect(coupons.error).toBe(error); + }); + }); + + describe('deleteCoupon', () => { + it('should handle deleteCoupon.fulfilled', async () => { + const couponId = 1; + (axios.delete as any).mockResolvedValueOnce({ data: { id: couponId } }); + + await store.dispatch(deleteCoupon({ couponId, token: 'testToken' })); + const { coupons } = store.getState(); + const coupon = coupons.coupons.find((c: any) => c.id === couponId); + expect(coupon).toBeUndefined(); + }); + + it('should handle deleteCoupon.rejected', async () => { + const error = 'Failed to delete coupon'; + (axios.delete as any).mockRejectedValueOnce(new Error(error)); + + await store.dispatch(deleteCoupon({ couponId: 1, token: 'testToken' })); + const { coupons } = store.getState(); + expect(coupons.error).toBe(error); + }); + }); +}); diff --git a/src/__test__/TableUserRole.test.tsx b/src/__test__/TableUserRole.test.tsx new file mode 100644 index 00000000..ca45761a --- /dev/null +++ b/src/__test__/TableUserRole.test.tsx @@ -0,0 +1,94 @@ +import React from 'react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { configureStore } from '@reduxjs/toolkit'; +import { vi } from 'vitest'; +import axios from 'axios'; +import TableUserRole from '@/components/dashBoard/UserRole'; +import { showErrorToast } from '@/utils/ToastConfig'; +import userRoleSlice from '@/features/userRole/userRoleSlice'; + +vi.mock('@/utils/ToastConfig', () => ({ + showErrorToast: vi.fn(), + showSuccessToast: vi.fn(), +})); + +vi.mock('axios'); + +const renderWithProviders = (ui: React.ReactElement) => { + const store = configureStore({ + reducer: { + userRoles: userRoleSlice, + }, + }); + return render({ui}); +}; + +describe('TableUserRole', () => { + beforeEach(() => { + vi.clearAllMocks(); + (axios.get as jest.Mock).mockResolvedValue({ + data: { data: [{ id: 1, name: 'Admin', permissions: [] }] }, + }); + }); + + it('renders TableUserRole component', () => { + renderWithProviders(); + expect(screen.getByText('Register Role')).toBeInTheDocument(); + }); + + it('fetches all roles on mount', async () => { + renderWithProviders(); + await waitFor(() => { + expect(screen.getByText('Register Role')).toBeInTheDocument(); + }); + }); + + it('shows error when role name is empty', async () => { + renderWithProviders(); + + fireEvent.click(screen.getByText('Add Role')); + + await waitFor(() => { + expect(showErrorToast).toHaveBeenCalledWith('Role name cannot be empty'); + }); + }); + + it('adds and removes permissions', async () => { + renderWithProviders(); + + const permissionInput = screen.getByPlaceholderText('Enter permissions'); + fireEvent.change(permissionInput, { target: { value: 'Permission 1' } }); + fireEvent.click(screen.getByText('+ Add Permissions')); + + expect(screen.getByText('Permission 1')).toBeInTheDocument(); + + const removePermissionButton = screen.getByText('X', { + selector: 'button', + }); + fireEvent.click(removePermissionButton); + + await waitFor(() => { + expect(screen.queryByText('Permission 1')).not.toBeInTheDocument(); + }); + }); + + it('adds a new role successfully', async () => { + renderWithProviders(); + + const roleNameInput = screen.getByPlaceholderText('Role Name'); + const permissionInput = screen.getByPlaceholderText('Enter permissions'); + const addPermissionsButton = screen.getByText('+ Add Permissions'); + const addRoleButton = screen.getByText('Add Role'); + + fireEvent.change(roleNameInput, { target: { value: 'New Role' } }); + fireEvent.change(permissionInput, { target: { value: 'Permission 1' } }); + fireEvent.click(addPermissionsButton); + + fireEvent.click(addRoleButton); + + await waitFor(() => { + expect(screen.queryByText('Permission 1')).not.toBeInTheDocument(); + }); + }); +}); diff --git a/src/__test__/dashBoard/dashBoardSideBar.test.tsx b/src/__test__/dashBoard/dashBoardSideBar.test.tsx index 32e9df43..1c800749 100644 --- a/src/__test__/dashBoard/dashBoardSideBar.test.tsx +++ b/src/__test__/dashBoard/dashBoardSideBar.test.tsx @@ -1,9 +1,58 @@ -import { render, fireEvent } from '@testing-library/react'; +import { render, fireEvent, waitFor } from '@testing-library/react'; +import { MemoryRouter } from 'react-router-dom'; +import { configureStore } from '@reduxjs/toolkit'; +import { Provider } from 'react-redux'; +import signInReducer from '@/features/Auth/SignInSlice'; import DashboardSideNav from '@/components/dashBoard/DashboardSideNav'; +const createTestStore = () => + configureStore({ + reducer: { signIn: signInReducer }, + + preloadedState: { + signIn: { + token: 'test token', + user: { + email: 'test@gmail.com', + firstName: 'Test', + id: 1, + lastName: 'User', + picture: 'http://fakeimage.png', + userType: { + id: 1, + name: 'Admin', + permissions: ['crud'], + }, + }, + loading: false, + error: null, + message: null, + role: null, + needsVerification: false, + needs2FA: false, + vendor: { + id: null, + email: null, + }, + }, + }, + }); + +const store = createTestStore(); + +const renderDashboardSideNav = () => { + return render( + + + + + + ); +}; + describe('DashboardSideNav', () => { it('renders the sidebar items', () => { - const { getByText } = render(); + const { getByText } = renderDashboardSideNav(); expect(getByText('Dashboard')).toBeInTheDocument(); expect(getByText('Orders')).toBeInTheDocument(); expect(getByText('Customers')).toBeInTheDocument(); @@ -11,7 +60,7 @@ describe('DashboardSideNav', () => { }); it('expands and collapses the subitems', () => { - const { getByText, queryByText } = render(); + const { getByText, queryByText } = renderDashboardSideNav(); const productsItem = getByText('Products'); fireEvent.click(productsItem); expect(getByText(/all products/i)).toBeVisible(); @@ -19,18 +68,18 @@ describe('DashboardSideNav', () => { expect(queryByText(/all products/i)).not.toBeInTheDocument(); }); - it('renders the subitems correctly', () => { - const { getByText } = render(); + it('renders the subitems correctly', async () => { + const { getByText } = renderDashboardSideNav(); const productsItem = getByText('Products'); fireEvent.click(productsItem); - expect(getByText('All Products')).toBeInTheDocument(); - expect(getByText('Add New')).toBeInTheDocument(); - expect(getByText('Categories')).toBeInTheDocument(); - expect(getByText('Tags')).toBeInTheDocument(); + await waitFor(() => { + expect(getByText('All Products')).toBeInTheDocument(); + expect(getByText('Categories')).toBeInTheDocument(); + }); }); it('handles keydown events for subitems', () => { - const { getByText, getAllByText } = render(); + const { getByText, getAllByText } = renderDashboardSideNav(); const productsItem = getByText('Products'); fireEvent.keyDown(productsItem, { key: 'Enter' }); const allProductsElements = getAllByText(/all products/i); @@ -41,7 +90,7 @@ describe('DashboardSideNav', () => { }); it('toggles sidebar visibility', () => { - const { getByLabelText } = render(); + const { getByLabelText } = renderDashboardSideNav(); const toggleButton = getByLabelText('Toggle Menu'); fireEvent.click(toggleButton); expect(getByLabelText('Close Menu')).toBeInTheDocument(); diff --git a/src/__test__/dashBoard/dashboardHome.test.tsx b/src/__test__/dashBoard/dashboardHome.test.tsx index 4303c968..a33e7779 100644 --- a/src/__test__/dashBoard/dashboardHome.test.tsx +++ b/src/__test__/dashBoard/dashboardHome.test.tsx @@ -3,19 +3,59 @@ import { render, screen } from '@testing-library/react'; import { Provider } from 'react-redux'; import { MemoryRouter } from 'react-router-dom'; import { vi } from 'vitest'; +import { configureStore } from '@reduxjs/toolkit'; import HomeDashboard from '@/components/dashBoard/HomeDash'; -import { fetchBuyers } from '@/app/Dashboard/buyerSlice'; -import { fetchOrders } from '@/app/Dashboard/orderSlice'; +import BuyerReducer, { fetchBuyers } from '@/app/Dashboard/buyerSlice'; +import OrderReducer, { fetchOrders } from '@/app/Dashboard/orderSlice'; import { fetchProducts } from '@/features/Products/ProductSlice'; -import { store as appStore } from '@/app/store'; +import signInReducer from '@/features/Auth/SignInSlice'; vi.mock('react-chartjs-2', () => ({ Line: () =>
, })); +const createTestStore = () => + configureStore({ + reducer: { + signIn: signInReducer, + buyer: BuyerReducer, + order: OrderReducer, + }, + + preloadedState: { + signIn: { + token: 'test token', + user: { + email: 'test@gmail.com', + firstName: 'Test', + id: 1, + lastName: 'User', + picture: 'http://fakeimage.png', + userType: { + id: 1, + name: 'Admin', + permissions: ['crud'], + }, + }, + loading: false, + error: null, + message: null, + role: null, + needsVerification: false, + needs2FA: false, + vendor: { + id: null, + email: null, + }, + }, + }, + }); + +const store = createTestStore(); + const renderWithProviders = (ui: React.ReactElement) => { return render( - + {ui} ); @@ -23,9 +63,9 @@ const renderWithProviders = (ui: React.ReactElement) => { describe('HomeDashboard', () => { beforeEach(async () => { - await appStore.dispatch(fetchProducts()); - await appStore.dispatch(fetchBuyers()); - await appStore.dispatch(fetchOrders()); + await store.dispatch(fetchProducts()); + await store.dispatch(fetchBuyers()); + await store.dispatch(fetchOrders()); }); test('renders the HomeDashboard component', () => { @@ -45,7 +85,7 @@ describe('HomeDashboard', () => { renderWithProviders(); expect( screen.getByText( - `${appStore.getState().buyer.buyers.filter((buyer) => buyer.userType.name === 'Buyer').length}` + `${store.getState().buyer.buyers.filter((buyer) => buyer.userType.name === 'Buyer').length}` ) ).toBeInTheDocument(); }); diff --git a/src/__test__/dashBoard/dashboardProductSlice.test.tsx b/src/__test__/dashBoard/dashboardProductSlice.test.tsx index 0ca21cb4..b3efa06f 100644 --- a/src/__test__/dashBoard/dashboardProductSlice.test.tsx +++ b/src/__test__/dashBoard/dashboardProductSlice.test.tsx @@ -2,7 +2,7 @@ import { describe, it, expect } from 'vitest'; import DeshboardProductsSlice, { initialState, fetchDashboardProduct, -} from '@/features/Dashboard/dashboardProductsSlice'; // Adjust path as needed +} from '@/features/Dashboard/dashboardProductsSlice'; describe('DeshboardProductsSlice reducer', () => { it('should return the initial state', () => { diff --git a/src/__test__/home/productCard.test.tsx b/src/__test__/home/productCard.test.tsx index f8ec34fe..bff773a2 100644 --- a/src/__test__/home/productCard.test.tsx +++ b/src/__test__/home/productCard.test.tsx @@ -101,7 +101,7 @@ describe('ProductCard Component', () => { expect(halfStar.length).toBe(1); const emptyStar = screen.getAllByTestId('emptyStar'); - expect(emptyStar.length).toBe(Math.floor(4 - mockProduct.averageRating)); + expect(emptyStar.length).toBe(Math.floor(5 - mockProduct.averageRating)); const addToCartIcon = screen.getByTestId('addToCart'); expect(addToCartIcon).toBeInTheDocument(); diff --git a/src/__test__/userRoleSlice.test.tsx b/src/__test__/userRoleSlice.test.tsx new file mode 100644 index 00000000..12bb7826 --- /dev/null +++ b/src/__test__/userRoleSlice.test.tsx @@ -0,0 +1,181 @@ +import { configureStore } from '@reduxjs/toolkit'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; +import axios from 'axios'; +import userRoleSlice, { + fetchUserRoles, + createUserRole, + deleteUserRole, + updateUserRole, +} from '@/features/userRole/userRoleSlice'; + +vi.mock('axios'); + +const initialState = { + roles: [], + status: 'idle' as 'idle' | 'loading' | 'succeeded', + error: null as string | null, +}; + +describe('userRoleSlice', () => { + let store: any; + + beforeEach(() => { + store = configureStore({ + reducer: { + userRoles: userRoleSlice, + }, + }); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it('should have the correct initial state', () => { + const state = store.getState().userRoles; + expect(state).toEqual(initialState); + }); + + it('should handle fetchUserRoles.pending', async () => { + const action = { type: fetchUserRoles.pending.type }; + const state = userRoleSlice(initialState, action); + expect(state.status).toBe('loading'); + }); + + it('should handle fetchUserRoles.fulfilled', async () => { + const mockRoles = [ + { id: 1, name: 'Admin', permissions: ['read', 'write'] }, + { id: 2, name: 'User', permissions: ['read'] }, + ]; + + (axios.get as any).mockResolvedValue({ data: { roles: mockRoles } }); + + const action = { type: fetchUserRoles.fulfilled.type, payload: mockRoles }; + const state = userRoleSlice(initialState, action); + + expect(state.status).toBe('succeeded'); + expect(state.roles).toEqual(mockRoles); + }); + + it('should handle fetchUserRoles.rejected', async () => { + (axios.get as any).mockRejectedValue(new Error('Failed to fetch roles')); + + const action = { + type: fetchUserRoles.rejected.type, + error: { message: 'Failed to fetch roles' }, + }; + const state = userRoleSlice(initialState, action); + + expect(state.status).toBe('failed'); + expect(state.error).toBe('Failed to fetch roles'); + }); + + it('should handle deleteUserRole.pending', async () => { + const action = { type: deleteUserRole.pending.type }; + const state = userRoleSlice(initialState, action); + expect(state.status).toBe('loading'); + }); + + it('should handle deleteUserRole.fulfilled', async () => { + const existingRoles = [ + { id: 1, name: 'Admin', permissions: ['read', 'write'] }, + { id: 2, name: 'User', permissions: ['read'] }, + ]; + + (axios.delete as any).mockResolvedValue({}); + + const action = { type: deleteUserRole.fulfilled.type, payload: 1 }; + const state = userRoleSlice( + { ...initialState, roles: existingRoles }, + action + ); + + expect(state.roles).toEqual([ + { id: 2, name: 'User', permissions: ['read'] }, + ]); + }); + + it('should handle deleteUserRole.rejected', async () => { + (axios.delete as any).mockRejectedValue(new Error('Failed to delete role')); + + const action = { + type: deleteUserRole.rejected.type, + error: { message: 'Failed to delete role' }, + }; + const state = userRoleSlice( + { + ...initialState, + roles: [{ id: 1, name: 'Admin', permissions: ['read', 'write'] }], + }, + action + ); + + expect(state.status).toBe('failed'); + expect(state.error).toBe('Failed to delete role'); + }); + + it('should handle createUserRole.pending', async () => { + const action = { type: createUserRole.pending.type }; + const state = userRoleSlice(initialState, action); + expect(state.status).toBe('loading'); + }); + + it('should handle createUserRole.fulfilled', async () => { + const newRole = { id: 3, name: 'Editor', permissions: ['read', 'write'] }; + + (axios.post as any).mockResolvedValue({ data: { role: newRole } }); + + const action = { type: createUserRole.fulfilled.type, payload: newRole }; + const state = userRoleSlice({ ...initialState, roles: [] }, action); + + expect(state.roles).toEqual([newRole]); + }); + + it('should handle updateUserRole.pending', async () => { + const action = { type: updateUserRole.pending.type }; + const state = userRoleSlice(initialState, action); + expect(state.status).toBe('loading'); + }); + + it('should handle updateUserRole.fulfilled', async () => { + const existingRoles = [ + { id: 1, name: 'Admin', permissions: ['read', 'write'] }, + { id: 2, name: 'User', permissions: ['read'] }, + ]; + + const updatedRole = { + id: 1, + name: 'Super Admin', + permissions: ['read', 'write', 'delete'], + }; + + (axios.put as any).mockResolvedValue({ data: updatedRole }); + + const action = { + type: updateUserRole.fulfilled.type, + payload: updatedRole, + }; + const state = userRoleSlice( + { ...initialState, roles: existingRoles }, + action + ); + + expect(state.roles).toEqual([ + updatedRole, + { id: 2, name: 'User', permissions: ['read'] }, + ]); + }); + + it('should handle updateUserRole.rejected', async () => { + (axios.put as any).mockRejectedValue(new Error('Failed to update role')); + + const action = { + type: updateUserRole.rejected.type, + error: { message: 'Failed to update role' }, + }; + const state = userRoleSlice(initialState, action); + + expect(state.status).toBe('failed'); + expect(state.error).toBe('Failed to update role'); + }); +}); diff --git a/src/app/store.ts b/src/app/store.ts index 0f7f79c9..a9229a19 100644 --- a/src/app/store.ts +++ b/src/app/store.ts @@ -21,6 +21,8 @@ import checkoutSlice from '@/features/Checkout/checkoutSlice'; import ordersSliceReducer from '@/features/Orders/ordersSlice'; import contactReducer from '@/features/contact/contactSlice'; +import userRoleSlice from '@/features/userRole/userRoleSlice'; +import couponsSliceReducer from '@/features/Coupons/CouponsFeature'; export const store = configureStore({ reducer: { @@ -43,6 +45,8 @@ export const store = configureStore({ allProducts: allProductSlice, contact: contactReducer, checkout: checkoutSlice, + coupons: couponsSliceReducer, + userRoles: userRoleSlice, }, }); diff --git a/src/assets/TableLogo.png b/src/assets/TableLogo.png new file mode 100644 index 00000000..b07a1047 Binary files /dev/null and b/src/assets/TableLogo.png differ diff --git a/src/assets/icons/Airtel.png b/src/assets/icons/Airtel.png deleted file mode 100644 index 895e2935..00000000 Binary files a/src/assets/icons/Airtel.png and /dev/null differ diff --git a/src/assets/icons/MemberDiscount.png b/src/assets/icons/MemberDiscount.png deleted file mode 100644 index 6f74e16b..00000000 Binary files a/src/assets/icons/MemberDiscount.png and /dev/null differ diff --git a/src/assets/icons/masterCARD.svg b/src/assets/icons/masterCARD.svg deleted file mode 100644 index 56d537c3..00000000 --- a/src/assets/icons/masterCARD.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/src/assets/icons/moneyReturn.png b/src/assets/icons/moneyReturn.png deleted file mode 100644 index efd7cd9f..00000000 Binary files a/src/assets/icons/moneyReturn.png and /dev/null differ diff --git a/src/assets/icons/moneyReturn.svg b/src/assets/icons/moneyReturn.svg deleted file mode 100644 index 0ea7fe08..00000000 --- a/src/assets/icons/moneyReturn.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/assets/icons/mtn-momo.jpg b/src/assets/icons/mtn-momo.jpg deleted file mode 100644 index 606a810e..00000000 Binary files a/src/assets/icons/mtn-momo.jpg and /dev/null differ diff --git a/src/assets/icons/mtn_momo.png b/src/assets/icons/mtn_momo.png deleted file mode 100644 index bfbef758..00000000 Binary files a/src/assets/icons/mtn_momo.png and /dev/null differ diff --git a/src/assets/icons/sports.svg b/src/assets/icons/sports.svg deleted file mode 100644 index b85c42a9..00000000 --- a/src/assets/icons/sports.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/assets/icons/support.svg b/src/assets/icons/support.svg deleted file mode 100644 index 4c2b7bcc..00000000 --- a/src/assets/icons/support.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/src/assets/icons/supportIcon.png b/src/assets/icons/supportIcon.png deleted file mode 100644 index be0b0e9d..00000000 Binary files a/src/assets/icons/supportIcon.png and /dev/null differ diff --git a/src/assets/icons/truck.png b/src/assets/icons/truck.png deleted file mode 100644 index 816173db..00000000 Binary files a/src/assets/icons/truck.png and /dev/null differ diff --git a/src/assets/icons/truck.svg b/src/assets/icons/truck.svg deleted file mode 100644 index 34fa8375..00000000 --- a/src/assets/icons/truck.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/src/assets/icons/visaIcon.svg b/src/assets/icons/visaIcon.svg deleted file mode 100644 index 16f4c63c..00000000 --- a/src/assets/icons/visaIcon.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/src/components/Cart/Cart.tsx b/src/components/Cart/Cart.tsx index 0be7c7d4..ec536e69 100644 --- a/src/components/Cart/Cart.tsx +++ b/src/components/Cart/Cart.tsx @@ -65,6 +65,7 @@ export default function Cart() { ( ))}
-
-

Total:

- ${total} -
- + {cartItems.length > 0 && ( +
+

Total:

+ ${total} +
+ )} + {cartItems.length === 0 && ( +

Cart Empty

+ )} + {cartItems.length > 0 && ( + + )}
diff --git a/src/components/Cart/CartItem.tsx b/src/components/Cart/CartItem.tsx index a6deef70..250e8f2d 100644 --- a/src/components/Cart/CartItem.tsx +++ b/src/components/Cart/CartItem.tsx @@ -10,9 +10,10 @@ interface CartProps { price: number; name: string; quantity: number; + image: string; } -function CartItem({ id, price, name, quantity }: CartProps) { +function CartItem({ id, price, name, quantity, image }: CartProps) { const dispatch = useAppDispatch(); const [size, setSize] = useState<'M' | 'S' | 'L'>('M'); @@ -33,59 +34,15 @@ function CartItem({ id, price, name, quantity }: CartProps) { return (
Product
{name}
-
- - Color - -
- - -
-
-
- Size -
- - - -
-
-
+ +
Quantity
@@ -389,25 +420,23 @@ function Checkout() {
Total Cost - ${checkoutState.checkout.totalAmount} + ${order.totalAmount || total}
- + className={`w-full bg-primary text-white py-4 text-2xl font-medium rounded-md ${chosen ? '' : 'opacity-50 cursor-not-allowed'} ${paying ? 'opacity-75 cursor-not-allowed' : ''}`} + type="button" + onClick={handlePayment} + disabled={!chosen || paying} + > + {paying ? ( + + ) : ( + 'Pay Here' + )} +
); diff --git a/src/components/TopCategories.tsx b/src/components/TopCategories.tsx index 087357d1..bdce3c7d 100644 --- a/src/components/TopCategories.tsx +++ b/src/components/TopCategories.tsx @@ -29,7 +29,7 @@ function TopCategories() { }, [token]); return ( -
+

Top Categories

Categories

diff --git a/src/components/dashBoard/BestSellingProducts.tsx b/src/components/dashBoard/BestSellingProducts.tsx index 2c50bbac..6c4d2158 100644 --- a/src/components/dashBoard/BestSellingProducts.tsx +++ b/src/components/dashBoard/BestSellingProducts.tsx @@ -19,13 +19,13 @@ function ProductTable() { }); }, [token]); return ( -
+

Best selling Products

- +
- - + + @@ -35,7 +35,7 @@ function ProductTable() { {bestselling.map((product, idx) => ( - +
ID
No IMAGE PRODUCT NAME CATEGORY
{idx + 1} , + role: ['Admin', 'Vendor'], }, { path: '/dashboard/orders', name: 'Orders', icon: , + subItems: [ + { + path: '/dashboard/orders', + name: 'All orders', + role: ['Admin', 'Vendor'], + }, + ], + role: ['Admin', 'Vendor'], }, { - path: '/customers', + path: '/dashboard/customers', name: 'Customers', icon: , + subItems: [ + { + name: 'All customers', + path: '/dashboard/customers', + role: ['Admin'], + }, + ], + role: ['Admin'], }, { name: 'seller', @@ -33,12 +54,15 @@ const sideBarItems = [ { name: 'All Seller', path: '/dashboard/seller', + role: ['Admin'], }, { name: 'Add New', path: '/dashboard/addSeller', + role: ['Admin'], }, ], + role: ['Admin'], }, { name: 'Products', @@ -47,20 +71,50 @@ const sideBarItems = [ { path: '/dashboard/product', name: 'All Products', + role: ['Admin', 'Vendor'], }, { path: '/dashboard/addProduct', name: 'Add New', + role: ['Vendor'], }, { path: '/products/categories', name: 'Categories', + role: ['Admin'], + }, + ], + role: ['Admin', 'Vendor'], + }, + { + path: '/dashboard/coupons', + name: 'Coupons', + icon: , + subItems: [ + { + path: '/dashboard/coupons', + name: 'All coupons', + role: ['Admin', 'Vendor'], }, { - path: '/products/tags', - name: 'Tags', + path: '/dashboard/addCoupons', + name: 'Add New', + role: ['Vendor'], + }, + ], + role: ['Admin', 'Vendor'], + }, + { + name: 'user Role', + icon: , + subItems: [ + { + name: 'Add & All Roles', + path: '/dashboard/userRole', + role: ['Admin'], }, ], + role: ['Admin'], }, ]; @@ -69,15 +123,20 @@ interface SideBarItemProps { path?: string; name: string; icon: React.ReactNode; - subItems?: { path: string; name: string }[]; + subItems?: { path: string; name: string; role: string[] }[]; }; activeItem: string; setActiveItem: React.Dispatch>; + Role: string; } -function SideBarItem({ item, activeItem, setActiveItem }: SideBarItemProps) { +function SideBarItem({ + item, + activeItem, + setActiveItem, + Role, +}: SideBarItemProps) { const [expanded, setExpanded] = useState(false); - const handleExpand = () => { setExpanded(!expanded); }; @@ -109,7 +168,9 @@ function SideBarItem({ item, activeItem, setActiveItem }: SideBarItemProps) { >
{item.icon} - {item.name} + + {item.name} +
{item.subItems && (expanded ? ( @@ -120,20 +181,26 @@ function SideBarItem({ item, activeItem, setActiveItem }: SideBarItemProps) { {expanded && item.subItems && (
    - {item.subItems.map((subItem) => ( -
  • - setActiveItem(subItem.name)} - > - {subItem.name} - -
  • - ))} + {item.subItems.map((subItem) => { + if (subItem.role.includes(Role!)) { + return ( +
  • + setActiveItem(subItem.name)} + > + {subItem.name} + +
  • + ); + } + + return null; + })}
)} @@ -141,6 +208,8 @@ function SideBarItem({ item, activeItem, setActiveItem }: SideBarItemProps) { } function DashboardSideNav() { + const Role = useAppSelector((state) => state.signIn.user?.userType.name); + const [isVisible, setIsVisible] = useState(false); const [activeItem, setActiveItem] = useState('Dashboard'); @@ -172,14 +241,20 @@ function DashboardSideNav() { - {sideBarItems.map((item) => ( - - ))} + {sideBarItems.map((item) => { + if (item.role.includes(Role!)) { + return ( + + ); + } + return null; + })} diff --git a/src/components/dashBoard/EditProduct.tsx b/src/components/dashBoard/EditProduct.tsx index 45322097..e67bd1e8 100644 --- a/src/components/dashBoard/EditProduct.tsx +++ b/src/components/dashBoard/EditProduct.tsx @@ -1,5 +1,3 @@ -/* eslint-disable jsx-a11y/label-has-associated-control */ - import axios from 'axios'; import { useState, useEffect } from 'react'; import { useSelector } from 'react-redux'; diff --git a/src/components/dashBoard/HomeDash.tsx b/src/components/dashBoard/HomeDash.tsx index 054e5599..4c5914cb 100644 --- a/src/components/dashBoard/HomeDash.tsx +++ b/src/components/dashBoard/HomeDash.tsx @@ -10,6 +10,8 @@ import SalesMap from '../salesMap/SalesMap'; import ProductTable from './BestSellingProducts'; function HomeDash() { + const Role = useAppSelector((state) => state.signIn.user?.userType.name); + function getGreeting(): string { const now = new Date(); const hour = now.getHours(); @@ -69,87 +71,93 @@ function HomeDash() { farmer - -
-
-

Total Sales Available

- -
-

Sales Summary

-
-
-
-
- Sales -
-
-
{sum}$
-
-
-
- Total Sales + {Role === 'Admin' && ( + <> +
+
+

Total Sales Available

+
-

All Products Sales

-
-
-
-
- Order +

Sales Summary

+
+
+
+
+ Sales +
+
+
{sum}$
+
+
+
+ Total Sales +
+

+ All Products Sales +

-
{order.length}
-
-
- Total Order -
-

All Orders

-
-
-
-
- Product Sold +
+
+
+ Order +
+
{order.length}
+
+
+ Total Order +
+

All Orders

-
{tproduct}
-
-
- Product Sold -
-

All Products Sold

-
-
-
-
- New Customers +
+
+
+ Product Sold +
+
{tproduct}
+
+
+ Product Sold +
+

+ All Products Sold{' '} +

-
- {buyers && - buyers.filter( - (user) => user.userType && user.userType.name === 'Buyer' - ).length} +
+
+
+ New Customers +
+
+ {buyers && + buyers.filter( + (user) => + user.userType && user.userType.name === 'Buyer' + ).length} +
+
+
+ New Customers +
+

All Buyers

-
- New Customers -
-

All Buyers

-
-
-
- - -
-
- -
-
- -
+
+ + +
+
+ + +
+ + )}
); diff --git a/src/components/dashBoard/UserRole.tsx b/src/components/dashBoard/UserRole.tsx new file mode 100644 index 00000000..6ac15ba7 --- /dev/null +++ b/src/components/dashBoard/UserRole.tsx @@ -0,0 +1,357 @@ +/* eslint-disable react/button-has-type */ +import { useEffect, useState, useCallback } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { FaRegTrashAlt } from 'react-icons/fa'; +import { MdOutlineEdit } from 'react-icons/md'; +import BeatLoader from 'react-spinners/BeatLoader'; +import { RootState, AppDispatch } from '@/app/store'; +import { showErrorToast, showSuccessToast } from '@/utils/ToastConfig'; +import { + fetchUserRoles, + deleteUserRole, + createUserRole, + updateUserRole, +} from '@/features/userRole/userRoleSlice'; +import ConfirmationCard from './ConfirmationCard'; +import CircularPagination from './NavigateonPage'; +import TableLogo from '@/assets/TableLogo.png'; + +function TableUserRole() { + const dispatch: AppDispatch = useDispatch(); + const { roles, status } = useSelector((state: RootState) => state.userRoles); + const [editRole, setEditRole] = useState<{ + id: number; + name: string; + permissions: string[]; + } | null>(null); + + const [isConfirmationModalVisible, setModalVisible] = useState(false); + const [itemSelected, setItemSelected] = useState(null); + const [mode, setMode] = useState(''); + const [permissions, setPermissions] = useState([]); + const [newPermission, setNewPermission] = useState(''); + const [roleName, setRoleName] = useState(''); + const [deleting, setDeleting] = useState(false); + const [popupMessage, setPopupMessage] = useState(null); + const [isPopupVisible, setIsPopupVisible] = useState(false); + const [color, setColor] = useState(null); + const [isSubmitting, setIsSubmitting] = useState(false); + useEffect(() => { + dispatch(fetchUserRoles()); + }, [dispatch]); + + const handleDelete = useCallback(async () => { + if (itemSelected !== null) { + const response = await dispatch(deleteUserRole(itemSelected)); + if (deleteUserRole.fulfilled.match(response)) { + setPopupMessage('User Role deleted permanently'); + setColor('green'); + dispatch(fetchUserRoles()); + } else { + setPopupMessage( + 'Delete User Role failed. This may be due to a network issue.' + ); + setColor('red'); + } + setDeleting(false); + setModalVisible(false); + setIsPopupVisible(true); + setTimeout(() => { + setIsPopupVisible(false); + }, 10000); + } + }, [dispatch, itemSelected]); + + useEffect(() => { + if (deleting) { + handleDelete(); + } + }, [deleting, handleDelete]); + + useEffect(() => { + if (editRole) { + setRoleName(editRole.name); + setPermissions(editRole.permissions); + } else { + setRoleName(''); + setPermissions([]); + } + }, [editRole]); + + const addPermission = () => { + const trimmedPermission = newPermission.trim(); + if (trimmedPermission && !permissions.includes(trimmedPermission)) { + setPermissions([...permissions, trimmedPermission]); + setNewPermission(''); + } else { + showErrorToast('Permission cannot be empty'); + } + }; + + const removePermission = (permissionToRemove: string) => { + setPermissions( + permissions.filter((permission) => permission !== permissionToRemove) + ); + }; + + const handleDeleteClick = (roleId: number) => { + setItemSelected(roleId); + setMode('delete'); + setModalVisible(true); + }; + + const handleAddRole = async () => { + if (roleName.trim() === '') { + showErrorToast('Role name cannot be empty'); + return; + } + dispatch(fetchUserRoles()); + setIsSubmitting(true); + await dispatch(createUserRole({ name: roleName, permissions })); + showSuccessToast('Success Role added'); + setRoleName(''); + setPermissions([]); + setIsSubmitting(false); + }; + + const handleEditRole = async () => { + if (editRole && roleName.trim() !== '') { + setIsSubmitting(true); + try { + const response = await dispatch( + updateUserRole({ + id: editRole.id, + name: roleName, + permissions, + }) + ); + + if (updateUserRole.fulfilled.match(response)) { + dispatch(fetchUserRoles()); + setEditRole(null); + showSuccessToast('Success Role updated'); + } else { + showErrorToast('Failed to update role'); + } + } catch (error) { + showErrorToast('Failed to update role'); + } + setIsSubmitting(false); + } else { + showErrorToast('Role name cannot be empty'); + } + }; + + return ( +
+

Manage User Role

+
+
+ + + + + + + + + + + {status === 'loading' && + Array(6) + .fill(null) + .map((_, index) => ( + + + + ))} + {status === 'failed' && + Array(6) + .fill(null) + .map((_, index) => ( + + + + ))} + {status === 'succeeded' && + roles?.map((role) => ( + + + + + + ))} + +
+ ID + + Role Name + + Action +
+
+
+
+ Failed to load roles... +
+
{role.id}{role.name} +
+ setEditRole(role)} + /> +
+ +
+ handleDeleteClick(role.id)} + className="text-red-500 cursor-pointer h-[16px] w-[16px]" + /> +
+
+
+ {}} + /> +
+
+
+
+ +

Register Role

+
+
+ + setRoleName(e.target.value)} + className="w-[100%] border relative bg-grayLight text-black duration-100 outline-none justify-between flex items-center gap-2 px-3 rounded-md font-light group-hover:border-grayDark p-3 mb-5 lg:w-[70%] md:w-[70%]" + /> +
+ +
+ +
+
+ {permissions.map((permission, index) => ( + + {permission} + + + ))} +
+
+
+ setNewPermission(e.target.value)} + className="w-[100%] border relative bg-grayLight duration-100 outline-none justify-between flex items-center gap-2 px-3 rounded-md font-light group-hover:border-grayDark p-3 lg:w-[70%] md:w-[70%]" + /> + +
+
+ +
+ {editRole ? ( + + ) : ( + + )} +
+
+ + {mode === 'delete' && ( +
+ setModalVisible(false)} + onConfirm={() => setDeleting(true)} + message="Are you sure you want to delete this user role?" + /> +
+ )} + + {isPopupVisible && ( +
+
+
+ + + +
+
+

DELETE ROLE

+

{popupMessage}

+
+
+
+ )} +
+
+ ); +} + +export default TableUserRole; diff --git a/src/components/dashBoard/addProducts.tsx b/src/components/dashBoard/addProducts.tsx index b2a2206a..36fed32b 100644 --- a/src/components/dashBoard/addProducts.tsx +++ b/src/components/dashBoard/addProducts.tsx @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/label-has-associated-control */ import React, { useState, ChangeEvent, useEffect } from 'react'; import { Formik, diff --git a/src/components/home/ProductCard.tsx b/src/components/home/ProductCard.tsx index 0e7755b9..5afa3a60 100644 --- a/src/components/home/ProductCard.tsx +++ b/src/components/home/ProductCard.tsx @@ -1,18 +1,22 @@ import { useNavigate } from 'react-router-dom'; +import { useState } from 'react'; import { FaRegHeart, FaHeart } from 'react-icons/fa'; import { useAppDispatch, useAppSelector } from '@/app/hooks'; +import Cart from '@/interfaces/cart'; import { addToWishlist, removeFromWishlist, } from '@/features/Products/ProductSlice'; import { Product } from '@/types/Product'; -import { addCartItem } from '@/features/Cart/cartSlice'; +import { addCartItem, removeCartItem } from '@/features/Cart/cartSlice'; +import { showSuccessToast } from '@/utils/ToastConfig'; interface ProductCardProps { product: Product; } function ProductCard({ product }: ProductCardProps) { + const [cartId, setCartId] = useState(null); const navigate = useNavigate(); const dispatch = useAppDispatch(); const { token } = useAppSelector((state) => state.signIn); @@ -22,6 +26,26 @@ function ProductCard({ product }: ProductCardProps) { return wishlistProds?.some((wishlistProd) => wishlistProd.id === prod.id); }; + function handleAddtoCart(e: React.MouseEvent) { + const element = e.target as HTMLElement; + const [sibling, message, action] = element.classList.contains('bg-red-600') + ? [ + element.nextSibling, + 'Product Removed From Cart', + dispatch(removeCartItem(cartId as number)), + ] + : [ + element.previousSibling, + 'Product added to cart', + dispatch(addCartItem({ productId: product.id, quantity: 1 })), + ]; + (sibling as HTMLElement)?.style.setProperty('display', 'inline'); + element.style.setProperty('display', 'none'); + action.then((res) => { + setCartId((res.payload as Cart).id || null); + showSuccessToast(message); + }); + } return (
- {Array.from({ length: Math.floor(4 - product.averageRating) }).map( + {Array.from({ length: Math.floor(5 - product.averageRating) }).map( (_, index) => { return (
@@ -162,13 +194,25 @@ function ProductCard({ product }: ProductCardProps) { ${product.regularPrice}
-
category.id === focused) + ?.name || categories[0].name + } />
diff --git a/src/features/Cart/cartSlice.tsx b/src/features/Cart/cartSlice.tsx index a6837279..914986ed 100644 --- a/src/features/Cart/cartSlice.tsx +++ b/src/features/Cart/cartSlice.tsx @@ -2,12 +2,7 @@ import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'; import axios from 'axios'; import Cart from '@/interfaces/cart'; import { RootState } from '../../app/store'; -import { - showSuccessToast, - showErrorToast, - showInfoToast, -} from '@/utils/ToastConfig'; - +import { showErrorToast } from '@/utils/ToastConfig'; interface CartState { cartItems: Cart[]; @@ -40,7 +35,19 @@ export const fetchCartItems = createAsyncThunk( Authorization: `Bearer ${tokenFromStorage}`, }, }); - return response.data.cartItems; + const res = response.data.cartItems; + res.reduce((acc: Cart[], curr: Cart) => { + const existingItem = acc.find( + (item) => item.product.id === curr.product.id + ); + if (existingItem) { + existingItem.quantity += curr.quantity; + } else { + acc.push(curr); + } + return acc; + }, []); + return res; } ); @@ -76,7 +83,10 @@ export const removeCartItem = createAsyncThunk( export const addCartItem = createAsyncThunk( 'cart/addCartItem', - async ({ productId, quantity }: { productId: number; quantity: number }, { rejectWithValue }) => { + async ( + { productId, quantity }: { productId: number; quantity: number }, + { rejectWithValue } + ) => { try { const tokenFromStorage = localStorage.getItem('token') || ''; const response = await axios.post( @@ -88,7 +98,6 @@ export const addCartItem = createAsyncThunk( }, } ); - showSuccessToast(response.data.cartItem.product.name + ' added to cart'); return response.data.cartItem; } catch (error) { showErrorToast('Failed to add cart item'); diff --git a/src/features/Checkout/checkoutSlice.ts b/src/features/Checkout/checkoutSlice.ts index 2aecf29b..a1791ee6 100644 --- a/src/features/Checkout/checkoutSlice.ts +++ b/src/features/Checkout/checkoutSlice.ts @@ -13,8 +13,8 @@ export interface CheckoutState { } const initialOrder: Order = { - id: 31, - totalAmount: 160, + id: -1, + totalAmount: 0, status: 'Pending', couponCode: '', deliveryInfo: { @@ -42,7 +42,6 @@ interface MomoPaymentParams { orderId: number; } - const initialState: CheckoutState = { checkout: initialOrder, loading: false, @@ -87,22 +86,21 @@ export const makeMomoPayment = createAsyncThunk( }, } ); - showSuccessToast(response.data.message); + showSuccessToast('Transaction successful'); + return response.data; } catch (error) { if (axios.isAxiosError(error)) { - // const errorMessage = error.response?.data?.message || 'Payment failed'; - // showErrorToast(errorMessage); + const errorMessage = error.response?.data?.message || 'Payment failed'; + showErrorToast(errorMessage); return rejectWithValue(error.response?.data || 'Payment failed'); } - console.error('Unexpected error:', error); showErrorToast('Payment failed'); return rejectWithValue('Payment failed'); } } ); - export const getOrders = createAsyncThunk('order/get', async () => { const tokenFromStorage = localStorage.getItem('token') || ''; const response = await axios.get(`${baseUrl}/checkout/getall-order`, { @@ -165,6 +163,9 @@ const checkoutSlice = createSlice({ updateLastName: (state, action: PayloadAction) => { state.checkout.lastName = action.payload; }, + resetState: () => { + return initialState; + }, }, extraReducers: (builder) => { builder @@ -214,6 +215,7 @@ export const { updateFirstName, updateLastName, updateStatus, + resetState, } = checkoutSlice.actions; export const selectCheckout = (state: RootState) => state.checkout; diff --git a/src/features/Coupons/CouponsFeature.ts b/src/features/Coupons/CouponsFeature.ts new file mode 100644 index 00000000..d72a7d2f --- /dev/null +++ b/src/features/Coupons/CouponsFeature.ts @@ -0,0 +1,191 @@ +import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'; +import axios from 'axios'; +import { showSuccessToast } from '@/utils/ToastConfig'; +import Product from '@/interfaces/product'; + +interface Coupon { + id: number; + code: string; + description: string; + percentage: number; + expirationDate: string; + status: string; + applicableProducts: Product[]; + vendor: { + id: number; + firstName: string; + lastName: string; + }; +} + +interface CouponsState { + coupons: Coupon[]; + loading: boolean; + error: string | null; +} + +const initialState: CouponsState = { + coupons: [], + loading: false, + error: null, +}; + +export const fetchCoupons = createAsyncThunk( + 'coupons/fetchCoupons', + async () => { + const response = await axios.get( + `${import.meta.env.VITE_BASE_URL}/coupons` + ); + return response.data; + } +); +export const fetchMyCoupons = createAsyncThunk( + 'coupons/fetchMyCoupons', + async () => { + const token = localStorage.getItem('token'); + const response = await axios.get( + `${import.meta.env.VITE_BASE_URL}/coupons/mine`, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ); + return response.data; + } +); + +interface NewCoupon { + description: string; + percentage: number; + expirationDate: string; + applicableProducts: number[]; +} +interface UpdatedCoupon { + id: number; + description: string; + percentage: number; + expirationDate: string; + applicableProducts: number[]; +} + +export const createCoupon = createAsyncThunk( + 'coupons/createCoupon', + async ({ newCoupon, token }: { newCoupon: NewCoupon; token: string }) => { + const response = await axios.post( + `${import.meta.env.VITE_BASE_URL}/coupons`, + newCoupon, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ); + return response.data; + } +); + +export const updateCoupon = createAsyncThunk( + 'coupons/updateCoupon', + async (updatedCoupon: UpdatedCoupon) => { + const token = localStorage.getItem('token'); + const response = await axios.put( + `${import.meta.env.VITE_BASE_URL}/coupons/${updatedCoupon.id}`, + updatedCoupon, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ); + return response.data; + } +); + +export const deleteCoupon = createAsyncThunk( + 'coupons/deleteCoupon', + async ({ couponId, token }: { couponId: number; token: string }) => { + const response = await axios.delete( + `${import.meta.env.VITE_BASE_URL}/coupons/${couponId}`, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ); + return response.data; + } +); + +const couponsSlice = createSlice({ + name: 'coupons', + initialState, + reducers: {}, + extraReducers: (builder) => { + builder + .addCase(fetchCoupons.pending, (state) => { + state.loading = true; + }) + .addCase(fetchCoupons.fulfilled, (state, action) => { + state.loading = false; + state.coupons = action.payload; + state.error = null; + }) + .addCase(fetchCoupons.rejected, (state, action) => { + state.loading = false; + state.error = action.error.message || 'Failed to fetch coupons'; + }) + .addCase(fetchMyCoupons.pending, (state) => { + state.loading = true; + }) + .addCase(fetchMyCoupons.fulfilled, (state, action) => { + state.loading = false; + state.coupons = action.payload; + state.error = null; + }) + .addCase(fetchMyCoupons.rejected, (state, action) => { + state.loading = false; + state.error = action.error.message || 'Failed to fetch coupons'; + }) + .addCase(createCoupon.pending, (state) => { + state.loading = true; + }) + .addCase(createCoupon.fulfilled, (state, action) => { + state.loading = false; + state.coupons.push(action.payload); + showSuccessToast(action.payload.message); + }) + .addCase(createCoupon.rejected, (state, action) => { + state.loading = false; + state.error = action.error.message || 'Failed to create coupon'; + }) + .addCase(updateCoupon.pending, (state) => { + state.loading = true; + }) + .addCase(updateCoupon.fulfilled, (state, action) => { + const index = state.coupons.findIndex( + (coupon) => coupon.id === action.payload.id + ); + if (index !== -1) { + state.coupons[index] = action.payload; + } + showSuccessToast('Coupon updated successfully'); + }) + .addCase(updateCoupon.rejected, (state, action) => { + state.error = action.error.message || 'Failed to update coupon'; + }) + .addCase(deleteCoupon.fulfilled, (state, action) => { + state.coupons = state.coupons.filter( + (coupon) => coupon.id !== action.payload + ); + showSuccessToast(action.payload.message); + }) + .addCase(deleteCoupon.rejected, (state, action) => { + state.error = action.error.message || 'Failed to delete coupon'; + }); + }, +}); + +export const selectCoupons = (state: { coupons: CouponsState }) => + state.coupons; +export default couponsSlice.reducer; diff --git a/src/features/SaleByCountry/SaleByCountrySlice.ts b/src/features/SaleByCountry/SaleByCountrySlice.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/features/userRole/userRoleSlice.tsx b/src/features/userRole/userRoleSlice.tsx new file mode 100644 index 00000000..38951cab --- /dev/null +++ b/src/features/userRole/userRoleSlice.tsx @@ -0,0 +1,132 @@ +import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'; +import axios from 'axios'; + +interface UserRole { + id: number; + name: string; + permissions: string[]; +} + +interface UserRoleState { + roles: UserRole[]; + status: 'idle' | 'loading' | 'succeeded' | 'failed'; + error: string | null; +} + +const initialState: UserRoleState = { + roles: [], + status: 'idle', + error: null, +}; + +export const fetchUserRoles = createAsyncThunk( + 'userRoles/fetchUserRoles', + async () => { + const response = await axios.get( + `${import.meta.env.VITE_BASE_URL}/roles/get_roles` + ); + return response.data.roles; + } +); + +export const deleteUserRole = createAsyncThunk( + 'userRoles/deleteUserRole', + async (id: number) => { + try { + await axios.delete( + `${import.meta.env.VITE_BASE_URL}/roles/delete_role/${id}` + ); + return id; + } catch (error) { + throw new Error('Failed to delete role'); + } + } +); + +export const createUserRole = createAsyncThunk( + 'userRoles/createUserRole', + async (roleData: { name: string; permissions: string[] }) => { + const response = await axios.post( + `${import.meta.env.VITE_BASE_URL}/roles/create_role`, + roleData + ); + return response.data.role; + } +); + +export const updateUserRole = createAsyncThunk( + 'userRoles/updateUserRole', + async (roleData: { id: number; name: string; permissions: string[] }) => { + const response = await axios.put( + 'https://dynamites-ecomm-be.onrender.com/api/v1/roles/update_role', + roleData + ); + return response.data; + } +); + +const userRoleSlice = createSlice({ + name: 'userRoles', + initialState, + reducers: {}, + extraReducers: (builder) => { + builder + .addCase(fetchUserRoles.pending, (state) => { + state.status = 'loading'; + }) + .addCase( + fetchUserRoles.fulfilled, + (state, action: PayloadAction) => { + state.status = 'succeeded'; + state.roles = action.payload; + } + ) + .addCase(fetchUserRoles.rejected, (state, action) => { + state.status = 'failed'; + state.error = action.error.message || 'Failed to fetch roles'; + }) + .addCase( + deleteUserRole.fulfilled, + (state, action: PayloadAction) => { + state.roles = state.roles.filter( + (role) => role.id !== action.payload + ); + } + ) + .addCase(createUserRole.pending, (state) => { + state.status = 'loading'; + }) + .addCase( + createUserRole.fulfilled, + (state, action: PayloadAction) => { + state.roles.push(action.payload); + } + ) + .addCase(deleteUserRole.pending, (state) => { + state.status = 'loading'; + }) + .addCase(deleteUserRole.rejected, (state, action) => { + state.status = 'failed'; + state.error = action.error.message || 'Failed to delete role'; + }) + .addCase(updateUserRole.pending, (state) => { + state.status = 'loading'; + }) + + .addCase(updateUserRole.fulfilled, (state, action) => { + const index = state.roles.findIndex( + (role) => role.id === action.payload.id + ); + if (index !== -1) { + state.roles[index] = action.payload; // Update the existing role + } + state.status = 'succeeded'; + }) + .addCase(updateUserRole.rejected, (state, action) => { + state.status = 'failed'; + state.error = action.error.message || 'Failed to update role'; // Set error message + }); + }, +}); + +export default userRoleSlice.reducer; diff --git a/src/layout/DashbordLayout.tsx b/src/layout/DashbordLayout.tsx index acc72875..3d87ada9 100644 --- a/src/layout/DashbordLayout.tsx +++ b/src/layout/DashbordLayout.tsx @@ -1,5 +1,4 @@ import { Outlet } from 'react-router-dom'; -// import { ToastContainer } from 'react-toastify'; import DashboardSideNav from '@/components/dashBoard/DashboardSideNav'; import Navbar from '@/components/dashBoard/dashBoardNav'; diff --git a/src/pages/AddCoupon.tsx b/src/pages/AddCoupon.tsx new file mode 100644 index 00000000..39229066 --- /dev/null +++ b/src/pages/AddCoupon.tsx @@ -0,0 +1,287 @@ +import { useEffect, useState } from 'react'; +import axios from 'axios'; +import * as Yup from 'yup'; +import { Formik, Field, Form, FieldArray, ErrorMessage } from 'formik'; +import BeatLoader from 'react-spinners/BeatLoader'; +import { IoIosCloseCircle } from 'react-icons/io'; +import { useNavigate } from 'react-router-dom'; +import { useAppSelector, useAppDispatch } from '@/app/hooks'; +import { createCoupon } from '@/features/Coupons/CouponsFeature'; +import { RootState } from '@/app/store'; +import { showErrorToast } from '@/utils/ToastConfig'; +import Product from '@/interfaces/product'; + +interface CouponFormData { + description: string; + percentage: number; + expirationDate: string; + applicableProducts: Product[]; +} + +function CouponForm() { + const [products, setProducts] = useState([]); + const token = useAppSelector((state: RootState) => state.signIn.token)!; + const dispatch = useAppDispatch(); + const { loading } = useAppSelector((state) => state.coupons); + const navigate = useNavigate(); + + useEffect(() => { + axios + .get(`${import.meta.env.VITE_BASE_URL}/product/mine`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((response) => { + setProducts(response.data.data); + }) + .catch((err) => { + showErrorToast(err.message); + }); + }, [token]); + + const handleSubmit = ( + values: CouponFormData, + { resetForm }: { resetForm: () => void } + ) => { + const newCoupon = { + description: values.description, + percentage: values.percentage, + expirationDate: values.expirationDate, + applicableProducts: values.applicableProducts.map( + (product) => product.id + ), + }; + + dispatch(createCoupon({ newCoupon, token })) + .unwrap() + .then(() => { + resetForm(); + navigate('/dashboard/coupons'); + }) + .catch((err) => { + showErrorToast(err.message); + }); + }; + + return ( +
+
+

Create New Coupon

+ + {({ values, setFieldValue, errors, touched }) => ( +
+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + {({ push }) => ( + <> + + + + )} + +
+
+
+
+ {values.applicableProducts.map((product) => ( +
+
+ {product.name} +
+

{product.name}

+

+ ${product.salesPrice} +

+
+
+
+ +
+
+ ))} +
+
+
+
+ +
+
+ )} +
+
+
+ ); +} + +export default CouponForm; diff --git a/src/pages/Coupons.tsx b/src/pages/Coupons.tsx new file mode 100644 index 00000000..2842afa1 --- /dev/null +++ b/src/pages/Coupons.tsx @@ -0,0 +1,353 @@ +import React, { useEffect, useState } from 'react'; +import { Link } from 'react-router-dom'; +import { FaRegTrashAlt } from 'react-icons/fa'; +import { MdOutlineEdit } from 'react-icons/md'; +import { IoIosArrowDown, IoIosSearch } from 'react-icons/io'; +import PuffLoader from 'react-spinners/PuffLoader'; +import { useDispatch, useSelector } from 'react-redux'; +import { AppDispatch, RootState } from '@/app/store'; +import { + fetchCoupons, + deleteCoupon, + selectCoupons, + fetchMyCoupons, +} from '@/features/Coupons/CouponsFeature'; + +import CircularPagination from '@/components/dashBoard/NavigateonPage'; +import { useAppSelector } from '@/app/hooks'; +import { showErrorToast } from '@/utils/ToastConfig'; +import Button from '@/components/form/Button'; + +function Coupons() { + const [currentPage, setCurrentPage] = useState(1); + const [searchTerm, setSearchTerm] = useState(''); + const [expandedRows, setExpandedRows] = useState([]); + const [deleteModal, setDeleteModal] = useState(false); + const [selectedCouponId, setSelectedCouponId] = useState(null); + const token = useAppSelector((state: RootState) => state.signIn.token)!; + const Role = useAppSelector((state) => state.signIn.user?.userType.name); + const User = useAppSelector((state) => state.signIn.user?.lastName); + + const dispatch: AppDispatch = useDispatch(); + const { coupons, loading, error } = useSelector(selectCoupons); + + useEffect(() => { + if (Role === 'Admin') { + dispatch(fetchCoupons()); + } else { + dispatch(fetchMyCoupons()); + } + }, [dispatch, Role]); + + const toggleRow = (id: number) => { + setExpandedRows((prev: any) => + prev.includes(id) + ? prev.filter((rowId: number) => rowId !== id) + : [...prev, id] + ); + }; + + const showDeleteModal = (couponId: number) => { + setSelectedCouponId(couponId); + setDeleteModal(true); + }; + + const handleConfirmDelete = () => { + if (selectedCouponId !== null) { + dispatch(deleteCoupon({ couponId: selectedCouponId, token })) + .unwrap() + .then(() => { + setDeleteModal(false); + setSelectedCouponId(null); + dispatch(fetchCoupons()); + }) + .catch((Anerror) => { + showErrorToast(Anerror || 'Failed to delete the coupon:'); + }); + } + }; + + const handleCancelDelete = () => { + setDeleteModal(false); + setSelectedCouponId(null); + }; + + const getStatus = (expirationDate: string) => { + const currentDate = new Date(); + const expiration = new Date(expirationDate); + return expiration >= currentDate ? 'Active' : 'Expired'; + }; + + // ********* Pagination ********** + const COUPONS_PER_PAGE = 8; + const totalPages = Math.ceil(coupons.length / COUPONS_PER_PAGE); + const startIndex = (currentPage - 1) * COUPONS_PER_PAGE; + + const paginatedData = coupons + .filter( + (coupon) => + coupon.description.toLowerCase().includes(searchTerm.toLowerCase()) || + coupon.code.toLowerCase().includes(searchTerm.toLowerCase()) + ) + .slice(startIndex, startIndex + COUPONS_PER_PAGE); + + const handlePageChange = (page: number) => { + setCurrentPage(page); + }; + + return ( +
+
+

Coupons

+
+
+
    +
  • + + ({coupons.length}) +
  • + | +
  • + + ( + { + coupons.filter( + (coupon) => getStatus(coupon.expirationDate) === 'Active' + ).length + } + ) +
  • + | +
  • + + ( + { + coupons.filter( + (coupon) => getStatus(coupon.expirationDate) === 'Expired' + ).length + } + ) +
  • +
+
+ + setSearchTerm(e.target.value)} + className="w-full outline-none bg-white placeholder:text-gray-400 font-light" + /> +
+
+ {/* Table */} + {deleteModal && ( +
+
+
+ Are you sure you want to Delete? +
+

This coupons

+
+
+
+
+
+
+ )} + {loading ? ( +
+ +
+ ) : error ? ( + <>{showErrorToast(error)} + ) : ( +
+ + + + + + + + + + + + + + + {paginatedData.map((coupon) => ( + + + + + + + + + + + {Role === 'Vendor' ? ( +
+
+ + + ) : ( +

+ Contact Own{' '} +

+ )} + + {expandedRows.includes(coupon.id) && ( + + + + )} + + ))} + +
+ Code + + Description + + Percentage(%) + + Expiration Date + + Status + + A/P + + Seller + + Action +
+ toggleRow(coupon.id)} + /> + {coupon.code}{coupon.description}{coupon.percentage}%{coupon.expirationDate} + + {getStatus(coupon.expirationDate)} + + + {coupon.applicableProducts.length} + + {coupon.vendor?.firstName || User} + + + + + + showDeleteModal(coupon.id)} + /> +
+
+

+ Applicable Products +

+
+ {coupon.applicableProducts.length > 0 && + coupon.applicableProducts.map((product) => ( +
+
+ {product.name} +
+
+

{product.name}

+

+ {' '} + + Quantity: + {' '} + {product.quantity} +

+

+ + Prices: + {' '} + + {' '} + $ + {product.salesPrice === 0 + ? product.regularPrice + : product.salesPrice} + +

+
+
+ ))} +
+
+
+
+ +
+
+ )} +
+ ); +} + +export default Coupons; diff --git a/src/pages/EditCoupon.tsx b/src/pages/EditCoupon.tsx new file mode 100644 index 00000000..a1fdd75f --- /dev/null +++ b/src/pages/EditCoupon.tsx @@ -0,0 +1,320 @@ +import { useEffect, useState } from 'react'; +import axios from 'axios'; +import { useParams, useNavigate } from 'react-router-dom'; +import * as Yup from 'yup'; +import { Formik, Field, Form, FieldArray, ErrorMessage } from 'formik'; +import BeatLoader from 'react-spinners/BeatLoader'; +import { IoIosCloseCircle } from 'react-icons/io'; +import PuffLoader from 'react-spinners/PuffLoader'; +import { useAppSelector, useAppDispatch } from '@/app/hooks'; +import { updateCoupon } from '@/features/Coupons/CouponsFeature'; +import { RootState } from '@/app/store'; +import { showErrorToast } from '@/utils/ToastConfig'; +import Product from '@/interfaces/product'; + +interface CouponFormData { + description: string; + percentage: number; + expirationDate: string; + applicableProducts: Product[]; +} + +function EditCoupon() { + const [products, setProducts] = useState([]); + const [initialValues, setInitialValues] = useState( + null + ); + const token = useAppSelector((state: RootState) => state.signIn.token)!; + const dispatch = useAppDispatch(); + const { loading } = useAppSelector((state) => state.coupons); + const { id } = useParams<{ id: string }>(); + const navigate = useNavigate(); + + useEffect(() => { + axios + .get(`${import.meta.env.VITE_BASE_URL}/product/mine`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((response) => { + setProducts(response.data.data); + }) + .catch((err) => { + showErrorToast(err.message); + }); + + axios + .get(`${import.meta.env.VITE_BASE_URL}/coupons/${id}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((response) => { + const coupon = response.data; + setInitialValues({ + description: coupon.description, + percentage: coupon.percentage, + expirationDate: coupon.expirationDate, + applicableProducts: coupon.applicableProducts, + }); + }) + .catch((err) => { + showErrorToast(err.message); + }); + }, [token, id]); + + const handleSubmit = ( + values: CouponFormData, + { resetForm }: { resetForm: () => void } + ) => { + const updatedCoupon = { + id: parseInt(id!, 10), + description: values.description, + percentage: values.percentage, + expirationDate: values.expirationDate, + applicableProducts: values.applicableProducts.map( + (product) => product.id + ), + }; + + dispatch(updateCoupon(updatedCoupon)) + .unwrap() + .then(() => { + resetForm(); + navigate('/dashboard/coupons'); + }) + .catch((err) => { + showErrorToast(err.message); + }); + }; + + if (!initialValues) { + return ( +
+ +
+ ); + } + + return ( +
+
+

Edit Coupon

+ + {({ values, setFieldValue, errors, touched }) => ( +
+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + {({ push }) => ( + <> + + + + )} + +
+
+
+
+ {values.applicableProducts.map((product) => ( +
+
+ {product.name} +
+

{product.name}

+

+ ${product.salesPrice} +

+
+
+
+ +
+
+ ))} +
+
+
+
+ +
+
+ )} +
+
+
+ ); +} + +export default EditCoupon; diff --git a/src/pages/ProductDetails.tsx b/src/pages/ProductDetails.tsx index aed5e19a..37d2583e 100644 --- a/src/pages/ProductDetails.tsx +++ b/src/pages/ProductDetails.tsx @@ -6,6 +6,8 @@ import ClipLoader from 'react-spinners/ClipLoader'; import { IoClose } from 'react-icons/io5'; import { useAppDispatch, useAppSelector } from '@/app/hooks'; import Button from '@/components/form/Button'; +import { addCartItem, removeCartItem } from '@/features/Cart/cartSlice'; +import Cart from '@/interfaces/cart'; import { addToWishlist, fetchProductDetails, @@ -161,6 +163,7 @@ function ProductDetails() { const [toggleLoginOverlay, setToggleLoginOverlay] = useState(false); const [isVisible, setIsVisible] = useState({ state: true, name: 'details' }); const [activeImg, setActiveImg] = useState(''); + const [cartId, setCartId] = useState(null); const wishlistProducts = useAppSelector( (state) => state.products.wishlistProducts ); @@ -233,6 +236,25 @@ function ProductDetails() { showErrorToast((errorObj.response.data as { message: string }).message); } }; + function handleAddtoCart(e: React.MouseEvent) { + const element = e.target as HTMLElement; + const [, message, action] = + element.textContent === 'Remove from Cart' + ? [ + (element.textContent = 'Add to Cart'), + 'Product Removed From Cart', + dispatch(removeCartItem(cartId as number)), + ] + : [ + (element.textContent = 'Remove from Cart'), + 'Product added to cart', + dispatch(addCartItem({ productId: product!.id, quantity: 1 })), + ]; + action.then((res) => { + setCartId((res.payload as Cart).id || null); + showSuccessToast(message); + }); + } return (
@@ -343,45 +365,47 @@ function ProductDetails() { ); })}
- - - - - - - - - + {product.averageRating % 1 !== 0 && ( + + + + + + + + + + )}
{Array.from({ - length: Math.floor(4 - product.averageRating), + length: Math.floor(5 - product.averageRating), }).map((_, index) => { return (
@@ -436,6 +460,7 @@ function ProductDetails() {
+
+
+ )} + + {activate && ( +
+
+
+ Are you sure you want to activate? +
+ {clickedcustomer?.firstName} +
+
+
+
+
+
+ )} + +
+
+
Customers
+
+
+
+

All ({customers.length})

+

+ Approved ({customers.filter((v) => v.status === 'active').length}) +

+

+ Suspended ( + {customers.filter((v) => v.status === 'inactive').length}) +

+
+
+ + HandleSearch(e.target.value)} + /> +
+
+
+
+ {status === 'loading' && ( +
+ +
+ )} +
+
+
+
+
Image
+
+ First Name +
+
+ Last Name +
+
Email
+
Date
+
Status
+
Role
+
Action
+
+ {customers.length > 0 ? ( + visiblePage.map((v, id) => ( +
+
+ +
+
+ {v.firstName} +
+
+ {v.lastName} +
+
+ {v.email} +
+
+ {DateFormat(v.updatedAt)} +
+
+ + {v.status} + +
+
+ Buyer +
+ handleRole(v)} + /> +
+
+
+ + + +
+
+ )) + ) : ( +
No customer Found
+ )} +
+ + {pages && + pages.map((page) => ( + + ))} + +
+
+
+ +
+ {customers && + visiblePage.map((v, id) => ( +
+
+ +
+

+ {v.firstName} {v.lastName} +

+

{v.email}

+
+
+
+

First Name: {v.firstName}

+

Date: {DateFormat(v.updatedAt)}

+

+ Status: + + {v.status} + +

+
+
+ + + +
+
+ ))} +
+ +
+
+ +
+
+ + {/* -------------------------------------------------------- */} + {updateRole && ( +
+
+
+
+

Change Role

+
+
Current Details:
+
+

Name:

+

+ {clickedcustomer?.firstName} {clickedcustomer?.lastName} +

+
+
+

Email:

+

{clickedcustomer?.email}

+
+
+

Status:

+ + {clickedcustomer?.status} + +
+
+

Current Role:

+ + Buyer + +
+
+
+
+ Make change: +
+
+
Select Role
+
+ +
+
+
+
+ +
+ +
+
+ +
+ + +
+
+
+ )} + {/* -------------------------------------------------------- */} +
+ ); +} + +export default Customer; diff --git a/src/routes/AppRoutes.tsx b/src/routes/AppRoutes.tsx index 4c6dc335..bb9c1d16 100644 --- a/src/routes/AppRoutes.tsx +++ b/src/routes/AppRoutes.tsx @@ -23,7 +23,11 @@ import Cart from '@/components/Cart/Cart'; import Seller from '@/pages/Seller'; import CheckoutPage from '@/pages/Checkout'; import Aboutus from '@/components/home/Aboutus'; -import OrderCompletion from '@/pages/OrderCompletion'; +import AddCoupon from '@/pages/AddCoupon'; +import Coupons from '@/pages/Coupons'; +import EditCoupon from '@/pages/EditCoupon'; +import TableUserRole from '@/components/dashBoard/UserRole'; +import Customer from '@/pages/customer'; function AppRoutes() { return ( @@ -45,7 +49,6 @@ function AppRoutes() { } /> } /> } /> - } /> } /> } /> @@ -64,6 +67,7 @@ function AppRoutes() { } /> } /> } /> + } /> } /> } /> + } /> + } /> + } /> + } /> } /> } /> diff --git a/src/services/apiService b/src/services/apiService deleted file mode 100644 index e69de29b..00000000 diff --git a/vite.config.ts b/vite.config.ts index 03ea1849..f0b392ee 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -28,6 +28,13 @@ export default defineConfig({ 'src/main.tsx', 'src/components/dashBoard/Admin.tsx', 'src/components/dashBoard/Table.tsx', + 'src/pages/AddCoupon.tsx', + 'src/pages/Coupons.tsx', + 'src/pages/EditCoupon.tsx', + 'src/pages/customer.tsx', + 'src/components/Cart/Cart.tsx', + 'src/components/Checkout/Checkout.tsx', + 'src/features/Checkout/checkoutSlice.ts' ], }, },