diff --git a/src/app/actions/auth.ts b/src/app/actions/auth.ts index 0b926fa..823d3ac 100644 --- a/src/app/actions/auth.ts +++ b/src/app/actions/auth.ts @@ -142,6 +142,7 @@ export type FormState = { inn?: string | undefined; } | undefined, mailConfirm?: boolean, + userId?: number, error: Record | null }; @@ -256,7 +257,7 @@ export async function registration( if (response.ok) { let parsed = await response.json() as { message_desc: string, - message_body: { token: string }, + message_body: { token: string, userId: number }, message_code: number }; @@ -271,7 +272,24 @@ export async function registration( ...(referralCode !== '' && { referralLink: referralCode }), ...(accountType === 'b2b' && { companyName: companyName, inn: inn }) }); - await createSession(parsed.message_body.token, email as string); + /* await createSession(parsed.message_body.token, email as string); */ + + return { + previousState: { + fullName, + email, + password, + confirm_password, + phone, + agree, + ...(referralCode !== '' && { referralLink: referralCode }), + ...(accountType === 'b2b' && { companyName: companyName, inn: inn }) + }, + mailConfirm: true, + userId: parsed.message_body.userId, + error: null + }; + } else { console.log(parsed); throw parsed; @@ -280,19 +298,6 @@ export async function registration( throw (`${response.status}`); } - /* return { - previousState: { - fullName, - email, - password, - confirm_password, - phone, - companyName, - agree - }, - mailConfirm: true, - error: null - }; */ } catch (error: unknown) { const errors: Record = {}; if (error) { @@ -341,6 +346,7 @@ export async function registration( agree, inn }, + mailConfirm: false, error: errors }; } @@ -397,34 +403,28 @@ export async function tokenLifeExtension() { } export async function confirmEmail( - state: any | undefined, - formData: any, + state: { error: string } | undefined, + formData: FormData ) { console.log('confirmEmail'); const emailConfirm = formData.get('emailConfirm') as string || ''; console.log(emailConfirm); -} - -export async function resetPassword( - state: any | undefined, - formData: FormData, -) { - const email = formData.get('email'); - console.log('resetPassword'); + const userId = formData.get('userId') as string || ''; try { const response = await fetch(`${API_BASE_URL}/api/v1/data`, { method: 'POST', headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json', + "Content-Type": "application/json", + "Accept": "application/json", }, body: JSON.stringify({ version: 1, - msg_id: 20010, + msg_id: 20009, message_body: { - email: email, - action: "resetPassword" + resend: 0, + user_id: userId, + verify_token: emailConfirm } }), }); @@ -432,122 +432,54 @@ export async function resetPassword( if (response.ok) { const parsed = await response.json(); console.log(parsed); - if (parsed.message_code === 0) { - } else { - throw 'error'; + if (parsed.message_code === 0) { + await createSession(parsed.message_body.token, parsed.message_body.email as string); } } } catch (error) { return { - error: error - }; + error: 'error' + } } - console.log('redirect') - redirect(`/reset-password?email=${email}`); + + redirect('/pages/dashboard'); } -export type FormStateConfirmPassword = { - previousState: { - email: string; - password: string; - confirm_password: string; - verifyToken: string; - }, - error: Record | null -}; +export async function resendConfirmEmail(userId: number) { + console.log('resendConfirmEmail'); -export async function confirmPassword( - state: FormStateConfirmPassword | undefined, - formData: any, -): Promise { - const email = formData.get('email'); - const password = formData.get('password'); - const confirm_password = formData.get('confirm_password'); - const verifyToken = formData.get('verify-token'); - console.log('confirmPassword'); - - const SignupFormSchema = await getSignupFormSchema('resetPassword'); - - const dataToValidate = { - password, - confirm_password - }; - - const validatedFields = SignupFormSchema.safeParse(dataToValidate); - - if (!validatedFields.success) { - 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, - password, - confirm_password, - verifyToken - }, - error: errors - }; - } try { const response = await fetch(`${API_BASE_URL}/api/v1/data`, { method: 'POST', headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json', + "Content-Type": "application/json", + "Accept": "application/json", }, body: JSON.stringify({ version: 1, - msg_id: 20010, + msg_id: 20009, message_body: { - email: email, - password: password, - verifyToken: verifyToken, - action: "confirmVerification" + resend: 1, + user_id: userId, } }), }); if (response.ok) { - const parsed = await response.json(); console.log(parsed); + if (parsed.message_code === 0) { - await createSession(parsed.message_body.authToken, email as string); - } else { - throw parsed.message_body; + return { + fine: true + } } - } else { - throw (`${response.status}`); } - } catch (error: unknown) { - const typedError = error as any; - const errors: Record = {}; - - if (error) { - return { - previousState: { - email, - password, - confirm_password, - verifyToken - }, - error: errors - }; + } catch (error) { + return { + fine: false } - throw error; } - - redirect('/pages/dashboard'); } \ No newline at end of file diff --git a/src/app/styles/module/login.module.scss b/src/app/styles/module/login.module.scss index 5b70ea0..aa108e6 100644 --- a/src/app/styles/module/login.module.scss +++ b/src/app/styles/module/login.module.scss @@ -172,13 +172,22 @@ margin-bottom: 18px; margin: 20px 0 0 0; - &:disabled { - opacity: 0.5; - } - &:hover:not(:disabled) { transform: translateY(-2px); } + + &:disabled { + opacity: 0.5; + background: linear-gradient(135deg, #414291, #4b3975); + + &:hover { + transform: none; + } + } + + &.refresh { + width: fit-content; + } } .form-group-confrim-window { diff --git a/src/app/ui/forms/confirm-mail-modal-window.tsx b/src/app/ui/forms/confirm-mail-modal-window.tsx new file mode 100644 index 0000000..f2a300e --- /dev/null +++ b/src/app/ui/forms/confirm-mail-modal-window.tsx @@ -0,0 +1,127 @@ +import styles from '@/app/styles/module/login.module.scss'; +import { useTranslations } from 'next-intl'; +import { ChangeEvent, MouseEvent, useActionState, useState, useEffect } from 'react'; +import { resendConfirmEmail, confirmEmail } from '@/app/actions/auth'; +import { IconRefresh } from '@/app/ui/icons/icons'; +export default function ConfirmMailModalWindow({ userId, email }: { userId: number | undefined, email: string | undefined }) { + const [stateEmailConfrim, formActionEmailConfrim, isPendingEmailConfrim] = useActionState( + confirmEmail, + undefined, + ); + const [confirmCodeValue, setConfirmCodeValue] = useState(''); + const [isInputDisabled, setIsInputDisabled] = useState(true); + const [timer, setTimer] = useState(30); + const t = useTranslations('Login-register-form'); + + async function reSendEmailConfirmCode(e: MouseEvent) { + e.preventDefault(); + if (userId) { + await resendConfirmEmail(userId); + } + } + + function onChangeHandler(e: ChangeEvent) { + const newValue = e.target.value.replace(/([^0-9])/g, ''); + if (newValue.length <= 6) { + setConfirmCodeValue(newValue); + } + } + + useEffect(() => { + let interval: NodeJS.Timeout; + + if (timer > 0 && isInputDisabled) { + interval = setInterval(() => { + setTimer(prev => { + if (prev <= 1) { + setIsInputDisabled(false); + return 0; + } + return prev - 1; + }); + }, 1000); + } + + return () => { + if (interval) clearInterval(interval); + }; + }, [timer, isInputDisabled]); + + /* const resetTimer = () => { + setIsInputDisabled(true); + setTimer(30); + }; */ + + return ( +
e.stopPropagation()} + > +
+
{ + formActionEmailConfrim(e); + }}> +
+

