diff --git a/src/RoomDetail/components/RoomCalendar.tsx b/src/RoomDetail/components/RoomCalendar.tsx index c6a38826..a6a8ca72 100644 --- a/src/RoomDetail/components/RoomCalendar.tsx +++ b/src/RoomDetail/components/RoomCalendar.tsx @@ -1,65 +1,67 @@ +import { MouseEvent, useRef, useContext } from 'react'; import clsx from 'clsx'; +import { twMerge } from 'tailwind-merge'; +import { makeWeekCalendar } from '../utils/utils'; +import { DAY_OF_THE_WEEK } from '../constants/constant'; +import { DateRoomDetailContext } from './RoomDetailProvider'; import { Icon } from '@/shared/Icon'; +import { Toast } from '@/shared/Toast'; -const calendar = [ - { - day: '월', - date: '8', - bug: true, - point: false - }, - { - day: '화', - date: '9', - bug: true, - point: false - }, - { - day: '수', - date: '10', - bug: false, - point: false - }, - { - day: '목', - date: '11', - bug: true, - point: true - }, - { - day: '금', - date: '12', - bug: true, - point: false - }, - { - day: '토', - date: '13', - bug: false, - point: false - }, - { - day: '일', - date: '14', - bug: true, - point: false - } -]; +interface RoomCalendarProps { + certifiedDates: string[]; + certifyTime: number; + serverTime: Date; +} + +const RoomCalendar = ({ + certifiedDates, + certifyTime, + serverTime +}: RoomCalendarProps) => { + const dateRef = useRef(null); + const { selectDate, date: chooseDate } = useContext(DateRoomDetailContext); + + const { thisWeekTimestamp } = makeWeekCalendar(serverTime); + const chooseDateTimestamp = `${chooseDate.getFullYear()}-${ + chooseDate.getMonth() + 1 + }-${chooseDate.getDate()}`; + + const handleDateClick = (e: MouseEvent) => { + if (e.target !== dateRef.current) { + return; + } + + selectDate(new Date()); + }; -const RoomCalendar = () => { return (

2023년 10월

-
- {calendar.map(({ day, date, point, bug }) => { +
+ {thisWeekTimestamp.map((thisDate) => { + const date = thisDate.getDate(); + const day = thisDate.getDay(); + const thisDateTimestamp = `${thisDate.getFullYear()}-${ + thisDate.getMonth() + 1 + }-${date}`; + const langKoDay = DAY_OF_THE_WEEK[day]; + const bug = certifiedDates.find((el) => el === thisDateTimestamp); + const RoomCalendarStyle = { - calendarItem: clsx( - 'flex h-[5.87rem] w-[3.12rem] flex-col items-center rounded-[0.62rem] pt-1 text-center ', - { - 'border-light-point text-light-point dark:border-dark-point dark:text-dark-point border-[0.06rem]': - point === true, - 'text-darkGray': point === false - } + calendarItem: twMerge( + clsx( + 'relative flex h-[5.87rem] w-[3.12rem] cursor-default flex-col items-center pt-1 text-center', + { + 'text-dark-gray': serverTime.getTime() < thisDate.getTime(), + 'text-black': serverTime.getTime() >= thisDate.getTime(), + 'rounded-[0.62rem] border-light-point text-light-point dark:border-dark-point dark:text-dark-point border-[0.06rem]': + thisDateTimestamp === chooseDateTimestamp + } + ) ) }; @@ -67,8 +69,38 @@ const RoomCalendar = () => {
{ + const routineLimitTime = new Date(serverTime); + routineLimitTime.setHours(certifyTime); + routineLimitTime.setMinutes(50); + + if (serverTime.getTime() >= thisDate.getTime()) { + selectDate(thisDate); + + if ( + thisDate.getDate() === routineLimitTime.getDate() && + serverTime.getTime() < routineLimitTime.getTime() + ) { + Toast.show( + { + message: '인증 시간 이후 확인 가능합니다', + status: 'info' + }, + 2000 + ); + } + } else { + Toast.show( + { + message: '조회가 가능하지 않은 날짜입니다', + status: 'info' + }, + 2000 + ); + } + }} > -
{day}
+
{langKoDay}
{date}
{bug && ( diff --git a/src/RoomDetail/components/RoomDetailContainer.tsx b/src/RoomDetail/components/RoomDetailContainer.tsx new file mode 100644 index 00000000..462f28ad --- /dev/null +++ b/src/RoomDetail/components/RoomDetailContainer.tsx @@ -0,0 +1,47 @@ +import { useContext } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import { roomOptions } from '@/core/api/options'; +import { DateRoomDetailContext } from './RoomDetailProvider'; +import { RoomInfo, RoomWorkspace } from '@/RoomDetail'; +import { RoomInfo as RoomInfoType } from '@/core/types/Room'; +interface RoomDetailContainerProps { + roomDetailData: RoomInfoType; + serverTime: Date; +} + +const RoomDetailContainer = ({ + roomDetailData, + serverTime +}: RoomDetailContainerProps) => { + const { date } = useContext(DateRoomDetailContext); + const roomId = '1234'; + const chooseDate = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`; + + const { data: roomDetailDataByDate, status } = useQuery({ + ...roomOptions.detailByDate(roomId, chooseDate) + }); + + if (roomDetailDataByDate) { + roomDetailData = roomDetailDataByDate; + } + + return ( + <> +
+ +
+
+ +
+ + ); +}; + +export default RoomDetailContainer; diff --git a/src/RoomDetail/components/RoomDetailProvider.tsx b/src/RoomDetail/components/RoomDetailProvider.tsx new file mode 100644 index 00000000..9971bd24 --- /dev/null +++ b/src/RoomDetail/components/RoomDetailProvider.tsx @@ -0,0 +1,38 @@ +import { ReactNode, useState, createContext } from 'react'; + +export const DateRoomDetailContext = createContext<{ + date: Date; + selectDate: (value: Date) => void; +}>({ + date: new Date(), + selectDate: (value: Date) => { + return value; + } +}); + +interface RoomDetailProviderProps { + children: ReactNode; + serverTime: Date; +} + +const RoomDetailProvider = ({ + children, + serverTime +}: RoomDetailProviderProps) => { + const [changedDate, setChangeDate] = useState(serverTime); + + return ( + { + setChangeDate(dateValue); + } + }} + > + {children} + + ); +}; + +export default RoomDetailProvider; diff --git a/src/RoomDetail/components/RoomInfo.tsx b/src/RoomDetail/components/RoomInfo.tsx index e523adc1..83f7872e 100644 --- a/src/RoomDetail/components/RoomInfo.tsx +++ b/src/RoomDetail/components/RoomInfo.tsx @@ -2,19 +2,28 @@ import RoomMemberRank from './RoomMemberRank'; import { ProgressBar } from '@/shared/ProgressBar'; import { RoomInfo as RoomInfoType } from '@/core/types/Room'; +interface extendedProps { + status: 'pending' | 'error' | 'success'; +} +type RoomInfoProps = extendedProps & RoomInfoType; const RoomInfo = ({ level, currentUserCount, maxUserCount, todayCertificateRank, - certifyTime -}: RoomInfoType) => { + certifyTime, + status +}: RoomInfoProps) => { return ( -
- +
+ {status !== 'success' ? ( +
임시 Loading...
+ ) : ( + + )}
diff --git a/src/RoomDetail/components/RoomWorkspace.tsx b/src/RoomDetail/components/RoomWorkspace.tsx index cdba4255..24331469 100644 --- a/src/RoomDetail/components/RoomWorkspace.tsx +++ b/src/RoomDetail/components/RoomWorkspace.tsx @@ -6,11 +6,22 @@ import { BottomSheet, useBottomSheet } from '@/shared/BottomSheet'; import { Tab, TabItem } from '@/shared/Tab'; import { RoomInfo } from '@/core/types/Room'; +interface extendedProps { + status: 'pending' | 'error' | 'success'; + serverTime: Date; +} + +type RoomWorkspaceProps = extendedProps & RoomInfo; + const RoomWorkspace = ({ completePercentage, routine, - todayCertificateRank -}: RoomInfo) => { + todayCertificateRank, + certifiedDates, + certifyTime, + status, + serverTime +}: RoomWorkspaceProps) => { const { bottomSheetProps, toggle, close } = useBottomSheet(); const myCertificationImage = todayCertificateRank.find( @@ -45,12 +56,22 @@ const RoomWorkspace = ({ defaultIndex={0} > - - - + {status !== 'success' ? ( +
임시 Loading...
+ ) : ( + <> + + + + )}
-
- -
-
- -
+ + +
); };