diff --git a/src/collections/Pages/preistraegerIndexFields.ts b/src/collections/Pages/preistraegerIndexFields.ts index 5c8ba8e..7fea11f 100644 --- a/src/collections/Pages/preistraegerIndexFields.ts +++ b/src/collections/Pages/preistraegerIndexFields.ts @@ -100,6 +100,18 @@ export const preistraegerIndexFields: Field[] = [ fields: [ uploadField('fallbackImage', 'Fallback card image', `Current frontend fallback image: /images/${preistraegerIndexContent.card.fallbackImageFilename}`), text('hoverLabel', 'Hover label', preistraegerIndexContent.card.hoverLabel), + { + name: 'fallbackWinner', + label: 'Missing winner field fallbacks', + type: 'group', + fields: [ + text('name', 'Name', preistraegerIndexContent.card.fallbackWinner.name), + text('category', 'Category', preistraegerIndexContent.card.fallbackWinner.category), + text('awardType', 'Award type', preistraegerIndexContent.card.fallbackWinner.awardType), + text('location', 'Location', preistraegerIndexContent.card.fallbackWinner.location), + text('industry', 'Industry', preistraegerIndexContent.card.fallbackWinner.industry), + ], + }, ], }, { diff --git a/src/collections/Preistraeger.ts b/src/collections/Preistraeger.ts index 739db9f..0ab25bf 100644 --- a/src/collections/Preistraeger.ts +++ b/src/collections/Preistraeger.ts @@ -138,6 +138,22 @@ export const Preistraeger: CollectionConfig = { { name: 'label', type: 'text', label: 'Label', defaultValue: preistraegerDetailContent.breadcrumb.label }, ], }, + { + name: 'fallbackWinner', + label: 'Missing winner field fallbacks', + type: 'group', + fields: [ + { name: 'name', type: 'text', defaultValue: preistraegerDetailContent.fallbackWinner.name }, + { name: 'category', type: 'text', defaultValue: preistraegerDetailContent.fallbackWinner.category }, + { name: 'awardType', type: 'text', defaultValue: preistraegerDetailContent.fallbackWinner.awardType }, + { name: 'longDesc', type: 'textarea', defaultValue: preistraegerDetailContent.fallbackWinner.longDesc }, + { name: 'quote', type: 'textarea', defaultValue: preistraegerDetailContent.fallbackWinner.quote }, + { name: 'quotePerson', type: 'text', defaultValue: preistraegerDetailContent.fallbackWinner.quotePerson }, + { name: 'quoteRole', type: 'text', defaultValue: preistraegerDetailContent.fallbackWinner.quoteRole }, + { name: 'location', type: 'text', defaultValue: preistraegerDetailContent.fallbackWinner.location }, + { name: 'industry', type: 'text', defaultValue: preistraegerDetailContent.fallbackWinner.industry }, + ], + }, { name: 'sections', label: 'Section copy', diff --git a/src/payload-types.ts b/src/payload-types.ts index 73cea34..f8a4c1d 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -1463,6 +1463,13 @@ export interface Page { */ fallbackImage?: (number | null) | Media; hoverLabel?: string | null; + fallbackWinner?: { + name?: string | null; + category?: string | null; + awardType?: string | null; + location?: string | null; + industry?: string | null; + }; }; /** * Bottom application and membership CTA. @@ -2782,6 +2789,17 @@ export interface Preistraeger { url?: string | null; label?: string | null; }; + fallbackWinner?: { + name?: string | null; + category?: string | null; + awardType?: string | null; + longDesc?: string | null; + quote?: string | null; + quotePerson?: string | null; + quoteRole?: string | null; + location?: string | null; + industry?: string | null; + }; sections?: { companyHeading?: string | null; juryHeading?: string | null; @@ -4336,6 +4354,15 @@ export interface PagesSelect { | { fallbackImage?: T; hoverLabel?: T; + fallbackWinner?: + | T + | { + name?: T; + category?: T; + awardType?: T; + location?: T; + industry?: T; + }; }; cta?: | T @@ -5243,6 +5270,19 @@ export interface PreistraegerSelect { url?: T; label?: T; }; + fallbackWinner?: + | T + | { + name?: T; + category?: T; + awardType?: T; + longDesc?: T; + quote?: T; + quotePerson?: T; + quoteRole?: T; + location?: T; + industry?: T; + }; sections?: | T | { diff --git a/src/spa/pages/Preistraeger.tsx b/src/spa/pages/Preistraeger.tsx index e3596a6..81b9101 100644 --- a/src/spa/pages/Preistraeger.tsx +++ b/src/spa/pages/Preistraeger.tsx @@ -22,21 +22,25 @@ type PreistraegerIndexCms = Partial & { const fallbackText = (value: unknown, fallback: string) => typeof value === 'string' && value.length > 0 ? value : fallback; -const normalizeWinner = (doc: CmsRouteDoc, fallbackImage: string): Winner => ({ +const normalizeWinner = ( + doc: CmsRouteDoc, + fallbackImage: string, + fallbackWinner: typeof preistraegerIndexContent.card.fallbackWinner, +): Winner => ({ 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 || preistraegerIndexContent.card.fallbackWinner.name), + category: String(doc.category || fallbackWinner.category || preistraegerIndexContent.card.fallbackWinner.category), year: Number(doc.year || new Date().getFullYear()), - type: String(doc.awardType || 'Auszeichnung'), + type: String(doc.awardType || fallbackWinner.awardType || preistraegerIndexContent.card.fallbackWinner.awardType), img: docImageUrl(doc, fallbackImage), shortDesc: String(doc.shortDesc || doc.description || doc.meta?.description || ''), longDesc: String(doc.longDesc || doc.description || doc.meta?.description || ''), quote: String(doc.quote || ''), quotePerson: String(doc.quotePerson || ''), quoteRole: String(doc.quoteRole || ''), - location: String(doc.location || 'Bayern'), - industry: String(doc.industry || 'Mittelstand'), + location: String(doc.location || fallbackWinner.location || preistraegerIndexContent.card.fallbackWinner.location), + industry: String(doc.industry || fallbackWinner.industry || preistraegerIndexContent.card.fallbackWinner.industry), website: String(doc.website || '#'), hasMedia: Boolean(doc.hasMedia), }); @@ -60,9 +64,10 @@ export default function Preistraeger() { [card], ); const winners = useMemo(() => { - if (cmsPreistraeger.length) return cmsPreistraeger.map((doc) => normalizeWinner(doc, cardFallbackImage)).filter((winner) => winner.slug); + const fallbackWinner = card.fallbackWinner || preistraegerIndexContent.card.fallbackWinner; + if (cmsPreistraeger.length) return cmsPreistraeger.map((doc) => normalizeWinner(doc, cardFallbackImage, fallbackWinner)).filter((winner) => winner.slug); return WINNERS; - }, [cardFallbackImage, cmsPreistraeger]); + }, [card, cardFallbackImage, cmsPreistraeger]); const years = useMemo(() => [...new Set(winners.map((winner) => winner.year))].sort((a, b) => b - a), [winners]); const categories = useMemo(() => [...new Set(winners.map((winner) => winner.category))].sort((a, b) => a.localeCompare(b, 'de')), [winners]); const [activeYear, setActiveYear] = useState(undefined); diff --git a/src/spa/pages/PreistraegerDetail.tsx b/src/spa/pages/PreistraegerDetail.tsx index 15fcb8e..26e94a2 100644 --- a/src/spa/pages/PreistraegerDetail.tsx +++ b/src/spa/pages/PreistraegerDetail.tsx @@ -31,22 +31,23 @@ export default function PreistraegerDetail() { ...preistraegerDetailContent, ...((cmsWinner?.detailPage || {}) as PreistraegerDetailCms), } as PreistraegerDetailCms; + const fallbackWinner = cmsDetail.fallbackWinner || preistraegerDetailContent.fallbackWinner; const winnerFallbackImage = mediaUrl(cmsDetail.fallbackImage, `/images/${preistraegerDetailContent.fallbackImageFilename}`); const winner = cmsWinner ? { id: String(cmsWinner.id), slug: String(cmsWinner.slug || slug), - name: String(cmsWinner.title || 'Preisträger'), - category: String(cmsWinner.category || 'Preisträger'), + name: String(cmsWinner.title || fallbackWinner.name || preistraegerDetailContent.fallbackWinner.name), + category: String(cmsWinner.category || fallbackWinner.category || preistraegerDetailContent.fallbackWinner.category), year: Number(cmsWinner.year || new Date().getFullYear()), - type: String(cmsWinner.awardType || 'Auszeichnung'), + type: String(cmsWinner.awardType || fallbackWinner.awardType || preistraegerDetailContent.fallbackWinner.awardType), img: docImageUrl(cmsWinner, winnerFallbackImage), shortDesc: String(cmsWinner.shortDesc || cmsWinner.description || cmsWinner.meta?.description || ''), - longDesc: String(cmsWinner.longDesc || cmsWinner.description || cmsWinner.meta?.description || 'Dieser Preisträger wird aus Payload CMS geladen.'), - quote: String(cmsWinner.quote || 'Diese Erfolgsgeschichte wird aktuell in Payload CMS gepflegt.'), - quotePerson: String(cmsWinner.quotePerson || cmsWinner.title || 'BMP'), - quoteRole: String(cmsWinner.quoteRole || 'Preisträger'), - location: String(cmsWinner.location || 'Bayern'), - industry: String(cmsWinner.industry || 'Mittelstand'), + longDesc: String(cmsWinner.longDesc || cmsWinner.description || cmsWinner.meta?.description || fallbackWinner.longDesc || preistraegerDetailContent.fallbackWinner.longDesc), + quote: String(cmsWinner.quote || fallbackWinner.quote || preistraegerDetailContent.fallbackWinner.quote), + quotePerson: String(cmsWinner.quotePerson || cmsWinner.title || fallbackWinner.quotePerson || preistraegerDetailContent.fallbackWinner.quotePerson), + quoteRole: String(cmsWinner.quoteRole || fallbackWinner.quoteRole || preistraegerDetailContent.fallbackWinner.quoteRole), + location: String(cmsWinner.location || fallbackWinner.location || preistraegerDetailContent.fallbackWinner.location), + industry: String(cmsWinner.industry || fallbackWinner.industry || preistraegerDetailContent.fallbackWinner.industry), website: String(cmsWinner.website || '#'), hasMedia: Boolean(cmsWinner.hasMedia), detailPage: (cmsWinner.detailPage || {}) as PreistraegerDetailCms, diff --git a/src/spa/preistraegerDetailContent.ts b/src/spa/preistraegerDetailContent.ts index 27219d2..50caaba 100644 --- a/src/spa/preistraegerDetailContent.ts +++ b/src/spa/preistraegerDetailContent.ts @@ -5,6 +5,17 @@ export const preistraegerDetailContent = { url: '/preistraeger', label: 'Preisträger:innen', }, + fallbackWinner: { + name: 'Preisträger', + category: 'Preisträger', + awardType: 'Auszeichnung', + longDesc: 'Dieser Preisträger wird aus Payload CMS geladen.', + quote: 'Diese Erfolgsgeschichte wird aktuell in Payload CMS gepflegt.', + quotePerson: 'BMP', + quoteRole: 'Preisträger', + location: 'Bayern', + industry: 'Mittelstand', + }, sections: { companyHeading: 'Über das Unternehmen', juryHeading: 'Warum ausgezeichnet?', diff --git a/src/spa/preistraegerIndexContent.ts b/src/spa/preistraegerIndexContent.ts index 1375e36..8419d34 100644 --- a/src/spa/preistraegerIndexContent.ts +++ b/src/spa/preistraegerIndexContent.ts @@ -23,6 +23,13 @@ export const preistraegerIndexContent = { card: { fallbackImageFilename: 'gala-saal-overview.jpg', hoverLabel: 'Mehr erfahren', + fallbackWinner: { + name: 'Preisträger', + category: 'Preisträger', + awardType: 'Auszeichnung', + location: 'Bayern', + industry: 'Mittelstand', + }, }, cta: { text: 'Werden Sie der nächste Preisträger.',