1
0
Fork 0
polaris-task-force/src/components/frontend/intelligence/SideOpControls.tsx
Z8MB1E 03f699d852 feat(missions): add Friday Ops calendar page and side-op dialog UI
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-09-06 23:29:54 -04:00

98 lines
2.8 KiB
TypeScript

"use client";
import { useState, useTransition } from "react";
import { useRouter } from "next/navigation";
import { toast } from "sonner";
import { PencilIcon, XCircleIcon } from "lucide-react";
import { Item, ItemContent, ItemHeader, ItemTitle } from "@/components/ui/item";
import { Button } from "@/components/ui/button";
import { cancelFridaySideOp } from "@/app/(frontend)/intelligence/missions/actions";
import {
CreateSideOpDialog,
type SideOpDialogInitial,
type SideOpDialogOption,
} from "./CreateSideOpDialog";
interface SideOpControlsProps {
initial: SideOpDialogInitial;
status: string;
maps: SideOpDialogOption[];
campaigns: SideOpDialogOption[];
modLists: SideOpDialogOption[];
}
export function SideOpControls({
initial,
status,
maps,
campaigns,
modLists,
}: SideOpControlsProps) {
const router = useRouter();
const [editOpen, setEditOpen] = useState(false);
const [confirmingCancel, setConfirmingCancel] = useState(false);
const [isPending, startTransition] = useTransition();
const isTerminal = status === "Completed" || status === "Cancelled";
function handleCancel() {
if (!confirmingCancel) {
setConfirmingCancel(true);
return;
}
startTransition(async () => {
const result = await cancelFridaySideOp(initial.missionId);
if (!result.success) {
toast.error(result.error ?? "Failed to cancel the side operation.");
setConfirmingCancel(false);
return;
}
toast.success("Side operation cancelled. Discord roll-call will be updated.");
setConfirmingCancel(false);
router.refresh();
});
}
if (isTerminal) {
return null;
}
return (
<Item variant="outline">
<ItemHeader>
<ItemTitle>Side Operation Controls</ItemTitle>
</ItemHeader>
<ItemContent>
<div className="flex flex-wrap gap-2">
<Button size="sm" variant="outline" onClick={() => setEditOpen(true)} disabled={isPending}>
<PencilIcon className="size-3.5" />
Edit
</Button>
<Button
size="sm"
variant={confirmingCancel ? "destructive" : "outline"}
onClick={handleCancel}
disabled={isPending}
>
<XCircleIcon className="size-3.5" />
{confirmingCancel ? "Confirm cancel?" : "Cancel mission"}
</Button>
</div>
<p className="text-xs text-muted-foreground">
Editing covers details, campaign, and narrative. Cancelling frees your scheduling slot
and updates the Discord embed.
</p>
</ItemContent>
<CreateSideOpDialog
open={editOpen}
onOpenChange={setEditOpen}
maps={maps}
campaigns={campaigns}
modLists={modLists}
initial={initial}
onSaved={() => router.refresh()}
/>
</Item>
);
}