(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 GO_API_PATH_PREFIX = "/go"; const LOCAL_GO_API_BASE_URL = "http://127.0.0.1:1100"; const defaultPropsType = "RIDE"; // 后端经理中心 VIP 赠送默认 30 天;接口缺 days 时前端兜底展示同一口径。 const defaultNobleVIPGiftDays = 30; const fallbackMessages = { en: { document_title: "Manager Center", page_label: "Manager Center", back: "Back", title: "Manager Center", language_button_aria: "Change language", close: "Close", current_manager: "Current Manager", user: "User", user_search_placeholder: "Enter user ID or account", search: "Search", searching: "Searching...", target_user: "Target User", current_country: "Current country", change_country: "Change Country", change_country_disabled: "Change Country disabled", select_country: "Select country", changing_country: "Changing...", country_changed: "Country changed", no_countries: "No countries available", bd_leaders: "BD Leaders", bd_leader_count: "{count} BD Leaders", refresh: "Refresh", refreshing: "Refreshing...", no_bd_leaders: "No BD Leaders yet", add_bd_leader: "Add BD Leader", add_bd_leader_disabled: "Add BD Leader disabled", adding_bd_leader: "Adding...", add_bd_leader_success: "BD Leader added", gift_props: "Gift Props", gift_props_disabled: "Gift Props disabled", gift_type: "Gift Type", prop_type_ride: "Ride", prop_type_noble_vip: "Noble VIP", prop_type_avatar_frame: "Avatar Frame", prop_type_badge: "Badge", prop_type_chat_bubble: "Chat Bubble", prop_type_data_card: "Profile Card", no_giftable_props: "No giftable props", send: "Send", sending: "Sending...", send_success: "Sent successfully", ban_user: "Ban User", ban_user_disabled: "Ban User disabled", ban_reason: "Ban reason", ban: "Ban", submitting: "Submitting...", ban_success: "User banned", unban_user: "Unban User", unban_user_disabled: "Unban User disabled", unban_reason: "Unban reason", unban: "Unban", unban_success: "User unbanned", can_unban: "Can unban", cannot_unban: "Cannot unban", loading: "Loading...", uid_label: "UID", days: "{count} days", recharged: "Recharged", not_recharged: "Not recharged", recharge_unknown: "Recharge unknown", can_ban: "Can ban", cannot_ban: "Cannot ban", missing_token: "Missing token", not_manager: "Current account is not a manager", user_not_found: "User not found", user_recharged: "This user has recharge records and cannot be banned", user_already_banned: "This user is already banned", user_not_banned: "This user is not banned", manager_region_required: "Manager region is required", bd_leader_origin_mismatch: "The user is not in this manager's origin", user_is_admin: "Admin users cannot be added as BD Leaders", user_already_bd_leader: "This user is already a BD Leader", user_already_bound_bd_leader: "This user is already bound to a BD Leader", user_identity_locked: "This user has Host, Agency, BD, BD Leader, or Coin Seller identity and cannot be moved", country_not_found: "Country not found", country_required: "Select country", prop_not_giftable: "This prop is not available for manager gifting", vip_not_giftable: "This noble prop cannot be gifted", manager_feature_disabled: "This feature is disabled by admin", request_failed: "Request failed", enter_user: "Enter user ID or account" }, ar: { document_title: "مركز المدير", page_label: "مركز المدير", back: "رجوع", title: "مركز المدير", language_button_aria: "تغيير اللغة", close: "إغلاق", current_manager: "المدير الحالي", user: "المستخدم", user_search_placeholder: "أدخل معرّف المستخدم أو الحساب", search: "بحث", searching: "جار البحث...", target_user: "المستخدم المستهدف", current_country: "Current country", change_country: "Change Country", change_country_disabled: "Change Country disabled", select_country: "Select country", changing_country: "Changing...", country_changed: "Country changed", no_countries: "No countries available", bd_leaders: "قادة BD", bd_leader_count: "{count} قادة BD", refresh: "تحديث", refreshing: "جار التحديث...", no_bd_leaders: "لا يوجد قادة BD بعد", add_bd_leader: "إضافة قائد BD", add_bd_leader_disabled: "إضافة قائد BD معطلة", adding_bd_leader: "جار الإضافة...", add_bd_leader_success: "تمت إضافة قائد BD", gift_props: "إرسال العناصر", gift_props_disabled: "إرسال العناصر معطل", gift_type: "نوع الهدية", prop_type_ride: "مركبة", prop_type_noble_vip: "VIP نبيل", prop_type_avatar_frame: "إطار الصورة", prop_type_badge: "شارة", prop_type_chat_bubble: "فقاعة الدردشة", prop_type_data_card: "بطاقة الملف", no_giftable_props: "لا توجد عناصر قابلة للإهداء", send: "إرسال", sending: "جار الإرسال...", send_success: "تم الإرسال بنجاح", ban_user: "حظر المستخدم", ban_user_disabled: "حظر المستخدم معطل", ban_reason: "سبب الحظر", ban: "حظر", submitting: "جار الإرسال...", ban_success: "تم حظر المستخدم", unban_user: "إلغاء حظر المستخدم", unban_user_disabled: "إلغاء حظر المستخدم معطل", unban_reason: "سبب إلغاء الحظر", unban: "إلغاء الحظر", unban_success: "تم إلغاء حظر المستخدم", can_unban: "يمكن إلغاء الحظر", cannot_unban: "لا يمكن إلغاء الحظر", loading: "جار التحميل...", uid_label: "UID", days: "{count} يوم", recharged: "تم الشحن", not_recharged: "لم يتم الشحن", recharge_unknown: "حالة الشحن غير معروفة", can_ban: "يمكن الحظر", cannot_ban: "لا يمكن الحظر", missing_token: "رمز الدخول مفقود", not_manager: "الحساب الحالي ليس مديرًا", user_not_found: "المستخدم غير موجود", user_recharged: "لدى هذا المستخدم سجلات شحن ولا يمكن حظره", user_already_banned: "هذا المستخدم محظور بالفعل", user_not_banned: "هذا المستخدم غير محظور", manager_region_required: "منطقة المدير مطلوبة", bd_leader_origin_mismatch: "المستخدم ليس ضمن نظام هذا المدير", user_is_admin: "لا يمكن إضافة مستخدم إداري كقائد BD", user_already_bd_leader: "هذا المستخدم قائد BD بالفعل", user_already_bound_bd_leader: "هذا المستخدم مرتبط بالفعل بقائد BD", user_identity_locked: "This user has Host, Agency, BD, BD Leader, or Coin Seller identity and cannot be moved", country_not_found: "Country not found", country_required: "Select country", prop_not_giftable: "هذا العنصر غير متاح كهديّة من المدير", vip_not_giftable: "لا يمكن إهداء عنصر VIP هذا", manager_feature_disabled: "تم تعطيل هذه الميزة من الإدارة", request_failed: "فشل الطلب", enter_user: "أدخل معرّف المستخدم أو الحساب" }, tr: { document_title: "Yönetici Merkezi", page_label: "Yönetici Merkezi", back: "Geri", title: "Yönetici Merkezi", language_button_aria: "Dili değiştir", close: "Kapat", current_manager: "Mevcut Yönetici", user: "Kullanıcı", user_search_placeholder: "Kullanıcı ID veya hesap gir", search: "Ara", searching: "Aranıyor...", target_user: "Hedef Kullanıcı", current_country: "Current country", change_country: "Change Country", change_country_disabled: "Change Country disabled", select_country: "Select country", changing_country: "Changing...", country_changed: "Country changed", no_countries: "No countries available", bd_leaders: "BD Liderleri", bd_leader_count: "{count} BD Lideri", refresh: "Yenile", refreshing: "Yenileniyor...", no_bd_leaders: "Henüz BD lideri yok", add_bd_leader: "BD Lideri Ekle", add_bd_leader_disabled: "BD lideri ekleme kapalı", adding_bd_leader: "Ekleniyor...", add_bd_leader_success: "BD lideri eklendi", gift_props: "Eşya Gönder", gift_props_disabled: "Eşya gönderme kapalı", gift_type: "Hediye Türü", prop_type_ride: "Araç", prop_type_noble_vip: "Noble VIP", prop_type_avatar_frame: "Avatar Çerçevesi", prop_type_badge: "Rozet", prop_type_chat_bubble: "Sohbet Balonu", prop_type_data_card: "Profil Kartı", no_giftable_props: "Gönderilebilir eşya yok", send: "Gönder", sending: "Gönderiliyor...", send_success: "Başarıyla gönderildi", ban_user: "Kullanıcıyı Yasakla", ban_user_disabled: "Kullanıcı yasaklama kapalı", ban_reason: "Yasaklama nedeni", ban: "Yasakla", submitting: "Gönderiliyor...", ban_success: "Kullanıcı yasaklandı", unban_user: "Yasağı Kaldır", unban_user_disabled: "Yasak kaldırma kapalı", unban_reason: "Yasağı kaldırma nedeni", unban: "Yasağı kaldır", unban_success: "Kullanıcının yasağı kaldırıldı", can_unban: "Yasak kaldırılabilir", cannot_unban: "Yasak kaldırılamaz", loading: "Yükleniyor...", uid_label: "UID", days: "{count} gün", recharged: "Yükleme yaptı", not_recharged: "Yükleme yapmadı", recharge_unknown: "Yükleme durumu bilinmiyor", can_ban: "Yasaklanabilir", cannot_ban: "Yasaklanamaz", missing_token: "Token eksik", not_manager: "Mevcut hesap yönetici değil", user_not_found: "Kullanıcı bulunamadı", user_recharged: "Bu kullanıcının yükleme kaydı var, yasaklanamaz", user_already_banned: "Bu kullanıcı zaten yasaklı", user_not_banned: "Bu kullanıcı yasaklı değil", manager_region_required: "Yönetici bölgesi gerekli", bd_leader_origin_mismatch: "Kullanıcı bu yöneticinin origin değerinde değil", user_is_admin: "Admin kullanıcılar BD lideri eklenemez", user_already_bd_leader: "Bu kullanıcı zaten BD lideri", user_already_bound_bd_leader: "Bu kullanıcı zaten bir BD liderine bağlı", user_identity_locked: "This user has Host, Agency, BD, BD Leader, or Coin Seller identity and cannot be moved", country_not_found: "Country not found", country_required: "Select country", prop_not_giftable: "Bu eşya yönetici hediyesi için açık değil", vip_not_giftable: "Bu noble eşyası gönderilemez", manager_feature_disabled: "Bu özellik admin tarafından kapatıldı", request_failed: "İstek başarısız", enter_user: "Kullanıcı ID veya hesap gir" }, id: { document_title: "Pusat Manajer", page_label: "Pusat Manajer", back: "Kembali", title: "Pusat Manajer", language_button_aria: "Ubah bahasa", close: "Tutup", current_manager: "Manajer Saat Ini", user: "Pengguna", user_search_placeholder: "Masukkan ID pengguna atau akun", search: "Cari", searching: "Mencari...", target_user: "Pengguna Target", current_country: "Current country", change_country: "Change Country", change_country_disabled: "Change Country disabled", select_country: "Select country", changing_country: "Changing...", country_changed: "Country changed", no_countries: "No countries available", bd_leaders: "BD Leader", bd_leader_count: "{count} BD Leader", refresh: "Segarkan", refreshing: "Menyegarkan...", no_bd_leaders: "Belum ada BD Leader", add_bd_leader: "Tambah BD Leader", add_bd_leader_disabled: "Tambah BD Leader dinonaktifkan", adding_bd_leader: "Menambahkan...", add_bd_leader_success: "BD Leader ditambahkan", gift_props: "Kirim Properti", gift_props_disabled: "Kirim properti dinonaktifkan", gift_type: "Jenis Hadiah", prop_type_ride: "Kendaraan", prop_type_noble_vip: "Noble VIP", prop_type_avatar_frame: "Bingkai Avatar", prop_type_badge: "Lencana", prop_type_chat_bubble: "Gelembung Chat", prop_type_data_card: "Kartu Profil", no_giftable_props: "Tidak ada properti yang dapat dikirim", send: "Kirim", sending: "Mengirim...", send_success: "Berhasil dikirim", ban_user: "Blokir Pengguna", ban_user_disabled: "Blokir pengguna dinonaktifkan", ban_reason: "Alasan blokir", ban: "Blokir", submitting: "Mengirim...", ban_success: "Pengguna diblokir", unban_user: "Buka Blokir Pengguna", unban_user_disabled: "Buka blokir pengguna dinonaktifkan", unban_reason: "Alasan buka blokir", unban: "Buka blokir", unban_success: "Blokir pengguna dibuka", can_unban: "Dapat dibuka", cannot_unban: "Tidak dapat dibuka", loading: "Memuat...", uid_label: "UID", days: "{count} hari", recharged: "Sudah isi ulang", not_recharged: "Belum isi ulang", recharge_unknown: "Status isi ulang tidak diketahui", can_ban: "Dapat diblokir", cannot_ban: "Tidak dapat diblokir", missing_token: "Token tidak ditemukan", not_manager: "Akun saat ini bukan manajer", user_not_found: "Pengguna tidak ditemukan", user_recharged: "Pengguna ini memiliki riwayat isi ulang dan tidak dapat diblokir", user_already_banned: "Pengguna ini sudah diblokir", user_not_banned: "Pengguna ini tidak diblokir", manager_region_required: "Region manajer diperlukan", bd_leader_origin_mismatch: "Pengguna tidak berada di origin manajer ini", user_is_admin: "Pengguna admin tidak dapat ditambahkan sebagai BD Leader", user_already_bd_leader: "Pengguna ini sudah menjadi BD Leader", user_already_bound_bd_leader: "Pengguna ini sudah terhubung ke BD Leader", user_identity_locked: "This user has Host, Agency, BD, BD Leader, or Coin Seller identity and cannot be moved", country_not_found: "Country not found", country_required: "Select country", prop_not_giftable: "Properti ini tidak tersedia untuk hadiah manajer", vip_not_giftable: "Properti noble ini tidak dapat dikirim", manager_feature_disabled: "Fitur ini dinonaktifkan oleh admin", request_failed: "Permintaan gagal", enter_user: "Masukkan ID pengguna atau akun" } }; const state = { manager: null, target: null, activeAction: "", features: defaultFeatures(), propsType: defaultPropsType, props: [], selectedPropsId: "", countries: [], selectedCountryId: "", countriesLoading: false, changingCountry: false, bdLeaders: [], bdLeadersLoading: false, bdLeadersError: "", addingBDLeader: false }; const actionConfigs = { addBDLeader: { titleKey: "add_bd_leader", disabledKey: "add_bd_leader_disabled", feature: "addBdLeader", panel: "#addBDLeaderPanel", status: "#addBDLeaderStatus", needsUser: true }, changeCountry: { titleKey: "change_country", disabledKey: "change_country_disabled", feature: "changeCountry", panel: "#countryPanel", status: "#countryStatus", needsUser: true }, giftProps: { titleKey: "gift_props", disabledKey: "gift_props_disabled", feature: "giftProps", panel: "#giftPanel", status: "#propsStatus", needsUser: true }, banUser: { titleKey: "ban_user", disabledKey: "ban_user_disabled", feature: "banUser", panel: "#banPanel", status: "#banStatus", needsUser: true }, unbanUser: { titleKey: "unban_user", disabledKey: "unban_user_disabled", feature: "unbanUser", panel: "#unbanPanel", status: "#unbanStatus", needsUser: true }, bdLeaders: { titleKey: "bd_leaders", panel: "#bdLeaderPanel", needsUser: false } }; const params = readURLParams(); let currentLang = normalizeLanguage(params.get("lang")); let currentMessages = fallbackMessages[currentLang] || fallbackMessages.en; 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=20260626-0100`, { 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-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 setLanguageMenuOpen(open) { const languageButton = $(".language-button"); const languageMenu = $(".language-menu"); if (!languageButton || !languageMenu) return; languageMenu.hidden = !open; languageButton.setAttribute("aria-expanded", String(open)); } function renderLanguageControls(messages) { const languageButton = $(".language-button"); if (languageButton) { languageButton.textContent = languageLabels[currentLang]; languageButton.setAttribute("aria-label", localizedValue(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)); }); } function setPropsTypeMenuOpen(open) { const root = $("#propsTypeSelect"); const button = $("#propsTypeButton"); const menu = $("#propsTypeMenu"); if (!root || !button || !menu) return; root.classList.toggle("is-open", open); menu.hidden = !open; button.setAttribute("aria-expanded", String(open)); } function setCountryMenuOpen(open) { const root = $("#countrySelect"); const button = $("#countryButton"); const menu = $("#countryMenu"); if (!root || !button || !menu) return; root.classList.toggle("is-open", open); menu.hidden = !open; button.setAttribute("aria-expanded", String(open)); } function renderPropsTypeSelect() { const root = $("#propsTypeSelect"); const label = $("#propsTypeSelectedLabel"); if (root) root.dataset.value = state.propsType; if (label) label.textContent = propTypeLabel(state.propsType); document.querySelectorAll("#propsTypeMenu [data-value]").forEach((button) => { const isSelected = button.dataset.value === state.propsType; button.classList.toggle("is-selected", isSelected); button.setAttribute("aria-selected", String(isSelected)); }); } function renderCountrySelect() { const root = $("#countrySelect"); const label = $("#countrySelectedLabel"); const menu = $("#countryMenu"); if (root) root.dataset.value = state.selectedCountryId || ""; if (label) label.textContent = countryLabel(selectedCountry()) || message("select_country"); if (!menu) return; menu.replaceChildren(); state.countries.forEach((country) => { const button = document.createElement("button"); button.type = "button"; button.setAttribute("role", "option"); button.dataset.value = String(country.id); button.textContent = countryLabel(country); const isSelected = String(country.id) === String(state.selectedCountryId); button.classList.toggle("is-selected", isSelected); button.setAttribute("aria-selected", String(isSelected)); button.addEventListener("click", (event) => { event.stopPropagation(); chooseCountry(country.id); }); menu.appendChild(button); }); } function chooseCountry(countryId) { state.selectedCountryId = String(countryId || ""); setCountryMenuOpen(false); renderCountrySelect(); updateActionState(); } async function choosePropsType(value) { const nextValue = String(value || defaultPropsType); setPropsTypeMenuOpen(false); setCountryMenuOpen(false); if (nextValue === state.propsType) { renderPropsTypeSelect(); return; } state.propsType = nextValue; renderPropsTypeSelect(); try { await loadProps(); } catch (error) { setStatus($("#propsStatus"), friendlyError(error), "error"); } } 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 = message("document_title", "Manager Center"); renderMessages(messages); renderLanguageControls(messages); renderPropsTypeSelect(); renderCountrySelect(); renderManager(state.manager); renderTarget(); renderActionModal(); renderProps(); renderBDLeaders(); updateActionState(); } function $(selector) { return document.querySelector(selector); } function apiBaseURL() { const override = window.HYAPP_API_BASE_URL || params.get("apiBase"); if (override) return String(override).replace(/\/+$/, ""); return API_BASE_URL.replace(/\/+$/, ""); } function isLocalDocumentsFile() { if (window.location.protocol !== "file:") return false; let pathname = window.location.pathname || ""; try { pathname = decodeURIComponent(pathname); } catch (error) { return false; } return pathname.startsWith("/Users/hy/Documents/"); } function goApiBaseURL() { const override = window.HYAPP_GO_API_BASE_URL || params.get("goApiBase") || params.get("goBase"); if (override) return String(override).replace(/\/+$/, ""); if (isLocalDocumentsFile()) return `${LOCAL_GO_API_BASE_URL}${GO_API_PATH_PREFIX}`; return `${apiBaseURL()}${GO_API_PATH_PREFIX}`; } function buildRequestURL(baseURL, path) { const base = `${String(baseURL || API_BASE_URL).replace(/\/+$/, "")}/`; const target = String(path || "").replace(/^\/+/, ""); return new URL(target, base).toString(); } function normalizeAuthorization(token) { const value = String(token || "").trim(); if (!value) return ""; return /^bearer\s+/i.test(value) ? value : `Bearer ${value}`; } function authHeadersFromToken(token) { const sysOrigin = params.get("sysOrigin") || params.get("origin") || "ATYOU"; 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=${sysOrigin};originChild=${sysOrigin}` }; } async function requestGoJSON(path, options = {}) { const token = readRawParam("token"); if (!token) { const error = new Error(message("missing_token")); error.code = "missing_token"; throw error; } 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(buildRequestURL(goApiBaseURL(), path), 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.code = data.code || data.errorCodeName || ""; error.response = data; throw error; } return data.body ?? data.data ?? null; } function endpointProfile() { return "/app/h5/manager-center/profile"; } function endpointSearchUser(account) { return `/app/h5/manager-center/users/search?account=${encodeURIComponent(account)}`; } function endpointCountries() { return "/app/h5/manager-center/countries"; } function endpointChangeUserCountry() { return "/app/h5/manager-center/users/country"; } function endpointProps(type) { return `/app/h5/manager-center/props?type=${encodeURIComponent(type || "")}`; } function endpointSendProps() { return "/app/h5/manager-center/props/send"; } function endpointBDLeaders() { return "/app/h5/manager-center/bd-leaders"; } function endpointBanUser() { return "/app/h5/manager-center/users/ban"; } function endpointUnbanUser() { return "/app/h5/manager-center/users/unban"; } function setLoading(isLoading) { const root = $(".manager-center"); const mask = $("#loadingMask"); if (root) root.dataset.loading = isLoading ? "true" : "false"; if (mask) mask.hidden = !isLoading; } function setStatus(node, text, type = "") { if (!node) return; node.textContent = text || ""; node.hidden = !text; node.classList.toggle("is-error", type === "error"); } function showToast(text) { const toast = $("#toast"); if (!toast) return; toast.textContent = text || ""; toast.hidden = !text; window.clearTimeout(showToast.timer); showToast.timer = window.setTimeout(() => { toast.hidden = true; }, 2300); } function syncModalState() { document.body.classList.toggle("is-modal-open", Boolean(document.querySelector(".modal-mask:not([hidden])"))); } function activeConfig() { return actionConfigs[state.activeAction] || null; } function clearActionStatuses() { setStatus($("#modalSearchStatus"), ""); Object.values(actionConfigs).forEach((config) => { if (config.status) setStatus($(config.status), ""); }); } function clearActionModalForm() { const input = $("#modalAccountInput"); if (input) input.value = ""; const banReason = $("#banReason"); const unbanReason = $("#unbanReason"); if (banReason) banReason.value = ""; if (unbanReason) unbanReason.value = ""; state.target = null; state.selectedCountryId = ""; renderTarget(); clearActionStatuses(); } function renderActionModal() { const config = activeConfig(); const title = $("#actionModalTitle"); if (title) title.textContent = config ? message(config.titleKey) : "-"; const needsUser = config?.needsUser !== false; const searchForm = $("#modalSearchForm"); const modalTarget = $("#targetCard"); if (searchForm) searchForm.hidden = !needsUser; if (modalTarget && !needsUser) modalTarget.hidden = true; Object.values(actionConfigs).forEach((item) => { const panel = $(item.panel); if (panel) panel.hidden = item !== config || (item.needsUser !== false && !state.target); }); } function setModalOpen(selector, open) { const modal = $(selector); if (!modal) return; modal.hidden = !open; if (open) { setLanguageMenuOpen(false); setPropsTypeMenuOpen(false); setCountryMenuOpen(false); } syncModalState(); } function closeModals() { document.querySelectorAll(".modal-mask").forEach((modal) => { modal.hidden = true; }); state.activeAction = ""; state.target = null; setPropsTypeMenuOpen(false); setCountryMenuOpen(false); renderTarget(); syncModalState(); } function openActionModal(action) { const config = actionConfigs[action]; if (!config) return; if (config.feature && !featureEnabled(config.feature)) { showToast(message(config.disabledKey)); return; } state.activeAction = action; clearActionModalForm(); renderActionModal(); setModalOpen("#actionModal", true); updateActionState(); if (action === "giftProps" && !state.props.length) { loadProps().catch((error) => { setStatus($("#propsStatus"), friendlyError(error), "error"); }); } if (action === "bdLeaders") { renderBDLeaders(); } window.setTimeout(() => { if (config.needsUser !== false) $("#modalAccountInput")?.focus(); }, 0); } function openGiftModal() { openActionModal("giftProps"); } function openCountryModal() { openActionModal("changeCountry"); } function openBanModal() { openActionModal("banUser"); } function openUnbanModal() { openActionModal("unbanUser"); } function closePage() { 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 manager center failed:", error); if (window.history.length > 1) window.history.back(); } } function firstLetter(name, fallback) { const value = String(name || fallback || "U").trim(); return value ? value.slice(0, 1).toUpperCase() : "U"; } function renderAvatar(imgSelector, fallbackSelector, url, name, fallback) { const img = $(imgSelector); const fallbackNode = $(fallbackSelector); if (!img || !fallbackNode) return; const src = String(url || "").trim(); fallbackNode.textContent = firstLetter(name, fallback); if (src) { img.src = src; img.hidden = false; fallbackNode.hidden = true; } else { img.removeAttribute("src"); img.hidden = true; fallbackNode.hidden = false; } } function displayName(user) { return user?.userNickname || user?.nickname || user?.name || "-"; } function displayUserID(user) { return String(user?.userId || user?.id || "-"); } function sameUserID(left, right) { return displayUserID(left) === displayUserID(right); } function displayShortID(user) { return String(user?.actualAccount || user?.account || user?.shortId || user?.userId || user?.id || "-"); } function canBanTarget(target) { return Boolean(target) && target.canBan !== false && !target.hasRecharge && !canUnbanTarget(target); } function defaultFeatures() { return { addBdLeader: true, giftProps: true, banUser: true, unbanUser: true, changeCountry: true }; } function normalizeFeatures(features) { return { addBdLeader: features?.addBdLeader !== false, giftProps: features?.giftProps !== false, banUser: features?.banUser !== false, unbanUser: features?.unbanUser !== false, changeCountry: features?.changeCountry !== false }; } function featureEnabled(key) { return state.features?.[key] !== false; } function canUnbanTarget(target) { const status = String(target?.accountStatus || "").trim().toUpperCase(); return Boolean(target) && (status === "FREEZE" || status === "ARCHIVE" || status === "ARCHIVE_DEVICE"); } function userIDText(user) { return `${message("uid_label", "UID")}: ${displayShortID(user)}`; } function displayCountryText(user) { const name = String(user?.countryName || "").trim(); const code = String(user?.countryCode || "").trim(); if (name && code) return `${name} (${code})`; return name || code || "-"; } function countryLabel(country) { if (!country) return ""; const name = String(country.countryName || "").trim(); const code = String(country.countryCode || "").trim(); if (name && code) return `${name} (${code})`; return name || code || ""; } function selectedCountry() { return state.countries.find((country) => String(country.id) === String(state.selectedCountryId)) || null; } function matchingCountryId(user) { const code = String(user?.countryCode || "").trim().toUpperCase(); if (!code) return ""; const country = state.countries.find((item) => String(item.countryCode || "").trim().toUpperCase() === code); return country?.id || ""; } function propTypeLabel(type) { const key = `prop_type_${String(type || "").toLowerCase()}`; return message(key, type || "-"); } function formatDays(days) { return message("days", "{count} days").replace("{count}", new Intl.NumberFormat("en-US").format(Number(days) || 0)); } function formatBDLeaderCount(count) { return message("bd_leader_count", "{count} BD Leaders").replace("{count}", new Intl.NumberFormat("en-US").format(Number(count) || 0)); } function formatBDLeaderSummary() { const countText = formatBDLeaderCount(state.bdLeaders.length); const firstLeader = state.bdLeaders[0]; if (!firstLeader) return countText; return `${countText} - ${userIDText(firstLeader)}`; } function formatDateTime(value) { if (!value) return ""; const date = new Date(value); if (Number.isNaN(date.getTime())) return ""; try { return new Intl.DateTimeFormat(currentLang, { month: "short", day: "2-digit", hour: "2-digit", minute: "2-digit" }).format(date); } catch (error) { return date.toLocaleString(); } } function giftDays(item) { const days = Number(item?.days); if (Number.isFinite(days) && days > 0) return days; return String(item?.type || state.propsType).toUpperCase() === "NOBLE_VIP" ? defaultNobleVIPGiftDays : 7; } function renderManager(manager) { $("#managerName").textContent = displayName(manager); $("#managerUid").textContent = userIDText(manager); renderAvatar("#managerAvatar", "#managerAvatarFallback", manager?.userAvatar, displayName(manager), "M"); } function renderTarget() { const card = $("#targetCard"); if (!state.target) { if (card) card.hidden = true; renderActionModal(); updateActionState(); return; } const target = state.target; if (card) card.hidden = false; $("#targetName").textContent = displayName(target); $("#targetUid").textContent = userIDText(target); $("#targetAccountStatus").textContent = target.accountStatus || "-"; $("#targetCountryStatus").textContent = displayCountryText(target); const canBan = canBanTarget(target); const banEligibility = $("#banEligibility"); if (banEligibility) { banEligibility.textContent = canBan ? message("can_ban") : message("cannot_ban"); banEligibility.classList.toggle("is-danger", !canBan); } const canUnban = canUnbanTarget(target); const unbanEligibility = $("#unbanEligibility"); if (unbanEligibility) { unbanEligibility.textContent = canUnban ? message("can_unban") : message("cannot_unban"); unbanEligibility.classList.toggle("is-danger", !canUnban); } renderAvatar("#targetAvatar", "#targetAvatarFallback", target.userAvatar, displayName(target), "U"); renderActionModal(); updateActionState(); } async function prepareActiveActionAfterTarget() { if (!state.target) return; if (state.activeAction === "changeCountry") { const currentCountryText = $("#currentCountryText"); if (currentCountryText) currentCountryText.textContent = `${message("current_country")}: ${displayCountryText(state.target)}`; state.selectedCountryId = String(state.target.countryId || matchingCountryId(state.target) || ""); renderCountrySelect(); if (!state.countries.length) { await loadCountries(); } return; } if (state.activeAction === "giftProps") { renderProps(); } updateActionState(); } function renderProps() { const list = $("#propsList"); if (!list) return; list.replaceChildren(); if (!state.props.length) { setStatus($("#propsStatus"), message("no_giftable_props")); updateActionState(); return; } setStatus($("#propsStatus"), ""); state.props.forEach((item) => { const button = document.createElement("button"); button.type = "button"; button.className = "prop-option"; button.dataset.propsId = String(item.id); if (String(item.id) === String(state.selectedPropsId)) { button.classList.add("is-selected"); } const cover = document.createElement("span"); cover.className = "prop-cover"; if (item.cover || item.sourceUrl) { const img = document.createElement("img"); img.alt = ""; img.src = item.cover || item.sourceUrl; cover.appendChild(img); } else { const fallback = document.createElement("span"); fallback.textContent = firstLetter(item.name, "G"); cover.appendChild(fallback); } const copy = document.createElement("span"); copy.className = "prop-copy"; const name = document.createElement("span"); name.className = "prop-name"; name.textContent = item.name || `ID ${item.id}`; const meta = document.createElement("span"); meta.className = "prop-meta"; meta.textContent = item.vipLevel ? `${propTypeLabel(item.type)} · VIP ${item.vipLevel}` : propTypeLabel(item.type); copy.append(name, meta); const days = document.createElement("span"); days.className = "prop-days"; days.textContent = formatDays(giftDays(item)); button.append(cover, copy, days); button.addEventListener("click", () => { state.selectedPropsId = String(item.id); renderProps(); updateActionState(); }); list.appendChild(button); }); updateActionState(); } function isTargetBDLeader() { if (!state.target) return false; return state.bdLeaders.some((leader) => sameUserID(leader, state.target)); } function renderBDLeaders() { const list = $("#bdLeaderList"); const count = $("#bdLeaderCount"); const summary = $("#bdLeaderSummary"); const leaderCountText = formatBDLeaderCount(state.bdLeaders.length); if (count) count.textContent = leaderCountText; if (summary) summary.textContent = formatBDLeaderSummary(); if (!list) return; list.replaceChildren(); if (state.bdLeadersLoading) { setStatus($("#bdLeaderStatus"), message("refreshing")); updateActionState(); return; } if (state.bdLeadersError) { setStatus($("#bdLeaderStatus"), state.bdLeadersError, "error"); updateActionState(); return; } if (!state.bdLeaders.length) { setStatus($("#bdLeaderStatus"), message("no_bd_leaders")); updateActionState(); return; } setStatus($("#bdLeaderStatus"), ""); state.bdLeaders.forEach((leader) => { const row = document.createElement("div"); row.className = "bd-leader-row"; const avatar = document.createElement("span"); avatar.className = "bd-leader-avatar"; if (leader.userAvatar) { const img = document.createElement("img"); img.alt = ""; img.src = leader.userAvatar; avatar.appendChild(img); } else { const fallback = document.createElement("span"); fallback.textContent = firstLetter(displayName(leader), "B"); avatar.appendChild(fallback); } const copy = document.createElement("span"); copy.className = "bd-leader-copy"; const name = document.createElement("span"); name.className = "bd-leader-name"; name.textContent = displayName(leader); const meta = document.createElement("span"); meta.className = "bd-leader-meta"; meta.textContent = userIDText(leader); copy.append(name, meta); const time = document.createElement("span"); time.className = "bd-leader-time"; time.textContent = formatDateTime(leader.createTime); row.append(avatar, copy, time); list.appendChild(row); }); updateActionState(); } function updateActionState() { const addBDLeaderButton = $("#addBDLeaderButton"); const countryEntryButton = $("#countryEntryButton"); const giftEntryButton = $("#giftEntryButton"); const banEntryButton = $("#banEntryButton"); const unbanEntryButton = $("#unbanEntryButton"); const bdLeaderListButton = $("#bdLeaderListButton"); const refreshBDLeaderButton = $("#refreshBDLeaderButton"); const addBDLeaderConfirmButton = $("#addBDLeaderConfirmButton"); const sendButton = $("#sendPropsButton"); const changeCountryButton = $("#changeCountryButton"); const banButton = $("#banButton"); const unbanButton = $("#unbanButton"); if (addBDLeaderButton) { const disabledByFeature = !featureEnabled("addBdLeader"); addBDLeaderButton.disabled = disabledByFeature || state.addingBDLeader; addBDLeaderButton.classList.toggle("is-feature-disabled", disabledByFeature); const title = addBDLeaderButton.querySelector(".action-item-title"); if (title) { title.textContent = disabledByFeature ? message("add_bd_leader_disabled") : state.addingBDLeader ? message("adding_bd_leader") : message("add_bd_leader"); } } if (giftEntryButton) { const disabledByFeature = !featureEnabled("giftProps"); giftEntryButton.disabled = disabledByFeature; giftEntryButton.classList.toggle("is-feature-disabled", disabledByFeature); const title = giftEntryButton.querySelector(".action-item-title"); if (title) title.textContent = disabledByFeature ? message("gift_props_disabled") : message("gift_props"); } if (countryEntryButton) { const disabledByFeature = !featureEnabled("changeCountry"); countryEntryButton.disabled = disabledByFeature || state.changingCountry; countryEntryButton.classList.toggle("is-feature-disabled", disabledByFeature); const title = countryEntryButton.querySelector(".action-item-title"); if (title) title.textContent = disabledByFeature ? message("change_country_disabled") : message("change_country"); } if (banEntryButton) { const disabledByFeature = !featureEnabled("banUser"); banEntryButton.disabled = disabledByFeature; banEntryButton.classList.toggle("is-feature-disabled", disabledByFeature); const title = banEntryButton.querySelector(".action-item-title"); if (title) title.textContent = disabledByFeature ? message("ban_user_disabled") : message("ban_user"); } if (unbanEntryButton) { const disabledByFeature = !featureEnabled("unbanUser"); unbanEntryButton.disabled = disabledByFeature; unbanEntryButton.classList.toggle("is-feature-disabled", disabledByFeature); const title = unbanEntryButton.querySelector(".action-item-title"); if (title) title.textContent = disabledByFeature ? message("unban_user_disabled") : message("unban_user"); } if (bdLeaderListButton) bdLeaderListButton.disabled = state.bdLeadersLoading; if (refreshBDLeaderButton) refreshBDLeaderButton.disabled = state.bdLeadersLoading; if (addBDLeaderConfirmButton) { addBDLeaderConfirmButton.disabled = !featureEnabled("addBdLeader") || !state.target || state.addingBDLeader || isTargetBDLeader(); addBDLeaderConfirmButton.textContent = state.addingBDLeader ? message("adding_bd_leader") : message("add_bd_leader"); } if (sendButton) sendButton.disabled = !featureEnabled("giftProps") || !state.target || !state.selectedPropsId; if (changeCountryButton) { const currentID = String(state.target?.countryId || matchingCountryId(state.target) || ""); changeCountryButton.disabled = !featureEnabled("changeCountry") || !state.target || state.countriesLoading || state.changingCountry || !state.selectedCountryId || state.selectedCountryId === currentID; changeCountryButton.textContent = state.changingCountry ? message("changing_country") : message("change_country"); } if (banButton) banButton.disabled = !featureEnabled("banUser") || !canBanTarget(state.target); if (unbanButton) unbanButton.disabled = !featureEnabled("unbanUser") || !canUnbanTarget(state.target); } async function loadProfile() { const body = await requestGoJSON(endpointProfile()); state.manager = body?.manager || body || {}; state.features = normalizeFeatures(body?.features); renderManager(state.manager); updateActionState(); } async function loadProps() { state.props = []; state.selectedPropsId = ""; renderProps(); if (!featureEnabled("giftProps")) { setStatus($("#propsStatus"), message("gift_props_disabled")); return; } setStatus($("#propsStatus"), message("loading")); const body = await requestGoJSON(endpointProps(state.propsType)); state.props = Array.isArray(body?.records) ? body.records : []; state.selectedPropsId = state.props.length ? String(state.props[0].id) : ""; renderProps(); } async function loadCountries() { state.countriesLoading = true; setStatus($("#countryStatus"), message("loading")); updateActionState(); try { const body = await requestGoJSON(endpointCountries()); state.countries = Array.isArray(body?.records) ? body.records : []; if (!state.selectedCountryId) state.selectedCountryId = String(state.target?.countryId || matchingCountryId(state.target) || ""); setStatus($("#countryStatus"), state.countries.length ? "" : message("no_countries")); renderCountrySelect(); } finally { state.countriesLoading = false; updateActionState(); } } async function loadBDLeaders() { state.bdLeadersLoading = true; state.bdLeadersError = ""; renderBDLeaders(); try { const body = await requestGoJSON(endpointBDLeaders()); state.bdLeaders = Array.isArray(body?.records) ? body.records : []; setStatus($("#bdLeaderStatus"), ""); } catch (error) { state.bdLeadersError = friendlyError(error); throw error; } finally { state.bdLeadersLoading = false; renderBDLeaders(); } } async function searchUser(event) { event.preventDefault(); const input = $("#modalAccountInput"); const status = $("#modalSearchStatus"); const button = $("#modalSearchButton"); const account = String(input?.value || "").trim(); if (!account) { setStatus(status, message("enter_user"), "error"); return; } button.disabled = true; setStatus(status, message("searching")); try { const body = await requestGoJSON(endpointSearchUser(account)); state.target = body?.user || body || null; renderTarget(); await prepareActiveActionAfterTarget(); setStatus(status, ""); } catch (error) { state.target = null; renderTarget(); setStatus(status, friendlyError(error), "error"); } finally { button.disabled = false; } } async function addBDLeader() { if (!featureEnabled("addBdLeader")) { showToast(message("add_bd_leader_disabled")); return; } if (!state.target) { setStatus($("#addBDLeaderStatus"), message("enter_user"), "error"); return; } if (state.addingBDLeader) return; if (isTargetBDLeader()) { setStatus($("#addBDLeaderStatus"), message("user_already_bd_leader"), "error"); return; } state.addingBDLeader = true; setStatus($("#addBDLeaderStatus"), message("adding_bd_leader")); updateActionState(); try { await requestGoJSON(endpointBDLeaders(), { method: "POST", body: { userId: displayUserID(state.target) } }); setStatus($("#addBDLeaderStatus"), ""); closeModals(); showToast(message("add_bd_leader_success")); await loadBDLeaders(); } catch (error) { setStatus($("#addBDLeaderStatus"), friendlyError(error), "error"); } finally { state.addingBDLeader = false; updateActionState(); } } async function sendProps() { if (!featureEnabled("giftProps")) { showToast(message("gift_props_disabled")); return; } if (!state.target) { setStatus($("#propsStatus"), message("enter_user"), "error"); return; } if (!state.selectedPropsId) return; const button = $("#sendPropsButton"); button.disabled = true; try { await requestGoJSON(endpointSendProps(), { method: "POST", body: { acceptUserId: displayUserID(state.target), propsId: state.selectedPropsId } }); closeModals(); showToast(message("send_success")); } catch (error) { showToast(friendlyError(error)); } finally { updateActionState(); } } async function banUser() { if (!featureEnabled("banUser")) { setStatus($("#banStatus"), message("ban_user_disabled"), "error"); return; } if (!state.target) { setStatus($("#banStatus"), message("enter_user"), "error"); return; } if (!canBanTarget(state.target)) return; const button = $("#banButton"); button.disabled = true; setStatus($("#banStatus"), message("submitting")); try { await requestGoJSON(endpointBanUser(), { method: "POST", body: { userId: displayUserID(state.target), reason: $("#banReason").value || "" } }); state.target.accountStatus = "ARCHIVE"; renderTarget(); setStatus($("#banStatus"), ""); closeModals(); showToast(message("ban_success")); } catch (error) { setStatus($("#banStatus"), friendlyError(error), "error"); } finally { updateActionState(); } } async function unbanUser() { if (!featureEnabled("unbanUser")) { setStatus($("#unbanStatus"), message("unban_user_disabled"), "error"); return; } if (!state.target) { setStatus($("#unbanStatus"), message("enter_user"), "error"); return; } if (!canUnbanTarget(state.target)) return; const button = $("#unbanButton"); button.disabled = true; setStatus($("#unbanStatus"), message("submitting")); try { await requestGoJSON(endpointUnbanUser(), { method: "POST", body: { userId: displayUserID(state.target), reason: $("#unbanReason").value || "" } }); state.target.accountStatus = "NORMAL"; renderTarget(); setStatus($("#unbanStatus"), ""); closeModals(); showToast(message("unban_success")); } catch (error) { setStatus($("#unbanStatus"), friendlyError(error), "error"); } finally { updateActionState(); } } async function changeUserCountry() { if (!state.target) { setStatus($("#countryStatus"), message("enter_user"), "error"); return; } if (!featureEnabled("changeCountry")) { setStatus($("#countryStatus"), message("change_country_disabled"), "error"); return; } if (!state.selectedCountryId) { setStatus($("#countryStatus"), message("country_required"), "error"); return; } state.changingCountry = true; setStatus($("#countryStatus"), message("changing_country")); updateActionState(); try { const body = await requestGoJSON(endpointChangeUserCountry(), { method: "POST", body: { userId: displayUserID(state.target), countryId: state.selectedCountryId } }); state.target = body?.user || state.target; renderTarget(); setStatus($("#countryStatus"), ""); closeModals(); showToast(message("country_changed")); } catch (error) { setStatus($("#countryStatus"), friendlyError(error), "error"); } finally { state.changingCountry = false; updateActionState(); } } function friendlyError(error) { const code = error?.code || error?.response?.code || error?.response?.errorCodeName || ""; if (code === "missing_token") return message("missing_token"); if (code === "not_manager") return message("not_manager"); if (code === "user_not_found") return message("user_not_found"); if (code === "user_recharged") return message("user_recharged"); if (code === "user_already_banned") return message("user_already_banned"); if (code === "user_not_banned") return message("user_not_banned"); if (code === "manager_region_required") return message("manager_region_required"); if (code === "bd_leader_origin_mismatch") return message("bd_leader_origin_mismatch"); if (code === "user_is_admin") return message("user_is_admin"); if (code === "user_already_bd_leader") return message("user_already_bd_leader"); if (code === "user_already_bound_bd_leader") return message("user_already_bound_bd_leader"); if (code === "user_identity_locked") return message("user_identity_locked"); if (code === "country_not_found") return message("country_not_found"); if (code === "country_required") return message("country_required"); if (code === "prop_not_giftable") return message("prop_not_giftable"); if (code === "vip_not_giftable") return message("vip_not_giftable"); if (code === "manager_feature_disabled") return message("manager_feature_disabled"); return error?.message || message("request_failed"); } function bindEvents() { $(".back-button")?.addEventListener("click", closePage); $(".language-button")?.addEventListener("click", (event) => { event.stopPropagation(); setCountryMenuOpen(false); setLanguageMenuOpen(Boolean($(".language-menu")?.hidden)); }); document.querySelectorAll(".language-menu [data-lang]").forEach((button) => { button.addEventListener("click", async (event) => { event.stopPropagation(); setLanguageMenuOpen(false); await applyLanguage(button.dataset.lang); }); }); document.addEventListener("click", () => { setLanguageMenuOpen(false); setPropsTypeMenuOpen(false); setCountryMenuOpen(false); }); $("#addBDLeaderButton")?.addEventListener("click", () => openActionModal("addBDLeader")); $("#bdLeaderListButton")?.addEventListener("click", () => openActionModal("bdLeaders")); $("#refreshBDLeaderButton")?.addEventListener("click", () => { loadBDLeaders().catch((error) => { showToast(friendlyError(error)); }); }); $("#giftEntryButton")?.addEventListener("click", openGiftModal); $("#countryEntryButton")?.addEventListener("click", openCountryModal); $("#banEntryButton")?.addEventListener("click", openBanModal); $("#unbanEntryButton")?.addEventListener("click", openUnbanModal); document.querySelectorAll("[data-modal-close]").forEach((button) => { button.addEventListener("click", closeModals); }); document.querySelectorAll(".modal-mask").forEach((modal) => { modal.addEventListener("click", (event) => { if (event.target === modal) closeModals(); }); }); $("#propsTypeButton")?.addEventListener("click", (event) => { event.stopPropagation(); setLanguageMenuOpen(false); setCountryMenuOpen(false); setPropsTypeMenuOpen(Boolean($("#propsTypeMenu")?.hidden)); }); document.querySelectorAll("#propsTypeMenu [data-value]").forEach((button) => { button.addEventListener("click", async (event) => { event.stopPropagation(); await choosePropsType(button.dataset.value); }); }); $("#countryButton")?.addEventListener("click", (event) => { event.stopPropagation(); setLanguageMenuOpen(false); setPropsTypeMenuOpen(false); setCountryMenuOpen(Boolean($("#countryMenu")?.hidden)); }); document.addEventListener("keydown", (event) => { if (event.key !== "Escape") return; setLanguageMenuOpen(false); setPropsTypeMenuOpen(false); setCountryMenuOpen(false); closeModals(); }); $("#modalSearchForm")?.addEventListener("submit", searchUser); $("#addBDLeaderConfirmButton")?.addEventListener("click", addBDLeader); $("#sendPropsButton")?.addEventListener("click", sendProps); $("#banButton")?.addEventListener("click", banUser); $("#unbanButton")?.addEventListener("click", unbanUser); $("#changeCountryButton")?.addEventListener("click", changeUserCountry); } async function init() { bindEvents(); renderPropsTypeSelect(); await applyLanguage(currentLang); if (!readRawParam("token")) { setLoading(false); setStatus($("#pageStatus"), message("missing_token"), "error"); return; } try { await loadProfile(); await Promise.all([loadProps(), loadBDLeaders()]); } catch (error) { showToast(friendlyError(error)); } finally { setLoading(false); } } init(); })();