오늘은 드디어 React 개인과제 돌입!
오전에는 거의 CRA랑 Vite, Tailwind css를 설치해보는데 시간을 다 보냈다. 캠프 전에 경험해본 것이 딱 javascript였기 때문에 React고 Tailwind고 죄다 처음이여서 엄청 헤맸다.
아직 컴포넌트 분리나 이런 것들이 어려워서 일단 완성해보고 컴포넌트 분리도 해 볼듯!
import PropTypes from "prop-types";
import { useState } from "react";
const ToDosTitle = ({ title }) => {
return <h2 className="text-3xl font-bold py-2">{title}</h2>;
};
ToDosTitle.propTypes = {
title: PropTypes.string.isRequired,
};
const ToDo = ({ id, title, body, isDone, setToDos }) => {
return (
<div className=" h-32 w-48 p-2 ml-8 bg-white rounded-2xl">
<div className="flex justify-between text-xs border-black border-b-2 pb-2">
<p className={"flex justify-center items-center text-lg font-black"}>
{isDone ? "완료" : "진행중"}
</p>
<button
className={"px-2 py-1 border-2 border-black rounded-lg"}
onClick={() => {
setToDos((toDos) => {
return toDos.map((toDo) => {
if (toDo.id === id) {
const newToDo = { ...toDo };
newToDo.isDone = !newToDo.isDone;
return newToDo;
}
return toDo;
});
});
}}
>
{isDone ? "취소" : "완료"}
</button>
<button
className={
" bg-red-800 text-white px-2 py-1 rounded-lg border-2 border-black"
}
onClick={() => {
setToDos((toDos) => {
return toDos.filter((toDo) => {
if (toDo.id === id) {
return false;
}
return true;
});
});
}}
>
삭제
</button>
</div>
<h3 className={isDone ? "text-lg line-through" : "text-lg no-underline"}>
{title}
</h3>
<p className={isDone ? "text-sm line-through" : "text-sm no-underline"}>
{body}
</p>
</div>
);
};
ToDo.propTypes = {
setToDos: PropTypes.func.isRequired,
title: PropTypes.string.isRequired,
body: PropTypes.string.isRequired,
isDone: PropTypes.bool.isRequired,
id: PropTypes.number.isRequired,
};
const App = () => {
const [toDoTitle, setToDoTitle] = useState("");
const [toDoBody, setToDoBody] = useState("");
const [toDos, setToDos] = useState([]);
const template = {
toDoTitle: "제목을 입력해주세요",
toDoBody: "내용을 입력해주세요",
};
console.log("to do title: ", toDoTitle, "to do body: ", toDoBody);
console.log("current to dos", toDos);
return (
<article className=" max-w-[1200px] min-w-[800px] h-[600px] bg-blue-200">
<form
className=" flex flex-col justify-center items-center h-1/3"
onSubmit={(e) => {
e.preventDefault();
const newToDo = {
id: new Date().getTime(),
title: toDoTitle,
body: toDoBody,
isDone: false,
};
setToDos([newToDo, ...toDos]);
setToDoTitle("");
setToDoBody("");
}}
>
<label>할 일</label>
<input
type="text"
onChange={(e) => {
setToDoTitle(e.target.value);
}}
value={toDoTitle}
placeholder={template.toDoTitle}
/>
<label>내용</label>
<input
type="text"
onChange={(e) => {
setToDoBody(e.target.value);
}}
value={toDoBody}
placeholder={template.toDoBody}
/>
<button>Add To Do</button>
</form>
<section className="h-1/3 bg-yellow-600 box-border">
<ToDosTitle title="진행중인 목록" />
<ul className="flex justify-start items-center">
{toDos
.filter((toDo) => {
return toDo.isDone === false;
})
.map((toDo) => {
const { id, title, body, isDone } = toDo;
return (
<li className="h-full" key={id}>
<ToDo
id={id}
title={title}
body={body}
isDone={isDone}
setToDos={setToDos}
/>
</li>
);
})}
</ul>
</section>
<section className="h-1/3 bg-yellow-300 flex flex-col items-start">
<ToDosTitle title="완료된 목록" />
<ul className="flex justify-start">
{toDos
.filter((toDo) => {
return toDo.isDone === true;
})
.map((toDo) => {
const { id, title, body, isDone } = toDo;
return (
<li key={id}>
<ToDo
id={id}
title={title}
body={body}
isDone={isDone}
setToDos={setToDos}
/>
</li>
);
})}
</ul>
</section>
</article>
);
};
export default App;
재훈님 고생하셨어요!!ㅋㅋ