(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: "Join Agency", page_label: "Join Agency", back: "Back", title: "Join Agency", language_button_aria: "Change language", agency_id: "Agency ID", enter_agent_id: "Enter agency ID", search: "Search", searching: "Searching...", apply: "Apply", applying: "Applying...", agency: "Agency", uid_prefix: "UID:", account_not_found: "Account not found or not an agency", missing_token: "Missing token", found: "Agency found", application_submitted: "Application submitted", application_failed: "Application failed", application_records: "Application Records", pending: "Pending", cancel: "Cancel", cancelling: "Cancelling...", cancellation_failed: "Cancellation failed", application_cancelled: "Application cancelled", network_error: "Network error" }, ar: { document_title: "الانضمام إلى وكالة", page_label: "الانضمام إلى وكالة", back: "رجوع", title: "الانضمام إلى وكالة", language_button_aria: "تغيير اللغة", agency_id: "معرّف الوكالة", enter_agent_id: "أدخل معرّف الوكالة", search: "بحث", searching: "جار البحث...", apply: "تقديم", applying: "جار التقديم...", agency: "الوكالة", uid_prefix: "UID:", account_not_found: "لم يتم العثور على وكالة", missing_token: "رمز الدخول مفقود", found: "تم العثور على الوكالة", application_submitted: "تم إرسال الطلب", application_failed: "فشل الطلب", application_records: "سجلات الطلب", pending: "قيد الانتظار", cancel: "إلغاء", cancelling: "جار الإلغاء...", cancellation_failed: "فشل الإلغاء", application_cancelled: "تم إلغاء الطلب", network_error: "خطأ في الشبكة" }, tr: { document_title: "Ajansa Katıl", page_label: "Ajansa Katıl", back: "Geri", title: "Ajansa Katıl", language_button_aria: "Dili değiştir", agency_id: "Ajans ID", enter_agent_id: "Ajans ID gir", search: "Ara", searching: "Aranıyor...", apply: "Başvur", applying: "Başvuruluyor...", agency: "Ajans", uid_prefix: "UID:", account_not_found: "Hesap bulunamadı veya ajans değil", missing_token: "Token eksik", found: "Ajans bulundu", application_submitted: "Başvuru gönderildi", application_failed: "Başvuru başarısız", application_records: "Başvuru Kayıtları", pending: "Beklemede", cancel: "İptal", cancelling: "İptal ediliyor...", cancellation_failed: "İptal başarısız", application_cancelled: "Başvuru iptal edildi", network_error: "Ağ hatası" }, id: { document_title: "Gabung Agensi", page_label: "Gabung Agensi", back: "Kembali", title: "Gabung Agensi", language_button_aria: "Ubah bahasa", agency_id: "ID Agensi", enter_agent_id: "Masukkan ID agensi", search: "Cari", searching: "Mencari...", apply: "Ajukan", applying: "Mengajukan...", agency: "Agensi", uid_prefix: "UID:", account_not_found: "Akun tidak ditemukan atau bukan agensi", missing_token: "Token tidak ditemukan", found: "Agensi ditemukan", application_submitted: "Pengajuan dikirim", application_failed: "Pengajuan gagal", application_records: "Riwayat Pengajuan", pending: "Menunggu", cancel: "Batal", cancelling: "Membatalkan...", cancellation_failed: "Gagal membatalkan", application_cancelled: "Pengajuan dibatalkan", network_error: "Kesalahan jaringan" } }; const params = readURLParams(); let currentLang = normalizeLanguage(params.get("lang")); let currentMessages = fallbackMessages[currentLang] || fallbackMessages.en; let foundAgency = null; let pendingRecord = 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"; } function t(key) { return currentMessages[key] || fallbackMessages.en[key] || key; } 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 apiRequest(path, options = {}) { const token = readRawParam("token"); if (!token) throw new Error(t("missing_token")); const method = options.method || "GET"; const headers = authHeadersFromToken(token); const request = { method, cache: "no-store", headers }; if (options.body) { 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; } async function loadMessages(lang) { return fallbackMessages[normalizeLanguage(lang)] || fallbackMessages.en; } function renderMessages(messages) { document.querySelectorAll("[data-i18n]").forEach((node) => { const value = messages[node.dataset.i18n]; if (value) node.textContent = value; }); document.querySelectorAll("[data-i18n-aria]").forEach((node) => { const value = messages[node.dataset.i18nAria]; if (value) node.setAttribute("aria-label", value); }); document.querySelectorAll("[data-i18n-placeholder]").forEach((node) => { const value = messages[node.dataset.i18nPlaceholder]; if (value) node.setAttribute("placeholder", value); }); } 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 || "Join Agency"; renderMessages(messages); renderLanguageControls(messages); renderFoundAgency(foundAgency); renderPendingRecord(pendingRecord); } function showMessage(message, type = "") { const node = document.querySelector("#statusMessage"); if (!node) return; node.textContent = message || ""; node.hidden = !message; node.classList.toggle("is-error", type === "error"); node.classList.toggle("is-success", type === "success"); } function pickProfile(body) { return body?.ownUserProfile || body?.userProfile || body?.teamProfile || body || null; } function pickSpecialAccount(profile) { return profile?.ownSpecialId?.account || profile?.specialId?.account || profile?.specialAccount || profile?.shortAccount || profile?.shortId || ""; } 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 pickName(profile) { return profile?.userNickname || profile?.name || profile?.teamName || "-"; } function pickAccount(profile) { return pickSpecialAccount(profile) || profile?.displayAccount || profile?.account || profile?.id || "-"; } function initials(name) { const value = String(name || "A").trim(); return value ? value.slice(0, 1).toUpperCase() : "A"; } function renderAvatar(profile, imageSelector, fallbackSelector) { const image = document.querySelector(imageSelector); const fallback = document.querySelector(fallbackSelector); if (!image || !fallback) return; const name = pickName(profile); const avatar = profile?.userAvatar || profile?.avatar || ""; fallback.textContent = initials(name); 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 syncApplyAvailability() { const button = document.querySelector("#applyButton"); if (button) button.hidden = Boolean(pendingRecord); } function renderFoundAgency(profile) { const card = document.querySelector("#resultCard"); if (!card) return; if (!profile) { card.hidden = true; syncApplyAvailability(); return; } card.hidden = false; document.querySelector("#agencyName").textContent = pickName(profile); document.querySelector("#agencyAccountText").textContent = `${t("uid_prefix")} ${pickAccount(profile)}`.trim(); renderAvatar(profile, "#agencyAvatar", "#agencyAvatarFallback"); syncApplyAvailability(); } function renderPendingRecord(record) { const card = document.querySelector("#pendingCard"); if (!card) return; if (!record) { card.hidden = true; syncApplyAvailability(); return; } const profile = pickProfile(record); card.hidden = false; document.querySelector("#pendingName").textContent = pickName(profile); document.querySelector("#pendingAccount").textContent = `${t("uid_prefix")} ${pickAccount(profile)}`.trim(); renderAvatar(profile, "#pendingAvatar", "#pendingAvatarFallback"); syncApplyAvailability(); } function errorMessage(error, fallbackKey) { return error?.response?.errorMsg || error?.response?.message || error?.message || t(fallbackKey); } async function searchAgency() { const input = document.querySelector("#agencyAccount"); const button = document.querySelector("#searchButton"); const account = input?.value.trim() || ""; if (!account) { showMessage(t("enter_agent_id"), "error"); return; } button.disabled = true; button.textContent = t("searching"); showMessage(""); try { const body = await apiRequest(`/team/search-account?account=${encodeURIComponent(account)}`); const profile = pickSearchAgency(body); if (!profile?.id) { foundAgency = null; renderFoundAgency(null); showMessage(t("account_not_found"), "error"); return; } foundAgency = profile; renderFoundAgency(foundAgency); showMessage(t("found"), "success"); } catch (error) { foundAgency = null; renderFoundAgency(null); showMessage(errorMessage(error, "network_error"), "error"); } finally { button.disabled = false; button.textContent = t("search"); } } async function fetchPendingRecord() { try { pendingRecord = await apiRequest("/team/wait-apply/profile"); renderPendingRecord(pendingRecord); } catch (error) { pendingRecord = null; renderPendingRecord(null); if (error.message === t("missing_token")) showMessage(error.message, "error"); } } async function applyToAgency() { if (pendingRecord) return; if (!foundAgency?.id) return; const button = document.querySelector("#applyButton"); button.disabled = true; button.textContent = t("applying"); showMessage(""); try { await apiRequest("/team/user/apply", { method: "POST", body: { teamId: foundAgency.id, reason: "JOIN" } }); foundAgency = null; renderFoundAgency(null); showMessage(t("application_submitted"), "success"); await fetchPendingRecord(); } catch (error) { showMessage(errorMessage(error, "application_failed"), "error"); } finally { button.disabled = false; button.textContent = t("apply"); } } async function cancelApplication() { const id = pendingRecord?.messageId || pendingRecord?.id; if (!id) return; const button = document.querySelector("#cancelButton"); button.disabled = true; button.textContent = t("cancelling"); showMessage(""); try { await apiRequest("/team/user/join-apply-cancel", { method: "POST", body: { id } }); pendingRecord = null; renderPendingRecord(null); showMessage(t("application_cancelled"), "success"); } catch (error) { showMessage(errorMessage(error, "cancellation_failed"), "error"); } finally { button.disabled = false; button.textContent = t("cancel"); } } function buildPageURL(path) { const url = new URL(path, window.location.href); const nextParams = new URLSearchParams(params); const token = readRawParam("token"); if (token) nextParams.set("token", token); if (currentLang) nextParams.set("lang", currentLang); url.search = nextParams.toString(); return url.toString(); } 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", () => { if (window.history.length > 1) { window.history.back(); return; } window.location.href = buildPageURL("../host-center/index.html"); }); document.querySelector("#searchForm")?.addEventListener("submit", (event) => { event.preventDefault(); searchAgency(); }); document.querySelector("#applyButton")?.addEventListener("click", applyToAgency); document.querySelector("#cancelButton")?.addEventListener("click", cancelApplication); applyLanguage(currentLang).then(fetchPendingRecord); })();