//document.addEventListener("live-pricing-done", () => { (() => { if (!document.body.classList.contains("ex-product")) return; const skuObj = { IVCP0001: ["Google"], IVCP0002: ["Facebook"], IVCP0003: ["Facebook"], IVCP0004: ["Google"], IVCP0005: ["Google", "Facebook"], IVCP0006: ["Google", "Facebook"], }; let totalLines = 0; let prodSku = (document.body?.className?.match(/\bex-sku-(\S+)/g) || []).map((key) => key.replace("ex-sku-", "").toUpperCase()).join(); const trashSvg = ` `; // If product SKU not in the list, return if (!prodSku || !skuObj[prodSku]) return; // Utility Functions // Create new Add to Cart Button const createAddCartButton = () => { const btn = document.createElement("button"); btn.classList = "btn btn-primary btn-sm btn-add-to-cart btn-add-to-cart-new"; btn.setAttribute("type", "button"); btn.dataset.loadingText = " Adding"; btn.dataset.loadingComplete = " Added"; btn.textContent = "Add to basket"; return btn; }; // Replace symbols for line reference const replaceSymbols = (input) => input?.replaceAll(/[\\,+()$~^'"*<>{}]/g, "") || ""; // Remove all not digits symbols const removeNotDigits = (input) => input?.replace(/[^0-9]/g, "") || ""; // Create line reference const createlineRefWrapper = () => { const lineRefWrapper = document.createElement("div"); lineRefWrapper.className = "row line-ref-wrapper"; lineRefWrapper.innerHTML = `

Customise Your Order

