관리-도구
편집 파일: 61a0665d62455e60043d89bb06319f0d.php
<?php $__env->startSection('content'); ?> <?php $currency = $s->currency_code ?? '$'; $total = $products->total(); $hasFilters = filled($q ?? null) || filled($cat ?? null) || filled($collection ?? null) || filled($min ?? null) || filled($max ?? null); ?> <section class="shop-hero border-bottom bg-gradient-subtle"> <div class="container py-4"> <div class="d-flex align-items-center justify-content-between flex-wrap gap-3"> <div> <h1 class="h3 mb-1"><?php echo e(__('messages.Shop')); ?></h1> <div class="text-muted small"> <?php echo e(trans_choice('messages.products', $total, ['count' => $total])); ?> <?php if($hasFilters): ?> • <?php echo e(__('messages.FiltersApplied')); ?> <?php endif; ?> </div> </div> <form method="get" action="<?php echo e(route('store.shop')); ?>" class="d-flex align-items-end gap-2 flex-wrap"> <?php $__currentLoopData = request()->except(['sort','page']); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $k => $v): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?> <?php if(is_array($v)): ?> <?php $__currentLoopData = $v; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $vv): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?><input type="hidden" name="<?php echo e($k); ?>[]" value="<?php echo e($vv); ?>"><?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?> <?php else: ?> <input type="hidden" name="<?php echo e($k); ?>" value="<?php echo e($v); ?>"> <?php endif; ?> <?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?> <div class="d-flex align-items-end gap-2"> <div> <label class="form-label small mb-1"><?php echo e(__('messages.Sort')); ?></label> <select name="sort" class="form-select form-select-sm"> <option value="latest" <?php if(($sort ?? 'latest') === 'latest'): echo 'selected'; endif; ?>><?php echo e(__('messages.Latest')); ?></option> <option value="price_asc" <?php if($sort === 'price_asc'): echo 'selected'; endif; ?>><?php echo e(__('messages.PriceUp')); ?></option> <option value="price_desc" <?php if($sort === 'price_desc'): echo 'selected'; endif; ?>><?php echo e(__('messages.PriceDown')); ?></option> </select> </div> <button class="btn btn-sm btn-primary"> <i class="bi bi-arrow-repeat"></i> <?php echo e(__('messages.Update')); ?> </button> </div> <button class="btn btn-outline-primary d-lg-none ms-2" type="button" data-bs-toggle="offcanvas" data-bs-target="#filtersOffcanvas"> <i class="bi bi-funnel"></i> <?php echo e(__('messages.Filters')); ?> </button> </form> </div> </div> </section> <div class="container py-4"> <div class="row"> <aside class="col-lg-3 d-none d-lg-block"> <?php echo $__env->make('store.partials.filters-card', [ 'q' => $q, 'cat' => $cat, 'collection' => $collection, 'min' => $min, 'max' => $max, 'sort' => $sort, 'categories' => $categories, 'collections' => $collections ], \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?> </aside> <main class="col-lg-9"> <?php if($hasFilters): ?> <div class="d-flex flex-wrap gap-2 mb-3"> <?php if(filled($q)): ?> <a href="<?php echo e(route('store.shop', request()->except('q','page'))); ?>" class="chip"> <i class="bi bi-search"></i> “<?php echo e($q); ?>” <span class="chip-x">×</span> </a> <?php endif; ?> <?php if(filled($cat)): ?> <?php $catName = optional($categories->firstWhere('id', $cat))->name ?? $cat; ?> <a href="<?php echo e(route('store.shop', request()->except('category','page'))); ?>" class="chip"> <i class="bi bi-tag"></i> <?php echo e($catName); ?> <span class="chip-x">×</span> </a> <?php endif; ?> <?php if(filled($collection)): ?> <?php $coObj = $collections->first(fn($c) => (string)$c->slug === (string)$collection || (string)$c->id === (string)$collection); $coName = $coObj->title ?? $collection; ?> <a href="<?php echo e(route('store.shop', request()->except('collection','page'))); ?>" class="chip"> <i class="bi bi-collection"></i> <?php echo e($coName); ?> <span class="chip-x">×</span> </a> <?php endif; ?> <?php if(filled($min)): ?> <a href="<?php echo e(route('store.shop', request()->except('min','page'))); ?>" class="chip"> <?php echo e(__('messages.Min')); ?>: <?php echo e($currency); ?><?php echo e(number_format((float)$min, 2)); ?> <span class="chip-x">×</span> </a> <?php endif; ?> <?php if(filled($max)): ?> <a href="<?php echo e(route('store.shop', request()->except('max','page'))); ?>" class="chip"> <?php echo e(__('messages.Max')); ?>: <?php echo e($currency); ?><?php echo e(number_format((float)$max, 2)); ?> <span class="chip-x">×</span> </a> <?php endif; ?> <a href="<?php echo e(route('store.shop')); ?>" class="chip chip-reset"> <i class="bi bi-x-circle"></i> <?php echo e(__('messages.ResetAll')); ?> </a> </div> <?php endif; ?> <?php if($products->count()): ?> <div class="row g-4"> <?php $__currentLoopData = $products; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $p): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?> <?php // Media & description $imgUrl = $p->image ? asset('images/products/'.$p->image) : asset('images/products/no-image.png'); $descShort = \Illuminate\Support\Str::limit(strip_tags($p->description ?? ''), 600); // FINAL product price from controller (already discount+tax). Fallback to model helper if needed. $taxRate = isset($p->TaxNet) ? (float)$p->TaxNet : (float)($s->default_tax_rate ?? 0); $finalPrice = (float)($p->display_price ?? (method_exists($p,'minDisplayPrice') ? $p->minDisplayPrice($taxRate) : ($p->price ?? 0))); // Variants payload with FINAL price for each (display_price) $hasVariants = $p->variants && $p->variants->count() > 0; $variantsPayload = $hasVariants ? $p->variants->map(function($v) use ($p, $imgUrl, $taxRate, $currency) { $base = (float)($v->price ?? 0); $calc = method_exists($p,'computeFinalPrice') ? $p->computeFinalPrice($taxRate, $base) : ['final' => $base]; return [ 'id' => (int)$v->id, 'name' => (string)($v->name ?? ''), 'price' => (float)$base, 'display_price' => (float)$calc['final'], 'display_price_formatted' => $currency . number_format($calc['final'], 2), 'image' => $v->image ? asset('images/products/'.$v->image) : $imgUrl, ]; })->values() : collect([]); ?> <div class="col-6 col-md-4 col-xl-3"> <div class="card product-card h-100 border-0 rounded-4 shadow-sm"> <div class="product-media ratio ratio-1x1 position-relative rounded-top-4 overflow-hidden"> <img src="<?php echo e($imgUrl); ?>" class="img-cover" alt="<?php echo e($p->name); ?>"> <div class="icon-stack"> <button type="button" class="btn btn-light btn-sm rounded-circle shadow position-absolute top-0 end-0 m-2 js-quick-view" title="<?php echo e(__('messages.QuickView')); ?>" style="z-index:3" data-id="<?php echo e($p->id); ?>" data-slug="<?php echo e($p->slug); ?>" data-name="<?php echo e(e($p->name)); ?>" data-price="<?php echo e(number_format($finalPrice, 2, '.', '')); ?>" data-image="<?php echo e($imgUrl); ?>" data-currency="<?php echo e($currency); ?>" data-description="<?php echo e(e($descShort)); ?>" data-variants='<?php echo json_encode($variantsPayload, 15, 512) ?>'> <i class="bi bi-eye"></i> </button> </div> <div class="media-gradient"></div> </div> <div class="card-body p-3"> <h6 class="product-title text-truncate mb-1" title="<?php echo e($p->name); ?>"> <span class="text-reset text-decoration-none"><?php echo e($p->name); ?></span> </h6> <div class="product-price fw-bold"> <?php echo e($currency); ?><?php echo e(number_format($finalPrice, 2)); ?> </div> </div> <div class="card-footer bg-white border-0 pt-0 pb-3 px-3"> <div class="d-grid"> <button type="button" class="btn btn-sm btn-primary w-100 js-add-to-cart" data-id="<?php echo e($p->id); ?>" data-slug="<?php echo e($p->slug); ?>" data-name="<?php echo e(e($p->name)); ?>" data-price="<?php echo e(number_format($finalPrice, 2, '.', '')); ?>" data-image="<?php echo e($imgUrl); ?>" data-currency="<?php echo e($currency); ?>" data-qty="1" data-product-id="<?php echo e($p->id); ?>" data-product-image="<?php echo e($imgUrl); ?>" data-variants='<?php echo json_encode($variantsPayload, 15, 512) ?>'> <i class="bi bi-cart-plus"></i> <?php echo e(__('messages.AddToCart')); ?> </button> <div class="small mt-2 js-add-status text-muted" style="min-height:1.25rem;"></div> </div> </div> </div> </div> <?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?> </div> <?php $products->appends(request()->except('page')); ?> <?php if($products->hasPages()): ?> <div class="mt-4 d-flex flex-column align-items-center gap-2"> <div class="text-muted small"> <?php if($products->total() > 0): ?> <?php echo e(__('messages.Showing')); ?> <strong><?php echo e($products->firstItem()); ?></strong>–<strong><?php echo e($products->lastItem()); ?></strong> <?php echo e(__('messages.of')); ?> <strong><?php echo e($products->total()); ?></strong> <?php echo e(__('messages.productsLower')); ?> <?php else: ?> <?php echo e(__('messages.NoProductsFound')); ?> <?php endif; ?> </div> <nav aria-label="Product pagination"> <ul class="pagination pagination-modern"> <?php if($products->onFirstPage()): ?> <li class="page-item disabled"><span class="page-link"><i class="bi bi-chevron-left"></i></span></li> <?php else: ?> <li class="page-item"><a class="page-link" href="<?php echo e($products->previousPageUrl()); ?>"><i class="bi bi-chevron-left"></i></a></li> <?php endif; ?> <?php $current = $products->currentPage(); $last = $products->lastPage(); $window = 1; $pages = collect([1, $last]) ->merge(range(max(1, $current - $window), min($last, $current + $window))) ->unique()->sort()->values(); $prev = null; ?> <?php $__currentLoopData = $pages; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $page): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?> <?php if(!is_null($prev) && $page - $prev > 1): ?> <li class="page-item disabled"><span class="page-link">…</span></li> <?php endif; ?> <?php if($page == $current): ?> <li class="page-item active"><span class="page-link"><?php echo e($page); ?></span></li> <?php else: ?> <li class="page-item"><a class="page-link" href="<?php echo e($products->url($page)); ?>"><?php echo e($page); ?></a></li> <?php endif; ?> <?php $prev = $page; ?> <?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?> <?php if($products->hasMorePages()): ?> <li class="page-item"><a class="page-link" href="<?php echo e($products->nextPageUrl()); ?>"><i class="bi bi-chevron-right"></i></a></li> <?php else: ?> <li class="page-item disabled"><span class="page-link"><i class="bi bi-chevron-right"></i></span></li> <?php endif; ?> </ul> </nav> </div> <?php endif; ?> <?php else: ?> <div class="text-center py-5"> <div class="display-6 mb-2">😕</div> <h5 class="mb-2"><?php echo e(__('messages.NoProductsFound')); ?></h5> <p class="text-muted mb-4"><?php echo e(__('messages.TryAdjustingFiltersOrBrowseAll')); ?></p> <a href="<?php echo e(route('store.shop')); ?>" class="btn btn-outline-primary"><?php echo e(__('messages.ClearFilters')); ?></a> </div> <?php endif; ?> </main> </div> </div> <div class="offcanvas offcanvas-end" tabindex="-1" id="filtersOffcanvas" aria-labelledby="filtersOffcanvasLabel"> <div class="offcanvas-header"> <h5 class="offcanvas-title" id="filtersOffcanvasLabel"><?php echo e(__('messages.Filters')); ?></h5> <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="<?php echo e(__('messages.Close')); ?>"></button> </div> <div class="offcanvas-body"> <?php echo $__env->make('store.partials.filters-card', [ 'q' => $q, 'cat' => $cat, 'collection' => $collection, 'min' => $min, 'max' => $max, 'sort' => $sort, 'categories' => $categories, 'collections' => $collections, 'isOffcanvas' => true ], \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?> </div> </div> <div class="modal fade" id="quickViewModal" tabindex="-1" aria-labelledby="quickViewLabel" aria-hidden="true"> <div class="modal-dialog modal-lg modal-dialog-centered"> <div class="modal-content rounded-4"> <div class="modal-body p-0"> <div class="row g-0"> <div class="col-lg-6"> <div class="qv-media"> <img id="qvImg" src="" alt="Product" class="qv-img"> </div> </div> <div class="col-lg-6"> <div class="p-4"> <button type="button" class="btn-close float-end" data-bs-dismiss="modal" aria-label="<?php echo e(__('messages.Close')); ?>"></button> <h3 id="qvTitle" class="h5 mb-1">—</h3> <div id="qvPrice" class="h4 text-primary mb-3">—</div> <div id="qvDesc" class="text-muted mb-3" style="max-height: 240px; overflow:auto;">—</div> <div id="qvVariantWrap" class="mb-3 d-none"> <div class="fw-semibold mb-1"><?php echo e(__('messages.ChooseVariant')); ?></div> <ul id="qvVariantList" class="list-group mb-2"></ul> <div class="text-muted small" id="qvSelectedInfo">—</div> </div> <div class="d-flex gap-2"> <button type="button" id="qvAddBtn" class="btn btn-primary"> <i class="bi bi-cart-plus"></i> <?php echo e(__('messages.AddToCart')); ?> </button> </div> <div id="qvStatus" class="small text-muted mt-3" style="min-height:1.25rem;"></div> </div> </div> </div> </div> </div> </div> </div> <div class="modal fade" id="variantPickerModal" tabindex="-1" aria-labelledby="variantPickerLabel" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered"> <div class="modal-content rounded-4"> <div class="modal-header"> <h5 class="modal-title" id="variantPickerLabel"><?php echo e(__('messages.ChooseVariant')); ?></h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="<?php echo e(__('messages.Close')); ?>"></button> </div> <div class="modal-body"> <div id="vpProductTitle" class="fw-semibold mb-2">—</div> <ul id="vpVariantList" class="list-group mb-3"></ul> <div class="d-flex align-items-center justify-content-between"> <div class="text-muted small" id="vpSelectedInfo">—</div> <button type="button" class="btn btn-primary" id="vpConfirmBtn" disabled> <i class="bi bi-cart-plus"></i> <?php echo e(__('messages.AddToCart')); ?> </button> </div> </div> </div> </div> </div> <style> .bg-gradient-subtle{ background: linear-gradient(90deg, rgba(108,92,231,.05), rgba(0,194,255,.05)); } .chip{ display:inline-flex; align-items:center; gap:.5rem; background:#f8fafc; border:1px solid #e5e7eb; border-radius:999px; padding:.35rem .7rem; text-decoration:none; color:#334155; font-size:.9rem; } .chip:hover{ background:#fff; border-color:#cbd5e1; color:#0f172a; } .chip .chip-x{ color:#94a3b8; margin-left:.2rem; } .product-card{ border-radius:1rem; transition: transform .15s ease, box-shadow .15s ease; box-shadow: 0 2px 10px rgba(15,23,42,.06); } .product-card:hover{ transform: translateY(-3px); box-shadow: 0 8px 24px rgba(15,23,42,.08); } .ratio.ratio-1x1{ --bs-aspect-ratio:100%; } .img-cover{ width:100%; height:100%; object-fit:cover; display:block; } .pagination-modern{ display:flex; gap:.25rem; } .pagination-modern .page-link{ border-radius:.6rem; border:1px solid #e5e7eb; color:#334155; background:#fff; padding:.45rem .75rem; } .pagination-modern .page-link:hover{ border-color:#cbd5e1; color:#0f172a; } .pagination-modern .page-item.active .page-link{ background:#0d6efd; border-color:#0d6efd; color:#fff; box-shadow:0 0 0 .15rem rgba(13,110,253,.15); } .pagination-modern .page-item.disabled .page-link{ color:#94a3b8; background:#f8fafc; border-color:#e5e7eb; } .product-media{ position:relative; } .icon-stack{ position:absolute; top:.6rem; right:.6rem; display:flex; flex-direction:column; gap:.4rem; z-index:2; } .media-gradient{ content:""; position:absolute; inset:0; background: linear-gradient(to top, rgba(0,0,0,.35), rgba(0,0,0,0) 50%); opacity:0; transition: opacity .2s ease; } .product-media:hover .media-gradient{ opacity:.9; } .qv-media{ position:relative; min-height: 420px; background:#0b1220; display:flex; align-items:center; justify-content:center; overflow:hidden; border-top-left-radius:1rem; border-bottom-left-radius:1rem; } .qv-img{ max-width:100%; max-height:80vh; } </style> <script> (function(){ const NOIMG = <?php echo json_encode(asset('images/products/no-image.png'), 15, 512) ?>; const CURRENCY = <?php echo json_encode($currency, 15, 512) ?>; const safeParse = (str) => { try { return JSON.parse(str || '[]'); } catch(e){ return []; } }; const money = (v) => CURRENCY + Number(v||0).toFixed(2); const html = (s) => String(s||'').replace(/[&<>"']/g, m => ({'&':'&','<':'<','>':'>','"':'"','\'':'''}[m])); /* ---------- QUICK VIEW ---------- */ const qvModalEl = document.getElementById('quickViewModal'); const qvImg = document.getElementById('qvImg'); const qvTitle = document.getElementById('qvTitle'); const qvPrice = document.getElementById('qvPrice'); const qvDesc = document.getElementById('qvDesc'); const qvWrap = document.getElementById('qvVariantWrap'); const qvList = document.getElementById('qvVariantList'); const qvInfo = document.getElementById('qvSelectedInfo'); const qvBtn = document.getElementById('qvAddBtn'); const qvStatus= document.getElementById('qvStatus'); let qvProduct = null, qvSelected = null; document.addEventListener('click', function(e){ const trigger = e.target.closest('.js-quick-view'); if(!trigger) return; e.preventDefault(); const variants = safeParse(trigger.dataset.variants); qvProduct = { id : Number(trigger.dataset.id), slug : trigger.dataset.slug, name : trigger.dataset.name || '', price : parseFloat(trigger.dataset.price || '0'), // FINAL min price image : trigger.dataset.image || NOIMG, currency : trigger.dataset.currency || CURRENCY, description: trigger.dataset.description || '', variants : Array.isArray(variants) ? variants : [] }; // Fill UI qvImg.src = qvProduct.image || NOIMG; qvTitle.textContent = qvProduct.name || '—'; qvDesc.textContent = qvProduct.description || ''; qvList.innerHTML = ''; qvSelected = null; if (qvProduct.variants.length){ qvWrap.classList.remove('d-none'); qvProduct.variants.forEach(v => { const show = (typeof v.display_price !== 'undefined') ? v.display_price : v.price; const li = document.createElement('li'); li.className = 'list-group-item d-flex align-items-center justify-content-between'; li.innerHTML = ` <div> <div class="fw-semibold">${html(v.name || '')}</div> <div class="text-muted small">${money(show)}</div> </div> <div><input class="form-check-input" type="radio" name="qvChoice" value="${v.id}"></div> `; qvList.appendChild(li); }); qvInfo.textContent = <?php echo json_encode(__('messages.SelectVariant'), 15, 512) ?>; qvBtn.disabled = true; qvList.addEventListener('change', onQVChange, { once:true }); qvPrice.textContent = money(qvProduct.price); } else { qvWrap.classList.add('d-none'); qvInfo.textContent = '—'; qvBtn.disabled = false; qvPrice.textContent = money(qvProduct.price); } if (window.bootstrap && qvModalEl) bootstrap.Modal.getOrCreateInstance(qvModalEl).show(); }); function onQVChange(){ const chosen = qvList.querySelector('input[name="qvChoice"]:checked'); if (!chosen){ qvSelected = null; qvInfo.textContent = <?php echo json_encode(__('messages.SelectVariant'), 15, 512) ?>; qvBtn.disabled = true; } else { const id = Number(chosen.value); qvSelected = (qvProduct.variants || []).find(v => Number(v.id) === id) || null; if (qvSelected){ const show = (typeof qvSelected.display_price !== 'undefined') ? qvSelected.display_price : qvSelected.price; qvInfo.textContent = `${qvSelected.name || ''} — ${money(show)}`; qvPrice.textContent = money(show); qvBtn.disabled = false; } } qvList.addEventListener('change', onQVChange, { once:true }); } qvBtn.addEventListener('click', function(){ if (!qvProduct) return; let item; if ((qvProduct.variants || []).length){ if (!qvSelected) { qvStatus.textContent = <?php echo json_encode(__('messages.SelectVariant'), 15, 512) ?>; return; } const priceUse = (typeof qvSelected.display_price !== 'undefined') ? qvSelected.display_price : qvSelected.price; item = { id: String(qvProduct.id) + ':' + String(qvSelected.id), product_id: qvProduct.id, product_variant_id: Number(qvSelected.id), name: (qvProduct.name || 'Item') + ' — ' + (qvSelected.name || ''), variant_name: qvSelected.name || '', price: Number(priceUse || 0), qty: 1, image: qvProduct.image || NOIMG, slug: qvProduct.slug || '', currency: qvProduct.currency || CURRENCY }; } else { item = { id: String(qvProduct.id), product_id: qvProduct.id, name: qvProduct.name || 'Item', price: Number(qvProduct.price || 0), qty: 1, image: qvProduct.image || NOIMG, slug: qvProduct.slug || '', currency: qvProduct.currency || CURRENCY }; } try { CartLS.add(item, 1); } catch(e){ console.error(e); } if (window.bootstrap && qvModalEl) bootstrap.Modal.getOrCreateInstance(qvModalEl).hide(); }); /* ---------- VARIANT PICKER (for card Add-to-cart) ---------- */ const vpEl = document.getElementById('variantPickerModal'); const vpTitle = document.getElementById('vpProductTitle'); const vpList = document.getElementById('vpVariantList'); const vpInfo = document.getElementById('vpSelectedInfo'); const vpBtn = document.getElementById('vpConfirmBtn'); let vpProduct = null, vpSelected = null; function openVariantPicker(source){ const variants = safeParse(source.dataset.variants); vpProduct = { id: Number(source.dataset.productId || source.dataset.id), name: source.dataset.name || source.getAttribute('data-name') || '', image: source.dataset.productImage || source.dataset.image || NOIMG, currency: source.dataset.currency || CURRENCY, slug: source.dataset.slug || '', variants: Array.isArray(variants) ? variants : [] }; vpSelected = null; vpTitle.textContent = vpProduct.name || ''; vpList.innerHTML = ''; (vpProduct.variants || []).forEach(v => { const show = (typeof v.display_price !== 'undefined') ? v.display_price : v.price; const li = document.createElement('li'); li.className = 'list-group-item d-flex align-items-center justify-content-between'; li.innerHTML = ` <div> <div class="fw-semibold">${html(v.name || '')}</div> <div class="text-muted small">${money(show)}</div> </div> <div><input class="form-check-input" type="radio" name="vpChoice" value="${v.id}"></div> `; vpList.appendChild(li); }); vpInfo.textContent = <?php echo json_encode(__('messages.SelectVariant'), 15, 512) ?>; vpBtn.disabled = true; function onVPChange(){ const chosen = vpList.querySelector('input[name="vpChoice"]:checked'); if (!chosen){ vpSelected = null; vpBtn.disabled = true; vpInfo.textContent = <?php echo json_encode(__('messages.SelectVariant'), 15, 512) ?>; } else { const id = Number(chosen.value); vpSelected = (vpProduct.variants || []).find(v => Number(v.id) === id) || null; if (vpSelected){ const show = (typeof vpSelected.display_price !== 'undefined') ? vpSelected.display_price : vpSelected.price; vpInfo.textContent = `${vpSelected.name || ''} — ${money(show)}`; vpBtn.disabled = false; } } vpList.addEventListener('change', onVPChange, { once:true, passive:false }); } vpList.addEventListener('change', onVPChange, { once:true, passive:false }); if (window.bootstrap && vpEl) bootstrap.Modal.getOrCreateInstance(vpEl).show(); } vpBtn.addEventListener('click', function(){ if (!vpProduct || !vpSelected) return; const priceUse = (typeof vpSelected.display_price !== 'undefined') ? vpSelected.display_price : vpSelected.price; const item = { id: String(vpProduct.id) + ':' + String(vpSelected.id), product_id: vpProduct.id, product_variant_id: Number(vpSelected.id), name: (vpProduct.name || 'Item') + ' — ' + (vpSelected.name || ''), variant_name: vpSelected.name || '', price: Number(priceUse || 0), qty: 1, image: vpSelected.image || vpProduct.image || NOIMG, slug: vpProduct.slug || '', currency: vpProduct.currency || CURRENCY }; try { CartLS.add(item, 1); } catch(e){ console.error(e); } if (window.bootstrap && vpEl) bootstrap.Modal.getOrCreateInstance(vpEl).hide(); }); // Capture-phase: if .js-add-to-cart has variants, open picker and stop global handler (SAME as your base) document.addEventListener('click', function(e){ const btn = e.target.closest('.js-add-to-cart'); if (!btn) return; const variants = safeParse(btn.dataset.variants); if (Array.isArray(variants) && variants.length){ e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); if (!btn.dataset.productId) btn.dataset.productId = btn.dataset.id || ''; if (!btn.dataset.productImage) btn.dataset.productImage = btn.dataset.image || NOIMG; openVariantPicker(btn); return; } // else: no variants => allow global handler on the page to handle add-to-cart }, true); })(); </script> <?php $__env->stopSection(); ?> <?php echo $__env->make('layouts.store', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH /home/inprosysltd/public_html/rtlpos.inprosysltd.com/resources/views/store/shop.blade.php ENDPATH**/ ?>