2026-06-29 18:27:25 +08:00

1045 lines
36 KiB
JavaScript

(function () {
var EXCHANGE_RATE = 80000;
var WITHDRAW_MIN_AMOUNT = 50;
var params = new URLSearchParams(window.location.search);
var isMock = params.get('mock') === '1';
var currentMode = normalizeMode(params.get('mode')) || 'transfer';
var identity = String(params.get('identity') || '').trim();
var salaryAssetType = String(
params.get('salaryType') || params.get('asset_type') || ''
).trim();
var state = {
balance: 0,
paymentInfo: null,
selectedPayee: null,
isSearching: false,
isSaving: false,
isSavingContact: false,
isSubmitting: false,
contactInfo: '',
historyItems: [],
transferRateTiers: [],
};
var lastSearchTriggerAt = 0;
var autoSearchTimer = 0;
var mockBalances = {
HOST_SALARY_USD: 30650.75,
AGENCY_SALARY_USD: 30650.75,
BD_SALARY_USD: 48620.8,
ADMIN_SALARY_USD: 168250.5,
};
var mock = {
balance: mockBalances[salaryAssetType] || 30650.75,
paymentInfo: null,
payees: {
163003: {
id: 'payee_163003',
name: 'Yumi Star Agency',
account: '163003',
avatar: '',
},
163000: {
id: 'payee_163000',
name: 'quick_1780052629537',
account: '163000',
avatar: '',
},
},
history: [
{
key: historyTitleKey(),
title: historyTitle(),
amount: 18400.25,
balance: mockBalances[salaryAssetType] || 30650.75,
type: 0,
date: '2026-06-01 12:10',
},
{
key: 'withdraw_exchange.history_exchange_to_golds',
title: 'Exchange to golds',
amount: 800,
balance: 12250.5,
type: 1,
date: '2026-05-30 20:42',
},
{
key: 'withdraw_exchange.history_gift_reward',
title: 'Gift reward',
amount: 8250.5,
balance: 13050.5,
type: 0,
date: '2026-05-28 18:30',
},
],
};
var inputs = {
withdraw: $('withdrawAmount'),
exchange: $('exchangeAmount'),
transfer: $('transferAmount'),
};
function $(id) {
return document.getElementById(id);
}
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 normalizeMode(mode) {
var value = String(mode || '').trim();
return ['withdraw', 'exchange', 'transfer'].indexOf(value) >= 0
? value
: '';
}
function normalizeIdentity(value) {
value = String(value || '').trim().toUpperCase().replace(/-/g, '_');
if (value === 'ADMIN') return 'BD_LEADER';
if (['HOST', 'AGENCY', 'BD', 'BD_LEADER'].indexOf(value) >= 0)
return value;
if (salaryAssetType === 'AGENCY_SALARY_USD') return 'AGENCY';
if (salaryAssetType === 'BD_SALARY_USD') return 'BD';
if (salaryAssetType === 'ADMIN_SALARY_USD') return 'BD_LEADER';
return 'HOST';
}
function api() {
if (window.HyAppAPI && window.HyAppAPI.salaryWallet)
return window.HyAppAPI.salaryWallet;
return window.HyApp && window.HyApp.api
? window.HyApp.api.salaryWallet
: null;
}
function userApi() {
if (window.HyAppAPI && window.HyAppAPI.user)
return window.HyAppAPI.user;
return window.HyApp && window.HyApp.api ? window.HyApp.api.user : null;
}
function commandId(prefix) {
return prefix + '-' + Date.now() + '-' + Math.random().toString(16).slice(2);
}
function money(value) {
var number = Number(value || 0);
return number.toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
}
function moneyInput(value) {
var number = Number(value || 0);
return Number.isFinite(number) ? number.toFixed(2) : '0.00';
}
function amount() {
var input = inputs[currentMode];
return Number(input && input.value ? input.value : 0) || 0;
}
function amountText(value) {
return moneyInput(value);
}
function usdMinorToNumber(value) {
return Number(value || 0) / 100;
}
function findTransferRate(value) {
var minor = Math.round(Number(value || 0) * 100);
return (state.transferRateTiers || []).find(function (tier) {
return (
String(tier.status || 'active') === 'active' &&
minor >= Number(tier.min_usd_minor || 0) &&
minor <= Number(tier.max_usd_minor || 0)
);
});
}
function delay(value) {
return new Promise(function (resolve) {
window.setTimeout(function () {
resolve(value);
}, 260);
});
}
function mockRequest(action, payload) {
if (action === 'balance') return delay(mock.balance);
if (action === 'payment') return delay(mock.paymentInfo);
if (action === 'history') return delay(mock.history.slice());
if (action === 'saveAddress') {
mock.paymentInfo = {
id: 'usdt_mock_1',
cardNo: payload.cardNo,
};
return delay(mock.paymentInfo);
}
if (action === 'searchPayee') {
var account = String(payload.account || '').trim();
var payee = mock.payees[account];
if (!payee && account && account !== '000000') {
payee = {
id: 'payee_' + account,
name: 'User ' + account,
nameKey: 'withdraw_exchange.mock_user_name',
account: account,
avatar: '',
};
}
return delay(payee || null);
}
if (action === 'submit') {
mock.balance = Math.max(0, mock.balance - payload.amount);
mock.history.unshift({
title: titleForMode(payload.mode),
amount: payload.amount,
balance: mock.balance,
type: 1,
date: new Date().toISOString().replace('T', ' ').slice(0, 16),
});
return delay({ ok: true });
}
return delay(null);
}
function titleForMode(mode) {
if (mode === 'withdraw')
return t('withdraw_exchange.withdraw', 'Withdraw');
if (mode === 'exchange')
return t('withdraw_exchange.exchange', 'Exchange');
return t('withdraw_exchange.transfer', 'Transfer');
}
function historyTitleKey() {
if (salaryAssetType === 'BD_SALARY_USD')
return 'withdraw_exchange.history_bd_salary';
if (salaryAssetType === 'ADMIN_SALARY_USD')
return 'withdraw_exchange.history_admin_salary';
if (salaryAssetType === 'AGENCY_SALARY_USD')
return 'withdraw_exchange.history_agency_salary';
return 'withdraw_exchange.history_host_salary';
}
function historyTitle() {
if (salaryAssetType === 'BD_SALARY_USD') return 'BD salary';
if (salaryAssetType === 'ADMIN_SALARY_USD') return 'Admin salary';
if (salaryAssetType === 'AGENCY_SALARY_USD') return 'Agency salary';
return 'Host salary';
}
function firstValue(source, keys) {
if (!source) return '';
for (var i = 0; i < keys.length; i += 1) {
var value = source[keys[i]];
if (value !== undefined && value !== null && value !== '')
return value;
}
return '';
}
function contactFrom(value) {
if (!value || typeof value !== 'object') return '';
var source = value.profile || value.user || value;
return String(
firstValue(source, [
'contact_info',
'contactInfo',
'whatsapp_phone',
'whatsappPhone',
'contact',
]) || ''
).trim();
}
function timeLabelFromMS(value) {
var number = Number(value || 0);
if (!Number.isFinite(number) || number <= 0) return '';
var date = new Date(number);
if (Number.isNaN(date.getTime())) return '';
return (
date.getFullYear() +
'-' +
String(date.getMonth() + 1).padStart(2, '0') +
'-' +
String(date.getDate()).padStart(2, '0') +
' ' +
String(date.getHours()).padStart(2, '0') +
':' +
String(date.getMinutes()).padStart(2, '0')
);
}
function historyLabelForBizType(bizType, delta) {
if (bizType === 'salary_exchange_to_coin') {
return {
key: 'withdraw_exchange.history_exchange_to_golds',
title: 'Exchange to golds',
};
}
if (bizType === 'salary_transfer_to_coin_seller') {
return {
key: 'withdraw_exchange.transfer',
title: 'Transfer',
};
}
if (bizType === 'host_salary_settlement' || delta >= 0) {
return {
key: historyTitleKey(),
title: historyTitle(),
};
}
return {
key: 'withdraw_exchange.withdraw',
title: 'Withdraw',
};
}
function normalizeHistoryItem(item, index) {
var delta = Number(
firstValue(item, ['available_delta', 'availableDelta'])
);
if (!Number.isFinite(delta)) delta = 0;
var balance = Number(
firstValue(item, ['available_after', 'availableAfter'])
);
if (!Number.isFinite(balance)) balance = 0;
var label = historyLabelForBizType(
String(firstValue(item, ['biz_type', 'bizType']) || ''),
delta
);
return {
id:
firstValue(item, ['transaction_id', 'transactionId']) ||
String(firstValue(item, ['entry_id', 'entryId']) || index),
key: label.key,
title: label.title,
amount: Math.abs(usdMinorToNumber(delta)),
balance: usdMinorToNumber(balance),
type: delta < 0 ? 1 : 0,
date: timeLabelFromMS(firstValue(item, ['created_at_ms', 'createdAtMs'])),
};
}
function normalizeHistoryItems(payload) {
var source = payload || {};
if (source.identity) identity = normalizeIdentity(source.identity);
if (source.salary_asset_type) {
salaryAssetType = source.salary_asset_type;
}
var items = Array.isArray(source.items)
? source.items
: Array.isArray(source.transactions)
? source.transactions
: Array.isArray(source)
? source
: [];
return items.map(function (item, index) {
return normalizeHistoryItem(item || {}, index);
});
}
function isValidTrc20(value) {
return /^T[1-9A-HJ-NP-Za-km-z]{33}$/.test(String(value || '').trim());
}
function maskAddress(value) {
var text = String(value || '').trim();
if (text.length <= 12) return text || '-';
return text.slice(0, 6) + '...' + text.slice(-6);
}
function activeSubmitLabel() {
if (currentMode === 'withdraw')
return t('withdraw_exchange.withdraw_now', 'Withdraw now');
if (currentMode === 'exchange')
return t('withdraw_exchange.exchange_now', 'Exchange now');
return t('withdraw_exchange.transfer_now', 'Transfer now');
}
function renderBalance() {
$('balanceAmount').textContent = money(state.balance);
Object.keys(inputs).forEach(function (key) {
if (inputs[key]) inputs[key].max = moneyInput(state.balance);
});
}
function renderMode() {
document.querySelectorAll('.mode-tab').forEach(function (tab) {
var active = tab.getAttribute('data-mode') === currentMode;
tab.classList.toggle('active', active);
tab.setAttribute('aria-selected', String(active));
});
document.querySelectorAll('.mode-panel').forEach(function (panel) {
panel.classList.toggle(
'active',
panel.getAttribute('data-panel') === currentMode
);
});
$('paymentSection').hidden = currentMode !== 'withdraw';
updateSubmit();
}
function renderPaymentInfo() {
var payment = state.paymentInfo;
$('emptyAddressState').hidden = Boolean(payment);
$('addressForm').hidden = Boolean(payment);
$('boundAddressCard').hidden = !payment;
if (payment)
$('boundAddress').textContent = maskAddress(payment.cardNo);
updateSubmit();
}
function renderPayee() {
var result = $('payeeResult');
result.textContent = '';
if (!state.selectedPayee) {
result.hidden = true;
updateSubmit();
return;
}
var payee = state.selectedPayee;
var payeeName = payee.nameKey
? t(payee.nameKey, payee.name || 'User {account}').replace(
'{account}',
payee.account
)
: payee.name;
var avatar = document.createElement('div');
var copy = document.createElement('div');
var name = document.createElement('div');
var id = document.createElement('div');
avatar.className = 'payee-avatar';
copy.className = 'payee-copy';
name.className = 'payee-name';
id.className = 'payee-id';
if (payee.avatar) {
var avatarImage = document.createElement('img');
avatarImage.src = payee.avatar;
avatarImage.alt = '';
avatar.appendChild(avatarImage);
} else {
avatar.textContent = String(payeeName || 'U')
.charAt(0)
.toUpperCase();
}
name.textContent = payeeName || '-';
id.textContent =
t('withdraw_exchange.uid_prefix', 'UID:') + ' ' + payee.account;
copy.appendChild(name);
copy.appendChild(id);
result.appendChild(avatar);
result.appendChild(copy);
result.hidden = false;
updateSubmit();
}
function renderHistory() {
$('salaryHistoryTotal').textContent = '$' + money(state.balance);
var list = $('salaryHistoryList');
list.textContent = '';
if (!state.historyItems.length) {
var empty = document.createElement('div');
empty.className = 'salary-history-empty';
empty.textContent = t(
'withdraw_exchange.no_salary_history',
'No salary history'
);
list.appendChild(empty);
return;
}
state.historyItems.forEach(function (item) {
var row = document.createElement('article');
var main = document.createElement('div');
var title = document.createElement('div');
var meta = document.createElement('div');
var value = document.createElement('div');
var isOut = Number(item.type) === 1;
row.className = 'salary-history-item';
main.className = 'salary-history-item-main';
title.className = 'salary-history-item-title';
meta.className = 'salary-history-item-meta';
value.className =
'salary-history-amount' + (isOut ? ' is-out' : '');
title.textContent = item.key ? t(item.key, item.title) : item.title;
meta.textContent =
item.date +
' ' +
t('withdraw_exchange.balance', 'Balance') +
': $' +
money(item.balance);
value.textContent = (isOut ? '-' : '+') + '$' + money(item.amount);
main.appendChild(title);
main.appendChild(meta);
row.appendChild(main);
row.appendChild(value);
list.appendChild(row);
});
}
function updateSubmit() {
var button = $('submitButton');
if (state.isSubmitting) {
button.textContent = t(
'withdraw_exchange.submitting',
'Submitting...'
);
button.disabled = true;
return;
}
var value = amount();
var transferRateMissing =
currentMode === 'transfer' && value > 0 && !findTransferRate(value);
var disabled =
value <= 0 ||
value > state.balance ||
(currentMode === 'withdraw' &&
(!state.paymentInfo || value < WITHDRAW_MIN_AMOUNT)) ||
(currentMode === 'transfer' &&
(!state.selectedPayee || transferRateMissing));
button.textContent = activeSubmitLabel();
button.disabled = disabled;
}
function needsContactForSubmit() {
return currentMode === 'exchange' || currentMode === 'transfer';
}
function normalizeAmount(event) {
var input = event.target;
var raw = String(input.value || '').replace(/[^\d.]/g, '');
var parts = raw.split('.');
var next =
parts.length > 2 ? parts[0] + '.' + parts.slice(1).join('') : raw;
var value = Number(next);
if (Number.isFinite(value) && value > state.balance)
next = moneyInput(state.balance);
input.value = next;
updateSubmit();
}
function setMode(mode) {
currentMode = normalizeMode(mode) || 'transfer';
renderMode();
}
function openHistory() {
$('salaryHistoryModal').hidden = false;
document.body.classList.add('modal-open');
$('salaryHistoryList').textContent = t(
'withdraw_exchange.loading',
'Loading...'
);
var historyRequest = isMock
? mockRequest('history')
: api() && api().history
? api().history(identity, 30).then(normalizeHistoryItems)
: Promise.resolve([]);
historyRequest.then(function (items) {
state.historyItems = items || [];
renderHistory();
}).catch(function (err) {
state.historyItems = [];
renderHistory();
toast(err && err.message ? err.message : t('withdraw_exchange.load_failed', 'Load failed. Try again later.'));
});
}
function closeHistory() {
$('salaryHistoryModal').hidden = true;
document.body.classList.remove('modal-open');
}
function setContactStatus(message) {
var node = $('contactStatus');
node.textContent = message || '';
node.hidden = !message;
}
function setContactSaving(saving) {
state.isSavingContact = saving;
$('saveContactButton').disabled = saving;
$('saveContactButton').textContent = saving
? t('contact_card.saving', 'Saving...')
: t('contact_card.save', 'Save');
}
function openContactModal() {
$('contactInput').value = state.contactInfo || '';
setContactStatus('');
$('contactModal').hidden = false;
$('contactModal').setAttribute('aria-hidden', 'false');
document.body.classList.add('modal-open');
window.setTimeout(function () {
$('contactInput').focus();
}, 0);
}
function closeContactModal() {
$('contactModal').hidden = true;
$('contactModal').setAttribute('aria-hidden', 'true');
document.body.classList.remove('modal-open');
}
function saveContact(event) {
if (event) event.preventDefault();
var contact = String($('contactInput').value || '').trim();
if (!contact) {
setContactStatus(
t('contact_card.required', 'Enter WhatsApp contact.')
);
return;
}
var apiClient = userApi();
if (!apiClient || !apiClient.updateContact) {
setContactStatus(
t('contact_card.api_unavailable', 'Contact API unavailable.')
);
return;
}
// Exchange/Transfer 需要运营联系方式用于后台跟进;联系方式是用户主资料,保存成功后才允许继续提交工资兑换或转账请求。
setContactSaving(true);
setContactStatus('');
apiClient
.updateContact({ contact_info: contact })
.then(function (response) {
state.contactInfo = contactFrom(response) || contact;
closeContactModal();
updateSubmit();
toast(t('contact_card.saved', 'Saved.'));
})
.catch(function () {
setContactStatus(
t('contact_card.save_failed', 'Save failed.')
);
})
.finally(function () {
setContactSaving(false);
});
}
function saveAddress() {
var address = String($('trc20Address').value || '').trim();
if (!isValidTrc20(address)) {
toast(
t(
'withdraw_exchange.invalid_address',
'Please enter a valid TRC20 USDT address'
)
);
return;
}
state.isSaving = true;
$('saveAddressButton').disabled = true;
$('saveAddressButton').textContent = t(
'withdraw_exchange.saving',
'Saving...'
);
mockRequest('saveAddress', { cardNo: address }).then(
function (payment) {
state.paymentInfo = payment;
state.isSaving = false;
$('saveAddressButton').disabled = false;
$('saveAddressButton').textContent = t(
'withdraw_exchange.save_address',
'Save address'
);
renderPaymentInfo();
toast(t('withdraw_exchange.address_saved', 'Address saved'));
}
);
}
function searchPayee() {
var now = Date.now();
if (now - lastSearchTriggerAt < 240) return;
lastSearchTriggerAt = now;
var account = String($('transferAccount').value || '').trim();
if (!account) {
toast(
t(
'withdraw_exchange.missing_payee',
'Please search and select a user'
)
);
return;
}
state.selectedPayee = null;
renderPayee();
if (!isMock && !api()) {
toast(t('withdraw_exchange.search_failed', 'Search failed. Try again later.'));
return;
}
state.isSearching = true;
$('searchPayeeButton').disabled = true;
$('searchPayeeButton').textContent = t(
'withdraw_exchange.searching',
'Searching...'
);
var request = isMock
? mockRequest('searchPayee', { account: account })
: api().searchCoinSeller(account, identity).then(function (data) {
var seller = data && data.seller;
if (!seller) return null;
return {
id: seller.user_id || seller.userId,
name: seller.username || seller.display_user_id || account,
account: seller.display_user_id || account,
avatar: seller.avatar || '',
};
});
request
.then(function (payee) {
state.isSearching = false;
$('searchPayeeButton').disabled = false;
$('searchPayeeButton').textContent = t(
'withdraw_exchange.search',
'Search'
);
if (!payee) {
toast(t('withdraw_exchange.payee_not_found', 'User not found'));
return;
}
state.selectedPayee = payee;
renderPayee();
})
.catch(function (err) {
state.isSearching = false;
$('searchPayeeButton').disabled = false;
$('searchPayeeButton').textContent = t(
'withdraw_exchange.search',
'Search'
);
toast(err && err.message ? err.message : t('withdraw_exchange.payee_not_found', 'User not found'));
});
}
function validateSubmit() {
var value = amount();
if (value <= 0)
return t(
'withdraw_exchange.invalid_amount',
'Please enter a valid amount'
);
if (value > state.balance)
return t(
'withdraw_exchange.amount_exceeds_balance',
'Amount exceeds salary'
);
if (currentMode === 'withdraw' && !state.paymentInfo)
return t(
'withdraw_exchange.missing_payment_info',
'Please add a TRC20 USDT address'
);
if (currentMode === 'withdraw' && value < WITHDRAW_MIN_AMOUNT)
return t(
'withdraw_exchange.amount_too_low',
'Minimum withdrawal amount is 50 USD'
);
if (currentMode === 'transfer' && !state.selectedPayee)
return t(
'withdraw_exchange.missing_payee',
'Please search and select a user'
);
if (currentMode === 'transfer' && !findTransferRate(value))
return t(
'withdraw_exchange.rate_not_configured',
'Exchange rate not configured.'
);
return '';
}
function submit() {
var error = validateSubmit();
if (error) {
toast(error);
return;
}
if (needsContactForSubmit() && !state.contactInfo) {
openContactModal();
return;
}
if (!isMock && currentMode === 'withdraw') {
toast(
t(
'withdraw_exchange.withdraw_not_available',
'Withdraw is not available yet.'
)
);
return;
}
state.isSubmitting = true;
updateSubmit();
submitRequest()
.then(function (result) {
var input = inputs[currentMode];
if (input) input.value = '';
if (currentMode === 'transfer') {
state.selectedPayee = null;
$('transferAccount').value = '';
renderPayee();
}
if (isMock) {
state.balance = mock.balance;
} else if (currentMode === 'exchange') {
state.balance = usdMinorToNumber(result.salary_balance_after);
} else if (currentMode === 'transfer') {
state.balance = usdMinorToNumber(
result.source_salary_balance_after
);
}
state.isSubmitting = false;
renderBalance();
updateSubmit();
var key =
currentMode === 'withdraw'
? 'withdraw_exchange.withdraw_success'
: currentMode === 'exchange'
? 'withdraw_exchange.exchange_success'
: 'withdraw_exchange.transfer_success';
toast(t(key, 'Submitted'));
})
.catch(function (err) {
state.isSubmitting = false;
updateSubmit();
toast(err && err.message ? err.message : t('withdraw_exchange.submit_failed', 'Submit failed.'));
});
}
function submitRequest() {
var value = amount();
if (isMock) {
return mockRequest('submit', {
mode: currentMode,
amount: value,
payee: state.selectedPayee,
paymentInfo: state.paymentInfo,
});
}
if (!api()) {
return Promise.reject(
new Error(t('withdraw_exchange.submit_failed', 'Submit failed.'))
);
}
if (currentMode === 'exchange') {
return api().exchange({
command_id: commandId('salary-exchange'),
identity: identity,
amount_usd: amountText(value),
reason: 'salary exchange',
});
}
return api().transferToCoinSeller({
command_id: commandId('salary-transfer'),
identity: identity,
target_display_user_id: state.selectedPayee.account,
amount_usd: amountText(value),
reason: 'salary transfer',
});
}
function goBack() {
if (window.history.length > 1) {
window.history.back();
return;
}
var nextParams = new URLSearchParams(window.location.search);
nextParams.delete('mode');
var query = nextParams.toString();
var centerPath = '../host-center/index.html';
if (identity === 'BD') centerPath = '../bd-center/index.html';
if (identity === 'BD_LEADER')
centerPath = '../superadmin-center/index.html';
if (identity === 'AGENCY') centerPath = '../agency-center/index.html';
window.location.href = centerPath + (query ? '?' + query : '');
}
function bindEvents() {
function bindTap(id, handler) {
var node = $(id);
var last = 0;
function run(event) {
var now = Date.now();
if (now - last < 220) return;
last = now;
if (event && event.type === 'pointerdown') {
event.preventDefault();
}
handler(event);
}
node.addEventListener('pointerdown', run);
node.addEventListener('click', run);
}
bindTap('backButton', goBack);
document.querySelectorAll('.mode-tab').forEach(function (tab) {
tab.addEventListener('click', function () {
setMode(tab.getAttribute('data-mode'));
});
});
Object.keys(inputs).forEach(function (key) {
if (inputs[key])
inputs[key].addEventListener('input', normalizeAmount);
});
bindTap('allButton', function () {
inputs.withdraw.value = moneyInput(state.balance);
updateSubmit();
});
$('transferAccount').addEventListener('input', function () {
state.selectedPayee = null;
renderPayee();
window.clearTimeout(autoSearchTimer);
if (String($('transferAccount').value || '').trim().length >= 3) {
autoSearchTimer = window.setTimeout(searchPayee, 260);
}
});
$('transferAccount').addEventListener('keydown', function (event) {
if (event.key === 'Enter') searchPayee();
});
bindTap('searchPayeeButton', searchPayee);
bindTap('saveAddressButton', saveAddress);
bindTap('submitButton', submit);
bindTap('salaryHistoryButton', openHistory);
bindTap('salaryHistoryBackdrop', closeHistory);
bindTap('salaryHistoryCloseButton', closeHistory);
bindTap('contactBackdrop', closeContactModal);
bindTap('contactCloseButton', closeContactModal);
$('contactForm').addEventListener('submit', saveContact);
}
function renderStaticDynamicText() {
$('exchangeRateText').textContent = t(
'withdraw_exchange.exchange_rate_value',
'1$ = {amount} golds'
).replace('{amount}', EXCHANGE_RATE.toLocaleString('en-US'));
if (!$('salaryHistoryModal').hidden) renderHistory();
if (!$('contactModal').hidden && !state.isSavingContact) {
$('saveContactButton').textContent = t('contact_card.save', 'Save');
}
updateSubmit();
renderPayee();
}
function init() {
identity = normalizeIdentity(identity);
bindEvents();
setMode(currentMode);
renderStaticDynamicText();
loadOverview();
loadPaymentInfo();
loadContactInfo();
if (window.HyAppBridge) {
window.HyAppBridge.ready({
page: 'withdraw-exchange',
mock: isMock,
});
}
}
function loadOverview() {
if (isMock) {
mockRequest('balance').then(function (balance) {
state.balance = balance;
state.transferRateTiers = [
{
min_usd_minor: 100,
max_usd_minor: 1000,
coin_per_usd: 90000,
status: 'active',
},
{
min_usd_minor: 1100,
max_usd_minor: 5000,
coin_per_usd: 92000,
status: 'active',
},
];
renderBalance();
updateSubmit();
});
return;
}
if (!api()) {
toast(t('withdraw_exchange.load_failed', 'Load failed. Try again later.'));
return;
}
api()
.overview(identity)
.then(function (data) {
identity = normalizeIdentity(data.identity || identity);
salaryAssetType = data.salary_asset_type || salaryAssetType;
EXCHANGE_RATE = Number(data.exchange_rate || EXCHANGE_RATE);
state.balance = usdMinorToNumber(
data.salary && data.salary.available_amount
);
state.transferRateTiers = data.transfer_rate_tiers || [];
renderStaticDynamicText();
renderBalance();
updateSubmit();
})
.catch(function (err) {
toast(err && err.message ? err.message : t('withdraw_exchange.load_failed', 'Load failed. Try again later.'));
});
}
function loadPaymentInfo() {
if (isMock) {
mockRequest('payment').then(function (payment) {
state.paymentInfo = payment;
renderPaymentInfo();
});
return;
}
state.paymentInfo = null;
renderPaymentInfo();
}
function loadContactInfo() {
if (isMock) {
state.contactInfo = String(params.get('contact') || '').trim();
updateSubmit();
return;
}
var apiClient = userApi();
if (!apiClient || !apiClient.me) {
state.contactInfo = '';
updateSubmit();
return;
}
apiClient
.me()
.then(function (profile) {
state.contactInfo = contactFrom(profile);
updateSubmit();
})
.catch(function () {
state.contactInfo = '';
updateSubmit();
});
}
document.addEventListener('DOMContentLoaded', init);
window.addEventListener('hyapp:i18n-ready', renderStaticDynamicText);
})();