This commit is contained in:
Your Name committed 2026-06-13 23:25:19 -04:00
1 parent 0d10c7a071
commit b867063efb
2 files changed
+26 -11

No files matched your search

+16 -8
View File
@@ -6,10 +6,18 @@ import AddToCartSection from '../../../components/AddToCartSection'
import ProductCard from '../../../components/ProductCard'
import { API_BASE } from '../../../lib/api'
import type { TranslatableString } from '@homaroma/types'
/** Resolve TranslatableString → plain string (SSR: always defaults to 'th') */
function resolveStr(v: TranslatableString | null | undefined, lang = 'th'): string {
if (!v) return ''
if (typeof v === 'string') return v
return v[lang] ?? v['th'] ?? v['en'] ?? Object.values(v)[0] ?? ''
}
async function getProduct(id: string): Promise<Product | null> {
try {
const res = await fetch(`${API_BASE}/products/${id}`, { next: { revalidate: 60 } })
const res = await fetch(`${API_BASE}/products/${id}?lang=th`, { next: { revalidate: 60 } })
return res.ok ? res.json() : null
} catch { return null }
}
@@ -29,10 +37,10 @@ export async function generateMetadata({ params }: { params: Promise<{ id: strin
if (!product) return { title: 'Product Not Found | HomAroma' }
return {
title: `${product.scent.name} ${product.category.name} | HomAroma`,
description: product.description ?? `Premium ${product.category.name} — ${product.scent.name}. Shop HomAroma for high-quality botanical scents.`,
description: resolveStr(product.description) ?? `Premium ${product.category.name} — ${product.scent.name}. Shop HomAroma for high-quality botanical scents.`,
openGraph: {
title: product.scent.name,
description: product.description ?? '',
description: resolveStr(product.description) ?? '',
images: product.images?.[0]?.url ? [product.images[0].url] : [],
},
}
@@ -85,12 +93,12 @@ export default async function ProductDetailPage({ params }: { params: Promise<{
</div>
{/* Full Details Section */}
{product.details && (
<div className="pt-16 border-t border-white/5 space-y-6">
{resolveStr(product.details) && (
<div className="pt-16 border-t border-white/10 space-y-6">
<h2 className="text-3xl font-bold">Product Details</h2>
<div
className="prose prose-invert prose-lg max-w-4xl product-editorial"
dangerouslySetInnerHTML={{ __html: product.details }}
<div
className="text-slate-300 leading-relaxed prose prose-invert max-w-none"
dangerouslySetInnerHTML={{ __html: resolveStr(product.details) }}
/>
</div>
)}
@@ -1,9 +1,16 @@
"use client";
import { useState } from 'react'
import Link from 'next/link'
import { getCategoryImage, formatPrice, type Product } from '@homaroma/types'
import { getCategoryImage, formatPrice, type Product, type TranslatableString } from '@homaroma/types'
import { useCartStore } from '../store/cartStore'
/** Resolve TranslatableString → plain string */
function resolveStr(v: TranslatableString | null | undefined, lang = 'th'): string {
if (!v) return ''
if (typeof v === 'string') return v
return v[lang] ?? v['th'] ?? v['en'] ?? Object.values(v)[0] ?? ''
}
interface Props {
product: Product
}
@@ -40,8 +47,8 @@ export default function AddToCartSection({ product }: Props) {
<p className="text-slate-400 text-sm uppercase tracking-widest">Premium Collection</p>
</div>
{product.description && (
<p className="text-slate-300 leading-relaxed">{product.description}</p>
{resolveStr(product.description) && (
<p className="text-slate-300 leading-relaxed">{resolveStr(product.description)}</p>
)}
{/* Price */}