(function () { var query = new URLSearchParams(window.location.search); var state = { activeTab: 'bd', inviteMode: 'bd', inviteQuery: '', inviteStatus: '', inviteStatusType: '', inviteSearchResults: [], inviteSubmitting: {}, selectedDetails: null, isMock: query.get('mock') === '1', }; var mock = { profile: { name: 'Admin Sophia', uid: 'SA-100001', avatar: avatarData('S', '#dbc8ff', '#7d57c7'), }, balance: { available: 168250.5, }, overview: { totalBD: 8, totalAgency: 36, totalHosts: 428, teamSalary: 586420.8, teamRecharge: 1268800, }, bdList: [ { id: '880001', userId: '3200901', name: 'Mila BD', avatar: avatarData('M', '#dbc8ff', '#7d57c7'), agencies: 12, hosts: 126, salary: 128450.35, recharge: 356900, }, { id: '880018', userId: '3200918', name: 'Jasmine BD', avatar: avatarData('J', '#f4ebff', '#7d57c7'), agencies: 9, hosts: 104, salary: 106280.4, recharge: 298520, }, { id: '880026', userId: '3200926', name: 'Omar BD', avatar: avatarData('O', '#efe4ff', '#7d57c7'), agencies: 7, hosts: 82, salary: 86140, recharge: 214330, }, ], agencyList: [ { id: '163003', userId: '3200801', name: 'Yumi Star Agency', avatar: avatarData('Y', '#dbc8ff', '#7d57c7'), bdId: '880001', hosts: 28, salary: 38420.55, recharge: 126880, }, { id: '163086', userId: '3200802', name: 'Moon Live Agency', avatar: avatarData('M', '#f4ebff', '#7d57c7'), bdId: '880018', hosts: 19, salary: 29106.2, recharge: 98540, }, { id: '163221', userId: '3200803', name: 'Nova Host Guild', avatar: avatarData('N', '#efe4ff', '#7d57c7'), bdId: '880026', hosts: 16, salary: 22450, recharge: 73150, }, ], history: [ { month: '2026-06', status: 'In progress', bdCount: 8, agencyCount: 36, totalSalary: 586420.8, totalRecharge: 1268800, }, { month: '2026-05', status: 'Completed', bdCount: 7, agencyCount: 31, totalSalary: 520180.25, totalRecharge: 1112900, }, { month: '2026-04', status: 'Completed', bdCount: 6, agencyCount: 26, totalSalary: 462300, totalRecharge: 980400, }, ], inviteRecords: { bd: [ { id: 'bd-inv-01', status: 'Success', profile: { userId: '3200901', id: '3200901', name: 'BD_River', account: '880099', avatar: avatarData('R', '#dbc8ff', '#7d57c7'), }, }, ], agent: [ { id: 'agent-inv-01', status: 'Success', profile: { userId: '3200801', id: '3200801', name: 'Agent_Lina', account: '168801', avatar: avatarData('L', '#f4ebff', '#7d57c7'), }, }, ], }, searchPool: { bd: [ { userId: '3200902', id: '3200902', name: 'BD_Kai', account: '880102', avatar: avatarData('K', '#dbc8ff', '#7d57c7'), }, { userId: '3200903', id: '3200903', name: 'BD_Ayla', account: '880103', avatar: avatarData('A', '#efe4ff', '#7d57c7'), }, ], agent: [ { userId: '3200802', id: '3200802', name: 'Agent_Omar', account: '168802', avatar: avatarData('O', '#dbc8ff', '#7d57c7'), }, { userId: '3200803', id: '3200803', name: 'Agent_Sara', account: '168803', avatar: avatarData('S', '#efe4ff', '#7d57c7'), }, ], }, }; var data = { profile: mock.profile, balance: mock.balance, overview: mock.overview, bdList: mock.bdList, agencyList: mock.agencyList, history: mock.history, inviteRecords: mock.inviteRecords, }; function $(id) { return document.getElementById(id); } function avatarData(text, background, foreground) { var value = String(text || 'S') .trim() .charAt(0) || 'S'; var letter = value.replace(/[<>&"']/g, ''); 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 money(value) { return Number(value || 0).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2, }); } function compactMoney(value) { var amount = Number(value || 0); var abs = Math.abs(amount); if (abs >= 1000000) { return ( (amount / 1000000).toLocaleString('en-US', { minimumFractionDigits: 0, maximumFractionDigits: 2, }) + 'M' ); } if (abs >= 1000) { return ( (amount / 1000).toLocaleString('en-US', { minimumFractionDigits: 0, maximumFractionDigits: 2, }) + 'K' ); } return money(amount); } function count(value) { return Number(value || 0).toLocaleString('en-US', { maximumFractionDigits: 0, }); } function initial(text) { return String(text || '') .trim() .charAt(0) .toUpperCase(); } function displayName(user, fallback) { return ( (user && (user.username || user.name || user.display_user_id)) || fallback || '-' ); } function displayID(user) { return ( (user && (user.display_user_id || user.displayUserID)) || (user && (user.user_id || user.userId)) || '-' ); } function displayAmount(salary) { if (!salary) return 0; if (salary.display_amount !== undefined) return salary.display_amount; if (salary.displayAmount !== undefined) return salary.displayAmount; return Number(salary.available_amount || salary.availableAmount || 0) / 100; } function toast(message) { if (!message) return; if (window.HyAppToast && window.HyAppToast.show) { window.HyAppToast.show(message); return; } window.alert(message); } function setImage(image, fallback, src, name) { if (!image || !fallback) return; fallback.textContent = initial(name) || 'S'; 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 = 'member-avatar'; fallback.className = 'member-fallback'; fallback.textContent = initial(item.name) || 'S'; avatar.appendChild(fallback); if (item.avatar) { var image = document.createElement('img'); image.src = item.avatar; image.alt = ''; image.addEventListener('load', function () { fallback.hidden = true; }); image.addEventListener('error', function () { image.remove(); fallback.hidden = false; }); avatar.appendChild(image); } return avatar; } function replaceChildren(node, children) { node.textContent = ''; children.forEach(function (child) { node.appendChild(child); }); } function applyMockData() { data.profile = mock.profile; data.balance = mock.balance; data.overview = mock.overview; data.bdList = mock.bdList; data.agencyList = mock.agencyList; data.history = mock.history; data.inviteRecords = mock.inviteRecords; } function applyEmptyData() { data.profile = { name: '-', uid: '-', avatar: '' }; data.balance = { available: 0 }; data.overview = { totalBD: 0, totalAgency: 0, totalHosts: 0, teamSalary: 0, teamRecharge: 0, }; data.bdList = []; data.agencyList = []; data.history = []; data.inviteRecords = { bd: [], agent: [] }; } function normalizeOverview(payload) { var overview = payload && payload.overview ? payload.overview : {}; return { totalBD: overview.total_bd || overview.totalBD || 0, totalAgency: overview.total_agency || overview.totalAgency || 0, totalHosts: overview.total_hosts || overview.totalHosts || 0, teamSalary: overview.team_salary || overview.teamSalary || 0, teamRecharge: overview.team_recharge || overview.teamRecharge || 0, }; } function normalizeBDItem(item) { var name = displayName(item, 'BD ' + displayID(item)); return { id: displayID(item), userId: item.user_id || item.userId || '', name: name, avatar: item.avatar || '', agencies: item.agency_count || item.agencies || 0, hosts: item.host_count || item.hosts || 0, salary: item.salary === undefined ? null : item.salary, recharge: item.recharge === undefined ? null : item.recharge, sideValue: count(item.agency_count || item.agencies || 0) + ' ' + t('superadmin_center.agencies', 'Agencies'), sideSub: '', }; } function normalizeAgencyItem(item) { var agency = (item && item.agency) || item || {}; var owner = (item && item.owner) || {}; var parentBD = (item && item.parent_bd) || {}; var parentBDID = parentBD.display_user_id || parentBD.displayUserID || parentBD.user_id || parentBD.userId || agency.parent_bd_user_id || agency.parentBdUserId || ''; var name = agency.name || displayName(owner, 'Agency ' + (agency.agency_id || agency.id || '-')); return { id: agency.agency_id || agency.id || '-', userId: owner.user_id || owner.userId || agency.owner_user_id || '', name: name, avatar: owner.avatar || '', bdId: parentBDID || '-', hosts: item.host_count || agency.active_host_count || 0, salary: item.salary === undefined ? null : item.salary, recharge: item.recharge === undefined ? null : item.recharge, sideValue: count(item.host_count || agency.active_host_count || 0) + ' ' + t('superadmin_center.hosts', 'Hosts'), sideSub: parentBDID ? 'BD: ' + parentBDID : '', }; } function normalizeInviteProfile(payload) { var user = payload && (payload.user || payload.profile || payload); if (!user || !(user.user_id || user.userId)) return null; var id = displayID(user); return { userId: user.user_id || user.userId, id: user.user_id || user.userId, name: displayName(user, 'User ' + id), account: id, avatar: user.avatar || '', }; } function commandID(prefix, targetUserID) { return [ prefix, targetUserID, Date.now(), Math.random().toString(16).slice(2), ].join('-'); } function api() { return window.HyAppAPI || {}; } function loadRealData() { var centerAPI = api().superadminCenter; if (!centerAPI) { toast('API module is not ready.'); return Promise.reject(new Error('api_not_ready')); } return Promise.all([ centerAPI.overview(), centerAPI.bds(50), centerAPI.agencies(50), ]) .then(function (results) { var overviewPayload = results[0] || {}; var bdPayload = results[1] || {}; var agencyPayload = results[2] || {}; var profile = overviewPayload.profile || {}; var overview = normalizeOverview(overviewPayload); var agencies = (agencyPayload.items || []).map( normalizeAgencyItem ); var bds = (bdPayload.items || []).map(normalizeBDItem); if (!overview.totalHosts) { overview.totalHosts = agencies.reduce(function (sum, item) { return sum + Number(item.hosts || 0); }, 0); } overview.teamSalary = displayAmount(overviewPayload.salary); data.profile = { name: displayName(profile, 'Super Admin'), uid: displayID(profile), avatar: profile.avatar || '', }; data.balance = { available: displayAmount(overviewPayload.salary), }; data.overview = overview; data.bdList = bds; data.agencyList = agencies; data.history = [ { month: new Date().toISOString().slice(0, 7), status: 'In progress', bdCount: overview.totalBD, agencyCount: overview.totalAgency, totalSalary: overview.teamSalary, totalRecharge: overview.teamRecharge, }, ]; data.inviteRecords = { bd: [], agent: [] }; render(); }) .catch(function (error) { toast(error.message || 'Load failed.'); throw error; }); } function renderProfile() { $('profileName').textContent = data.profile.name; $('profileUID').textContent = t( 'superadmin_center.uid_prefix', 'UID: {id}' ).replace('{id}', data.profile.uid); setImage( $('profileAvatar'), $('profileAvatarFallback'), data.profile.avatar, data.profile.name ); } function renderBalance() { $('availableBalance').textContent = money(data.balance.available); } function summaryCell(label, value) { var cell = document.createElement('div'); var labelNode = document.createElement('span'); var valueNode = document.createElement('strong'); labelNode.textContent = label; valueNode.textContent = value; cell.appendChild(labelNode); cell.appendChild(valueNode); return cell; } function activeItems() { return state.activeTab === 'agency' ? data.agencyList : data.bdList; } function renderTeamSummary() { $('teamSummary').classList.toggle( 'is-two', state.activeTab !== 'agency' ); var cells = state.activeTab === 'agency' ? [ summaryCell( t('superadmin_center.agency_number', 'Agency number'), count(data.overview.totalAgency) ), summaryCell( t('superadmin_center.hosts', 'Hosts'), count(data.overview.totalHosts) ), summaryCell( t('superadmin_center.team_salary', 'Team salary'), '$' + compactMoney(data.overview.teamSalary) ), ] : [ summaryCell( t('superadmin_center.bd_number', 'BD number'), count(data.overview.totalBD) ), summaryCell( t('superadmin_center.agencies', 'Agencies'), count(data.overview.totalAgency) ), ]; replaceChildren($('teamSummary'), cells); } function createMemberRow(item) { var row = document.createElement('article'); var main = document.createElement('div'); var name = document.createElement('div'); var meta = document.createElement('div'); var side = document.createElement('div'); var salary = document.createElement('strong'); var sub = document.createElement('span'); var sideValue = item.sideValue || (item.salary === null || item.salary === undefined ? '' : '$' + money(item.salary)); var subText = item.sideSub !== undefined ? item.sideSub : state.activeTab === 'agency' ? count(item.hosts) + ' ' + t('superadmin_center.hosts', 'Hosts') : count(item.agencies) + ' ' + t('superadmin_center.agencies', 'Agencies'); row.className = 'member-row'; main.className = 'member-main'; name.className = 'member-name'; meta.className = 'member-meta'; side.className = 'member-side'; name.textContent = item.name; meta.textContent = state.activeTab === 'agency' ? 'ID: ' + item.id + ' ยท BD: ' + item.bdId : 'ID: ' + item.id; salary.textContent = sideValue || subText; sub.textContent = sideValue ? subText : ''; main.appendChild(name); main.appendChild(meta); side.appendChild(salary); if (sub.textContent) side.appendChild(sub); row.appendChild(makeAvatar(item)); row.appendChild(main); row.appendChild(side); row.addEventListener('click', function () { state.selectedDetails = item; renderDetails(); openModal('detailsModal'); }); return row; } function renderTeamList() { document.querySelectorAll('[data-team-tab]').forEach(function (button) { var active = button.getAttribute('data-team-tab') === state.activeTab; button.classList.toggle('is-active', active); button.setAttribute('aria-selected', String(active)); }); renderTeamSummary(); replaceChildren( $('teamList'), activeItems().map(function (item) { return createMemberRow(item); }) ); } function renderHistory() { var previous = data.history[1] || { totalSalary: 0 }; replaceChildren($('historySummary'), [ summaryCell( t('superadmin_center.total_income', 'Total income'), '$' + money(data.overview.teamSalary) ), summaryCell( t('superadmin_center.previous_income', 'Previous income'), '$' + money(previous.totalSalary) ), ]); replaceChildren( $('historyList'), data.history.map(function (item) { var row = document.createElement('article'); var title = document.createElement('div'); var status = document.createElement('span'); var grid = document.createElement('div'); row.className = 'history-row'; title.className = 'history-title'; status.className = 'status-tag'; grid.className = 'history-grid'; title.textContent = item.month; status.textContent = item.status; grid.appendChild( summaryCell( t('superadmin_center.bd_number', 'BD number'), count(item.bdCount) ) ); grid.appendChild( summaryCell( t('superadmin_center.agency_number', 'Agency number'), count(item.agencyCount) ) ); grid.appendChild( summaryCell( t('superadmin_center.team_salary', 'Team salary'), '$' + compactMoney(item.totalSalary) ) ); row.appendChild(status); row.appendChild(title); row.appendChild(grid); return row; }) ); } function renderDetails() { var item = state.selectedDetails; var summaryRows; if (!item) return; $('detailsTitle').textContent = item.name; summaryRows = [summaryCell('ID', item.id)]; if (item.salary !== null && item.salary !== undefined) { summaryRows.push( summaryCell( t('superadmin_center.team_salary', 'Team salary'), '$' + money(item.salary) ) ); } if (item.recharge !== null && item.recharge !== undefined) { summaryRows.push( summaryCell( t('superadmin_center.team_recharge', 'Team recharge'), '$' + money(item.recharge) ) ); } replaceChildren($('detailsSummary'), summaryRows); replaceChildren($('detailsList'), [ createReadonlyLine( state.activeTab === 'agency' ? t('superadmin_center.hosts', 'Hosts') : t('superadmin_center.agencies', 'Agencies'), count(state.activeTab === 'agency' ? item.hosts : item.agencies) ), ]); } function createReadonlyLine(label, value) { var row = document.createElement('div'); var labelNode = document.createElement('span'); var valueNode = document.createElement('strong'); row.className = 'readonly-line'; labelNode.textContent = label; valueNode.textContent = value; row.appendChild(labelNode); row.appendChild(valueNode); return row; } function inviteTitle() { return state.inviteMode === 'agent' ? t('superadmin_center.invite_agent', 'Invite Agent') : t('superadmin_center.invite_bd', 'Invite BD'); } function inviteRecords() { if (!state.inviteQuery) return data.inviteRecords[state.inviteMode] || []; if (!state.isMock) return state.inviteSearchResults; var keyword = state.inviteQuery.toLowerCase(); return mock.searchPool[state.inviteMode].filter(function (item) { return ( item.name.toLowerCase().indexOf(keyword) >= 0 || item.account.indexOf(keyword) >= 0 || item.id.indexOf(keyword) >= 0 ); }); } function renderInvite() { $('inviteModalTitle').textContent = inviteTitle(); var status = $('inviteStatus'); var records = inviteRecords(); status.hidden = !state.inviteStatus; status.textContent = state.inviteStatus; status.className = 'invite-status' + (state.inviteStatusType ? ' ' + state.inviteStatusType : ''); $('inviteEmpty').hidden = records.length > 0 || !!state.inviteStatus; replaceChildren( $('inviteList'), records.map(function (record) { var profile = record.profile || record; var card = document.createElement('article'); var main = document.createElement('div'); var name = document.createElement('div'); var meta = document.createElement('div'); var action = document.createElement('button'); var submitting = !!state.inviteSubmitting[profile.userId]; card.className = 'invite-card'; main.className = 'invite-main'; name.className = 'invite-name'; meta.className = 'invite-meta'; action.className = 'invite-action'; action.type = 'button'; name.textContent = profile.name; meta.textContent = 'ID: ' + profile.account; action.textContent = record.status || (submitting ? t('superadmin_center.in_progress', 'In progress') : t('superadmin_center.invite', 'Invite')); action.disabled = !!record.status || submitting; action.addEventListener('click', function () { submitInvite(record, profile); }); main.appendChild(name); main.appendChild(meta); card.appendChild(makeAvatar(profile)); card.appendChild(main); card.appendChild(action); return card; }) ); } function searchInviteProfile(queryValue) { if (state.isMock) { renderInvite(); return; } if (!api().user || !api().user.resolveDisplayUserID) { state.inviteStatus = 'API module is not ready.'; state.inviteStatusType = 'warning'; renderInvite(); return; } state.inviteSearchResults = []; state.inviteStatus = t('superadmin_center.in_progress', 'In progress'); state.inviteStatusType = ''; renderInvite(); api() .user.resolveDisplayUserID(queryValue) .then(function (payload) { var profile = normalizeInviteProfile(payload); state.inviteStatus = ''; state.inviteStatusType = ''; state.inviteSearchResults = profile ? [profile] : []; renderInvite(); }) .catch(function (error) { state.inviteSearchResults = []; state.inviteStatus = error.message || t('superadmin_center.no_users_found', 'No users found'); state.inviteStatusType = 'warning'; renderInvite(); }); } function submitInvite(record, profile) { var targetUserID = String(profile.userId || profile.id || ''); var centerAPI = api().superadminCenter; if (!targetUserID) return; if (state.isMock) { record.status = 'Success'; state.inviteStatus = t( 'superadmin_center.invite_success', 'Invitation submitted.' ); state.inviteStatusType = 'success'; renderInvite(); return; } if (!centerAPI) { state.inviteStatus = 'API module is not ready.'; state.inviteStatusType = 'warning'; renderInvite(); return; } state.inviteSubmitting[targetUserID] = true; renderInvite(); var payload = { command_id: commandID(state.inviteMode, targetUserID), target_user_id: targetUserID, }; var request = state.inviteMode === 'agent' ? centerAPI.inviteAgency( Object.assign({}, payload, { agency_name: profile.name, }) ) : centerAPI.inviteBD(payload); request .then(function () { record.status = 'Success'; state.inviteStatus = t( 'superadmin_center.invite_success', 'Invitation submitted.' ); state.inviteStatusType = 'success'; loadRealData().catch(function () {}); renderInvite(); }) .catch(function (error) { state.inviteStatus = error.message || 'Invite failed.'; state.inviteStatusType = 'warning'; renderInvite(); }) .finally(function () { delete state.inviteSubmitting[targetUserID]; renderInvite(); }); } function openModal(id) { var modal = $(id); if (!modal) return; modal.hidden = false; modal.setAttribute('aria-hidden', 'false'); document.body.classList.add('modal-open'); } function closeModal(id) { var modal = $(id); if (!modal) return; modal.hidden = true; modal.setAttribute('aria-hidden', 'true'); var hasOpen = Array.prototype.some.call( document.querySelectorAll('.sheet-modal, .invite-modal'), function (node) { return !node.hidden; } ); document.body.classList.toggle('modal-open', hasOpen); } function navigateToWithdrawExchange() { var params = new URLSearchParams(window.location.search); params.set('identity', 'SUPER_ADMIN'); params.set('salaryType', 'SUPER_ADMIN_SALARY'); if (!params.has('mode')) params.set('mode', 'withdraw'); window.location.href = '../withdraw-exchange/index.html?' + params.toString(); } function bindEvents() { $('backButton').addEventListener('click', function () { if (window.HyAppBridge) window.HyAppBridge.back(); }); $('withdrawExchangeButton').addEventListener( 'click', navigateToWithdrawExchange ); document.querySelectorAll('.menu-row').forEach(function (button) { button.addEventListener('click', function () { var action = button.getAttribute('data-action'); if (action === 'history') { renderHistory(); openModal('historyModal'); return; } if (action === 'invite-bd' || action === 'invite-agent') { state.inviteMode = action === 'invite-agent' ? 'agent' : 'bd'; state.inviteQuery = ''; state.inviteStatus = ''; state.inviteStatusType = ''; state.inviteSearchResults = []; $('inviteSearchInput').value = ''; renderInvite(); openModal('inviteModal'); } }); }); document.querySelectorAll('[data-team-tab]').forEach(function (button) { button.addEventListener('click', function () { state.activeTab = button.getAttribute('data-team-tab') || 'bd'; renderTeamList(); }); }); document .querySelectorAll('[data-close-modal]') .forEach(function (node) { node.addEventListener('click', function () { closeModal(node.getAttribute('data-close-modal')); }); }); $('inviteSearchForm').addEventListener('submit', function (event) { event.preventDefault(); state.inviteQuery = $('inviteSearchInput').value.trim(); state.inviteStatus = state.inviteQuery ? '' : t('superadmin_center.enter_user_id', 'Enter User ID'); state.inviteStatusType = state.inviteQuery ? '' : 'warning'; state.inviteSearchResults = []; if (state.inviteQuery) { searchInviteProfile(state.inviteQuery); } else { renderInvite(); } }); document.addEventListener('keydown', function (event) { if (event.key !== 'Escape') return; closeModal('historyModal'); closeModal('detailsModal'); closeModal('inviteModal'); }); } function render() { renderProfile(); renderBalance(); renderTeamList(); } function init() { if (state.isMock) { applyMockData(); } else { applyEmptyData(); } render(); bindEvents(); if (!state.isMock) { loadRealData().catch(function () {}); } if (window.HyAppBridge) { window.HyAppBridge.ready({ page: 'superadmin-center', mock: state.isMock, }); } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } window.addEventListener('hyapp:i18n-ready', function () { render(); if (!$('historyModal').hidden) renderHistory(); if (!$('inviteModal').hidden) renderInvite(); if (!$('detailsModal').hidden) renderDetails(); }); })();