10 KiB
2026-05-21 — Avatar & Display Name Fixes
Overview
8 замечаний по отображению аватаров, имён, ссылок и stock-статусов в админке и на клиенте.
Approach
Локальные изолированные правки (Подход 1). Каждый пункт правится в своём контексте без переиспользования общих компонентов с /me — минимизирует риск регрессии.
1. Admin settings page (/admin/settings)
Проблема: Админ не может настроить displayName/avatar. Страница /me/settings существует, но админ редиректится с /me на /admin.
Решение:
- Новая FSD-страница
client/src/pages/admin-settings/ - Пункт «Настройки» в сайдбаре
AdminLayoutPage(после «Уведомления») - Форма: редактирование
displayName, выбор/генерация аватара (DiceBear, 16 стилей), загрузка своего аватара. Копирует UI с/me/settings(SettingsPage), но как отдельный компонент, не шаринг. - API:
GET /api/admin/profileиPATCH /api/admin/profile(новый роут вserver/src/routes/api/) - Роут защищён
verifyAdmin, работает с полями:displayName,avatar,avatarType,avatarStyle - После сохранения — инвалидация
$userстора на клиенте, чтобы хедер подхватил новый аватар
Файлы:
client/src/pages/admin-settings/ui/AdminSettingsPage.tsx(новый)client/src/pages/admin-layout/ui/AdminLayoutPage.tsx(добавить пункт меню)server/src/routes/api/admin-profile.js(новый)server/src/index.js(зарегистрировать роут)
2. Admin avatar in header
Проблема: В хедере админ видит только кнопку «Выход», без аватара.
Решение:
- В
AppHeaderдля админа:IconButtonсUserAvatar+ выпадающее меню с пунктами «Настройки» (/admin/settings) и «Выход» - Аватар из
AuthUser.avatar/avatarType/avatarStyle, при отсутствии — DiceBear fallback - Компонент по аналогии с
UserMenu, но упрощённый: только 2 пункта, без профиля покупателя. Можно сделать какAdminUserMenuвfeatures/user/user-menu/или прямо вAppHeader
Файлы:
client/src/app/layout/AppHeader.tsx(заменить кнопку «Выход» на меню с аватаром)
3. Avatar column in admin users table
Проблема: В таблице пользователей (/admin/users) нет колонки с аватарами.
Решение:
AdminUserтип (entities/user/model/types.ts): добавитьavatar,avatarType,avatarStyle(опциональные)- Серверный
GET /api/admin/users: добавить эти поля в SELECT AdminUsersPage: колонка «Аватар» первой (перед email), рендер через<UserAvatar size={28} />
Файлы:
client/src/entities/user/model/types.tsclient/src/pages/admin-users/ui/AdminUsersPage.tsxserver/src/routes/api/admin-users.js
4. Avatars in order messages
Проблема: ChatMessageBubble показывает только текст «Админ»/«Вы»/«Пользователь», без аватаров.
Решение:
ChatMessageBubble: добавить опциональный пропavatar?: ReactNode— рендерится слева от сообщения дляauthorType='admin', справа для'user'OrderChat(пользователь): для админских сообщений — DiceBear по'admin'seed, для своих — аватар изAuthUserOrderDetailContent(админ): для пользователя — аватар изorder.user.avatar/avatarType/avatarStyle, для админа — изAuthUser- API
GET /api/orders/:idиGET /api/admin/orders/:id: добавитьuser { avatar, avatarType, avatarStyle }в ответ - Клиентский тип заказа: добавить эти поля в
user
Файлы:
client/src/shared/ui/ChatMessageBubble.tsxclient/src/features/order-chat/ui/OrderChat.tsxclient/src/features/order-detail/ui/OrderDetailContent.tsxserver/src/routes/user-orders.js(GET /:id)server/src/routes/api/admin-orders.js(GET /:id)- Типы заказа на клиенте
5. Actual user avatars in reviews
Проблема: В отзывах всегда генерируется DiceBear по строке authorDisplay, а не используется реальный аватар пользователя.
Решение:
- API
public-reviews: добавитьauthorAvatar,authorAvatarType,authorAvatarStyleв ответ (изuser.avatar/avatarType/avatarStyle) - Тип
PublicProductReviewItemиPublicReviewFeedItem: добавить эти поля ReviewsBlockиProductReviewsList: передавать реальные значения вUserAvatarвместоnull
Файлы:
server/src/routes/api/public-reviews.jsclient/src/entities/review/api/reviews-api.ts(типы)client/src/widgets/reviews-block/ui/ReviewsBlock.tsxclient/src/features/product-review/ui/ProductReviewsList.tsxserver/src/routes/api/admin-reviews.js(тоже может использовать)
6. Product link in reviews only if published
Проблема: В ReviewsBlock ссылка на товар показывается всегда, даже если товар скрыт из каталога.
Решение:
- API
public-reviews: добавить объектproduct: { id, title, published, slug }в каждый элемент фида - Тип
PublicReviewFeedItem: обновить поле сproductId/productTitleнаproduct: { id, title, published, slug } ReviewsBlock: еслиproduct.published === true— ссылка<RouterLink>, иначе — просто текст<Typography>
Файлы:
server/src/routes/api/public-reviews.jsclient/src/entities/review/api/reviews-api.tsclient/src/widgets/reviews-block/ui/ReviewsBlock.tsx
7. "Out of stock" chip visibility in catalog
Проблема: Чип «Нет в наличии» существует в DOM, но визуально не виден в каталоге.
Решение:
- Проверить
z-indexчипа вProductCard— поднять выше (напримерzIndex: 2), чтобы не перекрывалсяCardMediaили другими элементами - Предположительно проблема в том, что чип рендерится до изображения в DOM, и изображение перекрывает его по z-order
Файлы:
client/src/entities/product/ui/ProductCard.tsx
8. Person icon for unauthenticated users
Проблема: До авторизации в хедере нет иконки пользователя.
Решение:
- В
AppHeader: когдаuser === nullи!loading, показыватьIconButtonсPersonIcon, ведущую на/auth - Сейчас
UserMenuне рендерится безuser— добавить условиеuser ? <UserMenu ...> : <IconButton href="/auth"><PersonIcon /></IconButton>
Файлы:
client/src/app/layout/AppHeader.tsx
Data flow summary
┌─ Admin settings ─────────────────────────────────────┐
│ PATCH /api/admin/profile → DB → invalidate $user │
│ → AppHeader reads $user.avatar → UserAvatar │
└───────────────────────────────────────────────────────┘
┌─ Admin users table ───────────────────────────────────┐
│ GET /api/admin/users → { ..., avatar, avatarType, │
│ avatarStyle } → AdminUsersPage → <UserAvatar /> │
└───────────────────────────────────────────────────────┘
┌─ Order chat ──────────────────────────────────────────┐
│ GET /api/orders/:id → { user: { avatar, ... } } │
│ → OrderChat → ChatMessageBubble(avatar={<UserAvatar/>})│
│ Admin avatar: from AuthUser store │
└───────────────────────────────────────────────────────┘
┌─ Reviews ─────────────────────────────────────────────┐
│ GET /api/public-reviews → { authorAvatar, ..., │
│ product: { published, ... } } │
│ → ReviewsBlock/ProductReviewsList → UserAvatar + link│
└───────────────────────────────────────────────────────┘
Testing
- Client unit tests: Проверить рендер аватаров в
ProductReviewsList,ReviewsBlock,AdminUsersPage,ChatMessageBubble,AppHeaderдля разных состояний (авторизован/неавторизован/админ) - Server tests: Проверить новые поля в ответах API
- Manual: Проверить видимость чипа «Нет в наличии», отображение ссылки в отзывах для published/unpublished товаров