import type { ReactNode } from "react";
import { AlertTriangle, Inbox, type LucideIcon } from "lucide-react";
import { cn } from "@/lib/utils";
interface EmptyStateProps {
title: ReactNode;
description?: ReactNode;
icon?: LucideIcon;
action?: ReactNode;
className?: string;
}
/** Rien à afficher : dire pourquoi, et quoi faire. */
export function EmptyState({ title, description, icon: Icon = Inbox, action, className }: EmptyStateProps) {
return (
{title}
{description &&
{description}
}
{action &&
{action}
}
);
}
interface ErrorStateProps {
title?: ReactNode;
/** Explication pour l'utilisateur ; le détail technique va dans `detail`. */
description?: ReactNode;
/** Message technique, replié par défaut. */
detail?: string;
action?: ReactNode;
className?: string;
}
/** Un chargement a échoué : message clair, détail technique replié, action de reprise. */
export function ErrorState({
title = "Les données n'ont pas pu être chargées",
description = "Réessayez dans un instant. Si le problème persiste, prévenez un administrateur.",
detail,
action,
className,
}: ErrorStateProps) {
return (
{title}
{description}
{detail && (
Détail technique
{detail}
)}
{action &&
{action}
}
);
}
export function Skeleton({ className }: { className?: string }) {
return ;
}
/**
* Silhouette d'une page pendant son chargement : la mise en page reste visible
* et rien ne bloque l'écran (contrairement à l'ancienne fenêtre plein écran).
*/
export function PageSkeleton({ cards = 0, rows = 8 }: { cards?: number; rows?: number }) {
return (
{cards > 0 && (
{Array.from({ length: cards }, (_, i) => )}
)}
{Array.from({ length: rows }, (_, i) => )}
);
}