Files
frontend/app/ProfilePage/page.jsx
fullofempt 433b9e896c WIP API
2025-12-14 18:47:14 +05:00

193 lines
6.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import React, { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { FaUserCircle, FaStar } from "react-icons/fa";
import TabBar from "../components/TabBar";
const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL;
const ProfilePage = () => {
const router = useRouter();
const [profile, setProfile] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
useEffect(() => {
const fetchProfile = async () => {
if (!API_BASE) {
setError("API_BASE_URL не задан");
setLoading(false);
return;
}
const saved =
typeof window !== "undefined"
? localStorage.getItem("authUser")
: null;
const authUser = saved ? JSON.parse(saved) : null;
const accessToken = authUser?.accessToken;
if (!accessToken) {
setError("Вы не авторизованы");
setLoading(false);
return;
}
try {
const res = await fetch(`${API_BASE}/users/me`, {
headers: {
Accept: "application/json",
Authorization: `Bearer ${accessToken}`,
},
});
if (!res.ok) {
let msg = "Не удалось загрузить профиль";
try {
const data = await res.json();
if (data.error) msg = data.error;
} catch {
const text = await res.text();
if (text) msg = text;
}
setError(msg);
setLoading(false);
return;
}
const data = await res.json(); // UserProfile[file:519]
setProfile(data);
setLoading(false);
} catch (e) {
setError(e.message || "Ошибка сети");
setLoading(false);
}
};
fetchProfile();
}, []);
const handleLogout = () => {
// опционально: запрос /auth/logout, если используешь[file:519]
localStorage.removeItem("authUser");
router.push("/");
};
const fullName =
profile &&
[profile.first_name, profile.last_name].filter(Boolean).join(" ").trim();
const rating = profile?.volunteer_rating ?? 0;
const email = profile?.email || "—";
const phone = profile?.phone || "—";
const address = profile?.address || "Адрес не указан";
const city = profile?.city || "";
return (
<div className="min-h-screen w-full bg-[#90D2F9] flex justify-center px-4">
<div className="relative w-full max-w-md flex flex-col pb-20 pt-4">
{/* Header с кнопкой назад и заголовком по центру */}
<header className="flex items-center mb-4">
<button
type="button"
onClick={() => router.back()}
className="text-white w-8 h-8 rounded-full flex items-center justify-center text-lg"
>
</button>
<h1 className="flex-1 text-center font-montserrat font-extrabold text-[20px] leading-[24px] text-white">
Профиль
</h1>
<span className="w-8" />
</header>
{/* Карточка профиля */}
<main className="bg-white rounded-3xl p-4 flex flex-col items-center gap-4 shadow-lg">
{/* Ошибка / загрузка */}
{error && (
<p className="w-full text-center text-xs font-montserrat text-red-500">
{error}
</p>
)}
{loading && !error && (
<p className="w-full text-center text-xs font-montserrat text-black">
Загрузка профиля...
</p>
)}
{/* Аватар */}
<FaUserCircle className="text-[#72B8E2] w-20 h-20" />
{/* ФИО и рейтинг */}
<div className="text-center space-y-1">
<p className="font-montserrat font-bold text-[20px] text-black">
{fullName || email}
</p>
{/* Рейтинг + звезды */}
<div className="mt-2 flex items-center justify-center gap-2">
<span className="font-montserrat font-semibold text-[14px] text-black">
Рейтинг: {rating.toFixed(1)}
</span>
<div className="flex gap-1">
{[1, 2, 3, 4, 5].map((star) => (
<FaStar
key={star}
size={18}
className={
star <= Math.round(rating)
? "text-[#F6E168] fill-[#F6E168]"
: "text-[#F6E168] fill-[#F6E168]/30"
}
/>
))}
</div>
</div>
</div>
{/* Контакты и адрес */}
<div className="w-full bg-[#72B8E2] rounded-2xl p-3 text-white space-y-1">
<p className="font-montserrat text-[12px]">
Почта: {email}
</p>
<p className="font-montserrat text-[12px]">
Телефон: {phone}
</p>
<p className="font-montserrat text-[12px]">
Адрес: {address}
{city ? `, ${city}` : ""}
</p>
</div>
{/* Кнопки */}
<div className="w-full flex flex-col gap-2 mt-2">
<button
type="button"
onClick={() => router.push("/profileSettings")}
className="w-full bg-[#E0B267] rounded-full py-2 flex items-center justify-center"
>
<span className="font-montserrat font-extrabold text-[14px] text-white">
Редактировать профиль
</span>
</button>
<button
type="button"
onClick={handleLogout}
className="w-full bg-[#E07567] rounded-full py-2 flex items-center justify-center"
>
<span className="font-montserrat font-extrabold text-[14px] text-white">
Выйти из аккаунта
</span>
</button>
</div>
</main>
<TabBar />
</div>
</div>
);
};
export default ProfilePage;