first deployment of kikomiko with url photos
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
8d98304137
commit
ae3ed7c7b7
Vendored
+89
@@ -0,0 +1,89 @@
|
||||
import {
|
||||
hydrateCart,
|
||||
subscribe,
|
||||
getSnapshot,
|
||||
updateQuantity,
|
||||
removeItem,
|
||||
formatPrice,
|
||||
} from "/js/cart.js";
|
||||
|
||||
function escapeHtml(s) {
|
||||
return String(s)
|
||||
.replaceAll("&", "&")
|
||||
.replaceAll("<", "<")
|
||||
.replaceAll(">", ">")
|
||||
.replaceAll('"', """);
|
||||
}
|
||||
|
||||
/** Cart page: items + totals only (checkout is a separate step). */
|
||||
export function initCartPage() {
|
||||
const root = document.querySelector("[data-cart-page]");
|
||||
if (!root) return;
|
||||
|
||||
hydrateCart();
|
||||
const list = root.querySelector("[data-cart-lines]");
|
||||
const totalEl = root.querySelector("[data-cart-total]");
|
||||
const checkoutBtn = root.querySelector("[data-cart-checkout]");
|
||||
const emptyEl = root.querySelector("[data-cart-empty]");
|
||||
const contentEl = root.querySelector("[data-cart-content]");
|
||||
|
||||
function render(snap) {
|
||||
const empty = !snap.items.length;
|
||||
if (emptyEl) emptyEl.hidden = !empty;
|
||||
if (contentEl) contentEl.hidden = empty;
|
||||
if (checkoutBtn) {
|
||||
if (empty) checkoutBtn.setAttribute("disabled", "");
|
||||
else checkoutBtn.removeAttribute("disabled");
|
||||
}
|
||||
if (!list || !totalEl) return;
|
||||
|
||||
if (empty) {
|
||||
list.innerHTML = "";
|
||||
totalEl.textContent = formatPrice(0);
|
||||
return;
|
||||
}
|
||||
|
||||
list.innerHTML = snap.items
|
||||
.map(
|
||||
(item) => `
|
||||
<div class="cart-line" data-id="${escapeHtml(item.productId)}">
|
||||
${
|
||||
item.image
|
||||
? `<img src="${escapeHtml(item.image)}" alt="" width="72" height="96" />`
|
||||
: `<div style="width:72px;height:96px;background:#f7f7f7"></div>`
|
||||
}
|
||||
<div style="flex:1;min-width:0">
|
||||
<a href="/products/${escapeHtml(item.slug)}/">${escapeHtml(item.name)}</a>
|
||||
<div class="text-muted" style="font-size:0.85rem;margin-top:0.25rem">${formatPrice(item.price)}</div>
|
||||
<div class="qty-controls">
|
||||
<button type="button" data-qty-dec aria-label="کاهش تعداد">−</button>
|
||||
<span>${item.quantity}</span>
|
||||
<button type="button" data-qty-inc aria-label="افزایش تعداد">+</button>
|
||||
<button type="button" data-qty-remove aria-label="حذف از سبد" style="margin-inline-start:0.5rem;font-size:0.75rem;color:#8a8a8a">حذف</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
)
|
||||
.join("");
|
||||
|
||||
totalEl.textContent = formatPrice(snap.subtotal);
|
||||
|
||||
list.querySelectorAll(".cart-line").forEach((row) => {
|
||||
const id = row.getAttribute("data-id");
|
||||
const item = snap.items.find((i) => i.productId === id);
|
||||
if (!item || !id) return;
|
||||
row.querySelector("[data-qty-dec]")?.addEventListener("click", () =>
|
||||
updateQuantity(id, item.quantity - 1)
|
||||
);
|
||||
row.querySelector("[data-qty-inc]")?.addEventListener("click", () =>
|
||||
updateQuantity(id, item.quantity + 1)
|
||||
);
|
||||
row.querySelector("[data-qty-remove]")?.addEventListener("click", () =>
|
||||
removeItem(id)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
subscribe(render);
|
||||
render(getSnapshot());
|
||||
}
|
||||
Reference in New Issue
Block a user