import type { CollectionConfig } from 'payload' import { tenantScopedPublicRead, authenticatedOnly } from '../lib/tenantAccess' export const Products: CollectionConfig = { slug: 'products', admin: { useAsTitle: 'title', group: 'Produkte', defaultColumns: ['title', 'category', 'status', 'price', 'isFeatured', 'updatedAt'], description: 'Produkte und Artikel', }, access: { read: tenantScopedPublicRead, create: authenticatedOnly, update: authenticatedOnly, delete: authenticatedOnly, }, fields: [ // ========================================================================= // Grundinformationen // ========================================================================= { name: 'title', type: 'text', required: true, label: 'Produktname', localized: true, }, { name: 'slug', type: 'text', required: true, unique: false, // Uniqueness per tenant label: 'URL-Slug', admin: { description: 'URL-freundlicher Name (z.B. "premium-widget")', }, }, { name: 'sku', type: 'text', label: 'Artikelnummer (SKU)', admin: { description: 'Eindeutige Artikelnummer für interne Verwaltung', }, }, { name: 'shortDescription', type: 'textarea', label: 'Kurzbeschreibung', localized: true, admin: { description: 'Kurze Beschreibung für Produktlisten (max. 200 Zeichen)', }, }, { name: 'description', type: 'richText', label: 'Produktbeschreibung', localized: true, }, // ========================================================================= // Kategorisierung // ========================================================================= { name: 'category', type: 'relationship', // eslint-disable-next-line @typescript-eslint/no-explicit-any relationTo: 'product-categories' as any, label: 'Kategorie', admin: { description: 'Hauptkategorie des Produkts', }, }, { name: 'tags', type: 'array', label: 'Tags', admin: { description: 'Zusätzliche Schlagworte für Filterung', }, fields: [ { name: 'tag', type: 'text', required: true, }, ], }, // ========================================================================= // Medien // ========================================================================= { name: 'featuredImage', type: 'upload', relationTo: 'media', label: 'Hauptbild', required: true, }, { name: 'gallery', type: 'array', label: 'Bildergalerie', admin: { description: 'Zusätzliche Produktbilder', }, fields: [ { name: 'image', type: 'upload', relationTo: 'media', required: true, }, { name: 'caption', type: 'text', label: 'Bildunterschrift', localized: true, }, ], }, // ========================================================================= // Preisgestaltung // ========================================================================= { name: 'pricing', type: 'group', label: 'Preisgestaltung', fields: [ { type: 'row', fields: [ { name: 'price', type: 'number', label: 'Preis', admin: { width: '33%', description: 'Regulärer Preis in Euro', }, }, { name: 'salePrice', type: 'number', label: 'Angebotspreis', admin: { width: '33%', description: 'Reduzierter Preis (optional)', }, }, { name: 'currency', type: 'select', label: 'Währung', defaultValue: 'EUR', options: [ { label: 'Euro (EUR)', value: 'EUR' }, { label: 'US-Dollar (USD)', value: 'USD' }, { label: 'Schweizer Franken (CHF)', value: 'CHF' }, ], admin: { width: '34%', }, }, ], }, { name: 'priceType', type: 'select', label: 'Preistyp', defaultValue: 'fixed', options: [ { label: 'Festpreis', value: 'fixed' }, { label: 'Ab Preis', value: 'from' }, { label: 'Auf Anfrage', value: 'on_request' }, { label: 'Kostenlos', value: 'free' }, ], }, { name: 'priceNote', type: 'text', label: 'Preishinweis', localized: true, admin: { description: 'z.B. "zzgl. MwSt.", "pro Monat", "Einmalzahlung"', }, }, ], }, // ========================================================================= // Produktdetails // ========================================================================= { name: 'details', type: 'group', label: 'Produktdetails', admin: { description: 'Technische Daten und Spezifikationen', }, fields: [ { name: 'specifications', type: 'array', label: 'Spezifikationen', admin: { description: 'Technische Daten als Schlüssel-Wert-Paare', }, fields: [ { type: 'row', fields: [ { name: 'key', type: 'text', label: 'Eigenschaft', required: true, localized: true, admin: { width: '50%', placeholder: 'z.B. Gewicht, Maße, Material', }, }, { name: 'value', type: 'text', label: 'Wert', required: true, localized: true, admin: { width: '50%', placeholder: 'z.B. 500g, 10x20cm, Aluminium', }, }, ], }, ], }, { name: 'features', type: 'array', label: 'Highlights / Features', admin: { description: 'Wichtigste Produktvorteile', }, fields: [ { name: 'feature', type: 'text', required: true, localized: true, }, { name: 'icon', type: 'text', label: 'Icon', admin: { description: 'Optional: Lucide-Icon Name', }, }, ], }, ], }, // ========================================================================= // Lager & Verfügbarkeit // ========================================================================= { name: 'inventory', type: 'group', label: 'Lager & Verfügbarkeit', fields: [ { type: 'row', fields: [ { name: 'stockStatus', type: 'select', label: 'Verfügbarkeit', defaultValue: 'in_stock', options: [ { label: 'Auf Lager', value: 'in_stock' }, { label: 'Nur noch wenige', value: 'low_stock' }, { label: 'Nicht auf Lager', value: 'out_of_stock' }, { label: 'Auf Bestellung', value: 'on_order' }, { label: 'Vorbestellung', value: 'preorder' }, ], admin: { width: '50%', }, }, { name: 'stockQuantity', type: 'number', label: 'Lagerbestand', admin: { width: '50%', description: 'Aktuelle Stückzahl (optional)', }, }, ], }, { name: 'deliveryTime', type: 'text', label: 'Lieferzeit', localized: true, admin: { description: 'z.B. "1-3 Werktage", "Sofort lieferbar"', }, }, ], }, // ========================================================================= // Verknüpfungen // ========================================================================= { name: 'relatedProducts', type: 'relationship', relationTo: 'products', hasMany: true, label: 'Ähnliche Produkte', admin: { description: 'Produktempfehlungen für Cross-Selling', }, }, { name: 'downloadFiles', type: 'array', label: 'Downloads', admin: { description: 'Produktdatenblätter, Anleitungen, etc.', }, fields: [ { name: 'file', type: 'upload', relationTo: 'media', required: true, }, { name: 'title', type: 'text', label: 'Titel', localized: true, }, ], }, // ========================================================================= // Call-to-Action // ========================================================================= { name: 'cta', type: 'group', label: 'Call-to-Action', admin: { description: 'Handlungsaufforderung für das Produkt', }, fields: [ { name: 'type', type: 'select', label: 'CTA-Typ', defaultValue: 'contact', options: [ { label: 'Kontakt aufnehmen', value: 'contact' }, { label: 'Angebot anfordern', value: 'quote' }, { label: 'In den Warenkorb', value: 'cart' }, { label: 'Externer Link', value: 'external' }, { label: 'Download', value: 'download' }, ], }, { name: 'buttonText', type: 'text', label: 'Button-Text', localized: true, admin: { description: 'z.B. "Jetzt anfragen", "Kaufen", "Herunterladen"', }, }, { name: 'externalUrl', type: 'text', label: 'Externer Link', admin: { condition: (_, siblingData) => siblingData?.type === 'external', description: 'URL für externen Shop oder Bestellseite', }, }, ], }, // ========================================================================= // SEO // ========================================================================= { name: 'seo', type: 'group', label: 'SEO', fields: [ { name: 'metaTitle', type: 'text', label: 'Meta-Titel', localized: true, admin: { description: 'Überschreibt den Produktnamen für Suchmaschinen', }, }, { name: 'metaDescription', type: 'textarea', label: 'Meta-Beschreibung', localized: true, admin: { description: 'Kurze Beschreibung für Suchergebnisse (max. 160 Zeichen)', }, }, { name: 'ogImage', type: 'upload', relationTo: 'media', label: 'Social Media Bild', admin: { description: 'Bild für Social Media Shares (1200x630px empfohlen)', }, }, ], }, // ========================================================================= // Status & Sortierung (Sidebar) // ========================================================================= { name: 'status', type: 'select', label: 'Status', defaultValue: 'draft', options: [ { label: 'Entwurf', value: 'draft' }, { label: 'Veröffentlicht', value: 'published' }, { label: 'Archiviert', value: 'archived' }, ], admin: { position: 'sidebar', }, }, { name: 'isFeatured', type: 'checkbox', label: 'Hervorgehoben', defaultValue: false, admin: { position: 'sidebar', description: 'Auf Startseite oder in Highlights anzeigen', }, }, { name: 'isNew', type: 'checkbox', label: 'Neu', defaultValue: false, admin: { position: 'sidebar', description: '"Neu"-Badge anzeigen', }, }, { name: 'order', type: 'number', label: 'Sortierung', defaultValue: 0, admin: { position: 'sidebar', description: 'Kleinere Zahlen erscheinen zuerst', }, }, { name: 'publishedAt', type: 'date', label: 'Veröffentlichungsdatum', admin: { position: 'sidebar', date: { pickerAppearance: 'dayAndTime', }, }, }, ], }