"use client"; import * as React from "react"; import { useRouter } from "next/navigation"; import { Button, type ButtonProps } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import type { AdminActionResult } from "@/actions/admin"; /** * Runs a server action inside a transition and refreshes the router. When `confirm` is given, a * dialog gates the (usually destructive) action. */ export function ActionButton({ action, children, confirm, onDone, ...btn }: { action: () => Promise>; children: React.ReactNode; confirm?: { title: string; description?: React.ReactNode; confirmLabel?: string; variant?: ButtonProps["variant"] }; onDone?: (r: AdminActionResult) => void; } & Omit) { const router = useRouter(); const [pending, start] = React.useTransition(); const [open, setOpen] = React.useState(false); const [msg, setMsg] = React.useState<{ kind: "error" | "warning"; text: string } | null>(null); const run = () => start(async () => { setMsg(null); const r = await action(); if (!r.ok) setMsg({ kind: "error", text: r.error }); else if (r.warning) setMsg({ kind: "warning", text: r.warning }); onDone?.(r); if (r.ok) { setOpen(false); router.refresh(); } }); return ( <> {msg && !confirm ? ( {msg.text} ) : null} {confirm ? ( {confirm.title} {confirm.description ? {confirm.description} : null} {msg ? (

{msg.text}

) : null}
) : null} ); } export function ResultMessage({ result }: { result: AdminActionResult | null }) { if (!result) return null; if (!result.ok) return (

{result.error}

); if (result.warning) return (

{result.warning}

); return (

Saved.

); }