import React, { useState, useEffect, useRef } from "react"; import { useNavigate } from "react-router-dom"; import { Icon } from "@iconify/react"; import { useAppSelector, useAppDispatch } from "../store/hooks"; import { userApi } from "../api/userApi"; import { authApi } from "../api/authApi"; import { clearAuth } from "../store/slices/authSlice"; import { setUser, setAiSettings } from "../store/slices/profileSlice"; import { setAccentColor as setAccentColorAction } from "../store/slices/uiSlice"; import { setAccentColor } from "../utils/colorUtils"; import { useNotification } from "../hooks/useNotification"; import { Modal } from "../components/common/Modal"; import { ThemeToggle } from "../components/common/ThemeToggle"; const ProfilePage: React.FC = () => { const navigate = useNavigate(); const dispatch = useAppDispatch(); const { showNotification } = useNotification(); const user = useAppSelector((state) => state.profile.user); const [username, setUsername] = useState(""); const [email, setEmail] = useState(""); const [avatarUrl, setAvatarUrl] = useState(null); const [hasAvatar, setHasAvatar] = useState(false); const [currentPassword, setCurrentPassword] = useState(""); const [newPassword, setNewPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [deletePassword, setDeletePassword] = useState(""); const [isDeleting, setIsDeleting] = useState(false); const avatarInputRef = useRef(null); useEffect(() => { loadProfile(); }, []); const loadProfile = async () => { try { const userData = await userApi.getProfile(); dispatch(setUser(userData)); setUsername(userData.username || ""); setEmail(userData.email || ""); // Устанавливаем цвет акцента из профиля пользователя const accent = userData.accent_color || "#007bff"; dispatch(setAccentColorAction(accent)); setAccentColor(accent); if (userData.avatar) { setAvatarUrl(userData.avatar); setHasAvatar(true); } else { setAvatarUrl(null); setHasAvatar(false); } // Загружаем AI настройки try { const aiSettings = await userApi.getAiSettings(); dispatch(setAiSettings(aiSettings)); } catch (aiError) { console.error("Ошибка загрузки AI настроек:", aiError); } } catch (error) { console.error("Ошибка загрузки профиля:", error); showNotification("Ошибка загрузки данных профиля", "error"); } }; const handleAvatarUpload = async ( event: React.ChangeEvent ) => { const file = event.target.files?.[0]; if (!file) return; // Проверка размера файла (5MB) if (file.size > 5 * 1024 * 1024) { showNotification( "Файл слишком большой. Максимальный размер: 5 МБ", "error" ); return; } // Проверка типа файла const allowedTypes = ["image/jpeg", "image/jpg", "image/png", "image/gif"]; if (!allowedTypes.includes(file.type)) { showNotification( "Недопустимый формат файла. Используйте JPG, PNG или GIF", "error" ); return; } try { const result = await userApi.uploadAvatar(file); setAvatarUrl(result.avatar + "?t=" + Date.now()); setHasAvatar(true); await loadProfile(); showNotification("Аватарка успешно загружена", "success"); } catch (error: any) { console.error("Ошибка загрузки аватарки:", error); showNotification( error.response?.data?.error || "Ошибка загрузки аватарки", "error" ); } // Сбрасываем input if (avatarInputRef.current) { avatarInputRef.current.value = ""; } }; const handleDeleteAvatar = async () => { try { await userApi.deleteAvatar(); setAvatarUrl(null); setHasAvatar(false); await loadProfile(); showNotification("Аватарка успешно удалена", "success"); } catch (error: any) { console.error("Ошибка удаления аватарки:", error); showNotification( error.response?.data?.error || "Ошибка удаления аватарки", "error" ); } }; const handleUpdateProfile = async () => { if (!username.trim()) { showNotification("Логин не может быть пустым", "error"); return; } if (username.length < 3) { showNotification("Логин должен быть не менее 3 символов", "error"); return; } if (email && !isValidEmail(email)) { showNotification("Некорректный email адрес", "error"); return; } try { await userApi.updateProfile({ username: username.trim(), email: email.trim() || undefined, }); await loadProfile(); showNotification("Профиль успешно обновлен", "success"); } catch (error: any) { console.error("Ошибка обновления профиля:", error); showNotification( error.response?.data?.error || "Ошибка обновления профиля", "error" ); } }; const handleChangePassword = async () => { if (!currentPassword) { showNotification("Введите текущий пароль", "error"); return; } if (!newPassword) { showNotification("Введите новый пароль", "error"); return; } if (newPassword.length < 6) { showNotification("Новый пароль должен быть не менее 6 символов", "error"); return; } if (newPassword !== confirmPassword) { showNotification("Новый пароль и подтверждение не совпадают", "error"); return; } try { await userApi.updateProfile({ currentPassword, newPassword, }); setCurrentPassword(""); setNewPassword(""); setConfirmPassword(""); showNotification("Пароль успешно изменен", "success"); } catch (error: any) { console.error("Ошибка изменения пароля:", error); showNotification( error.response?.data?.error || "Ошибка изменения пароля", "error" ); } }; const handleDeleteAccount = async () => { if (!deletePassword.trim()) { showNotification("Введите пароль", "warning"); return; } setIsDeleting(true); try { await userApi.deleteAccount(deletePassword); showNotification("Аккаунт успешно удален", "success"); dispatch(clearAuth()); setTimeout(() => { navigate("/"); }, 2000); } catch (error: any) { console.error("Ошибка удаления аккаунта:", error); showNotification( error.response?.data?.error || "Ошибка удаления аккаунта", "error" ); setIsDeleting(false); } }; const isValidEmail = (email: string) => { const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return re.test(email); }; return (
Личный кабинет
{/* Секция аватарки */}
{hasAvatar && avatarUrl ? ( Аватар ) : (
)}
{hasAvatar && ( )}

Максимальный размер: 5 МБ. Форматы: JPG, PNG, GIF

{/* Секция данных профиля */}

Данные профиля

setUsername(e.target.value)} />
setEmail(e.target.value)} />

Изменить пароль

setCurrentPassword(e.target.value)} />
setNewPassword(e.target.value)} />
setConfirmPassword(e.target.value)} />

Удаление аккаунта - это необратимое действие. Все ваши заметки, изображения и данные будут удалены навсегда.

{/* Модальное окно подтверждения удаления аккаунта */} { setIsDeleteModalOpen(false); setDeletePassword(""); }} onConfirm={handleDeleteAccount} title="Удаление аккаунта" message={ <>

⚠️ ВНИМАНИЕ: Это действие нельзя отменить!

Вы действительно хотите удалить свой аккаунт? Все ваши заметки, изображения, настройки и данные будут удалены навсегда.

setDeletePassword(e.target.value)} onKeyPress={(e) => { if (e.key === "Enter" && !isDeleting) { handleDeleteAccount(); } }} />
} confirmText={isDeleting ? "Удаление..." : "Удалить аккаунт"} cancelText="Отмена" confirmType="danger" />
); }; export default ProfilePage;