From f6fa3fedab46d787ba861eb33eca71f0fa2d7fdc Mon Sep 17 00:00:00 2001 From: root Date: Fri, 21 Aug 2026 11:59:09 +0000 Subject: [PATCH] =?UTF-8?q?Fix:=20UserProfileView=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D1=82=D0=B0=D0=BF=D0=B0=20=D0=BD=D0=B0=20=D0=BC=D0=B0=D1=80?= =?UTF-8?q?=D0=BA=D0=B5=D1=80=20=D1=87=D0=B5=D0=BB=D0=BE=D0=B2=D0=B5=D0=BA?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Проблема: app.js вызывал UserProfileView.render при showView('user-profile'), но view был не создан. ReferenceError. Создал UserProfileView в profile.js: - Читает /users/:id + /users/:id/stats - Card с avatar-b.lg, name, city, ★ rating (если есть отзывы) - bio - Кнопки: 'Написать' (ensureChat → openChat) + 'Все отзывы' (UserReviewsView) - Error/toast на любой сбой API: добавил UserApi.get|reviews|stats namespace. --- public/index.html | 22 +++++----- public/js/api.js | 7 +++ public/js/views/profile.js | 89 +++++++++++++++++++++++++++++++++++++- 3 files changed, 106 insertions(+), 12 deletions(-) diff --git a/public/index.html b/public/index.html index 1b54461..6127380 100644 --- a/public/index.html +++ b/public/index.html @@ -8,7 +8,7 @@ - + @@ -34,15 +34,15 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/public/js/api.js b/public/js/api.js index 3b80112..4f1c70c 100644 --- a/public/js/api.js +++ b/public/js/api.js @@ -103,6 +103,13 @@ const Auth = { getUser: function (id) { return apiGet('/api/v1/users/' + id); }, }; +// === API namespaces === +const UserApi = { + get: function (userId) { return apiGet('/api/v1/users/' + userId); }, + reviews: function (userId) { return apiGet('/api/v1/users/' + userId + '/reviews'); }, + stats: function (userId) { return apiGet('/api/v1/users/' + userId + '/stats'); }, +}; + const ChatApi = { ensureChat: function (otherId) { return apiPost('/api/v1/chats', { other_id: otherId }); }, listChats: function () { return apiGet('/api/v1/chats'); }, diff --git a/public/js/views/profile.js b/public/js/views/profile.js index 312dd37..0dd6533 100644 --- a/public/js/views/profile.js +++ b/public/js/views/profile.js @@ -198,4 +198,91 @@ const ProfileView = { }, }; -window.ProfileView = ProfileView; \ No newline at end of file +window.ProfileView = ProfileView; + +// UserProfileView — чужой профиль (read-only) — открывается по тапу на маркер на карте +const UserProfileView = { + userId: null, + userName: null, + data: null, + + async render(root, params) { + this.userId = params.userId; + this.userName = params.name || 'Пользователь'; + root.innerHTML = ` +
+

👤 ${escapeHtml(this.userName)}

+
${'
⏳ Загружаю…
'}
+
+ `; + try { + const [user, stats] = await Promise.all([ + API.UserApi.get(this.userId), + API.ReviewApi.stats(this.userId).catch(() => ({})), + ]); + this.data = user.user || user; + const u = this.data; + const init = ((u.name || u.email || '?')[0] || '?').toUpperCase(); + const rating = stats.rating_avg ? Number(stats.rating_avg).toFixed(1) : '—'; + const reviewsCount = stats.rating_count || 0; + + document.getElementById('up-content').innerHTML = ` + +
+
${u.photo_url ? '' : init}
+
+
${escapeHtml(u.name || '')}
+ ${u.city ? `
📍 ${escapeHtml(u.city)}
` : ''} + ${reviewsCount > 0 ? `
★ ${rating} · ${reviewsCount} ${pluralRu(reviewsCount, 'отзыв', 'отзыва', 'отзывов')}
` : ''} +
+
+ + + ${u.bio ? ` +
+
О себе
+
${escapeHtml(u.bio)}
+
+ ` : ''} + + +
+ + ${reviewsCount > 0 ? `` : ''} +
+ `; + + const msgBtn = document.getElementById('up-message'); + if (msgBtn) msgBtn.onclick = async () => { + msgBtn.className = 'btn-b load'; + msgBtn.textContent = '⏳ Открываем…'; + try { + const r = await API.ChatApi.ensureChat(this.userId); + const cid = r.chat_id || r.chat?.id; + if (!cid) throw new Error('chat not created'); + App.openChat(cid, this.userId, u.name); + } catch (e) { + msgBtn.className = 'btn-b err'; + msgBtn.textContent = '⚠️ ' + (e.message || 'Ошибка'); + App._toast('Не удалось открыть чат', 'err'); + setTimeout(() => { msgBtn.className = 'btn-b'; msgBtn.textContent = '💬 Написать'; }, 2000); + } + }; + + const revBtn = document.getElementById('up-reviews'); + if (revBtn) revBtn.onclick = () => UserReviewsView.render(root, { userId: this.userId, userName: u.name }); + } catch (e) { + document.getElementById('up-content').innerHTML = `
⚠️ Не удалось загрузить
`; + App._toast('Ошибка загрузки профиля', 'err'); + } + }, +}; + +window.UserProfileView = UserProfileView; + +function pluralRu(n, one, few, many) { + const mod10 = n % 10, mod100 = n % 100; + if (mod10 === 1 && mod100 !== 11) return one; + if (mod10 >= 2 && mod10 <= 4 && (mod100 < 10 || mod100 >= 20)) return few; + return many; +} \ No newline at end of file