From 87044a747b47bd83249d61a45842c7f7b2eae56d Mon Sep 17 00:00:00 2001
From: soryu <soryu@soryu.co>
Date: Sun, 11 Jan 2026 05:52:14 +0000
Subject:  Contract system

---
 .../src/components/workflow/PhaseColumn.tsx        | 123 +++++++++++++++++++++
 1 file changed, 123 insertions(+)
 create mode 100644 makima/frontend/src/components/workflow/PhaseColumn.tsx

(limited to 'makima/frontend/src/components/workflow/PhaseColumn.tsx')

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>
+  );
+}
-- 
cgit v1.2.3

