diff --git a/packages/web/src/components/ActionMenu.tsx b/packages/web/src/components/ActionMenu.tsx new file mode 100644 index 0000000..2713446 --- /dev/null +++ b/packages/web/src/components/ActionMenu.tsx @@ -0,0 +1,64 @@ +import { MoreHorizontal } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { trpc } from "@/lib/trpc"; + +interface ActionMenuProps { + initiativeId: string; + onDelete?: () => void; +} + +export function ActionMenu({ initiativeId, onDelete }: ActionMenuProps) { + const utils = trpc.useUtils(); + + const archiveMutation = trpc.updateInitiative.useMutation({ + onSuccess: () => { + utils.listInitiatives.invalidate(); + onDelete?.(); + }, + onError: (err) => { + console.error("Failed to archive initiative:", err.message); + }, + }); + + function handleArchive() { + const confirmed = window.confirm( + "Are you sure you want to archive this initiative? It can be restored later." + ); + if (!confirmed) return; + + archiveMutation.mutate({ + id: initiativeId, + status: "archived", + }); + } + + return ( + + + + + + Edit + Duplicate + + + {archiveMutation.isPending ? "Archiving..." : "Archive"} + + Delete + + + ); +} diff --git a/packages/web/src/components/SpawnArchitectDropdown.tsx b/packages/web/src/components/SpawnArchitectDropdown.tsx new file mode 100644 index 0000000..e54bb97 --- /dev/null +++ b/packages/web/src/components/SpawnArchitectDropdown.tsx @@ -0,0 +1,80 @@ +import { useState } from "react"; +import { ChevronDown } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { trpc } from "@/lib/trpc"; + +interface SpawnArchitectDropdownProps { + initiativeId: string; + initiativeName: string; +} + +export function SpawnArchitectDropdown({ + initiativeId, + initiativeName, +}: SpawnArchitectDropdownProps) { + const [open, setOpen] = useState(false); + const [successText, setSuccessText] = useState(null); + + const discussMutation = trpc.spawnArchitectDiscuss.useMutation({ + onSuccess: () => { + setOpen(false); + setSuccessText("Spawned!"); + setTimeout(() => setSuccessText(null), 2000); + }, + onError: (err) => { + console.error("Failed to spawn discuss architect:", err.message); + }, + }); + + const breakdownMutation = trpc.spawnArchitectBreakdown.useMutation({ + onSuccess: () => { + setOpen(false); + setSuccessText("Spawned!"); + setTimeout(() => setSuccessText(null), 2000); + }, + onError: (err) => { + console.error("Failed to spawn breakdown architect:", err.message); + }, + }); + + const isPending = discussMutation.isPending || breakdownMutation.isPending; + + function handleDiscuss() { + discussMutation.mutate({ + name: initiativeName + "-discuss", + initiativeId, + }); + } + + function handleBreakdown() { + breakdownMutation.mutate({ + name: initiativeName + "-breakdown", + initiativeId, + }); + } + + return ( + + + + + + + Discuss + + + Breakdown + + + + ); +}