summaryrefslogtreecommitdiff
path: root/makima/frontend/src/components/directives/DirectiveList.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'makima/frontend/src/components/directives/DirectiveList.tsx')
-rw-r--r--makima/frontend/src/components/directives/DirectiveList.tsx87
1 files changed, 87 insertions, 0 deletions
diff --git a/makima/frontend/src/components/directives/DirectiveList.tsx b/makima/frontend/src/components/directives/DirectiveList.tsx
new file mode 100644
index 0000000..6393ea7
--- /dev/null
+++ b/makima/frontend/src/components/directives/DirectiveList.tsx
@@ -0,0 +1,87 @@
+import type { DirectiveSummary, DirectiveStatus } from "../../lib/api";
+
+const STATUS_BADGE: Record<DirectiveStatus, { color: string; label: string }> = {
+ draft: { color: "text-[#7788aa] border-[#2a3a5a]", label: "DRAFT" },
+ active: { color: "text-green-400 border-green-800", label: "ACTIVE" },
+ idle: { color: "text-yellow-400 border-yellow-800", label: "IDLE" },
+ paused: { color: "text-orange-400 border-orange-800", label: "PAUSED" },
+ archived: { color: "text-[#556677] border-[#2a3a5a]", label: "ARCHIVED" },
+};
+
+interface DirectiveListProps {
+ directives: DirectiveSummary[];
+ selectedId: string | null;
+ onSelect: (id: string) => void;
+ onCreate: () => void;
+}
+
+export function DirectiveList({ directives, selectedId, onSelect, onCreate }: DirectiveListProps) {
+ return (
+ <div className="flex flex-col h-full">
+ <div className="flex items-center justify-between px-3 py-2 border-b border-dashed border-[rgba(117,170,252,0.2)]">
+ <span className="text-[11px] font-mono text-[#9bc3ff] uppercase tracking-wide">
+ Directives
+ </span>
+ <button
+ type="button"
+ onClick={onCreate}
+ className="text-[11px] font-mono text-[#75aafc] hover:text-white bg-transparent border border-[rgba(117,170,252,0.3)] rounded px-2 py-0.5 hover:border-[rgba(117,170,252,0.6)] transition-colors"
+ >
+ + New
+ </button>
+ </div>
+ <div className="flex-1 overflow-y-auto">
+ {directives.length === 0 ? (
+ <div className="px-3 py-6 text-center text-[#556677] font-mono text-[11px]">
+ No directives yet
+ </div>
+ ) : (
+ directives.map((d) => {
+ const badge = STATUS_BADGE[d.status] || STATUS_BADGE.draft;
+ const progress = d.totalSteps > 0
+ ? Math.round((d.completedSteps / d.totalSteps) * 100)
+ : 0;
+
+ return (
+ <button
+ key={d.id}
+ type="button"
+ onClick={() => onSelect(d.id)}
+ className={`w-full text-left px-3 py-2.5 border-b border-[rgba(117,170,252,0.1)] hover:bg-[rgba(117,170,252,0.05)] transition-colors ${
+ selectedId === d.id ? "bg-[rgba(117,170,252,0.1)]" : ""
+ }`}
+ >
+ <div className="flex items-center justify-between mb-1">
+ <span className="text-[12px] font-mono text-white truncate pr-2">
+ {d.title}
+ </span>
+ <span
+ className={`text-[9px] font-mono ${badge.color} border rounded px-1.5 py-0.5 shrink-0`}
+ >
+ {badge.label}
+ </span>
+ </div>
+ <p className="text-[10px] text-[#7788aa] font-mono truncate mb-1.5">
+ {d.goal}
+ </p>
+ {d.totalSteps > 0 && (
+ <div className="flex items-center gap-2">
+ <div className="flex-1 h-1 bg-[#1a2540] rounded overflow-hidden">
+ <div
+ className="h-full bg-emerald-600 rounded transition-all"
+ style={{ width: `${progress}%` }}
+ />
+ </div>
+ <span className="text-[9px] font-mono text-[#556677] shrink-0">
+ {d.completedSteps}/{d.totalSteps}
+ </span>
+ </div>
+ )}
+ </button>
+ );
+ })
+ )}
+ </div>
+ </div>
+ );
+}