본문 바로가기

DEVELOPE/앱개발시작하기

[20240510] 앱개발 시작하기 #25 | 투두리스트 만들기

App.jsx 

// import { useState } from 'react'
import './App.css'
import Header from './components/Header'
import Editor from './components/Editor'
import List from './components/List'
import { useState, useRef } from 'react'


const mockData = [
  {
    id : 0,
    isDone: false,
    content: "React 공부하기",
    date: new Date().getTime(),
  },{
    id : 1,
    isDone: false,
    content: "React 공부하기1",
    date: new Date().getTime(),
  }, {
    id : 2,
    isDone: false,
    content: "React 공부하기2",
    date: new Date().getTime(),
  }
]

function App() {
  const [todos, setTodos] = useState(mockData);
  const idRef = useRef(3);

  const onCreate=(content)=>{
    const newTodo = {
      id:idRef.current++,
      isDone:false,
      content:content,
      date:new Date().getTime(),
    }
    setTodos([newTodo,...todos]);
  }
  
  const onUpdate = (targetId) => {
    //todos State의 값들 중에
    //targetId와 일치하는 id를 갖는 투두 아이템의 isDone 변경

    // 인수 : todos 배열에서 targetId와 일치하는 id를 갖는 요소의 데이터만 딱 바꾼 새로운 배열
    setTodos(todos.map((todo)=>{
      if(todo.id === targetId){
        return{
          ...todo,
          isDone: !todo.isDone
        }
      }
      return todo
    }))
  }

  const onDelete = (targetId) => {
    // 인수 : todos 배열에서 targetId와 일치하는 id를 갖는 요소만 삭제한 새로운 배열
    setTodos(todos.filter((todo)=>todo.id !== targetId))
  }

  return (
    <div className='app'>
      <Header></Header>
      <Editor onCreate={onCreate}></Editor>
      <List todos={todos} onUpdate={onUpdate} onDelete={onDelete}></List>
    </div>
  )
}

export default App;

Editor.jsx

import './Editor.css'
import { useState, useRef } from 'react'

const Editor = ({onCreate}) => {
    const [content, setContent] = useState("");
    const contentRef = useRef();

    const onChangeContent = (e) => {
        setContent(e.target.value);
    }

    const onSubmit = () => {
        if (content===""){
            contentRef.current.focus(); // 빈 값에 추가버튼 누르면 focus 작동되도록
            return;
        }
        onCreate(content);
        setContent(""); // 값 추가하면 빈 input 되도록 설정해주는 함수
    }

    const onKeydown = (e) => {
        if(e.keyCode ===13 ){ //엔터치면 제출되도록
            onSubmit();
        }
    }

    return(
        <div className="editor">
            <input ref={contentRef} onKeyDown={onKeydown} value={content} onChange={onChangeContent} placeholder="새로운 Todo..."></input>
            <button onClick={onSubmit}>추가</button>
        </div>
    );
}

export default Editor;

Header.jsx

import './Header.css';

const Header = () => {
    return(
        <div className="header">
            <h3>오늘은🫶</h3>
            <h1 >{new Date().toDateString()}</h1>
        </div>
    );
}

export default Header;

List.jsx

import "./List.css";
import TodoItem from "./TodoItem";
import { useState } from "react";

const List = ({todos, onUpdate, onDelete}) => {
    const [search, setSearch] = useState("");
    const onChangeSearch = (e) => {
        setSearch(e.target.value);
    }
    const getFilterdData = () => {
        if(search===""){return todos;}
        return todos.filter((todo)=>todo.content.toLowerCase().includes(search.toLowerCase()));

    }

    const filteredTodos = getFilterdData();

    return(
        <div className="list">
            <h4>🐰Todo List🐰</h4>
            <input value={search} onChange={onChangeSearch} placeholder="검색어를 입력하세요 ..."></input>
            <div className="todos.wrapper">
                {filteredTodos.map((todo)=>{
                    return <TodoItem key={todo.id} {...todo} onUpdate={onUpdate} onDelete={onDelete}></TodoItem>
                })}
            </div>
        </div>
    );
}

export default List;

TodoItem.jsx

import "./TodoItem.css";

const TodoItem = ({id, isDone, content, date, onUpdate, onDelete}) => {

    const onChangeCheckbox = () => {
        onUpdate(id);
    }

    const onClickDeleteButton = () => {
        onDelete(id);
    }

    return(
        <div className="todoitem">
            <input onChange={onChangeCheckbox} readOnly checked={isDone} type="checkbox"></input>
            <div className="content">{content}</div>
            <div className="date">{new Date(date).toLocaleDateString()}</div>
            <button onClick={onClickDeleteButton}>삭제</button>
        </div>
    )
}

export default TodoItem;
728x90