71 lines
1.6 KiB
TypeScript
71 lines
1.6 KiB
TypeScript
|
|
import {
|
||
|
|
createContext,
|
||
|
|
useCallback,
|
||
|
|
useEffect,
|
||
|
|
useMemo,
|
||
|
|
useState,
|
||
|
|
type ReactNode,
|
||
|
|
} from 'react';
|
||
|
|
import type { AuthResponse, User } from '../types';
|
||
|
|
import { api } from '../utils/api';
|
||
|
|
|
||
|
|
interface AuthContextValue {
|
||
|
|
user: User | null;
|
||
|
|
token: string | null;
|
||
|
|
loading: boolean;
|
||
|
|
login: (googleToken: string) => Promise<void>;
|
||
|
|
logout: () => void;
|
||
|
|
}
|
||
|
|
|
||
|
|
export const AuthContext = createContext<AuthContextValue>({
|
||
|
|
user: null,
|
||
|
|
token: null,
|
||
|
|
loading: true,
|
||
|
|
login: async () => {},
|
||
|
|
logout: () => {},
|
||
|
|
});
|
||
|
|
|
||
|
|
export function AuthProvider({ children }: { children: ReactNode }) {
|
||
|
|
const [user, setUser] = useState<User | null>(null);
|
||
|
|
const [token, setToken] = useState<string | null>(
|
||
|
|
() => localStorage.getItem('token'),
|
||
|
|
);
|
||
|
|
const [loading, setLoading] = useState(true);
|
||
|
|
|
||
|
|
const logout = useCallback(() => {
|
||
|
|
localStorage.removeItem('token');
|
||
|
|
setToken(null);
|
||
|
|
setUser(null);
|
||
|
|
}, []);
|
||
|
|
|
||
|
|
const login = useCallback(async (googleToken: string) => {
|
||
|
|
const res = await api.post<AuthResponse>('/auth/google', {
|
||
|
|
idToken: googleToken,
|
||
|
|
});
|
||
|
|
localStorage.setItem('token', res.token);
|
||
|
|
setToken(res.token);
|
||
|
|
setUser(res.user);
|
||
|
|
}, []);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
if (!token) {
|
||
|
|
setLoading(false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
api
|
||
|
|
.get<User>('/auth/me')
|
||
|
|
.then(setUser)
|
||
|
|
.catch(() => {
|
||
|
|
logout();
|
||
|
|
})
|
||
|
|
.finally(() => setLoading(false));
|
||
|
|
}, [token, logout]);
|
||
|
|
|
||
|
|
const value = useMemo(
|
||
|
|
() => ({ user, token, loading, login, logout }),
|
||
|
|
[user, token, loading, login, logout],
|
||
|
|
);
|
||
|
|
|
||
|
|
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||
|
|
}
|