(function () { var AGENCY_SALARY_USD = 'AGENCY_SALARY_USD'; var HOST_SALARY_USD = 'HOST_SALARY_USD'; var mock = { profile: { name: 'Yumi Star Agency', shortId: '163003', avatar: avatarData('A', '#dbc8ff', '#7d57c7'), bd: { name: 'Mila BD', shortId: '880001', avatar: avatarData('M', '#efe4ff', '#7d57c7'), }, }, metrics: { salary: 12880.75, }, hosts: [ { id: '163000', name: 'quick_1780052629537', avatar: avatarData('Q', '#dbc8ff', '#7d57c7'), workTime: 86, gift: 2450, salary: 3050.25, }, { id: '163011', name: 'Lina_voice', avatar: avatarData('L', '#f4ebff', '#7d57c7'), workTime: 124, gift: 3760, salary: 4280.5, }, { id: '163024', name: 'Nora_live', avatar: avatarData('N', '#efe4ff', '#7d57c7'), workTime: 98, gift: 2990, salary: 2298, }, ], bills: [ { month: '2026-06', hostSalary: 8420.2, agencySalary: 3260.55, total: 11680.75, status: 'In progress', }, { month: '2026-05', hostSalary: 13240, agencySalary: 5140.8, total: 18380.8, status: 'Completed', }, ], messages: [ { id: 'apply-1001', applicationId: '1001', name: 'Mona_host', account: '163088', avatar: avatarData('M', '#dbc8ff', '#7d57c7'), }, { id: 'apply-1002', applicationId: '1002', name: 'Sara_room', account: '163099', avatar: avatarData('S', '#f4ebff', '#7d57c7'), }, ], }; var state = { hosts: mock.hosts.slice(), messages: mock.messages.slice(), hostSearch: '', pendingRemoveHost: null, profile: mock.profile, salary: mock.metrics.salary, loading: false, isMock: shouldUseMock(), }; function $(id) { return document.getElementById(id); } function shouldUseMock() { var params = new URLSearchParams(window.location.search); return params.get('mock') === '1' || params.get('mock') === 'true'; } function avatarData(text, background, foreground) { var letter = encodeURIComponent(String(text || 'A').charAt(0)); var svg = '' + '' + '' + letter + '' + ''; return 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg); } function t(key, fallback) { return window.HyAppI18n && window.HyAppI18n.t ? window.HyAppI18n.t(key, fallback) : fallback || key; } function toast(message) { if (window.HyAppToast) { window.HyAppToast.show(message); return; } window.alert(message); } function formatMoney(value) { var number = Number(value || 0); return number.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2, }); } function formatCount(value) { var number = Number(value || 0); return number.toLocaleString('en-US', { maximumFractionDigits: 2, }); } function toNumber(value) { var number = Number(value || 0); return Number.isFinite(number) ? number : 0; } function commandID(prefix) { return ( prefix + '-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2, 8) ); } function salaryDisplayAmount(salary, assetType) { if (!salary) return 0; if ( salary.display_amount !== undefined && salary.display_amount !== null ) { return toNumber(salary.display_amount); } if (assetType === AGENCY_SALARY_USD || assetType === HOST_SALARY_USD) { return toNumber(salary.available_amount) / 100; } return toNumber(salary.available_amount); } function initial(text) { return String(text || '') .trim() .charAt(0) .toUpperCase(); } function setImage(image, fallback, src, name) { if (!image || !fallback) return; fallback.textContent = initial(name) || 'A'; if (!src) { image.hidden = true; fallback.hidden = false; return; } image.onload = function () { image.hidden = false; fallback.hidden = true; }; image.onerror = function () { image.hidden = true; fallback.hidden = false; }; image.src = src; } function makeAvatar(item) { var avatar = document.createElement('div'); var fallback = document.createElement('span'); avatar.className = 'small-avatar'; fallback.textContent = initial(item.name) || 'A'; avatar.appendChild(fallback); if (item.avatar) { var image = document.createElement('img'); image.src = item.avatar; image.alt = ''; image.addEventListener('error', function () { image.remove(); }); avatar.appendChild(image); } return avatar; } function hasRealAPI() { return !state.isMock && window.HyAppAPI && window.HyAppAPI.agencyCenter; } function displayName(user, fallback) { if (!user) return fallback || '-'; return ( user.username || user.display_user_id || user.user_id || fallback || '-' ); } function normalizeOverview(payload) { var agency = payload && payload.agency ? payload.agency : {}; var bd = payload && payload.bd ? payload.bd : null; state.profile = { name: agency.name || mock.profile.name, shortId: agency.agency_id || mock.profile.shortId, avatar: agency.avatar || '', bd: bd ? { name: displayName(bd, ''), shortId: bd.display_user_id || bd.user_id || '', avatar: bd.avatar || '', } : null, }; state.salary = salaryDisplayAmount( payload ? payload.salary : null, AGENCY_SALARY_USD ); } function normalizeHost(item) { var userId = String(item.host_user_id || item.user_id || item.id || ''); var displayId = String(item.display_user_id || userId); return { id: displayId, userId: userId, name: item.username || displayId || userId || '-', avatar: item.avatar || '', salary: salaryDisplayAmount(item.salary, HOST_SALARY_USD), }; } function normalizeMessage(item) { var applicant = item.applicant || {}; var applicantUserId = String( item.applicant_user_id || applicant.user_id || '' ); return { id: String(item.application_id || item.id || ''), applicationId: String(item.application_id || item.id || ''), name: displayName(applicant, applicantUserId), account: applicant.display_user_id || applicantUserId, avatar: applicant.avatar || '', }; } function applyAgencyCenterPayload(overview, hosts, applications) { normalizeOverview(overview || {}); state.hosts = ((hosts && hosts.items) || []).map(normalizeHost); state.messages = ((applications && applications.items) || []).map( normalizeMessage ); } function loadAgencyCenter() { if (!hasRealAPI()) return Promise.resolve(); if (window.HyAppParams && window.HyAppParams.parse) { window.HyAppParams.parse(); } state.loading = true; return Promise.all([ window.HyAppAPI.agencyCenter.overview(), window.HyAppAPI.agencyCenter.hosts(), window.HyAppAPI.agencyCenter.applications('pending'), ]) .then(function (results) { applyAgencyCenterPayload(results[0], results[1], results[2]); render(); }) .catch(function () { toast( t( 'agency_center.load_failed', 'Load failed. Try again later.' ) ); }) .finally(function () { state.loading = false; }); } function renderProfile() { var profile = state.profile || mock.profile; var bd = profile.bd || null; var bdRow = $('bdRow'); $('agencyName').textContent = profile.name; $('agencyShortId').textContent = t( 'agency_center.agency_short_id', 'ID: {id}' ).replace('{id}', profile.shortId || '-'); if (bd && bd.shortId) { bdRow.hidden = false; $('bdShortId').textContent = bd.shortId; setImage($('bdAvatar'), $('bdAvatarFallback'), bd.avatar, bd.name); } else { bdRow.hidden = true; $('bdShortId').textContent = ''; } setImage( $('agencyAvatar'), $('agencyAvatarFallback'), profile.avatar, profile.name ); } function renderSalary() { $('currentSalary').textContent = formatMoney(state.salary); } function renderHostCount() { $('hostCount').textContent = formatCount(state.hosts.length); } function renderUnread() { var dot = $('messageUnreadDot'); if (dot) dot.hidden = state.messages.length <= 0; } function filteredHosts() { var keyword = state.hostSearch.trim(); if (!keyword) return state.hosts; return state.hosts.filter(function (host) { return ( host.id.indexOf(keyword) >= 0 || String(host.userId || '').indexOf(keyword) >= 0 || host.name.toLowerCase().indexOf(keyword.toLowerCase()) >= 0 ); }); } function renderHostList() { var list = $('hostList'); var empty = $('hostListEmpty'); var hosts = filteredHosts(); list.textContent = ''; empty.hidden = hosts.length > 0; empty.textContent = t('agency_center.no_hosts', 'No hosts'); hosts.forEach(function (host) { var row = document.createElement('div'); var user = document.createElement('div'); var copy = document.createElement('div'); var name = document.createElement('div'); var meta = document.createElement('div'); var remove = document.createElement('button'); row.className = 'host-row'; user.className = 'host-user'; copy.className = 'host-copy'; name.className = 'host-name'; meta.className = 'host-meta'; remove.className = 'remove-host-button'; remove.type = 'button'; name.textContent = host.name; meta.textContent = 'UID: ' + host.id + ' · ' + t('agency_center.salary', 'Salary') + ': ' + '$' + formatMoney(host.salary); remove.textContent = t('agency_center.remove', 'Remove'); remove.addEventListener('click', function () { state.pendingRemoveHost = host; renderRemoveConfirm(); openSheet('removeConfirmModal'); }); user.appendChild(makeAvatar(host)); copy.appendChild(name); copy.appendChild(meta); user.appendChild(copy); row.appendChild(user); row.appendChild(remove); list.appendChild(row); }); } function renderRemoveConfirm() { var host = state.pendingRemoveHost; var text = $('removeConfirmText'); if (!text) return; text.textContent = t( 'agency_center.remove_confirm_message', 'Confirm remove {name} from your agency?' ).replace('{name}', host ? host.name : '-'); } function confirmRemoveHost() { var host = state.pendingRemoveHost; if (!host) return; if (hasRealAPI()) { window.HyAppAPI.agencyCenter .removeHost(host.userId || host.id, { command_id: commandID('agency-remove-host'), reason: 'agency_center', }) .then(function () { state.pendingRemoveHost = null; closeSheet('removeConfirmModal'); toast(t('agency_center.host_removed', 'Host removed.')); return loadAgencyCenter(); }) .catch(function (error) { if (error && error.status === 409) return; toast( t( 'agency_center.remove_failed', 'Remove failed. Try again later.' ) ); }); return; } state.hosts = state.hosts.filter(function (item) { return item.id !== host.id; }); state.pendingRemoveHost = null; closeSheet('removeConfirmModal'); renderHostCount(); renderHostList(); toast(t('agency_center.host_removed', 'Host removed.')); } function createBillCell(label, value) { var cell = document.createElement('div'); var title = document.createElement('span'); var strong = document.createElement('strong'); cell.className = 'bill-cell'; title.textContent = label; strong.textContent = value; cell.appendChild(title); cell.appendChild(strong); return cell; } function renderBillList() { var list = $('billList'); list.textContent = ''; mock.bills.forEach(function (bill) { var row = document.createElement('div'); var month = document.createElement('div'); var values = document.createElement('div'); row.className = 'bill-row'; month.className = 'bill-month'; values.className = 'bill-values'; month.textContent = bill.month + ' · ' + bill.status; values.appendChild( createBillCell( t('agency_center.host_salary', 'Host salary'), formatMoney(bill.hostSalary) ) ); values.appendChild( createBillCell( t('agency_center.agency_salary', 'Agency salary'), formatMoney(bill.agencySalary) ) ); values.appendChild( createBillCell( t('agency_center.total', 'Total'), formatMoney(bill.total) ) ); row.appendChild(month); row.appendChild(values); list.appendChild(row); }); } function renderMessages() { var list = $('messageList'); var empty = $('messageEmpty'); list.textContent = ''; empty.hidden = state.messages.length > 0; empty.textContent = t('agency_center.no_messages', 'No messages'); state.messages.forEach(function (message) { var card = document.createElement('div'); var user = document.createElement('div'); var copy = document.createElement('div'); var name = document.createElement('div'); var id = document.createElement('div'); var actions = document.createElement('div'); var agree = document.createElement('button'); var refuse = document.createElement('button'); card.className = 'message-card'; user.className = 'message-user'; copy.className = 'message-copy'; name.className = 'message-name'; id.className = 'message-id'; actions.className = 'message-actions'; agree.className = 'message-action agree'; refuse.className = 'message-action refuse'; agree.type = 'button'; refuse.type = 'button'; name.textContent = message.name; id.textContent = 'ID: ' + message.account; agree.textContent = t('agency_center.agree', 'Agree'); refuse.textContent = t('agency_center.refuse', 'Refuse'); agree.addEventListener('click', function () { processMessage(message, 'agree'); }); refuse.addEventListener('click', function () { processMessage(message, 'refuse'); }); user.appendChild(makeAvatar(message)); copy.appendChild(name); copy.appendChild(id); user.appendChild(copy); actions.appendChild(agree); actions.appendChild(refuse); card.appendChild(user); card.appendChild(actions); list.appendChild(card); }); } function processMessage(message, action) { if (hasRealAPI()) { var decision = action === 'agree' ? 'approve' : 'reject'; window.HyAppAPI.agencyCenter .reviewApplication(message.applicationId || message.id, { command_id: commandID('agency-review-application'), decision: decision, reason: 'agency_center', }) .then(function () { var key = action === 'agree' ? 'agency_center.approved_application' : 'agency_center.rejected_application'; var fallback = action === 'agree' ? "Approved {name}'s application." : "Rejected {name}'s application."; toast(t(key, fallback).replace('{name}', message.name)); return loadAgencyCenter(); }) .catch(function (error) { if (error && error.status === 409) return; toast( t( 'agency_center.review_failed', 'Review failed. Try again later.' ) ); }); return; } state.messages = state.messages.filter(function (item) { return item.id !== message.id; }); renderUnread(); renderMessages(); var key = action === 'agree' ? 'agency_center.approved_application' : 'agency_center.rejected_application'; var fallback = action === 'agree' ? "Approved {name}'s application." : "Rejected {name}'s application."; toast(t(key, fallback).replace('{name}', message.name)); } function openSheet(id) { var sheet = $(id); if (!sheet) return; sheet.hidden = false; sheet.setAttribute('aria-hidden', 'false'); document.body.classList.add('modal-open'); } function closeSheet(id) { var sheet = $(id); if (!sheet) return; sheet.hidden = true; sheet.setAttribute('aria-hidden', 'true'); var hasOpen = Array.prototype.some.call( document.querySelectorAll( '.sheet-modal, .message-modal, .confirm-modal' ), function (modal) { return !modal.hidden; } ); document.body.classList.toggle('modal-open', hasOpen); } function closeAllSheets() { document .querySelectorAll('.sheet-modal, .message-modal, .confirm-modal') .forEach(function (sheet) { sheet.hidden = true; sheet.setAttribute('aria-hidden', 'true'); }); state.pendingRemoveHost = null; document.body.classList.remove('modal-open'); } function navigateToWithdrawExchange() { var params = new URLSearchParams(window.location.search); if (!params.has('mode')) params.set('mode', 'transfer'); window.location.href = '../withdraw-exchange/index.html?' + params.toString(); } function bindEvents() { $('backButton').addEventListener('click', function () { if (window.HyAppBridge) window.HyAppBridge.back(); }); $('messageButton').addEventListener('click', function () { renderMessages(); openSheet('messageModal'); }); $('withdrawExchangeButton').addEventListener( 'click', navigateToWithdrawExchange ); $('salaryValueButton').addEventListener( 'click', navigateToWithdrawExchange ); $('hostSearchForm').addEventListener('submit', function (event) { event.preventDefault(); state.hostSearch = $('hostSearchInput').value || ''; renderHostList(); }); $('confirmRemoveButton').addEventListener('click', confirmRemoveHost); document .querySelectorAll('[data-close-sheet]') .forEach(function (node) { node.addEventListener('click', function () { if ( node.getAttribute('data-close-sheet') === 'removeConfirmModal' ) { state.pendingRemoveHost = null; } closeSheet(node.getAttribute('data-close-sheet')); }); }); document.querySelectorAll('.menu-row').forEach(function (button) { button.addEventListener('click', function () { var action = button.getAttribute('data-action'); if (action === 'host-list') { state.hostSearch = ''; $('hostSearchInput').value = ''; renderHostList(); openSheet('hostSheet'); return; } if (action === 'team-bill') { renderBillList(); openSheet('billSheet'); return; } if (action === 'invite') { openSheet('inviteSheet'); return; } toast( t( 'agency_center.mock_navigation', 'Mock navigation: {label}' ).replace( '{label}', t('agency_center.agency_policy', 'Agency Policy') ) ); }); }); document.addEventListener('keydown', function (event) { if (event.key === 'Escape') closeAllSheets(); }); } function render() { renderProfile(); renderSalary(); renderHostCount(); renderUnread(); renderHostList(); renderBillList(); renderMessages(); } function initPage() { render(); bindEvents(); loadAgencyCenter(); if (window.HyAppBridge) { window.HyAppBridge.ready({ page: 'agency-center', mock: state.isMock, }); } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initPage); } else { initPage(); } window.addEventListener('hyapp:i18n-ready', function () { render(); }); })();