원티드 프리온보딩 프론트엔드 개발자 교육과정 중 일정 등록할 때 이미 등록된 일정이 있을 경우 중복된 일정인지 검사해주는 구현 사항이 있었다. 프로젝트 진행 과정 중에는 구현하지 못했지만 과정이 끝나고 리팩토링을 진행하면서 중복 방지 기능 구현을 해보았다.
일정 리스트 UI
일정 추가 form UI
시간을 숫자로 변경하고 중복된 시간의 수 인지 비교하여 검사하는 로직으로 구현
AddForm.tsx 저장 버튼 눌렀을 때 실행되는 함수
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
const startTimeStr = `${times.hour}:${times.minute}`;
const submitDate = new Date(`${today} ${startTimeStr}`);
const { startTime, endTime } = submitTime(submitDate, times.meridiem);
days.map((day: string) => {
const newSchedule: ScheduleTypes = {
day: day,
start: `${startTime} ${times.meridiem}`,
end: `${endTime} ${times.meridiem}`,
};
// TODO: any 제거
const yoilData: any = data?.filter(
(day: any) => day.day === newSchedule.day
);
const isDuplicate: boolean = duplicateTime(newSchedule, yoilData);
if (isDuplicate) {
mutate(newSchedule);
alert("일정이 추가되었습니다.");
navigate("/view");
} else {
setPopupOpen(true);
}
});
};
시간 변환 파일 분리
import { add, format } from "date-fns";
export const submitTime = (time: Date, meridiem: string) => {
const startAddTime = add(time, {
hours: meridiem === "pm" ? 12 : 0,
});
const endAddTime = add(time, {
hours: meridiem === "pm" ? 12 : 0,
minutes: CLASSTIME,
});
const startTime = format(startAddTime, "HH:mm");
const endTime = format(endAddTime, "HH:mm");
return { startTime, endTime };
};
중복 검사 훅으로 분리
param - 등록할 시간, yoilData(체크된 요일에 대한 기존 데이터)
export const duplicateTime = (
input: ScheduleTypes,
times: ScheduleTypes[]
) => {
let isDuplicate = true;
const inputMridiem = getMridiem(input.start);
const inputStartTime = timeToNumber(input.start, inputMridiem);
const inputEndTime = timeToNumber(input.end, inputMridiem);
times &&
Object.values(times).map((time: ScheduleTypes) => {
const timeMridiem = getMridiem(time.start);
const startTime = timeToNumber(time.start, timeMridiem);
const endTime = timeToNumber(time.end, timeMridiem);
if (
inputMridiem === timeMridiem &&
inputStartTime > Math.floor(startTime - CLASSTIME) &&
inputEndTime < Math.floor(endTime + CLASSTIME)
) {
isDuplicate = false;
}
});
return isDuplicate;
};
function timeToNumber(time: string, mridiem: string) {
const str = Number(time.split(" ")[0].replace(":", ""));
const result = mridiem === "pm" ? Math.floor(str + 1200) : str;
return result;
}
function getMridiem(time: string) {
const str = time.split(" ")[1];
return str;
}
hook, typescript any로 넣어진 부분 수정, 중복 검사 다른 로직 고민