import React, { useState } from 'react'; import { Button } from '@/spa/components/ui/button'; import { Play, ChevronRight, X, Star } from 'lucide-react'; import { Link } from '@/spa/router'; import { PartnerTicker } from '@/spa/components/ui/partner-ticker'; import { WINNERS } from '@/spa/data/winners'; import BewerbungsForm from '@/spa/components/forms/BewerbungsForm'; import TestimonialsSection from '@/spa/components/TestimonialsSection'; import MunichSkylineBg from '@/spa/components/ui/munich-skyline-bg'; import { useIsMobile } from '@/spa/hooks/useIsMobile'; import Image from '@/spa/components/ui/UnoptimizedImage' import { useCmsCollection, useCmsRoute } from '@/spa/cmsRoute' import { mediaAlt, mediaUrl } from '@/spa/cmsMediaField' const PARTNERS = [ { id: 'rsm', label: <>RSM
Ebner Stolz }, { id: 'wwk', label: WWK }, { id: 'db', label: Deutsche Bank }, { id: 'bio', label: Bionorica }, { id: 'bcl', label: Berchtesgadener
Land
}, { id: 'mtz', label: Metzler }, { id: 'vbw', label: vbw }, { id: 'wby', label: Wirtschafts-
beirat Bayern
}, { id: 'rgong', label: Radio Gong 96.3 }, { id: 'mtvr', label: münchen.tv }, { id: 'ews', label: EWS }, ]; const FF = '"IBM Plex Sans", sans-serif'; type HomeCms = Record; const fallbackText = (value: unknown, fallback: string) => typeof value === 'string' && value.length > 0 ? value : fallback; const fallbackArray = (value: unknown, fallback: T[]) => Array.isArray(value) && value.length > 0 ? (value as T[]) : fallback; function Lines({ text }: { text: string }) { return <>{text.split('\n').map((line, i) => {i > 0 &&
}{line}
)}; } const DEFAULT_QUICK_CRITERIA = [ { label: 'Standort Bayern', desc: 'Sitz oder Betriebsstätte im Freistaat' }, { label: '50–1.500 Mitarbeiter', desc: 'Klassischer Mittelstand' }, { label: 'Min. 3 Geschäftsjahre', desc: 'Markterfahrung und Stabilität' }, { label: 'Privatwirtschaft', desc: 'Kein staatlicher Träger' }, { label: 'Familien- bzw. eigentümergeführt', desc: 'Ihr Unternehmen ist inhabergeführt' }, ]; const DEFAULT_INTRO_STATS = [['20+', 'Jahre Exzellenz'], ['0 €', 'Teilnahmegebühr'], ['100%', 'Unabhängig']]; const DEFAULT_BENEFITS = [ { num: '01', title: 'Netzwerk', desc: 'Direkter Zugang zu Entscheidern aus Staatsregierung, Wirtschaft und Wissenschaft.' }, { num: '02', title: 'Sichtbarkeit', desc: 'Breite mediale Begleitung durch TV-, Radio- und Print-Partner bayernweit.' }, { num: '03', title: 'Bestätigung', desc: 'Ein unabhängiger Qualitätsnachweis – das stärkste Siegel für Ihren Marktauftritt.' }, ]; const DEFAULT_APPLICATION_BENEFITS = [ { num: '01', label: 'Kostenfrei', desc: 'Ohne Teilnahmegebühr' }, { num: '02', label: 'Jury', desc: 'Aus Wissenschaft und Praxis' }, { num: '03', label: 'Sichtbarkeit', desc: 'Medial bayernweit' }, { num: '04', label: 'Gala', desc: 'Verleihung München' }, ]; // ─── Status Phase Slider ──────────────────────────────────────────────────── /** * 🔧 DEPLOYMENT CONFIG * Setze ACTIVE_PHASE je nach aktuellem Stand des BMP-Zyklus: * 0 = Bewerbungsphase offen * 1 = Auswertungsphase (Jury bewertet) * 2 = Nach der Preisverleihung (Erfolg) */ const ACTIVE_PHASE: 0 | 1 | 2 = 0; interface StatusPhase { num: string; tag: string; pulse: boolean; phase: string; headline: string; body: string; cta: { label: string; to: string } | null; accent: string; bg: string; glow: string; meta: string; } const STATUS_PHASES: StatusPhase[] = [ { num: '01', tag: 'JETZT OFFEN', pulse: true, phase: 'Bewerbungsphase 2026', headline: 'BEWERBEN SIE SICH JETZT.', body: 'Die Bewerbungsphase 2026 ist eröffnet – es ist noch nicht zu spät. Reichen Sie Ihre Unterlagen bis zum 30. Juni kostenlos ein und zeigen Sie, was den bayerischen Mittelstand ausmacht.', cta: { label: 'Jetzt kostenlos bewerben', to: '/teilnahme' }, accent: '#EFBF04', bg: '#020A1E', glow: 'rgba(239,191,4,0.14)', meta: 'Deadline: 30. Juni 2026', }, { num: '02', tag: 'IN AUSWERTUNG', pulse: true, phase: 'Auswertungsphase 2026', headline: 'DIE JURY BEWERTET GERADE.', body: 'Die Anmeldephase 2026 ist geschlossen. Unsere unabhängige Expertenjury aus Wissenschaft und Praxis sichtet und bewertet derzeit alle Einreichungen.', cta: null, accent: '#4A8FC9', bg: '#060D1C', glow: 'rgba(74,143,201,0.12)', meta: 'Ergebnis: August 2026', }, { num: '03', tag: 'ABGESCHLOSSEN', pulse: false, phase: 'Preisverleihung · Oktober 2026', headline: 'DER BMP 2026 WAR EIN ERFOLG.', body: 'Wir danken allen 247 Bewerberinnen und Bewerbern für Mut und Exzellenz. Drei außergewöhnliche Unternehmen wurden in München ausgezeichnet – ein unvergesslicher Abend.', cta: { label: 'Alle Preisträger ansehen', to: '/preistraeger' }, accent: '#EFBF04', bg: '#06090F', glow: 'rgba(239,191,4,0.08)', meta: 'Gala · Oktober 2026 · München', }, ]; function HomeWinnerCard({ winner }: { winner: any }) { const [hovered, setHovered] = useState(false); const isMobile = useIsMobile(); const staticWinner = WINNERS.find( (item) => String(item.id) === String(winner?.id) || item.slug === winner?.slug || item.name === winner?.title || item.name === winner?.name, ); const title = fallbackText(winner?.title, fallbackText(winner?.name, staticWinner?.name || 'Preisträger')); const imageSrc = mediaUrl(winner?.image, winner?.img || staticWinner?.img || '/images/gala-saal-overview.jpg'); const href = winner?.spaPath || (winner?.slug ? `/preistraeger/${winner.slug}` : staticWinner ? `/preistraeger/${staticWinner.slug}` : '/preistraeger'); return ( setHovered(true)} onMouseLeave={() => setHovered(false)} > {title}
{winner?.year || staticWinner?.year} · {winner?.awardType || winner?.type || staticWinner?.type}

