"use client"; import type { FormEvent } from "react"; import { useState } from "react"; import { useRouter } from "next/navigation"; import type { AdminOrderRecord, AdminPaymentRecord, AdminProductRecord, AdminVariantRecord, } from "@/server/admin/repository"; import { FormField, Notification } from "./ui"; function key(kind: string) { return `admin:${kind}:${crypto.randomUUID()}`; } function useMutation() { const router = useRouter(); const [message, setMessage] = useState(); const [error, setError] = useState(); const [pending, setPending] = useState(false); async function run(url: string, method: "DELETE" | "PATCH" | "POST", body: unknown) { setPending(true); setError(undefined); setMessage(undefined); try { const response = await fetch(url, { body: JSON.stringify(body), headers: { "content-type": "application/json" }, method, }); const result = (await response.json()) as { error?: { message?: string }; ok?: boolean }; if (!response.ok || result.ok !== true) throw new Error(result.error?.message ?? "Operation failed."); setMessage("Saved."); router.refresh(); return true; } catch (cause) { setError(cause instanceof Error ? cause.message : "Operation failed."); return false; } finally { setPending(false); } } return { error, message, pending, run }; } function Result({ error, message, }: Readonly<{ error: string | undefined; message: string | undefined }>) { if (error !== undefined) return (

{error}

); if (message !== undefined) return (

{message}

); return null; } export function AdminLoginForm() { const mutation = useMutation(); const router = useRouter(); async function submit(event: FormEvent) { event.preventDefault(); const form = event.currentTarget; const data = new FormData(form); if ( await mutation.run("/api/admin/session", "POST", { email: data.get("email"), password: data.get("password"), }) ) router.replace("/admin"); } return (
); } export function AdminSignOutButton() { const mutation = useMutation(); const router = useRouter(); return ( ); } export function AdminProductControls({ product }: Readonly<{ product: AdminProductRecord }>) { const mutation = useMutation(); async function submit(event: FormEvent) { event.preventDefault(); const data = new FormData(event.currentTarget); await mutation.run(`/api/admin/products/${product.id}`, "PATCH", { description: String(data.get("description") ?? "").trim() || null, idempotencyKey: key("product"), name: data.get("name"), status: data.get("status"), }); } return (