diff --git a/src/app/[locale]/templates/[id]/page.tsx b/src/app/[locale]/templates/[id]/page.tsx index f998316..c8ca660 100644 --- a/src/app/[locale]/templates/[id]/page.tsx +++ b/src/app/[locale]/templates/[id]/page.tsx @@ -2,24 +2,43 @@ import type { Metadata } from "next"; import { notFound } from "next/navigation"; import { TemplateDetailContent } from "@/components/templates/TemplateDetailContent"; -import { VIDEO_TEMPLATES_CATALOG } from "@/lib/video-templates-catalog"; +import { fetchProject } from "@/lib/admin-api"; +import { + adminProjectToCatalogTemplate, + VIDEO_TEMPLATES_CATALOG, + type VideoCatalogTemplate, +} from "@/lib/video-templates-catalog"; interface TemplateDetailPageProps { - params: { id: string }; + params: Promise<{ id: string }>; } +/** + * Resolve a template by its `[id]` route param — which is the container SLUG used + * in catalog links. Real (admin-managed) templates come from the content service + * via fetchProject(slug); the hardcoded demo catalog is the offline fallback. + */ +async function resolveTemplate(id: string): Promise { + const admin = await fetchProject(id); + if (admin) return adminProjectToCatalogTemplate(admin); + return VIDEO_TEMPLATES_CATALOG.find((item) => item.id === id) ?? null; +} + +// Pre-render the demo catalog; real container slugs render on demand (ISR). export function generateStaticParams() { return VIDEO_TEMPLATES_CATALOG.map((template) => ({ id: template.id })); } -export function generateMetadata({ params }: TemplateDetailPageProps): Metadata { - const template = VIDEO_TEMPLATES_CATALOG.find((item) => item.id === params.id); +export async function generateMetadata({ params }: TemplateDetailPageProps): Promise { + const { id } = await params; + const template = await resolveTemplate(id); if (!template) return {}; return { title: `${template.name} — FlatRender` }; } -export default function TemplateDetailPage({ params }: TemplateDetailPageProps) { - const template = VIDEO_TEMPLATES_CATALOG.find((item) => item.id === params.id); +export default async function TemplateDetailPage({ params }: TemplateDetailPageProps) { + const { id } = await params; + const template = await resolveTemplate(id); if (!template) notFound(); return (
diff --git a/src/components/templates/TemplateDetailBreadcrumb.tsx b/src/components/templates/TemplateDetailBreadcrumb.tsx index 1802c82..12fbddc 100644 --- a/src/components/templates/TemplateDetailBreadcrumb.tsx +++ b/src/components/templates/TemplateDetailBreadcrumb.tsx @@ -1,15 +1,17 @@ +"use client"; + import Link from "next/link"; import { ChevronRight } from "lucide-react"; -import { getTranslations } from "next-intl/server"; +import { useTranslations } from "next-intl"; interface TemplateDetailBreadcrumbProps { templateName: string; } -export async function TemplateDetailBreadcrumb({ +export function TemplateDetailBreadcrumb({ templateName, }: TemplateDetailBreadcrumbProps) { - const t = await getTranslations("auto.componentsTemplatesTemplateDetailBreadcrumb"); + const t = useTranslations("auto.componentsTemplatesTemplateDetailBreadcrumb"); return (