(function () { const supportedLanguages = ["en", "ar", "tr", "id"]; const languageLabels = { en: "EN", ar: "AR", tr: "TR", id: "ID" }; const API_BASE_URL = "https://jvapi.haiyihy.com"; const fallbackMessages = { en: { document_title: "Host Center", page_label: "Host Center", back: "Back", title: "Host Center", language_button_aria: "Change language", uid: "UID: 1234567890", agency: "Agency: Bilibili(101013)", streaming_duration: "Work Time (min)", target: "Target", daily_details: "Daily data", gift_points: "Gift points", online_minutes: "Online minutes", no_daily_data: "No daily data", close: "Close", open_daily_data: "Open daily data", my_income: "Salary", join_agency_title: "Join Agency", join_agency_text: "Search for an agency ID and submit your application.", join_agency_action: "Join now", agency_id: "Agency ID", enter_agent_id: "Enter agency ID", search: "Search", searching: "Searching...", agency_label: "Agency", apply: "Apply", applying: "Applying...", found: "Agency found", account_not_found: "Account not found or not an agency", application_submitted: "Application submitted", application_failed: "Application failed", application_records: "Application Records", pending: "Pending", join_pending_note: "Application is pending. Please wait for agency approval.", cancel: "Cancel", cancelling: "Cancelling...", cancellation_failed: "Cancellation failed", application_cancelled: "Application cancelled", missing_token: "Missing token", network_error: "Network error. Please try again.", withdraw_exchange: "Withdraw/Exchange", open_withdraw_exchange: "Open withdraw and exchange page", open_anchor_policy: "Open host policy", anchor_policy: "Host Policy", policy_loading: "Loading policy...", policy_empty: "No policy data", policy_missing_token: "Missing token", policy_load_failed: "Failed to load policy", policy_level: "Level", policy_online: "Online (Hour)", policy_effective_day: "Valid days", policy_target: "Target", policy_host_salary: "Host salary", policy_agent_salary: "Agent salary", policy_total_salary: "Total salary" }, ar: { document_title: "مركز المضيف", page_label: "مركز المضيف", back: "رجوع", title: "مركز المضيف", language_button_aria: "تغيير اللغة", uid: "معرّف المستخدم: 1234567890", agency: "الوكالة: Bilibili(101013)", streaming_duration: "وقت العمل (دقيقة)", target: "الهدف", daily_details: "البيانات اليومية", gift_points: "نقاط الهدايا", online_minutes: "دقائق الاتصال", no_daily_data: "لا توجد بيانات يومية", close: "إغلاق", open_daily_data: "فتح البيانات اليومية", my_income: "الراتب", join_agency_title: "الانضمام إلى وكالة", join_agency_text: "ابحث عن معرّف وكالة وأرسل طلبك.", join_agency_action: "انضم الآن", agency_id: "معرّف الوكالة", enter_agent_id: "أدخل معرّف الوكالة", search: "بحث", searching: "جار البحث...", agency_label: "الوكالة", apply: "تقديم", applying: "جار التقديم...", found: "تم العثور على الوكالة", account_not_found: "لم يتم العثور على الحساب أو ليس وكالة", application_submitted: "تم إرسال الطلب", application_failed: "فشل إرسال الطلب", application_records: "سجلات الطلب", pending: "قيد الانتظار", join_pending_note: "الطلب قيد الانتظار. يرجى انتظار موافقة الوكالة.", cancel: "إلغاء", cancelling: "جار الإلغاء...", cancellation_failed: "فشل الإلغاء", application_cancelled: "تم إلغاء الطلب", missing_token: "رمز الدخول مفقود", network_error: "خطأ في الشبكة. حاول مرة أخرى.", withdraw_exchange: "سحب/استبدال", open_withdraw_exchange: "فتح صفحة السحب والاستبدال", open_anchor_policy: "فتح سياسة المضيف", anchor_policy: "سياسة المضيف", policy_loading: "جار تحميل السياسة...", policy_empty: "لا توجد بيانات سياسة", policy_missing_token: "رمز الدخول مفقود", policy_load_failed: "فشل تحميل السياسة", policy_level: "المستوى", policy_online: "الاتصال (ساعة)", policy_effective_day: "الأيام الصالحة", policy_target: "الهدف", policy_host_salary: "راتب المضيف", policy_agent_salary: "راتب الوكيل", policy_total_salary: "إجمالي الراتب" }, tr: { document_title: "Host Merkezi", page_label: "Host Merkezi", back: "Geri", title: "Host Merkezi", language_button_aria: "Dili değiştir", uid: "UID: 1234567890", agency: "Ajans: Bilibili(101013)", streaming_duration: "Çalışma Süresi (dk)", target: "Hedef", daily_details: "Günlük veri", gift_points: "Hediye puanı", online_minutes: "Online dakika", no_daily_data: "Günlük veri yok", close: "Kapat", open_daily_data: "Günlük veriyi aç", my_income: "Maaş", join_agency_title: "Ajansa Katıl", join_agency_text: "Ajans ID ile arama yapıp başvurunu gönder.", join_agency_action: "Şimdi katıl", agency_id: "Ajans ID", enter_agent_id: "Ajans ID gir", search: "Ara", searching: "Aranıyor...", agency_label: "Ajans", apply: "Başvur", applying: "Başvuruluyor...", found: "Ajans bulundu", account_not_found: "Hesap bulunamadı veya ajans değil", application_submitted: "Başvuru gönderildi", application_failed: "Başvuru başarısız", application_records: "Başvuru Kayıtları", pending: "Beklemede", join_pending_note: "Başvuru beklemede. Lütfen ajans onayını bekleyin.", cancel: "İptal", cancelling: "İptal ediliyor...", cancellation_failed: "İptal başarısız", application_cancelled: "Başvuru iptal edildi", missing_token: "Token eksik", network_error: "Ağ hatası. Lütfen tekrar deneyin.", withdraw_exchange: "Çek/Değiştir", open_withdraw_exchange: "Çekme ve değişim sayfasını aç", open_anchor_policy: "Host politikasını aç", anchor_policy: "Host Politikası", policy_loading: "Politika yükleniyor...", policy_empty: "Politika verisi yok", policy_missing_token: "Token eksik", policy_load_failed: "Politika yüklenemedi", policy_level: "Seviye", policy_online: "Online (Saat)", policy_effective_day: "Geçerli gün", policy_target: "Hedef", policy_host_salary: "Host maaşı", policy_agent_salary: "Ajans maaşı", policy_total_salary: "Toplam maaş" }, id: { document_title: "Pusat Host", page_label: "Pusat Host", back: "Kembali", title: "Pusat Host", language_button_aria: "Ubah bahasa", uid: "UID: 1234567890", agency: "Agensi: Bilibili(101013)", streaming_duration: "Waktu Kerja (mnt)", target: "Target", daily_details: "Data harian", gift_points: "Poin hadiah", online_minutes: "Menit online", no_daily_data: "Tidak ada data harian", close: "Tutup", open_daily_data: "Buka data harian", my_income: "Gaji", join_agency_title: "Gabung Agensi", join_agency_text: "Cari ID agensi dan kirim pengajuan Anda.", join_agency_action: "Gabung sekarang", agency_id: "ID Agensi", enter_agent_id: "Masukkan ID agensi", search: "Cari", searching: "Mencari...", agency_label: "Agensi", apply: "Ajukan", applying: "Mengajukan...", found: "Agensi ditemukan", account_not_found: "Akun tidak ditemukan atau bukan agensi", application_submitted: "Pengajuan terkirim", application_failed: "Pengajuan gagal", application_records: "Catatan Pengajuan", pending: "Menunggu", join_pending_note: "Pengajuan sedang menunggu. Harap tunggu persetujuan agensi.", cancel: "Batal", cancelling: "Membatalkan...", cancellation_failed: "Gagal membatalkan", application_cancelled: "Pengajuan dibatalkan", missing_token: "Token tidak ditemukan", network_error: "Kesalahan jaringan. Silakan coba lagi.", withdraw_exchange: "Tarik/Tukar", open_withdraw_exchange: "Buka halaman tarik dan tukar", open_anchor_policy: "Buka kebijakan host", anchor_policy: "Kebijakan Host", policy_loading: "Memuat kebijakan...", policy_empty: "Tidak ada data kebijakan", policy_missing_token: "Token tidak ditemukan", policy_load_failed: "Gagal memuat kebijakan", policy_level: "Level", policy_online: "Online (Jam)", policy_effective_day: "Hari valid", policy_target: "Target", policy_host_salary: "Gaji host", policy_agent_salary: "Gaji agensi", policy_total_salary: "Total gaji" } }; const params = readURLParams(); let currentLang = normalizeLanguage(params.get("lang")); let currentMessages = fallbackMessages[currentLang] || fallbackMessages.en; let currentProfile = null; let currentAgencyProfile = null; let currentTeamId = ""; let currentIdentity = null; let currentSalary = "0.00"; let currentStreamingDuration = "0"; let currentGiftValue = "0"; let currentDailyTargets = []; let foundJoinAgency = null; let pendingJoinRecord = null; function readURLParams() { const result = new URLSearchParams(window.location.search); const hashQuery = window.location.hash.includes("?") ? window.location.hash.split("?")[1] : ""; const hashParams = new URLSearchParams(hashQuery); hashParams.forEach((value, key) => { if (!result.has(key)) result.set(key, value); }); return result; } function readRawParam(name) { const queries = [window.location.search.replace(/^\?/, "")]; if (window.location.hash.includes("?")) queries.push(window.location.hash.split("?")[1]); for (const query of queries) { for (const part of query.split("&")) { if (!part) continue; const equalIndex = part.indexOf("="); const rawKey = equalIndex >= 0 ? part.slice(0, equalIndex) : part; const rawValue = equalIndex >= 0 ? part.slice(equalIndex + 1) : ""; let decodedKey = ""; try { decodedKey = decodeURIComponent(rawKey); } catch (error) { continue; } if (decodedKey !== name) continue; try { return decodeURIComponent(rawValue.replace(/\+/g, "%2B")); } catch (error) { return rawValue; } } } return ""; } function normalizeLanguage(lang) { const value = String(lang || "en").toLowerCase(); return supportedLanguages.includes(value) ? value : "en"; } async function loadMessages(lang) { const normalizedLang = normalizeLanguage(lang); if (window.location.protocol === "file:") return fallbackMessages[normalizedLang]; try { const response = await fetch(`./locales/${normalizedLang}.json?v=20260428-2070`, { cache: "no-store" }); if (response.ok) return await response.json(); } catch (error) { return fallbackMessages[normalizedLang]; } return fallbackMessages[normalizedLang]; } function localizedValue(messages, key) { return messages?.[key] || fallbackMessages[currentLang]?.[key] || fallbackMessages.en[key] || ""; } function message(key, fallback = "") { return localizedValue(currentMessages, key) || fallback || key; } function renderMessages(messages) { document.querySelectorAll("[data-i18n]").forEach((node) => { const value = localizedValue(messages, node.dataset.i18n); if (value) node.textContent = value; }); document.querySelectorAll("[data-i18n-html]").forEach((node) => { const value = localizedValue(messages, node.dataset.i18nHtml); if (value) node.innerHTML = value; }); document.querySelectorAll("[data-i18n-aria]").forEach((node) => { const value = localizedValue(messages, node.dataset.i18nAria); if (value) node.setAttribute("aria-label", value); }); document.querySelectorAll("[data-i18n-placeholder]").forEach((node) => { const value = localizedValue(messages, node.dataset.i18nPlaceholder); if (value) node.setAttribute("placeholder", value); }); } function apiBaseURL() { const override = window.HYAPP_API_BASE_URL || params.get("apiBase"); if (override) return String(override).replace(/\/+$/, ""); return API_BASE_URL.replace(/\/+$/, ""); } function normalizeAuthorization(token) { const value = String(token || "").trim(); if (!value) return ""; return /^bearer\s+/i.test(value) ? value : `Bearer ${value}`; } function authHeadersFromToken(token) { return { Authorization: normalizeAuthorization(token), "req-lang": currentLang, "req-client": "H5", "req-version": "V2", "req-zone": Intl.DateTimeFormat().resolvedOptions().timeZone || "Asia/Shanghai", "req-app-intel": "version=1.0.0;build=1;model=H5;sysVersion=Web;channel=Web", "req-sys-origin": "origin=ATYOU;originChild=ATYOU" }; } async function requestJSON(path, options = {}) { const token = readRawParam("token"); if (!token) throw new Error(message("missing_token", "Missing token")); const headers = authHeadersFromToken(token); const request = { method: options.method || "GET", cache: "no-store", headers }; if (options.body !== undefined) { headers["Content-Type"] = "application/json"; request.body = JSON.stringify(options.body); } const response = await fetch(new URL(path, `${apiBaseURL()}/`).toString(), request); 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.body ?? data.data ?? null; } function profileUidPrefix(messages) { const template = messages.uid || fallbackMessages.en.uid; const marker = "1234567890"; return template.includes(marker) ? template.replace(marker, "").trim() : "UID:"; } function pickProfileName(profile) { return profile?.userNickname || profile?.name || "Oscar"; } function pickProfileAccount(profile) { return profile?.ownSpecialId?.account || profile?.account || profile?.id || "1234567890"; } function agencyPrefix(messages) { const template = messages.agency || fallbackMessages.en.agency; const marker = "Bilibili(101013)"; return template.includes(marker) ? template.replace(marker, "").trim() : "Agency:"; } function pickAgencyName(profile) { return profile?.userNickname || profile?.name || profile?.teamName || "-"; } function pickAgencyAccount(profile) { return profile?.ownSpecialId?.account || profile?.account || profile?.id || ""; } function formatAgencyText(profile, messages = currentMessages) { const prefix = agencyPrefix(messages); if (!profile) return `${prefix} -`; const name = pickAgencyName(profile); const account = pickAgencyAccount(profile); return account ? `${prefix} ${name}(${account})` : `${prefix} ${name}`; } function renderAgencyProfile(profile, messages = currentMessages) { const agencyButton = document.querySelector(".agency"); const agencyTextNode = document.querySelector(".agency span:first-child"); if (!agencyButton || !agencyTextNode) return; agencyTextNode.textContent = formatAgencyText(profile, messages); agencyButton.dataset.teamId = String(currentTeamId || pickAgencyTeamId(profile) || ""); agencyButton.dataset.account = String(profile?.account || ""); agencyButton.dataset.specialAccount = String(profile?.ownSpecialId?.account || ""); syncPolicyLink(); } function pickSpecialAccount(profile) { return profile?.ownSpecialId?.account || profile?.specialId?.account || profile?.specialAccount || profile?.shortAccount || profile?.shortId || ""; } function pickJoinAgencyProfile(body) { return body?.ownUserProfile || body?.userProfile || body?.teamProfile || body || null; } function pickSearchAgency(body) { const teamProfile = body?.teamProfile || null; const userProfile = body?.ownUserProfile || body?.userProfile || teamProfile?.ownUserProfile || teamProfile?.userProfile || null; if (!teamProfile?.id) return null; const specialAccount = pickSpecialAccount(userProfile) || pickSpecialAccount(teamProfile); return { ...(teamProfile || {}), ...(userProfile || {}), id: teamProfile.id, teamId: teamProfile.id, teamName: teamProfile.teamName || userProfile?.teamName || "", userNickname: userProfile?.userNickname || teamProfile.userNickname || teamProfile.name || teamProfile.teamName || "", name: userProfile?.name || teamProfile.name || teamProfile.teamName || "", userAvatar: userProfile?.userAvatar || teamProfile.userAvatar || userProfile?.avatar || teamProfile.avatar || "", avatar: userProfile?.avatar || teamProfile.avatar || userProfile?.userAvatar || teamProfile.userAvatar || "", displayAccount: specialAccount || userProfile?.account || teamProfile.account || "", account: userProfile?.account || teamProfile.account || "", ownSpecialId: userProfile?.ownSpecialId || teamProfile.ownSpecialId || (specialAccount ? { account: specialAccount } : null), specialId: userProfile?.specialId || teamProfile.specialId || null, specialAccount, shortAccount: userProfile?.shortAccount || teamProfile.shortAccount || "", shortId: userProfile?.shortId || teamProfile.shortId || "" }; } function pickJoinAgencyName(profile) { return profile?.userNickname || profile?.name || profile?.teamName || "-"; } function pickJoinAgencyAccount(profile) { return pickSpecialAccount(profile) || profile?.displayAccount || profile?.account || profile?.id || "-"; } function pickAgencyTeamId(profile) { return profile?.teamId || profile?.teamProfile?.id || profile?.id || ""; } function pickTeamEntryId(entry) { return entry?.teamProfile?.id || entry?.teamId || entry?.id || ""; } function removeAvatarFallback() { document.querySelector("#profileAvatarFallback")?.remove(); } function ensureAvatarFallback(displayName) { const avatarShell = document.querySelector(".avatar-shell"); if (!avatarShell) return null; let avatarFallback = document.querySelector("#profileAvatarFallback"); if (avatarFallback) { avatarFallback.hidden = false; avatarFallback.setAttribute("aria-label", `${displayName} avatar`); return avatarFallback; } const template = document.createElement("template"); template.innerHTML = ` `; avatarFallback = template.content.firstElementChild; avatarFallback.setAttribute("aria-label", `${displayName} avatar`); avatarShell.appendChild(avatarFallback); return avatarFallback; } function renderProfile(profile, messages = currentMessages) { if (!profile) return; const profileCard = document.querySelector(".profile-card"); const nameNode = document.querySelector("#profileName"); const uidNode = document.querySelector("#profileUid"); const avatarImage = document.querySelector("#profileAvatar"); const displayName = pickProfileName(profile); const displayAccount = pickProfileAccount(profile); if (profileCard) { profileCard.dataset.userId = String(profile.id || ""); profileCard.dataset.account = String(profile.account || ""); profileCard.dataset.specialAccount = String(profile?.ownSpecialId?.account || ""); } if (nameNode) nameNode.textContent = displayName; if (uidNode) uidNode.textContent = `${profileUidPrefix(messages)} ${displayAccount}`.trim(); if (!avatarImage) return; const avatar = profile.userAvatar ? String(profile.userAvatar) : ""; avatarImage.alt = displayName; if (!avatar) { avatarImage.hidden = true; avatarImage.onerror = null; avatarImage.removeAttribute("src"); ensureAvatarFallback(displayName); return; } avatarImage.hidden = false; removeAvatarFallback(); avatarImage.onerror = () => { avatarImage.hidden = true; avatarImage.removeAttribute("src"); ensureAvatarFallback(displayName); }; avatarImage.src = avatar; } function hasOwn(object, key) { return Boolean(object && Object.prototype.hasOwnProperty.call(object, key)); } function isTruthyIdentityValue(value) { if (typeof value === "boolean") return value; if (typeof value === "number") return value === 1; if (typeof value === "string") return ["true", "1", "yes"].includes(value.toLowerCase()); return false; } function shouldOpenJoinAgency(identity) { if (!hasOwn(identity, "anchor")) return false; return !isTruthyIdentityValue(identity.anchor); } function setLoading(isLoading) { const root = document.querySelector(".host-center"); const loadingMask = document.querySelector("#loadingMask"); if (root) root.dataset.loading = isLoading ? "true" : "false"; if (loadingMask) { loadingMask.hidden = !isLoading; loadingMask.setAttribute("aria-busy", String(isLoading)); } } function setIdentityView(identity) { const root = document.querySelector(".host-center"); const showJoinAgency = shouldOpenJoinAgency(identity); if (root) root.dataset.view = showJoinAgency ? "join-agency" : "host"; document.querySelectorAll(".host-only").forEach((node) => { node.hidden = showJoinAgency; }); const joinAgencyCard = document.querySelector("#joinAgencyCard"); if (joinAgencyCard) joinAgencyCard.hidden = !showJoinAgency; const agencyButton = document.querySelector(".agency"); if (agencyButton) agencyButton.hidden = showJoinAgency; } function closeHostCenterPage() { try { 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"); return; } if (window.history.length > 1) window.history.back(); } catch (error) { console.error("close host center page failed:", error); if (window.history.length > 1) window.history.back(); } } function formatCurrentSalary(value) { const numericValue = Number(value); if (Number.isFinite(numericValue)) return numericValue.toFixed(2); return "0.00"; } function pickCurrentSalary(body) { if (typeof body === "number") return body; if (body && typeof body === "object") { return body.currentSalary ?? body.availableBalance ?? body.balance ?? 0; } return 0; } function renderCurrentSalary(value) { currentSalary = formatCurrentSalary(value); const salaryNode = document.querySelector("#currentSalary"); if (salaryNode) salaryNode.textContent = currentSalary; } function formatStreamingDuration(value) { const numericValue = Number(value); if (!Number.isFinite(numericValue)) return "0"; const safeValue = Math.max(0, numericValue); return Number.isInteger(safeValue) ? String(safeValue) : String(Number(safeValue.toFixed(2))); } function pickStreamingDuration(body) { const workTarget = pickFirstMemberWorkTarget(body); return body?.onlineTime ?? body?.target?.onlineTime ?? workTarget?.target?.onlineTime ?? workTarget?.onlineTime ?? 0; } function renderStreamingDuration(value) { currentStreamingDuration = formatStreamingDuration(value); const durationNode = document.querySelector("#streamingDuration"); if (durationNode) durationNode.textContent = currentStreamingDuration; } function formatCountValue(value) { if (value === null || value === undefined || value === "") return "-"; const number = Number(value); if (Number.isFinite(number) && Number.isInteger(number)) return String(number); if (Number.isFinite(number)) return String(Number(number.toFixed(2))); return String(value); } function renderCurrentGiftValue(value) { currentGiftValue = formatCountValue(value === null || value === undefined || value === "" ? 0 : value); const giftNode = document.querySelector("#currentGiftValue"); const dailyGiftNode = document.querySelector("#dailyCurrentGift"); if (giftNode) giftNode.textContent = currentGiftValue; if (dailyGiftNode) dailyGiftNode.textContent = currentGiftValue; } function pickFirstMemberWorkTarget(body) { const targets = Array.isArray(body?.targets) ? body.targets : []; return targets[0] || body?.target || null; } function pickGiftValue(workTarget) { const target = workTarget?.target || workTarget || {}; return target.acceptGiftValue ?? target.giftValue ?? target.giftScore ?? target.currentGiftValue ?? null; } function pickDailyTargets(workTarget) { const target = workTarget?.target || workTarget || {}; return Array.isArray(target.dailyTargets) ? target.dailyTargets : []; } function formatDateNumber(value) { const text = String(value || ""); if (/^\d{8}$/.test(text)) { return `${text.slice(0, 4)}.${text.slice(4, 6)}.${text.slice(6, 8)}`; } return text || "-"; } function createDailyRow(item) { const row = document.createElement("div"); row.className = "daily-row"; const date = document.createElement("div"); date.className = "daily-date"; date.textContent = formatDateNumber(item?.dateNumber); const values = document.createElement("div"); values.className = "daily-values"; const gift = document.createElement("div"); gift.className = "daily-cell"; gift.innerHTML = `${currentMessages.gift_points || fallbackMessages.en.gift_points}${formatCountValue(item?.acceptGiftValue ?? 0)}`; const online = document.createElement("div"); online.className = "daily-cell"; online.innerHTML = `${currentMessages.online_minutes || fallbackMessages.en.online_minutes}${formatCountValue(item?.onlineTime ?? 0)}`; values.appendChild(gift); values.appendChild(online); row.appendChild(date); row.appendChild(values); return row; } function replaceNodeChildren(node, children) { while (node.firstChild) node.removeChild(node.firstChild); children.forEach((child) => node.appendChild(child)); } function renderDailyTargets(targets = currentDailyTargets) { currentDailyTargets = Array.isArray(targets) ? targets : []; const list = document.querySelector("#dailyList"); if (!list) return; if (!currentDailyTargets.length) { const empty = document.createElement("div"); empty.className = "daily-empty"; empty.textContent = currentMessages.no_daily_data || fallbackMessages.en.no_daily_data; replaceNodeChildren(list, [empty]); return; } replaceNodeChildren(list, currentDailyTargets.map(createDailyRow)); } function updateModalBodyLock() { const hasOpenModal = Array.from(document.querySelectorAll(".daily-modal, .join-agency-modal")).some((modal) => !modal.hidden); document.body.classList.toggle("daily-modal-open", hasOpenModal); } function renderMemberWorkSummary(memberWork) { const workTarget = pickFirstMemberWorkTarget(memberWork); renderStreamingDuration(pickStreamingDuration(memberWork)); renderCurrentGiftValue(pickGiftValue(workTarget) ?? 0); renderDailyTargets(pickDailyTargets(workTarget)); } function setDailyModalOpen(open) { const modal = document.querySelector("#dailyModal"); if (!modal) return; modal.hidden = !open; updateModalBodyLock(); if (open) renderDailyTargets(); } function showJoinAgencyStatus(text, type = "") { const node = document.querySelector("#joinAgencyStatus"); if (!node) return; node.textContent = text || ""; node.hidden = !text; node.classList.toggle("is-error", type === "error"); node.classList.toggle("is-success", type === "success"); } function renderJoinAgencyAvatar(profile, imageSelector, fallbackSelector) { const image = document.querySelector(imageSelector); const fallback = document.querySelector(fallbackSelector); if (!image || !fallback) return; const name = pickJoinAgencyName(profile); const avatar = profile?.userAvatar || profile?.avatar || ""; fallback.textContent = String(name || "A").slice(0, 1).toUpperCase() || "A"; image.alt = name; if (!avatar) { image.hidden = true; image.removeAttribute("src"); fallback.hidden = false; return; } fallback.hidden = true; image.hidden = false; image.onerror = () => { image.hidden = true; image.removeAttribute("src"); fallback.hidden = false; }; image.src = avatar; } function syncJoinAgencyApplyAvailability() { const button = document.querySelector("#joinAgencyApplyButton"); if (button) button.hidden = Boolean(pendingJoinRecord) || !foundJoinAgency?.id; const cancelButton = document.querySelector("#joinAgencyCancelButton"); if (cancelButton) cancelButton.hidden = !pendingJoinRecord || !pickPendingJoinRecordId(pendingJoinRecord); } function pickPendingJoinRecordId(record) { return record?.messageId || record?.id || ""; } function renderFoundJoinAgency(profile = foundJoinAgency) { const card = document.querySelector("#joinAgencyResult"); if (!card) return; if (!profile) { card.hidden = true; syncJoinAgencyApplyAvailability(); return; } card.hidden = false; const nameNode = document.querySelector("#joinAgencyName"); const accountNode = document.querySelector("#joinAgencyAccountText"); if (nameNode) nameNode.textContent = pickJoinAgencyName(profile); if (accountNode) accountNode.textContent = `${profileUidPrefix(currentMessages)} ${pickJoinAgencyAccount(profile)}`.trim(); renderJoinAgencyAvatar(profile, "#joinAgencyAvatar", "#joinAgencyAvatarFallback"); syncJoinAgencyApplyAvailability(); } function renderPendingJoinRecord(record = pendingJoinRecord) { const card = document.querySelector("#joinAgencyPending"); if (!card) return; if (!record) { card.hidden = true; syncJoinAgencyApplyAvailability(); return; } const profile = pickJoinAgencyProfile(record); card.hidden = false; const nameNode = document.querySelector("#joinAgencyPendingName"); const accountNode = document.querySelector("#joinAgencyPendingAccount"); if (nameNode) nameNode.textContent = pickJoinAgencyName(profile); if (accountNode) accountNode.textContent = `${profileUidPrefix(currentMessages)} ${pickJoinAgencyAccount(profile)}`.trim(); renderJoinAgencyAvatar(profile, "#joinAgencyPendingAvatar", "#joinAgencyPendingAvatarFallback"); syncJoinAgencyApplyAvailability(); } function joinAgencyErrorMessage(error, fallbackKey) { return error?.response?.errorMsg || error?.response?.message || error?.message || message(fallbackKey); } async function fetchPendingJoinRecord() { try { pendingJoinRecord = await requestJSON("/team/wait-apply/profile"); renderPendingJoinRecord(pendingJoinRecord); return pendingJoinRecord; } catch (error) { pendingJoinRecord = null; renderPendingJoinRecord(null); if (error.message === message("missing_token")) showJoinAgencyStatus(error.message, "error"); return null; } } async function searchJoinAgency(event) { event?.preventDefault(); const input = document.querySelector("#joinAgencyAccount"); const button = document.querySelector("#joinAgencySearchButton"); const account = String(input?.value || "").trim(); if (!account) { showJoinAgencyStatus(message("enter_agent_id"), "error"); return; } foundJoinAgency = null; renderFoundJoinAgency(null); if (button) { button.disabled = true; button.textContent = message("searching"); } showJoinAgencyStatus(""); try { const body = await requestJSON(`/team/search-account?account=${encodeURIComponent(account)}`); const profile = pickSearchAgency(body); if (!profile?.id) { showJoinAgencyStatus(message("account_not_found"), "error"); return; } foundJoinAgency = profile; renderFoundJoinAgency(foundJoinAgency); showJoinAgencyStatus(message("found"), "success"); } catch (error) { foundJoinAgency = null; renderFoundJoinAgency(null); showJoinAgencyStatus(joinAgencyErrorMessage(error, "network_error"), "error"); } finally { if (button) { button.disabled = false; button.textContent = message("search"); } } } async function applyToJoinAgency() { if (pendingJoinRecord || !foundJoinAgency?.id) return; const button = document.querySelector("#joinAgencyApplyButton"); if (button) { button.disabled = true; button.textContent = message("applying"); } showJoinAgencyStatus(""); try { const appliedAgency = foundJoinAgency; await requestJSON("/team/user/apply", { method: "POST", body: { teamId: appliedAgency.id, reason: "JOIN" } }); foundJoinAgency = null; renderFoundJoinAgency(null); showJoinAgencyStatus(message("application_submitted"), "success"); const pending = await fetchPendingJoinRecord(); if (!pending) { pendingJoinRecord = { ownUserProfile: appliedAgency }; renderPendingJoinRecord(pendingJoinRecord); } } catch (error) { showJoinAgencyStatus(joinAgencyErrorMessage(error, "application_failed"), "error"); } finally { if (button) { button.disabled = false; button.textContent = message("apply"); } syncJoinAgencyApplyAvailability(); } } async function cancelJoinApplication() { const id = pickPendingJoinRecordId(pendingJoinRecord); if (!id) return; const button = document.querySelector("#joinAgencyCancelButton"); if (button) { button.disabled = true; button.textContent = message("cancelling"); } showJoinAgencyStatus(""); try { await requestJSON("/team/user/join-apply-cancel", { method: "POST", body: { id } }); pendingJoinRecord = null; renderPendingJoinRecord(null); showJoinAgencyStatus(message("application_cancelled"), "success"); } catch (error) { showJoinAgencyStatus(joinAgencyErrorMessage(error, "cancellation_failed"), "error"); } finally { if (button) { button.disabled = false; button.textContent = message("cancel"); } syncJoinAgencyApplyAvailability(); } } function setJoinAgencyModalOpen(open) { const modal = document.querySelector("#joinAgencyModal"); if (!modal) return; modal.hidden = !open; updateModalBodyLock(); if (!open) return; showJoinAgencyStatus(""); fetchPendingJoinRecord(); window.setTimeout(() => { document.querySelector("#joinAgencyAccount")?.focus(); }, 0); } async function fetchUserProfile() { const token = readRawParam("token"); if (!token) { console.warn("Missing token for /team/member/profile"); return null; } try { const url = new URL("/team/member/profile", `${apiBaseURL()}/`); const response = await fetch(url.toString(), { cache: "no-store", headers: authHeadersFromToken(token) }); const data = await response.json().catch(() => ({})); if (!response.ok || data.status === false) { throw new Error(data.errorMsg || data.message || `Request failed: ${response.status}`); } currentProfile = data.body || data.data || {}; renderProfile(currentProfile); return currentProfile; } catch (error) { console.error("Failed to load user profile:", error); return null; } } async function fetchIdentity() { const token = readRawParam("token"); if (!token) { console.warn("Missing token for /app/h5/identity"); return null; } try { const url = new URL("/app/h5/identity", `${apiBaseURL()}/`); const response = await fetch(url.toString(), { cache: "no-store", headers: authHeadersFromToken(token) }); const data = await response.json().catch(() => ({})); if (!response.ok || data.status === false) { throw new Error(data.errorMsg || data.message || `Request failed: ${response.status}`); } currentIdentity = data.body || data.data || {}; return currentIdentity; } catch (error) { console.error("Failed to load H5 identity:", error); return null; } } async function fetchAgencyProfile() { const token = readRawParam("token"); if (!token) { console.warn("Missing token for /team/team-own/profile"); renderAgencyProfile(null); return null; } try { const url = new URL("/team/team-own/profile", `${apiBaseURL()}/`); const response = await fetch(url.toString(), { cache: "no-store", headers: authHeadersFromToken(token) }); const data = await response.json().catch(() => ({})); if (!response.ok || data.status === false) { throw new Error(data.errorMsg || data.message || `Request failed: ${response.status}`); } currentAgencyProfile = data.body || data.data || null; renderAgencyProfile(currentAgencyProfile); return currentAgencyProfile; } catch (error) { console.error("Failed to load agency profile:", error); renderAgencyProfile(null); return null; } } async function fetchTeamEntry() { const token = readRawParam("token"); if (!token) { console.warn("Missing token for /team/entry"); return ""; } try { const url = new URL("/team/entry", `${apiBaseURL()}/`); const response = await fetch(url.toString(), { cache: "no-store", headers: authHeadersFromToken(token) }); const data = await response.json().catch(() => ({})); if (!response.ok || data.status === false) { throw new Error(data.errorMsg || data.message || `Request failed: ${response.status}`); } currentTeamId = pickTeamEntryId(data.body || data.data || {}); renderAgencyProfile(currentAgencyProfile); syncPolicyLink(); return currentTeamId; } catch (error) { console.error("Failed to load team entry:", error); return ""; } } async function fetchBankBalance() { const token = readRawParam("token"); if (!token) { console.warn("Missing token for /wallet/bank/balance"); return; } try { const url = new URL("/wallet/bank/balance", `${apiBaseURL()}/`); const response = await fetch(url.toString(), { cache: "no-store", headers: authHeadersFromToken(token) }); const data = await response.json().catch(() => ({})); if (!response.ok || data.status === false) { throw new Error(data.errorMsg || data.message || `Request failed: ${response.status}`); } renderCurrentSalary(pickCurrentSalary(data.body ?? data.data)); } catch (error) { console.error("Failed to load bank balance:", error); renderCurrentSalary(0); } } async function fetchStreamingDuration(memberId) { const memberWork = await fetchMemberWork(memberId); renderMemberWorkSummary(memberWork); return memberWork; } async function fetchMemberWork(memberId) { if (!memberId) { console.warn("Missing memberId for /team/member-work"); return null; } try { const url = new URL("/team/member-work", `${apiBaseURL()}/`); url.searchParams.set("userId", String(memberId)); const token = readRawParam("token"); if (!token) { console.warn("Missing token for /team/member-work"); return null; } const response = await fetch(url.toString(), { cache: "no-store", headers: authHeadersFromToken(token) }); const data = await response.json().catch(() => ({})); if (!response.ok || data.status === false) { throw new Error(data.errorMsg || data.message || `Request failed: ${response.status}`); } return data.body || data.data || null; } catch (error) { console.error("Failed to load member work:", error); return null; } } function syncLocalizedLinks() { const nextParams = new URLSearchParams(params); const token = readRawParam("token"); if (token) nextParams.set("token", token); if (currentLang) nextParams.set("lang", currentLang); const query = nextParams.toString(); document.querySelectorAll('a[href^="../withdraw-exchange/index.html"]').forEach((link) => { link.setAttribute("href", `../withdraw-exchange/index.html${query ? `?${query}` : ""}`); }); } function syncPolicyLink() { const link = document.querySelector("#anchorPolicyLink"); if (!link) return; const nextParams = new URLSearchParams(params); const token = readRawParam("token"); const teamId = currentTeamId; if (token) nextParams.set("token", token); if (currentLang) nextParams.set("lang", currentLang); if (teamId) nextParams.set("teamId", teamId); const query = nextParams.toString(); link.setAttribute("href", `./policy.html${query ? `?${query}` : ""}`); } function setLanguageMenuOpen(open) { const languageButton = document.querySelector(".language-button"); const languageMenu = document.querySelector(".language-menu"); if (!languageButton || !languageMenu) return; languageMenu.hidden = !open; languageButton.setAttribute("aria-expanded", String(open)); } function renderLanguageControls(messages) { const languageButton = document.querySelector(".language-button"); if (languageButton) { languageButton.textContent = languageLabels[currentLang]; languageButton.setAttribute("aria-label", messages.language_button_aria || "Change language"); } document.querySelectorAll(".language-menu [data-lang]").forEach((button) => { const isActive = button.dataset.lang === currentLang; button.classList.toggle("is-active", isActive); button.setAttribute("aria-pressed", String(isActive)); }); } async function applyLanguage(lang) { currentLang = normalizeLanguage(lang); const messages = await loadMessages(currentLang); currentMessages = messages; document.documentElement.lang = currentLang; document.documentElement.dir = currentLang === "ar" ? "rtl" : "ltr"; document.title = messages.document_title || messages.title || "Host Center"; renderMessages(messages); renderLanguageControls(messages); syncLocalizedLinks(); syncPolicyLink(); renderProfile(currentProfile, messages); renderAgencyProfile(currentAgencyProfile, messages); renderDailyTargets(); renderFoundJoinAgency(foundJoinAgency); renderPendingJoinRecord(pendingJoinRecord); } document.querySelector(".language-button")?.addEventListener("click", (event) => { event.stopPropagation(); const languageMenu = document.querySelector(".language-menu"); setLanguageMenuOpen(Boolean(languageMenu?.hidden)); }); document.querySelectorAll(".language-menu [data-lang]").forEach((button) => { button.addEventListener("click", (event) => { event.stopPropagation(); setLanguageMenuOpen(false); applyLanguage(button.dataset.lang); }); }); document.addEventListener("click", () => { setLanguageMenuOpen(false); }); document.querySelector(".back-button")?.addEventListener("click", () => { closeHostCenterPage(); }); document.querySelector(".agency")?.addEventListener("click", () => { if (currentIdentity && shouldOpenJoinAgency(currentIdentity)) setJoinAgencyModalOpen(true); }); document.querySelector("#joinAgencyButton")?.addEventListener("click", () => { setJoinAgencyModalOpen(true); }); document.querySelector("#joinAgencySearchForm")?.addEventListener("submit", searchJoinAgency); document.querySelector("#joinAgencyApplyButton")?.addEventListener("click", () => { applyToJoinAgency(); }); document.querySelector("#joinAgencyCancelButton")?.addEventListener("click", () => { cancelJoinApplication(); }); document.querySelectorAll("[data-close-join-agency]").forEach((node) => { node.addEventListener("click", () => { setJoinAgencyModalOpen(false); }); }); document.querySelector(".gift-value")?.addEventListener("click", () => { setDailyModalOpen(true); }); document.querySelectorAll("[data-close-daily]").forEach((node) => { node.addEventListener("click", () => { setDailyModalOpen(false); }); }); document.addEventListener("keydown", (event) => { if (event.key === "Escape") { setDailyModalOpen(false); setJoinAgencyModalOpen(false); } }); ensureAvatarFallback("Oscar"); async function initializePage() { setLoading(true); try { await applyLanguage(currentLang); const identity = await fetchIdentity(); setIdentityView(identity); const profile = await fetchUserProfile(); const pendingRequests = []; if (!shouldOpenJoinAgency(identity)) { pendingRequests.push(fetchAgencyProfile()); pendingRequests.push(fetchTeamEntry()); pendingRequests.push(fetchBankBalance()); const memberId = profile?.id || profile?.account; if (memberId) pendingRequests.push(fetchStreamingDuration(memberId)); } await Promise.allSettled(pendingRequests); } catch (error) { console.error("Failed to initialize host center:", error); setIdentityView(currentIdentity); } finally { setLoading(false); } } initializePage(); })();