import { renderHeader } from '../components/header.js'; import { renderUserAvatar } from '../components/avatar-image.js'; import { authService } from '../state.js'; import { navigateBack } from '../router.js'; import { userDisplayName } from '../services/user-display.js'; export const pageMeta = { id: 'user-profile-list-view', title: 'Список' }; function parseAvatar(raw) { const value = String(raw || ''); const m = value.match(/(?:^|,)\s*AR:([A-Za-z0-9_-]{43})(?:,|$)/); return m ? { ar: m[1] } : null; } const TITLES = { friends: 'Друзья', close_friends: 'Близкие друзья', primary_received: 'Подтвердили основной аккаунт', primary_given: 'Подтверждённые аккаунты', shine_received: 'Считают сияющим', shine_given: 'Подтверждённые сияющие', channels_owned: 'Каналы', channels_following: 'Подписки на каналы', }; export function render({ navigate, route }) { const login = String(route?.params?.login || '').trim(); const kind = String(route?.params?.kind || '').trim(); const screen = document.createElement('section'); screen.className = 'stack'; const body = document.createElement('div'); body.className = 'stack'; const status = document.createElement('div'); status.className = 'status-line'; status.textContent = 'Загрузка...'; screen.append(renderHeader({ title: TITLES[kind] || 'Список', leftAction: { label: '←', onClick: () => navigateBack() } }), status, body); (async () => { try { if (kind === 'channels_owned' || kind === 'channels_following') { const payload = await authService.listUserProfileChannels(login, kind === 'channels_owned' ? 'owned' : 'following', 200, 0); const rows = Array.isArray(payload?.channels) ? payload.channels : []; rows.forEach((row) => { const el = document.createElement('button'); el.type = 'button'; el.className = 'card row profile-list-row'; el.append(renderUserAvatar({ login: row.ownerLogin, firstName: row.displayName, lastName: '', avatar: parseAvatar(row.avatarAr), size: 'md' })); const t = document.createElement('div'); t.className = 'profile-list-row-text'; t.innerHTML = `${String(row.displayName || row.slug || '')}${String(row.ownerLogin || '')} / ${String(row.slug || '')}`; el.append(t); el.addEventListener('click', () => navigate(`channel/${encodeURIComponent(row.ownerBlockchainName)}/${Number(row.rootBlockNumber || 0)}/${encodeURIComponent(row.rootBlockHashHex || '')}/about`)); body.append(el); }); status.textContent = rows.length ? '' : 'Список пуст.'; return; } const payload = await authService.listUserProfileRelations(login, kind, 200, 0); const rows = Array.isArray(payload?.users) ? payload.users : []; rows.forEach((row) => { const el = document.createElement('button'); el.type = 'button'; el.className = 'card row profile-list-row'; el.append(renderUserAvatar({ login: row.login, firstName: row.firstName, lastName: row.lastName, avatar: parseAvatar(row.avatarAr), size: 'md' })); const fullName = userDisplayName(row); const t = document.createElement('div'); t.className = 'profile-list-row-text'; const marks = [ row.relationType && row.relationType !== 'none' ? ({contact:'контакт',friend:'друг',close_friend:'близкий друг'}[row.relationType] || row.relationType) : '', row.accountRole === 'primary' ? 'основной' : row.accountRole === 'non_voting' ? 'голос не учитывается' : '', row.shineStatus === 'shining' ? 'сияющий' : row.shineStatus === 'not_interested' ? 'сияние неинтересно' : '', row.primaryConfirmed ? 'основной подтверждён ✓' : '', row.shineConfirmed ? 'сияющий подтверждён ✓' : '', ].filter(Boolean).join(' · '); t.innerHTML = `${fullName}${String(row.login || '')}${marks ? ` · ${marks}` : ''}`; el.append(t); el.addEventListener('click', () => navigate(`SHiNE/${encodeURIComponent(row.login)}`)); body.append(el); }); status.textContent = rows.length ? '' : 'Список пуст.'; } catch (e) { status.className = 'status-line is-unavailable'; status.textContent = `Ошибка: ${e.message || 'unknown'}`; } })(); return screen; }