From 35cbe6c87ba6c7bf464636c83c75c342b9625742 Mon Sep 17 00:00:00 2001 From: Ed Code Date: Mon, 17 Apr 2023 17:57:32 +0200 Subject: [PATCH 01/13] init --- code/package-lock.json | 263 +++++++++++++++++++++++++++++++++++++++-- code/package.json | 4 +- 2 files changed, 257 insertions(+), 10 deletions(-) diff --git a/code/package-lock.json b/code/package-lock.json index bb51e893e..8b198f142 100644 --- a/code/package-lock.json +++ b/code/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "dependencies": { "@babel/eslint-parser": "^7.18.9", + "@reduxjs/toolkit": "^1.9.4", "eslint": "^8.21.0", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-import": "^2.26.0", @@ -16,7 +17,8 @@ "eslint-plugin-react": "^7.30.1", "eslint-plugin-react-hooks": "^4.6.0", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-redux": "^8.0.5" }, "devDependencies": { "react-scripts": "5.0.1" @@ -3124,6 +3126,29 @@ } } }, + "node_modules/@reduxjs/toolkit": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.4.tgz", + "integrity": "sha512-j2R4I+dzt7cWjf50CNS17A/TBX0rH5SmFhKcOQDZlFtFvmSGWfEQvNPjrCI729Am5o1USFWT1PaxV/JflmP/Dg==", + "dependencies": { + "immer": "^9.0.21", + "redux": "^4.2.1", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.8" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.0.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -3621,6 +3646,15 @@ "@types/node": "*" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -3695,6 +3729,11 @@ "integrity": "sha512-fOwvpvQYStpb/zHMx0Cauwywu9yLDmzWiiQBC7gJyq5tYLUXFZvDG7VK1B7WBxxjBJNKFOZ0zLoOQn8vmATbhw==", "dev": true }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, "node_modules/@types/q": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", @@ -3713,6 +3752,16 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", "dev": true }, + "node_modules/@types/react": { + "version": "18.0.35", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.35.tgz", + "integrity": "sha512-6Laome31HpetaIUGFWl1VQ3mdSImwxtFZ39rh059a1MNnKGqBpC88J6NJ8n/Is3Qx7CefDGLgf/KhN/sYCf7ag==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -3728,6 +3777,11 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, + "node_modules/@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + }, "node_modules/@types/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", @@ -3768,6 +3822,11 @@ "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==", "dev": true }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" + }, "node_modules/@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -6095,6 +6154,11 @@ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "dev": true }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -8515,6 +8579,14 @@ "he": "bin/he" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -8800,10 +8872,9 @@ } }, "node_modules/immer": { - "version": "9.0.15", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz", - "integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==", - "dev": true, + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -14375,6 +14446,49 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/react-redux": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz", + "integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==", + "dependencies": { + "@babel/runtime": "^7.12.1", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/use-sync-external-store": "^0.0.3", + "hoist-non-react-statics": "^3.3.2", + "react-is": "^18.0.0", + "use-sync-external-store": "^1.0.0" + }, + "peerDependencies": { + "@types/react": "^16.8 || ^17.0 || ^18.0", + "@types/react-dom": "^16.8 || ^17.0 || ^18.0", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0", + "react-native": ">=0.59", + "redux": "^4" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/react-redux/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -14531,6 +14645,22 @@ "node": "*" } }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/redux-thunk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "peerDependencies": { + "redux": "^4" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -14686,6 +14816,11 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, + "node_modules/reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" + }, "node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -16340,6 +16475,14 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -19509,6 +19652,17 @@ "source-map": "^0.7.3" } }, + "@reduxjs/toolkit": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.4.tgz", + "integrity": "sha512-j2R4I+dzt7cWjf50CNS17A/TBX0rH5SmFhKcOQDZlFtFvmSGWfEQvNPjrCI729Am5o1USFWT1PaxV/JflmP/Dg==", + "requires": { + "immer": "^9.0.21", + "redux": "^4.2.1", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.8" + } + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -19876,6 +20030,15 @@ "@types/node": "*" } }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -19950,6 +20113,11 @@ "integrity": "sha512-fOwvpvQYStpb/zHMx0Cauwywu9yLDmzWiiQBC7gJyq5tYLUXFZvDG7VK1B7WBxxjBJNKFOZ0zLoOQn8vmATbhw==", "dev": true }, + "@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, "@types/q": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", @@ -19968,6 +20136,16 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", "dev": true }, + "@types/react": { + "version": "18.0.35", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.35.tgz", + "integrity": "sha512-6Laome31HpetaIUGFWl1VQ3mdSImwxtFZ39rh059a1MNnKGqBpC88J6NJ8n/Is3Qx7CefDGLgf/KhN/sYCf7ag==", + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -19983,6 +20161,11 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, + "@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + }, "@types/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", @@ -20023,6 +20206,11 @@ "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==", "dev": true }, + "@types/use-sync-external-store": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" + }, "@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -21748,6 +21936,11 @@ } } }, + "csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, "damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -23521,6 +23714,14 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, "hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -23739,10 +23940,9 @@ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" }, "immer": { - "version": "9.0.15", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz", - "integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==", - "dev": true + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==" }, "import-fresh": { "version": "3.3.0", @@ -27678,6 +27878,26 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "react-redux": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz", + "integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==", + "requires": { + "@babel/runtime": "^7.12.1", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/use-sync-external-store": "^0.0.3", + "hoist-non-react-statics": "^3.3.2", + "react-is": "^18.0.0", + "use-sync-external-store": "^1.0.0" + }, + "dependencies": { + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + } + } + }, "react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -27800,6 +28020,20 @@ } } }, + "redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "requires": { + "@babel/runtime": "^7.9.2" + } + }, + "redux-thunk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "requires": {} + }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -27924,6 +28158,11 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, + "reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" + }, "resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -29163,6 +29402,12 @@ "punycode": "^2.1.0" } }, + "use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "requires": {} + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/code/package.json b/code/package.json index 7aad26ebc..a6f0cfadc 100644 --- a/code/package.json +++ b/code/package.json @@ -4,6 +4,7 @@ "private": true, "dependencies": { "@babel/eslint-parser": "^7.18.9", + "@reduxjs/toolkit": "^1.9.4", "eslint": "^8.21.0", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-import": "^2.26.0", @@ -11,7 +12,8 @@ "eslint-plugin-react": "^7.30.1", "eslint-plugin-react-hooks": "^4.6.0", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-redux": "^8.0.5" }, "scripts": { "start": "react-scripts start", From 9444fcb4d615b9643b7e68d06353cff3577aca19 Mon Sep 17 00:00:00 2001 From: Ed Code Date: Tue, 18 Apr 2023 21:39:12 +0200 Subject: [PATCH 02/13] basic functionality --- code/package-lock.json | 202 +++++++++++++++++++++++++++++-- code/package.json | 3 +- code/src/App.js | 19 ++- code/src/components/CheckBox.js | 16 +++ code/src/components/Task.js | 33 +++++ code/src/components/TaskAdder.js | 32 +++++ code/src/components/TaskList.js | 20 +++ code/src/reducers/tasks.js | 19 +++ 8 files changed, 329 insertions(+), 15 deletions(-) create mode 100644 code/src/components/CheckBox.js create mode 100644 code/src/components/Task.js create mode 100644 code/src/components/TaskAdder.js create mode 100644 code/src/components/TaskList.js create mode 100644 code/src/reducers/tasks.js diff --git a/code/package-lock.json b/code/package-lock.json index 8b198f142..bb3e29c41 100644 --- a/code/package-lock.json +++ b/code/package-lock.json @@ -18,7 +18,8 @@ "eslint-plugin-react-hooks": "^4.6.0", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-redux": "^8.0.5" + "react-redux": "^8.0.5", + "styled-components": "^5.3.9" }, "devDependencies": { "react-scripts": "5.0.1" @@ -131,7 +132,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "dev": true, "dependencies": { "@babel/types": "^7.18.6" }, @@ -2155,6 +2155,29 @@ "postcss-selector-parser": "^6.0.10" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz", + "integrity": "sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==", + "dependencies": { + "@emotion/memoize": "^0.8.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", + "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" + }, + "node_modules/@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, "node_modules/@eslint/eslintrc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", @@ -4926,6 +4949,26 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/babel-plugin-styled-components": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.1.tgz", + "integrity": "sha512-c8lJlszObVQPguHkI+akXv8+Jgb9Ccujx0EetL7oIvwU100LxO6XAGe45qry37wUL40a5U9f23SYrivro2XKhA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-module-imports": "^7.16.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.21", + "picomatch": "^2.3.0" + }, + "peerDependencies": { + "styled-components": ">= 2" + } + }, + "node_modules/babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==" + }, "node_modules/babel-plugin-transform-react-remove-prop-types": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", @@ -5263,6 +5306,14 @@ "node": ">= 6" } }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -5750,6 +5801,14 @@ "postcss": "^8.4" } }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "engines": { + "node": ">=4" + } + }, "node_modules/css-declaration-sorter": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.0.tgz", @@ -5958,6 +6017,16 @@ "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", "dev": true }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "node_modules/css-tree": { "version": "1.0.0-alpha.37", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", @@ -11766,8 +11835,7 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash.debounce": { "version": "4.0.8", @@ -14011,8 +14079,7 @@ "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/prelude-ls": { "version": "1.2.1", @@ -15341,6 +15408,11 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -15750,6 +15822,35 @@ "webpack": "^5.0.0" } }, + "node_modules/styled-components": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.9.tgz", + "integrity": "sha512-Aj3kb13B75DQBo2oRwRa/APdB5rSmwUfN5exyarpX+x/tlM/rwZA2vVk2vQgVSP6WKaZJHWwiFrzgHt+CLtB4A==", + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^1.1.0", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0", + "react-is": ">= 16.8.0" + } + }, "node_modules/stylehacks": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.0.tgz", @@ -17603,7 +17704,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "dev": true, "requires": { "@babel/types": "^7.18.6" } @@ -18935,6 +19035,29 @@ "dev": true, "requires": {} }, + "@emotion/is-prop-valid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz", + "integrity": "sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==", + "requires": { + "@emotion/memoize": "^0.8.0" + } + }, + "@emotion/memoize": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", + "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" + }, + "@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, "@eslint/eslintrc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", @@ -21019,6 +21142,23 @@ "@babel/helper-define-polyfill-provider": "^0.3.2" } }, + "babel-plugin-styled-components": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.1.tgz", + "integrity": "sha512-c8lJlszObVQPguHkI+akXv8+Jgb9Ccujx0EetL7oIvwU100LxO6XAGe45qry37wUL40a5U9f23SYrivro2XKhA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-module-imports": "^7.16.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.21", + "picomatch": "^2.3.0" + } + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==" + }, "babel-plugin-transform-react-remove-prop-types": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", @@ -21287,6 +21427,11 @@ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "dev": true }, + "camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==" + }, "caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -21659,6 +21804,11 @@ "postcss-selector-parser": "^6.0.9" } }, + "css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==" + }, "css-declaration-sorter": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.0.tgz", @@ -21789,6 +21939,16 @@ "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", "dev": true }, + "css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "requires": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "css-tree": { "version": "1.0.0-alpha.37", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", @@ -26074,8 +26234,7 @@ "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash.debounce": { "version": "4.0.8", @@ -27549,8 +27708,7 @@ "postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "prelude-ls": { "version": "1.2.1", @@ -28545,6 +28703,11 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -28859,6 +29022,23 @@ "dev": true, "requires": {} }, + "styled-components": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.9.tgz", + "integrity": "sha512-Aj3kb13B75DQBo2oRwRa/APdB5rSmwUfN5exyarpX+x/tlM/rwZA2vVk2vQgVSP6WKaZJHWwiFrzgHt+CLtB4A==", + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^1.1.0", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + } + }, "stylehacks": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.0.tgz", diff --git a/code/package.json b/code/package.json index a6f0cfadc..fbda365d4 100644 --- a/code/package.json +++ b/code/package.json @@ -13,7 +13,8 @@ "eslint-plugin-react-hooks": "^4.6.0", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-redux": "^8.0.5" + "react-redux": "^8.0.5", + "styled-components": "^5.3.9" }, "scripts": { "start": "react-scripts start", diff --git a/code/src/App.js b/code/src/App.js index f2007d229..532de6453 100644 --- a/code/src/App.js +++ b/code/src/App.js @@ -1,9 +1,22 @@ import React from 'react'; +import { Provider } from 'react-redux' +import { combineReducers, configureStore } from '@reduxjs/toolkit'; +import { tasks } from './reducers/tasks' +import TaskList from './components/TaskList' +import TaskAdder from './components/TaskAdder' + +const reducer = combineReducers({ + tasks: tasks.reducer +}) + +const store = configureStore({ reducer }) export const App = () => { return ( -
- Find me in src/app.js! -
+ + Todo! + + + ); } diff --git a/code/src/components/CheckBox.js b/code/src/components/CheckBox.js new file mode 100644 index 000000000..21aa5b877 --- /dev/null +++ b/code/src/components/CheckBox.js @@ -0,0 +1,16 @@ +import React from 'react' +import { useDispatch } from 'react-redux'; +import { tasks } from 'reducers/tasks' + +const CheckBox = ({ id }) => { + const dispatch = useDispatch(); + const checkComplete = () => { + dispatch(tasks.actions.toggleTask(id)) + } + return ( + + + ); +} + +export default CheckBox; \ No newline at end of file diff --git a/code/src/components/Task.js b/code/src/components/Task.js new file mode 100644 index 000000000..6c01a15c3 --- /dev/null +++ b/code/src/components/Task.js @@ -0,0 +1,33 @@ +import React from 'react' +import { useSelector } from 'react-redux' +import styled from 'styled-components' +import CheckBox from './CheckBox' + +const StyledContainer = styled.div`` + +const StyledText = styled.p` +font-size: 12px; +text-decoration: underline; + +&.completed { + color: green; + text-decoration: line-through; +} +` + +const Task = ({ id }) => { + const task = useSelector((state) => state.tasks.find((t) => t.id === id)) + return ( + + + {task.text} + + + + ); +} + +export default Task; \ No newline at end of file diff --git a/code/src/components/TaskAdder.js b/code/src/components/TaskAdder.js new file mode 100644 index 000000000..5fc0d02fd --- /dev/null +++ b/code/src/components/TaskAdder.js @@ -0,0 +1,32 @@ +import React, { useState } from 'react' +import { useDispatch, useSelector } from 'react-redux' +import { tasks } from 'reducers/tasks' +import styled from 'styled-components' + +const StyledContainer = styled.div` +` + +const StyledInput = styled.input` +` + +const StyledButton = styled.button`` + +const TaskAdder = () => { + const [todoText, setTodoText] = useState(''); + const dispatch = useDispatch(); + + const tasksLength = useSelector((state) => state.tasks.length) + + const handleSubmit = () => { + dispatch(tasks.actions.addTask({ id: tasksLength + 1, text: todoText, complete: false })) + } + + return ( + + + setTodoText(e.target.value)} /> + + ); +} + +export default TaskAdder; \ No newline at end of file diff --git a/code/src/components/TaskList.js b/code/src/components/TaskList.js new file mode 100644 index 000000000..2c6aaee85 --- /dev/null +++ b/code/src/components/TaskList.js @@ -0,0 +1,20 @@ +import React from 'react' +import styled from 'styled-components' +import { useSelector } from 'react-redux' +import Task from './Task' + +const StyledContainer = styled.div` +display: flex; +flex-direction: column; +gap: 5px;` + +const TaskList = () => { + const tasks = useSelector((state) => state.tasks) + return ( +

Tasklist

+ {tasks.map((task) => ( + ))} +
); +} + +export default TaskList; \ No newline at end of file diff --git a/code/src/reducers/tasks.js b/code/src/reducers/tasks.js new file mode 100644 index 000000000..bf61378ff --- /dev/null +++ b/code/src/reducers/tasks.js @@ -0,0 +1,19 @@ +import { createSlice } from '@reduxjs/toolkit' + +export const tasks = createSlice({ name: 'tasks', + initialState: [ + { id: 1, text: 'Vejpa', complete: true }, + { id: 2, text: 'Gamea', complete: false }, + { id: 3, text: 'Kodea', complete: true }, + { id: 4, text: 'Chilla', complete: true } + ], + reducers: { + addTask(state, action) { + console.log(action.payload) + state.push(action.payload) + }, + toggleTask(state, action) { + const todo = state.find((t) => t.id === action.payload) + todo.complete = !todo.complete + } + } }) \ No newline at end of file From 1a4eb38f327e51824085ad955e4155dc1b141b80 Mon Sep 17 00:00:00 2001 From: Ed Code Date: Tue, 18 Apr 2023 21:40:50 +0200 Subject: [PATCH 03/13] t --- code/src/reducers/tasks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/src/reducers/tasks.js b/code/src/reducers/tasks.js index bf61378ff..476772d87 100644 --- a/code/src/reducers/tasks.js +++ b/code/src/reducers/tasks.js @@ -2,7 +2,7 @@ import { createSlice } from '@reduxjs/toolkit' export const tasks = createSlice({ name: 'tasks', initialState: [ - { id: 1, text: 'Vejpa', complete: true }, + { id: 1, text: 'Plugga', complete: true }, { id: 2, text: 'Gamea', complete: false }, { id: 3, text: 'Kodea', complete: true }, { id: 4, text: 'Chilla', complete: true } From 07997e985b9ce9ca2ccacc32a6164bf70ac1df18 Mon Sep 17 00:00:00 2001 From: Ed Code Date: Tue, 18 Apr 2023 22:29:59 +0200 Subject: [PATCH 04/13] non functional delete button --- code/src/components/DeleteButton.js | 20 ++++++++++++++++++++ code/src/components/Task.js | 3 ++- code/src/reducers/tasks.js | 4 +++- 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 code/src/components/DeleteButton.js diff --git a/code/src/components/DeleteButton.js b/code/src/components/DeleteButton.js new file mode 100644 index 000000000..92c8af0d5 --- /dev/null +++ b/code/src/components/DeleteButton.js @@ -0,0 +1,20 @@ +import React from 'react' +import { useDispatch } from 'react-redux'; +import { tasks } from 'reducers/tasks' +import styled from 'styled-components' + +const StyledButton = styled.button` +background-color: red; +width: 15px; +height: 15px;` + +const DeleteButton = ({ id }) => { + const dispatch = useDispatch(); + + const handleDelete = () => { + dispatch(tasks.actions.deleteTask(id)) + } + return (); +} + +export default DeleteButton; \ No newline at end of file diff --git a/code/src/components/Task.js b/code/src/components/Task.js index 6c01a15c3..d76f32e0e 100644 --- a/code/src/components/Task.js +++ b/code/src/components/Task.js @@ -2,12 +2,12 @@ import React from 'react' import { useSelector } from 'react-redux' import styled from 'styled-components' import CheckBox from './CheckBox' +import DeleteButton from './DeleteButton' const StyledContainer = styled.div`` const StyledText = styled.p` font-size: 12px; -text-decoration: underline; &.completed { color: green; @@ -26,6 +26,7 @@ const Task = ({ id }) => { {task.text} + ); } diff --git a/code/src/reducers/tasks.js b/code/src/reducers/tasks.js index 476772d87..0cb8fca59 100644 --- a/code/src/reducers/tasks.js +++ b/code/src/reducers/tasks.js @@ -9,11 +9,13 @@ export const tasks = createSlice({ name: 'tasks', ], reducers: { addTask(state, action) { - console.log(action.payload) state.push(action.payload) }, toggleTask(state, action) { const todo = state.find((t) => t.id === action.payload) todo.complete = !todo.complete + }, + deleteTask(state, action) { + state = state.filter((t) => t.id !== action.payload) } } }) \ No newline at end of file From 0dd1c2a097e964c093a3f01a81b1f5114bfc9c73 Mon Sep 17 00:00:00 2001 From: Ed Code Date: Tue, 18 Apr 2023 22:41:26 +0200 Subject: [PATCH 05/13] functional delete button --- code/package-lock.json | 13 ++++++++++++- code/package.json | 3 ++- code/src/components/Task.js | 2 +- code/src/components/TaskAdder.js | 7 +++---- code/src/reducers/tasks.js | 12 +++++++----- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/code/package-lock.json b/code/package-lock.json index bb3e29c41..de59857db 100644 --- a/code/package-lock.json +++ b/code/package-lock.json @@ -19,7 +19,8 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-redux": "^8.0.5", - "styled-components": "^5.3.9" + "styled-components": "^5.3.9", + "uniqid": "^5.4.0" }, "devDependencies": { "react-scripts": "5.0.1" @@ -16497,6 +16498,11 @@ "node": ">=4" } }, + "node_modules/uniqid": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-5.4.0.tgz", + "integrity": "sha512-38JRbJ4Fj94VmnC7G/J/5n5SC7Ab46OM5iNtSstB/ko3l1b5g7ALt4qzHFgGciFkyiRNtDXtLNb+VsxtMSE77A==" + }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -29532,6 +29538,11 @@ "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", "dev": true }, + "uniqid": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-5.4.0.tgz", + "integrity": "sha512-38JRbJ4Fj94VmnC7G/J/5n5SC7Ab46OM5iNtSstB/ko3l1b5g7ALt4qzHFgGciFkyiRNtDXtLNb+VsxtMSE77A==" + }, "unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", diff --git a/code/package.json b/code/package.json index fbda365d4..cd89baf39 100644 --- a/code/package.json +++ b/code/package.json @@ -14,7 +14,8 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-redux": "^8.0.5", - "styled-components": "^5.3.9" + "styled-components": "^5.3.9", + "uniqid": "^5.4.0" }, "scripts": { "start": "react-scripts start", diff --git a/code/src/components/Task.js b/code/src/components/Task.js index d76f32e0e..81b602343 100644 --- a/code/src/components/Task.js +++ b/code/src/components/Task.js @@ -26,7 +26,7 @@ const Task = ({ id }) => { {task.text} - + ); } diff --git a/code/src/components/TaskAdder.js b/code/src/components/TaskAdder.js index 5fc0d02fd..1a24e5d07 100644 --- a/code/src/components/TaskAdder.js +++ b/code/src/components/TaskAdder.js @@ -1,7 +1,8 @@ import React, { useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import { useDispatch } from 'react-redux' import { tasks } from 'reducers/tasks' import styled from 'styled-components' +import uniqid from 'uniqid' const StyledContainer = styled.div` ` @@ -15,10 +16,8 @@ const TaskAdder = () => { const [todoText, setTodoText] = useState(''); const dispatch = useDispatch(); - const tasksLength = useSelector((state) => state.tasks.length) - const handleSubmit = () => { - dispatch(tasks.actions.addTask({ id: tasksLength + 1, text: todoText, complete: false })) + dispatch(tasks.actions.addTask({ id: uniqid(), text: todoText, complete: false })) } return ( diff --git a/code/src/reducers/tasks.js b/code/src/reducers/tasks.js index 0cb8fca59..148766288 100644 --- a/code/src/reducers/tasks.js +++ b/code/src/reducers/tasks.js @@ -2,10 +2,10 @@ import { createSlice } from '@reduxjs/toolkit' export const tasks = createSlice({ name: 'tasks', initialState: [ - { id: 1, text: 'Plugga', complete: true }, - { id: 2, text: 'Gamea', complete: false }, - { id: 3, text: 'Kodea', complete: true }, - { id: 4, text: 'Chilla', complete: true } + { id: 0, text: 'Plugga', complete: true }, + { id: 1, text: 'Gamea', complete: false }, + { id: 2, text: 'Kodea', complete: true }, + { id: 3, text: 'Chilla', complete: true } ], reducers: { addTask(state, action) { @@ -16,6 +16,8 @@ export const tasks = createSlice({ name: 'tasks', todo.complete = !todo.complete }, deleteTask(state, action) { - state = state.filter((t) => t.id !== action.payload) + // state = state.filter((t) => t.id !== action.payload) + const todo = state.find((t) => t.id === action.payload) + state.splice(state.indexOf(todo), 1) } } }) \ No newline at end of file From 30acf00acac16ebee8cdc9219240550bbde5af0d Mon Sep 17 00:00:00 2001 From: Ed Code Date: Wed, 19 Apr 2023 17:09:45 +0200 Subject: [PATCH 06/13] refactoring --- code/src/App.js | 8 +++----- code/src/components/TaskList.js | 2 +- code/src/components/Todos.js | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 code/src/components/Todos.js diff --git a/code/src/App.js b/code/src/App.js index 532de6453..7ce7d0cc2 100644 --- a/code/src/App.js +++ b/code/src/App.js @@ -2,8 +2,8 @@ import React from 'react'; import { Provider } from 'react-redux' import { combineReducers, configureStore } from '@reduxjs/toolkit'; import { tasks } from './reducers/tasks' -import TaskList from './components/TaskList' -import TaskAdder from './components/TaskAdder' + +import Todos from './components/Todos' const reducer = combineReducers({ tasks: tasks.reducer @@ -14,9 +14,7 @@ const store = configureStore({ reducer }) export const App = () => { return ( - Todo! - - + ); } diff --git a/code/src/components/TaskList.js b/code/src/components/TaskList.js index 2c6aaee85..7a1e66c33 100644 --- a/code/src/components/TaskList.js +++ b/code/src/components/TaskList.js @@ -13,7 +13,7 @@ const TaskList = () => { return (

Tasklist

{tasks.map((task) => ( - ))} + ))}
); } diff --git a/code/src/components/Todos.js b/code/src/components/Todos.js new file mode 100644 index 000000000..496e80fb7 --- /dev/null +++ b/code/src/components/Todos.js @@ -0,0 +1,14 @@ +import React from 'react' +import TaskAdder from './TaskAdder'; +import TaskList from './TaskList'; + +const Todos = () => { + return ( + <> + + + + ); +} + +export default Todos; \ No newline at end of file From c5aaabad23970ad1c5158405be1619abfed3262c Mon Sep 17 00:00:00 2001 From: Ed Code Date: Wed, 19 Apr 2023 17:33:09 +0200 Subject: [PATCH 07/13] complete all and clear all functionality --- code/src/components/CheckBox.js | 2 +- code/src/components/Task.js | 2 +- code/src/components/TaskList.js | 27 ++++++++++++++++++++++++--- code/src/reducers/tasks.js | 29 +++++++++++++++++++---------- 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/code/src/components/CheckBox.js b/code/src/components/CheckBox.js index 21aa5b877..347ea5c2b 100644 --- a/code/src/components/CheckBox.js +++ b/code/src/components/CheckBox.js @@ -5,7 +5,7 @@ import { tasks } from 'reducers/tasks' const CheckBox = ({ id }) => { const dispatch = useDispatch(); const checkComplete = () => { - dispatch(tasks.actions.toggleTask(id)) + dispatch(tasks.actions.completeTask(id)) } return ( diff --git a/code/src/components/Task.js b/code/src/components/Task.js index 81b602343..80a751e03 100644 --- a/code/src/components/Task.js +++ b/code/src/components/Task.js @@ -16,7 +16,7 @@ font-size: 12px; ` const Task = ({ id }) => { - const task = useSelector((state) => state.tasks.find((t) => t.id === id)) + const task = useSelector((state) => state.tasks.todos.find((t) => t.id === id)) return ( { - const tasks = useSelector((state) => state.tasks) + const dispatch = useDispatch(); + + const handleCompleteAll = () => { + dispatch(tasks.actions.completeAllTasks()) + } + const handleDeleteAll = () => { + if (window.confirm('Are you sure you want to delete all?')) { + dispatch(tasks.actions.deleteAllTasks()) + } + } + const tasksData = useSelector((state) => state.tasks.todos) return (

Tasklist

- {tasks.map((task) => ( + + + {tasksData.map((task) => ( ))}
); } diff --git a/code/src/reducers/tasks.js b/code/src/reducers/tasks.js index 148766288..4f3226a7b 100644 --- a/code/src/reducers/tasks.js +++ b/code/src/reducers/tasks.js @@ -1,23 +1,32 @@ import { createSlice } from '@reduxjs/toolkit' export const tasks = createSlice({ name: 'tasks', - initialState: [ - { id: 0, text: 'Plugga', complete: true }, - { id: 1, text: 'Gamea', complete: false }, - { id: 2, text: 'Kodea', complete: true }, - { id: 3, text: 'Chilla', complete: true } - ], + initialState: { + todos: [ + { id: 0, text: 'Plugga', complete: true }, + { id: 1, text: 'Gamea', complete: false }, + { id: 2, text: 'Kodea', complete: true }, + { id: 3, text: 'Chilla', complete: true } + ] + }, reducers: { addTask(state, action) { - state.push(action.payload) + state.todos.push(action.payload) }, - toggleTask(state, action) { - const todo = state.find((t) => t.id === action.payload) + completeTask(state, action) { + const todo = state.todos.find((t) => t.id === action.payload) todo.complete = !todo.complete }, deleteTask(state, action) { // state = state.filter((t) => t.id !== action.payload) - const todo = state.find((t) => t.id === action.payload) + const todo = state.todos.find((t) => t.id === action.payload) state.splice(state.indexOf(todo), 1) + }, + deleteAllTasks(state) { + /* eslint-disable no-unused-vars */ + state.todos = [] + }, + completeAllTasks(state) { + state.todos.forEach((t) => { t.complete = true }) } } }) \ No newline at end of file From a1b216e5b41fbfb3c02ee3229317d4aae2de8db8 Mon Sep 17 00:00:00 2001 From: Ed Code Date: Wed, 19 Apr 2023 22:46:09 +0200 Subject: [PATCH 08/13] started styling mobile first --- code/src/App.js | 13 ++++++++- code/src/components/CheckBox.js | 5 +++- code/src/components/DeleteButton.js | 2 +- code/src/components/Task.js | 12 ++++++--- code/src/components/TaskAdder.js | 7 +++-- code/src/components/TaskList.js | 42 +++++++++++++++++++++++------ code/src/components/Todos.js | 17 +++++++++--- code/src/index.css | 6 +++++ code/src/reducers/tasks.js | 3 +-- 9 files changed, 86 insertions(+), 21 deletions(-) diff --git a/code/src/App.js b/code/src/App.js index 7ce7d0cc2..132b41323 100644 --- a/code/src/App.js +++ b/code/src/App.js @@ -1,10 +1,19 @@ import React from 'react'; import { Provider } from 'react-redux' import { combineReducers, configureStore } from '@reduxjs/toolkit'; +import styled from 'styled-components/macro' import { tasks } from './reducers/tasks' import Todos from './components/Todos' +const StyledContainer = styled.div` +background-color: var(--background-color); +display: flex; +flex-direction: row; +justify-content: center; +align-items: center; +height: 100vh;` + const reducer = combineReducers({ tasks: tasks.reducer }) @@ -14,7 +23,9 @@ const store = configureStore({ reducer }) export const App = () => { return ( - + + + ); } diff --git a/code/src/components/CheckBox.js b/code/src/components/CheckBox.js index 347ea5c2b..8b54e7fdc 100644 --- a/code/src/components/CheckBox.js +++ b/code/src/components/CheckBox.js @@ -1,6 +1,9 @@ import React from 'react' import { useDispatch } from 'react-redux'; import { tasks } from 'reducers/tasks' +import styled from 'styled-components/macro' + +const StyledCheckbox = styled.input`` const CheckBox = ({ id }) => { const dispatch = useDispatch(); @@ -9,7 +12,7 @@ const CheckBox = ({ id }) => { } return ( - + ); } diff --git a/code/src/components/DeleteButton.js b/code/src/components/DeleteButton.js index 92c8af0d5..6a5b83be5 100644 --- a/code/src/components/DeleteButton.js +++ b/code/src/components/DeleteButton.js @@ -1,7 +1,7 @@ import React from 'react' import { useDispatch } from 'react-redux'; import { tasks } from 'reducers/tasks' -import styled from 'styled-components' +import styled from 'styled-components/macro' const StyledButton = styled.button` background-color: red; diff --git a/code/src/components/Task.js b/code/src/components/Task.js index 80a751e03..7e7a7aed0 100644 --- a/code/src/components/Task.js +++ b/code/src/components/Task.js @@ -1,10 +1,16 @@ import React from 'react' import { useSelector } from 'react-redux' -import styled from 'styled-components' +import styled from 'styled-components/macro' import CheckBox from './CheckBox' import DeleteButton from './DeleteButton' -const StyledContainer = styled.div`` +const StyledContainer = styled.div` +display: flex; +padding: 5px; +flex-direction: row; +align-items: center; +justify-content: space-around; +` const StyledText = styled.p` font-size: 12px; @@ -19,13 +25,13 @@ const Task = ({ id }) => { const task = useSelector((state) => state.tasks.todos.find((t) => t.id === id)) return ( + {task.text} - ); diff --git a/code/src/components/TaskAdder.js b/code/src/components/TaskAdder.js index 1a24e5d07..2a1c5dff7 100644 --- a/code/src/components/TaskAdder.js +++ b/code/src/components/TaskAdder.js @@ -1,10 +1,13 @@ import React, { useState } from 'react' import { useDispatch } from 'react-redux' import { tasks } from 'reducers/tasks' -import styled from 'styled-components' +import styled from 'styled-components/macro' import uniqid from 'uniqid' const StyledContainer = styled.div` +padding: 5px; +display: flex; +flex-direction: column; ` const StyledInput = styled.input` @@ -22,8 +25,8 @@ const TaskAdder = () => { return ( - setTodoText(e.target.value)} /> + ); } diff --git a/code/src/components/TaskList.js b/code/src/components/TaskList.js index 9f36afe3e..1421128c4 100644 --- a/code/src/components/TaskList.js +++ b/code/src/components/TaskList.js @@ -1,5 +1,5 @@ import React from 'react' -import styled from 'styled-components' +import styled from 'styled-components/macro' import { useSelector, useDispatch } from 'react-redux' import { tasks } from '../reducers/tasks' import Task from './Task' @@ -7,13 +7,32 @@ import Task from './Task' const StyledContainer = styled.div` display: flex; flex-direction: column; -gap: 5px;` +gap: 5px; +width: 100%;` -const CompleteAllButton = styled.button`background-color: green; +const StyledTasklistBar = styled.div` +background-color: var(--foreground-primary-color); + +h1 { + color: white; + text-align: center; +} + +` + +const StyledActionBar = styled.div` +display: flex; +flex-direction: row; +justify-content: center; +gap: 10px;` + +const CompleteAllButton = styled.button` +background-color: green; width: 15px; height: 15px;` -const DeleteAllButton = styled.button`background-color: red; +const DeleteAllButton = styled.button` +background-color: red; width: 15px; height: 15px;` @@ -30,12 +49,19 @@ const TaskList = () => { } const tasksData = useSelector((state) => state.tasks.todos) return ( -

Tasklist

- - + + + +

Tasklist

+
+ + + + {tasksData.map((task) => ( ))} -
); +
+ ); } export default TaskList; \ No newline at end of file diff --git a/code/src/components/Todos.js b/code/src/components/Todos.js index 496e80fb7..3bcde7496 100644 --- a/code/src/components/Todos.js +++ b/code/src/components/Todos.js @@ -1,13 +1,24 @@ import React from 'react' +import styled from 'styled-components/macro' import TaskAdder from './TaskAdder'; import TaskList from './TaskList'; +const TodoSection = styled.section` +display: flex; +flex-direction: column; +align-items: center; +background-color: var(--foreground-secondary-color); +overflow: visible; +box-shadow: + 0.3em 0.3em 1em rgba(0, 0, 0, 0.3); +` + const Todos = () => { return ( - <> - + - + + ); } diff --git a/code/src/index.css b/code/src/index.css index 4a1df4db7..c6e2ad773 100644 --- a/code/src/index.css +++ b/code/src/index.css @@ -1,3 +1,9 @@ +:root { + --background-color: rgb(228, 233, 255); + --foreground-primary-color: rgb(174, 128, 232); + --foreground-secondary-color: #fff; +} + body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", diff --git a/code/src/reducers/tasks.js b/code/src/reducers/tasks.js index 4f3226a7b..47304666e 100644 --- a/code/src/reducers/tasks.js +++ b/code/src/reducers/tasks.js @@ -20,10 +20,9 @@ export const tasks = createSlice({ name: 'tasks', deleteTask(state, action) { // state = state.filter((t) => t.id !== action.payload) const todo = state.todos.find((t) => t.id === action.payload) - state.splice(state.indexOf(todo), 1) + state.todos.splice(state.todos.indexOf(todo), 1) }, deleteAllTasks(state) { - /* eslint-disable no-unused-vars */ state.todos = [] }, completeAllTasks(state) { From f8d2e4de3e618f7c1fa9e1581311b6dff73f8a95 Mon Sep 17 00:00:00 2001 From: Ed Code Date: Thu, 20 Apr 2023 22:19:28 +0200 Subject: [PATCH 09/13] hamburger menu --- code/src/components/TaskList.js | 73 +++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/code/src/components/TaskList.js b/code/src/components/TaskList.js index 1421128c4..475e91507 100644 --- a/code/src/components/TaskList.js +++ b/code/src/components/TaskList.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useState } from 'react' import styled from 'styled-components/macro' import { useSelector, useDispatch } from 'react-redux' import { tasks } from '../reducers/tasks' @@ -11,9 +11,15 @@ gap: 5px; width: 100%;` const StyledTasklistBar = styled.div` +display: flex; +flex-direction: row; +justify-content: center; +padding: 5px; +align-items: center; background-color: var(--foreground-primary-color); h1 { + flex: 1; color: white; text-align: center; } @@ -21,22 +27,55 @@ h1 { ` const StyledActionBar = styled.div` -display: flex; -flex-direction: row; -justify-content: center; -gap: 10px;` +display: none; +height: 0px; +opacity: 0; +transition: opacity 1s ease-out; +overflow: hidden; + + +&.active { + opacity: 1; + height: auto; + display: flex; + flex-direction: row; + justify-content: center; + gap: 10px; + padding: 2px; +} +` + +const HamburgerMenuButton = styled.button` +width: 30px; +height: 30px; +background-color: inherit; +border: none; + +::before { + content: "="; +} +` const CompleteAllButton = styled.button` -background-color: green; -width: 15px; -height: 15px;` +font-size: 12px; +font-weight: 400; +background-color: transparent; +border: 1px solid grey; +border-radius: 3px; +width: 50%; +` -const DeleteAllButton = styled.button` -background-color: red; -width: 15px; -height: 15px;` +const DeleteAllButton = styled(CompleteAllButton)` +color: red; +` const TaskList = () => { + const [toggledActionBar, setToggledActionBar] = useState(true); + + const toggleActionBar = () => { + setToggledActionBar(!toggledActionBar); + } + const dispatch = useDispatch(); const handleCompleteAll = () => { @@ -51,12 +90,12 @@ const TaskList = () => { return ( - +

Tasklist

- - - + + complete all + delete all {tasksData.map((task) => ( ))} @@ -64,4 +103,4 @@ const TaskList = () => { ); } -export default TaskList; \ No newline at end of file +export default TaskList; From d65a63544c229167c241a7ad1fcfd235bc0ce5d9 Mon Sep 17 00:00:00 2001 From: Ed Code Date: Thu, 20 Apr 2023 22:54:26 +0200 Subject: [PATCH 10/13] styling --- code/package-lock.json | 77 +++++++++++++++++++++++++++++ code/package.json | 3 ++ code/public/index.html | 8 ++- code/src/components/DeleteButton.js | 14 +++--- code/src/components/Task.js | 24 ++++++--- code/src/components/TaskAdder.js | 17 +++++-- code/src/components/TaskList.js | 13 ++--- code/src/index.css | 4 +- 8 files changed, 132 insertions(+), 28 deletions(-) diff --git a/code/package-lock.json b/code/package-lock.json index de59857db..ca6677e36 100644 --- a/code/package-lock.json +++ b/code/package-lock.json @@ -9,6 +9,9 @@ "version": "1.0.0", "dependencies": { "@babel/eslint-parser": "^7.18.9", + "@fortawesome/fontawesome-svg-core": "^6.4.0", + "@fortawesome/free-solid-svg-icons": "^6.4.0", + "@fortawesome/react-fontawesome": "^0.2.0", "@reduxjs/toolkit": "^1.9.4", "eslint": "^8.21.0", "eslint-config-airbnb": "^19.0.4", @@ -2223,6 +2226,51 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz", + "integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz", + "integrity": "sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.4.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz", + "integrity": "sha512-kutPeRGWm8V5dltFP1zGjQOEAzaLZj4StdQhWVZnfGFCvAPVvHh8qk5bRrU4KXnRRRNni5tKQI9PBAdI6MP8nQ==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.4.0" + }, + "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.10.4", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", @@ -19095,6 +19143,35 @@ } } }, + "@fortawesome/fontawesome-common-types": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz", + "integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==" + }, + "@fortawesome/fontawesome-svg-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz", + "integrity": "sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.4.0" + } + }, + "@fortawesome/free-solid-svg-icons": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz", + "integrity": "sha512-kutPeRGWm8V5dltFP1zGjQOEAzaLZj4StdQhWVZnfGFCvAPVvHh8qk5bRrU4KXnRRRNni5tKQI9PBAdI6MP8nQ==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.4.0" + } + }, + "@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==", + "requires": { + "prop-types": "^15.8.1" + } + }, "@humanwhocodes/config-array": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", diff --git a/code/package.json b/code/package.json index cd89baf39..a0f3536bb 100644 --- a/code/package.json +++ b/code/package.json @@ -4,6 +4,9 @@ "private": true, "dependencies": { "@babel/eslint-parser": "^7.18.9", + "@fortawesome/fontawesome-svg-core": "^6.4.0", + "@fortawesome/free-solid-svg-icons": "^6.4.0", + "@fortawesome/react-fontawesome": "^0.2.0", "@reduxjs/toolkit": "^1.9.4", "eslint": "^8.21.0", "eslint-config-airbnb": "^19.0.4", diff --git a/code/public/index.html b/code/public/index.html index e6730aa66..fe993bc3d 100644 --- a/code/public/index.html +++ b/code/public/index.html @@ -1,6 +1,5 @@ - @@ -13,6 +12,12 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> + + + Technigo React App @@ -30,5 +35,4 @@ To create a production bundle, use `npm run build` or `yarn build`. --> - diff --git a/code/src/components/DeleteButton.js b/code/src/components/DeleteButton.js index 6a5b83be5..b830191fa 100644 --- a/code/src/components/DeleteButton.js +++ b/code/src/components/DeleteButton.js @@ -2,19 +2,21 @@ import React from 'react' import { useDispatch } from 'react-redux'; import { tasks } from 'reducers/tasks' import styled from 'styled-components/macro' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faX } from '@fortawesome/free-solid-svg-icons' const StyledButton = styled.button` -background-color: red; -width: 15px; -height: 15px;` - -const DeleteButton = ({ id }) => { +background-color: inherit; +border: none; +transition: color 0.2s ease-out; +` +const DeleteButton = ({ id, completed }) => { const dispatch = useDispatch(); const handleDelete = () => { dispatch(tasks.actions.deleteTask(id)) } - return (); + return (); } export default DeleteButton; \ No newline at end of file diff --git a/code/src/components/Task.js b/code/src/components/Task.js index 7e7a7aed0..f378d7395 100644 --- a/code/src/components/Task.js +++ b/code/src/components/Task.js @@ -1,8 +1,8 @@ import React from 'react' -import { useSelector } from 'react-redux' +import { useSelector, useDispatch } from 'react-redux' import styled from 'styled-components/macro' -import CheckBox from './CheckBox' import DeleteButton from './DeleteButton' +import { tasks } from '../reducers/tasks' const StyledContainer = styled.div` display: flex; @@ -13,26 +13,34 @@ justify-content: space-around; ` const StyledText = styled.p` -font-size: 12px; +font-weight: 400; +font-size: 15px; +color: var(--foreground-primary-color); +flex: 1; +text-align: center; +transition: color 0.1s ease-out; &.completed { - color: green; - text-decoration: line-through; + color: var(--background-color);; } ` const Task = ({ id }) => { + const dispatch = useDispatch(); + const checkComplete = () => { + dispatch(tasks.actions.completeTask(id)) + } const task = useSelector((state) => state.tasks.todos.find((t) => t.id === id)) return ( - - + + {task.text} - + ); } diff --git a/code/src/components/TaskAdder.js b/code/src/components/TaskAdder.js index 2a1c5dff7..7deca2f87 100644 --- a/code/src/components/TaskAdder.js +++ b/code/src/components/TaskAdder.js @@ -7,13 +7,24 @@ import uniqid from 'uniqid' const StyledContainer = styled.div` padding: 5px; display: flex; -flex-direction: column; +flex-direction: row; +background-color: var(--foreground-primary-color); ` const StyledInput = styled.input` +border: none; +height: 20px; +font-family: "Raleway"; ` -const StyledButton = styled.button`` +const StyledButton = styled.button` +background-color: var(--foreground-primary-color); +font-weight: 400; +color: white; +border: none; +font-family: "Raleway"; +font-size: 15px; +` const TaskAdder = () => { const [todoText, setTodoText] = useState(''); @@ -26,7 +37,7 @@ const TaskAdder = () => { return ( setTodoText(e.target.value)} /> - + task ); } diff --git a/code/src/components/TaskList.js b/code/src/components/TaskList.js index 475e91507..87acd0a66 100644 --- a/code/src/components/TaskList.js +++ b/code/src/components/TaskList.js @@ -1,6 +1,8 @@ import React, { useState } from 'react' import styled from 'styled-components/macro' import { useSelector, useDispatch } from 'react-redux' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faBars } from '@fortawesome/free-solid-svg-icons' import { tasks } from '../reducers/tasks' import Task from './Task' @@ -19,6 +21,7 @@ align-items: center; background-color: var(--foreground-primary-color); h1 { + font-size: 15px; flex: 1; color: white; text-align: center; @@ -50,10 +53,6 @@ width: 30px; height: 30px; background-color: inherit; border: none; - -::before { - content: "="; -} ` const CompleteAllButton = styled.button` @@ -90,8 +89,10 @@ const TaskList = () => { return ( - -

Tasklist

+ + + +

tasks

complete all diff --git a/code/src/index.css b/code/src/index.css index c6e2ad773..efb9b1439 100644 --- a/code/src/index.css +++ b/code/src/index.css @@ -6,9 +6,7 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: "Raleway"; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } From 92eadfe537ef921adffd0110ea677b70cdf1a479 Mon Sep 17 00:00:00 2001 From: Ed Code Date: Thu, 20 Apr 2023 23:05:20 +0200 Subject: [PATCH 11/13] more styling --- code/src/components/DeleteButton.js | 2 ++ code/src/components/Task.js | 15 +++++++++++---- code/src/components/TaskAdder.js | 2 ++ code/src/components/TaskList.js | 17 ++++++++++++----- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/code/src/components/DeleteButton.js b/code/src/components/DeleteButton.js index b830191fa..1e80b91ac 100644 --- a/code/src/components/DeleteButton.js +++ b/code/src/components/DeleteButton.js @@ -9,6 +9,8 @@ const StyledButton = styled.button` background-color: inherit; border: none; transition: color 0.2s ease-out; +cursor: pointer; + ` const DeleteButton = ({ id, completed }) => { const dispatch = useDispatch(); diff --git a/code/src/components/Task.js b/code/src/components/Task.js index f378d7395..8b82d4ff8 100644 --- a/code/src/components/Task.js +++ b/code/src/components/Task.js @@ -10,6 +10,7 @@ padding: 5px; flex-direction: row; align-items: center; justify-content: space-around; + ` const StyledText = styled.p` @@ -19,10 +20,14 @@ color: var(--foreground-primary-color); flex: 1; text-align: center; transition: color 0.1s ease-out; +cursor: pointer; + + &.completed { color: var(--background-color);; } + ` const Task = ({ id }) => { @@ -32,12 +37,14 @@ const Task = ({ id }) => { } const task = useSelector((state) => state.tasks.todos.find((t) => t.id === id)) return ( - + - + } + onClick={checkComplete}> {task.text} diff --git a/code/src/components/TaskAdder.js b/code/src/components/TaskAdder.js index 7deca2f87..4bffb1b4a 100644 --- a/code/src/components/TaskAdder.js +++ b/code/src/components/TaskAdder.js @@ -24,6 +24,8 @@ color: white; border: none; font-family: "Raleway"; font-size: 15px; +cursor: pointer; + ` const TaskAdder = () => { diff --git a/code/src/components/TaskList.js b/code/src/components/TaskList.js index 87acd0a66..d45039526 100644 --- a/code/src/components/TaskList.js +++ b/code/src/components/TaskList.js @@ -9,7 +9,7 @@ import Task from './Task' const StyledContainer = styled.div` display: flex; flex-direction: column; -gap: 5px; + width: 100%;` const StyledTasklistBar = styled.div` @@ -35,6 +35,8 @@ height: 0px; opacity: 0; transition: opacity 1s ease-out; overflow: hidden; +background-color: var(--foreground-primary-color); + &.active { @@ -53,15 +55,20 @@ width: 30px; height: 30px; background-color: inherit; border: none; +cursor: pointer; ` const CompleteAllButton = styled.button` -font-size: 12px; font-weight: 400; -background-color: transparent; -border: 1px solid grey; -border-radius: 3px; +color: white; +border: none; +font-family: "Raleway"; +font-size: 12px; width: 50%; +padding: 5px; +background-color: inherit; +cursor: pointer; + ` const DeleteAllButton = styled(CompleteAllButton)` From 3de4918ce07dbe3823577d4c7715eeefc724127b Mon Sep 17 00:00:00 2001 From: Ed Code Date: Mon, 24 Apr 2023 16:01:38 +0200 Subject: [PATCH 12/13] changed task data --- code/src/components/TaskList.js | 4 +++- code/src/reducers/tasks.js | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/code/src/components/TaskList.js b/code/src/components/TaskList.js index d45039526..2ed0d7e2c 100644 --- a/code/src/components/TaskList.js +++ b/code/src/components/TaskList.js @@ -72,7 +72,9 @@ cursor: pointer; ` const DeleteAllButton = styled(CompleteAllButton)` -color: red; +text-decoration: underline; +text-decoration-color: red; +text-underline-offset: 4px; ` const TaskList = () => { diff --git a/code/src/reducers/tasks.js b/code/src/reducers/tasks.js index 47304666e..c9167151d 100644 --- a/code/src/reducers/tasks.js +++ b/code/src/reducers/tasks.js @@ -3,10 +3,10 @@ import { createSlice } from '@reduxjs/toolkit' export const tasks = createSlice({ name: 'tasks', initialState: { todos: [ - { id: 0, text: 'Plugga', complete: true }, - { id: 1, text: 'Gamea', complete: false }, - { id: 2, text: 'Kodea', complete: true }, - { id: 3, text: 'Chilla', complete: true } + { id: 0, text: 'Study', complete: true }, + { id: 1, text: 'Work out', complete: false }, + { id: 2, text: 'Code', complete: true }, + { id: 3, text: 'Chill', complete: false } ] }, reducers: { From 8a9023cef9a73c5b40776d97091ff8da19b1ac5e Mon Sep 17 00:00:00 2001 From: Edvard Date: Mon, 24 Apr 2023 16:03:09 +0200 Subject: [PATCH 13/13] Update README.md --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e9b474ba2..04450b695 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,11 @@ # Project Todos -Replace this readme with your own information about your project. -Start by briefly describing the assignment in a sentence or two. Keep it short and to the point. ## The problem -Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next? + ## View it live -Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about. +https://reliable-torte-e7250c.netlify.app/