47 lines
1.3 KiB
TypeScript
47 lines
1.3 KiB
TypeScript
"use client";
|
|
|
|
import { useRouter } from "next/navigation";
|
|
import { useState } from "react";
|
|
import { apiFetch, errorMessage } from "@/lib/client-api";
|
|
|
|
interface Props {
|
|
path: string;
|
|
label: string;
|
|
method?: "POST" | "PUT" | "PATCH" | "DELETE";
|
|
body?: unknown;
|
|
confirm?: string;
|
|
variant?: "primary" | "danger" | "secondary";
|
|
onDone?: (result: unknown) => void;
|
|
}
|
|
|
|
/** Botão que executa uma ação na API e recarrega os dados da página. */
|
|
export function ActionButton({ path, label, method = "POST", body, confirm, variant = "secondary", onDone }: Props) {
|
|
const router = useRouter();
|
|
const [busy, setBusy] = useState(false);
|
|
const [error, setError] = useState("");
|
|
|
|
async function run() {
|
|
if (confirm && !window.confirm(confirm)) return;
|
|
setBusy(true);
|
|
setError("");
|
|
try {
|
|
const result = await apiFetch(path, { method, body });
|
|
onDone?.(result);
|
|
router.refresh();
|
|
} catch (err) {
|
|
setError(errorMessage(err));
|
|
} finally {
|
|
setBusy(false);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<span className="action">
|
|
<button type="button" className={`btn ${variant}`} onClick={run} disabled={busy}>
|
|
{busy ? "Aguarde…" : label}
|
|
</button>
|
|
{error && <span className="error-text">{error}</span>}
|
|
</span>
|
|
);
|
|
}
|