EditModal.tsx 할일 누르면 > 상세정보 열고 닫힘
닫힘 아이콘 FiX 를 누르면 > handleCloseButton 함수 호출
dispatch로 상태관리한 setModalActive를 false로 만들면
modalActive가 false가 되어서 App.js에서 <EditModal /> 호출한 거에서 null 이 된다.
import React, { useState } from "react";
import { FiX } from "react-icons/fi";
import { useTypedDispatch, useTypedSelector } from "../../hooks/redux";
import { setModalActive } from "../../store/slices/boardsSlice";
const EditModal = () => {
const dispatch = useTypedDispatch();
const editingState = useTypedSelector((state) => state.modal);
const [data, setData] = useState(editingState);
const handleCloseButton = () => {
dispatch(setModalActive(false));
};
return (
<div>
<div>
<div>
<div> {editingState.task.taskName} </div>
<FiX onClick={handleCloseButton} />
</div>
<div>제목</div>
<input type="text" value={data.task.taskName} />
<div>설명</div>
<input type="text" value={data.task.taskDescription} />
<div>생성한 사람</div>
<input type="text" value={data.task.taskOwner} />
<div>
<button>일 수정하기</button>
<button>일 삭제하기</button>
</div>
</div>
</div>
);
};
export default EditModal;
//boardsSlice.ts
setModalActive: (state, { payload }: PayloadAction<boolean>) => {
state.modalActive = payload;
},
input 데이터
data 얕은복사로 현재 목록 로그 가져오고 > 이름, 설명, 사용자 입력값 추적한다.
const handleNameChange = (e: ChangeEvent<HTMLInputElement>) => {
setData({
...data,
task: {
...data.task,
taskName: e.target.value,
},
});
};
const handleDescriptionChange = (e: ChangeEvent<HTMLInputElement>) => {
setData({
...data,
task: {
...data.task,
taskDescription: e.target.value,
},
});
};
const handleOwnerChange = (e: ChangeEvent<HTMLInputElement>) => {
setData({
...data,
task: {
...data.task,
taskOwner: e.target.value,
},
});
};
///
<input
type="text"
value={data.task.taskName}
onChange={handleNameChange}
/>
수정하기 버튼 > 상태값 저장된거 업데이트
addTask와 비슷한 로직!인데 > push 가 아닌, map을 돌면서 같은 id가 있으면 수정, 아닐경우 기본 task 반환
`TAddTaskAction` 타입값 그대로 사용한다.
//boardsSlice.ts
updateTask: (state, { payload }: PayloadAction<TAddTaskAction>) => {
state.boardArray = state.boardArray.map((board) =>
board.boardId === payload.boardId
? {
...board,
lists: board.lists.map((list) =>
list.listId === payload.listId
? {
...list,
tasks: list.tasks.map((task) =>
task.taskId === payload.task.taskId
? payload.task
: task
),
}
: list
),
}
: board
);
},
//EditModal.tsx
const handleUpdate = () => {
dispatch(
updateTask({
boardId: editingState.boardId,
listId: editingState.listId,
task: data.task,
})
);
dispatch(
addLog({
logId: v4(),
logMessage: `일 수정하기 : ${editingState.task.taskName}`,
logAuthor: "User",
logTimestamp: String(Date.now()),
})
);
dispatch(setModalActive(false));
};
삭제하기 버튼
//boardsSlice.ts
deleteTask: (state, { payload }: PayloadAction<TDeleteTaskAction>) => {
state.boardArray = state.boardArray.map((board) =>
board.boardId === payload.boardId
? {
...board,
lists: board.lists.map((list) =>
list.listId === payload.listId
? {
...list,
tasks: list.tasks.filter(
(task) => task.taskId !== payload.taskId
),
}
: list
),
}
: board
);
//EditModal.tsx
const handleDelete = () => {
dispatch(
deleteTask({
boardId: editingState.boardId,
listId: editingState.listId,
taskId: editingState.task.taskId,
})
);
dispatch(
addLog({
logId: v4(),
logMessage: `일 삭제하기 : ${editingState.task.taskName}`,
logAuthor: "User",
logTimestamp: String(Date.now()),
})
);
dispatch(setModalActive(false));
};
},
LoggerModal.tsx 활동 목록 보이기
app.js 에서 버튼을 누르면 > isLoggerOopen이 열리고 > LoggerModal.tsx 에서 열리게 된다.
{isLoggerOpen ? <LoggerModal setIsLoggerOpen={setIsLoggerOpen} /> : null}
//...
<button
className={loggerButton}
onClick={() => setIsLoggerOpen(!isLoggerOpen)}
onBlur={() => setIsLoggerOpen(false)}
>
{isLoggerOpen ? "활동 목록 숨기기" : "활동 목록 보이기"}
</button>
LoggerModal.tsx는 스타일, props 전달의 구성요소
> 여기에서 LogItem의 값을 logId로 값을 구분해 전달하면 (map으로 순회하면서 가지고있는 모든 로그)
>LogItem에서 해당 로그를 띄워준다.
let timeOffset = new Date(Date.now() - Number(logItem.logTimestamp));
const showOffsetTime = `
${timeOffset.getMinutes() > 0 ? `${timeOffset.getMinutes()}m` : ""}
${timeOffset.getSeconds() > 0 ? `${timeOffset.getSeconds()}s ago` : ""}
${timeOffset.getSeconds() === 0 ? `just now` : ""}
`;
timeOffset 형태 : `Thu Jan 01 1970 09:00:20 GMT+0900 (한국 표준시)`
showOffsetTiem 형태 : `4m 12s ago`
게시판 삭제
하나만 있을때 > 삭제 불가
두개 이상 있을때 > 삭제 가능
게시판 개수만큼 boardArray에 지운다.
//App.tsx
const handleDeleteBoard = () => {
if (boards.length > 1) {
dispatch(deleteBoard({ boardId: getActiveBoard.boardId }));
dispatch(
addLog({
logId: v4(),
logMessage: `게시판 지우기 : ${getActiveBoard.boardName}`,
logAuthor: "User",
logTimestamp: String(Date.now()),
})
);
const newIndeToSet = () => {
const indexToBeDelete = boards.findIndex(
(board) => board.boardId === activeBoardId
);
return indexToBeDelete === 0
? indexToBeDelete + 1
: indexToBeDelete - 1;
};
setActiveBoardId(boards[newIndeToSet()].boardId);
} else {
alert("최소 게시판 개수는 한 개 입니다.");
}
};
//boardsSlice.ts
deleteBoard: (state, { payload }: PayloadAction<TDeleteBoardAction>) => {
state.boardArray = state.boardArray.filter(
(board) => board.boardId !== payload.boardId
);
},
`newIndexToSet()` 함수로 지워야할 게시물board 인덱스를 찾아서 > 0이면 뒤의 인덱스 활성화, 작으면 앞의 인덱스를 활성화 시킨다.
☑️ 배운 점