2025-12-11 10:50:09 +00:00
|
|
|
"use client";
|
|
|
|
|
|
2026-01-09 17:39:19 +00:00
|
|
|
import { useState, useEffect } from 'react';
|
2025-12-11 10:50:09 +00:00
|
|
|
import DashboardHeader from './dashboard-header';
|
|
|
|
|
import StatsOverview from './stats-overview';
|
|
|
|
|
import ProjectGrid from './project-grid';
|
2026-01-09 17:39:19 +00:00
|
|
|
import { getProjects } from '@/lib/projectsService'; // Importar desde el service
|
2025-12-11 10:50:09 +00:00
|
|
|
import { Project } from '@/types/project';
|
|
|
|
|
|
|
|
|
|
export default function ProjectDashboard() {
|
|
|
|
|
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');
|
|
|
|
|
const [searchTerm, setSearchTerm] = useState('');
|
2026-01-09 17:39:19 +00:00
|
|
|
const [projects, setProjects] = useState<Project[]>([]);
|
|
|
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
|
const [error, setError] = useState<string | null>(null);
|
2025-12-11 10:50:09 +00:00
|
|
|
|
2026-01-09 17:39:19 +00:00
|
|
|
useEffect(() => {
|
|
|
|
|
async function loadProjects() {
|
|
|
|
|
try {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
const data = await getProjects();
|
|
|
|
|
setProjects(data);
|
|
|
|
|
setError(null);
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error('Error loading projects:', err);
|
|
|
|
|
setError('Error al cargar los proyectos');
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
loadProjects();
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const filteredProjects = projects.filter(project =>
|
2025-12-11 10:50:09 +00:00
|
|
|
project.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
2026-01-09 17:39:19 +00:00
|
|
|
project.client.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
|
|
|
|
project.ref.toLowerCase().includes(searchTerm.toLowerCase())
|
2025-12-11 10:50:09 +00:00
|
|
|
);
|
|
|
|
|
|
2026-01-09 17:39:19 +00:00
|
|
|
if (loading) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 flex items-center justify-center">
|
|
|
|
|
<div className="text-center">
|
|
|
|
|
<div className="inline-block h-8 w-8 animate-spin rounded-full border-4 border-solid border-blue-600 border-r-transparent"></div>
|
|
|
|
|
<p className="mt-4 text-gray-600">Cargando proyectos...</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 flex items-center justify-center">
|
|
|
|
|
<div className="text-center">
|
|
|
|
|
<p className="text-red-600">{error}</p>
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => window.location.reload()}
|
|
|
|
|
className="mt-4 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
|
|
|
|
|
>
|
|
|
|
|
Reintentar
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-11 10:50:09 +00:00
|
|
|
return (
|
|
|
|
|
<div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100">
|
|
|
|
|
<DashboardHeader
|
|
|
|
|
searchTerm={searchTerm}
|
|
|
|
|
onSearchChange={setSearchTerm}
|
|
|
|
|
viewMode={viewMode}
|
|
|
|
|
onViewModeChange={setViewMode}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
2026-01-09 17:39:19 +00:00
|
|
|
<StatsOverview projects={projects} />
|
2025-12-11 10:50:09 +00:00
|
|
|
<ProjectGrid projects={filteredProjects} viewMode={viewMode} />
|
|
|
|
|
</main>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
2026-01-09 17:39:19 +00:00
|
|
|
}
|