Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
be84854
chore: 예약금정책 변경에 따른 코드수정
jjjsun Jan 31, 2026
eabecd8
feat: 메뉴선택 UI로 이동 구현
jjjsun Jan 31, 2026
e814d96
feat: 예약시 메뉴선택 UI모달추가 및 예약금을 메뉴총액대비 예약금률 적용하도록 수정
jjjsun Feb 1, 2026
d4b54d5
chore: hooks 호출 순서 꺠뜨리는 조건부 return 수정, draft 변경시 selectedMenus 상태 동기화…
jjjsun Feb 1, 2026
5206887
chore:오타수정, open prop에 따른 조건부 랜덜이 누락
jjjsun Feb 1, 2026
d774647
chore: 메뉴 최대수량일때 증가버튼 비활성화되도록 기능추가
jjjsun Feb 1, 2026
5d7df3b
style: 너비/패딩 수정
jjjsun Feb 1, 2026
2e8e1cc
style: 메뉴선택모달하단부분 예약금 블루색깔추가, 메뉴총액은 가로로 위치변경
jjjsun Feb 1, 2026
81dc525
chore: 모바일 너비처리를 위한 코드추가(이전 작업범위)
jjjsun Feb 1, 2026
1f6ac36
chore: 메뉴선택에서 우측상단 X 아이콘은 모달닫기로 수정, 하단에 다음버튼 왼쪽에 이전으로 이동하는 버튼추가
jjjsun Feb 1, 2026
899ea66
chore: 식당예약모달에서 우측상단 X아이콘 모달닫기로 수정
jjjsun Feb 1, 2026
2e5e8e6
chore: 예약모든 모달 X아이콘 클리시 창닫기로 모드수정, 창닫기알림창 훅 새로 생성해서 모든 모달에 적용
jjjsun Feb 1, 2026
f04db06
refactore:주석삭제
jjjsun Feb 1, 2026
2983d88
chore: 모달이외지역클릭시 닫기 -> hooks사용으로 변경
jjjsun Feb 1, 2026
aa21f06
chore:예약금 표시비율 통일
jjjsun Feb 1, 2026
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
48 changes: 27 additions & 21 deletions src/components/reservation/PaymentModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import { formatKrw } from "@/utils/money";
import { Button } from "../ui/button";
import { cn } from "@/lib/utils";
import { X } from "lucide-react";
import { useMenus } from "@/hooks/useMenus";
import { useDepositRate } from "@/hooks/useDepositRate";
import { calcMenuTotal } from "@/utils/menu";
import { calcDeposit } from "@/utils/payment";
import { useConfirmClose } from "@/hooks/useConfirmClose";

type PayMethod = "KAKAOPAY" | "TOSSPAY";

Expand All @@ -14,7 +19,6 @@ type Props = {
restaurant: Restaurant;
draft: ReservationDraft;
onSuccess: () => void;
onBack: () => void;
};

