diff --git a/src/components/addTime/calendar/index.tsx b/src/components/addTime/calendar/index.tsx index a9ad8a3..ed3900d 100644 --- a/src/components/addTime/calendar/index.tsx +++ b/src/components/addTime/calendar/index.tsx @@ -32,8 +32,12 @@ const Calendar = ({ const [date, setDate] = useState(new Date()); + // date: 현재 캘린더에 보이는 날짜들 (react-calendar) + // return: class name (string) const addTileClassName = ({ date }: { date: Date }) => { + // 일정 등록이 가능한 날짜인 경우 if (dates.indexOf(dayjs(date).format('YYYY-MM-DD')) !== -1) { + // 선택된 날짜인 경우 if (selected.indexOf(dayjs(date).format('YYYY-MM-DD 00:00')) !== -1) { return `selected valid availableDate${dayjs(date).format( 'YYYY-MM-DD' @@ -47,17 +51,12 @@ const Calendar = ({ }; useEffect(() => { - const index = selected.indexOf(`${dayjs(date).format('YYYY-MM-DD')} 00:00`); - const element = document.querySelector( `.availableDate${dayjs(date).format('YYYY-MM-DD')}` ) as HTMLElement; if (element) { - if (index === -1) { - element.classList.add('selected'); - setSelected([...selected, `${dayjs(date).format('YYYY-MM-DD')} 00:00`]); - } else { + if (selected.includes(`${dayjs(date).format('YYYY-MM-DD')} 00:00`)) { element.classList.remove('selected'); setSelected( selected.filter( @@ -65,6 +64,9 @@ const Calendar = ({ availableDate !== `${dayjs(date).format('YYYY-MM-DD')} 00:00` ) ); + } else { + element.classList.add('selected'); + setSelected([...selected, `${dayjs(date).format('YYYY-MM-DD')} 00:00`]); } } }, [date]); diff --git a/src/components/addTime/table/index.tsx b/src/components/addTime/table/index.tsx index 0b6d8a1..228e026 100644 --- a/src/components/addTime/table/index.tsx +++ b/src/components/addTime/table/index.tsx @@ -17,6 +17,11 @@ import { } from './index.styles'; import { TableType } from '../tableArea/index.types'; +interface ValidDateType { + date: string; + isValidDate: boolean; +} + const Table = ({ contentRef, selected, @@ -28,12 +33,12 @@ const Table = ({ isResetButtonClick, setIsResetButtonClick, }: TableType) => { - const timeDetail = getTimeArray(times); - const selectoRef = useRef(null); + const timeDetail = getTimeArray(times); useEffect(() => { if (selected[tablePage]) { + // 등록했던 일정을 수정할 경우 className 제거하는 과정 필요 const selectedElements = document.querySelectorAll('.selected'); selectedElements.forEach((element) => { element.classList.remove('selected'); @@ -44,40 +49,48 @@ const Table = ({ element?.classList.add('selected'); }); + // 페이지 진입 시 이전에 선택했던 칸에 선택 표시 selectoRef.current.setSelectedTargets( selected[tablePage].map((id) => document.getElementById(id)) ); } }, [tablePage, selected]); + // 시간 선택 방법을 토글하면 선택한 항목 초기화 useEffect(() => { selectoRef.current.setSelectedTargets([]); setIsResetButtonClick(false); }, [selectedMethod, isResetButtonClick]); + // Selecto 컴포넌트에 전달할 onSelect 핸들러 const handleCellSelect = (e: any) => { if (e.inputEvent.type !== 'touchstart') { - e.added.forEach((el: any) => { + e.added.forEach((el: HTMLElement) => { el.classList.add('selected'); }); - e.removed.forEach((el: any) => { + e.removed.forEach((el: HTMLElement) => { el.classList.remove('selected'); }); } }; const addSelectedToObject = () => { + // 현재 table page에서 선택된 시간 const newArr: string[] = Array.from( document.querySelectorAll('.selected') ).map((node: Element) => node.id); + // key: table page + // value: 각 table page에서 선택된 시간 배열 const newObj = { ...selected }; + newObj[tablePage] = newArr; setSelected(newObj); }; + // 한 칸씩 클릭해서 선택할 경우 const handleClickOneElement = ( e: React.MouseEvent | React.TouchEvent ) => { @@ -102,7 +115,7 @@ const Table = ({ {validDateChunks[tablePage].map( - ({ date, isValidDate }: { date: string; isValidDate: boolean }) => + ({ date, isValidDate }: ValidDateType) => date.slice(0, 5) === 'blank' ? ( ) : ( @@ -122,7 +135,7 @@ const Table = ({ {validDateChunks[tablePage]?.map( - ({ date, isValidDate }: { date: string; isValidDate: boolean }) => ( + ({ date, isValidDate }: ValidDateType) => ( { - validDateChunks.map((chunk, index) => { - chunk.map((date) => { - if (date.date.slice(0, 10) === time.slice(0, 10)) { - if (newObj[index] === undefined) { - newObj[index] = [time]; + data.availableDateTimes.forEach((date: string) => { + validDateChunks.map((chunk, tablePage) => { + chunk.map((item) => { + if (item.date.slice(0, 10) === date.slice(0, 10)) { + if (newObj[tablePage]) { + newObj[tablePage].push(date); } else { - newObj[index].push(time); + newObj[tablePage] = [date]; } } }); diff --git a/src/components/addTime/tooltip/index.tsx b/src/components/addTime/tooltip/index.tsx index 33fd876..e22682d 100644 --- a/src/components/addTime/tooltip/index.tsx +++ b/src/components/addTime/tooltip/index.tsx @@ -8,9 +8,14 @@ import { import guideIcon from '@/assets/icons/guide.png'; import guideHandle from '@/assets/icons/guideHandle.png'; import closeIcon from '@/assets/icons/close.png'; -import { useCallback } from 'react'; +import { Dispatch, SetStateAction, useCallback } from 'react'; -const Tooltip = ({ isTooltipShown, setIsTooltipShown }: any) => { +interface Props { + isTooltipShown: boolean; + setIsTooltipShown: Dispatch>; +} + +const Tooltip = ({ isTooltipShown, setIsTooltipShown }: Props) => { const handleGuideCloseClick = useCallback(() => { localStorage.setItem('isTooltipShown', JSON.stringify(false)); setIsTooltipShown(false); diff --git a/src/components/createRoom/calendar/index.tsx b/src/components/createRoom/calendar/index.tsx index 2887811..1932160 100644 --- a/src/components/createRoom/calendar/index.tsx +++ b/src/components/createRoom/calendar/index.tsx @@ -1,4 +1,10 @@ -import { useCallback, useEffect, useState } from 'react'; +import { + Dispatch, + SetStateAction, + useCallback, + useEffect, + useState, +} from 'react'; import { DateObject, getAllDatesInRange } from 'react-multi-date-picker'; import { CalendarComponent, @@ -9,8 +15,8 @@ import Toggle from '../toggle'; interface Calendar { dates: string[]; - setDates: React.Dispatch>; - setMonth: React.Dispatch>; + setDates: Dispatch>; + setMonth: Dispatch>; } const Calendar = ({ dates, setDates, setMonth }: Calendar) => { diff --git a/src/components/current/shareLinkBottomSheet/index.tsx b/src/components/current/shareLinkBottomSheet/index.tsx index 1e24a6f..1ec8ed7 100644 --- a/src/components/current/shareLinkBottomSheet/index.tsx +++ b/src/components/current/shareLinkBottomSheet/index.tsx @@ -1,5 +1,5 @@ import { useEffect } from 'react'; -import { useRecoilState } from 'recoil'; +import { useSetRecoilState } from 'recoil'; import { LinkShareBottomSheetState } from '@/atoms/LinkShareBottomSheetAtom'; import { @@ -23,7 +23,7 @@ const ShareLinkBottomSheet = () => { const { inviteURL, handleUseShareAPI, handleCopyToClipBoard } = useShareLink(); - const [, setIsLinkShareBottomSheetOpened] = useRecoilState( + const setIsLinkShareBottomSheetOpened = useSetRecoilState( LinkShareBottomSheetState ); diff --git a/src/components/current/table/index.tsx b/src/components/current/table/index.tsx index 17fa2e9..af9fef4 100644 --- a/src/components/current/table/index.tsx +++ b/src/components/current/table/index.tsx @@ -1,4 +1,3 @@ -import { useEffect, useState } from 'react'; import { useParams } from 'react-router-dom'; import { @@ -14,8 +13,6 @@ import { Wrapper, } from './index.styles'; -import { AvailableDateTimeTypes } from '@/types/current'; - import { getTimeRange } from '@/utils/getTimeRange'; import { getTableDateFormat } from '@/utils/getTableDateFormat'; import { getCurrentTableInfo } from '@/utils/getCurrentTableInfo'; @@ -32,20 +29,8 @@ const Table = ({ dates, startTime, endTime, participants }: TableTypes) => { const { roomUUID } = useParams() as { roomUUID: string }; const timeRange = getTimeRange(parseInt(startTime), parseInt(endTime)); - const [currentTableInfo, setCurrentTableInfo] = useState< - AvailableDateTimeTypes[] - >([]); - const { data } = useGetAvailableTimesByGroup(roomUUID); - useEffect(() => { - if (data) { - setCurrentTableInfo( - getCurrentTableInfo(data.availableDateTimes, timeRange) - ); - } - }, [data]); - return ( @@ -70,19 +55,22 @@ const Table = ({ dates, startTime, endTime, participants }: TableTypes) => { ))} - {currentTableInfo.map(({ availableDate, availableTimeInfos }: any) => ( - - {availableTimeInfos.map( - ({ time, count }: { time: number; count: number }) => ( - + ) + )} + + ) + )} ); diff --git a/src/hooks/useScroll.ts b/src/hooks/useScroll.ts index b820de8..2d8804b 100644 --- a/src/hooks/useScroll.ts +++ b/src/hooks/useScroll.ts @@ -20,15 +20,18 @@ export const useScroll = () => { const onMouseMove = (e: MouseEvent) => { const newTop = e.clientY - shiftY - track.getBoundingClientRect().top; - const bottomEdge = track.offsetHeight - thumb.offsetHeight; - const updatedOffsetY = Math.min(Math.max(0, newTop), bottomEdge); + // track에서 thumb의 위치 + // 0일 경우 thumb는 track의 최상단에 위치 + const diff = track.offsetHeight - thumb.offsetHeight; + + const updatedOffsetY = Math.min(Math.max(0, newTop), diff); setOffsetY(updatedOffsetY); }; const onMouseUp = () => { - document.removeEventListener('mouseup', onMouseUp); document.removeEventListener('mousemove', onMouseMove); + document.removeEventListener('mouseup', onMouseUp); }; document.addEventListener('mousemove', onMouseMove); @@ -46,15 +49,15 @@ export const useScroll = () => { const onTouchMove = (e: TouchEvent) => { const newTop = e.touches[0].clientY - shiftY - track.getBoundingClientRect().top; - const bottomEdge = track.offsetHeight - thumb.offsetHeight; + const diff = track.offsetHeight - thumb.offsetHeight; - const updatedOffsetY = Math.min(Math.max(0, newTop), bottomEdge); + const updatedOffsetY = Math.min(Math.max(0, newTop), diff); setOffsetY(updatedOffsetY); }; const onTouchEnd = () => { - document.removeEventListener('touchend', onTouchEnd); document.removeEventListener('touchmove', onTouchMove); + document.removeEventListener('touchend', onTouchEnd); }; document.addEventListener('touchmove', onTouchMove); diff --git a/src/pages/addTime/index.tsx b/src/pages/addTime/index.tsx index 4f44ac0..d66ca95 100644 --- a/src/pages/addTime/index.tsx +++ b/src/pages/addTime/index.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react'; +import { useRef, useState } from 'react'; import { useParams } from 'react-router-dom'; import { useRecoilState } from 'recoil'; @@ -11,10 +11,8 @@ import AddToggle from '@/components/addTime/toggle'; import AddTimeTable from '@/components/addTime/tableArea'; import AddCalendar from '@/components/addTime/calendar'; import { Body, Main, Title, TitleWrapper, Wrapper } from './index.styles'; -import { initialRoomInfoData } from '@/assets/data/initialRoomInfoData'; import { TableSelectedTypes } from './index.types'; -import { RoomTypes } from '@/types/roomInfo'; import { useGetRoomInfo } from '@/queries/room/useGetRoomInfo'; import { ROUTES } from '@/constants/ROUTES'; @@ -34,15 +32,9 @@ const AddTime = () => { const [isTooltipShown, setIsTooltipShown] = useRecoilState(tooltipState); - const { data } = useGetRoomInfo(roomUUID); - const [{ title, dates, startTime, endTime }, setRoomInfo] = - useState(initialRoomInfoData); - - useEffect(() => { - if (data) { - setRoomInfo(data); - } - }, [data]); + const { + data: { title, dates, startTime, endTime }, + } = useGetRoomInfo(roomUUID); const isTableView = startTime !== null && endTime !== null ? true : false; @@ -63,7 +55,7 @@ const AddTime = () => { 시간으로 선택해 주세요
- {startTime !== null && endTime !== null ? ( + {isTableView ? ( { newDates = [...newDates, `blank${i}`]; } - const validDates: ValidDate[][] = [ - newDates.map((date: string) => - date.slice(0, 5) === 'blank' - ? { date: date, isValidDate: false } - : { date: date, isValidDate: true } - ), - ]; + const validDates: ValidDate[] = newDates.map((date: string) => + date.slice(0, 5) === 'blank' + ? { date: date, isValidDate: false } + : { date: date, isValidDate: true } + ); let dateChunks: Array = []; - for (let i = 0; i < validDates[0].length; i += 3) { - dateChunks = [...dateChunks, validDates[0].slice(i, i + 3)]; + for (let i = 0; i < validDates.length; i += 3) { + dateChunks = [...dateChunks, validDates.slice(i, i + 3)]; } return dateChunks; diff --git a/src/utils/getCountdown.ts b/src/utils/getCountdown.ts index 2fe709b..9d80289 100644 --- a/src/utils/getCountdown.ts +++ b/src/utils/getCountdown.ts @@ -1,26 +1,14 @@ import dayjs from 'dayjs'; import { useEffect, useState } from 'react'; -export const getCountdown = (targetDate: string) => { - const deadLine = dayjs(targetDate).format('YYYY-MM-DD HH:mm:00:00'); - - const [countDown, setCountDown] = useState(dayjs(deadLine).diff(dayjs())); - - useEffect(() => { - setInterval(() => { - setCountDown(dayjs(deadLine).diff(dayjs())); - }, 10); - }, [deadLine]); - - return getReturnValues(countDown); -}; - +// 한 자리수 숫자인 경우 앞에 0 추가 const addZero = (num: number) => { if (num.toString().length === 1) { return '0' + num.toString(); } else return num; }; +// countDown: 마감 시간까지 남은 시간 const getReturnValues = (countDown: number) => { const days = Math.floor(countDown / (1000 * 60 * 60 * 24)); const hours = Math.floor( @@ -38,3 +26,17 @@ const getReturnValues = (countDown: number) => { milliseconds: addZero(milliseconds), }; }; + +export const getCountdown = (targetDate: string) => { + const deadLine = dayjs(targetDate).format('YYYY-MM-DD HH:mm:00:00'); + + const [countDown, setCountDown] = useState(dayjs(deadLine).diff(dayjs())); + + useEffect(() => { + setInterval(() => { + setCountDown(dayjs(deadLine).diff(dayjs())); + }, 10); + }, [deadLine]); + + return getReturnValues(countDown); +}; diff --git a/src/utils/getCurrentTableInfo.ts b/src/utils/getCurrentTableInfo.ts index b202001..10ef132 100644 --- a/src/utils/getCurrentTableInfo.ts +++ b/src/utils/getCurrentTableInfo.ts @@ -16,6 +16,7 @@ export const getCurrentTableInfo = ( }) ); + // 최소 column 개수: 4 if (availableDateTimes.length < 4) { const remainder = 4 - (availableDateTimes.length % 4); const timeArray = getTimeArray(timeRange);