97 lines
3.5 KiB
TypeScript
97 lines
3.5 KiB
TypeScript
import React from 'react'
|
|
import { notFound } from 'next/navigation'
|
|
import { getPayload } from 'payload'
|
|
import configPromise from '@payload-config'
|
|
import { resolveRoute } from '@intecion/ipal-kit'
|
|
import { getLocalizedSlugs } from '@intecion/ipal-kit'
|
|
import { i18n } from '../../../../i18n.config'
|
|
import { SetLanguageSlugs } from '../../../../components/LanguageSlugsProvider'
|
|
import { RenderBlocks } from '../../../../blocks/RenderBlocks'
|
|
import type { Page } from '../../../../payload-types'
|
|
|
|
type FAQFullBlock = Extract<NonNullable<Page['layout']>[0], { blockType: 'faqFull' }>
|
|
|
|
export default async function Page(props: {
|
|
params: Promise<{ locale: string; slug?: string[] }>
|
|
}) {
|
|
const params = await props.params;
|
|
const { locale, slug } = params;
|
|
const payload = await getPayload({ config: configPromise })
|
|
|
|
// Rozwiązanie routingu z użyciem mechanizmów ipal-kit
|
|
const route = await resolveRoute({ payload, locale, segments: slug || [] })
|
|
|
|
// Jeśli strona nie istnieje, 404
|
|
if (!route) {
|
|
notFound()
|
|
}
|
|
|
|
// Pobranie pełnego rekordu strony we wszystkich językach (locale: 'all'),
|
|
// by przekazać prawidłowe zlokalizowane slugi do LanguageSwitcher
|
|
const doc = await payload.findByID({
|
|
collection: ('collection' in route ? route.collection : 'pages') as 'pages',
|
|
id: route.doc.id as string,
|
|
locale: 'all',
|
|
})
|
|
|
|
// getLocalizedSlugs oczekuje pola slug jako obiektu ze slugami we wszystkich językach
|
|
// Rzutowanie na any jest zabronione przez wytyczne, rzutujemy na Record<string, unknown> (zgodnie z .d.ts)
|
|
const slugs = getLocalizedSlugs({
|
|
config: i18n,
|
|
slugField: doc.slug as unknown as Record<string, unknown>,
|
|
})
|
|
|
|
// Dla obecnego języka potrzebujemy konkretnych danych do renderowania (fallback default locale behavior)
|
|
const docForRender = await payload.findByID({
|
|
collection: ('collection' in route ? route.collection : 'pages') as 'pages',
|
|
id: route.doc.id as string,
|
|
locale: locale as 'all' | 'pl' | 'de',
|
|
})
|
|
|
|
const layout = docForRender.layout || []
|
|
|
|
// Generowanie schematu FAQPage dla bloku faqFull (na poziomie Server Component gwarantuje to SSR)
|
|
let faqSchema: Record<string, unknown> | null = null;
|
|
const faqBlock = layout.find((b) => b !== null && typeof b === 'object' && 'blockType' in b && b.blockType === 'faqFull') as FAQFullBlock | undefined;
|
|
if (faqBlock && faqBlock.questions) {
|
|
const validQuestions = faqBlock.questions.filter((q: NonNullable<FAQFullBlock['questions']>[0]) => !q.isDraft);
|
|
if (validQuestions.length > 0) {
|
|
faqSchema = {
|
|
"@context": "https://schema.org",
|
|
"@type": "FAQPage",
|
|
"mainEntity": validQuestions.map((q: NonNullable<FAQFullBlock['questions']>[0]) => ({
|
|
"@type": "Question",
|
|
"name": q.question,
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": q.answer
|
|
}
|
|
}))
|
|
};
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="pt-8 pb-24">
|
|
{faqSchema && (
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(faqSchema) }}
|
|
/>
|
|
)}
|
|
{/* Rejestracja zlokalizowanych slugów w globalnym kontekście dla LanguageSwitcher */}
|
|
<SetLanguageSlugs slugs={slugs} />
|
|
|
|
{layout.length === 0 && (
|
|
<div className="container-premium text-center text-muted-foreground mt-20">
|
|
Strona jest pusta. Skonfiguruj układ (layout) w panelu CMS.
|
|
</div>
|
|
)}
|
|
|
|
<main>
|
|
<RenderBlocks blocks={layout} locale={locale} />
|
|
</main>
|
|
</div>
|
|
)
|
|
}
|