'use client' import { useState, useCallback, useMemo, useEffect } from 'react' import ItemCard from './ItemCard' import SearchBar from './SearchBar' import FilterPanel from './FilterPanel' import SearchResults from './SearchResults' import EmptyState from './EmptyState' import { searchItems, getItemsByFilter } from '@/lib/actions' import { useSearch, useFilters, useScrollPosition } from '@/hooks' interface Item { id: string title: string description: string | null completed: boolean priority: string dueDate: Date | null tags: any notes: string | null createdAt: Date updatedAt: Date listId: string } interface ItemWithList extends Item { list: { id: string title: string color: string } } interface ListDetailViewProps { listId: string initialItems: Item[] } export default function ListDetailView({ listId, initialItems }: ListDetailViewProps) { const [searchResults, setSearchResults] = useState([]) const [isSearching, setIsSearching] = useState(false) const [filteredItems, setFilteredItems] = useState(initialItems) // Use scroll position preservation hook useScrollPosition({ key: `list-${listId}` }) // Extract all unique tags from items const availableTags = useMemo(() => { const tagSet = new Set() initialItems.forEach(item => { const tags = Array.isArray(item.tags) ? item.tags : [] tags.forEach(tag => { if (typeof tag === 'string') { tagSet.add(tag) } }) }) return Array.from(tagSet).sort() }, [initialItems]) // Use search hook const handleSearchCallback = useCallback(async (query: string) => { if (!query.trim()) { setSearchResults([]) setIsSearching(false) return } setIsSearching(true) try { const results = await searchItems(query, listId) setSearchResults(results as ItemWithList[]) } catch (error) { console.error('Search error:', error) setSearchResults([]) } finally { setIsSearching(false) } }, [listId]) const { debouncedQuery } = useSearch({ onSearch: handleSearchCallback }) // Use filters hook const handleFiltersCallback = useCallback(async (newFilters: any) => { try { const results = await getItemsByFilter(listId, { priority: newFilters.priority, completed: newFilters.completed, tags: newFilters.tags, dueDateRange: newFilters.dueDateRange, sortBy: newFilters.sortBy, sortOrder: newFilters.sortOrder }) // Extract items from pagination result const items = 'items' in results ? results.items : results setFilteredItems(items as Item[]) } catch (error) { console.error('Filter error:', error) setFilteredItems(initialItems) } }, [listId, initialItems]) const { filters, setFilters } = useFilters({ onFiltersChange: handleFiltersCallback }) // Apply initial filters on mount useEffect(() => { handleFiltersCallback(filters) }, []) // Only run on mount // Determine which items to display const displayItems = debouncedQuery.trim() ? searchResults : filteredItems const completedItems = displayItems.filter(item => item.completed) const incompleteItems = displayItems.filter(item => !item.completed) return (
{/* Search Bar */} {/* Filter Panel */} {/* Results */} {debouncedQuery.trim() ? ( ) : (
{/* Incomplete Items */} {incompleteItems.length > 0 && (

To Do ({incompleteItems.length})

{incompleteItems.map((item) => ( ))}
)} {/* Completed Items */} {completedItems.length > 0 && (

Completed ({completedItems.length})

{completedItems.map((item) => ( ))}
)} {/* Empty State */} {displayItems.length === 0 && ( 0 ? 'filter' : 'inbox'} title="No tasks found" description={ filters.priority || filters.completed !== null || filters.tags.length > 0 ? 'Try adjusting your filters to see more tasks' : 'Add your first task using the button above' } /> )}
)}
) }