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/missions/assignment-dispatch-button.tsx
1.8 KB
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { Send, Loader2, AlertTriangle } from "lucide-react";
import { Button } from "@/components/ui/button";
import type { AssignmentStatus } from "@/lib/missions/types";
/** Dispatch control for an assignment detail page. */
export function AssignmentDispatchButton({
missionId,
aid,
status,
}: {
missionId: string;
aid: string;
status: AssignmentStatus;
}) {
const router = useRouter();
const [busy, setBusy] = useState(false);
const [error, setError] = useState<string | null>(null);
const canDispatch = status === "Pending" || status === "Failed";
async function dispatch() {
setBusy(true);
setError(null);
try {
const res = await fetch(
`/api/missions/${missionId}/assignments/${aid}/dispatch`,
{ method: "POST" },
);
const data = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(data.error ?? "Dispatch failed.");
router.refresh();
} catch (err) {
setError(err instanceof Error ? err.message : "Dispatch failed.");
setBusy(false);
}
}
if (!canDispatch) {
return (
<span className="text-[12px] text-muted-foreground">
Already {status.toLowerCase()}.
</span>
);
}
return (
<div className="flex flex-col items-end gap-1">
<Button type="button" size="sm" onClick={dispatch} disabled={busy}>
{busy ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <Send className="h-3.5 w-3.5" />}
Dispatch Assignment
</Button>
{error && (
<span className="flex items-center gap-1 text-[11px] text-destructive">
<AlertTriangle className="h-3 w-3" /> {error}
</span>
)}
</div>
);
}
root · /srv/aaf