Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: handle UI auth error #202

Merged
merged 10 commits into from
Jan 16, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import { TextInput } from '@/common/components/TextInput'
import { FormTextInput } from '@/common/components/FormTextInput'
import { Button } from '@/common/components/Button'
import Success from '@/common/assets/Success.svg'
import EmailIcon from '../assets/EmailIcon.svg'
Expand Down Expand Up @@ -46,7 +46,7 @@ export function InviteForm() {
want to invite.
</TextSm>
</div>
<TextInput
<FormTextInput
type="email"
name="emailAddress"
label="Email"
Expand Down
54 changes: 40 additions & 14 deletions packages/frontend/src/app/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import { useRouter } from 'next/navigation'
import { useForm } from 'react-hook-form'
import { getUser, logIn } from '@/api'
import { TextInput } from '@/common/components/TextInput'
import { FormTextInput } from '@/common/components/FormTextInput'
import { Button } from '@/common/components/Button'
import { PageContainer } from '@/common/components/PageContainer'
import { Text2xlBold } from '@/common/components/Typography'
import { Text2xlBold, TextSm } from '@/common/components/Typography'
import React, { useEffect } from 'react'
import { Card, CardWrapper } from '@/common/components/Card'
import { NavigationBreadcrumbsPlaceholder } from '@/common/components/navigation/Breadcrumbs'
Expand All @@ -15,18 +15,30 @@ interface Inputs {
password: string
}

type AuthError = { server: string }

export default function LoginPage() {
const router = useRouter()
const { register, handleSubmit, formState } = useForm<Inputs>()
const {
register,
handleSubmit,
formState: { errors, isSubmitting },
setError,
clearErrors,
} = useForm<Inputs & AuthError>()

function onSubmit(data: Inputs) {
console.log('formState.errors', formState.errors)
console.log('data', data)
logIn(data)
.then(() => {
router.push('/')
async function onSubmit(inputs: Inputs) {
try {
console.log('inputs', inputs)
await logIn(inputs)
router.push('/')
} catch (error) {
console.error(error)
setError('server', {
type: 'manual',
message: 'Authorization failed.',
})
.catch(console.error)
}
}

useEffect(() => {
Expand All @@ -43,25 +55,39 @@ export default function LoginPage() {
<CardWrapper>
<Card>
<div className="flex flex-col items-center gap-y-8">
<Text2xlBold>Admin Login</Text2xlBold>
<div className="flex flex-col items-center gap-y-2">
<Text2xlBold>Admin Login</Text2xlBold>
{errors.server && (
<TextSm className="text-error">
Your email or your password is incorrect. Please, try again.
</TextSm>
)}
</div>
<div className="flex flex-col w-full gap-y-4">
<TextInput
<FormTextInput
type="email"
name="email"
label="E-mail address"
placeholder="Enter e-mail address"
register={register}
onChange={clearErrors}
/>
<TextInput
<FormTextInput
type="password"
name="password"
label="Password"
placeholder="Enter password"
register={register}
onChange={clearErrors}
/>
</div>
<div className="card-actions justify-center w-full">
<Button onClick={handleSubmit(onSubmit)} title="Log in" />
<Button
onClick={handleSubmit(onSubmit)}
title="Log in"
loading={isSubmitting}
disabled={!!errors.server}
/>
</div>
</div>
</Card>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import { FieldError, Invitation } from '@ssi-trust-registry/common'
import { backendUrl, betterFetch } from '@/api'
import { TextInput } from '@/common/components/TextInput'
import { FormTextInput } from '@/common/components/FormTextInput'
import { TextArea } from '@/common/components/TextArea'
import { Checkbox } from '@/common/components/Checkbox'
import Success from '@/common/assets/Success.svg'
Expand Down Expand Up @@ -95,7 +95,7 @@ export function SubmissionForm({ invitation }: { invitation: Invitation }) {
</TextSm>
</div>
<div className="flex flex-col gap-4">
<TextInput
<FormTextInput
type="text"
name="name"
label="Entity Name"
Expand All @@ -110,7 +110,7 @@ export function SubmissionForm({ invitation }: { invitation: Invitation }) {
name="dids"
errors={errors.dids}
/>
<TextInput
<FormTextInput
type="text"
name="domain"
label="Domain"
Expand Down Expand Up @@ -142,7 +142,7 @@ export function SubmissionForm({ invitation }: { invitation: Invitation }) {
name="credentials"
errors={errors.credentials}
/>
<TextInput
<FormTextInput
type="text"
name="logo_url"
label="Logo URL (SVG Format)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@ interface TextInputProps<T extends FieldValues> {
register: UseFormRegister<T>
icon?: ReactComponentElement<any>
error?: FieldError
onChange?: () => void
}

export function TextInput<T extends FieldValues>({
export function FormTextInput<T extends FieldValues>({
type,
name,
label,
placeholder,
register,
icon,
error,
onChange,
}: TextInputProps<T>) {
return (
<div
Expand All @@ -44,7 +46,9 @@ export function TextInput<T extends FieldValues>({
className={`input w-full text-sm bg-lightHover text-gray-600 leading-6 placeholder:font-normal focus-within:placeholder:font-normal font-bold ${
error?.message && '!input-error !bg-error !bg-opacity-20'
} ${icon && 'pl-12'}`}
{...register(name)}
{...register(name, {
onChange: () => onChange && onChange(),
andrii-uhryn-absa marked this conversation as resolved.
Show resolved Hide resolved
})}
/>
</div>
<div className="ml-4">
Expand Down
Loading