56 lines
1.8 KiB
TypeScript
56 lines
1.8 KiB
TypeScript
import { Suspense } from 'react'
|
|
import Link from 'next/link'
|
|
import { ArrowLeft } from 'lucide-react'
|
|
import ProductDetailClient from '@/components/shop/ProductDetailClient'
|
|
|
|
export const dynamic = 'force-dynamic'
|
|
export const revalidate = 0
|
|
|
|
const VULA_CMS_URL = process.env.VULA_CMS_URL || 'https://ide.vulai.co.za'
|
|
const VULA_PROJECT_ID = process.env.VULA_CMS_PROJECT_ID || ''
|
|
|
|
async function getProduct(productId: string) {
|
|
try {
|
|
const res = await fetch(
|
|
`${VULA_CMS_URL}/api/store/${VULA_PROJECT_ID}/products/${productId}`,
|
|
{ cache: 'no-store', signal: AbortSignal.timeout(8000) }
|
|
)
|
|
if (!res.ok) return null
|
|
const data = await res.json()
|
|
return data.product ?? data ?? null
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
interface PageProps { params: { productId: string } }
|
|
|
|
export default async function ProductDetailPage({ params }: PageProps) {
|
|
const product = await getProduct(params.productId)
|
|
return (
|
|
<main className="min-h-screen bg-background">
|
|
<div className="container mx-auto px-4 py-10 max-w-6xl">
|
|
<nav className="flex items-center gap-2 text-sm text-muted-foreground mb-8">
|
|
<Link href="/products" className="hover:text-foreground transition-colors flex items-center gap-1">
|
|
<ArrowLeft className="h-4 w-4" />
|
|
All Products
|
|
</Link>
|
|
{product?.collection?.title && (
|
|
<>
|
|
<span>/</span>
|
|
<span className="text-foreground">{product.collection.title}</span>
|
|
</>
|
|
)}
|
|
</nav>
|
|
<Suspense fallback={
|
|
<div className="flex justify-center py-20">
|
|
<div className="animate-spin rounded-full h-10 w-10 border-b-2 border-primary" />
|
|
</div>
|
|
}>
|
|
<ProductDetailClient product={product} productId={params.productId} />
|
|
</Suspense>
|
|
</div>
|
|
</main>
|
|
)
|
|
}
|