Files
SHiNE-server/shine-UI/js/pages/profile-view.js
T
qandClaude Opus 5.5 f8900e531a UI: новый общий стиль, тёмная/светлая тема, настраиваемая палитра
- styles/main.css: роли цветов (по умолчанию «Индиго»), шкала отступов/скруглений/шрифтов,
  цвета отношений для обеих тем; жёсткие цвета в стилях заменены на роли.
- Палитра: пресеты и личные правки, «Оформление» Авто/День/Ночь, долгое нажатие —
  редактор цветов с экспортом/импортом.
- Каналы: пузыри постов автора, плашки дней, строка «Написать в канал…», «О канале»,
  создание канала с адресом из названия; лента открывается на свежих постах.
- Чаты: плоский список, чипы-фильтры, пузыри, плашки дней; нижняя панель скрыта в переписке.
- Корневые разделы — единая шапка; профиль и чужой профиль — общая карточка;
  настройки, кошелёк, сеансы — меню-списки.
- Нижняя панель: иконки без подписей, бейджи на иконках.
- confirmDialog вместо window.confirm/alert; на телефоне диалоги — шторки снизу.
- docs/UI-Design/ISSUES-for-dev.md — найденные ошибки сервера/UI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:05:26 +03:00

103 lines
4.0 KiB
JavaScript

import { profile } from '../mock-data.js';
import { state } from '../state.js';
import { renderUserAvatar } from '../components/avatar-image.js';
import { createTopBar } from '../components/topbar.js';
import { loadUserProfileCard } from '../services/user-connections.js';
import { profileCardHtml, profileTileHtml } from '../components/profile-card.js';
export const pageMeta = { id: 'profile-view', title: 'Профиль' };
export function render({ navigate, chrome }) {
const login = String(state.session.login || profile.login || '').trim();
const screen = document.createElement('section');
screen.className = 'stack user-profile-screen';
const topbar = createTopBar({
title: 'Профиль',
className: 'topbar--root user-profile-header',
});
chrome?.setTopbar(topbar);
const status = document.createElement('div');
status.className = 'status-line user-profile-status';
status.textContent = 'Загрузка профиля...';
const body = document.createElement('div');
body.className = 'user-profile-body';
screen.append(status, body);
let card = null;
function renderProfile() {
if (!card) return;
const official = card.accountRole === 'primary';
const shining = card.shineStatus === 'shining';
body.innerHTML = profileCardHtml({
card,
login,
tilesHtml: [
profileTileHtml({ icon: 'edit', label: 'Редактировать', attrs: 'data-self-profile-action="edit"' }),
profileTileHtml({ icon: 'wallet', label: 'Кошелёк', attrs: 'data-self-profile-action="wallet"' }),
profileTileHtml({ icon: 'settings', label: 'Настройки', attrs: 'data-self-profile-action="settings"' }),
].join(''),
}) + `
<div class="nav-list profile-more-list">
<button class="nav-row" type="button" data-profile-list="primary_given"><span class="nav-row__label">Подтверждённые мной аккаунты</span><span class="nav-row__hint">Аккаунты, за которые вы поручились</span></button>
<button class="nav-row" type="button" data-profile-list="shine_given"><span class="nav-row__label">Отмеченные мной как сияющие</span></button>
<button class="nav-row" type="button" data-self-profile-action="profiles"><span class="nav-row__label">Сменить профиль</span><span class="nav-row__hint">Другие аккаунты на этом устройстве</span></button>
</div>`;
const avatarSlot = body.querySelector('.user-profile-avatar-slot');
avatarSlot?.append(renderUserAvatar({
login: card.login,
firstName: card.firstName,
lastName: card.lastName,
avatar: card.avatar,
size: 'xl',
className: 'user-profile-hero-avatar',
glow: shining,
official,
}));
status.textContent = '';
}
body.addEventListener('click', (event) => {
if (!card) return;
const listButton = event.target.closest('[data-profile-list]');
if (listButton) {
const kind = listButton.dataset.profileList;
if (kind) navigate(`SHiNE/${encodeURIComponent(card.login)}/list/${encodeURIComponent(kind)}`);
return;
}
const actionButton = event.target.closest('[data-self-profile-action]');
if (actionButton) {
const action = actionButton.dataset.selfProfileAction;
if (action === 'edit') navigate('profile-edit-view');
if (action === 'wallet') navigate('wallet-view');
if (action === 'settings') navigate('settings-view');
if (action === 'profiles') navigate('profiles-view');
return;
}
});
async function refresh() {
if (state.session.isLocalDemo) {
status.textContent = 'Локальный тестовый режим.';
return;
}
card = await loadUserProfileCard(login);
renderProfile();
}
refresh().catch((error) => {
status.className = 'status-line user-profile-status is-unavailable';
status.textContent = `Ошибка: ${error?.message || 'unknown'}`;
});
return screen;
}