feat: join agency in host center modal

This commit is contained in:
170-carry 2026-04-28 22:28:40 +08:00
parent b32628de5c
commit 72031c5b08
3 changed files with 702 additions and 40 deletions

View File

@ -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>&times;</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>

View File

@ -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");

View File

@ -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;