mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-26 19:12:50 +00:00
changed the otp verification page style
This commit is contained in:
@@ -1,15 +1,17 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import {
|
||||
Anchor,
|
||||
Button,
|
||||
Center,
|
||||
Group,
|
||||
PinInput,
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
ThemeIcon,
|
||||
Title,
|
||||
} from '@mantine/core';
|
||||
import { IconArrowRight, IconShieldLock } from '@tabler/icons-react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { z } from 'zod';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
@@ -17,8 +19,13 @@ import { useApiMutation } from '@ema-platform/api';
|
||||
import { notify } from '@ema-platform/ui';
|
||||
import { AuthShell } from '../components/AuthShell';
|
||||
|
||||
const CODE_LENGTH = 6;
|
||||
const RESEND_SECONDS = 30;
|
||||
|
||||
const schema = z.object({
|
||||
verificationCode: z.string().min(1, { message: 'Verification code is required' }),
|
||||
verificationCode: z
|
||||
.string()
|
||||
.length(CODE_LENGTH, { message: `Enter the ${CODE_LENGTH}-digit code` }),
|
||||
});
|
||||
|
||||
type FormValues = z.infer<typeof schema>;
|
||||
@@ -34,15 +41,23 @@ export function OTPVerificationPage() {
|
||||
|
||||
const [verifyTrigger, { isLoading: loading }] = useApiMutation();
|
||||
const [resendTrigger, { isLoading: resending }] = useApiMutation();
|
||||
const [secondsLeft, setSecondsLeft] = useState(RESEND_SECONDS);
|
||||
|
||||
const {
|
||||
register,
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm<FormValues>({
|
||||
resolver: zodResolver(schema),
|
||||
defaultValues: { verificationCode: '' },
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (secondsLeft <= 0) return;
|
||||
const id = setInterval(() => setSecondsLeft((s) => s - 1), 1000);
|
||||
return () => clearInterval(id);
|
||||
}, [secondsLeft]);
|
||||
|
||||
const onSubmit = async (values: FormValues) => {
|
||||
try {
|
||||
await verifyTrigger({
|
||||
@@ -60,6 +75,7 @@ export function OTPVerificationPage() {
|
||||
};
|
||||
|
||||
const handleResendOtp = async () => {
|
||||
if (secondsLeft > 0 || resending) return;
|
||||
try {
|
||||
await resendTrigger({
|
||||
url: '/auth/resend-otp',
|
||||
@@ -68,6 +84,7 @@ export function OTPVerificationPage() {
|
||||
}).unwrap();
|
||||
|
||||
notify.success('Verification code resent to your email');
|
||||
setSecondsLeft(RESEND_SECONDS);
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : 'Something went wrong';
|
||||
notify.error(msg);
|
||||
@@ -99,12 +116,30 @@ export function OTPVerificationPage() {
|
||||
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<Stack gap="md">
|
||||
<TextInput
|
||||
label="Verification code"
|
||||
placeholder="Enter the 6-digit code"
|
||||
size="md"
|
||||
error={errors.verificationCode?.message}
|
||||
{...register('verificationCode')}
|
||||
<Controller
|
||||
control={control}
|
||||
name="verificationCode"
|
||||
render={({ field }) => (
|
||||
<Stack gap={6} align="center">
|
||||
<PinInput
|
||||
length={CODE_LENGTH}
|
||||
type="number"
|
||||
inputMode="numeric"
|
||||
oneTimeCode
|
||||
size="md"
|
||||
gap="sm"
|
||||
error={!!errors.verificationCode}
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
onComplete={() => handleSubmit(onSubmit)()}
|
||||
/>
|
||||
{errors.verificationCode?.message && (
|
||||
<Text c="red" size="sm">
|
||||
{errors.verificationCode.message}
|
||||
</Text>
|
||||
)}
|
||||
</Stack>
|
||||
)}
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
@@ -118,19 +153,29 @@ export function OTPVerificationPage() {
|
||||
</Stack>
|
||||
</form>
|
||||
|
||||
<Group justify="center" gap={6}>
|
||||
<Text size="sm" c="dimmed">
|
||||
Didn't receive a code?
|
||||
</Text>
|
||||
<Anchor
|
||||
size="sm"
|
||||
fw={600}
|
||||
onClick={handleResendOtp}
|
||||
style={resending ? { pointerEvents: 'none', opacity: 0.6 } : undefined}
|
||||
>
|
||||
Resend code
|
||||
</Anchor>
|
||||
</Group>
|
||||
<Center>
|
||||
<Group justify="center" gap={6}>
|
||||
<Text size="sm" c="dimmed">
|
||||
Didn't receive a code?
|
||||
</Text>
|
||||
{secondsLeft > 0 ? (
|
||||
<Text size="sm" c="dimmed" fw={600}>
|
||||
Resend in {secondsLeft}s
|
||||
</Text>
|
||||
) : (
|
||||
<Anchor
|
||||
size="sm"
|
||||
fw={600}
|
||||
onClick={handleResendOtp}
|
||||
style={
|
||||
resending ? { pointerEvents: 'none', opacity: 0.6 } : undefined
|
||||
}
|
||||
>
|
||||
Resend code
|
||||
</Anchor>
|
||||
)}
|
||||
</Group>
|
||||
</Center>
|
||||
</Stack>
|
||||
</AuthShell>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user