summaryrefslogtreecommitdiff
path: root/makima/frontend/src/components/workflow/PhaseColumn.tsx
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-01-11 05:52:14 +0000
committersoryu <soryu@soryu.co>2026-01-15 00:21:16 +0000
commit87044a747b47bd83249d61a45842c7f7b2eae56d (patch)
treeef2000ce79ffcc2723ef841acef5aa1deb1d5378 /makima/frontend/src/components/workflow/PhaseColumn.tsx
parent077820c4167c168072d217a1b01df840463a12a8 (diff)
downloadsoryu-87044a747b47bd83249d61a45842c7f7b2eae56d.tar.gz
soryu-87044a747b47bd83249d61a45842c7f7b2eae56d.zip
Contract system
Diffstat (limited to 'makima/frontend/src/components/workflow/PhaseColumn.tsx')
-rw-r--r--makima/frontend/src/components/workflow/PhaseColumn.tsx123
1 files changed, 123 insertions, 0 deletions
diff --git a/makima/frontend/src/components/workflow/PhaseColumn.tsx b/makima/frontend/src/components/workflow/PhaseColumn.tsx
new file mode 100644
index 0000000..ddea85f
--- /dev/null
+++ b/makima/frontend/src/components/workflow/PhaseColumn.tsx
@@ -0,0 +1,123 @@
+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;
+}
+
+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,
+}: 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";
+ }}
+ />
+ ))
+ )}
+ </div>
+ </div>
+ );
+}