Files
j_kedzierski/src/app/(frontend)/[locale]/[[...slug]]/page.tsx
T

105 lines
3.7 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' }>
const PLACEHOLDER_PL = "Odpowiedź w przygotowaniu"
const PLACEHOLDER_DE = "Antwort in Vorbereitung"
function isPlaceholder(answer: string | null | undefined): boolean {
if (!answer) return true;
return answer.includes(PLACEHOLDER_PL) || answer.includes(PLACEHOLDER_DE) || answer.includes('DO POTWIERDZENIA');
}
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 any, // Payload locale typ nie zawsze przyjmuje string
})
const layout = docForRender.layout || []
// Generowanie schematu FAQPage dla bloku faqFull (na poziomie Server Component gwarantuje to SSR)
let faqSchema: Record<string, any> | null = null;
const faqBlock = layout.find((b: any) => b.blockType === 'faqFull') as FAQFullBlock | undefined;
if (faqBlock && faqBlock.questions) {
const validQuestions = faqBlock.questions.filter((q: any) => !isPlaceholder(q.answer));
if (validQuestions.length > 0) {
faqSchema = {
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": validQuestions.map((q: any) => ({
"@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>
)
}