Intelligence
Artifacts
Browse the repository, read documents, and manage the governance folders. Source, runtime, and infrastructure are read-only.
Repository
assignment-dispatch-button.tsxassignment-status-badge.tsxassignments-panel.tsxcreate-mission-form.tsxgovernance-panels.tsxmission-dispatch.tsxmission-edit.tsxmission-state-actions.tsxmission-status-badge.tsxobjective-edit.tsxobjective-status-badge.tsxobjective-status-select.tsxobjectives-panel.tsxreport-list.tsxwork-orders-panel.tsx
README.md
CONSTITUTION_COMPLIANCE_AUDIT_V1.mdREADME.md
repositories/aaf-holdings/hq01/components/files/file-delete-button.tsx
2.6 KB
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { Trash2, Loader2 } from "lucide-react";
import { cn } from "@/lib/utils";
/**
* Delete control shown in the file viewer for documents inside the managed
* governance folders. Uses an inline confirm rather than a modal. On success it
* navigates to the document's parent folder.
*/
export function FileDeleteButton({ path }: { path: string }) {
const router = useRouter();
const [confirming, setConfirming] = useState(false);
const [busy, setBusy] = useState(false);
const [error, setError] = useState<string | null>(null);
async function del() {
setBusy(true);
setError(null);
try {
const res = await fetch("/api/files/document", {
method: "DELETE",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ path }),
});
const data = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(data.error ?? "Delete failed.");
const parent = path.split("/").slice(0, -1).join("/");
router.push(`/artifacts?dir=${encodeURIComponent(parent)}`);
} catch (err) {
setError(err instanceof Error ? err.message : "Delete failed.");
setBusy(false);
setConfirming(false);
}
}
if (confirming) {
return (
<div className="flex items-center gap-2 text-[12px]">
<span className="text-muted-foreground">Delete this document?</span>
<button
type="button"
onClick={del}
disabled={busy}
className="inline-flex items-center gap-1 rounded-md bg-destructive px-2 py-1 font-medium text-destructive-foreground hover:bg-destructive/90"
>
{busy ? <Loader2 className="h-3 w-3 animate-spin" /> : <Trash2 className="h-3 w-3" />}
Delete
</button>
<button
type="button"
onClick={() => setConfirming(false)}
disabled={busy}
className="rounded-md px-2 py-1 text-muted-foreground hover:bg-secondary"
>
Cancel
</button>
</div>
);
}
return (
<div className="flex items-center gap-2">
{error && <span className="text-[11px] text-destructive">{error}</span>}
<button
type="button"
onClick={() => setConfirming(true)}
className={cn(
"inline-flex items-center gap-1 rounded-md px-2 py-1 text-[12px] text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive",
)}
title="Delete this document"
>
<Trash2 className="h-3.5 w-3.5" /> Delete
</button>
</div>
);
}
root · /srv/aaf