import { useEffect, useState, useCallback } from 'react' import { useNavigate, Link } from 'react-router-dom' import { Plus, Pencil, Globe, Lock, X } from 'lucide-react' import { treesApi, categoriesApi, foldersApi } from '@/api' import type { TreeListItem, CategoryListItem, FolderListItem } from '@/types' import { TagBadges } from '@/components/common/TagBadges' import { FolderSidebar } from '@/components/library/FolderSidebar' import { FolderEditModal } from '@/components/library/FolderEditModal' import { AddToFolderMenu } from '@/components/library/AddToFolderMenu' import { cn } from '@/lib/utils' export function TreeLibraryPage() { const navigate = useNavigate() const [trees, setTrees] = useState([]) const [categories, setCategories] = useState([]) const [folders, setFolders] = useState([]) const [selectedCategoryId, setSelectedCategoryId] = useState('') const [selectedTags, setSelectedTags] = useState([]) const [selectedFolderId, setSelectedFolderId] = useState(null) const [searchQuery, setSearchQuery] = useState('') const [isLoading, setIsLoading] = useState(true) const [error, setError] = useState(null) // Folder modal state const [folderModalOpen, setFolderModalOpen] = useState(false) const [editingFolder, setEditingFolder] = useState(null) const [newFolderParentId, setNewFolderParentId] = useState(null) const loadFolders = useCallback(async () => { try { const foldersData = await foldersApi.list() setFolders(foldersData) } catch (err) { console.error('Failed to load folders:', err) } }, []) useEffect(() => { loadData() }, [selectedCategoryId, selectedTags, selectedFolderId]) // Load folders on mount and listen for changes useEffect(() => { loadFolders() const handleFolderChange = () => loadFolders() window.addEventListener('folder-changed', handleFolderChange) return () => window.removeEventListener('folder-changed', handleFolderChange) }, [loadFolders]) const loadData = async () => { setIsLoading(true) setError(null) try { const [treesData, categoriesData] = await Promise.all([ treesApi.list({ category_id: selectedCategoryId || undefined, tags: selectedTags.length > 0 ? selectedTags.join(',') : undefined, folder_id: selectedFolderId || undefined, }), categoriesApi.list(), ]) setTrees(treesData) setCategories(categoriesData) } catch (err) { setError('Failed to load trees') console.error(err) } finally { setIsLoading(false) } } const handleSearch = async () => { if (!searchQuery.trim()) { loadData() return } setIsLoading(true) setError(null) try { const results = await treesApi.search(searchQuery) setTrees(results) } catch (err) { setError('Search failed') console.error(err) } finally { setIsLoading(false) } } const handleTagClick = (tag: string) => { if (!selectedTags.includes(tag)) { setSelectedTags([...selectedTags, tag]) } } const removeTagFilter = (tag: string) => { setSelectedTags(selectedTags.filter((t) => t !== tag)) } const clearAllFilters = () => { setSelectedCategoryId('') setSelectedTags([]) setSelectedFolderId(null) setSearchQuery('') } const handleStartSession = (treeId: string) => { navigate(`/trees/${treeId}/navigate`) } const handleCreateFolder = (parentId?: string | null) => { setEditingFolder(null) setNewFolderParentId(parentId || null) setFolderModalOpen(true) } const handleEditFolder = (folder: FolderListItem) => { setEditingFolder(folder) setNewFolderParentId(null) setFolderModalOpen(true) } const hasActiveFilters = selectedCategoryId || selectedTags.length > 0 || searchQuery || selectedFolderId return (
{/* Folder Sidebar */} {/* Main Content */}

Decision Trees

Select a troubleshooting tree to start a new session

Create Tree
{/* Search and Filter */}
setSearchQuery(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSearch()} className={cn( 'flex-1 rounded-md border border-input bg-background px-3 py-2', 'text-foreground placeholder:text-muted-foreground', 'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary' )} />
{/* Active Filters */} {hasActiveFilters && (
Filters: {selectedFolderId && ( Folder )} {selectedCategoryId && ( {categories.find((c) => c.id === selectedCategoryId)?.name} )} {selectedTags.map((tag) => ( {tag} ))}
)} {/* Error State */} {error && (
{error}
)} {/* Loading State */} {isLoading ? (
) : trees.length === 0 ? (
No trees found.{' '} {(searchQuery || hasActiveFilters) && 'Try adjusting your filters.'}
) : (
{trees.map((tree) => (

{tree.name}

{tree.is_public ? ( ) : ( )} {tree.category_info && ( {tree.category_info.name} )}

{tree.description || 'No description available'}

{/* Tags */} {tree.tags && tree.tags.length > 0 && (
)}
v{tree.version} ยท {tree.usage_count} uses
))}
)}
{/* Folder Edit Modal */} { setFolderModalOpen(false) setNewFolderParentId(null) }} onSave={loadData} />
) } export default TreeLibraryPage