From 5fecde5773675e30e7576a3480b5cf0be29c241b Mon Sep 17 00:00:00 2001 From: dandamdandam Date: Sun, 9 Jun 2024 10:40:54 +0900 Subject: [PATCH 01/15] init --- README.md | 24 +++++++++++++++++++++++- index.html | 2 +- src/App.tsx | 12 ++++++++++++ src/main.js | 0 src/main.tsx | 10 ++++++++++ 5 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/App.tsx delete mode 100644 src/main.js create mode 100644 src/main.tsx diff --git a/README.md b/README.md index 3c0710d2..0cafcda4 100644 --- a/README.md +++ b/README.md @@ -1 +1,23 @@ -# react-todo-list-precourse \ No newline at end of file +# react-todo-list-precourse + +## 기능 정리 + +### 필수 기능 + +- [참고](https://todomvc.com/examples/react/dist/) +- [ ] 할 일 목록 뷰 +- [ ] 할 일 추가 + - input에 입력한 후 Enter나 추가 버튼을 이용해 목록에 추가 + - 아무것도 입력되 있지 않은 경우 추가 불가 +- [ ] 할 일 삭제 + +### 추가 기능 + +- [ ] 할 일 필터링(진행 중, 완료 된 일, 전체) +- [ ] 해야 할 일의 총 개수 출력 +- [ ] 새로고침 시에도 유지 + +## code convention + +- 들여쓰기 depth 2 이하. +- 함수 길이 15라인 이하. diff --git a/index.html b/index.html index b021b5c8..a0af4558 100644 --- a/index.html +++ b/index.html @@ -7,6 +7,6 @@
- + diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 00000000..35e8eeea --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,12 @@ +const App = () => { + return( +
+ dldl + {/*
+ + */} +
+ ); +}; + +export default App; \ No newline at end of file diff --git a/src/main.js b/src/main.js deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main.tsx b/src/main.tsx new file mode 100644 index 00000000..b3078395 --- /dev/null +++ b/src/main.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; + +const root = ReactDOM.createRoot(document.getElementById('app')!); +root.render( + + + +); \ No newline at end of file From 8e8289d8bec3d1034e5a8bb2a059f1d72822e9ef Mon Sep 17 00:00:00 2001 From: dandamdandam Date: Sun, 9 Jun 2024 11:32:12 +0900 Subject: [PATCH 02/15] refactor: main.tsx -> app.js --- index.html | 2 +- src/{App.tsx => Home.tsx} | 8 ++++++-- src/app.js | 6 ++++++ src/main.tsx | 10 ---------- 4 files changed, 13 insertions(+), 13 deletions(-) rename src/{App.tsx => Home.tsx} (57%) create mode 100644 src/app.js delete mode 100644 src/main.tsx diff --git a/index.html b/index.html index a0af4558..d7785a5b 100644 --- a/index.html +++ b/index.html @@ -7,6 +7,6 @@
- + diff --git a/src/App.tsx b/src/Home.tsx similarity index 57% rename from src/App.tsx rename to src/Home.tsx index 35e8eeea..99073dfa 100644 --- a/src/App.tsx +++ b/src/Home.tsx @@ -1,4 +1,8 @@ -const App = () => { +/** + * Todo 홈페이지 컴포넌트 + * + todoList state 관리 + */ +const Home = () => { return(
dldl @@ -9,4 +13,4 @@ const App = () => { ); }; -export default App; \ No newline at end of file +export default Home; \ No newline at end of file diff --git a/src/app.js b/src/app.js new file mode 100644 index 00000000..ceca2066 --- /dev/null +++ b/src/app.js @@ -0,0 +1,6 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import Home from './Home'; + +const root = ReactDOM.createRoot(document.getElementById('app')); +root.render(React.createElement(Home)); \ No newline at end of file diff --git a/src/main.tsx b/src/main.tsx deleted file mode 100644 index b3078395..00000000 --- a/src/main.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import App from './App'; - -const root = ReactDOM.createRoot(document.getElementById('app')!); -root.render( - - - -); \ No newline at end of file From 55ff0190cbc23685ea0b8d81bb1592106ac8a4ed Mon Sep 17 00:00:00 2001 From: dandamdandam Date: Sun, 9 Jun 2024 11:37:43 +0900 Subject: [PATCH 03/15] feat: (Home.tsx) add todoList state --- src/Home.tsx | 22 ++++++++++++++++++++++ src/interfaces/todo.tsx | 5 +++++ 2 files changed, 27 insertions(+) create mode 100644 src/interfaces/todo.tsx diff --git a/src/Home.tsx b/src/Home.tsx index 99073dfa..a845fd56 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -1,8 +1,30 @@ +import { useState, useEffect } from "react"; +import { Todo } from "./interfaces/todo"; + /** * Todo 홈페이지 컴포넌트 * + todoList state 관리 */ const Home = () => { + const [todoList, setTodoList] = useState([]); + + // TODO 테스트 용 데이터 지우기 + const dummyData: Todo[] = [ + { + id: 1, + done: false, + content: 'make todo project' + }, + { + id: 2, + done: true, + content: 'clean room' + }, + ] + useEffect(() => { + setTodoList(dummyData); + },[]) + return(
dldl diff --git a/src/interfaces/todo.tsx b/src/interfaces/todo.tsx new file mode 100644 index 00000000..7cf4d6b2 --- /dev/null +++ b/src/interfaces/todo.tsx @@ -0,0 +1,5 @@ +export interface Todo { + id: number; + done: boolean; + content: string; +} \ No newline at end of file From 00202d36b92d64bb1d2c327668d0b4ac1d3b56e5 Mon Sep 17 00:00:00 2001 From: dandamdandam Date: Sun, 9 Jun 2024 12:12:47 +0900 Subject: [PATCH 04/15] feat:add todoView --- src/Home.tsx | 18 ++++++++---------- src/components/TodoView.tsx | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 src/components/TodoView.tsx diff --git a/src/Home.tsx b/src/Home.tsx index a845fd56..9e798e8e 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -1,5 +1,6 @@ import { useState, useEffect } from "react"; import { Todo } from "./interfaces/todo"; +import TodoView from "./components/TodoView"; /** * Todo 홈페이지 컴포넌트 @@ -20,19 +21,16 @@ const Home = () => { done: true, content: 'clean room' }, - ] + ]; useEffect(() => { setTodoList(dummyData); - },[]) + },[]); - return( -
- dldl - {/*
- - */} -
- ); + return
+ {/*
+ */} + +
; }; export default Home; \ No newline at end of file diff --git a/src/components/TodoView.tsx b/src/components/TodoView.tsx new file mode 100644 index 00000000..723c73d9 --- /dev/null +++ b/src/components/TodoView.tsx @@ -0,0 +1,21 @@ +import { Todo } from "../interfaces/todo"; + +const TodoEl = ({ todo }: { todo: Todo }) => { + return
  • + + +
  • +}; + +/** + * todo 리스트 컴포넌트 + * @param todoList todo 리스트 데이터 + * @returns + */ +const TodoView = ({ todoList }: { todoList:Todo[] }) => { + return
      {todoList.map(todo => + + )}
    ; +}; + +export default TodoView; \ No newline at end of file From 30c6dbfee5de7cf01cd9c986e0880dd3dbe747ab Mon Sep 17 00:00:00 2001 From: dandamdandam Date: Sun, 9 Jun 2024 14:24:42 +0900 Subject: [PATCH 05/15] feat: implement toggle done todo --- README.md | 2 +- src/Home.tsx | 10 +++++++++- src/components/InputTodo.tsx | 0 src/components/TodoView.tsx | 13 +++++++------ 4 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 src/components/InputTodo.tsx diff --git a/README.md b/README.md index 0cafcda4..cfd80460 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ### 필수 기능 - [참고](https://todomvc.com/examples/react/dist/) -- [ ] 할 일 목록 뷰 +- [x] 할 일 목록 뷰 - [ ] 할 일 추가 - input에 입력한 후 Enter나 추가 버튼을 이용해 목록에 추가 - 아무것도 입력되 있지 않은 경우 추가 불가 diff --git a/src/Home.tsx b/src/Home.tsx index 9e798e8e..5bcd8c54 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -8,6 +8,14 @@ import TodoView from "./components/TodoView"; */ const Home = () => { const [todoList, setTodoList] = useState([]); + /** + * todoList의 n번째 todo의 done 여부를 토글하는 함수 + * @param index + */ + const toggleTodoDone = (index: number) => { + todoList[index].done=!todoList[index].done; + setTodoList([...todoList]); + } // TODO 테스트 용 데이터 지우기 const dummyData: Todo[] = [ @@ -29,7 +37,7 @@ const Home = () => { return
    {/*
    */} - +
    ; }; diff --git a/src/components/InputTodo.tsx b/src/components/InputTodo.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/components/TodoView.tsx b/src/components/TodoView.tsx index 723c73d9..2e20e02b 100644 --- a/src/components/TodoView.tsx +++ b/src/components/TodoView.tsx @@ -1,20 +1,21 @@ +import React from "react"; import { Todo } from "../interfaces/todo"; -const TodoEl = ({ todo }: { todo: Todo }) => { +const TodoEl = React.memo(({ todo, index, toggleTodoDone }: { todo: Todo, index: number, toggleTodoDone: (index: number) => void }) => { return
  • - + toggleTodoDone(index)} name={`todo${todo.id}`}/>
  • -}; +}); /** * todo 리스트 컴포넌트 * @param todoList todo 리스트 데이터 * @returns */ -const TodoView = ({ todoList }: { todoList:Todo[] }) => { - return
      {todoList.map(todo => - +const TodoView = ({ todoList, toggleTodoDone }: { todoList:Todo[], toggleTodoDone: (index: number) => void }) => { + return
        {todoList.map((todo, index) => + )}
      ; }; From 25f268397abf820c003940c8bede913b3ce6ba95 Mon Sep 17 00:00:00 2001 From: dandamdandam Date: Sun, 9 Jun 2024 15:22:08 +0900 Subject: [PATCH 06/15] refactor: (Home) toggleTodoDone -> changeNthTodo --- src/Home.tsx | 11 ++++++----- src/components/TodoView.tsx | 14 +++++++++----- src/{interfaces/todo.tsx => interfaces.tsx} | 4 ++++ 3 files changed, 19 insertions(+), 10 deletions(-) rename src/{interfaces/todo.tsx => interfaces.tsx} (51%) diff --git a/src/Home.tsx b/src/Home.tsx index 5bcd8c54..6366383e 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -1,5 +1,6 @@ import { useState, useEffect } from "react"; -import { Todo } from "./interfaces/todo"; + +import { Todo } from "./interfaces"; import TodoView from "./components/TodoView"; /** @@ -9,11 +10,11 @@ import TodoView from "./components/TodoView"; const Home = () => { const [todoList, setTodoList] = useState([]); /** - * todoList의 n번째 todo의 done 여부를 토글하는 함수 + * todoList의 n번째 todo를 변경하는 함수 * @param index */ - const toggleTodoDone = (index: number) => { - todoList[index].done=!todoList[index].done; + const changeNthTodo = (index: number, value: Todo) => { + todoList[index]=value; setTodoList([...todoList]); } @@ -37,7 +38,7 @@ const Home = () => { return
      {/*
      */} - +
      ; }; diff --git a/src/components/TodoView.tsx b/src/components/TodoView.tsx index 2e20e02b..9d4e055a 100644 --- a/src/components/TodoView.tsx +++ b/src/components/TodoView.tsx @@ -1,9 +1,13 @@ import React from "react"; -import { Todo } from "../interfaces/todo"; +import { Todo, ChangeNthTodo } from "../interfaces"; -const TodoEl = React.memo(({ todo, index, toggleTodoDone }: { todo: Todo, index: number, toggleTodoDone: (index: number) => void }) => { +const TodoEl = React.memo(({ todo, index, changeNthTodo }: { todo: Todo, index: number, changeNthTodo: ChangeNthTodo }) => { + const toggleTodoDone = () => { + todo.done = !todo.done; + changeNthTodo(index, todo); + } return
    • - toggleTodoDone(index)} name={`todo${todo.id}`}/> +
    • }); @@ -13,9 +17,9 @@ const TodoEl = React.memo(({ todo, index, toggleTodoDone }: { todo: Todo, index: * @param todoList todo 리스트 데이터 * @returns */ -const TodoView = ({ todoList, toggleTodoDone }: { todoList:Todo[], toggleTodoDone: (index: number) => void }) => { +const TodoView = ({ todoList, changeNthTodo }: { todoList:Todo[], changeNthTodo: ChangeNthTodo }) => { return
        {todoList.map((todo, index) => - + )}
      ; }; diff --git a/src/interfaces/todo.tsx b/src/interfaces.tsx similarity index 51% rename from src/interfaces/todo.tsx rename to src/interfaces.tsx index 7cf4d6b2..81bc5aee 100644 --- a/src/interfaces/todo.tsx +++ b/src/interfaces.tsx @@ -2,4 +2,8 @@ export interface Todo { id: number; done: boolean; content: string; +} + +export interface ChangeNthTodo{ + (index: number, value: Todo): void; } \ No newline at end of file From 580664c15a92cf8c8c011031ffd4456a405a5675 Mon Sep 17 00:00:00 2001 From: dandamdandam Date: Sun, 9 Jun 2024 15:38:15 +0900 Subject: [PATCH 07/15] Revert "refactor: (Home) toggleTodoDone -> changeNthTodo" This reverts commit 25f268397abf820c003940c8bede913b3ce6ba95. --- src/Home.tsx | 11 +++++------ src/components/TodoView.tsx | 14 +++++--------- src/{interfaces.tsx => interfaces/todo.tsx} | 4 ---- 3 files changed, 10 insertions(+), 19 deletions(-) rename src/{interfaces.tsx => interfaces/todo.tsx} (51%) diff --git a/src/Home.tsx b/src/Home.tsx index 6366383e..5bcd8c54 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -1,6 +1,5 @@ import { useState, useEffect } from "react"; - -import { Todo } from "./interfaces"; +import { Todo } from "./interfaces/todo"; import TodoView from "./components/TodoView"; /** @@ -10,11 +9,11 @@ import TodoView from "./components/TodoView"; const Home = () => { const [todoList, setTodoList] = useState([]); /** - * todoList의 n번째 todo를 변경하는 함수 + * todoList의 n번째 todo의 done 여부를 토글하는 함수 * @param index */ - const changeNthTodo = (index: number, value: Todo) => { - todoList[index]=value; + const toggleTodoDone = (index: number) => { + todoList[index].done=!todoList[index].done; setTodoList([...todoList]); } @@ -38,7 +37,7 @@ const Home = () => { return
      {/*
      */} - +
      ; }; diff --git a/src/components/TodoView.tsx b/src/components/TodoView.tsx index 9d4e055a..2e20e02b 100644 --- a/src/components/TodoView.tsx +++ b/src/components/TodoView.tsx @@ -1,13 +1,9 @@ import React from "react"; -import { Todo, ChangeNthTodo } from "../interfaces"; +import { Todo } from "../interfaces/todo"; -const TodoEl = React.memo(({ todo, index, changeNthTodo }: { todo: Todo, index: number, changeNthTodo: ChangeNthTodo }) => { - const toggleTodoDone = () => { - todo.done = !todo.done; - changeNthTodo(index, todo); - } +const TodoEl = React.memo(({ todo, index, toggleTodoDone }: { todo: Todo, index: number, toggleTodoDone: (index: number) => void }) => { return
    • - + toggleTodoDone(index)} name={`todo${todo.id}`}/>
    • }); @@ -17,9 +13,9 @@ const TodoEl = React.memo(({ todo, index, changeNthTodo }: { todo: Todo, index: * @param todoList todo 리스트 데이터 * @returns */ -const TodoView = ({ todoList, changeNthTodo }: { todoList:Todo[], changeNthTodo: ChangeNthTodo }) => { +const TodoView = ({ todoList, toggleTodoDone }: { todoList:Todo[], toggleTodoDone: (index: number) => void }) => { return
        {todoList.map((todo, index) => - + )}
      ; }; diff --git a/src/interfaces.tsx b/src/interfaces/todo.tsx similarity index 51% rename from src/interfaces.tsx rename to src/interfaces/todo.tsx index 81bc5aee..7cf4d6b2 100644 --- a/src/interfaces.tsx +++ b/src/interfaces/todo.tsx @@ -2,8 +2,4 @@ export interface Todo { id: number; done: boolean; content: string; -} - -export interface ChangeNthTodo{ - (index: number, value: Todo): void; } \ No newline at end of file From a118e415b2c0a00458f64d5fa168a62471660674 Mon Sep 17 00:00:00 2001 From: dandamdandam Date: Sun, 9 Jun 2024 15:45:12 +0900 Subject: [PATCH 08/15] refactor: interfaces folder -> interfaces.tsx --- src/Home.tsx | 5 +++-- src/components/TodoView.tsx | 6 +++--- src/{interfaces/todo.tsx => interfaces.tsx} | 3 +++ 3 files changed, 9 insertions(+), 5 deletions(-) rename src/{interfaces/todo.tsx => interfaces.tsx} (56%) diff --git a/src/Home.tsx b/src/Home.tsx index 5bcd8c54..6c257776 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -1,5 +1,6 @@ import { useState, useEffect } from "react"; -import { Todo } from "./interfaces/todo"; + +import { Todo, ToggleTodoDone } from "./interfaces"; import TodoView from "./components/TodoView"; /** @@ -12,7 +13,7 @@ const Home = () => { * todoList의 n번째 todo의 done 여부를 토글하는 함수 * @param index */ - const toggleTodoDone = (index: number) => { + const toggleTodoDone: ToggleTodoDone = index => { todoList[index].done=!todoList[index].done; setTodoList([...todoList]); } diff --git a/src/components/TodoView.tsx b/src/components/TodoView.tsx index 2e20e02b..4f30d052 100644 --- a/src/components/TodoView.tsx +++ b/src/components/TodoView.tsx @@ -1,7 +1,7 @@ import React from "react"; -import { Todo } from "../interfaces/todo"; +import { Todo, ToggleTodoDone } from "../interfaces"; -const TodoEl = React.memo(({ todo, index, toggleTodoDone }: { todo: Todo, index: number, toggleTodoDone: (index: number) => void }) => { +const TodoEl = React.memo(({ todo, index, toggleTodoDone }: { todo: Todo, index: number, toggleTodoDone: ToggleTodoDone }) => { return
    • toggleTodoDone(index)} name={`todo${todo.id}`}/> @@ -13,7 +13,7 @@ const TodoEl = React.memo(({ todo, index, toggleTodoDone }: { todo: Todo, index: * @param todoList todo 리스트 데이터 * @returns */ -const TodoView = ({ todoList, toggleTodoDone }: { todoList:Todo[], toggleTodoDone: (index: number) => void }) => { +const TodoView = ({ todoList, toggleTodoDone }: { todoList:Todo[], toggleTodoDone: ToggleTodoDone }) => { return
        {todoList.map((todo, index) => )}
      ; diff --git a/src/interfaces/todo.tsx b/src/interfaces.tsx similarity index 56% rename from src/interfaces/todo.tsx rename to src/interfaces.tsx index 7cf4d6b2..113e20a5 100644 --- a/src/interfaces/todo.tsx +++ b/src/interfaces.tsx @@ -2,4 +2,7 @@ export interface Todo { id: number; done: boolean; content: string; +} +export interface ToggleTodoDone{ + (index: number): void; } \ No newline at end of file From 4b6950be2b5cfaa9dac2810e0c745b34029d2528 Mon Sep 17 00:00:00 2001 From: dandamdandam Date: Sun, 9 Jun 2024 16:29:36 +0900 Subject: [PATCH 09/15] feat: implement add todo --- README.md | 2 +- src/Home.tsx | 35 ++++++++++------------------------- src/components/InputTodo.tsx | 18 ++++++++++++++++++ src/components/TodoView.tsx | 5 ++--- src/interfaces.tsx | 8 ++++++++ 5 files changed, 39 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index cfd80460..8dbbc03d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ - [참고](https://todomvc.com/examples/react/dist/) - [x] 할 일 목록 뷰 -- [ ] 할 일 추가 +- [x] 할 일 추가 - input에 입력한 후 Enter나 추가 버튼을 이용해 목록에 추가 - 아무것도 입력되 있지 않은 경우 추가 불가 - [ ] 할 일 삭제 diff --git a/src/Home.tsx b/src/Home.tsx index 6c257776..417fae95 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -1,7 +1,8 @@ -import { useState, useEffect } from "react"; +import { useState } from "react"; -import { Todo, ToggleTodoDone } from "./interfaces"; +import { Todo, ToggleTodoDone, AddTodo } from "./interfaces"; import TodoView from "./components/TodoView"; +import InputTodo from "./components/InputTodo"; /** * Todo 홈페이지 컴포넌트 @@ -9,35 +10,19 @@ import TodoView from "./components/TodoView"; */ const Home = () => { const [todoList, setTodoList] = useState([]); - /** - * todoList의 n번째 todo의 done 여부를 토글하는 함수 - * @param index - */ const toggleTodoDone: ToggleTodoDone = index => { todoList[index].done=!todoList[index].done; setTodoList([...todoList]); } - - // TODO 테스트 용 데이터 지우기 - const dummyData: Todo[] = [ - { - id: 1, - done: false, - content: 'make todo project' - }, - { - id: 2, - done: true, - content: 'clean room' - }, - ]; - useEffect(() => { - setTodoList(dummyData); - },[]); + const addTodo: AddTodo = content => { + let nextId: number = todoList.length>0 ? todoList[todoList.length-1].id+1 : 0; + todoList.push({id: nextId, done: false, content: content}); + setTodoList([...todoList]); + } return
      - {/*
      - */} + {/*
      */} +
      ; }; diff --git a/src/components/InputTodo.tsx b/src/components/InputTodo.tsx index e69de29b..a73f6568 100644 --- a/src/components/InputTodo.tsx +++ b/src/components/InputTodo.tsx @@ -0,0 +1,18 @@ +import { useState } from "react"; + +import { AddTodo } from "../interfaces"; + +const InputTodo = ({ addTodo }: { addTodo: AddTodo }) => { + const [content, setContent] = useState(""); + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + addTodo(content); + setContent(""); + } + return
      + {setContent(e.currentTarget.value)}}/> + +
      ; +} + +export default InputTodo; \ No newline at end of file diff --git a/src/components/TodoView.tsx b/src/components/TodoView.tsx index 4f30d052..eeebcd82 100644 --- a/src/components/TodoView.tsx +++ b/src/components/TodoView.tsx @@ -1,12 +1,11 @@ -import React from "react"; import { Todo, ToggleTodoDone } from "../interfaces"; -const TodoEl = React.memo(({ todo, index, toggleTodoDone }: { todo: Todo, index: number, toggleTodoDone: ToggleTodoDone }) => { +const TodoEl = ({ todo, index, toggleTodoDone }: { todo: Todo, index: number, toggleTodoDone: ToggleTodoDone }) => { return
    • toggleTodoDone(index)} name={`todo${todo.id}`}/>
    • -}); +}; /** * todo 리스트 컴포넌트 diff --git a/src/interfaces.tsx b/src/interfaces.tsx index 113e20a5..f4d69773 100644 --- a/src/interfaces.tsx +++ b/src/interfaces.tsx @@ -3,6 +3,14 @@ export interface Todo { done: boolean; content: string; } + +/** + * todoList의 n번째 todo의 done 여부를 토글하는 함수 + * @param index + */ export interface ToggleTodoDone{ (index: number): void; +} +export interface AddTodo{ + (content: string): void; } \ No newline at end of file From e64fc6ee2926d9f7a0f43631f0c4328459e9b7e6 Mon Sep 17 00:00:00 2001 From: dandamdandam Date: Sun, 9 Jun 2024 21:16:07 +0900 Subject: [PATCH 10/15] feat: implement remove todo --- src/Home.tsx | 6 +++++- src/components/TodoView.tsx | 9 +++++---- src/interfaces.tsx | 11 +++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Home.tsx b/src/Home.tsx index 417fae95..e05dc10a 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -19,11 +19,15 @@ const Home = () => { todoList.push({id: nextId, done: false, content: content}); setTodoList([...todoList]); } + const removeTodo = (index: number) => { + todoList.splice(index, 1); + setTodoList([...todoList]); + } return
      {/*
      */} - +
      ; }; diff --git a/src/components/TodoView.tsx b/src/components/TodoView.tsx index eeebcd82..b624b79f 100644 --- a/src/components/TodoView.tsx +++ b/src/components/TodoView.tsx @@ -1,9 +1,10 @@ -import { Todo, ToggleTodoDone } from "../interfaces"; +import { RemoveTodo, Todo, ToggleTodoDone } from "../interfaces"; -const TodoEl = ({ todo, index, toggleTodoDone }: { todo: Todo, index: number, toggleTodoDone: ToggleTodoDone }) => { +const TodoEl = ({ todo, index, toggleTodoDone, removeTodo }: { todo: Todo, index: number, toggleTodoDone: ToggleTodoDone, removeTodo: RemoveTodo }) => { return
    • toggleTodoDone(index)} name={`todo${todo.id}`}/> +
    • }; @@ -12,9 +13,9 @@ const TodoEl = ({ todo, index, toggleTodoDone }: { todo: Todo, index: number, to * @param todoList todo 리스트 데이터 * @returns */ -const TodoView = ({ todoList, toggleTodoDone }: { todoList:Todo[], toggleTodoDone: ToggleTodoDone }) => { +const TodoView = ({ todoList, toggleTodoDone, removeTodo }: { todoList:Todo[], toggleTodoDone: ToggleTodoDone, removeTodo: RemoveTodo }) => { return
        {todoList.map((todo, index) => - + )}
      ; }; diff --git a/src/interfaces.tsx b/src/interfaces.tsx index f4d69773..996ed235 100644 --- a/src/interfaces.tsx +++ b/src/interfaces.tsx @@ -11,6 +11,17 @@ export interface Todo { export interface ToggleTodoDone{ (index: number): void; } +/** + * todoList에 todo 추가 + * @param content + */ export interface AddTodo{ (content: string): void; +} +/** + * todoList의 n번째 todo를 삭제하는 함수 + * @param index + */ +export interface RemoveTodo{ + (index: number): void; } \ No newline at end of file From c6f9f1222757a97cbd623f4df5b85ab65c7580cf Mon Sep 17 00:00:00 2001 From: dandamdandam Date: Sun, 9 Jun 2024 21:22:06 +0900 Subject: [PATCH 11/15] fix: block add if content=='' --- src/components/InputTodo.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/InputTodo.tsx b/src/components/InputTodo.tsx index a73f6568..6d25b80f 100644 --- a/src/components/InputTodo.tsx +++ b/src/components/InputTodo.tsx @@ -6,6 +6,7 @@ const InputTodo = ({ addTodo }: { addTodo: AddTodo }) => { const [content, setContent] = useState(""); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); + if(""===content) return; addTodo(content); setContent(""); } From 3158b512ff4ce70d3e1bd045a6bc3c99b6badcad Mon Sep 17 00:00:00 2001 From: dandamdandam Date: Sun, 9 Jun 2024 21:30:40 +0900 Subject: [PATCH 12/15] refactor: split Home component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit todoList를 관리하는 함수와 UI 랜더링 컴포넌트로 나눔 --- README.md | 2 +- src/Home.tsx | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8dbbc03d..02a84f43 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ - [x] 할 일 추가 - input에 입력한 후 Enter나 추가 버튼을 이용해 목록에 추가 - 아무것도 입력되 있지 않은 경우 추가 불가 -- [ ] 할 일 삭제 +- [x] 할 일 삭제 ### 추가 기능 diff --git a/src/Home.tsx b/src/Home.tsx index e05dc10a..f021b1d4 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -1,15 +1,16 @@ import { useState } from "react"; -import { Todo, ToggleTodoDone, AddTodo } from "./interfaces"; +import { Todo, ToggleTodoDone, AddTodo, RemoveTodo } from "./interfaces"; import TodoView from "./components/TodoView"; import InputTodo from "./components/InputTodo"; /** - * Todo 홈페이지 컴포넌트 - * + todoList state 관리 + * todo state 관련된 CRUD 함수 + * @param todoList + * @param setTodoList + * @returns */ -const Home = () => { - const [todoList, setTodoList] = useState([]); +const TodoListFunc = (todoList: Todo[], setTodoList: React.Dispatch>) => { const toggleTodoDone: ToggleTodoDone = index => { todoList[index].done=!todoList[index].done; setTodoList([...todoList]); @@ -19,10 +20,19 @@ const Home = () => { todoList.push({id: nextId, done: false, content: content}); setTodoList([...todoList]); } - const removeTodo = (index: number) => { + const removeTodo: RemoveTodo = index => { todoList.splice(index, 1); setTodoList([...todoList]); } + return {toggleTodoDone, addTodo, removeTodo}; +} +/** + * Todo 홈페이지 컴포넌트 + * + todoList state 관리 + */ +const Home = () => { + const [todoList, setTodoList] = useState([]); + const {toggleTodoDone, addTodo, removeTodo} = TodoListFunc(todoList, setTodoList); return
      {/*
      */} From 1f08ca3f6b3568eff31a6db16006050c125746d5 Mon Sep 17 00:00:00 2001 From: dandamdandam Date: Sun, 9 Jun 2024 23:13:37 +0900 Subject: [PATCH 13/15] feat: add global design file --- index.html | 1 + src/Home.tsx | 6 +- src/styles/Home.css | 3 + src/styles/global.css | 156 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 src/styles/Home.css create mode 100644 src/styles/global.css diff --git a/index.html b/index.html index d7785a5b..a3ee5a7a 100644 --- a/index.html +++ b/index.html @@ -3,6 +3,7 @@ + diff --git a/src/Home.tsx b/src/Home.tsx index f021b1d4..48bbc6f6 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -3,6 +3,8 @@ import { useState } from "react"; import { Todo, ToggleTodoDone, AddTodo, RemoveTodo } from "./interfaces"; import TodoView from "./components/TodoView"; import InputTodo from "./components/InputTodo"; +import Header from "./components/Header"; +import "./styles/Home.css"; /** * todo state 관련된 CRUD 함수 @@ -34,8 +36,8 @@ const Home = () => { const [todoList, setTodoList] = useState([]); const {toggleTodoDone, addTodo, removeTodo} = TodoListFunc(todoList, setTodoList); - return
      - {/*
      */} + return
      +
      ; diff --git a/src/styles/Home.css b/src/styles/Home.css new file mode 100644 index 00000000..faca44b0 --- /dev/null +++ b/src/styles/Home.css @@ -0,0 +1,3 @@ +.homepage{ + padding: 30px; +} \ No newline at end of file diff --git a/src/styles/global.css b/src/styles/global.css new file mode 100644 index 00000000..5469e36f --- /dev/null +++ b/src/styles/global.css @@ -0,0 +1,156 @@ +:root { + --main-c: #517acd; + --side-c: #c2cf7d; +} + +body{ + background-color: #111111; +} + +html, +body, +div, +span, +applet, +object, +iframe, +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +big, +cite, +code, +del, +dfn, +em, +img, +ins, +kbd, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +b, +u, +i, +center, +dl, +dt, +dd, +ol, +ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td, +article, +aside, +canvas, +details, +embed, +figure, +figcaption, +footer, +header, +hgroup, +menu, +nav, +output, +ruby, +section, +summary, +time, +mark, +audio, +video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +ol, +ul { + list-style: none; +} +blockquote, +q { + quotes: none; +} +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ""; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} + +a{ + color: inherit; + text-decoration: none; +} + +a:hover{ + text-decoration: underline; +} + +button{ + background: none; + color: inherit; + border: none; + padding: 0; + font: inherit; + cursor: pointer; + outline: inherit; +} + +input, textarea, select{ + background: var(--side-c); + color: inherit; + border: none; + font: inherit; + cursor: text; + outline: inherit; + resize: none; +} \ No newline at end of file From e9b36c0c12ac20ef2c1c70b44d35ce711195debe Mon Sep 17 00:00:00 2001 From: dandamdandam Date: Sun, 9 Jun 2024 23:48:28 +0900 Subject: [PATCH 14/15] feat: add header design --- src/components/Header.tsx | 17 +++++++++++++++++ src/styles/global.css | 10 ++++++++++ src/styles/header.css | 25 +++++++++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 src/components/Header.tsx create mode 100644 src/styles/header.css diff --git a/src/components/Header.tsx b/src/components/Header.tsx new file mode 100644 index 00000000..452ea95b --- /dev/null +++ b/src/components/Header.tsx @@ -0,0 +1,17 @@ +import { useState } from "react"; + +import "../styles/header.css"; + +const Header = () => { + const [gettedAdvice, setGettedAdvice] = useState("Loading..."); + fetch("https://api.adviceslip.com/advice") + .then(res => res.json()) + .then(data => {setGettedAdvice(data.slip.advice)}); + + return
      +

      Todo List

      +

      {gettedAdvice}

      +
      ; +} + +export default Header; \ No newline at end of file diff --git a/src/styles/global.css b/src/styles/global.css index 5469e36f..dbaf6b8e 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -1,10 +1,20 @@ +@font-face { + font-family: 'Pretendard-Regular'; + src: url('https://fastly.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Regular.woff') format('woff'); + font-weight: 400; + font-style: normal; +} + :root { --main-c: #517acd; --side-c: #c2cf7d; } body{ + font-family: 'Pretendard-Regular'; + font-size: 16px; background-color: #111111; + color: #f9f9f9; } html, diff --git a/src/styles/header.css b/src/styles/header.css new file mode 100644 index 00000000..39e3d1d2 --- /dev/null +++ b/src/styles/header.css @@ -0,0 +1,25 @@ +.header h1{ + width: fit-content; + margin-bottom: 20px; + + background: linear-gradient(40deg, var(--main-c), var(--side-c)); + color: transparent; + -webkit-background-clip: text; + + font-weight: 800; + font-size: 30px; +} +.header p{ + padding: 10px 10px 0px 10px; + margin-bottom: 20px; + border-radius: 10px; + font-style: italic; + background-color: #181818; +} +.header p::before, .header p::after{ + content: "‟"; + display: block; + + color: var(--side-c); + font-size: 30px; +} \ No newline at end of file From d5946d9c2164293b5e6bb86bb5af2a784bc7b2d3 Mon Sep 17 00:00:00 2001 From: dandamdandam Date: Sun, 9 Jun 2024 23:56:24 +0900 Subject: [PATCH 15/15] add inputTodo design --- src/components/InputTodo.tsx | 3 ++- src/styles/global.css | 21 +++++++++++++-------- src/styles/inputTodo.css | 8 ++++++++ 3 files changed, 23 insertions(+), 9 deletions(-) create mode 100644 src/styles/inputTodo.css diff --git a/src/components/InputTodo.tsx b/src/components/InputTodo.tsx index 6d25b80f..f6fc740d 100644 --- a/src/components/InputTodo.tsx +++ b/src/components/InputTodo.tsx @@ -1,6 +1,7 @@ import { useState } from "react"; import { AddTodo } from "../interfaces"; +import "../styles/inputTodo.css" const InputTodo = ({ addTodo }: { addTodo: AddTodo }) => { const [content, setContent] = useState(""); @@ -10,7 +11,7 @@ const InputTodo = ({ addTodo }: { addTodo: AddTodo }) => { addTodo(content); setContent(""); } - return
      + return {setContent(e.currentTarget.value)}}/>
      ; diff --git a/src/styles/global.css b/src/styles/global.css index dbaf6b8e..0ff3cc13 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -10,13 +10,6 @@ --side-c: #c2cf7d; } -body{ - font-family: 'Pretendard-Regular'; - font-size: 16px; - background-color: #111111; - color: #f9f9f9; -} - html, body, div, @@ -146,7 +139,7 @@ a:hover{ } button{ - background: none; + background: none; color: inherit; border: none; padding: 0; @@ -163,4 +156,16 @@ input, textarea, select{ cursor: text; outline: inherit; resize: none; +} + +body{ + font-family: 'Pretendard-Regular'; + font-size: 16px; + background-color: #111111; + color: #f9f9f9; +} +button{ + padding: 5px 10px; + border: 3px solid var(--side-c); + border-radius: 10px; } \ No newline at end of file diff --git a/src/styles/inputTodo.css b/src/styles/inputTodo.css new file mode 100644 index 00000000..9720809d --- /dev/null +++ b/src/styles/inputTodo.css @@ -0,0 +1,8 @@ +.inputTodo input{ + padding: 5px 10px; + margin-right: 5px; + border-radius: 8px; + border: 2px solid var(--side-c); + + color: #111111; +} \ No newline at end of file