"use client"; import { useState, type FormEvent } from "react"; import { useRouter } from "next/navigation"; import { FormField, Notification } from "./ui"; export function CheckoutForm({ formattedSubtotal, itemCount, }: Readonly<{ formattedSubtotal: string; itemCount: number }>) { const router = useRouter(); const [pending, setPending] = useState(false); const [message, setMessage] = useState(null); async function submit(event: FormEvent) { event.preventDefault(); setPending(true); setMessage(null); const form = new FormData(event.currentTarget); try { const response = await fetch("/api/orders", { body: JSON.stringify({ contactEmail: form.get("email"), idempotencyKey: crypto.randomUUID(), }), headers: { "content-type": "application/json" }, method: "POST", }); const payload: unknown = await response.json(); const reference = readOrderReference(payload); if (!response.ok || reference === null) { setMessage(readApiMessage(payload)); return; } router.push(`/order-confirmation?reference=${encodeURIComponent(reference)}`); router.refresh(); } catch { setMessage("The order request could not be completed."); } finally { setPending(false); } } return (
Merchandise subtotal: {formattedSubtotal}

{itemCount} item(s). Payment currently uses this merchandise subtotal; tax and shipping remain out of scope.

{message === null ? null : (

{message}

)}
); } function readOrderReference(value: unknown): string | null { if ( typeof value === "object" && value !== null && "data" in value && typeof value.data === "object" && value.data !== null && "order" in value.data && typeof value.data.order === "object" && value.data.order !== null && "reference" in value.data.order && typeof value.data.order.reference === "string" && /^ORD-[0-9]{12}$/u.test(value.data.order.reference) ) { return value.data.order.reference; } return null; } function readApiMessage(value: unknown): string { if ( typeof value === "object" && value !== null && "error" in value && typeof value.error === "object" && value.error !== null && "message" in value.error && typeof value.error.message === "string" ) { return value.error.message; } return "The order request could not be completed."; }