summaryrefslogtreecommitdiff
path: root/makima/frontend/src/components/orders/OrderDetail.tsx
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-03-05 23:25:40 +0000
committersoryu <soryu@soryu.co>2026-03-07 02:28:19 +0000
commitae3bc57de7a240c3c8ab15080b405e8ea3e16ccb (patch)
tree96562ad1b73efa0f21ea79ae571e1c8674549d31 /makima/frontend/src/components/orders/OrderDetail.tsx
parentb8ec238084d9d5b210a67bc8c8cbb9a293facf28 (diff)
downloadsoryu-ae3bc57de7a240c3c8ab15080b405e8ea3e16ccb.tar.gz
soryu-ae3bc57de7a240c3c8ab15080b405e8ea3e16ccb.zip
Diffstat (limited to 'makima/frontend/src/components/orders/OrderDetail.tsx')
-rw-r--r--makima/frontend/src/components/orders/OrderDetail.tsx91
1 files changed, 91 insertions, 0 deletions
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