import { useState, useCallback, useEffect, useMemo } from "react"; import { useNavigate } from "react-router"; import { Masthead } from "../components/Masthead"; import { WorkflowBoard } from "../components/workflow/WorkflowBoard"; import { useContracts } from "../hooks/useContracts"; import { useAuth } from "../contexts/AuthContext"; import type { ContractPhase, ContractStatus, ContractSummary } from "../lib/api"; type StatusFilter = "all" | ContractStatus; export default function WorkflowPage() { const { isAuthenticated, isAuthConfigured, isLoading: authLoading } = useAuth(); const navigate = useNavigate(); // Redirect to login if not authenticated (when auth is configured) useEffect(() => { if (!authLoading && isAuthConfigured && !isAuthenticated) { navigate("/login"); } }, [authLoading, isAuthConfigured, isAuthenticated, navigate]); // Show loading while checking auth if (authLoading) { return (

Loading...

); } // Don't render if not authenticated (will redirect) if (isAuthConfigured && !isAuthenticated) { return null; } return ; } function WorkflowPageContent() { const navigate = useNavigate(); const { contracts, loading, error, changePhase, saveContract, editContract, removeContract } = useContracts(); const [statusFilter, setStatusFilter] = useState("all"); const [isCreating, setIsCreating] = useState(false); const [newContractName, setNewContractName] = useState(""); // Filter contracts by status const filteredContracts = useMemo(() => { if (statusFilter === "all") { return contracts; } return contracts.filter((c) => c.status === statusFilter); }, [contracts, statusFilter]); const handleContractClick = useCallback( (contractId: string) => { navigate(`/contracts/${contractId}`); }, [navigate] ); const handlePhaseChange = useCallback( async (contractId: string, newPhase: ContractPhase) => { await changePhase(contractId, newPhase); }, [changePhase] ); // Context menu handlers 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}"?`)) { await removeContract(contract.id); } }, [removeContract] ); const handleContextGoToSupervisor = useCallback( (contract: ContractSummary) => { if (contract.supervisorTaskId) { navigate(`/mesh/${contract.supervisorTaskId}`); } }, [navigate] ); const handleCreateContract = useCallback(async () => { if (!newContractName.trim()) return; const contract = await saveContract({ name: newContractName.trim(), }); if (contract) { setNewContractName(""); setIsCreating(false); navigate(`/contracts/${contract.id}`); } }, [newContractName, saveContract, navigate]); const handleCancelCreate = useCallback(() => { setNewContractName(""); setIsCreating(false); }, []); return (
{error && (
{error}
)} {/* Header with filter and create button */}

Board

{/* Status filter */}
{(["all", "active", "completed", "archived"] as StatusFilter[]).map( (status) => ( ) )}
{/* Create contract modal */} {isCreating && (

Create Contract

setNewContractName(e.target.value)} placeholder="Contract name" className="w-full px-3 py-2 bg-[#0d1b2d] border border-[#3f6fb3] text-[#dbe7ff] font-mono text-sm focus:outline-none focus:border-[#75aafc]" autoFocus onKeyDown={(e) => { if (e.key === "Enter") handleCreateContract(); if (e.key === "Escape") handleCancelCreate(); }} />
)} {/* Board */}
{loading ? (

Loading...

) : filteredContracts.length === 0 && statusFilter === "all" ? (

No contracts yet

) : ( )}
); }