Somedding

[Toy Projects] 'TODOoO' project (7) 본문

Toy Projects

[Toy Projects] 'TODOoO' project (7)

somedding 2023. 3. 9. 16:33

마지막으로 카테고리를 추가할 수 있는 setting 메뉴를 만들었다.

setting 메뉴에 들어갈 것은 우선 카테고리 추가 기능과 다크모드 기능이다.

우선 component 디렉터리의 하위에 Setting.js 파일을 추가하고, Nav.js에서 컴포넌트로 사용했다.

// component/Nav.js

import { useState } from "react";
import Setting from "./Setting";

function Nav(props) {
  const { category, setCategory } = props;
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div className="nav">
      <p className="nav-title">TODOoO</p>
      <p
        className="nav-setting"
        onClick={() => {
          // 닫기 버튼은 모달창에 만들 것이기 때문에 여기서 되돌아갈 필요가 없음
          setIsOpen(true);
        }}
      >
        ☸︎
      </p>
      {isOpen ? <Setting category={category} setCategory={setCategory}></Setting> : null}
    </div>
  );
}

export default Nav;

 

이때, App.js에서 Nav로 category를 props로 전달했다.

// App.js

<Nav
  category={category}
  setCategory={setCategory}
></Nav>

 

Setting 컴포넌트에서는 모달창 형식으로 표현할 예정인데,

우선 Nav 컴포넌트로부터 category를 전달받아 화면에 전시해 주었다.

각각의 카테고리 명에 삭제 버튼을 만들었고, 마지막엔 카테고리 추가 버튼을 만들었다.

// component/Setting.js

  useEffect(() => {
    let _allCategory = [];
    for (let i = 0; i < category.length; i++) {
      _allCategory.push(
        <div key={i}>
          <span>{category[i]}</span>
          <span>×</span>
        </div>
      );
    }
    _allCategory.push(
      <div key={-1}>
        <span onClick={PlusCategory}>+</span>
      </div>
    );
    setAllCategory(_allCategory);
  }, [category]);

 

카테고리를 추가하는 기능을 담은 함수는 PlusCategory로, 사용자의 입력을 받아 중복인지, 혹은 빈칸인지 확인 후 추가가 가능하도록 했다.

// component/Setting.js

function PlusCategory() {
    let str = "추가할 카테고리 명을 입력해주세요!";
    let _new = window.prompt(str);
    if (_new !== null) { // null이 아니라면
      if (category.indexOf(_new) !== -1 || _new === '') {
        while(true){
          if(category.indexOf(_new) !== -1) {
            _new = window.prompt("중복입니다.\n추가할 카테고리 명을 입력해주세요!");
            continue;
          }
          else if(_new === '') {
            _new = window.prompt("추가할 카테고리 명을 입력해주세요!");
            continue;
          }
          else if(_new !== null) {
            setCategory([...category, _new]);
            break;
          }
          else break;
        }
      } else {
        setCategory([...category, _new]);
      }
    }
}

 

Setting을 열었을 때의 화면

 

카테고리 추가버튼을 눌렀을 때

 

카테고리 명이 중복일 때

 

 

카테고리 3 추가한 화면

 

다음은 카테고리 삭제이다.

활동이 이미 저장되어 있는 카테고리를 삭제할 때가 있을 수 있어서, 삭제하기 전에 ‘해당 카테고리 내의 활동이 삭제됩니다.’라는 문구를 띄어줄 것이다.

 

카테고리를 삭제하게 되면, category 뿐만 아니라 todo 객체 역시 삭제를 해줘야 하기 때문에, props를 통해 todo와 setTodo를 전달하게 됐다.

// component/Setting.js

function DeleteCategory(index){
    if(window.confirm('해당 카테고리 내의 활동이 삭제됩니다.\n삭제하시겠습니까?')){
      let _category = Array.from(category);
      let trash = _category.splice(index,1);
      setCategory(_category);

      let _todo = Array.from(todo);
      for(let i = todo.length - 1; i >= 0; i--){
        if(_todo[i].category === trash[0]){
          _todo.splice(i,1);
        }
      }
      setTodo(_todo);
    }
  }

DeleteCategory를 통해 category와 todo를 업데이트해주었다.

 

 

다음은 App.js 전체 코드이다.

// App.js

import './App.css';
import Nav from './component/Nav';
import Category from './component/Category';
import { useEffect, useState } from 'react';

