Archived
62 lines
1.7 KiB
TypeScript
62 lines
1.7 KiB
TypeScript
import { createContext, useContext, useEffect, useMemo, useState, type ReactNode } from 'react';
|
|
import { apiClient, getStoredToken, setAuthToken } from '../api/client';
|
|
import type { User } from '../api/types';
|
|
|
|
interface AuthContextValue {
|
|
user: User | null;
|
|
token: string | null;
|
|
loading: boolean;
|
|
login: (token: string, user: User) => void;
|
|
logout: () => void;
|
|
}
|
|
|
|
const AuthContext = createContext<AuthContextValue | undefined>(undefined);
|
|
|
|
export function AuthProvider({ children }: { children: ReactNode }) {
|
|
const [token, setToken] = useState<string | null>(getStoredToken());
|
|
const [user, setUser] = useState<User | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
const stored = getStoredToken();
|
|
if (!stored) {
|
|
setLoading(false);
|
|
return;
|
|
}
|
|
setAuthToken(stored);
|
|
apiClient
|
|
.get<{ user: User }>('/auth/me')
|
|
.then((res) => {
|
|
setUser(res.data.user);
|
|
setToken(stored);
|
|
})
|
|
.catch(() => {
|
|
setAuthToken(null);
|
|
setToken(null);
|
|
})
|
|
.finally(() => setLoading(false));
|
|
}, []);
|
|
|
|
const login = (newToken: string, newUser: User) => {
|
|
setAuthToken(newToken);
|
|
setToken(newToken);
|
|
setUser(newUser);
|
|
};
|
|
|
|
const logout = () => {
|
|
setAuthToken(null);
|
|
setToken(null);
|
|
setUser(null);
|
|
};
|
|
|
|
const value = useMemo(() => ({ user, token, loading, login, logout }), [user, token, loading]);
|
|
|
|
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
|
}
|
|
|
|
export function useAuth() {
|
|
const ctx = useContext(AuthContext);
|
|
if (!ctx) throw new Error('useAuth must be used within AuthProvider');
|
|
return ctx;
|
|
}
|