import type { ReactNode } from "react"; import Link from "next/link"; import { ArrowLeftIcon } from "@heroicons/react/24/outline"; import { Skeleton } from "@/components/atoms/loading-skeleton"; import { ErrorState } from "@/components/atoms/error-state"; interface PageLayoutProps { icon?: ReactNode | undefined; title: string; description?: string | undefined; actions?: ReactNode | undefined; backLink?: { label: string; href: string } | undefined; statusPill?: ReactNode | undefined; loading?: boolean | undefined; loadingFallback?: ReactNode | undefined; error?: Error | string | null | undefined; onRetry?: (() => void) | undefined; children: ReactNode; } export function PageLayout({ icon, title, description, actions, backLink, statusPill, loading = false, loadingFallback, error = null, onRetry, children, }: PageLayoutProps) { return (
{/* Page header */}
{backLink && (
{backLink.label}
)}
{icon && (
{icon}
)}

{title}

{statusPill}
{description && (

{description}

)}
{actions && (
{actions}
)}
{/* Content */}
{renderPageContent({ loading, error: error ?? undefined, children, onRetry, loadingFallback, })}
); } function renderPageContent({ loading, error, children, onRetry, loadingFallback, }: { loading: boolean | undefined; error: Error | string | undefined; children: React.ReactNode; onRetry: (() => void) | undefined; loadingFallback: React.ReactNode; }): React.ReactNode { if (loading) { return loadingFallback ?? ; } if (error) { return ; } return children; } function PageLoadingState() { return (
{Array.from({ length: 3 }).map((_, i) => (
))}
); } interface PageErrorStateProps { error: Error | string; onRetry?: (() => void) | undefined; } function PageErrorState({ error, onRetry }: PageErrorStateProps) { const errorMessage = typeof error === "string" ? error : error.message; return (
); }