feat: trang chi tiết di tích /di-tich/[slug]
This commit is contained in:
@@ -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)]">
|
||||
Tư liệu VR360 cho di tích này đang được bổ sung và sẽ sớm ra mắt.
|
||||
</p>
|
||||
)}
|
||||
</section>
|
||||
|
||||
<SiteFooter />
|
||||
<BackToTopButton />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user