diff --git a/src/app/actions/auth.ts b/src/app/actions/auth.ts index f9a3240..a72c6b3 100644 --- a/src/app/actions/auth.ts +++ b/src/app/actions/auth.ts @@ -1,6 +1,6 @@ 'use server' -import {SignupFormSchema, loginFormSchema, localDevelopmentUrl} from '@/app/lib/definitions'; +import { SignupFormSchema, loginFormSchema, localDevelopmentUrl } from '@/app/lib/definitions'; import { createSession, deleteSession, getSessionData } from '@/app/lib/session'; import { redirect } from 'next/navigation'; @@ -29,16 +29,41 @@ export async function logout() { } export async function authorization( - state: string | undefined, + state: { + previousState: { + email: string; + } + error: Record + } | undefined, formData: FormData, ) { + const email = formData.get('email') as string || ''; + const password = formData.get('password'); + const validatedFields = loginFormSchema.safeParse({ - email: formData.get('email'), - password: formData.get('password'), + email, + password }) if (!validatedFields.success) { - return 'error'; + const errors: Record = {} + JSON.parse(validatedFields.error.message).forEach((obj: { + message: string, + path: string + }) => { + if (errors[obj.path[0]]) { + errors[obj.path[0]] = `${errors[obj.path[0]]} ${obj.message}`; + } else { + errors[obj.path[0]] = obj.message; + } + }); + + return { + previousState: { + email + }, + error: errors + }; } try { @@ -58,12 +83,21 @@ export async function authorization( let parsed = await response.json(); await createSession(parsed.token, parsed.email); } else { - throw new Error('Something went wrong. from server'); + throw new Error(`Something went wrong. Status from server ${response.status}`); } } catch (error) { + const errors: Record = {} + errors['server'] = `${error}`; + if (error) { - return 'Something went wrong. from server'; + return { + previousState: { + email, + password + }, + error: errors + }; } throw error; } @@ -71,16 +105,35 @@ export async function authorization( redirect('/pages/dashboard'); } +type FormState = { + previousState: { + full_name: string; + email: string; + password: string; + confirm_password: string; + phone: string; + company: string; + } + error: Record +}; + export async function registration( - state: Record | undefined, + state: FormState | undefined, formData: FormData, -) { +): Promise { + const full_name = formData.get('full_name') as string || ''; + const email = formData.get('email') as string || ''; + const password = formData.get('password') as string || ''; + const confirm_password = formData.get('confirm_password') as string || ''; + const phone = formData.get('phone') as string || ''; + const company = formData.get('company') as string || ''; + const validatedFields = SignupFormSchema.safeParse({ - full_name: formData.get('full_name'), - email: formData.get('email'), - password: formData.get('password'), - confirm_password: formData.get('confirm_password'), - }) + full_name, + email, + password, + confirm_password, + }); if (!validatedFields.success) { const errors: Record = {} @@ -95,14 +148,24 @@ export async function registration( } }); - return errors; + return { + previousState: { + full_name, + email, + password, + confirm_password, + phone, + company + }, + error: errors + }; } try { const { full_name, email, password } = validatedFields.data; const response = await fetch(`${API_BASE_URL}/v1/api/auth/register`, { method: 'POST', - body: JSON.stringify({ fullName: full_name, email, password }), + body: JSON.stringify({ fullName: full_name, email, password, phone, company }), headers: { "Content-Type": "application/json", "Accept": "application/json" @@ -121,7 +184,18 @@ export async function registration( if (error) { const errors: Record = {} errors['server'] = `-error-2 -> ${error}` - return errors; + + return { + previousState: { + full_name, + email, + password, + confirm_password, + phone, + company + }, + error: errors + }; } throw error; } diff --git a/src/app/lib/definitions.ts b/src/app/lib/definitions.ts index be6d944..7a00ff4 100644 --- a/src/app/lib/definitions.ts +++ b/src/app/lib/definitions.ts @@ -20,20 +20,20 @@ export const SignupFormSchema = z .object({ full_name: z .string() - .min(3, { error: 'Name must be at least 3 characters long.' }) + .min(3, { error: 'Имя должно содержать не менее 3 символов.' }) .trim(), - email: z.email({ error: 'Please enter a valid email.' }).trim(), + email: z.email({ error: 'Пожалуйста, введите правильный адрес электронной почты.' }).trim(), password: z .string() - .min(8, { error: 'Be at least 8 characters long' }) - .regex(/[a-zA-Z]/, { error: 'Contain at least one letter.' }) - .regex(/[0-9]/, { error: 'Contain at least one number.' }) + .min(8, { error: 'Длина пароля должна быть не менее 8 символов.' }) + .regex(/[a-zA-Z]/, { error: 'Пароль должен содержать хотя бы одну букву.' }) + .regex(/[0-9]/, { error: 'Пароль должен содержать хотя бы одну цифру.' }) .trim(), confirm_password: z .string() }) .refine((data) => data.password === data.confirm_password, { - message: 'passwordMismatchErrorMessage', + message: 'Повторите пароль', path: ['confirm_password'], }); @@ -41,11 +41,11 @@ export const loginFormSchema = z .object({ email: z .string() - .min(1, { error: 'Email must be not empty' }) + .min(1, { error: 'Адрес электронной почты не должен быть пустым' }) .trim(), password: z .string() - .min(1, { error: 'Password must be not empty' }) + .min(1, { error: 'Пароль не должен быть пустым' }) .trim(), }) diff --git a/src/app/ui/login-form.tsx b/src/app/ui/login-form.tsx index 74e6191..4520894 100644 --- a/src/app/ui/login-form.tsx +++ b/src/app/ui/login-form.tsx @@ -5,7 +5,7 @@ import { useActionState } from 'react'; import { authorization } from '@/app/actions/auth'; export default function LoginForm() { - const [errorMessage, formAction, isPending] = useActionState( + const [state, formAction, isPending] = useActionState( authorization, undefined, ); @@ -14,14 +14,33 @@ export default function LoginForm() {
- + + {state?.error?.email && ( +

{state?.error?.email}

+ )}
- + + {state?.error?.password && ( +

{state?.error?.password}

+ )}
- {errorMessage && ( -

{errorMessage}

+ {state?.error.server && ( +

{state?.error.server}

)}
diff --git a/src/app/ui/register-form.tsx b/src/app/ui/register-form.tsx index 7d2a9d6..7a8d37e 100644 --- a/src/app/ui/register-form.tsx +++ b/src/app/ui/register-form.tsx @@ -1,19 +1,15 @@ 'use client' import styles from '@/app/styles/login.module.scss'; -import { useActionState, useEffect } from 'react'; +import { useActionState } from 'react'; import { registration } from '@/app/actions/auth'; export default function RegisterForm() { - const [errorMessage, formAction, isPending] = useActionState( + const [state, formAction, isPending] = useActionState( registration, undefined, ); - useEffect(() => { - console.log(errorMessage); - }, [errorMessage]) - return ( { formAction(e); @@ -24,22 +20,43 @@ export default function RegisterForm() { > Полное имя - - {errorMessage?.full_name && ( -

{errorMessage!.full_name}

+ + {state?.error?.full_name && ( +

{state?.error?.full_name}

)}
- - {errorMessage?.email && ( -

{errorMessage!.email}

+ + {state?.error?.email && ( +

{state?.error?.email}

)}
- +
@@ -48,21 +65,41 @@ export default function RegisterForm() { > Компания - +
- - {errorMessage?.password && ( -

{errorMessage!.password}

+ + {state?.error?.password && ( +

{state?.error?.password}

)}
- - {errorMessage?.confirm_password && ( -

{errorMessage!.confirm_password}

+ + {state?.error?.confirm_password && ( +

{state?.error?.confirm_password}

)}