"use client"; import { useEffect, useState } from "react"; import Link from "next/link"; import { Card, CardHeader, CardContent } from "@/components/ui/Card"; import Button from "@/components/ui/Button"; import Badge from "@/components/ui/Badge"; import { Input } from "@/components/ui/Input"; import PageContainer from "@/components/ui/PageContainer"; import PageHeader from "@/components/ui/PageHeader"; import SearchBar from "@/components/ui/SearchBar"; import { LoadingState } from "@/components/ui/States"; import { formatDate } from "@/lib/utils"; import { useTranslation } from "@/lib/i18n"; import { useSession } from "next-auth/react"; export default function ProjectListPage() { const { t } = useTranslation(); const { data: session } = useSession(); const [projects, setProjects] = useState([]); const [searchTerm, setSearchTerm] = useState(""); const [filteredProjects, setFilteredProjects] = useState([]); const [filters, setFilters] = useState({ status: 'all', type: 'all', customer: 'all', mine: false }); const [customers, setCustomers] = useState([]); const [filtersExpanded, setFiltersExpanded] = useState(true); // Start expanded on mobile so users know filters exist useEffect(() => { fetch("/api/projects") .then((res) => res.json()) .then((data) => { setProjects(data); setFilteredProjects(data); // Extract unique customers for filter const uniqueCustomers = [...new Set(data.map(p => p.customer).filter(Boolean))]; setCustomers(uniqueCustomers); }); }, []); // Filter projects based on search term and filters useEffect(() => { let filtered = projects; // Apply status filter if (filters.status !== 'all') { if (filters.status === 'not_finished') { filtered = filtered.filter(project => project.project_status !== 'fulfilled'); } else { filtered = filtered.filter(project => project.project_status === filters.status); } } // Apply type filter if (filters.type !== 'all') { filtered = filtered.filter(project => project.project_type === filters.type); } // Apply customer filter if (filters.customer !== 'all') { filtered = filtered.filter(project => project.customer === filters.customer); } // Apply mine filter if (filters.mine && session?.user?.id) { filtered = filtered.filter(project => project.assigned_to === session.user.id); } // Apply search term if (searchTerm.trim()) { const searchLower = searchTerm.toLowerCase(); filtered = filtered.filter((project) => { return ( project.project_name?.toLowerCase().includes(searchLower) || project.wp?.toLowerCase().includes(searchLower) || project.plot?.toLowerCase().includes(searchLower) || project.investment_number?.toLowerCase().includes(searchLower) || project.address?.toLowerCase().includes(searchLower) || project.customer?.toLowerCase().includes(searchLower) || project.investor?.toLowerCase().includes(searchLower) ); }); } setFilteredProjects(filtered); }, [searchTerm, projects, filters, session]); async function handleDelete(id) { const confirmed = confirm(t('projects.deleteConfirm')); if (!confirmed) return; const res = await fetch(`/api/projects/${id}`, { method: "DELETE", }); if (res.ok) { setProjects((prev) => prev.filter((p) => p.project_id !== id)); } } const handleSearchChange = (e) => { setSearchTerm(e.target.value); }; const handleFilterChange = (filterType, value) => { setFilters(prev => ({ ...prev, [filterType]: value })); }; const clearAllFilters = () => { setFilters({ status: 'all', type: 'all', customer: 'all', mine: false }); setSearchTerm(''); }; const handleExportExcel = async () => { try { const response = await fetch('/api/projects/export'); if (response.ok) { const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `projects_export_${new Date().toISOString().split('T')[0]}.xlsx`; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); } else { alert('Failed to export projects. Please try again.'); } } catch (error) { console.error('Export error:', error); alert('An error occurred during export. Please try again.'); } }; const toggleFilters = () => { setFiltersExpanded(!filtersExpanded); }; const hasActiveFilters = filters.status !== 'all' || filters.type !== 'all' || filters.customer !== 'all' || filters.mine || searchTerm.trim() !== ''; const getActiveFilterCount = () => { let count = 0; if (filters.status !== 'all') count++; if (filters.type !== 'all') count++; if (filters.customer !== 'all') count++; if (filters.mine) count++; if (searchTerm.trim()) count++; return count; }; const getStatusLabel = (status) => { switch(status) { case "registered": return t('projectStatus.registered'); case "in_progress_design": return t('projectStatus.in_progress_design'); case "in_progress_construction": return t('projectStatus.in_progress_construction'); case "fulfilled": return t('projectStatus.fulfilled'); case "cancelled": return t('projectStatus.cancelled'); default: return "-"; } }; const getTypeLabel = (type) => { switch(type) { case "design": return t('projectType.design'); case "construction": return t('projectType.construction'); case "design+construction": return t('projectType.design+construction'); default: return "-"; } }; return (
{session?.user && ( )}
{/* Filters */} {/* Mobile collapsible header */}

{t('common.filters') || 'Filtry'} {hasActiveFilters && ( {getActiveFilterCount()} )}

{hasActiveFilters && ( )}
{t('projects.showingResults', { shown: filteredProjects.length, total: projects.length }) || `Wyświetlono ${filteredProjects.length} z ${projects.length} projektów`}
{/* Mobile collapsible content */}
{/* Desktop always visible content */}
{(filters.status !== 'all' || filters.type !== 'all' || filters.customer !== 'all' || searchTerm) && ( )}
{t('projects.showingResults', { shown: filteredProjects.length, total: projects.length }) || `Wyświetlono ${filteredProjects.length} z ${projects.length} projektów`}
{filteredProjects.length === 0 && searchTerm ? (

{t('common.noResults')}

{t('projects.noMatchingResults') || 'Brak projektów pasujących do kryteriów wyszukiwania. Spróbuj zmienić wyszukiwane frazy.'}

) : projects.length === 0 ? (

{t('projects.noProjects')}

{t('projects.noProjectsMessage')}

) : (
{/* Mobile scroll container */}
{filteredProjects.map((project, index) => ( ))}
Nr. {t('projects.projectName')} {t('projects.address')} WP {t('projects.city')} {t('projects.plot')} {t('projects.finishDate')} {t('common.type') || 'Typ'} {t('common.status') || 'Status'} {t('projects.assigned') || 'Przypisany'}
{project.project_number} {project.project_name.length > 20 ? `${project.project_name.substring(0, 20)}...` : project.project_name} {project.project_name} {project.address || "N/A"} {project.wp || "N/A"} {project.city || "N/A"} {project.plot || "N/A"} {project.finish_date ? formatDate(project.finish_date) : "N/A"} {project.project_type === "design" ? "P" : project.project_type === "construction" ? "B" : project.project_type === "design+construction" ? "P+B" : "-"}
{project.project_status === 'registered' ? ( N ) : project.project_status === 'in_progress_design' ? ( ) : project.project_status === 'in_progress_construction' ? ( ) : project.project_status === 'fulfilled' ? ( ) : project.project_status === 'cancelled' ? ( × ) : ( - )}
{project.assigned_to_initial ? (
{project.assigned_to_initial}
) : ( - )}
)}
); }