[2024.05.16] TIL 21일차

김선민·2024년 5월 16일

[ 본캠프 21일차 기록 ]

🖥️ 오늘 공부한 내용 🖥️

react 과제 수행

  1. 리액트 개인 과제 수행 2

App.jsx : 메인 페이지

import React, { useState } from "react";
import { createGlobalStyle } from "styled-components";
import reset from "styled-reset";
import "./App.css";
import Swal from "sweetalert2";
import FormComp from "./components/FormComp/FormComp";
import ListComp from "./components/TodoListComp/ListComp";
import ScrollTopComp from "./components/ScrollComp/ScrollTopComp";

const GlobalStyle = createGlobalStyle`
  ${reset}
`;

const App = () => {
  const [todo, setTodo] = useState([]);
  const [done, setDone] = useState([]);

  const addList = (newTodo) => {
    if (!newTodo.title || !newTodo.cont) {
      Swal.fire({
        title: "Error!",
        text: "이름과 나이 모두 입력해주세요",
        confirmButtonText: "확인",
      });
      return;
    }

    const id = Date.now();
    const todoInfo = {
      id: id,
      title: newTodo.title,
      cont: newTodo.cont,
      isDone: false,
    };
    setTodo([...todo, todoInfo]);
  };

  const toggleDone = (id) => {
    const updatedTodoList = todo.map((item) => {
      if (item.id === id) {
        return { ...item, isDone: !item.isDone };
      }
      return item;
    });
    const updatedTodo = updatedTodoList.filter((item) => !item.isDone);
    const updatedDone = updatedTodoList.filter((item) => item.isDone);
    setTodo(updatedTodo);
    setDone((prevDone) => [...prevDone, ...updatedDone]);
  };

  const toggleCancle = (id) => {
    const updatedDoneList = done.map((item) => {
      if (item.id === id) {
        return { ...item, isDone: !item.isDone };
      }
      return item;
    });
    const updatedTodo = updatedDoneList.filter((item) => !item.isDone);
    const updatedDone = updatedDoneList.filter((item) => item.isDone);
    setTodo((prevTodo) => [...prevTodo, ...updatedTodo]);
    setDone(updatedDone);
  };

  const onRemove = (id) => {
    setTodo(todo.filter((cards) => cards.id !== id));
    setDone(done.filter((cards) => cards.id !== id));
  };

  return (
    <React.Fragment>
      <GlobalStyle />
      <div className="layout">
        <header className="headerBar">
          <h1 className="pageTitle">My To Do List</h1>
        </header>

        <FormComp addList={addList} />

        <ListComp
          todo={todo}
          done={done}
          toggleDone={toggleDone}
          toggleCancle={toggleCancle}
          onRemove={onRemove}
        />

        <ScrollTopComp />
      </div>
    </React.Fragment>
  );
};

export default App;

FormComp.jsx : 할 일 작성 input form

import React, { useState } from "react";
import "./FormComp.css";

const FormComp = ({ addList }) => {
  const [title, setTitle] = useState("");
  const [cont, setCont] = useState("");

  const handleSubmit = (e) => {
    e.preventDefault();
    addList({ title, cont });
    setTitle("");
    setCont("");
  };

  return (
    <div className="inputBar">
      <form onSubmit={handleSubmit} className="formFlex">
        <div className="inputBox">
          <div className="inputFlex1">
            <h4 className="inputTitle">제목</h4>
            <input
              className="input-title"
              type="text"
              placeholder="제목을 입력하세요..."
              value={title}
              onChange={(e) => {
                setTitle(e.target.value);
              }}
            />
          </div>
          <div className="inputFlex2">
            <h4 className="inputCont">내용</h4>
            <input
              className="input-content"
              type="text"
              placeholder="내용을 입력하세요..."
              value={cont}
              onChange={(e) => {
                setCont(e.target.value);
              }}
            />
          </div>
        </div>
        <button className="addBtn">추가하기</button>
      </form>
    </div>
  );
};

export default FormComp;

ListComp.jsx : Working / Done 카드 렌더링

import React from "react";
import CardComp from "../CardComp/CardComp";
import "./ListComp.css";

const ListComp = ({ todo, done, toggleDone, toggleCancle, onRemove }) => {
  return (
    <React.Fragment>
      <div className="workingList">
        <h1 className="workingTitle">Working...🔥</h1>
        <div className="cardFlex">
          <div className="gridContainer">
            {todo.map((cards) => (
              <CardComp
                key={cards.id}
                id={cards.id}
                title={cards.title}
                content={cards.cont}
                onRemove={onRemove}
                toggleDone={() => toggleDone(cards.id)}
                state={"완료"}
              />
            ))}
          </div>
        </div>
      </div>

      <div className="doneList">
        <h1 className="doneTitle">Done ✅</h1>
        <div className="cardFlex2">
          <div className="gridContainer2">
            {done.map((cards) => (
              <CardComp
                key={cards.id}
                id={cards.id}
                title={cards.title}
                content={cards.cont}
                onRemove={onRemove}
                toggleCancle={() => toggleCancle(cards.id)}
                state={"취소"}
              />
            ))}
          </div>
        </div>
      </div>
    </React.Fragment>
  );
};

export default ListComp;

CardComp.jsx : 할 일 카드 컴포넌트

import React from "react";
import { createGlobalStyle } from "styled-components";
import reset from "styled-reset";
import "./CardComp.css";

const GlobalStyle = createGlobalStyle`
  ${reset}
`;

const CardComp = ({
  id,
  title,
  content,
  toggleDone,
  toggleCancle,
  onRemove,
  state,
}) => {
  const handleClick = () => {
    if (state === "완료") {
      toggleDone(id);
    } else if (state === "취소") {
      toggleCancle(id);
    }
  };

  return (
    <React.Fragment>
      <GlobalStyle />
      <div className="cardLayout">
        <div className="cardInfo">
          <h2 className="cardTitle">{title}</h2>
          <div className="sectionLine"></div>
          <h3 className="cardCont">{content}</h3>
        </div>

        <div className="cardBtns">
          <button className="cardDelete" onClick={() => onRemove(id)}>
            삭제하기
          </button>
          <button className="cardBtn" onClick={handleClick}>
            {state}
          </button>
        </div>
      </div>
    </React.Fragment>
  );
};

export default CardComp;

ScrollTopComp.jsx : 페이지 자동 스크롤 기능

import React, { useState, useEffect, useRef } from "react";
import "./ScrollTopComp.css";

function ScrollTopComp() {
  const [isAtTop, setAtTop] = useState(true);
  const scrollBtnRef = useRef(null);

  useEffect(() => {
    const handleScroll = () => {
      if (window.scrollY === 0) {
        setAtTop(true);
      } else {
        setAtTop(false);
      }
    };

    window.addEventListener("scroll", handleScroll);

    return () => {
      window.removeEventListener("scroll", handleScroll);
    };
  }, []);

  const scrollToTop = () => {
    window.scrollTo({
      top: 0,
      left: 0,
      behavior: "smooth",
    });
  };

  const scrollToBottom = () => {
    window.scrollTo({
      top: document.body.scrollHeight,
      left: 0,
      behavior: "smooth",
    });
  };

  return (
    <button
      className="scrollBtn"
      onClick={isAtTop ? scrollToBottom : scrollToTop}
      ref={scrollBtnRef}
    >
      <i className="scroll">{isAtTop ? "▼" : "▲"}</i>
    </button>
  );
}

export default ScrollTopComp;
profile
웹 프론트엔드

0개의 댓글