Skip to main content

Test

Cart: 0
Home Search
Showing 0 results | User can only see maximum 9 products on a page
1
Done
issues in inline scripts. [2](https://sqlpey.com/javascript/safely-include-external-scripts/)[3](https://stackoverflow.com/questions/8749001/escaping-html-entities-in-javascript-string-literals-within-the-script-block) ============================================================ */ function openProductDetails(pid){ const id = String(pid || "").trim(); if(!id){ toast("Invalid product id"); return; } const w = window.open("about:blank", "_blank"); if(!w){ toast("Popup blocked — allow popups"); return; } try { w.opener = null; } catch(_){} const doc = w.document; doc.open(); doc.write('' + 'Product Details' + '' + '
' + '
DETAILS

Loading...

' + '
' + '
' + ' Product image' + '
' + '
' + '
' + '

Loading...

' + '
' + '
' + '
' + ' ' + ' ' + '
' + '
' + '
' + '
More Details
' + '
' + '
' + '
' + ' ' + ' ' + '
' + '
Loading product from API...
' + '
' + '
' + '
'); doc.close(); const titleEl = doc.getElementById("pdTitle"); const nameEl = doc.getElementById("pdName"); const metaEl = doc.getElementById("pdMeta"); const priceEl = doc.getElementById("pdPrice"); const strikeEl= doc.getElementById("pdStrike"); const saveEl = doc.getElementById("pdSave"); const descEl = doc.getElementById("pdDesc"); const mainImg = doc.getElementById("pdMain"); const thumbs = doc.getElementById("pdThumbs"); const noteEl = doc.getElementById("pdNote"); const btnClose= doc.getElementById("pdClose"); const btnRefresh= doc.getElementById("pdRefresh"); const detailsGrid = doc.getElementById("pdDetailsGrid"); btnClose.addEventListener("click", () => w.close()); function pill(text, tid){ const s = doc.createElement("span"); s.className = "pill"; s.textContent = text; if(tid){ s.setAttribute("data-testid", tid); s.setAttribute("data-qa", tid); } return s; } function addDetail(label, value, idx){ if(value === undefined || value === null || value === "") return; const item = doc.createElement("div"); item.className = "detail"; item.setAttribute("data-testid", "pd-detail-" + idx); item.setAttribute("data-qa", "pd-detail-" + idx); const k = doc.createElement("div"); k.className = "k"; k.textContent = label; const v = doc.createElement("div"); v.className = "v"; v.textContent = String(value); item.appendChild(k); item.appendChild(v); detailsGrid.appendChild(item); } function moneyLocal(n){ return "\u20B9 " + Number(n || 0).toLocaleString("en-IN"); } function setSelected(btn){ Array.from(thumbs.children).forEach(x => x.setAttribute("aria-selected","false")); btn.setAttribute("aria-selected","true"); } function renderDetails(p){ const title = String(p.title || ("Product " + id)); w.document.title = title + " - Details"; titleEl.textContent = title; nameEl.textContent = title; metaEl.innerHTML = ""; if(p.brand) metaEl.appendChild(pill("Brand: " + p.brand, "pd-pill-brand")); if(p.category) metaEl.appendChild(pill("Category: " + p.category, "pd-pill-category")); metaEl.appendChild(pill("ID: " + id, "pd-pill-id")); const price = Number(p.price || 0); const disc = (p.discountPercentage != null) ? Number(p.discountPercentage) : null; priceEl.textContent = moneyLocal(price); strikeEl.style.display = "none"; saveEl.style.display = "none"; if(disc !== null && !Number.isNaN(disc) && disc > 0){ const original = price / (1 - (disc/100)); strikeEl.textContent = moneyLocal(original.toFixed(0)); strikeEl.style.display = "block"; saveEl.textContent = "Save " + disc.toFixed(2) + "%"; saveEl.style.display = "block"; metaEl.appendChild(pill("Discount: " + disc.toFixed(2) + "%", "pd-pill-discount")); } descEl.textContent = p.description || "No description available."; detailsGrid.innerHTML = ""; let i = 0; addDetail("Price", moneyLocal(price), i++); if(disc !== null && !Number.isNaN(disc)) addDetail("Discount", disc.toFixed(2) + "%", i++); if(p.rating != null) addDetail("Rating", p.rating, i++); if(p.stock != null) addDetail("Stock", p.stock, i++); // Optional fields (only show if present) addDetail("SKU", p.sku, i++); addDetail("Availability", p.availabilityStatus, i++); addDetail("Warranty", p.warrantyInformation, i++); addDetail("Shipping", p.shippingInformation, i++); addDetail("Return Policy", p.returnPolicy, i++); addDetail("Min Order Qty", p.minimumOrderQuantity, i++); const images = Array.isArray(p.images) ? p.images.filter(Boolean) : []; const primary = p.thumbnail || images[0] || ""; mainImg.src = primary || ""; mainImg.alt = title; thumbs.innerHTML = ""; const all = []; if(primary) all.push(primary); images.forEach(u => { if(u && !all.includes(u)) all.push(u); }); all.forEach((u, idx) => { const b = doc.createElement("button"); b.type = "button"; b.className = "thumb"; b.setAttribute("aria-selected", idx === 0 ? "true" : "false"); b.setAttribute("data-testid", "pd-thumb-" + idx); b.setAttribute("data-qa", "pd-thumb-" + idx); const img = doc.createElement("img"); img.src = u; img.alt = "thumb " + (idx + 1); b.appendChild(img); b.addEventListener("click", () => { mainImg.src = u; setSelected(b); }); thumbs.appendChild(b); }); // Unicode escape avoids ✅ becoming ✅ noteEl.textContent = "Loaded from API \u2705"; } async function loadDetails(){ noteEl.textContent = "Loading product from API..."; try{ const res = await fetch(API_SINGLE(id), { headers: {"Accept":"application/json"} }); if(!res.ok) throw new Error("HTTP " + res.status); const data = await res.json(); renderDetails(data); } catch (e){ console.warn("Details load failed:", e); noteEl.textContent = "Failed to load from API. Click Refresh."; titleEl.textContent = "Product " + id; nameEl.textContent = "Product " + id; } } btnRefresh.addEventListener("click", loadDetails); loadDetails(); } /* ============================================================ 8) EVENTS (delegation + pagination) ============================================================ */ root.addEventListener("click", function(e){ const chipBtn = e.target.closest && e.target.closest("[data-action='remove-chip']"); if (chipBtn){ const chip = chipBtn.closest(".chip"); const key = chip && chip.getAttribute("data-chip-key"); if (key){ if (key === "search") els.search.value = ""; else if (key === "min") els.minPrice.value = ""; else if (key === "max") els.maxPrice.value = ""; else if (key.startsWith("cat:")){ const v = key.split(":")[1]; const idMap = {fashion:"catFashion", electronics:"catElectronics", household:"catHousehold"}; const cb = root.querySelector("#" + idMap[v]); if (cb) cb.checked = false; } else if (key.startsWith("sub:")){ const v = key.split(":")[1]; const idMap = {"t-shirts":"subTshirts", shirts:"subShirts", shoes:"subShoes", mobiles:"subMobiles", laptops:"subLaptops"}; const cb = root.querySelector("#" + idMap[v]); if (cb) cb.checked = false; } else if (key.startsWith("aud:")){ const v = key.split(":")[1]; const idMap = {men:"audMen", women:"audWomen"}; const cb = root.querySelector("#" + idMap[v]); if (cb) cb.checked = false; } state.page = 1; renderGrid(); toast("Filter removed"); } return; } const actionBtn = e.target.closest && e.target.closest("[data-action]"); if (actionBtn){ const action = actionBtn.getAttribute("data-action"); const pid = actionBtn.getAttribute("data-product-id"); if (action === "add"){ state.cart += 1; els.cartCount.textContent = String(state.cart); toast("Added to cart"); } else if (action === "view"){ openProductDetails(pid); } } }, {passive:true}); ["input","change"].forEach(evt => { root.addEventListener(evt, function(e){ const id = e.target && e.target.id; if (!id) return; const watch = new Set([ "searchInput","minPrice","maxPrice", "catFashion","catElectronics","catHousehold", "subTshirts","subShirts","subShoes","subMobiles","subLaptops", "audMen","audWomen" ]); if (watch.has(id)){ state.page = 1; renderGrid(); } }, {passive:true}); }); els.btnPrev.addEventListener("click", function(){ state.page = Math.max(1, state.page - 1); renderGrid(); }, {passive:true}); els.btnNext.addEventListener("click", function(){ state.page = state.page + 1; renderGrid(); }, {passive:true}); els.reset.addEventListener("click", resetAll, {passive:true}); /* ============================================================ 9) INIT ============================================================ */ (async function init(){ await loadProducts(); renderGrid(); })(); })();