From 4ba1d6322622b53ce873fa865ea3d3e7d233a9dc Mon Sep 17 00:00:00 2001 From: Urjit Chakraborty <135136842+urjitc@users.noreply.github.com> Date: Sat, 17 Jan 2026 15:43:53 -0500 Subject: [PATCH 1/7] fix: add deleteFolderWithContents operation to workspace operations --- .../workspace/use-workspace-operations.ts | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/hooks/workspace/use-workspace-operations.ts b/src/hooks/workspace/use-workspace-operations.ts index fd96e654..54b5b3c1 100644 --- a/src/hooks/workspace/use-workspace-operations.ts +++ b/src/hooks/workspace/use-workspace-operations.ts @@ -33,6 +33,7 @@ export interface WorkspaceOperations { createFolderWithItems: (name: string, itemIds: string[], color?: CardColor) => string; updateFolder: (folderId: string, changes: Partial) => void; deleteFolder: (folderId: string) => void; + deleteFolderWithContents: (folderId: string) => void; moveItemToFolder: (itemId: string, folderId: string | null) => void; moveItemsToFolder: (itemIds: string[], folderId: string | null) => void; isPending: boolean; @@ -484,6 +485,35 @@ export function useWorkspaceOperations( [deleteItem, currentState.items] ); + // deleteFolderWithContents deletes the folder and all items inside it + const deleteFolderWithContents = useCallback( + async (folderId: string) => { + const folder = currentState.items?.find(i => i.id === folderId && i.type === 'folder'); + logger.debug("📁 [FOLDER-DELETE-WITH-CONTENTS] Deleting folder and contents:", { folderId, folderName: folder?.name }); + + // Find all items in this folder + const itemsInFolder = currentState.items.filter(item => item.folderId === folderId); + const itemCount = itemsInFolder.length; + + logger.debug("📁 [FOLDER-DELETE-WITH-CONTENTS] Found items in folder:", { itemCount, itemIds: itemsInFolder.map(i => i.id) }); + + // Delete all items in the folder first + for (const item of itemsInFolder) { + await deleteItem(item.id); + } + + // Then delete the folder itself + await deleteItem(folderId); + + toast.success( + folder + ? `Folder "${folder.name}" and ${itemCount} ${itemCount === 1 ? 'item' : 'items'} deleted` + : `Folder and ${itemCount} ${itemCount === 1 ? 'item' : 'items'} deleted` + ); + }, + [deleteItem, currentState.items] + ); + const moveItemToFolder = useCallback( (itemId: string, folderId: string | null) => { logger.debug("📁 [ITEM-MOVE] Moving item to folder:", { itemId, folderId }); @@ -566,6 +596,7 @@ export function useWorkspaceOperations( createFolderWithItems, updateFolder, deleteFolder, + deleteFolderWithContents, moveItemToFolder, moveItemsToFolder, isPending: mutation.isPending, From f8a3f39441400842bc55a7314fa39a4f70b277fd Mon Sep 17 00:00:00 2001 From: Urjit Chakraborty <135136842+urjitc@users.noreply.github.com> Date: Sat, 17 Jan 2026 15:43:58 -0500 Subject: [PATCH 2/7] fix: add folder delete dialog with item deletion choice options --- .../workspace-canvas/FolderCard.tsx | 72 +++++++++++++++++-- 1 file changed, 65 insertions(+), 7 deletions(-) diff --git a/src/components/workspace-canvas/FolderCard.tsx b/src/components/workspace-canvas/FolderCard.tsx index 87f74c43..e512c78d 100644 --- a/src/components/workspace-canvas/FolderCard.tsx +++ b/src/components/workspace-canvas/FolderCard.tsx @@ -53,6 +53,7 @@ interface FolderCardProps { onOpenFolder: (folderId: string) => void; onUpdateItem: (itemId: string, updates: Partial) => void; onDeleteItem: (itemId: string) => void; + onDeleteFolderWithContents?: (folderId: string) => void; // Callback to delete folder and all items inside onMoveItem?: (itemId: string, folderId: string | null) => void; // Callback to move folder to another location } @@ -70,10 +71,12 @@ function FolderCardComponent({ onOpenFolder, onUpdateItem, onDeleteItem, + onDeleteFolderWithContents, onMoveItem, }: FolderCardProps) { const [showColorPicker, setShowColorPicker] = useState(false); const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); + const [deleteOption, setDeleteOption] = useState<'keep' | 'delete' | null>(null); const [showMoveDialog, setShowMoveDialog] = useState(false); const [isDropdownOpen, setIsDropdownOpen] = useState(false); const [isDragHover, setIsDragHover] = useState(false); @@ -210,9 +213,21 @@ function FolderCardComponent({ }, [item.id, onUpdateItem]); const handleDelete = useCallback(() => { - onDeleteItem(item.id); + if (deleteOption === 'delete' && onDeleteFolderWithContents) { + onDeleteFolderWithContents(item.id); + } else { + onDeleteItem(item.id); + } setShowDeleteConfirm(false); - }, [item.id, onDeleteItem]); + setDeleteOption(null); + }, [item.id, onDeleteItem, onDeleteFolderWithContents, deleteOption]); + + // Reset delete option when dialog closes + useEffect(() => { + if (!showDeleteConfirm) { + setDeleteOption(null); + } + }, [showDeleteConfirm]); // Calculate colors using the same utilities as WorkspaceCard const bodyBgColor = getCardColorCSS(folderColor, 0.4); // Body is more transparent @@ -436,14 +451,56 @@ function FolderCardComponent({ > Delete Folder - - Are you sure you want to delete "{item.name}"? Items in this - folder will be moved out, but not deleted. + +
+
+ Choose what happens to the {itemCount} {itemCount === 1 ? 'item' : 'items'} in "{item.name}": +
+
+ + +
+
e.stopPropagation()} + onClick={(e) => { + e.stopPropagation(); + setDeleteOption(null); + }} onMouseDown={(e) => e.stopPropagation()} > Cancel @@ -454,7 +511,8 @@ function FolderCardComponent({ handleDelete(); }} onMouseDown={(e) => e.stopPropagation()} - className="bg-destructive text-destructive-foreground hover:bg-destructive/90" + disabled={deleteOption === null} + className="bg-destructive text-destructive-foreground hover:bg-destructive/90 disabled:opacity-50 disabled:cursor-not-allowed" > Delete From 10014826fb4115df7038ddb4130172d6b3df1751 Mon Sep 17 00:00:00 2001 From: Urjit Chakraborty <135136842+urjitc@users.noreply.github.com> Date: Sat, 17 Jan 2026 15:44:01 -0500 Subject: [PATCH 3/7] fix: wire up deleteFolderWithContents prop through component chain --- src/components/workspace-canvas/WorkspaceContent.tsx | 3 +++ src/components/workspace-canvas/WorkspaceGrid.tsx | 3 +++ src/components/workspace-canvas/WorkspaceSection.tsx | 1 + 3 files changed, 7 insertions(+) diff --git a/src/components/workspace-canvas/WorkspaceContent.tsx b/src/components/workspace-canvas/WorkspaceContent.tsx index c2dd612f..7702d8a2 100644 --- a/src/components/workspace-canvas/WorkspaceContent.tsx +++ b/src/components/workspace-canvas/WorkspaceContent.tsx @@ -32,6 +32,7 @@ interface WorkspaceContentProps { onMoveItem?: (itemId: string, folderId: string | null) => void; // Callback to move item to folder onMoveItems?: (itemIds: string[], folderId: string | null) => void; // Callback to move multiple items to folder (bulk move) onOpenFolder?: (folderId: string) => void; // Callback when folder is clicked + onDeleteFolderWithContents?: (folderId: string) => void; // Callback to delete folder and all items inside onPDFUpload?: (files: File[]) => Promise; // Function to handle PDF upload } @@ -55,6 +56,7 @@ export default function WorkspaceContent({ onMoveItem, onMoveItems, onOpenFolder, + onDeleteFolderWithContents, onPDFUpload, }: WorkspaceContentProps) { // Use external ref if provided (from dashboard page), otherwise create local one @@ -406,6 +408,7 @@ export default function WorkspaceContent({ onMoveItem={onMoveItem} onMoveItems={onMoveItems} onOpenFolder={handleOpenFolder} + onDeleteFolderWithContents={onDeleteFolderWithContents} addItem={addItem} onPDFUpload={onPDFUpload} setOpenModalItemId={setOpenModalItemId} diff --git a/src/components/workspace-canvas/WorkspaceGrid.tsx b/src/components/workspace-canvas/WorkspaceGrid.tsx index 235b2ec3..98dab37a 100644 --- a/src/components/workspace-canvas/WorkspaceGrid.tsx +++ b/src/components/workspace-canvas/WorkspaceGrid.tsx @@ -30,6 +30,7 @@ interface WorkspaceGridProps { onMoveItem?: (itemId: string, folderId: string | null) => void; // Callback to move item to folder onMoveItems?: (itemIds: string[], folderId: string | null) => void; // Callback to move multiple items to folder (bulk move) onOpenFolder?: (folderId: string) => void; // Callback when folder is clicked + onDeleteFolderWithContents?: (folderId: string) => void; // Callback to delete folder and all items inside addItem?: (type: CardType, name?: string, initialData?: Partial) => string | void; // Function to add new items onPDFUpload?: (files: File[]) => Promise; // Function to handle PDF upload setOpenModalItemId?: (id: string | null) => void; // Function to open modal for newly created items @@ -59,6 +60,7 @@ export function WorkspaceGrid({ onMoveItem, onMoveItems, onOpenFolder, + onDeleteFolderWithContents, addItem, onPDFUpload, setOpenModalItemId, @@ -531,6 +533,7 @@ export function WorkspaceGrid({ onOpenFolder={handleOpenFolder} onUpdateItem={handleUpdateItem} onDeleteItem={handleDeleteItem} + onDeleteFolderWithContents={onDeleteFolderWithContents} onMoveItem={onMoveItem} /> ) : item.type === 'flashcard' ? ( diff --git a/src/components/workspace-canvas/WorkspaceSection.tsx b/src/components/workspace-canvas/WorkspaceSection.tsx index a2f7a30c..05432f7e 100644 --- a/src/components/workspace-canvas/WorkspaceSection.tsx +++ b/src/components/workspace-canvas/WorkspaceSection.tsx @@ -501,6 +501,7 @@ export function WorkspaceSection({ workspaceColor={workspaceColor} onMoveItem={operations?.moveItemToFolder} onMoveItems={operations?.moveItemsToFolder} + onDeleteFolderWithContents={operations?.deleteFolderWithContents} onPDFUpload={handlePDFUpload} /> )} From 8338a3da1b653bc4c246984df403beec2432f14c Mon Sep 17 00:00:00 2001 From: Urjit Chakraborty <135136842+urjitc@users.noreply.github.com> Date: Sat, 17 Jan 2026 15:52:49 -0500 Subject: [PATCH 4/7] fix: address code review feedback for folder deletion - Add recursive deletion for nested folders and their contents - Remove misleading async/await since deleteItem fires mutations synchronously - Disable 'Delete items' option when callback is unavailable - Add onDeleteFolderWithContents to useMemo dependency array --- .../workspace-canvas/FolderCard.tsx | 5 ++- .../workspace-canvas/WorkspaceGrid.tsx | 1 + .../workspace/use-workspace-operations.ts | 42 ++++++++++++++----- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/components/workspace-canvas/FolderCard.tsx b/src/components/workspace-canvas/FolderCard.tsx index e512c78d..5683d46e 100644 --- a/src/components/workspace-canvas/FolderCard.tsx +++ b/src/components/workspace-canvas/FolderCard.tsx @@ -474,14 +474,15 @@ function FolderCardComponent({ -