From 8742eec16d4963c59c9e971074d892724627dafd Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:05:59 +0900 Subject: [PATCH 01/16] =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=20=EB=AA=A9=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c0710d2..0e424896 100644 --- a/README.md +++ b/README.md @@ -1 +1,21 @@ -# react-todo-list-precourse \ No newline at end of file +# react-todo-list-precourse + +TodoList: 할 일 목록 렌더링 +Header: 할 일 추가 & 입력창 초기화 +Footer: 필터 + + +App.jsx 파일 내 기능들: + +초기 할 일 List 가져오는 함수 +초기 할 일 List 설정 + +Filter 설정 +할 일 Filtered 목록 가져오는 함수 +(할 일 Filtered 목록 가져오는 함수) 호출 + +할 일 추가 함수 +할 일 완료 업데이트 함수 +할 일 삭제 함수 + +할 일 목록이 변경될 때마다 로컬에 저장 \ No newline at end of file From 39233c4d0de6e8fd710ea8276789d9c1ca084ca9 Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:20:19 +0900 Subject: [PATCH 02/16] =?UTF-8?q?TodoList.jsx:=20=ED=95=A0=20=EC=9D=BC=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EB=A0=8C=EB=8D=94=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TodoList.jsx | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/components/TodoList.jsx diff --git a/src/components/TodoList.jsx b/src/components/TodoList.jsx new file mode 100644 index 00000000..08b2e194 --- /dev/null +++ b/src/components/TodoList.jsx @@ -0,0 +1,27 @@ +import React from 'react'; + +// 할 일 목록 렌더링 +const TodoList = ({ todos, toTodo, deleteTodo }) => ( + +); + +// 할 일 항목 컴포넌트 +const TodoItem = ({ todo, index, toTodo, deleteTodo }) => ( +
  • + toTodo(index)} /> + toTodo(index)}>{todo.text} + +
  • +); + +export default TodoList; From 4c48b85d1d2ec1b518dfa23941afeb904c3309a9 Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:21:22 +0900 Subject: [PATCH 03/16] =?UTF-8?q?Header:=20=ED=95=A0=20=EC=9D=BC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20&=20=EC=9E=85=EB=A0=A5=EC=B0=BD=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=ED=99=94=20=ED=95=A8=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Header.jsx | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/components/Header.jsx diff --git a/src/components/Header.jsx b/src/components/Header.jsx new file mode 100644 index 00000000..295cf154 --- /dev/null +++ b/src/components/Header.jsx @@ -0,0 +1,36 @@ +import React, { useState } from 'react'; + +const Header = ({ addTodo }) => { + const [text, setText] = useState(''); + + // 제출 함수 (할 일 추가 및 입력창 초기화) + const submit = (e) => { + e.preventDefault(); + if (text.trim().length > 0) { + addClear(text, setText); + } + }; + + // 할 일 추가 & 입력창 초기화 함수 + const addClear = (text, setText) => { + addTodo(text); + setText(''); + }; + + return ( +
    +

    todos

    +
    + setText(e.target.value)} + /> + +
    +
    + ); +}; + +export default Header; From 086146211f4f08c624cc16c7ca7309e11733a9c1 Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:21:59 +0900 Subject: [PATCH 04/16] =?UTF-8?q?Footer:=20=ED=95=84=ED=84=B0=20=ED=95=A8?= =?UTF-8?q?=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Footer.jsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/components/Footer.jsx diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx new file mode 100644 index 00000000..a65e55f1 --- /dev/null +++ b/src/components/Footer.jsx @@ -0,0 +1,13 @@ +import React from 'react'; + +// 필터 함수 +const Footer = ({ setFilter, filter, totalCount }) => ( +
    + {totalCount} items left + + + +
    +); + +export default Footer; From 8b39b4977ed49a9f7f0fd1a43d1a1edefd61be53 Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:22:56 +0900 Subject: [PATCH 05/16] =?UTF-8?q?=EC=B4=88=EA=B8=B0=20=ED=95=A0=20?= =?UTF-8?q?=EC=9D=BC=20List=20=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8A=94=20?= =?UTF-8?q?=ED=95=A8=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/App.jsx | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/components/App.jsx diff --git a/src/components/App.jsx b/src/components/App.jsx new file mode 100644 index 00000000..024387d1 --- /dev/null +++ b/src/components/App.jsx @@ -0,0 +1,9 @@ +import React, { useState, useEffect } from 'react'; +import Header from './Header'; +import TodoList from './TodoList'; +import Footer from './Footer'; + +// 초기 할 일 List 가져오는 함수 +const InitTodo = () => { + return JSON.parse(localStorage.getItem('todos')) || []; +}; \ No newline at end of file From bd1a854e33c9e2efe75cc63da29a17d8291e927e Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:23:17 +0900 Subject: [PATCH 06/16] =?UTF-8?q?=ED=95=A0=20=EC=9D=BC=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=ED=95=A8?= =?UTF-8?q?=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/App.jsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/App.jsx b/src/components/App.jsx index 024387d1..8a1f300d 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -6,4 +6,11 @@ import Footer from './Footer'; // 초기 할 일 List 가져오는 함수 const InitTodo = () => { return JSON.parse(localStorage.getItem('todos')) || []; +}; + +// 할 일 완료 업데이트 함수 +const updateTodo = (todos, index) => { + return todos.map((todo, i) => + i === index ? { ...todo, completed: !todo.completed } : todo + ); }; \ No newline at end of file From 79cd437579d05b376316e659a664811cdbfd5f88 Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:23:39 +0900 Subject: [PATCH 07/16] =?UTF-8?q?=ED=95=A0=20=EC=9D=BC=20Filtered=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8A=94=20?= =?UTF-8?q?=ED=95=A8=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/App.jsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/App.jsx b/src/components/App.jsx index 8a1f300d..40374b35 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -13,4 +13,11 @@ const updateTodo = (todos, index) => { return todos.map((todo, i) => i === index ? { ...todo, completed: !todo.completed } : todo ); +}; + +// 할 일 Filtered 목록 가져오는 함수 +const filteredTodo = (todos, filter) => { + return todos.filter(todo => + filter === 'all' ? true : filter === 'completed' ? todo.completed : !todo.completed + ); }; \ No newline at end of file From ccd90fea573d2073121cb70eda4dd1db9f417d6c Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:24:57 +0900 Subject: [PATCH 08/16] =?UTF-8?q?=EC=B4=88=EA=B8=B0=20=ED=95=A0=20?= =?UTF-8?q?=EC=9D=BC=20List,=20=ED=95=84=ED=84=B0=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/App.jsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/App.jsx b/src/components/App.jsx index 40374b35..079c8417 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -20,4 +20,11 @@ const filteredTodo = (todos, filter) => { return todos.filter(todo => filter === 'all' ? true : filter === 'completed' ? todo.completed : !todo.completed ); -}; \ No newline at end of file +}; + +const App = () => { + const [todos, setTodos] = useState(InitTodo()); // 초기 할 일 List 설정 + const [filter, setFilter] = useState('all'); // 필터 설정 +}; + +export default App; From 241613eee40e276220b0d374f51ae4b4155b166c Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:25:54 +0900 Subject: [PATCH 09/16] =?UTF-8?q?=ED=95=A0=20=EC=9D=BC=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=EC=9D=B4=20=EB=B3=80=EA=B2=BD=EB=90=A0=20=EB=95=8C?= =?UTF-8?q?=EB=A7=88=EB=8B=A4=20=EB=A1=9C=EC=BB=AC=EC=97=90=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/App.jsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/App.jsx b/src/components/App.jsx index 079c8417..9b9f7557 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -25,6 +25,10 @@ const filteredTodo = (todos, filter) => { const App = () => { const [todos, setTodos] = useState(InitTodo()); // 초기 할 일 List 설정 const [filter, setFilter] = useState('all'); // 필터 설정 + + useEffect(() => { + localStorage.setItem('todos', JSON.stringify(todos)); // 할 일 목록이 변경될 때마다 로컬에 저장 + }, [todos]); }; export default App; From 66d1260c77f7736851f91381d5a6476cc7d9a8d4 Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:26:14 +0900 Subject: [PATCH 10/16] =?UTF-8?q?=ED=95=A0=20=EC=9D=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=ED=95=A8=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/App.jsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/App.jsx b/src/components/App.jsx index 9b9f7557..d673cf91 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -29,6 +29,12 @@ const App = () => { useEffect(() => { localStorage.setItem('todos', JSON.stringify(todos)); // 할 일 목록이 변경될 때마다 로컬에 저장 }, [todos]); + + // 할 일 추가 함수 + const addTodo = (text) => { + if (text.trim().length === 0) return; + setTodos([...todos, { text, completed: false }]); + }; }; export default App; From 9b96ba4d128fcc1d57fbdab3e2e5193f4c51deea Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:29:29 +0900 Subject: [PATCH 11/16] =?UTF-8?q?=ED=95=A0=20=EC=9D=BC=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=ED=95=A8?= =?UTF-8?q?=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/App.jsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/App.jsx b/src/components/App.jsx index d673cf91..b3388ced 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -35,6 +35,11 @@ const App = () => { if (text.trim().length === 0) return; setTodos([...todos, { text, completed: false }]); }; + + // 할 일 완료 업데이트 함수 + const toTodo = (index) => { + setTodos(updateTodo(todos, index)); + }; }; export default App; From 8eb33f28321243bcfd47c714c8ea9a600e424a43 Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:30:10 +0900 Subject: [PATCH 12/16] =?UTF-8?q?=ED=95=A0=20=EC=9D=BC=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=ED=95=A8=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/App.jsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/App.jsx b/src/components/App.jsx index b3388ced..095bbdac 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -40,6 +40,11 @@ const App = () => { const toTodo = (index) => { setTodos(updateTodo(todos, index)); }; + + // 할 일 삭제 함수 + const deleteTodo = (index) => { + setTodos(todos.filter((_, i) => i !== index)); + }; }; export default App; From 9970eb4650528004d0dc9e882fb1d79d9e3f88c9 Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:30:41 +0900 Subject: [PATCH 13/16] =?UTF-8?q?(=ED=95=A0=20=EC=9D=BC=20Filtered=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8A=94=20?= =?UTF-8?q?=ED=95=A8=EC=88=98)=20=ED=98=B8=EC=B6=9C=20=EB=B0=8F=20?= =?UTF-8?q?=EB=A6=AC=ED=84=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/App.jsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/components/App.jsx b/src/components/App.jsx index 095bbdac..be32de71 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -45,6 +45,17 @@ const App = () => { const deleteTodo = (index) => { setTodos(todos.filter((_, i) => i !== index)); }; + + // (할 일 Filtered 목록 가져오는 함수) 호출 + const filteredTodos = filteredTodo(todos, filter); + + return ( +
    +
    + +
    +
    + ); }; export default App; From 7a65f76cb44fc016f43015d4b461c08adeb79639 Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:32:31 +0900 Subject: [PATCH 14/16] =?UTF-8?q?HTML=20=ED=8C=8C=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/index.html b/index.html index b021b5c8..b0145cb0 100644 --- a/index.html +++ b/index.html @@ -1,12 +1,12 @@ - + - - - - - - -
    - - + + + + React Todo List + + +
    + + From 20a6c7afcb6e21e3431649dce116db4f31c7242a Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:33:18 +0900 Subject: [PATCH 15/16] =?UTF-8?q?CSS=20=ED=8C=8C=EC=9D=BC=20=EB=94=94?= =?UTF-8?q?=EC=9E=90=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.css | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/main.css diff --git a/src/main.css b/src/main.css new file mode 100644 index 00000000..3c037974 --- /dev/null +++ b/src/main.css @@ -0,0 +1,79 @@ +body { + background-color: black; + color: white; + font-family: 'Gothic', Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + margin: 0; +} + +#root { + width: 100%; + max-width: 600px; + margin: auto; +} + +header { + text-align: center; +} + +header h1 { + font-size: 2.5em; + font-family: 'Gothic', Arial, sans-serif; +} + +input[type="text"] { + width: calc(100% - 60px); + padding: 10px; + font-size: 16px; + margin: 5px 0; + border: none; + border-radius: 4px; + box-sizing: border-box; + font-family: 'Gothic', Arial, sans-serif; +} + +button { + padding: 10px; + font-size: 16px; + margin: 5px 0; + border: none; + border-radius: 4px; + cursor: pointer; + font-family: 'Gothic', Arial, sans-serif; +} + +.todo-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px; + margin: 10px 0; + border: 1px solid #444; + border-radius: 4px; + background-color: #222; +} + +.todo-item.completed { + text-decoration: line-through; + color: gray; +} + +.todo-item span { + flex-grow: 1; + padding-left: 10px; + font-family: 'Gothic', Arial, sans-serif; +} + +.todo-item input[type="checkbox"] { + cursor: pointer; +} + +footer { + display: flex; + justify-content: space-between; + align-items: center; + font-family: 'Gothic', Arial, sans-serif; +} From c4cd5fa8bcabbfd52dda2fc0c72a6a5fcd4c5fd2 Mon Sep 17 00:00:00 2001 From: 2021048695 Date: Mon, 10 Jun 2024 02:33:42 +0900 Subject: [PATCH 16/16] =?UTF-8?q?main.jsx=20=ED=8C=8C=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.jsx | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main.jsx diff --git a/src/main.jsx b/src/main.jsx new file mode 100644 index 00000000..81752c23 --- /dev/null +++ b/src/main.jsx @@ -0,0 +1,7 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './components/App'; +import './main.css'; + +const root = ReactDOM.createRoot(document.getElementById('root')); +root.render();