function App() {
  const [todo, setTodo] = useState([{
    id:0,
    category:'일반',
    desc:'할일1'
  },{
    id:1,
    category:'일반',
    desc:'할일2'
  },{
    id:2,
    category:'카테고리2',
    desc:'할일1'
  }]);
  const [category, setCategory] = useState(['일반','카테고리2']);
  const [cateForm, setCateForm] = useState([]);
  const [isOpen, setIsOpen] = useState('');

  useEffect(()=>{
    let _cateform = [];
    for(let i = 0; i < category.length; i++){
      let _todo = [];
      for(let j = 0; j < todo.length; j++){
        if(category[i] === todo[j].category){
          _todo.push({id:todo[j].id, desc:todo[j].desc});
        }
      }
      _cateform.push(
        <Category
          key={i}
          category={category[i]}
          todo={_todo}
          onCreate={(data) => {
            let _id = todo[todo.length - 1].id;
            setTodo([...todo, {
              id:_id + 1,
              category: category[i],
              desc: data
            }]);
          }}
          onUpdate={(id, data)=>{
            let changeTodo = Array.from(todo);
            for(let i = 0; i < todo.length; i++){
              if(changeTodo[i].id === id){
                changeTodo[i].desc = data;
                break;
              }
            }
            setTodo(changeTodo);
          }}
          onDelete={(id)=>{
            let changeTodo = Array.from(todo);
            for(let i = 0; i < todo.length; i++){
              if(changeTodo[i].id === id){
                changeTodo.splice(i,1);
                break;
              }
            }
            setTodo(changeTodo);
          }}
          isOpen={isOpen}
          setIsOpen={setIsOpen}
          ></Category>
      );
    }
    setCateForm(_cateform);
  },[category, todo, isOpen])

  return (
    <div className="app">
      <Nav
        category={category}
        setCategory={setCategory}
        todo={todo}
        setTodo={setTodo}
      ></Nav>
      {cateForm}
    </div>
  );
}

export default App;

 

 

다음은 Nav.js의 전체 코드이다.

// component/Nav.js

import { useState } from "react";
import Setting from "./Setting";

function Nav(props) {
  const { category, setCategory,  todo, setTodo } = props;
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div className="nav">
      <p className="nav-title">TODOoO</p>
      <p
        className="nav-setting"
        onClick={() => {
          setIsOpen(true);
        }}
      >
        ☸︎
      </p>
      {isOpen ? <Setting category={category} setCategory={setCategory} todo={todo} setTodo={setTodo}></Setting> : null}
    </div>
  );
}

export default Nav;

 

 

다음은 Setting.js의 전체 코드이다.

// component/Setting.js

import { useEffect, useState } from "react";

function Setting(props) {
  const { category, setCategory, todo, setTodo } = props;
  const [allCategory, setAllCategory] = useState([]);

  useEffect(() => {
    let _allCategory = [];
    for (let i = 0; i < category.length; i++) {
      _allCategory.push(
        <div key={i}>
          <span>{category[i]}</span>
          <span onClick={() => DeleteCategory(i)}>×</span>
        </div>
      );
    }
    _allCategory.push(
      <div key={-1}>
        <span onClick={PlusCategory}>+</span>
      </div>
    );
    setAllCategory(_allCategory);
  }, [category, todo]);

  function PlusCategory() {
    let str = "추가할 카테고리 명을 입력해주세요!";
    let _new = window.prompt(str);
    if (_new !== null) { // null이 아니라면
      if (category.indexOf(_new) !== -1 || _new === '') {
        while(true){
          if(category.indexOf(_new) !== -1) _new = window.prompt("중복입니다.\n추가할 카테고리 명을 입력해주세요!");
          else if(_new === '') _new = window.prompt("추가할 카테고리 명을 입력해주세요!");
          else if(_new !== null) {
            setCategory([...category, _new]);
            break;
          }
          else break;
        }
      } else {
        setCategory([...category, _new]);
      }
    }
  }
  function DeleteCategory(index){
    if(window.confirm('해당 카테고리 내의 활동이 삭제됩니다.\n삭제하시겠습니까?')){
      let _category = Array.from(category);
      let trash = _category.splice(index,1);
      setCategory(_category);

      let _todo = Array.from(todo);
      for(let i = todo.length - 1; i >= 0; i--){
        if(_todo[i].category === trash[0]){
          _todo.splice(i,1);
        }
      }
      setTodo(_todo);
    }
  }
  return (
    <div className="setting">
      <div className="setting-area">
        <div>
          <p>카테고리</p>
          <div>{allCategory}</div>
        </div>
        <div></div>
      </div>
    </div>
  );
}

export default Setting;

 

 

 

 

 

 

 

 

글 내용 중, 잘못됐거나 더 알아야 하는 지식이 있다면 댓글로 남겨주시면 감사하겠습니다!

모두 좋은 하루 보내세요:)

'Toy Projects' 카테고리의 다른 글

[Toy Projects] 'TODOoO' project (9)  (0) 2023.03.14
[Toy Projects] 'TODOoO' project (8)  (0) 2023.03.13
[Toy Projects] 'TODOoO' project (6)  (0) 2023.03.08
[Toy Projects] 'TODOoO' project (5)  (0) 2023.03.07
[Toy Projects] 'TODOoO' project (4)  (0) 2023.03.06
Comments