+ {t('enter-confirmation-code')} +
+

+

+ {email} +

+ ) => { + onChangeHandler(e) + }} + /> + + {stateEmailConfrim?.error && ( +

+ {t('entered-code-is-incorrect')} +

+ )} +
+
+ {stateEmailConfrim?.error} +
+
+ + +
+
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/ui/forms/register-form.tsx b/src/app/ui/forms/register-form.tsx index 7f96827..6c65b6b 100644 --- a/src/app/ui/forms/register-form.tsx +++ b/src/app/ui/forms/register-form.tsx @@ -1,8 +1,10 @@ 'use client' import styles from '@/app/styles/module/login.module.scss'; -import { ChangeEvent, useActionState, useEffect, useMemo, useRef, useState } from 'react'; -import { registration, FormState, confirmEmail } from '@/app/actions/auth'; +import { ChangeEvent, useActionState, useEffect, useRef, useState } from 'react'; +import { registration, FormState } from '@/app/actions/auth'; + + import PhoneInput from '@/app/ui/inputs/phone-input'; import Link from 'next/link'; import { useTranslations } from 'next-intl'; @@ -10,9 +12,11 @@ import { IconEye } from '@/app/ui/icons/icons'; import { getSignupFormSchema } from '@/app/actions/definitions'; import { useSearchParams } from 'next/navigation'; import * as z from 'zod' +import ConfirmMailModalWindow from '@/app/ui/forms/confirm-mail-modal-window'; import { fetchINN } from '@/app/actions/action'; import { useDebouncedCallback } from 'use-debounce'; + export default function RegisterForm() { const searchParams = useSearchParams(); const referralCode = searchParams.get('ref'); @@ -22,11 +26,6 @@ export default function RegisterForm() { undefined, ); - const [stateEmailConfrim, formActionEmailConfrim, isPendingEmailConfrim] = useActionState( - confirmEmail, - undefined, - ); - const t = useTranslations('Login-register-form'); const [showPassword, setShowPassword] = useState(false); const [showConfirmPassword, setShowConfirmPassword] = useState(false); @@ -245,6 +244,13 @@ export default function RegisterForm() { return ( <> + {showMailConfirmWindow && (
-
e.stopPropagation()} - > -
-
{ - formActionEmailConfrim(e); - }}> -
-

- {t('enter-confirmation-code')} -

- - { - }} - /> -
- -
-
-
+
)}
{ diff --git a/src/app/ui/icons/icons.tsx b/src/app/ui/icons/icons.tsx index 3f2960c..9ec5852 100644 --- a/src/app/ui/icons/icons.tsx +++ b/src/app/ui/icons/icons.tsx @@ -162,6 +162,13 @@ export function IconBurgerMenu() { ) } + +export function IconRefresh() { + return ( + + ) +} + export function IconSearch() { return ( diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 442fadb..2ecd534 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -296,7 +296,10 @@ "register-error-phone-not-allowed-symbols": "Phone contains invalid characters.", "register-error-password-not-allowed-symbols": "Password contains invalid characters. Can be used @.!#$%&'*+/=?^_{|}~-", "confirmation-code": "Confirmation code", - "enter-confirmation-code": "Enter the confirmation code", + "enter-confirmation-code": "Enter the confirmation code sent to your email:", + "confirm": "Confirm", + "entered-code-is-incorrect": "The code you entered is incorrect.", + "resend-code": "Resend code", "personal": "Personal", "unknown-error": "Unknown error", "change-password": "Change Password", diff --git a/src/i18n/messages/ru.json b/src/i18n/messages/ru.json index 06689e0..dc4e879 100644 --- a/src/i18n/messages/ru.json +++ b/src/i18n/messages/ru.json @@ -296,7 +296,10 @@ "register-error-phone-not-allowed-symbols": "Телефон содержит недопустимые символы.", "register-error-password-not-allowed-symbols": "Пароль содержит недопустимые символы. Можно использовать @.!#$%&'*+/=?^_{|}~-", "confirmation-code": "Код подтверждения", - "enter-confirmation-code": "Введите код подтверждения", + "enter-confirmation-code": "Введите код подтверждения высланный на почту:", + "confirm": "Подтвердить", + "entered-code-is-incorrect": "Введенный код не верен.", + "resend-code": "Выслать код заново", "personal": "Личный", "unknown-error": "Неизвестная ошибка", "change-password": "Изменить пароль",