import { useState } from 'react' import Alert from '@mui/material/Alert' import Box from '@mui/material/Box' import Button from '@mui/material/Button' import Divider from '@mui/material/Divider' import FormControl from '@mui/material/FormControl' import InputLabel from '@mui/material/InputLabel' import MenuItem from '@mui/material/MenuItem' import Select from '@mui/material/Select' import Stack from '@mui/material/Stack' import TextField from '@mui/material/TextField' import Typography from '@mui/material/Typography' import { createAvatar } from '@dicebear/core' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useUnit } from 'effector-react' import { useForm } from 'react-hook-form' import { apiClient } from '@/shared/api/client' import { AVATAR_STYLE_LOADERS, DEFAULT_STYLE_ID, loadAvatarStyle } from '@/shared/lib/avatar-styles' import { $user, updateProfileFx } from '@/shared/model/auth' import type { UpdateProfileParams } from '@/shared/model/auth' import { UserAvatar } from '@/shared/ui/UserAvatar' function getApiErrorMessage(error: unknown): string | null { const e = error as { response?: { data?: { error?: string } } } const msg = e?.response?.data?.error return msg ? String(msg) : null } export function AdminSettingsPage() { const user = useUnit($user) const qc = useQueryClient() const pendingProfile = useUnit(updateProfileFx.pending) const { data: profile, isLoading, isError, } = useQuery({ queryKey: ['admin', 'profile'], queryFn: async () => { const { data } = await apiClient.get<{ id: string email: string displayName: string | null avatar: string | null avatarStyle: string | null }>('admin/profile') return data }, }) const profileForm = useForm<{ displayName: string }>({ defaultValues: { displayName: profile?.displayName ?? '' }, values: { displayName: profile?.displayName ?? '' }, mode: 'onChange', }) const [selectedStyle, setSelectedStyle] = useState(user?.avatarStyle || DEFAULT_STYLE_ID) const [previewSrc, setPreviewSrc] = useState(null) const [previewStyle, setPreviewStyle] = useState(DEFAULT_STYLE_ID) const hasUnsavedPreview = previewSrc !== null const profileSaveMut = useMutation({ mutationFn: (params: { displayName: string | null; avatar?: string | null; avatarStyle?: string | null }) => apiClient.patch('admin/profile', params), onSuccess: (_data, variables) => { const p: UpdateProfileParams = { displayName: variables.displayName ?? null } if (variables.avatar !== undefined) { p.avatar = variables.avatar p.avatarStyle = variables.avatarStyle ?? null } updateProfileFx(p) void qc.invalidateQueries({ queryKey: ['admin', 'profile'] }) }, }) const profileErrorMsg = getApiErrorMessage(profileSaveMut.error) if (isLoading) return Загрузка настроек… if (isError) return Не удалось загрузить настройки. if (!user) return Нужно войти. return ( Настройки Текущая почта: {String(user.email)} {profileErrorMsg && ( {profileErrorMsg} )} Профиль Аватар {hasUnsavedPreview ? 'Предпросмотр' : user.avatar ? 'Сохранён' : 'Авто'} {hasUnsavedPreview && ( Текущий )} Стиль {hasUnsavedPreview && ( )} ) }