feat: update Preistraeger page to include a simple winner grid for 2023 and remove unused components
fix: change featured status for participation content and remove deprecated award card feat: add migration for new participation phase form fields and backfill existing data feat: create AwardsGridSection component for displaying awards with improved layout feat: implement NewsletterInterestForm component for newsletter sign-up with validation
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import { Link } from '@/spa/router';
|
||||
import { Trophy, ChevronRight, ArrowRight } from 'lucide-react';
|
||||
import { Trophy, ArrowRight } from 'lucide-react';
|
||||
import { WINNERS, type Winner } from '@/spa/data/winners';
|
||||
import { useCmsCollection, useCmsRoute, type CmsRouteDoc } from '@/spa/cmsRoute';
|
||||
import { docImageUrl, mediaAlt, mediaUrl } from '@/spa/cmsMediaField';
|
||||
@@ -14,6 +14,7 @@ const GOLD = '#EFBF04';
|
||||
const BORDER = '#D0D5DD';
|
||||
const GRAY = '#666666';
|
||||
const BG_ALT = '#E4E2E3';
|
||||
const SIMPLE_LIST_YEAR = 2023;
|
||||
|
||||
type PreistraegerIndexCms = Partial<typeof preistraegerIndexContent> & {
|
||||
hero?: Partial<typeof preistraegerIndexContent.hero> & { image?: unknown }
|
||||
@@ -69,6 +70,7 @@ export default function Preistraeger() {
|
||||
const selectedYear = activeYear ?? years[0] ?? new Date().getFullYear();
|
||||
|
||||
const filtered = useMemo(() => winners.filter(w => w.year === selectedYear), [selectedYear, winners]);
|
||||
const usesSimpleWinnerGrid = selectedYear === SIMPLE_LIST_YEAR;
|
||||
|
||||
return (
|
||||
<div style={{ background: '#fff', minHeight: '100vh' }}>
|
||||
@@ -129,6 +131,8 @@ export default function Preistraeger() {
|
||||
<div style={{ padding: isMobile ? '56px 24px' : '80px', textAlign: 'center', color: GRAY, fontFamily: FF }}>
|
||||
{fallbackText(empty.message, preistraegerIndexContent.empty.message)}
|
||||
</div>
|
||||
) : usesSimpleWinnerGrid ? (
|
||||
<SimpleWinnerGrid winners={filtered} />
|
||||
) : (
|
||||
<div style={{
|
||||
display: 'grid',
|
||||
@@ -165,38 +169,6 @@ export default function Preistraeger() {
|
||||
>
|
||||
{fallbackText(cta.primaryCta?.label, preistraegerIndexContent.cta.primaryCta.label)} <ArrowRight size={14} />
|
||||
</Link>
|
||||
<div style={{ marginTop: 20, display: 'flex', alignItems: 'center', justifyContent: isMobile ? 'center' : undefined, flexWrap: isMobile ? 'wrap' : 'nowrap', gap: 8 }}>
|
||||
<span style={{ width: 20, height: 1, background: 'rgba(239,191,4,0.3)', display: 'inline-block' }} />
|
||||
<span style={{ fontFamily: '"IBM Plex Sans", sans-serif', fontSize: 11, color: 'rgba(16,24,40,0.4)' }}>{fallbackText(cta.secondaryPrefix, preistraegerIndexContent.cta.secondaryPrefix)}</span>
|
||||
<Link
|
||||
to={fallbackText(cta.secondaryCta?.url, preistraegerIndexContent.cta.secondaryCta.url)}
|
||||
style={{
|
||||
fontFamily: '"IBM Plex Sans", sans-serif',
|
||||
fontSize: 11,
|
||||
fontWeight: 700,
|
||||
letterSpacing: '0.12em',
|
||||
textTransform: 'uppercase',
|
||||
color: 'rgba(239,191,4,0.7)',
|
||||
textDecoration: 'none',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
gap: 6,
|
||||
borderBottom: '1px solid rgba(239,191,4,0.3)',
|
||||
paddingBottom: 1,
|
||||
transition: 'color 0.15s, borderColor 0.15s',
|
||||
}}
|
||||
onMouseEnter={e => {
|
||||
(e.currentTarget as HTMLElement).style.color = '#EFBF04';
|
||||
(e.currentTarget as HTMLElement).style.borderBottomColor = '#EFBF04';
|
||||
}}
|
||||
onMouseLeave={e => {
|
||||
(e.currentTarget as HTMLElement).style.color = 'rgba(239,191,4,0.7)';
|
||||
(e.currentTarget as HTMLElement).style.borderBottomColor = 'rgba(239,191,4,0.3)';
|
||||
}}
|
||||
>
|
||||
{fallbackText(cta.secondaryCta?.label, preistraegerIndexContent.cta.secondaryCta.label)} <ChevronRight size={10} />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -257,3 +229,91 @@ function WinnerCard({ winner, hoverLabel }: { winner: Winner; hoverLabel: string
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
function SimpleWinnerGrid({ winners }: { winners: Winner[] }) {
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
background: '#F7F7F8',
|
||||
display: 'grid',
|
||||
gridTemplateColumns: isMobile ? '1fr' : 'repeat(3, minmax(0, 1fr))',
|
||||
gap: isMobile ? 12 : 16,
|
||||
padding: isMobile ? '24px' : '40px 80px 56px',
|
||||
}}>
|
||||
{winners.map(winner => (
|
||||
<SimpleWinnerCard key={winner.id} winner={winner} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function SimpleWinnerCard({ winner }: { winner: Winner }) {
|
||||
const isMobile = useIsMobile();
|
||||
const hasDescription = winner.shortDesc.trim().length > 0;
|
||||
|
||||
return (
|
||||
<article
|
||||
style={{
|
||||
background: '#fff',
|
||||
border: `1px solid ${BORDER}`,
|
||||
color: '#101828',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
minHeight: isMobile ? 0 : 220,
|
||||
padding: isMobile ? '20px' : '24px',
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', marginBottom: 18 }}>
|
||||
<span style={{
|
||||
color: GOLD,
|
||||
fontFamily: FF,
|
||||
fontSize: 12,
|
||||
fontWeight: 700,
|
||||
letterSpacing: '0.12em',
|
||||
textTransform: 'uppercase',
|
||||
}}>
|
||||
{winner.year} · {winner.type}
|
||||
</span>
|
||||
{winner.category ? (
|
||||
<span style={{
|
||||
border: `1px solid ${BORDER}`,
|
||||
color: GRAY,
|
||||
fontFamily: FF,
|
||||
fontSize: 12,
|
||||
fontWeight: 600,
|
||||
lineHeight: 1.2,
|
||||
padding: '5px 8px',
|
||||
}}>
|
||||
{winner.category}
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<h3 style={{
|
||||
color: NAVY,
|
||||
fontFamily: FF,
|
||||
fontSize: isMobile ? 20 : 22,
|
||||
fontWeight: 700,
|
||||
lineHeight: 1.18,
|
||||
margin: 0,
|
||||
overflowWrap: 'anywhere',
|
||||
}}>
|
||||
{winner.name}
|
||||
</h3>
|
||||
|
||||
{hasDescription ? (
|
||||
<p style={{
|
||||
color: GRAY,
|
||||
fontFamily: FF,
|
||||
fontSize: 15,
|
||||
lineHeight: 1.55,
|
||||
margin: '16px 0 0',
|
||||
overflowWrap: 'anywhere',
|
||||
}}>
|
||||
{winner.shortDesc}
|
||||
</p>
|
||||
) : null}
|
||||
</article>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user