Skip to content

Commit

Permalink
fix: Improve UX for auth flow
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-dalmet committed Oct 10, 2023
1 parent bae4d43 commit 16736f9
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 41 deletions.
3 changes: 3 additions & 0 deletions src/components/FieldPinInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const FieldPinInput = <FormattedValue = string,>(
otherProps,
} = useField(props);
const {
isDisabled,
label,
helper,
size = 'lg',
Expand Down Expand Up @@ -77,6 +78,8 @@ export const FieldPinInput = <FormattedValue = string,>(
autoFocus={autoFocus}
onComplete={handleOnComplete}
placeholder="·"
isInvalid={showError}
isDisabled={isDisabled}
>
<PinInputField flex={1} />
<PinInputField flex={1} />
Expand Down
4 changes: 3 additions & 1 deletion src/features/auth/LoginForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export const LoginForm = ({
<Stack spacing={4}>
<FieldInput
name="email"
size="lg"
label={t('auth:data.email.label')}
required={t('auth:data.email.required')}
validations={[
Expand All @@ -67,7 +68,8 @@ export const LoginForm = ({
isDisabled={form.isSubmitted && !form.isValid}
type="submit"
variant="@primary"
ms="auto"
size="lg"
flex={1}
>
{t('auth:login.actions.login')}
</Button>
Expand Down
75 changes: 39 additions & 36 deletions src/features/auth/PageLoginValidate.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React from 'react';

import {
Box,
Expand All @@ -7,19 +7,16 @@ import {
CardBody,
CardHeader,
Flex,
HStack,
Heading,
Stack,
Text,
chakra,
} from '@chakra-ui/react';
import { Formiz, useForm } from '@formiz/core';
import {
useParams,
usePathname,
useRouter,
useSearchParams,
} from 'next/navigation';
import { useParams, useRouter, useSearchParams } from 'next/navigation';
import { useTranslation } from 'react-i18next';
import { LuArrowLeft, LuArrowRight } from 'react-icons/lu';

import { FieldPinInput } from '@/components/FieldPinInput';
import { Logo } from '@/components/Logo';
Expand All @@ -29,10 +26,12 @@ import {
getRetryDelayInSeconds,
} from '@/features/auth/utils';
import { DevCodeHint } from '@/features/dev/DevCodeHint';
import { useRtl } from '@/hooks/useRtl';
import { useSearchParamsUpdater } from '@/hooks/useSearchParamsUpdater';
import { trpc } from '@/lib/trpc/client';

export default function PageLoginValidate() {
const { rtlValue } = useRtl();
const { t } = useTranslation(['auth']);
const router = useRouter();
const params = useParams();
Expand Down Expand Up @@ -60,10 +59,6 @@ export default function PageLoginValidate() {
const retries = parseInt(searchParams.get('retries') ?? '0', 10);
const seconds = getRetryDelayInSeconds(retries);

form.setErrors({
code: `Code is invalid, please wait ${seconds} seconds before submitting`,
});

searchParamsUpdater(
{
retries: (retries + 1).toString(),
Expand All @@ -75,6 +70,10 @@ export default function PageLoginValidate() {
setTimeout(r, seconds * 1_000);
});

form.setErrors({
code: `Code is invalid`,
});

return;
}

Expand All @@ -93,50 +92,54 @@ export default function PageLoginValidate() {
<Logo h="3rem" mb="8" mx="auto" />
<Card>
<CardHeader pb={0}>
<Stack>
<Heading size="md" data-test="login-page-heading">
{t('auth:login.code.title')}
</Heading>
<Text>
We&apos;ve sent a 6-character code to{' '}
<chakra.strong>{email}</chakra.strong>. The code expires shortly
({VALIDATION_TOKEN_EXPIRATION_IN_MINUTES} minutes), so please
enter it soon.
</Text>
</Stack>
<Button
me="auto"
size="sm"
leftIcon={rtlValue(<LuArrowLeft />, <LuArrowRight />)}
onClick={() => router.back()}
>
Back
</Button>
</CardHeader>
<CardBody>
<Formiz connect={form} autoForm>
<Stack spacing="4">
<Stack>
<Heading size="md" data-test="login-page-heading">
{t('auth:login.code.title')}
</Heading>
<Text fontSize="sm">
We&apos;ve sent a 6-character code to{' '}
<chakra.strong>{email}</chakra.strong>. The code expires
shortly ({VALIDATION_TOKEN_EXPIRATION_IN_MINUTES} minutes),
so please enter it soon.
</Text>
</Stack>
<FieldPinInput
name="code"
label="Code"
label="Verification code"
helper="Can't find the code? Check your spams."
autoFocus
isDisabled={validate.isLoading}
onComplete={() => {
if (validate.isLoading) {
// We don't want to submit if the previous request is
// still loading.
return;
// Only auto submit on first try
if (!form.isSubmitted) {
form.submit();
}

form.submit();
}}
/>
<Flex>
<Button type="button" onClick={() => router.back()}>
Back
</Button>
<HStack spacing={8}>
<Button
size="lg"
isLoading={validate.isLoading}
isDisabled={form.isSubmitted && !form.isValid}
type="submit"
variant="@primary"
ms="auto"
flex={1}
>
{t('auth:login.actions.login')}
Confirm
</Button>
</Flex>
</HStack>

<DevCodeHint />
</Stack>
Expand Down
3 changes: 2 additions & 1 deletion src/features/auth/PageRegister.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ export default function PageRegister() {
isDisabled={form.isSubmitted && !form.isValid}
type="submit"
variant="@primary"
ms="auto"
flex={1}
size="lg"
>
{t('auth:register.actions.create')}
</Button>
Expand Down
4 changes: 2 additions & 2 deletions src/locales/en/auth.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"login": {
"title": "Log In",
"title": "Sign in",
"feedbacks": {
"loginError": {
"title": "Failed to log in"
}
},
"actions": {
"forgotPassword": "Forgot Password?",
"login": "Log In",
"login": "Sign in",
"needAccount": "Need an Account?",
"register": "Register Now!"
},
Expand Down
2 changes: 1 addition & 1 deletion src/locales/sw/auth.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"actions": {
"forgotPassword": "Umesahau nenosiri yako ?",
"login": "Ingia",
"login": "Weka sahihi",
"needAccount": "Je, unahitaji akaunti?",
"register": "Jiandikishe sasa!"
}
Expand Down

0 comments on commit 16736f9

Please sign in to comment.