react 과제 수행
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;