From ae3bc57de7a240c3c8ab15080b405e8ea3e16ccb Mon Sep 17 00:00:00 2001
From: soryu <soryu@soryu.co>
Date: Thu, 5 Mar 2026 23:25:40 +0000
Subject: WIP: heartbeat checkpoint

---
 .../frontend/src/components/orders/OrderDetail.tsx | 91 ++++++++++++++++++++++
 1 file changed, 91 insertions(+)

(limited to 'makima/frontend/src/components/orders/OrderDetail.tsx')

diff --git a/makima/frontend/src/components/orders/OrderDetail.tsx b/makima/frontend/src/components/orders/OrderDetail.tsx
index 9c3ac97..4267725 100644
--- a/makima/frontend/src/components/orders/OrderDetail.tsx
+++ b/makima/frontend/src/components/orders/OrderDetail.tsx
@@ -6,6 +6,7 @@ import type {
   OrderType,
   UpdateOrderRequest,
   DirectiveSummary,
+  DirectiveOrderGroup,
 } from "../../lib/api";
 
 const STATUS_BADGE: Record<OrderStatus, { color: string; label: string }> = {
@@ -37,6 +38,7 @@ const STATUS_OPTIONS: OrderStatus[] = ["open", "in_progress", "under_review", "d
 interface OrderDetailProps {
   order: Order;
   directives: DirectiveSummary[];
+  dogs: DirectiveOrderGroup[];
   onUpdate: (req: UpdateOrderRequest) => Promise<void>;
   onDelete: () => void;
   onLinkDirective: (directiveId: string) => Promise<void>;
@@ -47,6 +49,7 @@ interface OrderDetailProps {
 export function OrderDetail({
   order,
   directives,
+  dogs,
   onUpdate,
   onDelete,
   onLinkDirective,
@@ -61,6 +64,7 @@ export function OrderDetail({
   const [labelsText, setLabelsText] = useState(order.labels.join(", "));
   const [showLinkDirective, setShowLinkDirective] = useState(false);
   const [directiveSearch, setDirectiveSearch] = useState("");
+  const [showDogSelector, setShowDogSelector] = useState(false);
 
   const badge = STATUS_BADGE[order.status] || STATUS_BADGE.open;
   const currentPriority = PRIORITY_OPTIONS.find((p) => p.value === order.priority) || PRIORITY_OPTIONS[4];
@@ -192,6 +196,18 @@ export function OrderDetail({
             Step: <span className="text-[#7788aa]">{order.directiveStepId.slice(0, 8)}...</span>
           </div>
         )}
+        {order.directiveId && (
+          <div className="text-[10px] font-mono text-[#556677] mb-1">
+            DOG:{" "}
+            {order.dogId ? (
+              <span className="text-[#75aafc]">
+                {dogs.find((d) => d.id === order.dogId)?.name || order.dogId.slice(0, 8) + "..."}
+              </span>
+            ) : (
+              <span className="text-[#445566] italic">None</span>
+            )}
+          </div>
+        )}
 
         {/* Controls */}
         <div className="flex flex-wrap gap-2 mt-2">
@@ -501,6 +517,81 @@ export function OrderDetail({
             )}
           </div>
 
+          {/* Assign to DOG */}
+          {order.directiveId && (
+            <div>
+              <div className="flex items-center gap-1.5">
+                <button
+                  type="button"
+                  onClick={() => setShowDogSelector(!showDogSelector)}
+                  className="text-[10px] font-mono text-[#75aafc] hover:text-white border border-[rgba(117,170,252,0.3)] rounded px-2 py-1 flex-1 text-left"
+                >
+                  {order.dogId ? "Change DOG" : "Assign to DOG"}
+                </button>
+                {order.dogId && (
+                  <button
+                    type="button"
+                    onClick={() => onUpdate({ dogId: null })}
+                    className="text-[10px] font-mono text-red-400 hover:text-red-300 border border-red-800 rounded px-2 py-1"
+                    title="Remove DOG assignment"
+                  >
+                    Unlink
+                  </button>
+                )}
+              </div>
+              {showDogSelector && (
+                <div className="mt-1 border border-[rgba(117,170,252,0.2)] bg-[#0a1525] rounded">
+                  <div className="max-h-32 overflow-y-auto">
+                    {dogs.length === 0 ? (
+                      <div className="px-3 py-2 text-[10px] font-mono text-[#556677]">
+                        No DOGs available for this directive
+                      </div>
+                    ) : (
+                      dogs.map((d) => {
+                        const isAssigned = d.id === order.dogId;
+                        const statusColors: Record<string, string> = {
+                          open: "text-[#75aafc] border-[rgba(117,170,252,0.4)]",
+                          in_progress: "text-yellow-400 border-yellow-800",
+                          done: "text-emerald-400 border-emerald-800",
+                          archived: "text-[#556677] border-[#2a3a5a]",
+                        };
+                        const sColor = statusColors[d.status] || statusColors.open;
+                        return (
+                          <button
+                            key={d.id}
+                            type="button"
+                            onClick={async () => {
+                              await onUpdate({ dogId: d.id });
+                              setShowDogSelector(false);
+                            }}
+                            className={`w-full text-left px-3 py-1.5 text-[10px] font-mono hover:bg-[rgba(117,170,252,0.1)] border-b border-[rgba(117,170,252,0.1)] last:border-b-0 ${
+                              isAssigned ? "bg-[rgba(117,170,252,0.08)] text-white" : "text-[#9bc3ff]"
+                            }`}
+                          >
+                            <div className="flex items-center gap-1.5">
+                              <span className={`shrink-0 text-[8px] font-mono ${sColor} border rounded px-1 py-0.5 uppercase`}>
+                                {d.status}
+                              </span>
+                              <span className="truncate">{d.name}</span>
+                              {isAssigned && (
+                                <span className="shrink-0 text-[8px] text-emerald-400">current</span>
+                              )}
+                            </div>
+                            {d.description && (
+                              <div className="text-[8px] text-[#556677] truncate mt-0.5">
+                                {d.description}
+                              </div>
+                            )}
+                          </button>
+                        );
+                      })
+                    )}
+                  </div>
+                </div>
+              )}
+            </div>
+          )}
+
           {/* Convert to Directive Step */}
           {!order.directiveStepId && order.directiveId && (
             <button
-- 
cgit v1.2.3

