refactor: shared components, ConfirmDialog migration, pinned flow fixes
- Create shared Spinner component with sm/md/lg sizes - Migrate 13 page-level spinners to shared Spinner - Promote EmptyState to shared component, adopt in MyShares and SessionHistory - Replace window.confirm with ConfirmDialog in 3 files - Fix PinnedFlow.tree_type to include maintenance, update emoji display - Verify sidebar unpin handler already correct (no-op) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { Folder, ChevronDown, ChevronRight, Plus, MoreVertical, Pencil, Trash2, FolderPlus, X } from 'lucide-react'
|
||||
import { foldersApi } from '@/api/folders'
|
||||
import { ConfirmDialog } from '@/components/common/ConfirmDialog'
|
||||
import type { FolderListItem, FolderTreeItem } from '@/types'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
@@ -245,6 +246,7 @@ export function FolderSidebar({
|
||||
const [menuOpenId, setMenuOpenId] = useState<string | null>(null)
|
||||
const [expandedIds, setExpandedIds] = useState<Set<string>>(new Set())
|
||||
const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null)
|
||||
const [pendingDelete, setPendingDelete] = useState<{ id: string; message: string } | null>(null)
|
||||
|
||||
const loadFolders = useCallback(async () => {
|
||||
setIsLoading(true)
|
||||
@@ -277,15 +279,19 @@ export function FolderSidebar({
|
||||
})
|
||||
}
|
||||
|
||||
const handleDeleteFolder = async (folderId: string, folderHasChildren: boolean) => {
|
||||
const handleDeleteFolder = (folderId: string, folderHasChildren: boolean) => {
|
||||
const descendantCount = getDescendantIds(folders, folderId).length
|
||||
const message = folderHasChildren
|
||||
? `Are you sure you want to delete this folder and its ${descendantCount} subfolder(s)? The trees in them will not be deleted.`
|
||||
: 'Are you sure you want to delete this folder? The trees in it will not be deleted.'
|
||||
|
||||
if (!confirm(message)) {
|
||||
return
|
||||
}
|
||||
setPendingDelete({ id: folderId, message })
|
||||
}
|
||||
|
||||
const confirmDeleteFolder = async () => {
|
||||
if (!pendingDelete) return
|
||||
const folderId = pendingDelete.id
|
||||
setPendingDelete(null)
|
||||
try {
|
||||
await foldersApi.delete(folderId)
|
||||
// Remove folder and all descendants from local state
|
||||
@@ -494,6 +500,15 @@ export function FolderSidebar({
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<ConfirmDialog
|
||||
isOpen={!!pendingDelete}
|
||||
onClose={() => setPendingDelete(null)}
|
||||
onConfirm={confirmDeleteFolder}
|
||||
title="Delete Folder"
|
||||
message={pendingDelete?.message || ''}
|
||||
confirmLabel="Delete"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user