{title}

{winner?.category || staticWinner?.category}

Detail →
); } const Home: React.FC = () => { const [showVideo, setShowVideo] = useState(false); const isMobile = useIsMobile(); const home = (useCmsRoute()?.doc?.home || {}) as HomeCms; const hero = home.hero || {}; const quickCheck = home.quickCheck || {}; const intro = home.intro || {}; const winnersSection = home.winners || {}; const benefits = home.benefits || {}; const application = home.application || {}; const videoModal = home.videoModal || {}; const cmsPreistraeger = useCmsCollection('preistraeger'); const selectedWinners = fallbackArray(winnersSection.featured, []); const selectedWinnerDocs = selectedWinners .map((selected: any) => { const selectedID = typeof selected === 'object' ? selected.id : selected const listDoc = cmsPreistraeger.find((doc: any) => String(doc.id) === String(selectedID)) return listDoc || (typeof selected === 'object' ? selected : undefined) }) .filter(Boolean) const homeWinners = selectedWinnerDocs.length ? selectedWinnerDocs : (cmsPreistraeger.length ? cmsPreistraeger : WINNERS).filter((w: any) => Number(w.year) === 2025).slice(0, 8); const quickCriteria = fallbackArray(quickCheck.criteria, DEFAULT_QUICK_CRITERIA); const introStats = fallbackArray( intro.stats, DEFAULT_INTRO_STATS.map(([value, label]) => ({ value, label })), ); const benefitItems = fallbackArray(benefits.items, DEFAULT_BENEFITS); const applicationBenefits = fallbackArray(application.benefits, DEFAULT_APPLICATION_BENEFITS); return (
{/* Hero Section */}
{mediaAlt(hero.backgroundImage,
{fallbackText(hero.badge, 'Bewerbungsphase 2026 geschlossen')}

{fallbackText(hero.headingLine1, 'BAYERNS BESTE')}
{fallbackText(hero.headingAccent, 'MITTELSTÄNDLER.')}

{fallbackText(hero.description, 'Der Bayerische Mittelstandspreis würdigt herausragende Leistungen – von Innovation über Nachhaltigkeit bis hin zur Exzellenz.')}

{ (e.currentTarget as HTMLElement).style.background = '#FFD130'; (e.currentTarget as HTMLElement).style.boxShadow = '0 0 18px rgba(239,191,4,0.65), 0 0 40px rgba(239,191,4,0.3)'; }} onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = '#EFBF04'; (e.currentTarget as HTMLElement).style.boxShadow = 'none'; }} > {fallbackText(hero.primaryCta?.label, 'Jetzt kostenlos bewerben')}
{ (e.currentTarget as HTMLElement).style.borderColor = '#EFBF04'; (e.currentTarget as HTMLElement).style.color = '#EFBF04'; }} onMouseLeave={e => { (e.currentTarget as HTMLElement).style.borderColor = 'rgba(255,255,255,0.35)'; (e.currentTarget as HTMLElement).style.color = 'rgba(255,255,255,0.85)'; }} > {fallbackText(hero.secondaryCta?.label, 'Mitglied werden')}
{/* Partner Bar */}
{/* Left: label – stays put */} {fallbackText(hero.partnersLabel, 'Unsere Partner')} {/* Right: ticker – fixed window, exactly 4 logos wide */}
partner.label ? partner : { id: partner.id || partner.name, label: {partner.name} })} />
{/* Schnell-Check Section */}
{/* Left (desktop) / Bottom (mobile) – text block (light bg, dark text) */}
{/* Eyebrow + heading – desktop only (on mobile these are overlaid on the image) */} {!isMobile && ( <> {fallbackText(quickCheck.eyebrow, 'Schnell-Check')}

)}

