import { createContext, useContext, useState, useEffect } from "react";
import { Auth, AuthProviderProps, AuthContextProps } from "../@types/auth";
import axiosInstance from "../utils/axios";
import { useSnackbar } from "notistack";
import useAxiosPrivate from "../hooks/useAxiosPrivate";
const AuthContext = createContext<AuthContextProps | null>(null);
AuthContext.displayName = "AuthContext";
export const useAuth = () => {
return useContext(AuthContext);
};
export default function AuthProvider(props: AuthProviderProps) {
const [auth, setAuth] = useState<Auth>({
isAuthenticated: false,
name: "",
role: "",
accessToken: "",
refreshToken: "",
});
useEffect(() => {
console.log("AUTH CONTEXT");
const accessToken = sessionStorage.getItem("accessToken")!;
const refreshToken = sessionStorage.getItem("refreshToken")!;
if (accessToken && refreshToken) {
setAuth((prev) => ({ isAuthenticated: true,
name: "",
role: "",
accessToken,
refreshToken, }));
}
}, []);
const { enqueueSnackbar } = useSnackbar();
const privateAxiosInstance = useAxiosPrivate();
const login = (name: string, accessToken: string, refreshToken: string) => {
setAuth({
isAuthenticated: true,
name,
role: "",
accessToken,
refreshToken,
});
sessionStorage.setItem("accessToken", accessToken);
sessionStorage.setItem("refreshToken", refreshToken);
privateAxiosInstance.get("/users/me",{
headers: {
authorization: "Bearer " + accessToken,
},
}).then((res) => {
const { name } = res.data.user;
setAuth((prev) => ({ ...prev, name: name }));
});
};
const logout = () => {
const refreshToken = sessionStorage.getItem("refreshToken")!;
sessionStorage.removeItem("accessToken");
sessionStorage.removeItem("refreshToken");
axiosInstance.post(
"/logout",
{
refreshToken: refreshToken,
},
{
headers: {
Authorization: Date.now(),
},
}
);
enqueueSnackbar("sessiontimeout Logged out due to session expired", {
variant: "error",
});
setAuth({
isAuthenticated: false,
name: "",
role: "",
accessToken: "",
refreshToken: "",
});
window.location.href = "/";
};
const refresh = async () => {
try {
console.log("refreshing");
if (!auth.refreshToken) {
throw new Error("Refresh token not found!");
}
const { data } = await axiosInstance.post(
"/accessToken",
{
refreshToken: auth.refreshToken,
},
{
headers: {
Authorization: Date.now(),
},
}
);
sessionStorage.setItem("accessToken", data.accessToken);
setAuth((prev) => ({ ...prev, accessToken: data.accessToken }));
return data.accessToken;
} catch (error) {
logout();
}
};
const setName = (name: string) => {
setAuth((prev) => ({ ...prev, name: name }));
};
return (
<AuthContext.Provider value={{ auth, login, logout, refresh, setName }}>
{props.children}
</AuthContext.Provider>
);
}