function mockPay(method: PayMethod, amount: number) {
Expand All @@ -31,12 +35,20 @@ export default function PaymentModal({
restaurant,
draft,
onSuccess,
onBack,
}: Props) {
const [method, setMethod] = useState<PayMethod | undefined>();
const [loading, setLoading] = useState(false);

const amount = useMemo(() => draft.payment.depositAmount, [draft.payment]);
const { menus } = useMenus(restaurant.id);
const { rate } = useDepositRate(restaurant.id);

const menuTotal = useMemo(() => {
return calcMenuTotal(menus, draft.selectedMenus);
}, [menus, draft.selectedMenus]);

const amount = useMemo(() => {
return calcDeposit(menuTotal, rate);
}, [menuTotal, rate]);

const onClickPay = async () => {
if (loading) return;
Expand All @@ -50,18 +62,7 @@ export default function PaymentModal({
}
};

const handleBack = () => {
onOpenChange(false);
onBack();
};

const handleRequestClose = () => {
const ok = window.confirm(
"예약금이 결제되지 않았습니다. \n 예약화면을 벗어나시겠습니까?",
);
if (ok) onClose();
};

const handleRequestClose = useConfirmClose(onClose);
if (!open) return null;

return (
Expand All @@ -83,7 +84,7 @@ export default function PaymentModal({
<h3 className="text-lg">예약금 결제</h3>
<button
type="button"
onClick={handleBack}
onClick={handleRequestClose}
aria-label="닫기"
className="p-2 rounded-lg hover:bg-gray-100 transition-colors cursor-pointer"
>
Expand All @@ -96,13 +97,18 @@ export default function PaymentModal({
<div className="text-sm text-muted-foreground">매장</div>
<div className="mt-1 text-base truncate">{restaurant.name}</div>
</div>
<div className="border rounded-xl p-4 flex items-center justify-between gap-3">
<div className="min-w-0">
<div className="text-sm text-muted-foreground">결제 금액</div>
<div className="mt-1 text-xl font-semibold">
{formatKrw(amount)}원
<div className="border rounded-xl p-4 space-y-1">
<div className="flex items-center justify-between gap-3">
<div className="min-w-0">
<div className="text-sm text-muted-foreground">결제 금액</div>
<div className="mt-1 text-xl font-semibold">
{formatKrw(amount)}원
</div>
</div>
</div>
<p className="text-xs text-muted-foreground">
메뉴 총액 {formatKrw(menuTotal)}원 * {Math.round(rate * 100)}%
</p>
</div>
{/* 본문 */}
<div className="space-y-2">
Expand Down
37 changes: 21 additions & 16 deletions src/components/reservation/ReservationConfirmModal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { useConfirmClose } from "@/hooks/useConfirmClose";
import { useDepositRate } from "@/hooks/useDepositRate";
import { useMenus } from "@/hooks/useMenus";
import { getMockLayoutByRestaurantId } from "@/mock/seatLayout";
import type { ReservationDraft, Restaurant } from "@/types/restaurant";
import { toYmd } from "@/utils/date";
import { calcMenuTotal } from "@/utils/menu";
import { formatKrw } from "@/utils/money";
import { calcDeposit } from "@/utils/payment";
import { tablePrefLabel } from "@/utils/reservation";
import { X } from "lucide-react";

Expand All @@ -22,22 +27,21 @@ export default function ReservationConfirmMoodal({
restaurant,
draft,
}: Props) {
if (!open) return null;

const { people, date, time, seatType, tablePref } = draft;

//UI테스트를 위해서 r-1로 고정함. 나중에 백엔드 연결시 주석으로 변경필요. ReservationModal또한 변경필요.
// const layout = getMockLayoutByRestaurantId(restaurant.id ?? "r-1");
const layout = getMockLayoutByRestaurantId("r-1");
const layout = getMockLayoutByRestaurantId(restaurant.id ?? "1");

const seatTable = layout?.tables.find((t) => t.id === draft.tableId);

const handleRequestClose = () => {
const ok = window.confirm(
"예약이 확정되지 않았습니다.\n예약화면을 벗어나시겠습니까?",
);
if (ok) onClose();
};
const handleRequestClose = useConfirmClose(onClose);

const { menus } = useMenus(restaurant.id);
const { rate } = useDepositRate(restaurant.id);
const { selectedMenus } = draft;
const menuTotal = calcMenuTotal(menus, selectedMenus);
const depositAmount = calcDeposit(menuTotal, rate);
Comment thread
jjjsun marked this conversation as resolved.

if (!open) return null;

return (
<div
Expand Down Expand Up @@ -100,12 +104,13 @@ export default function ReservationConfirmMoodal({
<div className="border rounded-lg p-3 bg-blue-50 border-blue-200">
<div className="text-sm text-gray-500">결제 유형</div>
<div className="text-blue-700">사전 결제</div>
<div className="text-sm text-gray-800 mt-1">
예약금: {formatKrw(draft.payment.depositAmount)}원
{draft.payment.depositRate
? ` (${Math.round(draft.payment.depositRate * 100)}% 정책 적용)`
: null}
<div className="text-gray-800 mt-1 font-semibold">
예약금: {formatKrw(depositAmount)}원
</div>
<p className="text-xs text-muted-foreground mt-2">
{restaurant.paymentPolicy?.notice ??
"예약 확정을 위해 예약금 결제가 필요합니다.(노쇼 방지 목적)"}
</p>
</div>
<p className="text-gray-700 text-center">
위 내용으로 예약을 진행할까요?
Expand Down
Loading