mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-17 17:24:12 +00:00
- Add Bookings Collection for porwoll.de (photography booking system) - Add Certifications Collection for C2S (healthcare certifications) - Add Projects Collection for gunshin.de (game development portfolio) - Add BeforeAfterBlock for before/after image comparisons - Add migration for 28 new database tables - Update documentation and clean up TODO.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
451 lines
11 KiB
TypeScript
451 lines
11 KiB
TypeScript
import type { CollectionConfig } from 'payload'
|
|
|
|
/**
|
|
* Certifications Collection
|
|
*
|
|
* Zertifizierungen, Akkreditierungen und Qualitätssiegel (C2S)
|
|
* Für Pflegeeinrichtungen und Gesundheitsdienstleister.
|
|
*/
|
|
export const Certifications: CollectionConfig = {
|
|
slug: 'certifications',
|
|
labels: {
|
|
singular: 'Zertifizierung',
|
|
plural: 'Zertifizierungen',
|
|
},
|
|
admin: {
|
|
group: 'Qualität',
|
|
useAsTitle: 'name',
|
|
defaultColumns: ['name', 'issuer', 'type', 'validUntil', 'status'],
|
|
description: 'Zertifizierungen, Akkreditierungen und Qualitätssiegel',
|
|
},
|
|
access: {
|
|
read: () => true,
|
|
create: ({ req: { user } }) => Boolean(user),
|
|
update: ({ req: { user } }) => Boolean(user),
|
|
delete: ({ req: { user } }) => Boolean(user?.isSuperAdmin),
|
|
},
|
|
fields: [
|
|
// Grundinformationen
|
|
{
|
|
name: 'name',
|
|
type: 'text',
|
|
required: true,
|
|
label: 'Name der Zertifizierung',
|
|
localized: true,
|
|
},
|
|
{
|
|
name: 'slug',
|
|
type: 'text',
|
|
required: true,
|
|
unique: true,
|
|
label: 'Slug',
|
|
admin: {
|
|
description: 'URL-freundlicher Name',
|
|
},
|
|
},
|
|
{
|
|
name: 'description',
|
|
type: 'richText',
|
|
label: 'Beschreibung',
|
|
localized: true,
|
|
},
|
|
{
|
|
name: 'shortDescription',
|
|
type: 'textarea',
|
|
label: 'Kurzbeschreibung',
|
|
localized: true,
|
|
admin: {
|
|
description: 'Für Übersichten und Meta-Beschreibungen',
|
|
},
|
|
},
|
|
// Zertifizierungs-Typ
|
|
{
|
|
name: 'type',
|
|
type: 'select',
|
|
required: true,
|
|
label: 'Typ',
|
|
options: [
|
|
{ label: 'ISO-Zertifizierung', value: 'iso' },
|
|
{ label: 'DIN-Norm', value: 'din' },
|
|
{ label: 'Akkreditierung', value: 'accreditation' },
|
|
{ label: 'Qualitätssiegel', value: 'seal' },
|
|
{ label: 'Mitgliedschaft', value: 'membership' },
|
|
{ label: 'Auszeichnung', value: 'award' },
|
|
{ label: 'Lizenz', value: 'license' },
|
|
{ label: 'Genehmigung', value: 'approval' },
|
|
{ label: 'Sonstiges', value: 'other' },
|
|
],
|
|
},
|
|
// Branchen-Kategorien (speziell für Pflege/Gesundheit)
|
|
{
|
|
name: 'category',
|
|
type: 'select',
|
|
label: 'Branchenkategorie',
|
|
options: [
|
|
{ label: 'Qualitätsmanagement', value: 'quality' },
|
|
{ label: 'Pflege', value: 'care' },
|
|
{ label: 'Medizin', value: 'medical' },
|
|
{ label: 'Hygiene', value: 'hygiene' },
|
|
{ label: 'Arbeitsschutz', value: 'safety' },
|
|
{ label: 'Datenschutz', value: 'privacy' },
|
|
{ label: 'Umwelt', value: 'environment' },
|
|
{ label: 'Personal', value: 'hr' },
|
|
{ label: 'IT-Sicherheit', value: 'it-security' },
|
|
{ label: 'Barrierefreiheit', value: 'accessibility' },
|
|
{ label: 'Sonstiges', value: 'other' },
|
|
],
|
|
},
|
|
// Aussteller
|
|
{
|
|
name: 'issuer',
|
|
type: 'group',
|
|
label: 'Ausstellende Organisation',
|
|
fields: [
|
|
{
|
|
name: 'name',
|
|
type: 'text',
|
|
required: true,
|
|
label: 'Name',
|
|
},
|
|
{
|
|
name: 'logo',
|
|
type: 'upload',
|
|
relationTo: 'media',
|
|
label: 'Logo',
|
|
},
|
|
{
|
|
name: 'website',
|
|
type: 'text',
|
|
label: 'Website',
|
|
},
|
|
{
|
|
name: 'country',
|
|
type: 'select',
|
|
label: 'Land',
|
|
options: [
|
|
{ label: 'Deutschland', value: 'DE' },
|
|
{ label: 'Österreich', value: 'AT' },
|
|
{ label: 'Schweiz', value: 'CH' },
|
|
{ label: 'EU', value: 'EU' },
|
|
{ label: 'International', value: 'INT' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
// Zertifikat-Details
|
|
{
|
|
name: 'certNumber',
|
|
type: 'text',
|
|
label: 'Zertifikatsnummer',
|
|
},
|
|
{
|
|
type: 'row',
|
|
fields: [
|
|
{
|
|
name: 'issuedDate',
|
|
type: 'date',
|
|
label: 'Ausstellungsdatum',
|
|
admin: {
|
|
width: '50%',
|
|
date: {
|
|
pickerAppearance: 'dayOnly',
|
|
displayFormat: 'dd.MM.yyyy',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: 'validUntil',
|
|
type: 'date',
|
|
label: 'Gültig bis',
|
|
admin: {
|
|
width: '50%',
|
|
date: {
|
|
pickerAppearance: 'dayOnly',
|
|
displayFormat: 'dd.MM.yyyy',
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: 'renewalCycle',
|
|
type: 'select',
|
|
label: 'Erneuerungszyklus',
|
|
options: [
|
|
{ label: 'Jährlich', value: 'yearly' },
|
|
{ label: 'Alle 2 Jahre', value: '2years' },
|
|
{ label: 'Alle 3 Jahre', value: '3years' },
|
|
{ label: 'Alle 5 Jahre', value: '5years' },
|
|
{ label: 'Unbefristet', value: 'unlimited' },
|
|
],
|
|
},
|
|
// Medien
|
|
{
|
|
name: 'logo',
|
|
type: 'upload',
|
|
relationTo: 'media',
|
|
label: 'Zertifikats-Logo/Siegel',
|
|
},
|
|
{
|
|
name: 'certificate',
|
|
type: 'upload',
|
|
relationTo: 'media',
|
|
label: 'Zertifikat (PDF)',
|
|
admin: {
|
|
description: 'Das offizielle Zertifikatsdokument',
|
|
},
|
|
},
|
|
{
|
|
name: 'gallery',
|
|
type: 'array',
|
|
label: 'Weitere Dokumente',
|
|
fields: [
|
|
{
|
|
name: 'document',
|
|
type: 'upload',
|
|
relationTo: 'media',
|
|
label: 'Dokument',
|
|
},
|
|
{
|
|
name: 'title',
|
|
type: 'text',
|
|
label: 'Titel',
|
|
},
|
|
],
|
|
},
|
|
// Geltungsbereich
|
|
{
|
|
name: 'scope',
|
|
type: 'group',
|
|
label: 'Geltungsbereich',
|
|
fields: [
|
|
{
|
|
name: 'description',
|
|
type: 'textarea',
|
|
label: 'Beschreibung des Geltungsbereichs',
|
|
localized: true,
|
|
},
|
|
{
|
|
name: 'locations',
|
|
type: 'relationship',
|
|
relationTo: 'locations',
|
|
hasMany: true,
|
|
label: 'Standorte',
|
|
admin: {
|
|
description: 'Für welche Standorte gilt die Zertifizierung?',
|
|
},
|
|
},
|
|
{
|
|
name: 'services',
|
|
type: 'relationship',
|
|
relationTo: 'services',
|
|
hasMany: true,
|
|
label: 'Leistungen',
|
|
admin: {
|
|
description: 'Für welche Leistungen gilt die Zertifizierung?',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
// Anforderungen & Standards
|
|
{
|
|
name: 'requirements',
|
|
type: 'array',
|
|
label: 'Erfüllte Anforderungen',
|
|
fields: [
|
|
{
|
|
name: 'requirement',
|
|
type: 'text',
|
|
required: true,
|
|
label: 'Anforderung',
|
|
localized: true,
|
|
},
|
|
{
|
|
name: 'description',
|
|
type: 'textarea',
|
|
label: 'Erläuterung',
|
|
localized: true,
|
|
},
|
|
],
|
|
},
|
|
// Vorteile für Kunden
|
|
{
|
|
name: 'benefits',
|
|
type: 'array',
|
|
label: 'Vorteile / Was bedeutet das für Sie?',
|
|
fields: [
|
|
{
|
|
name: 'title',
|
|
type: 'text',
|
|
required: true,
|
|
label: 'Titel',
|
|
localized: true,
|
|
},
|
|
{
|
|
name: 'description',
|
|
type: 'textarea',
|
|
label: 'Beschreibung',
|
|
localized: true,
|
|
},
|
|
{
|
|
name: 'icon',
|
|
type: 'select',
|
|
label: 'Icon',
|
|
options: [
|
|
{ label: 'Häkchen', value: 'check' },
|
|
{ label: 'Stern', value: 'star' },
|
|
{ label: 'Schild', value: 'shield' },
|
|
{ label: 'Herz', value: 'heart' },
|
|
{ label: 'Schloss', value: 'lock' },
|
|
{ label: 'Lupe', value: 'search' },
|
|
{ label: 'Uhr', value: 'clock' },
|
|
{ label: 'Dokument', value: 'document' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
// Audit-Informationen
|
|
{
|
|
name: 'audits',
|
|
type: 'array',
|
|
label: 'Audits / Prüfungen',
|
|
admin: {
|
|
description: 'Historie der durchgeführten Audits',
|
|
},
|
|
fields: [
|
|
{
|
|
name: 'date',
|
|
type: 'date',
|
|
required: true,
|
|
label: 'Datum',
|
|
admin: {
|
|
date: {
|
|
pickerAppearance: 'dayOnly',
|
|
displayFormat: 'dd.MM.yyyy',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: 'type',
|
|
type: 'select',
|
|
label: 'Art',
|
|
options: [
|
|
{ label: 'Erst-Zertifizierung', value: 'initial' },
|
|
{ label: 'Überwachungsaudit', value: 'surveillance' },
|
|
{ label: 'Re-Zertifizierung', value: 'recertification' },
|
|
{ label: 'Sonderaudit', value: 'special' },
|
|
],
|
|
},
|
|
{
|
|
name: 'result',
|
|
type: 'select',
|
|
label: 'Ergebnis',
|
|
options: [
|
|
{ label: 'Bestanden', value: 'passed' },
|
|
{ label: 'Mit Auflagen bestanden', value: 'conditional' },
|
|
{ label: 'Nicht bestanden', value: 'failed' },
|
|
],
|
|
},
|
|
{
|
|
name: 'notes',
|
|
type: 'textarea',
|
|
label: 'Anmerkungen',
|
|
},
|
|
],
|
|
},
|
|
// Status
|
|
{
|
|
name: 'status',
|
|
type: 'select',
|
|
required: true,
|
|
defaultValue: 'active',
|
|
label: 'Status',
|
|
options: [
|
|
{ label: 'Aktiv', value: 'active' },
|
|
{ label: 'In Bearbeitung', value: 'pending' },
|
|
{ label: 'Erneuerung fällig', value: 'renewal' },
|
|
{ label: 'Ausgesetzt', value: 'suspended' },
|
|
{ label: 'Abgelaufen', value: 'expired' },
|
|
{ label: 'Zurückgezogen', value: 'withdrawn' },
|
|
],
|
|
admin: {
|
|
position: 'sidebar',
|
|
},
|
|
},
|
|
// Sichtbarkeit
|
|
{
|
|
name: 'visibility',
|
|
type: 'select',
|
|
defaultValue: 'public',
|
|
label: 'Sichtbarkeit',
|
|
options: [
|
|
{ label: 'Öffentlich', value: 'public' },
|
|
{ label: 'Nur auf Anfrage', value: 'request' },
|
|
{ label: 'Intern', value: 'internal' },
|
|
],
|
|
admin: {
|
|
position: 'sidebar',
|
|
},
|
|
},
|
|
// Priorität für Anzeige
|
|
{
|
|
name: 'priority',
|
|
type: 'number',
|
|
defaultValue: 0,
|
|
label: 'Priorität',
|
|
admin: {
|
|
position: 'sidebar',
|
|
description: 'Höhere Zahl = höhere Priorität in der Anzeige',
|
|
},
|
|
},
|
|
// Auf Startseite anzeigen
|
|
{
|
|
name: 'showOnHomepage',
|
|
type: 'checkbox',
|
|
defaultValue: false,
|
|
label: 'Auf Startseite anzeigen',
|
|
admin: {
|
|
position: 'sidebar',
|
|
},
|
|
},
|
|
// SEO
|
|
{
|
|
name: 'seo',
|
|
type: 'group',
|
|
label: 'SEO',
|
|
fields: [
|
|
{
|
|
name: 'metaTitle',
|
|
type: 'text',
|
|
label: 'Meta-Titel',
|
|
localized: true,
|
|
},
|
|
{
|
|
name: 'metaDescription',
|
|
type: 'textarea',
|
|
label: 'Meta-Beschreibung',
|
|
localized: true,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
timestamps: true,
|
|
hooks: {
|
|
beforeChange: [
|
|
({ data }) => {
|
|
// Auto-generate slug if not provided
|
|
if (data && !data.slug && data.name) {
|
|
data.slug = data.name
|
|
.toLowerCase()
|
|
.replace(/[äöüß]/g, (char: string) => {
|
|
const map: Record<string, string> = { ä: 'ae', ö: 'oe', ü: 'ue', ß: 'ss' }
|
|
return map[char] || char
|
|
})
|
|
.replace(/[^a-z0-9]+/g, '-')
|
|
.replace(/(^-|-$)/g, '')
|
|
}
|
|
return data
|
|
},
|
|
],
|
|
},
|
|
}
|