fix: resolve website typescript errors from category i18n
This commit is contained in:
1 parent
93012a3bdf
commit
363be70e11
8 files changed
+25
-25
No files matched your search
@@ -61,9 +61,9 @@ export default function CategoryPage() {
|
||||
{/* Hero Banner */}
|
||||
<div className="relative h-64 md:h-80 overflow-hidden">
|
||||
<img
|
||||
src={category?.imageUrl || getCategoryImage(category?.name ?? '')}
|
||||
src={category?.imageUrl || getCategoryImage(typeof category?.name === 'string' ? category.name : (category?.name as any)?.th || (category?.name as any)?.en || '')}
|
||||
className="absolute inset-0 w-full h-full object-cover brightness-30 scale-105"
|
||||
alt={category?.name}
|
||||
alt={typeof category?.name === 'string' ? category.name : (category?.name as any)?.th || (category?.name as any)?.en || ''}
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-night-900 via-night-900/60 to-transparent" />
|
||||
<div className="absolute bottom-0 left-0 right-0 px-6 pb-10 pt-20">
|
||||
@@ -73,10 +73,10 @@ export default function CategoryPage() {
|
||||
<span>/</span>
|
||||
<Link href="/shop" className="hover:text-white transition-colors">Shop</Link>
|
||||
<span>/</span>
|
||||
<span className="text-cyan-glow">{category?.name ?? '...'}</span>
|
||||
<span className="text-cyan-glow">{typeof category?.name === 'string' ? category.name : (category?.name as any)?.th || (category?.name as any)?.en || '...'}</span>
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl font-bold">
|
||||
{loading ? <div className="h-10 w-48 bg-white/10 animate-pulse rounded-lg" /> : category?.name}
|
||||
{loading ? <div className="h-10 w-48 bg-white/10 animate-pulse rounded-lg" /> : typeof category?.name === 'string' ? category.name : (category?.name as any)?.th || (category?.name as any)?.en || ''}
|
||||
</h1>
|
||||
{!loading && category?._count && (
|
||||
<p className="text-slate-400 mt-2">{category._count.products} products available</p>
|
||||
@@ -98,7 +98,7 @@ export default function CategoryPage() {
|
||||
: 'glass hover:bg-white/10'
|
||||
}`}
|
||||
>
|
||||
{cat.name}
|
||||
{typeof cat.name === 'string' ? cat.name : (cat.name as any)?.th || (cat.name as any)?.en || ''}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -119,13 +119,13 @@ export default async function HomePage() {
|
||||
>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent z-10 opacity-80 group-hover:opacity-100 transition-opacity" />
|
||||
<img
|
||||
src={cat.imageUrl || getCategoryImage(cat.name)}
|
||||
src={cat.imageUrl || getCategoryImage(typeof cat.name === 'string' ? cat.name : (cat.name as any)?.th || (cat.name as any)?.en || '')}
|
||||
className="absolute inset-0 w-full h-full object-cover group-hover:scale-105 transition-transform duration-700"
|
||||
alt={cat.name}
|
||||
alt={typeof cat.name === 'string' ? cat.name : (cat.name as any)?.th || (cat.name as any)?.en || ''}
|
||||
/>
|
||||
<div className="absolute bottom-6 left-6 right-6 z-20 text-white">
|
||||
<span className="font-semibold text-xl block mb-1">
|
||||
{cat.name}
|
||||
{typeof cat.name === 'string' ? cat.name : (cat.name as any)?.th || (cat.name as any)?.en || ''}
|
||||
</span>
|
||||
{cat._count && (
|
||||
<span className="text-sm font-medium text-white/80">
|
||||
|
||||
@@ -36,8 +36,8 @@ export async function generateMetadata({ params }: { params: Promise<{ id: strin
|
||||
const product = await getProduct(id)
|
||||
if (!product) return { title: 'Product Not Found | HomAroma' }
|
||||
return {
|
||||
title: `${product.scent.name} ${product.category.name} | HomAroma`,
|
||||
description: resolveStr(product.description) ?? `Premium ${product.category.name} — ${product.scent.name}. Shop HomAroma for high-quality botanical scents.`,
|
||||
title: `${product.scent.name} ${typeof product.category.name === 'string' ? product.category.name : (product.category.name as any)?.th || (product.category.name as any)?.en || ''} | HomAroma`,
|
||||
description: resolveStr(product.description) ?? `Premium ${typeof product.category.name === 'string' ? product.category.name : (product.category.name as any)?.th || (product.category.name as any)?.en || ''} — ${product.scent.name}. Shop HomAroma for high-quality botanical scents.`,
|
||||
openGraph: {
|
||||
title: product.scent.name,
|
||||
description: resolveStr(product.description) ?? '',
|
||||
@@ -67,7 +67,7 @@ export default async function ProductDetailPage({ params }: { params: Promise<{
|
||||
<Link href="/shop" className="hover:text-white transition-colors">Shop</Link>
|
||||
<span>/</span>
|
||||
<Link href={`/category/${product.category.id}`} className="hover:text-white transition-colors">
|
||||
{product.category.name}
|
||||
{typeof product.category.name === 'string' ? product.category.name : (product.category.name as any)?.th || (product.category.name as any)?.en || ''}
|
||||
</Link>
|
||||
<span>/</span>
|
||||
<span className="text-cyan-glow">{product.scent.name}</span>
|
||||
@@ -78,13 +78,13 @@ export default async function ProductDetailPage({ params }: { params: Promise<{
|
||||
{/* Image */}
|
||||
<div className="relative rounded-2xl overflow-hidden h-[480px] group">
|
||||
<img
|
||||
src={product.images?.[0]?.url || product.category.imageUrl || getCategoryImage(product.category.name)}
|
||||
src={product.images?.[0]?.url || product.category.imageUrl || getCategoryImage(typeof product.category.name === 'string' ? product.category.name : (product.category.name as any)?.th || (product.category.name as any)?.en || '')}
|
||||
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-700"
|
||||
alt={product.scent.name}
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-night-900/50 to-transparent" />
|
||||
<div className="absolute top-6 left-6 glass px-3 py-1.5 rounded-full text-[10px] font-bold uppercase tracking-widest text-cyan-glow border border-cyan-glow/20">
|
||||
{product.category.name}
|
||||
{typeof product.category.name === 'string' ? product.category.name : (product.category.name as any)?.th || (product.category.name as any)?.en || ''}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -109,7 +109,7 @@ export default async function ProductDetailPage({ params }: { params: Promise<{
|
||||
<div className="flex justify-between items-end">
|
||||
<div>
|
||||
<p className="text-cyan-glow uppercase tracking-[0.3em] text-xs font-semibold opacity-70 mb-2">
|
||||
More {product.category.name}
|
||||
More {typeof product.category.name === 'string' ? product.category.name : (product.category.name as any)?.th || (product.category.name as any)?.en || ''}
|
||||
</p>
|
||||
<h2 className="text-3xl font-bold">Related Products</h2>
|
||||
</div>
|
||||
|
||||
@@ -103,7 +103,7 @@ export default function ShopPage() {
|
||||
activeCategory === cat.id ? 'bg-cyan-glow text-night-900 shadow-[0_0_15px_rgba(102,252,241,0.3)]' : 'glass hover:bg-white/10'
|
||||
}`}
|
||||
>
|
||||
{cat.name}
|
||||
{typeof cat.name === 'string' ? cat.name : (cat.name as any)?.th || (cat.name as any)?.en || ''}
|
||||
{cat._count && <span className="ml-2 opacity-60">({cat._count.products})</span>}
|
||||
</button>
|
||||
))}
|
||||
|
||||
@@ -30,7 +30,7 @@ export default function AddToCartSection({ product }: Props) {
|
||||
price: currentVariant.price || product.price || 0,
|
||||
productName: product.scent.name,
|
||||
variantSize: currentVariant.size,
|
||||
productImage: product.images?.[0]?.url || product.category.imageUrl || getCategoryImage(product.category.name),
|
||||
productImage: product.images?.[0]?.url || product.category.imageUrl || getCategoryImage(typeof product.category.name === 'string' ? product.category.name : (product.category.name as any)?.th || (product.category.name as any)?.en || ''),
|
||||
})
|
||||
toggleCart(true)
|
||||
}
|
||||
@@ -41,7 +41,7 @@ export default function AddToCartSection({ product }: Props) {
|
||||
<div className="space-y-8">
|
||||
<div className="space-y-2">
|
||||
<p className="text-cyan-glow uppercase tracking-[0.3em] text-xs font-semibold opacity-80">
|
||||
{product.category.name}
|
||||
{typeof product.category.name === 'string' ? product.category.name : (product.category.name as any)?.th || (product.category.name as any)?.en || ''}
|
||||
</p>
|
||||
<h1 className="text-5xl font-bold leading-tight">{product.scent.name}</h1>
|
||||
<p className="text-slate-400 text-sm uppercase tracking-widest">Premium Collection</p>
|
||||
@@ -108,7 +108,7 @@ export default function AddToCartSection({ product }: Props) {
|
||||
<div>
|
||||
<span className="text-xs uppercase tracking-widest block mb-1">Category</span>
|
||||
<Link href={`/category/${product.category.id}`} className="text-white font-medium hover:text-cyan-glow transition-colors">
|
||||
{product.category.name}
|
||||
{typeof product.category.name === 'string' ? product.category.name : (product.category.name as any)?.th || (product.category.name as any)?.en || ''}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -45,7 +45,7 @@ export default function Footer({ categories = [] }: FooterProps) {
|
||||
<div className="flex flex-col space-y-2 text-sm text-slate-400">
|
||||
{categories.map((c) => (
|
||||
<Link key={c.id} href={`/category/${c.id}`} className="hover:text-white transition-colors">
|
||||
{c.name}
|
||||
{typeof c.name === 'string' ? c.name : (c.name as any)?.th || (c.name as any)?.en || ''}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -101,7 +101,7 @@ export default function Navbar({ categories = [] }: NavbarProps) {
|
||||
href={`/category/${cat.id}`}
|
||||
className="flex items-center justify-between px-4 py-2.5 text-xs uppercase tracking-widest rounded-lg hover:bg-white/10 hover:text-cyan-glow transition-colors"
|
||||
>
|
||||
{cat.name}
|
||||
{typeof cat.name === 'string' ? cat.name : (cat.name as any)?.th || (cat.name as any)?.en || ''}
|
||||
<svg className="w-3 h-3 opacity-30" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
@@ -281,7 +281,7 @@ export default function Navbar({ categories = [] }: NavbarProps) {
|
||||
onClick={() => setMobileOpen(false)}
|
||||
className="flex items-center justify-between px-4 py-2.5 rounded-xl text-sm text-slate-400 hover:text-white hover:bg-white/5 transition-all"
|
||||
>
|
||||
{cat.name}
|
||||
{typeof cat.name === 'string' ? cat.name : (cat.name as any)?.th || (cat.name as any)?.en || ''}
|
||||
<svg className="w-3 h-3 opacity-30" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
@@ -350,7 +350,7 @@ export default function Navbar({ categories = [] }: NavbarProps) {
|
||||
<p className="text-xs text-slate-500 uppercase tracking-widest mb-3">Quick Links</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{[
|
||||
...categories.map(c => ({ label: c.name, to: `/category/${c.id}` })),
|
||||
...categories.map(c => ({ label: typeof c.name === 'string' ? c.name : (c.name as any)?.th || (c.name as any)?.en || '', to: `/category/${c.id}` })),
|
||||
{ label: '✨ Scent Guide', to: '/scent-guide' },
|
||||
{ label: 'All Products', to: '/shop' },
|
||||
].map(item => (
|
||||
|
||||
@@ -11,13 +11,13 @@ export default function ProductCard({ product }: ProductCardProps) {
|
||||
<div className="glass glass-hover rounded-2xl overflow-hidden flex flex-col group p-1.5 md:p-2">
|
||||
<div className="h-40 md:h-64 overflow-hidden rounded-xl relative">
|
||||
<img
|
||||
src={product.images?.[0]?.url || product.category.imageUrl || getCategoryImage(product.category.name)}
|
||||
src={product.images?.[0]?.url || product.category.imageUrl || getCategoryImage(typeof product.category.name === 'string' ? product.category.name : (product.category.name as any)?.th || (product.category.name as any)?.en || '')}
|
||||
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-700"
|
||||
alt={product.scent.name}
|
||||
/>
|
||||
{/* Category badge */}
|
||||
<div className="absolute top-4 left-4 glass px-3 py-1 rounded-full text-[10px] font-bold uppercase tracking-widest text-cyan-glow">
|
||||
{product.category.name}
|
||||
{typeof product.category.name === 'string' ? product.category.name : (product.category.name as any)?.th || (product.category.name as any)?.en || ''}
|
||||
</div>
|
||||
{/* Available badge */}
|
||||
<div className="hidden md:block absolute top-4 right-4 glass px-3 py-1 rounded-full text-[10px] font-bold uppercase tracking-widest">
|
||||
@@ -32,7 +32,7 @@ export default function ProductCard({ product }: ProductCardProps) {
|
||||
{product.scent.name}
|
||||
</h3>
|
||||
<p className="text-[10px] md:text-xs text-slate-400 mt-0.5 md:mt-1 uppercase tracking-widest line-clamp-1">
|
||||
{product.category.name}
|
||||
{typeof product.category.name === 'string' ? product.category.name : (product.category.name as any)?.th || (product.category.name as any)?.en || ''}
|
||||
</p>
|
||||
</div>
|
||||
<span className="text-cyan-glow font-bold text-xs md:text-lg">
|
||||
|
||||
Reference in new issue
Block a user