Files
mdm-ordinis/ordinis-admin-ui/src/routes/__root.tsx
T
2026-05-10 21:19:07 +00:00

106 lines
3.9 KiB
TypeScript

import { createRootRouteWithContext, Link, Outlet } from '@tanstack/react-router'
import type { QueryClient } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
import { LanguageSwitch } from '@nstart/ui'
import { AuthBadge } from '@/auth/AuthBadge'
import { useCanMutate } from '@/auth/useCanMutate'
import { UpdateBanner } from '@/components/version/UpdateBanner'
import { VersionBadge } from '@/components/version/VersionBadge'
export const Route = createRootRouteWithContext<{ queryClient: QueryClient }>()({
component: RootLayout,
})
const LANG_OPTIONS = [
{ id: 'ru-RU', label: 'RU' },
{ id: 'en-US', label: 'EN' },
]
function RootLayout() {
const { t, i18n } = useTranslation()
// Гость (anonymous) видит только ссылку на /dictionaries и /search.
// Аудит, outbox, webhooks, drafts, reviews — admin-only страницы, требуют
// JWT (backend SecurityConfig + admin role). Скрываем из top-nav чтобы
// user не получал 401 toast при навигации.
const canMutate = useCanMutate()
return (
<div className="min-h-full flex flex-col bg-white">
<UpdateBanner />
<header className="border-b border-regolith bg-white">
<div className="max-w-6xl mx-auto px-4 sm:px-6 py-3 sm:py-4 flex items-center flex-wrap gap-3 sm:gap-6">
<Link to="/" className="font-primary text-base sm:text-lg text-ultramarain">
{t('app.title')}
</Link>
<nav className="flex gap-4 text-sm">
<Link
to="/dictionaries"
className="text-carbon hover:text-ultramarain"
activeProps={{ className: 'text-ultramarain font-medium' }}
>
{t('nav.dictionaries')}
</Link>
<Link
to="/search"
className="text-carbon hover:text-ultramarain"
activeProps={{ className: 'text-ultramarain font-medium' }}
>
{t('nav.search')}
</Link>
{canMutate && (
<>
<Link
to="/audit"
className="text-carbon hover:text-ultramarain"
activeProps={{ className: 'text-ultramarain font-medium' }}
>
{t('nav.audit')}
</Link>
<Link
to="/outbox"
className="text-carbon hover:text-ultramarain"
activeProps={{ className: 'text-ultramarain font-medium' }}
>
{t('nav.outbox')}
</Link>
<Link
to="/webhooks"
className="text-carbon hover:text-ultramarain"
activeProps={{ className: 'text-ultramarain font-medium' }}
>
{t('nav.webhooks')}
</Link>
<Link
to="/reviews"
className="text-carbon hover:text-ultramarain"
activeProps={{ className: 'text-ultramarain font-medium' }}
>
{t('nav.reviews')}
</Link>
<Link
to="/my-drafts"
className="text-carbon hover:text-ultramarain"
activeProps={{ className: 'text-ultramarain font-medium' }}
>
{t('nav.myDrafts')}
</Link>
</>
)}
</nav>
<div className="ml-auto flex items-center gap-3">
<VersionBadge />
<LanguageSwitch
value={i18n.language}
options={LANG_OPTIONS}
onChange={(id) => i18n.changeLanguage(id)}
/>
<AuthBadge />
</div>
</div>
</header>
<main className="flex-1 max-w-6xl mx-auto w-full px-4 sm:px-6 py-4 sm:py-8">
<Outlet />
</main>
</div>
)
}