/** * Projects List Page * * Displays all projects with filtering, sorting, and search. * Supports grid and list view modes. * * @see Issue #54 */ 'use client'; import { useState, useCallback, useMemo } from 'react'; import { useRouter } from '@/lib/i18n/routing'; import { toast } from 'sonner'; import { Plus } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Link } from '@/lib/i18n/routing'; import { ProjectFilters, ProjectsGrid } from '@/components/projects'; import type { ViewMode, SortBy, SortOrder, Complexity } from '@/components/projects'; import type { ProjectStatus } from '@/components/projects/types'; import { useProjects, type ProjectListItem } from '@/lib/api/hooks/useProjects'; import { useDebounce } from '@/lib/hooks/useDebounce'; export default function ProjectsPage() { const router = useRouter(); // Filter state const [searchQuery, setSearchQuery] = useState(''); const [statusFilter, setStatusFilter] = useState('all'); const [complexityFilter, setComplexityFilter] = useState('all'); const [sortBy, setSortBy] = useState('recent'); const [sortOrder, setSortOrder] = useState('desc'); const [viewMode, setViewMode] = useState('grid'); // Debounce search for API calls const debouncedSearch = useDebounce(searchQuery, 300); // Fetch projects const { data, isLoading, error } = useProjects({ search: debouncedSearch || undefined, status: statusFilter, complexity: complexityFilter !== 'all' ? complexityFilter : undefined, sortBy, sortOrder, page: 1, limit: 50, }); // Check if any filters are active (for empty state message) const hasFilters = useMemo(() => { return searchQuery !== '' || statusFilter !== 'all' || complexityFilter !== 'all'; }, [searchQuery, statusFilter, complexityFilter]); // Handle project card click const handleProjectClick = useCallback( (project: ProjectListItem) => { router.push(`/projects/${project.id}`); }, [router] ); // Handle project action const handleProjectAction = useCallback( (project: ProjectListItem, action: 'archive' | 'pause' | 'resume' | 'delete') => { // TODO: Implement actual API calls switch (action) { case 'archive': toast.success(`Archived: ${project.name}`); break; case 'pause': toast.info(`Paused: ${project.name}`); break; case 'resume': toast.success(`Resumed: ${project.name}`); break; case 'delete': toast.error(`Deleted: ${project.name}`); break; } }, [] ); // Show error toast if fetch fails if (error) { toast.error('Failed to load projects', { description: 'Please try again later', }); } return (
{/* Header */}

Projects

Manage and monitor your projects

{/* Filters */} {/* Projects Grid */} {/* Pagination - TODO: Add when more than 50 projects */} {data && data.pagination.totalPages > 1 && (
Showing {data.data.length} of {data.pagination.total} projects {/* TODO: Add pagination controls */}
)}
); }