472 lines
14 KiB
JavaScript
472 lines
14 KiB
JavaScript
(function () {
|
|
var HOST_SALARY_USD = 'HOST_SALARY_USD';
|
|
var HOST_LEVEL_TRACK = 'charm';
|
|
|
|
var mock = {
|
|
profile: {
|
|
name: 'quick_1780052629537',
|
|
uid: '163000',
|
|
avatar: avatarData('Y', '#dbc8ff', '#7d57c7'),
|
|
},
|
|
agency: {
|
|
shortId: '163003',
|
|
},
|
|
salary: {
|
|
available: 30650.75,
|
|
monthKey: 'host_center.month_june',
|
|
month: 'June',
|
|
currencyKey: 'host_center.currency_usd',
|
|
currency: 'USD',
|
|
useCurrentMonth: false,
|
|
},
|
|
level: {
|
|
current: 3,
|
|
currentRequired: 0,
|
|
currentValue: 2450,
|
|
nextValue: 4000,
|
|
},
|
|
};
|
|
|
|
var state = cloneHostState(mock);
|
|
|
|
function $(id) {
|
|
return document.getElementById(id);
|
|
}
|
|
|
|
function cloneHostState(value) {
|
|
return {
|
|
profile: Object.assign({}, value.profile),
|
|
agency: Object.assign({}, value.agency),
|
|
salary: Object.assign({}, value.salary),
|
|
level: Object.assign({}, value.level),
|
|
};
|
|
}
|
|
|
|
function avatarData(text, background, foreground) {
|
|
var value =
|
|
String(text || 'Y')
|
|
.trim()
|
|
.charAt(0) || 'Y';
|
|
var letter = value.replace(/[<>&"']/g, '');
|
|
var svg =
|
|
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96">' +
|
|
'<rect width="96" height="96" rx="48" fill="' +
|
|
background +
|
|
'"/>' +
|
|
'<text x="50%" y="54%" text-anchor="middle" dominant-baseline="middle" fill="' +
|
|
foreground +
|
|
'" font-family="Arial, sans-serif" font-size="38" font-weight="800">' +
|
|
letter +
|
|
'</text>' +
|
|
'</svg>';
|
|
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) {
|
|
var number = Number(value || 0);
|
|
return number.toLocaleString('en-US', {
|
|
minimumFractionDigits: 2,
|
|
maximumFractionDigits: 2,
|
|
});
|
|
}
|
|
|
|
function initial(text) {
|
|
return String(text || '')
|
|
.trim()
|
|
.charAt(0)
|
|
.toUpperCase();
|
|
}
|
|
|
|
function queryValue(name) {
|
|
return new URLSearchParams(window.location.search).get(name);
|
|
}
|
|
|
|
function isMockMode() {
|
|
return queryValue('mock') === '1';
|
|
}
|
|
|
|
function hasAccessToken() {
|
|
return (
|
|
window.HyAppAPI &&
|
|
window.HyAppAPI.getAccessToken &&
|
|
!!window.HyAppAPI.getAccessToken()
|
|
);
|
|
}
|
|
|
|
function unwrapData(payload) {
|
|
if (!payload || typeof payload !== 'object') return payload;
|
|
return Object.prototype.hasOwnProperty.call(payload, 'data')
|
|
? payload.data
|
|
: payload;
|
|
}
|
|
|
|
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 toNumber(value) {
|
|
var number = Number(value);
|
|
return Number.isFinite(number) ? number : 0;
|
|
}
|
|
|
|
function safeRequest(factory) {
|
|
return factory().catch(function (error) {
|
|
if (window.console && window.console.warn) {
|
|
window.console.warn('[host-center] api failed', error);
|
|
}
|
|
return null;
|
|
});
|
|
}
|
|
|
|
function currentLocale() {
|
|
var lang =
|
|
window.HyAppI18n && window.HyAppI18n.lang
|
|
? window.HyAppI18n.lang()
|
|
: 'en';
|
|
var map = {
|
|
en: 'en-US',
|
|
ar: 'ar',
|
|
tr: 'tr-TR',
|
|
es: 'es-ES',
|
|
zh: 'zh-CN',
|
|
id: 'id-ID',
|
|
};
|
|
return map[lang] || 'en-US';
|
|
}
|
|
|
|
function currentMonthName() {
|
|
try {
|
|
return new Date().toLocaleString(currentLocale(), {
|
|
month: 'long',
|
|
});
|
|
} catch (_) {
|
|
return 'June';
|
|
}
|
|
}
|
|
|
|
function salaryMonthLabel(salary) {
|
|
if (salary.monthKey) return t(salary.monthKey, salary.month);
|
|
if (salary.useCurrentMonth) return currentMonthName();
|
|
return salary.month || currentMonthName();
|
|
}
|
|
|
|
function salaryCurrencyLabel(salary) {
|
|
if (salary.currencyKey) return t(salary.currencyKey, salary.currency);
|
|
return salary.currency || t('host_center.currency_usd', 'USD');
|
|
}
|
|
|
|
function renderProfile() {
|
|
var image = $('profileAvatar');
|
|
var fallback = $('profileAvatarFallback');
|
|
var badge = $('profileBadge');
|
|
var profile = state.profile;
|
|
var agency = state.agency;
|
|
|
|
$('profileName').textContent = profile.name || 'User';
|
|
$('profileUID').textContent = 'UID: ' + (profile.uid || '-');
|
|
fallback.textContent = initial(profile.name || profile.uid) || 'Y';
|
|
|
|
if (agency.shortId) {
|
|
badge.hidden = false;
|
|
badge.textContent = t(
|
|
'host_center.agency_short_id',
|
|
'Agency ID: {id}'
|
|
).replace('{id}', agency.shortId);
|
|
} else {
|
|
badge.hidden = true;
|
|
badge.textContent = '';
|
|
}
|
|
|
|
if (!profile.avatar) {
|
|
image.hidden = true;
|
|
image.removeAttribute('src');
|
|
fallback.hidden = false;
|
|
return;
|
|
}
|
|
image.onload = function () {
|
|
image.hidden = false;
|
|
fallback.hidden = true;
|
|
};
|
|
image.onerror = function () {
|
|
image.hidden = true;
|
|
fallback.hidden = false;
|
|
};
|
|
image.src = profile.avatar;
|
|
}
|
|
|
|
function renderIncome() {
|
|
var salary = state.salary;
|
|
$('availableSalary').textContent = money(salary.available);
|
|
$('incomeFoot').textContent = t(
|
|
'host_center.salary_month_note',
|
|
'{month} settlement · {currency}'
|
|
)
|
|
.replace('{month}', salaryMonthLabel(salary))
|
|
.replace('{currency}', salaryCurrencyLabel(salary));
|
|
}
|
|
|
|
function renderLevel() {
|
|
var level = state.level;
|
|
var currentRequired = toNumber(level.currentRequired);
|
|
var currentValue = toNumber(level.currentValue);
|
|
var nextValue = toNumber(level.nextValue);
|
|
var need = Math.max(0, nextValue - currentValue);
|
|
var denominator = Math.max(1, nextValue - currentRequired);
|
|
var currentInLevel = Math.max(0, currentValue - currentRequired);
|
|
var percent =
|
|
nextValue > currentRequired
|
|
? Math.min(
|
|
100,
|
|
Math.round((currentInLevel / denominator) * 100)
|
|
)
|
|
: 100;
|
|
|
|
$('currentLevel').textContent = t(
|
|
'host_center.level_value',
|
|
'Lv. {level}'
|
|
).replace('{level}', String(level.current || 0));
|
|
$('nextLevelNeed').textContent = money(need);
|
|
$('levelProgress').style.width = percent + '%';
|
|
$('levelStatus').textContent = t(
|
|
'host_center.in_progress',
|
|
'In progress'
|
|
);
|
|
}
|
|
|
|
function render() {
|
|
renderProfile();
|
|
renderIncome();
|
|
renderLevel();
|
|
}
|
|
|
|
function applyProfile(payload) {
|
|
var profile = unwrapData(payload);
|
|
if (!profile) return;
|
|
|
|
var name = firstValue(profile, [
|
|
'username',
|
|
'nickname',
|
|
'name',
|
|
'display_name',
|
|
]);
|
|
var uid = firstValue(profile, [
|
|
'display_user_id',
|
|
'default_display_user_id',
|
|
'uid',
|
|
'user_id',
|
|
]);
|
|
var avatar = firstValue(profile, ['avatar', 'avatar_url', 'avatarUrl']);
|
|
|
|
state.profile = {
|
|
name: name || state.profile.name,
|
|
uid: uid || state.profile.uid,
|
|
avatar:
|
|
avatar ||
|
|
avatarData(
|
|
initial(name || uid || state.profile.name),
|
|
'#dbc8ff',
|
|
'#7d57c7'
|
|
),
|
|
};
|
|
}
|
|
|
|
function applyRoleSummary(payload) {
|
|
var summary = unwrapData(payload);
|
|
if (!summary) return;
|
|
|
|
var agencyId = firstValue(summary, [
|
|
'agency_id',
|
|
'agencyId',
|
|
'host_agency_id',
|
|
'hostAgencyId',
|
|
]);
|
|
state.agency = {
|
|
shortId: agencyId ? String(agencyId) : '',
|
|
};
|
|
}
|
|
|
|
function displayAmountForAsset(assetType, amount) {
|
|
if (assetType === HOST_SALARY_USD) return toNumber(amount) / 100;
|
|
return toNumber(amount);
|
|
}
|
|
|
|
function findBalance(payload, assetType) {
|
|
var data = unwrapData(payload);
|
|
var balances =
|
|
data && Array.isArray(data.balances) ? data.balances : [];
|
|
for (var i = 0; i < balances.length; i += 1) {
|
|
if (
|
|
balances[i].asset_type === assetType ||
|
|
balances[i].assetType === assetType
|
|
) {
|
|
return balances[i];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function applyWallet(payload) {
|
|
var balance = findBalance(payload, HOST_SALARY_USD);
|
|
if (!balance) return;
|
|
|
|
var amount = firstValue(balance, [
|
|
'available_amount',
|
|
'availableAmount',
|
|
]);
|
|
state.salary = Object.assign({}, state.salary, {
|
|
available: displayAmountForAsset(HOST_SALARY_USD, amount),
|
|
monthKey: '',
|
|
month: '',
|
|
currencyKey: 'host_center.currency_usd',
|
|
currency: 'USD',
|
|
useCurrentMonth: true,
|
|
});
|
|
}
|
|
|
|
function pickLevelTrack(payload) {
|
|
var data = unwrapData(payload);
|
|
var tracks = data && Array.isArray(data.tracks) ? data.tracks : [];
|
|
if (!tracks.length) return null;
|
|
|
|
for (var i = 0; i < tracks.length; i += 1) {
|
|
if (tracks[i].track === HOST_LEVEL_TRACK) return tracks[i];
|
|
}
|
|
return tracks[0];
|
|
}
|
|
|
|
function applyLevel(payload) {
|
|
var track = pickLevelTrack(payload);
|
|
if (!track) return;
|
|
|
|
state.level = {
|
|
current: toNumber(
|
|
firstValue(track, ['level', 'current_level', 'currentLevel'])
|
|
),
|
|
currentRequired: toNumber(
|
|
firstValue(track, [
|
|
'current_level_required_value',
|
|
'currentLevelRequiredValue',
|
|
])
|
|
),
|
|
currentValue: toNumber(
|
|
firstValue(track, ['total_value', 'totalValue'])
|
|
),
|
|
nextValue: toNumber(
|
|
firstValue(track, [
|
|
'next_level_required_value',
|
|
'nextLevelRequiredValue',
|
|
'total_value',
|
|
'totalValue',
|
|
])
|
|
),
|
|
};
|
|
}
|
|
|
|
function toast(message) {
|
|
if (!message) return;
|
|
if (window.HyAppToast && window.HyAppToast.show) {
|
|
window.HyAppToast.show(message);
|
|
}
|
|
}
|
|
|
|
function loadRealData() {
|
|
if (isMockMode() || !window.HyAppAPI) return Promise.resolve(false);
|
|
if (window.HyAppParams && window.HyAppParams.parse) {
|
|
window.HyAppParams.parse();
|
|
}
|
|
if (!hasAccessToken()) return Promise.resolve(false);
|
|
|
|
return Promise.all([
|
|
safeRequest(function () {
|
|
return window.HyAppAPI.user.me();
|
|
}),
|
|
safeRequest(function () {
|
|
return window.HyAppAPI.user.roleSummary();
|
|
}),
|
|
safeRequest(function () {
|
|
return window.HyAppAPI.wallet.balances([HOST_SALARY_USD]);
|
|
}),
|
|
safeRequest(function () {
|
|
return window.HyAppAPI.level.overview();
|
|
}),
|
|
]).then(function (results) {
|
|
applyProfile(results[0]);
|
|
applyRoleSummary(results[1]);
|
|
applyWallet(results[2]);
|
|
applyLevel(results[3]);
|
|
render();
|
|
|
|
var hasAnyData = results.some(function (item) {
|
|
return !!item;
|
|
});
|
|
if (!hasAnyData) {
|
|
toast(
|
|
t(
|
|
'host_center.load_failed',
|
|
'Load failed. Try again later.'
|
|
)
|
|
);
|
|
}
|
|
return hasAnyData;
|
|
});
|
|
}
|
|
|
|
function openWithdrawExchange() {
|
|
var params = new URLSearchParams(window.location.search);
|
|
params.set('mode', params.get('mode') || 'transfer');
|
|
window.location.href =
|
|
'../withdraw-exchange/index.html?' + params.toString();
|
|
}
|
|
|
|
function bindEvents() {
|
|
$('backButton').addEventListener('click', function () {
|
|
if (window.HyAppBridge) window.HyAppBridge.back();
|
|
});
|
|
|
|
$('incomeWithdrawExchangeButton').addEventListener(
|
|
'click',
|
|
openWithdrawExchange
|
|
);
|
|
}
|
|
|
|
var initialized = false;
|
|
|
|
function init() {
|
|
if (initialized) return;
|
|
initialized = true;
|
|
render();
|
|
bindEvents();
|
|
loadRealData().then(function (loaded) {
|
|
if (window.HyAppBridge) {
|
|
window.HyAppBridge.ready({
|
|
page: 'host-center',
|
|
mock: !loaded,
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', init);
|
|
} else {
|
|
init();
|
|
}
|
|
|
|
window.addEventListener('hyapp:i18n-ready', function () {
|
|
render();
|
|
});
|
|
})();
|