import { createContext, useContext, useEffect, useMemo, useState, type ReactNode } from "react"; import { api, setPreviewToken, type Me } from "../../api"; import { yandexRedirectUri } from "../../auth/yandexRedirect"; type AuthState = { user: Me | null; loading: boolean; error: string | null; refresh: () => Promise; logout: () => Promise; }; const AuthContext = createContext(null); export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const refresh = async () => { try { setUser(await api.me()); setError(null); } catch { setUser(null); } }; useEffect(() => { const params = new URLSearchParams(window.location.search); const code = params.get("code"); const state = params.get("state"); const boot = async () => { try { if (code) { const redirectUri = sessionStorage.getItem("ts.oauthRedirect") ?? yandexRedirectUri("https://tile-server.ru"); const auth = await api.loginYandex(code, redirectUri, state); sessionStorage.removeItem("ts.oauthState"); sessionStorage.removeItem("ts.oauthRedirect"); setUser(auth.user); if (auth.cabinetToken) { setPreviewToken(auth.cabinetToken); } window.history.replaceState({}, "", "/"); } else { await refresh(); } } catch (err) { setError(err instanceof Error ? err.message : "Ошибка входа"); setUser(null); } finally { setLoading(false); } }; void boot(); }, []); const logout = async () => { await api.logout(); setUser(null); }; const value = useMemo( () => ({ user, loading, error, refresh, logout }), [user, loading, error] ); return {children}; } export function useAuth(): AuthState { const ctx = useContext(AuthContext); if (!ctx) { throw new Error("AuthProvider is required"); } return ctx; }