diff options
| author | soryu <soryu@soryu.co> | 2026-01-19 17:55:22 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-19 17:55:22 +0000 |
| commit | 52d121269195f0e799d0ab4241e4facc3c7c0596 (patch) | |
| tree | 13d3dcdd743cf15f31d6d87097bf51ebfd01a305 /makima/frontend/src/routes/contracts.tsx | |
| parent | 164941cbd591b46f69a034bb9b86521fd7700ddb (diff) | |
| download | soryu-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/routes/contracts.tsx')
| -rw-r--r-- | makima/frontend/src/routes/contracts.tsx | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/makima/frontend/src/routes/contracts.tsx b/makima/frontend/src/routes/contracts.tsx index d2b6b1b..0893ff6 100644 --- a/makima/frontend/src/routes/contracts.tsx +++ b/makima/frontend/src/routes/contracts.tsx @@ -1,4 +1,4 @@ -import { useState, useCallback, useEffect } from "react"; +import { useState, useCallback, useEffect, useMemo } from "react"; import { useParams, useNavigate } from "react-router"; import { Masthead } from "../components/Masthead"; import { ContractList } from "../components/contracts/ContractList"; @@ -9,6 +9,7 @@ import { useAuth } from "../contexts/AuthContext"; import { createTask, getDaemonDirectories, getRepositorySuggestions } from "../lib/api"; import type { ContractWithRelations, + ContractSummary, ContractPhase, ContractStatus, ContractType, @@ -411,6 +412,49 @@ function ContractsPageContent() { [contractDetail, fetchContract, navigate] ); + // Context menu handlers for ContractList + const handleContextMarkComplete = useCallback( + async (contract: ContractSummary) => { + await editContract(contract.id, { status: "completed", version: contract.version }); + }, + [editContract] + ); + + const handleContextMarkActive = useCallback( + async (contract: ContractSummary) => { + await editContract(contract.id, { status: "active", version: contract.version }); + }, + [editContract] + ); + + const handleContextArchive = useCallback( + async (contract: ContractSummary) => { + await editContract(contract.id, { status: "archived", version: contract.version }); + }, + [editContract] + ); + + const handleContextDelete = useCallback( + async (contract: ContractSummary) => { + if (confirm(`Are you sure you want to delete "${contract.name}"?`)) { + const success = await removeContract(contract.id); + if (success && contract.id === id) { + navigate("/contracts"); + } + } + }, + [removeContract, id, navigate] + ); + + const handleContextGoToSupervisor = useCallback( + (contract: ContractSummary) => { + if (contract.supervisorTaskId) { + navigate(`/mesh/${contract.supervisorTaskId}`); + } + }, + [navigate] + ); + return ( <div className="relative z-10 min-h-screen flex flex-col bg-[#0a1628]"> <Masthead showNav /> @@ -684,6 +728,11 @@ function ContractsPageContent() { onSelect={handleSelect} onCreate={handleCreate} selectedId={id} + onMarkComplete={handleContextMarkComplete} + onMarkActive={handleContextMarkActive} + onArchive={handleContextArchive} + onDelete={handleContextDelete} + onGoToSupervisor={handleContextGoToSupervisor} /> {/* Contract detail or empty state */} |
