diff --git a/package-lock.json b/package-lock.json index 2af4262..80829b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.2.0", "dependencies": { "@babel/plugin-proposal-private-property-in-object": "7.21.11", - "@chakra-ui/icons": "^2.2.4", + "@chakra-ui/icons": "^2.2.0", "@chakra-ui/react": "^2.8.2", "@emotion/react": "^11", "@emotion/styled": "^11", @@ -28,7 +28,8 @@ "react-firebase-hooks": "^5.1.1", "react-icons": "^5.2.1", "react-router-dom": "^6.24.0", - "react-scripts": "5.0.1", + "react-scripts": "^5.0.1", + "react-toastify": "^11.0.5", "uuid": "^10.0.0", "web-vitals": "^4.2.0", "yup": "^1.4.0" @@ -7719,6 +7720,15 @@ "node": ">=12" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -18135,6 +18145,19 @@ } } }, + "node_modules/react-toastify": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.5.tgz", + "integrity": "sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA==", + "license": "MIT", + "dependencies": { + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": "^18 || ^19", + "react-dom": "^18 || ^19" + } + }, "node_modules/react-universal-interface": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", diff --git a/package.json b/package.json index cd6d054..a7764f8 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,8 @@ "private": true, "dependencies": { "@babel/plugin-proposal-private-property-in-object": "7.21.11", + "@chakra-ui/icons": "^2.2.0", "@chakra-ui/react": "^2.8.2", - "@chakra-ui/icons":"^2.2.0", "@emotion/react": "^11", "@emotion/styled": "^11", "@giphy/js-fetch-api": "^5.6.0", @@ -24,6 +24,7 @@ "react-icons": "^5.2.1", "react-router-dom": "^6.24.0", "react-scripts": "^5.0.1", + "react-toastify": "^11.0.5", "uuid": "^10.0.0", "web-vitals": "^4.2.0", "yup": "^1.4.0" diff --git a/src/App.js b/src/App.js index cdb47bb..e0cbd19 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,7 @@ import Signin from "./pages/SignIn"; import SignUp from "./pages/SignUp"; +import { ToastContainer } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; import Home from "./pages/Home"; @@ -9,6 +11,14 @@ import { Route, Routes, Navigate } from "react-router-dom"; export default function App() { return ( + <> + } /> } /> } /> + ); } diff --git a/src/pages/SignIn.js b/src/pages/SignIn.js index 8d26ed5..a23d72b 100644 --- a/src/pages/SignIn.js +++ b/src/pages/SignIn.js @@ -7,31 +7,51 @@ import { import { auth } from "../firebase"; import { useEffect } from "react"; - import { useNavigate } from "react-router-dom"; -import FormContainer from "../components/Form/FormContainer"; -import { Button, VStack, HStack, useColorMode } from "@chakra-ui/react"; +import { ToastContainer, toast } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; +import FormContainer from "../components/Form/FormContainer"; +import { Button, VStack, HStack, useColorMode } from "@chakra-ui/react"; import YupValidation, { initialValues } from "../components/Form/YupSignIn"; import TextField from "../components/Form/TextField"; import { Formik, Form } from "formik"; - import { IconContext } from "react-icons"; import { FiLogIn } from "react-icons/fi"; +const getAuthErrorMessage = (error) => { + switch (error.code) { + case 'auth/user-not-found': + case 'auth/wrong-password': + case 'auth/invalid-credential': + return 'Invalid email or password. Please try again.'; + case 'auth/invalid-email': + return 'Please enter a valid email address.'; + case 'auth/too-many-requests': + return 'Too many attempts. Please try again later or reset your password.'; + case 'auth/popup-closed-by-user': + case 'auth/cancelled-popup-request': + return 'The sign-in process was cancelled.'; + case 'auth/popup-blocked': + return 'Pop-up blocked. Please allow pop-ups for this site to sign in.'; + default: + return 'An unexpected error occurred. Please try again.'; + } +}; + export default function Signin() { const Navigate = useNavigate(); const { colorMode } = useColorMode(); useEffect(() => { - onAuthStateChanged(auth, (user) => { + const unsubscribe = onAuthStateChanged(auth, (user) => { if (user) { Navigate("/main"); } }); - // eslint-disable-next-line - }, [auth]); + return () => unsubscribe(); + }, [Navigate]); const NavToSignUp = () => { Navigate("/signup"); @@ -40,28 +60,33 @@ export default function Signin() { const SignInWithGoogle = () => { const provider = new GoogleAuthProvider(); signInWithPopup(auth, provider) - .then((cred) => { - console.log("Log in successfully"); + .then(() => { + toast.success("Successfully logged in!"); }) .catch((err) => { - console.log(err); + const message = getAuthErrorMessage(err); + toast.error(message); + console.error("Firebase Google Auth Error:", err); }); }; const SignInWithEmailPassword = (values, actions) => { signInWithEmailAndPassword(auth, values.email, values.password) .then(() => { + toast.success("Successfully logged in!"); actions.setSubmitting(false); - console.log("Sign in Successfully"); }) .catch((err) => { + const message = getAuthErrorMessage(err); + toast.error(message); actions.setSubmitting(false); - console.error("Something went wrong", err); + console.error("Firebase Email Auth Error:", err); }); }; return ( - + + { + switch (error.code) { + case 'auth/email-already-in-use': + return 'This email address is already taken.'; + case 'auth/weak-password': + return 'The password is too weak. Please use at least 6 characters.'; + case 'auth/invalid-email': + return 'Please enter a valid email address.'; + default: + return 'An unexpected error occurred. Please try again.'; + } +}; + + export default function SignUp() { - // Init const auth = getAuth(); const Navigate = useNavigate(); const SignUp = (values, actions) => { - console.log(actions) - createUserWithEmailAndPassword(auth, values.email, values.confirmPassword) + createUserWithEmailAndPassword(auth, values.email, values.password) .then(() => { + toast.success("Account created successfully!", { + autoClose: 2000, + onClose: () => Navigate("/signin"), + }); actions.setSubmitting(false); }) - .catch(() => { + .catch((error) => { + + const message = getSignUpErrorMessage(error); + toast.error(message); actions.setSubmitting(false); + console.error("Firebase SignUp Error:", error); }); }; @@ -31,6 +52,7 @@ export default function SignUp() { return ( + - ); -} +} \ No newline at end of file