feat: add JuryMitglieder collection and migration for jury members

- Created a new collection `JuryMitglieder` with fields for name, image, quote, role, organization, bio, website, LinkedIn, sort order, active status, and published date.
- Implemented access control for creating, reading, updating, and deleting jury members.
- Added migration script to create necessary database tables and columns for jury members, including versioning support.
- Updated existing `preistraeger` table to include new columns for award group, winner rank, sort order, and visibility settings.
- Introduced a temporary global switch to control the visibility of testimonials in the SPA.
This commit is contained in:
syntaxbullet
2026-07-07 14:57:15 +02:00
parent 4167730fc2
commit d2fdf8e3c5
25 changed files with 1139 additions and 595 deletions

View File

@@ -24,6 +24,15 @@ const textarea = (name: string, label: string, defaultValue?: string): Field =>
defaultValue,
})
const number = (name: string, label: string, defaultValue: number, description?: string): Field => ({
name,
type: 'number',
label,
defaultValue,
min: 1,
admin: description ? { description } : undefined,
})
const ctaGroup = (name: string, label: string, labelDefault: string, urlDefault: string): Field => ({
name,
label,
@@ -71,16 +80,49 @@ export const preistraegerIndexFields: Field[] = [
admin: sectionAdmin('Label after the selected-year result count.'),
fields: [text('label', 'Count label', preistraegerIndexContent.count.label)],
},
{
name: 'rules',
label: '04 · Gewinnerlogik',
type: 'group',
admin: sectionAdmin('Public page rules for the selected year. Winner records are still managed in the Preisträger collection.'),
fields: [
number('totalWinners', 'Gewinner gesamt', preistraegerIndexContent.rules.totalWinners, 'The public page displays at most this many winners per year.'),
number('goldeneBavariaCount', 'Goldene Bavaria Gewinner', preistraegerIndexContent.rules.goldeneBavariaCount, 'These top-ranked winners are shown in the separate Goldene Bavaria section.'),
],
},
{
name: 'empty',
label: '04 · Empty state',
label: '05 · Empty state',
type: 'group',
admin: sectionAdmin('Message when the selected year returns no winners.'),
fields: [textarea('message', 'Empty message', preistraegerIndexContent.empty.message)],
},
{
name: 'goldeneBavaria',
label: '06 · Goldene Bavaria section',
type: 'group',
admin: sectionAdmin('Copy for the separate section that highlights the best three winners.'),
fields: [
text('eyebrow', 'Eyebrow', preistraegerIndexContent.goldeneBavaria.eyebrow),
textarea('heading', 'Heading', preistraegerIndexContent.goldeneBavaria.heading),
textarea('description', 'Description', preistraegerIndexContent.goldeneBavaria.description),
textarea('emptyMessage', 'Empty message', preistraegerIndexContent.goldeneBavaria.emptyMessage),
],
},
{
name: 'winners',
label: '07 · Winners section',
type: 'group',
admin: sectionAdmin('Copy for the remaining winners below the Goldene Bavaria section.'),
fields: [
text('eyebrow', 'Eyebrow', preistraegerIndexContent.winners.eyebrow),
textarea('heading', 'Heading', preistraegerIndexContent.winners.heading),
textarea('description', 'Description', preistraegerIndexContent.winners.description),
],
},
{
name: 'card',
label: '05 · Winner cards',
label: '08 · Winner cards',
type: 'group',
admin: sectionAdmin('Hover label shown on winner cards.'),
fields: [
@@ -102,7 +144,7 @@ export const preistraegerIndexFields: Field[] = [
},
{
name: 'cta',
label: '06 · Bottom CTA',
label: '09 · Bottom CTA',
type: 'group',
admin: sectionAdmin('Bottom application and membership CTA.'),
fields: [