trello_fake/components/projects/projects-table.tsx

128 lines
3.6 KiB
TypeScript

"use client";
import { useState, useEffect, useMemo } from "react";
import { FolderKanban, RefreshCw } from "lucide-react";
import { Project } from "@/types/project";
import { getProjects } from "@/lib/projectsService";
import { DataTable } from "./data-table";
import { DataTableToolbar } from "./data-table-toolbar";
import { DataTableSkeleton } from "./data-table-skeleton";
import { EmptyState } from "./empty-state";
import { projectColumns } from "./columns";
import { Button } from "@/components/ui/button";
export function ProjectsTable() {
const [projects, setProjects] = useState<Project[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
// Filtros
const [searchValue, setSearchValue] = useState("");
const [statusFilter, setStatusFilter] = useState("all");
// Cargar proyectos
const fetchProjects = async () => {
setIsLoading(true);
setError(null);
try {
const data = await getProjects();
setProjects(data);
} catch (err) {
console.error("Error fetching projects:", err);
setError("Error al cargar los proyectos. Por favor, intenta de nuevo.");
} finally {
setIsLoading(false);
}
};
useEffect(() => {
fetchProjects();
}, []);
// Filtrar proyectos
const filteredProjects = useMemo(() => {
let result = [...projects];
// Filtro de búsqueda (nombre o referencia)
if (searchValue) {
const search = searchValue.toLowerCase();
result = result.filter(
(project) =>
project.name.toLowerCase().includes(search) ||
project.ref.toLowerCase().includes(search) ||
project.client.toLowerCase().includes(search)
);
}
// Filtro de estado
if (statusFilter !== "all") {
result = result.filter((project) => project.status === statusFilter);
}
return result;
}, [projects, searchValue, statusFilter]);
// Limpiar filtros
const handleClearFilters = () => {
setSearchValue("");
setStatusFilter("all");
};
// Contar seleccionados (placeholder - el DataTable lo maneja internamente)
const selectedCount = 0;
// Estado de error
if (error) {
return (
<div className="flex flex-col items-center justify-center p-8 text-center">
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-destructive/10">
<FolderKanban className="h-6 w-6 text-destructive" />
</div>
<h3 className="mt-4 text-lg font-semibold">Error al cargar</h3>
<p className="mt-2 text-sm text-muted-foreground max-w-sm">{error}</p>
<Button onClick={fetchProjects} variant="outline" className="mt-4">
<RefreshCw className="mr-2 h-4 w-4" />
Reintentar
</Button>
</div>
);
}
// Estado de carga
if (isLoading) {
return <DataTableSkeleton />;
}
// Estado vacío
if (projects.length === 0) {
return (
<EmptyState
title="No hay proyectos"
description="Aún no tienes proyectos creados. Comienza creando tu primer proyecto."
actionLabel="Crear proyecto"
onAction={() => console.log("Create project")}
/>
);
}
return (
<div className="space-y-4">
<DataTableToolbar
searchValue={searchValue}
onSearchChange={setSearchValue}
statusFilter={statusFilter}
onStatusFilterChange={setStatusFilter}
selectedCount={selectedCount}
onClearFilters={handleClearFilters}
/>
<DataTable
columns={projectColumns}
data={filteredProjects}
searchKey="name"
searchValue={searchValue}
/>
</div>
);
}