Skip to content

Commit

Permalink
Registration Using Password (#54)
Browse files Browse the repository at this point in the history
* Sign Up

* Sign up with password

* Display username on successfull registration
  • Loading branch information
vidyaaKhandekar authored Dec 3, 2024
1 parent 1d24f88 commit 6fcb6e0
Showing 4 changed files with 278 additions and 3 deletions.
1 change: 0 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -17,7 +17,6 @@ function App() {
>([]);
const token = localStorage.getItem("authToken");
// const { keycloak } = useKeycloak();
console.log("token", token);

useEffect(() => {
if (token) {
2 changes: 1 addition & 1 deletion src/routes/GuestRoutes.tsx
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ import { lazy } from "react";
import SignIn from "../screens/auth/SignIn";

const Splash = lazy(() => import("../screens/auth/Splash"));
const Signup = lazy(() => import("../screens/auth/SignUp"));
const Signup = lazy(() => import("../screens/auth/SignUpWithPassword"));

const routes = [
{
255 changes: 255 additions & 0 deletions src/screens/auth/SignUpWithPassword.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
import React, { useEffect, useState } from "react";
import {
Box,
FormControl,
Text,
VStack,
Center,
useToast,
} from "@chakra-ui/react";
import { Link as RouterLink, useNavigate } from "react-router-dom";

import Layout from "../../components/common/layout/Layout";
import FloatingInput from "../../components/common/input/Input";
import FloatingPasswordInput from "../../components/common/input/PasswordInput";
import CommonButton from "../../components/common/button/Button";
import { useTranslation } from "react-i18next";
import Loader from "../../components/common/Loader";
import { registerWithPassword } from "../../services/auth/auth";

interface UserDetails {
firstName: string;
lastName: string;
phoneNumber: string;
password: string;
}

const SignUpWithPassword: React.FC = () => {
const navigate = useNavigate();
const { t } = useTranslation();
const toast = useToast();

const [userDetails, setUserDetails] = useState<UserDetails>({
firstName: "",
lastName: "",
phoneNumber: "",
password: "",
});
const [confirmPassword, setConfirmPassword] = useState<string>("");
const [loading, setLoading] = useState(false);
// const [isFormValid, setIsFormValid] = useState<boolean>(false);
const [UserName, SetUserName] = useState<string>("");
const handleBack = () => {
navigate(-1);
};

const [mobileError, setMobileError] = useState<string>("");

const validateMobile = (mobile: string): string => {
console.log("calling");

const trimmedMobile = mobile.trim();

if (!trimmedMobile) {
return "Mobile number is required.";
}

if (trimmedMobile.length !== 10) {
return "Mobile number must be exactly 10 digits long.";
}

const mobilePattern = /^[6-9]\d{9}$/;

if (!mobilePattern.test(trimmedMobile)) {
return "Mobile number must start with a digit between 6 and 9.";
}

return "";
};

const handleInputChange = (
e: React.ChangeEvent<HTMLInputElement>,
key: keyof UserDetails
) => {
const value = e.target.value;

setUserDetails((prev) => {
const updatedDetails = {
...prev,
[key]: value,
};

// Generate username based on available values
const { firstName, lastName, phoneNumber } = updatedDetails;

SetUserName(
`${firstName?.trim() || ""}_${lastName?.charAt(0) || ""}_${
phoneNumber?.slice(-4) || ""
}`
);

if (key === "phoneNumber") {
const errorMessage = validateMobile(value);
if (errorMessage !== "") {
setMobileError(errorMessage);
} else {
setMobileError("");
}
}

return updatedDetails;
});
};

const handleSignUp = async () => {
const errorMessage = validateMobile(userDetails.phoneNumber);
if (errorMessage !== "") {
toast({
title: t("SIGNUP_INVALID_MOBILE_NUMBER"),
status: "error",
duration: 3000,
isClosable: true,
});
return;
}
if (userDetails.password !== confirmPassword) {
toast({
title: t("SIGNUP_PASSWORDS_DO_NOT_MATCH"),
status: "error",
duration: 3000,
isClosable: true,
});
return;
}
try {
setLoading(true);
const response = await registerWithPassword(userDetails);
console.log("response", response);

if (response) {
toast({
title: "Sign Up Successfully",
status: "success",
description: `Your Username is ${response?.data?.userName}`,
duration: 15000,
isClosable: true,
});
navigate("/signin");
}
} catch (error) {
toast({
title: "Sign Up Failed",
description: error,
status: "error",
duration: 3000,
isClosable: true,
});
} finally {
setLoading(false);
}
};

useEffect(() => {
const { firstName, lastName, phoneNumber } = userDetails;

if (firstName && lastName && phoneNumber.length >= 6) {
const username = `${firstName}_${lastName?.charAt(
0
)}_${phoneNumber?.slice(-4)}`;
SetUserName(username);
}
}, [userDetails.firstName, userDetails.lastName, userDetails.phoneNumber]);
const validate = (phoneNumber) => {
const value = validateMobile(phoneNumber);
if (value === "") {
return true;
}
return false;
};
return (
<Layout
isMenu={false}
_heading={{
heading: t("LOGIN_REGISTER_BUTTON"),
handleBack,
}}
isBottombar={false}
>
{loading && <Loader />}
<Box p={5}>
<VStack align="stretch" spacing={4}>
<FormControl>
<FloatingInput
name="firstName"
label={t("SIGNUP_FIRST_NAME")}
value={userDetails.firstName}
onChange={(e) => handleInputChange(e, "firstName")}
isInvalid={!userDetails.firstName.trim()}
errorMessage={t("SIGNUP_FIRST_NAME_REQUIRED")}
/>
<FloatingInput
name="lastName"
label={t("SIGNUP_LAST_NAME")}
value={userDetails.lastName}
onChange={(e) => handleInputChange(e, "lastName")}
isInvalid={!userDetails.lastName.trim()}
errorMessage={t("SIGNUP_LAST_NAME_REQUIRED")}
/>
<FloatingInput
name="phoneNumber"
label={t("SIGNUP_MOBILE_NUMBER")}
value={userDetails.phoneNumber}
onChange={(e) => handleInputChange(e, "phoneNumber")}
isInvalid={!validate(userDetails.phoneNumber)}
errorMessage={mobileError}
/>
<FloatingPasswordInput
label={t("SIGNUP_PASSWORD")}
value={userDetails.password}
onChange={(e) => handleInputChange(e, "password")}
isInvalid={!userDetails.password.trim()}
errorMessage={t("SIGNUP_PASSWORD_REQUIRED")}
/>

<FloatingPasswordInput
label={t("SIGNUP_CONFIRM_PASSWORD")}
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
isInvalid={confirmPassword.trim() === ""}
errorMessage={t("SIGNUP_CONFIRM_PASSWORD_REQUIRED")}
/>
{UserName.length > 0 && (
<Text textAlign="center" fontSize="14px" mt={4}>
{"Your username will be "}
<Text as="span" fontWeight="bold" color="#06164B">
{UserName}
</Text>
</Text>
)}
<CommonButton
mt={4}
label={"Register"}
onClick={handleSignUp}
//
/>
</FormControl>
</VStack>
<Center>
<Text mt={6}>
{t("SIGNUP_ALREADY_HAVE_AN_ACCOUNT")}
<Box as="span" ml={2}>
<RouterLink
to="/signin"
style={{ color: "blue", textDecoration: "underline" }}
>
{t("LOGIN_LOGIN_BUTTON")}
</RouterLink>
</Box>
</Text>
</Center>
</Box>
</Layout>
);
};

export default SignUpWithPassword;
23 changes: 22 additions & 1 deletion src/services/auth/auth.tsx
Original file line number Diff line number Diff line change
@@ -244,11 +244,32 @@ export const verifyOTP = async (payload: MobileData) => {
};
export const registerUser = async (userData: UserData) => {
try {
const response = await axios.post(`${apiBaseUrl}/auth/register`, userData);
const response = await axios.post(
`${apiBaseUrl}/auth/register_with_password`,
userData
);
console.log(response);
return response?.data;
} catch (error) {
console.log(error);
return error;
}
};
export const registerWithPassword = async (userData) => {
try {
const response = await axios.post(
`${apiBaseUrl}/auth/register_with_password`,
userData
);
console.log(response.data);

return response.data; // Handle the response data
} catch (error) {
console.log(error);
console.error(
"Error during registration:",
error.response?.data?.message?.[0] || ""
);
throw error.response?.data?.message?.[0];
}
};

0 comments on commit 6fcb6e0

Please sign in to comment.