e081f54bd4
- Added a new "HeritageSeal" SVG component for branding consistency across the site. - Updated "CulturalSpaceExplorer" to include a descriptive header and introductory text. - Modified "SiteHeader" to replace the logo with the new "HeritageSeal". - Enhanced "HeritageDetailPage" with improved layout and styling for better readability. - Updated "HeritageListPage" to include new visual elements and improved section layouts. - Revamped "AboutPage" with new content structure and visual enhancements. - Improved "ContactPage" with a visually appealing hero section and map integration. - Updated global styles for better visual consistency and improved accessibility. - Introduced "SectionDivider" component for decorative separation in content sections.
97 lines
3.9 KiB
TypeScript
97 lines
3.9 KiB
TypeScript
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 preload sizes="100vw" className="public-subpage-hero-image public-parallax-bg object-cover" />
|
|
<div className="public-subpage-hero-content mx-auto flex min-h-[inherit] max-w-7xl flex-col justify-end px-4 py-16 sm:px-6 lg:py-22">
|
|
<Link href="/di-tich" className="inline-flex w-fit items-center gap-2 text-sm font-bold text-[rgb(243_236_221_/_0.86)] transition hover:text-[var(--tour-gold-light)]">
|
|
<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-hero-display public-heading-safe mt-5 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-[rgb(243_236_221_/_0.86)]">
|
|
<MapPin className="h-4 w-4 text-[var(--tour-gold-light)]" 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">
|
|
<p className="public-kicker">Về di tích</p>
|
|
<div className="mt-5 grid gap-5 text-base leading-8 text-[var(--foreground)]/82">
|
|
{paragraphs.map((text, i) => (
|
|
<p key={i} className={i === 0 ? "text-lg leading-9 text-[var(--tour-ink)]" : undefined}>
|
|
{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>
|
|
);
|
|
}
|