From 442d17e61bbc9647734c0f5676c693894484d171 Mon Sep 17 00:00:00 2001 From: Tamal Das Date: Thu, 15 Feb 2024 16:55:05 +0530 Subject: [PATCH] feat: changes to auth and redux store --- package-lock.json | 9 ++ package.json | 1 + src/components/private/landing/Landing.jsx | 11 +- .../profileCompletion/ProfileCompletion.jsx | 151 ++++++++++++++---- src/constants/ProfileCompletionDetails.js | 8 + src/hooks/useAuth.js | 5 + src/index.jsx | 7 +- src/pages/auth/SignUp.jsx | 34 ++-- src/pages/profile/Profile.jsx | 33 ++-- src/pages/profile/Profile.scss | 1 + src/redux/rootReducer.js | 6 - src/redux/slice/authTypeSlice.js | 26 --- src/redux/slice/userSlice.js | 24 +++ src/redux/store.js | 26 +++ src/store.js | 6 - src/utils/checkMissingFields.js | 1 + 16 files changed, 247 insertions(+), 102 deletions(-) delete mode 100644 src/redux/rootReducer.js delete mode 100644 src/redux/slice/authTypeSlice.js create mode 100644 src/redux/slice/userSlice.js create mode 100644 src/redux/store.js delete mode 100644 src/store.js diff --git a/package-lock.json b/package-lock.json index b273c778..f97d6565 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "react-select": "^5.7.5", "react-spinners": "^0.13.7", "react-toastify": "^9.1.1", + "redux-persist": "^6.0.0", "swiper": "^10.3.0", "swr": "^2.1.0", "url": "^0.11.0", @@ -15962,6 +15963,14 @@ "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" }, + "node_modules/redux-persist": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz", + "integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==", + "peerDependencies": { + "redux": ">4.0.0" + } + }, "node_modules/redux-thunk": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", diff --git a/package.json b/package.json index 8a459fce..289edcb4 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "react-select": "^5.7.5", "react-spinners": "^0.13.7", "react-toastify": "^9.1.1", + "redux-persist": "^6.0.0", "swiper": "^10.3.0", "swr": "^2.1.0", "url": "^0.11.0", diff --git a/src/components/private/landing/Landing.jsx b/src/components/private/landing/Landing.jsx index 786e5d52..f1370d80 100644 --- a/src/components/private/landing/Landing.jsx +++ b/src/components/private/landing/Landing.jsx @@ -1,24 +1,25 @@ import Cookies from "js-cookie"; import React, { useEffect, useState } from "react"; import Marquee from "react-fast-marquee"; +import { useSelector } from "react-redux"; import Vector from "../../../assets/pictures/Banner/Vector.png"; import { Button } from "../../shared"; import "./Landing.css"; const Landing = () => { const [windowWidth, setWindowWidth] = useState(window.innerWidth); + const user = useSelector((state) => state.user); useEffect(() => { const handleResize = () => { setWindowWidth(window.innerWidth); }; - window.addEventListener("resize", handleResize); - return () => { window.removeEventListener("resize", handleResize); }; }, []); + return ( <>
@@ -64,7 +65,11 @@ const Landing = () => {
-

+

{ + console.log(user); + }} + > Collaborate. Connect. Build.

diff --git a/src/components/shared/profileCompletion/ProfileCompletion.jsx b/src/components/shared/profileCompletion/ProfileCompletion.jsx index e9855c6f..bb554703 100644 --- a/src/components/shared/profileCompletion/ProfileCompletion.jsx +++ b/src/components/shared/profileCompletion/ProfileCompletion.jsx @@ -1,19 +1,31 @@ +import Cookies from "js-cookie"; import React, { useEffect, useState } from "react"; import { IoMdCloseCircleOutline } from "react-icons/io"; +import { useDispatch, useSelector } from "react-redux"; import { ProfileCompletionDetails } from "../../../constants"; +import { updateUserData } from "../../../redux/slice/userSlice"; import { UpdateUser } from "../../../service/MilanApi"; import { showErrorToast, showSuccessToast } from "../../../utils/Toasts"; import Button from "../buttons/globalbutton/Button"; import "./ProfileCompletion.scss"; -const ProfileCompletion = ({ setShowProfileModal, info }) => { +const ProfileCompletion = ({ + setShowProfileModal, + editProfile, + seteditProfile, +}) => { const [missingElements, setMissingElements] = useState([]); const [currentStep, setcurrentStep] = useState(0); const [formData, setFormData] = useState({}); const [errors, setErrors] = useState({}); + const info = useSelector((state) => state.user); + const dispatch = useDispatch(); useEffect(() => { calculateMissingElements(); + if (editProfile) { + setFormData(info); + } }, [info]); const calculateMissingElements = () => { @@ -29,10 +41,32 @@ const ProfileCompletion = ({ setShowProfileModal, info }) => { setMissingElements(missing); }; - const totalSteps = - missingElements.length % 2 === 0 - ? Math.ceil(missingElements.length / 2) - : Math.ceil(missingElements.length / 2) + 1; + const editProfileFields = [ + "name", + "tagLine", + "description", + "city", + "state", + "address", + "country", + "pincode", + ]; + + const calculateTotalSteps = () => { + if (editProfile) { + if (editProfileFields.length % 2 === 0) { + return Math.ceil(editProfileFields.length / 2); + } else { + return Math.ceil(editProfileFields.length / 2) + 1; + } + } else { + if (missingElements.length % 2 === 0) { + return Math.ceil(missingElements.length / 2); + } else { + return Math.ceil(missingElements.length / 2) + 1; + } + } + }; const validateFields = () => { let stepErrors = {}; @@ -60,8 +94,12 @@ const ProfileCompletion = ({ setShowProfileModal, info }) => { }; const handleIncrementStep = () => { - if (validateFields() && currentStep < totalSteps) - setcurrentStep(currentStep + 2); + if (editProfile) { + if (currentStep < calculateTotalSteps()) setcurrentStep(currentStep + 2); + } else { + if (validateFields() && currentStep < calculateTotalSteps()) + setcurrentStep(currentStep + 2); + } }; const handleDecrementStep = () => { @@ -80,12 +118,19 @@ const ProfileCompletion = ({ setShowProfileModal, info }) => { if (response?.status !== 200) { showErrorToast(response?.data?.message); } else { + dispatch(updateUserData(formData)); + setFormData({}); setShowProfileModal(false); + seteditProfile(false); showSuccessToast(response?.data?.message); } } }; + const maxSteps = editProfile + ? editProfileFields.length + : missingElements.length; + return (
@@ -93,38 +138,78 @@ const ProfileCompletion = ({ setShowProfileModal, info }) => { className="crossButton" onClick={() => { setShowProfileModal(false); + seteditProfile(false); + Cookies.set("skipProfileCompletion", "true", { expires: 7 }); }} />
-

We're almost done

-

- Please complete your profile to enjoy the full benefits of the - platform -

+

{editProfile ? "Edit Profile" : `We're almost done`}

+ {!editProfile && ( +

+ Please complete your profile to enjoy the full benefits of the + platform +

+ )}
- {missingElements.slice(currentStep, currentStep + 2).map((elId) => { - const formElement = ProfileCompletionDetails.elements.find( - (element) => element.id === elId, - ); - - return ( -
- - - {errors[formElement?.id] &&

{errors[formElement?.id]}

} -
- ); - })} + {editProfile + ? editProfileFields + .slice(currentStep, currentStep + 2) + .map((elId) => { + const formElement = ProfileCompletionDetails.elements.find( + (element) => element.id === elId, + ); + console.log("🚀 ~ .map ~ formElement:", formElement); + + return ( +
+ + + {errors[formElement?.id] && ( +

{errors[formElement?.id]}

+ )} +
+ ); + }) + : missingElements + .slice(currentStep, currentStep + 2) + .map((elId) => { + const formElement = ProfileCompletionDetails.elements.find( + (element) => element.id === elId, + ); + + return ( +
+ + + {errors[formElement?.id] && ( +

{errors[formElement?.id]}

+ )} +
+ ); + })}
@@ -135,7 +220,7 @@ const ProfileCompletion = ({ setShowProfileModal, info }) => { > Previous - {currentStep + 2 >= missingElements.length ? ( + {currentStep + 2 >= maxSteps ? ( diff --git a/src/constants/ProfileCompletionDetails.js b/src/constants/ProfileCompletionDetails.js index 184ebb0e..efac46bf 100644 --- a/src/constants/ProfileCompletionDetails.js +++ b/src/constants/ProfileCompletionDetails.js @@ -2,6 +2,14 @@ import { z } from "zod"; const ProfileCompletionDetails = { elements: [ + { + id: "name", + label: "Name", + placeholder: "Your organization's name", + minimumLength: 5, + errorMessage: "Name must be at least 5 characters long", + type: "text", + }, { id: "tagLine", label: "Tagline", diff --git a/src/hooks/useAuth.js b/src/hooks/useAuth.js index fe54526f..b476c687 100644 --- a/src/hooks/useAuth.js +++ b/src/hooks/useAuth.js @@ -1,5 +1,7 @@ import { useState } from "react"; +import { useDispatch } from "react-redux"; import { useNavigate } from "react-router-dom"; +import { updateUserData } from "../redux/slice/userSlice"; import { LoginUser, RegisterUser } from "../service/MilanApi"; import checkInternetConnection from "../utils/CheckInternetConnection"; import { showErrorToast, showSuccessToast } from "../utils/Toasts"; @@ -7,6 +9,7 @@ import { showErrorToast, showSuccessToast } from "../utils/Toasts"; export function useAuth(authType) { const navigate = useNavigate(); const [loading, setloading] = useState(false); + const dispatch = useDispatch(); async function authenticateUser(credentials) { if (!checkInternetConnection()) { @@ -21,6 +24,8 @@ export function useAuth(authType) { if (response?.status === 201 || response?.status === 200) { showSuccessToast(response?.data?.message); + dispatch(updateUserData(response.data.user)); + setTimeout(() => { navigate("/"); setloading(false); diff --git a/src/index.jsx b/src/index.jsx index 3be0c00f..63e84183 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -2,8 +2,9 @@ import React from "react"; import ReactDOM from "react-dom/client"; import { HelmetProvider } from "react-helmet-async"; import { Provider } from "react-redux"; +import { PersistGate } from "redux-persist/integration/react"; import App from "./App"; -import { store } from "./store"; +import { persistor, store } from "./redux/store"; import "./styles/index.css"; let vh = window.innerHeight * 0.01; @@ -12,7 +13,9 @@ document.documentElement.style.setProperty("--vh", `${vh}px`); ReactDOM.createRoot(document.getElementById("root")).render( - + + + , ); diff --git a/src/pages/auth/SignUp.jsx b/src/pages/auth/SignUp.jsx index 61d27111..a58333e7 100644 --- a/src/pages/auth/SignUp.jsx +++ b/src/pages/auth/SignUp.jsx @@ -1,10 +1,9 @@ import { zodResolver } from "@hookform/resolvers/zod"; -import React from "react"; +import React, { useState } from "react"; import { Helmet } from "react-helmet-async"; import { useForm } from "react-hook-form"; import { FaChevronDown } from "react-icons/fa"; import { FcGoogle } from "react-icons/fc"; -import { useDispatch, useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; import { ToastContainer } from "react-toastify"; import rightabstract from "../../assets/pictures/authpages/authbanner.png"; @@ -12,7 +11,6 @@ import { Button } from "../../components/shared"; import { AuthSchema } from "../../constants"; import { useAuth } from "../../hooks/useAuth"; -import { toggleActiveAuthType } from "../../redux/slice/authTypeSlice"; import { GoogleAuth } from "../../service/MilanApi"; import "./index.css"; @@ -35,11 +33,19 @@ const SignUp = () => { const navigate = useNavigate(); + const authTypeOptions = [ + { value: "individual", label: "Individual (Person)" }, + { value: "club", label: "Organization (Charity/Club/NGO)" }, + ]; + const [authType, setauthType] = useState("individual"); + const handleGoogle = async () => { const response = await GoogleAuth(); window.location.href = response; }; + const { authenticateUser, loading } = useAuth("signup"); + const handleNavigatePages = () => { navigate( window.location.pathname.includes("signup") @@ -48,14 +54,6 @@ const SignUp = () => { ); }; - const { authenticateUser, loading } = useAuth("signup"); - const authTypeOptions = useSelector( - (state) => state.authType.authTypeOptions, - ); - - const authTypeActive = useSelector((state) => state.authType.active); - const dispatch = useDispatch(); - return ( <> @@ -72,7 +70,7 @@ const SignUp = () => {

Sign Up

- {authTypeActive === "individual" ? ( + {authType === "individual" ? (
{ authenticateUser(data); @@ -86,7 +84,11 @@ const SignUp = () => { name="userType" className="form-control auth_select" {...iregister("usertype")} - onChange={() => dispatch(toggleActiveAuthType())} + onChange={() => { + authType === "individual" + ? setauthType("club") + : setauthType("individual"); + }} > {authTypeOptions.map((option) => (