summaryrefslogtreecommitdiff
path: root/makima/frontend/src/components/contracts/ContractList.tsx
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-01-19 17:55:22 +0000
committerGitHub <noreply@github.com>2026-01-19 17:55:22 +0000
commit52d121269195f0e799d0ab4241e4facc3c7c0596 (patch)
tree13d3dcdd743cf15f31d6d87097bf51ebfd01a305 /makima/frontend/src/components/contracts/ContractList.tsx
parent164941cbd591b46f69a034bb9b86521fd7700ddb (diff)
downloadsoryu-52d121269195f0e799d0ab4241e4facc3c7c0596.tar.gz
soryu-52d121269195f0e799d0ab4241e4facc3c7c0596.zip
Add right-click context menu for contracts on contracts and board pages (#8)
Implement a reusable ContractContextMenu component that provides: - Mark as Complete/Active/Archive status actions (conditionally shown) - Go to Supervisor Task link (when supervisor exists) - Delete action with confirmation Integrate context menu into: - ContractList.tsx on the contracts page - WorkflowBoard on the workflow/board page via PhaseColumn and WorkflowContractCard Features match ElementContextMenu patterns: - Fixed positioning with z-50 - Click outside and Escape key close handlers - Viewport overflow prevention - Dark theme colors (#0a1628, #0d1b2d, #75aafc, #9bc3ff) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'makima/frontend/src/components/contracts/ContractList.tsx')
-rw-r--r--makima/frontend/src/components/contracts/ContractList.tsx40
1 files changed, 40 insertions, 0 deletions
diff --git a/makima/frontend/src/components/contracts/ContractList.tsx b/makima/frontend/src/components/contracts/ContractList.tsx
index 3a7b163..ebde497 100644
--- a/makima/frontend/src/components/contracts/ContractList.tsx
+++ b/makima/frontend/src/components/contracts/ContractList.tsx
@@ -2,6 +2,7 @@ import { useState } from "react";
import type { ContractSummary, ContractStatus } from "../../lib/api";
import { PhaseBadge } from "./PhaseBadge";
import { PhaseProgressBarCompact } from "./PhaseProgressBar";
+import { ContractContextMenu } from "./ContractContextMenu";
interface ContractListProps {
contracts: ContractSummary[];
@@ -9,6 +10,11 @@ interface ContractListProps {
onSelect: (id: string) => void;
onCreate: () => void;
selectedId?: string;
+ onMarkComplete?: (contract: ContractSummary) => void;
+ onMarkActive?: (contract: ContractSummary) => void;
+ onArchive?: (contract: ContractSummary) => void;
+ onDelete?: (contract: ContractSummary) => void;
+ onGoToSupervisor?: (contract: ContractSummary) => void;
}
const statusColors: Record<ContractStatus, string> = {
@@ -23,8 +29,26 @@ export function ContractList({
onSelect,
onCreate,
selectedId,
+ onMarkComplete,
+ onMarkActive,
+ onArchive,
+ onDelete,
+ onGoToSupervisor,
}: ContractListProps) {
const [filter, setFilter] = useState<ContractStatus | "all">("all");
+ const [contextMenuPosition, setContextMenuPosition] = useState<{ x: number; y: number } | null>(null);
+ const [contextMenuContract, setContextMenuContract] = useState<ContractSummary | null>(null);
+
+ const handleContextMenu = (e: React.MouseEvent, contract: ContractSummary) => {
+ e.preventDefault();
+ setContextMenuPosition({ x: e.clientX, y: e.clientY });
+ setContextMenuContract(contract);
+ };
+
+ const closeContextMenu = () => {
+ setContextMenuPosition(null);
+ setContextMenuContract(null);
+ };
const filteredContracts =
filter === "all"
@@ -92,6 +116,7 @@ export function ContractList({
<button
key={contract.id}
onClick={() => onSelect(contract.id)}
+ onContextMenu={(e) => handleContextMenu(e, contract)}
className={`
w-full text-left p-4 transition-colors
${
@@ -139,6 +164,21 @@ export function ContractList({
</div>
)}
</div>
+
+ {/* Context Menu */}
+ {contextMenuPosition && contextMenuContract && (
+ <ContractContextMenu
+ x={contextMenuPosition.x}
+ y={contextMenuPosition.y}
+ contract={contextMenuContract}
+ onClose={closeContextMenu}
+ onMarkComplete={() => onMarkComplete?.(contextMenuContract)}
+ onMarkActive={() => onMarkActive?.(contextMenuContract)}
+ onArchive={() => onArchive?.(contextMenuContract)}
+ onDelete={() => onDelete?.(contextMenuContract)}
+ onGoToSupervisor={() => onGoToSupervisor?.(contextMenuContract)}
+ />
+ )}
</div>
);
}