diff --git a/frontend/src/components/test-detail/TestDetailHeader.tsx b/frontend/src/components/test-detail/TestDetailHeader.tsx index 26b58f7..fd3bfee 100644 --- a/frontend/src/components/test-detail/TestDetailHeader.tsx +++ b/frontend/src/components/test-detail/TestDetailHeader.tsx @@ -87,17 +87,21 @@ export default function TestDetailHeader({ const role = user?.role ?? ""; const currentIdx = STATE_INDEX[test.state]; const [showDiscussModal, setShowDiscussModal] = useState(false); + const [discussionSent, setDiscussionSent] = useState(false); const [discussResult, setDiscussResult] = useState<{ username: string; email: string | null; role: string; } | null>(null); const discussMutation = useMutation({ mutationFn: () => requestDiscussion(test.id), - onSuccess: (data) => setDiscussResult({ - username: data.rejector_username, - email: data.rejector_email, - role: data.rejector_role, - }), + onSuccess: (data) => { + setDiscussResult({ + username: data.rejector_username, + email: data.rejector_email, + role: data.rejector_role, + }); + setDiscussionSent(true); + }, }); const formatDate = (d: string | null) => { @@ -234,37 +238,74 @@ export default function TestDetailHeader({ ); } - // Disputed: the lead who approved can change their vote to rejected + // Disputed state: symmetric actions for both leads if (test.state === "disputed") { - const canChangeVote = + const isApproving = (role === "red_lead" && test.red_validation_status === "approved") || (role === "blue_lead" && test.blue_validation_status === "approved") || - role === "admin"; + (role === "admin" && test.red_validation_status === "approved"); - if (canChangeVote) { - const side = role === "red_lead" ? "red" : role === "blue_lead" ? "blue" : null; - if (side || role === "admin") { - buttons.push( -
- {/* Confirm keeping approval → open discussion modal */} + const isRejecting = + (role === "red_lead" && test.red_validation_status === "rejected") || + (role === "blue_lead" && test.blue_validation_status === "rejected") || + (role === "admin" && test.blue_validation_status === "rejected"); + + const approvingSide: "red" | "blue" = + test.red_validation_status === "approved" ? "red" : "blue"; + const rejectingSide: "red" | "blue" = + test.red_validation_status === "rejected" ? "red" : "blue"; + + if (isApproving || role === "admin") { + buttons.push( +
+
+ {/* Discussion request button — shows ✓ after sent */} + {discussionSent ? ( + + + Discussion Requested ✓ + + ) : ( + + )} + {/* Change approving vote to rejected */} - {/* Change vote to rejected */} - -
, - ); - } +
+

+ You approved — change your vote or request a discussion +

+
, + ); + } + + if (isRejecting && !isApproving) { + buttons.push( +
+ {/* Change rejecting vote to approved */} + +

+ You rejected — change your vote if you agree after discussion +

+
, + ); } }