feat: manage impressum page via payload

This commit is contained in:
syntaxbullet
2026-06-22 10:45:54 +02:00
parent 2e9ad5cdf8
commit e1713f6d6e
7 changed files with 625 additions and 184 deletions

View File

@@ -0,0 +1,81 @@
import type { Field } from 'payload'
import { impressumContent } from '@/spa/impressumContent'
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 sectionAdmin = (description: string) => ({
description,
initCollapsed: true,
})
export const impressumFields: Field[] = [
{
name: 'impressum',
label: 'Impressum page content',
type: 'group',
admin: {
description:
'Edit the Impressum page content. Legal section body blocks are stored as JSON so nested paragraphs, lists, notices, addresses, and subsections can keep their frontend order.',
},
fields: [
{
name: 'hero',
label: '01 · Hero',
type: 'group',
admin: sectionAdmin('Top legal page heading and description line.'),
fields: [
text('backLabel', 'Back link label', impressumContent.hero.backLabel),
text('eyebrow', 'Eyebrow', impressumContent.hero.eyebrow),
textarea('heading', 'Heading', impressumContent.hero.heading),
textarea('descriptionHtml', 'Description HTML', impressumContent.hero.descriptionHtml),
],
},
{
name: 'navigation',
label: '02 · Side navigation',
type: 'group',
admin: sectionAdmin('Sticky table-of-contents title and related legal-page link.'),
fields: [
text('tocTitle', 'TOC title', impressumContent.navigation.tocTitle),
text('sideLinkLabel', 'Side link label', impressumContent.navigation.sideLinkLabel),
text('sideLinkUrl', 'Side link URL', impressumContent.navigation.sideLinkUrl),
],
},
{
name: 'sections',
label: '03 · Legal sections',
type: 'array',
dbName: 'imp_sections',
admin: sectionAdmin('Each section controls one heading, table-of-contents label, and ordered JSON body blocks.'),
defaultValue: impressumContent.sections,
fields: [
text('id', 'Anchor ID'),
text('tocLabel', 'TOC label'),
text('title', 'Section title'),
{
name: 'items',
label: 'Content blocks JSON',
type: 'json',
admin: {
description:
'Array of blocks: paragraph, legal, address, list, or subsection. Paragraph/legal blocks use HTML strings for inline links.',
},
},
],
},
],
},
]

View File

@@ -10,6 +10,7 @@ import { MediaBlock } from '../../blocks/MediaBlock/config'
import { hero } from '@/heros/config'
import { contactFields } from './contactFields'
import { homeFields } from './homeFields'
import { impressumFields } from './impressumFields'
import { participationFields } from './participationFields'
import { slugField } from 'payload'
import { populatePublishedAt } from '../../hooks/populatePublishedAt'
@@ -48,8 +49,19 @@ const isParticipationPage = (_: unknown, siblingData?: { slug?: string; spaPath?
return spaPath === '/teilnahme' || slug === 'teilnahme' || slug === 'participation' || title === 'teilnahme' || title === 'participation'
}
const isImpressumPage = (_: unknown, siblingData?: { slug?: string; spaPath?: string; title?: string }) => {
const slug = siblingData?.slug
const spaPath = siblingData?.spaPath
const title = siblingData?.title?.toLowerCase()
return spaPath === '/impressum' || slug === 'impressum' || title === 'impressum'
}
const isManagedSpaPage = (_: unknown, siblingData?: { slug?: string; spaPath?: string; title?: string }) =>
isHomePage(undefined, siblingData) || isContactPage(undefined, siblingData) || isParticipationPage(undefined, siblingData)
isHomePage(undefined, siblingData) ||
isContactPage(undefined, siblingData) ||
isParticipationPage(undefined, siblingData) ||
isImpressumPage(undefined, siblingData)
export const Pages: CollectionConfig<'pages'> = {
slug: 'pages',
@@ -138,6 +150,13 @@ export const Pages: CollectionConfig<'pages'> = {
fields: participationFields,
label: 'Participation Page',
},
{
admin: {
condition: (data) => isImpressumPage(undefined, data),
},
fields: impressumFields,
label: 'Impressum Page',
},
{
name: 'meta',
label: 'SEO',