Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
46f769d
docs: 할 일 목록 애플리케이션 요구 사항 및 가이드라인 추가
hys990730 Jun 8, 2024
60ea321
docs: 구현할 기능 목록 정리
hys990730 Jun 8, 2024
9a89b92
feat: 초기 HTML 구조 설정
hys990730 Jun 8, 2024
59d95ec
feat: App.js에 Main 컴포넌트 통합 및 루트 div에 렌더링
hys990730 Jun 8, 2024
3b5b97c
feat: 기본 할 일 목록 UI 구조 추가
hys990730 Jun 8, 2024
33257de
feat: 입력 폼을 별도 컴포넌트로 분리
hys990730 Jun 8, 2024
6aad5f9
refactor: main.jsx 파일명을 Bain.jsx로 변경
hys990730 Jun 8, 2024
8117bcc
refactor: Bain.jsx 파일명을 Main.jsx로 변경
hys990730 Jun 8, 2024
93736e2
refactor: 컴포넌트 모듈화
hys990730 Jun 8, 2024
6308da0
refactor: 유틸리티 함수 모듈화
hys990730 Jun 8, 2024
4a9202c
refactor: 모든 함수를 모듈화하고 주석 추가
hys990730 Jun 8, 2024
a5e713f
refactor: TodoForm 컴포넌트 함수 모듈화
hys990730 Jun 8, 2024
2c4c44c
docs: 기본 기능 요구 사항 재정의
hys990730 Jun 8, 2024
84fc3f9
feat: Main 컴포넌트 할 일 목록 표시 기능 구현
hys990730 Jun 8, 2024
2b6fa5a
refactor: Main 컴포넌트 분리 및 상태 관리 컴포넌트 생성
hys990730 Jun 8, 2024
c9d3fb8
refactor: TodoContainer 컴포넌트 분리
hys990730 Jun 8, 2024
2af35e4
docs: 선택 기능 요구 사항 재정의
hys990730 Jun 8, 2024
cf54f1f
feat: 필터링 버튼 추가
hys990730 Jun 9, 2024
63c0bf0
feat: 필터링 기능 구현
hys990730 Jun 9, 2024
16116f9
refactor: useTodos 훅 모듈화
hys990730 Jun 9, 2024
8f708a5
refactor: useTodos 훅 모듈화 #2
hys990730 Jun 9, 2024
cb8cc6f
refactor: useFilteredTodos 리팩토링
hys990730 Jun 9, 2024
92bc5b3
refactor: useTodos 함수 네이밍 간소화
hys990730 Jun 9, 2024
f8475c0
refactor: addTodo 함수 주석 추가
hys990730 Jun 9, 2024
3b98c74
refactor: deleteTodo 함수 주석 추가
hys990730 Jun 9, 2024
9bcfffe
refactor: handleSubmit 함수 리팩토링 및 주석 추가
hys990730 Jun 9, 2024
340d73d
refactor: handleInputChange 함수 리팩토링 및 주석 추가
hys990730 Jun 9, 2024
4d184d1
refactor: toggleComplete 함수 주석 추가
hys990730 Jun 9, 2024
406090a
refactor: validateTodo 함수 주석 추가
hys990730 Jun 9, 2024
5bfcb15
refactor: TodoList 컴포넌트 key 값으로 인덱스 대신 고유 식별자 사용
hys990730 Jun 9, 2024
1c8a611
refactor: TodoItem 컴포넌트 index 대신 todo.id 사용
hys990730 Jun 9, 2024
55791b4
refactor: 폴더 구조 개선 및 파일 이동
hys990730 Jun 9, 2024
3ca79d0
refactor: components 폴더 생성
hys990730 Jun 9, 2024
5e88bac
Merge branch 'sugoring' into fix/addTodo-function-error
sugoring Jun 9, 2024
fadb5db
Merge pull request #1 from sugoring/fix/addTodo-function-error
sugoring Jun 9, 2024
d840aa3
refactor: 컴포넌트 구조 개선
hys990730 Jun 9, 2024
8978e4e
Merge branch 'sugoring' into fix/addTodo-function-error#2
sugoring Jun 9, 2024
0c9e046
Merge pull request #2 from sugoring/fix/addTodo-function-error#2
sugoring Jun 9, 2024
f809163
fix: addTodo 함수 오류 해결
hys990730 Jun 9, 2024
8f2a017
docs: README 업데이트 및 할 일 필터링 기능 완료
hys990730 Jun 9, 2024
57841e2
feat: 필터링 관련 버튼 TodoFilter 컴포넌트 추가
hys990730 Jun 9, 2024
9ec3ffe
feat: 총 할 일 개수를 표시하는 영역 추가
hys990730 Jun 9, 2024
430cb88
feat: 완료된 할 일과 진행 중인 할 일의 개수를 각각 표시
hys990730 Jun 9, 2024
20fb0e8
docs: README 업데이트
hys990730 Jun 9, 2024
896a9ce
reafactor: TodoStats 컴포넌트 분리
hys990730 Jun 9, 2024
5e4fb4c
refactor: TodoContainer 내부 로직을 TodoApp 컴포넌트로 이동
hys990730 Jun 9, 2024
07b5ffb
refactor: FilterButton 컴포넌트를 분리
hys990730 Jun 9, 2024
1e103e1
refactor: 핸들러 모듈화 및 index.js 사용하여 import 간소화
hys990730 Jun 9, 2024
bba2f37
docs: 각 핸들러 함수에 기능 설명 주석 추가
hys990730 Jun 9, 2024
2651c06
docs: 각 유틸리티 함수에 기능 설명 주석 추가
hys990730 Jun 9, 2024
626c88c
docs: 각 훅에 기능 설명 주석 추가
hys990730 Jun 9, 2024
89670d9
fix: TodoStats 컴포넌트가 필터에 따른 올바른 할 일 개수를 계산하도록 수정
hys990730 Jun 9, 2024
9a232cd
refactor : main 컴포넌트 내용을 하위 컴포넌트로 수정
hys990730 Jun 9, 2024
a2ea7e8
refactor: useTodos 훅을 분리
hys990730 Jun 9, 2024
745a7c4
feat: handleSubmit 함수 분리
hys990730 Jun 9, 2024
27accf9
refactor: useTodos 훅 분리
hys990730 Jun 9, 2024
a7fc501
refactor: useTodosState 훅을 상태별로 분리
hys990730 Jun 9, 2024
1bbdf2c
refactor: useTodoStateManager 훅을 분리
hys990730 Jun 9, 2024
6e42d04
refactor: useFilteredTodos 훅을 한 가지 일만 하도록 분리
hys990730 Jun 9, 2024
a51779a
efactor: TodoFilter 컴포넌트를 필터 버튼별로 분리
hys990730 Jun 9, 2024
60eecc5
refactor: TodoForm 컴포넌트를 입력 필드와 폼 제출 처리로 분리
hys990730 Jun 9, 2024
23e3a66
refactor: TodoItem 컴포넌트를 역할별로 분리
hys990730 Jun 9, 2024
08b68ea
refactor: TodoStats 컴포넌트를 역할별로 분리
hys990730 Jun 9, 2024
1ba92eb
chore: 파일명 수정 준비를 위해 모든 파일 삭제
hys990730 Jun 9, 2024
634d387
chore: 파일명을 카멜케이스로 수정
hys990730 Jun 9, 2024
becd89f
docs: README update
hys990730 Jun 9, 2024
58a15ac
feat: 로컬 스토리지에서 할 일 목록 불러오는 기능 추가
hys990730 Jun 9, 2024
79feb59
feat: 할 일 목록 변경 시 로컬 스토리지에 저장 기능 추가
hys990730 Jun 9, 2024
02dfe44
feat: 필터 상태 변경 시 로컬 스토리지에 저장 기능 추가
hys990730 Jun 9, 2024
7685280
refactor: useTodos 훅을 역할별로 분리
hys990730 Jun 9, 2024
b5eb9e2
refactor: filterTodos 함수를 역할별로 분리
hys990730 Jun 9, 2024
6fe70e7
chore: 파일명을 카멜케이스로 수정하고 폴더 구조를 명확하게 정리
hys990730 Jun 9, 2024
14b8128
chore: 함수에 기능 주석 추가
hys990730 Jun 9, 2024
fb67722
chore: utils 함수에 기능 주석 추가
hys990730 Jun 9, 2024
b9359e2
chore: hooks 폴더 구조 변경
hys990730 Jun 9, 2024
3604fc1
docs: renamed Handlers
hys990730 Jun 9, 2024
8fae7f5
refactor: 이전 버전으로 import 오류 해결
hys990730 Jun 9, 2024
6643b50
chore: components 폴더의 파일 기능 설명에 대한 주석 작성
hys990730 Jun 9, 2024
7b0d0c9
design: body와 container 스타일 추가
hys990730 Jun 10, 2024
44c55ff
design: todoContainer의 container 스타일 추가
hys990730 Jun 10, 2024
e424b9a
design: todoApp의 스타일 추가
hys990730 Jun 10, 2024
6ec5a41
design: todoForm의 placeholder 스타일 추가 및 hover 효과
hys990730 Jun 10, 2024
9685a4b
design: todoList 버튼 스타일링
hys990730 Jun 10, 2024
187ea5e
design: 전체 스타일링 공통 적용
hys990730 Jun 10, 2024
5249193
docs: readme 선택 기능 구현 문서 완료 표시
hys990730 Jun 10, 2024
a4bbd1c
Merge pull request #4 from sugoring/develop
sugoring Jun 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 98 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,98 @@
# react-todo-list-precourse
# [강원대 FE_허윤수]

