일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 자바스크립트
- 웹
- Github Pages
- javascript
- 배너 슬라이더
- 인덱스된 데이터베이스
- 비동기 함수
- 배너
- React.js
- js
- github
- array
- HTTP
- 슬라이더
- 배포
- deploy
- 슬라이드
- slide
- 웹스토리지
- 리액트배포
- 자바스크립트 배열
- vite
- 배열
- react
- 렌더링
- dnd-kit
- IndexedDB
- 리액트
- banner
- 웹사이트
- Today
- Total
Somedding
[Toy Projects] 'TODOoO' project (7) 본문
마지막으로 카테고리를 추가할 수 있는 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 |