390 lines
9.6 KiB
JavaScript
390 lines
9.6 KiB
JavaScript
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;
|
|
}
|
|
}
|
|
|
|
function extractModelId(url) {
|
|
switch (extractDomain(url)) {
|
|
case "https://www.grays.com": {
|
|
const match = url.match(/\/lot\/([\d-]+)\//);
|
|
return match ? match[1] : null;
|
|
}
|
|
case "https://www.langtons.com.au": {
|
|
const match = url.match(/auc-var-\d+/);
|
|
return match[0];
|
|
}
|
|
case "https://www.lawsons.com.au": {
|
|
const match = url.split("_");
|
|
return match ? match[1] : null;
|
|
}
|
|
case "https://www.pickles.com.au": {
|
|
const model = url.split("/").pop();
|
|
return model ? model : null;
|
|
}
|
|
}
|
|
}
|
|
|
|
const showPage = async (pageLink = "pages/popup/popup.html") => {
|
|
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);
|
|
};
|
|
|
|
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 = `
|
|
<div class="col">
|
|
<label>ID</label>
|
|
<input readonly value="${data?.id || "None"}" type="text" id="id" />
|
|
</div>
|
|
|
|
<div class="col">
|
|
<label>Name</label>
|
|
<textarea readonly id="maxPrice">${data?.name || "None"}</textarea>
|
|
</div>
|
|
`;
|
|
|
|
inputsContainer.insertAdjacentHTML("afterbegin", otherEls);
|
|
|
|
// 2. Tạo và chèn Current Price ngay sau #url-col
|
|
const currentPriceDiv = document.createElement("div");
|
|
currentPriceDiv.className = "col";
|
|
currentPriceDiv.innerHTML = `
|
|
<label>Current price</label>
|
|
<input readonly type="text" value="${
|
|
data?.current_price || "None"
|
|
}" id="currentPrice" />
|
|
`;
|
|
|
|
urlCol.parentNode.insertBefore(currentPriceDiv, urlCol.nextSibling);
|
|
|
|
formElements.quantity.value = data?.quantity || 1;
|
|
formElements.plusPrice.value = data?.plus_price || 0;
|
|
};
|
|
|
|
const showInfo = async (model, formElements) => {
|
|
const key = await getKey();
|
|
if (!key) {
|
|
showKey();
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await fetch(`${CONFIG.API_BASE_URL}/bids/${model}`, {
|
|
method: "GET",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
Authorization: key,
|
|
},
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (!result || result?.status_code !== 200 || !result?.data) {
|
|
if (result.status_code !== 404) {
|
|
alert(result.message);
|
|
}
|
|
|
|
PREV_DATA = null;
|
|
return null;
|
|
}
|
|
|
|
formElements.maxPrice.value = result.data.max_price;
|
|
|
|
createInfoColumn(result.data, formElements);
|
|
|
|
PREV_DATA = result;
|
|
return result;
|
|
} catch (error) {
|
|
alert("Error: " + error.message);
|
|
console.error("API Error:", error);
|
|
}
|
|
};
|
|
|
|
(async () => {
|
|
await showPage();
|
|
handleToogle();
|
|
|
|
const formElements = {
|
|
url: document.querySelector("#form-bid #url"),
|
|
maxPrice: document.querySelector("#form-bid #maxPrice"),
|
|
plusPrice: document.querySelector("#form-bid #plusPrice"),
|
|
quantity: document.querySelector("#form-bid #quantity"),
|
|
createBtn: document.querySelector("#form-bid #createBtn"),
|
|
form: document.querySelector("#form-bid form"),
|
|
};
|
|
|
|
const style = document.createElement("link");
|
|
style.rel = "stylesheet";
|
|
style.href = chrome.runtime.getURL("assets/css/index.css");
|
|
document.head.appendChild(style);
|
|
|
|
const script = document.createElement("script");
|
|
script.type = "module";
|
|
script.src = chrome.runtime.getURL("pages/popup/popup.js");
|
|
script.defer = true;
|
|
|
|
document.body.appendChild(script);
|
|
|
|
handleSaveKey();
|
|
|
|
const currentUrl = window.location.href;
|
|
|
|
const model = extractModelId(currentUrl);
|
|
|
|
if (!model) return;
|
|
|
|
// set url on form
|
|
formElements.url.value = currentUrl;
|
|
|
|
await showInfo(model, formElements);
|
|
handleChangeTitleButton(!!PREV_DATA, formElements);
|
|
|
|
formElements.form.addEventListener("submit", (e) =>
|
|
PREV_DATA
|
|
? handleUpdate(e, formElements, PREV_DATA.data.id)
|
|
: handleCreate(e, formElements)
|
|
);
|
|
})();
|