diff --git a/web/src/lib/ui/patterns/kpi/kpi-metrics-grid.svelte b/web/src/lib/ui/patterns/kpi/kpi-metrics-grid.svelte new file mode 100644 index 0000000..6e9de52 --- /dev/null +++ b/web/src/lib/ui/patterns/kpi/kpi-metrics-grid.svelte @@ -0,0 +1,112 @@ + + +
+ {#if loading} + {#each Array(skeletonCount) as _, i (i)} + + {/each} + {:else} + {#each cards as card (card.id)} + {@const Icon = card.icon} + {@const a = card.accent} + + + {#if card.href} +
+ + + {card.label} + + +
+ {:else} + + + {card.label} + + {/if} + {card.value} +
+ + {card.badge} + {#if card.error} +

{card.error}

+ {:else} +

{card.description}

+ {/if} +
+
+ {/each} + {/if} +
diff --git a/web/src/routes/+page.svelte b/web/src/routes/+page.svelte index 7dd7636..1b2a53b 100644 --- a/web/src/routes/+page.svelte +++ b/web/src/routes/+page.svelte @@ -26,6 +26,7 @@ import { Alert, AlertDescription, AlertTitle } from '$lib/ui/core/alert/index.js'; import { Skeleton } from '$lib/ui/core/skeleton/index.js'; import CardSkeleton from '$lib/ui/patterns/feedback/card-skeleton.svelte'; + import KpiMetricsGrid from '$lib/ui/patterns/kpi/kpi-metrics-grid.svelte'; import PageHeader from '$lib/ui/app/page-header/page-header.svelte'; import { notifyApiError } from '$lib/ui/app/toast.js'; import OverviewRecentJobsCard from '$lib/components/overview/OverviewRecentJobsCard.svelte'; @@ -38,7 +39,6 @@ import Radio from '@lucide/svelte/icons/radio'; import Activity from '@lucide/svelte/icons/activity'; import Clock from '@lucide/svelte/icons/clock'; - import ArrowRight from '@lucide/svelte/icons/arrow-right'; import LayoutDashboard from '@lucide/svelte/icons/layout-dashboard'; import Info from '@lucide/svelte/icons/info'; import RefreshCw from '@lucide/svelte/icons/refresh-cw'; @@ -251,50 +251,12 @@ {/if} -
- {#if initialLoading} - {#each Array(5) as _, i (i)} - - {/each} - {:else} - {#each kpiCards as card (card.id)} - {@const Icon = card.icon} - {@const a = card.accent} - - -
- - - {card.label} - - -
- {card.value} -
- - {card.badge} -

{card.description}

-
-
- {/each} - {/if} -
+
-
- {#if initialLoading} - {#each Array(3) as _, i (i)} - - {/each} - {:else} - {#each kpiCards as card (card.id)} - {@const Icon = card.icon} - {@const a = card.accent} - - -
- - - {card.label} - - {#if card.href} - - {/if} -
- {card.value} -
- - {card.badge} -

{card.description}

-
-
- {/each} - {/if} -
+ diff --git a/web/src/routes/modules/+page.svelte b/web/src/routes/modules/+page.svelte index fcda6a4..c18a951 100644 --- a/web/src/routes/modules/+page.svelte +++ b/web/src/routes/modules/+page.svelte @@ -22,6 +22,7 @@ import { Checkbox } from '$lib/ui/core/checkbox/index.js'; import AppDataTable from '$lib/ui/patterns/data-table/app-data-table.svelte'; import CardSkeleton from '$lib/ui/patterns/feedback/card-skeleton.svelte'; + import KpiMetricsGrid from '$lib/ui/patterns/kpi/kpi-metrics-grid.svelte'; import PageHeader from '$lib/ui/app/page-header/page-header.svelte'; import { confirm } from '$lib/ui/patterns/confirm/confirm-state.svelte.js'; import { notify, notifyApiError } from '$lib/ui/app/toast.js'; @@ -217,36 +218,12 @@ -
- {#if initialLoading} - {#each Array(3) as _, i (i)} - - {/each} - {:else} - {#each kpiCards as card (card.id)} - {@const Icon = card.icon} - {@const a = card.accent} - - - - - {card.label} - - {card.value} - - - {card.badge} -

{card.description}

-
-
- {/each} - {/if} -
+ diff --git a/web/src/routes/monitoring/+page.svelte b/web/src/routes/monitoring/+page.svelte index 2a9e21b..7457c75 100644 --- a/web/src/routes/monitoring/+page.svelte +++ b/web/src/routes/monitoring/+page.svelte @@ -46,6 +46,7 @@ TableRow } from '$lib/ui/core/table/index.js'; import CardSkeleton from '$lib/ui/patterns/feedback/card-skeleton.svelte'; + import KpiMetricsGrid from '$lib/ui/patterns/kpi/kpi-metrics-grid.svelte'; import ScrollPreBlock from '$lib/components/app/scroll-pre-block.svelte'; import PageHeader from '$lib/ui/app/page-header/page-header.svelte'; import { cn } from '$lib/utils.js'; @@ -223,6 +224,7 @@ badge: version ? 'Загружена' : '—', badgeVariant: version ? ('outline' as const) : ('secondary' as const), badgeClass: undefined, + valueClass: 'font-mono text-xl', error: versionError, href: undefined } @@ -342,66 +344,12 @@ {/if} {/if} -
- {#if initialLoading} - {#each Array(4) as _, i (i)} - - {/each} - {:else} - {#each kpiCards as card (card.id)} - {@const Icon = card.icon} - {@const a = card.accent} - - -
- - - {card.label} - - {#if card.href} - - {/if} -
- - {card.value} - -
- -
- {card.badge} -
- {#if card.error} -

{card.error}

- {:else} -

{card.description}

- {/if} -
-
- {/each} - {/if} -
+
{#if initialLoading} diff --git a/web/src/routes/network/+page.svelte b/web/src/routes/network/+page.svelte index 2097814..f422b84 100644 --- a/web/src/routes/network/+page.svelte +++ b/web/src/routes/network/+page.svelte @@ -15,6 +15,7 @@ import { Alert, AlertDescription, AlertTitle } from '$lib/ui/core/alert/index.js'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '$lib/ui/core/tabs/index.js'; import CardSkeleton from '$lib/ui/patterns/feedback/card-skeleton.svelte'; + import KpiMetricsGrid from '$lib/ui/patterns/kpi/kpi-metrics-grid.svelte'; import PageHeader from '$lib/ui/app/page-header/page-header.svelte'; import { notifyApiError } from '$lib/ui/app/toast.js'; import NetworkPeersCard from '$lib/components/network/NetworkPeersCard.svelte'; @@ -179,36 +180,12 @@ -
- {#if initialLoading} - {#each Array(3) as _, i (i)} - - {/each} - {:else} - {#each kpiCards as card (card.id)} - {@const Icon = card.icon} - {@const a = card.accent} - - - - - {card.label} - - {card.value} - - - {card.badge} -

{card.description}

-
-
- {/each} - {/if} -
+ diff --git a/web/src/routes/operations/+page.svelte b/web/src/routes/operations/+page.svelte index 4ea2a4f..12bf745 100644 --- a/web/src/routes/operations/+page.svelte +++ b/web/src/routes/operations/+page.svelte @@ -60,6 +60,7 @@ } from '$lib/components/operations/types.js'; import ScrollPreBlock from '$lib/components/app/scroll-pre-block.svelte'; import CardSkeleton from '$lib/ui/patterns/feedback/card-skeleton.svelte'; + import KpiMetricsGrid from '$lib/ui/patterns/kpi/kpi-metrics-grid.svelte'; import { confirm } from '$lib/ui/patterns/confirm/confirm-state.svelte.js'; import PageHeader from '$lib/ui/app/page-header/page-header.svelte'; import { notify, notifyApiError } from '$lib/ui/app/toast.js'; @@ -891,53 +892,12 @@ -
- {#if initialLoading} - {#each Array(3) as _, i (i)} - - {/each} - {:else} - {#each kpiCards as card (card.id)} - {@const Icon = card.icon} - {@const a = card.accent} - - -
- - - {card.label} - - {#if card.href} - - {/if} -
- {card.value} -
- - {card.badge} -

{card.description}

-
-
- {/each} - {/if} -
+ -
- {#if initialLoading} - {#each Array(3) as _, i (i)} - - {/each} - {:else} - {#each kpiCards as card (card.id)} - {@const Icon = card.icon} - {@const a = card.accent} - - -
- - - {card.label} - - {#if card.href} - - {/if} -
- {card.value} -
- - {card.badge} -

{card.description}

-
-
- {/each} - {/if} -
+