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 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: 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;
}