import { isApiError, type SessionDto } from '@impuestos/contracts'; import { setRequestLocale } from 'next-intl/server'; import type { ReactNode } from 'react'; import { Card } from '@/components/ui/card'; import { EmptyState } from '@/components/ui/empty-state'; import { LanguageSwitcher } from '@/components/language-switcher'; import { Link, redirect } from '@/i18n/navigation'; import { getT } from '@/i18n/t'; import { serverApi } from '@/lib/api-server'; const ADMIN_ROLES = new Set(['staff', 'superadmin']); const TABS = [ { href: '/usuarios', key: 'admin.users.title' }, { href: '/errores', key: 'admin.errors.title' }, { href: '/auditoria', key: 'admin.audit.title' }, ] as const; /** * FLOWS.md Flow H. No tab bar, no floating button, no playfulness: a wide page with a * plain nav. The role is checked here and again on every API call, because a layout is a * convenience and the server is the rule. */ export default async function AdminLayout({ children, params, }: { children: ReactNode; params: Promise<{ locale: string }>; }) { const { locale } = await params; setRequestLocale(locale); const t = await getT(locale); const api = await serverApi(); const session: SessionDto | null = await api.getSession().catch((error: unknown) => { if (isApiError(error) && error.code === 'unauthorized') return null; throw error; }); if (!session) redirect({ href: '/login', locale }); if (!session || !ADMIN_ROLES.has(session.role)) { return (
); } return (
{t('admin.nav.console')}
{session.email} {t('common.back')}
{/* The reminder sits above every screen in the console, not only the user search. */}

{t('admin.users.auditBanner')}

{children}
); }