const API_BASE_URL = "https://jvapi.haiyihy.com"; let commonHeaders = { authorization: "Bearer undefined", "req-app-intel": "version=1.0.0;build=1;model=SM-G9550;sysVersion=9;channel=Google", "req-client": "Android", "req-imei": "8fa54d728ab449e04f9292329ed44bda", "req-lang": "id-ID", "req-sys-origin": "origin=ATYOU;originChild=ATYOU", "req-version": "V2", "req-zone": "Asia/Shanghai" }; const fallbackConfig = { title: "Center", identity: "USER", heroTitle: "Available salary", heroLink: "Details", heroRoute: "/history-salary", balanceType: "", summaries: [], sections: [] }; const config = { ...fallbackConfig, ...(window.CENTER_PAGE || {}) }; const state = { lang: resolveLanguage(), heroValue: "0", summaries: [...(config.summaries || [])] }; function resolveLanguage() { const params = new URLSearchParams(window.location.search); const hashQuery = window.location.hash.includes("?") ? window.location.hash.split("?")[1] : ""; const hashParams = new URLSearchParams(hashQuery); const lang = params.get("lang") || hashParams.get("lang") || navigator.language || "en"; if (lang.startsWith("ar")) return "ar"; if (lang.startsWith("tr")) return "tr"; if (lang.startsWith("bn")) return "bn"; return "en"; } function formatMoney(value) { if (value === null || value === undefined || value === "") return "0"; const number = Number(value); if (Number.isNaN(number)) return String(value); return Number.isInteger(number) ? String(number) : number.toFixed(2); } function splitHeaderPairs(value) { const result = {}; if (!value) return result; value.split(";").forEach((item) => { const index = item.indexOf("="); if (index > -1) result[item.slice(0, index)] = item.slice(index + 1); }); return result; } function parseAccessOrigin(raw) { const data = JSON.parse(raw); const appIntel = splitHeaderPairs(data["Req-App-Intel"]); const sysOrigin = splitHeaderPairs(data["Req-Sys-Origin"]); return { reqLang: data["Req-Lang"], authorization: data.Authorization, buildVersion: appIntel.build, appVersion: appIntel.version, appChannel: appIntel.channel, reqImei: appIntel["Req-Imei"], sysOrigin: sysOrigin.origin, sysOriginChild: sysOrigin.child }; } function setHeadersFromApp(headers) { const next = {}; if (headers.authorization) next.authorization = headers.authorization; if (headers.reqLang) next["req-lang"] = headers.reqLang; if (headers.appVersion || headers.buildVersion || headers.appChannel) { const intel = []; if (headers.appVersion) intel.push(`version=${headers.appVersion}`); if (headers.buildVersion) intel.push(`build=${headers.buildVersion}`); if (headers.appChannel) intel.push(`channel=${headers.appChannel}`); next["req-app-intel"] = intel.join(";"); } if (headers.reqImei) next["req-imei"] = headers.reqImei; if (headers.sysOrigin) { const origin = [`origin=${headers.sysOrigin}`]; if (headers.sysOriginChild) origin.push(`child=${headers.sysOriginChild}`); next["req-sys-origin"] = origin.join(";"); } commonHeaders = { ...commonHeaders, ...next }; } function requestAccessOrigin() { return new Promise((resolve) => { window.renderData = resolve; window.getIosAccessOriginParam = resolve; if (!(window.app || window.webkit || window.FlutterPageControl)) { setHeadersFromApp({ authorization: "", reqLang: state.lang, appVersion: "1.0.0", buildVersion: "1", appChannel: "Web", reqImei: "H5-STATIC", sysOrigin: "LIKEI", sysOriginChild: "LIKEI" }); resolve(null); return; } let attempt = 0; const poll = () => { attempt += 1; if (window.app && typeof window.app.getAccessOrigin === "function") { resolve(window.app.getAccessOrigin()); return; } if (attempt < 50) { window.setTimeout(poll, 100); return; } if (window.FlutterApp && typeof window.FlutterApp.postMessage === "function") { window.FlutterApp.postMessage("requestAccessOrigin"); } }; poll(); }); } async function connectToApp() { const raw = await requestAccessOrigin(); if (raw) setHeadersFromApp(parseAccessOrigin(raw)); } async function apiGet(path) { const response = await fetch(`${API_BASE_URL}${path}`, { method: "GET", headers: commonHeaders }); const data = await response.json().catch(() => ({})); if (!response.ok || data.status === false) { const error = new Error(data.errorMsg || data.message || `Request failed: ${response.status}`); error.response = data; throw error; } return data; } async function fetchHeroValue() { if (config.balanceType) { const result = await apiGet(`/wallet/salary-account/balance?salaryType=${config.balanceType}`); if (result.status && result.body) state.heroValue = formatMoney(result.body.availableBalance || 0); return; } if (config.balanceEndpoint) { const result = await apiGet(config.balanceEndpoint); const body = result.body || {}; state.heroValue = formatMoney(body.currentSalary ?? body.availableBalance ?? body.balance ?? 0); } } function showToast(message) { const toast = document.getElementById("toast"); toast.textContent = message; toast.hidden = false; window.clearTimeout(showToast.timer); showToast.timer = window.setTimeout(() => { toast.hidden = true; }, 2500); } function normalizeRoute(target) { const alias = { "/invite-agency": "/invite-agency/", "/invite-bd": "/invite-bd/", "/invite-bd-leader": "/invite-bd-leader/", "/invite-recharge-agency": "/invite-recharge-agency/" }; const url = new URL(alias[target] || target, window.location.origin); const currentLang = new URLSearchParams(window.location.search).get("lang"); if (currentLang && !url.searchParams.has("lang")) url.searchParams.set("lang", currentLang); return `${url.pathname}${url.search}${url.hash}`; } function navigateTo(target) { window.location.href = normalizeRoute(target); } function menuIcon(text) { return (text || "?").trim().slice(0, 1).toUpperCase(); } function render() { document.documentElement.lang = state.lang; document.documentElement.dir = state.lang === "ar" ? "rtl" : "ltr"; document.getElementById("pageTitle").textContent = config.title; document.querySelector("[data-action='language']").textContent = state.lang.toUpperCase(); document.getElementById("heroTitle").textContent = config.heroTitle; document.getElementById("heroLink").textContent = config.heroLink || "Details"; document.getElementById("heroValue").textContent = `$${state.heroValue}`; const summaryRoot = document.getElementById("summaryGrid"); summaryRoot.innerHTML = ""; state.summaries.forEach((item) => { const node = document.createElement("div"); node.className = "summary-item"; node.innerHTML = `
`; node.querySelector(".summary-label").textContent = item.label; node.querySelector(".summary-value").textContent = item.value; summaryRoot.appendChild(node); }); summaryRoot.hidden = !state.summaries.length; const oldTask = document.getElementById("taskCard"); if (oldTask) oldTask.remove(); if (config.task) { const taskCard = document.createElement("section"); taskCard.className = "surface-card task-card"; taskCard.id = "taskCard"; taskCard.innerHTML = `
`; taskCard.querySelector(".task-title").textContent = config.task.title || ""; const taskGrid = taskCard.querySelector(".task-grid"); (config.task.items || []).forEach((item) => { const node = document.createElement("div"); node.innerHTML = `
`; node.querySelector(".task-label").textContent = item.label; node.querySelector(".task-value").textContent = item.value; taskGrid.appendChild(node); }); const sections = document.getElementById("sections"); sections.parentNode.insertBefore(taskCard, sections); } const sectionRoot = document.getElementById("sections"); sectionRoot.innerHTML = ""; (config.sections || []).forEach((section) => { const card = document.createElement("section"); card.className = "surface-card menu-card"; const title = document.createElement("div"); title.className = "section-title"; title.textContent = section.title || ""; card.appendChild(title); (section.items || []).forEach((item) => { const row = document.createElement("button"); row.type = "button"; row.className = "menu-row"; row.dataset.route = item.route; row.innerHTML = ``; row.querySelector(".menu-icon").textContent = item.icon || menuIcon(item.label); row.querySelector(".menu-text").textContent = item.label; row.addEventListener("click", () => navigateTo(item.route)); card.appendChild(row); }); sectionRoot.appendChild(card); }); } function bindEvents() { document.querySelector("[data-action='back']").addEventListener("click", () => { if (window.history.length > 1) { window.history.back(); return; } if (window.app && typeof window.app.closePage === "function") { window.app.closePage(); return; } if (window.FlutterPageControl && typeof window.FlutterPageControl.postMessage === "function") { window.FlutterPageControl.postMessage("close_page"); } }); document.querySelector("[data-action='language']").addEventListener("click", () => navigateTo("/language")); document.getElementById("heroLink").addEventListener("click", () => navigateTo(config.heroRoute || "/history-salary")); } async function init() { localStorage.setItem("identity", JSON.stringify({ identity: config.identity })); render(); bindEvents(); try { await connectToApp(); await fetchHeroValue(); } catch (error) { console.warn(`${config.title} data request failed:`, error); showToast(error.response?.errorMsg || error.message || "Failed to load data."); } finally { render(); } } init();