feat: join agency in host center modal
This commit is contained in:
parent
b32628de5c
commit
72031c5b08
@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
||||
<title>Host Center</title>
|
||||
<link rel="stylesheet" href="./style.css?v=20260428-2085" />
|
||||
<link rel="stylesheet" href="./style.css?v=20260428-2110" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="host-center" aria-label="Host Center" data-i18n-aria="page_label" data-loading="true" data-view="loading">
|
||||
@ -56,7 +56,7 @@
|
||||
<div class="join-agency-title" data-i18n="join_agency_title">Join Agency</div>
|
||||
<div class="join-agency-text" data-i18n="join_agency_text">Search for an agency ID and submit your application.</div>
|
||||
</div>
|
||||
<a class="join-agency-action" id="joinAgencyLink" href="../join-agency/index.html" data-i18n="join_agency_action">Join now</a>
|
||||
<button class="join-agency-action" id="joinAgencyButton" type="button" data-i18n="join_agency_action">Join now</button>
|
||||
</section>
|
||||
|
||||
<section class="card metrics-card host-only">
|
||||
@ -124,6 +124,62 @@
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="join-agency-modal" id="joinAgencyModal" hidden>
|
||||
<div class="join-agency-backdrop" data-close-join-agency></div>
|
||||
<section class="join-agency-dialog" role="dialog" aria-modal="true" aria-labelledby="joinAgencyModalTitle">
|
||||
<div class="join-agency-head">
|
||||
<h2 id="joinAgencyModalTitle" data-i18n="join_agency_title">Join Agency</h2>
|
||||
<button class="join-agency-close" type="button" aria-label="Close" data-i18n-aria="close" data-close-join-agency>×</button>
|
||||
</div>
|
||||
<div class="join-agency-modal-body">
|
||||
<form class="join-agency-search-form" id="joinAgencySearchForm">
|
||||
<label class="join-agency-field">
|
||||
<span data-i18n="agency_id">Agency ID</span>
|
||||
<div class="join-agency-search-control">
|
||||
<input id="joinAgencyAccount" type="text" inputmode="numeric" autocomplete="off" placeholder="Enter agency ID" data-i18n-placeholder="enter_agent_id" />
|
||||
<button class="join-agency-search-button" id="joinAgencySearchButton" type="submit" data-i18n="search">Search</button>
|
||||
</div>
|
||||
</label>
|
||||
</form>
|
||||
|
||||
<div class="join-agency-status" id="joinAgencyStatus" role="status" hidden></div>
|
||||
|
||||
<section class="join-agency-modal-card" id="joinAgencyResult" hidden>
|
||||
<div class="join-agency-section-title" data-i18n="agency_label">Agency</div>
|
||||
<div class="join-agency-profile-row">
|
||||
<div class="join-agency-avatar">
|
||||
<img id="joinAgencyAvatar" alt="" hidden />
|
||||
<span id="joinAgencyAvatarFallback">A</span>
|
||||
</div>
|
||||
<div class="join-agency-profile-copy">
|
||||
<div class="join-agency-profile-name" id="joinAgencyName">-</div>
|
||||
<div class="join-agency-profile-account" id="joinAgencyAccountText">UID: -</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="join-agency-apply-button" id="joinAgencyApplyButton" type="button" data-i18n="apply">Apply</button>
|
||||
</section>
|
||||
|
||||
<section class="join-agency-modal-card join-agency-pending-card" id="joinAgencyPending" hidden>
|
||||
<div class="join-agency-pending-head">
|
||||
<div class="join-agency-section-title" data-i18n="application_records">Application Records</div>
|
||||
<span data-i18n="pending">Pending</span>
|
||||
</div>
|
||||
<div class="join-agency-profile-row">
|
||||
<div class="join-agency-avatar">
|
||||
<img id="joinAgencyPendingAvatar" alt="" hidden />
|
||||
<span id="joinAgencyPendingAvatarFallback">A</span>
|
||||
</div>
|
||||
<div class="join-agency-profile-copy">
|
||||
<div class="join-agency-profile-name" id="joinAgencyPendingName">-</div>
|
||||
<div class="join-agency-profile-account" id="joinAgencyPendingAccount">UID: -</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="join-agency-pending-note" data-i18n="join_pending_note">Application is pending. Please wait for agency approval.</p>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="home-indicator" aria-hidden="true"></div>
|
||||
<div class="loading-mask" id="loadingMask" role="status" aria-live="polite" aria-busy="true">
|
||||
<div class="runner-stick" aria-hidden="true">
|
||||
@ -138,6 +194,6 @@
|
||||
<div class="loading-copy">loading....</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="./script.js?v=20260428-2070" defer></script>
|
||||
<script src="./script.js?v=20260428-2110" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -29,6 +29,22 @@
|
||||
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.",
|
||||
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",
|
||||
@ -65,6 +81,22 @@
|
||||
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: "الطلب قيد الانتظار. يرجى انتظار موافقة الوكالة.",
|
||||
missing_token: "رمز الدخول مفقود",
|
||||
network_error: "خطأ في الشبكة. حاول مرة أخرى.",
|
||||
withdraw_exchange: "سحب/استبدال",
|
||||
open_withdraw_exchange: "فتح صفحة السحب والاستبدال",
|
||||
open_anchor_policy: "فتح سياسة المضيف",
|
||||
@ -101,6 +133,22 @@
|
||||
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.",
|
||||
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ç",
|
||||
@ -137,6 +185,22 @@
|
||||
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.",
|
||||
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",
|
||||
@ -166,6 +230,8 @@
|
||||
let currentStreamingDuration = "0";
|
||||
let currentGiftValue = "0";
|
||||
let currentDailyTargets = [];
|
||||
let foundJoinAgency = null;
|
||||
let pendingJoinRecord = null;
|
||||
|
||||
function readURLParams() {
|
||||
const result = new URLSearchParams(window.location.search);
|
||||
@ -223,21 +289,34 @@
|
||||
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 = messages[node.dataset.i18n];
|
||||
const value = localizedValue(messages, node.dataset.i18n);
|
||||
if (value) node.textContent = value;
|
||||
});
|
||||
|
||||
document.querySelectorAll("[data-i18n-html]").forEach((node) => {
|
||||
const value = messages[node.dataset.i18nHtml];
|
||||
const value = localizedValue(messages, node.dataset.i18nHtml);
|
||||
if (value) node.innerHTML = value;
|
||||
});
|
||||
|
||||
document.querySelectorAll("[data-i18n-aria]").forEach((node) => {
|
||||
const value = messages[node.dataset.i18nAria];
|
||||
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() {
|
||||
@ -264,6 +343,33 @@
|
||||
};
|
||||
}
|
||||
|
||||
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";
|
||||
@ -313,6 +419,54 @@
|
||||
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 || "";
|
||||
}
|
||||
@ -443,22 +597,6 @@
|
||||
|
||||
const agencyButton = document.querySelector(".agency");
|
||||
if (agencyButton) agencyButton.hidden = showJoinAgency;
|
||||
|
||||
syncJoinAgencyLink();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
function openJoinAgencyPage() {
|
||||
window.location.replace(buildPageURL("../join-agency/index.html"));
|
||||
}
|
||||
|
||||
function closeHostCenterPage() {
|
||||
@ -604,6 +742,11 @@
|
||||
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));
|
||||
@ -615,10 +758,204 @@
|
||||
const modal = document.querySelector("#dailyModal");
|
||||
if (!modal) return;
|
||||
modal.hidden = !open;
|
||||
document.body.classList.toggle("daily-modal-open", 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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -806,21 +1143,6 @@
|
||||
document.querySelectorAll('a[href^="../withdraw-exchange/index.html"]').forEach((link) => {
|
||||
link.setAttribute("href", `../withdraw-exchange/index.html${query ? `?${query}` : ""}`);
|
||||
});
|
||||
|
||||
syncJoinAgencyLink();
|
||||
}
|
||||
|
||||
function syncJoinAgencyLink() {
|
||||
const link = document.querySelector("#joinAgencyLink");
|
||||
if (!link) return;
|
||||
|
||||
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();
|
||||
link.setAttribute("href", `../join-agency/index.html${query ? `?${query}` : ""}`);
|
||||
}
|
||||
|
||||
function syncPolicyLink() {
|
||||
@ -876,6 +1198,8 @@
|
||||
renderProfile(currentProfile, messages);
|
||||
renderAgencyProfile(currentAgencyProfile, messages);
|
||||
renderDailyTargets();
|
||||
renderFoundJoinAgency(foundJoinAgency);
|
||||
renderPendingJoinRecord(pendingJoinRecord);
|
||||
}
|
||||
|
||||
document.querySelector(".language-button")?.addEventListener("click", (event) => {
|
||||
@ -901,7 +1225,23 @@
|
||||
});
|
||||
|
||||
document.querySelector(".agency")?.addEventListener("click", () => {
|
||||
if (currentIdentity && shouldOpenJoinAgency(currentIdentity)) openJoinAgencyPage();
|
||||
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.querySelectorAll("[data-close-join-agency]").forEach((node) => {
|
||||
node.addEventListener("click", () => {
|
||||
setJoinAgencyModalOpen(false);
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelector(".gift-value")?.addEventListener("click", () => {
|
||||
@ -915,7 +1255,10 @@
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Escape") setDailyModalOpen(false);
|
||||
if (event.key === "Escape") {
|
||||
setDailyModalOpen(false);
|
||||
setJoinAgencyModalOpen(false);
|
||||
}
|
||||
});
|
||||
|
||||
ensureAvatarFallback("Oscar");
|
||||
|
||||
@ -1098,6 +1098,254 @@ a {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.join-agency-modal[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.join-agency-modal {
|
||||
position: fixed;
|
||||
z-index: 24;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
.join-agency-backdrop {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(15, 21, 28, 0.38);
|
||||
}
|
||||
|
||||
.join-agency-dialog {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: min(394px, 100%);
|
||||
max-height: 78vh;
|
||||
max-height: 78dvh;
|
||||
overflow: hidden;
|
||||
border-radius: 14px;
|
||||
background: #fff;
|
||||
box-shadow: 0 18px 44px rgba(23, 31, 42, 0.2);
|
||||
}
|
||||
|
||||
.join-agency-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
min-height: 58px;
|
||||
padding: 16px 18px 12px;
|
||||
border-bottom: 1px solid #eef0f2;
|
||||
}
|
||||
|
||||
.join-agency-head h2 {
|
||||
margin: 0;
|
||||
color: #24282e;
|
||||
font-size: 18px;
|
||||
font-weight: 950;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.join-agency-close {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border-radius: 50%;
|
||||
background: #f4f6f7;
|
||||
color: #50545b;
|
||||
font-size: 25px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.join-agency-modal-body {
|
||||
display: grid;
|
||||
flex: 1 1 auto;
|
||||
gap: 12px;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
padding: 16px 18px max(18px, env(safe-area-inset-bottom));
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.join-agency-field {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.join-agency-field > span,
|
||||
.join-agency-section-title {
|
||||
color: #24282e;
|
||||
font-size: 16px;
|
||||
font-weight: 900;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.join-agency-search-control {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.join-agency-search-control input {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
min-width: 0;
|
||||
border: 1px solid #eef0f2;
|
||||
border-radius: 8px;
|
||||
outline: none;
|
||||
background: #f8fafa;
|
||||
color: #25282e;
|
||||
font: inherit;
|
||||
font-size: 15px;
|
||||
font-weight: 750;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.join-agency-search-control input::placeholder {
|
||||
color: #b3b5ba;
|
||||
}
|
||||
|
||||
.join-agency-search-button,
|
||||
.join-agency-apply-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 44px;
|
||||
border-radius: 8px;
|
||||
font-size: 15px;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.join-agency-search-button {
|
||||
min-width: 86px;
|
||||
padding: 0 16px;
|
||||
background: #31d9cb;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.join-agency-search-button:disabled,
|
||||
.join-agency-apply-button:disabled {
|
||||
opacity: 0.58;
|
||||
}
|
||||
|
||||
.join-agency-status {
|
||||
min-height: 38px;
|
||||
border-radius: 8px;
|
||||
padding: 10px 12px;
|
||||
background: #f8fafa;
|
||||
color: #8b8d92;
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.join-agency-status.is-error {
|
||||
color: #d64f4f;
|
||||
}
|
||||
|
||||
.join-agency-status.is-success {
|
||||
color: #0d988d;
|
||||
}
|
||||
|
||||
.join-agency-modal-card {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
padding: 14px;
|
||||
border: 1px solid #eef0f2;
|
||||
border-radius: 8px;
|
||||
background: #fbfcfc;
|
||||
}
|
||||
|
||||
.join-agency-profile-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.join-agency-avatar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
flex: 0 0 56px;
|
||||
overflow: hidden;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(145deg, #d7fff9, #45e7d8);
|
||||
color: #0c5f58;
|
||||
font-size: 21px;
|
||||
font-weight: 950;
|
||||
}
|
||||
|
||||
.join-agency-avatar img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.join-agency-profile-copy {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.join-agency-profile-name {
|
||||
overflow: hidden;
|
||||
color: #25282e;
|
||||
font-size: 18px;
|
||||
font-weight: 900;
|
||||
line-height: 1.2;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.join-agency-profile-account {
|
||||
margin-top: 6px;
|
||||
overflow: hidden;
|
||||
color: #8b8d92;
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
line-height: 1.2;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.join-agency-apply-button {
|
||||
width: 100%;
|
||||
background: linear-gradient(135deg, #35dfd2 0%, #18bfb4 100%);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.join-agency-pending-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.join-agency-pending-head span {
|
||||
flex: 0 0 auto;
|
||||
color: #f2a329;
|
||||
font-size: 13px;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.join-agency-pending-note {
|
||||
margin: 0;
|
||||
color: #8b8d92;
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.daily-modal-open {
|
||||
overflow: hidden;
|
||||
}
|
||||
@ -1163,6 +1411,21 @@ a {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
[dir="rtl"] .join-agency-profile-copy,
|
||||
[dir="rtl"] .join-agency-field {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@media (max-width: 360px) {
|
||||
.join-agency-search-control {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.join-agency-search-button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 360px) {
|
||||
.status-bar {
|
||||
padding-right: 22px;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user