Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Button } from '@what-today/design-system';
import { useQueryClient } from '@tanstack/react-query';
import { Button, useToast } from '@what-today/design-system';

import CalendarSelector from './CalendarSelector';
import HeadCountSelector from './HeadCountSelector';
Expand All @@ -7,17 +8,40 @@ import TimeSelector from './TimeSelector';
import type { ReservationFormProps } from './types';

export default function ReservationForm({
activityId,
schedules,
price,
onReservationChange,
onSubmit,
showSubmitButton = false,
showSubmitButton = true,
isSubmitting: externalIsSubmitting,
isAuthor = false,
isLoggedIn = true,
}: ReservationFormProps) {
const { toast } = useToast();
const queryClient = useQueryClient();

const reservation = useReservation(schedules, price, {
onReservationChange,
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ['reservations'],
});

toast({
title: '예약 완료',
description: '마이페이지에서 예약을 확인해보세요!',
type: 'success',
});
},
onError: (error) => {
const errorMessage = error instanceof Error ? error.message : '예약 중 오류가 발생했습니다.';
toast({
title: '예약 실패',
description: errorMessage,
type: 'error',
});
},
});

const {
Expand All @@ -33,18 +57,25 @@ export default function ReservationForm({
totalPrice,
isReadyToReserve,
isSubmitting: internalIsSubmitting,
submitReservation,
} = reservation;

// 외부에서 전달받은 isSubmitting을 우선시
const isSubmitting = externalIsSubmitting ?? internalIsSubmitting;

const handleSubmit = async () => {
if (!onSubmit || !selectedScheduleId) return;
if (!selectedScheduleId) return;

await onSubmit({
scheduleId: selectedScheduleId,
headCount,
});
// onSubmit이 있으면 기존 방식 사용 (하위 호환성)
if (onSubmit) {
await onSubmit({
scheduleId: selectedScheduleId,
headCount,
});
} else {
// 기본 방식: submitReservation 사용 (자동 초기화)
await submitReservation(activityId);
}
};

// 버튼 텍스트 결정
Expand All @@ -54,7 +85,7 @@ export default function ReservationForm({
else if (isAuthor) buttonText = '예약 불가';
else buttonText = '예약하기';

return (
const content = (
<div className='flex flex-col gap-24'>
{/* 가격 표시 */}
<p className='text-xl text-[#79747E]'>
Expand Down Expand Up @@ -98,4 +129,10 @@ export default function ReservationForm({
</div>
</div>
);

return (
<section className='flex flex-col justify-between rounded-3xl border border-[#DDDDDD] p-30 shadow-sm'>
{content}
</section>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export interface UseReservationReturn {
}

export interface ReservationFormProps {
activityId: number;
schedules: Schedule[];
price: number;
onReservationChange?: (summary: ReservationSummary | null) => void;
Expand All @@ -60,14 +61,6 @@ export interface ReservationFormProps {
isLoggedIn?: boolean;
}

export interface DesktopReservationProps {
activityId: number;
price: number;
schedules: Schedule[];
isAuthor?: boolean;
isLoggedIn?: boolean;
}

export interface TabletReservationSheetProps {
schedules: Schedule[];
price: number;
Expand Down
2 changes: 1 addition & 1 deletion apps/what-today/src/layouts/DefaultLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default function DefaultLayout() {
const footerMarginBottom = isActivityDetailPage && !isDesktop ? 'w-full mb-125' : 'w-full';

// FloatingTranslateButton의 bottom 위치 조건부 설정
const floatingButtonClass = !isDesktop && isActivityDetailPage ? 'bottom-140' : undefined;
const floatingButtonClass = !isDesktop && isActivityDetailPage ? 'bottom-160' : undefined;

return (
<div className='flex w-full flex-col items-center gap-8 overflow-x-hidden'>
Expand Down
23 changes: 14 additions & 9 deletions apps/what-today/src/pages/activities/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useToast } from '@what-today/design-system';
import { SpinIcon, useToast } from '@what-today/design-system';
import { useState } from 'react';
import { useParams } from 'react-router-dom';

Expand All @@ -7,14 +7,15 @@ import ActivitiesInformation from '@/components/activities/ActivitiesInformation
import ActivitiesMap from '@/components/activities/ActivitiesMap';
import ActivityImages from '@/components/activities/ActivityImages';
import Divider from '@/components/activities/Divider';
import DesktopReservation from '@/components/activities/reservation/DesktopReservation';
import MobileReservationSheet from '@/components/activities/reservation/MobileReservationSheet';
import ReservationForm from '@/components/activities/reservation/ReservationForm';
import TabletReservationSheet from '@/components/activities/reservation/TabletReservationSheet';
import type { ReservationSummary } from '@/components/activities/reservation/types';
import ReservationBottomBar from '@/components/activities/ReservationBottomBar';
import ReviewSection from '@/components/activities/ReviewSection';
import { useActivityDetail, useCreateReservation } from '@/hooks/activityDetail';
import { useResponsive } from '@/hooks/useResponsive';
import NotFoundPage from '@/pages/not-found-page';
import { useWhatTodayStore } from '@/stores';

export default function ActivityDetailPage() {
Expand All @@ -32,10 +33,14 @@ export default function ActivityDetailPage() {

const createReservationMutation = useCreateReservation(Number(id));

if (loading) return <p>로딩 중...</p>;
if (error)
return <p>오류: {error instanceof Error ? error.message : '활동 정보를 불러오는 중 오류가 발생했습니다.'}</p>;
if (!activity) return <p>데이터 없음</p>;
if (loading)
return (
<div className='flex h-screen items-center justify-center p-40'>
<SpinIcon className='size-200' color='var(--color-gray-100)' />
</div>
);
if (error) return <NotFoundPage />;
if (!activity) return <NotFoundPage />;

const handleConfirmTabletReservation = (reservation: ReservationSummary) => {
setReservationSummary(reservation);
Expand All @@ -56,10 +61,10 @@ export default function ActivityDetailPage() {
headCount: reservationSummary.headCount,
},
{
onSuccess: (data) => {
onSuccess: () => {
toast({
title: '예약 완료',
description: `예약 ID: ${data.id}`,
description: '마이페이지에서 예약을 확인해보세요!',
type: 'success',
});
setReservationSummary(null); // 예약 완료 후 상태 초기화
Expand Down Expand Up @@ -99,7 +104,7 @@ export default function ActivityDetailPage() {
reviewCount={activity.reviewCount}
title={activity.title}
/>
<DesktopReservation
<ReservationForm
activityId={activity.id}
isAuthor={user?.id ? activity?.userId === user.id : false}
isLoggedIn={!!user}
Expand Down