const CONFIG = { // API_BASE_URL: "http://localhost:4000/api/v1", API_BASE_URL: "https://bids.apactech.io/api/v1", }; let PREV_DATA = null; function removeFalsyValues(obj, excludeKeys = []) { return Object.entries(obj).reduce((acc, [key, value]) => { if (value || excludeKeys.includes(key)) { acc[key] = value; } return acc; }, {}); } function extractDomain(url) { try { const parsedUrl = new URL(url); return parsedUrl.origin; } catch (error) { return null; } } const webs = { grays: "https://www.grays.com", langtons: "https://www.langtons.com.au", lawsons: "https://www.lawsons.com.au", pickles: "https://www.pickles.com.au", allbids: "https://www.allbids.com.au", }; function extractModelId(url) { switch (extractDomain(url)) { case webs.grays: { const match = url.match(/\/lot\/([\d-]+)\//); return match ? match[1] : null; } case webs.langtons: { const match = url.match(/auc-var-\d+/); return match[0]; } case webs.lawsons: { const match = url.split("_"); return match ? match[1] : null; } case webs.pickles: { const model = url.split("/").pop(); return model ? model : null; } case webs.allbids: { const match = url.match(/-(\d+)(?:[\?#]|$)/); return match ? match[1] : null; } } } const isValidUrl = (url) => { return !!Object.keys(webs).find((item) => url.includes(webs[item])); }; const showPage = async (pageLink = "pages/popup/popup.html") => { const url = window.location.href; // sửa lỗi ở đây if (!isValidUrl(url)) return; try { const res = await fetch(chrome.runtime.getURL(pageLink)); const html = await res.text(); const wrapper = document.createElement("div"); wrapper.innerHTML = html; document.body.appendChild(wrapper); } catch (err) { console.error("Failed to load popup page:", err); } }; const getKey = () => { return new Promise((resolve, reject) => { chrome.storage.local.get("key", (result) => { if (chrome.runtime.lastError) { reject(chrome.runtime.lastError); } else { resolve(result.key || null); } }); }); }; async function handleCreate(event, formElements) { event.preventDefault(); const key = await getKey(); if (!key) { showKey(); return; } const maxPrice = parseFloat(formElements.maxPrice.value); const plusPrice = parseFloat(formElements.plusPrice.value); const quantity = parseInt(formElements.quantity.value, 10); const payload = { url: formElements.url.value.trim(), max_price: isNaN(maxPrice) ? null : maxPrice, plus_price: isNaN(plusPrice) ? null : plusPrice, quantity: isNaN(quantity) ? null : quantity, }; // Validate required fields if (!payload.url || payload.max_price === null) { alert("Please fill out the URL and Max Price fields correctly."); return; } try { const response = await fetch(`${CONFIG.API_BASE_URL}/bids`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: key, }, body: JSON.stringify(removeFalsyValues(payload)), }); const result = await response.json(); alert(result.message); // showInfo await showInfo(extractModelId(payload.url), formElements); // handleChangeTitleButton handleChangeTitleButton(true, formElements); } catch (error) { alert("Error: " + error.message); console.error("API Error:", error); } } async function handleUpdate(event, formElements, id) { event.preventDefault(); const key = await getKey(); if (!key) { showKey(); return; } const maxPrice = parseFloat(formElements.maxPrice.value); const plusPrice = parseFloat(formElements.plusPrice.value); const quantity = parseInt(formElements.quantity.value, 10); const payload = { max_price: isNaN(maxPrice) ? null : maxPrice, plus_price: isNaN(plusPrice) ? null : plusPrice, quantity: isNaN(quantity) ? null : quantity, }; // Validate required fields if (payload.max_price === null) { alert("Please fill out the URL and Max Price fields correctly."); return; } try { const response = await fetch(`${CONFIG.API_BASE_URL}/bids/info/${id}`, { method: "PUT", headers: { "Content-Type": "application/json", Authorization: key, }, body: JSON.stringify(removeFalsyValues(payload)), }); const result = await response.json(); alert(result.message); } catch (error) { alert("Error: " + error.message); console.error("API Error:", error); } } const showBid = () => { const formKey = document.getElementById("form-key"); const formBid = document.getElementById("form-bid"); formKey.style.display = "none"; formBid.style.display = "block"; }; const showKey = async () => { chrome.storage.local.set({ key: null }, async () => { console.log("abc"); }); const key = await getKey(); const formKey = document.getElementById("form-key"); const formBid = document.getElementById("form-bid"); const keyEl = document.querySelector("#form-key #key"); formBid.style.display = "none"; formKey.style.display = "block"; if (key && keyEl) { keyEl.value = key; } }; const handleToogle = async () => { const btn = document.getElementById("toggle-bid-extension"); const panel = document.getElementById("bid-extension"); if (btn && panel) { btn.addEventListener("click", async () => { const isHidden = panel.style.display === "none"; panel.style.display = isHidden ? "block" : "none"; if (isHidden) { await handleShowForm(); } }); } else { console.error("Không tìm thấy nút hoặc panel!"); } }; const handleShowForm = async () => { const formBid = document.getElementById("form-bid"); const formKey = document.getElementById("form-key"); const keyBtn = document.getElementById("key-btn"); const currentKey = await getKey(); if (!currentKey) { await showKey(); } else { showBid(); } keyBtn?.addEventListener("click", () => { showKey(); }); }; const handleChangeTitleButton = (result, formElements) => { if (result) { formElements.createBtn.textContent = "Update"; } else { formElements.createBtn.textContent = "Create"; } }; const handleSaveKey = () => { const form = document.querySelector("#form-key form"); if (!form) return; form.addEventListener("submit", async (e) => { e.preventDefault(); const inputKey = form.querySelector("#key"); if (!inputKey) return; const keyValue = inputKey.value.trim(); if (!keyValue) { alert("Please enter a key"); return; } // Lưu vào chrome.storage.local chrome.storage.local.set({ key: keyValue }, async () => { alert("Key saved successfully!"); showBid(); if (!isValidModel()) return; await showInfo(); }); }); }; const isValidModel = () => { const currentUrl = window.location.href; const model = extractModelId(currentUrl); return !!model; }; const createInfoColumn = (data, formElements) => { const inputsContainer = document.querySelector("#bid-extension .inputs"); const urlCol = document.querySelector("#url-col"); if (!inputsContainer || !urlCol) return; // 1. Thêm ID và Name vào đầu inputsContainer const otherEls = `