diff --git a/.eslintrc.cjs b/.eslintrc.cjs index ea1313b..038aa9f 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -10,9 +10,6 @@ module.exports = { parser: '@typescript-eslint/parser', plugins: ['react-refresh'], rules: { - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], + 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], }, }; diff --git a/.mocharc.cjs b/.mocharc.cjs deleted file mode 100644 index ae6622f..0000000 --- a/.mocharc.cjs +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - require: ['@ts-tools/node/r'], - 'enable-source-maps': true, - color: true, -}; diff --git a/.mocharc.json b/.mocharc.json new file mode 100644 index 0000000..ee6c956 --- /dev/null +++ b/.mocharc.json @@ -0,0 +1,5 @@ +{ + "extensions": ["ts"], + "it": ["**/*.test.*"], + "node-option": ["experimental-specifier-resolution=node", "loader=ts-node/esm"] +} diff --git a/.prettierrc b/.prettierrc index 363b934..3682992 100644 --- a/.prettierrc +++ b/.prettierrc @@ -3,5 +3,6 @@ "tabWidth": 3, "semi": true, "singleQuote": true, - "bracketSameLine": true + "bracketSameLine": true, + "printWidth": 100 } diff --git a/package-lock.json b/package-lock.json index 54542a9..5e05c9f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,17 +8,12 @@ "name": "ecommerce", "version": "0.0.0", "dependencies": { - "@fortawesome/fontawesome-free": "^6.5.1", - "@fortawesome/fontawesome-svg-core": "^6.5.1", - "@fortawesome/free-solid-svg-icons": "^6.5.1", - "@fortawesome/react-fontawesome": "^0.2.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-icons": "^4.12.0", "react-router-dom": "^6.18.0" }, "devDependencies": { - "@ts-tools/node": "^5.0.2", "@types/chai": "^4.3.11", "@types/mocha": "^10.0.6", "@types/react": "^18.2.15", @@ -33,8 +28,10 @@ "eslint-plugin-react-refresh": "^0.4.3", "mocha": "^10.2.0", "playwright": "^1.40.1", + "playwright-chromium": "^1.40.1", "prettier": "3.1.0", "stylelint-config-standard": "^34.0.0", + "ts-node": "^10.9.2", "typescript": "^5.0.2", "vite": "^4.4.5" } @@ -406,6 +403,28 @@ "node": ">=6.9.0" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@csstools/css-parser-algorithms": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.3.2.tgz", @@ -583,60 +602,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@fortawesome/fontawesome-common-types": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.1.tgz", - "integrity": "sha512-GkWzv+L6d2bI5f/Vk6ikJ9xtl7dfXtoRu3YGE6nq0p/FFqA1ebMOAWg3XgRyb0I6LYyYkiAo+3/KrwuBp8xG7A==", - "hasInstallScript": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/fontawesome-free": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.1.tgz", - "integrity": "sha512-CNy5vSwN3fsUStPRLX7fUYojyuzoEMSXPl7zSLJ8TgtRfjv24LOnOWKT2zYwaHZCJGkdyRnTmstR0P+Ah503Gw==", - "hasInstallScript": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.1.tgz", - "integrity": "sha512-MfRCYlQPXoLlpem+egxjfkEuP9UQswTrlCOsknus/NcMoblTH2g0jPrapbcIb04KGA7E2GZxbAccGZfWoYgsrQ==", - "hasInstallScript": true, - "dependencies": { - "@fortawesome/fontawesome-common-types": "6.5.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/free-solid-svg-icons": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.1.tgz", - "integrity": "sha512-S1PPfU3mIJa59biTtXJz1oI0+KAXW6bkAb31XKhxdxtuXDiUIFsih4JR1v5BbxY7hVHsD1RKq+jRkVRaf773NQ==", - "hasInstallScript": true, - "dependencies": { - "@fortawesome/fontawesome-common-types": "6.5.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/react-fontawesome": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", - "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", - "dependencies": { - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "@fortawesome/fontawesome-svg-core": "~1 || ~6", - "react": ">=16.3" - } - }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.13", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", @@ -761,33 +726,29 @@ "node": ">=14.0.0" } }, - "node_modules/@ts-tools/node": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@ts-tools/node/-/node-5.0.2.tgz", - "integrity": "sha512-sYRQr7H9kwJDdHs+llp6csi3CgiBJSJrffRuPdsfL0fUD9hZWQWFn6tOyS6a5W6X/WwuLf1/t4nZDsxEik7UMA==", - "dev": true, - "dependencies": { - "@ts-tools/transpile": "^5.0.2", - "source-map-support": "^0.5.21" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=2.8.0" - } + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true }, - "node_modules/@ts-tools/transpile": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@ts-tools/transpile/-/transpile-5.0.2.tgz", - "integrity": "sha512-Uc05dB9324pTud/PeGZU2rs8o0/qMGC6PegWhwRoNAysdJe+x0da2Iot/AmcJq5SP8xTRhfhcjhaqzu6LETyPw==", - "dev": true, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=2.8.0" - } + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true }, "node_modules/@types/babel__core": { "version": "7.20.4", @@ -855,6 +816,16 @@ "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", "dev": true }, + "node_modules/@types/node": { + "version": "20.11.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.2.tgz", + "integrity": "sha512-cZShBaVa+UO1LjWWBPmWRR4+/eY/JR/UIEcDlVsw3okjWEu+rB7/mH6X3B/L+qJVHDLjk9QW/y2upp9wp1yDXA==", + "dev": true, + "peer": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, "node_modules/@types/normalize-package-data": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", @@ -1154,6 +1125,15 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -1213,6 +1193,12 @@ "node": ">= 8" } }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1332,12 +1318,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1561,6 +1541,12 @@ } } }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2916,6 +2902,12 @@ "yallist": "^3.0.2" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "node_modules/map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", @@ -3263,14 +3255,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3439,6 +3423,22 @@ "fsevents": "2.3.2" } }, + "node_modules/playwright-chromium": { + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/playwright-chromium/-/playwright-chromium-1.40.1.tgz", + "integrity": "sha512-3atylP47OCTBW0siGI7LOEG/XKL/vnrFH8xdr4uaTnqMsc0Xq4gOLk2gGwniPJ76LSc++9ASc0w/nfqtLAmm3A==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "playwright-core": "1.40.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/playwright-core": { "version": "1.40.1", "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.1.tgz", @@ -3562,16 +3562,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3654,11 +3644,6 @@ "react": "*" } }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, "node_modules/react-refresh": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", @@ -4049,15 +4034,6 @@ "dev": true, "peer": true }, - "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/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -4067,16 +4043,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -4439,6 +4405,58 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4476,6 +4494,13 @@ "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "peer": true + }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", @@ -4522,6 +4547,12 @@ "dev": true, "peer": true }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -4757,6 +4788,15 @@ "node": ">=8" } }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index caacdb1..91ac058 100644 --- a/package.json +++ b/package.json @@ -10,20 +10,15 @@ "preview": "vite preview", "format": "prettier --write .", "pretest": "tsc --noEmit && npm run lint", - "test": "mocha ֿ\"src/test/*.test.ts\"" + "test": "mocha src/test/*.test.ts" }, "dependencies": { - "@fortawesome/fontawesome-free": "^6.5.1", - "@fortawesome/fontawesome-svg-core": "^6.5.1", - "@fortawesome/free-solid-svg-icons": "^6.5.1", - "@fortawesome/react-fontawesome": "^0.2.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-icons": "^4.12.0", "react-router-dom": "^6.18.0" }, "devDependencies": { - "@ts-tools/node": "^5.0.2", "@types/chai": "^4.3.11", "@types/mocha": "^10.0.6", "@types/react": "^18.2.15", @@ -38,8 +33,10 @@ "eslint-plugin-react-refresh": "^0.4.3", "mocha": "^10.2.0", "playwright": "^1.40.1", + "playwright-chromium": "^1.40.1", "prettier": "3.1.0", "stylelint-config-standard": "^34.0.0", + "ts-node": "^10.9.2", "typescript": "^5.0.2", "vite": "^4.4.5" } diff --git a/src/App.tsx b/src/App.tsx index a6bff96..9e16916 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { BrowserRouter, Route, Routes } from 'react-router-dom'; import styles from './app.module.css'; import { BagModal } from './components/bagModal/bagModal'; import { Header } from './components/header'; @@ -9,11 +9,10 @@ import { Pants } from './pages/pants'; import { Shirts } from './pages/shirts'; import { Blur } from './components/blur/blur'; - export const App = () => { return ( - -
+ +
@@ -27,6 +26,6 @@ export const App = () => {
-
+ ); }; diff --git a/src/CartContext.tsx b/src/CartContext.tsx index 9c744ed..d034e5c 100644 --- a/src/CartContext.tsx +++ b/src/CartContext.tsx @@ -1,22 +1,11 @@ import React, { createContext, useState } from 'react'; -import { - CartContextProps, - CartItem, - Item, - Sizes, -} from './components/datatypes'; +import { CartContextProps, CartItem, Item, Sizes } from './components/datatypes'; import { generateCartItemId } from './utility'; -export const CartContext = createContext( - undefined -); +export const CartContext = createContext(undefined); -export const CartProvider: React.FC<{ children: React.ReactNode }> = ({ - children, -}) => { - const [cartItems, setCartItems] = useState>( - new Map() - ); +export const CartProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [cartItems, setCartItems] = useState>(new Map()); const [showModal, setShowModal] = useState(false); const [totalPrice, setTotalPrice] = useState(0); const [numOfItems, setNumOfItems] = useState(0); @@ -28,10 +17,7 @@ export const CartProvider: React.FC<{ children: React.ReactNode }> = ({ const generatedId = generateCartItemId(item.id, item.size); const quantity = prevCartItems.get(generatedId) ?? 0; - return new Map(prevCartItems).set( - generatedId, - quantity + 1 - ); + return new Map(prevCartItems).set(generatedId, quantity + 1); }); }; @@ -55,9 +41,10 @@ export const CartProvider: React.FC<{ children: React.ReactNode }> = ({ const oldItemPrice: number = oldNumOfItems * parseFloat(item.price); const newItemPrice: number = parseFloat(item.price) * quantity; - // Update the quantity for the specific item and size + // Update the quantity for the specific item and sizeß newCartItems.set(generatedId, quantity); setCartItems(newCartItems); + setNumOfItems((prevNumOfItems: number) => prevNumOfItems - oldNumOfItems + quantity); setTotalPrice((prevPrice) => prevPrice - oldItemPrice + newItemPrice); }; diff --git a/src/_codux/boards/bag-item/bag-item.board.tsx b/src/_codux/boards/bag-item/bag-item.board.tsx index 3a77920..8d2ffa6 100644 --- a/src/_codux/boards/bag-item/bag-item.board.tsx +++ b/src/_codux/boards/bag-item/bag-item.board.tsx @@ -12,7 +12,7 @@ export default createBoard({ mainTitle={PantsData[0].mainTitle} secondaryTitle={PantsData[0].secondaryTitle} image={PantsData[0].image} - price={'400'} + price={'19.999'} size={'S'} /> diff --git a/src/_codux/boards/card-size-selector/card-size-selector.board.tsx b/src/_codux/boards/card-size-selector/card-size-selector.board.tsx index 19de387..94a5910 100644 --- a/src/_codux/boards/card-size-selector/card-size-selector.board.tsx +++ b/src/_codux/boards/card-size-selector/card-size-selector.board.tsx @@ -7,6 +7,7 @@ export default createBoard({ Board: () => (
- + GeekBazar @@ -351,12 +348,8 @@
-

- Location -

-

- 123 Code Lane, Devtown, REACT 54321 -

+

Location

+

123 Code Lane, Devtown, REACT 54321

Follow Us

@@ -415,9 +408,7 @@

Follow Us

-

- Contact Us -

+

Contact Us

= ({ }; return ( - ); diff --git a/src/components/bag-item/bag-item.module.css b/src/components/bag-item/bag-item.module.css index bc2dbd4..100a872 100644 --- a/src/components/bag-item/bag-item.module.css +++ b/src/components/bag-item/bag-item.module.css @@ -1,45 +1,44 @@ .container { - display: flex; - flex-direction: row; - margin: 5px; + display: flex; + flex-direction: row; + margin: 5px; } .test { - flex-direction: column; - display: flex; + flex-direction: column; + display: flex; } .productSelectionContainer { - display: flex; - flex-direction: row; - gap: 0px 12px; - align-items: baseline; - align-content: end; - margin: 12px 0px 0px 2px; - justify-items: end; + display: flex; + flex-direction: row; + gap: 0px 12px; + align-items: baseline; + align-content: end; + margin: 12px 0px 0px 2px; + justify-items: end; } .price { - color: #111111; - font-family: Helvetica Now; - font-weight: 500; - text-align: start; - margin: 6px 0px 0px 16px; - font-size: 20px; + color: #111111; + font-family: Helvetica Now; + font-weight: 500; + text-align: start; + margin: 6px 0px 0px 16px; + font-size: 20px; } .deleteButton { - background: transparent url('../../../src/assets/delete-button.svg') - no-repeat center; - width: 30px; - height: 32px; - border: none; - margin-left: 10px; - margin-top: 3px; - padding: 0px; - align-self: stretch; + background: transparent url('../../../src/assets/delete-button.svg') no-repeat center; + height: 32px; + border: none; + margin-left: 10px; + margin-top: 3px; + padding: 0px; + align-self: stretch; + width: 29px; } .deleteButton:hover { - cursor: pointer; -} + cursor: pointer; +} \ No newline at end of file diff --git a/src/components/bag-item/bag-item.tsx b/src/components/bag-item/bag-item.tsx index 1fcf330..23c2068 100644 --- a/src/components/bag-item/bag-item.tsx +++ b/src/components/bag-item/bag-item.tsx @@ -27,7 +27,7 @@ export const BagItem: React.FC = ({ return (
- +

{mainTitle}

{secondaryTitle}

@@ -45,7 +45,8 @@ export const BagItem: React.FC = ({
+ onClick={handleClick} + data-testid={`${id} delete-button`}>

{`$ ${price}`}

diff --git a/src/components/bag-size-selector/bag-size-selector.module.css b/src/components/bag-size-selector/bag-size-selector.module.css index e35b97c..06344d8 100644 --- a/src/components/bag-size-selector/bag-size-selector.module.css +++ b/src/components/bag-size-selector/bag-size-selector.module.css @@ -1,33 +1,33 @@ .container { - display: flex; - flex-direction: row; + display: flex; + flex-direction: row; } .text { - font-family: 'Helvetica Now Text', Helvetica, Arial, sans-serif; - line-height: 28px; - color: #707072; - margin: 0px; - align-self: center; - font-weight: 400; - font-size: 16px; + font-family: 'Helvetica Now Text', Helvetica, Arial, sans-serif; + line-height: 28px; + color: #707072; + margin: 0px; + align-self: center; + font-weight: 400; + font-size: 16px; } .selectBar { - font-weight: 100; - border: 0px solid black; - text-align: center; - align-self: center; - margin: 0px 0px 2px 2px; - padding: 0px; - font-family: Tahoma, sans-serif; - width: 38px; - color: #707072; - height: 25px; - line-height: 28px; - font-size: 14px; + font-weight: 100; + border: 0px solid black; + text-align: center; + align-self: center; + margin: 0px 0px 2px 2px; + padding: 0px; + font-family: Tahoma, sans-serif; + width: 37px; + color: #707072; + height: 25px; + line-height: 28px; + font-size: 14px; } .selectBar:hover { - cursor: pointer; -} + cursor: pointer; +} \ No newline at end of file diff --git a/src/components/bagModal/bagModal.tsx b/src/components/bagModal/bagModal.tsx index 386b90f..958d3ae 100644 --- a/src/components/bagModal/bagModal.tsx +++ b/src/components/bagModal/bagModal.tsx @@ -10,6 +10,7 @@ export const BagModal = () => { const { cartItems, showModal, toggleCartModal, totalPrice } = useCart(); const modalRef = useRef(null); const [isMouseOver, setIsMouseOver] = useState(false); + const currentModalRef = modalRef.current; useEffect(() => { const handleMouseEnter = () => { setIsMouseOver(true); @@ -20,18 +21,13 @@ export const BagModal = () => { }; const handleClickOutside = (event: MouseEvent) => { - if ( - modalRef.current && - !modalRef.current.contains(event.target as Node) - ) { + if (modalRef.current && !modalRef.current.contains(event.target as Node)) { toggleCartModal(); } }; const handleGlobalMouseMove = (event: MouseEvent) => { - setIsMouseOver( - modalRef.current?.contains(event.target as Node) ?? false - ); + setIsMouseOver(modalRef.current?.contains(event.target as Node) ?? false); }; if (showModal) { @@ -43,18 +39,14 @@ export const BagModal = () => { return () => { document.removeEventListener('mousedown', handleClickOutside); - modalRef.current?.removeEventListener('mouseenter', handleMouseEnter); - modalRef.current?.removeEventListener('mouseleave', handleMouseLeave); + currentModalRef?.removeEventListener('mouseenter', handleMouseEnter); + currentModalRef?.removeEventListener('mouseleave', handleMouseLeave); document.removeEventListener('mousemove', handleGlobalMouseMove); }; - }, [showModal, toggleCartModal]); + }, [showModal, toggleCartModal, currentModalRef]); useEffect(() => { - document.body.style.cursor = showModal - ? isMouseOver - ? 'default' - : 'pointer' - : 'default'; + document.body.style.cursor = showModal ? (isMouseOver ? 'default' : 'pointer') : 'default'; return () => { document.body.style.cursor = 'default'; }; @@ -65,38 +57,34 @@ export const BagModal = () => { const prefix = id.replace(/[0-9]+$/, ''); // Capitalize the first letter and concatenate "Data" - const arrayDataName = - prefix.charAt(0).toUpperCase() + prefix.slice(1) + 'Data'; + const arrayDataName = prefix.charAt(0).toUpperCase() + prefix.slice(1) + 'Data'; const arrayData: Item[] | undefined = dataArrayByName[arrayDataName]; return arrayData.find((item) => item.id == id)!; } return ( - showModal && ( -
-
- {Array.from(cartItems.entries()).map(([key]) => { - const [id, size] = key.split('#'); - const cartItem: CartItem = { - ...getItemFromId(id), - size: size as Sizes, - }; - return ; - })} -
-
-
-

- {' '} - Order Summary -

-

{`$ ${totalPrice.toFixed(2)}`}

-
+
+
+ {Array.from(cartItems.entries()).map(([key]) => { + const [id, size] = key.split('#'); + const cartItem: CartItem = { + ...getItemFromId(id), + size: size as Sizes, + }; + return ; + })} +
+
+
+

Order Summary

+

+ {totalPrice.toFixed(2)} +

- ) +
); }; diff --git a/src/components/bagModal/bagmodal.module.css b/src/components/bagModal/bagmodal.module.css index 9e852a5..e944ed7 100644 --- a/src/components/bagModal/bagmodal.module.css +++ b/src/components/bagModal/bagmodal.module.css @@ -16,6 +16,12 @@ justify-content: center; } +.notVisible { + visibility: hidden; + height: 0px; + width: 0px; +} + .itemList { margin: 0px; overflow: auto; diff --git a/src/components/card-size-selector/card-size-selector.module.css b/src/components/card-size-selector/card-size-selector.module.css index 4aebba3..55f75ac 100644 --- a/src/components/card-size-selector/card-size-selector.module.css +++ b/src/components/card-size-selector/card-size-selector.module.css @@ -23,11 +23,10 @@ font-family: 'Inconsolata', monospace; font-weight: 500; font-size: 20px; - } .sizeButton:hover { - color:white; + color: white; background-color: black; } @@ -35,5 +34,5 @@ color: #162944; border: 2px solid #162944; background-color: black; - color:white; + color: white; } diff --git a/src/components/card-size-selector/card-size-selector.tsx b/src/components/card-size-selector/card-size-selector.tsx index 288fd82..406e4b3 100644 --- a/src/components/card-size-selector/card-size-selector.tsx +++ b/src/components/card-size-selector/card-size-selector.tsx @@ -2,7 +2,7 @@ import React from 'react'; import styles from './card-size-selector.module.css'; import { CardSizeSelector, Sizes } from '../datatypes'; -const SizeSelector: React.FC = ({ size, setSize }) => { +const SizeSelector: React.FC = ({ id, size, setSize }) => { const sizes: Sizes[] = ['S', 'M', 'L', 'XL']; const handleSelectSize = (currentSize: Sizes) => { @@ -13,14 +13,11 @@ const SizeSelector: React.FC = ({ size, setSize }) => { {sizes.map((currentSize) => ( diff --git a/src/components/card.module.css b/src/components/card.module.css index 7c53610..08b9f5f 100644 --- a/src/components/card.module.css +++ b/src/components/card.module.css @@ -1,77 +1,83 @@ .cardContainer { - display: flex; - align-items: center; - height: 450px; - width: 320px; - flex-direction: column; - border-radius: 18px; - background-color: white; - border: 1px solid rgb(0, 0, 0); - box-shadow: 5px 5px; - transition: box-shadow 0.5s ease; - flex-wrap: nowrap; + display: flex; + align-items: center; + height: 450px; + width: 320px; + flex-direction: column; + border-radius: 18px; + background-color: white; + border: 1px solid rgb(0, 0, 0); + box-shadow: 5px 5px; + transition: box-shadow 0.5s ease; + flex-wrap: nowrap; } .cardContainer:hover { - box-shadow: 10px 10px rgb(253, 0, 207); + box-shadow: 10px 10px rgb(253, 0, 207); +} + +.notVisible { + visibility: hidden; + height: 0px; + width: 0px; } .img { - align-self: center; - width: 55%; - height: 45%; - border-radius: 18px; - margin-bottom: 15px; + align-self: center; + width: 55%; + height: 45%; + border-radius: 18px; + margin-bottom: 15px; } .listingContainer { - display: flex; - flex-direction: column; - align-items: center; - text-align: center; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; } .mainTitle { - font-size: 16px; + font-size: 16px; } .mainTitle, .secondaryTitle, .price { - margin: 2px 0; + margin: 2px 0; } .mainTitle { - font-family: 'Climate Crisis', sans-serif; - letter-spacing: 0.5px; + font-family: 'Climate Crisis', sans-serif; + letter-spacing: 0.5px; } .price { - font-size: 1.6rem; - color: #3498db; - font-weight: bold; + font-size: 1.6rem; + color: #3498db; + font-weight: bold; } .errorAndSizeContainer { - display: flex; - flex-direction: column; - align-items: flex-start; + display: flex; + flex-direction: column; + align-items: flex-start; } .errorMessage { - color: red; - margin-left: 20px; - font-weight: 600; - font-size: 16px; - animation: showErrorMessage 0.8s ease-in-out; + color: red; + margin-left: 20px; + font-weight: 600; + font-size: 16px; + animation: showErrorMessage 0.8s ease-in-out; } @keyframes showErrorMessage { - from { - opacity: 0%; - } + from { + opacity: 0%; + } - to { - opacity: 100%; - } -} \ No newline at end of file + to { + opacity: 100%; + } +} diff --git a/src/components/card.tsx b/src/components/card.tsx index d2dddbe..76077a8 100644 --- a/src/components/card.tsx +++ b/src/components/card.tsx @@ -4,35 +4,33 @@ import { Item, Sizes } from './datatypes'; import CardSizeSelector from './card-size-selector/card-size-selector'; import { useState } from 'react'; -export const Card: React.FC = ({ - id, - mainTitle, - secondaryTitle, - image, - price, -}) => { +export const Card: React.FC = ({ id, mainTitle, secondaryTitle, image, price }) => { const [size, setSize] = useState(null); const [addToCartClicked, setAddToCartClicked] = useState(false); return ( -
- {mainTitle} +
+ {mainTitle}

{mainTitle}

{secondaryTitle}

-

{`$ ${price}`}

+

+ {price} +

{/* The following div is just so that the error message will be aligned left just as the sizeselector */}
- {addToCartClicked && !size && ( -

Please choose a size

- )} - +

+ Please choose a size +

+
void; } diff --git a/src/components/header.module.css b/src/components/header.module.css index 82010b5..46dc312 100644 --- a/src/components/header.module.css +++ b/src/components/header.module.css @@ -77,8 +77,7 @@ input:focus { height: 40px; overflow: hidden; border: solid transparent; - background: transparent url('../../src/assets/shopping-bag.svg') no-repeat - center; + background: transparent url('../../src/assets/shopping-bag.svg') no-repeat center; cursor: pointer; opacity: 1; } diff --git a/src/components/header.tsx b/src/components/header.tsx index fcf8fa6..ddc7fd4 100644 --- a/src/components/header.tsx +++ b/src/components/header.tsx @@ -9,31 +9,23 @@ export const Header = () => { return (
- Logo + Logo
- +