summaryrefslogtreecommitdiff
path: root/makima/frontend/src/components/workflow
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-02-14 21:29:26 +0000
committerGitHub <noreply@github.com>2026-02-14 21:29:26 +0000
commit9aadbc7958d39d181c0dd0600e2b7c30bb6c391a (patch)
treeef8bed9718c39041191b58a284ee31f5d8d32521 /makima/frontend/src/components/workflow
parentc1e55ce4fec79f9909b957f86bd7fa8b76939746 (diff)
downloadsoryu-9aadbc7958d39d181c0dd0600e2b7c30bb6c391a.tar.gz
soryu-9aadbc7958d39d181c0dd0600e2b7c30bb6c391a.zip
Makima system improvements: Orders, directive questions, PR creation fix, bug fixes (#62)
* feat: soryu-co/soryu - makima: Fix directive goal update bug - stale closure issue * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Create Orders database schema and backend API * feat: soryu-co/soryu - makima: Fix task Claude instance not receiving user inputs from input box * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Build Orders frontend page replacing the Board page * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Fix directive PR creation system
Diffstat (limited to 'makima/frontend/src/components/workflow')
-rw-r--r--makima/frontend/src/components/workflow/PhaseColumn.tsx126
-rw-r--r--makima/frontend/src/components/workflow/WorkflowBoard.tsx98
-rw-r--r--makima/frontend/src/components/workflow/WorkflowContractCard.tsx76
3 files changed, 0 insertions, 300 deletions
diff --git a/makima/frontend/src/components/workflow/PhaseColumn.tsx b/makima/frontend/src/components/workflow/PhaseColumn.tsx
deleted file mode 100644
index 277b04c..0000000
--- a/makima/frontend/src/components/workflow/PhaseColumn.tsx
+++ /dev/null
@@ -1,126 +0,0 @@
-import { useState } from "react";
-import type { ContractSummary, ContractPhase } from "../../lib/api";
-import { WorkflowContractCard } from "./WorkflowContractCard";
-
-interface PhaseColumnProps {
- phase: ContractPhase;
- contracts: ContractSummary[];
- onContractClick: (contractId: string) => void;
- onDrop: (contractId: string, phase: ContractPhase) => void;
- onContextMenu?: (e: React.MouseEvent, contract: ContractSummary) => void;
-}
-
-const phaseConfig: Record<
- ContractPhase,
- { label: string; color: string; bgColor: string; borderColor: string }
-> = {
- research: {
- label: "Research",
- color: "text-purple-400",
- bgColor: "bg-purple-400/10",
- borderColor: "border-purple-400/30",
- },
- specify: {
- label: "Specify",
- color: "text-blue-400",
- bgColor: "bg-blue-400/10",
- borderColor: "border-blue-400/30",
- },
- plan: {
- label: "Plan",
- color: "text-cyan-400",
- bgColor: "bg-cyan-400/10",
- borderColor: "border-cyan-400/30",
- },
- execute: {
- label: "Execute",
- color: "text-yellow-400",
- bgColor: "bg-yellow-400/10",
- borderColor: "border-yellow-400/30",
- },
- review: {
- label: "Review",
- color: "text-green-400",
- bgColor: "bg-green-400/10",
- borderColor: "border-green-400/30",
- },
-};
-
-export function PhaseColumn({
- phase,
- contracts,
- onContractClick,
- onDrop,
- onContextMenu,
-}: PhaseColumnProps) {
- const [isDragOver, setIsDragOver] = useState(false);
- const config = phaseConfig[phase];
-
- const handleDragOver = (e: React.DragEvent) => {
- e.preventDefault();
- setIsDragOver(true);
- };
-
- const handleDragLeave = () => {
- setIsDragOver(false);
- };
-
- const handleDrop = (e: React.DragEvent) => {
- e.preventDefault();
- setIsDragOver(false);
- const contractId = e.dataTransfer.getData("contractId");
- if (contractId) {
- onDrop(contractId, phase);
- }
- };
-
- return (
- <div
- className={`
- flex flex-col min-w-[220px] flex-1 border border-[rgba(117,170,252,0.15)]
- ${isDragOver ? "bg-[rgba(117,170,252,0.05)]" : "bg-transparent"}
- transition-colors
- `}
- onDragOver={handleDragOver}
- onDragLeave={handleDragLeave}
- onDrop={handleDrop}
- >
- {/* Column header */}
- <div
- className={`
- p-3 border-b ${config.borderColor} ${config.bgColor}
- flex items-center justify-between
- `}
- >
- <span className={`font-mono text-xs uppercase tracking-wider ${config.color}`}>
- {config.label}
- </span>
- <span className="font-mono text-[10px] text-[#555]">
- ({contracts.length})
- </span>
- </div>
-
- {/* Cards container */}
- <div className="flex-1 overflow-y-auto p-2 space-y-2">
- {contracts.length === 0 ? (
- <div className="p-4 text-center font-mono text-[10px] text-[#555]">
- No contracts
- </div>
- ) : (
- contracts.map((contract) => (
- <WorkflowContractCard
- key={contract.id}
- contract={contract}
- onClick={() => onContractClick(contract.id)}
- onDragStart={(e) => {
- e.dataTransfer.setData("contractId", contract.id);
- e.dataTransfer.effectAllowed = "move";
- }}
- onContextMenu={onContextMenu ? (e) => onContextMenu(e, contract) : undefined}
- />
- ))
- )}
- </div>
- </div>
- );
-}
diff --git a/makima/frontend/src/components/workflow/WorkflowBoard.tsx b/makima/frontend/src/components/workflow/WorkflowBoard.tsx
deleted file mode 100644
index e36ca21..0000000
--- a/makima/frontend/src/components/workflow/WorkflowBoard.tsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import { useMemo, useState } from "react";
-import type { ContractSummary, ContractPhase } from "../../lib/api";
-import { PhaseColumn } from "./PhaseColumn";
-import { ContractContextMenu } from "../contracts/ContractContextMenu";
-
-interface WorkflowBoardProps {
- contracts: ContractSummary[];
- onContractClick: (contractId: string) => void;
- onPhaseChange: (contractId: string, newPhase: ContractPhase) => void;
- onMarkComplete?: (contract: ContractSummary) => void;
- onMarkActive?: (contract: ContractSummary) => void;
- onArchive?: (contract: ContractSummary) => void;
- onDelete?: (contract: ContractSummary) => void;
- onGoToSupervisor?: (contract: ContractSummary) => void;
-}
-
-const phases: ContractPhase[] = ["research", "specify", "plan", "execute", "review"];
-
-export function WorkflowBoard({
- contracts,
- onContractClick,
- onPhaseChange,
- onMarkComplete,
- onMarkActive,
- onArchive,
- onDelete,
- onGoToSupervisor,
-}: WorkflowBoardProps) {
- 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();
- e.stopPropagation(); // Prevent interference with drag-and-drop
- setContextMenuPosition({ x: e.clientX, y: e.clientY });
- setContextMenuContract(contract);
- };
-
- const closeContextMenu = () => {
- setContextMenuPosition(null);
- setContextMenuContract(null);
- };
-
- // Group contracts by phase
- const contractsByPhase = useMemo(() => {
- const grouped: Record<ContractPhase, ContractSummary[]> = {
- research: [],
- specify: [],
- plan: [],
- execute: [],
- review: [],
- };
-
- for (const contract of contracts) {
- const phase = contract.phase as ContractPhase;
- if (grouped[phase]) {
- grouped[phase].push(contract);
- } else {
- // Default to research if unknown phase
- grouped.research.push(contract);
- }
- }
-
- return grouped;
- }, [contracts]);
-
- return (
- <>
- <div className="flex gap-2 h-full overflow-x-auto">
- {phases.map((phase) => (
- <PhaseColumn
- key={phase}
- phase={phase}
- contracts={contractsByPhase[phase]}
- onContractClick={onContractClick}
- onDrop={onPhaseChange}
- onContextMenu={handleContextMenu}
- />
- ))}
- </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)}
- />
- )}
- </>
- );
-}
diff --git a/makima/frontend/src/components/workflow/WorkflowContractCard.tsx b/makima/frontend/src/components/workflow/WorkflowContractCard.tsx
deleted file mode 100644
index 86fcd13..0000000
--- a/makima/frontend/src/components/workflow/WorkflowContractCard.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-import { useNavigate } from "react-router";
-import type { ContractSummary, ContractStatus } from "../../lib/api";
-
-interface WorkflowContractCardProps {
- contract: ContractSummary;
- onClick: () => void;
- onDragStart: (e: React.DragEvent) => void;
- onContextMenu?: (e: React.MouseEvent) => void;
-}
-
-const statusConfig: Record<ContractStatus, { label: string; color: string }> = {
- active: { label: "Active", color: "text-green-400" },
- completed: { label: "Done", color: "text-blue-400" },
- archived: { label: "Archived", color: "text-[#555]" },
-};
-
-export function WorkflowContractCard({
- contract,
- onClick,
- onDragStart,
- onContextMenu,
-}: WorkflowContractCardProps) {
- const navigate = useNavigate();
- const status = statusConfig[contract.status] || statusConfig.active;
-
- const handleSupervisorClick = (e: React.MouseEvent) => {
- e.stopPropagation();
- if (contract.supervisorTaskId) {
- navigate(`/mesh/${contract.supervisorTaskId}`);
- }
- };
-
- return (
- <div
- draggable
- onDragStart={onDragStart}
- onClick={onClick}
- onContextMenu={onContextMenu}
- className="p-3 bg-[rgba(9,13,20,0.8)] border border-[rgba(117,170,252,0.2)] hover:border-[rgba(117,170,252,0.4)] cursor-pointer transition-colors select-none"
- >
- {/* Header row with name and supervisor button */}
- <div className="flex items-center justify-between gap-2 mb-1">
- <div className="font-mono text-sm text-[#dbe7ff] truncate flex-1">
- {contract.name}
- </div>
- {contract.supervisorTaskId && (
- <button
- onClick={handleSupervisorClick}
- title="Open Supervisor Task"
- className="flex-shrink-0 px-1.5 py-0.5 font-mono text-[10px] text-[#75aafc] hover:text-[#9bc3ff] border border-[rgba(117,170,252,0.25)] hover:border-[#3f6fb3] hover:bg-[rgba(117,170,252,0.1)] transition-colors"
- >
- ▶
- </button>
- )}
- </div>
-
- {/* Status and counts row */}
- <div className="flex items-center justify-between">
- <span className={`font-mono text-[10px] uppercase ${status.color}`}>
- {status.label}
- </span>
- <div className="flex items-center gap-2 font-mono text-[10px] text-[#555]">
- <span title="Files">{contract.fileCount} files</span>
- <span title="Tasks">{contract.taskCount} tasks</span>
- </div>
- </div>
-
- {/* Description preview if exists */}
- {contract.description && (
- <div className="mt-1 font-mono text-[10px] text-[#555] truncate">
- {contract.description}
- </div>
- )}
- </div>
- );
-}