diff --git a/README.md b/README.md index 3c0710d2..89e65911 100644 --- a/README.md +++ b/README.md @@ -1 +1,15 @@ -# react-todo-list-precourse \ No newline at end of file +# react-todo-list-precourse +## ๐Ÿช ํ”„๋กœ์ ํŠธ ๊ฐœ์š” +2024 ์นด์นด์˜ค ํ…Œํฌ ์บ ํผ์Šค 2๊ธฐ FE 2์ฐจ ๋ฏธ๋‹ˆ๊ณผ์ œ - ํ•  ์ผ ๋ชฉ๋ก + +## ๐Ÿšง ๊ธฐ๋Šฅ ๋ชฉ๋ก +### ํ•„์ˆ˜ ์š”๊ตฌ ์‚ฌํ•ญ +- [X] ํ•  ์ผ ์ถ”๊ฐ€ +- [X] ํ•  ์ผ ์‚ญ์ œ +- [X] ํ•  ์ผ ๋ชฉ๋ก ๋ณด๊ธฐ +- [X] ํ•  ์ผ ์™„๋ฃŒ ์ƒํƒœ ์ „ํ™˜ + +### ์„ ํƒ ์š”๊ตฌ ์‚ฌํ•ญ +- [ ] 'ํ˜„์žฌ ์ง„ํ–‰ ์ค‘ / ์™„๋ฃŒ / ๋ชจ๋‘' ์„ธ ๊ฐ€์ง€ ํ•„ํ„ฐ๋ง +- [ ] ํ•ด์•ผ ํ•  ์ผ์˜ ์ด ๊ฐœ์ˆ˜ ํ™•์ธ +- [ ] ์ƒˆ๋กœ๊ณ ์นจ์‹œ ์ž‘์„ฑ ์ค‘์ธ ๋ฐ์ดํ„ฐ ์œ ์ง€ 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.css b/src/App.css new file mode 100644 index 00000000..590109a2 --- /dev/null +++ b/src/App.css @@ -0,0 +1,41 @@ +.App { + text-align: center; + max-width: 600px; + margin: auto; +} + +form { + margin-bottom: 20px; +} + +input { + padding: 10px; + font-size: 16px; + width: 70%; + margin-right: 10px; +} + +button { + padding: 10px 15px; + font-size: 16px; + cursor: pointer; +} + +ul { + list-style: none; + padding: 0; +} + +li { + padding: 10px; + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid #ccc; +} + +li span { + cursor: pointer; + flex-grow: 1; + text-align: left; +} diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 00000000..b71947db --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,48 @@ +import React, { useState } from 'react'; +import TodoList from './TodoList'; +import TodoForm from './TodoForm'; +import TodoFilter from './TodoFilter'; +import './App.css'; + +const App = () => { + const [todos, setTodos] = useState([]); + const [filter, setFilter] = useState('all'); + + const addTodo = (text) => { + if (text === '') return; + const newTodo = { text: text, id: Date.now() }; + setTodos([...todos, newTodo]); + }; + + const deleteTodo = (todoId) => { + setTodos(todos.filter(todo => todo.id !== todoId )); + }; + + const filteredTodos = todos.filter(todo => { + if (filter === 'all') return true; + if (filter === 'completed') return todo.completed; + if (filter === 'active') return !todo.completed; + return true; + }); + + const toggleTodo = (id) => { + setTodos( + todos.map(todo => + todo.id === id ? { ...todo, completed: !todo.completed } : todo + ) + ); + }; + + return ( +
+

TODO

+ + +
+ ); +}; + +export default App; diff --git a/src/TodoFilter.jsx b/src/TodoFilter.jsx new file mode 100644 index 00000000..b67ea085 --- /dev/null +++ b/src/TodoFilter.jsx @@ -0,0 +1,14 @@ +// src/TodoFilter.js +import React from 'react'; + +const TodoFilter = ({ setFilter }) => { + return ( +
+ + + +
+ ); +}; + +export default TodoFilter; diff --git a/src/TodoForm.jsx b/src/TodoForm.jsx new file mode 100644 index 00000000..acc6eb19 --- /dev/null +++ b/src/TodoForm.jsx @@ -0,0 +1,25 @@ +import React, { useState } from 'react'; + +const TodoForm = ({ addTodo }) => { + const [text, setText] = useState(''); + + const addSubmit = (e) => { + e.preventDefault(); + addTodo(text); + setText(''); + }; + + return ( +
+ setText(e.target.value)} + placeholder="ํ•  ์ผ์„ ์ž…๋ ฅํ•˜์„ธ์š”." + /> + +
+ ); +}; + +export default TodoForm; diff --git a/src/TodoList.jsx b/src/TodoList.jsx new file mode 100644 index 00000000..4ff1c165 --- /dev/null +++ b/src/TodoList.jsx @@ -0,0 +1,18 @@ +import React from 'react'; + +const TodoList = ({ todos, deleteTodo, toggleTodo }) => { + return ( + + ); +}; + +export default TodoList; diff --git a/src/main.jsx b/src/main.jsx new file mode 100644 index 00000000..8463ecaa --- /dev/null +++ b/src/main.jsx @@ -0,0 +1,11 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; +import './App.css'; + +ReactDOM.render( + + + , + document.getElementById('app') +);