Files
digicraft-fe/AuthContext.tsx
Fahri Can Seçer 6e3bee17ef
Some checks failed
Deploy Frontend / deploy (push) Has been cancelled
main
2026-02-05 01:34:13 +03:00

95 lines
3.3 KiB
TypeScript

import React, { createContext, useContext, useState, useEffect } from 'react';
import axios from 'axios';
import { User } from './types';
interface AuthContextType {
user: User | null;
token: string | null;
login: (token: string, user: User) => void;
logout: () => void;
refreshUser: () => Promise<void>;
isAuthenticated: boolean;
}
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [user, setUser] = useState<User | null>(null);
const [token, setToken] = useState<string | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const savedToken = localStorage.getItem('token');
const savedUser = localStorage.getItem('user');
if (savedToken && savedUser) {
setToken(savedToken);
setUser(JSON.parse(savedUser));
axios.defaults.headers.common['Authorization'] = `Bearer ${savedToken}`;
}
setLoading(false);
}, []);
const login = (newToken: string, newUser: User) => {
setToken(newToken);
setUser(newUser);
localStorage.setItem('token', newToken);
localStorage.setItem('user', JSON.stringify(newUser));
axios.defaults.headers.common['Authorization'] = `Bearer ${newToken}`;
};
const logout = React.useCallback(() => {
setToken(null);
setUser(null);
localStorage.removeItem('token');
localStorage.removeItem('user');
delete axios.defaults.headers.common['Authorization'];
window.location.href = '/login'; // Force redirect
}, []);
// Global Axios Interceptor for 401/403
useEffect(() => {
const interceptor = axios.interceptors.response.use(
(response) => response,
(error) => {
if (error.response && (error.response.status === 401 || error.response.status === 403)) {
console.warn("Auth session expired or invalid. Logging out...");
logout();
}
return Promise.reject(error);
}
);
return () => axios.interceptors.response.eject(interceptor);
}, [logout]);
const refreshUser = async () => {
const currentToken = localStorage.getItem('token');
if (!currentToken) return;
try {
// Ensure auth header is set just in case
axios.defaults.headers.common['Authorization'] = `Bearer ${currentToken}`;
const res = await axios.get('/api/auth/me');
if (res.data) {
setUser(res.data);
localStorage.setItem('user', JSON.stringify(res.data));
}
} catch (error) {
console.error("Failed to refresh user data", error);
}
};
if (loading) return <div className="flex h-screen items-center justify-center">Loading...</div>;
return (
<AuthContext.Provider value={{ user, token, login, logout, refreshUser, isAuthenticated: !!user }}>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => {
const context = useContext(AuthContext);
if (!context) throw new Error('useAuth must be used within an AuthProvider');
return context;
};