From 8b52dd4a29aa67997c8bb04e2b932ee4b535d11f Mon Sep 17 00:00:00 2001 From: Meenadeveloper Date: Tue, 3 Mar 2026 18:14:58 +0530 Subject: [PATCH] edit api integrate --- src/api/axiosInstance.js | 16 +- src/components/auth/ChangePasswordForm.jsx | 58 +++--- src/components/auth/ForgotPassworForm.jsx | 110 ++++++----- src/components/auth/ForgotPasswordForm.jsx | 125 ++++++++++++ src/components/common/ProfileHeader.jsx | 7 +- src/components/ui/ProfileCardDemo.jsx | 163 +++++++++------- src/feature/PersonalDetailsForm.jsx | 6 +- src/feature/StepperForm.jsx | 70 ++++++- src/pages/auth/LoginPage.jsx | 216 +++++++++++++++++++-- src/routes/PublicRoutes.jsx | 20 +- 10 files changed, 592 insertions(+), 199 deletions(-) create mode 100644 src/components/auth/ForgotPasswordForm.jsx diff --git a/src/api/axiosInstance.js b/src/api/axiosInstance.js index 8c74df0..bda533b 100644 --- a/src/api/axiosInstance.js +++ b/src/api/axiosInstance.js @@ -65,7 +65,7 @@ const addErrorInterceptor = (instance) => { instance.interceptors.response.use( (response) => response, (error) => { - if (error.response && error.response.status === 401) { + if (error.response && error.response.status === 401 && !error.config?.url?.includes("/login") && !error.config?.url?.includes("/forgot_password_send_otp") && !error.config?.url?.includes("/forgot_password_verify_otp") && !error.config?.url?.includes("/forgot_password_update")) { console.error("Unauthorized access - logging out..."); localStorage.removeItem("access_token"); // window.location.href = "/"; @@ -168,19 +168,15 @@ const clearFcmToken = () => { }; export const logoutAPI = async () => { - console.log("Calling logout API..."); try { - const res = await axiosInstance.post(API_ENDPOINTS.LOGOUT); - return res.data; // assuming API returns { message: "Logout successful" } + await axiosInstance.post(API_ENDPOINTS.LOGOUT); } catch (error) { console.error("Logout API failed:", error); - // even if API fails, still clear local storage } finally { - console.log("Clearing local storage..."); - // always clear local storage - localStorage.removeItem("access_token"); - clearFcmToken(); - window.location.replace("/"); + setAccessToken(null); + localStorage.clear(); + sessionStorage.clear(); + window.location.replace("/login"); } }; diff --git a/src/components/auth/ChangePasswordForm.jsx b/src/components/auth/ChangePasswordForm.jsx index 85bffe8..63e6bc4 100644 --- a/src/components/auth/ChangePasswordForm.jsx +++ b/src/components/auth/ChangePasswordForm.jsx @@ -20,6 +20,9 @@ import CheckIcon from '@mui/icons-material/Check' import CloseIcon from '@mui/icons-material/Close' import { keyframes } from '@mui/system' import MuiDynamicInput from '../../utills/MuiDynamicInput' +import { useMutation } from '@tanstack/react-query' +import axiosInstance from '../../api/axiosInstance' +import toast from 'react-hot-toast' // Keyframe animations const scaleIn = keyframes` @@ -237,11 +240,9 @@ function PasswordRequirements({ password }) { } const ChangePasswordPage = () => { - const [loading, setLoading] = React.useState(false) const [successModal, setSuccessModal] = React.useState(false) const [formData, setFormData] = React.useState({ - currentPassword: '', newPassword: '', confirmPassword: '', }) @@ -259,10 +260,6 @@ const ChangePasswordPage = () => { const validateForm = () => { const newErrors = {} - if (!formData.currentPassword) { - newErrors.currentPassword = 'Current password is required' - } - if (!formData.newPassword) { newErrors.newPassword = 'New password is required' } else if (formData.newPassword.length < 8) { @@ -277,31 +274,34 @@ const ChangePasswordPage = () => { newErrors.confirmPassword = 'Passwords do not match' } - if (formData.currentPassword === formData.newPassword) { - newErrors.newPassword = 'New password must be different from current' - } - setErrors(newErrors) return Object.keys(newErrors).length === 0 } - const handleSubmit = async () => { - if (!validateForm()) return - - setLoading(true) - setTimeout(() => { - setLoading(false) + const { mutate, isPending } = useMutation({ + mutationFn: async (password) => { + const response = await axiosInstance.post(`/change_password?password=${encodeURIComponent(password)}`) + return response.data + }, + onSuccess: (data) => { setSuccessModal(true) - console.log('Change Password Data:', { - currentPassword: formData.currentPassword, - newPassword: formData.newPassword, - }) - }, 1500) + toast.success(data.message || "Password changed successfully") + }, + onError: (error) => { + console.error("Change password error:", error) + const msg = error.response?.data?.message || "Failed to update password" + toast.error(msg) + } + }) + + const handleSubmit = () => { + if (!validateForm()) return + mutate(formData.newPassword) } const handleSuccessClose = () => { setSuccessModal(false) - setFormData({ currentPassword: '', newPassword: '', confirmPassword: '' }) + setFormData({ newPassword: '', confirmPassword: '' }) console.log('Navigate to profile or dashboard...') } @@ -476,16 +476,6 @@ const ChangePasswordPage = () => { {/* Form Fields */} - { variant="contained" onClick={handleSubmit} - disabled={loading} + disabled={isPending} sx={{ width:"fit-content", mx: 'auto', @@ -573,7 +563,7 @@ const ChangePasswordPage = () => { }, }} > - {loading ? ( + {isPending ? ( ) : ( 'Update Password' diff --git a/src/components/auth/ForgotPassworForm.jsx b/src/components/auth/ForgotPassworForm.jsx index bcc7746..a3487af 100644 --- a/src/components/auth/ForgotPassworForm.jsx +++ b/src/components/auth/ForgotPassworForm.jsx @@ -3,7 +3,7 @@ import { Card, Typography, Button, - Link, + // Link, Container, Dialog, DialogContent, @@ -18,12 +18,14 @@ import { import CheckCircleIcon from '@mui/icons-material/CheckCircle' import ArrowBackIcon from '@mui/icons-material/ArrowBack' import LockResetIcon from '@mui/icons-material/LockReset' -import EmailIcon from '@mui/icons-material/Email' +import PhoneAndroidIcon from '@mui/icons-material/PhoneAndroid' import VpnKeyIcon from '@mui/icons-material/VpnKey' import { keyframes } from '@mui/system' import { useEffect, useRef, useState } from 'react' import MuiDynamicInput from '../../utills/MuiDynamicInput' - +import axiosInstance from '../../api/axiosInstance' +import toast from 'react-hot-toast' +import { Link } from 'react-router-dom' // Keyframe animations const scaleIn = keyframes` 0% { transform: scale(0); opacity: 0; } @@ -151,7 +153,7 @@ function SuccessModal({ open, onClose, title, message }) { // OTP Input Component function OTPInput({ value, onChange, error, disabled }) { const inputRefs = useRef([]) - const otpLength = 6 + const otpLength = 4 const handleChange = (index, e) => { const val = e.target.value @@ -245,7 +247,7 @@ function OTPInput({ value, onChange, error, disabled }) { const ForgotPassworForm = () => { - const steps = ['Enter Email', 'Verify OTP', 'Reset Password'] + const steps = ['Enter Mobile', 'Verify OTP', 'Reset Password'] const [activeStep, setActiveStep] = useState(0) const [loading, setLoading] = useState(false) @@ -253,7 +255,7 @@ const ForgotPassworForm = () => { const [resendTimer, setResendTimer] = useState(0) const [formData, setFormData] = useState({ - email: '', + mobile: '', otp: '', newPassword: '', confirmPassword: '', @@ -280,13 +282,13 @@ const ForgotPassworForm = () => { } } - // Step 1: Validate Email - const validateEmail = () => { + // Step 1: Validate Mobile + const validateMobile = () => { const newErrors = {} - if (!formData.email) { - newErrors.email = 'Email is required' - } else if (!/^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/.test(formData.email)) { - newErrors.email = 'Enter a valid email address' + if (!formData.mobile) { + newErrors.mobile = 'Mobile number is required' + } else if (!/^\d{10}$/.test(formData.mobile)) { + newErrors.mobile = 'Enter a valid 10-digit mobile number' } setErrors(newErrors) return Object.keys(newErrors).length === 0 @@ -295,7 +297,7 @@ const ForgotPassworForm = () => { // Step 2: Validate OTP const validateOTP = () => { const newErrors = {} - if (!formData.otp || formData.otp.length !== 6) { + if (!formData.otp || formData.otp.length !== 4) { newErrors.otp = 'Please enter the 6-digit OTP' } setErrors(newErrors) @@ -323,17 +325,23 @@ const ForgotPassworForm = () => { return Object.keys(newErrors).length === 0 } - // Submit Email - const handleEmailSubmit = async () => { - if (!validateEmail()) return + // Submit Mobile + const handleMobileSubmit = async () => { + if (!validateMobile()) return setLoading(true) - setTimeout(() => { + try { + const response = await axiosInstance.post(`/forgot_password_send_otp?mobile=${formData.mobile}`) + toast.success(response.data?.message || "OTP sent successfully") setLoading(false) setActiveStep(1) setResendTimer(120) // 2 minutes timer - console.log('OTP sent to:', formData.email) - }, 1500) + } catch (error) { + setLoading(false) + console.error("Forgot password error:", error) + const errorMessage = error.response?.data?.message || error.response?.data?.error || "Failed to send OTP" + toast.error(errorMessage) + } } // Verify OTP @@ -341,18 +349,22 @@ const ForgotPassworForm = () => { if (!validateOTP()) return setLoading(true) - setTimeout(() => { + try { + const response = await axiosInstance.post(`/forgot_password_verify_otp?mobile=${formData.mobile}&otp=${formData.otp}`) + toast.success(response.data?.message || "OTP Verified Successfully") setLoading(false) setActiveStep(2) - console.log('OTP Verified:', formData.otp) - }, 1500) + } catch (error) { + setLoading(false) + console.error("OTP verification error:", error) + const errorMessage = error.response?.data?.message || error.response?.data?.error || "Invalid OTP" + toast.error(errorMessage) + } } // Resend OTP const handleResendOTP = () => { - setResendTimer(120) - setFormData((prev) => ({ ...prev, otp: '' })) - console.log('OTP Resent to:', formData.email) + handleMobileSubmit() } // Submit New Password @@ -360,15 +372,18 @@ const ForgotPassworForm = () => { if (!validatePassword()) return setLoading(true) - setTimeout(() => { + try { + const encodedPassword = encodeURIComponent(formData.newPassword) + const response = await axiosInstance.post(`/forgot_password_update?mobile=${formData.mobile}&otp=${formData.otp}&password=${encodedPassword}`) + toast.success(response.data?.message || "Password updated successfully") setLoading(false) setSuccessModal(true) - console.log('Password Reset Data:', { - email: formData.email, - otp: formData.otp, - newPassword: formData.newPassword, - }) - }, 1500) + } catch (error) { + setLoading(false) + console.error("Password update error:", error) + const errorMessage = error.response?.data?.message || error.response?.data?.error || "Failed to update password" + toast.error(errorMessage) + } } const handleBack = () => { @@ -381,7 +396,7 @@ const ForgotPassworForm = () => { const handleSuccessClose = () => { setSuccessModal(false) setActiveStep(0) - setFormData({ email: '', otp: '', newPassword: '', confirmPassword: '' }) + setFormData({ mobile: '', otp: '', newPassword: '', confirmPassword: '' }) // Navigate to login page console.log('Navigate to login...') } @@ -396,7 +411,7 @@ const ForgotPassworForm = () => { const getStepIcon = (step) => { switch (step) { case 0: - return + return case 1: return case 2: @@ -484,7 +499,7 @@ const ForgotPassworForm = () => { {/* Form Content */} - {/* Step 1: Email */} + {/* Step 1: Mobile */} {activeStep === 0 && ( @@ -506,7 +521,7 @@ const ForgotPassworForm = () => { justifyContent: 'center', }} > - + @@ -514,17 +529,18 @@ const ForgotPassworForm = () => { variant="body1" sx={{ textAlign: 'center', mb: 3, color: 'text.secondary' }} > - Enter your email address and we'll send you an OTP to reset + Enter your mobile number and we'll send you an OTP to reset your password. @@ -532,7 +548,7 @@ const ForgotPassworForm = () => { + + + + Remember your password?{" "} + + Login + + + + + + + ); +}; + +export default ForgotPasswordForm; \ No newline at end of file diff --git a/src/components/common/ProfileHeader.jsx b/src/components/common/ProfileHeader.jsx index bd5df70..39d29bd 100644 --- a/src/components/common/ProfileHeader.jsx +++ b/src/components/common/ProfileHeader.jsx @@ -24,6 +24,9 @@ import { useTheme, useMediaQuery, ListItemIcon } from "@mui/material"; import { Home, Users, Heart, MessageCircle, Search, Bell } from "lucide-react"; import { isAuthenticated } from "../../utills/auth"; import userimg from "../../assets/images/bride1.jpg" +import axiosInstance, { logoutAPI } from "../../api/axiosInstance"; +import toast from "react-hot-toast"; +import { API_ENDPOINTS } from "../../api/apiEndpoints"; const NAV_LINKS = [ // { label: "Home", path: "/" }, { label: "Matches", path: "/matches" }, @@ -187,10 +190,8 @@ const ProfileHeader = () => { }; const handleLogout = () => { - // Add your logout logic here - console.log("Logged out"); setLogoutModalOpen(false); - navigate("/login"); + logoutAPI(); }; const modalStyle = { diff --git a/src/components/ui/ProfileCardDemo.jsx b/src/components/ui/ProfileCardDemo.jsx index 69c272b..d5f71bf 100644 --- a/src/components/ui/ProfileCardDemo.jsx +++ b/src/components/ui/ProfileCardDemo.jsx @@ -1,17 +1,11 @@ import React from "react"; +import { Heart, X, Crown, Bookmark, Eye } from "lucide-react"; // Import your images import Profile1 from "../../assets/images/bride1.jpg"; import Profile2 from "../../assets/images/bride2.jpg"; import Profile3 from "../../assets/images/bride3.jpg"; import Profile4 from "../../assets/images/bride4.jpg"; import { motion } from "framer-motion"; -import ProfileCardItem from "../profiledashboard/ProfileCardItem"; -import CakeIcon from "@mui/icons-material/Cake"; -import AccessibilityNewIcon from "@mui/icons-material/AccessibilityNew"; -import AccountBalanceWalletIcon from "@mui/icons-material/AccountBalanceWallet"; -import LocationOnIcon from "@mui/icons-material/LocationOn"; -import GroupsIcon from "@mui/icons-material/Groups"; -import AutoAwesomeIcon from "@mui/icons-material/AutoAwesome"; export default function ProfileCard() { @@ -75,75 +69,96 @@ export default function ProfileCard() { }, ]; - const buildProfileRows = (profile) => [ - [ - { - icon: , - text: profile?.age || "-", - }, - { - icon: , - text: profile?.height || "-", - }, - ], - [ - { - icon: , - text: profile?.salary ? `${profile.salary} LPA` : "-", - }, - { - icon: , - text: profile?.location || "-", - }, - ], - [ - { - icon: , - text: profile?.caste || "-", - }, - { - icon: , - text: profile?.zodiac1 || "-", - }, - ], - [ - { - icon: , - text: profile?.zodiac2 || "-", - }, - ], - ]; + return ( +
- return ( -
- {/* HEADING */} - -

- Daily Recommended -

-

- Find your perfect match today -

-
+ {/* HEADING */} + +

+ Daily Recommended +

+

+ Find your perfect match today +

+
- {/* CARDS GRID */} -
-
- {profiles.map((profile) => ( - - ))} -
+ {/* CARDS GRID */} +
+
+ {profiles.map((profile) => ( +
+ {/* IMAGE SECTION */} +
+ profile + +
+ +
+ +
+ Shortlist +
+
+ + {/* CONTENT */} +
+

+ {profile.name} +

+ +
+

ID: {profile.idNumber}

+

+ {profile.lastSeen} +

+
+ +
+ {[ + profile.age, + profile.height, + profile.salary + " LPA", + profile.location, + profile.caste, + profile.zodiac1, + profile.zodiac2, + ].map((v, i) => ( + + {v} + + ))} +
+ +
+ + + +
+
+
+ ))}
- ); +
+); -} +} \ No newline at end of file diff --git a/src/feature/PersonalDetailsForm.jsx b/src/feature/PersonalDetailsForm.jsx index 200fbc4..0ae8fca 100644 --- a/src/feature/PersonalDetailsForm.jsx +++ b/src/feature/PersonalDetailsForm.jsx @@ -35,7 +35,7 @@ import { useSendOtp, useVerifyOtp } from "../hooks/useAuth"; const OTP_LENGTH = 4; const OTP_TIMER_SEC = 120; // 2 minutes -const PersonalDetailsForm = ({ onSubmitStep, errors, onFieldChange }) => { +const PersonalDetailsForm = ({ onSubmitStep, errors, onFieldChange, isStep1Update }) => { const dispatch = useDispatch(); const data = useSelector((state) => state.registerform.personalDetails); const nameInputRef = useRef(null); @@ -1012,6 +1012,7 @@ const PersonalDetailsForm = ({ onSubmitStep, errors, onFieldChange }) => {
{/* Password */} + {!isStep1Update && (
)}
+ )} {/* Confirm Password */} + {!isStep1Update && (
+ )} {/* State */}
diff --git a/src/feature/StepperForm.jsx b/src/feature/StepperForm.jsx index 2b8f025..7c65f25 100644 --- a/src/feature/StepperForm.jsx +++ b/src/feature/StepperForm.jsx @@ -23,7 +23,7 @@ import { useRegisterStep4, useRegisterStep5, } from "../hooks/useRegister"; -import { setAccessToken } from "../api/axiosInstance"; +import axiosInstance, { setAccessToken } from "../api/axiosInstance"; import toast from "react-hot-toast"; const STEP_FIELD_ORDER = { @@ -180,6 +180,7 @@ const StepperForm = () => { const initialStep = location.state?.step || 1; const [currentStep, setCurrentStep] = useState(initialStep); + const [isStep1Update, setIsStep1Update] = useState(false); const [errors, setErrors] = useState({}); const registerStep1 = useRegisterStep1(); @@ -329,6 +330,53 @@ const StepperForm = () => { } }, [location.state?.step]); + useEffect(() => { + const fetchPersonalDetails = async () => { + try { + const response = await axiosInstance.get("/get_personal_details"); + const data = response.data; + if (data.status === "success" && data.personal_details) { + const pd = data.personal_details; + setIsStep1Update(true); + + const mappedImages = (pd.images || []).map((url, index) => ({ + id: `server-${index}`, + preview: url, + name: `image-${index}.png`, + })); + + const formattedDob = pd.dob ? pd.dob.split("T")[0] : ""; + + dispatch( + updatePersonalDetails({ + name: pd.name || "", + mobileNumber: pd.mobile || "", + email: pd.email || "", + gender: pd.gender || "", + dob: formattedDob, + height: pd.height || "", + weight: pd.weight || "", + maritalStatus: pd.marital_status_id || "", + religion: pd.religion_id || "", + profileFor: pd.profile_for_id || "", + caste: pd.caste_id || "", + subCaste: pd.sub_caste_id || "", + gothram: pd.gothram_id || "", + raasi: pd.raasi_id || "", + star: pd.star_id || "", + state: pd.state_id || "", + city: pd.district_id || "", + pincode: pd.pincode || "", + profiles: mappedImages, + }) + ); + } + } catch (error) { + console.error("Error fetching personal details:", error); + } + }; + fetchPersonalDetails(); + }, [dispatch]); @@ -345,8 +393,6 @@ const StepperForm = () => { "profileFor", "caste", "email", - "password", - "confirmPassword", "state", "city", "pincode", @@ -358,6 +404,11 @@ const StepperForm = () => { } }); + if (!isStep1Update) { + if (!personalDetails.password) newErrors.password = "This field is required"; + if (!personalDetails.confirmPassword) newErrors.confirmPassword = "This field is required"; + } + if ( personalDetails.email && !/\S+@\S+\.\S+/.test(personalDetails.email) @@ -474,7 +525,7 @@ const StepperForm = () => { formData.append("state", personalDetails.state); formData.append("district", personalDetails.city); formData.append("password", personalDetails.password || ""); - formData.append("fcm_token", localStorage.getItem("fcm_token") || ""); + formData.append("web_fcm_token", localStorage.getItem("fcm_token") || ""); if (personalDetails.profiles && Array.isArray(personalDetails.profiles)) { for (const [index, item] of personalDetails.profiles.entries()) { @@ -633,8 +684,14 @@ const StepperForm = () => { try { if (currentStep === 1) { const payload = await buildRegisterStep1Payload(); - const res = await registerStep1.mutateAsync(payload); - const token = extractAccessToken(res); + let res; + if (isStep1Update) { + res = await axiosInstance.post("/update_personal_details", payload); + } else { + res = await registerStep1.mutateAsync(payload); + } + + const token = extractAccessToken(res.data || res); if (token) { setAccessToken(token); } @@ -725,6 +782,7 @@ const StepperForm = () => { onSubmitStep={handleStepSubmit} errors={errors} onFieldChange={clearFieldErrors} + isStep1Update={isStep1Update} /> ); case 2: diff --git a/src/pages/auth/LoginPage.jsx b/src/pages/auth/LoginPage.jsx index 07e00f7..0119a95 100644 --- a/src/pages/auth/LoginPage.jsx +++ b/src/pages/auth/LoginPage.jsx @@ -1,25 +1,203 @@ -import LoginPanel from "../../components/auth/LoginPanel" -import PromoPanel from "../../components/auth/PromoPanel" +import React, { useState } from "react"; +import { + Box, + Button, + TextField, + Typography, + InputAdornment, + IconButton, + Link as MuiLink, +} from "@mui/material"; +import { Visibility, VisibilityOff } from "@mui/icons-material"; +import { useNavigate, Link } from "react-router-dom"; +import toast from "react-hot-toast"; +import axiosInstance, { setAccessToken } from "../../api/axiosInstance"; +import PromoPanel from "../../components/auth/PromoPanel"; const LoginPage = () => { + const navigate = useNavigate(); + const [showPassword, setShowPassword] = useState(false); + const [loading, setLoading] = useState(false); + const [formData, setFormData] = useState({ + mobile: "", + password: "", + }); + const [errors, setErrors] = useState({}); + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData((prev) => ({ + ...prev, + [name]: value, + })); + if (errors[name]) { + setErrors((prev) => ({ ...prev, [name]: "" })); + } + }; + + const validate = () => { + const newErrors = {}; + if (!formData.mobile) newErrors.mobile = "Mobile number is required"; + else if (!/^\d{10}$/.test(formData.mobile)) + newErrors.mobile = "Enter a valid 10-digit mobile number"; + + if (!formData.password) newErrors.password = "Password is required"; + + setErrors(newErrors); + return Object.keys(newErrors).length === 0; + }; + + const handleLogin = async (e) => { + e.preventDefault(); + if (!validate()) return; + + setLoading(true); + + // Retrieve FCM token from localStorage + const fcmToken = localStorage.getItem("fcm_token") || ""; + + const payload = { + mobile: formData.mobile, + password: formData.password, + web_fcm_token: fcmToken, + }; + + try { + const response = await axiosInstance.post("/login", payload); + const data = response.data; + + // Extract token from response + const token = data?.access_token || data?.token || data?.accessToken || data?.data?.access_token; + + if (token) { + // Store token in localStorage and axios instance + localStorage.setItem("access_token", token); + setAccessToken(token); + + toast.success("Login Successful!"); + navigate("/dashboard-home"); + } else { + toast.error("Login failed: No access token received."); + } + } catch (error) { + console.error("Login error:", error); + const errorMessage = + error?.response?.data?.message || + error?.response?.data?.error || + "Login failed. Please check your credentials."; + toast.error(errorMessage); + } finally { + setLoading(false); + } + }; + return ( - <> -
- -
-
- {/* Left: Promo */} +
+
+
-
+
-
- {/* Right: Login */} - -
-
-
- - ) -} +
+
+ + Welcome Back + + + Please login to your account + -export default LoginPage +
+ + + + + setShowPassword(!showPassword)} + edge="end" + > + {showPassword ? : } + + + ), + }} + /> + + + + Forgot Password? + + + + + + + + Don't have an account?{" "} + + Register Now + + + + +
+
+
+
+
+ ); +}; + +export default LoginPage; \ No newline at end of file diff --git a/src/routes/PublicRoutes.jsx b/src/routes/PublicRoutes.jsx index 4c98607..10cd86a 100644 --- a/src/routes/PublicRoutes.jsx +++ b/src/routes/PublicRoutes.jsx @@ -1,23 +1,33 @@ import { lazy } from "react"; -import { Route } from "react-router-dom"; +import { Route, Navigate, Outlet } from "react-router-dom"; import HomeLayout from "../layout/HomeLayout"; +import { isAuthenticated } from "../utills/auth"; const HomePage = lazy(() => import("../pages/HomePage")); const LoginPage = lazy(() => import("../pages/auth/LoginPage")); const ForgotPasswordPage = lazy(() => import("../pages/auth/ForgotPasswordPage")); const StepperForm = lazy(() => import("../feature/StepperForm")); const NotFound = lazy(() => import("../pages/NotFound")); + +const PublicGuard = () => { + const auth = isAuthenticated(); + return auth ? : ; +}; + const PublicRoutes = () => { return ( <> }> } /> - } /> - + }> + } /> + - } /> - } /> + }> + } /> + } /> + {/* 404 route MUST be last */} } />