summaryrefslogblamecommitdiff
path: root/makima/frontend/src/components/workflow/PhaseColumn.tsx
blob: 277b04cbe252f7c255baafe8794be46fafb26c9c (plain) (tree)
1
2
3
4
5
6
7
8
9








                                                                    
                                                                           










































                                                                        
                































































                                                                                       
                                                                                           






              
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>
  );
}