// Profile — user stats, cashback, referrals, settings.
// One stat row inside the hero card — icon + label on the left, value on the right.
function StatRow({ icon: I, label, value, accent }) {
return (
);
}
function SettingsRow({ icon: I, title, sub, right, danger, onClick }) {
return (
{right !== undefined ? right :
}
);
}
function ProfileScreen() {
const [notif, setNotif] = React.useState(true);
const [sound, setSound] = React.useState(() => (window.SFX ? window.SFX.isEnabled() : false));
const toggleSound = (on) => { setSound(on); if (window.SFX) window.SFX.setEnabled(on); };
const openTgLink = (url) => {
try {
const tg = window.Telegram && window.Telegram.WebApp;
if (tg && tg.openTelegramLink) tg.openTelegramLink(url);
else window.open(url, '_blank', 'noopener');
} catch (_) {}
};
// Реальный профиль из GET /me (имя/username/потрачено/куплено).
const meState = (window.DataSource && window.DataSource.useMe) ? window.DataSource.useMe() : { data: null };
const me = meState.data || null;
const u = (me && me.user) || {};
const dispName = [u.first_name, u.last_name].filter(Boolean).join(' ') || (u.username ? '@' + u.username : 'Гость');
const dispUser = u.username ? '@' + u.username : (u.id ? 'id' + u.id : '');
const avatarCh = String(u.first_name || u.username || '?').trim().charAt(0).toUpperCase() || '?';
const spent = me ? Math.round(me.total_spent_rub || 0) : 0;
const boughtN = me ? (me.orders || []).filter(o => o.status === 'success' && (o.kind === 'purchase' || o.kind === 'buy')).length : 0;
const totalN = me ? (me.orders_total || 0) : 0;
return (
{/* user header */}
Уведомления и язык
Push в Telegram
Новые сделки, выгодные предложения
Звуки сделок
Лёгкий щелчок при покупке
Поддержка
openTgLink('https://t.me/portals_rub_help')} />
vMarket — маркет NFT-подарков
● онлайн
{/* Атрибуция обязательна: данные о моделях/фонах/символах берём из @GiftChanges
(api.changes.tg). Убирать нельзя — условие использования их API. */}
Данные о подарках — @GiftChanges
);
}
window.ProfileScreen = React.memo(ProfileScreen);