From 8f2719a145fe213a18f02ef8ec1ab216f4a0a5c9 Mon Sep 17 00:00:00 2001 From: anheejeong Date: Fri, 31 May 2024 21:34:05 +0900 Subject: [PATCH 01/11] Docs: Update README.md --- README.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c0710d2..ff82efd9 100644 --- a/README.md +++ b/README.md @@ -1 +1,33 @@ -# react-todo-list-precourse \ No newline at end of file +# react-todo-list-precourse + +## 할 일 목록 + +하루 또는 한 주의 할 일 목록을 업데이트하는 할 일 목록을 구현한다. + +### 기능 설명 + +- 사용자는 할 일을 입력한다. +- 추가 버튼 클릭, 혹은 엔터 키 클릭으로 할 일을 추가한다.(아무것도 입력하지 않았을 경우 추가 x) +- 사용자가 추가한 할 일의 목록을 볼 수 있다. +- 할 일의 완료 상태를 전활할 수 있다. + +### 선택 기능 설명 + +- 현재 진행 중인 할 일, 완료된 할 일, 모든 할 일을 필터링할 수 있다. +- 해야 할 일의 총개수를 확인할 수 있다. +- 새로고침을 하여도 이전에 작성한 데이터는 유지되어야 한다. + +### 에러 처리 + +사용자가 아무것도 입력하지 않았을 경우
+-> 추가 버튼 클릭 비활성화 및 엔터 키 비활성화 + +### 기술 스택 + +HTML, CSS, JavaScript, React + +### 컴포넌트 분리 + +- 할 일 입력 +- 할 일 목록 +- 필터링 버튼 \ No newline at end of file From 523ccafd0abcf682399432ca54308dd800f8ecc7 Mon Sep 17 00:00:00 2001 From: anheejeong Date: Fri, 7 Jun 2024 23:38:32 +0900 Subject: [PATCH 02/11] Feat: Implement new text input --- index.html | 23 +++++++------ src/App.js | 6 ++++ src/components/newTodo/NewTodo.jsx | 32 +++++++++++++++++++ .../newTodo/newTodo.module.scss} | 0 src/main.jsx | 19 +++++++++++ 5 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 src/App.js create mode 100644 src/components/newTodo/NewTodo.jsx rename src/{main.js => components/newTodo/newTodo.module.scss} (100%) create mode 100644 src/main.jsx diff --git a/index.html b/index.html index b021b5c8..29923517 100644 --- a/index.html +++ b/index.html @@ -1,12 +1,15 @@ - - - - - - -
- - - + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/src/App.js b/src/App.js new file mode 100644 index 00000000..c5f7e962 --- /dev/null +++ b/src/App.js @@ -0,0 +1,6 @@ +import React from "react"; +import { createRoot } from "react-dom/client"; +import Main from "./main"; + +const root = createRoot(document.getElementById("root")); +root.render(React.createElement(Main)); \ No newline at end of file diff --git a/src/components/newTodo/NewTodo.jsx b/src/components/newTodo/NewTodo.jsx new file mode 100644 index 00000000..9434be73 --- /dev/null +++ b/src/components/newTodo/NewTodo.jsx @@ -0,0 +1,32 @@ +import React, { useCallback, useState } from "react"; + +const NewTodo = ({ newText, setNewTodo }) => { + const [texting, setTexting] = useState(''); + const onChangeText = useCallback((e) => { + setTexting(e.target.value) + }, [texting]) + const onEnterSubmitHandler = useCallback((e) => { + if (e.key === 'Enter' && texting) { + setNewTodo(texting); + } + }, [texting, newText]) + const onButtonSubmitHandler = useCallback(() => { + setNewTodo(texting); + }, [texting, newText]) + return ( +
+ + {texting ? + + : <>} +
+ ); +} + +export default NewTodo; \ No newline at end of file diff --git a/src/main.js b/src/components/newTodo/newTodo.module.scss similarity index 100% rename from src/main.js rename to src/components/newTodo/newTodo.module.scss diff --git a/src/main.jsx b/src/main.jsx new file mode 100644 index 00000000..64db6c4b --- /dev/null +++ b/src/main.jsx @@ -0,0 +1,19 @@ +import React, { useState, useEffect } from "react"; +import NewTodo from "./components/newTodo/NewTodo"; + +const Main = () => { + const [newTodo, setNewTodo] = useState(''); + useEffect(() => { console.log(newTodo) }, [newTodo]) + + return ( +
+

todos

+ +
+ ); +} + +export default Main; \ No newline at end of file From 280ef7ebc9fd9edac38e05c22deb4a08c9a1ff5a Mon Sep 17 00:00:00 2001 From: anheejeong Date: Sat, 8 Jun 2024 00:31:26 +0900 Subject: [PATCH 03/11] Feat: Implement todo list --- src/components/todoList/TodoList.jsx | 23 ++++++++++++++++++++ src/components/todoList/todoList.module.scss | 0 src/main.jsx | 11 +++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/components/todoList/TodoList.jsx create mode 100644 src/components/todoList/todoList.module.scss diff --git a/src/components/todoList/TodoList.jsx b/src/components/todoList/TodoList.jsx new file mode 100644 index 00000000..4921ec9a --- /dev/null +++ b/src/components/todoList/TodoList.jsx @@ -0,0 +1,23 @@ +import React, { useState, useEffect } from "react"; + +const TodoList = ({ todoList }) => { + const [doneStatus, setDoneStatus] = useState(Array(todoList.length).fill(false)); + useEffect(() => { + setDoneStatus(Array(todoList.length).fill(false)); + }, [todoList]); + const toggleDone = (idx) => { + setDoneStatus(doneStatus.map((status, index) => idx === index ? !status : status)); + }; + return ( +
+ {todoList ? todoList.map((todo, idx) => ( +
+ {todo} + +
+ )) : <>} +
+ ) +} + +export default TodoList; \ No newline at end of file diff --git a/src/components/todoList/todoList.module.scss b/src/components/todoList/todoList.module.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/main.jsx b/src/main.jsx index 64db6c4b..006fb2cd 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -1,9 +1,15 @@ import React, { useState, useEffect } from "react"; import NewTodo from "./components/newTodo/NewTodo"; +import TodoList from "./components/todoList/TodoList"; const Main = () => { const [newTodo, setNewTodo] = useState(''); - useEffect(() => { console.log(newTodo) }, [newTodo]) + const [todoList, setTodoList] = useState([]); + useEffect(() => { + console.log(newTodo); + newTodo ? setTodoList([...todoList, newTodo]) : ''; + setNewTodo(''); + }, [newTodo]) return (
@@ -12,6 +18,9 @@ const Main = () => { newText={newTodo} setNewTodo={setNewTodo} /> +
); } From a359260f3fe7f7e01b21222f655fb16113707d2e Mon Sep 17 00:00:00 2001 From: anheejeong Date: Mon, 10 Jun 2024 01:04:30 +0900 Subject: [PATCH 04/11] Feat: Implement Delete Button --- src/components/todoList/TodoList.jsx | 8 ++++++-- src/main.jsx | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/todoList/TodoList.jsx b/src/components/todoList/TodoList.jsx index 4921ec9a..934233e3 100644 --- a/src/components/todoList/TodoList.jsx +++ b/src/components/todoList/TodoList.jsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from "react"; -const TodoList = ({ todoList }) => { +const TodoList = ({ todoList, setTodoList }) => { const [doneStatus, setDoneStatus] = useState(Array(todoList.length).fill(false)); useEffect(() => { setDoneStatus(Array(todoList.length).fill(false)); @@ -8,12 +8,16 @@ const TodoList = ({ todoList }) => { const toggleDone = (idx) => { setDoneStatus(doneStatus.map((status, index) => idx === index ? !status : status)); }; + const onDeleteButtonHandler = (idx) => { + setTodoList(todoList.filter((_, index) => index !== idx)); + } return (
{todoList ? todoList.map((todo, idx) => (
{todo} - + +
)) : <>}
diff --git a/src/main.jsx b/src/main.jsx index 006fb2cd..15632bd8 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -20,6 +20,7 @@ const Main = () => { /> ); From 5f99bb49b77a443bd8e2cb6467c7bd4f65a9e2cd Mon Sep 17 00:00:00 2001 From: anheejeong Date: Mon, 10 Jun 2024 01:09:34 +0900 Subject: [PATCH 05/11] Fix: Empty input field if previous todo submit --- src/components/newTodo/NewTodo.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/newTodo/NewTodo.jsx b/src/components/newTodo/NewTodo.jsx index 9434be73..847ebab7 100644 --- a/src/components/newTodo/NewTodo.jsx +++ b/src/components/newTodo/NewTodo.jsx @@ -1,4 +1,4 @@ -import React, { useCallback, useState } from "react"; +import React, { useCallback, useState, useEffect } from "react"; const NewTodo = ({ newText, setNewTodo }) => { const [texting, setTexting] = useState(''); @@ -13,6 +13,9 @@ const NewTodo = ({ newText, setNewTodo }) => { const onButtonSubmitHandler = useCallback(() => { setNewTodo(texting); }, [texting, newText]) + useEffect(() => { + setTexting(''); + }, [newText]) return (
Date: Mon, 10 Jun 2024 01:25:46 +0900 Subject: [PATCH 06/11] Style: todolist style --- src/components/todoList/TodoList.jsx | 3 ++- src/components/todoList/todoList.module.scss | 0 src/components/todoList/todoList.styles.css | 25 ++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) delete mode 100644 src/components/todoList/todoList.module.scss create mode 100644 src/components/todoList/todoList.styles.css diff --git a/src/components/todoList/TodoList.jsx b/src/components/todoList/TodoList.jsx index 934233e3..af927990 100644 --- a/src/components/todoList/TodoList.jsx +++ b/src/components/todoList/TodoList.jsx @@ -1,4 +1,5 @@ import React, { useState, useEffect } from "react"; +import './todoList.styles.css'; const TodoList = ({ todoList, setTodoList }) => { const [doneStatus, setDoneStatus] = useState(Array(todoList.length).fill(false)); @@ -14,7 +15,7 @@ const TodoList = ({ todoList, setTodoList }) => { return (
{todoList ? todoList.map((todo, idx) => ( -
+
{todo} diff --git a/src/components/todoList/todoList.module.scss b/src/components/todoList/todoList.module.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/src/components/todoList/todoList.styles.css b/src/components/todoList/todoList.styles.css new file mode 100644 index 00000000..63ab0e03 --- /dev/null +++ b/src/components/todoList/todoList.styles.css @@ -0,0 +1,25 @@ +.todolist-boxs button { + margin-left: 10px; +} + +.todolist-boxs-done button { + margin-left: 10px; +} + +.todolist-boxs-done button:nth-child(1) { + color: #ccc; +} + +.todolist-boxs { + padding: 10px; + border: 1px solid #ccc; + margin: 5px 0; +} + +.todolist-boxs-done { + padding: 10px; + border: 1px solid #ccc; + margin: 5px 0; + text-decoration: line-through; + color: #ccc; +} \ No newline at end of file From 5ec6343c10a65fb47167785b06d8a98cad2123c5 Mon Sep 17 00:00:00 2001 From: anheejeong Date: Mon, 10 Jun 2024 01:35:17 +0900 Subject: [PATCH 07/11] Style: newtodo style --- src/components/newTodo/NewTodo.jsx | 1 + src/components/newTodo/newTodo.module.scss | 0 src/components/newTodo/newTodo.styles.css | 17 +++++++++++++++++ 3 files changed, 18 insertions(+) delete mode 100644 src/components/newTodo/newTodo.module.scss create mode 100644 src/components/newTodo/newTodo.styles.css diff --git a/src/components/newTodo/NewTodo.jsx b/src/components/newTodo/NewTodo.jsx index 847ebab7..ca762e59 100644 --- a/src/components/newTodo/NewTodo.jsx +++ b/src/components/newTodo/NewTodo.jsx @@ -1,4 +1,5 @@ import React, { useCallback, useState, useEffect } from "react"; +import './newTodo.styles.css'; const NewTodo = ({ newText, setNewTodo }) => { const [texting, setTexting] = useState(''); diff --git a/src/components/newTodo/newTodo.module.scss b/src/components/newTodo/newTodo.module.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/src/components/newTodo/newTodo.styles.css b/src/components/newTodo/newTodo.styles.css new file mode 100644 index 00000000..07a5b4e1 --- /dev/null +++ b/src/components/newTodo/newTodo.styles.css @@ -0,0 +1,17 @@ +.newtodo { + width: 100vw; + text-align: center; + height: 50px; +} + +.newtodo input { + padding: 10px 20px; + font-size: 15px; + border: 1.7px solid rgb(167, 44, 54); + border-radius: 10px; +} + +.newtodo button { + margin-left: 10px; + padding: 5px 10px; +} \ No newline at end of file From e71f09ad671573f0f010280d7072dc6c8a7455ba Mon Sep 17 00:00:00 2001 From: anheejeong Date: Mon, 10 Jun 2024 01:55:42 +0900 Subject: [PATCH 08/11] Refactor: Refactoring newtodo field --- src/components/newTodo/ButtonSubmit.jsx | 8 ++++++ src/components/newTodo/ChangeTexting.jsx | 5 ++++ src/components/newTodo/EnterSubmit.jsx | 8 ++++++ src/components/newTodo/NewTodo.jsx | 34 +++++------------------- src/components/newTodo/Texting.jsx | 14 ++++++++++ 5 files changed, 42 insertions(+), 27 deletions(-) create mode 100644 src/components/newTodo/ButtonSubmit.jsx create mode 100644 src/components/newTodo/ChangeTexting.jsx create mode 100644 src/components/newTodo/EnterSubmit.jsx create mode 100644 src/components/newTodo/Texting.jsx diff --git a/src/components/newTodo/ButtonSubmit.jsx b/src/components/newTodo/ButtonSubmit.jsx new file mode 100644 index 00000000..a90adbbc --- /dev/null +++ b/src/components/newTodo/ButtonSubmit.jsx @@ -0,0 +1,8 @@ +import { useCallback } from 'react'; + +export const onButtonSubmitHandler = (texting, setNewTodo, setTexting) => useCallback(() => { + if (texting) { + setNewTodo(texting); + setTexting(''); + } +}, [texting, setNewTodo]); \ No newline at end of file diff --git a/src/components/newTodo/ChangeTexting.jsx b/src/components/newTodo/ChangeTexting.jsx new file mode 100644 index 00000000..7e2199c1 --- /dev/null +++ b/src/components/newTodo/ChangeTexting.jsx @@ -0,0 +1,5 @@ +import { useCallback } from 'react'; + +export const onChangeText = (setTexting) => useCallback((e) => { + setTexting(e.target.value); +}, []); \ No newline at end of file diff --git a/src/components/newTodo/EnterSubmit.jsx b/src/components/newTodo/EnterSubmit.jsx new file mode 100644 index 00000000..736f35c2 --- /dev/null +++ b/src/components/newTodo/EnterSubmit.jsx @@ -0,0 +1,8 @@ +import { useCallback } from 'react'; + +export const onEnterSubmitHandler = (texting, setNewTodo, setTexting) => useCallback((e) => { + if (e.key === 'Enter' && texting) { + setNewTodo(texting); + setTexting(''); + } +}, [texting, setNewTodo]); \ No newline at end of file diff --git a/src/components/newTodo/NewTodo.jsx b/src/components/newTodo/NewTodo.jsx index ca762e59..9adcc3e0 100644 --- a/src/components/newTodo/NewTodo.jsx +++ b/src/components/newTodo/NewTodo.jsx @@ -1,34 +1,14 @@ -import React, { useCallback, useState, useEffect } from "react"; +import React from 'react'; import './newTodo.styles.css'; +import { Texting } from './Texting'; + +const NewTodo = ({ setNewTodo }) => { + const { texting, onChangeText, onEnterSubmitHandler, onButtonSubmitHandler } = Texting(setNewTodo); -const NewTodo = ({ newText, setNewTodo }) => { - const [texting, setTexting] = useState(''); - const onChangeText = useCallback((e) => { - setTexting(e.target.value) - }, [texting]) - const onEnterSubmitHandler = useCallback((e) => { - if (e.key === 'Enter' && texting) { - setNewTodo(texting); - } - }, [texting, newText]) - const onButtonSubmitHandler = useCallback(() => { - setNewTodo(texting); - }, [texting, newText]) - useEffect(() => { - setTexting(''); - }, [newText]) return (
- - {texting ? - - : <>} + + {texting && }
); } diff --git a/src/components/newTodo/Texting.jsx b/src/components/newTodo/Texting.jsx new file mode 100644 index 00000000..b923c4a1 --- /dev/null +++ b/src/components/newTodo/Texting.jsx @@ -0,0 +1,14 @@ +import { useState } from 'react'; +import { onChangeText } from './ChangeTexting'; +import { onEnterSubmitHandler } from './EnterSubmit'; +import { onButtonSubmitHandler } from './ButtonSubmit'; + +export const Texting = (setNewTodo) => { + const [texting, setTexting] = useState(''); + + const changeText = onChangeText(setTexting); + const enterSubmitHandler = onEnterSubmitHandler(texting, setNewTodo, setTexting); + const buttonSubmitHandler = onButtonSubmitHandler(texting, setNewTodo, setTexting); + + return { texting, onChangeText: changeText, onEnterSubmitHandler: enterSubmitHandler, onButtonSubmitHandler: buttonSubmitHandler }; +}; \ No newline at end of file From 1f07009cff4a5b65e5217ef8d561847f7bb8b3b6 Mon Sep 17 00:00:00 2001 From: anheejeong Date: Mon, 10 Jun 2024 02:01:35 +0900 Subject: [PATCH 09/11] Refactor: Refactoring todolist field --- src/components/todoList/DeleteButton.js | 3 +++ src/components/todoList/TodoList.jsx | 18 ++++++++---------- src/components/todoList/ToggleDone.js | 3 +++ 3 files changed, 14 insertions(+), 10 deletions(-) create mode 100644 src/components/todoList/DeleteButton.js create mode 100644 src/components/todoList/ToggleDone.js diff --git a/src/components/todoList/DeleteButton.js b/src/components/todoList/DeleteButton.js new file mode 100644 index 00000000..33b4de4d --- /dev/null +++ b/src/components/todoList/DeleteButton.js @@ -0,0 +1,3 @@ +export const onDeleteButtonHandler = (todoList, setTodoList, idx) => { + setTodoList(todoList.filter((_, index) => index !== idx)); +}; \ No newline at end of file diff --git a/src/components/todoList/TodoList.jsx b/src/components/todoList/TodoList.jsx index af927990..8934b850 100644 --- a/src/components/todoList/TodoList.jsx +++ b/src/components/todoList/TodoList.jsx @@ -1,28 +1,26 @@ import React, { useState, useEffect } from "react"; import './todoList.styles.css'; +import { toggleDone } from "./ToggleDone"; +import { onDeleteButtonHandler } from "./DeleteButton"; const TodoList = ({ todoList, setTodoList }) => { const [doneStatus, setDoneStatus] = useState(Array(todoList.length).fill(false)); + useEffect(() => { setDoneStatus(Array(todoList.length).fill(false)); }, [todoList]); - const toggleDone = (idx) => { - setDoneStatus(doneStatus.map((status, index) => idx === index ? !status : status)); - }; - const onDeleteButtonHandler = (idx) => { - setTodoList(todoList.filter((_, index) => index !== idx)); - } + return (
{todoList ? todoList.map((todo, idx) => ( -
+
{todo} - - + +
)) : <>}
- ) + ); } export default TodoList; \ No newline at end of file diff --git a/src/components/todoList/ToggleDone.js b/src/components/todoList/ToggleDone.js new file mode 100644 index 00000000..08a6c84f --- /dev/null +++ b/src/components/todoList/ToggleDone.js @@ -0,0 +1,3 @@ +export const toggleDone = (doneStatus, setDoneStatus, idx) => { + setDoneStatus(doneStatus.map((status, index) => idx === index ? !status : status)); +}; \ No newline at end of file From 275cdcbc13c5b72a25c0dd649756198807056211 Mon Sep 17 00:00:00 2001 From: anheejeong Date: Mon, 10 Jun 2024 02:02:25 +0900 Subject: [PATCH 10/11] Fix: fix newtodo file type --- src/components/newTodo/{ButtonSubmit.jsx => ButtonSubmit.js} | 0 src/components/newTodo/{ChangeTexting.jsx => ChangeTexting.js} | 0 src/components/newTodo/{EnterSubmit.jsx => EnterSubmit.js} | 0 src/components/newTodo/{Texting.jsx => Texting.js} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/components/newTodo/{ButtonSubmit.jsx => ButtonSubmit.js} (100%) rename src/components/newTodo/{ChangeTexting.jsx => ChangeTexting.js} (100%) rename src/components/newTodo/{EnterSubmit.jsx => EnterSubmit.js} (100%) rename src/components/newTodo/{Texting.jsx => Texting.js} (100%) diff --git a/src/components/newTodo/ButtonSubmit.jsx b/src/components/newTodo/ButtonSubmit.js similarity index 100% rename from src/components/newTodo/ButtonSubmit.jsx rename to src/components/newTodo/ButtonSubmit.js diff --git a/src/components/newTodo/ChangeTexting.jsx b/src/components/newTodo/ChangeTexting.js similarity index 100% rename from src/components/newTodo/ChangeTexting.jsx rename to src/components/newTodo/ChangeTexting.js diff --git a/src/components/newTodo/EnterSubmit.jsx b/src/components/newTodo/EnterSubmit.js similarity index 100% rename from src/components/newTodo/EnterSubmit.jsx rename to src/components/newTodo/EnterSubmit.js diff --git a/src/components/newTodo/Texting.jsx b/src/components/newTodo/Texting.js similarity index 100% rename from src/components/newTodo/Texting.jsx rename to src/components/newTodo/Texting.js From f7580f1632311a1b9854773137014f6814f7a1a8 Mon Sep 17 00:00:00 2001 From: anheejeong Date: Mon, 10 Jun 2024 02:07:10 +0900 Subject: [PATCH 11/11] Refacor: refactoring main file --- src/main.jsx | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/main.jsx b/src/main.jsx index 15632bd8..f23e43d8 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -6,22 +6,14 @@ const Main = () => { const [newTodo, setNewTodo] = useState(''); const [todoList, setTodoList] = useState([]); useEffect(() => { - console.log(newTodo); newTodo ? setTodoList([...todoList, newTodo]) : ''; setNewTodo(''); }, [newTodo]) - return (

todos

- - + +
); }