summaryrefslogtreecommitdiff
path: root/makima/frontend/src/components/orders/OrderDetail.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'makima/frontend/src/components/orders/OrderDetail.tsx')
-rw-r--r--makima/frontend/src/components/orders/OrderDetail.tsx84
1 files changed, 84 insertions, 0 deletions
diff --git a/makima/frontend/src/components/orders/OrderDetail.tsx b/makima/frontend/src/components/orders/OrderDetail.tsx
index 338cc60..ebc8124 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,11 @@ export function OrderDetail({
step:{order.directiveStepId.slice(0, 8)}
</span>
)}
+ {order.directiveId && (
+ <span className="text-[10px] font-mono text-[#75aafc] border border-[rgba(117,170,252,0.3)] rounded px-1.5 py-0.5 truncate max-w-[120px]">
+ DOG: {order.dogId ? (dogs.find((d) => d.id === order.dogId)?.name || order.dogId.slice(0, 8) + "...") : "None"}
+ </span>
+ )}
<button
type="button"
onClick={onDelete}
@@ -498,6 +507,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