SHA256
57 lines
5.8 KiB
JavaScript
57 lines
5.8 KiB
JavaScript
import { renderHeader } from '../components/header.js';
|
|
import { state } from '../state.js';
|
|
import { loadUserProfileCard } from '../services/user-connections.js';
|
|
import { renderUserAvatar } from '../components/avatar-image.js';
|
|
import { makeProfileLinksRoute } from '../services/shine-routes.js';
|
|
import { navigateBack } from '../router.js';
|
|
|
|
export const pageMeta = { id: 'user', title: 'Профиль пользователя' };
|
|
|
|
function escapeHtml(text){return String(text||'').replaceAll('&','&').replaceAll('<','<').replaceAll('>','>').replaceAll('"','"').replaceAll("'",''');}
|
|
function fullName(card){return [card.firstName,card.lastName].filter(Boolean).join(' ')||card.login;}
|
|
|
|
function openTextModal(title,text){
|
|
const root=document.getElementById('modal-root'); if(!root)return;
|
|
root.innerHTML=`<div class="modal" id="profile-text-modal"><div class="modal-card stack"><h3>${escapeHtml(title)}</h3><div style="white-space:pre-wrap;line-height:1.5">${escapeHtml(text||'Не заполнено')}</div><button class="secondary-btn" id="profile-text-close">Закрыть</button></div></div>`;
|
|
const close=()=>{root.innerHTML='';}; root.querySelector('#profile-text-close')?.addEventListener('click',close); root.querySelector('#profile-text-modal')?.addEventListener('click',e=>{if(e.target?.id==='profile-text-modal')close();});
|
|
}
|
|
|
|
function statusBadges(card){
|
|
const role=card.accountRole==='primary'?'Основной аккаунт':card.accountRole==='non_voting'?'Голос не учитывать':'';
|
|
const shine=card.shineStatus==='shining'?'Сияющий':'';
|
|
return `<div class="row wrap-row">${role?`<span class="badge">${escapeHtml(role)}</span>`:''}${shine?'<span class="badge is-yes-shine">Сияющий</span>':''}${card.shineStatus==='not_interested'?'<span class="profile-shine-not-interested" title="Сияние неинтересно"><img src="/assets/shine-status-not-interested.svg" alt="Сияние неинтересно"></span>':''}</div>`;
|
|
}
|
|
|
|
function statsHtml(card){
|
|
const s=card.stats||{};
|
|
const rows=[
|
|
['friends','Друзья',s.friendsCount],['close_friends','Близкие друзья',s.closeFriendsCount],
|
|
['primary_received','Подтвердили основной аккаунт',s.primaryReceivedCount],['primary_given','Подтверждённые аккаунты',s.primaryGivenCount],
|
|
['shine_received','Считают сияющим',s.shineReceivedCount],['shine_given','Подтверждённые сияющие',s.shineGivenCount],
|
|
['channels_following','Подписки на каналы',s.followingChannelsCount],['channels_owned','Каналы',s.ownedPublicChannelsCount],
|
|
];
|
|
return `<div class="profile-stats-grid">${rows.map(([kind,label,n])=>`<button type="button" class="card profile-stat-card" data-profile-list="${kind}"><b>${Number(n||0)}</b><span>${escapeHtml(label)}</span></button>`).join('')}</div>`;
|
|
}
|
|
|
|
export function render({navigate,route}){
|
|
const requestedLogin=String(route?.params?.login||'').trim(); const selfLogin=String(state.session.login||'').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:'Профиль пользователя',leftAction:{label:'←',onClick:()=>navigateBack()}}),status,body);
|
|
let card=null;
|
|
async function refresh(){
|
|
card=await loadUserProfileCard(requestedLogin); const isSelf=card.login.toLowerCase()===selfLogin.toLowerCase();
|
|
body.innerHTML=`${statusBadges(card)}<div class="card profile-about" style="white-space:pre-wrap">${escapeHtml(card.about||'')}</div>${statsHtml(card)}
|
|
<div class="row wrap-row"><button class="secondary-btn" data-profile-detail="contacts">Контакты</button><button class="secondary-btn" data-profile-detail="spiritual">Духовный путь</button></div>
|
|
${!isSelf?`<div class="row profile-bottom-actions"><button class="icon-btn" data-bottom="chat" title="Диалог">💬</button><button class="icon-btn" data-bottom="links" title="Связи">✦</button><button class="primary-btn" data-bottom="add">Добавить</button></div>`:''}`;
|
|
const identity=document.createElement('div');identity.className='card row';identity.style.gap='12px';identity.style.alignItems='center';
|
|
identity.append(renderUserAvatar({login:card.login,firstName:card.firstName,lastName:card.lastName,avatar:card.avatar,size:'xl',className:'profile-avatar'}));
|
|
const txt=document.createElement('div');txt.innerHTML=`<div class="profile-identity-line">${escapeHtml(fullName(card))}</div><div class="profile-identity-login">${escapeHtml(card.login)}</div>`;identity.append(txt);body.prepend(identity);status.textContent='';
|
|
}
|
|
body.addEventListener('click',e=>{const el=e.target.closest('[data-profile-list],[data-profile-detail],[data-bottom]');if(!el||!card)return;
|
|
const list=el.dataset.profileList;if(list){navigate(`SHiNE/${encodeURIComponent(card.login)}/list/${encodeURIComponent(list)}`);return;}
|
|
const detail=el.dataset.profileDetail;if(detail==='contacts'){openTextModal('Контакты',[card.web?`Links: ${card.web}`:'',card.phone?`Телефон: ${card.phone}`:'',card.address?`Адрес: ${card.address}`:''].filter(Boolean).join('\n')||'Не заполнено');return;} if(detail==='spiritual'){openTextModal('Духовный путь',card.spiritualPath);return;}
|
|
const bottom=el.dataset.bottom;if(bottom==='chat')navigate(`chat/${encodeURIComponent(card.login)}`);if(bottom==='links')navigate(makeProfileLinksRoute(card.login));if(bottom==='add')navigate(`SHiNE/${encodeURIComponent(card.login)}/manage`);
|
|
});
|
|
refresh().catch(e=>{status.className='status-line is-unavailable';status.textContent=`Ошибка: ${e.message||'unknown'}`;}); return screen;
|
|
}
|