feat: manage generic page fallback copy via payload
This commit is contained in:
33
src/SiteSettings/config.ts
Normal file
33
src/SiteSettings/config.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import type { GlobalConfig } from 'payload'
|
||||
|
||||
import { defaultSiteSettings } from '@/spa/siteSettings'
|
||||
|
||||
export const SiteSettings: GlobalConfig = {
|
||||
slug: 'site-settings',
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
admin: {
|
||||
group: 'Site Settings',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'genericPageKicker',
|
||||
type: 'text',
|
||||
defaultValue: defaultSiteSettings.genericPageKicker,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'genericPageTitle',
|
||||
type: 'text',
|
||||
defaultValue: defaultSiteSettings.genericPageTitle,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'genericPageDescription',
|
||||
type: 'textarea',
|
||||
defaultValue: defaultSiteSettings.genericPageDescription,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import { notFound } from 'next/navigation'
|
||||
import NextApp from '@/spa/NextApp'
|
||||
import { normalizeFooterData, normalizeHeaderData } from '@/spa/cmsNavigation'
|
||||
import type { CmsRouteDoc } from '@/spa/cmsRoute'
|
||||
import { normalizeSiteSettings, type SpaSiteSettingsData } from '@/spa/siteSettings'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
@@ -73,9 +74,10 @@ export default async function Page({ params }: Args) {
|
||||
const pathname = `/${slug.join('/')}`.replace(/\/$/, '') || '/'
|
||||
const payload = await getPayload({ config: configPromise })
|
||||
const { isEnabled: draft } = await draftMode()
|
||||
const [header, footer, route, preistraeger, events, posts] = await Promise.all([
|
||||
const [header, footer, siteSettings, route, preistraeger, events, posts] = await Promise.all([
|
||||
payload.findGlobal({ slug: 'header', depth: 1 }).catch(() => undefined),
|
||||
payload.findGlobal({ slug: 'footer', depth: 1 }).catch(() => undefined),
|
||||
payload.findGlobal({ slug: 'site-settings', depth: 0 }).catch(() => undefined),
|
||||
findRouteDoc(payload, pathname, draft),
|
||||
findList(payload, 'preistraeger', draft).catch(() => []),
|
||||
findList(payload, 'events', draft).catch(() => []),
|
||||
@@ -89,6 +91,7 @@ export default async function Page({ params }: Args) {
|
||||
pathname={pathname}
|
||||
header={normalizeHeaderData(header)}
|
||||
footer={normalizeFooterData(footer)}
|
||||
siteSettings={normalizeSiteSettings(siteSettings as Partial<SpaSiteSettingsData> | undefined)}
|
||||
cmsRoute={{
|
||||
collection: route.collection,
|
||||
doc: route.doc as unknown as CmsRouteDoc,
|
||||
|
||||
@@ -10,6 +10,7 @@ import { post1 } from './post-1'
|
||||
import { post2 } from './post-2'
|
||||
import { post3 } from './post-3'
|
||||
import { defaultFooterData, defaultHeaderData } from '@/spa/cmsNavigation'
|
||||
import { defaultSiteSettings } from '@/spa/siteSettings'
|
||||
|
||||
const collections: CollectionSlug[] = [
|
||||
'categories',
|
||||
@@ -21,7 +22,7 @@ const collections: CollectionSlug[] = [
|
||||
'search',
|
||||
]
|
||||
|
||||
const globals: GlobalSlug[] = ['header', 'footer']
|
||||
const globals: GlobalSlug[] = ['header', 'footer', 'site-settings']
|
||||
|
||||
const categories = ['Technology', 'News', 'Finance', 'Design', 'Software', 'Engineering']
|
||||
|
||||
@@ -228,6 +229,10 @@ export const seed = async ({
|
||||
slug: 'footer',
|
||||
data: footerSeedData as never,
|
||||
}),
|
||||
payload.updateGlobal({
|
||||
slug: 'site-settings',
|
||||
data: defaultSiteSettings as never,
|
||||
}),
|
||||
])
|
||||
|
||||
payload.logger.info('Seeded database successfully!')
|
||||
|
||||
@@ -116,10 +116,12 @@ export interface Config {
|
||||
globals: {
|
||||
header: Header;
|
||||
footer: Footer;
|
||||
'site-settings': SiteSetting;
|
||||
};
|
||||
globalsSelect: {
|
||||
header: HeaderSelect<false> | HeaderSelect<true>;
|
||||
footer: FooterSelect<false> | FooterSelect<true>;
|
||||
'site-settings': SiteSettingsSelect<false> | SiteSettingsSelect<true>;
|
||||
};
|
||||
locale: null;
|
||||
widgets: {
|
||||
@@ -5886,6 +5888,18 @@ export interface Footer {
|
||||
updatedAt?: string | null;
|
||||
createdAt?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "site-settings".
|
||||
*/
|
||||
export interface SiteSetting {
|
||||
id: number;
|
||||
genericPageKicker: string;
|
||||
genericPageTitle: string;
|
||||
genericPageDescription: string;
|
||||
updatedAt?: string | null;
|
||||
createdAt?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "header_select".
|
||||
@@ -6007,6 +6021,18 @@ export interface FooterSelect<T extends boolean = true> {
|
||||
createdAt?: T;
|
||||
globalType?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "site-settings_select".
|
||||
*/
|
||||
export interface SiteSettingsSelect<T extends boolean = true> {
|
||||
genericPageKicker?: T;
|
||||
genericPageTitle?: T;
|
||||
genericPageDescription?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
globalType?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "collections_widget".
|
||||
|
||||
@@ -14,6 +14,7 @@ import { Users } from './collections/Users'
|
||||
import { Footer } from './Footer/config'
|
||||
import { Header } from './Header/config'
|
||||
import { plugins } from './plugins'
|
||||
import { SiteSettings } from './SiteSettings/config'
|
||||
import { defaultLexical } from '@/fields/defaultLexical'
|
||||
import { getServerSideURL } from './utilities/getURL'
|
||||
|
||||
@@ -66,7 +67,7 @@ export default buildConfig({
|
||||
}),
|
||||
collections: [Pages, Posts, Events, Preistraeger, Media, Categories, Users],
|
||||
cors: [getServerSideURL()].filter(Boolean),
|
||||
globals: [Header, Footer],
|
||||
globals: [Header, Footer, SiteSettings],
|
||||
plugins,
|
||||
secret: process.env.PAYLOAD_SECRET,
|
||||
sharp,
|
||||
|
||||
@@ -6,6 +6,7 @@ import Layout from '@/spa/components/layout/Layout'
|
||||
import ScrollToTop from '@/spa/components/layout/ScrollToTop'
|
||||
import { defaultHeaderData, type SpaFooterData, type SpaHeaderData } from '@/spa/cmsNavigation'
|
||||
import { CmsRouteProvider, type CmsRouteData } from '@/spa/cmsRoute'
|
||||
import type { SpaSiteSettingsData } from '@/spa/siteSettings'
|
||||
import About from '@/spa/pages/About'
|
||||
import BlogDetail from '@/spa/pages/BlogDetail'
|
||||
import Contact from '@/spa/pages/Contact'
|
||||
@@ -58,11 +59,13 @@ export default function NextApp({
|
||||
header,
|
||||
footer,
|
||||
cmsRoute,
|
||||
siteSettings,
|
||||
}: {
|
||||
pathname: string
|
||||
header?: SpaHeaderData
|
||||
footer?: SpaFooterData
|
||||
cmsRoute?: CmsRouteData
|
||||
siteSettings?: SpaSiteSettingsData
|
||||
}) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const headerData = header || defaultHeaderData
|
||||
@@ -92,7 +95,7 @@ export default function NextApp({
|
||||
|
||||
return (
|
||||
<>
|
||||
<CmsRouteProvider value={cmsRoute}>
|
||||
<CmsRouteProvider value={cmsRoute ? { ...cmsRoute, siteSettings } : undefined}>
|
||||
<ScrollToTop />
|
||||
<Layout header={header} footer={footer}>
|
||||
{page}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
import React, { createContext, useContext } from 'react'
|
||||
|
||||
import type { SpaSiteSettingsData } from '@/spa/siteSettings'
|
||||
|
||||
export type CmsRouteCollection = 'pages' | 'posts' | 'events' | 'preistraeger'
|
||||
|
||||
export type CmsRouteDoc = {
|
||||
@@ -21,6 +23,7 @@ export type CmsRouteData = {
|
||||
collection: CmsRouteCollection
|
||||
doc: CmsRouteDoc
|
||||
lists?: Partial<Record<CmsRouteCollection, CmsRouteDoc[]>>
|
||||
siteSettings?: SpaSiteSettingsData
|
||||
}
|
||||
|
||||
const CmsRouteContext = createContext<CmsRouteData | undefined>(undefined)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import React from 'react'
|
||||
|
||||
import { useCmsRoute } from '@/spa/cmsRoute'
|
||||
import { defaultSiteSettings } from '@/spa/siteSettings'
|
||||
|
||||
const NAVY = '#111D55'
|
||||
const GOLD = '#EFBF04'
|
||||
@@ -13,14 +14,15 @@ const FB = '"Inter", sans-serif'
|
||||
export default function CmsGenericPage() {
|
||||
const route = useCmsRoute()
|
||||
const doc = route?.doc
|
||||
const title = doc?.title || doc?.meta?.title || 'Seite'
|
||||
const siteSettings = route?.siteSettings || defaultSiteSettings
|
||||
const title = doc?.title || doc?.meta?.title || siteSettings.genericPageTitle
|
||||
const description = doc?.description || doc?.meta?.description
|
||||
|
||||
return (
|
||||
<main style={{ minHeight: '70vh', background: CREAM, padding: '140px 24px 80px' }}>
|
||||
<div style={{ maxWidth: 960, margin: '0 auto' }}>
|
||||
<div style={{ color: GOLD, fontFamily: FF, fontWeight: 800, fontSize: 12, letterSpacing: '0.18em', textTransform: 'uppercase', marginBottom: 20 }}>
|
||||
{route?.collection || 'CMS'}
|
||||
{route?.collection || siteSettings.genericPageKicker}
|
||||
</div>
|
||||
<h1 style={{ color: NAVY, fontFamily: FF, fontSize: 'clamp(2.25rem, 7vw, 5rem)', lineHeight: 1, fontWeight: 900, textTransform: 'uppercase', margin: 0 }}>
|
||||
{title}
|
||||
@@ -31,7 +33,7 @@ export default function CmsGenericPage() {
|
||||
</p>
|
||||
) : (
|
||||
<p style={{ color: 'rgba(58,58,58,0.65)', fontFamily: FB, fontSize: 18, lineHeight: 1.7, marginTop: 28, maxWidth: 760 }}>
|
||||
Diese Route wird aus Payload CMS geladen. Ergänze Inhalte im entsprechenden Collection-Dokument.
|
||||
{siteSettings.genericPageDescription}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
18
src/spa/siteSettings.ts
Normal file
18
src/spa/siteSettings.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export type SpaSiteSettingsData = {
|
||||
genericPageKicker: string
|
||||
genericPageTitle: string
|
||||
genericPageDescription: string
|
||||
}
|
||||
|
||||
export const defaultSiteSettings: SpaSiteSettingsData = {
|
||||
genericPageKicker: 'CMS',
|
||||
genericPageTitle: 'Seite',
|
||||
genericPageDescription: 'Diese Route wird aus Payload CMS geladen. Ergänze Inhalte im entsprechenden Collection-Dokument.',
|
||||
}
|
||||
|
||||
export function normalizeSiteSettings(settings?: Partial<SpaSiteSettingsData> | null): SpaSiteSettingsData {
|
||||
return {
|
||||
...defaultSiteSettings,
|
||||
...settings,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user