import { useRef, useState } from "react"; import { useNavigate } from "react-router-dom"; import { ApiError } from "../api/client"; import { Avatar } from "../components/Avatar"; import { ProfileStatsCard } from "../components/ProfileStatsCard"; import { Spinner } from "../components/Spinner"; import { useToast } from "../context/ToastContext"; import { useDeleteAvatar, useLogout, useMe, useUpdateBio, useUpdateNickname, useUploadAvatar, } from "../hooks/auth"; import { useMyStats } from "../hooks/stats"; export function AccountPage() { const { data: me, isLoading } = useMe(); const { data: stats } = useMyStats(); const updateNick = useUpdateNickname(); const updateBio = useUpdateBio(); const uploadAvatar = useUploadAvatar(); const deleteAvatar = useDeleteAvatar(); const logout = useLogout(); const toast = useToast(); const navigate = useNavigate(); const fileRef = useRef(null); const [nickname, setNickname] = useState(""); const [bio, setBio] = useState(null); if (isLoading || !me) return ; // bio редактируется локально; до первого ввода берём значение из профиля. const bioValue = bio ?? me.bio ?? ""; const saveNick = async () => { const nick = nickname.trim(); if (!nick) return; try { await updateNick.mutateAsync(nick); setNickname(""); toast.show("Никнейм обновлён"); } catch (e) { toast.show(e instanceof ApiError ? e.message : "Ошибка"); } }; const saveBio = async () => { try { await updateBio.mutateAsync(bioValue.trim()); toast.show("Сохранено"); } catch (e) { toast.show(e instanceof ApiError ? e.message : "Ошибка"); } }; const onPickFile = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; e.target.value = ""; // позволяем выбрать тот же файл повторно if (!file) return; try { await uploadAvatar.mutateAsync(file); toast.show("Аватар обновлён"); } catch (err) { toast.show(err instanceof ApiError ? err.message : "Не удалось загрузить"); } }; const removeAvatar = async () => { try { await deleteAvatar.mutateAsync(); toast.show("Аватар удалён"); } catch (e) { toast.show(e instanceof ApiError ? e.message : "Ошибка"); } }; const doLogout = async () => { await logout.mutateAsync().catch(() => {}); navigate("/login", { replace: true }); }; return (

Профиль

{me.nickname}
{me.avatar_url && ( )}