feat: add Team collection and block

- Add Team collection with comprehensive member profiles
- Support for role, department, bio, contact info, social links
- Qualifications, specializations, and language skills
- Optional link to User account for author attribution
- Add TeamBlock with multiple layouts (grid, list, slider, compact, detailed)
- Filter by department, featured, or manual selection
- Multi-tenant enabled via plugin configuration
- Update documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Martin Porwoll 2025-12-10 07:15:59 +00:00
parent 16be4cf553
commit 261a126f08
9 changed files with 17822 additions and 1 deletions

View file

@ -49,6 +49,7 @@ Internet → 37.24.237.181 → Caddy (443) → Payload (3000)
│ │ ├── Portfolios.ts
│ │ ├── PortfolioCategories.ts
│ │ ├── FAQs.ts
│ │ ├── Team.ts
│ │ ├── EmailLogs.ts
│ │ ├── AuditLogs.ts
│ │ └── ...
@ -402,6 +403,7 @@ SELECT * FROM audit_logs ORDER BY created_at DESC LIMIT 10;
| PortfolioCategories | portfolio-categories | Kategorien für Portfolios |
| Testimonials | testimonials | Kundenbewertungen |
| FAQs | faqs | Häufig gestellte Fragen (FAQ) |
| Team | team | Team-Mitglieder und Mitarbeiter |
| NewsletterSubscribers | newsletter-subscribers | Newsletter mit Double Opt-In |
| SocialLinks | social-links | Social Media Links |
| Forms | forms | Formular-Builder |

266
src/blocks/TeamBlock.ts Normal file
View file

