diff --git a/README2.md b/README2.md
new file mode 100644
index 0000000..5385438
--- /dev/null
+++ b/README2.md
@@ -0,0 +1,128 @@
+# 고급 투두리스트 (2단계)
+
+React의 복잡한 상태 관리와 필터 기능들을 구현하는 실습 프로젝트입니다.
+
+## AdvancedTodo.jsx 구현하기
+
+```
+AdvancedTodo.jsx 고급 투두리스트의 메인 컴포넌트입니다.
+TodoFilter.jsx 필터링 기능을 제공하는 컴포넌트입니다.
+TodoActions.jsx 일괄 작업 기능을 제공하는 컴포넌트입니다.
+```
+
+### 1. 사용자 입력값, 필터 상태, 수정 관련 state들 생성
+
+기존 기본 투두리스트에서 확장된 상태들을 추가합니다.
+현재 필터 상태를 저장할 state와 수정 모드 관리를 위한 state들을 추가합니다.
+이러한 상태들을 통해 더 복잡한 사용자 인터랙션을 처리할 수 있습니다.
+
+### 2. 새로운 할 일을 목록에 추가하는 함수 구현
+
+기존의 배열 인덱스 대신 고유한 id를 사용하여 할 일을 관리합니다.
+Date.now()를 활용하여 고유한 id를 생성하고, 새로운 할 일 객체를 생성합니다.
+스프레드 연산자로 기존 배열을 복사한 후 새로운 할 일을 추가합니다.
+
+### 3. 할 일의 완료/미완료 상태를 전환하는 함수 구현
+
+map 메서드를 사용하여 특정 id의 할 일 상태를 변경합니다.
+조건부로 해당 id와 일치하는 할 일의 state 속성을 토글합니다.
+불변성을 유지하면서 새로운 배열을 반환합니다.
+
+### 4. 특정 할 일을 목록에서 제거하는 함수 구현
+
+filter 메서드를 사용하여 특정 id의 할 일을 제외한 새로운 배열을 생성합니다.
+인덱스 기반이 아닌 id 기반으로 삭제하여 더 안전한 데이터 관리가 가능합니다.
+
+### 5. 할 일 텍스트 수정을 시작하는 함수 구현
+
+수정 시작 함수는 수정 모드를 시작하며, 수정 중인 할 일의 ID와 텍스트 상태를 설정합니다.
+사용자가 더블클릭하거나 수정 버튼을 클릭했을 때 호출됩니다.
+
+### 6. 수정된 할 일 텍스트를 저장하는 함수 구현
+
+수정 저장 함수는 수정된 내용을 저장하고, map을 통해 해당 id의 내용을 업데이트합니다.
+유효성 검사를 통해 빈 텍스트는 저장되지 않도록 처리합니다.
+
+### 7. 할 일 수정을 취소하고 원래 상태로 돌리는 함수 구현
+
+수정 취소 함수는 수정을 취소하고 수정 관련 상태들을 초기화합니다.
+ESC 키를 누르거나 취소 버튼을 클릭했을 때 호출됩니다.
+
+### 8. 엔터키를 눌렀을 때 할 일을 추가하는 키보드 이벤트 함수 구현
+
+Enter 키로 할 일을 추가하는 기능을 제공합니다.
+키보드 이벤트를 통해 더 나은 사용자 경험을 구현할 수 있습니다.
+
+### 9. 입력 필드와 사용자 입력값을 연결
+
+기본 HTML input 태그를 사용하여 사용자 입력을 받습니다.
+value, onChange, onKeyDown 속성을 적절히 연결하여 제어된 컴포넌트를 만듭니다.
+placeholder를 통해 사용자에게 입력 가이드를 제공합니다.
+
+### 10. 필터링 기능을 위한 TodoFilter 컴포넌트 연결
+
+TodoFilter 컴포넌트에 현재 필터 상태와 변경 함수를 props로 전달합니다.
+컴포넌트 분리를 통해 재사용성과 유지보수성을 향상시킵니다.
+
+### 11. 전체 선택/삭제 기능을 위한 TodoActions 컴포넌트 연결
+
+TodoActions 컴포넌트에 필요한 데이터와 함수들을 props로 전달합니다.
+전체 선택/해제, 완료 항목 삭제 등의 일괄 작업 기능을 제공합니다.
+
+### 12. 필터링된 할 일 목록을 화면에 표시
+
+필터링된 할 일 목록을 map으로 순회하여 각 할 일을 렌더링합니다.
+빈 상태일 때 적절한 메시지를 표시하여 사용자 경험을 개선합니다.
+
+### 13. 할 일 완료 상태를 체크박스에 연결
+
+체크박스의 checked 속성을 할 일의 완료 상태와 연결합니다.
+onChange 이벤트를 통해 체크박스 클릭 시 상태를 토글합니다.
+
+### 14. 할 일 내용을 표시하고 더블클릭으로 수정 모드 전환
+
+현재 수정 중인 할 일의 ID와 비교하여 수정 모드와 일반 모드를 조건부로 렌더링합니다.
+수정 중일 때는 input 태그를, 일반 상태일 때는 텍스트로 표시합니다.
+더블클릭 이벤트를 통해 수정 모드로 전환할 수 있습니다.
+
+### 15. 할 일의 상태 표시와 수정/삭제 버튼 구현
+
+할 일의 완료/진행중 상태를 배지로 표시합니다.
+수정 모드일 때는 저장/취소 버튼을, 일반 모드일 때는 수정/삭제 버튼을 표시합니다.
+조건부 렌더링을 통해 적절한 버튼들을 보여줍니다.
+
+## TodoFilter.jsx 구현하기
+
+### 1. 필터 옵션들 정의
+
+필터 버튼에 사용할 옵션들을 배열로 정의합니다.
+각 옵션은 key, label, color 속성을 가지며 동적 UI 생성에 활용됩니다.
+
+### 2. filters 배열을 map으로 렌더링
+
+map 메서드를 사용하여 필터 옵션들을 동적으로 버튼으로 렌더링합니다.
+key 속성을 반드시 지정하여 React의 효율적인 렌더링을 돕습니다.
+onClick 이벤트에서 화살표 함수를 사용하여 매개변수를 전달합니다.
+
+## TodoActions.jsx 구현하기
+
+### 1. 통계 계산
+
+filter 메서드와 length 속성을 사용하여 완료된 할 일의 개수를 계산합니다.
+totalCount는 전체 할 일의 개수를 나타내며 버튼의 활성화 상태를 결정합니다.
+
+### 2. 전체 선택/해제 버튼
+
+allSelected 상태에 따라 버튼의 텍스트와 동작을 변경합니다.
+disabled 속성을 사용하여 할 일이 없을 때 버튼을 비활성화합니다.
+삼항 연산자를 활용하여 조건부 스타일링을 적용합니다.
+
+### 3. 완료 항목 삭제 버튼
+
+completedCount가 0일 때 버튼을 비활성화하여 불필요한 동작을 방지합니다.
+버튼 텍스트에 현재 완료된 개수를 표시하여 사용자에게 정보를 제공합니다.
+
+### 4. 진행률 표시
+
+Math.round를 사용하여 완료율을 백분율로 계산하고 정수로 표시합니다.
+totalCount가 0일 때 0으로 나누기 오류를 방지하는 조건문을 추가합니다.
diff --git a/src/App.jsx b/src/App.jsx
index d59aaa8..cf61de9 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,8 +1,11 @@
import "./App.css";
-import BasicTodo from "./step1/BasicTodo";
+import AdvancedTodo from "./step2/AdvancedTodo";
function App() {
- return ;
+ return (
+ //
+
+ );
}
export default App;
diff --git a/src/step1/BasicTodo.jsx b/src/step1/BasicTodo.jsx
index 5af15b9..e62c141 100644
--- a/src/step1/BasicTodo.jsx
+++ b/src/step1/BasicTodo.jsx
@@ -8,19 +8,59 @@ const BasicTodo = () => {
{ job: "장보기", state: "완료" },
{ job: "산책하기", state: "미완료" },
]);
- // TODO: 1. 할 일 입력을 위한 state 생성
-
+ // TODO: 1. 할 일 입력을 위한 state 생성 => useState( // 초기값 )
+ const [newTodo, setNewTodo] = useState(""); // state, setState
+ const [isComposing, setIsComposing] = useState(false);
// TODO: 2. 할 일 추가 함수 구현
- const addTodo = () => { };
+ // 불변성 지키기 => 원본 배열을 그대로 수정하지 않기
+ const addTodo = () => {
+ // if(newTodo === "") return; // 공백 입력 방지
+ // if(!newTodo) return; falsy 값 => 빈문자열 처리 주로 이렇게 사용
+ if (newTodo.trim() === "") return; // early return
+ const updatedTodoList = [
+ ...todoList,
+ {
+ job: newTodo,
+ state: "미완료",
+ },
+ ];
+ setTodoList(updatedTodoList);
+ setNewTodo("")
+ //setTodoList([...todoList, { job: newTodo, state: "미완료" }]);
+ };
// TODO: 3. 완료/미완료 토글 함수 구현
- const toggleTodoState = (index) => { };
+ const toggleTodoState = (index) => {
+ // const toggledTodoList = [...todoList];
+ // 해당 index를 가진 배열의 객체 요소의 staste 값을 반대로 토글링!
+ // toggledTodoList[index].state = toggledTodoList[index].state === "완료" ? "미완료" : "완료";
+ const toggledTodoList = todoList.map((todo, i) =>
+ i === index
+ ? { ...todo, state: todo.state === "완료" ? "미완료" : "완료" }
+ : todo
+ );
+ //map => 새로운 배열 반환 좀 더 깔끔 할 수 있다.
+ setTodoList(toggledTodoList);
+ };
// TODO: 4. 할 일 삭제 함수 구현
- const deleteTodo = (index) => { };
+ const deleteTodo = (index) => {
+ const deletedTodoList = todoList.filter((_, i) => i !== index);
+ // item, index => _ , i => _ 언더바는 사용하지 않는다는 의미
+ // map, fileter => map((item, index) => {}) 객체와 인덱스
+ setTodoList(deletedTodoList);
+ };
// TODO: 5. Enter 키 처리 함수 (한국어 입력 고려)
- const handleKeyDown = (e) => { };
+ const handleKeyDown = (e) => { // event를 받음. keyboradEvent
+ //console.log(e.key,e.nativeEvent.isComposing);
+ //if (e.nativeEvent.isComposing) return; // 조합 중이면 무시
+ if (e.key === "Enter" && !isComposing) {
+ addTodo();
+ }
+ // if(e.key !== "Enter") return;
+ // addTodo();
+ };
return (
@@ -32,9 +72,14 @@ const BasicTodo = () => {
type="text"
placeholder="새로운 할 일을 입력하세요..."
/* TODO: 7. input 값 채우기 */
- // value={} // 1번의 state 적용
- onChange={(e) => { }} // 1번의 setState 적용
+ value={newTodo}
+ onChange={(e) => {
+ setNewTodo(e.target.value);
+ //지금 내가 발생시키고 있는 요소의 값을 가져와 변경
+ }} // 1번의 setState 적용
onKeyDown={handleKeyDown}
+ onCompositionStart={() => setIsComposing(true)}
+ onCompositionEnd={() => setIsComposing(false)}
/>