fix(home): honor phase headline line breaks

This commit is contained in:
syntaxbullet
2026-07-31 17:24:36 +02:00
parent adda9ddbd0
commit f465839af0
6 changed files with 112 additions and 9 deletions

View File

@@ -26,7 +26,7 @@ const phaseFields: Field[] = [
text('tag', 'Badge'),
{ name: 'pulse', label: 'Show pulse dot', type: 'checkbox', defaultValue: true },
text('phase', 'Phase label'),
text('headline', 'Headline'),
textarea('headline', 'Headline'),
textarea('body', 'Body copy'),
{ name: 'cta', label: 'Primary CTA', type: 'group', fields: linkGroup() },
text('accent', 'Accent color'),

View File

@@ -0,0 +1,23 @@
import { type MigrateDownArgs, type MigrateUpArgs, sql } from '@payloadcms/db-sqlite'
const literal = (value: string) => `'${value.replace(/'/g, "''")}'`
const previousHeadline = 'DER BMP 2026 WAR EIN ERFOLG.'
const unbrokenHeadline = 'Ein weiteres erfolgreiches Jahr'
const splitHeadline = 'Ein weiteres\nerfolgreiches Jahr'
export async function up({ db, payload: _payload, req: _req }: MigrateUpArgs): Promise<void> {
await db.run(
sql.raw(
`UPDATE application_phase_phases SET headline = ${literal(splitHeadline)} WHERE num = '03' AND headline IN (${literal(previousHeadline)}, ${literal(unbrokenHeadline)});`,
),
)
}
export async function down({ db, payload: _payload, req: _req }: MigrateDownArgs): Promise<void> {
await db.run(
sql.raw(
`UPDATE application_phase_phases SET headline = ${literal(previousHeadline)} WHERE num = '03' AND headline = ${literal(splitHeadline)};`,
),
)
}

View File

@@ -20,6 +20,7 @@ import * as migration_20260731_160000_focused_payload_cleanup from './20260731_1
import * as migration_20260731_170000_netzwerk_greeting_video from './20260731_170000_netzwerk_greeting_video';
import * as migration_20260731_180000_press_contact_image from './20260731_180000_press_contact_image';
import * as migration_20260731_190000_responsive_sponsor_hierarchy from './20260731_190000_responsive_sponsor_hierarchy';
import * as migration_20260731_200000_home_phase_headline_line_break from './20260731_200000_home_phase_headline_line_break';
export const migrations = [
{
@@ -132,4 +133,9 @@ export const migrations = [
down: migration_20260731_190000_responsive_sponsor_hierarchy.down,
name: '20260731_190000_responsive_sponsor_hierarchy',
},
{
up: migration_20260731_200000_home_phase_headline_line_break.up,
down: migration_20260731_200000_home_phase_headline_line_break.down,
name: '20260731_200000_home_phase_headline_line_break',
},
];

View File

@@ -70,7 +70,7 @@ export const defaultApplicationPhaseData: SpaApplicationPhaseData = {
tag: 'ABGESCHLOSSEN',
pulse: false,
phase: 'Preisverleihung · Oktober 2026',
headline: 'DER BMP 2026 WAR EIN ERFOLG.',
headline: 'Ein weiteres\nerfolgreiches Jahr',
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', url: '/preistraeger' },

View File

@@ -116,7 +116,7 @@ const isMembershipCta = (cta?: { label?: string; url?: string; to?: string } | n
cta?.label?.trim().toLowerCase() === 'mitglied werden';
function Lines({ text }: { text: string }) {
return <>{text.split('\n').map((line, i) => <React.Fragment key={`${line}-${i}`}>{i > 0 && <br />}{line}</React.Fragment>)}</>;
return <>{text.split(/\r?\n/).map((line, i) => <React.Fragment key={`${line}-${i}`}>{i > 0 && <br />}{line}</React.Fragment>)}</>;
}
function partnerLogos(partners: PartnerLogoData[]) {
@@ -542,7 +542,7 @@ const Home: React.FC = () => {
// ─── StatusSlider ─────────────────────────────────────────────────────────────
function StatusSlider({ data }: { data?: SpaApplicationPhaseData }) {
export function StatusSlider({ data }: { data?: SpaApplicationPhaseData }) {
const isMobile = useIsMobile();
if (!data?.phases?.length) return null;
@@ -568,11 +568,12 @@ function StatusSlider({ data }: { data?: SpaApplicationPhaseData }) {
return (
<section
data-testid="phase-section"
style={{
position: 'relative',
overflow: 'hidden',
height: isMobile ? 'auto' : 480,
minHeight: isMobile ? 360 : 'auto',
height: 'auto',
minHeight: isMobile ? 360 : 480,
}}
>
<StatusSlideCard
@@ -605,7 +606,7 @@ function StatusSlideCard({
<div
style={{
width: '100vw',
height: '100%',
minHeight: isMobile ? 360 : 480,
flexShrink: 0,
position: 'relative',
background: phase.bg,
@@ -629,8 +630,8 @@ function StatusSlideCard({
{/* Headline + body + CTA */}
<div>
<h2 className="type-page-title text-role-inverse" style={{ textTransform: 'uppercase', margin: '0 0 24px' }}>
{phase.headline}
<h2 className="type-page-title text-role-inverse" data-testid="phase-headline" style={{ textTransform: 'uppercase', margin: '0 0 24px' }}>
<Lines text={fallbackText(phase.headline, '')} />
</h2>
<p className="type-body text-role-inverse-secondary" style={{ marginBottom: 32, maxWidth: isMobile ? 520 : 760 }}>
{phase.body}