feat: manage netzwerk page via payload

This commit is contained in:
syntaxbullet
2026-06-22 11:30:21 +02:00
parent a9283b2e46
commit c35e45499e
8 changed files with 1455 additions and 276 deletions

View File

@@ -14,6 +14,7 @@ import { datenschutzFields } from './datenschutzFields'
import { formularUploadFields } from './formularUploadFields'
import { homeFields } from './homeFields'
import { impressumFields } from './impressumFields'
import { netzwerkFields } from './netzwerkFields'
import { participationFields } from './participationFields'
import { preistraegerIndexFields } from './preistraegerIndexFields'
import { pressIndexFields } from './pressIndexFields'
@@ -102,6 +103,14 @@ const isFormularUploadPage = (_: unknown, siblingData?: { slug?: string; spaPath
return spaPath === '/formular-hochladen' || slug === 'formular-hochladen' || slug === 'upload' || title === 'formular hochladen'
}
const isNetzwerkPage = (_: unknown, siblingData?: { slug?: string; spaPath?: string; title?: string }) => {
const slug = siblingData?.slug
const spaPath = siblingData?.spaPath
const title = siblingData?.title?.toLowerCase()
return spaPath === '/netzwerk' || slug === 'netzwerk' || slug === 'network' || title === 'netzwerk' || title === 'network'
}
const isManagedSpaPage = (_: unknown, siblingData?: { slug?: string; spaPath?: string; title?: string }) =>
isHomePage(undefined, siblingData) ||
isContactPage(undefined, siblingData) ||
@@ -111,7 +120,8 @@ const isManagedSpaPage = (_: unknown, siblingData?: { slug?: string; spaPath?: s
isDatenschutzPage(undefined, siblingData) ||
isPreistraegerIndexPage(undefined, siblingData) ||
isPressIndexPage(undefined, siblingData) ||
isFormularUploadPage(undefined, siblingData)
isFormularUploadPage(undefined, siblingData) ||
isNetzwerkPage(undefined, siblingData)
export const Pages: CollectionConfig<'pages'> = {
slug: 'pages',
@@ -242,6 +252,13 @@ export const Pages: CollectionConfig<'pages'> = {
fields: formularUploadFields,
label: 'Formular Upload Page',
},
{
admin: {
condition: (data) => isNetzwerkPage(undefined, data),
},
fields: netzwerkFields,
label: 'Network Page',
},
{
name: 'meta',
label: 'SEO',

View File

@@ -0,0 +1,334 @@
import type { Field } from 'payload'
import { netzwerkContent } from '@/spa/netzwerkContent'
const text = (name: string, label: string, defaultValue?: string): Field => ({
name,
type: 'text',
label,
defaultValue,
})
const textarea = (name: string, label: string, defaultValue?: string): Field => ({
name,
type: 'textarea',
label,
defaultValue,
})
const numberField = (name: string, label: string, defaultValue?: number): Field => ({
name,
type: 'number',
label,
defaultValue,
})
const uploadField = (name: string, label: string, description?: string): Field => ({
name,
type: 'upload',
relationTo: 'media',
label,
admin: description ? { description } : undefined,
})
const sectionAdmin = (description: string) => ({
description,
initCollapsed: true,
})
const statFields: Field[] = [text('value', 'Value'), text('label', 'Label')]
const personFields: Field[] = [
text('image', 'Image URL'),
text('imageAlt', 'Image alt text'),
text('name', 'Name'),
text('titleLine1', 'Title line 1'),
text('titleLine2', 'Title line 2'),
text('institution', 'Institution'),
]
const juryMemberFields: Field[] = [
text('name', 'Name'),
text('role', 'Role'),
textarea('bio', 'Bio'),
text('image', 'Image URL'),
]
const rowFields: Field[] = [text('num', 'Number'), text('label', 'Label'), textarea('body', 'Body')]
const partnerFields: Field[] = [
text('id', 'Stable ID'),
text('name', 'Name'),
text('role', 'Role'),
numberField('tier', 'Tier'),
textarea('desc', 'Short description'),
textarea('fullDesc', 'Full modal description'),
{
name: 'logoKind',
label: 'Logo style',
type: 'select',
defaultValue: 'text',
options: [
{ label: 'Text', value: 'text' },
{ label: 'Serif text', value: 'serif' },
{ label: 'Badge', value: 'badge' },
{ label: 'Monogram', value: 'monogram' },
{ label: 'Dot mark', value: 'dot' },
{ label: 'Leaf mark', value: 'leaf' },
{ label: 'RSM blocks', value: 'rsm' },
{ label: 'Deutsche Bank mark', value: 'deutschebank' },
],
},
text('logoText', 'Logo text'),
text('logoSubtext', 'Logo subtext'),
text('logoColor', 'Logo color'),
text('industry', 'Industry'),
text('location', 'Location'),
text('website', 'Website'),
text('linkedin', 'LinkedIn URL'),
text('heroImg', 'Modal hero image URL'),
]
const benefitFields: Field[] = [text('num', 'Number'), text('label', 'Label'), text('sub', 'Subline')]
const packageFields: Field[] = [text('value', 'Value'), text('title', 'Title'), textarea('desc', 'Description')]
const formStepFields: Field[] = [text('label', 'Label')]
export const netzwerkFields: Field[] = [
{
name: 'netzwerk',
label: 'Network page content',
type: 'group',
admin: {
description: 'Edit the Netzwerk page sections, partner records, modal labels, and sponsoring form copy.',
},
fields: [
{
name: 'hero',
label: '01 · Hero',
type: 'group',
admin: sectionAdmin('Hero image, eyebrow, headline, highlight word, and intro copy.'),
fields: [
uploadField('image', 'Hero image', `Current frontend image: /images/${netzwerkContent.hero.imageFilename}`),
text('imageAlt', 'Image alt text', netzwerkContent.hero.imageAlt),
text('eyebrow', 'Eyebrow', netzwerkContent.hero.eyebrow),
textarea('heading', 'Heading', netzwerkContent.hero.heading),
text('highlight', 'Highlighted heading token', netzwerkContent.hero.highlight),
textarea('description', 'Description', netzwerkContent.hero.description),
],
},
{
name: 'patronage',
label: '02 · Patronage',
type: 'group',
admin: sectionAdmin('Patron cards and greeting quote.'),
fields: [
text('eyebrow', 'Eyebrow', netzwerkContent.patronage.eyebrow),
textarea('heading', 'Heading', netzwerkContent.patronage.heading),
text('description', 'Description', netzwerkContent.patronage.description),
{
name: 'people',
label: 'People',
type: 'array',
dbName: 'network_patrons',
defaultValue: netzwerkContent.patronage.people,
fields: personFields,
},
text('greetingEyebrow', 'Greeting eyebrow', netzwerkContent.patronage.greetingEyebrow),
text('greetingRole', 'Greeting role', netzwerkContent.patronage.greetingRole),
text('greetingName', 'Greeting name', netzwerkContent.patronage.greetingName),
text('greetingTitleLine1', 'Greeting title line 1', netzwerkContent.patronage.greetingTitleLine1),
text('greetingTitleLine2', 'Greeting title line 2', netzwerkContent.patronage.greetingTitleLine2),
textarea('greetingQuote', 'Greeting quote', netzwerkContent.patronage.greetingQuote),
text('greetingAttribution', 'Greeting attribution', netzwerkContent.patronage.greetingAttribution),
],
},
{
name: 'juryIntro',
label: '03 · Jury intro',
type: 'group',
admin: sectionAdmin('Editorial jury intro and stat strips.'),
fields: [
text('eyebrow', 'Eyebrow', netzwerkContent.juryIntro.eyebrow),
textarea('heading', 'Heading', netzwerkContent.juryIntro.heading),
textarea('description', 'Description', netzwerkContent.juryIntro.description),
{
name: 'stats',
label: 'Mobile stats',
type: 'array',
dbName: 'network_jury_stats',
defaultValue: netzwerkContent.juryIntro.stats,
fields: statFields,
},
{
name: 'desktopStats',
label: 'Desktop stats',
type: 'array',
dbName: 'network_jury_d_stats',
defaultValue: netzwerkContent.juryIntro.desktopStats,
fields: statFields,
},
],
},
{
name: 'jury',
label: '04 · Jury members',
type: 'group',
admin: sectionAdmin('Jury section heading, chair badge, members, and note.'),
fields: [
text('eyebrow', 'Eyebrow', netzwerkContent.jury.eyebrow),
textarea('heading', 'Heading', netzwerkContent.jury.heading),
textarea('description', 'Description', netzwerkContent.jury.description),
text('chairBadge', 'Chair badge', netzwerkContent.jury.chairBadge),
textarea('note', 'Note', netzwerkContent.jury.note),
{
name: 'members',
label: 'Members',
type: 'array',
dbName: 'network_jury',
defaultValue: netzwerkContent.jury.members,
fields: juryMemberFields,
},
],
},
{
name: 'expertise',
label: '05 · Expertise',
type: 'group',
admin: sectionAdmin('Evaluation process rows and quote.'),
fields: [
text('eyebrow', 'Eyebrow', netzwerkContent.expertise.eyebrow),
textarea('heading', 'Heading', netzwerkContent.expertise.heading),
textarea('quote', 'Quote', netzwerkContent.expertise.quote),
text('quoteAttribution', 'Quote attribution', netzwerkContent.expertise.quoteAttribution),
{
name: 'rows',
label: 'Process rows',
type: 'array',
dbName: 'network_eval',
defaultValue: netzwerkContent.expertise.rows,
fields: rowFields,
},
],
},
{
name: 'partners',
label: '06 · Partners',
type: 'group',
admin: sectionAdmin('Partner section, tier labels, partner records, and modal labels.'),
fields: [
text('eyebrow', 'Eyebrow', netzwerkContent.partners.eyebrow),
textarea('heading', 'Heading', netzwerkContent.partners.heading),
textarea('description', 'Description', netzwerkContent.partners.description),
text('detailLabel', 'Detail label', netzwerkContent.partners.detailLabel),
text('premiumLabel', 'Premium label', netzwerkContent.partners.premiumLabel),
{
name: 'tiers',
label: 'Tiers',
type: 'array',
dbName: 'network_tiers',
defaultValue: netzwerkContent.partners.tiers,
fields: [numberField('tier', 'Tier'), text('label', 'Label'), text('note', 'Note')],
},
{
name: 'modal',
label: 'Modal labels',
type: 'group',
fields: [
text('industryLabel', 'Industry label', netzwerkContent.partners.modal.industryLabel),
text('locationLabel', 'Location label', netzwerkContent.partners.modal.locationLabel),
text('webLabel', 'Web label', netzwerkContent.partners.modal.webLabel),
text('aboutLabel', 'About label', netzwerkContent.partners.modal.aboutLabel),
text('websiteLabel', 'Website CTA label', netzwerkContent.partners.modal.websiteLabel),
text('closeLabel', 'Close label', netzwerkContent.partners.modal.closeLabel),
text('footerTitle', 'Footer title', netzwerkContent.partners.modal.footerTitle),
text('footerRolePrefix', 'Footer role prefix', netzwerkContent.partners.modal.footerRolePrefix),
],
},
{
name: 'items',
label: 'Partners',
type: 'array',
dbName: 'network_partners',
defaultValue: netzwerkContent.partners.items,
fields: partnerFields,
},
],
},
{
name: 'sponsoring',
label: '07 · Sponsoring section',
type: 'group',
admin: sectionAdmin('Sponsoring pitch, image, benefits, form eyebrow, and membership footnote.'),
fields: [
text('eyebrow', 'Eyebrow', netzwerkContent.sponsoring.eyebrow),
textarea('heading', 'Heading', netzwerkContent.sponsoring.heading),
textarea('description', 'Description', netzwerkContent.sponsoring.description),
uploadField('image', 'Form panel image', `Current frontend image: /images/${netzwerkContent.sponsoring.imageFilename}`),
text('imageAlt', 'Image alt text', netzwerkContent.sponsoring.imageAlt),
text('imageLabel', 'Image label', netzwerkContent.sponsoring.imageLabel),
text('formEyebrow', 'Form eyebrow', netzwerkContent.sponsoring.formEyebrow),
text('footnotePrefix', 'Footnote prefix', netzwerkContent.sponsoring.footnotePrefix),
text('footnoteLabel', 'Footnote link label', netzwerkContent.sponsoring.footnoteLabel),
text('footnoteUrl', 'Footnote link URL', netzwerkContent.sponsoring.footnoteUrl),
{
name: 'benefits',
label: 'Benefits',
type: 'array',
dbName: 'network_sponsor_bens',
defaultValue: netzwerkContent.sponsoring.benefits,
fields: benefitFields,
},
],
},
{
name: 'sponsoringForm',
label: '08 · Sponsoring form',
type: 'group',
admin: sectionAdmin('Wizard labels, package options, validation messages, success copy, and footer note.'),
fields: [
{
name: 'steps',
label: 'Step labels',
type: 'array',
dbName: 'network_form_steps',
defaultValue: netzwerkContent.sponsoringForm.steps,
fields: formStepFields,
},
{
name: 'packages',
label: 'Package options',
type: 'array',
dbName: 'network_form_pkgs',
defaultValue: netzwerkContent.sponsoringForm.packages,
fields: packageFields,
},
text('step1Eyebrow', 'Step 1 eyebrow', netzwerkContent.sponsoringForm.step1Eyebrow),
text('step1Heading', 'Step 1 heading', netzwerkContent.sponsoringForm.step1Heading),
text('step2Eyebrow', 'Step 2 eyebrow', netzwerkContent.sponsoringForm.step2Eyebrow),
text('step2Heading', 'Step 2 heading', netzwerkContent.sponsoringForm.step2Heading),
text('companyLabel', 'Company label', netzwerkContent.sponsoringForm.companyLabel),
text('companyPlaceholder', 'Company placeholder', netzwerkContent.sponsoringForm.companyPlaceholder),
text('industryLabel', 'Industry label', netzwerkContent.sponsoringForm.industryLabel),
text('industryPlaceholder', 'Industry placeholder', netzwerkContent.sponsoringForm.industryPlaceholder),
text('step3Eyebrow', 'Step 3 eyebrow', netzwerkContent.sponsoringForm.step3Eyebrow),
text('step3Heading', 'Step 3 heading', netzwerkContent.sponsoringForm.step3Heading),
text('contactLabel', 'Contact label', netzwerkContent.sponsoringForm.contactLabel),
text('contactPlaceholder', 'Contact placeholder', netzwerkContent.sponsoringForm.contactPlaceholder),
text('emailLabel', 'Email label', netzwerkContent.sponsoringForm.emailLabel),
text('emailPlaceholder', 'Email placeholder', netzwerkContent.sponsoringForm.emailPlaceholder),
text('backLabel', 'Back label', netzwerkContent.sponsoringForm.backLabel),
text('nextLabel', 'Next label', netzwerkContent.sponsoringForm.nextLabel),
text('submitLabel', 'Submit label', netzwerkContent.sponsoringForm.submitLabel),
text('requiredPackageError', 'Required package error', netzwerkContent.sponsoringForm.requiredPackageError),
text('requiredFieldError', 'Required field error', netzwerkContent.sponsoringForm.requiredFieldError),
text('invalidEmailError', 'Invalid email error', netzwerkContent.sponsoringForm.invalidEmailError),
text('doneLabel', 'Done step label', netzwerkContent.sponsoringForm.doneLabel),
text('successHeading', 'Success heading', netzwerkContent.sponsoringForm.successHeading),
text('successMessagePrefix', 'Success message prefix', netzwerkContent.sponsoringForm.successMessagePrefix),
text('successMessageSuffix', 'Success message suffix', netzwerkContent.sponsoringForm.successMessageSuffix),
text('footerText', 'Footer text', netzwerkContent.sponsoringForm.footerText),
],
},
],
},
]