mirror of
https://github.com/complexcaresolutions/frontend.porwoll.de.git
synced 2026-03-17 16:23:41 +00:00
Bypass broken contracts client navigation filter (queries non-existent 'type' field) with direct fetch to /api/navigations. Transform CMS mainMenu structure (page/custom/submenu types) into NavItem format. Replace JS-state dropdown (AnimatePresence) with pure CSS group-hover to fix SSR hydration issues where both dropdowns opened simultaneously. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
120 lines
3.7 KiB
TypeScript
120 lines
3.7 KiB
TypeScript
import type { Metadata } from 'next'
|
|
import { Montserrat, Open_Sans } from 'next/font/google'
|
|
import { Navigation } from '@/components/Navigation'
|
|
import { Footer } from '@/components/Footer'
|
|
import { getNavigation, getSiteSettings, getSocialLinks } from '@/lib/api'
|
|
import './globals.css'
|
|
|
|
export async function generateMetadata(): Promise<Metadata> {
|
|
const settings = await getSiteSettings() as Record<string, unknown> | null
|
|
const favicon = settings?.favicon as Record<string, unknown> | undefined
|
|
const faviconUrl = favicon?.url as string | undefined
|
|
|
|
return {
|
|
title: 'Martin Porwoll',
|
|
description: 'Whistleblower. Unternehmer. Mensch.',
|
|
icons: faviconUrl ? { icon: faviconUrl } : undefined,
|
|
}
|
|
}
|
|
|
|
const montserrat = Montserrat({
|
|
subsets: ['latin'],
|
|
weight: ['400', '700'],
|
|
variable: '--font-montserrat',
|
|
display: 'swap',
|
|
})
|
|
|
|
const openSans = Open_Sans({
|
|
subsets: ['latin'],
|
|
weight: ['300', '400', '600', '700', '800'],
|
|
variable: '--font-open-sans',
|
|
display: 'swap',
|
|
})
|
|
|
|
export default async function RootLayout({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode
|
|
}) {
|
|
const [navigation, siteSettings, socialLinks] = await Promise.all([
|
|
getNavigation('header'),
|
|
getSiteSettings(),
|
|
getSocialLinks(),
|
|
])
|
|
|
|
// Transform CMS navigation into NavItem format
|
|
const nav = navigation as unknown as Record<string, unknown> | null
|
|
const mainMenu = (nav?.mainMenu || nav?.items) as Array<Record<string, unknown>> | undefined
|
|
|
|
function pageSlugToHref(page: Record<string, unknown> | null): string {
|
|
if (!page?.slug) return '#'
|
|
return page.slug === 'startseite' ? '/' : `/${page.slug}`
|
|
}
|
|
|
|
function buildSubmenuItems(items: Array<Record<string, unknown>>): { label: string; href: string }[] {
|
|
return items.map((sub) => {
|
|
const subPage = sub.page as Record<string, unknown> | null
|
|
const subUrl = sub.url as string | null
|
|
const linkType = sub.linkType as string
|
|
return {
|
|
label: (sub.label as string) || '',
|
|
href: linkType === 'page' ? pageSlugToHref(subPage) : (subUrl || '#'),
|
|
}
|
|
})
|
|
}
|
|
|
|
const navItems = mainMenu?.length
|
|
? mainMenu.map((item) => {
|
|
const type = item.type as string
|
|
const page = item.page as Record<string, unknown> | null
|
|
const submenu = item.submenu as Array<Record<string, unknown>> | undefined
|
|
const children = submenu?.length ? buildSubmenuItems(submenu) : undefined
|
|
|
|
let href = '#'
|
|
if (type === 'page') href = pageSlugToHref(page)
|
|
else if (type === 'custom') href = (item.url as string) || '#'
|
|
|
|
return {
|
|
label: (item.label as string) || '',
|
|
href,
|
|
children,
|
|
}
|
|
})
|
|
: [
|
|
{ label: 'Home', href: '/' },
|
|
{ label: 'Der Mensch', href: '/mensch' },
|
|
{ label: 'Whistleblowing', href: '/whistleblowing' },
|
|
{ label: 'Kontakt', href: '/kontakt' },
|
|
]
|
|
|
|
const settings = siteSettings as unknown as Record<string, unknown> | null
|
|
const logoMedia = settings?.logo as Record<string, unknown> | undefined
|
|
const logoUrl = logoMedia?.url as string | undefined
|
|
|
|
const contactInfo = settings?.contactInfo as Record<string, string> | undefined
|
|
|
|
return (
|
|
<html lang="de" className={`${montserrat.variable} ${openSans.variable}`}>
|
|
<body className="font-body">
|
|
<Navigation
|
|
items={navItems}
|
|
logo={logoUrl}
|
|
transparent={true}
|
|
/>
|
|
|
|
<main id="top">
|
|
{children}
|
|
</main>
|
|
|
|
<Footer
|
|
socialLinks={socialLinks}
|
|
contact={{
|
|
email: contactInfo?.email,
|
|
phone: contactInfo?.phone,
|
|
address: contactInfo?.address,
|
|
}}
|
|
/>
|
|
</body>
|
|
</html>
|
|
)
|
|
}
|