diff --git a/src/App.jsx b/src/App.jsx index aa8f6b4..e78635c 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,6 +1,7 @@ import { BrowserRouter, Routes, Route, useNavigate } from 'react-router-dom'; import { CssBaseline } from '@mui/material'; import LanguageSelect from './components/LanguageSelect'; +import Signup from './components/Signup'; import Login from './components/Login'; import Home from './components/Home'; import Upload from './components/Upload'; @@ -48,6 +49,7 @@ const App = () => { } /> + } /> {/* } /> */} } /> } /> diff --git a/src/components/Header.jsx b/src/components/Header.jsx index c8ecade..fec26ad 100644 --- a/src/components/Header.jsx +++ b/src/components/Header.jsx @@ -1,4 +1,5 @@ import React, { useState } from "react"; +import { useLocation } from "react-router-dom"; import { AppBar, Toolbar, @@ -12,6 +13,7 @@ import SlideMenu from "./SlideMenu"; const Header = () => { // Define the state to store selected language const [language, setLanguage] = useState("EN"); + const shouldShowSlideMenu = location.pathname !== "/signup"; const handleLanguageChange = (event) => { setLanguage(event.target.value); @@ -26,7 +28,7 @@ const Header = () => { > {/* Menu */} - + {shouldShowSlideMenu && } {/* E-Wallet Title */} { fullWidth size="large" onClick={handleLogin} - sx={{ borderRadius: 7 }} + sx={{ borderRadius: 7,fontFamily: "Poppins, sans-serif",bgcolor: "#121943" }} > Log In to E-Wallet + ); diff --git a/src/components/Signup.jsx b/src/components/Signup.jsx new file mode 100644 index 0000000..c2dec8a --- /dev/null +++ b/src/components/Signup.jsx @@ -0,0 +1,266 @@ +import React, { useState, useEffect } from "react"; +import { useNavigate } from "react-router-dom"; +import axios from "axios"; +import { + Box, + Paper, + Typography, + AppBar, + Button, + TextField, + Toolbar, + IconButton, + Container, + FormHelperText, +} from "@mui/material"; +import ArrowBackIcon from "@mui/icons-material/ArrowBack"; +import { MuiOtpInput } from "mui-one-time-password-input"; +import Header from "./Header"; + +const Signup = () => { + const navigate = useNavigate(); + const [firstName, setFirstName] = useState(""); + const [lastName, setLastName] = useState(""); + const [phone, setPhone] = useState(""); + const [otp, setOtp] = useState(""); + const [timer, setTimer] = useState(0); + const [showOtpSection, setShowOtpSection] = useState(false); + const [error, setError] = useState({ phone: "", otp: "" }); + const [tokens, setTokens] = useState(""); // Store the token received from the API + const apiURL= import.meta.env.VITE_APP_API_URL; + + // Timer countdown logic + useEffect(() => { + if (timer === 0) return; + + const interval = setInterval(() => { + setTimer((prevTime) => prevTime - 1); + }, 1000); + + return () => clearInterval(interval); + }, [timer]); + + const formatTime = (time) => { + const minutes = Math.floor(time / 60); + const seconds = time % 60; + return `${minutes < 10 ? `0${minutes}` : minutes}:${seconds < 10 ? `0${seconds}` : seconds}`; + }; + + const validatePhoneNumber = (phoneNumber) => { + const regex = /^\d{10}$/; + if (phoneNumber === "" || !regex.test(phoneNumber)) { + setError((prevState) => ({ + ...prevState, + phone: "Please enter a valid 10-digit phone number.", + })); + } else { + setError((prevState) => ({ ...prevState, phone: "" })); + } + }; + + const handlePhoneChange = (e) => { + const value = e.target.value; + setPhone(value); + validatePhoneNumber(value); + }; + + const handleOtpChange = (newOtp) => { + setOtp(newOtp); + if (newOtp.length !== 6) { + setError((prevState) => ({ + ...prevState, + otp: "OTP must be exactly 6 digits.", + })); + } else { + setError((prevState) => ({ ...prevState, otp: "" })); + } + }; + + const handleProceed = async () => { + if (!phone || error.phone) return; + + try { + const response = await axios.post(`${apiURL}/otp/send_otp`, { + phone_number: `+91-${phone}`, + }); + + setTokens(response.data.data.token); // Save the token for OTP verification + setShowOtpSection(true); + setTimer(300); // Start 5-minute timer + } catch (err) { + setError((prevState) => ({ + ...prevState, + phone: err.response?.data?.message || "Failed to send OTP.", + })); + } + }; + + const handleResendOtp = async () => { + try { + const response = await axios.post(`${apiURL}/otp/send_otp`, { + phone_number: `+91-${phone}`, + }); + + setTokens(response.data.data.token); // Save the token again + setOtp(""); + setTimer(300); // Reset timer + } catch (err) { + setError((prevState) => ({ + ...prevState, + phone: err.response?.data?.message || "Failed to resend OTP.", + })); + } + }; + + const handleSignUp = async () => { + if (!otp || error.otp) return; + + try { + // First, verify the OTP + const otpResponse = await axios.post(`${apiURL}/otp/verify_otp`, { + phone_number: `+91-${phone}`, + otp: Number(otp), + token: tokens, + }); + + // If OTP is verified successfully, proceed to register the user + if (otpResponse?.data?.statusCode === 200) { + const registrationResponse = await axios.post(`${apiURL}/auth/register`, { + firstName: firstName, + lastName: lastName, + phoneNumber: phone, + }); + + // If registration is successful, navigate to the login page + if (registrationResponse?.data?.statusCode === 200) { + navigate("/"); + } else { + // Handle registration failure (optional) + setError((prevState) => ({ + ...prevState, + otp: registrationResponse?.data?.message || "Registration failed. Please try again.", + })); + } + } else { + setError((prevState) => ({ + ...prevState, + otp: otpResponse?.data?.message || "Invalid OTP. Please try again.", + })); + } + } catch (err) { + // Handle any other errors (network issues, etc.) + setError((prevState) => ({ + ...prevState, + otp: err.response?.data?.message || "An error occurred. Please try again.", + })); + } + }; + + return ( + + +
+ + navigate(-1)}> + + + + Register + + + + + + + setFirstName(e.target.value)} + sx={{ mb: 2 }} + /> + setLastName(e.target.value)} + sx={{ mb: 2 }} + /> + + + {!showOtpSection && ( + + )} + + {showOtpSection && ( + <> + + Enter the 6-digit OTP sent via SMS + + + {error.otp && ( + + {error.otp} + + )} + + Resend OTP in {formatTime(timer)} + + + + + )} + + + + Already signed up? + + + + + ); +}; + +export default Signup; \ No newline at end of file