From 78af786a5236b158c634147a1fab3acb10efd80a Mon Sep 17 00:00:00 2001 From: syntaxbullet Date: Mon, 22 Jun 2026 12:51:51 +0200 Subject: [PATCH] feat: manage about highlight fallback copy via payload --- src/collections/Pages/aboutFields.ts | 10 +++++++ src/payload-types.ts | 12 +++++++++ src/spa/aboutContent.ts | 5 ++++ src/spa/pages/About.tsx | 39 ++++++++++++++++++++-------- 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/collections/Pages/aboutFields.ts b/src/collections/Pages/aboutFields.ts index 2d86ddf..83b41b2 100644 --- a/src/collections/Pages/aboutFields.ts +++ b/src/collections/Pages/aboutFields.ts @@ -134,6 +134,16 @@ export const aboutFields: Field[] = [ textarea('heading', 'Heading', aboutContent.highlights.heading), ctaGroup('cta', 'CTA', aboutContent.highlights.cta.label, aboutContent.highlights.cta.url), text('hoverLabel', 'Card hover label', aboutContent.highlights.hoverLabel), + { + name: 'fallbackWinner', + label: 'Fallback winner text', + type: 'group', + fields: [ + text('name', 'Name fallback', aboutContent.highlights.fallbackWinner.name), + text('category', 'Category fallback', aboutContent.highlights.fallbackWinner.category), + text('awardType', 'Award type fallback', aboutContent.highlights.fallbackWinner.awardType), + ], + }, { name: 'year', label: 'Fallback winner year', diff --git a/src/payload-types.ts b/src/payload-types.ts index f8a4c1d..9151e58 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -1230,6 +1230,11 @@ export interface Page { url?: string | null; }; hoverLabel?: string | null; + fallbackWinner?: { + name?: string | null; + category?: string | null; + awardType?: string | null; + }; year?: number | null; /** * Choose up to 8 Preisträger to show. If empty, the frontend falls back to winners from the selected year. @@ -4169,6 +4174,13 @@ export interface PagesSelect { url?: T; }; hoverLabel?: T; + fallbackWinner?: + | T + | { + name?: T; + category?: T; + awardType?: T; + }; year?: T; selectedWinners?: T; }; diff --git a/src/spa/aboutContent.ts b/src/spa/aboutContent.ts index 94fee6e..d1194c7 100644 --- a/src/spa/aboutContent.ts +++ b/src/spa/aboutContent.ts @@ -50,6 +50,11 @@ export const aboutContent = { cta: { label: 'Alle Preisträger', url: '/preistraeger' }, hoverLabel: 'Detail →', year: 2025, + fallbackWinner: { + name: 'Preisträger', + category: 'Preisträger', + awardType: 'Auszeichnung', + }, selectedWinners: [], }, testimonials: testimonialsContent, diff --git a/src/spa/pages/About.tsx b/src/spa/pages/About.tsx index 5bb443b..22b2274 100644 --- a/src/spa/pages/About.tsx +++ b/src/spa/pages/About.tsx @@ -21,7 +21,11 @@ type AboutCms = Partial & { hero?: Partial & { backgroundImage?: unknown } prize?: Partial & { image?: unknown } mittelstand?: Partial & { image?: unknown } - highlights?: Partial & { fallbackImage?: unknown; selectedWinners?: unknown[] | null } + highlights?: Partial & { + fallbackImage?: unknown + fallbackWinner?: Partial + selectedWinners?: unknown[] | null + } } type TextRow = { text?: string | null } @@ -63,15 +67,19 @@ function HighlightedText({ text, highlight }: { text: string; highlight: string ) } -const normalizeWinner = (doc: CmsRouteDoc | undefined, fallbackImage: string): Winner | undefined => { +const normalizeWinner = ( + doc: CmsRouteDoc | undefined, + fallbackImage: string, + fallbackWinner: typeof aboutContent.highlights.fallbackWinner, +): Winner | undefined => { if (!doc) return undefined return { id: String(doc.id), slug: String(doc.slug || ''), - name: String(doc.title || 'Preisträger'), - category: String(doc.category || 'Preisträger'), + name: String(doc.title || fallbackWinner.name), + category: String(doc.category || fallbackWinner.category), year: Number(doc.year || aboutContent.highlights.year), - type: String(doc.awardType || 'Auszeichnung'), + type: String(doc.awardType || fallbackWinner.awardType), img: mediaUrl(doc.image, fallbackImage), shortDesc: String(doc.shortDesc || doc.description || doc.meta?.description || ''), longDesc: String(doc.longDesc || doc.description || doc.meta?.description || ''), @@ -85,10 +93,15 @@ const normalizeWinner = (doc: CmsRouteDoc | undefined, fallbackImage: string): W } } -const winnerFromRelationship = (entry: unknown, allDocs: CmsRouteDoc[], fallbackImage: string) => { - if (entry && typeof entry === 'object') return normalizeWinner(entry as CmsRouteDoc, fallbackImage) +const winnerFromRelationship = ( + entry: unknown, + allDocs: CmsRouteDoc[], + fallbackImage: string, + fallbackWinner: typeof aboutContent.highlights.fallbackWinner, +) => { + if (entry && typeof entry === 'object') return normalizeWinner(entry as CmsRouteDoc, fallbackImage, fallbackWinner) const doc = allDocs.find((item) => String(item.id) === String(entry)) - return normalizeWinner(doc, fallbackImage) + return normalizeWinner(doc, fallbackImage, fallbackWinner) } const About: React.FC = () => { @@ -108,10 +121,14 @@ const About: React.FC = () => { highlights.fallbackImage, `/images/${aboutContent.highlights.fallbackImageFilename}`, ) + const highlightFallbackWinner = useMemo( + () => ({ ...aboutContent.highlights.fallbackWinner, ...(highlights.fallbackWinner || {}) }), + [highlights], + ) const highlightWinners = useMemo(() => { const selected = fallbackArray(highlights.selectedWinners, []) - .map((entry) => winnerFromRelationship(entry, cmsWinners, highlightFallbackImage)) + .map((entry) => winnerFromRelationship(entry, cmsWinners, highlightFallbackImage, highlightFallbackWinner)) .filter((winner): winner is Winner => Boolean(winner)) if (selected.length) return selected.slice(0, 8) @@ -120,12 +137,12 @@ const About: React.FC = () => { Boolean(winner) && winner?.year === Number(highlights.year || aboutContent.highlights.year) const cmsByYear = cmsWinners - .map((winner) => normalizeWinner(winner, highlightFallbackImage)) + .map((winner) => normalizeWinner(winner, highlightFallbackImage, highlightFallbackWinner)) .filter(isWinnerFromYear) .slice(0, 8) return cmsByYear.length ? cmsByYear : FALLBACK_HIGHLIGHTS - }, [cmsWinners, highlightFallbackImage, highlights]) + }, [cmsWinners, highlightFallbackImage, highlightFallbackWinner, highlights]) return (