feat: implement i18n for product and category, add 5 new locales
This commit is contained in:
1 parent
b867063efb
commit
96d874233d
17 files changed
+557
-62
No files matched your search
@@ -1,10 +1,17 @@
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useState } from 'react';
|
||||
import type { Product } from '../types';
|
||||
import type { Product, TranslatableString } from '../types';
|
||||
import { getCategoryImage, formatPrice } from '../types';
|
||||
import { Heart, ShoppingBag } from 'lucide-react';
|
||||
import { useWishlistStore } from '../store/wishlistStore';
|
||||
import { useCartStore } from '../store/cartStore';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function resolveStr(v: TranslatableString | null | undefined, lang: string): string {
|
||||
if (!v) return ''
|
||||
if (typeof v === 'string') return v
|
||||
return v[lang] ?? v[lang.slice(0, 2)] ?? v['th'] ?? v['en'] ?? Object.values(v)[0] ?? ''
|
||||
}
|
||||
|
||||
interface ProductCardProps {
|
||||
product: Product;
|
||||
@@ -15,8 +22,10 @@ export default function ProductCard({ product, enableQuickShop = false }: Produc
|
||||
const navigate = useNavigate();
|
||||
const { addItem, removeItem, isInWishlist } = useWishlistStore();
|
||||
const { addToCart } = useCartStore();
|
||||
const { i18n, t } = useTranslation();
|
||||
const isWished = isInWishlist(product.id);
|
||||
const [selectedVariant, setSelectedVariant] = useState(product.variants?.[0] || null);
|
||||
const displayName = resolveStr(product.name, i18n.language) || product.scent.name;
|
||||
|
||||
const handleWishlistClick = (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
@@ -67,7 +76,7 @@ export default function ProductCard({ product, enableQuickShop = false }: Produc
|
||||
<div className="p-4 flex flex-col flex-1">
|
||||
<div className="mb-2">
|
||||
<h3 className="text-base md:text-lg font-bold text-pop-black leading-tight line-clamp-1 group-hover:text-spa-forest transition-colors">
|
||||
{product.scent.name}
|
||||
{displayName}
|
||||
</h3>
|
||||
<p className="text-[10px] md:text-xs text-spa-stone/60 mt-1 uppercase tracking-widest line-clamp-1 font-semibold">
|
||||
{product.category.name}
|
||||
@@ -109,7 +118,7 @@ export default function ProductCard({ product, enableQuickShop = false }: Produc
|
||||
</span>
|
||||
{!enableQuickShop && (
|
||||
<span className="text-[10px] md:text-xs font-bold text-spa-forest uppercase tracking-widest flex items-center gap-1 group-hover:translate-x-1 transition-transform">
|
||||
View Details →
|
||||
{t('product.viewDetails')}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@@ -125,7 +134,7 @@ export default function ProductCard({ product, enableQuickShop = false }: Produc
|
||||
variantId: selectedVariant.id,
|
||||
quantity: 1,
|
||||
price: selectedVariant.price || 0,
|
||||
productName: product.scent.name,
|
||||
productName: displayName,
|
||||
variantSize: selectedVariant.size,
|
||||
productImage: product.images?.[0]?.url || getCategoryImage(product.category.name)
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user