'use client'; import { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; import { ArrowLeft, CreditCard } from 'lucide-react'; import { fetchApi } from '@/lib/utils/client'; import PayButton, { type PayButtonState } from '@/app/component/PayButton'; import useAuth from '@/hooks/useAuth'; import useCart from '@/hooks/useCart'; import type { PlaceOrderResponse } from '@/types/store'; function formatPrice(n: number): string { return n.toLocaleString('ko-KR'); } function pad(n: number): string { return String(n).padStart(2, '0'); } function formatNow(): string { const d = new Date(); return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`; } export default function CheckoutPage() { const router = useRouter(); const { isAuthenticated } = useAuth(); const { items, channel, totalCount, totalPrice } = useCart(); const [hydrated, setHydrated] = useState(false); const [payState, setPayState] = useState('idle'); const [error, setError] = useState(null); const [issuedAt] = useState(() => formatNow()); useEffect(() => { setHydrated(true); }, []); // 인증 / 빈 cart 가드 — hydration 이후에만 판단 useEffect(() => { if (!hydrated) { return; } if (!isAuthenticated) { // 동의를 받고 이동 (취소 시 장바구니로 복귀) if (confirm('로그인 후 이용 가능합니다.\n로그인하시겠습니까?')) { router.replace('/login?returnUrl=/checkout'); } else { router.replace('/cart'); } return; } if (items.length === 0) { router.replace('/cart'); } }, [hydrated, isAuthenticated, items.length, router]); const handleConfirmPayment = async () => { if (items.length === 0 || payState !== 'idle') { return; } setPayState('loading'); setError(null); const res = await fetchApi('/api/store/orders', { method: 'POST', body: { channelID: channel?.id ?? null, items: items.map(i => ({ productID: i.productID, quantity: i.quantity })) }, silent: true }); if (res.success && res.data) { setPayState('success'); // cart clear 는 /order-complete 페이지 진입 시 수행 (이중 이동 시 데이터 안정성) router.push(`/order-complete/${res.data.orderID}`); return; } setPayState('idle'); setError(res.message ?? '결제에 실패했습니다.'); }; if (!hydrated || items.length === 0) { return null; } return (
{/* 인보이스 카드 */}
{/* 헤더: 페이지 제목 + 소제목 */}

구매 확인

아래 영수증을 확인하신 후 구매하기를 눌러주세요.

{issuedAt}
{/* 상품 테이블 */} {items.map((item) => ( ))}
상품 수량 가격
{item.thumbnail ? ( // eslint-disable-next-line @next/next/no-img-element {item.name} ) : ( 이미지 없음 )}
{item.name}
{item.gameName} · {item.type === 1 ? '실물' : '쿠폰'}
{item.quantity} {formatPrice(item.price * item.quantity)}P
{/* 합계 */}
소계 {formatPrice(totalPrice)}P
할인 0P
합계 {formatPrice(totalPrice)}P
총 {totalCount.toLocaleString()}개 상품
{/* 결제수단 */}
결제수단: 캐시 잔액
{error && (
{error}
)}
} onClick={handleConfirmPayment} className='sm:flex-1' />

결제 시 POINT 잔액에서 차감됩니다. 결제 후 취소/환불은 주문 목록에서 신청할 수 있습니다.

); }