From 71a9858eec2b253f6f316d99bdabe459be58ef00 Mon Sep 17 00:00:00 2001 From: yejinleee <81412212+yejinleee@users.noreply.github.com> Date: Mon, 13 Nov 2023 10:56:49 +0900 Subject: [PATCH 01/16] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e7140d8..a11f31d 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,8 @@ ## ⚙️ 컨벤션 * 본인 이름의 브랜치에 정리 파일 및 실습 파일 올리고 PR 보내기 -* 파일명 규칙 - * 본인 이름 폴더 / 챕터 {번호 및 제목} / {정리}.md - * 본인 이름 폴더 / 챕터 {번호 및 제목} / Practice / {문제}.ts +* 파일업로드 + * `본인 이름 폴더` / 내에 정리 md 파일, 예제문제 풀이 ts파일
@@ -43,5 +42,6 @@ | 회차 | 일시 | 스터디 내용 | | ---- | -------- | -------- | | 1 | 23.11.13 월 | CHAPTER 1, 2, 3, 4 | +| 2 | 23.11.20 월 | CHAPTER 5, 6, 7 ,10 | From a1cc1737ad89709d70dd22414da132b55718b919 Mon Sep 17 00:00:00 2001 From: yejinleee <81412212+yejinleee@users.noreply.github.com> Date: Mon, 20 Nov 2023 11:25:23 +0900 Subject: [PATCH 02/16] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a11f31d..0344022 100644 --- a/README.md +++ b/README.md @@ -43,5 +43,6 @@ | ---- | -------- | -------- | | 1 | 23.11.13 월 | CHAPTER 1, 2, 3, 4 | | 2 | 23.11.20 월 | CHAPTER 5, 6, 7 ,10 | +| 3 | 23.11.27 월 | CHAPTER 8,9 + type-challenges 워밍업(1) & 쉬움(13) | From 904462d17f198e04452805a4b8635f4d10b0ca76 Mon Sep 17 00:00:00 2001 From: yejinleee <81412212+yejinleee@users.noreply.github.com> Date: Tue, 28 Nov 2023 16:29:29 +0900 Subject: [PATCH 03/16] Update README.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0344022..71dffce 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,9 @@ ## ⏰ 스터디 시간 -**매주 월요일 10:00** +~~매주 월요일 10:00~~ + +**월요일 16:00**
@@ -44,5 +46,7 @@ | 1 | 23.11.13 월 | CHAPTER 1, 2, 3, 4 | | 2 | 23.11.20 월 | CHAPTER 5, 6, 7 ,10 | | 3 | 23.11.27 월 | CHAPTER 8,9 + type-challenges 워밍업(1) & 쉬움(13) | +| 4 | 23.12.04 월 | CHAPTER 15, Vue+TS 과제 중 이슈 공유 | +| 5 | 23.12.11 월 | TodoList 과제 TS 전환 | From d4194fa96b122d8d6bb78005f8746cfed5a3bcc6 Mon Sep 17 00:00:00 2001 From: Cho-Ik-Jun Date: Sun, 10 Dec 2023 17:24:59 +0900 Subject: [PATCH 04/16] =?UTF-8?q?=F0=9F=8E=89=20init:=20index.html?= =?UTF-8?q?=EA=B3=BC=20main.css=20=EC=B4=88=EA=B8=B0=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 22 +++++++++ main.css | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 index.html create mode 100644 main.css diff --git a/index.html b/index.html new file mode 100644 index 0000000..fee1225 --- /dev/null +++ b/index.html @@ -0,0 +1,22 @@ + + + + + + + To Do List + + +
+ + + + + diff --git a/main.css b/main.css new file mode 100644 index 0000000..bd1f22a --- /dev/null +++ b/main.css @@ -0,0 +1,135 @@ +/* 전역 css */ +body { + font-size: 62.5%; + background-color: #fff2d8; + margin: 0; + padding: 10px; +} + +main { + background-color: #ead7bb; + margin: 0 auto; + padding: 20px; + width: 90vw; + height: 90vh; +} + +/* 제목 */ +h1 { + font-size: 2rem; + text-align: center; + margin: 10px 0; +} + +/* 입력 폼 */ +.todoForm { + display: flex; + width: 80%; + height: 10%; + text-align: center; + vertical-align: middle; + margin: 0 auto; + background: #ead7bb; + justify-content: center; + align-items: center; +} + +.todoForm > input { + margin: 5px auto; + padding: 10px; + width: 80%; + height: 70%; + font-size: 1.4rem; + font-weight: 700; + border: 0; + border-radius: 5px; + vertical-align: middle; + box-sizing: border-box; +} + +.todoForm > button { + margin: 5px auto; + text-align: center; + background: #113946; + color: white; + font-size: 1.2rem; + font-weight: 700; + width: 15%; + height: 75%; + border: 0; + border-radius: 5px; + cursor: pointer; + box-sizing: border-box; +} + +.todoForm > button:hover { + background: #267b97; +} + +/* TodoList */ +.todoList { + width: 80%; + margin: 10px auto; +} + +.todoList > ul { + display: flex; + margin: 0 auto; + padding: 0; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.todoList li { + display: flex; + list-style: none; + margin: 10px 0; + padding: 10px; + width: 100%; + text-align: center; + background: #bca37f; + border-radius: 5px; + align-items: center; + justify-content: center; +} + +.todoList li span { + margin: 0 auto; + font-size: 1.1rem; + font-weight: 700; + cursor: pointer; +} + +.todoList li span:hover { + text-decoration: underline; + color: #fff2d8; +} + +.todoList button { + padding: 5px 10px; + background: #113946; + color: white; + font-size: 1rem; + font-weight: 700; + border: 0; + border-radius: 5px; + cursor: pointer; +} + +.todoList button:hover { + background: #267b97; +} + +.completed { + text-decoration: line-through; +} + +/* TodoCount */ +.todoCount { + width: 80%; + margin: 10px auto; + text-align: center; + font-size: 1.2rem; + font-weight: 700; +} From def3c1b5532e8334cab180b49204fb83af338cec Mon Sep 17 00:00:00 2001 From: Cho-Ik-Jun Date: Sun, 10 Dec 2023 17:25:52 +0900 Subject: [PATCH 05/16] =?UTF-8?q?=E2=9C=A8=20feat:=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?Type=20=EA=B4=80=EB=A6=AC=20=ED=8C=8C=EC=9D=BC=20Type.ts=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Type.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/Type.ts diff --git a/src/Type.ts b/src/Type.ts new file mode 100644 index 0000000..2ce7b67 --- /dev/null +++ b/src/Type.ts @@ -0,0 +1,13 @@ +export type QuerySelectItem = HTMLElement | null; + +export type StateArray = StateArrayItem[]; + +export interface StateArrayItem { + text: string; + isCompleted: boolean; +} + +export interface NewFuncParams { + $target: QuerySelectItem; + initialState: StateArray; +} From e7927cc9e7fb71dcc0adeff70168c5cbab4dfe41 Mon Sep 17 00:00:00 2001 From: Cho-Ik-Jun Date: Sun, 10 Dec 2023 17:26:34 +0900 Subject: [PATCH 06/16] =?UTF-8?q?=E2=9C=A8=20feat:=20storage,=20validation?= =?UTF-8?q?=20=ED=95=A8=EC=88=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/storage.ts | 28 ++++++++++++++++++++++++++++ src/validation.ts | 25 +++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 src/storage.ts create mode 100644 src/validation.ts diff --git a/src/storage.ts b/src/storage.ts new file mode 100644 index 0000000..c620710 --- /dev/null +++ b/src/storage.ts @@ -0,0 +1,28 @@ +export const storage = (function (storage) { + const setItem = (key: string, value: string) => { + try { + storage.setItem(key, value); + } catch (e) { + console.log(e); + } + }; + + const getItem = (key: string, defaultValue: string | string[]) => { + try { + const storedValue = storage.getItem(key); + + if (storedValue) { + return JSON.parse(storedValue); + } + return defaultValue; + } catch (e) { + console.log(e); + return defaultValue; + } + }; + + return { + setItem, + getItem, + }; +})(window.localStorage); diff --git a/src/validation.ts b/src/validation.ts new file mode 100644 index 0000000..abcda16 --- /dev/null +++ b/src/validation.ts @@ -0,0 +1,25 @@ +import { StateArray, StateArrayItem } from './Type'; + +export default function validation(state: StateArray) { + // 불가능 값 + const invalidValue = [undefined, null, '']; + + // 전체가 배열 형태인지 체크 + if (!Array.isArray(state)) { + throw new Error('데이터 타입이 배열 형태가 아닙니다.'); + } + // 각 요소 체크 + state.forEach((todo: StateArrayItem) => { + // 객체 타입인지 체크 + if (!(todo instanceof Object)) + throw new Error('데이터 요소가 객체 타입이 아닙니다.'); + // 객체 키 값이 'text'가 존재하는지 체크 + if (invalidValue.indexOf(typeof todo.text) !== -1) + throw new Error('객체 키에 "text"가 없습니다.'); + // 객체 키 값이 'isCompleted'가 존재하는지 체크 + if (invalidValue.indexOf(typeof todo.isCompleted) !== -1) + throw new Error('객체 키에 "isCompleted"가 없습니다.'); + }); + + return state; // 괜찮으면 반환 +} From 9254ed79cd141ba59c0cbb5af2b8d7c2b1688168 Mon Sep 17 00:00:00 2001 From: Cho-Ik-Jun Date: Sun, 10 Dec 2023 17:26:58 +0900 Subject: [PATCH 07/16] =?UTF-8?q?=E2=9C=A8=20feat:=20main,=20App.ts=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.ts | 13 +++++++++++++ src/main.ts | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/App.ts create mode 100644 src/main.ts diff --git a/src/App.ts b/src/App.ts new file mode 100644 index 0000000..49cde54 --- /dev/null +++ b/src/App.ts @@ -0,0 +1,13 @@ +import { NewFuncParams, StateArray } from './Type'; + +export default function App({ $target, initialState }: NewFuncParams) { + // new 미사용 방어코드 + if (!new.target) { + throw new Error('new 키워드를 사용하여야 합니다.'); + } + this.state = initialState; + + this.setState = (nextState: StateArray) => { + this.state = nextState; + }; +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..9014620 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,13 @@ +import App from './App'; +import { QuerySelectItem } from './Type'; +import { storage } from './storage'; +import validation from './validation'; + +const $app: QuerySelectItem = document.querySelector('.app'); + +const initialState = storage.getItem('todos', []); + +new App({ + $target: $app, + initialState: validation(initialState), +}); From e2cbaa16e52f7caf81652d6d5dd6ebc7b56b435e Mon Sep 17 00:00:00 2001 From: Cho-Ik-Jun Date: Sun, 10 Dec 2023 19:28:40 +0900 Subject: [PATCH 08/16] =?UTF-8?q?=F0=9F=94=A8=20fix:=20vite=20ts=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Todo-ts/.gitignore | 24 +++++++++++++++++++ README.md => Todo-ts/README.md | 26 +++++++++------------ Todo-ts/index.html | 15 ++++++++++++ main.css => Todo-ts/main.css | 0 Todo-ts/package.json | 15 ++++++++++++ Todo-ts/public/vite.svg | 1 + Todo-ts/src/components/App.ts | 28 +++++++++++++++++++++++ Todo-ts/src/components/Header.ts | 23 +++++++++++++++++++ src/Type.ts => Todo-ts/src/globalTypes.ts | 0 {src => Todo-ts/src}/main.ts | 8 +++---- Todo-ts/src/typescript.svg | 1 + {src => Todo-ts/src/utils}/storage.ts | 0 {src => Todo-ts/src/utils}/validation.ts | 2 +- Todo-ts/src/vite-env.d.ts | 1 + Todo-ts/tsconfig.json | 24 +++++++++++++++++++ index.html | 22 ------------------ src/App.ts | 13 ----------- 17 files changed, 148 insertions(+), 55 deletions(-) create mode 100644 Todo-ts/.gitignore rename README.md => Todo-ts/README.md (60%) create mode 100644 Todo-ts/index.html rename main.css => Todo-ts/main.css (100%) create mode 100644 Todo-ts/package.json create mode 100644 Todo-ts/public/vite.svg create mode 100644 Todo-ts/src/components/App.ts create mode 100644 Todo-ts/src/components/Header.ts rename src/Type.ts => Todo-ts/src/globalTypes.ts (100%) rename {src => Todo-ts/src}/main.ts (52%) create mode 100644 Todo-ts/src/typescript.svg rename {src => Todo-ts/src/utils}/storage.ts (100%) rename {src => Todo-ts/src/utils}/validation.ts (93%) create mode 100644 Todo-ts/src/vite-env.d.ts create mode 100644 Todo-ts/tsconfig.json delete mode 100644 index.html delete mode 100644 src/App.ts diff --git a/Todo-ts/.gitignore b/Todo-ts/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/Todo-ts/.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/README.md b/Todo-ts/README.md similarity index 60% rename from README.md rename to Todo-ts/README.md index 71dffce..76c4b29 100644 --- a/README.md +++ b/Todo-ts/README.md @@ -1,9 +1,9 @@ # FEDC5_LearningTS_Study + [러닝 타입스크립트](https://www.yes24.com/Product/Goods/116585556)로 타입스크립트 뿌시기 !
- ## ⭐️ 스타디 팀 ⭐️ > 조익준 김석주 이예진 백윤서 손호민 최용재 현세인 @@ -18,11 +18,10 @@
- ## 🔨 진행 방식 - 정해진 챕터의 내용을 공부하고 본인 폴더에 정리.md 올리기 - - 안올리면 반성문 + - 안올리면 반성문 - 지정 문제 풀고 코드파일도 올리기 - 모르는 것 자유롭게 많이 많이 질문하기 - 다른 팀원 코드 리뷰하기 @@ -32,21 +31,18 @@ ## ⚙️ 컨벤션 -* 본인 이름의 브랜치에 정리 파일 및 실습 파일 올리고 PR 보내기 -* 파일업로드 - * `본인 이름 폴더` / 내에 정리 md 파일, 예제문제 풀이 ts파일 +- 본인 이름의 브랜치에 정리 파일 및 실습 파일 올리고 PR 보내기 +- 파일업로드 + - `본인 이름 폴더` / 내에 정리 md 파일, 예제문제 풀이 ts파일
- ## 🗓 스터디 일정 -| 회차 | 일시 | 스터디 내용 | -| ---- | -------- | -------- | -| 1 | 23.11.13 월 | CHAPTER 1, 2, 3, 4 | -| 2 | 23.11.20 월 | CHAPTER 5, 6, 7 ,10 | +| 회차 | 일시 | 스터디 내용 | +| ---- | ----------- | -------------------------------------------------- | +| 1 | 23.11.13 월 | CHAPTER 1, 2, 3, 4 | +| 2 | 23.11.20 월 | CHAPTER 5, 6, 7 ,10 | | 3 | 23.11.27 월 | CHAPTER 8,9 + type-challenges 워밍업(1) & 쉬움(13) | -| 4 | 23.12.04 월 | CHAPTER 15, Vue+TS 과제 중 이슈 공유 | -| 5 | 23.12.11 월 | TodoList 과제 TS 전환 | - - +| 4 | 23.12.04 월 | CHAPTER 15, Vue+TS 과제 중 이슈 공유 | +| 5 | 23.12.11 월 | TodoList 과제 TS 전환 | diff --git a/Todo-ts/index.html b/Todo-ts/index.html new file mode 100644 index 0000000..7492532 --- /dev/null +++ b/Todo-ts/index.html @@ -0,0 +1,15 @@ + + + + + + + + To Do List TS + + +
+ + + + diff --git a/main.css b/Todo-ts/main.css similarity index 100% rename from main.css rename to Todo-ts/main.css diff --git a/Todo-ts/package.json b/Todo-ts/package.json new file mode 100644 index 0000000..0c30663 --- /dev/null +++ b/Todo-ts/package.json @@ -0,0 +1,15 @@ +{ + "name": "vanilla-ts", + "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/Todo-ts/public/vite.svg b/Todo-ts/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/Todo-ts/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Todo-ts/src/components/App.ts b/Todo-ts/src/components/App.ts new file mode 100644 index 0000000..a0fffbc --- /dev/null +++ b/Todo-ts/src/components/App.ts @@ -0,0 +1,28 @@ +import { NewFuncParams, StateArray } from '../globalTypes'; +import Header from './Header'; + +interface NewApp { + state: StateArray; + setState: (nextState: StateArray) => void; +} + +export default function App( + this: NewApp, + { $target, initialState }: NewFuncParams +) { + // new 미사용 방어코드 + if (!new.target) { + throw new Error('new 키워드를 사용하여야 합니다.'); + } + this.state = initialState; + + this.setState = (nextState: StateArray) => { + this.state = nextState; + }; + + // 헤더 + new Header({ + $target, + text: 'Simple Todo List', + }); +} diff --git a/Todo-ts/src/components/Header.ts b/Todo-ts/src/components/Header.ts new file mode 100644 index 0000000..9211f40 --- /dev/null +++ b/Todo-ts/src/components/Header.ts @@ -0,0 +1,23 @@ +import { QuerySelectItem } from '../globalTypes'; + +interface HeaderParams { + $target: QuerySelectItem; + text: string; +} + +export default function Header({ $target, text }: HeaderParams) { + // new 미사용 방어코드 + if (!new.target) { + throw new Error('new 키워드를 사용하여야 합니다.'); + } + + const $header: QuerySelectItem = document.createElement('h1'); + + $target?.appendChild($header); + + this.render = () => { + $header.textContent = text; + }; + + this.render(); +} diff --git a/src/Type.ts b/Todo-ts/src/globalTypes.ts similarity index 100% rename from src/Type.ts rename to Todo-ts/src/globalTypes.ts diff --git a/src/main.ts b/Todo-ts/src/main.ts similarity index 52% rename from src/main.ts rename to Todo-ts/src/main.ts index 9014620..d754c06 100644 --- a/src/main.ts +++ b/Todo-ts/src/main.ts @@ -1,7 +1,7 @@ -import App from './App'; -import { QuerySelectItem } from './Type'; -import { storage } from './storage'; -import validation from './validation'; +import App from './components/App'; +import { QuerySelectItem } from './globalTypes'; +import { storage } from './utils/storage'; +import validation from './utils/validation'; const $app: QuerySelectItem = document.querySelector('.app'); diff --git a/Todo-ts/src/typescript.svg b/Todo-ts/src/typescript.svg new file mode 100644 index 0000000..d91c910 --- /dev/null +++ b/Todo-ts/src/typescript.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/storage.ts b/Todo-ts/src/utils/storage.ts similarity index 100% rename from src/storage.ts rename to Todo-ts/src/utils/storage.ts diff --git a/src/validation.ts b/Todo-ts/src/utils/validation.ts similarity index 93% rename from src/validation.ts rename to Todo-ts/src/utils/validation.ts index abcda16..dcf3156 100644 --- a/src/validation.ts +++ b/Todo-ts/src/utils/validation.ts @@ -1,4 +1,4 @@ -import { StateArray, StateArrayItem } from './Type'; +import { StateArray, StateArrayItem } from '../globalTypes'; export default function validation(state: StateArray) { // 불가능 값 diff --git a/Todo-ts/src/vite-env.d.ts b/Todo-ts/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/Todo-ts/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/Todo-ts/tsconfig.json b/Todo-ts/tsconfig.json new file mode 100644 index 0000000..d897a5c --- /dev/null +++ b/Todo-ts/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "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, + "noImplicitAny": false + }, + "include": ["src"] +} diff --git a/index.html b/index.html deleted file mode 100644 index fee1225..0000000 --- a/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - To Do List - - -
- - - - - diff --git a/src/App.ts b/src/App.ts deleted file mode 100644 index 49cde54..0000000 --- a/src/App.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { NewFuncParams, StateArray } from './Type'; - -export default function App({ $target, initialState }: NewFuncParams) { - // new 미사용 방어코드 - if (!new.target) { - throw new Error('new 키워드를 사용하여야 합니다.'); - } - this.state = initialState; - - this.setState = (nextState: StateArray) => { - this.state = nextState; - }; -} From 41d515817af8b76f0ceb042781a919c1b8d41436 Mon Sep 17 00:00:00 2001 From: Cho-Ik-Jun Date: Sun, 10 Dec 2023 19:51:30 +0900 Subject: [PATCH 09/16] =?UTF-8?q?=20=F0=9F=90=9B=20fix:=20new=20=ED=82=A4?= =?UTF-8?q?=EC=9B=8C=EB=93=9C=20=EB=AA=85=EC=8B=9C=EC=A0=81=20any=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=20=EC=86=94=EB=A3=A8=EC=85=98=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Todo-ts/src/components/App.ts | 7 +------ Todo-ts/src/main.ts | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Todo-ts/src/components/App.ts b/Todo-ts/src/components/App.ts index a0fffbc..cf97974 100644 --- a/Todo-ts/src/components/App.ts +++ b/Todo-ts/src/components/App.ts @@ -1,13 +1,8 @@ import { NewFuncParams, StateArray } from '../globalTypes'; import Header from './Header'; -interface NewApp { - state: StateArray; - setState: (nextState: StateArray) => void; -} - export default function App( - this: NewApp, + this: any, { $target, initialState }: NewFuncParams ) { // new 미사용 방어코드 diff --git a/Todo-ts/src/main.ts b/Todo-ts/src/main.ts index d754c06..5244f56 100644 --- a/Todo-ts/src/main.ts +++ b/Todo-ts/src/main.ts @@ -7,7 +7,7 @@ const $app: QuerySelectItem = document.querySelector('.app'); const initialState = storage.getItem('todos', []); -new App({ +new (App as any)({ $target: $app, initialState: validation(initialState), }); From 4bf9c5844506bbba6dfb905c5823c234b51602c0 Mon Sep 17 00:00:00 2001 From: Cho-Ik-Jun Date: Sun, 10 Dec 2023 20:41:34 +0900 Subject: [PATCH 10/16] =?UTF-8?q?=E2=9C=A8=20feat:=20TodoList,=20TodoForm,?= =?UTF-8?q?=20TodoCount.ts=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Todo-ts/src/components/App.ts | 55 ++++++++++++++++++ Todo-ts/src/components/Header.ts | 9 +-- Todo-ts/src/components/TodoCount.ts | 32 +++++++++++ Todo-ts/src/components/TodoForm.ts | 44 +++++++++++++++ Todo-ts/src/components/TodoList.ts | 87 +++++++++++++++++++++++++++++ Todo-ts/src/globalTypes.ts | 4 +- Todo-ts/src/main.ts | 5 +- 7 files changed, 228 insertions(+), 8 deletions(-) create mode 100644 Todo-ts/src/components/TodoCount.ts create mode 100644 Todo-ts/src/components/TodoForm.ts create mode 100644 Todo-ts/src/components/TodoList.ts diff --git a/Todo-ts/src/components/App.ts b/Todo-ts/src/components/App.ts index cf97974..caf6d11 100644 --- a/Todo-ts/src/components/App.ts +++ b/Todo-ts/src/components/App.ts @@ -1,5 +1,11 @@ import { NewFuncParams, StateArray } from '../globalTypes'; +import { $app } from '../main'; +import { storage } from '../utils/storage'; +import validation from '../utils/validation'; import Header from './Header'; +import TodoCount from './TodoCount'; +import TodoForm from './TodoForm'; +import TodoList from './TodoList'; export default function App( this: any, @@ -13,6 +19,8 @@ export default function App( this.setState = (nextState: StateArray) => { this.state = nextState; + todoCount.setState(this.state); + todoList.setState(this.state); }; // 헤더 @@ -20,4 +28,51 @@ export default function App( $target, text: 'Simple Todo List', }); + + // Todo 입력폼 + new TodoForm({ + $target, + onSubmit: (text: string) => { + const nextState = [ + ...todoList.state, + { + text, + isCompleted: false, + }, + ]; + + // state 유효성 검사 후 업데이트 + this.setState(validation(nextState)); + storage.setItem('todos', JSON.stringify(nextState)); + }, + }); + + // Todo 리스트 + const todoList = new TodoList({ + $target, + initialState: validation(initialState), + onClick: (text: string, id: string) => { + const nextState = [...this.state]; + + // 삭제할 값이 있을 경우 삭제 + if (text === '삭제') nextState.splice(Number(id), 1); + + nextState.forEach((task, i) => { + if (task.text === text && i === Number(id)) { + // 데이터 수정 + nextState[i].isCompleted = !nextState[i].isCompleted; + } + }); + + // state 유효성 검사 후 업데이트 + this.setState(validation(nextState)); + storage.setItem('todos', JSON.stringify(nextState)); + }, + }); + + // TodoCount + const todoCount = new TodoCount({ + $target: $app, + initialState: this.state, + }); } diff --git a/Todo-ts/src/components/Header.ts b/Todo-ts/src/components/Header.ts index 9211f40..7e86757 100644 --- a/Todo-ts/src/components/Header.ts +++ b/Todo-ts/src/components/Header.ts @@ -1,17 +1,18 @@ -import { QuerySelectItem } from '../globalTypes'; +import { QuerySelectType } from '../globalTypes'; interface HeaderParams { - $target: QuerySelectItem; + $target: HTMLElement; text: string; } -export default function Header({ $target, text }: HeaderParams) { +export default function Header(this: any, { $target, text }: HeaderParams) { // new 미사용 방어코드 if (!new.target) { throw new Error('new 키워드를 사용하여야 합니다.'); } - const $header: QuerySelectItem = document.createElement('h1'); + const $header: QuerySelectType = + document.createElement('h1'); $target?.appendChild($header); diff --git a/Todo-ts/src/components/TodoCount.ts b/Todo-ts/src/components/TodoCount.ts new file mode 100644 index 0000000..ca4d2fd --- /dev/null +++ b/Todo-ts/src/components/TodoCount.ts @@ -0,0 +1,32 @@ +import { StateArray, StateArrayItem } from '../globalTypes'; +import validation from '../utils/validation'; + +export default function TodoCount(this: any, { $target, initialState }) { + // new 미사용 방어코드 + if (!new.target) { + throw new Error('new 키워드를 사용하여야 합니다.'); + } + + const $todoCount = document.createElement('div'); + $todoCount.className = 'todoCount'; + + $target.appendChild($todoCount); + + // state 유효성 검사 + this.state = validation(initialState); + + this.render = () => { + const totalTodos = this.state.length; + const completedTodos = this.state.filter( + (todo: StateArrayItem) => todo.isCompleted + ).length; + $todoCount.innerHTML = `완료된 Todo의 갯수 : ${completedTodos} / 전체 Todo 갯수 : ${totalTodos} `; + }; + + this.setState = (nextState: StateArray) => { + this.state = validation(nextState); + this.render(); + }; + + this.render(); +} diff --git a/Todo-ts/src/components/TodoForm.ts b/Todo-ts/src/components/TodoForm.ts new file mode 100644 index 0000000..a0fb663 --- /dev/null +++ b/Todo-ts/src/components/TodoForm.ts @@ -0,0 +1,44 @@ +import { QuerySelectType } from '../globalTypes'; + +export default function TodoForm(this: any, { $target, onSubmit }) { + // new 미사용 방어코드 + if (!new.target) { + throw new Error('new 키워드를 사용하여야 합니다.'); + } + + const $form = document.createElement('form'); + $form.className = 'todoForm'; + + $target.appendChild($form); + + let isInit = false; + + this.render = () => { + $form.innerHTML = ` + + + `; + + if (!isInit) { + $form.addEventListener('submit', (e) => { + e.preventDefault(); + // 이건 강사님이 수정한 코드 + const $todo: QuerySelectType = + $form.querySelector('input[name="todo"]'); + + if ($todo) { + const text = $todo.value; + // 입력값이 있을 경우만 추가 + if (text.length > 0) { + $todo.value = ''; + onSubmit(text); + } + } + }); + + isInit = true; + } + }; + + this.render(); +} diff --git a/Todo-ts/src/components/TodoList.ts b/Todo-ts/src/components/TodoList.ts new file mode 100644 index 0000000..e1d6995 --- /dev/null +++ b/Todo-ts/src/components/TodoList.ts @@ -0,0 +1,87 @@ +// params.$target - 해당 컴포넌트가 추가가 될 DOM element +// params.initialState - 해당 컴포넌트의 초기 상태 + +import validation from '../utils/validation'; + +export default function TodoList( + this: any, + { $target, initialState, onClick } +) { + // new 미사용 방어코드 + if (!new.target) { + throw new Error('new 키워드를 사용하여야 합니다.'); + } + + const $todoList = document.createElement('div'); + $todoList.className = 'todoList'; + + $target.appendChild($todoList); + + // state 유효성 검사 + this.state = validation(initialState); + + this.setState = (nextState) => { + // state 유효성 검사 + this.state = validation(nextState); + + this.render(); + }; + + this.render = () => { + $todoList.innerHTML = ` +
    + ${this.state + .map(({ text, isCompleted }, i) => { + return `
  • ${text}
  • `; + }) + .join('')} +
+ `; + + this.complete(); + this.delete(); + }; + // todolist 삭선 기능 + this.complete = () => { + const $todos = document.querySelectorAll('li'); + + $todos.forEach((todo) => { + todo.addEventListener('click', (e: MouseEvent) => { + const target = e.currentTarget; + if (target && target instanceof HTMLElement) { + // 클릭된 todo의 text와 id + const [clickedText, clickedId] = [ + target.innerText, + target.dataset.id, + ]; + + // 클릭 이벤트 내보내기 + onClick(clickedText, clickedId); + } + }); + }); + }; + + // 삭제 버튼 기능 + this.delete = () => { + // DOM element + const $deleteButtons = document.querySelectorAll('li > button'); + + $deleteButtons.forEach((button) => { + button.addEventListener('click', (e) => { + e.stopPropagation(); // 이벤트 버블링 방지 + + const target = e.currentTarget; + if (target && target instanceof HTMLElement) { + const [text, id] = [target.innerText, target.dataset.id]; + // 클릭 이벤트 내보내기 + onClick(text, id); + } + }); + }); + }; + + this.render(); +} diff --git a/Todo-ts/src/globalTypes.ts b/Todo-ts/src/globalTypes.ts index 2ce7b67..1b716bd 100644 --- a/Todo-ts/src/globalTypes.ts +++ b/Todo-ts/src/globalTypes.ts @@ -1,4 +1,4 @@ -export type QuerySelectItem = HTMLElement | null; +export type QuerySelectType = T | null; export type StateArray = StateArrayItem[]; @@ -8,6 +8,6 @@ export interface StateArrayItem { } export interface NewFuncParams { - $target: QuerySelectItem; + $target: HTMLElement; initialState: StateArray; } diff --git a/Todo-ts/src/main.ts b/Todo-ts/src/main.ts index 5244f56..3c9c4fe 100644 --- a/Todo-ts/src/main.ts +++ b/Todo-ts/src/main.ts @@ -1,9 +1,10 @@ import App from './components/App'; -import { QuerySelectItem } from './globalTypes'; +import { QuerySelectType } from './globalTypes'; import { storage } from './utils/storage'; import validation from './utils/validation'; -const $app: QuerySelectItem = document.querySelector('.app'); +export const $app: QuerySelectType = + document.querySelector('.app'); const initialState = storage.getItem('todos', []); From f0d36c052694a8f14deaaa90f34ba98e04caf31c Mon Sep 17 00:00:00 2001 From: Cho-Ik-Jun Date: Sun, 10 Dec 2023 20:47:43 +0900 Subject: [PATCH 11/16] =?UTF-8?q?=20=F0=9F=90=9B=20fix:=20=EC=9D=B4?= =?UTF-8?q?=EB=B2=A4=ED=8A=B8=20=EC=A0=81=EC=9A=A9=20=EC=95=88=EB=90=98?= =?UTF-8?q?=EB=8A=94=20=EC=97=90=EB=9F=AC=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Todo-ts/src/components/TodoList.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Todo-ts/src/components/TodoList.ts b/Todo-ts/src/components/TodoList.ts index e1d6995..aa8811b 100644 --- a/Todo-ts/src/components/TodoList.ts +++ b/Todo-ts/src/components/TodoList.ts @@ -31,7 +31,7 @@ export default function TodoList( $todoList.innerHTML = `
    ${this.state - .map(({ text, isCompleted }, i) => { + .map(({ text, isCompleted }, i: string) => { return `
  • ${text}
  • `; @@ -48,8 +48,8 @@ export default function TodoList( const $todos = document.querySelectorAll('li'); $todos.forEach((todo) => { - todo.addEventListener('click', (e: MouseEvent) => { - const target = e.currentTarget; + todo.addEventListener('click', (e) => { + const target = e.target; if (target && target instanceof HTMLElement) { // 클릭된 todo의 text와 id const [clickedText, clickedId] = [ @@ -73,7 +73,7 @@ export default function TodoList( button.addEventListener('click', (e) => { e.stopPropagation(); // 이벤트 버블링 방지 - const target = e.currentTarget; + const target = e.target; if (target && target instanceof HTMLElement) { const [text, id] = [target.innerText, target.dataset.id]; // 클릭 이벤트 내보내기 From c216faa67928efd7e06372d12a0ebe5e3831588a Mon Sep 17 00:00:00 2001 From: Cho-Ik-Jun Date: Sun, 10 Dec 2023 21:09:11 +0900 Subject: [PATCH 12/16] =?UTF-8?q?=20=F0=9F=90=9B=20fix:=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=ED=8C=8C=EB=9D=BC=EB=AF=B8?= =?UTF-8?q?=ED=84=B0=20=EB=AA=85=EC=8B=9C=EC=A0=81=20any=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 --- Todo-ts/main.css | 6 ++++++ Todo-ts/src/components/App.ts | 3 +-- Todo-ts/src/components/Header.ts | 2 +- Todo-ts/src/components/TodoCount.ts | 16 ++++++++++++---- Todo-ts/src/components/TodoForm.ts | 10 +++++++++- Todo-ts/src/components/TodoList.ts | 11 +++++++++-- 6 files changed, 38 insertions(+), 10 deletions(-) diff --git a/Todo-ts/main.css b/Todo-ts/main.css index bd1f22a..b8c129c 100644 --- a/Todo-ts/main.css +++ b/Todo-ts/main.css @@ -19,6 +19,7 @@ h1 { font-size: 2rem; text-align: center; margin: 10px 0; + user-select: none; } /* 입력 폼 */ @@ -60,6 +61,7 @@ h1 { border-radius: 5px; cursor: pointer; box-sizing: border-box; + user-select: none; } .todoForm > button:hover { @@ -99,6 +101,7 @@ h1 { font-size: 1.1rem; font-weight: 700; cursor: pointer; + user-select: none; } .todoList li span:hover { @@ -115,6 +118,7 @@ h1 { border: 0; border-radius: 5px; cursor: pointer; + user-select: none; } .todoList button:hover { @@ -123,6 +127,7 @@ h1 { .completed { text-decoration: line-through; + color: lightgray; } /* TodoCount */ @@ -132,4 +137,5 @@ h1 { text-align: center; font-size: 1.2rem; font-weight: 700; + user-select: none; } diff --git a/Todo-ts/src/components/App.ts b/Todo-ts/src/components/App.ts index caf6d11..08e61b7 100644 --- a/Todo-ts/src/components/App.ts +++ b/Todo-ts/src/components/App.ts @@ -1,5 +1,4 @@ import { NewFuncParams, StateArray } from '../globalTypes'; -import { $app } from '../main'; import { storage } from '../utils/storage'; import validation from '../utils/validation'; import Header from './Header'; @@ -72,7 +71,7 @@ export default function App( // TodoCount const todoCount = new TodoCount({ - $target: $app, + $target, initialState: this.state, }); } diff --git a/Todo-ts/src/components/Header.ts b/Todo-ts/src/components/Header.ts index 7e86757..c013bf9 100644 --- a/Todo-ts/src/components/Header.ts +++ b/Todo-ts/src/components/Header.ts @@ -14,7 +14,7 @@ export default function Header(this: any, { $target, text }: HeaderParams) { const $header: QuerySelectType = document.createElement('h1'); - $target?.appendChild($header); + $target.appendChild($header); this.render = () => { $header.textContent = text; diff --git a/Todo-ts/src/components/TodoCount.ts b/Todo-ts/src/components/TodoCount.ts index ca4d2fd..65c19d4 100644 --- a/Todo-ts/src/components/TodoCount.ts +++ b/Todo-ts/src/components/TodoCount.ts @@ -1,7 +1,15 @@ import { StateArray, StateArrayItem } from '../globalTypes'; import validation from '../utils/validation'; -export default function TodoCount(this: any, { $target, initialState }) { +interface TodoCountParams { + $target: HTMLElement; + initialState: StateArray; +} + +export default function TodoCount( + this: any, + { $target, initialState }: TodoCountParams +) { // new 미사용 방어코드 if (!new.target) { throw new Error('new 키워드를 사용하여야 합니다.'); @@ -16,11 +24,11 @@ export default function TodoCount(this: any, { $target, initialState }) { this.state = validation(initialState); this.render = () => { - const totalTodos = this.state.length; - const completedTodos = this.state.filter( + const totalTodos: number = this.state.length; + const completedTodos: number = this.state.filter( (todo: StateArrayItem) => todo.isCompleted ).length; - $todoCount.innerHTML = `완료된 Todo의 갯수 : ${completedTodos} / 전체 Todo 갯수 : ${totalTodos} `; + $todoCount.innerHTML = `완료된 Todo의 갯수 : ${completedTodos}
    전체 Todo 갯수 : ${totalTodos} `; }; this.setState = (nextState: StateArray) => { diff --git a/Todo-ts/src/components/TodoForm.ts b/Todo-ts/src/components/TodoForm.ts index a0fb663..2b21730 100644 --- a/Todo-ts/src/components/TodoForm.ts +++ b/Todo-ts/src/components/TodoForm.ts @@ -1,6 +1,14 @@ import { QuerySelectType } from '../globalTypes'; -export default function TodoForm(this: any, { $target, onSubmit }) { +interface TodoFormParams { + $target: HTMLElement; + onSubmit: (text: string) => void; +} + +export default function TodoForm( + this: any, + { $target, onSubmit }: TodoFormParams +) { // new 미사용 방어코드 if (!new.target) { throw new Error('new 키워드를 사용하여야 합니다.'); diff --git a/Todo-ts/src/components/TodoList.ts b/Todo-ts/src/components/TodoList.ts index aa8811b..268a10b 100644 --- a/Todo-ts/src/components/TodoList.ts +++ b/Todo-ts/src/components/TodoList.ts @@ -1,11 +1,18 @@ // params.$target - 해당 컴포넌트가 추가가 될 DOM element // params.initialState - 해당 컴포넌트의 초기 상태 +import { StateArray } from '../globalTypes'; import validation from '../utils/validation'; +interface TodoListParams { + $target: HTMLElement; + initialState: StateArray; + onClick: (clickedText: string, clickedId: string | undefined) => void; +} + export default function TodoList( this: any, - { $target, initialState, onClick } + { $target, initialState, onClick }: TodoListParams ) { // new 미사용 방어코드 if (!new.target) { @@ -20,7 +27,7 @@ export default function TodoList( // state 유효성 검사 this.state = validation(initialState); - this.setState = (nextState) => { + this.setState = (nextState: StateArray) => { // state 유효성 검사 this.state = validation(nextState); From 2a97c5c7551a7b9830e47159839c32051a28e735 Mon Sep 17 00:00:00 2001 From: Cho-Ik-Jun Date: Sun, 10 Dec 2023 21:18:43 +0900 Subject: [PATCH 13/16] =?UTF-8?q?=F0=9F=9A=9A=20=20move:=20README=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Todo-ts/README.md => README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Todo-ts/README.md => README.md (100%) diff --git a/Todo-ts/README.md b/README.md similarity index 100% rename from Todo-ts/README.md rename to README.md From 0dd3a75b29d88acff3ce0efe7310ccea42eb053b Mon Sep 17 00:00:00 2001 From: Cho-Ik-Jun Date: Sun, 10 Dec 2023 21:40:19 +0900 Subject: [PATCH 14/16] =?UTF-8?q?=20=F0=9F=90=9B=20fix:=20onClick=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Todo-ts/src/components/App.ts | 2 +- Todo-ts/src/components/TodoList.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Todo-ts/src/components/App.ts b/Todo-ts/src/components/App.ts index 08e61b7..3e58b4a 100644 --- a/Todo-ts/src/components/App.ts +++ b/Todo-ts/src/components/App.ts @@ -50,7 +50,7 @@ export default function App( const todoList = new TodoList({ $target, initialState: validation(initialState), - onClick: (text: string, id: string) => { + onClick: (text: string, id: string | undefined) => { const nextState = [...this.state]; // 삭제할 값이 있을 경우 삭제 diff --git a/Todo-ts/src/components/TodoList.ts b/Todo-ts/src/components/TodoList.ts index 268a10b..47f590d 100644 --- a/Todo-ts/src/components/TodoList.ts +++ b/Todo-ts/src/components/TodoList.ts @@ -7,7 +7,7 @@ import validation from '../utils/validation'; interface TodoListParams { $target: HTMLElement; initialState: StateArray; - onClick: (clickedText: string, clickedId: string | undefined) => void; + onClick: (arg1: string, arg2: string | undefined) => void; } export default function TodoList( From 7434a8df050953f5125dc263aa9ece684df98cf6 Mon Sep 17 00:00:00 2001 From: Cho-Ik-Jun Date: Thu, 14 Dec 2023 14:09:09 +0900 Subject: [PATCH 15/16] =?UTF-8?q?=20=20=E2=99=BB=EF=B8=8F=20refactor:=20cr?= =?UTF-8?q?eateElement=EC=97=90=20=EB=8C=80=ED=95=9C=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=ED=83=80=EC=9E=85=20=EC=A7=80=EC=A0=95=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Todo-ts/src/components/Header.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Todo-ts/src/components/Header.ts b/Todo-ts/src/components/Header.ts index c013bf9..9c25d43 100644 --- a/Todo-ts/src/components/Header.ts +++ b/Todo-ts/src/components/Header.ts @@ -1,5 +1,3 @@ -import { QuerySelectType } from '../globalTypes'; - interface HeaderParams { $target: HTMLElement; text: string; @@ -11,8 +9,7 @@ export default function Header(this: any, { $target, text }: HeaderParams) { throw new Error('new 키워드를 사용하여야 합니다.'); } - const $header: QuerySelectType = - document.createElement('h1'); + const $header = document.createElement('h1'); $target.appendChild($header); From fcb266ef79cf9651ecde0cf9ce8bcfdeef0a6881 Mon Sep 17 00:00:00 2001 From: Cho-Ik-Jun Date: Thu, 14 Dec 2023 14:10:08 +0900 Subject: [PATCH 16/16] =?UTF-8?q?=20=20=E2=99=BB=EF=B8=8F=20style:=20min?= =?UTF-8?q?=20width=20=EB=B0=8F=20box-sizing=20=EC=A0=81=EC=9A=A9,=20index?= =?UTF-8?q?.html=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Todo-ts/index.html | 1 - Todo-ts/main.css | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Todo-ts/index.html b/Todo-ts/index.html index 7492532..8cc6b22 100644 --- a/Todo-ts/index.html +++ b/Todo-ts/index.html @@ -9,7 +9,6 @@
    - diff --git a/Todo-ts/main.css b/Todo-ts/main.css index b8c129c..263075d 100644 --- a/Todo-ts/main.css +++ b/Todo-ts/main.css @@ -25,6 +25,7 @@ h1 { /* 입력 폼 */ .todoForm { display: flex; + min-width: 400px; width: 80%; height: 10%; text-align: center; @@ -94,6 +95,7 @@ h1 { border-radius: 5px; align-items: center; justify-content: center; + box-sizing: border-box; } .todoList li span {