기존 등록된 일정과 추가/수정할 일정의 시간이 겹치지 않도록 로직을 짰는데, 수정모드일 경우 현재 수정중인 데이터는 비교할 데이터에서 제외해야 한다는걸 깜빡했다.
생각정리
- 수정모드와 등록모드에서 비교할 배열을 각각 따로만들기 (수정모드만 만들면됨)
- Edit의 부모쪽에서 데이터 가공해서 보내주기(calendarData fiter로 !== 해서 내려줘서)
- 수정 등록 모드별로 다르게 적용하면 안될까? → 근데 이 수정/등록 모드를 어떻게 구별해서 나눌건데? (같은 컴포넌트 사용하는 중)
- 부모에서 각각 mode=“create” / mode=“edit” 모드를 다르게 줘서 조건문 처리 해보자
구현과정
① 수정모드에서 시간 비교할 데이터 배열 만들기
수정과 등록 두 부모컴포넌트 모두 calendarData 를 가지고있고 수정모드에서는 선택된 데이터도 이미 가지고 있으므로 filter 메서드로 선택된 데이터를 제외한 일정 리스트를 만들주었다.
// 전체일정에서 수정중인 일정 제외한 리스트
const existTimeWithoutEdit = calendarData?.filter(
(data) => data.calendar_id !== event.calendar_id,
);
② 수정 / 등록 부모컴포넌트에서 props로 모드를 전달
일정등록 폼인 CreateEventForm 에 mode="create" / mode="edit" props 각각 전달
// 일정 등록 부모 컴포넌트
<CreateEventForm
studyId={studyId}
eventDate={eventDate}
deleteForm={closeForm}
calendarData={data}
mode="create"
/>
// 일정 수정 부모 컴포넌트
<CreateEventForm
studyId={event.study_id}
eventDate={event.event_date}
deleteForm={handleDelete}
setIsEdit={setIsEdit}
initialData={{
calendarId: event.calendar_id,
description: event.event_description,
startTime: event.start_time,
endTime: event.end_time,
}}
calendarData={calendarData}
withoutEditData={existTimeWithoutEdit}
mode="edit"
/>
CreateEventForm 컴포넌트는 모드를 mode: "create" | "edit" 받아서 selectTime 컴포넌트로 전달
// CreateEventForm 컴포넌트
interface CreateEventFormProps {
studyId: string;
eventDate: string;
deleteForm: () => void;
setIsEdit?: React.Dispatch<React.SetStateAction<boolean>>;
initialData?: {
calendarId: string;
description: string;
startTime: string;
endTime: string;
};
calendarData: Tables<"calendar">[] | undefined;
withoutEditData?: Tables<"calendar">[];
mode: "create" | "edit";
}
<SelectTime
onTimeSelect={handleTimeSelect}
onClose={() => {
setIsModalOpen(false);
setActiveInput(null);
}}
eventStart={eventStart}
eventEnd={eventEnd}
selectingType={activeInput === "start" ? "start" : "end"}
calendarData={calendarData}
withoutEditData={withoutEditData}
mode={mode}
/>
③ create / edit 조건 별로 데이터 가공 및 적용할 함수 생성
// 기존 일정의 시간데이터 가공(등록 모드)
const existTimeRanges = calendarData?.map((event) => ({
start: convertTimeToMinutes(event.start_time.slice(0, -3)),
end: convertTimeToMinutes(event.end_time.slice(0, -3)),
}));
// 기존 일정의 시간데이터 가공(수정 모드)
const existTimeRangesWithoutEdit = withoutEditData?.map((event) => ({
start: convertTimeToMinutes(event.start_time.slice(0, -3)),
end: convertTimeToMinutes(event.end_time.slice(0, -3)),
}));
// 선택된 시간이 이미 존재하는지 확인하는 함수(등록 모드)
const checkTimeExist = (selectedMinutes: number) => {
for (const timeRange of existTimeRanges!) {
if (selectingType === "start") {
if (
selectedMinutes === timeRange.start ||
(selectedMinutes > timeRange.start && selectedMinutes < timeRange.end)
) {
return true;
}
} else {
if (
selectedMinutes > timeRange.start &&
selectedMinutes < timeRange.end
) {
return true;
}
}
}
return false;
};
// 선택된 시간이 이미 존재하는지 확인하는 함수(등록 모드)
const checkTimeExistWithoutEdit = (selectedMinutes: number) => {
for (const timeRange of existTimeRangesWithoutEdit!) {
if (selectingType === "start") {
if (
selectedMinutes === timeRange.start ||
(selectedMinutes > timeRange.start && selectedMinutes < timeRange.end)
) {
return true;
}
} else {
if (
selectedMinutes > timeRange.start &&
selectedMinutes < timeRange.end
) {
return true;
}
}
}
return false;
};
④ 조건별 유효성 적용
// 확인&유효성(시작시간 < 종료시간)
const handleConfirm = () => {
const selectedTime = `${selectedHour}:${selectedMinute}`;
const selectedMinutes = convertTimeToMinutes(selectedTime);
if (mode === "create" && checkTimeExist(selectedMinutes)) {
alert("등록된 일정 중 겹치는 시간이 있습니다! 확인해주세요!");
return;
}
if (mode === "edit" && checkTimeExistWithoutEdit(selectedMinutes)) {
alert("등록된 일정 중 겹치는 시간이 있습니다! 확인해주세요!");
return;
}
if (selectingType === "start" && eventEnd) {
const endMinutes = convertTimeToMinutes(eventEnd);
if (selectedMinutes >= endMinutes) {
alert("시작 시간이 종료 시간보다 늦을 수 없습니다! 다시 확인해주세요!");
return;
}
}
if (selectingType === "end" && eventStart) {
const startMinutes = convertTimeToMinutes(eventStart);
if (selectedMinutes <= startMinutes) {
alert("종료 시간이 시작 시간보다 빠를 수 없습니다! 다시 확인해주세요!");
return;
}
}
onTimeSelect(selectedTime);
onClose();
};
결과
이제 수정모드일때는 수정중인 일정을 제외한 일정들과 비교를 한다!
🧐 느낀점
여러 유효성들을 적용하면서 처음에는 이것들을 어떻게 다 처리해줘야하지.. 감이 안잡혔다. 시간이 좀 걸렸지만 어떻게든 구현하고 하다보니 오늘같이 이런 추가적인 부분은 생각보다 금방 처리했다. 작업을 어떻게 해줄지 하나하나 생각을 정리하고 그에맞게 로직 작성과 테스트를 반복했다. 중복되는 코드들은 리팩토링해야하지만, 의도한대로 잘 적용되는 모습을 보니 꽤 뿌듯했다.
앞으로 더 효율적인 방향으로 생각하고 코드에도 적용하고 싶다. 결국 많이 많이 경험해보는게 중요한 것 같다.
'TIL' 카테고리의 다른 글
[Refactoring] 바텀시트 재사용 컴포넌트로 분리하기 (0) | 2024.11.05 |
---|---|
댓글&답글 삭제 유효성 적용하기 (1) | 2024.11.04 |
캘린더 일정관리 - 일정 시간 중복 체크 유효성 ① (0) | 2024.11.01 |
캘린더 일정관리 - 시작시간 / 종료시간 유효성 (0) | 2024.10.31 |
모의면접 ② (1) | 2024.10.30 |