{fallbackText(quickCheck.body, 'Der Bayerische Mittelstandspreis richtet sich an inhabergeführte KMU im Freistaat. Fünf Kriterien entscheiden, erfüllen Sie alle fünf, steht Ihrer Bewerbung nichts im Weg.')}

{/* Criteria list */}
{quickCriteria.map((item, i) => (
{item.label}
{item.desc}
))}

{fallbackText(quickCheck.note, 'Auch ein Verbund bzw. eine Gemeinschaft von mittelständischen Unternehmen oder von mittelständischen Unternehmen und Organisationen/Institutionen mit Schwerpunkt in Bayern kann teilnehmen.')}

{ (e.currentTarget as HTMLElement).style.background = '#FFD130'; (e.currentTarget as HTMLElement).style.boxShadow = '0 0 18px rgba(239,191,4,0.65), 0 0 40px rgba(239,191,4,0.3)'; }} onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = '#EFBF04'; (e.currentTarget as HTMLElement).style.boxShadow = 'none'; }} > {fallbackText(quickCheck.cta?.label, 'Ihr Weg zum Preis')}
{/* Right (desktop) / Top (mobile) – image; on mobile the heading is overlaid here */}
{mediaAlt(quickCheck.image, {/* Overlay: mobile = navy shadow bottom-left (for the heading); desktop = leftward fade into text bg */}
{/* Heading overlay – mobile only */} {isMobile && (
{fallbackText(quickCheck.eyebrow, 'Schnell-Check')}

)} {/* Gold accent line – bottom edge */}
{/* Intro Section – editorial split, no radius, no floating badge */}
{/* Left – full-bleed image with stats overlay (+ heading on mobile) */}
{mediaAlt(intro.image, {/* Dark overlay */}
{/* Heading overlay – mobile only (bottom-left) */} {isMobile && (
{fallbackText(intro.eyebrow, 'Ein Gewinn für alle')}

)} {/* Stats bottom-left – desktop only (mobile shows them below the image) */} {!isMobile && (
{introStats.map(({ value: v, label: l }) => (
{v}
{l}
))}
)}
{/* Right – editorial text */}
{!isMobile && ( <> {fallbackText(intro.eyebrow, 'Ein Gewinn für alle')}

)} {/* Stats row – mobile only, below the image */} {isMobile && (
{introStats.map(({ value: v, label: l }) => (
{v}
{l}
))}
)}
{fallbackText(intro.quote, '„Ein Unternehmen zu gründen erfordert nicht allein spezielle Fähigkeiten. Es erfordert Persönlichkeit!“')}

{fallbackText(intro.body, 'Wir suchen Vorbilder, die sich trotz aller Risiken nicht scheuen, Visionen in Businesspläne und Ideen in Unternehmungen zu verwandeln, und das mit großem persönlichen Einsatz und Verantwortung für Ihre Mitarbeiter. Seit vielen Jahren würdigen wir herausragende unternehmerische Leistungen im Freistaat.')}

{ (e.currentTarget as HTMLElement).style.background = '#FFD130'; (e.currentTarget as HTMLElement).style.boxShadow = '0 0 18px rgba(239,191,4,0.65), 0 0 40px rgba(239,191,4,0.3)'; }} onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = '#EFBF04'; (e.currentTarget as HTMLElement).style.boxShadow = 'none'; }} > {fallbackText(intro.cta?.label, 'Mehr über den Preis')}
{/* Status Phase Slider */} {/* Winners Grid – neue Preisträger-Übersicht */}
{fallbackText(winnersSection.eyebrow, 'Success Stories')}

{fallbackText(winnersSection.cta?.label, 'Alle Preisträger')}
{homeWinners.map((w: any) => ( ))}
{/* Testimonials Section */} {/* Benefits Section – editorial split */}
{/* Left – text on cream */}
{!isMobile && ( <> {fallbackText(benefits.eyebrow, 'Mehr als nur ein Preis')}

)} {/* Numbered rows – no cards, no shadows */}
{benefitItems.map((item, i) => (
(e.currentTarget.style.background = '#EAE7E6')} onMouseLeave={e => (e.currentTarget.style.background = 'transparent')} > {item.num}
{item.title}
{item.desc}
))}
{/* Right – full-bleed photo (+ heading on mobile) */}
{mediaAlt(benefits.image,
{/* Heading overlay – mobile only (bottom-left) */} {isMobile && (
{fallbackText(benefits.eyebrow, 'Mehr als nur ein Preis')}

)} {/* Bottom-left label – desktop only */} {!isMobile && (
{fallbackText(benefits.imageLabel, 'BMP Gala-Netzwerk')}
)}
{/* CTA Section – with embedded form */}
{/* Subtle radial glow behind left copy */}
{/* Left – pitch copy */}
{fallbackText(application.eyebrow, 'Chance ergreifen')}

{fallbackText(application.body, 'Werden Sie Teil der Wall of Fame des bayerischen Mittelstands – vollständig kostenfrei.')}

{/* Benefit rows */}
{applicationBenefits.map(item => (
{item.num}
{item.label} {item.desc}
))}
{/* Divider */} {!isMobile &&
} {/* Right – gold premium panel */}
{/* Premium award crosshatch pattern */} {/* Inner vignette – edges slightly deeper gold */}
{/* Award ceremony photo */} {!isMobile && (
{mediaAlt(application.awardImage, {/* Blend photo into gold panel */}
{fallbackText(application.awardCaption, 'Preisverleihung 2025')}
)} {/* Form area */}
{fallbackText(application.formEyebrow, 'Direktbewerbung 2026')}

{fallbackText(application.formTitle, 'Kostenlos bewerben')}

{/* Footnote row */}
{fallbackText(application.footnote, 'Kostenlos und unverbindlich –')} {fallbackText(application.footnoteStrong, 'keine Teilnahmegebühr')}
{/* Video Modal */} {showVideo && (

{fallbackText(videoModal.title, 'Video-Player Platzhalter')}

{fallbackText(videoModal.description, 'Hier würde das Image-Video des BMP geladen werden.')}

)}
); }; // ─── StatusSlider ───────────────────────────────────────────────────────────── function StatusSlider({ data }: { data?: HomeCms }) { const isMobile = useIsMobile(); const phases = fallbackArray(data?.phases, STATUS_PHASES).map((phase: any, i) => { const fallbackPhase = STATUS_PHASES[i] const cta = phase?.cta?.label ? { label: phase.cta.label, to: phase.cta.to || phase.cta.url || fallbackPhase?.cta?.to || '/' } : fallbackPhase?.cta const membershipCta = phase?.membershipCta?.label ? { label: phase.membershipCta.label, to: phase.membershipCta.to || phase.membershipCta.url || '/mitglied-werden' } : undefined return { ...fallbackPhase, ...phase, cta, membershipCta } }); const configuredActive = data?.activePhase !== undefined && data?.activePhase !== null ? Number(data.activePhase) : ACTIVE_PHASE; const active = Math.max(0, Math.min(phases.length - 1, Number.isFinite(configuredActive) ? configuredActive : ACTIVE_PHASE)); const phase = phases[active]; return (
); } // ─── StatusSlideCard ────────────────────────────────────────────────────────── function StatusSlideCard({ phase, isMobile, noActionLabel }: { phase: StatusPhase & HomeCms; isMobile: boolean; noActionLabel: string }) { return (
{/* Left content */}
{/* Status badge + phase label */}
{phase.pulse && } {phase.tag}
{phase.phase}
{/* Headline + body + CTA */}

