/* =========================================================================
* cart.js — количка, checkout и потвърждение (клиентски рендер, фаза 1)
* Фаза 2: тези страници стават server-rendered от Spring MVC (session cart),
* стъпките на checkout — отделни partials (както cart step1/2/3 в salex).
* ========================================================================= */
(function () {
'use strict';
var esc = window.ACM.esc, fmt = window.ACM.fmtPrice, DEMO = window.ACM.demo;
var Cart = window.ACM.cart, find = window.ACM.findProduct;
function el(id) { return document.getElementById(id); }
function icon(paths, size, sw) {
return '';
}
var IC = {
minus: '',
plus: '',
trash: '',
package: '',
arrowRight: '',
arrowLeft: '',
info: '',
warn: '',
ban: '',
check: ''
};
function lines() {
return Cart.items().map(function (i) {
var p = find(i.productId);
if (!p) return null;
var isPack = p.package.unitLabel === 'пакет';
return { product: p, qty: i.qty, isPack: isPack, unit: isPack ? 'бр.' : 'каш.', lineTotal: p.price.perBox * i.qty };
}).filter(Boolean);
}
function thumb(p, size) {
var inner = p.image
? '
'
: '' + icon(IC.package, Math.round(size * 0.4), 1.25) + '';
return '' + inner + '';
}
function stepperHTML(id, qty, unit) {
return '
' +
'
' +
'
' +
'' +
'' + esc(unit) + '' +
'
' +
'
' +
'
';
}
function wireSteppers(root) {
Array.prototype.forEach.call(root.querySelectorAll('[data-stepper]'), function (st) {
var id = st.getAttribute('data-stepper');
var input = st.querySelector('input');
function val() { var v = parseInt(input.value, 10); return isNaN(v) ? 1 : Math.min(9999, Math.max(1, v)); }
st.querySelector('[data-minus]').addEventListener('click', function () { Cart.setQty(id, val() - 1); });
st.querySelector('[data-plus]').addEventListener('click', function () { Cart.setQty(id, val() + 1); });
input.addEventListener('change', function () { Cart.setQty(id, val()); });
});
}
function wireRemoves(root) {
Array.prototype.forEach.call(root.querySelectorAll('[data-remove]'), function (b) {
b.addEventListener('click', function () {
var id = b.getAttribute('data-remove');
var snapshot = Cart.items();
Cart.remove(id);
window.ACM.showToast('Продуктът е премахнат', {
actionLabel: 'Върни',
onAction: function () { Cart.restore(snapshot); }
});
});
});
}
/* ---------------------- Кредитен статус (както в оригинала) ------------- */
function creditBanner(state) {
var map = {
info: { ic: IC.info, box: 'bg-green-tint text-ink', icc: 'text-green-deep', text: 'Кредитни условия: отложено плащане по договорени падежи.' },
warning: { ic: IC.warn, box: 'bg-warn-bg text-warn-text', icc: 'text-warn-text', text: 'Наближавате кредитния си лимит. При въпроси се свържете с вашия търговски представител.' },
blocked: { ic: IC.ban, box: 'bg-danger-bg text-danger', icc: 'text-danger', text: 'Поръчката надвишава кредитния ви лимит. Свържете се с АСМ за съдействие.' }
};
var c = map[state];
return '' +
'
' + icon(c.ic, 20) + '' +
'
' + c.text + '
';
}
/* ---------------------- Резюме на поръчката ----------------------------- */
function summaryHTML(deliveryMethod, ctaHTML) {
var ls = lines();
var subtotal = ls.reduce(function (s, l) { return s + l.lineTotal; }, 0);
var delivery = deliveryMethod === null ? 0 : window.ACM.deliveryCost(deliveryMethod, subtotal);
var m = deliveryMethod === null ? null : DEMO.deliveryMethods.find(function (d) { return d.method === deliveryMethod; });
var deliveryDisplay = deliveryMethod === null ? '—'
: (m && m.cost === null) ? 'по тарифа'
: delivery === 0 ? 'Безплатно' : fmt(delivery);
var vat = (subtotal + delivery) * DEMO.vat;
var total = subtotal + delivery + vat;
var credit = window.ACM.creditState(subtotal);
function row(label, value, muted) {
return '' +
'' + label + '' +
'' + value + '
';
}
return '';
}
/* ======================== Страница: Количка ============================ */
function renderCartPage() {
var ls = lines();
el('cart-empty').hidden = ls.length > 0;
el('cart-full').hidden = ls.length === 0;
if (!ls.length) return;
el('cart-rows').innerHTML = ls.map(function (l) {
var p = l.product;
return '' +
' | ' +
'' + fmt(p.price.perBox) + ' | ' +
'' + stepperHTML(p.id, l.qty, l.unit) + ' | ' +
'' + fmt(l.lineTotal) + ' | ' +
' | ' +
'
';
}).join('');
el('cart-cards').innerHTML = ls.map(function (l) {
var p = l.product;
return '' +
'
' + thumb(p, 56) +
'
' +
'
' +
'
' +
stepperHTML(p.id, l.qty, l.unit) +
'' + fmt(l.lineTotal) + '
';
}).join('');
el('cart-summary').innerHTML = summaryHTML(null,
'Продължи към доставка' + icon(IC.arrowRight, 20) + '');
wireSteppers(document);
wireRemoves(document);
}
/* ======================== Страница: Checkout =========================== */
var coState = {
step: 2,
delivery: 'pickup',
warehouse: 'Монтана',
addressId: 'addr-1',
payment: 'deferred'
};
function radioCard(name, value, checked, title, note) {
return '';
}
function renderCheckoutStep2() {
var html = '';
html += '' +
'
' + icon(IC.check, 20) + '' +
'
Всички продукти са налични
';
html += '' +
'Начин на доставка
' +
'' +
DEMO.deliveryMethods.map(function (m) {
return radioCard('co-delivery', m.method, coState.delivery === m.method, m.label, m.note);
}).join('') + '
';
if (coState.delivery === 'pickup') {
html += '' +
'Склад за изпълнение
' +
'' +
DEMO.warehouses.map(function (w) {
var sel = coState.warehouse === w.name;
return '';
}).join('') + '
';
} else {
html += '' +
'Адрес за доставка
' +
'' +
DEMO.addresses.map(function (a) {
return radioCard('co-address', a.id, coState.addressId === a.id, a.label, a.isDefault ? 'По подразбиране' : '');
}).join('') + '
' +
'Добавянето на нов адрес не е част от демонстрацията.
' +
'';
}
html += '' +
'Начин на плащане (демо)
' +
'' +
radioCard('co-payment', 'deferred', coState.payment === 'deferred', 'Отложено', 'Отложено плащане, падеж ' + DEMO.paymentDueDates[0] + ' — съгласно вашите търговски условия.') +
radioCard('co-payment', 'advance', coState.payment === 'advance', 'Авансово', 'Плащане по проформа фактура преди експедиция.') +
'
';
el('co-content').innerHTML = html;
Array.prototype.forEach.call(document.querySelectorAll('input[name="co-delivery"]'), function (r) {
r.addEventListener('change', function () { coState.delivery = r.value; renderCheckout(); });
});
Array.prototype.forEach.call(document.querySelectorAll('button[data-wh]'), function (b) {
b.addEventListener('click', function () { coState.warehouse = b.getAttribute('data-wh'); renderCheckout(); });
});
Array.prototype.forEach.call(document.querySelectorAll('input[name="co-address"]'), function (r) {
r.addEventListener('change', function () { coState.addressId = r.value; renderCheckout(); });
});
Array.prototype.forEach.call(document.querySelectorAll('input[name="co-payment"]'), function (r) {
r.addEventListener('change', function () { coState.payment = r.value; renderCheckout(); });
});
el('co-summary').innerHTML = summaryHTML(coState.delivery,
'' +
'' + icon(IC.arrowLeft, 20) + 'Назад');
el('co-next').addEventListener('click', function () { coState.step = 3; renderCheckout(); window.scrollTo(0, 0); });
}
function renderCheckoutStep3() {
var ls = lines();
var m = DEMO.deliveryMethods.find(function (d) { return d.method === coState.delivery; });
var addr = DEMO.addresses.find(function (a) { return a.id === coState.addressId; });
var deliveryDetail = coState.delivery === 'pickup'
? 'Склад за изпълнение: ' + coState.warehouse
: 'Адрес за доставка: ' + (addr ? addr.label : '');
var paymentDetail = coState.payment === 'deferred'
? 'Отложено плащане, падеж ' + DEMO.paymentDueDates[0]
: 'Авансово — проформа фактура';
var html = '';
html += '' +
'Продукти
' +
'' +
ls.map(function (l) {
return '- ' + thumb(l.product, 44) +
'' + esc(l.product.name) + '' +
'' + l.qty + ' ' + l.unit + ' × ' + fmt(l.product.price.perBox) + '' +
'' + fmt(l.lineTotal) + '
';
}).join('') + '
';
html += '' +
'Доставка и плащане
' +
'' +
'- Начин на доставка
- ' + esc(m.label) + '
' +
'- ' + (coState.delivery === 'pickup' ? 'Склад за изпълнение' : 'Адрес за доставка') + '
- ' + esc(coState.delivery === 'pickup' ? coState.warehouse : (addr ? addr.label : '')) + '
' +
'- Условие на плащане
- ' + esc(paymentDetail) + '
' +
'- Фирма
- ' + esc(DEMO.company.name) + ' · ЕИК ' + esc(DEMO.company.eik) + '
' +
'
';
el('co-content').innerHTML = html;
el('co-summary').innerHTML = summaryHTML(coState.delivery,
'' +
'');
var subtotal = ls.reduce(function (s, l) { return s + l.lineTotal; }, 0);
var blocked = window.ACM.creditState(subtotal) === 'blocked';
var submit = el('co-submit');
if (blocked) submit.disabled = true;
submit.addEventListener('click', function () {
var delivery = window.ACM.deliveryCost(coState.delivery, subtotal);
var vat = (subtotal + delivery) * DEMO.vat;
try {
sessionStorage.setItem('acm-last-order', JSON.stringify({
number: DEMO.nextOrderNumber,
total: subtotal + delivery + vat
}));
} catch (e) {}
Cart.clear();
window.location.href = '/confirmation/';
});
el('co-back').addEventListener('click', function () { coState.step = 2; renderCheckout(); window.scrollTo(0, 0); });
}
function renderCheckoutSteps() {
var dots = document.querySelectorAll('#co-steps [data-step-dot]');
var labels = document.querySelectorAll('#co-steps li > span:last-child');
for (var i = 0; i < dots.length; i++) {
var stepNo = i + 1;
var done = stepNo < coState.step, current = stepNo === coState.step;
dots[i].className = 'grid h-8 w-8 place-items-center rounded-full text-[13px] font-bold ' +
(done || current ? 'bg-brand-green text-ink' : 'border border-border bg-surface text-muted');
labels[i].className = current ? 'font-medium text-ink' : 'text-muted';
}
el('co-progress').style.width = ((coState.step - 1) / 2 * 100) + '%';
}
function renderCheckout() {
var ls = lines();
el('co-empty').hidden = ls.length > 0;
el('co-full').hidden = ls.length === 0;
if (!ls.length) return;
renderCheckoutSteps();
if (coState.step === 2) renderCheckoutStep2(); else renderCheckoutStep3();
}
/* ======================== Страница: Потвърждение ======================= */
function renderConfirmation() {
var raw = null;
try { raw = sessionStorage.getItem('acm-last-order'); } catch (e) {}
if (!raw) { window.location.replace('/home/'); return; }
try {
var o = JSON.parse(raw);
el('conf-number').textContent = o.number || DEMO.nextOrderNumber;
} catch (e) {
el('conf-number').textContent = DEMO.nextOrderNumber;
}
}
/* ======================== Инициализация ================================ */
document.addEventListener('DOMContentLoaded', function () {
var path = window.location.pathname;
if (path.indexOf('/cart') === 0) {
renderCartPage();
document.addEventListener('acm:cart-changed', renderCartPage);
} else if (path.indexOf('/checkout') === 0) {
renderCheckout();
document.addEventListener('acm:cart-changed', renderCheckout);
} else if (path.indexOf('/confirmation') === 0) {
renderConfirmation();
}
});
})();