From cf879b34d5467f42556afc9909f0de6993ddc874 Mon Sep 17 00:00:00 2001 From: Hiren Kangad Date: Thu, 12 Mar 2026 19:34:28 +0530 Subject: [PATCH] feat(review): add draftCommentText state and double-submit guard --- frontend/src/pages/Editor.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/Editor.tsx b/frontend/src/pages/Editor.tsx index a45f537..603f0ef 100644 --- a/frontend/src/pages/Editor.tsx +++ b/frontend/src/pages/Editor.tsx @@ -109,6 +109,8 @@ export default function Editor({ isPublicView }: EditorProps) { const [draftPin, setDraftPin] = useState(null); const [openThreadDetailId, setOpenThreadDetailId] = useState(null); const expandSeqRef = useRef(0); + const [draftCommentText, setDraftCommentText] = useState(''); + const [creatingPointThread, setCreatingPointThread] = useState(false); const [focusMode, setFocusMode] = useState(false); const [layerList, setLayerList] = useState([]); const [selectedLayerIds, setSelectedLayerIds] = useState([]); @@ -320,6 +322,7 @@ export default function Editor({ isPublicView }: EditorProps) { if (draftPin) { e.preventDefault(); setDraftPin(null); + setDraftCommentText(''); return; } if (openThreadDetailId) { @@ -345,9 +348,10 @@ export default function Editor({ isPublicView }: EditorProps) { // Create point-pinned thread via REST const handleCreatePointThread = useCallback(async (draft: DraftPin, content: string) => { - if (!resolvedBoardId) return; + if (!resolvedBoardId || creatingPointThread) return; const token = localStorage.getItem('refboard_token'); if (!token) return; + setCreatingPointThread(true); try { const res = await fetch(`/api/boards/${resolvedBoardId}/threads`, { method: 'POST', @@ -368,18 +372,22 @@ export default function Editor({ isPublicView }: EditorProps) { const data = await res.json(); // Clear draft, pre-focus the new thread setDraftPin(null); + setDraftCommentText(''); setFocusedThreadId(data.thread.id); expandSeqRef.current += 1; setExpandRequest({ threadId: data.thread.id, seq: expandSeqRef.current }); } catch (err: any) { showToast('Failed to create comment: ' + (err.message || 'network error')); + } finally { + setCreatingPointThread(false); } - }, [resolvedBoardId, showToast]); + }, [resolvedBoardId, showToast, creatingPointThread]); // Clear draft and focus when exiting review mode useEffect(() => { if (!reviewMode) { setDraftPin(null); + setDraftCommentText(''); setFocusedThreadId(null); setExpandRequest(null); }