revision: auth page components

This commit is contained in:
Mahyar Khanbolooki
2025-07-01 17:34:44 +03:30
parent b5ee3a6b26
commit f11d85cb0b
8 changed files with 27 additions and 20 deletions
+6 -6
View File
@@ -35,20 +35,20 @@ function AuthIndex({ }: Props) {
}, [isAuthenticated]) }, [isAuthenticated])
const onChange = (e: ChangeEvent<HTMLInputElement>) => { const onChange = (e: ChangeEvent<HTMLInputElement>) => {
if (e.target.id == AUTH_PAGE_ELEMENT.INPUT_PHONE) { if (e.target.name == AUTH_PAGE_ELEMENT.INPUT_PHONE) {
setNumber(() => e.target.value) setNumber(() => e.target.value)
} }
else if (e.target.id == AUTH_PAGE_ELEMENT.INPUT_PASSWORD) { else if (e.target.name == AUTH_PAGE_ELEMENT.INPUT_PASSWORD) {
setPassword(() => e.target.value) setPassword(() => e.target.value)
} }
else if (e.target.id == AUTH_PAGE_ELEMENT.INPUT_PASSWORD_REPEAT) { else if (e.target.name == AUTH_PAGE_ELEMENT.INPUT_PASSWORD_REPEAT) {
setPasswordRepeat(() => e.target.value) setPasswordRepeat(() => e.target.value)
} }
else if (e.target.id == AUTH_PAGE_ELEMENT.INPUT_REMEMBER_ME) { else if (e.target.name == AUTH_PAGE_ELEMENT.INPUT_REMEMBER_ME) {
setRememberMe((state) => !state) setRememberMe((state) => !state)
} }
else if (e.target.id.startsWith(AUTH_PAGE_ELEMENT.INPUT_OTP)) { else if (e.target.name.startsWith(AUTH_PAGE_ELEMENT.INPUT_OTP)) {
const index = +e.target.id.split('-')[2]; const index = +e.target.name.split('-')[2];
const prev = otp.padEnd(6).split(''); const prev = otp.padEnd(6).split('');
prev[index] = e.target.value; prev[index] = e.target.value;
const next = prev.join(''); const next = prev.join('');
+1 -1
View File
@@ -20,7 +20,7 @@ function InputField({ onChange, htmlFor, labelText, children, valid = true, clas
<input <input
onChange={onChange} onChange={onChange}
className='py-2.5 pt-3.5 text-base w-full outline-0 !leading-6' className='py-2.5 pt-3.5 text-base w-full outline-0 !leading-6'
id={htmlFor} name={htmlFor}
{...inputProps} /> {...inputProps} />
{children} {children}
</div> </div>
+5 -4
View File
@@ -12,7 +12,7 @@ type Props = {
} & Omit<React.InputHTMLAttributes<HTMLInputElement>, "id">; } & Omit<React.InputHTMLAttributes<HTMLInputElement>, "id">;
function OTPInputField({ onChange, maxLength = 6, htmlFor, labelText, className, value = '' }: Props) { function OTPInputField({ onChange, maxLength = 6, htmlFor, labelText, className, value = '', ...restProps }: Props) {
const values = value?.toString().split('').slice(0, maxLength); const values = value?.toString().split('').slice(0, maxLength);
const inputRefs = useRef(Array.from({ length: maxLength }, () => createRef<HTMLInputElement>())); const inputRefs = useRef(Array.from({ length: maxLength }, () => createRef<HTMLInputElement>()));
const [prevLength, setPrevLength] = useState(0); const [prevLength, setPrevLength] = useState(0);
@@ -54,15 +54,16 @@ function OTPInputField({ onChange, maxLength = 6, htmlFor, labelText, className,
htmlFor={htmlFor}> htmlFor={htmlFor}>
{labelText} {labelText}
</label> </label>
<div className='inline-flex justify-between items-center gap-2'> <div id={htmlFor} className='inline-flex justify-between items-center gap-2'>
{inputRefs?.current?.map((ref, i) => { {inputRefs?.current?.map((ref, i) => {
return ( return (
<input <input
{...restProps}
key={i} key={i}
onKeyDown={keyDown} onKeyDown={keyDown}
onChange={onChange} onChange={onChange}
id={`${htmlFor}-data-${i}`} name={`${htmlFor}-data-${i}`}
readOnly={Math.max(0, values?.length) != i && prevLength != i} readOnly={i != maxLength - 1 && Math.max(0, values?.length) != i && prevLength != i}
ref={ref} ref={ref}
value={values?.at(i) ?? ''} value={values?.at(i) ?? ''}
maxLength={1} maxLength={1}
+1 -1
View File
@@ -7,5 +7,5 @@ export enum AUTH_PAGE_ELEMENT {
INPUT_REMEMBER_ME = "rememberMe", INPUT_REMEMBER_ME = "rememberMe",
INPUT_PASSWORD_REPEAT = "passwordRepeat", INPUT_PASSWORD_REPEAT = "passwordRepeat",
INPUT_OTP = "opt", INPUT_OTP = "opt",
INPUT_PHONE = "phoneNumber" INPUT_PHONE = "phone"
} }
@@ -19,13 +19,15 @@ function StepEnterNumber({ onSubmit, onChange, value }: Props) {
<p className='mt-3 text-[13px]'>برای ورود شماره همراه خود را وارد نمایید.</p> <p className='mt-3 text-[13px]'>برای ورود شماره همراه خود را وارد نمایید.</p>
</div> </div>
<InputField <InputField
inputMode='tel'
autoComplete='tel'
className='mt-10' className='mt-10'
htmlFor={AUTH_PAGE_ELEMENT.INPUT_PHONE} htmlFor={AUTH_PAGE_ELEMENT.INPUT_PHONE}
labelText='شماره همراه' labelText='شماره همراه'
value={value} value={value}
placeholder='09120000000' placeholder='09120000000'
onChange={onChange} onChange={onChange}
type='number' /> type='tel' />
</div> </div>
<Button type='submit'>بعدی</Button> <Button type='submit'>بعدی</Button>
</form> </form>
@@ -16,7 +16,7 @@ type Props = {
function StepEnterOtp({ onSubmit, onChange, onClick, value, phoneNumber, timerRunning, secondsLeft }: Props) { function StepEnterOtp({ onSubmit, onChange, onClick, value, phoneNumber, timerRunning, secondsLeft }: Props) {
return ( return (
<form onSubmit={onSubmit} className='p-6 h-full flex flex-col justify-between'> <form autoComplete='off' onSubmit={onSubmit} className='p-6 h-full flex flex-col justify-between'>
<div className='block'> <div className='block'>
<img src='/assets/images/login-banner.png' /> <img src='/assets/images/login-banner.png' />
<div className='pt-4' dir='rtl'> <div className='pt-4' dir='rtl'>
@@ -25,16 +25,17 @@ function StepEnterOtp({ onSubmit, onChange, onClick, value, phoneNumber, timerRu
<p className='mt-3 text-[13px]'>کد ۶ رقمی ارسال شده به شماره {phoneNumber} را وارد نمایید.</p> <p className='mt-3 text-[13px]'>کد ۶ رقمی ارسال شده به شماره {phoneNumber} را وارد نمایید.</p>
</div> </div>
<OTPInputField <OTPInputField
autoComplete='one-time-code'
type='number'
inputMode='numeric'
className='mt-10' className='mt-10'
maxLength={6} maxLength={6}
htmlFor={AUTH_PAGE_ELEMENT.INPUT_OTP} htmlFor={AUTH_PAGE_ELEMENT.INPUT_OTP}
labelText='' labelText=''
value={value} value={value}
placeholder='' placeholder=''
onChange={onChange} onChange={onChange} />
type='text'>
</OTPInputField>
<div className='inline-flex justify-center items-center w-full pt-6 text-xs'> <div className='inline-flex justify-center items-center w-full pt-6 text-xs'>
<div dir='rtl'> <div dir='rtl'>
{timerRunning ? {timerRunning ?
@@ -23,6 +23,7 @@ function StepEnterPassword({ onSubmit, onChange, onClick, value, passwordVisible
<p className='mt-3 text-[13px]'>کلمه عبور خود را وارد نمایید.</p> <p className='mt-3 text-[13px]'>کلمه عبور خود را وارد نمایید.</p>
</div> </div>
<InputField <InputField
autoComplete='current-password'
className='mt-10' className='mt-10'
htmlFor={AUTH_PAGE_ELEMENT.INPUT_PASSWORD} htmlFor={AUTH_PAGE_ELEMENT.INPUT_PASSWORD}
labelText='کلمه عبور' labelText='کلمه عبور'
@@ -40,7 +41,7 @@ function StepEnterPassword({ onSubmit, onChange, onClick, value, passwordVisible
<div className='inline-flex justify-between items-center'> <div className='inline-flex justify-between items-center'>
{/* TODO: customize checkbox */} {/* TODO: customize checkbox */}
<label htmlFor={AUTH_PAGE_ELEMENT.INPUT_REMEMBER_ME} className='text-sm2 px-2 py-0.5'>مرا به خاطر بسپار</label> <label htmlFor={AUTH_PAGE_ELEMENT.INPUT_REMEMBER_ME} className='text-sm2 px-2 py-0.5'>مرا به خاطر بسپار</label>
<input id={AUTH_PAGE_ELEMENT.INPUT_REMEMBER_ME} className='h-4.5 w-4.5 checked:accent-primary' onChange={onChange} type='checkbox' checked={rememberMe} /> </div> <input name={AUTH_PAGE_ELEMENT.INPUT_REMEMBER_ME} className='h-4.5 w-4.5 checked:accent-primary' onChange={onChange} type='checkbox' checked={rememberMe} /></div>
</div> </div>
</div> </div>
<Button type='submit'>ورود به منو</Button> <Button type='submit'>ورود به منو</Button>
@@ -17,7 +17,7 @@ type Props = {
function StepNewPassword({ reset = false, onSubmit, onChange, onClick, value, repeatValue, passwordVisible, repeatPasswordVisible }: Props) { function StepNewPassword({ reset = false, onSubmit, onChange, onClick, value, repeatValue, passwordVisible, repeatPasswordVisible }: Props) {
return ( return (
<form onSubmit={onSubmit} className='p-6 h-full flex flex-col justify-between'> <form autoComplete='off' onSubmit={onSubmit} className='p-6 h-full flex flex-col justify-between'>
<div className='block'> <div className='block'>
<img src='/assets/images/login-banner.png' /> <img src='/assets/images/login-banner.png' />
<div className='pt-4' dir='rtl'> <div className='pt-4' dir='rtl'>
@@ -27,6 +27,7 @@ function StepNewPassword({ reset = false, onSubmit, onChange, onClick, value, re
<p className='mt-3 text-[13px]'>کلمه عبور جدید باید ترکیبی از حروف بزرگ و کوچک و نشانه ها باشد مثل A126bdz@</p> <p className='mt-3 text-[13px]'>کلمه عبور جدید باید ترکیبی از حروف بزرگ و کوچک و نشانه ها باشد مثل A126bdz@</p>
</div> </div>
<InputField <InputField
autoComplete='new-password'
className='mt-10' className='mt-10'
htmlFor={AUTH_PAGE_ELEMENT.INPUT_PASSWORD} htmlFor={AUTH_PAGE_ELEMENT.INPUT_PASSWORD}
labelText='کلمه عبور' labelText='کلمه عبور'
@@ -39,6 +40,7 @@ function StepNewPassword({ reset = false, onSubmit, onChange, onClick, value, re
</button> </button>
</InputField> </InputField>
<InputField <InputField
autoComplete='new-password'
valid={value === repeatValue} valid={value === repeatValue}
className='mt-6' className='mt-6'
htmlFor={AUTH_PAGE_ELEMENT.INPUT_PASSWORD_REPEAT} htmlFor={AUTH_PAGE_ELEMENT.INPUT_PASSWORD_REPEAT}