This commit is contained in:
2026-01-17 01:50:54 +01:00
parent c12b32ed5e
commit c8f61257c9
62 changed files with 1297 additions and 1028 deletions

View File

@@ -1,8 +1,11 @@
import { notFound } from 'next/navigation';
import { MDXRemote } from 'next-mdx-remote/rsc';
import { getProductBySlug } from '@/lib/mdx';
import { getProductBySlug, getAllProducts } from '@/lib/mdx';
import ProductTechnicalData from '@/components/ProductTechnicalData';
import Image from 'next/image';
import ProductTabs from '@/components/ProductTabs';
import RequestQuoteForm from '@/components/RequestQuoteForm';
import RelatedProducts from '@/components/RelatedProducts';
import Link from 'next/link';
interface ProductPageProps {
params: {
@@ -13,12 +16,64 @@ interface ProductPageProps {
const components = {
ProductTechnicalData,
ProductTabs,
p: (props: any) => <div {...props} className="mb-4" />,
table: (props: any) => (
<div className="overflow-x-auto my-8">
<table {...props} className="min-w-full divide-y divide-neutral-dark border border-neutral-dark" />
</div>
),
};
export default async function ProductPage({ params }: ProductPageProps) {
const { locale, slug } = params;
const productSlug = slug[slug.length - 1]; // Use the last segment as the slug
const productSlug = slug[slug.length - 1];
// Check if it's a category page
const categories = ['low-voltage-cables', 'medium-voltage-cables', 'high-voltage-cables', 'solar-cables'];
if (categories.includes(productSlug)) {
const allProducts = await getAllProducts(locale);
const categoryTitle = productSlug.split('-').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
// Filter products for this category
// Note: MDX categories are like "Low Voltage Cables"
const filteredProducts = allProducts.filter(p =>
p.frontmatter.categories.some(cat => cat.toLowerCase().replace(/\s+/g, '-') === productSlug)
);
return (
<div className="container mx-auto px-4 py-12">
<h1 className="text-4xl font-bold text-primary mb-8">{categoryTitle}</h1>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{filteredProducts.map((product) => (
<Link
key={product.slug}
href={`/${locale}/products/${productSlug}/${product.slug}`}
className="group block bg-white rounded-lg overflow-hidden shadow-sm hover:shadow-md transition-all border border-neutral-dark"
>
<div className="aspect-[4/3] relative bg-neutral-light">
{product.frontmatter.images?.[0] && (
<img
src={product.frontmatter.images[0]}
alt={product.frontmatter.title}
className="w-full h-full object-contain p-4 group-hover:scale-105 transition-transform duration-300"
/>
)}
</div>
<div className="p-6">
<h2 className="text-xl font-bold text-text-primary group-hover:text-primary transition-colors">
{product.frontmatter.title}
</h2>
<p className="text-text-secondary mt-2 line-clamp-2 text-sm">
{product.frontmatter.description}
</p>
</div>
</Link>
))}
</div>
</div>
);
}
const product = await getProductBySlug(productSlug, locale);
@@ -41,42 +96,46 @@ export default async function ProductPage({ params }: ProductPageProps) {
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div className="lg:col-span-2">
<div className="prose max-w-none mb-8">
<MDXRemote source={product.content} components={components} />
{/* Main Content Area */}
<div className="bg-white p-6 rounded-lg shadow-sm border border-neutral-dark">
<MDXRemote source={product.content} components={components} />
</div>
{/* Related Products */}
<RelatedProducts
currentSlug={productSlug}
categories={product.frontmatter.categories}
locale={locale}
/>
</div>
<div className="lg:col-span-1">
{product.frontmatter.images && product.frontmatter.images.length > 0 && (
<div className="sticky top-4">
<div className="sticky top-4 space-y-6">
{/* Image Gallery */}
{product.frontmatter.images && product.frontmatter.images.length > 0 && (
<div className="bg-white p-4 rounded-lg shadow-sm border border-neutral-dark">
<div className="relative aspect-square mb-4">
{/* Note: Images from WC might be external URLs. Next/Image requires configuration for external domains. */}
{/* For now using standard img tag if domain not configured, or configure domains. */}
<div className="relative aspect-square mb-4 bg-neutral-light rounded overflow-hidden">
<img
src={product.frontmatter.images[0]}
alt={product.frontmatter.title}
className="w-full h-full object-contain"
/>
</div>
<div className="grid grid-cols-4 gap-2">
{product.frontmatter.images.slice(1, 5).map((img, idx) => (
<div key={idx} className="relative aspect-square border border-neutral-dark rounded overflow-hidden">
<img src={img} alt="" className="w-full h-full object-cover" />
</div>
))}
</div>
{product.frontmatter.images.length > 1 && (
<div className="grid grid-cols-4 gap-2">
{product.frontmatter.images.slice(1, 5).map((img, idx) => (
<div key={idx} className="relative aspect-square border border-neutral-dark rounded overflow-hidden bg-neutral-light">
<img src={img} alt="" className="w-full h-full object-cover" />
</div>
))}
</div>
)}
</div>
<div className="mt-6 bg-primary-light p-6 rounded-lg">
<h3 className="text-lg font-semibold text-primary-dark mb-2">Contact Us</h3>
<p className="text-text-secondary mb-4">Need more information about {product.frontmatter.title}?</p>
<button className="w-full bg-primary text-white py-2 px-4 rounded hover:bg-primary-dark transition-colors">
Request Quote
</button>
</div>
</div>
)}
)}
{/* Request Quote Form */}
<RequestQuoteForm productName={product.frontmatter.title} />
</div>
</div>
</div>
</div>