diff --git a/code/frontend/src/contexts/ContextLogin.js b/code/frontend/src/contexts/ContextLogin.js index 0d8ea8d..69fe044 100644 --- a/code/frontend/src/contexts/ContextLogin.js +++ b/code/frontend/src/contexts/ContextLogin.js @@ -7,6 +7,8 @@ import {createContext} from "react"; * - `server`: The base url of the N.E.S.T. backend * - `email`: The email of the account the user is logged in as * - `token`: The bearer token to use in authenticated API requests + * - `working`: `true` if the login procedure is running, `false` otherwise + * - `error`: `null` if no login error happened, an instance of {@link Error} otherwise. * - `login`: an async function which logs in the user if given the following parameters: `server, email, password` * - `logout`: a function which logs out the user * - `fetch_unauth`: a variant of {@link fetch} which uses `state.server` as the base url, allowing only the API path diff --git a/code/frontend/src/hooks/useSavedLogin.js b/code/frontend/src/hooks/useSavedLogin.js index 89e65c6..76788ed 100644 --- a/code/frontend/src/hooks/useSavedLogin.js +++ b/code/frontend/src/hooks/useSavedLogin.js @@ -1,3 +1,4 @@ +import {useState} from "react" import useLocalStorageState from "./useLocalStorageState" @@ -6,41 +7,53 @@ import useLocalStorageState from "./useLocalStorageState" */ export default function useSavedLogin() { const [state, setState] = useLocalStorageState("login", null) + const [working, setWorking] = useState(false) + const [error, setError] = useState(null) const login = async (server, email, password) => { - console.debug("Contacting server to login...") - const response = await fetch(`${server}/api/login`, { - method: "POST", - cache: "no-cache", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - "email": email, - "password": password, + setWorking(true) + try { + console.debug("Contacting server to login...") + const response = await fetch(`${server}/api/login`, { + method: "POST", + cache: "no-cache", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + "email": email, + "password": password, + }) }) - }) - console.debug("Decoding server response...") - const data = await response.json() + console.debug("Decoding server response...") + const data = await response.json() - console.debug("Ensuring the request was a success...") - if(data["result"] !== "success") { - console.error(`Login failed: ${data["msg"]}`) - return + console.debug("Ensuring the request was a success...") + if(data["result"] !== "success") { + // noinspection ExceptionCaughtLocallyJS + throw new Error(data["msg"]) + } + + console.debug("Storing login state...") + setState({ + server: server, + email: data["user"]["email"], + isAdmin: data["user"]["isAdmin"], + username: data["user"]["username"], + token: data["access_token"], + }) + + console.debug("Clearing error...") + setError(null) + + console.info("Login successful!") + } catch(e) { + console.error(`Caught error while trying to login: ${e}`) + setError(e) + } finally { + setWorking(false) } - - console.debug("Storing login state...") - setState({ - server: server, - email: data["user"]["email"], - isAdmin: data["user"]["isAdmin"], - username: data["user"]["username"], - token: data["access_token"], - }) - console.debug("Stored login state!") - - console.info("Login successful!") } const logout = () => { @@ -65,5 +78,5 @@ export default function useSavedLogin() { return await fetch_unauth(path, init) } - return {state, login, logout, fetch_unauth, fetch_auth} + return {state, working, error, login, logout, fetch_unauth, fetch_auth} } \ No newline at end of file diff --git a/code/frontend/src/routes/PageLogin.js b/code/frontend/src/routes/PageLogin.js index 2274e5f..d88b26e 100644 --- a/code/frontend/src/routes/PageLogin.js +++ b/code/frontend/src/routes/PageLogin.js @@ -16,7 +16,7 @@ export default function PageLogin({ className, ...props }) { const [server, setServer] = useState("http://localhost:5000") const [email, setEmail] = useState("admin@admin.com") const [password, setPassword] = useState("password") - const {login} = useContext(ContextLogin) + const {login, working, error} = useContext(ContextLogin) const history = useHistory() return ( @@ -60,7 +60,8 @@ export default function PageLogin({ className, ...props }) { history.push("/dashboard") }} icon={faArrowRight} - color={"Green"} + color={error ? "Green" : "Red"} + disabled={working} > Login