이 애플리케이션은 사용자가 할 일을 추가, 삭제, 완료 상태로 전환할 수 있는 간단한 할 일 목록(Todo List) 관리 웹 애플리케이션입니다. 동작은 TodoMVC의 기능 동작을 참고하였습니다.

---

## 과제 진행 소감

"함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만들어라"라는 요구사항에 맞추기 위해 최대한 노력했습니다. TodoApp(src\components\TodoApp\TodoApp.jsx) 컴포넌트를 더 작은 단위로 분리하여 상태 관리를 보다 효율적으로 하려고 시도했습니다. 이를 위해 상태를 저장하는 부분을 여러 컨테이너로 분리했으나, 이 과정에서 각 컨테이너 간에 상태가 공유되지 않는 문제점이 발생했습니다. 😓

이 문제를 해결하기 위해 CONTEXT API를 사용할 수 있다는 것을 알게 되었습니다. 하지만 아직 CONTEXT API에 대한 공부가 충분히 이루어지지 않아, 이를 적용하는 데 어려움을 겪었습니다. 앞으로 고급 개념을 학습하여 더 나은 코드를 작성할 수 있도록 노력할 것입니다. 📚

---

## 저장소

저장소 URL: [https://github.com/sugoring/react-todo-list-precourse.git](https://github.com/sugoring/react-todo-list-precourse.git)

## 브랜치

- **메인 브랜치(과제 제출)**: `sugoring`
- **오류 수정 브랜치**: `fix/addTodo-function-error`
- **개발 브랜치**: `develop`

### 1. 초기 개발

초기에 메인 브랜치인 `sugoring`에서 개발을 시작했습니다.

### 2. 오류 수정

개발 도중 `addTodo` 함수와 관련된 오류가 발생하여, 오류를 해결하기 위해 `fix/addTodo-function-error` 브랜치에서 수정 작업을 진행하였습니다.

### 3. 개발 브랜치 전환

오류 수정 후, 메인 브랜치(`sugoring`)로 돌아와서 오류가 해결된 상태를 반영한 뒤, 이후 개발 작업은 `develop` 브랜치에서 계속 진행하였습니다.

### 4. 과제 제출

개발 작업을 완료한 후, `develop` 브랜치에서 작업 내용을 `sugoring` 브랜치로 PR(Pull Request)하여 병합하였고, 과제를 제출하였습니다.

---

## 기본 기능

### [할 일 추가 기능 구현]

- [x] **할 일 입력 폼 생성**
- 사용자는 Enter 키 또는 추가 버튼을 통해 새로운 할 일을 입력할 수 있습니다.
- [x] **할 일 데이터 유효성 검사 (빈 문자열)**
- 입력된 할 일이 빈 문자열인 경우, 경고 메시지를 표시하고 추가하지 않습니다.
- [x] **할 일 목록 업데이트**
- 유효한 할 일은 목록에 추가되고 화면에 반영됩니다.

### [할 일 삭제 기능 구현]

- [x] **삭제 요청 인터페이스 생성**
- 각 할 일 항목 옆에 삭제 버튼이 있습니다.
- [x] **삭제 요청 처리**
- 사용자가 삭제 버튼을 클릭하면 해당 할 일이 목록에서 제거됩니다.

### [할 일 목록 보기 기능 구현]

- [x] **목록 불러오기**
- 할 일 목록을 불러옵니다.
- [x] **목록 표시**
- 불러온 할 일 목록을 화면에 표시합니다.

### [할 일 완료 상태 전환 기능 구현]

- [x] **완료 상태 전환 인터페이스 생성**
- 각 할 일 항목 옆에 완료/미완료 버튼이 있습니다.
- [x] **상태 전환 요청 처리**
- 사용자가 완료/미완료 버튼을 클릭하면 해당 할 일의 완료 상태가 토글됩니다.

---

## 선택 요구 사항

### [할 일 필터링]

- [x] **필터링 버튼 추가**
- 할 일 목록 상단에 '전체', '진행 중', '완료' 버튼을 추가합니다.
- [x] **필터링 기능 구현**
- 사용자는 이 버튼들을 클릭하여 필터링할 수 있습니다.
- [x] **실시간 필터링 반영**
- 필터링된 목록이 화면에 반영됩니다.

### [해야 할 일의 총 개수 확인]

- [x] **총 개수 표시 영역 추가**
- 할 일 목록 하단에 남아있는 할 일의 총 개수를 표시합니다.
- [x] **개별 개수 표시 옵션**
- 완료된 할 일과 미완료된 할 일의 개수를 각각 표시합니다.

### [데이터 지속성]

- [x] **데이터 저장 기능 구현**
- 새로고침을 하여도 이전에 작성한 데이터는 유지됩니다.
8 changes: 4 additions & 4 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<!doctype html>
<html lang="en">
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title></title>
<title>[강원대 FE_허윤수]</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
<script type="module" src="/src/App.js"></script>
</body>
</html>
10 changes: 10 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from "react";
import ReactDOM from "react-dom/client";
import Main from "./Main.jsx";

const App = () => {
return React.createElement(Main);
};

const root = ReactDOM.createRoot(document.getElementById("app"));
root.render(React.createElement(App));
11 changes: 11 additions & 0 deletions src/Main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f5f5f5;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}

