diff --git a/packages/web/src/components/SessionDetail.tsx b/packages/web/src/components/SessionDetail.tsx index 8c6f74afc..dd4e9e6aa 100644 --- a/packages/web/src/components/SessionDetail.tsx +++ b/packages/web/src/components/SessionDetail.tsx @@ -290,36 +290,79 @@ function ClientTimestamps({ // ── PR Card ────────────────────────────────────────────────────────── function PRCard({ pr, sessionId }: { pr: DashboardPR; sessionId: string }) { - const [sendingCommentUrl, setSendingCommentUrl] = useState(null); - const [sentCommentUrl, setSentCommentUrl] = useState(null); - const [errorCommentUrl, setErrorCommentUrl] = useState(null); - const timerRef = useRef | null>(null); + const [sendingComments, setSendingComments] = useState>(new Set()); + const [sentComments, setSentComments] = useState>(new Set()); + const [errorComments, setErrorComments] = useState>(new Set()); + const timersRef = useRef>>(new Map()); useEffect(() => { return () => { - if (timerRef.current) clearTimeout(timerRef.current); + timersRef.current.forEach((timer) => clearTimeout(timer)); }; }, []); const handleAskAgentToFix = async (comment: { url: string; path: string; body: string }) => { - setSendingCommentUrl(comment.url); - setErrorCommentUrl(null); - setSentCommentUrl(null); + // Clear any existing feedback state for this comment + setSentComments((prev) => { + const next = new Set(prev); + next.delete(comment.url); + return next; + }); + setErrorComments((prev) => { + const next = new Set(prev); + next.delete(comment.url); + return next; + }); + + // Mark as sending + setSendingComments((prev) => new Set(prev).add(comment.url)); await askAgentToFix( sessionId, comment, () => { - setSendingCommentUrl(null); - setSentCommentUrl(comment.url); - if (timerRef.current) clearTimeout(timerRef.current); - timerRef.current = setTimeout(() => setSentCommentUrl(null), 3000); + // Success: remove from sending, add to sent + setSendingComments((prev) => { + const next = new Set(prev); + next.delete(comment.url); + return next; + }); + setSentComments((prev) => new Set(prev).add(comment.url)); + + // Clear sent state after 3 seconds + const existingTimer = timersRef.current.get(comment.url); + if (existingTimer) clearTimeout(existingTimer); + const timer = setTimeout(() => { + setSentComments((prev) => { + const next = new Set(prev); + next.delete(comment.url); + return next; + }); + timersRef.current.delete(comment.url); + }, 3000); + timersRef.current.set(comment.url, timer); }, () => { - setSendingCommentUrl(null); - setErrorCommentUrl(comment.url); - if (timerRef.current) clearTimeout(timerRef.current); - timerRef.current = setTimeout(() => setErrorCommentUrl(null), 3000); + // Error: remove from sending, add to error + setSendingComments((prev) => { + const next = new Set(prev); + next.delete(comment.url); + return next; + }); + setErrorComments((prev) => new Set(prev).add(comment.url)); + + // Clear error state after 3 seconds + const existingTimer = timersRef.current.get(comment.url); + if (existingTimer) clearTimeout(existingTimer); + const timer = setTimeout(() => { + setErrorComments((prev) => { + const next = new Set(prev); + next.delete(comment.url); + return next; + }); + timersRef.current.delete(comment.url); + }, 3000); + timersRef.current.set(comment.url, timer); }, ); }; @@ -433,21 +476,21 @@ function PRCard({ pr, sessionId }: { pr: DashboardPR; sessionId: string }) {