import React, { useEffect, useState } from "react"; import { createUser as registerApi, isLoggedIn, login as loginApi, logout as logoutApi, } from "../api"; import { useQuery } from "../hooks"; import { useLocation, useNavigate } from "react-router-dom"; const initState = { user: undefined, }; export const AuthenticationContext = React.createContext({ ...initState, login: () => {}, register: () => {}, logout: () => {}, }); export const AuthenticationProvider = ({ children }) => { const navigate = useNavigate(); const location = useLocation(); const query = useQuery(); const [authState, setAuthState] = useState(initState); const [isLoading, setIsLoading] = useState(true); const redirect = () => { navigate(query.get("redirect_uri") || "/"); }; const login = async (email, password) => { loginApi(email, password) .then((user) => { setAuthState({ user }); redirect(); }) .catch(() => { setAuthState({ user: undefined }); }); }; const register = async (username, password, confirmation) => { registerApi(username, password, confirmation).then((user) => { setAuthState({ user }); redirect(); }); }; const logout = () => { logoutApi().then(() => { setAuthState(initState); navigate(`/login`); }); }; useEffect(() => { isLoggedIn() .then((user) => { if (user === "Unauthorized") throw new Error("Unauthorized"); setAuthState({ user }); if (location.pathname === "/login") { redirect(); } }) .catch(() => { setAuthState({ user: undefined }); if (!location.pathname.match(/^(\/|\/login|\/register)$/)) { navigate( `/login?redirect_uri=${encodeURI(location.pathname)}` ); } }) .finally(() => { setIsLoading(false); }); }, []); useEffect(() => { if (location.pathname === "/logout") { logout(); } }, [location]); if (isLoading) { return
Loading...
; } return (