From b2e9cebeff66f9825983e45aa6fa9f397cbf7c0b Mon Sep 17 00:00:00 2001 From: MaheshtheDev <38828053+MaheshtheDev@users.noreply.github.com> Date: Tue, 12 May 2026 00:33:50 +0000 Subject: [PATCH] feat: add close confirmation when modal has unsaved content - Intercepts all close paths: outside click, Escape, Cancel button, mobile X - Checks ALL tabs for unsaved content (not just active tab) - Blocks close during active submissions - Successful saves bypass confirmation (content was saved) --- apps/web/components/add-document/index.tsx | 57 ++++++++++++++++++++-- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/apps/web/components/add-document/index.tsx b/apps/web/components/add-document/index.tsx index 8702c774..0d9ebe0c 100644 --- a/apps/web/components/add-document/index.tsx +++ b/apps/web/components/add-document/index.tsx @@ -28,9 +28,20 @@ interface AddDocumentModalProps { export function AddDocumentModal({ isOpen, onClose }: AddDocumentModalProps) { const isMobile = useIsMobile() + const hasUnsavedContentRef = useRef<() => boolean>(() => false) + const isSubmittingRef = useRef(false) + + const handleCloseRequest = useCallback(() => { + if (isSubmittingRef.current) return // Block close during submission + if (hasUnsavedContentRef.current()) { + const confirmed = window.confirm("You have unsaved content. Are you sure you want to close?") + if (!confirmed) return + } + onClose() + }, [onClose]) return ( - !open && onClose()}> + !open && handleCloseRequest()}> Add Document
- +
@@ -85,9 +101,13 @@ const tabs = [ export function AddDocument({ onClose, isOpen, + hasUnsavedContentRef, + isSubmittingRef, }: { onClose: () => void isOpen?: boolean + hasUnsavedContentRef?: React.MutableRefObject<() => boolean> + isSubmittingRef?: React.MutableRefObject }) { const isMobile = useIsMobile() const [addParam, setAddParam] = useQueryState("add", addDocumentParam) @@ -380,6 +400,35 @@ export function AddDocument({ const isSubmitting = noteMutation.isPending || linkMutation.isPending || fileMutation.isPending + const hasUnsavedContent = useCallback((): boolean => { + if (noteContent.trim().length > 0) return true + if (noteDroppedFiles.length > 0) return true + if (linkData.url.trim().length > 0) return true + if (fileData.items.length > 0) return true + return false + }, [noteContent, noteDroppedFiles, linkData, fileData]) + + useEffect(() => { + if (hasUnsavedContentRef) { + hasUnsavedContentRef.current = hasUnsavedContent + } + }, [hasUnsavedContent, hasUnsavedContentRef]) + + useEffect(() => { + if (isSubmittingRef) { + isSubmittingRef.current = isSubmitting + } + }, [isSubmitting, isSubmittingRef]) + + const handleClose = useCallback(() => { + if (isSubmitting) return + if (hasUnsavedContent()) { + const confirmed = window.confirm("You have unsaved content. Are you sure you want to close?") + if (!confirmed) return + } + onClose() + }, [isSubmitting, hasUnsavedContent, onClose]) + const fileTabHasPending = fileData.items.some((i) => i.status === "pending") const fileTabSubmitDisabled = activeTab === "file" && (!fileTabHasPending || isSubmitting) @@ -411,7 +460,7 @@ export function AddDocument({