diff --git a/src/app/[lang]/identification/adornment.tsx b/src/app/[lang]/identification/adornment.tsx
new file mode 100644
index 00000000..067e88cc
--- /dev/null
+++ b/src/app/[lang]/identification/adornment.tsx
@@ -0,0 +1,14 @@
+import { CircularProgress } from '@mui/material';
+import { useFormStatus } from 'react-dom';
+
+export function LoadingAdornment() {
+ const status = useFormStatus();
+
+ if (!status.pending) return null;
+
+ return (
+
+
+
+ );
+}
diff --git a/src/app/[lang]/identification/form.tsx b/src/app/[lang]/identification/form.tsx
index 5fd67751..a746ceaf 100644
--- a/src/app/[lang]/identification/form.tsx
+++ b/src/app/[lang]/identification/form.tsx
@@ -1,29 +1,22 @@
'use client';
-import ArrowCircleRightOutlinedIcon from '@mui/icons-material/ArrowCircleRightOutlined';
-import { CircularProgress, TextField, Tooltip } from '@mui/material';
import { zodResolver } from '@hookform/resolvers/zod';
+import { TextField, Tooltip } from '@mui/material';
import { useReCaptcha } from 'next-recaptcha-v3';
-import { useRouter } from 'next/navigation';
import { useForm } from 'react-hook-form';
-import * as Sentry from '@sentry/nextjs';
-import { useState } from 'react';
+import { useFormState } from 'react-dom';
import Link from 'next/link';
+import React from 'react';
import { z } from 'zod';
-import {
- findCitizen,
- findIamCitizen,
- setCookie,
- validateRecaptcha,
-} from '@/actions';
import { GridContainer, GridItem } from '@/components/elements/grid';
import { createCedulaSchema } from '@/common/validation-schemas';
import { TextBodyTiny } from '@/components/elements/typography';
import { CustomTextMask } from '@/components/CustomTextMask';
import { useSnackAlert } from '@/components/elements/alert';
-import { ButtonApp } from '@/components/elements/button';
-import { Validations } from '@/common/helpers';
+import { identifyAccount } from './identify.action';
+import { SubmitButton } from './submit.button';
+import { LoadingAdornment } from './adornment';
import theme from '@/components/themes/theme';
import { useLanguage } from '../provider';
import { LOGIN_URL } from '@/common';
@@ -32,127 +25,100 @@ type CedulaForm = z.infer>;
export function Form() {
const { AlertError, AlertWarning } = useSnackAlert();
- const [loading, setLoading] = useState(false);
- const { executeRecaptcha } = useReCaptcha();
- const router = useRouter();
-
+ const { executeRecaptcha, loaded } = useReCaptcha();
const { intl } = useLanguage();
- const {
- handleSubmit,
- formState: { errors },
- setValue,
- watch,
- } = useForm({
- reValidateMode: 'onSubmit',
- resolver: zodResolver(createCedulaSchema(intl)),
- });
-
- const cedulaFormValue = watch('cedula', '');
+ const { formState, setValue, register, trigger, clearErrors, setError } =
+ useForm({
+ reValidateMode: 'onChange',
+ resolver: zodResolver(createCedulaSchema(intl)),
+ });
- const onChange = (event: React.ChangeEvent) => {
- const valueWithoutHyphens = event.target.value.replace(/-/g, '');
- setValue('cedula', valueWithoutHyphens);
- };
-
- const onSubmit = handleSubmit(async (data) => {
- setLoading(true);
-
- const cedula = data.cedula.replace(/-/g, '');
- const isValidByLuhn = Validations.luhnCheck(cedula);
+ const [state, action] = useFormState(identifyAccount, {
+ message: '',
+ });
- if (!isValidByLuhn) {
- AlertError(intl.errors.cedula.invalid);
- setLoading(false);
+ const onChange = ({ target }: React.ChangeEvent) => {
+ const cedula = target.value.replace(/-/g, '');
+ setValue('cedula', cedula);
- return;
+ if (formState.errors.cedula) {
+ clearErrors('cedula');
}
- const reCaptchaToken = await executeRecaptcha('form_submit');
-
- if (!reCaptchaToken) {
- AlertWarning(intl.errors.recaptcha.issues);
- setLoading(false);
+ if (cedula.length === 11) {
+ trigger('cedula');
+ }
+ };
- return;
+ const [token, setToken] = React.useState('');
+ React.useEffect(() => {
+ if (loaded && !token) {
+ executeRecaptcha('form_submit')
+ .then(setToken)
+ .catch(() => '');
}
+ }, [token, loaded]);
- try {
- const { isHuman } = await validateRecaptcha(reCaptchaToken);
-
- if (!isHuman) {
- setLoading(false);
- return AlertError(intl.errors.recaptcha.validation);
- }
-
- const { exists } = await findIamCitizen(cedula);
-
- if (exists) {
- setLoading(false);
- return AlertError(intl.errors.cedula.exists);
- }
-
- const citizen = await findCitizen(cedula);
- await setCookie('citizen', citizen);
- router.push('liveness');
- setLoading(false);
- } catch (err: any) {
- Sentry.captureMessage(err.message || err, 'error');
- setLoading(false);
- return AlertError(intl.errors.cedula.invalid);
+ React.useEffect(() => {
+ if (state.message) {
+ AlertError(state.message);
}
- });
+ }, [state]);
return (
-