CI / changes (push) Successful in 10s
CI / commitlint (push) Has been skipped
CI / openapi (push) Has been skipped
CI / web (push) Successful in 52s
CI / go (push) Has been skipped
CI / bird2 (push) Has been skipped
CI / release (push) Successful in 4m7s
Refactored multiple dashboard components to utilize the new PanelCard for better organization and presentation. Updated the DashboardFramePanel, DashboardQuickLinks, and DashboardOperationsBreakdown components to streamline layouts and enhance user experience. Removed deprecated components and improved loading states in various sections, ensuring a cohesive interface throughout the application.
71 lines
1.8 KiB
TypeScript
71 lines
1.8 KiB
TypeScript
import type { ReactNode } from 'react'
|
|
import { AlertCircle, RefreshCwIcon } from 'lucide-react'
|
|
import { Button } from '@evobgp/ui/components/button'
|
|
import { Skeleton } from '@evobgp/ui/components/skeleton'
|
|
import { EmptyState } from './empty-state'
|
|
|
|
interface QueryStateProps<T> {
|
|
data: T | undefined
|
|
isLoading: boolean
|
|
isError: boolean
|
|
error?: unknown
|
|
empty?: boolean
|
|
emptyTitle?: string
|
|
emptyDescription?: string
|
|
emptyAction?: ReactNode
|
|
emptyContent?: ReactNode
|
|
onRetry?: () => void
|
|
skeleton?: ReactNode
|
|
children: (data: T) => ReactNode
|
|
}
|
|
|
|
export function QueryState<T>({
|
|
data,
|
|
isLoading,
|
|
isError,
|
|
error,
|
|
empty,
|
|
emptyTitle = 'Нет данных',
|
|
emptyDescription,
|
|
emptyAction,
|
|
emptyContent,
|
|
onRetry,
|
|
skeleton,
|
|
children,
|
|
}: QueryStateProps<T>) {
|
|
if (isLoading) {
|
|
return <>{skeleton ?? <DefaultSkeleton />}</>
|
|
}
|
|
if (isError) {
|
|
return (
|
|
<EmptyState
|
|
icon={<AlertCircle className="size-8" />}
|
|
title="Ошибка загрузки"
|
|
description={error instanceof Error ? error.message : 'Не удалось загрузить данные'}
|
|
action={
|
|
onRetry ? (
|
|
<Button variant="outline" size="sm" onClick={onRetry}>
|
|
<RefreshCwIcon data-icon="inline-start" />
|
|
Повторить
|
|
</Button>
|
|
) : null
|
|
}
|
|
/>
|
|
)
|
|
}
|
|
if (empty || data == null) {
|
|
if (emptyContent) return <>{emptyContent}</>
|
|
return <EmptyState title={emptyTitle} description={emptyDescription} action={emptyAction} />
|
|
}
|
|
return <>{children(data)}</>
|
|
}
|
|
|
|
function DefaultSkeleton() {
|
|
return (
|
|
<div className="flex flex-col gap-3">
|
|
<Skeleton className="h-8 w-48" />
|
|
<Skeleton className="h-32 w-full" />
|
|
</div>
|
|
)
|
|
}
|