104 lines
3.9 KiB
TypeScript
104 lines
3.9 KiB
TypeScript
import { notFound } from 'next/navigation'
|
|
import { getInstanceBySlug, getConfiguration, getSections, getGuidedPaths, getGuidedPathsForGame } from '@/lib/api/client'
|
|
import type { SectionDTO } from '@/lib/api/types'
|
|
|
|
// Section components
|
|
import ArticleSection from '@/components/sections/ArticleSection'
|
|
import AgendaSection from '@/components/sections/AgendaSection'
|
|
import MenuSection from '@/components/sections/MenuSection'
|
|
import SliderSection from '@/components/sections/SliderSection'
|
|
import VideoSection from '@/components/sections/VideoSection'
|
|
import MapSection from '@/components/sections/MapSection'
|
|
import PdfSection from '@/components/sections/PdfSection'
|
|
import WeatherSection from '@/components/sections/WeatherSection'
|
|
import WebSection from '@/components/sections/WebSection'
|
|
import QuizSection from '@/components/sections/QuizSection'
|
|
import GameSection from '@/components/sections/GameSection'
|
|
import EventSection from '@/components/sections/EventSection'
|
|
import TrackedSection from '@/components/TrackedSection'
|
|
|
|
export default async function SectionPage({
|
|
params,
|
|
}: {
|
|
params: Promise<{ slug: string; configId: string; sectionId: string }>
|
|
}) {
|
|
const { slug, configId, sectionId } = await params
|
|
|
|
let instance, config, sections
|
|
try {
|
|
instance = await getInstanceBySlug(slug)
|
|
;[config, sections] = await Promise.all([
|
|
getConfiguration(configId, instance.publicApiKey!),
|
|
getSections(configId, instance.publicApiKey!),
|
|
])
|
|
} catch {
|
|
notFound()
|
|
}
|
|
|
|
const section: SectionDTO | undefined =
|
|
sections.find((s) => s.id === sectionId) ??
|
|
sections.flatMap((s) => s.menu?.sections ?? []).find((s) => s.id === sectionId)
|
|
if (!section || section.isActive === false) notFound()
|
|
|
|
// For Map sections, eagerly load the guided paths server-side and merge into the DTO
|
|
if (section.type === 'Map' && section.map) {
|
|
try {
|
|
const paths = await getGuidedPaths(section.id, instance.publicApiKey!)
|
|
section.map = { ...section.map, guidedPaths: paths }
|
|
} catch {
|
|
// Silently ignore — Map still works without paths
|
|
}
|
|
}
|
|
|
|
// Escape Games also expose guided paths
|
|
if (section.type === 'Game' && section.gameType === 'Escape') {
|
|
try {
|
|
const paths = await getGuidedPathsForGame(section.id, instance.publicApiKey!)
|
|
section.guidedPaths = paths
|
|
} catch {
|
|
// Silently ignore
|
|
}
|
|
}
|
|
|
|
// Events also expose guided paths (same polymorphic endpoint)
|
|
if (section.type === 'Event' && section.event) {
|
|
try {
|
|
const paths = await getGuidedPaths(section.id, instance.publicApiKey!)
|
|
;(section.event as { guidedPaths?: typeof paths }).guidedPaths = paths
|
|
} catch {
|
|
// Silently ignore
|
|
}
|
|
}
|
|
|
|
const props = { section, slug, configId, languages: config.languages ?? ['FR'], apiKey: instance.publicApiKey! }
|
|
|
|
let content: React.ReactNode
|
|
switch (section.type) {
|
|
case 'Article': content = <ArticleSection {...props} />; break
|
|
case 'Agenda': content = <AgendaSection {...props} />; break
|
|
case 'Menu': content = <MenuSection {...props} />; break
|
|
case 'Slider': content = <SliderSection {...props} />; break
|
|
case 'Video': content = <VideoSection {...props} />; break
|
|
case 'Map': content = <MapSection {...props} />; break
|
|
case 'Pdf':
|
|
case 'PDF': content = <PdfSection {...props} />; break
|
|
case 'Weather': content = <WeatherSection {...props} />; break
|
|
case 'Quiz': content = <QuizSection {...props} />; break
|
|
case 'Game': content = <GameSection {...props} />; break
|
|
case 'Event': content = <EventSection {...props} />; break
|
|
case 'Web': content = <WebSection {...props} />; break
|
|
default:
|
|
content = (
|
|
<div className="p-8 text-center" style={{ color: 'var(--color-text-muted)' }}>
|
|
Section de type « {section.type} » à venir.
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<TrackedSection sectionId={section.id} configurationId={configId}>
|
|
{content}
|
|
</TrackedSection>
|
|
)
|
|
}
|