13 changes: 13 additions & 0 deletions src/Main.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";
import TodoContainer from "./components/todoApp/todoContainer";
import "./Main.css";

const Main = () => {
return (
<div className="container">
<TodoContainer />
</div>
);
};

export default Main;
8 changes: 8 additions & 0 deletions src/components/todoApp/stats/activeTodos.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// 진행 중인 할 일 개수를 표시하는 컴포넌트
import React from "react";

const ActiveTodos = ({ active }) => {
return <span>진행 중인 할 일: {active}</span>;
};

export default ActiveTodos;
8 changes: 8 additions & 0 deletions src/components/todoApp/stats/completedTodos.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// 완료된 할 일 개수를 표시하는 컴포넌트
import React from "react";

const CompletedTodos = ({ completed }) => {
return <span>완료된 할 일: {completed}</span>;
};

export default CompletedTodos;
8 changes: 8 additions & 0 deletions src/components/todoApp/stats/totalTodos.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// 전체 할 일 개수를 표시하는 컴포넌트
import React from "react";

const TotalTodos = ({ total }) => {
return <span>총 할 일 개수: {total}</span>;
};

export default TotalTodos;
103 changes: 103 additions & 0 deletions src/components/todoApp/todoApp.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
.todo-app {
background-color: #ffffff;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
max-width: 800px;
width: 100%;
padding: 20px;
display: flex;
flex-direction: column;
gap: 20px;
}

