'use client' import { createContext, useContext, useState, useCallback, useEffect, type ReactNode } from 'react' import type { User } from '@/types' import { api, setAccessToken } from '@/lib/api' /** * Состояние аутентификации, доступное через контекст * @property user - Текущий пользователь или null * @property isLoading - Флаг загрузки сессии * @property login - Функция входа (email, пароль) * @property register - Функция регистрации (email, пароль, роль) * @property logout - Функция выхода * @property refreshSession - Функция обновления сессии */ interface AuthState { user: User | null isLoading: boolean login: (email: string, password: string) => Promise register: (email: string, password: string, role: string) => Promise logout: () => Promise refreshSession: () => Promise } const AuthContext = createContext(null) /** * Провайдер аутентификации. Оборачивает приложение в контекст AuthState. * При монтировании пытается восстановить сессию через /auth/me. * Предоставляет дочерним компонентам методы login, register, logout, refreshSession. */ export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null) const [isLoading, setIsLoading] = useState(true) const refreshSession = useCallback(async () => { try { const res = await api.get('/auth/me') setUser(res) } catch { setAccessToken(null) setUser(null) } }, []) useEffect(() => { refreshSession().finally(() => setIsLoading(false)) }, [refreshSession]) const login = useCallback(async (email: string, password: string) => { const res = await api.post<{ user: User; access_token: string }>('/auth/login', { email, password }) setAccessToken(res.access_token) setUser(res.user) }, []) const register = useCallback(async (email: string, password: string, role: string) => { const res = await api.post<{ user: User; access_token: string }>('/auth/register', { email, password, role }) setAccessToken(res.access_token) setUser(res.user) }, []) const logout = useCallback(async () => { try { await api.post('/auth/logout', {}) } catch {} setAccessToken(null) setUser(null) }, []) return ( {children} ) } /** * Хук для доступа к контексту аутентификации. * Должен использоваться внутри компонента AuthProvider. * @returns Объект AuthState с пользователем, состоянием загрузки и методами auth * @throws Ошибка, если хук вызван вне AuthProvider */ export function useAuth() { const ctx = useContext(AuthContext) if (!ctx) throw new Error('useAuth must be used within AuthProvider') return ctx }