50 lines
1.7 KiB
TypeScript
50 lines
1.7 KiB
TypeScript
import { useState } from 'react';
|
|
import { Flex, PinInput, Title, Text, Stack, LoadingOverlay } from '@mantine/core';
|
|
import useConsumeCode from '../hooks/use-consume-code';
|
|
import { useSearch } from '@tanstack/react-router';
|
|
import { Trans, useLingui } from '@lingui/react/macro';
|
|
|
|
const CodePrompt = () => {
|
|
const { number } = useSearch({ from: '/login' });
|
|
const { t } = useLingui();
|
|
|
|
const [isWrong, setIsWrong] = useState(false);
|
|
const [code, setCode] = useState('');
|
|
|
|
const handleWrongCode = () => setIsWrong(true);
|
|
const { mutate: consumeCode, isPending } = useConsumeCode(handleWrongCode);
|
|
|
|
const handleChange = (value: string) => {
|
|
if (value.length === 0) return;
|
|
if (isWrong) setIsWrong(false);
|
|
|
|
setCode(value);
|
|
if (value.length === 6) {
|
|
consumeCode(value);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Flex direction="column" p={10} w='max-content' m='auto'>
|
|
<Title order={4}><Trans>Enter Verification Code</Trans></Title>
|
|
<Text size='xs'c="dimmed" mb={5}><Trans>A code was sent to +1 ({number?.slice(0, 3)}) {number?.slice(3, 6)}-{number?.slice(6)}</Trans></Text>
|
|
<Stack justify='center' p={10} gap={2} pos='relative'>
|
|
<PinInput aria-label={t`One time code`}
|
|
value={code}
|
|
error={isWrong}
|
|
onChange={handleChange}
|
|
autoFocus={true}
|
|
oneTimeCode
|
|
length={6}
|
|
disabled={isPending}
|
|
type='number'
|
|
/>
|
|
<LoadingOverlay visible={isPending} overlayProps={{ blur: 0.375, radius: 'md', backgroundOpacity: 0.35 }} />
|
|
{isWrong && <Text c='red' size='xs'><Trans>Incorrect code</Trans></Text>}
|
|
</Stack>
|
|
</Flex>
|
|
)
|
|
};
|
|
|
|
export default CodePrompt;
|