445 lines
17 KiB
React
445 lines
17 KiB
React
import React, { useCallback, useEffect, useState } from "react";
|
|
import { Link, useLocation, useNavigate } from "react-router-dom";
|
|
import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
|
|
import usersService from "../../../services/UsersService";
|
|
import InputCom from "../../Helpers/Inputs/InputCom";
|
|
import AuthLayout from "../AuthLayout2";
|
|
|
|
export default function SignUp() {
|
|
// eslint-disable-next-line no-restricted-globals
|
|
const queryParams = new URLSearchParams(location?.search);
|
|
const country = queryParams.get("cnt")?.toUpperCase();
|
|
|
|
const { pathname } = useLocation();
|
|
const currentPath = country
|
|
? `${pathname}?cnt=${country.toLowerCase()}`
|
|
: pathname; // Determines the new pathname is country query params exist
|
|
|
|
const [signUpLoading, setSignUpLoading] = useState(false);
|
|
const [checked, setValue] = useState(false);
|
|
// for the catch error
|
|
const [msgError, setMsgError] = useState("");
|
|
const [showPassword, setShowPassword] = useState(false);
|
|
const [countries, setCountries] = useState({ loading: true, data: [] });
|
|
|
|
const [formData, setFormData] = useState({
|
|
country: country ? country : "",
|
|
first_name: "",
|
|
last_name: "",
|
|
email: "",
|
|
password: "",
|
|
});
|
|
|
|
const handleInputChange = (event) => {
|
|
const { name, value } = event?.target;
|
|
setFormData({ ...formData, [name]: value });
|
|
};
|
|
|
|
// To Show and Hide Password
|
|
const togglePasswordVisibility = () => {
|
|
setShowPassword(!showPassword);
|
|
};
|
|
|
|
const rememberMe = () => {
|
|
setValue(!checked);
|
|
};
|
|
|
|
const navigate = useNavigate();
|
|
const userApi = new usersService();
|
|
|
|
// Get Country Api
|
|
const getCountryList = useCallback(async () => {
|
|
try {
|
|
const res = await userApi.getSignupCountryData();
|
|
if (res.status === 200 && res.data.internal_return >= 0) {
|
|
const { result_list } = await res.data;
|
|
if (country) {
|
|
// IF LINK/PATHNAME HAS CNT QUERY VALUE
|
|
let cnt = result_list.filter((item) => item.code == country); // test to see country passed in query param exist from list of countries supplied by API
|
|
if (!cnt.length) {
|
|
// IF CNT EMPTY, SET FORMDATA COUNTRY BACK TO EMPTY STRING: RE: THIS IS BCOS WE INITAIL SET COUNTRY VALUE IN FORMDATA, IF COUNTRY PARAM IS PRESENT IN LINK
|
|
setFormData((prev) => ({ ...prev, country: "" }));
|
|
return setCountries({ loading: false, data: result_list });
|
|
}
|
|
return setCountries({ loading: false, data: cnt });
|
|
}
|
|
setCountries({ loading: false, data: result_list });
|
|
} else if (res.data.result !== 100) {
|
|
setCountries({ loading: false, data: [] });
|
|
}
|
|
} catch (error) {
|
|
throw new Error(error);
|
|
}
|
|
}, []);
|
|
|
|
const handleSignUp = async () => {
|
|
let { country, first_name, last_name, email, password } = formData;
|
|
try {
|
|
if (
|
|
email !== "" &&
|
|
password !== "" &&
|
|
first_name !== "" &&
|
|
last_name !== "" &&
|
|
country !== ""
|
|
) {
|
|
//checks if email is a valid email address
|
|
let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/;
|
|
if (regEx.test(email) == false) {
|
|
setMsgError("Invalid Email");
|
|
return setTimeout(() => {
|
|
setMsgError("");
|
|
}, 3000);
|
|
}
|
|
|
|
//checks if terms and condition is checked
|
|
if (!checked) {
|
|
setMsgError("Terms and condition required");
|
|
return setTimeout(() => {
|
|
setMsgError("");
|
|
}, 3000);
|
|
}
|
|
|
|
setSignUpLoading(true);
|
|
const reqData = {
|
|
country: country,
|
|
firstname: first_name,
|
|
lastname: last_name,
|
|
email: email,
|
|
username: email,
|
|
password: password,
|
|
terms: 1,
|
|
news: 1,
|
|
};
|
|
|
|
const res = await userApi.CreateUser(reqData);
|
|
|
|
if (res.status === 200) {
|
|
const { data } = res;
|
|
if (data && data.acc === "DULPICATE") {
|
|
setMsgError("Duplicate username. Please try another email.");
|
|
setSignUpLoading(false);
|
|
}
|
|
if (data && data.status === "1") {
|
|
setTimeout(() => {
|
|
navigate("/outmessage", { replace: true });
|
|
setSignUpLoading(false);
|
|
}, 2000);
|
|
}
|
|
|
|
if (data && data.status === "5") {
|
|
setMsgError("Something went wrong. Please try another email.");
|
|
setSignUpLoading(false);
|
|
}
|
|
} else {
|
|
setSignUpLoading(false);
|
|
setMsgError("An error occurred");
|
|
}
|
|
} else {
|
|
setMsgError("Please fill in fields");
|
|
}
|
|
} catch (error) {
|
|
throw new Error(error);
|
|
} finally {
|
|
setTimeout(() => {
|
|
setMsgError(null);
|
|
}, process.env.REACT_APP_SIGNUP_ERROR_TIMEOUT);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
getCountryList();
|
|
}, []);
|
|
|
|
return (
|
|
<>
|
|
<AuthLayout slogan="Welcome to WrenchBoard">
|
|
<div className="w-full">
|
|
<div className="mb-5">
|
|
<Link to={currentPath}>
|
|
<img
|
|
src={WrenchBoard}
|
|
alt="wrenchboard"
|
|
className="h-10 mx-auto"
|
|
/>
|
|
</Link>
|
|
</div>
|
|
<div className="flex place-content-center">
|
|
<div className="w-10/12">
|
|
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
|
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
|
Create Account
|
|
</h1>
|
|
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
|
|
Already have an account?{" "}
|
|
<Link
|
|
to="/login"
|
|
className="font-semibold text-[#4687ba] hover:text-[#009ef7] transition"
|
|
>
|
|
Sign in here
|
|
</Link>
|
|
</span>
|
|
</div>
|
|
<div className="w-full flex items-center gap-2">
|
|
<div className="border-b border-[#eff2f5] max-w-[50%] w-full"></div>
|
|
<span className="text-[#b5b5c3] font-medium text-[0.7rem] w-[2%]">
|
|
OR
|
|
</span>
|
|
<div className="border-b border-[#eff2f5] max-w-[50%] w-full"></div>
|
|
</div>
|
|
<div className="input-area">
|
|
<SelectOption
|
|
label="Country"
|
|
data={countries}
|
|
name="country"
|
|
value={formData.country}
|
|
inputHandler={handleInputChange}
|
|
disable={
|
|
country && countries?.data?.length <= 1 ? true : false
|
|
}
|
|
/>
|
|
<div className="input-fl-name mb-4 sm:flex w-full sm:space-x-6 ">
|
|
<div className="input-item sm:w-1/2 w-full mb-4 sm:mb-0">
|
|
<InputCom
|
|
fieldClass="px-6"
|
|
placeholder="Firstname"
|
|
label="First Name"
|
|
name="first_name"
|
|
type="text"
|
|
value={formData.first_name}
|
|
inputHandler={handleInputChange}
|
|
/>
|
|
</div>
|
|
<div className="input-item flex-1">
|
|
<InputCom
|
|
fieldClass="px-6"
|
|
placeholder="Lastname"
|
|
label="Last Name"
|
|
name="last_name"
|
|
type="text"
|
|
value={formData.last_name}
|
|
inputHandler={handleInputChange}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="input-item mb-4">
|
|
<InputCom
|
|
fieldClass="px-6"
|
|
placeholder="support@mermsemr.com"
|
|
label="Email"
|
|
name="email"
|
|
type="email"
|
|
value={formData.email}
|
|
inputHandler={handleInputChange}
|
|
/>
|
|
</div>
|
|
<div className="input-item mb-4">
|
|
<InputCom
|
|
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
|
|
placeholder="● ● ● ● ● ●"
|
|
label="Password"
|
|
name="password"
|
|
type={showPassword ? "text" : "password"}
|
|
onClick={togglePasswordVisibility}
|
|
passIcon={showPassword ? "show-password" : "hide-password"}
|
|
value={formData.password}
|
|
inputHandler={handleInputChange}
|
|
/>
|
|
</div>
|
|
{msgError && (
|
|
<div className="p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px]">
|
|
{msgError}
|
|
</div>
|
|
)}
|
|
|
|
<div className="forgot-password-area flex justify-between items-center mb-6">
|
|
<div className="remember-checkbox flex items-center space-x-2.5 group cursor-pointer">
|
|
<button
|
|
onClick={rememberMe}
|
|
type="button"
|
|
className={`w-6 h-6 border-[#4687ba] text-white flex justify-center items-center border rounded-[.45em] group-checked:text-white transition-all duration-200 group-checked:cursor-default ${
|
|
checked && "text-white bg-[#4687ba]"
|
|
}`}
|
|
>
|
|
{checked && (
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
className="h-5 w-5"
|
|
viewBox="0 0 20 20"
|
|
fill="currentColor"
|
|
>
|
|
<path
|
|
fillRule="evenodd"
|
|
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
|
clipRule="evenodd"
|
|
/>
|
|
</svg>
|
|
)}
|
|
</button>
|
|
<span
|
|
onClick={rememberMe}
|
|
className="cursor-default text-dark-gray dark:text-white text-[15px] group-checked:text-white transition-all duration-200 group-checked:cursor-default"
|
|
>
|
|
I agree with all
|
|
<Link
|
|
href="#"
|
|
className="text-base text-[#4687ba] hover:text-[#009ef7] mx-1 inline-block"
|
|
>
|
|
terms and condition
|
|
</Link>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Forgot Password */}
|
|
{/* <div className="forgot-password-area flex justify-between items-center mb-6">
|
|
<div className="remember-checkbox flex items-center space-x-2.5">
|
|
<button
|
|
onClick={rememberMe}
|
|
type="button"
|
|
className="w-6 h-6 bg-[#4687ba] text-white flex justify-center items-center border border-light-gray rounded-[.45em]"
|
|
>
|
|
{checked && (
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
className="h-5 w-5"
|
|
viewBox="0 0 20 20"
|
|
fill="currentColor"
|
|
>
|
|
<path
|
|
fillRule="evenodd"
|
|
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
|
clipRule="evenodd"
|
|
/>
|
|
</svg>
|
|
)}
|
|
</button>
|
|
<span
|
|
onClick={rememberMe}
|
|
className="cursor-default text-dark-gray dark:text-white text-[15px]"
|
|
>
|
|
I agree with all
|
|
<Link
|
|
href="#"
|
|
className="text-base text-[#4687ba] hover:text-[#009ef7] mx-1 inline-block"
|
|
>
|
|
terms and condition
|
|
</Link>
|
|
</span>
|
|
</div>
|
|
</div> */}
|
|
<div className="signin-area mb-1">
|
|
<div className="flex justify-center">
|
|
<button
|
|
disabled={countries.loading}
|
|
type="button"
|
|
onClick={handleSignUp}
|
|
className={`rounded-full text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center h-[42px] py-[0.8875rem] px-[1.81rem] text-[14.95px] btn-login`}
|
|
>
|
|
{signUpLoading ? (
|
|
<div className="signup btn-loader"></div>
|
|
) : (
|
|
<span>Sign Up</span>
|
|
)}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* APP DOWNLOAD STORE */}
|
|
<div className="w-full mt-4">
|
|
<div className="w-full flex justify-center items-center gap-4">
|
|
<div className="w-28 lg:w-32">
|
|
<a
|
|
className="px-1 py-1 lg:py-2 flex justify-center items-center gap-1 w-full rounded-md bg-black text-white hover:text-slate-500 hover:shadow-lg transition-all duration-300"
|
|
target="_blank"
|
|
href={process.env.REACT_APP_APPLE_APP}
|
|
rel="noreferrer"
|
|
>
|
|
<i className="fa-brands fa-apple text-3xl"></i>
|
|
<div className="flex flex-col">
|
|
<span className="text-[11px]">Available on the</span>
|
|
<span className="text-[12px] lg:text-base">
|
|
App Store
|
|
</span>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
<div className="w-28 lg:w-32">
|
|
<a
|
|
className="px-1 py-1 lg:py-2 flex justify-center items-center gap-1 w-full rounded-md bg-black text-white hover:text-slate-500 hover:shadow-lg transition-all duration-300"
|
|
target="_blank"
|
|
href={process.env.REACT_APP_ANDROID_APP}
|
|
rel="noreferrer"
|
|
>
|
|
<i className="fa-brands fa-google-play text-2xl"></i>
|
|
<div className="flex flex-col">
|
|
<span className="text-[11px]">Available on the</span>
|
|
<span className="text-[12px] lg:text-base">
|
|
Google Play
|
|
</span>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</AuthLayout>
|
|
</>
|
|
);
|
|
}
|
|
|
|
const SelectOption = ({
|
|
label,
|
|
name,
|
|
inputHandler,
|
|
value,
|
|
data, // passing the data from parent
|
|
disable,
|
|
}) => {
|
|
return (
|
|
<div className="input-com mb-7">
|
|
<div className="flex items-center justify-between">
|
|
<label
|
|
className="input-label text-[#181c32] dark:text-white text-[15px] font-semibold block mb-2.5"
|
|
htmlFor={name}
|
|
>
|
|
{label}
|
|
</label>
|
|
</div>
|
|
<div>
|
|
<select
|
|
disabled={disable}
|
|
name={name}
|
|
id={name}
|
|
className="input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base focus-visible:border-transparent focus-visible:outline-0 focus-visible:ring-transparent "
|
|
onChange={inputHandler}
|
|
value={value}
|
|
>
|
|
{data?.data?.length > 1 ? (
|
|
<>
|
|
<option value={""}>Select your Country</option>
|
|
{data?.data?.map((item) => (
|
|
<option value={item.code} key={item.uid}>
|
|
{item.country}
|
|
</option>
|
|
))}
|
|
</>
|
|
) : data?.data?.length == 1 ? (
|
|
data?.data?.map((item) => (
|
|
<option value={item.code} key={item.uid}>
|
|
{item.country}
|
|
</option>
|
|
))
|
|
) : data?.data?.length < 1 && data.loading ? (
|
|
<option value="">Loading...</option>
|
|
) : (
|
|
<option value="">No Country Found!</option>
|
|
)}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|