- index.html: <nav id="tabbar" hidden> - app.js: updateTabbar() — скрыть/показать по loggedIn - emailLogin: onLogin() после успеха - settings.logout: onLogout() + POST /auth/logout - backend: POST /auth/logout — чистит cookie
117 lines
5.7 KiB
JavaScript
117 lines
5.7 KiB
JavaScript
// Settings view + consent gate + user profile (public)
|
||
const SettingsView = {
|
||
async render(root) {
|
||
const u = API.Store.user;
|
||
root.innerHTML = `
|
||
<div class="view">
|
||
<h1>⚙️ Настройки</h1>
|
||
<div class="card">
|
||
<div style="font-weight:600;">${escapeHtml(u?.name || '')}</div>
|
||
${u?.telegram_id ? `<div class="sub">Telegram ID: ${u.telegram_id}</div>` : ''}
|
||
${u?.email ? `<div class="sub">${escapeHtml(u.email)}</div>` : ''}
|
||
</div>
|
||
<div class="card">
|
||
<strong>Юридические документы</strong>
|
||
<div class="sub">
|
||
Версия 1.0 · 20.08.2026
|
||
</div>
|
||
<a class="btn ghost" href="/legal/TERMS.html" target="_blank" style="margin-top:8px;">📄 Пользовательское соглашение</a>
|
||
<a class="btn ghost" href="/legal/PRIVACY.html" target="_blank">🔒 Политика конфиденциальности</a>
|
||
<a class="btn ghost" href="/legal/DISCLAIMER.html" target="_blank">⚠️ Отказ от ответственности</a>
|
||
</div>
|
||
<button class="btn danger" id="logout">Выйти</button>
|
||
</div>
|
||
`;
|
||
document.getElementById('logout').onclick = async () => {
|
||
const ok = await TG_APP.showConfirm('Выйти из BuhApp?');
|
||
if (!ok) return;
|
||
// очистим cookie на бэкенде (best-effort, без await)
|
||
try { await fetch('https://api.buhapp.mygoodservice.ru/api/v1/auth/logout', { method: 'POST', credentials: 'include' }); } catch {}
|
||
App.onLogout();
|
||
location.reload();
|
||
};
|
||
},
|
||
};
|
||
|
||
// Public user profile (включая рейтинг и кнопку "написать")
|
||
const UserProfileView = {
|
||
async render(root, params) {
|
||
const userId = params.userId;
|
||
const name = params.name || '';
|
||
root.innerHTML = '<div class="view"><div class="loader">Загрузка...</div></div>';
|
||
try {
|
||
const [profile, stats] = await Promise.all([
|
||
API.Auth.getUser(userId),
|
||
API.ReviewApi.stats(userId),
|
||
]);
|
||
root.innerHTML = `
|
||
<div class="view">
|
||
<button class="btn ghost" id="up-back" style="width:auto;margin-bottom:12px;">← Назад</button>
|
||
<div class="card">
|
||
<div style="display:flex;align-items:center;gap:16px;">
|
||
${profile.photo ? `<div class="avatar" style="width:80px;height:80px;background-image:url(${profile.photo});"></div>` :
|
||
`<div class="avatar" style="width:80px;height:80px;font-size:32px;">${escapeHtml((profile.name||'?')[0])}</div>`}
|
||
<div>
|
||
<div style="font-size:22px;font-weight:700;">${escapeHtml(profile.name || '')}</div>
|
||
${profile.city ? `<div class="sub">📍 ${escapeHtml(profile.city)}</div>` : ''}
|
||
${profile.age ? `<div class="sub">${profile.age} лет</div>` : ''}
|
||
</div>
|
||
</div>
|
||
<div style="display:flex;align-items:center;gap:12px;margin-top:12px;">
|
||
<div class="rating-big">${stats.rating_avg ? stats.rating_avg.toFixed(1) : '—'}</div>
|
||
<div>
|
||
<div class="stars" style="font-size:18px;">
|
||
${[1,2,3,4,5].map(n=>`<span class="${n<=Math.round(stats.rating_avg||0)?'on':''}">★</span>`).join('')}
|
||
</div>
|
||
<div class="sub">${stats.rating_count || 0} отзывов</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
${profile.bio ? `<div class="card"><strong>О себе</strong><div style="margin-top:6px;">${escapeHtml(profile.bio)}</div></div>` : ''}
|
||
|
||
${profile.prefs ? this.renderPrefs(profile.prefs) : ''}
|
||
|
||
<button class="btn" id="up-chat">💬 Написать</button>
|
||
<button class="btn ghost" id="up-reviews">⭐ Все отзывы (${stats.rating_count || 0})</button>
|
||
<button class="btn danger" id="up-block">🚫 Заблокировать</button>
|
||
<button class="btn ghost" id="up-report">⚠️ Пожаловаться</button>
|
||
</div>
|
||
`;
|
||
|
||
document.getElementById('up-back').onclick = () => history.back();
|
||
document.getElementById('up-chat').onclick = async () => {
|
||
try {
|
||
const chat = await API.ChatApi.ensureChat(userId);
|
||
App.openChat(chat.id, userId, profile.name);
|
||
} catch (e) { TG_APP.showAlert('Ошибка: ' + e.message); }
|
||
};
|
||
document.getElementById('up-reviews').onclick = () => App.showView('user-reviews', { userId, userName: profile.name });
|
||
document.getElementById('up-block').onclick = async () => {
|
||
const ok = await TG_APP.showConfirm('Заблокировать ' + profile.name + '?');
|
||
if (!ok) return;
|
||
try { await API.ChatApi.block(userId); TG_APP.showAlert('Заблокировано'); history.back(); }
|
||
catch (e) { TG_APP.showAlert('Ошибка: ' + e.message); }
|
||
};
|
||
document.getElementById('up-report').onclick = async () => {
|
||
const reason = prompt('Причина жалобы:');
|
||
if (!reason) return;
|
||
try { await API.ChatApi.report('user', userId, reason); TG_APP.showAlert('Жалоба отправлена'); }
|
||
catch (e) { TG_APP.showAlert('Ошибка: ' + e.message); }
|
||
};
|
||
} catch (e) {
|
||
root.innerHTML = '<div class="view"><div class="empty">Ошибка: ' + e.message + '</div></div>';
|
||
}
|
||
},
|
||
|
||
renderPrefs(p) {
|
||
const blocks = [];
|
||
if (p.drinks?.length) {
|
||
blocks.push(`<div class="card"><strong>Предпочтения</strong><div style="margin-top:6px;">${p.drinks.map(d => `<span class="chip">${escapeHtml(d)}</span>`).join('')}</div></div>`);
|
||
}
|
||
return blocks.join('');
|
||
},
|
||
};
|
||
|
||
window.SettingsView = SettingsView;
|
||
window.UserProfileView = UserProfileView; |