@ -0,0 +1,266 @@
import type { Block } from 'payload'
/**
* Team Block
*
* Zeigt Team-Mitglieder aus der Team Collection.
* Unterstützt verschiedene Layouts und Filteroptionen.
*/
export const TeamBlock: Block = {
slug: 'team-block',
labels: {
singular: 'Team',
plural: 'Team',
},
fields: [
{
name: 'title',
type: 'text',
defaultValue: 'Unser Team',
label: 'Überschrift',
localized: true,
},
{
name: 'subtitle',
type: 'text',
label: 'Untertitel',
localized: true,
},
{
name: 'introduction',
type: 'richText',
label: 'Einleitungstext',
localized: true,
admin: {
description: 'Optionaler Text vor der Team-Anzeige',
},
},
// Auswahl-Modus
{
name: 'displayMode',
type: 'select',
defaultValue: 'all',
label: 'Auswahl',
options: [
{ label: 'Alle aktiven Mitglieder', value: 'all' },
{ label: 'Nur hervorgehobene', value: 'featured' },
{ label: 'Nach Abteilung', value: 'department' },
{ label: 'Handverlesene Auswahl', value: 'selected' },
],
},
{
name: 'department',
type: 'text',
label: 'Abteilung filtern',
admin: {
condition: (data, siblingData) => siblingData?.displayMode === 'department',
description: 'Zeigt nur Mitglieder dieser Abteilung',
},
},
{
name: 'selectedMembers',
type: 'relationship',
// eslint-disable-next-line @typescript-eslint/no-explicit-any
relationTo: 'team' as any,
hasMany: true,
label: 'Team-Mitglieder auswählen',
admin: {
condition: (data, siblingData) => siblingData?.displayMode === 'selected',
},
},
{
name: 'limit',
type: 'number',
defaultValue: 12,
min: 1,
max: 50,
label: 'Maximale Anzahl',
admin: {
condition: (data, siblingData) =>
siblingData?.displayMode === 'all' || siblingData?.displayMode === 'department',
},
},
// Layout
{
name: 'layout',
type: 'select',
defaultValue: 'grid',
label: 'Layout',
options: [
{ label: 'Grid (Karten)', value: 'grid' },
{ label: 'Liste', value: 'list' },
{ label: 'Slider/Karussell', value: 'slider' },
{ label: 'Kompakt (nur Foto + Name)', value: 'compact' },
{ label: 'Detailliert (mit Bio)', value: 'detailed' },
],
},
{
name: 'columns',
type: 'select',
defaultValue: '3',
label: 'Spalten',
options: [
{ label: '2 Spalten', value: '2' },
{ label: '3 Spalten', value: '3' },
{ label: '4 Spalten', value: '4' },
],
admin: {
condition: (data, siblingData) =>
siblingData?.layout === 'grid' || siblingData?.layout === 'compact',
},
},
// Anzeigeoptionen
{
name: 'showRole',
type: 'checkbox',
defaultValue: true,
label: 'Position/Rolle anzeigen',
},
{
name: 'showDepartment',
type: 'checkbox',
defaultValue: false,
label: 'Abteilung anzeigen',
},
{
name: 'showBio',
type: 'checkbox',
defaultValue: true,
label: 'Biografie anzeigen',
admin: {
condition: (data, siblingData) =>
siblingData?.layout !== 'compact',
},
},
{
name: 'showContact',
type: 'checkbox',
defaultValue: false,
label: 'Kontaktdaten anzeigen',
admin: {
description: 'Nur wenn beim Mitglied "Kontaktdaten öffentlich anzeigen" aktiviert ist',
},
},
{
name: 'showSocialLinks',
type: 'checkbox',
defaultValue: true,
label: 'Social Media Links anzeigen',
},
{
name: 'showQualifications',
type: 'checkbox',
defaultValue: false,
label: 'Qualifikationen anzeigen',
admin: {
condition: (data, siblingData) =>
siblingData?.layout === 'detailed' || siblingData?.layout === 'list',
},
},
{
name: 'showSpecializations',
type: 'checkbox',
defaultValue: false,
label: 'Fachgebiete anzeigen',
},
{
name: 'showLanguages',
type: 'checkbox',
defaultValue: false,
label: 'Sprachkenntnisse anzeigen',
},
// Gruppierung
{
name: 'groupByDepartment',
type: 'checkbox',
defaultValue: false,
label: 'Nach Abteilung gruppieren',
admin: {
condition: (data, siblingData) =>
siblingData?.displayMode !== 'department' && siblingData?.layout !== 'slider',
},
},
// Slider-Optionen
{
name: 'autoplay',
type: 'checkbox',
defaultValue: true,
label: 'Automatisch wechseln',
admin: {
condition: (data, siblingData) => siblingData?.layout === 'slider',
},
},
{
name: 'autoplaySpeed',
type: 'number',
defaultValue: 5000,
min: 2000,
max: 15000,
label: 'Wechselintervall (ms)',
admin: {
condition: (data, siblingData) =>
siblingData?.layout === 'slider' && siblingData?.autoplay,
},
},
// Detail-Ansicht
{
name: 'enableDetailView',
type: 'checkbox',
defaultValue: false,
label: 'Detail-Ansicht aktivieren',
admin: {
description: 'Klick auf Mitglied öffnet Modal/Lightbox mit allen Details',
},
},
// Styling
{
name: 'imageStyle',
type: 'select',
defaultValue: 'rounded',
label: 'Foto-Stil',
options: [
{ label: 'Rund', value: 'circle' },
{ label: 'Abgerundet', value: 'rounded' },
{ label: 'Eckig', value: 'square' },
],
},
{
name: 'backgroundColor',
type: 'select',
defaultValue: 'white',
label: 'Hintergrund',
options: [
{ label: 'Weiß', value: 'white' },
{ label: 'Hell (Grau)', value: 'light' },
{ label: 'Dunkel', value: 'dark' },
{ label: 'Akzentfarbe', value: 'accent' },
],
},
// CTA
{
name: 'showCTA',
type: 'checkbox',
defaultValue: false,
label: 'CTA-Button anzeigen',
},
{
name: 'ctaText',
type: 'text',
defaultValue: 'Jetzt bewerben',
label: 'CTA Text',
localized: true,
admin: {
condition: (data, siblingData) => siblingData?.showCTA,
},
},
{
name: 'ctaLink',
type: 'text',
defaultValue: '/karriere',
label: 'CTA Link',
admin: {
condition: (data, siblingData) => siblingData?.showCTA,
},
},
],
}

