From 433b9e896c0df1eb5701143ecbe9d19a4c962508 Mon Sep 17 00:00:00 2001 From: fullofempt <131869779+fullofempt@users.noreply.github.com> Date: Sun, 14 Dec 2025 18:47:14 +0500 Subject: [PATCH] WIP API --- app/AuthPage.jsx | 45 +- app/ProfilePage/page.jsx | 107 ++++- .../ModeratorRequestDetailsModal.jsx | 267 +++++++++-- app/components/RequestDetailsModal.jsx | 427 ++++++++++++------ app/components/TabBar.jsx | 2 +- .../ValounterRequestDetailsModal.jsx | 292 ++++++------ app/components/acceptPopUp.jsx | 119 +++-- app/context/AuthContext.jsx | 148 ++++-- app/createRequest/page.jsx | 319 +++++++++++-- app/historyRequest/page.jsx | 354 ++++++++------- app/mainValounter/page.jsx | 263 +++++++++-- app/moderatorHistoryRequest/page.jsx | 231 +++++++--- app/moderatorMain/page.jsx | 329 +++++++------- app/profileSettings/page.jsx | 251 ++++++++-- app/reg/page.jsx | 124 ++++- app/valounterHistoryRequest/page.jsx | 292 ++++++------ app/valounterProfilePage/page.jsx | 234 +++++++--- app/valounterProfileSettings/page.jsx | 347 +++++++++----- 18 files changed, 2891 insertions(+), 1260 deletions(-) diff --git a/app/AuthPage.jsx b/app/AuthPage.jsx index 6a94e19..9be7ab5 100644 --- a/app/AuthPage.jsx +++ b/app/AuthPage.jsx @@ -15,11 +15,12 @@ const AuthPage = () => { const [rememberMe, setRememberMe] = useState(false); const [checkboxError, setCheckboxError] = useState(false); const [authError, setAuthError] = useState(""); + const [isSubmitting, setIsSubmitting] = useState(false); const isEmailValid = emailRegex.test(email); const isFormValid = isEmailValid && password.length > 0; - const handleSubmit = (e) => { + const handleSubmit = async (e) => { e.preventDefault(); if (!rememberMe) { @@ -32,9 +33,11 @@ const AuthPage = () => { try { setAuthError(""); - login(email, password); + setIsSubmitting(true); + await login(email, password); // теперь это async } catch (err) { setAuthError(err.message || "Неверный логин или пароль"); + setIsSubmitting(false); } }; @@ -111,27 +114,45 @@ const AuthPage = () => {

+ {/* Ссылки */} +
+ {/* */} + +
+ {/* Кнопка Войти */} - {/* Подсказка по тестовым логинам */} -
-

Тестовые аккаунты:

-

Пользователь: user@mail.com / user123

-

Волонтёр: vol@mail.com / vol123

-

Модератор: mod@mail.com / mod123

+ {/* Подсказка по тестовым логинам — можно убрать, когда перейдёшь на реальные аккаунты */} +
+

Тестовые аккаунты (если настроены на бэке):

+

Пользователь: user@mail.com / user123123

+

Волонтёр: vol@mail.com / vol123123

+

Модератор: mod@mail.com / mod123123

diff --git a/app/ProfilePage/page.jsx b/app/ProfilePage/page.jsx index 613d788..3506485 100644 --- a/app/ProfilePage/page.jsx +++ b/app/ProfilePage/page.jsx @@ -1,16 +1,88 @@ "use client"; -import React from "react"; +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 fullName = "Иванов Александр Сергеевич"; - const birthDate = "12.03.1990"; - const rating = 4.8; + 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 (
@@ -32,16 +104,25 @@ const ProfilePage = () => { {/* Карточка профиля */}
+ {/* Ошибка / загрузка */} + {error && ( +

+ {error} +

+ )} + {loading && !error && ( +

+ Загрузка профиля... +

+ )} + {/* Аватар */} {/* ФИО и рейтинг */}
- {/*

- ФИО -

*/}

- {fullName} + {fullName || email}

{/* Рейтинг + звезды */} @@ -65,16 +146,17 @@ const ProfilePage = () => {
- {/* Контакты и день рождения */} + {/* Контакты и адрес */}

- Дата рождения: {birthDate} + Почта: {email}

- Почта: example@mail.com + Телефон: {phone}

- Телефон: +7 (900) 000-00-00 + Адрес: {address} + {city ? `, ${city}` : ""}

@@ -91,6 +173,7 @@ const ProfilePage = () => {

- Заявка от {request.date || "28.11.25"} + Заявка от {createdDate || "—"}

- {/* белая карточка во всю ширину контейнера */}
- {/* верхняя полоса: Описание + Дата + Время */}
@@ -59,7 +234,7 @@ const ModeratorRequestModal = ({ request, onClose, onApprove, onReject }) => { Дата - {request.date || "28.11.2025"} + {createdDate || "—"}
@@ -67,27 +242,27 @@ const ModeratorRequestModal = ({ request, onClose, onApprove, onReject }) => { Время - {request.time || "13:00"} + {createdTime || "—"}
- {/* блок ФИО / адрес */}
ФИО

- {request.fullName || "Клавдия Березова"} + {request.requesterName || "Заявитель"}

- {request.address || "г. Пермь, ул. Ленина 50"} + {request.address + ? `${request.city ? request.city + ", " : ""}${request.address}` + : "Адрес не указан"}

- {/* статус + сроки */}
{
- До {request.deadline || "28.11.2025"} - {request.deadlineTime || "13:00"} + До {deadlineDate || "—"} + {deadlineTime || "—"}
- {/* Заголовок задачи */}

- {request.title || "Приобрести продукты пенсионерке"} + {request.title || "Задача"}

- {/* краткое описание / товары */} {request.description && (

@@ -125,9 +298,8 @@ const ModeratorRequestModal = ({ request, onClose, onApprove, onReject }) => {

)} - {/* если заявка уже отклонена — показать причину */} {isRejected && ( -
+

Причина отклонения

@@ -138,44 +310,48 @@ const ModeratorRequestModal = ({ request, onClose, onApprove, onReject }) => {

)} + + {error && ( +

+ {error} +

+ )}
- {/* нижняя панель с кнопками — только если заявка ещё на модерации */} - {isPending && ( +
- )} + - {/* попап причины отказа во весь экран */} {showRejectPopup && (
- {/* заголовок */}

Причина

- {/* голубой блок с текстом */}