feat(profile): редактирование персональных данных и смена пароля

Бэкенд:
- PATCH /auth/me — изменение имени и/или email. Смена email проверяет
  уникальность, сбрасывает is_verified и отправляет новое письмо
  подтверждения. Пользователь перезагружается из БД (объект из Redis-кэша
  не привязан к сессии), кэш инвалидируется после изменения.
- POST /auth/change-password — смена пароля с подтверждением текущего;
  отклоняет неверный текущий и совпадение нового со старым.

Фронтенд:
- Страница /settings: карточка персональных данных (имя, email со статусом
  подтверждения и предупреждением о повторной верификации) и карточка смены
  пароля с проверкой совпадения.
- Ссылка «Настройки» в карточке профиля кабинета, методы API-клиента.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
jze9
2026-07-27 13:22:05 +05:00
parent 3af79e9d03
commit 5cbc1e127b
6 changed files with 366 additions and 3 deletions

View File

@@ -1,6 +1,6 @@
import { Navigate, useNavigate } from 'react-router-dom';
import { Navigate, useNavigate, Link } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import { Crown, Search, Shield, BookOpen, ShieldAlert } from 'lucide-react';
import { Crown, Search, Shield, BookOpen, ShieldAlert, Settings as SettingsIcon } from 'lucide-react';
import toast from 'react-hot-toast';
import { TaskCard } from '../components/TaskCard';
import { tasksApi, adminApi } from '../api/client';
@@ -60,6 +60,13 @@ export function Cabinet() {
<p className="text-gray-500 text-sm">{user?.email}</p>
</div>
<div className="flex items-center gap-2">
<Link
to="/settings"
className="flex items-center gap-1.5 px-4 py-2 text-sm font-medium text-gray-600 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors"
>
<SettingsIcon className="w-4 h-4" />
Настройки
</Link>
{user?.is_admin && (
<button
onClick={openAdmin}