'use client'
import * as React from 'react'
import { AlertCircle } from 'lucide-react'
import { useTranslations } from 'next-intl'
import { Button } from '@/components/ui/button'
import { Skeleton } from '@/components/ui/skeleton'
import { cn } from '@/lib/utils'
interface DataStateProps {
loading: boolean
error: string | null
/** When true (and not loading/error), render `empty` instead of `children`. */
isEmpty?: boolean
/** Retry handler: typically `useFetch().refetch`. Shows a retry button. */
onRetry?: () => void
/** Loading placeholder. Defaults to three skeleton rows. */
skeleton?: React.ReactNode
/** Shown when `isEmpty`. Pass an `EmptyState` / preset (e.g. ``). */
empty?: React.ReactNode
children: React.ReactNode
className?: string
}
/**
* Renders the loading / error / empty / ready states for a data-driven section,
* so callers stop hand-rolling that branch every time.
*
* Pairs with `useFetch`:
*
* @example
* const { data, loading, error, refetch } = useFetch(url, { select: b => b.data })
* return (
* }
* >
*
*
* )
*
* Loading uses the `Skeleton` primitive; empty expects an `EmptyState`; the
* error branch uses the only chrome-permitted semantic colour (`destructive`).
*/
export function DataState({
loading,
error,
isEmpty = false,
onRetry,
skeleton,
empty,
children,
className,
}: DataStateProps) {
const t = useTranslations('common')
if (loading) {
return (
)
}
if (error) {
return (
{t('load_error')}
{error}
{onRetry && (
)}
)
}
if (isEmpty) {
return {empty}
}
return <>{children}>
}