diff --git a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.stories.tsx b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.stories.tsx new file mode 100644 index 000000000..1af01b683 --- /dev/null +++ b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.stories.tsx @@ -0,0 +1,49 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import type { MeetingRecommend } from '@apis/meetings/recommends'; + +import MeetingRecommendCard from './MeetingRecommendCard'; + +const DEFAULT_SCHEDULE: MeetingRecommend = { + rank: '1', + startDate: '2024-07-15', + startDayOfWeek: '월', + startTime: '20:00', + endDate: '2024-07-15', + endDayOfWeek: '월', + endTime: '21:00', + attendeeNames: ['다온', '마크', '해리', '낙타', '빙봉', '재즈', '배키', '페드로'], +}; + +const meta: Meta = { + title: 'MeetingRecommendCard/Default', + component: MeetingRecommendCard, + parameters: { + layout: 'centered', + }, + decorators: (Story) => ( +
+ +
+ ), +}; + +export default meta; + +type Story = StoryObj; + +export const DateTime: Story = { + args: { + schedule: DEFAULT_SCHEDULE, + totalAttendees: DEFAULT_SCHEDULE.attendeeNames, + type: 'DATETIME', + }, +}; + +export const DaysOnly: Story = { + args: { + schedule: DEFAULT_SCHEDULE, + totalAttendees: DEFAULT_SCHEDULE.attendeeNames, + type: 'DAYSONLY', + }, +}; diff --git a/frontend/src/components/MeetingTimeCard/MeetingTimeCard.styles.ts b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.styles.ts similarity index 86% rename from frontend/src/components/MeetingTimeCard/MeetingTimeCard.styles.ts rename to frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.styles.ts index 389cf0b1b..1618586e5 100644 --- a/frontend/src/components/MeetingTimeCard/MeetingTimeCard.styles.ts +++ b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.styles.ts @@ -12,10 +12,10 @@ export const s_baseContainer = css` border-radius: 0.8rem; `; -export const s_recommendContainer = css` +export const s_scheduleContainer = css` display: flex; flex-direction: column; - gap: 1.2rem; + gap: 0.8rem; `; export const s_optionContainer = css` @@ -39,16 +39,6 @@ export const s_getSelectedStyle = (isSelected: boolean) => css` `}; `; -export const s_attendeeInfo = css` - color: #6cd929; - text-align: start; - ${theme.typography.captionBold} -`; - -export const s_dateInfo = css` - ${theme.typography.bodyBold} -`; - export const s_checkboxContainer = css` display: flex; align-items: center; diff --git a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.tsx b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.tsx new file mode 100644 index 000000000..ab71df616 --- /dev/null +++ b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.tsx @@ -0,0 +1,46 @@ +import type { MeetingType } from '@apis/meetings/meetings'; +import type { MeetingRecommend } from '@apis/meetings/recommends'; + +import { s_baseContainer, s_scheduleContainer } from './MeetingRecommendCard.styles'; +import RecommendAttendees from './RecommendAttendees'; +import RecommendDateTime from './RecommendSchedule/RecommendDateTime'; +import RecommendDaysOnly from './RecommendSchedule/RecommendDaysOnly'; + +export interface DateInfo { + fullDate: string; + time: string; + dayOfWeek: string; +} + +export interface RecommendCardProps { + type: MeetingType; + totalAttendees: string[]; + schedule: MeetingRecommend; +} + +export default function MeetingRecommendCard({ + type, + schedule, + totalAttendees, +}: RecommendCardProps) { + const renderRecommendCard = (type: MeetingType) => { + switch (type) { + case 'DATETIME': + return ; + case 'DAYSONLY': + return ; + } + }; + + return ( +
+
+ + {renderRecommendCard(type)} +
+
+ ); +} diff --git a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.stories.tsx b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.stories.tsx new file mode 100644 index 000000000..6813cc9d8 --- /dev/null +++ b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.stories.tsx @@ -0,0 +1,76 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { useState } from 'storybook/internal/preview-api'; + +import type { MeetingRecommend } from '@apis/meetings/recommends'; + +import MeetingRecommendCheckboxCard from './MeetingRecommendCheckboxCard'; + +const DEFAULT_SCHEDULE: MeetingRecommend = { + rank: '1', + startDate: '2024-07-15', + startDayOfWeek: '월', + startTime: '20:00', + endDate: '2024-07-15', + endDayOfWeek: '월', + endTime: '21:00', + attendeeNames: ['다온', '마크', '해리', '낙타', '빙봉', '재즈', '배키', '페드로'], +}; + +const meta: Meta = { + title: 'MeetingRecommendCard/Checkbox', + component: MeetingRecommendCheckboxCard, + parameters: { + layout: 'centered', + }, + args: { + schedule: DEFAULT_SCHEDULE, + totalAttendees: DEFAULT_SCHEDULE.attendeeNames, + }, + decorators: (Story) => ( +
+ +
+ ), +}; + +export default meta; + +type Story = StoryObj; + +export const DateTime: Story = { + render: (args) => { + const [isSelect, setIsSelect] = useState(false); + + const onToggle = () => { + setIsSelect((prevIsSelected) => !prevIsSelected); + }; + + return ( + + ); + }, +}; + +export const DaysOnly: Story = { + render: (args) => { + const [isSelect, setIsSelect] = useState(false); + + const onToggle = () => { + setIsSelect((prevIsSelected) => !prevIsSelected); + }; + + return ( + + ); + }, +}; diff --git a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.tsx b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.tsx new file mode 100644 index 000000000..926806506 --- /dev/null +++ b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.tsx @@ -0,0 +1,54 @@ +import type { MeetingType } from '@apis/meetings/meetings'; + +import type { RecommendCardProps } from './MeetingRecommendCard'; +import { + s_baseContainer, + s_checkboxContainer, + s_checkboxInput, + s_getSelectedStyle, + s_optionContainer, + s_scheduleContainer, +} from './MeetingRecommendCard.styles'; +import RecommendAttendees from './RecommendAttendees'; +import RecommendCardDateTime from './RecommendSchedule/RecommendDateTime'; +import RecommendCardDaysOnly from './RecommendSchedule/RecommendDaysOnly'; + +export interface MeetingRecommendCheckboxProps extends RecommendCardProps { + isSelected: boolean; + onSelect: () => void; +} + +export default function MeetingRecommendCheckboxCard({ + type, + isSelected, + schedule, + totalAttendees, + onSelect, +}: MeetingRecommendCheckboxProps) { + const renderRecommendCard = (type: MeetingType) => { + switch (type) { + case 'DATETIME': + return ; + case 'DAYSONLY': + return ; + } + }; + + return ( + + ); +} diff --git a/frontend/src/components/MeetingRecommendCard/RecommendAttendees.tsx b/frontend/src/components/MeetingRecommendCard/RecommendAttendees.tsx new file mode 100644 index 000000000..57ef46f48 --- /dev/null +++ b/frontend/src/components/MeetingRecommendCard/RecommendAttendees.tsx @@ -0,0 +1,17 @@ +import { s_attendeeInfo } from './RecommendSchedule/RecommendSchedule.style'; + +interface RecommendAttendeesProps { + totalAttendees: string[]; + recommendAttendees: string[]; +} + +export default function RecommendAttendees({ + totalAttendees, + recommendAttendees, +}: RecommendAttendeesProps) { + return ( + {`${totalAttendees.length}명 중 ${recommendAttendees.length}명`} + ); +} diff --git a/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDateTime.tsx b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDateTime.tsx new file mode 100644 index 000000000..959eb1f7d --- /dev/null +++ b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDateTime.tsx @@ -0,0 +1,32 @@ +import type { MeetingRecommend } from '@apis/meetings/recommends'; + +import { formatFullDate, formatTimeToKorean } from '@utils/date'; + +import { s_dateInfo, s_recommendContainer } from './RecommendSchedule.style'; + +interface RecommendDateTimeProps { + schedule: MeetingRecommend; +} + +export default function RecommendDateTime({ schedule }: RecommendDateTimeProps) { + const { startDate, startDayOfWeek, startTime, endDate, endDayOfWeek, endTime } = schedule; + + const startRecommendDate = formatFullDate({ + fullDate: startDate, + dayOfWeek: startDayOfWeek, + format: 'korean', + }); + + const endRecommendDate = formatFullDate({ + fullDate: endDate, + dayOfWeek: endDayOfWeek, + format: 'korean', + }); + + return ( +
+ {`${startRecommendDate} ${formatTimeToKorean(startTime)}`}부터 + {`${endRecommendDate} ${formatTimeToKorean(endTime)}`}까지 +
+ ); +} diff --git a/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDaysOnly.tsx b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDaysOnly.tsx new file mode 100644 index 000000000..4034a508a --- /dev/null +++ b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDaysOnly.tsx @@ -0,0 +1,41 @@ +import { Fragment } from 'react'; + +import type { MeetingRecommend } from '@apis/meetings/recommends'; + +import { formatFullDate, isSameDate } from '@utils/date'; + +import { s_dateInfo, s_recommendContainer } from './RecommendSchedule.style'; + +interface RecommendDaysOnlyProps { + schedule: MeetingRecommend; +} + +export default function RecommendDaysOnly({ schedule }: RecommendDaysOnlyProps) { + const { startDate, startDayOfWeek, endDate, endDayOfWeek } = schedule; + + const startRecommendDate = formatFullDate({ + fullDate: startDate, + dayOfWeek: startDayOfWeek, + format: 'korean', + }); + + const endRecommendDate = formatFullDate({ + fullDate: endDate, + dayOfWeek: endDayOfWeek, + format: 'korean', + }); + + return ( +
+ {/* 만약 하루만 추천해준다면 "00월 00일(수)"로 나오도록 구현(@낙타) */} + {isSameDate(new Date(startDate), new Date(endDate)) ? ( + {startRecommendDate} + ) : ( + + {startRecommendDate}부터 + {endRecommendDate}까지 + + )} +
+ ); +} diff --git a/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendSchedule.style.ts b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendSchedule.style.ts new file mode 100644 index 000000000..3bf35b502 --- /dev/null +++ b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendSchedule.style.ts @@ -0,0 +1,20 @@ +import { css } from '@emotion/react'; + +import theme from '@styles/theme'; + +export const s_recommendContainer = css` + display: flex; + align-items: flex-start; + flex-direction: column; + gap: 0.8rem; +`; + +export const s_attendeeInfo = css` + color: #6cd929; + text-align: start; + ${theme.typography.captionBold} +`; + +export const s_dateInfo = css` + ${theme.typography.bodyBold} +`; diff --git a/frontend/src/components/MeetingTimeCard/MeetingTimeOptionCard.tsx b/frontend/src/components/MeetingTimeCard/MeetingTimeOptionCard.tsx deleted file mode 100644 index c6eac97fc..000000000 --- a/frontend/src/components/MeetingTimeCard/MeetingTimeOptionCard.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { formatFullDate, formatTime } from '@utils/date'; - -import { - s_attendeeInfo, - s_baseContainer, - s_checkboxContainer, - s_checkboxInput, - s_dateInfo, - s_getSelectedStyle, - s_optionContainer, - s_recommendContainer, -} from './MeetingTimeCard.styles'; - -export interface DateInfo { - fullDate: string; - time: string; - dayOfWeek: string; -} - -const createRecommendDateInfo = ({ fullDate, time, dayOfWeek }: DateInfo) => { - const meetingDateWithDay = formatFullDate({ fullDate, dayOfWeek, format: 'korean' }); - const meetingTime = formatTime(time); - - return `${meetingDateWithDay} ${meetingTime}`; -}; - -interface MeetingTimeOptionCardProps { - isSelected: boolean; - onSelect: () => void; - attendeeCount: number; - schedule: { - startDate: string; - startDayOfWeek: string; - startTime: string; - endDate: string; - endDayOfWeek: string; - endTime: string; - attendeeNames: string[]; - }; -} - -export default function MeetingTimeOptionCard({ - isSelected, - onSelect, - attendeeCount, - schedule, -}: MeetingTimeOptionCardProps) { - const { startDate, startTime, startDayOfWeek, endDate, endTime, endDayOfWeek, attendeeNames } = - schedule; - - const currentAttendeeCount = attendeeNames.length; - - const startRecommendDateInfo = createRecommendDateInfo({ - fullDate: startDate, - time: startTime, - dayOfWeek: startDayOfWeek, - }); - - const endRecommendDateInfo = createRecommendDateInfo({ - fullDate: endDate, - time: endTime, - dayOfWeek: endDayOfWeek, - }); - - return ( - - ); -} diff --git a/frontend/src/components/MeetingTimeCard/MeetingTimeOptionCardDaysOnly.tsx b/frontend/src/components/MeetingTimeCard/MeetingTimeOptionCardDaysOnly.tsx deleted file mode 100644 index 222156500..000000000 --- a/frontend/src/components/MeetingTimeCard/MeetingTimeOptionCardDaysOnly.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { formatFullDate } from '@utils/date'; - -import { - s_attendeeInfo, - s_baseContainer, - s_checkboxContainer, - s_checkboxInput, - s_dateInfo, - s_getSelectedStyle, - s_optionContainer, - s_recommendContainer, -} from './MeetingTimeCard.styles'; - -export interface DateInfo { - fullDate: string; - time: string; - dayOfWeek: string; -} - -interface MeetingTimeOptionCardProps { - isSelected: boolean; - onSelect: () => void; - attendeeCount: number; - schedule: { - startDate: string; - startDayOfWeek: string; - startTime: string; - endDate: string; - endDayOfWeek: string; - endTime: string; - attendeeNames: string[]; - }; -} - -export default function MeetingTimeOptionCardDaysOnly({ - isSelected, - onSelect, - attendeeCount, - schedule, -}: MeetingTimeOptionCardProps) { - const { startDate, startDayOfWeek, endDate, endDayOfWeek, attendeeNames } = schedule; - - const startDateWithDay = formatFullDate({ - fullDate: startDate, - dayOfWeek: startDayOfWeek, - format: 'korean', - }); - - const endDateWithDay = formatFullDate({ - fullDate: endDate, - dayOfWeek: endDayOfWeek, - format: 'korean', - }); - - const currentAttendeeCount = attendeeNames.length; - - return ( - - ); -} diff --git a/frontend/src/components/MeetingTimeCard/MeetingTimeRecommendCard.tsx b/frontend/src/components/MeetingTimeCard/MeetingTimeRecommendCard.tsx deleted file mode 100644 index aa97ecaea..000000000 --- a/frontend/src/components/MeetingTimeCard/MeetingTimeRecommendCard.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { formatFullDate, formatTime } from '@utils/date'; - -import { - s_attendeeInfo, - s_baseContainer, - s_dateInfo, - s_recommendContainer, -} from './MeetingTimeCard.styles'; -import type { DateInfo } from './MeetingTimeOptionCard'; - -const createRecommendDateInfo = ({ fullDate, time, dayOfWeek }: DateInfo) => { - const meetingDateWithDay = formatFullDate({ fullDate, dayOfWeek, format: 'korean' }); - const meetingTime = formatTime(time); - - return `${meetingDateWithDay} ${meetingTime}`; -}; - -interface MeetingRecommendCardProps extends React.HTMLAttributes { - attendeeCount: number; - schedule: { - startDate: string; - startDayOfWeek: string; - startTime: string; - endDate: string; - endDayOfWeek: string; - endTime: string; - attendeeNames: string[]; - }; -} - -export default function MeetingTimeRecommendCard({ - schedule, - attendeeCount, -}: MeetingRecommendCardProps) { - const { startDate, startTime, startDayOfWeek, endDate, endTime, endDayOfWeek, attendeeNames } = - schedule; - - const currentAttendeeCount = attendeeNames.length; - - const startRecommendDateInfo = createRecommendDateInfo({ - fullDate: startDate, - time: startTime, - dayOfWeek: startDayOfWeek, - }); - - const endRecommendDateInfo = createRecommendDateInfo({ - fullDate: endDate, - time: endTime, - dayOfWeek: endDayOfWeek, - }); - - return ( -
- {`${attendeeCount}명 중 ${currentAttendeeCount}명`} - {startRecommendDateInfo}부터 - {endRecommendDateInfo}까지 -
- ); -} diff --git a/frontend/src/components/MeetingTimeCard/MeetingTimeRecommendCardDaysOnly.tsx b/frontend/src/components/MeetingTimeCard/MeetingTimeRecommendCardDaysOnly.tsx deleted file mode 100644 index f22c372bf..000000000 --- a/frontend/src/components/MeetingTimeCard/MeetingTimeRecommendCardDaysOnly.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { formatFullDate } from '@utils/date'; - -import { - s_attendeeInfo, - s_baseContainer, - s_dateInfo, - s_recommendContainer, -} from './MeetingTimeCard.styles'; - -interface MeetingRecommendCardProps extends React.HTMLAttributes { - attendeeCount: number; - schedule: { - startDate: string; - startDayOfWeek: string; - startTime: string; - endDate: string; - endDayOfWeek: string; - endTime: string; - attendeeNames: string[]; - }; -} - -export default function MeetingTimeRecommendCardDaysOnly({ - schedule, - attendeeCount, -}: MeetingRecommendCardProps) { - const { startDate, startDayOfWeek, endDate, endDayOfWeek, attendeeNames } = schedule; - - const currentAttendeeCount = attendeeNames.length; - - const startRecommendDate = formatFullDate({ - fullDate: startDate, - dayOfWeek: startDayOfWeek, - }); - - const endRecommendDate = formatFullDate({ - fullDate: endDate, - dayOfWeek: endDayOfWeek, - }); - - return ( -
- {`${attendeeCount}명 중 ${currentAttendeeCount}명`} - {startRecommendDate}부터 - {endRecommendDate}까지 -
- ); -} diff --git a/frontend/src/pages/MeetingConfirmPage/components/MeetingTimeOptions/index.tsx b/frontend/src/pages/MeetingConfirmPage/components/MeetingTimeOptions/index.tsx index d63479308..9b9c825b6 100644 --- a/frontend/src/pages/MeetingConfirmPage/components/MeetingTimeOptions/index.tsx +++ b/frontend/src/pages/MeetingConfirmPage/components/MeetingTimeOptions/index.tsx @@ -6,8 +6,7 @@ import { s_tipInfo, } from '@pages/MeetingConfirmPage/MeetingTimeConfirmPage.styles'; -import MeetingTimeOptionCard from '@components/MeetingTimeCard/MeetingTimeOptionCard'; -import MeetingTimeOptionCardDaysOnly from '@components/MeetingTimeCard/MeetingTimeOptionCardDaysOnly'; +import MeetingRecommendCheckboxCard from '@components/MeetingRecommendCard/MeetingRecommendCheckboxCard'; import { Button } from '@components/_common/Buttons/Button'; import TabButton from '@components/_common/Buttons/TabButton'; import Dropdown from '@components/_common/Dropdown'; @@ -81,6 +80,8 @@ export default function MeetingTimeOptions({ uuid, attendeeNames }: MeetingTimeO return (
+ {/* 만약 TabButton의 로직이 변경되면 MeetingRecommendPage에 있는 로직도 함께 변경되어야 함 (@낙타) */} + 원하는 참여인원을 선택해 보세요 :)
))}
- 원하는 참여인원을 선택해 보세요 :) +
); } diff --git a/frontend/src/pages/MeetingConfirmPage/index.tsx b/frontend/src/pages/MeetingConfirmPage/index.tsx index d3b4371a3..a13515ef7 100644 --- a/frontend/src/pages/MeetingConfirmPage/index.tsx +++ b/frontend/src/pages/MeetingConfirmPage/index.tsx @@ -1,4 +1,3 @@ -import { useQuery } from '@tanstack/react-query'; import { useContext } from 'react'; import ContentLayout from '@layouts/ContentLayout'; @@ -9,21 +8,14 @@ import BackButton from '@components/_common/Buttons/BackButton'; import Header from '@components/_common/Header'; import Text from '@components/_common/Text'; -import { getMeetingAttendees } from '@apis/meetings/recommends'; - -import { QUERY_KEY } from '@constants/queryKeys'; +import { useGetMeetingAttendeesQuery } from '@stores/servers/meeting/queries'; import { s_container, s_pageHeader } from './MeetingTimeConfirmPage.styles'; import MeetingTimeOptions from './components/MeetingTimeOptions'; export default function MeetingConfirmPage() { const { uuid } = useContext(UuidContext); - - const { data: attendeeNames } = useQuery({ - queryKey: [QUERY_KEY.meetingAttendees], - queryFn: () => getMeetingAttendees({ uuid }), - retry: 0, - }); + const { attendeeNames } = useGetMeetingAttendeesQuery(uuid); return ( <> diff --git a/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeRecommends.tsx b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeRecommends.tsx index 055c3f8f3..acdf136e0 100644 --- a/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeRecommends.tsx +++ b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeRecommends.tsx @@ -1,5 +1,4 @@ -import MeetingTimeRecommendCard from '@components/MeetingTimeCard/MeetingTimeRecommendCard'; -import MeetingTimeRecommendCardDaysOnly from '@components/MeetingTimeCard/MeetingTimeRecommendCardDaysOnly'; +import MeetingRecommendCard from '@components/MeetingRecommendCard/MeetingRecommendCard'; import TabButton from '@components/_common/Buttons/TabButton'; import Dropdown from '@components/_common/Dropdown'; @@ -25,6 +24,8 @@ export default function MeetingTimeRecommends({ uuid, attendeeNames }: MeetingRe return (
+ {/* 만약 TabButton의 로직이 변경되면 MeetingConfirmPage에 있는 로직도 함께 변경되어야 함 (@낙타) */} + 원하는 참여인원을 선택해 보세요 :)
))}
- 원하는 참여인원을 선택해 보세요 :) + {meetingRecommendResponse && meetingRecommendResponse.type === 'DATETIME' && ( )} {meetingRecommendResponse && - meetingRecommendResponse.recommendedSchedules.map((recommendInfo, index) => - meetingRecommendResponse.type === 'DATETIME' ? ( - - ) : ( - - ), - )} + meetingRecommendResponse.recommendedSchedules.map((recommendInfo) => ( + + ))}
); } diff --git a/frontend/src/pages/MeetingRecommendPage/index.tsx b/frontend/src/pages/MeetingRecommendPage/index.tsx index 81f48c1b3..de55c4994 100644 --- a/frontend/src/pages/MeetingRecommendPage/index.tsx +++ b/frontend/src/pages/MeetingRecommendPage/index.tsx @@ -1,4 +1,3 @@ -import { useQuery } from '@tanstack/react-query'; import { useContext } from 'react'; import ContentLayout from '@layouts/ContentLayout'; @@ -9,21 +8,14 @@ import BackButton from '@components/_common/Buttons/BackButton'; import Header from '@components/_common/Header'; import Text from '@components/_common/Text'; -import { getMeetingAttendees } from '@apis/meetings/recommends'; - -import { QUERY_KEY } from '@constants/queryKeys'; +import { useGetMeetingAttendeesQuery } from '@stores/servers/meeting/queries'; import { s_container, s_pageHeader } from './MeetingRecommendPage.styles'; import MeetingTimeRecommends from './components/MeetingTimeRecommends'; export default function MeetingRecommendPage() { const { uuid } = useContext(UuidContext); - - const { data: attendeeNames } = useQuery({ - queryKey: [QUERY_KEY.meetingAttendees], - queryFn: () => getMeetingAttendees({ uuid }), - retry: 0, - }); + const { attendeeNames } = useGetMeetingAttendeesQuery(uuid); return ( <> diff --git a/frontend/src/stores/servers/meeting/queries.ts b/frontend/src/stores/servers/meeting/queries.ts index 70d56ab1f..f6be775eb 100644 --- a/frontend/src/stores/servers/meeting/queries.ts +++ b/frontend/src/stores/servers/meeting/queries.ts @@ -1,7 +1,7 @@ import { useQuery } from '@tanstack/react-query'; import { getMeetingBase, getMeetingEntranceDetails } from '@apis/meetings/meetings'; -import { getMeetingTimeRecommends } from '@apis/meetings/recommends'; +import { getMeetingAttendees, getMeetingTimeRecommends } from '@apis/meetings/recommends'; import { QUERY_KEY } from '@constants/queryKeys'; @@ -38,3 +38,12 @@ export const useMeetingEntranceDetailQuery = (uuid: string) => { retry: 1, }); }; + +export const useGetMeetingAttendeesQuery = (uuid: string) => { + const { data } = useQuery({ + queryKey: [QUERY_KEY.meetingAttendees], + queryFn: () => getMeetingAttendees({ uuid }), + }); + + return { attendeeNames: data }; +}; diff --git a/frontend/src/utils/date.ts b/frontend/src/utils/date.ts index 543404419..72a2c7682 100644 --- a/frontend/src/utils/date.ts +++ b/frontend/src/utils/date.ts @@ -6,6 +6,8 @@ interface FormatDateProps { format?: DateFormat; } +// format이 korean일 때, "12월 25일(수)" 형태로 반환 +// format이 standard일 때, "2024/12/25(수)" 형태로 반환 export const formatFullDate = ({ fullDate, dayOfWeek, format = 'standard' }: FormatDateProps) => { const [year, month, day] = fullDate.split('-'); @@ -13,11 +15,15 @@ export const formatFullDate = ({ fullDate, dayOfWeek, format = 'standard' }: For return `${year}/${month}/${day}(${dayOfWeek})`; }; -export const formatTime = (time: string): string => { - const hour = parseInt(time, 10); +// "17:00" -> "오후 5시" +// "17:30" -> "오후 5시 30분" +// "03:00" -> "오전 3시" +export const formatTimeToKorean = (time: string): string => { + const [hour, minutes] = time.split(':').map(Number); const hourPrefix = hour >= 12 ? '오후' : '오전'; const formattedHour = hour % 12 || 12; + if (minutes === 30) return `${hourPrefix} ${formattedHour}시 ${minutes}분`; return `${hourPrefix} ${formattedHour}시`; }; @@ -38,3 +44,11 @@ export const hasSelectableDaysInMonth = (currentMonth: number, schedules: string return availableMonths.includes(currentMonth + 1); }; + +export const isSameDate = (startDate: Date, endDate: Date) => { + return ( + startDate.getFullYear() === endDate.getFullYear() && + startDate.getMonth() === endDate.getMonth() && + startDate.getDate() === endDate.getDate() + ); +};