"use client"; import React, { createContext, useContext, useState, useEffect } from "react"; import { useRouter } from "next/navigation"; const AuthContext = createContext(null); // базовый URL из YAML (у себя можешь вынести в .env) const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL; export const AuthProvider = ({ children }) => { const [user, setUser] = useState(null); // {id, email, role, name, accessToken, refreshToken} const [loading, setLoading] = useState(true); const router = useRouter(); // поднимаем пользователя из localStorage useEffect(() => { const saved = typeof window !== "undefined" ? localStorage.getItem("authUser") : null; if (saved) { setUser(JSON.parse(saved)); } setLoading(false); }, []); // основная авторизация: запрос на /auth/login const login = async (email, password) => { const res = await fetch(`${API_BASE}/auth/login`, { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json", }, body: JSON.stringify({ email, password }), }); // удобно смотреть в Postman: этот же URL, метод, тело из JSON[file:519] // в Postman просто скопируй URL и тело — увидишь точный JSON-ответ if (!res.ok) { // читаем тело как текст, чтобы в консоли / Postman было понятно let errorMessage = "Неверный логин или пароль"; try { const data = await res.json(); if (data.error) { errorMessage = data.error; } } catch { const text = await res.text(); if (text) errorMessage = text; } throw new Error(errorMessage); } const data = await res.json(); // ожидаемый формат по YAML: AuthResponse[file:519] // Примерно: // { // "access_token": "...", // "refresh_token": "...", // "token_type": "bearer", // "user": { "id": 1, "email": "...", ... } // } const authUser = { id: data.user?.id, email: data.user?.email, name: data.user?.first_name || data.user?.email, // роль пока не знаем наверняка — вытащим отдельным запросом role: null, accessToken: data.access_token, refreshToken: data.refresh_token, }; // 1) сохраняем токены/пользователя setUser(authUser); localStorage.setItem("authUser", JSON.stringify(authUser)); // 2) тянем роли пользователя (GET /users/me/roles)[file:519] try { const rolesRes = await fetch(`${API_BASE}/users/me/roles`, { method: "GET", headers: { Authorization: `Bearer ${data.access_token}`, Accept: "application/json", }, }); if (rolesRes.ok) { const roles = await rolesRes.json(); // массив объектов Role[file:519] // ищем первую подходящую роль const roleNames = roles.map((r) => r.name); let appRole = null; if (roleNames.includes("requester")) appRole = "requester"; if (roleNames.includes("volunteer")) appRole = "volunteer"; if (roleNames.includes("moderator")) appRole = "moderator"; if (roleNames.includes("admin")) appRole = "moderator"; // можно перекинуть в модераторский интерфейс const updatedUser = { ...authUser, role: appRole }; setUser(updatedUser); localStorage.setItem("authUser", JSON.stringify(updatedUser)); // 3) редирект по роли (как у тебя было) if (appRole === "requester") router.push("/home"); else if (appRole === "volunteer") router.push("/mainValounter"); else if (appRole === "moderator") router.push("/moderatorMain"); else router.push("/home"); // запасной вариант } else { // если роли не достали, всё равно пускаем как обычного пользователя router.push("/home"); } } catch (e) { console.error("Ошибка получения ролей:", e); router.push("/home"); } }; const logout = async () => { try { if (user?.accessToken) { await fetch(`${API_BASE}/auth/logout`, { method: "POST", headers: { Authorization: `Bearer ${user.accessToken}`, Accept: "application/json", }, }); } } catch (e) { console.error("Ошибка logout:", e); } setUser(null); localStorage.removeItem("authUser"); router.push("/login"); }; const value = { user, loading, isAuthenticated: !!user, login, logout, }; return {children}; }; export const useAuth = () => useContext(AuthContext);