import type { CollectionConfig } from 'payload' /** * Timelines Collection * * Dedizierte Collection für komplexe Timeline-Ereignisse * - Unternehmensgeschichte * - Projektmeilensteine * - Produkt-Releases * - Historische Ereignisse * * Multi-Tenant-fähig mit flexiblen Kategorisierungen */ export const Timelines: CollectionConfig = { slug: 'timelines', labels: { singular: 'Timeline', plural: 'Timelines', }, admin: { useAsTitle: 'name', group: 'Inhalte', defaultColumns: ['name', 'type', 'status', 'updatedAt'], description: 'Chronologische Darstellungen für Unternehmensgeschichte, Meilensteine, etc.', }, access: { read: () => true, // Öffentlich lesbar }, fields: [ // Timeline-Metadaten { name: 'name', type: 'text', required: true, label: 'Timeline-Name', localized: true, admin: { description: 'Interner Name zur Identifikation (z.B. "Unternehmensgeschichte")', }, }, { name: 'slug', type: 'text', required: true, unique: true, label: 'Slug', admin: { description: 'URL-freundlicher Identifier (z.B. "company-history")', }, }, { name: 'description', type: 'textarea', label: 'Beschreibung', localized: true, admin: { description: 'Optionale Beschreibung der Timeline', }, }, { name: 'type', type: 'select', required: true, defaultValue: 'history', label: 'Timeline-Typ', options: [ { label: 'Unternehmensgeschichte', value: 'history' }, { label: 'Projektmeilensteine', value: 'milestones' }, { label: 'Produkt-Releases', value: 'releases' }, { label: 'Karriere/Lebenslauf', value: 'career' }, { label: 'Ereignisse', value: 'events' }, { label: 'Prozess/Ablauf', value: 'process' }, ], }, { name: 'status', type: 'select', required: true, defaultValue: 'draft', label: 'Status', options: [ { label: 'Entwurf', value: 'draft' }, { label: 'Veröffentlicht', value: 'published' }, { label: 'Archiviert', value: 'archived' }, ], admin: { position: 'sidebar', }, }, // Display-Optionen { name: 'displayOptions', type: 'group', label: 'Darstellungsoptionen', fields: [ { name: 'layout', type: 'select', defaultValue: 'vertical', label: 'Layout', options: [ { label: 'Vertikal (Standard)', value: 'vertical' }, { label: 'Alternierend (links/rechts)', value: 'alternating' }, { label: 'Horizontal (Zeitleiste)', value: 'horizontal' }, { label: 'Kompakt (Liste)', value: 'compact' }, ], }, { name: 'sortOrder', type: 'select', defaultValue: 'desc', label: 'Sortierung', options: [ { label: 'Neueste zuerst', value: 'desc' }, { label: 'Älteste zuerst', value: 'asc' }, ], }, { name: 'showConnector', type: 'checkbox', defaultValue: true, label: 'Verbindungslinie anzeigen', }, { name: 'showImages', type: 'checkbox', defaultValue: true, label: 'Bilder anzeigen', }, { name: 'groupByYear', type: 'checkbox', defaultValue: false, label: 'Nach Jahr gruppieren', }, { name: 'markerStyle', type: 'select', defaultValue: 'dot', label: 'Marker-Stil', options: [ { label: 'Punkt', value: 'dot' }, { label: 'Nummer', value: 'number' }, { label: 'Icon', value: 'icon' }, { label: 'Datum', value: 'date' }, ], }, { name: 'colorScheme', type: 'select', defaultValue: 'primary', label: 'Farbschema', options: [ { label: 'Primär (Brand)', value: 'primary' }, { label: 'Sekundär', value: 'secondary' }, { label: 'Neutral (Grau)', value: 'neutral' }, { label: 'Bunt (je nach Kategorie)', value: 'colorful' }, ], }, ], }, // Timeline-Einträge { name: 'events', type: 'array', required: true, minRows: 1, label: 'Ereignisse', admin: { description: 'Die einzelnen Einträge der Timeline', initCollapsed: false, }, fields: [ // Datum-Optionen { type: 'row', fields: [ { name: 'dateType', type: 'select', defaultValue: 'year', label: 'Datumstyp', admin: { width: '30%', }, options: [ { label: 'Nur Jahr', value: 'year' }, { label: 'Monat & Jahr', value: 'monthYear' }, { label: 'Vollständiges Datum', value: 'fullDate' }, { label: 'Zeitraum', value: 'range' }, { label: 'Freitext', value: 'custom' }, ], }, { name: 'year', type: 'number', label: 'Jahr', admin: { width: '20%', condition: (_, siblingData) => ['year', 'monthYear', 'fullDate'].includes(siblingData?.dateType), }, min: 1900, max: 2100, }, { name: 'month', type: 'select', label: 'Monat', admin: { width: '25%', condition: (_, siblingData) => ['monthYear', 'fullDate'].includes(siblingData?.dateType), }, options: [ { label: 'Januar', value: '1' }, { label: 'Februar', value: '2' }, { label: 'März', value: '3' }, { label: 'April', value: '4' }, { label: 'Mai', value: '5' }, { label: 'Juni', value: '6' }, { label: 'Juli', value: '7' }, { label: 'August', value: '8' }, { label: 'September', value: '9' }, { label: 'Oktober', value: '10' }, { label: 'November', value: '11' }, { label: 'Dezember', value: '12' }, ], }, { name: 'day', type: 'number', label: 'Tag', admin: { width: '15%', condition: (_, siblingData) => siblingData?.dateType === 'fullDate', }, min: 1, max: 31, }, ], }, { type: 'row', fields: [ { name: 'endYear', type: 'number', label: 'Ende Jahr', admin: { width: '25%', condition: (_, siblingData) => siblingData?.dateType === 'range', }, min: 1900, max: 2100, }, { name: 'endMonth', type: 'select', label: 'Ende Monat', admin: { width: '25%', condition: (_, siblingData) => siblingData?.dateType === 'range', }, options: [ { label: 'Januar', value: '1' }, { label: 'Februar', value: '2' }, { label: 'März', value: '3' }, { label: 'April', value: '4' }, { label: 'Mai', value: '5' }, { label: 'Juni', value: '6' }, { label: 'Juli', value: '7' }, { label: 'August', value: '8' }, { label: 'September', value: '9' }, { label: 'Oktober', value: '10' }, { label: 'November', value: '11' }, { label: 'Dezember', value: '12' }, ], }, { name: 'ongoing', type: 'checkbox', label: 'Laufend (bis heute)', admin: { width: '25%', condition: (_, siblingData) => siblingData?.dateType === 'range', }, }, ], }, { name: 'customDate', type: 'text', label: 'Datum (Freitext)', admin: { description: 'z.B. "Frühjahr 2024", "Q1 2023", "1990er Jahre"', condition: (_, siblingData) => siblingData?.dateType === 'custom', }, }, // Inhalt { name: 'title', type: 'text', required: true, label: 'Titel', localized: true, }, { name: 'subtitle', type: 'text', label: 'Untertitel', localized: true, admin: { description: 'Optional: z.B. Rolle, Position, Ort', }, }, { name: 'description', type: 'richText', label: 'Beschreibung', localized: true, }, { name: 'shortDescription', type: 'textarea', label: 'Kurzbeschreibung', localized: true, admin: { description: 'Für kompakte Ansichten (max. 200 Zeichen empfohlen)', }, }, // Medien { name: 'image', type: 'upload', relationTo: 'media', label: 'Bild', }, { name: 'gallery', type: 'array', label: 'Galerie', admin: { description: 'Zusätzliche Bilder für dieses Ereignis', }, fields: [ { name: 'image', type: 'upload', relationTo: 'media', required: true, }, { name: 'caption', type: 'text', label: 'Bildunterschrift', localized: true, }, ], }, // Kategorisierung { name: 'category', type: 'select', label: 'Kategorie', admin: { description: 'Zur Filterung und farblichen Unterscheidung', }, options: [ { label: 'Meilenstein', value: 'milestone' }, { label: 'Gründung/Start', value: 'founding' }, { label: 'Produkt', value: 'product' }, { label: 'Team/Personal', value: 'team' }, { label: 'Auszeichnung', value: 'award' }, { label: 'Partnerschaft', value: 'partnership' }, { label: 'Expansion', value: 'expansion' }, { label: 'Technologie', value: 'technology' }, { label: 'Sonstiges', value: 'other' }, ], }, { name: 'importance', type: 'select', defaultValue: 'normal', label: 'Wichtigkeit', options: [ { label: 'Highlight', value: 'highlight' }, { label: 'Normal', value: 'normal' }, { label: 'Minor', value: 'minor' }, ], admin: { description: 'Highlights werden visuell hervorgehoben', }, }, // Prozess-spezifische Felder (für einfache Prozesse wie Onboarding, Bewerbung) { name: 'stepNumber', type: 'number', label: 'Schritt-Nummer', admin: { description: 'Explizite Nummerierung (optional, sonst wird Reihenfolge verwendet)', condition: (data) => data?.type === 'process', }, }, { name: 'duration', type: 'text', label: 'Dauer', localized: true, admin: { description: 'z.B. "2-3 Tage", "1 Woche", "30 Minuten"', condition: (data) => data?.type === 'process', }, }, { name: 'responsible', type: 'text', label: 'Verantwortlich', localized: true, admin: { description: 'Person oder Rolle (z.B. "HR-Team", "Projektleiter")', condition: (data) => data?.type === 'process', }, }, { name: 'actionRequired', type: 'select', label: 'Aktion erforderlich von', admin: { description: 'Wer muss in diesem Schritt aktiv werden?', condition: (data) => data?.type === 'process', }, options: [ { label: 'Kunde/Bewerber', value: 'customer' }, { label: 'Internes Team', value: 'internal' }, { label: 'Beide Seiten', value: 'both' }, { label: 'Automatisch', value: 'automatic' }, ], }, { name: 'deliverables', type: 'array', label: 'Ergebnisse/Dokumente', admin: { description: 'Was wird in diesem Schritt erstellt oder benötigt?', condition: (data) => data?.type === 'process', }, fields: [ { name: 'name', type: 'text', required: true, label: 'Name', localized: true, }, { name: 'type', type: 'select', defaultValue: 'output', label: 'Typ', options: [ { label: 'Ergebnis (Output)', value: 'output' }, { label: 'Benötigt (Input)', value: 'input' }, { label: 'Dokument', value: 'document' }, ], }, ], }, // Icon & Styling { name: 'icon', type: 'text', label: 'Icon', admin: { description: 'Emoji oder Lucide Icon-Name (z.B. "rocket", "award", "users")', }, }, { name: 'color', type: 'text', label: 'Farbe (optional)', admin: { description: 'Überschreibt die Kategorie-Farbe (z.B. "#FF5733" oder "blue")', }, }, // Links { name: 'links', type: 'array', label: 'Links', fields: [ { name: 'label', type: 'text', required: true, label: 'Link-Text', localized: true, }, { name: 'url', type: 'text', required: true, label: 'URL', }, { name: 'type', type: 'select', defaultValue: 'internal', label: 'Link-Typ', options: [ { label: 'Intern', value: 'internal' }, { label: 'Extern', value: 'external' }, { label: 'Download', value: 'download' }, ], }, ], }, // Zusätzliche Daten { name: 'metadata', type: 'json', label: 'Zusätzliche Daten (JSON)', admin: { description: 'Für spezielle Anwendungsfälle (z.B. Statistiken, Kennzahlen)', }, }, ], }, // SEO { name: 'seo', type: 'group', label: 'SEO', admin: { position: 'sidebar', }, fields: [ { name: 'metaTitle', type: 'text', label: 'Meta-Titel', localized: true, }, { name: 'metaDescription', type: 'textarea', label: 'Meta-Beschreibung', localized: true, }, ], }, ], hooks: { beforeChange: [ ({ data }) => { // Auto-generate slug from name if not provided if (data && !data.slug && data.name) { data.slug = data.name .toLowerCase() .replace(/[äöüß]/g, (match: string) => { const map: Record = { ä: 'ae', ö: 'oe', ü: 'ue', ß: 'ss' } return map[match] || match }) .replace(/[^a-z0-9]+/g, '-') .replace(/^-|-$/g, '') } return data }, ], }, }