diff --git a/src/contexts/AuthContext.tsx b/src/contexts/AuthContext.tsx index ddab047..3833121 100644 --- a/src/contexts/AuthContext.tsx +++ b/src/contexts/AuthContext.tsx @@ -1,7 +1,9 @@ -import { createContext, useContext, useState } from 'react' +import { createContext, useContext, useEffect, useState } from 'react' import type { User, AuthSession } from '../types' import { api, ApiError } from '../lib/api' +const BASE = (import.meta.env.VITE_API_URL as string | undefined) ?? 'https://api.hotelsync.ru' + interface AuthContextValue { session: AuthSession | null user: User | null @@ -11,11 +13,45 @@ interface AuthContextValue { const AuthContext = createContext(null) -export function AuthProvider({ children }: { children: React.ReactNode }) { - const [session, setSession] = useState(() => { +function loadSession(): AuthSession | null { + try { const stored = localStorage.getItem('hotelsync-session') - return stored ? JSON.parse(stored) : null - }) + if (!stored) return null + const parsed = JSON.parse(stored) as AuthSession + // If session is missing token — discard it, we'll refresh below + if (!parsed?.user) { localStorage.removeItem('hotelsync-session'); return null } + return parsed + } catch { + localStorage.removeItem('hotelsync-session') + return null + } +} + +export function AuthProvider({ children }: { children: React.ReactNode }) { + const [session, setSession] = useState(loadSession) + + // On mount: if session exists but token is missing/null, try to refresh via cookie + useEffect(() => { + if (!session) return + if (session.token) return // token present, all good + + fetch(`${BASE}/api/auth/refresh`, { method: 'POST', credentials: 'include' }) + .then(r => r.ok ? r.json() : null) + .then((data: { access_token?: string } | null) => { + if (data?.access_token) { + const s: AuthSession = { ...session, token: data.access_token } + setSession(s) + localStorage.setItem('hotelsync-session', JSON.stringify(s)) + } else { + setSession(null) + localStorage.removeItem('hotelsync-session') + } + }) + .catch(() => { + setSession(null) + localStorage.removeItem('hotelsync-session') + }) + }, []) // eslint-disable-line react-hooks/exhaustive-deps const login = async (email: string, password: string): Promise => { try {