trello_fake/components/dashboard/project-dashboard.tsx

139 lines
4.5 KiB
TypeScript

"use client";
import { useState, useEffect } from 'react';
import DashboardHeader from './dashboard-header';
import StatsOverview from './stats-overview';
import ProjectGrid from './project-grid';
import ProjectGridSkeleton from './project-grid-skeleton';
import { ProjectFormSheet } from '@/components/project-form/project-form-sheet';
import { getProjects } from '@/lib/projectsService';
import { Project } from '@/types/project';
import { Skeleton } from '@/components/ui/skeleton';
export default function ProjectDashboard() {
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');
const [searchTerm, setSearchTerm] = useState('');
const [projects, setProjects] = useState<Project[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [isCreateSheetOpen, setIsCreateSheetOpen] = useState(false);
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();
}, []);
// Handler para cuando se crea un proyecto
const handleProjectCreated = (newProject: Project) => {
setProjects(prevProjects => [newProject, ...prevProjects]);
};
// Handler para cuando se actualiza un proyecto
const handleProjectUpdated = (updatedProject: Project) => {
setProjects(prevProjects =>
prevProjects.map(p => p.id === updatedProject.id ? updatedProject : p)
);
};
// Handler para cuando se elimina un proyecto
const handleProjectDeleted = (projectId: number) => {
setProjects(prevProjects => prevProjects.filter(p => p.id !== projectId));
};
const filteredProjects = projects.filter(project =>
project.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
project.client.toLowerCase().includes(searchTerm.toLowerCase()) ||
project.ref.toLowerCase().includes(searchTerm.toLowerCase())
);
if (loading) {
return (
<div className="min-h-screen bg-background">
<DashboardHeader
searchTerm=""
onSearchChange={() => {}}
viewMode={viewMode}
onViewModeChange={setViewMode}
onCreateProject={() => {}}
/>
<main className="px-4 sm:px-6 lg:px-8 py-8">
{/* Stats skeleton */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
{Array.from({ length: 4 }).map((_, i) => (
<div key={i} className="bg-card border rounded-lg p-6">
<div className="flex items-center justify-between mb-4">
<Skeleton className="h-4 w-24" />
<Skeleton className="h-4 w-4 rounded" />
</div>
<Skeleton className="h-8 w-16 mb-2" />
<Skeleton className="h-3 w-32" />
</div>
))}
</div>
{/* Projects skeleton */}
<ProjectGridSkeleton viewMode={viewMode} count={6} />
</main>
</div>
);
}
if (error) {
return (
<div className="min-h-screen bg-background flex items-center justify-center">
<div className="text-center">
<p className="text-red-600 dark:text-red-400">{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>
);
}
return (
<div className="min-h-screen bg-background">
<DashboardHeader
searchTerm={searchTerm}
onSearchChange={setSearchTerm}
viewMode={viewMode}
onViewModeChange={setViewMode}
onCreateProject={() => setIsCreateSheetOpen(true)}
/>
<main className="px-4 sm:px-6 lg:px-8 py-8">
<StatsOverview projects={projects} />
<ProjectGrid
projects={filteredProjects}
viewMode={viewMode}
onProjectUpdated={handleProjectUpdated}
onProjectDeleted={handleProjectDeleted}
/>
</main>
{/* Sheet de creación de proyecto */}
<ProjectFormSheet
open={isCreateSheetOpen}
onOpenChange={setIsCreateSheetOpen}
mode="create"
onSuccess={handleProjectCreated}
/>
</div>
);
}