Files
EvoBGP/apps/web/src/components/modules/module-kpi-cards.tsx
T
Denozordec 821f342476
CI / changes (push) Successful in 7s
CI / commitlint (push) Skipped
CI / go (push) Skipped
CI / bird2 (push) Skipped
CI / openapi (push) Successful in 51s
CI / web (push) Successful in 1m26s
CI / release (push) Successful in 4m26s
feat(modules): enhance ModuleKpiCards and add update functionality for modules
Updated the ModuleKpiCards component to improve the display of KPI metrics by introducing a new entries count prop and simplifying the logic for displaying community and DoH information. Added a new mutation hook for updating modules, which includes success and error handling with toast notifications. Enhanced the ModuleDetailComponent to support editing modules with a new dialog and integrated the entries count into the KPI display.

Additionally, introduced a new helper function for generating short labels for DoH profiles, improving the overall user experience in module management.
2026-08-12 11:32:44 +07:00

114 lines
3.4 KiB
TypeScript

import { Clock, Gauge, Globe, Tags } from 'lucide-react'
import { KpiStatGrid, type KpiStatItem } from '@/components/kpi-stat-grid'
import { Badge } from '@/components/reui/badge'
import { KpiStatGridSkeleton } from '@/components/skeletons'
import { formatDateTime, moduleIntervalLabel } from '@/lib/modules/display'
import { communityLabel, moduleDohProfileIds } from '@/lib/modules/helpers'
import { dohPolicyRu } from '@/lib/ui-labels'
import type { AsEntry, BgpCommunity, ModuleRow } from '@/types/api'
interface ModuleKpiCardsProps {
mod: ModuleRow | null
communities: BgpCommunity[]
asEntries: AsEntry[]
entriesCount?: number
loading?: boolean
}
export function ModuleKpiCards({
mod,
communities,
asEntries,
entriesCount = 0,
loading = false,
}: ModuleKpiCardsProps) {
if (loading || !mod) {
return <KpiStatGridSkeleton count={4} />
}
const asPrefixTotal = asEntries.reduce((acc, entry) => acc + (entry.prefix_count ?? 0), 0)
const dohIds = moduleDohProfileIds(mod)
const isDomains = mod.type === 'DOMAINS'
const isAsPrefixes = mod.type === 'AS_PREFIXES'
const community = communityLabel(mod.default_community_id, communities)
const entriesFooter = isAsPrefixes ? (
<Badge variant="success-light" size="sm">
{asEntries.length} AS · в модуле
</Badge>
) : isDomains ? (
<Badge variant="outline" size="sm">
{mod.default_community_id ? community : 'без community'}
</Badge>
) : (
<Badge variant="success-light" size="sm">
{entriesCount} · в модуле
</Badge>
)
const policyItem: KpiStatItem = isDomains
? {
id: 'doh',
icon: <Globe aria-hidden />,
iconClassName: 'text-primary',
value: dohIds.length > 0 ? String(dohIds.length) : '—',
label: 'DoH',
footer: (
<Badge variant={dohIds.length > 0 ? 'info-light' : 'outline'} size="sm">
{dohIds.length > 0 ? dohPolicyRu(mod.doh_resolver_policy) : 'без DoH'}
</Badge>
),
}
: {
id: 'community',
icon: <Globe aria-hidden />,
iconClassName: 'text-primary',
value: community,
label: 'Community',
footer: (
<Badge variant="outline" size="sm">
по умолчанию
</Badge>
),
}
const items: KpiStatItem[] = [
{
id: 'priority',
icon: <Gauge aria-hidden />,
iconClassName: 'text-info',
value: String(mod.priority ?? 0),
label: 'Приоритет',
footer: (
<Badge variant={mod.enabled !== false ? 'success-light' : 'outline'} size="sm">
{mod.enabled !== false ? 'активен' : 'выключен'} · {mod.type}
</Badge>
),
},
{
id: 'interval',
icon: <Clock aria-hidden />,
iconClassName: 'text-warning',
value: moduleIntervalLabel(mod),
label: 'Интервал обновления',
footer: (
<Badge variant="primary-light" size="sm">
{formatDateTime(mod.last_refreshed_at) || 'никогда'}
</Badge>
),
},
{
id: 'prefixes',
icon: <Tags aria-hidden />,
iconClassName: 'text-success',
value: isAsPrefixes ? String(asPrefixTotal) : String(entriesCount),
label: isAsPrefixes ? 'Префиксы AS' : 'Записи модуля',
footer: entriesFooter,
},
policyItem,
]
return <KpiStatGrid items={items} aria-label="KPI модуля" />
}