feat: trang chi tiết di tích /di-tich/[slug]

This commit is contained in:
tuyenio
2026-06-23 11:29:35 +07:00
parent 35bc25cdc0
commit e2a5d0d305
+93
View File
@@ -0,0 +1,93 @@
import type { Metadata } from "next";
import Image from "next/image";
import Link from "next/link";
import { notFound } from "next/navigation";
import { ArrowLeft, MapPin, PlayCircle, Tag } from "lucide-react";
import { BackToTopButton } from "@/app/components/landing/BackToTopButton";
import { SiteFooter } from "@/app/components/landing/SiteFooter";
import { SiteHeader } from "@/app/components/landing/SiteHeader";
import { heritageSites } from "@/app/content";
export function generateStaticParams() {
return heritageSites.map((site) => ({ slug: site.id }));
}
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>;
}): Promise<Metadata> {
const { slug } = await params;
const site = heritageSites.find((s) => s.id === slug);
if (!site) return { title: "Không tìm thấy di tích | VR360 Như Quỳnh" };
return {
title: `${site.name} | VR360 Như Quỳnh`,
description: site.shortDescription,
};
}
export default async function HeritageDetailPage({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const site = heritageSites.find((s) => s.id === slug);
if (!site) notFound();
const paragraphs = site.longDescription ?? [site.shortDescription];
return (
<main className="public-page min-h-[100dvh] bg-[var(--background)] text-[var(--foreground)]">
<SiteHeader />
<section className="public-subpage-hero relative isolate overflow-hidden border-b border-[var(--surface-border)]">
<Image src={site.image} alt={site.name} fill priority sizes="100vw" className="public-subpage-hero-image object-cover" />
<div className="public-subpage-hero-content mx-auto max-w-7xl px-4 py-16 sm:px-6 lg:py-22">
<Link href="/di-tich" className="inline-flex items-center gap-2 text-sm font-bold text-[var(--tour-ink)] transition hover:text-[var(--primary)]">
<ArrowLeft className="h-4 w-4" strokeWidth={1.8} />
Tất cả di tích
</Link>
<div className="public-rise mt-5 max-w-4xl">
<div className="flex flex-wrap gap-2">
<span className="public-chip"><Tag className="h-4 w-4" strokeWidth={1.8} />{site.level}</span>
<span className="public-chip">{site.type}</span>
<span className="public-chip">{site.status}</span>
</div>
<h1 className="public-gradient-text public-heading-safe mt-4 text-[clamp(2.4rem,5.4vw,4.6rem)] font-extrabold">
{site.name}
</h1>
{site.location ? (
<p className="mt-4 inline-flex items-center gap-2 text-sm font-semibold text-[var(--foreground)]/82">
<MapPin className="h-4 w-4 text-[var(--primary)]" strokeWidth={1.8} />
{site.location}
</p>
) : null}
</div>
</div>
</section>
<section className="mx-auto max-w-3xl px-4 py-14 sm:px-6 lg:py-20">
<div className="grid gap-4 text-base leading-8 text-[var(--foreground)]/82">
{paragraphs.map((text, i) => (
<p key={i}>{text}</p>
))}
</div>
{site.isAvailable && site.vrUrl ? (
<Link href={site.vrUrl} className="public-cta mt-8 w-fit">
<PlayCircle className="h-4 w-4" strokeWidth={1.8} />
Tham quan VR360
</Link>
) : (
<p className="public-panel mt-8 rounded-[8px] p-5 text-sm leading-6 text-[var(--muted-foreground)]">
liệu VR360 cho di tích này đang đưc bổ sung sẽ sớm ra mắt.
</p>
)}
</section>
<SiteFooter />
<BackToTopButton />
</main>
);
}