-
Notifications
You must be signed in to change notification settings - Fork 2
[조익준]TS Todo Refactor 과제 #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: choikjun
Are you sure you want to change the base?
Changes from 15 commits
71a9858
a1cc173
904462d
d4194fa
def3c1b
e7927cc
9254ed7
9dcd031
e2cbaa1
41d5158
4bf9c58
f0d36c0
c216faa
2a97c5c
0dd3a75
7434a8d
fcb266e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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? |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8" /> | ||
| <link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
| <link rel="stylesheet" href="./main.css" /> | ||
| <title>To Do List TS</title> | ||
| </head> | ||
| <body> | ||
| <main class="app"></main> | ||
| <!-- <div id="app"></div> --> | ||
| <script type="module" src="/src/main.ts"></script> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| /* 전역 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; | ||
| user-select: none; | ||
| } | ||
|
|
||
| /* 입력 폼 */ | ||
| .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; | ||
| user-select: none; | ||
| } | ||
|
|
||
| .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; | ||
| } | ||
harry7435 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| .todoList li span { | ||
| margin: 0 auto; | ||
| font-size: 1.1rem; | ||
| font-weight: 700; | ||
| cursor: pointer; | ||
| user-select: none; | ||
| } | ||
|
|
||
| .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; | ||
| user-select: none; | ||
| } | ||
|
|
||
| .todoList button:hover { | ||
| background: #267b97; | ||
| } | ||
|
|
||
| .completed { | ||
| text-decoration: line-through; | ||
| color: lightgray; | ||
| } | ||
|
|
||
| /* TodoCount */ | ||
| .todoCount { | ||
| width: 80%; | ||
| margin: 10px auto; | ||
| text-align: center; | ||
| font-size: 1.2rem; | ||
| font-weight: 700; | ||
| user-select: none; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| import { NewFuncParams, StateArray } from '../globalTypes'; | ||
| 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, | ||
| { $target, initialState }: NewFuncParams | ||
| ) { | ||
| // new 미사용 방어코드 | ||
| if (!new.target) { | ||
| throw new Error('new 키워드를 사용하여야 합니다.'); | ||
| } | ||
| this.state = initialState; | ||
|
|
||
| this.setState = (nextState: StateArray) => { | ||
| this.state = nextState; | ||
| todoCount.setState(this.state); | ||
| todoList.setState(this.state); | ||
| }; | ||
|
|
||
| // 헤더 | ||
| new Header({ | ||
| $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 | undefined) => { | ||
harry7435 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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, | ||
| initialState: this.state, | ||
| }); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| import { QuerySelectType } from '../globalTypes'; | ||
|
|
||
| interface HeaderParams { | ||
| $target: HTMLElement; | ||
| text: string; | ||
| } | ||
|
|
||
| export default function Header(this: any, { $target, text }: HeaderParams) { | ||
| // new 미사용 방어코드 | ||
| if (!new.target) { | ||
| throw new Error('new 키워드를 사용하여야 합니다.'); | ||
| } | ||
|
|
||
| const $header: QuerySelectType<HTMLHeadingElement> = | ||
| document.createElement('h1'); | ||
|
||
|
|
||
| $target.appendChild($header); | ||
|
|
||
| this.render = () => { | ||
| $header.textContent = text; | ||
| }; | ||
|
|
||
| this.render(); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.