diff --git a/src/app/(home)/layout.tsx b/src/app/(home)/layout.tsx index ae83975..57f5f69 100644 --- a/src/app/(home)/layout.tsx +++ b/src/app/(home)/layout.tsx @@ -6,23 +6,41 @@ import { comment } from '@/app/(home)/layout-comment' import { FONT_MAP, getFont } from '@/assets/fonts' import { siteConfig } from '@/config/site' import { fetchDesign } from '@/fetch/design' +import { fetchSiteConfig } from '@/fetch/siteConfig' -export const metadata: Metadata = { - title: { - default: siteConfig.name, - template: `%s | ${siteConfig.shortName}`, - }, - description: siteConfig.description, - keywords: siteConfig.keywords, - openGraph: { - title: siteConfig.name, - description: siteConfig.description, - url: siteConfig.url, - siteName: siteConfig.name, - images: [siteConfig.ogImage], - locale: 'de_DE', - type: 'website', - }, +export async function generateMetadata(): Promise { + let site + try { + site = await fetchSiteConfig() + } catch { + site = null + } + + const name = site?.name || siteConfig.name + const shortName = site?.shortName || siteConfig.shortName + const description = site?.description || siteConfig.description + const url = site?.url || siteConfig.url + const ogImage = site?.ogImage || siteConfig.ogImage + const keywords = + site?.keywords?.map((k) => k.keyword) || siteConfig.keywords + + return { + title: { + default: name, + template: `%s | ${shortName}`, + }, + description, + keywords, + openGraph: { + title: name, + description, + url, + siteName: name, + images: [ogImage], + locale: 'de_DE', + type: 'website', + }, + } } const DESIGN_DEFAULTS = { diff --git a/src/collections/blocks/Contactform.ts b/src/collections/blocks/Contactform.ts index 5e9b5d0..7a3b8bc 100644 --- a/src/collections/blocks/Contactform.ts +++ b/src/collections/blocks/Contactform.ts @@ -33,8 +33,13 @@ export const ContactformBlock: Block = { { name: 'email', type: 'email', - defaultValue: siteConfig.email, - required: true + defaultValue: async ({ req }) => { + const config = await req.payload.findGlobal({ + slug: 'site-config', + }) + return config?.email || siteConfig.email + }, + required: true, } ] } \ No newline at end of file diff --git a/src/fetch/siteConfig.ts b/src/fetch/siteConfig.ts new file mode 100644 index 0000000..9b45a14 --- /dev/null +++ b/src/fetch/siteConfig.ts @@ -0,0 +1,16 @@ +import { SiteConfig } from '@/payload-types' + +export async function fetchSiteConfig(): Promise { + const res = await fetch( + 'http://localhost:3000/api/globals/site-config', + { + next: { tags: ['site-config'] }, + }, + ) + + if (!res.ok) { + throw new Error('Could not fetch site-config') + } + + return res.json() +} diff --git a/src/globals/SiteConfig.ts b/src/globals/SiteConfig.ts new file mode 100644 index 0000000..f760d78 --- /dev/null +++ b/src/globals/SiteConfig.ts @@ -0,0 +1,102 @@ +import { GlobalConfig } from 'payload' +import { isAdmin } from '@/collections/access/admin' +import { revalidateTag } from 'next/cache' + +export const SiteConfigGlobal: GlobalConfig = { + slug: 'site-config', + label: { + de: 'Website-Einstellungen', + }, + admin: { + description: + 'Hier können Sie den Namen, die Beschreibung und andere allgemeine Einstellungen der Website konfigurieren.', + }, + fields: [ + { + name: 'name', + type: 'text', + label: { de: 'Name der Pfarrei' }, + required: true, + defaultValue: + 'Katholische Pfarrei Heilige Drei Könige Berlin', + }, + { + name: 'shortName', + type: 'text', + label: { de: 'Kurzname' }, + required: true, + defaultValue: 'Hl. Drei Könige', + admin: { + description: + 'Wird im Browser-Tab als Suffix verwendet (z.B. "Seite | Hl. Drei Könige").', + }, + }, + { + name: 'description', + type: 'textarea', + label: { de: 'Beschreibung' }, + required: true, + defaultValue: + 'Katholische Pfarrei Heilige Drei Könige in Berlin – Gottesdienste, Veranstaltungen, Sakramente und Gemeindeleben.', + admin: { + description: 'Meta-Beschreibung für Suchmaschinen.', + }, + }, + { + name: 'url', + type: 'text', + label: { de: 'Website-URL' }, + required: true, + defaultValue: 'https://dreikoenige.berlin', + }, + { + name: 'ogImage', + type: 'text', + label: { de: 'Open Graph Bild' }, + defaultValue: '/og-logo.svg', + admin: { + description: + 'Pfad zum Vorschaubild für soziale Medien.', + }, + }, + { + name: 'email', + type: 'email', + label: { de: 'Kontakt-E-Mail' }, + required: true, + defaultValue: 'kontakt@dreikoenige.berlin', + admin: { + description: + 'Standard-E-Mail-Adresse für Kontaktformulare.', + }, + }, + { + name: 'keywords', + type: 'array', + label: { de: 'Schlüsselwörter' }, + labels: { + singular: { de: 'Schlüsselwort' }, + plural: { de: 'Schlüsselwörter' }, + }, + admin: { + description: + 'SEO-Schlüsselwörter für Suchmaschinen.', + }, + fields: [ + { + name: 'keyword', + type: 'text', + required: true, + label: { de: 'Schlüsselwort' }, + }, + ], + }, + ], + access: { + read: () => true, + update: isAdmin(), + }, + hooks: { + afterChange: [() => revalidateTag('site-config')], + }, +} diff --git a/src/payload-types.ts b/src/payload-types.ts index 14ea947..cc8ab43 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -127,11 +127,13 @@ export interface Config { menu: Menu; footer: Footer; design: Design; + 'site-config': SiteConfig; }; globalsSelect: { menu: MenuSelect | MenuSelect; footer: FooterSelect | FooterSelect; design: DesignSelect | DesignSelect; + 'site-config': SiteConfigSelect | SiteConfigSelect; }; locale: null; user: User & { @@ -1956,6 +1958,44 @@ export interface Design { updatedAt?: string | null; createdAt?: string | null; } +/** + * Hier können Sie den Namen, die Beschreibung und andere allgemeine Einstellungen der Website konfigurieren. + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "site-config". + */ +export interface SiteConfig { + id: string; + name: string; + /** + * Wird im Browser-Tab als Suffix verwendet (z.B. "Seite | Hl. Drei Könige"). + */ + shortName: string; + /** + * Meta-Beschreibung für Suchmaschinen. + */ + description: string; + url: string; + /** + * Pfad zum Vorschaubild für soziale Medien. + */ + ogImage?: string | null; + /** + * Standard-E-Mail-Adresse für Kontaktformulare. + */ + email: string; + /** + * SEO-Schlüsselwörter für Suchmaschinen. + */ + keywords?: + | { + keyword: string; + id?: string | null; + }[] + | null; + updatedAt?: string | null; + createdAt?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "menu_select". @@ -2077,6 +2117,27 @@ export interface DesignSelect { createdAt?: T; globalType?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "site-config_select". + */ +export interface SiteConfigSelect { + name?: T; + shortName?: T; + description?: T; + url?: T; + ogImage?: T; + email?: T; + keywords?: + | T + | { + keyword?: T; + id?: T; + }; + updatedAt?: T; + createdAt?: T; + globalType?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth". diff --git a/src/payload.config.ts b/src/payload.config.ts index 6f026cb..770355c 100644 --- a/src/payload.config.ts +++ b/src/payload.config.ts @@ -39,6 +39,7 @@ import { Classifieds } from '@/collections/Classifieds' import { MenuGlobal } from '@/globals/Menu' import { FooterGlobal } from '@/globals/Footer' import { DesignGlobal } from '@/globals/Design' +import { SiteConfigGlobal } from '@/globals/SiteConfig' import { Magazine } from '@/collections/Magazine' import { DonationForms } from '@/collections/DonationForms' import { Pages } from '@/collections/Pages' @@ -107,6 +108,7 @@ export default buildConfig({ MenuGlobal, FooterGlobal, DesignGlobal, + SiteConfigGlobal, ], graphQL: { disable: true