diff --git a/mvp/b2c/src/app/admin/layout.tsx b/mvp/b2c/src/app/admin/layout.tsx index e36379d..6f408ce 100644 --- a/mvp/b2c/src/app/admin/layout.tsx +++ b/mvp/b2c/src/app/admin/layout.tsx @@ -1,27 +1,29 @@ import Link from 'next/link'; import type { Metadata } from 'next'; import { requireAdmin } from '@/lib/auth/current-user'; +import AppNav from '@/components/AppNav'; export const metadata: Metadata = { title: 'Admin · Reformix' }; +const ADMIN_LINKS = [ + { href: '/admin', label: 'Resumen' }, + { href: '/admin/usuarios', label: 'Usuarios' }, + { href: '/admin/planes', label: 'Planes' }, +] as const; + export default async function AdminLayout({ children }: { children: React.ReactNode }) { await requireAdmin(); return (
-
-
- - R +
+
+ + R Reformix - / - Admin + / + Admin - +
{children}
diff --git a/mvp/b2c/src/app/panel/layout.tsx b/mvp/b2c/src/app/panel/layout.tsx index e12474d..56e9cc5 100644 --- a/mvp/b2c/src/app/panel/layout.tsx +++ b/mvp/b2c/src/app/panel/layout.tsx @@ -4,6 +4,13 @@ import { requireUser } from '@/lib/auth/current-user'; import { db } from '@/db'; import { tenants } from '@/db/schema'; import { eq } from 'drizzle-orm'; +import AppNav from '@/components/AppNav'; + +const PANEL_LINKS = [ + { href: '/panel', label: 'Leads' }, + { href: '/panel/precios', label: 'Precios' }, + { href: '/panel/empresa', label: 'Empresa' }, +] as const; export const metadata: Metadata = { title: 'Panel · Reformix', @@ -19,24 +26,19 @@ export default async function PanelLayout({ children }: { children: React.ReactN return (
-
-
- - +
+
+ + R Reformix - / - {nombreEmpresa} + / + + {nombreEmpresa} + - +
{children}
diff --git a/mvp/b2c/src/components/AppNav.tsx b/mvp/b2c/src/components/AppNav.tsx new file mode 100644 index 0000000..79cbc29 --- /dev/null +++ b/mvp/b2c/src/components/AppNav.tsx @@ -0,0 +1,105 @@ +'use client'; + +import { useState } from 'react'; +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; + +export type AppNavLink = { href: string; label: string }; + +// El enlace activo es el href más específico (más largo) que prefija el pathname. +function activeHref(pathname: string, links: readonly AppNavLink[]): string { + let best = ''; + for (const l of links) { + if ((pathname === l.href || pathname.startsWith(l.href + '/')) && l.href.length > best.length) { + best = l.href; + } + } + return best; +} + +export default function AppNav({ links }: { links: readonly AppNavLink[] }) { + const pathname = usePathname(); + const [open, setOpen] = useState(false); + const active = activeHref(pathname, links); + + return ( + <> + {/* Escritorio */} + + + {/* Móvil: botón hamburguesa */} + + + {/* Móvil: panel desplegable */} + {open && ( + <> + + +
+ + + )} + + ); +}