.todo-form,
.todo-list,
.todo-filter,
.todo-stats {
background-color: #f9f9f9;
border-radius: 8px;
padding: 15px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.todo-form input,
.todo-form button {
padding: 10px;
font-size: 16px;
border-radius: 5px;
border: 1px solid #ddd;
}

.todo-form button {
background-color: #b83f45;
color: #fff;
border: none;
cursor: pointer;
transition: background-color 0.3s ease;
}

.todo-form button:hover {
background-color: #a6373e;
}

.todo-list .todo-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px;
border-bottom: 1px solid #eee;
}

.todo-list .todo-item:last-child {
border-bottom: none;
}

.todo-filter {
display: flex;
justify-content: center;
gap: 10px;
}

.todo-filter button {
padding: 10px 20px;
border: 2px solid #b83f45;
border-radius: 5px;
background-color: transparent;
color: #b83f45;
cursor: pointer;
transition: all 0.3s ease;
font-size: 16px;
}

.todo-filter button:hover {
background-color: #b83f45;
color: #fff;
}

.todo-filter button.active {
background-color: #b83f45;
color: #fff;
font-weight: bold;
}

.todo-stats {
display: flex;
justify-content: space-around;
}

.todo-stats .stat {
text-align: center;
}

.todo-stats .stat h3 {
margin: 0;
font-size: 24px;
color: #b83f45;
}

