<!DOCTYPE html>
<html lang="{{ app.session.get('_locale') ?? 'en' }}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ produit.productName }} โ Julico</title>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/css/julico-home.css">
<style>
*, *::before, *::after { box-sizing: border-box; }
html, body { max-width: 100%; overflow-x: hidden; }
img, video, iframe { max-width: 100%; height: auto; }
body{background:var(--gray-50);min-height:100vh}
.prod-nav{background:var(--white);border-bottom:1px solid var(--gray-200);padding:0 24px;height:68px;display:flex;align-items:center;justify-content:space-between;box-shadow:var(--shadow-sm);position:sticky;top:0;z-index:100}
.prod-body{max-width:1280px;margin:0 auto;padding:28px 24px}
.breadcrumb{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--gray-400);margin-bottom:24px;flex-wrap:wrap}
.breadcrumb a{color:var(--gray-400);text-decoration:none;transition:color .2s}
.breadcrumb a:hover{color:var(--brand)}
.breadcrumb span{color:var(--gray-800);font-weight:600}
.prod-layout{display:grid;grid-template-columns:1fr 1fr;gap:40px;align-items:start}
.main-image{background:var(--white);border:1.5px solid var(--gray-100);border-radius:var(--rlg);overflow:hidden;aspect-ratio:1;display:flex;align-items:center;justify-content:center;margin-bottom:12px;box-shadow:var(--shadow-sm);position:relative}
.main-image img{width:80%;height:80%;object-fit:contain;transition:transform .3s}
.main-image:hover img{transform:scale(1.05)}
.main-image .no-img{font-size:80px;opacity:0.2}
.thumb-grid{display:flex;gap:10px;overflow-x:auto;scrollbar-width:none}
.thumb-grid::-webkit-scrollbar{display:none}
.thumb{width:72px;height:72px;background:var(--white);border:2px solid var(--gray-200);border-radius:var(--rsm);overflow:hidden;cursor:pointer;flex-shrink:0;display:flex;align-items:center;justify-content:center;transition:border-color .2s}
.thumb:hover,.thumb.active{border-color:var(--brand)}
.thumb img{width:100%;height:100%;object-fit:contain;pointer-events:none}
.prod-info{}
.prod-badges{display:flex;gap:8px;margin-bottom:14px;flex-wrap:wrap}
.prod-badge{font-size:11px;font-weight:700;padding:4px 10px;border-radius:100px}
.badge-promo{background:#fef3c7;color:#b45309}
.badge-new{background:#dcfce7;color:#166534}
.badge-b2b{background:var(--brand-light);color:var(--brand-dark)}
.badge-oos{background:#fee2e2;color:#991b1b}
.prod-name{font-size:28px;font-weight:800;color:var(--gray-900);letter-spacing:-0.02em;line-height:1.2;margin-bottom:8px}
.prod-cat{font-size:13px;font-weight:600;color:var(--brand);margin-bottom:16px}
.prod-desc{font-size:14px;color:var(--gray-500);line-height:1.7;margin-bottom:20px}
.prod-price-box{background:var(--brand-light);border:1.5px solid var(--brand-mid);border-radius:var(--r);padding:20px;margin-bottom:14px}
.prod-price{font-size:36px;font-weight:800;color:var(--brand);letter-spacing:-0.02em;line-height:1}
.prod-price sup{font-size:18px;font-weight:700;vertical-align:super}
.prod-old-price{font-size:16px;color:var(--gray-400);text-decoration:line-through;font-weight:500;margin-top:4px}
.prod-tax{font-size:12px;color:var(--gray-400);margin-top:6px}
.delivery-card{background:var(--white);border:1.5px solid var(--gray-100);border-radius:var(--r);padding:14px 16px;margin-bottom:18px;display:flex;align-items:flex-start;gap:12px}
.delivery-card.ok{background:linear-gradient(135deg,#f0fdf4,#ecfdf5);border-color:#86efac}
.delivery-card.no{background:linear-gradient(135deg,#fef2f2,#fee2e2);border-color:#fca5a5}
.delivery-card.warn{background:linear-gradient(135deg,#fffbeb,#fef3c7);border-color:#fcd34d}
.delivery-card .dc-icon{font-size:22px;line-height:1;flex:0 0 22px}
.delivery-card .dc-body{flex:1;font-size:13px;line-height:1.5}
.delivery-card .dc-title{font-weight:800;color:var(--gray-900);margin-bottom:2px}
.delivery-card.ok .dc-title{color:#166534}
.delivery-card.no .dc-title{color:#991b1b}
.delivery-card.warn .dc-title{color:#92400e}
.delivery-card .dc-sub{color:var(--gray-500);font-size:12px}
.delivery-card .dc-sub a{color:var(--brand);font-weight:700;text-decoration:none}
.delivery-card .dc-fee{font-weight:800;color:var(--gray-900);font-size:14px}
.prod-stock{display:flex;align-items:center;gap:6px;font-size:13px;font-weight:600;margin-bottom:20px}
.stock-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.stock-in{background:#22c55e}
.stock-out{background:#ef4444}
.variants-section{margin-bottom:20px}
.variants-label{font-size:13px;font-weight:700;color:var(--gray-700);margin-bottom:10px}
.color-options{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:14px}
.color-opt{width:44px;height:44px;border-radius:50%;border:3px solid transparent;cursor:pointer;transition:all .2s;outline:2px solid var(--gray-200);touch-action:manipulation;-webkit-tap-highlight-color:transparent}
.color-opt:hover,.color-opt.active{outline-color:var(--brand);outline-offset:2px}
.size-options{display:flex;gap:8px;flex-wrap:wrap}
.size-opt{min-height:44px;padding:10px 18px;border:1.5px solid var(--gray-200);border-radius:var(--rsm);font-size:14px;font-weight:600;color:var(--gray-700);cursor:pointer;transition:all .2s;background:var(--white);font-family:var(--font);touch-action:manipulation;-webkit-tap-highlight-color:transparent}
.size-opt:hover,.size-opt.active{border-color:var(--brand);color:var(--brand);background:var(--brand-light)}
.variant-list{display:flex;flex-direction:column;gap:10px;margin-bottom:6px}
.variant-card{display:flex;flex-direction:row;align-items:center;gap:12px;width:100%;text-align:left;padding:10px 12px;border:1.5px solid var(--gray-200);border-radius:var(--rsm);background:var(--white);cursor:pointer;font-family:var(--font);transition:all .2s;-webkit-tap-highlight-color:transparent}
.variant-card:hover{border-color:var(--brand);background:var(--brand-light)}
.variant-card.active{border-color:var(--brand);background:var(--brand-light);box-shadow:0 0 0 3px rgba(0,167,181,.12)}
.vc-thumb{width:56px;height:56px;flex-shrink:0;border-radius:var(--rsm);overflow:hidden;background:var(--gray-50);border:1px solid var(--gray-200);display:flex;align-items:center;justify-content:center}
.vc-thumb img{width:100%;height:100%;object-fit:contain}
.vc-thumb .vc-noimg{font-size:24px;opacity:0.3}
.vc-text{display:flex;flex-direction:column;gap:4px;min-width:0}
.vc-label{font-size:14px;font-weight:700;color:var(--gray-900);line-height:1.3;overflow-wrap:anywhere}
.vc-meta{font-size:12px;font-weight:600;color:var(--gray-500)}
.variant-card.active .vc-meta{color:var(--brand-dark)}
.prod-actions{display:flex;gap:12px;align-items:center;margin-bottom:20px}
.qty-wrap{display:flex;align-items:center;gap:0;border:1.5px solid var(--gray-200);border-radius:var(--rsm);overflow:hidden;background:var(--white)}
.qty-btn-large{width:44px;height:50px;background:var(--white);border:none;color:var(--gray-700);font-size:20px;font-weight:600;cursor:pointer;transition:background .2s;font-family:var(--font)}
.qty-btn-large:hover{background:var(--gray-100)}
.qty-input{width:60px;height:50px;border:none;border-left:1px solid var(--gray-200);border-right:1px solid var(--gray-200);text-align:center;font-family:var(--font);font-size:16px;font-weight:700;color:var(--gray-900);outline:none}
.btn-add-cart{flex:1;height:50px;background:var(--brand);color:white;border:none;border-radius:var(--rsm);font-family:var(--font);font-size:15px;font-weight:700;cursor:pointer;transition:background .2s;display:flex;align-items:center;justify-content:center;gap:8px;touch-action:manipulation}
.btn-add-cart:hover{background:var(--brand-dark)}
.btn-checkout-now{flex:1;height:50px;background:var(--gray-900);color:white;border:none;border-radius:var(--rsm);font-family:var(--font);font-size:15px;font-weight:700;cursor:pointer;transition:background .2s;display:flex;align-items:center;justify-content:center;gap:8px;touch-action:manipulation}
.btn-checkout-now:hover{background:var(--gray-700)}
.platform-note{background:var(--white);border:1.5px solid var(--gray-100);border-radius:var(--r);padding:14px 16px;margin-top:20px;display:flex;align-items:flex-start;gap:10px;box-shadow:var(--shadow-sm)}
.platform-note-icon{font-size:18px;flex-shrink:0;margin-top:1px}
.platform-note-text{font-size:12px;color:var(--gray-500);line-height:1.55}
.platform-note-text strong{color:var(--gray-800);font-weight:700}
.cart-toast{position:fixed;bottom:30px;left:50%;transform:translateX(-50%) translateY(20px);background:var(--gray-900);color:white;padding:14px 24px;border-radius:100px;font-size:13px;font-weight:600;display:flex;align-items:center;gap:12px;box-shadow:0 8px 32px rgba(0,0,0,0.25);z-index:400;opacity:0;pointer-events:none;transition:all .3s;white-space:nowrap}
.cart-toast.show{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto}
.cart-toast a{color:var(--brand);font-weight:700;text-decoration:none;margin-left:4px}
@media(max-width:900px){.prod-layout{grid-template-columns:1fr}.prod-actions{flex-wrap:wrap}}
@media (max-width: 768px) {
.prod-nav { padding: 0 14px !important; height: 60px !important; }
.prod-nav img { height: 38px !important; }
.prod-body { padding: 20px 14px !important; }
.breadcrumb { font-size: 12px !important; margin-bottom: 16px !important; }
.prod-layout { gap: 22px !important; }
.prod-name { font-size: 22px !important; }
.prod-cat { font-size: 12px !important; margin-bottom: 12px !important; }
.prod-desc { font-size: 13px !important; }
.prod-price { font-size: 30px !important; }
.prod-price sup { font-size: 15px !important; }
.prod-price-box { padding: 16px !important; }
.delivery-card { padding: 12px 14px !important; }
.delivery-card .dc-body { font-size: 12px !important; }
.delivery-card .dc-icon { font-size: 20px !important; }
.cart-toast {
left: 16px !important; right: 16px !important; width: auto !important;
max-width: calc(100vw - 32px) !important; transform: translateY(20px) !important;
white-space: normal !important; justify-content: center !important; text-align: center !important;
box-sizing: border-box !important; padding: 12px 18px !important;
}
.cart-toast.show { transform: translateY(0) !important; }
}
@media (max-width: 480px) {
.prod-body { padding: 16px 12px !important; }
.prod-name { font-size: 20px !important; }
.prod-price { font-size: 26px !important; }
.prod-actions { flex-direction: column !important; gap: 10px !important; align-items: stretch !important; }
.qty-wrap { width: 100% !important; justify-content: center !important; }
.qty-btn-large { flex: 1 !important; max-width: 80px !important; }
.qty-input { flex: 1 !important; max-width: 100px !important; }
.btn-add-cart, .btn-checkout-now { width: 100% !important; flex: none !important; font-size: 14px !important; }
.platform-note { padding: 12px 14px !important; }
.platform-note-text { font-size: 11px !important; }
.cart-toast { bottom: 16px !important; font-size: 12px !important; }
}
@media (max-width: 380px) {
.prod-nav { padding: 0 10px !important; }
.prod-nav img { height: 32px !important; }
.prod-body { padding: 14px 10px !important; }
.prod-name { font-size: 18px !important; }
.prod-price { font-size: 24px !important; }
}
</style>
</head>
<body>
<nav class="prod-nav">
<a href="{{ path('app_home') }}">
<img src="/images/julico-logo.png" alt="Julico" style="height:48px;object-fit:contain">
</a>
<div style="display:flex;align-items:center;gap:12px">
<a href="{{ path('app_panier') }}" style="display:flex;align-items:center;gap:6px;font-size:13px;font-weight:600;color:var(--gray-600);text-decoration:none;padding:8px 14px;border:1.5px solid var(--gray-200);border-radius:var(--rsm)">
๐ Cart
</a>
{% if app.user %}
<a href="{{ path('app_orders') }}" style="font-size:13px;font-weight:600;color:var(--gray-600);text-decoration:none;padding:8px 14px;border:1.5px solid var(--gray-200);border-radius:var(--rsm)">๐ฆ Orders</a>
<a href="{{ path('app_profile') }}" style="font-size:13px;font-weight:600;color:var(--brand);text-decoration:none">{{ app.user.pseudo }}</a>
{% else %}
<a href="/login" style="font-size:13px;font-weight:600;color:var(--brand);text-decoration:none">Sign In</a>
{% endif %}
</div>
</nav>
<div class="prod-body">
<div class="breadcrumb">
<a href="{{ path('app_home') }}">Home</a> โบ
{% if produit.category is defined and produit.category %}
<a href="{{ path('app_home') }}">{{ produit.category.nom }}</a> โบ
{% endif %}
<span>{{ produit.productName }}</span>
</div>
<div class="prod-layout">
<!-- IMAGES -->
<div class="prod-images">
<div class="main-image">
{% if produit.images|length > 0 %}
<img id="main-img"
src="{{ asset('assets/uploads/products/' ~ produit.images|first.fileName) }}"
alt="{{ produit.productName }}"
onerror="this.onerror=null;this.parentNode.innerHTML='<div class=no-img>๐ฆ</div>'">
{% else %}
<div class="no-img">๐ฆ</div>
{% endif %}
</div>
{% if produit.images|length > 1 %}
<div class="thumb-grid" id="thumb-grid">
{% for image in produit.images %}
<div class="thumb {% if loop.first %}active{% endif %}"
data-src="{{ asset('assets/uploads/products/' ~ image.fileName) }}"
data-fallback="/assets/uploads/products/{{ image.fileName }}"
data-vid="{% if image.produitVariant %}{{ image.produitVariant.id }}{% endif %}">
<img src="{{ asset('assets/uploads/products/' ~ image.fileName) }}"
alt="{{ loop.index }}"
onerror="this.onerror=null;this.src='/assets/uploads/products/{{ image.fileName }}'">
</div>
{% endfor %}
</div>
{% endif %}
</div>
<!-- INFO -->
<div class="prod-info">
{% set isFlex = produit.produitVariants|length > 0 and groupedVariantscolor|length == 0 and groupedVariantssize|length == 0 %}
<div class="prod-badges">
{% if produit.promo %}<span class="prod-badge badge-promo">๐ฅ On Promo</span>{% endif %}
{% if produit.qtt > 0 %}
<span class="prod-badge badge-new">โ
In Stock</span>
{% else %}
<span class="prod-badge badge-oos">โ Out of Stock</span>
{% endif %}
{% if produit.magasin is defined and produit.magasin %}
<span class="prod-badge badge-b2b">{{ produit.magasin.nom }}</span>
{% endif %}
</div>
<div class="prod-name">{{ produit.productName }}</div>
<div class="prod-cat">
{% if produit.category is defined and produit.category %}{{ produit.category.nom }}{% endif %}
{% if produit.magasin is defined and produit.magasin %} ยท Sold by {{ produit.magasin.nom }}{% endif %}
</div>
<div class="prod-desc">{{ produit.description }}</div>
<div class="prod-price-box">
{% if isFlex %}
<div class="prod-price"><sup>$</sup><span id="disp-price">{{ produit.prix|number_format(2) }}</span></div>
<div class="prod-tax" id="disp-price-note">Select an option below</div>
{% elseif produit.promo and produit.salePrice and produit.salePrice > 0 and produit.salePrice < produit.prix %}
<div class="prod-price"><sup>$</sup>{{ produit.salePrice|number_format(2) }}</div>
<div class="prod-old-price">${{ produit.prix|number_format(2) }}</div>
<div class="prod-tax">Price set by seller</div>
{% else %}
<div class="prod-price"><sup>$</sup>{{ produit.prix|number_format(2) }}</div>
<div class="prod-tax">Price set by seller</div>
{% endif %}
</div>
{# โโโโโโ Delivery preview card (Phase 3) โโโโโโ #}
{% if deliveryInfo is defined and deliveryInfo.shop_id %}
{% if not app.user %}
<div class="delivery-card">
<div class="dc-icon">๐</div>
<div class="dc-body">
<div class="dc-title">Sign in to see delivery cost</div>
<div class="dc-sub"><a href="/login">Sign in</a> and set your delivery address to see if <strong>{{ deliveryInfo.shop_name }}</strong> delivers to your region.</div>
</div>
</div>
{% elseif not deliveryInfo.address_set %}
<div class="delivery-card warn">
<div class="dc-icon">๐</div>
<div class="dc-body">
<div class="dc-title">Add a delivery address</div>
<div class="dc-sub"><a href="/addresse/add">Add an address</a> to see delivery availability and fees from <strong>{{ deliveryInfo.shop_name }}</strong>.</div>
</div>
</div>
{% elseif not deliveryInfo.has_region %}
<div class="delivery-card warn">
<div class="dc-icon">๐</div>
<div class="dc-body">
<div class="dc-title">Set your region</div>
<div class="dc-sub">Your address has no region set. <a href="{{ path('app_profile') }}">Update your profile</a> to see delivery fees.</div>
</div>
</div>
{% elseif deliveryInfo.can_deliver is null %}
<div class="delivery-card warn">
<div class="dc-icon">๐</div>
<div class="dc-body">
<div class="dc-title">Delivery info unavailable</div>
<div class="dc-sub"><strong>{{ deliveryInfo.shop_name }}</strong> has not configured delivery for <strong>{{ deliveryInfo.region_name }}</strong> yet.</div>
</div>
</div>
{% elseif not deliveryInfo.can_deliver %}
<div class="delivery-card no">
<div class="dc-icon">โ</div>
<div class="dc-body">
<div class="dc-title">Cannot deliver to {{ deliveryInfo.region_name }}</div>
<div class="dc-sub"><strong>{{ deliveryInfo.shop_name }}</strong> does not currently deliver to your region.</div>
</div>
</div>
{% else %}
<div class="delivery-card ok">
<div class="dc-icon">โ
</div>
<div class="dc-body">
<div class="dc-title">Delivers to {{ deliveryInfo.region_name }}</div>
<div class="dc-sub">Delivery fee: <span class="dc-fee">${{ deliveryInfo.fee|number_format(2) }}</span> set by {{ deliveryInfo.shop_name }}</div>
</div>
</div>
{% endif %}
{% endif %}
<div class="prod-stock">
<span class="stock-dot {{ produit.qtt > 0 ? 'stock-in' : 'stock-out' }}"></span>
<span id="disp-stock" style="color:{{ produit.qtt > 0 ? '#16a34a' : '#dc2626' }}">
{% if produit.qtt > 0 %}In Stock ({{ produit.qtt }} available){% else %}Out of Stock{% endif %}
</span>
</div>
{# โโ OLD color/size variants (legacy products) โโ #}
{% if groupedVariantscolor|length > 0 %}
<div class="variants-section">
<div class="variants-label">Color:</div>
<div class="color-options">
{% for color, variants in groupedVariantscolor %}
<div class="color-opt" data-color="{{ color }}"
style="background-color:{{ color }}" title="{{ color }}"></div>
{% endfor %}
</div>
</div>
{% endif %}
{% if groupedVariantssize|length > 0 %}
<div class="variants-section">
<div class="variants-label">Size:</div>
<div class="size-options">
{% for size, variants in groupedVariantssize %}
<button type="button" class="size-opt" data-size="{{ size }}">{{ size }}</button>
{% endfor %}
</div>
</div>
{% endif %}
{# โโ NEW flexible variants (Scent/Size/etc. typed by the vendor) โโ #}
{% if isFlex %}
<div class="variants-section">
<div class="variants-label">
{% set dimNames = [] %}
{% if produit.variantType %}{% set dimNames = dimNames|merge([produit.variantType]) %}{% endif %}
{% if produit.variantType2 %}{% set dimNames = dimNames|merge([produit.variantType2]) %}{% endif %}
{% if produit.variantType3 %}{% set dimNames = dimNames|merge([produit.variantType3]) %}{% endif %}
Choose {% if dimNames|length > 0 %}{{ dimNames|join(' / ') }}{% else %}an option{% endif %}:
</div>
<div class="variant-list" id="variant-list">
{% for v in produit.produitVariants %}
{% set vals = [] %}
{% if v.optionLabel %}{% set vals = vals|merge([v.optionLabel]) %}{% endif %}
{% if v.optionLabel2 %}{% set vals = vals|merge([v.optionLabel2]) %}{% endif %}
{% if v.optionLabel3 %}{% set vals = vals|merge([v.optionLabel3]) %}{% endif %}
{% if vals|length > 0 %}
{% set vimg = v.images|length > 0 ? asset('assets/uploads/products/' ~ v.images|first.fileName) : '' %}
<button type="button" class="variant-card {% if loop.first %}active{% endif %}"
data-vid="{{ v.id }}"
data-price="{{ v.prix }}"
data-stock="{{ v.qtt }}"
data-img="{{ vimg }}">
<span class="vc-thumb">
{% if vimg %}
<img src="{{ vimg }}" alt="{{ vals|join(' ') }}"
onerror="this.onerror=null;this.style.display='none';this.parentNode.innerHTML='<span class=vc-noimg>๐ฆ</span>'">
{% else %}
<span class="vc-noimg">๐ฆ</span>
{% endif %}
</span>
<span class="vc-text">
<span class="vc-label">{{ vals|join(' ยท ') }}</span>
<span class="vc-meta">${{ v.prix|number_format(2) }} ยท {{ v.qtt|number_format(0) }} in stock</span>
</span>
</button>
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
{% if produit.qtt > 0 %}
<form method="post" id="cart-form">
<input type="hidden" id="chosenColor" name="chosenColor">
<input type="hidden" id="chosenSize" name="chosenSize">
<input type="hidden" name="productid" value="{{ produit.id }}">
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
<div class="prod-actions">
<div class="qty-wrap">
<button type="button" class="qty-btn-large" id="qty-minus">โ</button>
<input type="number" class="qty-input" id="qttprdid" name="qttprdid"
min="1" max="{{ produit.qtt }}" value="1">
<button type="button" class="qty-btn-large" id="qty-plus">+</button>
</div>
<button type="button" class="btn-add-cart" id="btn-add-cart"
data-add-url="{{ path('panier_add', {'id': produit.id, 'idVariante': 'notdefined', 'option': 'continue'}) }}"
data-add-base="{{ path('panier_add', {'id': produit.id, 'idVariante': '__VID__', 'option': 'continue'}) }}">
๐ Add to Cart
</button>
<button type="submit" class="btn-checkout-now" id="btn-buy-now"
formaction="{{ path('panier_add', {'id': produit.id, 'idVariante': 'notdefined', 'option': 'done'}) }}"
data-buy-base="{{ path('panier_add', {'id': produit.id, 'idVariante': '__VID__', 'option': 'done'}) }}">
โก Buy Now
</button>
</div>
</form>
{% else %}
<div style="background:#fee2e2;border:1.5px solid #fecaca;border-radius:var(--rsm);padding:16px;text-align:center;color:#dc2626;font-weight:600;margin-bottom:20px">
โ This product is currently out of stock
</div>
{% endif %}
<div class="platform-note">
<span class="platform-note-icon">โน๏ธ</span>
<div class="platform-note-text">
<strong>Julico is a marketplace platform.</strong>
Pricing, delivery, and transactions are handled directly between you and the seller. Julico is not responsible for shipping, payments, or returns.
</div>
</div>
</div>
</div>
</div>
<div class="cart-toast" id="cart-toast">
<span>โ Added to cart!</span>
<a href="{{ path('app_panier') }}">View Cart โ</a>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
var thumbGrid = document.getElementById('thumb-grid');
var mainImgEl = document.getElementById('main-img');
var variantList = document.getElementById('variant-list');
var dispPrice = document.getElementById('disp-price');
var dispNote = document.getElementById('disp-price-note');
var dispStock = document.getElementById('disp-stock');
var addBtnEl = document.getElementById('btn-add-cart');
var buyBtnEl = document.getElementById('btn-buy-now');
var qtyEl = document.getElementById('qttprdid');
function activateThumbForVid(vid) {
if (!thumbGrid) return;
var thumbs = thumbGrid.querySelectorAll('.thumb');
var found = false;
for (var i = 0; i < thumbs.length; i++) {
if (thumbs[i].dataset.vid && thumbs[i].dataset.vid === String(vid)) {
thumbs.forEach(function(t){ t.classList.remove('active'); });
thumbs[i].classList.add('active');
found = true;
break;
}
}
return found;
}
function selectVariant(card) {
if (!card) return;
if (variantList) {
variantList.querySelectorAll('.variant-card').forEach(function(c) { c.classList.remove('active'); });
}
card.classList.add('active');
var vid = card.dataset.vid;
var price = parseFloat(card.dataset.price || '0');
var stock = parseInt(card.dataset.stock || '0', 10);
var img = card.dataset.img;
if (dispPrice) dispPrice.textContent = price.toFixed(2);
if (dispNote) dispNote.textContent = 'Price set by seller';
if (dispStock) dispStock.textContent = stock > 0 ? ('In Stock (' + stock + ' available)') : 'Out of Stock';
if (qtyEl) {
qtyEl.max = stock > 0 ? stock : 1;
if (parseInt(qtyEl.value, 10) > stock) { qtyEl.value = Math.max(1, stock); }
}
if (img && mainImgEl) { mainImgEl.src = img; }
if (addBtnEl && addBtnEl.dataset.addBase) {
addBtnEl.dataset.addUrl = addBtnEl.dataset.addBase.replace('__VID__', vid);
}
if (buyBtnEl && buyBtnEl.dataset.buyBase) {
buyBtnEl.setAttribute('formaction', buyBtnEl.dataset.buyBase.replace('__VID__', vid));
}
activateThumbForVid(vid);
}
function selectVariantById(vid) {
if (!variantList) return false;
var cards = variantList.querySelectorAll('.variant-card');
for (var i = 0; i < cards.length; i++) {
if (cards[i].dataset.vid === String(vid)) {
selectVariant(cards[i]);
return true;
}
}
return false;
}
if (thumbGrid) {
thumbGrid.addEventListener('click', function(e) {
var thumb = e.target.closest('.thumb');
if (!thumb) return;
var vid = thumb.dataset.vid;
if (vid && selectVariantById(vid)) {
return;
}
var src = thumb.dataset.src;
var fallback = thumb.dataset.fallback;
if (mainImgEl && src) {
mainImgEl.src = src;
mainImgEl.onerror = function() { this.onerror = null; this.src = fallback; };
}
thumbGrid.querySelectorAll('.thumb').forEach(function(t) { t.classList.remove('active'); });
thumb.classList.add('active');
});
}
var qtyMinus = document.getElementById('qty-minus');
var qtyPlus = document.getElementById('qty-plus');
if (qtyMinus && qtyEl) {
qtyMinus.addEventListener('click', function() {
var val = parseInt(qtyEl.value) - 1;
qtyEl.value = Math.max(1, val);
});
}
if (qtyPlus && qtyEl) {
qtyPlus.addEventListener('click', function() {
var val = parseInt(qtyEl.value) + 1;
var max = parseInt(qtyEl.max) || 999;
qtyEl.value = Math.min(max, val);
});
}
document.querySelectorAll('.color-opt').forEach(function(el) {
el.addEventListener('click', function() {
document.querySelectorAll('.color-opt').forEach(function(c) { c.classList.remove('active'); });
el.classList.add('active');
var chosenColor = document.getElementById('chosenColor');
if (chosenColor) chosenColor.value = el.dataset.color;
});
});
document.querySelectorAll('.size-opt').forEach(function(el) {
el.addEventListener('click', function() {
document.querySelectorAll('.size-opt').forEach(function(s) { s.classList.remove('active'); });
el.classList.add('active');
var chosenSize = document.getElementById('chosenSize');
if (chosenSize) chosenSize.value = el.dataset.size;
});
});
if (variantList) {
variantList.addEventListener('click', function(e) {
var card = e.target.closest('.variant-card');
if (card) selectVariant(card);
});
var firstCard = variantList.querySelector('.variant-card');
if (firstCard) selectVariant(firstCard);
}
var addBtn = document.getElementById('btn-add-cart');
if (addBtn) {
addBtn.addEventListener('click', function() {
var form = document.getElementById('cart-form');
var addUrl = addBtn.dataset.addUrl;
var origTxt = addBtn.innerHTML;
addBtn.innerHTML = 'โฆ';
addBtn.style.opacity = '0.7';
addBtn.disabled = true;
var formData = new FormData(form);
var xhr = new XMLHttpRequest();
xhr.open('POST', addUrl);
xhr.withCredentials = true;
xhr.onload = function() {
var toast = document.getElementById('cart-toast');
if (toast) {
toast.classList.add('show');
setTimeout(function() { toast.classList.remove('show'); }, 4000);
}
addBtn.innerHTML = 'โ Added!';
addBtn.style.background = '#16a34a';
addBtn.style.opacity = '1';
setTimeout(function() {
addBtn.innerHTML = origTxt;
addBtn.style.background = '';
addBtn.disabled = false;
}, 1500);
};
xhr.onerror = function() {
addBtn.innerHTML = origTxt;
addBtn.style.opacity = '1';
addBtn.disabled = false;
form.action = addUrl;
form.submit();
};
xhr.send(formData);
});
}
});
</script>
</body>
</html>