Initial commit
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
import { RefreshCw } from 'lucide-react'
|
||||
import type { UseFormReturn } from 'react-hook-form'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Field, FieldError, FieldLabel } from '@/components/ui/field'
|
||||
import {
|
||||
InputOTP,
|
||||
InputOTPGroup,
|
||||
InputOTPSeparator,
|
||||
InputOTPSlot,
|
||||
} from '@/components/ui/input-otp'
|
||||
import type { VerifyOtpValues } from '@/features/onboard/onboarding.types'
|
||||
|
||||
type OnboardingVerifyOtpStepProps = {
|
||||
form: UseFormReturn<VerifyOtpValues>
|
||||
email: string | null
|
||||
errorMessage: string | null
|
||||
infoMessage: string | null
|
||||
remainingAttempts: number
|
||||
resendCooldownSeconds: number
|
||||
isResending: boolean
|
||||
onSubmit: (values: VerifyOtpValues) => Promise<void>
|
||||
onResend: () => Promise<void>
|
||||
}
|
||||
|
||||
export function OnboardingVerifyOtpStep({
|
||||
form,
|
||||
email,
|
||||
errorMessage,
|
||||
infoMessage,
|
||||
remainingAttempts,
|
||||
resendCooldownSeconds,
|
||||
isResending,
|
||||
onSubmit,
|
||||
onResend,
|
||||
}: OnboardingVerifyOtpStepProps) {
|
||||
const resendDisabled = resendCooldownSeconds > 0 || isResending
|
||||
|
||||
return (
|
||||
<form className="space-y-4" onSubmit={form.handleSubmit(onSubmit)}>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Ingresa el codigo de 6 digitos que enviamos a{' '}
|
||||
<span className="font-medium text-foreground">{email ?? 'tu email'}</span>.
|
||||
</p>
|
||||
|
||||
<Field data-invalid={Boolean(form.formState.errors.otp)}>
|
||||
<div className="mb-2 flex items-center justify-between gap-3">
|
||||
<FieldLabel htmlFor="onboard-otp">Codigo de verificacion</FieldLabel>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
disabled={resendDisabled}
|
||||
onClick={() => {
|
||||
void onResend()
|
||||
}}
|
||||
>
|
||||
<RefreshCw className="mr-1 h-3.5 w-3.5" />
|
||||
{isResending
|
||||
? 'Reenviando...'
|
||||
: resendCooldownSeconds > 0
|
||||
? `Reenviar en ${resendCooldownSeconds}s`
|
||||
: 'Reenviar codigo'}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<InputOTP
|
||||
id="onboard-otp"
|
||||
maxLength={6}
|
||||
inputMode="numeric"
|
||||
pattern="\d*"
|
||||
value={form.watch('otp')}
|
||||
onChange={(value) => {
|
||||
form.setValue('otp', value, { shouldValidate: true })
|
||||
}}
|
||||
>
|
||||
<InputOTPGroup>
|
||||
<InputOTPSlot index={0} />
|
||||
<InputOTPSlot index={1} />
|
||||
<InputOTPSlot index={2} />
|
||||
</InputOTPGroup>
|
||||
<InputOTPSeparator />
|
||||
<InputOTPGroup>
|
||||
<InputOTPSlot index={3} />
|
||||
<InputOTPSlot index={4} />
|
||||
<InputOTPSlot index={5} />
|
||||
</InputOTPGroup>
|
||||
</InputOTP>
|
||||
|
||||
<FieldError errors={[form.formState.errors.otp]} />
|
||||
</Field>
|
||||
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Intentos restantes: <span className="font-medium">{remainingAttempts}</span>
|
||||
</p>
|
||||
|
||||
{errorMessage && <p className="text-sm text-destructive">{errorMessage}</p>}
|
||||
{infoMessage && <p className="text-sm text-muted-foreground">{infoMessage}</p>}
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
className="w-full"
|
||||
disabled={form.formState.isSubmitting || !form.formState.isValid}
|
||||
>
|
||||
{form.formState.isSubmitting ? 'Verificando...' : 'Verificar codigo'}
|
||||
</Button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user