import { renderHeader } from '../components/header.js'; import { authService, state } from '../state.js'; import { buildAvatarInitials, buildIdentityLines, loadRelationsForPair, loadUserProfileCard, } from '../services/user-connections.js'; export const pageMeta = { id: 'user-profile-view', title: 'Чужой профиль' }; function escapeHtml(text) { return String(text || '') .replaceAll('&', '&') .replaceAll('<', '<') .replaceAll('>', '>') .replaceAll('"', '"') .replaceAll("'", '''); } function boolText(flag) { return flag ? 'Да' : 'Нет'; } function genderText(value) { const normalized = String(value || '').trim().toLowerCase(); if (normalized === 'male') return 'Мужской'; if (normalized === 'female') return 'Женский'; return 'Не указан'; } function relationButtonLabel(kind, flags) { if (kind === 'follow') return flags.outFollow ? 'Отписаться' : 'Подписаться'; if (kind === 'friend') return flags.outFriend ? 'Убрать из друзей' : 'Добавить в друзья'; return flags.outContact ? 'Убрать из контактов' : 'Добавить в контакты'; } function relationNextState(kind, flags) { if (kind === 'follow') return !flags.outFollow; if (kind === 'friend') return !flags.outFriend; return !flags.outContact; } function relationConfirmLabel(kind) { if (kind === 'follow') return 'подписку'; if (kind === 'friend') return 'дружбу'; return 'контакт'; } function renderIdentity(card) { const lines = buildIdentityLines({ login: card.login, firstName: card.firstName, lastName: card.lastName, }); return `
${escapeHtml(buildAvatarInitials(card))}
${lines.map((line, idx) => ( `
${escapeHtml(line)}
` )).join('')}
`; } function renderReadOnlyBadges(card) { return `
Официальный: ${card.official ? 'Yes' : 'No'} Сияющий: ${card.shine ? 'Yes' : 'No'}
`; } function renderRelations(flags) { return `
Вы подписаны:${boolText(flags.outFollow)}
Подписан на вас:${boolText(flags.inFollow)}
Вы добавили в друзья:${boolText(flags.outFriend)}
Добавил вас в друзья:${boolText(flags.inFriend)}
Вы добавили в контакты:${boolText(flags.outContact)}
Добавил вас в контакты:${boolText(flags.inContact)}
`; } function renderReadOnlyParams(card) { const rows = [ { label: 'Имя', value: card.firstName }, { label: 'Фамилия', value: card.lastName }, { label: 'Пол', value: genderText(card.gender) }, { label: 'Адрес', value: card.address }, { label: 'Web', value: card.web }, { label: 'Телефон', value: card.phone }, ]; return `
${rows.map((row) => `
${row.label}: ${escapeHtml(String(row.value || '').trim() || 'не заполнено')}
`).join('')}
`; } export function render({ navigate, route }) { const requestedLogin = String(route.params.login || '').trim(); const fromPage = String(route.params.fromPage || 'messages-list').trim() || 'messages-list'; const sessionLogin = String(state.session.login || '').trim(); const screen = document.createElement('section'); screen.className = 'stack'; const status = document.createElement('div'); status.className = 'status-line'; status.textContent = 'Загрузка профиля...'; const body = document.createElement('div'); body.className = 'stack'; screen.append( renderHeader({ title: 'Профиль пользователя', leftAction: { label: '←', onClick: () => navigate(fromPage) }, rightActions: [{ label: 'Обновить', onClick: () => refresh() }], }), status, body, ); let currentCard = null; let currentFlags = null; let isBusy = false; function syncActionButtons() { const followBtn = body.querySelector('[data-relation-action="follow"]'); const friendBtn = body.querySelector('[data-relation-action="friend"]'); const contactBtn = body.querySelector('[data-relation-action="contact"]'); if (!followBtn || !friendBtn || !contactBtn || !currentFlags) return; const isSelf = currentCard && currentCard.login.toLowerCase() === sessionLogin.toLowerCase(); followBtn.textContent = relationButtonLabel('follow', currentFlags); friendBtn.textContent = relationButtonLabel('friend', currentFlags); contactBtn.textContent = relationButtonLabel('contact', currentFlags); followBtn.disabled = Boolean(isSelf); friendBtn.disabled = Boolean(isSelf); contactBtn.disabled = Boolean(isSelf); } async function refresh() { if (!requestedLogin) { status.className = 'status-line is-unavailable'; status.textContent = 'Не передан login пользователя.'; return; } isBusy = true; status.className = 'status-line'; status.textContent = 'Загрузка профиля...'; try { const card = await loadUserProfileCard(requestedLogin); const flags = await loadRelationsForPair({ currentLogin: sessionLogin, targetLogin: card.login, }); currentCard = card; currentFlags = flags; body.innerHTML = `
${renderIdentity(card)}
${renderReadOnlyBadges(card)} ${renderRelations(flags)} ${renderReadOnlyParams(card)}
`; syncActionButtons(); status.className = 'status-line is-available'; status.textContent = 'Профиль обновлён.'; } catch (error) { status.className = 'status-line is-unavailable'; status.textContent = `Ошибка загрузки профиля: ${error.message || 'unknown'}`; window.alert(`Не удалось загрузить профиль: ${error.message || 'unknown'}`); } finally { isBusy = false; } } async function onRelationAction(kind) { if (isBusy || !currentCard || !currentFlags) return; if (!sessionLogin) { window.alert('Для изменения связей нужен активный вход.'); return; } if (!state.session.storagePwdInMemory) { window.alert('Нет storagePwd в памяти сессии. Выполните вход заново.'); return; } const nextEnabled = relationNextState(kind, currentFlags); const confirmed = window.confirm( `Изменить ${relationConfirmLabel(kind)} с пользователем ${currentCard.login}?\n` + 'Будет отправлен AddBlock CONNECTION.', ); if (!confirmed) return; isBusy = true; status.className = 'status-line'; status.textContent = 'Сохранение отношения в блокчейн...'; try { await authService.setUserRelation({ login: sessionLogin, toLogin: currentCard.login, kind, enabled: nextEnabled, storagePwd: state.session.storagePwdInMemory, }); await refresh(); } catch (error) { status.className = 'status-line is-unavailable'; status.textContent = `Ошибка изменения связи: ${error.message || 'unknown'}`; window.alert(`Не удалось изменить связь: ${error.message || 'unknown'}`); isBusy = false; } } body.addEventListener('click', (event) => { const target = event.target; if (!(target instanceof HTMLElement)) return; const kind = target.dataset.relationAction; if (!kind) return; onRelationAction(kind); }); refresh(); return screen; }