Обновлены переводы на русский язык для различных компонентов, включая KPI, карточки сети и панели управления. Исправлены описания и метки для улучшения пользовательского интерфейса. Также добавлены новые элементы для поддержки локализации в компонентах, таких как DataGrid и ResourcePage. Co-authored-by: Cursor <[email protected]>
126 lines
3.9 KiB
TypeScript
126 lines
3.9 KiB
TypeScript
import type { ReactNode } from 'react'
|
|
import { Link, Outlet, useRouterState } from '@tanstack/react-router'
|
|
import { ServerCogIcon, SettingsIcon } from 'lucide-react'
|
|
|
|
import { useIsMobile } from '@evobgp/ui/hooks/use-mobile'
|
|
import { cn } from '@evobgp/ui/lib/utils'
|
|
import { PageShell } from '@/components/page-shell'
|
|
import { PageHeader } from '@/components/page-header'
|
|
|
|
export interface SettingsTabConfig {
|
|
id: string
|
|
to: '/settings' | '/tenant-settings'
|
|
label: string
|
|
icon?: ReactNode
|
|
}
|
|
|
|
/** Default nav for EvoBGP settings routes (`/settings`, `/tenant-settings`). */
|
|
const DEFAULT_TABS: SettingsTabConfig[] = [
|
|
{
|
|
id: 'ui',
|
|
to: '/settings',
|
|
label: 'Настройки UI',
|
|
icon: <SettingsIcon className="size-4" aria-hidden="true" />,
|
|
},
|
|
{
|
|
id: 'tenant',
|
|
to: '/tenant-settings',
|
|
label: 'Настройки BIRD',
|
|
icon: <ServerCogIcon className="size-4" aria-hidden="true" />,
|
|
},
|
|
]
|
|
|
|
interface SettingsShellProps {
|
|
title?: string
|
|
description?: string
|
|
tabs?: SettingsTabConfig[]
|
|
}
|
|
|
|
/**
|
|
* Settings shell — Frame surface, no hairline Separator under header.
|
|
* @see https://reui.io/preview/base/settings-16
|
|
* @see https://reui.io/preview/base/settings-3
|
|
*/
|
|
export function SettingsShell({
|
|
title = 'Настройки',
|
|
description,
|
|
tabs = DEFAULT_TABS,
|
|
}: SettingsShellProps) {
|
|
const isMobile = useIsMobile()
|
|
const pathname = useRouterState({ select: (s) => s.location.pathname })
|
|
const headerDescription =
|
|
description ??
|
|
(pathname.startsWith('/tenant-settings')
|
|
? 'Глобальные параметры BIRD и плоскости управления'
|
|
: 'Подключение UI и параметры плоскости управления')
|
|
|
|
return (
|
|
<PageShell>
|
|
<div className="mx-auto flex w-full max-w-4xl flex-col gap-5">
|
|
<PageHeader title={title} description={headerDescription} />
|
|
|
|
<div
|
|
className={cn(
|
|
'flex gap-5',
|
|
isMobile ? 'flex-col' : 'flex-row items-start',
|
|
)}
|
|
>
|
|
{tabs.length > 1 ? (
|
|
<nav
|
|
aria-label="Разделы настроек"
|
|
className={cn(
|
|
'flex gap-1',
|
|
isMobile
|
|
? 'scrollbar-none -mx-1 overflow-x-auto overflow-y-hidden pb-1'
|
|
: 'w-44 shrink-0 flex-col',
|
|
)}
|
|
>
|
|
{tabs.map((tab) => {
|
|
const isActive = pathname.startsWith(tab.to)
|
|
const className = cn(
|
|
'flex items-center gap-2 rounded-lg px-3 py-2 text-sm transition-colors',
|
|
isMobile && 'shrink-0',
|
|
!isMobile && 'w-full',
|
|
isActive
|
|
? 'bg-muted text-foreground font-medium shadow-sm ring-1 ring-border/60'
|
|
: 'text-muted-foreground hover:bg-muted/60 hover:text-foreground',
|
|
)
|
|
if (tab.to === '/tenant-settings') {
|
|
return (
|
|
<Link
|
|
key={tab.id}
|
|
to="/tenant-settings"
|
|
search={{ tab: 'bird' }}
|
|
aria-current={isActive ? 'page' : undefined}
|
|
className={className}
|
|
>
|
|
{tab.icon}
|
|
{tab.label}
|
|
</Link>
|
|
)
|
|
}
|
|
return (
|
|
<Link
|
|
key={tab.id}
|
|
to="/settings"
|
|
search={{ tab: 'connection' }}
|
|
aria-current={isActive ? 'page' : undefined}
|
|
className={className}
|
|
>
|
|
{tab.icon}
|
|
{tab.label}
|
|
</Link>
|
|
)
|
|
})}
|
|
</nav>
|
|
) : null}
|
|
|
|
<div className="min-w-0 flex-1">
|
|
<Outlet />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</PageShell>
|
|
)
|
|
}
|