123 lines
5.0 KiB
TypeScript
123 lines
5.0 KiB
TypeScript
import Image from 'next/image';
|
|
import Link from 'next/link';
|
|
import { products } from '@/data/products';
|
|
import { notFound } from 'next/navigation';
|
|
|
|
import type { Metadata } from "next";
|
|
|
|
// Pre-generate all product detail pages at build time
|
|
export function generateStaticParams() {
|
|
return products.map((product) => ({
|
|
slug: product.slug,
|
|
}));
|
|
}
|
|
|
|
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {
|
|
const { slug } = await params;
|
|
const product = products.find((p) => p.slug === slug);
|
|
|
|
if (!product) return { title: "Product Not Found" };
|
|
|
|
return {
|
|
title: `${product.name} | VG Fence Products`,
|
|
description: product.description,
|
|
alternates: {
|
|
canonical: `/products/${product.slug}`
|
|
}
|
|
};
|
|
}
|
|
|
|
// In Next.js 15+/16, params is a Promise and must be awaited
|
|
export default async function ProductDetailPage({
|
|
params,
|
|
}: {
|
|
params: Promise<{ slug: string }>;
|
|
}) {
|
|
const { slug } = await params;
|
|
const product = products.find((p) => p.slug === slug);
|
|
|
|
if (!product) {
|
|
notFound();
|
|
}
|
|
|
|
return (
|
|
<div className="product-detail-page">
|
|
{/* ── INNER BANNER ── */}
|
|
<section className="detail-banner fade-up">
|
|
<div className="detail-banner-content">
|
|
<h1 className="detail-title">{product.name}</h1>
|
|
<div className="banner-breadcrumb" style={{ marginTop: '30px', marginBottom: '0' }}>
|
|
<Link href="/">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
|
|
Home
|
|
</Link>
|
|
<span className="separator">/</span>
|
|
<Link href="/products">Products</Link>
|
|
<span className="separator">/</span>
|
|
<span>{product.name}</span>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<div className="section">
|
|
<div className="container">
|
|
<Link href="/products" className="back-link">
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>
|
|
Back to Catalog
|
|
</Link>
|
|
|
|
<div className="detail-grid">
|
|
{/* Left: Image */}
|
|
<div className="detail-image-column">
|
|
<Image
|
|
src="/assets/manufacturing-hero.png"
|
|
alt={product!.name}
|
|
fill
|
|
style={{ objectFit: 'cover' }}
|
|
priority
|
|
/>
|
|
</div>
|
|
|
|
{/* Right: Info */}
|
|
<div className="detail-info-column">
|
|
<div className="section-eyebrow" style={{ marginBottom: '16px' }}>{product!.category}</div>
|
|
<h1 className="section-h2" style={{ fontSize: '48px', marginBottom: '24px', lineHeight: 1.1 }}>{product!.name}</h1>
|
|
|
|
<div style={{ fontSize: '24px', fontWeight: 700, color: 'var(--orange)', fontFamily: 'var(--font-display)', marginBottom: '32px' }}>
|
|
{product!.price}
|
|
</div>
|
|
|
|
<div style={{ borderTop: '1px solid var(--gray-200)', borderBottom: '1px solid var(--gray-200)', padding: '32px 0', marginBottom: '40px' }}>
|
|
<h3 style={{ fontFamily: 'var(--font-display)', fontSize: '14px', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.1em', color: 'var(--navy)', marginBottom: '16px' }}>Description</h3>
|
|
<p style={{ fontSize: '16px', lineHeight: 1.8, color: 'var(--gray-600)', whiteSpace: 'pre-line' }}>
|
|
{product!.description}
|
|
</p>
|
|
</div>
|
|
|
|
{/* <div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}>
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', fontSize: '14px', color: 'var(--gray-600)' }}>
|
|
<span style={{ fontWeight: 600 }}>Category:</span>
|
|
<span>{product!.category}</span>
|
|
</div>
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', fontSize: '14px', color: 'var(--gray-600)' }}>
|
|
<span style={{ fontWeight: 600 }}>Availability:</span>
|
|
<span style={{ color: '#059669', fontWeight: 600 }}>In Stock (Same-day Delivery)</span>
|
|
</div>
|
|
</div> */}
|
|
|
|
<div style={{ marginTop: '56px' }}>
|
|
<Link href="/contact" className="btn-primary" style={{ width: '100%', textAlign: 'center', padding: '20px' }}>
|
|
Contact for Quote & Specs →
|
|
</Link>
|
|
{/* <p style={{ textAlign: 'center', fontSize: '13px', color: 'var(--gray-400)', marginTop: '16px' }}>
|
|
Bulk ordering and contractor pricing available on request.
|
|
</p> */}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|