ot / frontend /src /context /AuthContext.jsx
jashdoshi77's picture
OT NoteBuilder - Production deployment
ba95018
import { createContext, useContext, useState, useEffect, useCallback } from 'react';
const AuthContext = createContext();
const API_BASE = import.meta.env.VITE_API_URL || '';
export function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const [token, setToken] = useState(null);
const [loading, setLoading] = useState(true);
// On mount, check if we have a stored token and verify it
useEffect(() => {
const storedToken = sessionStorage.getItem('ot-token');
const storedUser = sessionStorage.getItem('ot-user');
if (storedToken && storedUser) {
// Verify the token is still valid
fetch(`${API_BASE}/api/verify`, {
headers: { Authorization: `Bearer ${storedToken}` },
})
.then(res => {
if (res.ok) {
setToken(storedToken);
setUser(storedUser);
} else {
// Token invalid/expired — clear storage
sessionStorage.removeItem('ot-token');
sessionStorage.removeItem('ot-user');
}
})
.catch(() => {
sessionStorage.removeItem('ot-token');
sessionStorage.removeItem('ot-user');
})
.finally(() => setLoading(false));
} else {
setLoading(false);
}
}, []);
const login = useCallback(async (username, password) => {
const res = await fetch(`${API_BASE}/api/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password }),
});
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(err.detail || 'Login failed');
}
const data = await res.json();
setToken(data.token);
setUser(data.username);
sessionStorage.setItem('ot-token', data.token);
sessionStorage.setItem('ot-user', data.username);
return data;
}, []);
const logout = useCallback(() => {
setToken(null);
setUser(null);
sessionStorage.removeItem('ot-token');
sessionStorage.removeItem('ot-user');
}, []);
const getAuthHeaders = useCallback(() => {
if (!token) return {};
return { Authorization: `Bearer ${token}` };
}, [token]);
const isAuthenticated = !!token && !!user;
return (
<AuthContext.Provider value={{ user, token, loading, isAuthenticated, login, logout, getAuthHeaders }}>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error('useAuth must be used within AuthProvider');
return ctx;
}