|
|
@ -10,6 +10,7 @@ import { useUserContext } from "@/components/contexts/userContext"; |
|
|
|
import { ToastContainer, toast } from "react-toastify"; |
|
|
|
import "react-toastify/dist/ReactToastify.css"; |
|
|
|
import { PhoneNumberUtil, PhoneNumberFormat } from "google-libphonenumber"; // Import libphonenumber
|
|
|
|
import { BiShow, BiHide } from "react-icons/bi"; |
|
|
|
|
|
|
|
export interface PageSignUpProps {} |
|
|
|
|
|
|
@ -18,14 +19,20 @@ const PageSignUp: FC<PageSignUpProps> = () => { |
|
|
|
const { setForm, setMethod } = useUserContext(); |
|
|
|
const phoneUtil = PhoneNumberUtil.getInstance(); |
|
|
|
|
|
|
|
const [name, setName] = useState(''); |
|
|
|
const [countryCode, setCountryCode] = useState('968'); |
|
|
|
const [phoneNumber, setPhoneNumber] = useState(''); |
|
|
|
const [password, setPassword] = useState(''); |
|
|
|
const [confirmPassword, setConfirmPassword] = useState(''); |
|
|
|
const [loading , setLoading] = useState(false) |
|
|
|
|
|
|
|
const [errors, setErrors] = useState<{ phoneNumber?: string; password?: string; confirmPassword?: string; countryCode? : string }>({}); |
|
|
|
const [name, setName] = useState(""); |
|
|
|
const [countryCode, setCountryCode] = useState("968"); |
|
|
|
const [phoneNumber, setPhoneNumber] = useState(""); |
|
|
|
const [password, setPassword] = useState(""); |
|
|
|
const [confirmPassword, setConfirmPassword] = useState(""); |
|
|
|
const [loading, setLoading] = useState(false); |
|
|
|
const [showPassword, setShowPassword] = useState(false); |
|
|
|
const [showConfirm, setShowConfirm] = useState(false); |
|
|
|
const [errors, setErrors] = useState<{ |
|
|
|
phoneNumber?: string; |
|
|
|
password?: string; |
|
|
|
confirmPassword?: string; |
|
|
|
countryCode?: string; |
|
|
|
}>({}); |
|
|
|
|
|
|
|
const countryCodeHandler = (e: React.ChangeEvent<HTMLInputElement>) => { |
|
|
|
if (e.target.value.length <= 3) { |
|
|
@ -35,7 +42,10 @@ const PageSignUp: FC<PageSignUpProps> = () => { |
|
|
|
|
|
|
|
const validatePhoneNumber = () => { |
|
|
|
try { |
|
|
|
const number = phoneUtil.parseAndKeepRawInput("+" + countryCode + phoneNumber, countryCode); |
|
|
|
const number = phoneUtil.parseAndKeepRawInput( |
|
|
|
"+" + countryCode + phoneNumber, |
|
|
|
countryCode |
|
|
|
); |
|
|
|
if (!phoneUtil.isValidNumber(number)) { |
|
|
|
return "Invalid phone number."; |
|
|
|
} |
|
|
@ -46,12 +56,17 @@ const PageSignUp: FC<PageSignUpProps> = () => { |
|
|
|
}; |
|
|
|
|
|
|
|
const validateForm = () => { |
|
|
|
const newErrors: { phoneNumber?: string; password?: string; confirmPassword?: string } = {}; |
|
|
|
const newErrors: { |
|
|
|
phoneNumber?: string; |
|
|
|
password?: string; |
|
|
|
confirmPassword?: string; |
|
|
|
} = {}; |
|
|
|
|
|
|
|
const phoneError = validatePhoneNumber(); |
|
|
|
if (phoneError) newErrors.phoneNumber = phoneError; |
|
|
|
if (!password) newErrors.password = "Password is required."; |
|
|
|
if (password !== confirmPassword) newErrors.confirmPassword = "Passwords do not match."; |
|
|
|
if (password !== confirmPassword) |
|
|
|
newErrors.confirmPassword = "Passwords do not match."; |
|
|
|
|
|
|
|
setErrors(newErrors); |
|
|
|
return Object.keys(newErrors).length === 0; // Return true if no errors
|
|
|
@ -73,7 +88,7 @@ const PageSignUp: FC<PageSignUpProps> = () => { |
|
|
|
}, [errors]); |
|
|
|
|
|
|
|
const submitHandler = async () => { |
|
|
|
setLoading(true) |
|
|
|
setLoading(true); |
|
|
|
setErrors({}); // Clear previous errors
|
|
|
|
|
|
|
|
if (!validateForm()) { |
|
|
@ -108,10 +123,9 @@ const PageSignUp: FC<PageSignUpProps> = () => { |
|
|
|
progress: undefined, |
|
|
|
theme: "light", |
|
|
|
}); |
|
|
|
}finally{ |
|
|
|
setLoading(false) |
|
|
|
} finally { |
|
|
|
setLoading(false); |
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
return ( |
|
|
@ -121,13 +135,24 @@ const PageSignUp: FC<PageSignUpProps> = () => { |
|
|
|
Change Password |
|
|
|
</h2> |
|
|
|
<div className="max-w-md mx-auto space-y-6"> |
|
|
|
<form className="grid grid-cols-1 gap-6" onSubmit={(e) => e.preventDefault()}> |
|
|
|
<form |
|
|
|
className="grid grid-cols-1 gap-6" |
|
|
|
onSubmit={(e) => e.preventDefault()} |
|
|
|
> |
|
|
|
<label className="block"> |
|
|
|
<span className="text-neutral-800 dark:text-neutral-200"> |
|
|
|
Phone Number |
|
|
|
</span> |
|
|
|
<div className={`flex items-center mt-1 rounded-2xl ${errors.countryCode || errors.phoneNumber ? "border border-red-600" : "border border-neutral-200"} bg-white dark:border-neutral-700 dark:bg-neutral-900 focus-within:border-primary-300 focus-within:ring focus-within:ring-primary-200 focus-within:ring-opacity-50`}> |
|
|
|
<span className="px-2 mr-[-15px] text-neutral-800 dark:text-neutral-200">+</span> |
|
|
|
<div |
|
|
|
className={`flex items-center mt-1 rounded-2xl ${ |
|
|
|
errors.countryCode || errors.phoneNumber |
|
|
|
? "border border-red-600" |
|
|
|
: "border border-neutral-200" |
|
|
|
} bg-white dark:border-neutral-700 dark:bg-neutral-900 focus-within:border-primary-300 focus-within:ring focus-within:ring-primary-200 focus-within:ring-opacity-50`}
|
|
|
|
> |
|
|
|
<span className="px-2 mr-[-15px] text-neutral-800 dark:text-neutral-200"> |
|
|
|
+ |
|
|
|
</span> |
|
|
|
<input |
|
|
|
value={countryCode} |
|
|
|
onChange={countryCodeHandler} |
|
|
@ -145,25 +170,59 @@ const PageSignUp: FC<PageSignUpProps> = () => { |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</label> |
|
|
|
<label className="block"> |
|
|
|
<span className="flex justify-between items-center text-neutral-800 dark:text-neutral-200">Password</span> |
|
|
|
<label className="block relative"> |
|
|
|
<span className="flex justify-between items-center text-neutral-800 dark:text-neutral-200"> |
|
|
|
Password |
|
|
|
</span> |
|
|
|
<Input |
|
|
|
value={password} |
|
|
|
onChange={(e) => setPassword(e.target.value)} |
|
|
|
type="password" |
|
|
|
type={`${showPassword ? "text" : "password"}`} |
|
|
|
className={`mt-1 ${errors.password ? "border-red-600" : ""}`} |
|
|
|
/> |
|
|
|
{showPassword ? ( |
|
|
|
<BiShow |
|
|
|
size={20} |
|
|
|
className="box-content rounded-full hover:bg-slate-100 p-[5px] absolute top-9 right-4" |
|
|
|
onClick={(e) => setShowPassword((prev) => !prev)} |
|
|
|
/> |
|
|
|
) : ( |
|
|
|
<BiHide |
|
|
|
size={20} |
|
|
|
className="box-content rounded-full hover:bg-slate-100 p-[5px] absolute top-9 right-4" |
|
|
|
onClick={(e) => setShowPassword((prev) => !prev)} |
|
|
|
/> |
|
|
|
)} |
|
|
|
</label> |
|
|
|
<label className="block"> |
|
|
|
<span className="flex justify-between items-center text-neutral-800 dark:text-neutral-200">Confirm Password</span> |
|
|
|
<label className="block relative"> |
|
|
|
<span className="flex justify-between items-center text-neutral-800 dark:text-neutral-200"> |
|
|
|
Confirm Password |
|
|
|
</span> |
|
|
|
<Input |
|
|
|
value={confirmPassword} |
|
|
|
onChange={(e) => setConfirmPassword(e.target.value)} |
|
|
|
type="password" |
|
|
|
className={`mt-1 ${errors.confirmPassword ? "border-red-600" : ""}`} |
|
|
|
type={`${showConfirm ? "text" : "password"}`} |
|
|
|
className={`mt-1 ${ |
|
|
|
errors.confirmPassword ? "border-red-600" : "" |
|
|
|
}`}
|
|
|
|
/> |
|
|
|
{showConfirm ? ( |
|
|
|
<BiShow |
|
|
|
size={20} |
|
|
|
className="box-content rounded-full hover:bg-slate-100 p-[5px] absolute top-9 right-4" |
|
|
|
onClick={(e) => setShowConfirm((prev) => !prev)} |
|
|
|
/> |
|
|
|
) : ( |
|
|
|
<BiHide |
|
|
|
size={20} |
|
|
|
className="box-content rounded-full hover:bg-slate-100 p-[5px] absolute top-9 right-4" |
|
|
|
onClick={(e) => setShowConfirm((prev) => !prev)} |
|
|
|
/> |
|
|
|
)} |
|
|
|
</label> |
|
|
|
<ButtonPrimary loading={loading} onClick={submitHandler}>Continue</ButtonPrimary> |
|
|
|
<ButtonPrimary loading={loading} onClick={submitHandler}> |
|
|
|
Continue |
|
|
|
</ButtonPrimary> |
|
|
|
</form> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|