// src/collections/YouTubeChannels.ts import type { CollectionConfig } from 'payload' import { isYouTubeManager, hasYouTubeAccess } from '../lib/youtubeAccess' import { downloadChannelImage } from '../hooks/youtubeChannels/downloadChannelImage' /** * YouTubeChannels Collection * * Verwaltet YouTube-Kanäle mit Branding, Content-Serien und Metriken. * Teil des YouTube Operations Hub. */ export const YouTubeChannels: CollectionConfig = { slug: 'youtube-channels', labels: { singular: 'YouTube-Kanal', plural: 'YouTube-Kanäle', }, admin: { useAsTitle: 'name', group: 'YouTube', defaultColumns: ['name', 'youtubeHandle', 'status', 'language'], description: 'YouTube-Kanäle und ihre Konfiguration', }, access: { read: hasYouTubeAccess, create: isYouTubeManager, update: isYouTubeManager, delete: isYouTubeManager, }, hooks: { afterChange: [downloadChannelImage], }, fields: [ { name: 'name', type: 'text', required: true, localized: true, label: 'Kanalname', admin: { description: 'z.B. "BlogWoman by Caroline Porwoll"', }, }, { name: 'slug', type: 'text', required: true, unique: true, label: 'Slug', admin: { description: 'Interner Kurzname (z.B. "blogwoman", "corporate-de")', }, }, { name: 'youtubeChannelId', type: 'text', required: true, label: 'YouTube Channel ID', admin: { description: 'Die YouTube Channel ID (z.B. "UCxxxxxxxxxxxxx")', }, }, { name: 'youtubeHandle', type: 'text', label: 'YouTube Handle', admin: { description: 'z.B. "@blogwoman" oder "@zweitmeinu.ng"', }, }, { name: 'language', type: 'select', required: true, label: 'Sprache', options: [ { label: 'Deutsch', value: 'de' }, { label: 'Englisch', value: 'en' }, ], admin: { position: 'sidebar', }, }, { name: 'category', type: 'select', required: true, label: 'Kategorie', options: [ { label: 'Lifestyle', value: 'lifestyle' }, { label: 'Corporate', value: 'corporate' }, { label: 'Business B2B', value: 'b2b' }, ], admin: { position: 'sidebar', }, }, { name: 'status', type: 'select', required: true, defaultValue: 'active', label: 'Status', options: [ { label: 'Aktiv', value: 'active' }, { label: 'In Planung', value: 'planned' }, { label: 'Pausiert', value: 'paused' }, { label: 'Archiviert', value: 'archived' }, ], admin: { position: 'sidebar', }, }, { name: 'channelThumbnailUrl', type: 'text', label: 'Kanal-Thumbnail URL', admin: { readOnly: true, description: 'Profil-Thumbnail URL von YouTube (automatisch befüllt)', position: 'sidebar', }, }, // Branding { name: 'branding', type: 'group', label: 'Branding', fields: [ { name: 'primaryColor', type: 'text', label: 'Primärfarbe (Hex)', admin: { description: 'z.B. #1278B3' }, validate: (value: string | undefined | null) => { if (!value) return true const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/ if (!hexRegex.test(value)) { return 'Bitte einen gültigen Hex-Farbcode eingeben (z.B. #1278B3)' } return true }, }, { name: 'secondaryColor', type: 'text', label: 'Sekundärfarbe (Hex)', validate: (value: string | undefined | null) => { if (!value) return true const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/ if (!hexRegex.test(value)) { return 'Bitte einen gültigen Hex-Farbcode eingeben' } return true }, }, { name: 'logo', type: 'upload', relationTo: 'media', label: 'Logo', }, { name: 'thumbnailTemplate', type: 'upload', relationTo: 'media', label: 'Thumbnail-Vorlage', }, ], }, // Content-Serien sind jetzt in der YtSeries Collection verwaltet // Siehe: YouTube → YouTube-Serien // Veröffentlichungsplan { name: 'publishingSchedule', type: 'group', label: 'Veröffentlichungsplan', fields: [ { name: 'defaultDays', type: 'select', hasMany: true, label: 'Standard-Tage', options: [ { label: 'Montag', value: 'monday' }, { label: 'Dienstag', value: 'tuesday' }, { label: 'Mittwoch', value: 'wednesday' }, { label: 'Donnerstag', value: 'thursday' }, { label: 'Freitag', value: 'friday' }, { label: 'Samstag', value: 'saturday' }, { label: 'Sonntag', value: 'sunday' }, ], }, { name: 'defaultTime', type: 'text', label: 'Standard-Uhrzeit', admin: { description: 'z.B. "12:00"' }, }, { name: 'shortsPerWeek', type: 'number', defaultValue: 4, label: 'Shorts pro Woche', }, { name: 'longformPerWeek', type: 'number', defaultValue: 1, label: 'Longform pro Woche', }, ], }, // Metriken (via YouTube API Sync) { name: 'currentMetrics', type: 'group', label: 'Aktuelle Metriken', admin: { description: 'Automatisch via YouTube API aktualisiert', }, fields: [ { name: 'subscriberCount', type: 'number', label: 'Abonnenten', admin: { readOnly: true } }, { name: 'totalViews', type: 'number', label: 'Gesamtaufrufe', admin: { readOnly: true } }, { name: 'videoCount', type: 'number', label: 'Anzahl Videos', admin: { readOnly: true } }, { name: 'lastSyncedAt', type: 'date', label: 'Letzter Sync', admin: { readOnly: true } }, ], }, ], timestamps: true, }