import { useEffect, useState } from 'react' import { useNavigate, Link } from 'react-router-dom' import { useAuthStore } from '@/store/auth' import { useCartStore } from '@/store/cart' import { api } from '@/lib/api' import { Button } from '@/components/ui/button' import { Card, CardContent } from '@/components/ui/card' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' function formatPrice(price: number): string { return new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }).format(price) } interface ShippingAddress { postal_code: string prefecture: string city: string address_line1: string address_line2: string recipient_name: string phone: string } const EMPTY_ADDRESS: ShippingAddress = { postal_code: '', prefecture: '', city: '', address_line1: '', address_line2: '', recipient_name: '', phone: '', } export function CheckoutPage() { const { user } = useAuthStore() const { items, total, clearCart } = useCartStore() const navigate = useNavigate() const [address, setAddress] = useState(EMPTY_ADDRESS) const [loading, setLoading] = useState(false) const [error, setError] = useState(null) useEffect(() => { if (!user) { navigate('/login') } }, [user, navigate]) if (!user) return null if (items.length === 0) { return (

カートが空です

) } function handleChange(field: keyof ShippingAddress, value: string) { setAddress(prev => ({ ...prev, [field]: value })) } async function handlePlaceOrder() { setError(null) const required: (keyof ShippingAddress)[] = ['postal_code', 'prefecture', 'city', 'address_line1', 'recipient_name', 'phone'] for (const field of required) { if (!address[field].trim()) { setError('必須項目を入力してください。 (Please fill in all required fields.)') return } } setLoading(true) try { const order = await api.post<{ id: string }>('/orders', { items: items.map(i => ({ product_id: i.product_id, quantity: i.quantity })), shipping_address: address, }) clearCart() navigate(`/account/orders/${order.id}`) } catch (err: unknown) { const message = err instanceof Error ? err.message : '注文に失敗しました。' setError(message) } finally { setLoading(false) } } return (

チェックアウト (Checkout)

{/* Shipping Address Form */}

配送先情報

handleChange('recipient_name', e.target.value)} placeholder="山田 太郎" className="mt-1" />
handleChange('postal_code', e.target.value)} placeholder="123-4567" className="mt-1" />
handleChange('prefecture', e.target.value)} placeholder="東京都" className="mt-1" />
handleChange('city', e.target.value)} placeholder="渋谷区" className="mt-1" />
handleChange('address_line1', e.target.value)} placeholder="1-2-3" className="mt-1" />
handleChange('address_line2', e.target.value)} placeholder="マンション101号室" className="mt-1" />
handleChange('phone', e.target.value)} placeholder="090-1234-5678" className="mt-1" />
{/* Order Summary */}

注文内容確認

{items.map(item => (

{item.name}

{formatPrice(item.price)} x {item.quantity}

{formatPrice(item.price * item.quantity)}

))}
合計 {formatPrice(total)}
{error && (
{error}
)}

注文確定後のキャンセルは注文詳細ページから可能です。

) }