"use client"; import { useEffect, useState, useMemo } from 'react'; import Link from 'next/link'; import { useToast } from '@/contexts/ToastContext'; import { useConfirm } from '@/contexts/ConfirmContext'; interface Project { id: string; title: string; category: string; client: string | null; status: string; completionDate: string | null; description: string | null; coverImage: string | null; galleryImages: string[]; featured: boolean; createdAt: string; updatedAt: string; } const STATUS_STYLES: Record = { 'Concluído': 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400', 'Em andamento': 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400', 'Rascunho': 'bg-gray-100 text-gray-600 dark:bg-white/10 dark:text-gray-300', }; export default function ProjectsList() { const [projects, setProjects] = useState([]); const [loading, setLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(''); const [filterCategory, setFilterCategory] = useState(''); const [filterStatus, setFilterStatus] = useState(''); const [filterDateFrom, setFilterDateFrom] = useState(''); const [filterDateTo, setFilterDateTo] = useState(''); const { success, error } = useToast(); const { confirm } = useConfirm(); useEffect(() => { fetchProjects(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const fetchProjects = async () => { try { setLoading(true); const response = await fetch('/api/projects'); if (!response.ok) { throw new Error('Falha ao carregar projetos'); } const data: Project[] = await response.json(); setProjects(data); } catch (err) { console.error('Erro ao carregar projetos:', err); error('Não foi possível carregar os projetos.'); } finally { setLoading(false); } }; // Extrair categorias e status únicos const categories = useMemo(() => { const cats = new Set(); projects.forEach((p) => { if (p.category) cats.add(p.category); }); return Array.from(cats).sort(); }, [projects]); const statuses = useMemo(() => { const stats = new Set(); projects.forEach((p) => { if (p.status) stats.add(p.status); }); return Array.from(stats); }, [projects]); // Filtrar projetos const filteredProjects = useMemo(() => { return projects.filter((project) => { // Filtro de pesquisa const matchesSearch = !searchTerm || project.title.toLowerCase().includes(searchTerm.toLowerCase()) || project.client?.toLowerCase().includes(searchTerm.toLowerCase()) || project.category?.toLowerCase().includes(searchTerm.toLowerCase()) || project.description?.toLowerCase().includes(searchTerm.toLowerCase()); // Filtro de categoria const matchesCategory = !filterCategory || project.category === filterCategory; // Filtro de status const matchesStatus = !filterStatus || project.status === filterStatus; // Filtro de data (criação) let matchesDateFrom = true; let matchesDateTo = true; if (filterDateFrom) { const projectDate = new Date(project.createdAt); const fromDate = new Date(filterDateFrom); matchesDateFrom = projectDate >= fromDate; } if (filterDateTo) { const projectDate = new Date(project.createdAt); const toDate = new Date(filterDateTo); toDate.setHours(23, 59, 59, 999); matchesDateTo = projectDate <= toDate; } return matchesSearch && matchesCategory && matchesStatus && matchesDateFrom && matchesDateTo; }); }, [projects, searchTerm, filterCategory, filterStatus, filterDateFrom, filterDateTo]); const clearFilters = () => { setSearchTerm(''); setFilterCategory(''); setFilterStatus(''); setFilterDateFrom(''); setFilterDateTo(''); }; const hasActiveFilters = searchTerm || filterCategory || filterStatus || filterDateFrom || filterDateTo; const handleDelete = async (id: string) => { const confirmed = await confirm({ title: 'Excluir projeto', message: 'Tem certeza que deseja remover este projeto? Esta ação não pode ser desfeita.', confirmText: 'Excluir', cancelText: 'Cancelar', type: 'danger', }); if (!confirmed) return; try { const response = await fetch(`/api/projects/${id}`, { method: 'DELETE' }); const result = await response.json(); if (!response.ok) { throw new Error(result?.error || 'Falha ao excluir projeto'); } success('Projeto excluído com sucesso!'); fetchProjects(); } catch (err) { console.error('Erro ao excluir projeto:', err); error('Não foi possível excluir o projeto.'); } }; const renderStatus = (status: string) => { const style = STATUS_STYLES[status] || 'bg-gray-100 text-gray-600 dark:bg-white/10 dark:text-gray-300'; return ( {status} ); }; const formatDate = (value: string | null) => { if (!value) return '—'; try { return new Intl.DateTimeFormat('pt-BR').format(new Date(value)); } catch (err) { console.error('Erro ao formatar data:', err); return '—'; } }; return (

Projetos

Gerencie os projetos exibidos no portfólio.

Novo Projeto
{/* Filters Section */}
{/* Search */}
setSearchTerm(e.target.value)} className="w-full px-4 py-2.5 pl-10 rounded-lg border border-gray-200 dark:border-white/10 bg-gray-50 dark:bg-white/5 text-secondary dark:text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all" /> {searchTerm && ( )}
{/* Category Filter */}
{/* Status Filter */}
{/* Date From Filter */}
setFilterDateFrom(e.target.value)} className="w-full px-4 py-2.5 rounded-lg border border-gray-200 dark:border-white/10 bg-gray-50 dark:bg-white/5 text-secondary dark:text-white focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all cursor-pointer" title="Data inicial" />
{/* Date To Filter */}
setFilterDateTo(e.target.value)} className="w-full px-4 py-2.5 rounded-lg border border-gray-200 dark:border-white/10 bg-gray-50 dark:bg-white/5 text-secondary dark:text-white focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all cursor-pointer" title="Data final" />
{/* Clear Filters */} {hasActiveFilters && ( )}
{/* Results count */} {!loading && (
{hasActiveFilters ? ( Exibindo {filteredProjects.length} de {projects.length} projetos ) : ( {projects.length} projeto{projects.length !== 1 ? 's' : ''} cadastrado{projects.length !== 1 ? 's' : ''} )}
)}
{loading ? (
) : filteredProjects.length === 0 ? (
{hasActiveFilters ? ( <> Nenhum projeto encontrado com os filtros aplicados. ) : ( 'Nenhum projeto cadastrado ainda.' )}
) : (
{filteredProjects.map((project) => ( ))}
Projeto Categoria Cliente Inserção Conclusão Status Ações
{project.coverImage ? ( {project.title} ) : (
)}

{project.title} {project.featured && ( Destaque )}

{project.category} {project.client || '—'}
{formatDate(project.createdAt)} {new Date(project.createdAt).toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })}
{formatDate(project.completionDate)} {renderStatus(project.status)}
)}
); }