x
This commit is contained in:
1 parent
07e9413a6b
commit
46d504e483
4 files changed
+112
-38
No files matched your search
@@ -7,6 +7,30 @@ import { useCartStore } from '../store/cartStore'
|
||||
import { resolveCategoryName, resolveLocalized } from '../lib/localization'
|
||||
import { useLang } from '../hooks/useLang'
|
||||
|
||||
function getBaseString(val: any): string {
|
||||
if (!val) return '';
|
||||
if (typeof val === 'string') return val;
|
||||
return val['th'] || val['en'] || Object.values(val)[0] || '';
|
||||
}
|
||||
|
||||
function resolveOptionValue(val: string, options: any[] | null | undefined, lang: string): string {
|
||||
if (!val) return '';
|
||||
if (!options || !Array.isArray(options)) return val;
|
||||
|
||||
for (const option of options) {
|
||||
if (!option.values || !Array.isArray(option.values)) continue;
|
||||
for (const v of option.values) {
|
||||
const baseStr = typeof v === 'string' ? v : (v['th'] || v['en'] || Object.values(v)[0] || '');
|
||||
if (baseStr === val) {
|
||||
if (typeof v === 'string') return v;
|
||||
return v[lang] ?? v[lang.slice(0, 2)] ?? v['th'] ?? v['en'] ?? Object.values(v)[0] ?? baseStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
product: Product
|
||||
}
|
||||
@@ -66,7 +90,10 @@ export default function AddToCartSection({ product }: Props) {
|
||||
const handleAddToCart = () => {
|
||||
if (!currentVariant) return
|
||||
|
||||
const variantName = [currentVariant.option1, currentVariant.option2, currentVariant.option3].filter(Boolean).join(' / ');
|
||||
const variantName = [currentVariant.option1, currentVariant.option2, currentVariant.option3]
|
||||
.filter(Boolean)
|
||||
.map(opt => resolveOptionValue(opt, product.options, lang))
|
||||
.join(' / ');
|
||||
|
||||
addToCart({
|
||||
productId: product.id,
|
||||
@@ -80,7 +107,12 @@ export default function AddToCartSection({ product }: Props) {
|
||||
toggleCart(true)
|
||||
}
|
||||
|
||||
const currentVariantName = currentVariant ? [currentVariant.option1, currentVariant.option2, currentVariant.option3].filter(Boolean).join(' / ') : null;
|
||||
const currentVariantName = currentVariant
|
||||
? [currentVariant.option1, currentVariant.option2, currentVariant.option3]
|
||||
.filter(Boolean)
|
||||
.map(opt => resolveOptionValue(opt, product.options, lang))
|
||||
.join(' / ')
|
||||
: null;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -108,34 +140,40 @@ export default function AddToCartSection({ product }: Props) {
|
||||
|
||||
{product.options && product.options.length > 0 && (
|
||||
<div className="space-y-6">
|
||||
{product.options.map((option, optIndex) => (
|
||||
<div key={option.name} className="space-y-3">
|
||||
<p className="text-xs font-bold uppercase tracking-widest text-muted-text">Select {option.name}</p>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{option.values.map(val => {
|
||||
const isSelected = selectedOptions[optIndex] === val;
|
||||
const isAvailable = isOptionAvailable(optIndex, val);
|
||||
|
||||
return (
|
||||
<button
|
||||
key={val}
|
||||
disabled={!isAvailable}
|
||||
onClick={() => handleOptionChange(optIndex, val)}
|
||||
className={`rounded-xl border px-5 py-3 text-sm font-bold uppercase tracking-widest transition ${
|
||||
isSelected
|
||||
? 'border-brand-primary bg-brand-primary text-surface-card shadow-card'
|
||||
: isAvailable
|
||||
? 'border-line-primary/20 bg-surface-card text-muted-text hover:border-brand-primary hover:text-brand-primary'
|
||||
: 'border-line-primary/10 bg-surface-card/50 text-muted-text/30 cursor-not-allowed'
|
||||
}`}
|
||||
>
|
||||
{val}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
{product.options.map((option, optIndex) => {
|
||||
const optNameBase = getBaseString(option.name);
|
||||
const optNameDisplay = resolveLocalized(option.name, lang);
|
||||
return (
|
||||
<div key={optNameBase} className="space-y-3">
|
||||
<p className="text-xs font-bold uppercase tracking-widest text-muted-text">Select {optNameDisplay}</p>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{option.values.map(val => {
|
||||
const baseVal = getBaseString(val);
|
||||
const displayVal = resolveLocalized(val, lang);
|
||||
const isSelected = selectedOptions[optIndex] === baseVal;
|
||||
const isAvailable = isOptionAvailable(optIndex, baseVal);
|
||||
|
||||
return (
|
||||
<button
|
||||
key={baseVal}
|
||||
disabled={!isAvailable}
|
||||
onClick={() => handleOptionChange(optIndex, baseVal)}
|
||||
className={`rounded-xl border px-5 py-3 text-sm font-bold uppercase tracking-widest transition ${
|
||||
isSelected
|
||||
? 'border-brand-primary bg-brand-primary text-surface-card shadow-card'
|
||||
: isAvailable
|
||||
? 'border-line-primary/20 bg-surface-card text-muted-text hover:border-brand-primary hover:text-brand-primary'
|
||||
: 'border-line-primary/10 bg-surface-card/50 text-muted-text/30 cursor-not-allowed'
|
||||
}`}
|
||||
>
|
||||
{displayVal}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
Reference in new issue
Block a user