Files
Dashboard/components/collections/collection-table.tsx
2025-10-05 16:10:35 +02:00

123 lines
3.4 KiB
TypeScript

"use client";
import { useCollection } from "@/hooks/useCollection";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Button } from "@/components/ui/button";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { useState } from "react";
interface CollectionTableProps<T = Record<string, unknown>> {
collectionName: string;
title: string;
columns: Array<{
key: string;
label: string;
render?: (value: unknown, item: T) => React.ReactNode;
}>;
}
export function CollectionTable<T extends Record<string, unknown>>({
collectionName,
title,
columns
}: CollectionTableProps<T>) {
const [page, setPage] = useState(1);
const { data, loading, error, total, totalPages } = useCollection<T>(
collectionName,
{ page, limit: 20 }
);
if (loading) {
return (
<Card>
<CardHeader>
<CardTitle>{title}</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
{Array.from({ length: 5 }).map((_, i) => (
<div key={i} className="h-12 bg-muted animate-pulse rounded" />
))}
</div>
</CardContent>
</Card>
);
}
if (error) {
return (
<Card>
<CardHeader>
<CardTitle>{title}</CardTitle>
</CardHeader>
<CardContent>
<div className="text-center py-8 text-muted-foreground">
Erreur: {error}
</div>
</CardContent>
</Card>
);
}
return (
<Card>
<CardHeader>
<CardTitle>{title} ({total} éléments)</CardTitle>
</CardHeader>
<CardContent>
<Table>
<TableHeader>
<TableRow>
{columns.map((column) => (
<TableHead key={column.key}>{column.label}</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
{data.map((item, index) => (
<TableRow key={(item as { _id?: string })._id || index}>
{columns.map((column) => (
<TableCell key={column.key}>
{column.render
? column.render(item[column.key], item)
: String(item[column.key] || '-')
}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
{totalPages > 1 && (
<div className="flex items-center justify-between mt-4">
<p className="text-sm text-muted-foreground">
Page {page} sur {totalPages}
</p>
<div className="flex gap-2">
<Button
variant="outline"
size="sm"
onClick={() => setPage(p => Math.max(1, p - 1))}
disabled={page === 1}
>
<ChevronLeft className="h-4 w-4" />
Précédent
</Button>
<Button
variant="outline"
size="sm"
onClick={() => setPage(p => Math.min(totalPages, p + 1))}
disabled={page === totalPages}
>
Suivant
<ChevronRight className="h-4 w-4" />
</Button>
</div>
</div>
)}
</CardContent>
</Card>
);
}