`; return lineRefWrapper; }; const createlineRefElement = (index) => { const lineRefElement = document.createElement("div"); lineRefElement.className = "line-ref-element"; lineRefElement.dataset.index = index; // Create delete button const deleteBtn = document.createElement("button"); deleteBtn.className = "line-ref-delete"; deleteBtn.setAttribute("type", "button"); deleteBtn.setAttribute("aria-label", "Delete line"); deleteBtn.innerHTML = trashSvg; // Create quantity button const quantityLine = document.createElement("div"); quantityLine.className = "quantity-line"; quantityLine.innerHTML = `Quantity: `; // Create url inputs skuObj[prodSku].forEach((service) => { const line = document.createElement("div"); line.className = `review-line ${service.toLowerCase()}-review-line`; line.innerHTML = ` ${service} review URL: `; lineRefElement.append(line); }); lineRefElement.append(quantityLine, deleteBtn); return lineRefElement; }; // Add new line reference const addLineRef = () => { totalLines += 1; const line = createlineRefElement(totalLines); const productSummaryContainer = document.querySelectorAll(".ex-product .product-summary"); productSummaryContainer.forEach((e) => { const mWrapper = e.querySelector(".line-ref-wrapper"); const addBtn = mWrapper.querySelector(".addline-wrapper"); addBtn.classList.remove("error"); mWrapper.insertBefore(line.cloneNode(true), addBtn); }); }; // Remove line reference const deleteLineRef = (index) => { totalLines -= 1; const productSummaryContainer = document.querySelectorAll(".ex-product .product-summary"); productSummaryContainer.forEach((e) => { const mWrapper = e.querySelector(".line-ref-wrapper"); mWrapper.querySelector(`.line-ref-element[data-index="${index}"]`).remove(); mWrapper.querySelectorAll(".line-ref-element").forEach((el, i) => { el.dataset.index = i + 1; }); }); }; // Helper function that returns a Promise which resolves when the event fires const waitForEvent = (eventName, productId, lineRef, element = document) => { return new Promise((resolve) => { const handler = (event) => { const eventTargetId = event.detail.item.item || NaN; const eventLineRef = event.detail.item.line_ref || ""; const eventType = event.detail.type || ""; if (eventTargetId === productId && eventLineRef === lineRef && eventType === "add-item") { element.removeEventListener(eventName, handler); resolve(event); } }; element.addEventListener(eventName, handler); }); }; // Add to cart all items const addToCart = () => { let isEmptyInput = false; const allInputs = document.querySelectorAll(`.line-ref-wrapper input`); // Check if there is any lines if (allInputs.length === 0) { document.querySelectorAll(".line-ref-wrapper .addline-wrapper").forEach((e) => { e.classList.add("error"); }); return; } // Check if all lines have information allInputs.forEach((e) => { if (e.value !== "" && e.value !== "0") return; e.classList.add("error"); isEmptyInput = true; }); if (isEmptyInput) return; const allBtn = document.querySelectorAll(".live-inventory-v2-add-to-cart-wrapper .btn-add-to-cart-new"); allBtn.forEach((e) => { const text = e.dataset.loadingText; if (text) e.innerHTML = text; e.setAttribute("disabled", true); }); const productAddToCart = document.querySelectorAll(".product-shopping-actions-addtocart"); const productSummaryContainer = document.querySelectorAll(".ex-product .product-summary"); const input = productAddToCart[0].querySelector(".buttons.group .inputquantity"); const button = productAddToCart[0].querySelector("#addItemToCart"); const lineRef = document.getElementById("lineref"); const lineRefElements = productSummaryContainer[0].querySelectorAll(".line-ref-element"); const productId = Number(button.closest(".product").dataset.itemId); let linerefObg = {}; let qtyValue = 0; for (let i = 0; i < lineRefElements.length; i++) { linerefObg[`Plate ${i + 1}`] = {}; const e = lineRefElements[i]; const qty = e.querySelector('.quantity-line input[name="quantity"]').value; qtyValue += Number(qty); const allLineInputs = e.querySelectorAll('.review-line input[type="text"]'); allLineInputs.forEach((input) => { linerefObg[`Plate ${i + 1}`][`${input.name[0].toUpperCase()}${input.name.slice(1)} review URL`] = input.value; }); linerefObg[`Plate ${i + 1}`]["Quantity"] = qty; } linerefObg["Total Quantity"] = qtyValue; input.value = qtyValue; const formData = createFormData(linerefObg); $.ajax({ method: "post", url: "/ajax/upload-file", data: formData, processData: false, contentType: false, }) .then(async function (response) { if (response.status == "success") { const filepath = response.data.filepath; if (!filepath) { throw new Error("File path is missing in the response"); } else { lineRef.value = `File URL: ${filepath}`; button.dispatchEvent(new Event("click", { bubbles: true })); const response = await waitForEvent("cart-total-update", productId, lineRef.value); } } else { console.log("✗ Upload failed - status not success"); } }) .catch(function (error) { console.log("✗ Upload failed", error); }); allBtn.forEach((e) => { const text = e.dataset.loadingComplete; if (text) e.innerHTML = text; e.removeAttribute("disabled"); }); }; // create formData const createFormData = (obj) => { const title = document.querySelector(".product-name")?.textContent || "product"; const textContent = `Title: ${title} Product SKU: ${document.querySelector(".product-summary")?.getAttribute("data-sku") || ""} Date: ${new Date().toLocaleString()} --- ${JSON.stringify(obj, null, 2)}`; // Create blob and file const blob = new Blob([textContent], { type: "text/plain" }); const filename = `product-order_${Date.now()}`; const file = new File([blob], `${filename}.txt`, { type: "text/plain" }); // Create FormData const formData = new FormData(); formData.append("file", file); // Change 'file' to match your backend field name formData.append("title", title); formData.append("content", textContent); return formData; }; // Main Logic const init = () => { const productSummaryContainer = document.querySelectorAll(".ex-product .product-summary"); const productAddToCart = document.querySelectorAll(".product-shopping-actions-addtocart"); if (productSummaryContainer[0].querySelector(".line-ref-wrapper")) return; totalLines = 0; prodSku = productSummaryContainer[0]?.getAttribute("data-sku")?.toUpperCase() || prodSku; // append hidden input for line reference to add to cart form if not exists if (!document.getElementById("lineref")) { productAddToCart[0].insertAdjacentHTML("beforeend", ''); } // Create add to cart button productAddToCart.forEach((e) => { if (e.querySelector(".btn-add-to-cart-new")) return; // Hide existing button and qty e.querySelector("#addItemToCart")?.classList.add("hide"); e.querySelector(".qnt-count")?.classList.add("hide"); // Append new button const liveInventoryWrapper = e.querySelector(".live-inventory-v2-add-to-cart-wrapper"); if (liveInventoryWrapper) { const cartBtn = createAddCartButton(); liveInventoryWrapper.append(cartBtn); liveInventoryWrapper.setAttribute("style", "max-width: 100%; width: 100%;"); cartBtn.addEventListener("click", (e) => { addToCart(); }); } }); for (let e of productSummaryContainer) { if (e.querySelector(".line-ref-wrapper")) continue; // Create main wrapper and insert const lineRefWrap = createlineRefWrapper(); const productDetails = e.querySelector(".product-details-wrapper"); productDetails.after(lineRefWrap); // Click event lineRefWrap.addEventListener("click", (e) => { const index = e.target.closest(".line-ref-element")?.dataset.index || ""; const input = e.target.closest(".quantity-line")?.querySelector("input") || null; let value = 0; if (e.target.matches(".line-ref-add")) { e.preventDefault(); setTimeout(addLineRef, 50); } else if (e.target.matches(".line-ref-delete")) { e.preventDefault(); deleteLineRef(index); } else if (e.target.matches(".inc-qty") || e.target.matches(".decr-qty")) { if (e.target.matches(".inc-qty")) { if (Number(input.value) === 999) return; value = Number(input.value) + 1; } else { if (Number(input.value) === 1) return; if (Number(input.value) < 1) { value = 1; return; } value = Number(input.value) - 1; } productSummaryContainer.forEach((el) => { el.querySelector(`.line-ref-element[data-index="${index}"] .quantity-line input`).value = value; }); } }); // Input event lineRefWrap.addEventListener("input", (e) => { const index = e.target.closest(".line-ref-element")?.dataset.index || ""; if (e.target.tagName !== "INPUT") return; if (e.target.getAttribute("name") === "quantity") { productSummaryContainer.forEach((el) => { const currInput = el.querySelector(`.line-ref-element[data-index="${index}"] .quantity-line input`); currInput.value = removeNotDigits(e.target.value); currInput.classList.remove("error"); }); } else { const name = e.target.getAttribute("name"); productSummaryContainer.forEach((el) => { const currInput = el.querySelector(`.line-ref-element[data-index="${index}"] input[name="${name}"]`); currInput.value = replaceSymbols(e.target.value); currInput.classList.remove("error"); }); } }); } addLineRef(); }; document.addEventListener("live-pricing-done", init); document.addEventListener("live-inventory-done", init); })();