diff --git a/frontend/src/api/tests.ts b/frontend/src/api/tests.ts index 0c789a5..5f12da4 100644 --- a/frontend/src/api/tests.ts +++ b/frontend/src/api/tests.ts @@ -248,6 +248,19 @@ export async function validateAsBlueLead( return data; } +// ── Dispute resolution ─────────────────────────────────────────────── + +export interface ResolveDisputePayload { + target_team: "red" | "blue"; + notes?: string; +} + +/** The approving lead flips to reject, choosing which team must redo the work. */ +export async function resolveDispute(testId: string, payload: ResolveDisputePayload): Promise { + const { data } = await client.post(`/tests/${testId}/resolve-dispute`, payload); + return data; +} + // ── Reopen ───────────────────────────────────────────────────────── /** Reopen a rejected test — moves back to draft. */ diff --git a/frontend/src/components/test-detail/ResolveDisputeModal.tsx b/frontend/src/components/test-detail/ResolveDisputeModal.tsx new file mode 100644 index 0000000..c279b90 --- /dev/null +++ b/frontend/src/components/test-detail/ResolveDisputeModal.tsx @@ -0,0 +1,112 @@ +import { useState } from "react"; +import { Shield, ShieldCheck, Loader2, X, XCircle } from "lucide-react"; + +// ── Props ────────────────────────────────────────────────────────── + +interface ResolveDisputeModalProps { + isSubmitting: boolean; + onSubmit: (targetTeam: "red" | "blue", notes: string) => void; + onClose: () => void; +} + +// ── Component ────────────────────────────────────────────────────── + +export default function ResolveDisputeModal({ + isSubmitting, + onSubmit, + onClose, +}: ResolveDisputeModalProps) { + const [targetTeam, setTargetTeam] = useState<"red" | "blue" | null>(null); + const [notes, setNotes] = useState(""); + + const canSubmit = targetTeam !== null && !isSubmitting; + + return ( +
+
+ {/* Header */} +
+
+ +

Change Vote to Rejected

+
+ +
+ + {/* Body */} +
+

+ You're agreeing that this test needs rework. Instead of restarting from scratch, + pick which team's work is actually the problem — the test goes straight back to + their queue and the other team's work is left untouched. +

+ +
+

Send back to

+
+ + +
+
+ +
+ +