View file

@ -15,3 +15,4 @@ export { TestimonialsBlock } from './TestimonialsBlock'
export { NewsletterBlock } from './NewsletterBlock'
export { ProcessStepsBlock } from './ProcessStepsBlock'
export { FAQBlock } from './FAQBlock'
export { TeamBlock } from './TeamBlock'

View file

@ -16,6 +16,7 @@ import {
NewsletterBlock,
ProcessStepsBlock,
FAQBlock,
TeamBlock,
} from '../blocks'
export const Pages: CollectionConfig = {
@ -99,6 +100,7 @@ export const Pages: CollectionConfig = {
NewsletterBlock,
ProcessStepsBlock,
FAQBlock,
TeamBlock,
],
},
{

277
src/collections/Team.ts Normal file
View file

@ -0,0 +1,277 @@
// src/collections/Team.ts
import type { CollectionConfig } from 'payload'
import { authenticatedOnly, tenantScopedPublicRead } from '../lib/tenantAccess'
/**
* Team Collection
*
* Mitarbeiter und Team-Mitglieder, wiederverwendbar auf allen Seiten.
* Tenant-scoped für Multi-Tenant-Betrieb.
*/
export const Team: CollectionConfig = {
slug: 'team',
admin: {
useAsTitle: 'name',
group: 'Content',
defaultColumns: ['name', 'role', 'department', 'order', 'isActive'],
description: 'Team-Mitglieder und Mitarbeiter',
},
access: {
read: tenantScopedPublicRead,
create: authenticatedOnly,
update: authenticatedOnly,
delete: authenticatedOnly,
},
fields: [
// Basis-Informationen
{
name: 'name',
type: 'text',
required: true,
label: 'Name',
admin: {
description: 'Vollständiger Name',
},
},
{
name: 'role',
type: 'text',
required: true,
label: 'Position/Rolle',
localized: true,
admin: {
description: 'z.B. "Geschäftsführer", "Pflegedienstleitung", "Fotograf"',
},
},
{
name: 'department',
type: 'text',
label: 'Abteilung',
localized: true,
admin: {
description: 'z.B. "Verwaltung", "Pflege", "Marketing"',
},
},
{
name: 'image',
type: 'upload',
relationTo: 'media',
label: 'Foto',
admin: {
description: 'Portrait-Foto (empfohlen: quadratisch, min. 400x400px)',
},
},
{
name: 'bio',
type: 'richText',
label: 'Biografie',
localized: true,
admin: {
description: 'Kurze Beschreibung zur Person',
},
},
{
name: 'bioShort',
type: 'textarea',
label: 'Kurzbiografie',
localized: true,
admin: {
description: 'Ein-Satz-Beschreibung für kompakte Darstellung',
},
},
// Kontaktdaten
{
type: 'collapsible',
label: 'Kontaktdaten',
admin: {
initCollapsed: true,
},
fields: [
{
name: 'email',
type: 'email',
label: 'E-Mail',
admin: {
description: 'Öffentliche Kontakt-E-Mail (optional)',
},
},
{
name: 'phone',
type: 'text',
label: 'Telefon',
admin: {
description: 'Öffentliche Telefonnummer (optional)',
},
},
{
name: 'showContactInfo',
type: 'checkbox',
defaultValue: false,
label: 'Kontaktdaten öffentlich anzeigen',
},
],
},
// Social Links
{
name: 'socialLinks',
type: 'array',
label: 'Social Media',
admin: {
initCollapsed: true,
},
fields: [
{
name: 'platform',
type: 'select',
required: true,
label: 'Plattform',
options: [
{ label: 'LinkedIn', value: 'linkedin' },
{ label: 'Xing', value: 'xing' },
{ label: 'Twitter/X', value: 'twitter' },
{ label: 'Instagram', value: 'instagram' },
{ label: 'Facebook', value: 'facebook' },
{ label: 'Website', value: 'website' },
{ label: 'GitHub', value: 'github' },
],
},
{
name: 'url',
type: 'text',
required: true,
label: 'URL',
},
],
},
// Qualifikationen
{
name: 'qualifications',
type: 'array',
label: 'Qualifikationen',
admin: {
initCollapsed: true,
description: 'Ausbildungen, Zertifikate, Abschlüsse',
},
fields: [
{
name: 'title',
type: 'text',
required: true,
label: 'Bezeichnung',
localized: true,
},
{
name: 'year',
type: 'number',
label: 'Jahr',
min: 1950,
max: 2100,
},
{
name: 'institution',
type: 'text',
label: 'Institution',
},
],
},
// Fachgebiete
{
name: 'specializations',
type: 'array',
label: 'Fachgebiete/Schwerpunkte',
admin: {
initCollapsed: true,
},
fields: [
{
name: 'title',
type: 'text',
required: true,
label: 'Fachgebiet',
localized: true,
},
],
},
// Sprachen (besonders für C2S/Pflege relevant)
{
name: 'languages',
type: 'array',
label: 'Sprachkenntnisse',
admin: {
initCollapsed: true,
},
fields: [
{
name: 'language',
type: 'text',
required: true,
label: 'Sprache',
localized: true,
},
{
name: 'level',
type: 'select',
label: 'Niveau',
options: [
{ label: 'Muttersprache', value: 'native' },
{ label: 'Fließend', value: 'fluent' },
{ label: 'Gut', value: 'good' },
{ label: 'Grundkenntnisse', value: 'basic' },
],
},
],
},
// Verknüpfung mit User (optional)
{
name: 'linkedUser',
type: 'relationship',
relationTo: 'users',
label: 'Verknüpfter Benutzer',
admin: {
position: 'sidebar',
description: 'Optional: Verknüpfung mit Login-User (z.B. für Autoren-Zuordnung)',
},
},
// Status & Sortierung
{
name: 'isActive',
type: 'checkbox',
defaultValue: true,
label: 'Aktiv/Sichtbar',
admin: {
position: 'sidebar',
description: 'Inaktive Mitglieder werden nicht angezeigt',
},
},
{
name: 'isFeatured',
type: 'checkbox',
defaultValue: false,
label: 'Hervorgehoben',
admin: {
position: 'sidebar',
description: 'Für Startseiten-Anzeige oder besondere Hervorhebung',
},
},
{
name: 'order',
type: 'number',
defaultValue: 0,
label: 'Sortierung',
admin: {
position: 'sidebar',
description: 'Niedrigere Zahlen werden zuerst angezeigt',
},
},
{
name: 'startDate',
type: 'date',
label: 'Im Team seit',
admin: {
position: 'sidebar',
description: 'Eintrittsdatum (optional)',
},
},
],
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,209 @@
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
await db.execute(sql`
CREATE TYPE "public"."enum_pages_blocks_team_block_display_mode" AS ENUM('all', 'featured', 'department', 'selected');
CREATE TYPE "public"."enum_pages_blocks_team_block_layout" AS ENUM('grid', 'list', 'slider', 'compact', 'detailed');
CREATE TYPE "public"."enum_pages_blocks_team_block_columns" AS ENUM('2', '3', '4');
CREATE TYPE "public"."enum_pages_blocks_team_block_image_style" AS ENUM('circle', 'rounded', 'square');
CREATE TYPE "public"."enum_pages_blocks_team_block_background_color" AS ENUM('white', 'light', 'dark', 'accent');
CREATE TYPE "public"."enum_team_social_links_platform" AS ENUM('linkedin', 'xing', 'twitter', 'instagram', 'facebook', 'website', 'github');
CREATE TYPE "public"."enum_team_languages_level" AS ENUM('native', 'fluent', 'good', 'basic');
CREATE TABLE "pages_blocks_team_block" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"_path" text NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"display_mode" "enum_pages_blocks_team_block_display_mode" DEFAULT 'all',
"department" varchar,
"limit" numeric DEFAULT 12,
"layout" "enum_pages_blocks_team_block_layout" DEFAULT 'grid',
"columns" "enum_pages_blocks_team_block_columns" DEFAULT '3',
"show_role" boolean DEFAULT true,
"show_department" boolean DEFAULT false,
"show_bio" boolean DEFAULT true,
"show_contact" boolean DEFAULT false,
"show_social_links" boolean DEFAULT true,
"show_qualifications" boolean DEFAULT false,
"show_specializations" boolean DEFAULT false,
"show_languages" boolean DEFAULT false,
"group_by_department" boolean DEFAULT false,
"autoplay" boolean DEFAULT true,
"autoplay_speed" numeric DEFAULT 5000,
"enable_detail_view" boolean DEFAULT false,
"image_style" "enum_pages_blocks_team_block_image_style" DEFAULT 'rounded',
"background_color" "enum_pages_blocks_team_block_background_color" DEFAULT 'white',
"show_c_t_a" boolean DEFAULT false,
"cta_link" varchar DEFAULT '/karriere',
"block_name" varchar
);
CREATE TABLE "pages_blocks_team_block_locales" (
"title" varchar DEFAULT 'Unser Team',
"subtitle" varchar,
"introduction" jsonb,
"cta_text" varchar DEFAULT 'Jetzt bewerben',
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "team_social_links" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"platform" "enum_team_social_links_platform" NOT NULL,
"url" varchar NOT NULL
);
CREATE TABLE "team_qualifications" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"year" numeric,
"institution" varchar
);
CREATE TABLE "team_qualifications_locales" (
"title" varchar NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "team_specializations" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"id" varchar PRIMARY KEY NOT NULL
);
CREATE TABLE "team_specializations_locales" (
"title" varchar NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "team_languages" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"level" "enum_team_languages_level"
);
CREATE TABLE "team_languages_locales" (
"language" varchar NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "team" (
"id" serial PRIMARY KEY NOT NULL,
"tenant_id" integer,
"name" varchar NOT NULL,
"image_id" integer,
"email" varchar,
"phone" varchar,
"show_contact_info" boolean DEFAULT false,
"linked_user_id" integer,
"is_active" boolean DEFAULT true,
"is_featured" boolean DEFAULT false,
"order" numeric DEFAULT 0,
"start_date" timestamp(3) with time zone,
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
);
CREATE TABLE "team_locales" (
"role" varchar NOT NULL,
"department" varchar,
"bio" jsonb,
"bio_short" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" integer NOT NULL
);
ALTER TABLE "pages_rels" ADD COLUMN "team_id" integer;
ALTER TABLE "payload_locked_documents_rels" ADD COLUMN "team_id" integer;
ALTER TABLE "pages_blocks_team_block" ADD CONSTRAINT "pages_blocks_team_block_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_team_block_locales" ADD CONSTRAINT "pages_blocks_team_block_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_team_block"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "team_social_links" ADD CONSTRAINT "team_social_links_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "team_qualifications" ADD CONSTRAINT "team_qualifications_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "team_qualifications_locales" ADD CONSTRAINT "team_qualifications_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team_qualifications"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "team_specializations" ADD CONSTRAINT "team_specializations_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "team_specializations_locales" ADD CONSTRAINT "team_specializations_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team_specializations"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "team_languages" ADD CONSTRAINT "team_languages_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "team_languages_locales" ADD CONSTRAINT "team_languages_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team_languages"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "team" ADD CONSTRAINT "team_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE set null ON UPDATE no action;
ALTER TABLE "team" ADD CONSTRAINT "team_image_id_media_id_fk" FOREIGN KEY ("image_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
ALTER TABLE "team" ADD CONSTRAINT "team_linked_user_id_users_id_fk" FOREIGN KEY ("linked_user_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
ALTER TABLE "team_locales" ADD CONSTRAINT "team_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team"("id") ON DELETE cascade ON UPDATE no action;
CREATE INDEX "pages_blocks_team_block_order_idx" ON "pages_blocks_team_block" USING btree ("_order");
CREATE INDEX "pages_blocks_team_block_parent_id_idx" ON "pages_blocks_team_block" USING btree ("_parent_id");
CREATE INDEX "pages_blocks_team_block_path_idx" ON "pages_blocks_team_block" USING btree ("_path");
CREATE UNIQUE INDEX "pages_blocks_team_block_locales_locale_parent_id_unique" ON "pages_blocks_team_block_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "team_social_links_order_idx" ON "team_social_links" USING btree ("_order");
CREATE INDEX "team_social_links_parent_id_idx" ON "team_social_links" USING btree ("_parent_id");
CREATE INDEX "team_qualifications_order_idx" ON "team_qualifications" USING btree ("_order");
CREATE INDEX "team_qualifications_parent_id_idx" ON "team_qualifications" USING btree ("_parent_id");
CREATE UNIQUE INDEX "team_qualifications_locales_locale_parent_id_unique" ON "team_qualifications_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "team_specializations_order_idx" ON "team_specializations" USING btree ("_order");
CREATE INDEX "team_specializations_parent_id_idx" ON "team_specializations" USING btree ("_parent_id");
CREATE UNIQUE INDEX "team_specializations_locales_locale_parent_id_unique" ON "team_specializations_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "team_languages_order_idx" ON "team_languages" USING btree ("_order");
CREATE INDEX "team_languages_parent_id_idx" ON "team_languages" USING btree ("_parent_id");
CREATE UNIQUE INDEX "team_languages_locales_locale_parent_id_unique" ON "team_languages_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "team_tenant_idx" ON "team" USING btree ("tenant_id");
CREATE INDEX "team_image_idx" ON "team" USING btree ("image_id");
CREATE INDEX "team_linked_user_idx" ON "team" USING btree ("linked_user_id");
CREATE INDEX "team_updated_at_idx" ON "team" USING btree ("updated_at");
CREATE INDEX "team_created_at_idx" ON "team" USING btree ("created_at");
CREATE UNIQUE INDEX "team_locales_locale_parent_id_unique" ON "team_locales" USING btree ("_locale","_parent_id");
ALTER TABLE "pages_rels" ADD CONSTRAINT "pages_rels_team_fk" FOREIGN KEY ("team_id") REFERENCES "public"."team"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_team_fk" FOREIGN KEY ("team_id") REFERENCES "public"."team"("id") ON DELETE cascade ON UPDATE no action;
CREATE INDEX "pages_rels_team_id_idx" ON "pages_rels" USING btree ("team_id");
CREATE INDEX "payload_locked_documents_rels_team_id_idx" ON "payload_locked_documents_rels" USING btree ("team_id");`)
}
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
await db.execute(sql`
ALTER TABLE "pages_blocks_team_block" DISABLE ROW LEVEL SECURITY;
ALTER TABLE "pages_blocks_team_block_locales" DISABLE ROW LEVEL SECURITY;
ALTER TABLE "team_social_links" DISABLE ROW LEVEL SECURITY;
ALTER TABLE "team_qualifications" DISABLE ROW LEVEL SECURITY;
ALTER TABLE "team_qualifications_locales" DISABLE ROW LEVEL SECURITY;
ALTER TABLE "team_specializations" DISABLE ROW LEVEL SECURITY;
ALTER TABLE "team_specializations_locales" DISABLE ROW LEVEL SECURITY;
ALTER TABLE "team_languages" DISABLE ROW LEVEL SECURITY;
ALTER TABLE "team_languages_locales" DISABLE ROW LEVEL SECURITY;
ALTER TABLE "team" DISABLE ROW LEVEL SECURITY;
ALTER TABLE "team_locales" DISABLE ROW LEVEL SECURITY;
DROP TABLE "pages_blocks_team_block" CASCADE;
DROP TABLE "pages_blocks_team_block_locales" CASCADE;
DROP TABLE "team_social_links" CASCADE;
DROP TABLE "team_qualifications" CASCADE;
DROP TABLE "team_qualifications_locales" CASCADE;
DROP TABLE "team_specializations" CASCADE;
DROP TABLE "team_specializations_locales" CASCADE;
DROP TABLE "team_languages" CASCADE;
DROP TABLE "team_languages_locales" CASCADE;
DROP TABLE "team" CASCADE;
DROP TABLE "team_locales" CASCADE;
ALTER TABLE "pages_rels" DROP CONSTRAINT "pages_rels_team_fk";
ALTER TABLE "payload_locked_documents_rels" DROP CONSTRAINT "payload_locked_documents_rels_team_fk";
DROP INDEX "pages_rels_team_id_idx";
DROP INDEX "payload_locked_documents_rels_team_id_idx";
ALTER TABLE "pages_rels" DROP COLUMN "team_id";
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN "team_id";
DROP TYPE "public"."enum_pages_blocks_team_block_display_mode";
DROP TYPE "public"."enum_pages_blocks_team_block_layout";
DROP TYPE "public"."enum_pages_blocks_team_block_columns";
DROP TYPE "public"."enum_pages_blocks_team_block_image_style";
DROP TYPE "public"."enum_pages_blocks_team_block_background_color";
DROP TYPE "public"."enum_team_social_links_platform";
DROP TYPE "public"."enum_team_languages_level";`)
}

