diff --git a/src/api/authApi.ts b/src/api/authApi.ts index 6a54830..164ba25 100644 --- a/src/api/authApi.ts +++ b/src/api/authApi.ts @@ -16,4 +16,8 @@ export const authApi = { const { data } = await apiClient.get('/v1/admin/me'); return data; }, + updateMe: async (payload: Partial): Promise => { + const { data } = await apiClient.put('/v1/admin/me', payload); + return data; + }, }; \ No newline at end of file diff --git a/src/hooks/useProfile.ts b/src/hooks/useProfile.ts new file mode 100644 index 0000000..70f946c --- /dev/null +++ b/src/hooks/useProfile.ts @@ -0,0 +1,18 @@ +import { useMutation } from '@tanstack/react-query'; +import { message } from 'antd'; +import { authApi } from '../api/authApi'; +import { useAuthStore } from '../store/authStore'; +import { Admin } from '../types/api'; + +export const useUpdateProfile = () => { + const setUser = useAuthStore((s) => s.setUser); + + return useMutation({ + mutationFn: (data: Partial) => authApi.updateMe(data), + onSuccess: (user) => { + setUser(user); + message.success('Профиль обновлён'); + }, + onError: () => message.error('Ошибка обновления профиля'), + }); +}; diff --git a/src/pages/profile/ProfilePage.tsx b/src/pages/profile/ProfilePage.tsx index 8b6ed9a..9030bf0 100644 --- a/src/pages/profile/ProfilePage.tsx +++ b/src/pages/profile/ProfilePage.tsx @@ -2,19 +2,44 @@ import React, { useState } from 'react'; import { Card, Descriptions, Spin, Button, Form, Input, Select, Tag, message, Space, Avatar } from 'antd'; import { UserOutlined } from '@ant-design/icons'; import { useAuthStore } from '../../store/authStore'; -import { useUpdateAdmin } from '../../hooks/useAdmins'; +import { useUpdateProfile } from '../../hooks/useProfile'; import dayjs from 'dayjs'; const ProfilePage: React.FC = () => { const { user } = useAuthStore(); - const updateAdmin = useUpdateAdmin(); + const updateProfile = useUpdateProfile(); const [editing, setEditing] = useState(false); const [form] = Form.useForm(); - // Проверка, является ли текущий пользователь superadmin - const isSuperadmin = user?.role === 'superadmin'; + // Редактирование своего профиля доступно всем ролям (PUT /v1/admin/me) + const handleSave = () => { + if (!user) return; + form.validateFields().then((values) => { + const allowed = ['nickname', 'timezone', 'language', 'phone', 'avatar_url', 'preferences'] as const; + const payload = Object.fromEntries( + Object.entries(values).filter(([key, v]) => + (allowed as readonly string[]).includes(key) && v !== '' && v !== undefined && v !== null + ) + ); + if (payload.preferences) { + try { + payload.preferences = JSON.parse(payload.preferences as string); + } catch { + message.error('Поле «Настройки» должно быть валидным JSON'); + return; + } + } + updateProfile.mutate( + payload, + { + onSuccess: () => { + setEditing(false); + }, + } + ); + }); + }; - // Заполняем форму при входе в режим редактирования const startEditing = () => { if (!user) return; const clean = (val: any) => (val === '-' || val === 'undefined' ? undefined : val); @@ -30,32 +55,6 @@ const ProfilePage: React.FC = () => { setEditing(true); }; - const handleSave = () => { - if (!user || !isSuperadmin) return; - form.validateFields().then((values) => { - const payload = Object.fromEntries( - Object.entries(values).filter(([_, v]) => v !== '' && v !== undefined && v !== null) - ); - if (payload.preferences) { - try { - payload.preferences = JSON.parse(payload.preferences as string); - } catch { - message.error('Поле «Настройки» должно быть валидным JSON'); - return; - } - } - updateAdmin.mutate( - { id: user.id, data: payload }, - { - onSuccess: () => { - message.success('Профиль обновлён'); - setEditing(false); - }, - } - ); - }); - }; - const isBadValue = (val: any) => val === '-' || val === 'undefined' || val === '' || val === null || val === undefined; @@ -126,11 +125,9 @@ const ProfilePage: React.FC = () => { {formatDate(user.last_login)} - {isSuperadmin && ( - - )} + ) : (
@@ -191,7 +188,7 @@ const ProfilePage: React.FC = () => { - diff --git a/src/store/authStore.ts b/src/store/authStore.ts index a2be7b1..ac0bfc6 100644 --- a/src/store/authStore.ts +++ b/src/store/authStore.ts @@ -13,6 +13,7 @@ interface AuthState { login: (email: string, password: string) => Promise; logout: () => Promise; checkAuth: () => Promise; + setUser: (user: Admin) => void; } export const useAuthStore = create((set) => ({ @@ -69,4 +70,6 @@ export const useAuthStore = create((set) => ({ }); } }, + + setUser: (user) => set({ user }), })); \ No newline at end of file