// Cart/Index.cshtml için modern ve güvenli sepet scripti
document.addEventListener('DOMContentLoaded', () => {
if (!window.location.pathname.startsWith('/Cart')) return;
// X-CSRF-TOKEN meta ve header ile fetch
const csrfToken = document.querySelector('meta[name="X-CSRF-TOKEN"]')?.content;
const format = v =>
new Intl.NumberFormat('tr-TR', {
style: 'currency',
currency: 'TRY'
}).format(v);
async function postJson(url, data) {
const res = await fetch(url, {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken
},
body: JSON.stringify(data)
});
return res.ok ? res.json() : null;
}
// Adet azalt/çoğalt
document.querySelectorAll('.btn-decr, .btn-incr').forEach(btn => {
btn.addEventListener('click', async () => {
const key = btn.dataset.key;
const [id, varId] = key.split('-');
const qtyEl = document.getElementById(`qty-${key}`);
const delta = btn.classList.contains('btn-incr') ? 1 : -1;
const newQty = parseInt(qtyEl.value) + delta;
if (newQty < 1) return;
const json = await postJson('/Cart/ChangeQuantity', {
UrunId: +id, VariationId: +varId, Adet: newQty
});
if (!json?.success) {
console.warn('Adet güncellenemedi:', json?.error);
return;
}
qtyEl.value = json.newQty;
document.getElementById(`line-total-${key}`).textContent =
json.lineTotalText ?? format(json.lineTotal);
if (json.cartTotal !== undefined) {
document.getElementById('cart-total').textContent =
json.cartTotalText ?? format(json.cartTotal);
}
if (window.updateCartCountUI) window.updateCartCountUI(json.itemCount);
});
});
// Ürünü sil
document.querySelectorAll('.btn-remove').forEach(btn => {
btn.addEventListener('click', async () => {
// Bu işlevi Cart/Index.cshtml'deki Bootstrap modal ile yönetiyoruz. Buradaki native confirm kaldırıldı.
// Kod burada boş bırakıldı veya sadece modal tetikleniyor olabilir.
// ...
const key = btn.dataset.key;
const [id, varId] = key.split('-');
const json = await postJson('/Cart/RemoveItem', {
UrunId: +id, VariationId: (varId && +varId > 0) ? +varId : null
});
if (!json?.success) {
console.warn('Silinemedi:', json?.error);
return;
}
document.getElementById(`row-${key}`)?.remove();
if (json.cartTotal !== undefined) {
document.getElementById('cart-total').textContent =
json.cartTotalText ?? format(json.cartTotal);
}
if (window.updateCartCountUI) window.updateCartCountUI(json.itemCount);
});
});
});
// window.removeItem fonksiyonu kaldırıldı. Sepet silme işlemi sadece Cart/Index.cshtml içindeki event listener ile çalışacak.
(function(){
function updateCartBadge() {
fetch('/Cart/Count')
.then(r => r.json())
.then(data => {
const count = data.cartCount ?? data.itemCount ?? 0;
const badge = document.querySelector('a.nav-link[href*="/Cart"] .badge');
if (badge) badge.textContent = count;
})
.catch(console.error);
}
window.updateCartBadge = updateCartBadge;
document.addEventListener('DOMContentLoaded', () => {
updateCartBadge();
});
}());
// Toastr konumunu sola almak için ayar
if (window.toastr) {
toastr.options.positionClass = 'toast-top-center';
}
// SignalR ile anlık bildirim (devre dışı bırakıldı — push gönderimi yerine e-posta kuyruğu kullanılacak)
if (window.signalR) {
// keep the client-side handlers for graceful re-enable, but do not start the connection
// const connection = new signalR.HubConnectionBuilder().withUrl("/hubs/notifications").build();
// connection.on("ReceiveNotification", data => { toastr.info(data.message, data.title); });
// connection.start().catch(err => console.error(err));
console.info('SignalR client disabled by server-side configuration');
}
// Bildirim dropdown tıklama davranışı
$('.notif-item').on('click', function() {
var id = $(this).data('id');
var $item = $(this).closest('li');
$.post('/Notifications/MarkAsRead', { id: id }, function(res) {
if (res.success || res.ok) {
$item.remove();
var $badge = $('.badge-notify');
var count = parseInt($badge.text() || '0') - 1;
if (count > 0) {
$badge.text(count);
} else {
$badge.remove();
}
$('#allNotifBtn').show();
}
});
});
// Modal ve ürün ekleme fonksiyonları
const addCartModalEl = document.getElementById('addCartModal');
let currentProductId = null;
window.showAddToCartModal = async function(productId, variantsJson) {
// productId may be undefined for some legacy callers; pick a sensible fallback after we parse variants
// If caller didn't include variants JSON, fetch from server
let variantsRaw = [];
try {
variantsRaw = JSON.parse(variantsJson || '[]');
} catch(e) { variantsRaw = []; }
try { console && console.debug && console.debug('[AddCartModal] .btn-add-cart clicked', { pid: productId, variantsJson: variantsJson }); } catch(e) {}
if ((!variantsRaw || variantsRaw.length === 0) && productId) {
try {
console.debug('[AddCartModal] fetching variants for product', productId);
const resp = await fetch(`/Urunler/GetVaryasyonlar?urunId=${encodeURIComponent(productId)}`, { credentials: 'same-origin' });
if (resp.ok) {
variantsRaw = await resp.json();
console.debug('[AddCartModal] fetched variants', variantsRaw);
} else {
console.debug('[AddCartModal] failed to fetch variants', resp.status);
}
} catch (err) { console.debug('[AddCartModal] fetch error', err); }
}
// normalize keys (server may return camelCase or lowercase)
const variants = (variantsRaw || []).map(v => ({
Id: v.Id ?? v.id ?? v.ID,
Uzunluk: v.Uzunluk ?? v.uzunluk ?? v.Uzunluk ?? '',
Olcu: v.Olcu ?? v.olcu ?? v.Olcu ?? '',
Fiyat: (v.Fiyat ?? v.fiyat) ?? 0,
BayiFiyat: (v.BayiFiyat ?? v.bayiFiyat) ?? 0
}));
// determine an effective product id: prefer provided id, otherwise use first variant's Id
const effectiveProductId = productId || (variants && variants.length ? (variants[0].Id ?? variants[0].id) : undefined);
currentProductId = effectiveProductId;
// if there are no variants and caller provided a product-level price in data attribute, use it
try {
if ((!variants || variants.length === 0) && productId) {
var opener = document.querySelector('.btn-add-cart[data-product-id="' + productId + '"]');
if (opener && opener.getAttribute) {
var pp = opener.getAttribute('data-product-price');
if (pp) {
// show price in modal if variant price area exists
try {
var priceEl = document.getElementById('variantPriceInfo');
if (priceEl) {
var n = parseFloat(pp);
if (!isNaN(n) && n > 0) {
priceEl.textContent = new Intl.NumberFormat('tr-TR', { style: 'currency', currency: 'TRY' }).format(n);
priceEl.style.display = 'block';
}
}
} catch(e) {}
}
}
}
} catch(e) {}
// keep a lookup map of variants for reliable price access during selection handlers
if (!window._currentVariants) window._currentVariants = {};
try { window._currentVariants[String(effectiveProductId)] = variants; } catch(e) { window._currentVariants = window._currentVariants || {}; }
console.debug('[AddCartModal] currentVariants for', effectiveProductId, window._currentVariants[String(effectiveProductId)]);
// If there are no variants, we still show the modal (hidden variant group) so the user can
// confirm quantity and see the product-level price; do not auto-submit from here.
// Support two modal variants used in the app:
// - Shared modal: #addCartModal with #cartVariant, #cartQuantity, #variantPriceInfo
// - Legacy page modal: #adetModal with #modalVaryasyon, #modalAdet, #modalUnitPrice, #varyasyonFiyat
const selGroup = document.getElementById('variantGroup');
const sel = document.getElementById('cartVariant');
const legacySel = document.getElementById('modalVaryasyon');
const legacyQty = document.getElementById('modalAdet');
const legacyUnitPrice = document.getElementById('modalUnitPrice');
const legacyVaryasyonFiyat = document.getElementById('varyasyonFiyat');
// populate shared select if present
if (sel) {
sel.innerHTML = '';
}
// populate legacy select if present
if (legacySel) {
legacySel.innerHTML = '';
}
if (variants.length) {
variants.forEach(v => {
const measure = (v.Uzunluk && v.Uzunluk.trim())
? v.Uzunluk.trim()
: (v.Olcu && v.Olcu.trim())
? v.Olcu.trim()
: '–';
const price = (v.BayiFiyat ?? v.Fiyat ?? 0);
// Show only measure text in option; price will be shown below when user selects a variant
const label = measure;
if (sel) {
const opt = document.createElement('option');
opt.value = v.Id;
opt.text = label;
opt.dataset.price = price;
opt.dataset.fiyat = v.Fiyat ?? 0;
opt.dataset.bayifiyat = v.BayiFiyat ?? 0;
sel.append(opt);
}
if (legacySel) {
const opt2 = document.createElement('option');
opt2.value = v.Id;
opt2.text = (v.Uzunluk && v.Uzunluk.trim()) ? v.Uzunluk : (v.Olcu ?? 'Varyant');
opt2.dataset.fiyat = v.Fiyat ?? 0;
opt2.dataset.bayifiyat = v.BayiFiyat ?? 0;
legacySel.append(opt2);
}
});
if (selGroup && sel) selGroup.classList.remove('d-none');
if (legacySel) legacySel.disabled = false;
} else {
if (selGroup && sel) selGroup.classList.add('d-none');
if (legacySel) legacySel.disabled = true;
}
const priceInfoEl = document.getElementById('variantPriceInfo');
if (priceInfoEl) priceInfoEl.style.display = 'none';
// Her çağrıda modal instance'ı güncelle
let modalInstance = window.addCartModal;
if (!modalInstance || typeof modalInstance.show !== 'function') {
modalInstance = bootstrap.Modal.getOrCreateInstance(addCartModalEl);
window.addCartModal = modalInstance;
}
// Also initialize legacy modal instance if present
const adagModalEl = document.getElementById('adetModal');
if (adagModalEl && window.bootstrap && bootstrap.Modal) {
bootstrap.Modal.getOrCreateInstance(adagModalEl);
}
// store modal-scoped data so the confirm handler in the partial can read them
try {
// use jQuery if present for consistent `.data()` semantics used elsewhere
if (window.jQuery && $(addCartModalEl)) {
$(addCartModalEl).data('product-id', effectiveProductId);
$(addCartModalEl).data('variants', variants);
} else {
// fallback to dataset (stringified)
addCartModalEl.dataset.productId = effectiveProductId;
addCartModalEl.dataset.variants = JSON.stringify(variants || []);
}
} catch (e) { console && console.debug && console.debug('[AddCartModal] set modal data error', e); }
modalInstance.show();
try { console && console.debug && console.debug('[AddCartModal] shown for', effectiveProductId, { variantsLength: variants.length }); } catch(e) {}
// set hidden modal inputs so the server receives UrunId even if client posts form-encoded
try {
const modalUrunIdEl = document.getElementById('modalUrunId'); if (modalUrunIdEl) modalUrunIdEl.value = effectiveProductId || '';
const modalVarEl = document.getElementById('modalVariationId'); if (modalVarEl) modalVarEl.value = '';
const modalOlcuHidden = document.getElementById('modalOlcuHidden'); if (modalOlcuHidden) modalOlcuHidden.value = '';
const modalUzunlukHidden = document.getElementById('modalUzunlukHidden'); if (modalUzunlukHidden) modalUzunlukHidden.value = '';
} catch(e) { console && console.debug && console.debug('[AddCartModal] set hidden inputs error', e); }
// ensure currentProductId stored as string for lookups
try { currentProductId = String(effectiveProductId || ''); addCartModalEl && (addCartModalEl.dataset.productId = String(effectiveProductId || '')); } catch(e) {}
};
// Note: add-to-cart button handling is implemented in the modal partial (_CartModalAndOffcanvas.cshtml)
// to avoid duplicate handlers and jQuery/vanilla conflicts. Do not add another global delegation here.
// Confirm button handler is implemented inside the modal partial to keep all modal logic together.
// Update displayed variant price when user changes selection inside modal
const variantSelect = document.getElementById('cartVariant');
const variantPriceInfo = document.getElementById('variantPriceInfo');
if (variantSelect && variantPriceInfo) {
variantSelect.addEventListener('change', async () => {
const opt = variantSelect.options[variantSelect.selectedIndex];
if (!opt) { variantPriceInfo.style.display = 'none'; return; }
const varId = opt.value;
let displayPrice = 0;
try { console && console.debug && console.debug('[AddCartModal] variant change', { currentProductId, varId, optDataset: opt.dataset }); } catch(e) {}
// try lookup from stored variants first
try {
const map = window._currentVariants && window._currentVariants[String(currentProductId)];
if (map && map.length) {
const found = map.find(v => String(v.Id) === String(varId));
if (found) {
displayPrice = Number(found.BayiFiyat ?? found.Fiyat ?? 0) || 0;
}
}
} catch (e) { /* ignore */ }
// fallback to dataset if lookup failed
if (!displayPrice) {
const bayif = parseFloat(opt.dataset.bayifiyat || opt.dataset.price || 0) || 0;
const fiyat = parseFloat(opt.dataset.fiyat || 0) || 0;
displayPrice = (bayif > 0 ? bayif : fiyat) || 0;
}
// If still zero, ask server for variant's price (handles computed bayi price)
if (!displayPrice && varId) {
try {
const resp = await fetch(`/Cart/VariantPrice?variationId=${encodeURIComponent(varId)}`, { credentials: 'same-origin' });
if (resp.ok) {
const j = await resp.json();
// prefer display text if provided, otherwise numeric price
if (j && (j.display || j.price !== undefined)) {
if (j.display) {
variantPriceInfo.textContent = j.display;
variantPriceInfo.style.display = 'block';
return;
}
displayPrice = Number(j.price || 0) || 0;
}
}
} catch (err) { console.debug('[AddCartModal] VariantPrice fetch error', err); }
}
if (displayPrice > 0) {
variantPriceInfo.textContent = new Intl.NumberFormat('tr-TR', { style: 'currency', currency: 'TRY' }).format(displayPrice);
variantPriceInfo.style.display = 'block';
variantPriceInfo.classList.add('text-success');
try { console && console.debug && console.debug('[AddCartModal] variant price resolved locally', { currentProductId, varId, displayPrice }); } catch(e) {}
} else {
variantPriceInfo.style.display = 'none';
variantPriceInfo.classList.remove('text-success');
try { console && console.debug && console.debug('[AddCartModal] variant price not found locally; varId, will try server if present', { currentProductId, varId }); } catch(e) {}
}
});
}
// Legacy modal handlers removed: we rely on shared modal (#cartVariant) behavior only.
// Confirm add-to-cart button handler (centralized here so partial no longer contains inline AJAX)
try {
// jQuery delegation if available
if (window.jQuery) {
$(document).on('click', '#confirmAddCart', async function (e) {
e.preventDefault();
e.stopPropagation();
if (window._addToCartInFlight) { console && console.debug && console.debug('[AddCartModal] add in flight, ignoring click'); return; }
window._addToCartInFlight = true;
try {
console && console.debug && console.debug('[AddCartModal] confirm clicked');
const modalEl = document.getElementById('addCartModal');
const $modal = $(modalEl);
const variants = $modal.data('variants') || (modalEl && modalEl.dataset && modalEl.dataset.variants ? JSON.parse(modalEl.dataset.variants) : []) || [];
const _productIdRaw = $modal.data('product-id') || (modalEl && modalEl.dataset && modalEl.dataset.productId) || document.getElementById('modalUrunId')?.value || null;
const productId = (_productIdRaw !== null && _productIdRaw !== undefined && _productIdRaw !== '') ? (isNaN(Number(_productIdRaw)) ? null : Number(_productIdRaw)) : null;
const varEl = document.getElementById('cartVariant');
const variationId = parseInt((varEl && varEl.value) || (document.getElementById('modalVariationId')?.value || '0')) || 0;
const adet = parseInt(document.getElementById('cartQuantity')?.value || '1') || 1;
if (variants && variants.length && variationId === 0) {
alert('Lütfen bir uzunluk seçiniz.');
return;
}
const selOpt = varEl && varEl.selectedOptions && varEl.selectedOptions[0];
const uzun = selOpt ? (selOpt.textContent || selOpt.innerText || '').trim() : '';
try { document.getElementById('modalUrunId') && (document.getElementById('modalUrunId').value = productId || ''); } catch(e){}
try { document.getElementById('modalVariationId') && (document.getElementById('modalVariationId').value = variationId || ''); } catch(e){}
try { document.getElementById('modalUzunlukHidden') && (document.getElementById('modalUzunlukHidden').value = uzun || ''); } catch(e){}
const payload = {
VariationId: variationId || null,
UrunId: productId || null,
Adet: adet || 1,
Olcu: null,
Uzunluk: uzun || null
};
const xsrf = document.querySelector('meta[name="X-CSRF-TOKEN"]')?.content || '';
const resp = await fetch('/Cart/AddToCart', {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': xsrf
},
body: JSON.stringify(payload)
});
if (!resp.ok) {
const txt = await resp.text();
let parsed = null;
try { parsed = JSON.parse(txt); } catch(e) {}
throw new Error(parsed?.error || parsed?.message || txt || ('HTTP ' + resp.status));
}
const j = await resp.json();
if (j && j.success) {
try { if (j.itemCount !== undefined) { $('.cart-count').text(j.itemCount); if (window.updateCartCountUI) window.updateCartCountUI(j.itemCount); } } catch(e){}
try { var bs = bootstrap.Modal.getInstance(document.getElementById('addCartModal')) || bootstrap.Modal.getOrCreateInstance(document.getElementById('addCartModal')); if (bs) bs.hide(); bootstrap.Modal.getOrCreateInstance(document.getElementById('addedSuccessModal')).show(); } catch(e){}
try { if (typeof variantPriceInfo !== 'undefined' && variantPriceInfo) variantPriceInfo.classList.add('text-success'); } catch(e){}
} else {
alert((j && (j.error || j.message)) || 'Sepete eklenemedi.');
}
} catch (err) {
console && console.error && console.error('[AddCartModal] add error', err);
alert(err && err.message ? err.message : 'Sepete ekleme başarısız.');
} finally {
window._addToCartInFlight = false;
}
});
}
// Native fallback if jQuery isn't available or delegation failed
// Use a single-flight guard to avoid double submissions when both capture and bubble handlers exist.
try {
document.addEventListener('click', function (e) {
try {
var btn = e.target && (e.target.closest ? e.target.closest('#confirmAddCart') : null);
if (!btn) return;
// prevent other handlers from running for this click
e.preventDefault();
e.stopPropagation();
// If jQuery exists, do not trigger it — run native flow to avoid double-calls
(async function(){
try {
if (window._addToCartInFlight) { console && console.debug && console.debug('[AddCartModal] add in flight, ignoring native click'); return; }
window._addToCartInFlight = true;
console && console.debug && console.debug('[AddCartModal][native] confirm clicked');
const modalEl = document.getElementById('addCartModal');
const variants = modalEl && modalEl.dataset && modalEl.dataset.variants ? JSON.parse(modalEl.dataset.variants) : (window._currentVariants && window._currentVariants[String(modalEl && modalEl.dataset && modalEl.dataset.productId)]) || [];
const _productIdRaw = (modalEl && modalEl.dataset && modalEl.dataset.productId) || document.getElementById('modalUrunId')?.value || null;
const productId = (_productIdRaw !== null && _productIdRaw !== undefined && _productIdRaw !== '') ? (isNaN(Number(_productIdRaw)) ? null : Number(_productIdRaw)) : null;
const varEl = document.getElementById('cartVariant');
const variationId = parseInt((varEl && varEl.value) || (document.getElementById('modalVariationId')?.value || '0')) || 0;
const adet = parseInt(document.getElementById('cartQuantity')?.value || '1') || 1;
if (variants && variants.length && variationId === 0) { alert('Lütfen bir uzunluk seçiniz.'); window._addToCartInFlight = false; return; }
const selOpt = varEl && varEl.selectedOptions && varEl.selectedOptions[0];
const uzun = selOpt ? (selOpt.textContent || selOpt.innerText || '').trim() : '';
try { document.getElementById('modalUrunId') && (document.getElementById('modalUrunId').value = productId || ''); } catch(e){}
try { document.getElementById('modalVariationId') && (document.getElementById('modalVariationId').value = variationId || ''); } catch(e){}
try { document.getElementById('modalUzunlukHidden') && (document.getElementById('modalUzunlukHidden').value = uzun || ''); } catch(e){}
const payload = { VariationId: variationId || null, UrunId: productId || null, Adet: adet || 1, Olcu: null, Uzunluk: uzun || null };
const xsrf = document.querySelector('meta[name="X-CSRF-TOKEN"]')?.content || '';
const resp = await fetch('/Cart/AddToCart', { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': xsrf }, body: JSON.stringify(payload) });
if (!resp.ok) { const txt = await resp.text(); let parsed=null; try{parsed=JSON.parse(txt);}catch{} throw new Error(parsed?.error||parsed?.message||txt||('HTTP '+resp.status)); }
const j = await resp.json();
if (j && j.success) {
try { var bs = bootstrap.Modal.getInstance(document.getElementById('addCartModal')) || bootstrap.Modal.getOrCreateInstance(document.getElementById('addCartModal')); if (bs) bs.hide(); bootstrap.Modal.getOrCreateInstance(document.getElementById('addedSuccessModal')).show(); } catch(e){}
try { document.querySelectorAll('.cart-count').forEach(el=>el.textContent = j.itemCount); if (window.updateCartCountUI) window.updateCartCountUI(j.itemCount); } catch(e){}
} else { alert((j && (j.error||j.message)) || 'Sepete eklenemedi.'); }
} catch(err) { console && console.error && console.error('[AddCartModal][native] add error', err); alert(err && err.message ? err.message : 'Sepete ekleme başarısız.'); }
finally { window._addToCartInFlight = false; }
})();
} catch(inner) { /* swallow */ }
}, true);
} catch(e) { /* ignore */ }
} catch(e) { /* ignore if modal elements not present */ }
// Delegate click on .btn-add-cart to open the shared add-to-cart modal.
// Some pages (like Views/Urunler/Detay.cshtml) render a simple button with data attributes
// but don't call showAddToCartModal directly. This ensures the modal opens and modal
// gets the correct product-id / variants data for the confirm handler.
try {
$(document).on('click', '.btn-add-cart', function (e) {
e.preventDefault();
var $btn = $(this);
var pid = $btn.data('product-id') || $btn.attr('data-product-id') || null;
var variantsAttr = $btn.data('variants') || $btn.attr('data-variants') || null;
// if variantsAttr is a string, pass it through; if it's an object/array, stringify
var variantsJson = null;
if (variantsAttr) {
if (typeof variantsAttr === 'string') variantsJson = variantsAttr;
else variantsJson = JSON.stringify(variantsAttr);
}
// call the modal opener which will populate selects and show the modal
try { window.showAddToCartModal(pid, variantsJson); } catch (err) { console && console.error && console.error('[AddCartModal] opener error', err); }
// also ensure the modal element has data set (some confirm handlers read from it)
try {
var $m = $('#addCartModal');
if ($m && $m.length) {
$m.data('product-id', pid);
if (variantsAttr) {
var parsed = null;
try { parsed = typeof variantsAttr === 'string' ? JSON.parse(variantsAttr) : variantsAttr; } catch(e) { parsed = variantsAttr; }
$m.data('variants', parsed || []);
}
}
} catch(e) {}
// If the opener sits inside a form that posts to /Cart/AddToCart (detay form), sync the form's hidden inputs too
try {
var $form = $btn.closest('form');
if ($form && $form.length && $form.attr('action') && $form.attr('action').toLowerCase().indexOf('/cart/addtocart') !== -1) {
// Set inputs by id (created in Detay.cshtml) or by name fallback
var setInput = function(selectorOrName, value){
var $el = $form.find(selectorOrName);
if (!$el || !$el.length) $el = $form.find('[name="' + selectorOrName.replace(/^#/, '') + '"]');
if ($el && $el.length) $el.val(value == null ? '' : String(value));
};
setInput('#detayUrunId', pid || '');
setInput('#detayVariationId', '0');
setInput('#detayAdet', '1');
setInput('#detayOlcu', '');
setInput('#detayUzunluk', '');
}
} catch(e) {}
});
} catch(e) { /* ignore if jQuery not available at this point */ }
// Native delegation fallback: ensure modal opens even if jQuery binding failed or jQuery errored.
try {
document.addEventListener('click', function (e) {
try {
var tgt = e.target || null;
if (!tgt) return;
var btn = (tgt.closest && tgt.closest('.btn-add-cart')) ? tgt.closest('.btn-add-cart') : null;
if (!btn) return;
// Avoid double-handling if jQuery already handled it and called preventDefault
// We'll still call showAddToCartModal to be safe.
var pid = btn.getAttribute('data-product-id') || (btn.dataset && btn.dataset.productId) || null;
var variants = btn.getAttribute('data-variants') || (btn.dataset && btn.dataset.variants) || null;
try { console && console.debug && console.debug('[AddCartModal][native-delegate] click', { pid: pid, variants: variants }); } catch(e) {}
try { if (typeof window.showAddToCartModal === 'function') { window.showAddToCartModal(pid, variants); } else { console && console.debug && console.debug('[AddCartModal][native-delegate] showAddToCartModal not defined'); } } catch(err) { console && console.error && console.error('[AddCartModal][native-delegate] opener error', err); }
} catch(inner) { /* swallow */ }
}, true);
} catch(e) { /* ignore */ }
// Tekil badge güncelleme kurgusu
// ...existing code...