View file

@ -5,6 +5,7 @@ import * as migration_20251206_134750_tenant_email_config from './20251206_13475
import * as migration_20251206_141403_email_logs_collection from './20251206_141403_email_logs_collection';
import * as migration_20251207_205727_audit_logs_collection from './20251207_205727_audit_logs_collection';
import * as migration_20251210_052757_add_faqs_collection from './20251210_052757_add_faqs_collection';
import * as migration_20251210_071506_add_team_collection from './20251210_071506_add_team_collection';
export const migrations = [
{
@ -40,6 +41,11 @@ export const migrations = [
{
up: migration_20251210_052757_add_faqs_collection.up,
down: migration_20251210_052757_add_faqs_collection.down,
name: '20251210_052757_add_faqs_collection'
name: '20251210_052757_add_faqs_collection',
},
{
up: migration_20251210_071506_add_team_collection.up,
down: migration_20251210_071506_add_team_collection.down,
name: '20251210_071506_add_team_collection'
},
];

View file

@ -24,6 +24,7 @@ import { Categories } from './collections/Categories'
import { SocialLinks } from './collections/SocialLinks'
import { Testimonials } from './collections/Testimonials'
import { FAQs } from './collections/FAQs'
import { Team } from './collections/Team'
import { NewsletterSubscribers } from './collections/NewsletterSubscribers'
// Portfolio Collections
@ -130,6 +131,7 @@ export default buildConfig({
SocialLinks,
Testimonials,
FAQs,
Team,
NewsletterSubscribers,
// Portfolio
PortfolioCategories,
@ -172,6 +174,7 @@ export default buildConfig({
...({
testimonials: {},
faqs: {},
team: {},
'newsletter-subscribers': {},
// Portfolio Collections
'portfolio-categories': {},