마감 날짜 0일이라고 뜨는 거 어떻게 수정하죠?
아마 달력 알고리즘을 건드려야 하나?
지금은 달력 알고리즘에서 날짜를 채우기 전에 default 값으로 0으로 채워놨기 때문에 이런 일이 발생하는 것이다.
그럼 처음에 null이나 ""으로 default값을 설정하면 안되나? 일단 시도해보자.
const dates: (number | null)[][] = [...Array(6)].map((_) =>
[...Array(7)].map(() => null),
);
이렇게 했더니 type 오류 잔뜩 난다.
숫자가 아니라 null 값이 들어갈 수도 있는데 +1을 하면 어떻게 해!!!라고 혼나는 중;;
아니 근데 잠깐만;; 이거 고칠 때가 아닌 것 같은데?
setStartDate: (state, action: PayloadAction<ReservationProps>) => {
const today = new Date();
if (
action.payload.startDate &&
action.payload.startDate?.year >= today.getFullYear() &&
action.payload.startDate?.month >= today.getMonth() + 1 &&
action.payload.startDate?.date >= today.getDate()
) {
state.startDate = action.payload.startDate;
} else {
return;
}
},
store 로직을 보니까 setEndDate 처럼 로직이 case 별로 세분화되어 있지 않다.
고치면 되겠지?
헷갈리니까 수도 코딩을 좀 하자.
일단 시작 날짜가 있어야 한다.
1) 오늘 날짜보다 연도가 큰 케이스
2) 오늘 날짜와 연도가 같고 월이 더 큰 케이스
3) 오늘 날짜와 연도/월이 같도 일이 같거나 큰 케이스
setStartDate: (state, action: PayloadAction<ReservationProps>) => {
const today = new Date();
if (
(action.payload.startDate &&
action.payload.startDate?.year > today.getFullYear()) ||
(action.payload.startDate?.year === today.getFullYear() &&
action.payload.startDate?.month > today.getMonth() + 1) ||
(action.payload.startDate?.year === today.getFullYear() &&
action.payload.startDate?.month === today.getMonth() + 1 &&
action.payload.startDate?.date >= today.getDate())
) {
state.startDate = action.payload.startDate;
} else {
return;
}
},
고쳤다!
근데 store 조건을 나타내는 코드가 너무 지저분하다.
이제 중간 리팩토링을 좀 하자.
import { configureStore, createSlice, PayloadAction } from '@reduxjs/toolkit';
type ReservationProps = {
startDate: { year: number; month: number; date: number } | null;
endDate: { year: number; month: number; date: number } | null;
};
const initialReservationState: ReservationProps = {
startDate: null,
endDate: null,
};
export const reservation = createSlice({
name: 'reservationReducer',
initialState: initialReservationState,
reducers: {
setStartDate: (state, action: PayloadAction<ReservationProps>) => {
const newStart = action.payload.startDate;
if (!newStart) return;
const newStartYear = newStart.year;
const newStartMonth = newStart.month;
const newStartDate = newStart.date;
const today = new Date();
const todaysYear = today.getFullYear();
const todaysMonth = today.getMonth() + 1;
const todaysDate = today.getDate();
if (
newStartYear > todaysYear ||
(newStartYear === todaysYear && newStartMonth > todaysMonth) ||
(newStartYear === todaysYear &&
newStartMonth === todaysMonth &&
newStartDate >= todaysDate)
) {
state.startDate = newStart;
}
},
setEndDate: (state, action: PayloadAction<ReservationProps>) => {
const newEnd = action.payload.endDate;
if (!newEnd) return;
const newEndYear = newEnd.year;
const newEndMonth = newEnd.month;
const newEndDate = newEnd.date;
const currentStart = state.startDate;
if (!currentStart) return;
const currentStartYear = currentStart.year;
const currentStartMonth = currentStart.month;
const currentStartDate = currentStart.date;
if (
currentStartYear < newEndYear ||
(currentStartYear === newEndYear && currentStartMonth < newEndMonth) ||
(currentStartYear === newEndYear &&
currentStartMonth === newEndMonth &&
currentStartDate <= newEndDate)
) {
state.endDate = newEnd;
}
},
clearReservationDates: () => {
return initialReservationState;
},
},
});
export const reservationStore = configureStore({
reducer: reservation.reducer,
});
export const { setStartDate, setEndDate } = reservation.actions;
정리를 해보고나니 조건이 생각보다 간단했다.
예약 시작 날짜는 오늘 날짜보다만 같거나 크도록 하면 되는 것이었고,
예약 마감 날짜는 시작 날짜보다만 같거나 크도록 하면 되는 것이었다.
아 말로 하면 쉽지! ㅋㅋㅋㅋㅋ
여튼 교훈은 코드가 복잡한 상태에서 버그가 잔뜩 껴있을 때는 수도코딩과 중간 리팩토링이 필수라는 것!
이렇게 코드를 정리하고 나니 날짜가 0일 때 return만 해주면 되겠다는 생각이 금방 들었다.
setStartDate: (state, action: PayloadAction<ReservationProps>) => {
const newStart = action.payload.startDate;
if (!newStart || !newStart.date) return;
const newStartYear = newStart.year;
const newStartMonth = newStart.month;
const newStartDate = newStart.date;
const today = new Date();
const todaysYear = today.getFullYear();
const todaysMonth = today.getMonth() + 1;
const todaysDate = today.getDate();
if (
newStartYear > todaysYear ||
(newStartYear === todaysYear && newStartMonth > todaysMonth) ||
(newStartYear === todaysYear &&
newStartMonth === todaysMonth &&
newStartDate >= todaysDate)
) {
state.startDate = newStart;
}
},
setEndDate: (state, action: PayloadAction<ReservationProps>) => {
const newEnd = action.payload.endDate;
if (!newEnd || !newEnd.date) return;
const newEndYear = newEnd.year;
const newEndMonth = newEnd.month;
const newEndDate = newEnd.date;
const currentStart = state.startDate;
if (!currentStart) return;
const currentStartYear = currentStart.year;
const currentStartMonth = currentStart.month;
const currentStartDate = currentStart.date;
if (
currentStartYear < newEndYear ||
(currentStartYear === newEndYear && currentStartMonth < newEndMonth) ||
(currentStartYear === newEndYear &&
currentStartMonth === newEndMonth &&
currentStartDate <= newEndDate)
) {
state.endDate = newEnd;
}
},
예이!!!!!!
이제 눈에 보이는 버그들과 문제들은 모두(?) 해결이 된 듯? 하다.
아직 예약 시작 날짜 / 예약 마감 날짜 텍스트가 날짜를 클릭했을 때 밀려 올라가는 현상 + 날짜를 뭘 클릭하는지에 따라 텍스트가 흔들리는 상황이 발생하고 있지만, 이건 더 중요한 로직들을 처리한 후 나중에 손 봐야겠다.
더 이상의 버그나 의도치 않은 상황이 생길지는 팀원분들의 확인 + 테스트 코드를 작성해봐야 알 듯 하다.
이제 유저가 선택한 예약 시작 날짜와 예약 마감 날짜 사이의 날짜들에 남색 배경을 줘보자.
예약 시작 날짜 클릭 시: 예약 시작 날짜 하나만 민트색 배경 지정
예약 마감 날짜 클릭 시: 예약 시작 날짜부터 예약 마감 날짜 사이의 모든 날짜들에 민트색 배경을 지정
오오 첫 스타트 아주 좋아
예약 시작 날짜 클릭 시 예약 시작 날짜 하나만 남색 배경 지정하기 성공!
export const EachDate = styled.th<EachDatesProps>`
.
.
.
(중략)
background-color: ${(props) => {
const start = useSelector(
(state: RootState) => state.reservation.startDate,
);
return start?.year === props.today.year &&
start?.month === props.today.month &&
start?.date === Number(props.children)
? colorPalette.deepMintColor
: 'white';
}};
`;
근데 예약 마감 날짜 클릭 시 예약 시작 날짜부터 예약 마감 날짜까지 전부 민트색으로 표시해야 되는데 이거 어찌하지?
조건 뭐라고 줘야하지? 두뇌 풀가동 🧠
이럴 때는 수도 코딩을 하라고 내 자신한테 그랬었지?
....
막막..하다...
.....
할 수 있다!
...
....
막막..하다...
.....
할 수 있다!
...
케이스 별로 나눠서 생각해보자. 이것이 바로 컴퓨테이셔널 띵킹!!!??
1) 예약 시작 날짜와 예약 마감 날짜의 연도가 같은 경우
2) 예약 시작 날짜보다 예약 마감 날짜의 연도가 더 큰 경우
천리길도 한 걸음부터!!
연도도 같고 월도 같을 때 유저가 클릭한 날짜의 배경색을 지정
background-color: ${(props) => {
const start = useSelector(
(state: RootState) => state.reservation.startDate,
);
const end = useSelector((state: RootState) => state.reservation.endDate);
const startYear = start?.year;
const startMonth = start?.month;
const startDate = start?.date;
const endYear = end?.year;
const endMonth = end?.month;
const endDate = end?.date;
if (start && !end) {
return startYear === props.today.year &&
startMonth === props.today.month &&
startDate === Number(props.children)
? colorPalette.deepMintColor
: 'white';
}
if (startDate && endDate) {
if (startYear === endYear) {
if (startMonth === endMonth) {
return startYear === props.today.year &&
startMonth === props.today.month &&
startDate <= Number(props.children) &&
endDate >= Number(props.children)
? colorPalette.deepMintColor
: 'white';
}
}
}
}};
`;
물론 아직 예약 시작 날짜와 예약 마감 날짜의 월이 다르면 적용이 안된다.
조건 추가!!! ㄱㄱ!!!!!
background-color: ${(props) => {
const start = useSelector(
(state: RootState) => state.reservation.startDate,
);
const end = useSelector((state: RootState) => state.reservation.endDate);
const startYear = start?.year;
const startMonth = start?.month;
const startDate = start?.date;
const endYear = end?.year;
const endMonth = end?.month;
const endDate = end?.date;
if (start && !end) {
return startYear === props.today.year &&
startMonth === props.today.month &&
startDate === Number(props.children)
? colorPalette.deepMintColor
: 'white';
}
if (startDate && endDate) {
if (startYear === endYear) {
if (startMonth === endMonth) {
return startYear === props.today.year &&
startMonth === props.today.month &&
startDate <= Number(props.children) &&
endDate >= Number(props.children)
? colorPalette.deepMintColor
: 'white';
} else {
return ((startYear === props.today.year &&
startMonth === props.today.month &&
startDate <= Number(props.children)) ||
(endYear === props.today.year &&
endMonth === props.today.month &&
endDate >= Number(props.children))) &&
Number(props.children) !== 0
? colorPalette.deepMintColor
: startMonth &&
endMonth &&
endMonth - startMonth > 1 &&
props.today.month > startMonth &&
props.today.month < endMonth &&
Number(props.children) !== 0
? colorPalette.deepMintColor
: 'white';
}
}
}
}};
`;
했다 ㅠㅠㅠㅠㅠ 감격 ㅠㅠㅠㅠㅠㅠ
근데 아직 연도 다를 때도 구현 남음.
function Router() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<MainPage />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/itemlist/:categoryId" element={<ItemListPage />} />
<Route path="/booking/:itemId" element={<BookingPage />} />
<Route path="/mypage" element={<MyPage />} />
<Route path="/detail/:itemId" element={<DetailPage />} />
<Route path="/create" element={<CreatePage />} />
<Route path="/update/:itemId" element={<UpdatePage />} />
<Route path="/chatting" element={<ChattingPage />} />
</Routes>
</BrowserRouter>
);
}
export default Router;
카테고리별 페이지에서 카테고리 아이디가 path에 들어가서 구분이 되도록
예약 페이지에서 아이템 id를 useParams로 잡아서 서버에 요청할 수 있도록
게시물 상세 페이지와 수정 페이지에서 아이템 id가 path에 포함되도록
라우터를 변경했다.
추후 카카오 로그인 구현이 완성되면 Private 라우터를 생성할 예정이다.