import type { CollectionConfig } from 'payload' import { authenticated } from '@/access/authenticated' import { authenticatedOrPublished } from '@/access/authenticatedOrPublished' import { populatePublishedAt } from '@/hooks/populatePublishedAt' import { eventDetailContent } from '@/spa/eventDetailContent' import { generatePreviewPath } from '@/utilities/generatePreviewPath' import { slugField } from 'payload' import { revalidateEvent, revalidateEventDelete } from './Events/hooks/revalidateEvent' import { MetaDescriptionField, MetaTitleField, OverviewField, PreviewField, } from '@payloadcms/plugin-seo/fields' export const Events: CollectionConfig = { slug: 'events', labels: { singular: 'Termin / Event', plural: 'Termine & Events', }, access: { create: authenticated, delete: authenticated, read: authenticatedOrPublished, update: authenticated, }, admin: { defaultColumns: ['title', 'spaPath', 'slug', 'updatedAt'], group: 'Inhalte', livePreview: { url: ({ data, req }) => generatePreviewPath({ slug: data?.spaPath || data?.slug, collection: 'events', req, }), }, preview: (data, { req }) => generatePreviewPath({ slug: ((data?.spaPath as string | undefined) || (data?.slug as string)), collection: 'events', req, }), useAsTitle: 'title', }, fields: [ { name: 'title', type: 'text', required: true, }, { name: 'subtitle', type: 'text', }, { name: 'image', type: 'upload', relationTo: 'media', }, { name: 'description', type: 'textarea', }, { name: 'longDescription', type: 'textarea', }, { name: 'date', type: 'text', }, { name: 'time', type: 'text', }, { name: 'location', type: 'text', }, { name: 'venue', type: 'text', }, { name: 'category', type: 'text', }, { name: 'status', type: 'select', options: [ { label: 'Geplant', value: 'geplant' }, { label: 'Anmeldung offen', value: 'anmeldung-offen' }, { label: 'Intern', value: 'intern' }, { label: 'Abgeschlossen', value: 'abgeschlossen' }, ], defaultValue: 'geplant', }, { name: 'eckdaten', type: 'array', fields: [ { name: 'label', type: 'text', required: true }, { name: 'value', type: 'text', required: true }, ], }, { name: 'updates', type: 'array', fields: [ { name: 'timestamp', type: 'text', required: true }, { name: 'type', type: 'select', options: ['ankündigung', 'erinnerung', 'update', 'highlight', 'ergebnis', 'wichtig'], required: true, }, { name: 'title', type: 'text', required: true }, { name: 'body', type: 'textarea', required: true }, ], }, { name: 'detailPage', label: 'Detail page chrome', type: 'group', admin: { description: 'Shared labels, status/update labels, subscription copy, CTAs, and formatting copy for the Event detail route.', }, fields: [ { name: 'fallbackImage', type: 'upload', relationTo: 'media', label: 'Fallback hero image', admin: { description: `Current frontend fallback image: /images/${eventDetailContent.fallbackImageFilename}`, }, }, { name: 'notFound', label: 'Not found state', type: 'group', fields: [ { name: 'title', type: 'text', defaultValue: eventDetailContent.notFound.title }, { name: 'backLabel', type: 'text', defaultValue: eventDetailContent.notFound.backLabel }, { name: 'backUrl', type: 'text', defaultValue: eventDetailContent.notFound.backUrl }, ], }, { name: 'dateFormat', label: 'Date format', type: 'group', fields: [ { name: 'monthNames', type: 'json', defaultValue: eventDetailContent.dateFormat.monthNames, admin: { description: 'Array of 12 month names used when formatting update timestamps.' }, }, { name: 'timeSuffix', type: 'text', defaultValue: eventDetailContent.dateFormat.timeSuffix }, ], }, { name: 'updateStyles', label: 'Update type labels/styles JSON', type: 'json', defaultValue: eventDetailContent.updateStyles, }, { name: 'statusStyles', label: 'Status labels/styles JSON', type: 'json', defaultValue: eventDetailContent.statusStyles, }, { name: 'heroBackLink', label: 'Hero back link', type: 'group', fields: [ { name: 'label', type: 'text', defaultValue: eventDetailContent.heroBackLink.label }, { name: 'url', type: 'text', defaultValue: eventDetailContent.heroBackLink.url }, ], }, { name: 'fallbackEvent', label: 'Missing event field fallbacks', type: 'group', fields: [ { name: 'title', type: 'text', defaultValue: eventDetailContent.fallbackEvent.title }, { name: 'date', type: 'text', defaultValue: eventDetailContent.fallbackEvent.date }, { name: 'time', type: 'text', defaultValue: eventDetailContent.fallbackEvent.time }, { name: 'location', type: 'text', defaultValue: eventDetailContent.fallbackEvent.location }, { name: 'venue', type: 'text', defaultValue: eventDetailContent.fallbackEvent.venue }, { name: 'category', type: 'text', defaultValue: eventDetailContent.fallbackEvent.category }, { name: 'status', type: 'text', defaultValue: eventDetailContent.fallbackEvent.status }, { name: 'longDescription', type: 'textarea', defaultValue: eventDetailContent.fallbackEvent.longDescription }, ], }, { name: 'sections', label: 'Section labels and CTAs', type: 'group', fields: [ { name: 'aboutEyebrow', type: 'text', defaultValue: eventDetailContent.sections.aboutEyebrow }, { name: 'factsEyebrow', type: 'text', defaultValue: eventDetailContent.sections.factsEyebrow }, { name: 'registerLabel', type: 'text', defaultValue: eventDetailContent.sections.registerLabel }, { name: 'registerUrl', type: 'text', defaultValue: eventDetailContent.sections.registerUrl }, { name: 'questionLabel', type: 'text', defaultValue: eventDetailContent.sections.questionLabel }, { name: 'questionUrl', type: 'text', defaultValue: eventDetailContent.sections.questionUrl }, ], }, { name: 'updatesCopy', label: 'Updates panel', type: 'group', fields: [ { name: 'heading', type: 'text', defaultValue: eventDetailContent.updates.heading }, { name: 'subscribeLabel', type: 'text', defaultValue: eventDetailContent.updates.subscribeLabel }, { name: 'unsubscribeLabel', type: 'text', defaultValue: eventDetailContent.updates.unsubscribeLabel }, { name: 'subscribedMessage', type: 'text', defaultValue: eventDetailContent.updates.subscribedMessage }, ], }, { name: 'bottomCta', label: 'Bottom CTA', type: 'group', fields: [ { name: 'eyebrow', type: 'text', defaultValue: eventDetailContent.bottomCta.eyebrow }, { name: 'heading', type: 'text', defaultValue: eventDetailContent.bottomCta.heading }, { name: 'label', type: 'text', defaultValue: eventDetailContent.bottomCta.label }, { name: 'url', type: 'text', defaultValue: eventDetailContent.bottomCta.url }, ], }, ], }, { name: 'spaPath', type: 'text', index: true, admin: { description: 'Route in the legacy SPA used for previewing the current migrated event state.', position: 'sidebar', }, }, { name: 'publishedAt', type: 'date', admin: { position: 'sidebar', }, }, { name: 'meta', type: 'group', fields: [ OverviewField({ titlePath: 'meta.title', descriptionPath: 'meta.description', }), MetaTitleField({ hasGenerateFn: true }), MetaDescriptionField({}), PreviewField({ hasGenerateFn: true, titlePath: 'meta.title', descriptionPath: 'meta.description', }), ], }, slugField(), ], hooks: { afterChange: [revalidateEvent], afterDelete: [revalidateEventDelete], beforeChange: [populatePublishedAt], }, versions: { drafts: { autosave: { interval: 100, }, schedulePublish: true, }, maxPerDoc: 50, }, }