diff --git a/src/components/Alert.jsx b/src/components/Alert.jsx new file mode 100644 index 0000000..efd5d50 --- /dev/null +++ b/src/components/Alert.jsx @@ -0,0 +1,25 @@ +import PropTypes from "prop-types"; +import { Alert as _Alert } from "@material-tailwind/react"; + +import { DEFAULT_CONFIG } from "../hooks"; + +export function Alert({ notifyConfig = DEFAULT_CONFIG }) { + return ( + <_Alert + open={notifyConfig.message !== ""} + animate={{ + mount: { y: 0 }, + unmount: { y: -100 }, + }} + variant={notifyConfig.config.variant} + color={notifyConfig.config.color} + className="fixed top-5 right-10 min-w-[350px] w-fit" + > + {notifyConfig.message} + + ); +} + +Alert.propTypes = { + notifyConfig: PropTypes.object, +}; diff --git a/src/components/index.js b/src/components/index.js new file mode 100644 index 0000000..b8e17a0 --- /dev/null +++ b/src/components/index.js @@ -0,0 +1 @@ +export * from "./Alert"; diff --git a/src/hooks/index.js b/src/hooks/index.js new file mode 100644 index 0000000..9f215cb --- /dev/null +++ b/src/hooks/index.js @@ -0,0 +1 @@ +export * from "./useNotify"; diff --git a/src/hooks/useNotify.js b/src/hooks/useNotify.js new file mode 100644 index 0000000..0a97860 --- /dev/null +++ b/src/hooks/useNotify.js @@ -0,0 +1,30 @@ +import { useState } from "react"; + +export const DEFAULT_CONFIG = { + message: "", + config: { + variant: "ghost", + color: "gray", + duration: 2500, + }, +}; + +export function useNotify() { + const [notifyConfig, setNotifyConfig] = useState(DEFAULT_CONFIG); + + const clearNotification = async () => { + setTimeout(() => { + setNotifyConfig(DEFAULT_CONFIG); + }, [notifyConfig.config.duration]); + }; + + const notify = (message, updatedConfig = {}) => { + setNotifyConfig({ + message, + config: { ...DEFAULT_CONFIG.config, ...updatedConfig }, + }); + clearNotification(); + }; + + return [notify, notifyConfig]; +} diff --git a/src/pages/login/Login.jsx b/src/pages/login/Login.jsx index 72888ae..7842628 100644 --- a/src/pages/login/Login.jsx +++ b/src/pages/login/Login.jsx @@ -1,18 +1,24 @@ import { GoogleAuthProvider } from "firebase/auth"; import { ManualLoginForm } from "./ManualLoginForm"; +import { Alert } from "../../components"; + +import { useNotify } from "../../hooks"; +import { useAuth } from "../../security/hooks"; import imageLogin from "../../assets/images/form.jpg"; import googleIcon from "../../assets/images/google.svg"; import formekouLogo from "../../assets/images/formekou.png"; -import { useAuth } from "../../security/hooks"; - -//TODO: create useNotify() hooks and gen api client to call properly the user export function Login() { const authentification = useAuth(); + const [notify, notifyConfig] = useNotify(); const loginWithGoogle = async () => { - await authentification.login(GoogleAuthProvider); + try { + await authentification.login(GoogleAuthProvider); + } catch (error) { + notify("Oops, An error occured, please try again !!", { color: "red" }); + } }; return ( @@ -42,6 +48,7 @@ export function Login() { + ); } diff --git a/src/pages/login/ManualLoginForm.jsx b/src/pages/login/ManualLoginForm.jsx index 52addd6..9c7d3ac 100644 --- a/src/pages/login/ManualLoginForm.jsx +++ b/src/pages/login/ManualLoginForm.jsx @@ -3,11 +3,16 @@ import { useForm } from "react-hook-form"; import { Button, Input } from "@material-tailwind/react"; import { Email, Lock, Person } from "@mui/icons-material"; +import { Alert } from "../../components"; + +import { useNotify } from "../../hooks"; import { useAuth } from "../../security/hooks"; + import { postSignup } from "../../security/authProvider"; export function ManualLoginForm() { const [isCreate, setIsCreate] = useState(false); + const [notify, notifyConfig] = useNotify(); const [isLoading, setIsLoading] = useState(false); const { register, handleSubmit } = useForm(); const authentification = useAuth(); @@ -15,79 +20,87 @@ export function ManualLoginForm() { const loginManually = async ({ ...data }) => { setIsLoading(true); if (!isCreate) { - delete data.lastName; - await authentification.login(data); - setIsLoading(false); + try { + delete data.lastName; + await authentification.login(data); + } catch (error) { + notify("Oops, An error occured, please try again !!", { color: "red" }); + } finally { + setIsLoading(false); + } return; } try { await postSignup(data); setIsCreate(false); + notify("Account created! You can now log in", { color: "green" }); } catch (error) { - alert("Signup failed"); - console.log(error); + notify("Oops, Signup failed, please try again !!", { color: "red" }); } finally { setIsLoading(false); } }; return ( -
- } - {...register("email")} - /> - } - {...register("password")} - /> - {isCreate ? ( + <> + } - type="text" + type="email" + name="Email" + label="Email" size="lg" - label="Lastname" - {...register("lastName")} + icon={} + {...register("email")} /> - ) : ( + } + {...register("password")} + /> + {isCreate ? ( + } + type="text" + size="lg" + label="Lastname" + {...register("lastName")} + /> + ) : ( + + )} + - )} - - - + + + ); } diff --git a/src/security/hooks/useAuth.js b/src/security/hooks/useAuth.js index 0e015f3..d0cab35 100644 --- a/src/security/hooks/useAuth.js +++ b/src/security/hooks/useAuth.js @@ -17,16 +17,10 @@ export function useAuth() { }; const login = async (provider) => { - try { - await authFirebase.login(provider); - const userConnected = await getWhoAmi(); - setUser(userConnected); - navigate("/profile"); - } catch (error) { - //TODO: show notification properly - alert("Connexion failed"); - console.log(error); - } + await authFirebase.login(provider); + const userConnected = await getWhoAmi(); + setUser(userConnected); + navigate("/profile"); }; return { user, setUser, isConnected, logout, login };