From 02636175c9f369419866d0ce0a47dcbbd5330760 Mon Sep 17 00:00:00 2001 From: yongjaechoi <88219703+yjc2021@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:48:42 +0900 Subject: [PATCH 01/12] =?UTF-8?q?5=EC=A3=BC=EC=B0=A8-=ED=94=84=EB=A1=9C?= =?UTF-8?q?=EC=A0=9D=ED=8A=B8=20TS=20=EA=B8=B0=EB=B3=B8=20=EB=B3=80?= =?UTF-8?q?=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../projects/FEDC5-3_VanillaJS_1/.gitignore | 24 + .../projects/FEDC5-3_VanillaJS_1/index.html | 13 + .../FEDC5-3_VanillaJS_1/package-lock.json | 732 ++++++++++++++++++ .../projects/FEDC5-3_VanillaJS_1/package.json | 15 + .../FEDC5-3_VanillaJS_1/public/vite.svg | 1 + .../FEDC5-3_VanillaJS_1/src/components/App.ts | 71 ++ .../src/components/Header.ts | 21 + .../src/components/TodoCount.ts | 40 + .../src/components/TodoForm.ts | 45 ++ .../src/components/TodoItem.ts | 41 + .../src/components/TodoList.ts | 45 ++ .../FEDC5-3_VanillaJS_1/src/counter.ts | 9 + .../projects/FEDC5-3_VanillaJS_1/src/main.ts | 11 + .../FEDC5-3_VanillaJS_1/src/typescript.svg | 1 + .../FEDC5-3_VanillaJS_1/src/utils/storage.ts | 28 + .../src/utils/validateState.ts | 45 ++ .../FEDC5-3_VanillaJS_1/src/vite-env.d.ts | 1 + .../FEDC5-3_VanillaJS_1/tsconfig.json | 23 + 18 files changed, 1166 insertions(+) create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/.gitignore create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/index.html create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/package-lock.json create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/package.json create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/public/vite.svg create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/counter.ts create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/main.ts create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/typescript.svg create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/vite-env.d.ts create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/tsconfig.json diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/.gitignore b/yongjae/projects/FEDC5-3_VanillaJS_1/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/index.html b/yongjae/projects/FEDC5-3_VanillaJS_1/index.html new file mode 100644 index 0000000..3f32d0c --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/index.html @@ -0,0 +1,13 @@ + + + + + + + TS Todo + + +
+ + + diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/package-lock.json b/yongjae/projects/FEDC5-3_VanillaJS_1/package-lock.json new file mode 100644 index 0000000..cffe8f2 --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/package-lock.json @@ -0,0 +1,732 @@ +{ + "name": "fedc5-3-vanillajs-1", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fedc5-3-vanillajs-1", + "version": "0.0.0", + "devDependencies": { + "typescript": "^5.2.2", + "vite": "^5.0.0" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.8.tgz", + "integrity": "sha512-31E2lxlGM1KEfivQl8Yf5aYU/mflz9g06H6S15ITUFQueMFtFjESRMoDSkvMo8thYvLBax+VKTPlpnx+sPicOA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.8.tgz", + "integrity": "sha512-B8JbS61bEunhfx8kasogFENgQfr/dIp+ggYXwTqdbMAgGDhRa3AaPpQMuQU0rNxDLECj6FhDzk1cF9WHMVwrtA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.8.tgz", + "integrity": "sha512-rdqqYfRIn4jWOp+lzQttYMa2Xar3OK9Yt2fhOhzFXqg0rVWEfSclJvZq5fZslnz6ypHvVf3CT7qyf0A5pM682A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.8.tgz", + "integrity": "sha512-RQw9DemMbIq35Bprbboyf8SmOr4UXsRVxJ97LgB55VKKeJOOdvsIPy0nFyF2l8U+h4PtBx/1kRf0BelOYCiQcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.8.tgz", + "integrity": "sha512-3sur80OT9YdeZwIVgERAysAbwncom7b4bCI2XKLjMfPymTud7e/oY4y+ci1XVp5TfQp/bppn7xLw1n/oSQY3/Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.8.tgz", + "integrity": "sha512-WAnPJSDattvS/XtPCTj1tPoTxERjcTpH6HsMr6ujTT+X6rylVe8ggxk8pVxzf5U1wh5sPODpawNicF5ta/9Tmw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.8.tgz", + "integrity": "sha512-ICvZyOplIjmmhjd6mxi+zxSdpPTKFfyPPQMQTK/w+8eNK6WV01AjIztJALDtwNNfFhfZLux0tZLC+U9nSyA5Zg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.8.tgz", + "integrity": "sha512-H4vmI5PYqSvosPaTJuEppU9oz1dq2A7Mr2vyg5TF9Ga+3+MGgBdGzcyBP7qK9MrwFQZlvNyJrvz6GuCaj3OukQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.8.tgz", + "integrity": "sha512-z1zMZivxDLHWnyGOctT9JP70h0beY54xDDDJt4VpTX+iwA77IFsE1vCXWmprajJGa+ZYSqkSbRQ4eyLCpCmiCQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.8.tgz", + "integrity": "sha512-1a8suQiFJmZz1khm/rDglOc8lavtzEMRo0v6WhPgxkrjcU0LkHj+TwBrALwoz/OtMExvsqbbMI0ChyelKabSvQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.8.tgz", + "integrity": "sha512-fHZWS2JJxnXt1uYJsDv9+b60WCc2RlvVAy1F76qOLtXRO+H4mjt3Tr6MJ5l7Q78X8KgCFudnTuiQRBhULUyBKQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.8.tgz", + "integrity": "sha512-Wy/z0EL5qZYLX66dVnEg9riiwls5IYnziwuju2oUiuxVc+/edvqXa04qNtbrs0Ukatg5HEzqT94Zs7J207dN5Q==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.8.tgz", + "integrity": "sha512-ETaW6245wK23YIEufhMQ3HSeHO7NgsLx8gygBVldRHKhOlD1oNeNy/P67mIh1zPn2Hr2HLieQrt6tWrVwuqrxg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.8.tgz", + "integrity": "sha512-T2DRQk55SgoleTP+DtPlMrxi/5r9AeFgkhkZ/B0ap99zmxtxdOixOMI570VjdRCs9pE4Wdkz7JYrsPvsl7eESg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.8.tgz", + "integrity": "sha512-NPxbdmmo3Bk7mbNeHmcCd7R7fptJaczPYBaELk6NcXxy7HLNyWwCyDJ/Xx+/YcNH7Im5dHdx9gZ5xIwyliQCbg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.8.tgz", + "integrity": "sha512-lytMAVOM3b1gPypL2TRmZ5rnXl7+6IIk8uB3eLsV1JwcizuolblXRrc5ShPrO9ls/b+RTp+E6gbsuLWHWi2zGg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.8.tgz", + "integrity": "sha512-hvWVo2VsXz/8NVt1UhLzxwAfo5sioj92uo0bCfLibB0xlOmimU/DeAEsQILlBQvkhrGjamP0/el5HU76HAitGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.8.tgz", + "integrity": "sha512-/7Y7u77rdvmGTxR83PgaSvSBJCC2L3Kb1M/+dmSIvRvQPXXCuC97QAwMugBNG0yGcbEGfFBH7ojPzAOxfGNkwQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.8.tgz", + "integrity": "sha512-9Lc4s7Oi98GqFA4HzA/W2JHIYfnXbUYgekUP/Sm4BG9sfLjyv6GKKHKKVs83SMicBF2JwAX6A1PuOLMqpD001w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.8.tgz", + "integrity": "sha512-rq6WzBGjSzihI9deW3fC2Gqiak68+b7qo5/3kmB6Gvbh/NYPA0sJhrnp7wgV4bNwjqM+R2AApXGxMO7ZoGhIJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.8.tgz", + "integrity": "sha512-AIAbverbg5jMvJznYiGhrd3sumfwWs8572mIJL5NQjJa06P8KfCPWZQ0NwZbPQnbQi9OWSZhFVSUWjjIrn4hSw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.8.tgz", + "integrity": "sha512-bfZ0cQ1uZs2PqpulNL5j/3w+GDhP36k1K5c38QdQg+Swy51jFZWWeIkteNsufkQxp986wnqRRsb/bHbY1WQ7TA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.6.1.tgz", + "integrity": "sha512-0WQ0ouLejaUCRsL93GD4uft3rOmB8qoQMU05Kb8CmMtMBe7XUDLAltxVZI1q6byNqEtU7N1ZX1Vw5lIpgulLQA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.6.1.tgz", + "integrity": "sha512-1TKm25Rn20vr5aTGGZqo6E4mzPicCUD79k17EgTLAsXc1zysyi4xXKACfUbwyANEPAEIxkzwue6JZ+stYzWUTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.6.1.tgz", + "integrity": "sha512-cEXJQY/ZqMACb+nxzDeX9IPLAg7S94xouJJCNVE5BJM8JUEP4HeTF+ti3cmxWeSJo+5D+o8Tc0UAWUkfENdeyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.6.1.tgz", + "integrity": "sha512-LoSU9Xu56isrkV2jLldcKspJ7sSXmZWkAxg7sW/RfF7GS4F5/v4EiqKSMCFbZtDu2Nc1gxxFdQdKwkKS4rwxNg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.6.1.tgz", + "integrity": "sha512-EfI3hzYAy5vFNDqpXsNxXcgRDcFHUWSx5nnRSCKwXuQlI5J9dD84g2Usw81n3FLBNsGCegKGwwTVsSKK9cooSQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.6.1.tgz", + "integrity": "sha512-9lhc4UZstsegbNLhH0Zu6TqvDfmhGzuCWtcTFXY10VjLLUe4Mr0Ye2L3rrtHaDd/J5+tFMEuo5LTCSCMXWfUKw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.6.1.tgz", + "integrity": "sha512-FfoOK1yP5ksX3wwZ4Zk1NgyGHZyuRhf99j64I5oEmirV8EFT7+OhUZEnP+x17lcP/QHJNWGsoJwrz4PJ9fBEXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.6.1.tgz", + "integrity": "sha512-DNGZvZDO5YF7jN5fX8ZqmGLjZEXIJRdJEdTFMhiyXqyXubBa0WVLDWSNlQ5JR2PNgDbEV1VQowhVRUh+74D+RA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.6.1.tgz", + "integrity": "sha512-RkJVNVRM+piYy87HrKmhbexCHg3A6Z6MU0W9GHnJwBQNBeyhCJG9KDce4SAMdicQnpURggSvtbGo9xAWOfSvIQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.6.1.tgz", + "integrity": "sha512-v2FVT6xfnnmTe3W9bJXl6r5KwJglMK/iRlkKiIFfO6ysKs0rDgz7Cwwf3tjldxQUrHL9INT/1r4VA0n9L/F1vQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.6.1.tgz", + "integrity": "sha512-YEeOjxRyEjqcWphH9dyLbzgkF8wZSKAKUkldRY6dgNR5oKs2LZazqGB41cWJ4Iqqcy9/zqYgmzBkRoVz3Q9MLw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.6.1.tgz", + "integrity": "sha512-0zfTlFAIhgz8V2G8STq8toAjsYYA6eci1hnXuyOTUFnymrtJwnS6uGKiv3v5UrPZkBlamLvrLV2iiaeqCKzb0A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/esbuild": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.8.tgz", + "integrity": "sha512-l7iffQpT2OrZfH2rXIp7/FkmaeZM0vxbxN9KfiCwGYuZqzMg/JdvX26R31Zxn/Pxvsrg3Y9N6XTcnknqDyyv4w==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.19.8", + "@esbuild/android-arm64": "0.19.8", + "@esbuild/android-x64": "0.19.8", + "@esbuild/darwin-arm64": "0.19.8", + "@esbuild/darwin-x64": "0.19.8", + "@esbuild/freebsd-arm64": "0.19.8", + "@esbuild/freebsd-x64": "0.19.8", + "@esbuild/linux-arm": "0.19.8", + "@esbuild/linux-arm64": "0.19.8", + "@esbuild/linux-ia32": "0.19.8", + "@esbuild/linux-loong64": "0.19.8", + "@esbuild/linux-mips64el": "0.19.8", + "@esbuild/linux-ppc64": "0.19.8", + "@esbuild/linux-riscv64": "0.19.8", + "@esbuild/linux-s390x": "0.19.8", + "@esbuild/linux-x64": "0.19.8", + "@esbuild/netbsd-x64": "0.19.8", + "@esbuild/openbsd-x64": "0.19.8", + "@esbuild/sunos-x64": "0.19.8", + "@esbuild/win32-arm64": "0.19.8", + "@esbuild/win32-ia32": "0.19.8", + "@esbuild/win32-x64": "0.19.8" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/postcss": { + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.6.1.tgz", + "integrity": "sha512-jZHaZotEHQaHLgKr8JnQiDT1rmatjgKlMekyksz+yk9jt/8z9quNjnKNRoaM0wd9DC2QKXjmWWuDYtM3jfF8pQ==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.6.1", + "@rollup/rollup-android-arm64": "4.6.1", + "@rollup/rollup-darwin-arm64": "4.6.1", + "@rollup/rollup-darwin-x64": "4.6.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.6.1", + "@rollup/rollup-linux-arm64-gnu": "4.6.1", + "@rollup/rollup-linux-arm64-musl": "4.6.1", + "@rollup/rollup-linux-x64-gnu": "4.6.1", + "@rollup/rollup-linux-x64-musl": "4.6.1", + "@rollup/rollup-win32-arm64-msvc": "4.6.1", + "@rollup/rollup-win32-ia32-msvc": "4.6.1", + "@rollup/rollup-win32-x64-msvc": "4.6.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/vite": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.6.tgz", + "integrity": "sha512-MD3joyAEBtV7QZPl2JVVUai6zHms3YOmLR+BpMzLlX2Yzjfcc4gTgNi09d/Rua3F4EtC8zdwPU8eQYyib4vVMQ==", + "dev": true, + "dependencies": { + "esbuild": "^0.19.3", + "postcss": "^8.4.32", + "rollup": "^4.2.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + } + } +} diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/package.json b/yongjae/projects/FEDC5-3_VanillaJS_1/package.json new file mode 100644 index 0000000..d35041d --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/package.json @@ -0,0 +1,15 @@ +{ + "name": "fedc5-3-vanillajs-1", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "devDependencies": { + "typescript": "^5.2.2", + "vite": "^5.0.0" + } +} diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/public/vite.svg b/yongjae/projects/FEDC5-3_VanillaJS_1/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts new file mode 100644 index 0000000..d356271 --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts @@ -0,0 +1,71 @@ +import { setItem } from "../utils/storage"; +import { TodoState, validateState } from "../utils/validateState"; +import Header from "./Header"; +import TodoCount from "./TodoCount"; +import TodoForm from "./TodoForm"; +import TodoList from "./TodoList"; + +interface AppProps { + $target: HTMLElement; + initialState: any; +} + +// 임시 Context : this의 property를 정의하는 부분 +interface AppContext {} +const App = function (this: AppContext, { $target, initialState }: AppProps) { + // ... + initialState = validateState(initialState); + + const syncState = (state: TodoState) => { + const validatedState = validateState(state).map((val, idx) => ({ + ...val, + id: idx, + })); + todoList.setState(validatedState); + todoCount.setState(validatedState); + }; + new Header({ + $target, + text: "Renewed Todo List", + }); + + new TodoForm({ + $target, + onSubmit: (text: string) => { + const nextState = [ + ...todoList.state, + { id: todoList.state.length, text, isCompleted: false }, + ]; + + syncState(nextState); + + setItem("todos", JSON.stringify(nextState)); + }, + }); + + const todoList = new TodoList({ + $target, + initialState, + onToggle: (todoId: number) => { + const nextState = todoList.state.map((todo) => { + if (todo.id === todoId) todo.isCompleted = !todo.isCompleted; + return todo; + }); + syncState(nextState); + }, + onDelete: (todoId: number) => { + const nextState = todoList.state.filter((todo) => { + if (todo.id === todoId) return false; + return true; + }); + syncState(nextState); + }, + }); + + const todoCount = new TodoCount({ + $target, + initialState, + }); +} as any as { new (props: AppProps): AppContext }; + +export default App; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts new file mode 100644 index 0000000..b90d492 --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts @@ -0,0 +1,21 @@ +interface HeaderProps { + $target: HTMLElement; + text: string; +} +interface HeaderContext { + render: () => void; +} + +const Header = function (this: HeaderContext, { $target, text }: HeaderProps) { + const $header = document.createElement("h1"); + + $target.appendChild($header); + + this.render = () => { + $header.textContent = text; + }; + + this.render(); +} as any as { new (props: HeaderProps): HeaderContext }; + +export default Header; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts new file mode 100644 index 0000000..3629438 --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts @@ -0,0 +1,40 @@ +interface TodoCountProps { + $target: HTMLElement; + initialState: StateContext[]; +} +type StateContext = { + isCompleted: boolean; +}; +// 임시 Context : this의 property를 정의하는 부분 +interface TodoCountContext { + state: StateContext[]; + setState: (nextState: StateContext[]) => void; + render: () => void; +} +const TodoCount = function ( + this: TodoCountContext, + { $target, initialState }: TodoCountProps +) { + this.state = initialState; + + const $todoCount = document.createElement("h3"); + $target.appendChild($todoCount); + + this.setState = (nextState: StateContext[]) => { + this.state = nextState; + this.render(); + }; + + this.render = () => { + const completedNum = this.state.filter( + ({ isCompleted }) => isCompleted + ).length; + + const totalNum = this.state.length; + $todoCount.innerHTML = `${completedNum} / ${totalNum}`; + }; + + this.render(); +} as any as { new (props: TodoCountProps): TodoCountContext }; + +export default TodoCount; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts new file mode 100644 index 0000000..c4919a7 --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts @@ -0,0 +1,45 @@ +interface TodoFormContext { + render: () => void; +} +interface TodoFormProps { + $target: HTMLElement; + onSubmit: (text: string) => void; +} + +const TodoForm = function ( + this: TodoFormContext, + { $target, onSubmit }: TodoFormProps +) { + const $form = document.createElement("form"); + let isInit = false; + $target.appendChild($form); + + this.render = () => { + $form.innerHTML = ` + + `; + if (!isInit) { + $form.addEventListener("submit", (e) => { + e.preventDefault(); + + const $todo = $form.querySelector( + `input[name=todo]` + ) as HTMLInputElement; + + let text = ""; + if ($todo && $todo.value) { + text = $todo.value; + } + + if (text.length > 1 && text.trim()) { + $todo.value = ""; + onSubmit(text); + } + }); + } + }; + + this.render(); +} as any as { new (props: TodoFormProps): TodoFormContext }; + +export default TodoForm; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts new file mode 100644 index 0000000..ce4fee8 --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts @@ -0,0 +1,41 @@ +type ValueContext = { + id: number; + text: string; + isCompleted: boolean; +}; +type TodoItemProps = { + $target: HTMLElement; + initialValue: ValueContext; + onToggle: (id: number) => void; + onDelete: (id: number) => void; +}; +type TodoItemContext = { + render: () => void; +}; +const TodoItem = function ( + this: TodoItemContext, + { $target, initialValue, onToggle, onDelete }: TodoItemProps +) { + const { id, text, isCompleted } = initialValue; + + const $todoItem = document.createElement("li"); + $todoItem.textContent = text; + $todoItem.style.textDecoration = isCompleted ? "line-through" : "none"; + const $todoButton = document.createElement("button"); + $todoButton.textContent = "삭제"; + + $todoItem.appendChild($todoButton); + $target.appendChild($todoItem); + + this.render = () => { + $todoButton.addEventListener("click", () => { + onDelete(id); + }); + $todoItem.addEventListener("click", () => { + onToggle(id); + }); + }; + this.render(); +} as any as { new (props: TodoItemProps): TodoItemContext }; + +export default TodoItem; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts new file mode 100644 index 0000000..00783e5 --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts @@ -0,0 +1,45 @@ +import { setItem } from "../utils/storage"; +import { TodoState } from "../utils/validateState"; +import TodoItem from "./TodoItem"; + +interface TodoListContext { + state: TodoState; + setState: (nextState: any) => void; + render: () => void; +} +interface TodoListProps { + $target: HTMLElement; + initialState: any; + onToggle: (id: number) => void; + onDelete: (id: number) => void; +} +const TodoList = function ( + this: TodoListContext, + { initialState, $target, onToggle, onDelete }: TodoListProps +) { + this.state = initialState; + + const $todoList = document.createElement("ul"); + $target.appendChild($todoList); + + this.setState = (nextState: any) => { + this.state = nextState; + setItem("todos", JSON.stringify(this.state)); + this.render(); + }; + + this.render = () => { + $todoList.innerHTML = ""; + this.state.map( + (itemContext: any) => + new TodoItem({ + $target: $todoList, + initialValue: itemContext, + onToggle, + onDelete, + }) + ); + }; +} as any as { new (props: TodoListProps): TodoListContext }; + +export default TodoList; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/counter.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/counter.ts new file mode 100644 index 0000000..09e5afd --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/counter.ts @@ -0,0 +1,9 @@ +export function setupCounter(element: HTMLButtonElement) { + let counter = 0 + const setCounter = (count: number) => { + counter = count + element.innerHTML = `count is ${counter}` + } + element.addEventListener('click', () => setCounter(counter + 1)) + setCounter(0) +} diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/main.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/main.ts new file mode 100644 index 0000000..75b21cd --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/main.ts @@ -0,0 +1,11 @@ +import { getItem } from "./utils/storage"; +import App from "./components/App.ts"; + +const initialState = getItem("todos", []); + +const $app = document.querySelector("#app")!; + +new App({ + $target: $app, + initialState, +}); diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/typescript.svg b/yongjae/projects/FEDC5-3_VanillaJS_1/src/typescript.svg new file mode 100644 index 0000000..d91c910 --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/typescript.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts new file mode 100644 index 0000000..29409a6 --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts @@ -0,0 +1,28 @@ +import { TodoState } from "./validateState"; + +const storage = window.localStorage; + +export const setItem = (key: string, value: string) => { + try { + storage.setItem(key, value); + } catch (e: unknown) { + if (e instanceof Error) { + console.error(e); + } + } +}; + +export const getItem = (key: string, defaultValue: TodoState) => { + try { + const storedValue = storage.getItem(key); + if (storedValue) { + return JSON.parse(storedValue); + } + return defaultValue; + } catch (e: unknown) { + if (e instanceof Error) { + console.error(e); + return defaultValue; + } + } +}; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts new file mode 100644 index 0000000..b208ce8 --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts @@ -0,0 +1,45 @@ +export interface TodoItemContext { + text: string; + id: number; + isCompleted: boolean; +} +export type TodoState = TodoItemContext[]; + +// todo 상태의 유효검사 함수 +export function validateState(state: TodoState, origin = []) { + if ( + Array.isArray(state) && + state.every( + (val) => + val && + Object.hasOwn(val, "text") && + val.text.split(" ").join("").length && + Object.hasOwn(val, "isCompleted") && + typeof val.isCompleted === "boolean" && + Object.hasOwn(val, "id") && + typeof val.id === "number" + ) + ) + return state; + return origin; +} + +export function filterValidStorageState(state: TodoState, defaultState = []) { + try { + return state + .filter( + (val) => + val && + Object.hasOwn(val, "text") && + val.text.split(" ").join("").length && + Object.hasOwn(val, "isCompleted") && + typeof val.isCompleted === "boolean" && + Object.hasOwn(val, "id") && + typeof val.id === "number" + ) + .map((val, idx) => ({ ...val, id: idx })); + } catch (e) { + console.log(e); + return defaultState; + } +} diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/vite-env.d.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/tsconfig.json b/yongjae/projects/FEDC5-3_VanillaJS_1/tsconfig.json new file mode 100644 index 0000000..f28fcc0 --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} From a6cbae6b61b3c8c7e6f176f958d67e47282c9844 Mon Sep 17 00:00:00 2001 From: yongjaechoi <88219703+yjc2021@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:58:55 +0900 Subject: [PATCH 02/12] =?UTF-8?q?5=EC=A3=BC=EC=B0=A8-fix:=20TodoList=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=20render=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts index 00783e5..9fac694 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts @@ -40,6 +40,7 @@ const TodoList = function ( }) ); }; + this.render(); } as any as { new (props: TodoListProps): TodoListContext }; export default TodoList; From c4cacc556b3145d02b5735f4c11095eb54589bf3 Mon Sep 17 00:00:00 2001 From: yongjaechoi <88219703+yjc2021@users.noreply.github.com> Date: Mon, 11 Dec 2023 12:26:52 +0900 Subject: [PATCH 03/12] =?UTF-8?q?refactor:=20=ED=83=80=EC=9E=85=20naming?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FEDC5-3_VanillaJS_1/src/components/App.ts | 5 +++-- .../src/components/TodoCount.ts | 14 +++++++------- .../FEDC5-3_VanillaJS_1/src/components/TodoItem.ts | 9 +++------ .../FEDC5-3_VanillaJS_1/src/components/TodoList.ts | 4 ++-- .../projects/FEDC5-3_VanillaJS_1/src/types/todo.ts | 6 ++++++ .../FEDC5-3_VanillaJS_1/src/utils/validateState.ts | 12 +++--------- 6 files changed, 24 insertions(+), 26 deletions(-) create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/types/todo.ts diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts index d356271..8db1880 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts @@ -1,5 +1,6 @@ +import { TodosType } from "../types/todo"; import { setItem } from "../utils/storage"; -import { TodoState, validateState } from "../utils/validateState"; +import { validateState } from "../utils/validateState"; import Header from "./Header"; import TodoCount from "./TodoCount"; import TodoForm from "./TodoForm"; @@ -16,7 +17,7 @@ const App = function (this: AppContext, { $target, initialState }: AppProps) { // ... initialState = validateState(initialState); - const syncState = (state: TodoState) => { + const syncState = (state: TodosType) => { const validatedState = validateState(state).map((val, idx) => ({ ...val, id: idx, diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts index 3629438..a1208f6 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts @@ -1,14 +1,14 @@ +import { TodosType } from "../types/todo"; + interface TodoCountProps { $target: HTMLElement; - initialState: StateContext[]; + initialState: TodosType; } -type StateContext = { - isCompleted: boolean; -}; + // 임시 Context : this의 property를 정의하는 부분 interface TodoCountContext { - state: StateContext[]; - setState: (nextState: StateContext[]) => void; + state: TodosType; + setState: (nextState: TodosType) => void; render: () => void; } const TodoCount = function ( @@ -20,7 +20,7 @@ const TodoCount = function ( const $todoCount = document.createElement("h3"); $target.appendChild($todoCount); - this.setState = (nextState: StateContext[]) => { + this.setState = (nextState: TodosType) => { this.state = nextState; this.render(); }; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts index ce4fee8..8858380 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts @@ -1,11 +1,8 @@ -type ValueContext = { - id: number; - text: string; - isCompleted: boolean; -}; +import { TodoType } from "../types/todo"; + type TodoItemProps = { $target: HTMLElement; - initialValue: ValueContext; + initialValue: TodoType; onToggle: (id: number) => void; onDelete: (id: number) => void; }; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts index 9fac694..b6258ba 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts @@ -1,9 +1,9 @@ +import { TodosType } from "../types/todo"; import { setItem } from "../utils/storage"; -import { TodoState } from "../utils/validateState"; import TodoItem from "./TodoItem"; interface TodoListContext { - state: TodoState; + state: TodosType; setState: (nextState: any) => void; render: () => void; } diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/todo.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/todo.ts new file mode 100644 index 0000000..19b0869 --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/todo.ts @@ -0,0 +1,6 @@ +export interface TodoType { + text: string; + id: number; + isCompleted: boolean; +} +export type TodosType = TodoType[]; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts index b208ce8..814a940 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts @@ -1,12 +1,6 @@ -export interface TodoItemContext { - text: string; - id: number; - isCompleted: boolean; -} -export type TodoState = TodoItemContext[]; - +import { TodosType } from "../types/todo"; // todo 상태의 유효검사 함수 -export function validateState(state: TodoState, origin = []) { +export function validateState(state: TodosType, origin = []) { if ( Array.isArray(state) && state.every( @@ -24,7 +18,7 @@ export function validateState(state: TodoState, origin = []) { return origin; } -export function filterValidStorageState(state: TodoState, defaultState = []) { +export function filterValidStorageState(state: TodosType, defaultState = []) { try { return state .filter( From c7900a2095d817b2d787d0f189fe1add77f2314e Mon Sep 17 00:00:00 2001 From: yongjaechoi <88219703+yjc2021@users.noreply.github.com> Date: Mon, 11 Dec 2023 17:26:10 +0900 Subject: [PATCH 04/12] =?UTF-8?q?refactor:=20storage=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=20=EC=A0=9C=EB=84=A4=EB=A6=AD=20=EC=A0=81=EC=9A=A9=20=EB=B0=8F?= =?UTF-8?q?=20=EC=9D=B8=EC=88=98=20=ED=83=80=EC=9E=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FEDC5-3_VanillaJS_1/src/components/App.ts | 2 +- .../src/components/TodoList.ts | 2 +- .../projects/FEDC5-3_VanillaJS_1/src/counter.ts | 9 --------- .../FEDC5-3_VanillaJS_1/src/utils/storage.ts | 17 +++++++++++++---- .../src/utils/validateState.ts | 9 +++++++-- 5 files changed, 22 insertions(+), 17 deletions(-) delete mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/counter.ts diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts index 8db1880..a1b3dcc 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts @@ -40,7 +40,7 @@ const App = function (this: AppContext, { $target, initialState }: AppProps) { syncState(nextState); - setItem("todos", JSON.stringify(nextState)); + setItem("todos", nextState); }, }); diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts index b6258ba..d8a92ed 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts @@ -24,7 +24,7 @@ const TodoList = function ( this.setState = (nextState: any) => { this.state = nextState; - setItem("todos", JSON.stringify(this.state)); + setItem("todos", this.state); this.render(); }; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/counter.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/counter.ts deleted file mode 100644 index 09e5afd..0000000 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/counter.ts +++ /dev/null @@ -1,9 +0,0 @@ -export function setupCounter(element: HTMLButtonElement) { - let counter = 0 - const setCounter = (count: number) => { - counter = count - element.innerHTML = `count is ${counter}` - } - element.addEventListener('click', () => setCounter(counter + 1)) - setCounter(0) -} diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts index 29409a6..764fdc3 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts @@ -1,10 +1,16 @@ -import { TodoState } from "./validateState"; +import { TodosType } from "../types/todo"; + +export type setStorage = (key: string, value: T) => void; +export type getStorage = (key: string, defaultValue: T) => T; const storage = window.localStorage; -export const setItem = (key: string, value: string) => { +export const setItem: setStorage = ( + key: string, + value: TodosType +) => { try { - storage.setItem(key, value); + storage.setItem(key, JSON.stringify(value)); } catch (e: unknown) { if (e instanceof Error) { console.error(e); @@ -12,7 +18,10 @@ export const setItem = (key: string, value: string) => { } }; -export const getItem = (key: string, defaultValue: TodoState) => { +export const getItem: getStorage = ( + key: string, + defaultValue = [] as TodosType +) => { try { const storedValue = storage.getItem(key); if (storedValue) { diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts index 814a940..b9108f6 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts @@ -18,7 +18,10 @@ export function validateState(state: TodosType, origin = []) { return origin; } -export function filterValidStorageState(state: TodosType, defaultState = []) { +export function filterValidStorageState( + state: TodosType, + defaultState = [] as TodosType +) { try { return state .filter( @@ -33,7 +36,9 @@ export function filterValidStorageState(state: TodosType, defaultState = []) { ) .map((val, idx) => ({ ...val, id: idx })); } catch (e) { - console.log(e); + if (e instanceof Error) { + console.log(e); + } return defaultState; } } From 550200344029d62db8092f878347d53fdc3c42ef Mon Sep 17 00:00:00 2001 From: yongjaechoi <88219703+yjc2021@users.noreply.github.com> Date: Mon, 11 Dec 2023 17:39:06 +0900 Subject: [PATCH 05/12] =?UTF-8?q?refactor:=20any=20=ED=83=80=EC=9D=B4?= =?UTF-8?q?=ED=95=91=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FEDC5-3_VanillaJS_1/src/components/TodoList.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts index d8a92ed..bc76f99 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts @@ -4,12 +4,12 @@ import TodoItem from "./TodoItem"; interface TodoListContext { state: TodosType; - setState: (nextState: any) => void; + setState: (nextState: TodosType) => void; render: () => void; } interface TodoListProps { $target: HTMLElement; - initialState: any; + initialState: TodosType; onToggle: (id: number) => void; onDelete: (id: number) => void; } @@ -22,7 +22,7 @@ const TodoList = function ( const $todoList = document.createElement("ul"); $target.appendChild($todoList); - this.setState = (nextState: any) => { + this.setState = (nextState: TodosType) => { this.state = nextState; setItem("todos", this.state); this.render(); @@ -31,7 +31,7 @@ const TodoList = function ( this.render = () => { $todoList.innerHTML = ""; this.state.map( - (itemContext: any) => + (itemContext) => new TodoItem({ $target: $todoList, initialValue: itemContext, From db556ee797bd3123d00eb99e680e7bf7bbb381f6 Mon Sep 17 00:00:00 2001 From: yongjaechoi <88219703+yjc2021@users.noreply.github.com> Date: Mon, 11 Dec 2023 18:08:12 +0900 Subject: [PATCH 06/12] =?UTF-8?q?refactor:=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20context=20=ED=83=80=EC=9D=B4=ED=95=91=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FEDC5-3_VanillaJS_1/src/components/App.ts | 2 +- .../src/components/Header.ts | 12 +++++----- .../src/components/TodoCount.ts | 12 +++------- .../src/components/TodoForm.ts | 9 ++++---- .../src/components/TodoItem.ts | 10 ++++----- .../src/components/TodoList.ts | 11 +++------- .../FEDC5-3_VanillaJS_1/src/types/todo.ts | 22 +++++++++++++++++++ 7 files changed, 44 insertions(+), 34 deletions(-) diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts index a1b3dcc..6fd40d3 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts @@ -8,7 +8,7 @@ import TodoList from "./TodoList"; interface AppProps { $target: HTMLElement; - initialState: any; + initialState: TodosType; } // 임시 Context : this의 property를 정의하는 부분 diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts index b90d492..1169810 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts @@ -1,12 +1,14 @@ +import { TodoComponentStatelessContext } from "../types/todo"; + interface HeaderProps { $target: HTMLElement; text: string; } -interface HeaderContext { - render: () => void; -} -const Header = function (this: HeaderContext, { $target, text }: HeaderProps) { +const Header = function ( + this: TodoComponentStatelessContext, + { $target, text }: HeaderProps +) { const $header = document.createElement("h1"); $target.appendChild($header); @@ -16,6 +18,6 @@ const Header = function (this: HeaderContext, { $target, text }: HeaderProps) { }; this.render(); -} as any as { new (props: HeaderProps): HeaderContext }; +} as any as { new (props: HeaderProps): TodoComponentStatelessContext }; export default Header; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts index a1208f6..1566776 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts @@ -1,18 +1,12 @@ -import { TodosType } from "../types/todo"; +import { TodoComponentStatefulContext, TodosType } from "../types/todo"; interface TodoCountProps { $target: HTMLElement; initialState: TodosType; } -// 임시 Context : this의 property를 정의하는 부분 -interface TodoCountContext { - state: TodosType; - setState: (nextState: TodosType) => void; - render: () => void; -} const TodoCount = function ( - this: TodoCountContext, + this: TodoComponentStatefulContext, { $target, initialState }: TodoCountProps ) { this.state = initialState; @@ -35,6 +29,6 @@ const TodoCount = function ( }; this.render(); -} as any as { new (props: TodoCountProps): TodoCountContext }; +} as any as { new (props: TodoCountProps): TodoComponentStatefulContext }; export default TodoCount; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts index c4919a7..1cfdda1 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts @@ -1,13 +1,12 @@ -interface TodoFormContext { - render: () => void; -} +import { TodoComponentStatelessContext } from "../types/todo"; + interface TodoFormProps { $target: HTMLElement; onSubmit: (text: string) => void; } const TodoForm = function ( - this: TodoFormContext, + this: TodoComponentStatelessContext, { $target, onSubmit }: TodoFormProps ) { const $form = document.createElement("form"); @@ -40,6 +39,6 @@ const TodoForm = function ( }; this.render(); -} as any as { new (props: TodoFormProps): TodoFormContext }; +} as any as { new (props: TodoFormProps): TodoComponentStatelessContext }; export default TodoForm; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts index 8858380..63f3473 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts @@ -1,4 +1,4 @@ -import { TodoType } from "../types/todo"; +import { TodoComponentStatelessContext, TodoType } from "../types/todo"; type TodoItemProps = { $target: HTMLElement; @@ -6,11 +6,9 @@ type TodoItemProps = { onToggle: (id: number) => void; onDelete: (id: number) => void; }; -type TodoItemContext = { - render: () => void; -}; + const TodoItem = function ( - this: TodoItemContext, + this: TodoComponentStatelessContext, { $target, initialValue, onToggle, onDelete }: TodoItemProps ) { const { id, text, isCompleted } = initialValue; @@ -33,6 +31,6 @@ const TodoItem = function ( }); }; this.render(); -} as any as { new (props: TodoItemProps): TodoItemContext }; +} as any as { new (props: TodoItemProps): TodoComponentStatelessContext }; export default TodoItem; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts index bc76f99..e8cdbc9 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts @@ -1,12 +1,7 @@ -import { TodosType } from "../types/todo"; +import { TodoComponentStatefulContext, TodosType } from "../types/todo"; import { setItem } from "../utils/storage"; import TodoItem from "./TodoItem"; -interface TodoListContext { - state: TodosType; - setState: (nextState: TodosType) => void; - render: () => void; -} interface TodoListProps { $target: HTMLElement; initialState: TodosType; @@ -14,7 +9,7 @@ interface TodoListProps { onDelete: (id: number) => void; } const TodoList = function ( - this: TodoListContext, + this: TodoComponentStatefulContext, { initialState, $target, onToggle, onDelete }: TodoListProps ) { this.state = initialState; @@ -41,6 +36,6 @@ const TodoList = function ( ); }; this.render(); -} as any as { new (props: TodoListProps): TodoListContext }; +} as any as { new (props: TodoListProps): TodoComponentStatefulContext }; export default TodoList; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/todo.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/todo.ts index 19b0869..f2acec3 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/todo.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/todo.ts @@ -4,3 +4,25 @@ export interface TodoType { isCompleted: boolean; } export type TodosType = TodoType[]; + +// 컴포넌트 구조 typing +interface CoreComponentContext { + state?: T; + setState?: (nextState: T) => void; + render: () => void; +} +type StatefulComponentContext = { + [K in keyof CoreComponentContext]-?: CoreComponentContext[K]; +}; +type StatelessComponentContext = Omit< + CoreComponentContext, + "state" | "setState" +>; +export type TodoComponentContext = CoreComponentContext; +export type TodoComponentStatefulContext = StatefulComponentContext; +export type TodoComponentStatelessContext = + StatelessComponentContext; + +interface CoreComponentProps { + $target: HTMLElement; +} From cc7092da1f9dc48cf4aaf16170ffc07effcc1a71 Mon Sep 17 00:00:00 2001 From: yongjaechoi <88219703+yjc2021@users.noreply.github.com> Date: Mon, 11 Dec 2023 19:07:44 +0900 Subject: [PATCH 07/12] =?UTF-8?q?refactor:=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20props=20=ED=83=80=EC=9D=B4=ED=95=91=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FEDC5-3_VanillaJS_1/src/components/App.ts | 15 ++++++--------- .../src/components/Header.ts | 10 +++++----- .../src/components/TodoCount.ts | 17 +++++++++-------- .../src/components/TodoForm.ts | 10 ++++++---- .../src/components/TodoItem.ts | 11 +++++++---- .../src/components/TodoList.ts | 12 +++++++----- .../src/types/{todo.ts => index.ts} | 14 +++++++++++++- .../FEDC5-3_VanillaJS_1/src/utils/storage.ts | 2 +- .../src/utils/validateState.ts | 2 +- 9 files changed, 55 insertions(+), 38 deletions(-) rename yongjae/projects/FEDC5-3_VanillaJS_1/src/types/{todo.ts => index.ts} (67%) diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts index 6fd40d3..c658c74 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts @@ -1,4 +1,4 @@ -import { TodosType } from "../types/todo"; +import { TodoComponentStatefulProps, TodosType } from "../types"; import { setItem } from "../utils/storage"; import { validateState } from "../utils/validateState"; import Header from "./Header"; @@ -6,14 +6,11 @@ import TodoCount from "./TodoCount"; import TodoForm from "./TodoForm"; import TodoList from "./TodoList"; -interface AppProps { - $target: HTMLElement; - initialState: TodosType; -} - -// 임시 Context : this의 property를 정의하는 부분 interface AppContext {} -const App = function (this: AppContext, { $target, initialState }: AppProps) { +const App = function ( + this: AppContext, + { $target, initialState }: TodoComponentStatefulProps +) { // ... initialState = validateState(initialState); @@ -67,6 +64,6 @@ const App = function (this: AppContext, { $target, initialState }: AppProps) { $target, initialState, }); -} as any as { new (props: AppProps): AppContext }; +} as any as { new (props: TodoComponentStatefulProps): AppContext }; export default App; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts index 1169810..ad82845 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts @@ -1,9 +1,9 @@ -import { TodoComponentStatelessContext } from "../types/todo"; +import { + TodoComponentStatelessContext, + TodoComponentStatelessProps, +} from "../types"; -interface HeaderProps { - $target: HTMLElement; - text: string; -} +type HeaderProps = TodoComponentStatelessProps<{ text: string }>; const Header = function ( this: TodoComponentStatelessContext, diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts index 1566776..ead33c2 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts @@ -1,13 +1,12 @@ -import { TodoComponentStatefulContext, TodosType } from "../types/todo"; - -interface TodoCountProps { - $target: HTMLElement; - initialState: TodosType; -} +import { + TodoComponentStatefulContext, + TodoComponentStatefulProps, + TodosType, +} from "../types"; const TodoCount = function ( this: TodoComponentStatefulContext, - { $target, initialState }: TodoCountProps + { $target, initialState }: TodoComponentStatefulProps ) { this.state = initialState; @@ -29,6 +28,8 @@ const TodoCount = function ( }; this.render(); -} as any as { new (props: TodoCountProps): TodoComponentStatefulContext }; +} as any as { + new (props: TodoComponentStatefulProps): TodoComponentStatefulContext; +}; export default TodoCount; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts index 1cfdda1..a86a886 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts @@ -1,9 +1,11 @@ -import { TodoComponentStatelessContext } from "../types/todo"; +import { + TodoComponentStatelessContext, + TodoComponentStatelessProps, +} from "../types"; -interface TodoFormProps { - $target: HTMLElement; +type TodoFormProps = TodoComponentStatelessProps<{ onSubmit: (text: string) => void; -} +}>; const TodoForm = function ( this: TodoComponentStatelessContext, diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts index 63f3473..83ba2e0 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts @@ -1,11 +1,14 @@ -import { TodoComponentStatelessContext, TodoType } from "../types/todo"; +import { + TodoComponentStatelessContext, + TodoComponentStatelessProps, + TodoType, +} from "../types"; -type TodoItemProps = { - $target: HTMLElement; +type TodoItemProps = TodoComponentStatelessProps<{ initialValue: TodoType; onToggle: (id: number) => void; onDelete: (id: number) => void; -}; +}>; const TodoItem = function ( this: TodoComponentStatelessContext, diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts index e8cdbc9..0fef739 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts @@ -1,13 +1,15 @@ -import { TodoComponentStatefulContext, TodosType } from "../types/todo"; +import { + TodoComponentStatefulContext, + TodoComponentStatefulProps, + TodosType, +} from "../types"; import { setItem } from "../utils/storage"; import TodoItem from "./TodoItem"; -interface TodoListProps { - $target: HTMLElement; - initialState: TodosType; +type TodoListProps = TodoComponentStatefulProps<{ onToggle: (id: number) => void; onDelete: (id: number) => void; -} +}>; const TodoList = function ( this: TodoComponentStatefulContext, { initialState, $target, onToggle, onDelete }: TodoListProps diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/todo.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/index.ts similarity index 67% rename from yongjae/projects/FEDC5-3_VanillaJS_1/src/types/todo.ts rename to yongjae/projects/FEDC5-3_VanillaJS_1/src/types/index.ts index f2acec3..ed5d61d 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/todo.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/index.ts @@ -23,6 +23,18 @@ export type TodoComponentStatefulContext = StatefulComponentContext; export type TodoComponentStatelessContext = StatelessComponentContext; -interface CoreComponentProps { +export interface CoreComponentProps { $target: HTMLElement; } + +export interface StatefulComponentProps extends CoreComponentProps { + initialState: T; +} + +export type TodoComponentStatefulProps = + StatefulComponentProps & { + [K in keyof T]: T[K]; + }; +export type TodoComponentStatelessProps = CoreComponentProps & { + [K in keyof T]: T[K]; +}; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts index 764fdc3..aec039d 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts @@ -1,4 +1,4 @@ -import { TodosType } from "../types/todo"; +import { TodosType } from "../types"; export type setStorage = (key: string, value: T) => void; export type getStorage = (key: string, defaultValue: T) => T; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts index b9108f6..f20cf37 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts @@ -1,4 +1,4 @@ -import { TodosType } from "../types/todo"; +import { TodosType } from "../types"; // todo 상태의 유효검사 함수 export function validateState(state: TodosType, origin = []) { if ( From cb5099de4ac2d7e817c109361f5121617e80d2ed Mon Sep 17 00:00:00 2001 From: yongjaechoi <88219703+yjc2021@users.noreply.github.com> Date: Thu, 14 Dec 2023 17:22:51 +0900 Subject: [PATCH 08/12] =?UTF-8?q?refactor:=20state=20id=EB=A5=BC=20string?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FEDC5-3_VanillaJS_1/src/components/App.ts | 11 +++----- .../src/components/TodoForm.ts | 10 +++---- .../src/components/TodoItem.ts | 4 +-- .../src/components/TodoList.ts | 4 +-- .../FEDC5-3_VanillaJS_1/src/types/index.ts | 2 +- .../FEDC5-3_VanillaJS_1/src/utils/storage.ts | 2 +- .../src/utils/validateState.ts | 28 +++++++++---------- 7 files changed, 28 insertions(+), 33 deletions(-) diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts index c658c74..e83c4d9 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts @@ -15,10 +15,7 @@ const App = function ( initialState = validateState(initialState); const syncState = (state: TodosType) => { - const validatedState = validateState(state).map((val, idx) => ({ - ...val, - id: idx, - })); + const validatedState = validateState(state); todoList.setState(validatedState); todoCount.setState(validatedState); }; @@ -32,7 +29,7 @@ const App = function ( onSubmit: (text: string) => { const nextState = [ ...todoList.state, - { id: todoList.state.length, text, isCompleted: false }, + { id: String(Date.now()), text, isCompleted: false }, ]; syncState(nextState); @@ -44,14 +41,14 @@ const App = function ( const todoList = new TodoList({ $target, initialState, - onToggle: (todoId: number) => { + onToggle: (todoId: string) => { const nextState = todoList.state.map((todo) => { if (todo.id === todoId) todo.isCompleted = !todo.isCompleted; return todo; }); syncState(nextState); }, - onDelete: (todoId: number) => { + onDelete: (todoId: string) => { const nextState = todoList.state.filter((todo) => { if (todo.id === todoId) return false; return true; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts index a86a886..240a991 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts @@ -23,9 +23,7 @@ const TodoForm = function ( $form.addEventListener("submit", (e) => { e.preventDefault(); - const $todo = $form.querySelector( - `input[name=todo]` - ) as HTMLInputElement; + const $todo = $form.querySelector(`input[name=todo]`); let text = ""; if ($todo && $todo.value) { @@ -33,8 +31,10 @@ const TodoForm = function ( } if (text.length > 1 && text.trim()) { - $todo.value = ""; - onSubmit(text); + if ($todo) { + $todo.value = ""; + onSubmit(text); + } } }); } diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts index 83ba2e0..0c7bab4 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts @@ -6,8 +6,8 @@ import { type TodoItemProps = TodoComponentStatelessProps<{ initialValue: TodoType; - onToggle: (id: number) => void; - onDelete: (id: number) => void; + onToggle: (id: string) => void; + onDelete: (id: string) => void; }>; const TodoItem = function ( diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts index 0fef739..ac45eb0 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts @@ -7,8 +7,8 @@ import { setItem } from "../utils/storage"; import TodoItem from "./TodoItem"; type TodoListProps = TodoComponentStatefulProps<{ - onToggle: (id: number) => void; - onDelete: (id: number) => void; + onToggle: (id: string) => void; + onDelete: (id: string) => void; }>; const TodoList = function ( this: TodoComponentStatefulContext, diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/index.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/index.ts index ed5d61d..8c529e7 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/index.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/index.ts @@ -1,6 +1,6 @@ export interface TodoType { text: string; - id: number; + id: string; isCompleted: boolean; } export type TodosType = TodoType[]; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts index aec039d..cb9434d 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts @@ -20,7 +20,7 @@ export const setItem: setStorage = ( export const getItem: getStorage = ( key: string, - defaultValue = [] as TodosType + defaultValue = [] ) => { try { const storedValue = storage.getItem(key); diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts index f20cf37..310188d 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts @@ -1,6 +1,6 @@ import { TodosType } from "../types"; // todo 상태의 유효검사 함수 -export function validateState(state: TodosType, origin = []) { +export function validateState(state: TodosType, origin: TodosType = []) { if ( Array.isArray(state) && state.every( @@ -11,7 +11,7 @@ export function validateState(state: TodosType, origin = []) { Object.hasOwn(val, "isCompleted") && typeof val.isCompleted === "boolean" && Object.hasOwn(val, "id") && - typeof val.id === "number" + typeof val.id === "string" ) ) return state; @@ -20,21 +20,19 @@ export function validateState(state: TodosType, origin = []) { export function filterValidStorageState( state: TodosType, - defaultState = [] as TodosType + defaultState: TodosType = [] ) { try { - return state - .filter( - (val) => - val && - Object.hasOwn(val, "text") && - val.text.split(" ").join("").length && - Object.hasOwn(val, "isCompleted") && - typeof val.isCompleted === "boolean" && - Object.hasOwn(val, "id") && - typeof val.id === "number" - ) - .map((val, idx) => ({ ...val, id: idx })); + return state.filter( + (val) => + val && + Object.hasOwn(val, "text") && + val.text.split(" ").join("").length && + Object.hasOwn(val, "isCompleted") && + typeof val.isCompleted === "boolean" && + Object.hasOwn(val, "id") && + typeof val.id === "string" + ); } catch (e) { if (e instanceof Error) { console.log(e); From c3a260dec4529c79ab4b2d75bd02862e1de5d0af Mon Sep 17 00:00:00 2001 From: yongjaechoi <88219703+yjc2021@users.noreply.github.com> Date: Thu, 14 Dec 2023 17:30:05 +0900 Subject: [PATCH 09/12] =?UTF-8?q?refactor:=20type=20=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EB=B0=8D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FEDC5-3_VanillaJS_1/src/components/App.ts | 4 ++-- .../FEDC5-3_VanillaJS_1/src/components/TodoCount.ts | 4 ++-- .../FEDC5-3_VanillaJS_1/src/components/TodoItem.ts | 4 ++-- .../FEDC5-3_VanillaJS_1/src/components/TodoList.ts | 4 ++-- .../projects/FEDC5-3_VanillaJS_1/src/types/index.ts | 13 ++++++------- .../FEDC5-3_VanillaJS_1/src/utils/storage.ts | 12 +++--------- .../FEDC5-3_VanillaJS_1/src/utils/validateState.ts | 8 ++++---- 7 files changed, 21 insertions(+), 28 deletions(-) diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts index e83c4d9..1779841 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts @@ -1,4 +1,4 @@ -import { TodoComponentStatefulProps, TodosType } from "../types"; +import { TodoComponentStatefulProps, Todos } from "../types"; import { setItem } from "../utils/storage"; import { validateState } from "../utils/validateState"; import Header from "./Header"; @@ -14,7 +14,7 @@ const App = function ( // ... initialState = validateState(initialState); - const syncState = (state: TodosType) => { + const syncState = (state: Todos) => { const validatedState = validateState(state); todoList.setState(validatedState); todoCount.setState(validatedState); diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts index ead33c2..cafc720 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts @@ -1,7 +1,7 @@ import { TodoComponentStatefulContext, TodoComponentStatefulProps, - TodosType, + Todos, } from "../types"; const TodoCount = function ( @@ -13,7 +13,7 @@ const TodoCount = function ( const $todoCount = document.createElement("h3"); $target.appendChild($todoCount); - this.setState = (nextState: TodosType) => { + this.setState = (nextState: Todos) => { this.state = nextState; this.render(); }; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts index 0c7bab4..816d4f1 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts @@ -1,11 +1,11 @@ import { TodoComponentStatelessContext, TodoComponentStatelessProps, - TodoType, + Todo, } from "../types"; type TodoItemProps = TodoComponentStatelessProps<{ - initialValue: TodoType; + initialValue: Todo; onToggle: (id: string) => void; onDelete: (id: string) => void; }>; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts index ac45eb0..cc95c6b 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts @@ -1,7 +1,7 @@ import { TodoComponentStatefulContext, TodoComponentStatefulProps, - TodosType, + Todos, } from "../types"; import { setItem } from "../utils/storage"; import TodoItem from "./TodoItem"; @@ -19,7 +19,7 @@ const TodoList = function ( const $todoList = document.createElement("ul"); $target.appendChild($todoList); - this.setState = (nextState: TodosType) => { + this.setState = (nextState: Todos) => { this.state = nextState; setItem("todos", this.state); this.render(); diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/index.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/index.ts index 8c529e7..53b1b0b 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/index.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/index.ts @@ -1,9 +1,9 @@ -export interface TodoType { +export interface Todo { text: string; id: string; isCompleted: boolean; } -export type TodosType = TodoType[]; +export type Todos = Todo[]; // 컴포넌트 구조 typing interface CoreComponentContext { @@ -18,10 +18,9 @@ type StatelessComponentContext = Omit< CoreComponentContext, "state" | "setState" >; -export type TodoComponentContext = CoreComponentContext; -export type TodoComponentStatefulContext = StatefulComponentContext; -export type TodoComponentStatelessContext = - StatelessComponentContext; +export type TodoComponentContext = CoreComponentContext; +export type TodoComponentStatefulContext = StatefulComponentContext; +export type TodoComponentStatelessContext = StatelessComponentContext; export interface CoreComponentProps { $target: HTMLElement; @@ -32,7 +31,7 @@ export interface StatefulComponentProps extends CoreComponentProps { } export type TodoComponentStatefulProps = - StatefulComponentProps & { + StatefulComponentProps & { [K in keyof T]: T[K]; }; export type TodoComponentStatelessProps = CoreComponentProps & { diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts index cb9434d..cf7e78b 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts @@ -1,14 +1,11 @@ -import { TodosType } from "../types"; +import { Todos } from "../types"; export type setStorage = (key: string, value: T) => void; export type getStorage = (key: string, defaultValue: T) => T; const storage = window.localStorage; -export const setItem: setStorage = ( - key: string, - value: TodosType -) => { +export const setItem: setStorage = (key: string, value: Todos) => { try { storage.setItem(key, JSON.stringify(value)); } catch (e: unknown) { @@ -18,10 +15,7 @@ export const setItem: setStorage = ( } }; -export const getItem: getStorage = ( - key: string, - defaultValue = [] -) => { +export const getItem: getStorage = (key: string, defaultValue = []) => { try { const storedValue = storage.getItem(key); if (storedValue) { diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts index 310188d..4bb9bc2 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts @@ -1,6 +1,6 @@ -import { TodosType } from "../types"; +import { Todos } from "../types"; // todo 상태의 유효검사 함수 -export function validateState(state: TodosType, origin: TodosType = []) { +export function validateState(state: Todos, origin: Todos = []) { if ( Array.isArray(state) && state.every( @@ -19,8 +19,8 @@ export function validateState(state: TodosType, origin: TodosType = []) { } export function filterValidStorageState( - state: TodosType, - defaultState: TodosType = [] + state: Todos, + defaultState: Todos = [] ) { try { return state.filter( From ab379cd6e060dde686c02ef53f569dbdadef9f3a Mon Sep 17 00:00:00 2001 From: yongjaechoi <88219703+yjc2021@users.noreply.github.com> Date: Thu, 14 Dec 2023 17:46:33 +0900 Subject: [PATCH 10/12] =?UTF-8?q?refactor:=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20constants=EB=A1=9C=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC=20=EB=B0=8F=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../projects/FEDC5-3_VanillaJS_1/src/constants.ts | 14 ++++++++++++++ .../FEDC5-3_VanillaJS_1/src/utils/storage.ts | 5 +++-- .../FEDC5-3_VanillaJS_1/src/utils/validateState.ts | 7 +++++-- 3 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/constants.ts diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/constants.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/constants.ts new file mode 100644 index 0000000..f9c8627 --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/constants.ts @@ -0,0 +1,14 @@ +export const STORAGE_KEY = "todos"; + +const KNOWN_ERROR_MESSAGES = { + invalidState: "올바르지 않은 상태 형식입니다", +}; + +export const ERROR_MESSAGES = new Proxy(KNOWN_ERROR_MESSAGES, { + get: function (target: { [key: string]: string }, prop: string) { + if (prop.length < 1) { + return "알 수 없는 에러입니다."; + } + return target[prop] ?? prop; + }, +}); diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts index cf7e78b..d1b6bad 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts @@ -1,3 +1,4 @@ +import { ERROR_MESSAGES } from "../constants"; import { Todos } from "../types"; export type setStorage = (key: string, value: T) => void; @@ -10,7 +11,7 @@ export const setItem: setStorage = (key: string, value: Todos) => { storage.setItem(key, JSON.stringify(value)); } catch (e: unknown) { if (e instanceof Error) { - console.error(e); + console.warn(ERROR_MESSAGES[e.message]); } } }; @@ -24,7 +25,7 @@ export const getItem: getStorage = (key: string, defaultValue = []) => { return defaultValue; } catch (e: unknown) { if (e instanceof Error) { - console.error(e); + console.warn(ERROR_MESSAGES[e.message]); return defaultValue; } } diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts index 4bb9bc2..96dcf00 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts @@ -1,3 +1,4 @@ +import { ERROR_MESSAGES } from "../constants"; import { Todos } from "../types"; // todo 상태의 유효검사 함수 export function validateState(state: Todos, origin: Todos = []) { @@ -13,8 +14,10 @@ export function validateState(state: Todos, origin: Todos = []) { Object.hasOwn(val, "id") && typeof val.id === "string" ) - ) + ) { return state; + } + console.warn(ERROR_MESSAGES["invalidState"]); return origin; } @@ -35,7 +38,7 @@ export function filterValidStorageState( ); } catch (e) { if (e instanceof Error) { - console.log(e); + console.warn(ERROR_MESSAGES[e.message]); } return defaultState; } From adf13a867f4af37523ad03953d1fb6e90fc61e30 Mon Sep 17 00:00:00 2001 From: yongjaechoi <88219703+yjc2021@users.noreply.github.com> Date: Thu, 14 Dec 2023 17:52:17 +0900 Subject: [PATCH 11/12] =?UTF-8?q?refactor:=20types=20=EC=84=A0=EC=96=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../projects/FEDC5-3_VanillaJS_1/src/components/App.ts | 3 ++- .../FEDC5-3_VanillaJS_1/src/components/Header.ts | 2 +- .../FEDC5-3_VanillaJS_1/src/components/TodoCount.ts | 4 ++-- .../FEDC5-3_VanillaJS_1/src/components/TodoForm.ts | 2 +- .../FEDC5-3_VanillaJS_1/src/components/TodoItem.ts | 4 ++-- .../FEDC5-3_VanillaJS_1/src/components/TodoList.ts | 4 ++-- .../src/types/{index.ts => components.ts} | 10 +++------- .../projects/FEDC5-3_VanillaJS_1/src/types/states.ts | 6 ++++++ .../projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts | 2 +- .../FEDC5-3_VanillaJS_1/src/utils/validateState.ts | 2 +- 10 files changed, 21 insertions(+), 18 deletions(-) rename yongjae/projects/FEDC5-3_VanillaJS_1/src/types/{index.ts => components.ts} (89%) create mode 100644 yongjae/projects/FEDC5-3_VanillaJS_1/src/types/states.ts diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts index 1779841..90c9bdb 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts @@ -1,4 +1,5 @@ -import { TodoComponentStatefulProps, Todos } from "../types"; +import { TodoComponentStatefulProps } from "../types/components"; +import { Todos } from "../types/states"; import { setItem } from "../utils/storage"; import { validateState } from "../utils/validateState"; import Header from "./Header"; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts index ad82845..9e119c4 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts @@ -1,7 +1,7 @@ import { TodoComponentStatelessContext, TodoComponentStatelessProps, -} from "../types"; +} from "../types/components"; type HeaderProps = TodoComponentStatelessProps<{ text: string }>; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts index cafc720..b57d460 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts @@ -1,8 +1,8 @@ import { TodoComponentStatefulContext, TodoComponentStatefulProps, - Todos, -} from "../types"; +} from "../types/components"; +import { Todos } from "../types/states"; const TodoCount = function ( this: TodoComponentStatefulContext, diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts index 240a991..b928fe9 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts @@ -1,7 +1,7 @@ import { TodoComponentStatelessContext, TodoComponentStatelessProps, -} from "../types"; +} from "../types/components"; type TodoFormProps = TodoComponentStatelessProps<{ onSubmit: (text: string) => void; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts index 816d4f1..ebb5698 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts @@ -1,8 +1,8 @@ import { TodoComponentStatelessContext, TodoComponentStatelessProps, - Todo, -} from "../types"; +} from "../types/components"; +import { Todo } from "../types/states"; type TodoItemProps = TodoComponentStatelessProps<{ initialValue: Todo; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts index cc95c6b..e869784 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts @@ -1,8 +1,8 @@ import { TodoComponentStatefulContext, TodoComponentStatefulProps, - Todos, -} from "../types"; +} from "../types/components"; +import { Todos } from "../types/states"; import { setItem } from "../utils/storage"; import TodoItem from "./TodoItem"; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/index.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/components.ts similarity index 89% rename from yongjae/projects/FEDC5-3_VanillaJS_1/src/types/index.ts rename to yongjae/projects/FEDC5-3_VanillaJS_1/src/types/components.ts index 53b1b0b..cb3c932 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/index.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/components.ts @@ -1,11 +1,6 @@ -export interface Todo { - text: string; - id: string; - isCompleted: boolean; -} -export type Todos = Todo[]; - +import { Todos } from "./states"; // 컴포넌트 구조 typing +// 컴포넌트 Context interface CoreComponentContext { state?: T; setState?: (nextState: T) => void; @@ -22,6 +17,7 @@ export type TodoComponentContext = CoreComponentContext; export type TodoComponentStatefulContext = StatefulComponentContext; export type TodoComponentStatelessContext = StatelessComponentContext; +// 컴포넌트 Props export interface CoreComponentProps { $target: HTMLElement; } diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/states.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/states.ts new file mode 100644 index 0000000..f20587b --- /dev/null +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/states.ts @@ -0,0 +1,6 @@ +export interface Todo { + text: string; + id: string; + isCompleted: boolean; +} +export type Todos = Todo[]; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts index d1b6bad..0c5d1d1 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts @@ -1,5 +1,5 @@ import { ERROR_MESSAGES } from "../constants"; -import { Todos } from "../types"; +import { Todos } from "../types/components"; export type setStorage = (key: string, value: T) => void; export type getStorage = (key: string, defaultValue: T) => T; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts index 96dcf00..076d2f0 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts @@ -1,5 +1,5 @@ import { ERROR_MESSAGES } from "../constants"; -import { Todos } from "../types"; +import { Todos } from "../types/components"; // todo 상태의 유효검사 함수 export function validateState(state: Todos, origin: Todos = []) { if ( From 0c1b3b713c8fed226bcaa82f28101f42e09d2277 Mon Sep 17 00:00:00 2001 From: yongjaechoi <88219703+yjc2021@users.noreply.github.com> Date: Thu, 14 Dec 2023 18:10:06 +0900 Subject: [PATCH 12/12] =?UTF-8?q?refactor:=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20type=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FEDC5-3_VanillaJS_1/src/components/App.ts | 9 ++-- .../src/components/Header.ts | 4 +- .../src/components/TodoCount.ts | 6 +-- .../src/components/TodoForm.ts | 6 +-- .../src/components/TodoItem.ts | 9 +--- .../src/components/TodoList.ts | 6 +-- .../src/types/components.ts | 53 +++++++++++-------- .../FEDC5-3_VanillaJS_1/src/utils/storage.ts | 2 +- .../src/utils/validateState.ts | 2 +- 9 files changed, 44 insertions(+), 53 deletions(-) diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts index 90c9bdb..9cf336a 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/App.ts @@ -1,4 +1,4 @@ -import { TodoComponentStatefulProps } from "../types/components"; +import { AppProps } from "../types/components"; import { Todos } from "../types/states"; import { setItem } from "../utils/storage"; import { validateState } from "../utils/validateState"; @@ -8,10 +8,7 @@ import TodoForm from "./TodoForm"; import TodoList from "./TodoList"; interface AppContext {} -const App = function ( - this: AppContext, - { $target, initialState }: TodoComponentStatefulProps -) { +const App = function (this: AppContext, { $target, initialState }: AppProps) { // ... initialState = validateState(initialState); @@ -62,6 +59,6 @@ const App = function ( $target, initialState, }); -} as any as { new (props: TodoComponentStatefulProps): AppContext }; +} as any as { new (props: AppProps): AppContext }; export default App; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts index 9e119c4..d2f1b47 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/Header.ts @@ -1,10 +1,8 @@ import { + HeaderProps, TodoComponentStatelessContext, - TodoComponentStatelessProps, } from "../types/components"; -type HeaderProps = TodoComponentStatelessProps<{ text: string }>; - const Header = function ( this: TodoComponentStatelessContext, { $target, text }: HeaderProps diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts index b57d460..8fd4d98 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoCount.ts @@ -1,12 +1,12 @@ import { TodoComponentStatefulContext, - TodoComponentStatefulProps, + TodoCountProps, } from "../types/components"; import { Todos } from "../types/states"; const TodoCount = function ( this: TodoComponentStatefulContext, - { $target, initialState }: TodoComponentStatefulProps + { $target, initialState }: TodoCountProps ) { this.state = initialState; @@ -29,7 +29,7 @@ const TodoCount = function ( this.render(); } as any as { - new (props: TodoComponentStatefulProps): TodoComponentStatefulContext; + new (props: TodoCountProps): TodoComponentStatefulContext; }; export default TodoCount; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts index b928fe9..bbaa05c 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoForm.ts @@ -1,12 +1,8 @@ import { TodoComponentStatelessContext, - TodoComponentStatelessProps, + TodoFormProps, } from "../types/components"; -type TodoFormProps = TodoComponentStatelessProps<{ - onSubmit: (text: string) => void; -}>; - const TodoForm = function ( this: TodoComponentStatelessContext, { $target, onSubmit }: TodoFormProps diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts index ebb5698..0118e2f 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoItem.ts @@ -1,14 +1,7 @@ import { TodoComponentStatelessContext, - TodoComponentStatelessProps, + TodoItemProps, } from "../types/components"; -import { Todo } from "../types/states"; - -type TodoItemProps = TodoComponentStatelessProps<{ - initialValue: Todo; - onToggle: (id: string) => void; - onDelete: (id: string) => void; -}>; const TodoItem = function ( this: TodoComponentStatelessContext, diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts index e869784..f0e833c 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/components/TodoList.ts @@ -1,15 +1,11 @@ import { TodoComponentStatefulContext, - TodoComponentStatefulProps, + TodoListProps, } from "../types/components"; import { Todos } from "../types/states"; import { setItem } from "../utils/storage"; import TodoItem from "./TodoItem"; -type TodoListProps = TodoComponentStatefulProps<{ - onToggle: (id: string) => void; - onDelete: (id: string) => void; -}>; const TodoList = function ( this: TodoComponentStatefulContext, { initialState, $target, onToggle, onDelete }: TodoListProps diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/components.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/components.ts index cb3c932..d4160e0 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/components.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/types/components.ts @@ -1,35 +1,46 @@ -import { Todos } from "./states"; +import { Todo, Todos } from "./states"; // 컴포넌트 구조 typing // 컴포넌트 Context -interface CoreComponentContext { - state?: T; - setState?: (nextState: T) => void; + +export type TodoComponentContext = { + state?: Todos; + setState?: (nextState: Todos) => void; render: () => void; -} -type StatefulComponentContext = { - [K in keyof CoreComponentContext]-?: CoreComponentContext[K]; }; -type StatelessComponentContext = Omit< - CoreComponentContext, +export type TodoComponentStatefulContext = { + [K in keyof TodoComponentContext]-?: TodoComponentContext[K]; +}; + +export type TodoComponentStatelessContext = Omit< + TodoComponentContext, "state" | "setState" >; -export type TodoComponentContext = CoreComponentContext; -export type TodoComponentStatefulContext = StatefulComponentContext; -export type TodoComponentStatelessContext = StatelessComponentContext; // 컴포넌트 Props export interface CoreComponentProps { $target: HTMLElement; } -export interface StatefulComponentProps extends CoreComponentProps { - initialState: T; +interface TodoStatefulComponentProps extends CoreComponentProps { + initialState: Todos; +} +export interface TodoItemProps extends CoreComponentProps { + initialValue: Todo; + onToggle: (id: string) => void; + onDelete: (id: string) => void; +} +export interface TodoListProps extends TodoStatefulComponentProps { + onToggle: (id: string) => void; + onDelete: (id: string) => void; } -export type TodoComponentStatefulProps = - StatefulComponentProps & { - [K in keyof T]: T[K]; - }; -export type TodoComponentStatelessProps = CoreComponentProps & { - [K in keyof T]: T[K]; -}; +export interface TodoCountProps extends TodoStatefulComponentProps {} + +export interface TodoFormProps extends CoreComponentProps { + onSubmit: (text: string) => void; +} + +export interface AppProps extends TodoStatefulComponentProps {} +export interface HeaderProps extends CoreComponentProps { + text: string; +} diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts index 0c5d1d1..3f77718 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/storage.ts @@ -1,5 +1,5 @@ import { ERROR_MESSAGES } from "../constants"; -import { Todos } from "../types/components"; +import { Todos } from "../types/states"; export type setStorage = (key: string, value: T) => void; export type getStorage = (key: string, defaultValue: T) => T; diff --git a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts index 076d2f0..48089c3 100644 --- a/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts +++ b/yongjae/projects/FEDC5-3_VanillaJS_1/src/utils/validateState.ts @@ -1,5 +1,5 @@ import { ERROR_MESSAGES } from "../constants"; -import { Todos } from "../types/components"; +import { Todos } from "../types/states"; // todo 상태의 유효검사 함수 export function validateState(state: Todos, origin: Todos = []) { if (