.todo-stats .stat p {
margin: 5px 0 0;
font-size: 16px;
color: #666;
}

41 changes: 41 additions & 0 deletions src/components/todoApp/todoApp.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// src/components/todoApp/todoApp.jsx
import React from "react";
import TodoForm from "../todoForm/todoForm";
import TodoList from "../todoList/todoList";
import TodoFilter from "../todoFilter/todoFilter";
import TodoStats from "./todoStats";
import useTodos from "../../hooks/todos/useTodos";
import "./todoApp.css";

// 할 일 앱 컴포넌트: 할 일 입력 폼, 할 일 필터, 할 일 목록, 할 일 통계를 표시하는 앱
const TodoApp = () => {
const {
todos,
allTodos,
handleAddTodo,
handleToggleComplete,
handleDeleteTodo,
handleSetFilter,
filter,
FILTERS,
} = useTodos();

return (
<div className="todo-app">
<TodoForm addTodo={handleAddTodo} />
<TodoList
todos={todos}
toggleComplete={handleToggleComplete}
deleteTodo={handleDeleteTodo}
/>
<TodoFilter
filter={filter}
FILTERS={FILTERS}
handleSetFilter={handleSetFilter}
/>
<TodoStats todos={todos} allTodos={allTodos} filter={filter} />
</div>
);
};

export default TodoApp;
22 changes: 22 additions & 0 deletions src/components/todoApp/todoContainer.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.todo-container {
text-align: center;
margin: 20px auto;
}

.todo-container h1 {
font-size: 80px;
color: #b83f45;
margin-bottom: 10px;
}

.todo-container p {
font-size: 16px;
color: #666;
margin-bottom: 20px;
}

.footer {
font-size: 14px;
color: #999;
margin-top: 20px;
}
16 changes: 16 additions & 0 deletions src/components/todoApp/todoContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from "react";
import TodoApp from "./todoApp";
import "./todoContainer.css";

const TodoContainer = () => {
return (
<div className="todo-container">
<h1>todos</h1>
<p>Enter 키나 추가 버튼을 사용하여 할 일을 목록에 추가하세요.</p>
<TodoApp />
<p className="footer">Created by [강원대 FE_허윤수]</p>
</div>
);
};

export default TodoContainer;
17 changes: 17 additions & 0 deletions src/components/todoApp/todoFilterContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from "react";
import TodoFilter from "../todoFilter/todoFilter";

// 할 일 필터 컨테이너 컴포넌트: 할 일 필터를 표시하고 설정하는 기능을 제공하는 컴포넌트
const TodoFilterContainer = ({ useTodos }) => {
const { filter, FILTERS, handleSetFilter } = useTodos();

return (
<TodoFilter
filter={filter}
FILTERS={FILTERS}
handleSetFilter={handleSetFilter}
/>
);
};

export default TodoFilterContainer;
11 changes: 11 additions & 0 deletions src/components/todoApp/todoFormContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from "react";
import TodoForm from "../todoForm/todoForm";

// 할 일 입력 폼 컨테이너 컴포넌트: 할 일 입력 폼을 표시하고 할 일 추가 기능을 제공하는 컴포넌트
const TodoFormContainer = ({ useTodos }) => {
const { handleAddTodo } = useTodos();

return <TodoForm addTodo={handleAddTodo} />;
};

export default TodoFormContainer;
Loading