From fab5b305967fd84bd6cd375b4c0d1abd53db91a5 Mon Sep 17 00:00:00 2001 From: Jihyun Date: Sat, 2 Aug 2025 14:07:23 +0900 Subject: [PATCH 01/11] =?UTF-8?q?=E2=9C=A8=20[#210]=20Feat:=20MypageMain?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1,=20Header=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/what-today/src/components/Header.tsx | 2 +- .../src/components/MypageMainSideBar.tsx | 97 +++++++++++++++++++ .../src/pages/mypage/main/index.tsx | 52 ++++++++++ apps/what-today/src/routes/index.tsx | 4 +- .../src/components/MypageProfileHeader.tsx | 35 ++++++- .../design-system/src/components/index.ts | 4 + 6 files changed, 187 insertions(+), 7 deletions(-) create mode 100644 apps/what-today/src/components/MypageMainSideBar.tsx create mode 100644 apps/what-today/src/pages/mypage/main/index.tsx diff --git a/apps/what-today/src/components/Header.tsx b/apps/what-today/src/components/Header.tsx index 117edd9d..5634296c 100644 --- a/apps/what-today/src/components/Header.tsx +++ b/apps/what-today/src/components/Header.tsx @@ -31,7 +31,7 @@ export default function Header() {
- + {user?.profileImageUrl ? ( 프로필 이미지 void; +// /** +// * 클릭했을 때 sidebar 열림 여부 변경 +// */ +// onClick: () => void; +// /** +// * MypageSidebar의 열림 여부 +// */ +// isOpen: boolean; +// } + +/** + * MypageSidebar 컴포넌트 + * + * 사용자의 프로필 이미지와 마이페이지 관련 메뉴를 표시합니다. + * 현재 URL 경로에 따라 해당 메뉴 항목을 하이라이트 처리합니다. + * 로그아웃 버튼을 포함하며, 클릭 시 지정된 콜백을 실행합니다. + * + * @component + * @example + * setSidebarOpen((prev) => !prev)} + * onLogoutClick={() => alert('hi')} + * /> + */ +export default function MypageMainSidebar() { + const location = useLocation(); + + /** + * 사이드바에 표시할 고정 메뉴 항목 목록 + * 각 항목은 라벨, 아이콘 컴포넌트, 이동 경로로 구성됩니다. + */ + const items = [ + { icon: UserIcon, label: '내 정보', to: '/mypage/edit-profile' }, + { icon: ListIcon, label: '예약 내역', to: '/mypage/reservations-list' }, + { icon: SettingIcon, label: '내 체험 관리', to: '/mypage/manage-activities' }, + { icon: CalendarIcon, label: '예약 현황', to: '/mypage/reservations-status' }, + ]; + + return ( + + ); +} diff --git a/apps/what-today/src/pages/mypage/main/index.tsx b/apps/what-today/src/pages/mypage/main/index.tsx new file mode 100644 index 00000000..d92df79a --- /dev/null +++ b/apps/what-today/src/pages/mypage/main/index.tsx @@ -0,0 +1,52 @@ +import { + CalendarIcon, + ListIcon, + MypageProfileHeader, + SettingIcon, + UserIcon, + useToast, +} from '@what-today/design-system'; +import { useNavigate } from 'react-router-dom'; + +import MypageMainSidebar from '@/components/MypageMainSideBar'; +import useAuth from '@/hooks/useAuth'; +import { useWhatTodayStore } from '@/stores'; + +/** + * 사이드바에 표시할 고정 메뉴 항목 목록 + * 각 항목은 라벨, 아이콘 컴포넌트, 이동 경로로 구성됩니다. + */ +const items = [ + { icon: UserIcon, label: '내 정보', to: '/mypage/edit-profile' }, + { icon: ListIcon, label: '예약 내역', to: '/mypage/reservations-list' }, + { icon: SettingIcon, label: '내 체험 관리', to: '/mypage/manage-activities' }, + { icon: CalendarIcon, label: '예약 현황', to: '/mypage/reservations-status' }, +]; + +export default function MyPage() { + const navigate = useNavigate(); + const { logoutUser } = useAuth(); + const { user } = useWhatTodayStore(); + const { toast } = useToast(); + const handleLogout = () => { + logoutUser(); + toast({ + title: '로그아웃 성공', + description: '다음에 또 만나요! 👋🏻', + type: 'success', + }); + navigate('/login'); + }; + return ( +
+ +
+ +
+
+ ); +} diff --git a/apps/what-today/src/routes/index.tsx b/apps/what-today/src/routes/index.tsx index 52568f54..ae254f1b 100644 --- a/apps/what-today/src/routes/index.tsx +++ b/apps/what-today/src/routes/index.tsx @@ -10,6 +10,7 @@ import KakaoCallbackSignup from '@/pages/kakao-callback-signup'; import LoginPage from '@/pages/login'; import MainPage from '@/pages/main'; import EditProfilePage from '@/pages/mypage/edit-profile'; +import MyPage from '@/pages/mypage/main'; import ManageActivitiesPage from '@/pages/mypage/manage-activities'; import ReservationsListPage from '@/pages/mypage/reservations-list'; import ReservationsStatusPage from '@/pages/mypage/reservations-status'; @@ -39,12 +40,13 @@ export const router = createBrowserRouter([ { path: 'activities/:id', element: }, { path: 'experiences/create', element: }, { path: 'experiences/create/:id', element: }, + { path: 'mypage', element: }, // ✅ 여기만 별도로 { path: 'mypage', loader: authGuardLoader, element: , children: [ - { index: true, element: }, + // { index: true, element: }, { path: 'edit-profile', element: }, { path: 'reservations-list', element: }, { path: 'manage-activities', element: }, diff --git a/packages/design-system/src/components/MypageProfileHeader.tsx b/packages/design-system/src/components/MypageProfileHeader.tsx index b1213205..363defbe 100644 --- a/packages/design-system/src/components/MypageProfileHeader.tsx +++ b/packages/design-system/src/components/MypageProfileHeader.tsx @@ -1,13 +1,38 @@ -export default function MypageProfileHeader() { +import Button from './button'; +import { ExitIcon } from './icons'; +import { ProfileLogo } from './logos'; + +interface MypageProfileHeaderProps { + name?: string; + profileImageUrl?: string; + onLogoutClick: () => void; +} + +export default function MypageProfileHeader({ name, profileImageUrl, onLogoutClick }: MypageProfileHeaderProps) { return ( -
+
-
+ {profileImageUrl ? ( + 프로필 이미지 + ) : ( + + )}
-

멋쟁이 개발자 님

-

로그아웃

+

{name}

+
); diff --git a/packages/design-system/src/components/index.ts b/packages/design-system/src/components/index.ts index 14eb3611..dfa7bbb0 100644 --- a/packages/design-system/src/components/index.ts +++ b/packages/design-system/src/components/index.ts @@ -16,8 +16,11 @@ export { default as MainBanner } from './MainBanner/MainBanner'; export * from './MainCard'; export { default as MainSearchInput } from './MainSearchInput/MainSearchInput'; export * from './modal'; +export { default as MypageProfileHeader } from './MypageProfileHeader'; +export * from './MypageSummaryCard'; export { default as NoResult } from './NoResult'; export { default as NotificationCard } from './NotificationCard'; +export { default as OngoingExperienceCard } from './OngoingExperienceCard'; export { default as OwnerBadge } from './OwnerBadge'; export { default as Pagination } from './Pagination'; export * from './popover'; @@ -29,4 +32,5 @@ export * from './select'; export { default as StarRating } from './StarRating'; export { default as TimePicker } from './TimePicker'; export { Toaster, useToast } from './Toast'; +export { default as UpcomingSchedule } from './UpcomingSchedule'; export { default as UserBadge } from './UserBadge'; From 8f46d2de53096622050f63912b7a77e336123d27 Mon Sep 17 00:00:00 2001 From: Jihyun Date: Sat, 2 Aug 2025 15:37:13 +0900 Subject: [PATCH 02/11] =?UTF-8?q?=E2=9C=A8=20[#210]=20Feat:=20=EB=A7=88?= =?UTF-8?q?=EC=9D=B4=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EA=B8=B0=EB=B3=B8=20UI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/mypage/main/index.tsx | 51 ++++++++++++++++++- .../src/components/MypageProfileHeader.tsx | 2 +- .../src/components/UpcomingSchedule.tsx | 13 +++-- 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/apps/what-today/src/pages/mypage/main/index.tsx b/apps/what-today/src/pages/mypage/main/index.tsx index d92df79a..f93e5112 100644 --- a/apps/what-today/src/pages/mypage/main/index.tsx +++ b/apps/what-today/src/pages/mypage/main/index.tsx @@ -1,15 +1,22 @@ +import { useQuery } from '@tanstack/react-query'; import { CalendarIcon, ListIcon, MypageProfileHeader, + MypageSummaryCard, + OngoingExperienceCard, SettingIcon, + UpcomingSchedule, UserIcon, useToast, } from '@what-today/design-system'; import { useNavigate } from 'react-router-dom'; +import { fetchMyReservations } from '@/apis/myReservations'; import MypageMainSidebar from '@/components/MypageMainSideBar'; import useAuth from '@/hooks/useAuth'; +import { useInfiniteMyActivitiesQuery } from '@/hooks/useMyActivitiesQuery'; +import type { MyReservationsResponse } from '@/schemas/myReservations'; import { useWhatTodayStore } from '@/stores'; /** @@ -28,6 +35,20 @@ export default function MyPage() { const { logoutUser } = useAuth(); const { user } = useWhatTodayStore(); const { toast } = useToast(); + // 등록한 체험 갯수 + const { data: activityData } = useInfiniteMyActivitiesQuery(1); + // 완료한 체험 갯수 + const { data: completedData } = useQuery({ + queryKey: ['reservations'], + queryFn: () => + fetchMyReservations({ + cursorId: null, // 첫 페이지부터 가져옴 + size: 1000, // 충분히 큰 숫자로 설정 (전체 데이터 한 번에) + status: 'completed', // 완료된 체험만 받아오기 + }), + staleTime: 1000 * 30, + }); + const handleLogout = () => { logoutUser(); toast({ @@ -40,12 +61,40 @@ export default function MyPage() { return (
-
+
+
+ + + + + + + + +
+
+

다가오는 일정

+ +
+
+

모집 중인 체험

+ +
); diff --git a/packages/design-system/src/components/MypageProfileHeader.tsx b/packages/design-system/src/components/MypageProfileHeader.tsx index 363defbe..1ca8c2f6 100644 --- a/packages/design-system/src/components/MypageProfileHeader.tsx +++ b/packages/design-system/src/components/MypageProfileHeader.tsx @@ -10,7 +10,7 @@ interface MypageProfileHeaderProps { export default function MypageProfileHeader({ name, profileImageUrl, onLogoutClick }: MypageProfileHeaderProps) { return ( -
+
{profileImageUrl ? ( {date}

; } @@ -25,12 +27,15 @@ function ScheduleItem({ ); } -export default function UpcomingSchedule() { +interface UpcomingScheduleProps { + className?: string; +} +export default function UpcomingSchedule({ className }: UpcomingScheduleProps) { return ( -
+
-
-
+
+
From 2a566bfd8c645e0f62252be78e31b57bee0893d8 Mon Sep 17 00:00:00 2001 From: Jihyun Date: Sat, 2 Aug 2025 15:52:42 +0900 Subject: [PATCH 03/11] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20[#210]=20Refactor:?= =?UTF-8?q?=20=EB=A7=88=EC=9D=B4-=EB=A9=94=EC=9D=B8=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EA=B2=BD=EB=A1=9C=20=EB=B3=80=EA=B2=BD,=20sidebar?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/MypageSidebar.tsx | 20 ++++++------------- .../src/pages/mypage/main/index.tsx | 3 +-- apps/what-today/src/routes/index.tsx | 4 ++-- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/apps/what-today/src/components/MypageSidebar.tsx b/apps/what-today/src/components/MypageSidebar.tsx index 3dcc0ea1..191220c9 100644 --- a/apps/what-today/src/components/MypageSidebar.tsx +++ b/apps/what-today/src/components/MypageSidebar.tsx @@ -1,12 +1,4 @@ -import { - Button, - CalendarIcon, - ExitIcon, - ListIcon, - ProfileLogo, - SettingIcon, - UserIcon, -} from '@what-today/design-system'; +import { Button, CalendarIcon, ExitIcon, ListIcon, SettingIcon, UserIcon } from '@what-today/design-system'; import { Link, useLocation } from 'react-router-dom'; import { twMerge } from 'tailwind-merge'; @@ -15,7 +7,7 @@ interface MypageSidebarProps { * 사용자 프로필 이미지 URL * 전달되지 않을 경우 기본 아이콘(ProfileLogo)이 표시됩니다. */ - profileImgUrl?: string; + // profileImgUrl?: string; /** * 로그아웃 버튼 클릭 시 실행되는 콜백 함수(아마 모달을 띄우지 않을까 싶습니다.) */ @@ -46,7 +38,7 @@ interface MypageSidebarProps { * onLogoutClick={() => alert('hi')} * /> */ -export default function MypageSidebar({ profileImgUrl, onLogoutClick, onClick, isOpen }: MypageSidebarProps) { +export default function MypageSidebar({ onLogoutClick, onClick, isOpen }: MypageSidebarProps) { const location = useLocation(); /** @@ -66,7 +58,7 @@ export default function MypageSidebar({ profileImgUrl, onLogoutClick, onClick, i // 공통 스타일 'fixed z-50 max-w-200 min-w-200 rounded-2xl border border-gray-50 bg-white transition duration-300 md:static md:h-fit xl:w-280', // 모바일에서 Drawer 위치 - isOpen ? 'h-474 translate-x-0' : 'h-50 -translate-x-full bg-gray-200', + isOpen ? 'translate-x-0' : 'h-50 -translate-x-full bg-gray-200', 'md:translate-x-0', 'md:bg-white', )} @@ -79,7 +71,7 @@ export default function MypageSidebar({ profileImgUrl, onLogoutClick, onClick, i 'md:flex', )} > - {profileImgUrl ? ( + {/* {profileImgUrl ? ( 프로필 이미지 ) : ( - )} + )} */}
    {items.map(({ label, icon: Icon, to }) => { const isSelected = location.pathname === to; diff --git a/apps/what-today/src/pages/mypage/main/index.tsx b/apps/what-today/src/pages/mypage/main/index.tsx index f93e5112..ebd0de64 100644 --- a/apps/what-today/src/pages/mypage/main/index.tsx +++ b/apps/what-today/src/pages/mypage/main/index.tsx @@ -13,7 +13,6 @@ import { import { useNavigate } from 'react-router-dom'; import { fetchMyReservations } from '@/apis/myReservations'; -import MypageMainSidebar from '@/components/MypageMainSideBar'; import useAuth from '@/hooks/useAuth'; import { useInfiniteMyActivitiesQuery } from '@/hooks/useMyActivitiesQuery'; import type { MyReservationsResponse } from '@/schemas/myReservations'; @@ -60,7 +59,7 @@ export default function MyPage() { }; return (
    - + {/* */}
    }, { path: 'experiences/create', element: }, { path: 'experiences/create/:id', element: }, - { path: 'mypage', element: }, // ✅ 여기만 별도로 + // { path: 'mypage', element: }, // ✅ 여기만 별도로(다시 변경) { path: 'mypage', loader: authGuardLoader, element: , children: [ - // { index: true, element: }, + { index: true, element: }, { path: 'edit-profile', element: }, { path: 'reservations-list', element: }, { path: 'manage-activities', element: }, From a9163f1a1ea3da3d6c9a62a3bc27cd89dbd41eeb Mon Sep 17 00:00:00 2001 From: Jihyun Date: Sat, 2 Aug 2025 20:29:36 +0900 Subject: [PATCH 04/11] =?UTF-8?q?=E2=9C=A8=20[#210]=20Feat:=20=EB=A7=88?= =?UTF-8?q?=EC=9D=B4-=EB=A9=94=EC=9D=B4=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EB=8B=A4=EA=B0=80=EC=98=A4=EB=8A=94=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/mypage/main/index.tsx | 53 +++++++----- .../src/components/UpcomingSchedule.tsx | 82 +++++++++---------- 2 files changed, 70 insertions(+), 65 deletions(-) diff --git a/apps/what-today/src/pages/mypage/main/index.tsx b/apps/what-today/src/pages/mypage/main/index.tsx index ebd0de64..a79a1cf4 100644 --- a/apps/what-today/src/pages/mypage/main/index.tsx +++ b/apps/what-today/src/pages/mypage/main/index.tsx @@ -1,13 +1,9 @@ import { useQuery } from '@tanstack/react-query'; import { - CalendarIcon, - ListIcon, MypageProfileHeader, MypageSummaryCard, OngoingExperienceCard, - SettingIcon, UpcomingSchedule, - UserIcon, useToast, } from '@what-today/design-system'; import { useNavigate } from 'react-router-dom'; @@ -18,27 +14,24 @@ import { useInfiniteMyActivitiesQuery } from '@/hooks/useMyActivitiesQuery'; import type { MyReservationsResponse } from '@/schemas/myReservations'; import { useWhatTodayStore } from '@/stores'; -/** - * 사이드바에 표시할 고정 메뉴 항목 목록 - * 각 항목은 라벨, 아이콘 컴포넌트, 이동 경로로 구성됩니다. - */ -const items = [ - { icon: UserIcon, label: '내 정보', to: '/mypage/edit-profile' }, - { icon: ListIcon, label: '예약 내역', to: '/mypage/reservations-list' }, - { icon: SettingIcon, label: '내 체험 관리', to: '/mypage/manage-activities' }, - { icon: CalendarIcon, label: '예약 현황', to: '/mypage/reservations-status' }, -]; - export default function MyPage() { const navigate = useNavigate(); const { logoutUser } = useAuth(); const { user } = useWhatTodayStore(); const { toast } = useToast(); // 등록한 체험 갯수 - const { data: activityData } = useInfiniteMyActivitiesQuery(1); + const { data: activityData } = useInfiniteMyActivitiesQuery(1000); + const totalActivity = activityData?.pages[0]?.totalCount; + // 예약 승인 대기 갯수 + const activityIds = activityData?.pages.flatMap((page) => page.activities.map((activity) => activity.id)) ?? []; + // const { data: monthlyReservations = [] } = useMonthlyScheduleQuery({ + // activityId: activityIds[0], + // year: calendarYear, + // month: calendarMonth, + // }); // 완료한 체험 갯수 const { data: completedData } = useQuery({ - queryKey: ['reservations'], + queryKey: ['reservations', 'completed'], queryFn: () => fetchMyReservations({ cursorId: null, // 첫 페이지부터 가져옴 @@ -47,6 +40,22 @@ export default function MyPage() { }), staleTime: 1000 * 30, }); + // 완료한 체험 중 리뷰 미작성 갯수 + const reviewRequired = completedData?.reservations.filter((res) => res.reviewSubmitted === false).length ?? 0; + + // 다가오는 체험 데이터 + const { data: confirmedData } = useQuery({ + queryKey: ['reservations', 'confirmed'], + queryFn: () => + fetchMyReservations({ + cursorId: null, // 첫 페이지부터 가져옴 + size: 1000, // 충분히 큰 숫자로 설정 (전체 데이터 한 번에) + status: 'confirmed', // 확정된 체험만 받아오기 + }), + staleTime: 1000 * 30, + }); + console.log(activityData); + console.log(activityIds); const handleLogout = () => { logoutUser(); @@ -68,7 +77,7 @@ export default function MyPage() { />
    - + @@ -79,18 +88,18 @@ export default function MyPage() { labelClassName='text-gray-200' />
    -
    +

    다가오는 일정

    - +
    -
    +

    모집 중인 체험

    diff --git a/packages/design-system/src/components/UpcomingSchedule.tsx b/packages/design-system/src/components/UpcomingSchedule.tsx index 92363020..a18f8e59 100644 --- a/packages/design-system/src/components/UpcomingSchedule.tsx +++ b/packages/design-system/src/components/UpcomingSchedule.tsx @@ -6,21 +6,27 @@ function ScheduleDateLabel({ date }: { date: string }) { function ScheduleItem({ title, - date, - location, + price, + headCount, + time, src, }: { title: string; - date: string; - location?: string; + price: number; + headCount: string; + time: string; src?: string; }) { return (

    {title}

    -

    {date}

    -

    {location}

    + +

    {time}

    +
    +

    ₩{price.toLocaleString()}

    +

    {headCount}명

    +
    @@ -29,46 +35,36 @@ function ScheduleItem({ interface UpcomingScheduleProps { className?: string; + reservation: Record[]; } -export default function UpcomingSchedule({ className }: UpcomingScheduleProps) { +export default function UpcomingSchedule({ className, reservation }: UpcomingScheduleProps) { return ( -
    -
    -
    +
    + {/*
    +
    -
    - -
    -
    - - - - -
    -
    - - -
    +
    */} +
    + {(() => { + let prevDate: string | null = null; + return reservation.map((res, idx) => { + const showDateLabel = res.date !== prevDate; + const isLast = idx === reservation.length - 1; + prevDate = res.date; + return ( +
    + {showDateLabel && } + +
    + ); + }); + })()}
    ); From cd00b994f27cc61c0523009f3b2ae74f1e4ae02c Mon Sep 17 00:00:00 2001 From: Jihyun Date: Sat, 2 Aug 2025 21:40:17 +0900 Subject: [PATCH 05/11] =?UTF-8?q?=E2=9C=A8=20[#210]=20Feat:=20=EB=A7=88?= =?UTF-8?q?=EC=9D=B4-=EB=A9=94=EC=9D=B8=ED=8E=98=EC=9D=B4=EC=A7=80=20Summa?= =?UTF-8?q?ryCard=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/mypage/main/index.tsx | 25 +++++---- .../src/components/UpcomingSchedule.tsx | 54 +++++++++++-------- 2 files changed, 49 insertions(+), 30 deletions(-) diff --git a/apps/what-today/src/pages/mypage/main/index.tsx b/apps/what-today/src/pages/mypage/main/index.tsx index a79a1cf4..44cc2b11 100644 --- a/apps/what-today/src/pages/mypage/main/index.tsx +++ b/apps/what-today/src/pages/mypage/main/index.tsx @@ -6,11 +6,13 @@ import { UpcomingSchedule, useToast, } from '@what-today/design-system'; +import dayjs from 'dayjs'; import { useNavigate } from 'react-router-dom'; import { fetchMyReservations } from '@/apis/myReservations'; +import { useInfiniteMyActivitiesQuery } from '@/hooks/myActivity/useMyActivitiesQuery'; +import { useMonthlyScheduleQuery } from '@/hooks/myReservation/useMonthlyScheduleQuery'; import useAuth from '@/hooks/useAuth'; -import { useInfiniteMyActivitiesQuery } from '@/hooks/useMyActivitiesQuery'; import type { MyReservationsResponse } from '@/schemas/myReservations'; import { useWhatTodayStore } from '@/stores'; @@ -23,12 +25,17 @@ export default function MyPage() { const { data: activityData } = useInfiniteMyActivitiesQuery(1000); const totalActivity = activityData?.pages[0]?.totalCount; // 예약 승인 대기 갯수 - const activityIds = activityData?.pages.flatMap((page) => page.activities.map((activity) => activity.id)) ?? []; - // const { data: monthlyReservations = [] } = useMonthlyScheduleQuery({ - // activityId: activityIds[0], - // year: calendarYear, - // month: calendarMonth, - // }); + const activityIds = + activityData?.pages.flatMap((page: { activities: { id: number }[] }) => + page.activities.map((activity) => activity.id), + ) ?? []; + const { data: monthlyReservations = [] } = useMonthlyScheduleQuery({ + activityId: activityIds[0], + year: dayjs().format('YYYY'), + month: dayjs().format('MM'), + }); + const totalPending = monthlyReservations.reduce((sum, item) => sum + item.reservations.pending, 0); + console.log(monthlyReservations); // 완료한 체험 갯수 const { data: completedData } = useQuery({ queryKey: ['reservations', 'completed'], @@ -78,7 +85,7 @@ export default function MyPage() {
    - +
    -
    +

    다가오는 일정

    diff --git a/packages/design-system/src/components/UpcomingSchedule.tsx b/packages/design-system/src/components/UpcomingSchedule.tsx index a18f8e59..50e82907 100644 --- a/packages/design-system/src/components/UpcomingSchedule.tsx +++ b/packages/design-system/src/components/UpcomingSchedule.tsx @@ -1,5 +1,8 @@ import { twMerge } from 'tailwind-merge'; +import Button from './button'; +import { EmptyLogo } from './logos'; + function ScheduleDateLabel({ date }: { date: string }) { return

    {date}

    ; } @@ -39,32 +42,41 @@ interface UpcomingScheduleProps { } export default function UpcomingSchedule({ className, reservation }: UpcomingScheduleProps) { return ( -
    +
    {/*
    */}
    - {(() => { - let prevDate: string | null = null; - return reservation.map((res, idx) => { - const showDateLabel = res.date !== prevDate; - const isLast = idx === reservation.length - 1; - prevDate = res.date; - return ( -
    - {showDateLabel && } - -
    - ); - }); - })()} + {reservation.length === 0 ? ( +
    + + +
    + ) : ( + (() => { + let prevDate: string | null = null; + return reservation.map((res, idx) => { + const showDateLabel = res.date !== prevDate; + const isLast = idx === reservation.length - 1; + prevDate = res.date; + return ( +
    + {showDateLabel && } + +
    + ); + }); + })() + )}
    ); From 461d9f9dd971c3945f5cd5f1d310dd00189c3bb2 Mon Sep 17 00:00:00 2001 From: Jihyun Date: Sun, 3 Aug 2025 01:31:35 +0900 Subject: [PATCH 06/11] =?UTF-8?q?=E2=9C=A8=20[#210]=20Feat:=20=EB=AA=A8?= =?UTF-8?q?=EC=A7=91=20=EC=A4=91=EC=9D=B8=20=EC=B2=B4=ED=97=98=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/what-today/src/apis/activityDetail.ts | 26 ++++++- apps/what-today/src/layouts/Mypage.tsx | 2 +- .../src/pages/mypage/main/index.tsx | 69 +++++++++++++++---- apps/what-today/src/schemas/activities.ts | 23 +++++++ .../src/components/OngoingExperienceCard.tsx | 30 +++++--- .../src/components/UpcomingSchedule.tsx | 2 +- 6 files changed, 125 insertions(+), 27 deletions(-) diff --git a/apps/what-today/src/apis/activityDetail.ts b/apps/what-today/src/apis/activityDetail.ts index 99d6476e..bdb9465c 100644 --- a/apps/what-today/src/apis/activityDetail.ts +++ b/apps/what-today/src/apis/activityDetail.ts @@ -1,4 +1,9 @@ -import { type ActivityWithSubImagesAndSchedules, activityWithSubImagesAndSchedulesSchema } from '@/schemas/activities'; +import { + type ActivityWithSubImagesAndSchedules, + activityWithSubImagesAndSchedulesSchema, + type Schedules, + schedulesSchema, +} from '@/schemas/activities'; import { type ActivityReviewsResponse, activityReviewsResponseSchema } from '@/schemas/activityReview'; import { type CreateReservationBodyDto, @@ -55,3 +60,22 @@ export const createReservation = async ( const response = await axiosInstance.post(`/activities/${activityId}/reservations`, body); return reservationResponseSchema.parse(response.data); }; + +// ✅ 체험 예약 가능일 리스트 조회 시 사용되는 파라미터 타입 +export interface ReservationAvailableScheduleParams { + year: string; + month: string; +} + +/** + * @description 체험 예약 가능일 리스트를 불러옵니다. + * @param activityId 체험 ID + * @returns ActivityWithSubImagesAndSchedules 타입의 체험 상세 데이터 + */ +export const fetchReservationAvailableSchedule = async ( + activityId: number, + params: ReservationAvailableScheduleParams, +): Promise => { + const response = await axiosInstance.get(`/activities/${activityId}/available-schedule`, { params }); + return schedulesSchema.parse(response.data); +}; diff --git a/apps/what-today/src/layouts/Mypage.tsx b/apps/what-today/src/layouts/Mypage.tsx index 0b4be6ab..a58748c8 100644 --- a/apps/what-today/src/layouts/Mypage.tsx +++ b/apps/what-today/src/layouts/Mypage.tsx @@ -37,7 +37,7 @@ export default function MyPageLayout() { )} setSidebarOpen((prev) => !prev)} onLogoutClick={handleLogout} /> diff --git a/apps/what-today/src/pages/mypage/main/index.tsx b/apps/what-today/src/pages/mypage/main/index.tsx index 44cc2b11..71772a4c 100644 --- a/apps/what-today/src/pages/mypage/main/index.tsx +++ b/apps/what-today/src/pages/mypage/main/index.tsx @@ -1,4 +1,4 @@ -import { useQuery } from '@tanstack/react-query'; +import { useQueries, useQuery } from '@tanstack/react-query'; import { MypageProfileHeader, MypageSummaryCard, @@ -9,10 +9,12 @@ import { import dayjs from 'dayjs'; import { useNavigate } from 'react-router-dom'; +import { fetchReservationAvailableSchedule } from '@/apis/activityDetail'; +import { getMonthlySchedule } from '@/apis/myActivities'; import { fetchMyReservations } from '@/apis/myReservations'; import { useInfiniteMyActivitiesQuery } from '@/hooks/myActivity/useMyActivitiesQuery'; -import { useMonthlyScheduleQuery } from '@/hooks/myReservation/useMonthlyScheduleQuery'; import useAuth from '@/hooks/useAuth'; +import type { monthlyScheduleResponse } from '@/schemas/myActivities'; import type { MyReservationsResponse } from '@/schemas/myReservations'; import { useWhatTodayStore } from '@/stores'; @@ -21,21 +23,32 @@ export default function MyPage() { const { logoutUser } = useAuth(); const { user } = useWhatTodayStore(); const { toast } = useToast(); + + const year = dayjs().format('YYYY'); + const month = dayjs().format('MM'); + // 등록한 체험 갯수 const { data: activityData } = useInfiniteMyActivitiesQuery(1000); const totalActivity = activityData?.pages[0]?.totalCount; - // 예약 승인 대기 갯수 + + // 이번달 예약 승인 대기 갯수 const activityIds = activityData?.pages.flatMap((page: { activities: { id: number }[] }) => page.activities.map((activity) => activity.id), ) ?? []; - const { data: monthlyReservations = [] } = useMonthlyScheduleQuery({ - activityId: activityIds[0], - year: dayjs().format('YYYY'), - month: dayjs().format('MM'), + + const monthlyReservationsResults = useQueries({ + queries: activityIds.map((id) => ({ + queryKey: ['monthlySchedule', id, year, month], + queryFn: () => getMonthlySchedule(id, { year, month }), + enabled: !!id, + })), }); - const totalPending = monthlyReservations.reduce((sum, item) => sum + item.reservations.pending, 0); - console.log(monthlyReservations); + const monthlyReservations = monthlyReservationsResults + .map((result) => result.data) + .filter(Boolean) as monthlyScheduleResponse[]; + const totalPending = monthlyReservations.flat().reduce((sum, item) => sum + item.reservations.pending, 0); + // 완료한 체험 갯수 const { data: completedData } = useQuery({ queryKey: ['reservations', 'completed'], @@ -47,6 +60,7 @@ export default function MyPage() { }), staleTime: 1000 * 30, }); + // 완료한 체험 중 리뷰 미작성 갯수 const reviewRequired = completedData?.reservations.filter((res) => res.reviewSubmitted === false).length ?? 0; @@ -61,8 +75,35 @@ export default function MyPage() { }), staleTime: 1000 * 30, }); - console.log(activityData); + + // 이번 달 모집 중인 체험 + const reservationAvailableResults = useQueries({ + queries: activityIds.map((id) => ({ + queryKey: ['availableSchedule', id, year, month], + queryFn: () => { + console.log('fetchReservationAvailableSchedule 실행됨', id, year, month); + return fetchReservationAvailableSchedule(id, { year, month }); + }, + enabled: !!id, + })), + }); + const reservationAvailableDataList = reservationAvailableResults + .map((result) => result.data) // result: { data, isLoading, isError, ... } + .filter(Boolean); // undefined 제거 + const availableActivityIds = reservationAvailableResults + .map((result, index) => ({ data: result.data, activityId: activityIds[index] })) + .filter(({ data }) => Array.isArray(data) && data.length > 0) + .map(({ activityId }) => activityId); + // 1. useInfiniteMyActivitiesQuery에서 받은 모든 pages를 펼침 + const allActivities = activityData?.pages.flatMap((page) => page.activities) ?? []; + + // 2. 예약 가능 activityId와 일치하는 항목만 필터링 + const availableActivities = allActivities.filter((activity) => availableActivityIds.includes(activity.id)); + console.log(activityIds); + console.log(reservationAvailableDataList); + console.log(availableActivityIds); + console.log(availableActivities); const handleLogout = () => { logoutUser(); @@ -104,11 +145,11 @@ export default function MyPage() {

    다가오는 일정

    - +
    -
    -

    모집 중인 체험

    - +
    +

    {`${dayjs().format('M')}월 모집 중인 체험`}

    +
    diff --git a/apps/what-today/src/schemas/activities.ts b/apps/what-today/src/schemas/activities.ts index 862fa37f..3672475a 100644 --- a/apps/what-today/src/schemas/activities.ts +++ b/apps/what-today/src/schemas/activities.ts @@ -37,6 +37,28 @@ export const scheduleSchema = z.object({ endTime: z.string().regex(/^\d{2}:\d{2}$/, 'HH:MM 형식이어야 합니다'), }); +/** + * @description 항목 스키마 + */ +export const timeSchema = z.object({ + id: z.number().int().positive(), + startTime: z.string().regex(/^\d{2}:\d{2}$/, 'HH:MM 형식이어야 합니다'), + endTime: z.string().regex(/^\d{2}:\d{2}$/, 'HH:MM 형식이어야 합니다'), +}); + +/** + * @description 스케줄 항목 스키마 + */ +const scheduleResponseSchema = z.object({ + date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'YYYY-MM-DD 형식이어야 합니다'), + times: z.array(timeSchema), +}); + +/** + * @description 스케줄 리스트 스키마 + */ +export const schedulesSchema = z.array(scheduleResponseSchema); + /** * @description subImages와 schedules를 포함한 확장 스키마 */ @@ -48,4 +70,5 @@ export const activityWithSubImagesAndSchedulesSchema = activitySchema.extend({ export type Activity = z.infer; export type SubImage = z.infer; export type Schedule = z.infer; +export type Schedules = z.infer; export type ActivityWithSubImagesAndSchedules = z.infer; diff --git a/packages/design-system/src/components/OngoingExperienceCard.tsx b/packages/design-system/src/components/OngoingExperienceCard.tsx index d009a9a7..35dca2bb 100644 --- a/packages/design-system/src/components/OngoingExperienceCard.tsx +++ b/packages/design-system/src/components/OngoingExperienceCard.tsx @@ -1,14 +1,24 @@ -export default function OngoingExperienceCard() { +import { twMerge } from 'tailwind-merge'; + +interface OngoingExperienceCardProps { + activities: Record[]; + className: string; +} + +export default function OngoingExperienceCard({ activities, className }: OngoingExperienceCardProps) { return ( -
    - -
    -

    도라에몽ㅇ도라에몽 도라에몽ㅇ도라에몽ㅇ

    -

    w 3,000,000 / 인

    -
    +
    + {activities.map((act) => { + return ( +
    + +
    +

    {act.title}

    +

    ₩{act.price.toLocaleString()} / 인

    +
    +
    + ); + })}
    ); } diff --git a/packages/design-system/src/components/UpcomingSchedule.tsx b/packages/design-system/src/components/UpcomingSchedule.tsx index 50e82907..2b8be29a 100644 --- a/packages/design-system/src/components/UpcomingSchedule.tsx +++ b/packages/design-system/src/components/UpcomingSchedule.tsx @@ -49,7 +49,7 @@ export default function UpcomingSchedule({ className, reservation }: UpcomingSch
    */}
    {reservation.length === 0 ? ( -
    +
    -
    +

    다가오는 일정

    - + navigate('/')} + onClickReservation={(id) => navigate(`/activities/${id}`)} + />

    {`${dayjs().format('M')}월 모집 중인 체험`}

    - + navigate('/experiences/create')} + onClickActivity={(id) => navigate(`/activities/${id}`)} + />
    diff --git a/packages/design-system/src/components/OngoingExperienceCard.tsx b/packages/design-system/src/components/OngoingExperienceCard.tsx index 35dca2bb..ac387e94 100644 --- a/packages/design-system/src/components/OngoingExperienceCard.tsx +++ b/packages/design-system/src/components/OngoingExperienceCard.tsx @@ -1,24 +1,44 @@ import { twMerge } from 'tailwind-merge'; +import Button from './button'; +import { EmptyLogo } from './logos'; + interface OngoingExperienceCardProps { + className?: string; activities: Record[]; - className: string; + onClickActivity: (id: number) => void; + onClick: () => void; } -export default function OngoingExperienceCard({ activities, className }: OngoingExperienceCardProps) { +export default function OngoingExperienceCard({ + className, + activities, + onClickActivity, + onClick, +}: OngoingExperienceCardProps) { + const flex = activities.length === 0 ? 'justify-center' : ''; return ( -
    - {activities.map((act) => { - return ( -
    - -
    -

    {act.title}

    -

    ₩{act.price.toLocaleString()} / 인

    +
    + {activities.length === 0 ? ( +
    + + +
    + ) : ( + activities.map((act) => { + return ( +
    onClickActivity(act.id)}> + +
    +

    {act.title}

    +

    ₩{act.price.toLocaleString()} / 인

    +
    -
    - ); - })} + ); + }) + )}
    ); } diff --git a/packages/design-system/src/components/UpcomingSchedule.tsx b/packages/design-system/src/components/UpcomingSchedule.tsx index 2b8be29a..680f30f9 100644 --- a/packages/design-system/src/components/UpcomingSchedule.tsx +++ b/packages/design-system/src/components/UpcomingSchedule.tsx @@ -39,19 +39,27 @@ function ScheduleItem({ interface UpcomingScheduleProps { className?: string; reservation: Record[]; + onClickReservation: (id: number) => void; + onClick?: () => void; } -export default function UpcomingSchedule({ className, reservation }: UpcomingScheduleProps) { +export default function UpcomingSchedule({ + className, + reservation, + onClickReservation, + onClick, +}: UpcomingScheduleProps) { + const flex = reservation.length === 0 ? 'justify-center' : ''; return ( -
    +
    {/*
    */}
    {reservation.length === 0 ? ( -
    +
    -
    @@ -63,7 +71,11 @@ export default function UpcomingSchedule({ className, reservation }: UpcomingSch const isLast = idx === reservation.length - 1; prevDate = res.date; return ( -
    +
    onClickReservation(res.activity.id)} + > {showDateLabel && } Date: Sun, 3 Aug 2025 11:18:39 +0900 Subject: [PATCH 08/11] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20[#210]=20Refactor:?= =?UTF-8?q?=20=EB=A7=88=EC=9D=B4-=EB=A9=94=EC=9D=B8=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EA=B0=95=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/what-today/src/pages/mypage/main/index.tsx | 10 +++++----- .../src/components/OngoingExperienceCard.tsx | 9 ++++++++- .../src/components/UpcomingSchedule.tsx | 16 +++++++++++++--- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/apps/what-today/src/pages/mypage/main/index.tsx b/apps/what-today/src/pages/mypage/main/index.tsx index eed954aa..009108d5 100644 --- a/apps/what-today/src/pages/mypage/main/index.tsx +++ b/apps/what-today/src/pages/mypage/main/index.tsx @@ -24,11 +24,12 @@ export default function MyPage() { const { user } = useWhatTodayStore(); const { toast } = useToast(); + const MAX_PAGE_SIZE = 1000; const year = dayjs().format('YYYY'); const month = dayjs().format('MM'); // 등록한 체험 갯수 - const { data: activityData } = useInfiniteMyActivitiesQuery(1000); + const { data: activityData } = useInfiniteMyActivitiesQuery(MAX_PAGE_SIZE); const totalActivity = activityData?.pages[0]?.totalCount; // 이번달 예약 승인 대기 갯수 @@ -47,7 +48,7 @@ export default function MyPage() { const monthlyReservations = monthlyReservationsResults .map((result) => result.data) .filter(Boolean) as monthlyScheduleResponse[]; - const totalPending = monthlyReservations.flat().reduce((sum, item) => sum + item.reservations.pending, 0); + const totalPending = monthlyReservations.flat().reduce((sum, item) => sum + item.reservations.pending || 0, 0); // 완료한 체험 갯수 const { data: completedData } = useQuery({ @@ -55,7 +56,7 @@ export default function MyPage() { queryFn: () => fetchMyReservations({ cursorId: null, // 첫 페이지부터 가져옴 - size: 1000, // 충분히 큰 숫자로 설정 (전체 데이터 한 번에) + size: MAX_PAGE_SIZE, // 충분히 큰 숫자로 설정 (전체 데이터 한 번에) status: 'completed', // 완료된 체험만 받아오기 }), staleTime: 1000 * 30, @@ -70,7 +71,7 @@ export default function MyPage() { queryFn: () => fetchMyReservations({ cursorId: null, // 첫 페이지부터 가져옴 - size: 1000, // 충분히 큰 숫자로 설정 (전체 데이터 한 번에) + size: MAX_PAGE_SIZE, // 충분히 큰 숫자로 설정 (전체 데이터 한 번에) status: 'confirmed', // 확정된 체험만 받아오기 }), staleTime: 1000 * 30, @@ -92,7 +93,6 @@ export default function MyPage() { .map(({ activityId }) => activityId); // 1. useInfiniteMyActivitiesQuery에서 받은 모든 pages를 펼침 const allActivities = activityData?.pages.flatMap((page) => page.activities) ?? []; - // 2. 예약 가능 activityId와 일치하는 항목만 필터링 const availableActivities = allActivities.filter((activity) => availableActivityIds.includes(activity.id)); diff --git a/packages/design-system/src/components/OngoingExperienceCard.tsx b/packages/design-system/src/components/OngoingExperienceCard.tsx index ac387e94..da9fb87a 100644 --- a/packages/design-system/src/components/OngoingExperienceCard.tsx +++ b/packages/design-system/src/components/OngoingExperienceCard.tsx @@ -3,9 +3,16 @@ import { twMerge } from 'tailwind-merge'; import Button from './button'; import { EmptyLogo } from './logos'; +interface Activity { + id: number; + bannerImageUrl: string; + title: string; + price: number; +} + interface OngoingExperienceCardProps { className?: string; - activities: Record[]; + activities: Activity[]; onClickActivity: (id: number) => void; onClick: () => void; } diff --git a/packages/design-system/src/components/UpcomingSchedule.tsx b/packages/design-system/src/components/UpcomingSchedule.tsx index 680f30f9..27b82d94 100644 --- a/packages/design-system/src/components/UpcomingSchedule.tsx +++ b/packages/design-system/src/components/UpcomingSchedule.tsx @@ -16,7 +16,7 @@ function ScheduleItem({ }: { title: string; price: number; - headCount: string; + headCount: number; time: string; src?: string; }) { @@ -31,14 +31,24 @@ function ScheduleItem({

    {headCount}명

    - + 체험 베너 이미지
    ); } +interface Reservation { + id: number; + activity: { id: number; title: string; bannerImageUrl: string }; + date: string; + headCount: number; + totalPrice: number; + startTime: string; + endTime: string; +} + interface UpcomingScheduleProps { className?: string; - reservation: Record[]; + reservation: Reservation[]; onClickReservation: (id: number) => void; onClick?: () => void; } From c620d2e9ad8e683bb21972df11e23bfc37823ecf Mon Sep 17 00:00:00 2001 From: Jihyun Date: Sun, 3 Aug 2025 15:00:42 +0900 Subject: [PATCH 09/11] =?UTF-8?q?=F0=9F=94=A8=20[#210]=20Fix:=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/what-today/src/routes/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/what-today/src/routes/index.tsx b/apps/what-today/src/routes/index.tsx index 8f4e0560..4086e06c 100644 --- a/apps/what-today/src/routes/index.tsx +++ b/apps/what-today/src/routes/index.tsx @@ -43,7 +43,6 @@ export const router = createBrowserRouter([ children: [ { path: 'experiences/create', element: }, { path: 'experiences/create/:id', element: }, - // { path: 'mypage', element: }, // ✅ 여기만 별도로(다시 변경) ], }, { From 1be2c37a5e3dbc50e212ea98b16682596a1e5e62 Mon Sep 17 00:00:00 2001 From: Jihyun Date: Sun, 3 Aug 2025 15:08:17 +0900 Subject: [PATCH 10/11] =?UTF-8?q?=F0=9F=93=9D=20[#210]=20Docs:=20=EB=94=94?= =?UTF-8?q?=EC=9E=90=EC=9D=B8=20=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/design-system/src/pages/MypageProfileHeaderDoc.tsx | 2 +- .../design-system/src/pages/OngoingExperienceCardDoc.tsx | 6 +++--- packages/design-system/src/pages/UpcomingScheduleDoc.tsx | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/design-system/src/pages/MypageProfileHeaderDoc.tsx b/packages/design-system/src/pages/MypageProfileHeaderDoc.tsx index 101098e0..a33baaa2 100644 --- a/packages/design-system/src/pages/MypageProfileHeaderDoc.tsx +++ b/packages/design-system/src/pages/MypageProfileHeaderDoc.tsx @@ -25,7 +25,7 @@ export default function MypageProfileHeaderDoc() { {/* 예시 코드 */} Click me`} /> - + {}} /> ); } diff --git a/packages/design-system/src/pages/OngoingExperienceCardDoc.tsx b/packages/design-system/src/pages/OngoingExperienceCardDoc.tsx index af9eb939..d4415456 100644 --- a/packages/design-system/src/pages/OngoingExperienceCardDoc.tsx +++ b/packages/design-system/src/pages/OngoingExperienceCardDoc.tsx @@ -26,9 +26,9 @@ export default function OngoingExperienceCardDoc() { Click me`} />
    - - - + {}} onClickActivity={() => {}} /> + {}} onClickActivity={() => {}} /> + {}} onClickActivity={() => {}} />
    ); diff --git a/packages/design-system/src/pages/UpcomingScheduleDoc.tsx b/packages/design-system/src/pages/UpcomingScheduleDoc.tsx index 7e42a5a1..b205cf0b 100644 --- a/packages/design-system/src/pages/UpcomingScheduleDoc.tsx +++ b/packages/design-system/src/pages/UpcomingScheduleDoc.tsx @@ -26,7 +26,7 @@ export default function UpcomingScheduleDoc() { {/* 예시 코드 */} Click me`} /> - + {}} /> ); } From 02f9df562e0ccd5b3d2e5c679781805611170c43 Mon Sep 17 00:00:00 2001 From: Jihyun Date: Sun, 3 Aug 2025 15:10:40 +0900 Subject: [PATCH 11/11] =?UTF-8?q?=F0=9F=94=A8=20[#210]=20Fix:=20=EB=AF=B8?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=20=EB=B3=80=EC=88=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/what-today/src/layouts/Mypage.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/what-today/src/layouts/Mypage.tsx b/apps/what-today/src/layouts/Mypage.tsx index a58748c8..8112c68e 100644 --- a/apps/what-today/src/layouts/Mypage.tsx +++ b/apps/what-today/src/layouts/Mypage.tsx @@ -5,14 +5,12 @@ import { twMerge } from 'tailwind-merge'; import MypageSidebar from '@/components/MypageSidebar'; import useAuth from '@/hooks/useAuth'; -import { useWhatTodayStore } from '@/stores'; export default function MyPageLayout() { const location = useLocation(); const navigate = useNavigate(); const [isSidebarOpen, setSidebarOpen] = useState(false); const { logoutUser } = useAuth(); - const { user } = useWhatTodayStore(); const { toast } = useToast(); const handleLogout = () => {