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

210 lines
6.8 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 ValounterProfilePage = () => {
const router = useRouter();
const [profile, setProfile] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
const getAccessToken = () => {
if (typeof window === "undefined") return null;
const saved = localStorage.getItem("authUser");
const authUser = saved ? JSON.parse(saved) : null;
return authUser?.accessToken || null;
};
useEffect(() => {
const fetchProfile = async () => {
if (!API_BASE) {
setError("API_BASE_URL не задан");
setLoading(false);
return;
}
const token = getAccessToken();
if (!token) {
setError("Вы не авторизованы");
setLoading(false);
return;
}
try {
const res = await fetch(`${API_BASE}/users/me`, {
headers: {
Accept: "application/json",
Authorization: `Bearer ${token}`,
},
});
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 fullName =
profile &&
([profile.first_name, profile.last_name].filter(Boolean).join(" ") ||
profile.email);
const rating =
profile && profile.volunteer_rating != null
? Number(profile.volunteer_rating)
: null;
const birthDateText = profile?.created_at
? new Date(profile.created_at).toLocaleDateString("ru-RU")
: "—";
const email = profile?.email || "—";
const phone = profile?.phone || "—";
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">
{loading && (
<p className="font-montserrat text-[14px] text-black">
Загрузка профиля...
</p>
)}
{error && !loading && (
<p className="font-montserrat text-[12px] text-red-500">
{error}
</p>
)}
{!loading && profile && (
<>
{/* Аватар */}
{profile.avatar_url ? (
// eslint-disable-next-line @next/next/no-img-element
<img
src={profile.avatar_url}
alt="Аватар"
className="w-20 h-20 rounded-full object-cover"
/>
) : (
<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}
</p>
{rating != null && (
<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]">
Дата регистрации: {birthDateText}
</p>
<p className="font-montserrat text-[12px]">Почта: {email}</p>
<p className="font-montserrat text-[12px]">
Телефон: {phone}
</p>
</div>
{/* Кнопки */}
<div className="w-full flex flex-col gap-2 mt-2">
<button
type="button"
onClick={() => router.push("/valounterProfileSettings")}
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"
className="w-full bg-[#E07567] rounded-full py-2 flex items-center justify-center"
onClick={() => {
if (typeof window !== "undefined") {
localStorage.removeItem("authUser");
}
router.push("/");
}}
>
<span className="font-montserrat font-extrabold text-[14px] text-white">
Выйти из аккаунта
</span>
</button>
</div>
</>
)}
</main>
<TabBar />
</div>
</div>
);
};
export default ValounterProfilePage;