137 lines
3.6 KiB
JavaScript
137 lines
3.6 KiB
JavaScript
import { useSearchParams, Link } from 'react-router'
|
|
import { useForm } from 'react-hook-form'
|
|
import { ErrorMessage } from '@hookform/error-message'
|
|
import { isValidCPF } from '@brazilian-utils/brazilian-utils'
|
|
import { yupResolver } from '@hookform/resolvers/yup'
|
|
import { Card } from '~/layouts/auth/layout'
|
|
import { Control, Label, Input, Button, Error } from '~/components/form'
|
|
import { Heading } from '~/components/heading'
|
|
import { useMutation } from '@tanstack/react-query'
|
|
import * as yup from 'yup'
|
|
import { encode, parse } from '../_base64state'
|
|
import axios from '~/axios'
|
|
import Password from './_password'
|
|
|
|
yup.addMethod(yup.string, 'username', function (message) {
|
|
return this.test(
|
|
'username',
|
|
message,
|
|
(x) => isValidCPF(x) || yup.string().email().isValid(x),
|
|
)
|
|
})
|
|
|
|
export const schema = yup.object({
|
|
username: yup
|
|
.string()
|
|
.trim()
|
|
.lowercase()
|
|
.username('Deve ser um Email ou CPF válido')
|
|
.transform((x) => (isValidCPF(x) ? x.replace(/\D/g, '') : x))
|
|
.required('Digite um Email ou CPF'),
|
|
})
|
|
|
|
export default function Component() {
|
|
const [searchParams] = useSearchParams()
|
|
const state = parse(searchParams.get('state'))
|
|
|
|
if (state?.['cognito:sub']) {
|
|
return <Password />
|
|
}
|
|
|
|
return <SignIn />
|
|
}
|
|
|
|
function SignIn() {
|
|
const [searchParams, setSearchParams] = useSearchParams()
|
|
const { handleSubmit, formState, setError, register } = useForm({
|
|
resolver: yupResolver(schema),
|
|
})
|
|
|
|
const { mutateAsync } = useMutation({
|
|
mutationFn: async ({ username }) => {
|
|
const { data } = await axios.get(`/search/lookup/${username}`)
|
|
return data
|
|
},
|
|
onSuccess: (data) => {
|
|
setSearchParams((searchParams) => {
|
|
searchParams.set('state', encode(data))
|
|
return searchParams
|
|
})
|
|
},
|
|
})
|
|
|
|
const formError = (message) => {
|
|
setError('username', {
|
|
type: 'manual',
|
|
message,
|
|
})
|
|
}
|
|
|
|
const onSubmit = async ({ username }) => {
|
|
try {
|
|
await mutateAsync({ username })
|
|
} catch ({ message }) {
|
|
switch (message) {
|
|
case 'User not found.':
|
|
return formError(
|
|
'Não encontramos sua conta. Por favor, verifique se seu Email ou CPF estão corretos.',
|
|
)
|
|
default:
|
|
return formError(message)
|
|
}
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Card>
|
|
<Heading>Digite o seu email ou cpf para continuar</Heading>
|
|
|
|
{/* Sign in */}
|
|
<form onSubmit={handleSubmit(onSubmit)} className="space-y-2.5">
|
|
<Control
|
|
className="space-y-0.5"
|
|
aria-invalid={'username' in formState.errors}
|
|
>
|
|
<Label aria-required={true}>Email ou CPF</Label>
|
|
<Input
|
|
className="w-full"
|
|
autoFocus={true}
|
|
{...register('username')}
|
|
/>
|
|
<ErrorMessage
|
|
errors={formState.errors}
|
|
name="username"
|
|
render={({ message }) => <Error>{message}</Error>}
|
|
/>
|
|
</Control>
|
|
|
|
<Button
|
|
type="submit"
|
|
className="w-full"
|
|
isLoading={formState.isSubmitting}
|
|
>
|
|
Continuar
|
|
</Button>
|
|
</form>
|
|
|
|
<div className="flex justify-center items-center gap-4">
|
|
<span className="flex-1 h-px bg-yellow-secondary dark:bg-gray-700" />
|
|
<span>ou</span>
|
|
<span className="flex-1 h-px bg-yellow-secondary dark:bg-gray-700" />
|
|
</div>
|
|
|
|
<Button
|
|
as={Link}
|
|
to={{
|
|
pathname: './passcode',
|
|
search: searchParams.toString(),
|
|
}}
|
|
relative="path"
|
|
className="flex justify-center items-center !bg-yellow-primary w-full"
|
|
>
|
|
Entrar com código de acesso
|
|
</Button>
|
|
</Card>
|
|
)
|
|
}
|