diff --git a/assets/css/index.css b/assets/css/index.css index 97743ce..af656ae 100644 --- a/assets/css/index.css +++ b/assets/css/index.css @@ -1,19 +1,10 @@ -/* #bid-extension body { - margin: 0; - padding: 0; - background-color: #121212; - color: #e0e0e0; - font-family: 'Segoe UI', Tahoma, sans-serif; - width: 320px; -} */ - #bid-extension { margin: 0; padding: 0; background-color: #121212; color: #e0e0e0; font-family: "Segoe UI", Tahoma, sans-serif; - width: 320px; + width: 500px; } #bid-extension .container { @@ -36,8 +27,9 @@ } #bid-extension input, +#bid-extension select, #bid-extension textarea { - padding: 8px; + padding: 4px 8px; background-color: #1e1e1e; color: #ffffff; border: 1px solid #333; @@ -45,9 +37,11 @@ font-size: 14px; width: 100%; box-sizing: border-box; + height: 32px; } #bid-extension input:focus, +#bid-extension select:focus, #bid-extension textarea:focus { border-color: #4a90e2; outline: none; @@ -71,12 +65,12 @@ #bid-extension button { margin-top: 10px; - padding: 10px; background: linear-gradient(to right, #4a90e2, #357abd); color: white; border: none; border-radius: 6px; font-size: 15px; + height: 36px; cursor: pointer; transition: background 0.3s ease; } @@ -129,6 +123,12 @@ height: 14px; } +#bid-extension .sub-col { + display: flex; + align-items: center; + gap: 10px; +} + #toggle-bid-extension svg { width: 20px; height: 20px; diff --git a/content.js b/content.js index 296b74e..c697469 100644 --- a/content.js +++ b/content.js @@ -157,12 +157,73 @@ async function handleUpdate(event, formElements, id) { quantity: isNaN(quantity) ? null : quantity, }; + const keys = Object.values(formElements.form) + .filter((item) => { + return [ + "mode_key", + "early_tracking_seconds", + "arrival_offset_seconds", + ].includes(item?.id); + }) + .reduce((prev, cur) => { + prev[cur.id] = cur.value; + return prev; + }, {}); + + const earlyTracking = parseInt(keys.early_tracking_seconds, 10); + const arrivalOffset = parseInt(keys.arrival_offset_seconds, 10); + + if (earlyTracking < 600) { + alert("Early Tracking Seconds must be at least 600 seconds (10 minutes)."); + return; + } + + if (arrivalOffset < 60) { + alert("Arrival Offset Seconds must be at least 60 seconds (1 minute)."); + return; + } + // Validate required fields if (payload.max_price === null) { alert("Please fill out the URL and Max Price fields correctly."); return; } + const localKeyName = keys["mode_key"]; + + const newKeys = Object.entries(keys).reduce((prev, [key, value]) => { + if (key === "mode_key") { + prev[key] = value; + } else { + prev[`${key}_${localKeyName}`] = Number(value); + } + return prev; + }, {}); + + let metadata = []; + + if ( + window.__result.metadata.length > 0 && + window.__result.metadata.some((item) => item.key_name === "mode_key") + ) { + metadata = window.__result.metadata.map((item) => { + if (Object.keys(newKeys).includes(item.key_name)) { + return { + ...item, + value: newKeys[item.key_name], + }; + } + return { ...item }; + }); + } else { + metadata = Object.entries(newKeys).map(([key, value]) => { + return { + key_name: key, + value, + }; + }); + } + try { const response = await fetch(`${CONFIG.API_BASE_URL}/bids/info/${id}`, { method: "PUT", @@ -170,7 +231,7 @@ async function handleUpdate(event, formElements, id) { "Content-Type": "application/json", Authorization: key, }, - body: JSON.stringify(removeFalsyValues(payload)), + body: JSON.stringify(removeFalsyValues({ ...payload, metadata })), }); const result = await response.json(); @@ -179,6 +240,8 @@ async function handleUpdate(event, formElements, id) { } catch (error) { alert("Error: " + error.message); console.error("API Error:", error); + } finally { + await showInfo(); } } @@ -289,6 +352,81 @@ const isValidModel = () => { return !!model; }; +const renderValueModeMetadata = (data, formElements, mode = null) => { + const early_tracking_seconds = getEarlyTrackingSeconds(data, mode); + const arrival_offset_seconds = getArrivalOffsetSeconds(data, mode); + + formElements.metadataMode.arrival_offset_seconds.value = + arrival_offset_seconds; + + formElements.metadataMode.early_tracking_seconds.value = + early_tracking_seconds; + + return { early_tracking_seconds, arrival_offset_seconds }; +}; + +function formatTimeFromMinutes(minutes) { + // Tính ngày, giờ, phút từ số phút + const days = Math.floor(minutes / (60 * 24)); + const hours = Math.floor((minutes % (60 * 24)) / 60); + const mins = minutes % 60; + + let result = ""; + + if (days > 0) result += `${days} ${days > 1 ? "days" : "day"} `; + if (hours > 0) result += `${hours} ${hours > 1 ? "hours" : "hour"} `; + if (mins > 0 || result === "") result += `${mins} minutes`; + + return result.trim(); +} + +function toReadableLabel(input) { + return input + .split("_") // Tách chuỗi theo dấu gạch dưới + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) // Viết hoa chữ cái đầu + .join(" "); // Nối lại bằng khoảng trắng +} + +const setMinusLabel = (input, minutes = null) => { + const label = document.querySelector(`[for="${input?.id}"]`); + + const text = toReadableLabel(input.id); + + label.textContent = `${text} (${formatTimeFromMinutes( + minutes || Number(input.value) || 300 / 60 + )})`; +}; + +const renderMetadaMode = (data, formElements, mode = null) => { + const mode_key = mode ? mode : getMode(data); + + formElements.metadataModeBox.style.display = "flex"; + + renderValueModeMetadata(data, formElements, mode_key); + + Object.values(formElements.form).forEach((item) => { + if (item?.id === "mode_key") { + item.value = mode_key; + + item.addEventListener("change", (e) => { + renderValueModeMetadata(data, formElements, e.target.value); + + Object.values(formElements.metadataMode).forEach((i) => { + setMinusLabel(i); + }); + }); + } + }); + + Object.values(formElements.metadataMode).forEach((item) => { + setMinusLabel(item); + + item.addEventListener("input", (e) => { + setMinusLabel(item, Number(e.target.value)); + }); + }); +}; + const createInfoColumn = (data, formElements) => { const inputsContainer = document.querySelector("#bid-extension .inputs"); const urlCol = document.querySelector("#url-col"); @@ -297,9 +435,19 @@ const createInfoColumn = (data, formElements) => { // 1. Thêm ID và Name vào đầu inputsContainer const otherEls = ` -