feat: public admin avatar endpoint, real admin avatar in user chat

This commit is contained in:
Kirill
2026-05-21 21:50:07 +05:00
parent 367ea1e501
commit f6729210db
4 changed files with 42 additions and 1 deletions
+11
View File
@@ -30,6 +30,17 @@ export async function updateAdminUser(
return data
}
export type AdminAvatarResponse = {
avatar: string | null
avatarType: string | null
avatarStyle: string | null
}
export async function fetchAdminAvatar(): Promise<AdminAvatarResponse> {
const { data } = await apiClient.get<AdminAvatarResponse>('admin/avatar')
return data
}
export async function deleteAdminUser(id: string): Promise<void> {
await apiClient.delete(`admin/users/${id}`)
}
@@ -3,7 +3,9 @@ import Box from '@mui/material/Box'
import Button from '@mui/material/Button'
import Stack from '@mui/material/Stack'
import Typography from '@mui/material/Typography'
import { useQuery } from '@tanstack/react-query'
import { useUnit } from 'effector-react'
import { fetchAdminAvatar } from '@/entities/user/api/user-api'
import { $user } from '@/shared/model/auth'
import { ChatMessageBubble } from '@/shared/ui/ChatMessageBubble'
import { OrderMessageBody } from '@/shared/ui/OrderMessageBody'
@@ -29,6 +31,12 @@ export function OrderChat({ messages, isPending, onSend }: Props) {
const canSend = text.replace(/<[^>]*>/g, ' ').trim().length > 0
const currentUser = useUnit($user)
const adminAvatarQuery = useQuery({
queryKey: ['admin', 'avatar'],
queryFn: fetchAdminAvatar,
staleTime: 5 * 60 * 1000,
})
const handleSend = () => {
if (!canSend || isPending) return
onSend(text.trim())
@@ -43,8 +51,15 @@ export function OrderChat({ messages, isPending, onSend }: Props) {
<Stack spacing={1} sx={{ mb: 2 }}>
{messages.map((m) => {
const isAdminMsg = m.authorType === 'admin'
const adminAv = adminAvatarQuery.data
const avatarNode = isAdminMsg ? (
<UserAvatar userId="admin" avatarUrl={null} avatarType={null} avatarStyle={null} size={24} />
<UserAvatar
userId="admin"
avatarUrl={adminAv?.avatar}
avatarType={adminAv?.avatarType}
avatarStyle={adminAv?.avatarStyle}
size={24}
/>
) : currentUser ? (
<UserAvatar
userId={currentUser.id}
Binary file not shown.
+15
View File
@@ -1,3 +1,4 @@
import { normalizeEmail } from '../../lib/auth.js'
import { prisma } from '../../lib/prisma.js'
export async function registerAdminProfileRoutes(fastify) {
@@ -15,6 +16,20 @@ export async function registerAdminProfileRoutes(fastify) {
}
})
fastify.get('/api/admin/avatar', async (request, reply) => {
const adminEmail = normalizeEmail(process.env.ADMIN_EMAIL)
if (!adminEmail || !adminEmail.includes('@')) return reply.code(404).send({ error: 'Администратор не найден' })
const user = await prisma.user.findUnique({ where: { email: adminEmail } })
if (!user) return reply.code(404).send({ error: 'Администратор не найден' })
return {
avatar: user.avatar,
avatarType: user.avatarType,
avatarStyle: user.avatarStyle,
}
})
fastify.patch('/api/admin/profile', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => {
const userId = request.user.sub
const nameRaw = request.body?.displayName