From 18b4d9cacb8fca0308aed4029c47826b04a7e228 Mon Sep 17 00:00:00 2001 From: Largopie Date: Wed, 25 Dec 2024 18:36:31 +0900 Subject: [PATCH 1/6] =?UTF-8?q?refactor:=20`MeetingTimeCard`=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=ED=8F=B4=EB=8D=94=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/MeetingTimeOptions/index.tsx | 4 ++-- .../components/MeetingTimeCard/MeetingTimeCard.styles.ts | 0 .../components/MeetingTimeCard/MeetingTimeOptionCard.tsx | 0 .../MeetingTimeCard/MeetingTimeOptionCardDaysOnly.tsx | 0 .../components/MeetingTimeCard/MeetingTimeRecommendCard.tsx | 0 .../MeetingTimeCard/MeetingTimeRecommendCardDaysOnly.tsx | 0 .../components/MeetingTimeRecommends.tsx | 5 +++-- 7 files changed, 5 insertions(+), 4 deletions(-) rename frontend/src/{ => pages/MeetingRecommendPage}/components/MeetingTimeCard/MeetingTimeCard.styles.ts (100%) rename frontend/src/{ => pages/MeetingRecommendPage}/components/MeetingTimeCard/MeetingTimeOptionCard.tsx (100%) rename frontend/src/{ => pages/MeetingRecommendPage}/components/MeetingTimeCard/MeetingTimeOptionCardDaysOnly.tsx (100%) rename frontend/src/{ => pages/MeetingRecommendPage}/components/MeetingTimeCard/MeetingTimeRecommendCard.tsx (100%) rename frontend/src/{ => pages/MeetingRecommendPage}/components/MeetingTimeCard/MeetingTimeRecommendCardDaysOnly.tsx (100%) diff --git a/frontend/src/pages/MeetingConfirmPage/components/MeetingTimeOptions/index.tsx b/frontend/src/pages/MeetingConfirmPage/components/MeetingTimeOptions/index.tsx index d63479308..ea604e5cd 100644 --- a/frontend/src/pages/MeetingConfirmPage/components/MeetingTimeOptions/index.tsx +++ b/frontend/src/pages/MeetingConfirmPage/components/MeetingTimeOptions/index.tsx @@ -5,9 +5,9 @@ import { s_attendeesContainer, s_tipInfo, } from '@pages/MeetingConfirmPage/MeetingTimeConfirmPage.styles'; +import MeetingTimeOptionCard from '@pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeOptionCard'; +import MeetingTimeOptionCardDaysOnly from '@pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeOptionCardDaysOnly'; -import MeetingTimeOptionCard from '@components/MeetingTimeCard/MeetingTimeOptionCard'; -import MeetingTimeOptionCardDaysOnly from '@components/MeetingTimeCard/MeetingTimeOptionCardDaysOnly'; import { Button } from '@components/_common/Buttons/Button'; import TabButton from '@components/_common/Buttons/TabButton'; import Dropdown from '@components/_common/Dropdown'; diff --git a/frontend/src/components/MeetingTimeCard/MeetingTimeCard.styles.ts b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeCard.styles.ts similarity index 100% rename from frontend/src/components/MeetingTimeCard/MeetingTimeCard.styles.ts rename to frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeCard.styles.ts diff --git a/frontend/src/components/MeetingTimeCard/MeetingTimeOptionCard.tsx b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeOptionCard.tsx similarity index 100% rename from frontend/src/components/MeetingTimeCard/MeetingTimeOptionCard.tsx rename to frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeOptionCard.tsx diff --git a/frontend/src/components/MeetingTimeCard/MeetingTimeOptionCardDaysOnly.tsx b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeOptionCardDaysOnly.tsx similarity index 100% rename from frontend/src/components/MeetingTimeCard/MeetingTimeOptionCardDaysOnly.tsx rename to frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeOptionCardDaysOnly.tsx diff --git a/frontend/src/components/MeetingTimeCard/MeetingTimeRecommendCard.tsx b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeRecommendCard.tsx similarity index 100% rename from frontend/src/components/MeetingTimeCard/MeetingTimeRecommendCard.tsx rename to frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeRecommendCard.tsx diff --git a/frontend/src/components/MeetingTimeCard/MeetingTimeRecommendCardDaysOnly.tsx b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeRecommendCardDaysOnly.tsx similarity index 100% rename from frontend/src/components/MeetingTimeCard/MeetingTimeRecommendCardDaysOnly.tsx rename to frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeRecommendCardDaysOnly.tsx diff --git a/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeRecommends.tsx b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeRecommends.tsx index 055c3f8f3..f1d5451de 100644 --- a/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeRecommends.tsx +++ b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeRecommends.tsx @@ -1,5 +1,6 @@ -import MeetingTimeRecommendCard from '@components/MeetingTimeCard/MeetingTimeRecommendCard'; -import MeetingTimeRecommendCardDaysOnly from '@components/MeetingTimeCard/MeetingTimeRecommendCardDaysOnly'; +import MeetingTimeRecommendCard from '@pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeRecommendCard'; +import MeetingTimeRecommendCardDaysOnly from '@pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeRecommendCardDaysOnly'; + import TabButton from '@components/_common/Buttons/TabButton'; import Dropdown from '@components/_common/Dropdown'; From f3e0d7088240d7cb19f13900ab5be30a3107aff5 Mon Sep 17 00:00:00 2001 From: Largopie Date: Sat, 28 Dec 2024 16:04:33 +0900 Subject: [PATCH 2/6] =?UTF-8?q?refactor:=20MeetingRecommendCard=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Default, Checkbox 두 가지 형태로 분리 - DASYONLY, DATETIME 타입에 따라 컴포넌트 분리 --- .../MeetingRecommendCard.stories.tsx | 49 +++++++++++ .../MeetingRecommendCard.styles.ts | 81 +++++++++++++++++++ .../MeetingRecommendCard.tsx | 39 +++++++++ .../MeetingRecommendCheckboxCard.stories.tsx | 76 +++++++++++++++++ .../MeetingRecommendCheckboxCard.tsx | 50 ++++++++++++ .../RecommendSchedule/RecommendDateTime.tsx | 33 ++++++++ .../RecommendSchedule/RecommendDaysOnly.tsx | 32 ++++++++ .../RecommendSchedule.style.ts | 19 +++++ 8 files changed, 379 insertions(+) create mode 100644 frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.stories.tsx create mode 100644 frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.styles.ts create mode 100644 frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.tsx create mode 100644 frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.stories.tsx create mode 100644 frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.tsx create mode 100644 frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDateTime.tsx create mode 100644 frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDaysOnly.tsx create mode 100644 frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendSchedule.style.ts diff --git a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.stories.tsx b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.stories.tsx new file mode 100644 index 000000000..6822f77ce --- /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, + totalAttendeeCount: DEFAULT_SCHEDULE.attendeeNames.length, + type: 'DATETIME', + }, +}; + +export const DaysOnly: Story = { + args: { + schedule: DEFAULT_SCHEDULE, + totalAttendeeCount: DEFAULT_SCHEDULE.attendeeNames.length, + type: 'DAYSONLY', + }, +}; diff --git a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.styles.ts b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.styles.ts new file mode 100644 index 000000000..492451f95 --- /dev/null +++ b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.styles.ts @@ -0,0 +1,81 @@ +import { css } from '@emotion/react'; + +import theme from '@styles/theme'; + +export const s_baseContainer = css` + width: 100%; + height: 100%; + padding: 0.8rem 1.2rem; + + opacity: 0.7; + background-color: ${theme.colors.pink.light}; + border-radius: 0.8rem; +`; + +export const s_optionContainer = css` + display: flex; + align-items: center; + justify-content: space-between; + border: none; +`; + +export const s_getSelectedStyle = (isSelected: boolean) => css` + transition: + transform 0.2s ease-in-out, + opacity 0.2s ease-in-out; + + ${isSelected && + css` + z-index: 1; + transform: scale(1.02); + opacity: 0.9; + border: 1px solid ${theme.colors.primary}; + `}; +`; + +export const s_checkboxContainer = css` + display: flex; + align-items: center; + justify-content: center; + height: 100%; +`; + +export const s_checkboxInput = css` + cursor: pointer; + + position: relative; + + display: flex; + align-items: center; + justify-content: center; + + width: 2rem; + height: 2rem; + + appearance: none; + background-color: transparent; + border: 2px solid ${theme.colors.grey.dark}; + border-radius: 0.4rem; + + transition: all 0.2s ease-in-out; + + &:checked { + background-color: ${theme.colors.primary}; + border-color: ${theme.colors.primary}; + } + + &:checked::after { + content: ''; + + position: absolute; + top: 40%; + left: 50%; + transform: translate(-50%, -50%) rotate(45deg); + + width: 0.6rem; + height: 1rem; + + border: solid white; + border-width: 0 2px 2px 0; + } +`; diff --git a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.tsx b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.tsx new file mode 100644 index 000000000..ef54838e9 --- /dev/null +++ b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.tsx @@ -0,0 +1,39 @@ +import type { MeetingType } from '@apis/meetings/meetings'; +import type { MeetingRecommend } from '@apis/meetings/recommends'; + +import { s_baseContainer } from './MeetingRecommendCard.styles'; +import RecommendCardDateTime from './RecommendSchedule/RecommendDateTime'; +import RecommendCardDaysOnly from './RecommendSchedule/RecommendDaysOnly'; + +export interface DateInfo { + fullDate: string; + time: string; + dayOfWeek: string; +} + +export interface RecommendCardProps { + type: MeetingType; + totalAttendeeCount: number; + schedule: MeetingRecommend; +} + +export default function MeetingRecommendCard({ + type, + schedule, + totalAttendeeCount, +}: 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..906fbf89c --- /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, + totalAttendeeCount: 8, + }, + 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..de43fc326 --- /dev/null +++ b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.tsx @@ -0,0 +1,50 @@ +import type { MeetingType } from '@apis/meetings/meetings'; + +import type { RecommendCardProps } from './MeetingRecommendCard'; +import { + s_baseContainer, + s_checkboxContainer, + s_checkboxInput, + s_getSelectedStyle, + s_optionContainer, +} from './MeetingRecommendCard.styles'; +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, + totalAttendeeCount, + onSelect, +}: MeetingRecommendCheckboxProps) { + const renderRecommendCard = (type: MeetingType) => { + switch (type) { + case 'DATETIME': + return ( + + ); + case 'DAYSONLY': + return ( + + ); + } + }; + + return ( + + ); +} diff --git a/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDateTime.tsx b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDateTime.tsx new file mode 100644 index 000000000..09d581caf --- /dev/null +++ b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDateTime.tsx @@ -0,0 +1,33 @@ +import { formatFullDate, formatTime } from '@utils/date'; + +import type { RecommendCardProps } from '../MeetingRecommendCard'; +import { s_attendeeInfo, s_dateInfo, s_recommendContainer } from './RecommendSchedule.style'; + +export default function RecommendCardDateTime({ + schedule, + totalAttendeeCount, +}: Omit) { + const { startDate, startDayOfWeek, startTime, endDate, endDayOfWeek, endTime, attendeeNames } = + schedule; + + const currentAttendeeCount = attendeeNames.length; + const startRecommendDate = formatFullDate({ + fullDate: startDate, + dayOfWeek: startDayOfWeek, + format: 'korean', + }); + + const endRecommendDate = formatFullDate({ + fullDate: endDate, + dayOfWeek: endDayOfWeek, + format: 'korean', + }); + + return ( +
+ {`${totalAttendeeCount}명 중 ${currentAttendeeCount}명`} + {`${startRecommendDate} ${formatTime(startTime)}`}부터 + {`${endRecommendDate} ${formatTime(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..9fa9220e6 --- /dev/null +++ b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDaysOnly.tsx @@ -0,0 +1,32 @@ +import { formatFullDate } from '@utils/date'; + +import type { RecommendCardProps } from '../MeetingRecommendCard'; +import { s_attendeeInfo, s_dateInfo, s_recommendContainer } from './RecommendSchedule.style'; + +export default function RecommendCardDaysOnly({ + schedule, + totalAttendeeCount, +}: Omit) { + const { startDate, startDayOfWeek, endDate, endDayOfWeek, attendeeNames } = schedule; + + const currentAttendeeCount = attendeeNames.length; + const startRecommendDate = formatFullDate({ + fullDate: startDate, + dayOfWeek: startDayOfWeek, + format: 'korean', + }); + + const endRecommendDate = formatFullDate({ + fullDate: endDate, + dayOfWeek: endDayOfWeek, + format: 'korean', + }); + + return ( +
+ {`${totalAttendeeCount}명 중 ${currentAttendeeCount}명`} + {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..6a57efa4f --- /dev/null +++ b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendSchedule.style.ts @@ -0,0 +1,19 @@ +import { css } from '@emotion/react'; + +import theme from '@styles/theme'; + +export const s_recommendContainer = css` + display: flex; + flex-direction: column; + gap: 1.2rem; +`; + +export const s_attendeeInfo = css` + color: #6cd929; + text-align: start; + ${theme.typography.captionBold} +`; + +export const s_dateInfo = css` + ${theme.typography.bodyBold} +`; From 225531479dcde70383e9fd4648fd7a66922755e9 Mon Sep 17 00:00:00 2001 From: Largopie Date: Tue, 31 Dec 2024 11:26:56 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat(date.util):=20=EB=8F=99=EC=9D=BC?= =?UTF-8?q?=ED=95=9C=20=EB=85=84/=EC=9B=94/=EC=9D=BC=20=EB=B9=84=EA=B5=90?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/utils/date.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/frontend/src/utils/date.ts b/frontend/src/utils/date.ts index 543404419..276a05ad5 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,6 +15,7 @@ export const formatFullDate = ({ fullDate, dayOfWeek, format = 'standard' }: For return `${year}/${month}/${day}(${dayOfWeek})`; }; +// 오후 6시, 오전 3시 와 같은 형태로 반환 export const formatTime = (time: string): string => { const hour = parseInt(time, 10); const hourPrefix = hour >= 12 ? '오후' : '오전'; @@ -38,3 +41,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() + ); +}; From e71d3d4261f64561e3a8d87b4178b178e6d41f90 Mon Sep 17 00:00:00 2001 From: Largopie Date: Tue, 31 Dec 2024 11:27:37 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat(useGetMeetingAttendeesQuery):=20?= =?UTF-8?q?=EC=95=BD=EC=86=8D=20=EC=B4=9D=20=EC=9D=B8=EC=9B=90=20query=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/MeetingConfirmPage/index.tsx | 12 ++---------- frontend/src/pages/MeetingRecommendPage/index.tsx | 12 ++---------- frontend/src/stores/servers/meeting/queries.ts | 11 ++++++++++- 3 files changed, 14 insertions(+), 21 deletions(-) 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/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 }; +}; From 7a264081bbf43c312f8a5961c60cae366b69fc93 Mon Sep 17 00:00:00 2001 From: Largopie Date: Tue, 31 Dec 2024 11:29:35 +0900 Subject: [PATCH 5/6] =?UTF-8?q?refactor:=20RecommendCard=20=EC=9E=AC?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=20=EA=B0=80=EB=8A=A5=ED=95=9C=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EC=83=81=ED=99=94=20=EB=B0=8F=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MeetingRecommendCard.stories.tsx | 4 +- .../MeetingRecommendCard.styles.ts | 6 ++ .../MeetingRecommendCard.tsx | 31 +++--- .../MeetingRecommendCheckboxCard.stories.tsx | 2 +- .../MeetingRecommendCheckboxCard.tsx | 20 ++-- .../RecommendAttendees.tsx | 17 ++++ .../RecommendSchedule/RecommendDateTime.tsx | 19 ++-- .../RecommendSchedule/RecommendDaysOnly.tsx | 33 ++++--- .../RecommendSchedule.style.ts | 2 +- .../components/MeetingTimeOptions/index.tsx | 36 +++---- .../MeetingTimeCard/MeetingTimeCard.styles.ts | 97 ------------------- .../MeetingTimeCard/MeetingTimeOptionCard.tsx | 80 --------------- .../MeetingTimeOptionCardDaysOnly.tsx | 72 -------------- .../MeetingTimeRecommendCard.tsx | 59 ----------- .../MeetingTimeRecommendCardDaysOnly.tsx | 48 --------- .../components/MeetingTimeRecommends.tsx | 31 +++--- 16 files changed, 114 insertions(+), 443 deletions(-) create mode 100644 frontend/src/components/MeetingRecommendCard/RecommendAttendees.tsx delete mode 100644 frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeCard.styles.ts delete mode 100644 frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeOptionCard.tsx delete mode 100644 frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeOptionCardDaysOnly.tsx delete mode 100644 frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeRecommendCard.tsx delete mode 100644 frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeRecommendCardDaysOnly.tsx diff --git a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.stories.tsx b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.stories.tsx index 6822f77ce..1af01b683 100644 --- a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.stories.tsx +++ b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.stories.tsx @@ -35,7 +35,7 @@ type Story = StoryObj; export const DateTime: Story = { args: { schedule: DEFAULT_SCHEDULE, - totalAttendeeCount: DEFAULT_SCHEDULE.attendeeNames.length, + totalAttendees: DEFAULT_SCHEDULE.attendeeNames, type: 'DATETIME', }, }; @@ -43,7 +43,7 @@ export const DateTime: Story = { export const DaysOnly: Story = { args: { schedule: DEFAULT_SCHEDULE, - totalAttendeeCount: DEFAULT_SCHEDULE.attendeeNames.length, + totalAttendees: DEFAULT_SCHEDULE.attendeeNames, type: 'DAYSONLY', }, }; diff --git a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.styles.ts b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.styles.ts index 492451f95..1618586e5 100644 --- a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.styles.ts +++ b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.styles.ts @@ -12,6 +12,12 @@ export const s_baseContainer = css` border-radius: 0.8rem; `; +export const s_scheduleContainer = css` + display: flex; + flex-direction: column; + gap: 0.8rem; +`; + export const s_optionContainer = css` display: flex; align-items: center; diff --git a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.tsx b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.tsx index ef54838e9..ab71df616 100644 --- a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.tsx +++ b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCard.tsx @@ -1,9 +1,10 @@ import type { MeetingType } from '@apis/meetings/meetings'; import type { MeetingRecommend } from '@apis/meetings/recommends'; -import { s_baseContainer } from './MeetingRecommendCard.styles'; -import RecommendCardDateTime from './RecommendSchedule/RecommendDateTime'; -import RecommendCardDaysOnly from './RecommendSchedule/RecommendDaysOnly'; +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; @@ -13,27 +14,33 @@ export interface DateInfo { export interface RecommendCardProps { type: MeetingType; - totalAttendeeCount: number; + totalAttendees: string[]; schedule: MeetingRecommend; } export default function MeetingRecommendCard({ type, schedule, - totalAttendeeCount, + totalAttendees, }: RecommendCardProps) { const renderRecommendCard = (type: MeetingType) => { switch (type) { case 'DATETIME': - return ( - - ); + return ; case 'DAYSONLY': - return ( - - ); + return ; } }; - return
{renderRecommendCard(type)}
; + return ( +
+
+ + {renderRecommendCard(type)} +
+
+ ); } diff --git a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.stories.tsx b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.stories.tsx index 906fbf89c..6813cc9d8 100644 --- a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.stories.tsx +++ b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.stories.tsx @@ -24,7 +24,7 @@ const meta: Meta = { }, args: { schedule: DEFAULT_SCHEDULE, - totalAttendeeCount: 8, + totalAttendees: DEFAULT_SCHEDULE.attendeeNames, }, decorators: (Story) => (
diff --git a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.tsx b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.tsx index de43fc326..926806506 100644 --- a/frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.tsx +++ b/frontend/src/components/MeetingRecommendCard/MeetingRecommendCheckboxCard.tsx @@ -7,7 +7,9 @@ import { 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'; @@ -20,19 +22,15 @@ export default function MeetingRecommendCheckboxCard({ type, isSelected, schedule, - totalAttendeeCount, + totalAttendees, onSelect, }: MeetingRecommendCheckboxProps) { const renderRecommendCard = (type: MeetingType) => { switch (type) { case 'DATETIME': - return ( - - ); + return ; case 'DAYSONLY': - return ( - - ); + return ; } }; @@ -41,7 +39,13 @@ export default function MeetingRecommendCheckboxCard({ css={[s_baseContainer, s_optionContainer, s_getSelectedStyle(isSelected)]} onClick={onSelect} > - {renderRecommendCard(type)} +
+ + {renderRecommendCard(type)} +
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 index 09d581caf..9555a9c75 100644 --- a/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDateTime.tsx +++ b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDateTime.tsx @@ -1,16 +1,16 @@ +import type { MeetingRecommend } from '@apis/meetings/recommends'; + import { formatFullDate, formatTime } from '@utils/date'; -import type { RecommendCardProps } from '../MeetingRecommendCard'; -import { s_attendeeInfo, s_dateInfo, s_recommendContainer } from './RecommendSchedule.style'; +import { s_dateInfo, s_recommendContainer } from './RecommendSchedule.style'; + +interface RecommendDateTimeProps { + schedule: MeetingRecommend; +} -export default function RecommendCardDateTime({ - schedule, - totalAttendeeCount, -}: Omit) { - const { startDate, startDayOfWeek, startTime, endDate, endDayOfWeek, endTime, attendeeNames } = - schedule; +export default function RecommendDateTime({ schedule }: RecommendDateTimeProps) { + const { startDate, startDayOfWeek, startTime, endDate, endDayOfWeek, endTime } = schedule; - const currentAttendeeCount = attendeeNames.length; const startRecommendDate = formatFullDate({ fullDate: startDate, dayOfWeek: startDayOfWeek, @@ -25,7 +25,6 @@ export default function RecommendCardDateTime({ return (
- {`${totalAttendeeCount}명 중 ${currentAttendeeCount}명`} {`${startRecommendDate} ${formatTime(startTime)}`}부터 {`${endRecommendDate} ${formatTime(endTime)}`}까지
diff --git a/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDaysOnly.tsx b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDaysOnly.tsx index 9fa9220e6..4034a508a 100644 --- a/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDaysOnly.tsx +++ b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDaysOnly.tsx @@ -1,15 +1,18 @@ -import { formatFullDate } from '@utils/date'; +import { Fragment } from 'react'; -import type { RecommendCardProps } from '../MeetingRecommendCard'; -import { s_attendeeInfo, s_dateInfo, s_recommendContainer } from './RecommendSchedule.style'; +import type { MeetingRecommend } from '@apis/meetings/recommends'; -export default function RecommendCardDaysOnly({ - schedule, - totalAttendeeCount, -}: Omit) { - const { startDate, startDayOfWeek, endDate, endDayOfWeek, attendeeNames } = schedule; +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 currentAttendeeCount = attendeeNames.length; const startRecommendDate = formatFullDate({ fullDate: startDate, dayOfWeek: startDayOfWeek, @@ -24,9 +27,15 @@ export default function RecommendCardDaysOnly({ return (
- {`${totalAttendeeCount}명 중 ${currentAttendeeCount}명`} - {startRecommendDate}부터 - {endRecommendDate}까지 + {/* 만약 하루만 추천해준다면 "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 index 6a57efa4f..f72306a02 100644 --- a/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendSchedule.style.ts +++ b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendSchedule.style.ts @@ -5,7 +5,7 @@ import theme from '@styles/theme'; export const s_recommendContainer = css` display: flex; flex-direction: column; - gap: 1.2rem; + gap: 0.8rem; `; export const s_attendeeInfo = css` diff --git a/frontend/src/pages/MeetingConfirmPage/components/MeetingTimeOptions/index.tsx b/frontend/src/pages/MeetingConfirmPage/components/MeetingTimeOptions/index.tsx index ea604e5cd..9b9c825b6 100644 --- a/frontend/src/pages/MeetingConfirmPage/components/MeetingTimeOptions/index.tsx +++ b/frontend/src/pages/MeetingConfirmPage/components/MeetingTimeOptions/index.tsx @@ -5,9 +5,8 @@ import { s_attendeesContainer, s_tipInfo, } from '@pages/MeetingConfirmPage/MeetingTimeConfirmPage.styles'; -import MeetingTimeOptionCard from '@pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeOptionCard'; -import MeetingTimeOptionCardDaysOnly from '@pages/MeetingRecommendPage/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/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeCard.styles.ts b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeCard.styles.ts deleted file mode 100644 index 389cf0b1b..000000000 --- a/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeCard.styles.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { css } from '@emotion/react'; - -import theme from '@styles/theme'; - -export const s_baseContainer = css` - width: 100%; - height: 100%; - padding: 0.8rem 1.2rem; - - opacity: 0.7; - background-color: ${theme.colors.pink.light}; - border-radius: 0.8rem; -`; - -export const s_recommendContainer = css` - display: flex; - flex-direction: column; - gap: 1.2rem; -`; - -export const s_optionContainer = css` - display: flex; - align-items: center; - justify-content: space-between; - border: none; -`; - -export const s_getSelectedStyle = (isSelected: boolean) => css` - transition: - transform 0.2s ease-in-out, - opacity 0.2s ease-in-out; - - ${isSelected && - css` - z-index: 1; - transform: scale(1.02); - opacity: 0.9; - border: 1px solid ${theme.colors.primary}; - `}; -`; - -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; - justify-content: center; - height: 100%; -`; - -export const s_checkboxInput = css` - cursor: pointer; - - position: relative; - - display: flex; - align-items: center; - justify-content: center; - - width: 2rem; - height: 2rem; - - appearance: none; - background-color: transparent; - border: 2px solid ${theme.colors.grey.dark}; - border-radius: 0.4rem; - - transition: all 0.2s ease-in-out; - - &:checked { - background-color: ${theme.colors.primary}; - border-color: ${theme.colors.primary}; - } - - &:checked::after { - content: ''; - - position: absolute; - top: 40%; - left: 50%; - transform: translate(-50%, -50%) rotate(45deg); - - width: 0.6rem; - height: 1rem; - - border: solid white; - border-width: 0 2px 2px 0; - } -`; diff --git a/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeOptionCard.tsx b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeOptionCard.tsx deleted file mode 100644 index c6eac97fc..000000000 --- a/frontend/src/pages/MeetingRecommendPage/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/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeOptionCardDaysOnly.tsx b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeOptionCardDaysOnly.tsx deleted file mode 100644 index 222156500..000000000 --- a/frontend/src/pages/MeetingRecommendPage/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/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeRecommendCard.tsx b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeRecommendCard.tsx deleted file mode 100644 index aa97ecaea..000000000 --- a/frontend/src/pages/MeetingRecommendPage/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/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeRecommendCardDaysOnly.tsx b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeRecommendCardDaysOnly.tsx deleted file mode 100644 index f22c372bf..000000000 --- a/frontend/src/pages/MeetingRecommendPage/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/MeetingRecommendPage/components/MeetingTimeRecommends.tsx b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeRecommends.tsx index f1d5451de..acdf136e0 100644 --- a/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeRecommends.tsx +++ b/frontend/src/pages/MeetingRecommendPage/components/MeetingTimeRecommends.tsx @@ -1,6 +1,4 @@ -import MeetingTimeRecommendCard from '@pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeRecommendCard'; -import MeetingTimeRecommendCardDaysOnly from '@pages/MeetingRecommendPage/components/MeetingTimeCard/MeetingTimeRecommendCardDaysOnly'; - +import MeetingRecommendCard from '@components/MeetingRecommendCard/MeetingRecommendCard'; import TabButton from '@components/_common/Buttons/TabButton'; import Dropdown from '@components/_common/Dropdown'; @@ -26,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) => ( + + ))}
); } From 799f591fbe51e72385508296aa3c6d4f345beb72 Mon Sep 17 00:00:00 2001 From: Largopie Date: Tue, 31 Dec 2024 12:31:00 +0900 Subject: [PATCH 6/6] =?UTF-8?q?refactor:=20=EC=B6=94=EC=B2=9C=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=2030=EB=B6=84=20=EB=8B=A8=EC=9C=84=EB=8F=84=20?= =?UTF-8?q?=EB=B3=B4=EC=97=AC=EC=A3=BC=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RecommendSchedule/RecommendDateTime.tsx | 6 +++--- .../RecommendSchedule/RecommendSchedule.style.ts | 1 + frontend/src/utils/date.ts | 9 ++++++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDateTime.tsx b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDateTime.tsx index 9555a9c75..959eb1f7d 100644 --- a/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDateTime.tsx +++ b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendDateTime.tsx @@ -1,6 +1,6 @@ import type { MeetingRecommend } from '@apis/meetings/recommends'; -import { formatFullDate, formatTime } from '@utils/date'; +import { formatFullDate, formatTimeToKorean } from '@utils/date'; import { s_dateInfo, s_recommendContainer } from './RecommendSchedule.style'; @@ -25,8 +25,8 @@ export default function RecommendDateTime({ schedule }: RecommendDateTimeProps) return (
- {`${startRecommendDate} ${formatTime(startTime)}`}부터 - {`${endRecommendDate} ${formatTime(endTime)}`}까지 + {`${startRecommendDate} ${formatTimeToKorean(startTime)}`}부터 + {`${endRecommendDate} ${formatTimeToKorean(endTime)}`}까지
); } diff --git a/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendSchedule.style.ts b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendSchedule.style.ts index f72306a02..3bf35b502 100644 --- a/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendSchedule.style.ts +++ b/frontend/src/components/MeetingRecommendCard/RecommendSchedule/RecommendSchedule.style.ts @@ -4,6 +4,7 @@ import theme from '@styles/theme'; export const s_recommendContainer = css` display: flex; + align-items: flex-start; flex-direction: column; gap: 0.8rem; `; diff --git a/frontend/src/utils/date.ts b/frontend/src/utils/date.ts index 276a05ad5..72a2c7682 100644 --- a/frontend/src/utils/date.ts +++ b/frontend/src/utils/date.ts @@ -15,12 +15,15 @@ export const formatFullDate = ({ fullDate, dayOfWeek, format = 'standard' }: For return `${year}/${month}/${day}(${dayOfWeek})`; }; -// 오후 6시, 오전 3시 와 같은 형태로 반환 -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}시`; };