220 lines
8.1 KiB
TypeScript
220 lines
8.1 KiB
TypeScript
import type { Footer, Header, Media } from '@/payload-types'
|
||
|
||
export type SpaIconName = 'instagram' | 'linkedin' | 'facebook'
|
||
export type SpaLink = { label: string; path: string }
|
||
export type SpaSocialLink = { label: string; href: string; icon: SpaIconName }
|
||
export type SpaCtaLink = SpaLink & { variant?: 'primary' | 'secondary' | 'subtle' | 'upload' }
|
||
export type SpaMedia = { url?: string; alt?: string }
|
||
|
||
export type SpaHeaderNavItem = SpaLink & {
|
||
key: string
|
||
subLabel?: string
|
||
sub?: SpaLink[]
|
||
}
|
||
|
||
export type SpaHeaderData = {
|
||
logo?: SpaMedia
|
||
overlayKicker: string
|
||
overlayHeadline: string
|
||
overlayLogoAlt: string
|
||
mobileWatermark: string
|
||
menuLabel: string
|
||
openLabel: string
|
||
closeLabel: string
|
||
overviewLabel: string
|
||
navItems: SpaHeaderNavItem[]
|
||
secondaryLinks: SpaLink[]
|
||
socialLinks: SpaSocialLink[]
|
||
ctas: SpaCtaLink[]
|
||
languages: string[]
|
||
}
|
||
|
||
export type SpaFooterLinkColumn = { label: string; links: SpaLink[] }
|
||
export type SpaPartnerLogo = { image?: SpaMedia; alt: string }
|
||
|
||
export type SpaFooterData = {
|
||
logo?: SpaMedia
|
||
logoAlt: string
|
||
headlinePrefix: string
|
||
headlineAccent: string
|
||
headlineSuffix: string
|
||
sinceLabel: string
|
||
year: string
|
||
description: string
|
||
ctas: SpaCtaLink[]
|
||
linkColumns: SpaFooterLinkColumn[]
|
||
partnerLabel: string
|
||
partnerLogos: SpaPartnerLogo[]
|
||
copyright: string
|
||
socialLinks: SpaSocialLink[]
|
||
}
|
||
|
||
export const defaultSocialLinks: SpaSocialLink[] = [
|
||
{ href: 'https://instagram.com', icon: 'instagram', label: 'Instagram' },
|
||
{ href: 'https://linkedin.com', icon: 'linkedin', label: 'LinkedIn' },
|
||
{ href: 'https://facebook.com', icon: 'facebook', label: 'Facebook' },
|
||
]
|
||
|
||
export const defaultHeaderData: SpaHeaderData = {
|
||
logo: { url: '/bmp-logo.png', alt: 'Der Bayerische Mittelstandspreis 2026' },
|
||
overlayKicker: 'Bayerischer Mittelstandspreis',
|
||
overlayHeadline: 'EXZELLENZ HAT\nEINEN NAMEN.',
|
||
overlayLogoAlt: 'BMP Logo',
|
||
mobileWatermark: 'Exzellenz\nseit 2005',
|
||
menuLabel: 'Menü',
|
||
openLabel: 'Navigation öffnen',
|
||
closeLabel: 'Menü schließen',
|
||
overviewLabel: 'Überblick',
|
||
languages: ['DE', 'EN'],
|
||
socialLinks: defaultSocialLinks,
|
||
navItems: [
|
||
{
|
||
key: 'preistraeger', label: 'Preisträger:innen', path: '/preistraeger', subLabel: 'PREISTRÄGER:INNEN',
|
||
sub: [
|
||
{ label: 'Alle Preisträger:innen', path: '/preistraeger' },
|
||
{ label: 'Sieger & Aufsteiger 2025', path: '/preistraeger' },
|
||
],
|
||
},
|
||
{
|
||
key: 'teilnahme', label: 'Ihr Weg zum Preis', path: '/teilnahme', subLabel: 'IHR WEG ZUM PREIS',
|
||
sub: [
|
||
{ label: 'Teilnahmevoraussetzungen', path: '/teilnahme#voraussetzungen' },
|
||
{ label: 'Kriterien & Bewertung', path: '/teilnahme#kriterien' },
|
||
{ label: 'Fristen & Termine', path: '/teilnahme#fristen' },
|
||
{ label: 'Bewerbungsformular', path: '/teilnahme#bewerben' },
|
||
],
|
||
},
|
||
{
|
||
key: 'bmp', label: 'Der BMP', path: '/der-bmp', subLabel: 'DER BMP',
|
||
sub: [
|
||
{ label: 'Was ist der Preis?', path: '/der-bmp#was-ist' },
|
||
{ label: 'Geschichte & Werte', path: '/der-bmp#geschichte' },
|
||
{ label: 'Vorteile der Auszeichnung', path: '/der-bmp#vorteile' },
|
||
],
|
||
},
|
||
{
|
||
key: 'netzwerk', label: 'Netzwerk', path: '/netzwerk', subLabel: 'NETZWERK',
|
||
sub: [
|
||
{ label: 'Jury-Mitglieder', path: '/netzwerk#jury' },
|
||
{ label: 'Partner & Sponsoren', path: '/netzwerk#partner' },
|
||
{ label: 'Schirmherrschaft', path: '/netzwerk#schirmherrschaft' },
|
||
{ label: 'Mitglied werden', path: '/mitglied-werden' },
|
||
],
|
||
},
|
||
{
|
||
key: 'presse', label: 'Presse', path: '/presse', subLabel: 'PRESSE',
|
||
sub: [
|
||
{ label: 'Events & Gala', path: '/presse#events' },
|
||
{ label: 'Downloads & Impressionen', path: '/presse#downloads' },
|
||
],
|
||
},
|
||
],
|
||
secondaryLinks: [
|
||
{ label: 'Startseite', path: '/' },
|
||
{ label: 'Kontakt', path: '/kontakt' },
|
||
{ label: 'Impressum', path: '/impressum' },
|
||
{ label: 'Datenschutz', path: '/datenschutz' },
|
||
],
|
||
ctas: [
|
||
{ label: 'Jetzt bewerben', path: '/teilnahme#bewerben', variant: 'primary' },
|
||
{ label: 'Mitglied werden', path: '/mitglied-werden', variant: 'secondary' },
|
||
{ label: 'Formular hochladen', path: '/formular-hochladen', variant: 'upload' },
|
||
],
|
||
}
|
||
|
||
export const defaultFooterData: SpaFooterData = {
|
||
logo: { url: '/bmp-logo.png', alt: 'Bayerischer Mittelstandspreis' },
|
||
logoAlt: 'Bayerischer Mittelstandspreis',
|
||
headlinePrefix: 'Der Preis des',
|
||
headlineAccent: 'Bayerischen',
|
||
headlineSuffix: 'Mittelstands',
|
||
sinceLabel: 'Exzellenz seit 2005',
|
||
year: '2026',
|
||
description: 'Die renommierteste Auszeichnung für herausragende Unternehmen des bayerischen Mittelstands.',
|
||
ctas: [
|
||
{ label: 'Kostenlos bewerben', path: '/teilnahme#bewerben', variant: 'primary' },
|
||
{ label: 'Mitglied werden', path: '/mitglied-werden', variant: 'secondary' },
|
||
{ label: 'Sponsoring-Anfrage →', path: '/netzwerk#sponsoring', variant: 'subtle' },
|
||
],
|
||
linkColumns: [
|
||
{ label: 'BMP 2026', links: [
|
||
{ label: 'Startseite', path: '/' },
|
||
{ label: 'Preisträger', path: '/preistraeger' },
|
||
{ label: 'Teilnahme', path: '/teilnahme' },
|
||
] },
|
||
{ label: 'Engagement', links: [
|
||
{ label: 'Netzwerk & Jury', path: '/netzwerk' },
|
||
{ label: 'Presse', path: '/presse' },
|
||
{ label: 'Kontakt', path: '/kontakt' },
|
||
] },
|
||
{ label: 'Legal', links: [
|
||
{ label: 'Datenschutz', path: '/datenschutz' },
|
||
{ label: 'Impressum', path: '/impressum' },
|
||
] },
|
||
],
|
||
partnerLabel: 'Partner',
|
||
partnerLogos: [
|
||
{ alt: 'EWIF – Europäisches Wirtschaftsforum', image: { url: '/images/ewif-logo.png' } },
|
||
{ alt: 'Hochschule für angewandtes Management · Gipfeldialog Altaussee', image: { url: '/images/partner-logos.png' } },
|
||
],
|
||
copyright: '© 2026 Bayerischer Mittelstandspreis · Alle Rechte vorbehalten',
|
||
socialLinks: defaultSocialLinks,
|
||
}
|
||
|
||
const isMedia = (value: unknown): value is Media => Boolean(value && typeof value === 'object' && 'url' in value)
|
||
const mediaToSpa = (value: unknown, fallback?: SpaMedia): SpaMedia | undefined => {
|
||
if (isMedia(value)) return { url: value.url || fallback?.url, alt: value.alt || fallback?.alt }
|
||
return fallback
|
||
}
|
||
|
||
type HeaderLanguage = string | { label?: string }
|
||
|
||
type FooterPartnerLogo = {
|
||
alt?: string
|
||
image?: unknown
|
||
}
|
||
|
||
export function normalizeHeaderData(header?: Partial<Header>): SpaHeaderData {
|
||
return {
|
||
...defaultHeaderData,
|
||
...header,
|
||
logo: mediaToSpa(header?.logo, defaultHeaderData.logo),
|
||
navItems: header?.navItems?.length
|
||
? (header.navItems as unknown as SpaHeaderNavItem[])
|
||
: defaultHeaderData.navItems,
|
||
secondaryLinks: header?.secondaryLinks?.length
|
||
? (header.secondaryLinks as unknown as SpaLink[])
|
||
: defaultHeaderData.secondaryLinks,
|
||
socialLinks: header?.socialLinks?.length
|
||
? (header.socialLinks as unknown as SpaSocialLink[])
|
||
: defaultHeaderData.socialLinks,
|
||
ctas: header?.ctas?.length ? (header.ctas as unknown as SpaCtaLink[]) : defaultHeaderData.ctas,
|
||
languages: header?.languages?.length
|
||
? (header.languages as HeaderLanguage[])
|
||
.map((item) => (typeof item === 'string' ? item : item.label))
|
||
.filter((label): label is string => Boolean(label))
|
||
: defaultHeaderData.languages,
|
||
}
|
||
}
|
||
|
||
export function normalizeFooterData(footer?: Partial<Footer>): SpaFooterData {
|
||
return {
|
||
...defaultFooterData,
|
||
...footer,
|
||
logo: mediaToSpa(footer?.logo, defaultFooterData.logo),
|
||
ctas: footer?.ctas?.length ? (footer.ctas as unknown as SpaCtaLink[]) : defaultFooterData.ctas,
|
||
linkColumns: footer?.linkColumns?.length
|
||
? (footer.linkColumns as unknown as SpaFooterData['linkColumns'])
|
||
: defaultFooterData.linkColumns,
|
||
socialLinks: footer?.socialLinks?.length
|
||
? (footer.socialLinks as unknown as SpaSocialLink[])
|
||
: defaultFooterData.socialLinks,
|
||
partnerLogos: footer?.partnerLogos?.length
|
||
? (footer.partnerLogos as FooterPartnerLogo[]).map((item, index) => ({
|
||
alt: item.alt || defaultFooterData.partnerLogos[index]?.alt || '',
|
||
image: mediaToSpa(item.image, defaultFooterData.partnerLogos[index]?.image),
|
||
}))
|
||
: defaultFooterData.partnerLogos,
|
||
}
|
||
}
|