{phase.headline}

{phase.body}

{phase.cta ? ( e.stopPropagation()} style={{ fontFamily: FF, fontSize: 14, fontWeight: 700, letterSpacing: '0.12em', textTransform: 'uppercase', color: '#101828', background: phase.accent, padding: '14px 32px', textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 10, transition: 'opacity 0.2s' }} onMouseEnter={e => ((e.currentTarget as HTMLElement).style.opacity = '0.85')} onMouseLeave={e => ((e.currentTarget as HTMLElement).style.opacity = '1')} > {phase.cta.label} ) : (
{noActionLabel}
)}
{/* Meta */}
{phase.meta}
{/* Right visual panel */} {!isMobile &&
{phase.num !== '03' ? ( /* Concentric rings for active phases */
{([0, 20, 44] as const).map((inset, i) => (
))}
{phase.num}
) : ( /* Success stats */
{fallbackText(phase.successApplications, '247')}
Bewerbungen
{fallbackText(phase.successWinners, '3')}
Preisträger
)} {/* Membership CTA – for active phases only */} {phase.num !== '03' && (
e.stopPropagation()} style={{ fontFamily: FF, fontSize: 10, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: phase.accent, border: `1.5px solid ${phase.accent}55`, background: 'transparent', textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 8, padding: '11px 22px', transition: 'border-color 0.2s, color 0.2s', }} onMouseEnter={e => { (e.currentTarget as HTMLElement).style.borderColor = phase.accent; }} onMouseLeave={e => { (e.currentTarget as HTMLElement).style.borderColor = `${phase.accent}55`; }} > {fallbackText(phase.membershipCta?.label, 'Mitglied werden')}
)}
}
); } export default Home;