From 396d3888dbea356c767f53fc4f723fc7206ff41f Mon Sep 17 00:00:00 2001 From: smanylov Date: Fri, 23 Jan 2026 17:33:48 +0700 Subject: [PATCH 1/4] add confirm mail modal window --- src/app/actions/auth.ts | 111 ++++++++++++++++++++++++----- src/app/ui/forms/register-form.tsx | 46 ++++++++++-- 2 files changed, 135 insertions(+), 22 deletions(-) diff --git a/src/app/actions/auth.ts b/src/app/actions/auth.ts index bd6a870..8af2ee2 100644 --- a/src/app/actions/auth.ts +++ b/src/app/actions/auth.ts @@ -139,6 +139,7 @@ export type FormState = { agree: string; }, mailConfirm?: boolean, + userId?: number, error: Record | null }; @@ -219,11 +220,27 @@ 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: string }; + console.log(parsed); if (parsed.message_desc === 'Operation successful') { - 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, + companyName, + agree + }, + mailConfirm: true, + userId: parsed.message_body.userId, + error: null + }; } else { throw parsed; } @@ -231,19 +248,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) { if (error) { const typedError = error as any; @@ -282,6 +286,7 @@ export async function registration( companyName, agree }, + mailConfirm: false, error: errors }; } @@ -327,9 +332,81 @@ export async function tokenLifeExtension() { export async function confirmEmail( state: any | undefined, - formData: any, + formData: any ) { console.log('confirmEmail'); const emailConfirm = formData.get('emailConfirm') as string || ''; - console.log(emailConfirm); + 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", + }, + body: JSON.stringify({ + version: 1, + msg_id: 20009, + message_body: { + resend: 0, + user_id: userId, + verify_token: emailConfirm + } + }), + }); + + if (response.ok) { + const parsed = await response.json(); + console.log(parsed); + + if (parsed.message_code === 0) { + await createSession(parsed.message_body.token, parsed.message_body.email as string); + } + } + } catch (error) { + return { + error: 'error' + } + } + + redirect('/pages/dashboard'); +} + +export async function resendConfirmEmail(userId: number) { + console.log('resendConfirmEmail'); + + + try { + const response = await fetch(`${API_BASE_URL}/api/v1/data`, { + method: 'POST', + headers: { + "Content-Type": "application/json", + "Accept": "application/json", + }, + body: JSON.stringify({ + version: 1, + msg_id: 20009, + message_body: { + resend: 1, + user_id: userId, + } + }), + }); + + if (response.ok) { + const parsed = await response.json(); + console.log(parsed); + + if (parsed.message_code === 0) { + return { + fine: true + } + } + } + } catch (error) { + return { + fine: false + } + } } \ 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 ca9c6ce..48f9d8a 100644 --- a/src/app/ui/forms/register-form.tsx +++ b/src/app/ui/forms/register-form.tsx @@ -1,8 +1,8 @@ 'use client' import styles from '@/app/styles/module/login.module.scss'; -import { ChangeEvent, useActionState, useEffect, useRef, useState } from 'react'; -import { registration, FormState, confirmEmail } from '@/app/actions/auth'; +import { ChangeEvent, useActionState, useEffect, useRef, useState, MouseEvent } from 'react'; +import { registration, FormState, confirmEmail, resendConfirmEmail } from '@/app/actions/auth'; import PhoneInput from '@/app/ui/inputs/phone-input'; import Link from 'next/link'; import { useTranslations } from 'next-intl'; @@ -113,8 +113,23 @@ export default function RegisterForm() { } } + async function reSendEmailConfirmCode(e: MouseEvent) { + e.preventDefault(); + console.log(state?.userId ? state?.userId : ''); + if (state?.userId) { + await resendConfirmEmail(state?.userId); + } + } + return ( <> + {showMailConfirmWindow && (
{ }} /> +
- +
+ {stateEmailConfrim?.error} +
+
+ + +
+ -- 2.54.0 From 4166cb1d80f78b8ed42a89c801b966e7e1ec016d Mon Sep 17 00:00:00 2001 From: smanylov Date: Fri, 23 Jan 2026 18:06:08 +0700 Subject: [PATCH 2/4] refactor confirm window --- .../ui/forms/confirm-mail-modal-window.tsx | 80 +++++++++++++++++++ src/app/ui/forms/register-form.tsx | 74 +---------------- 2 files changed, 83 insertions(+), 71 deletions(-) create mode 100644 src/app/ui/forms/confirm-mail-modal-window.tsx 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..81bb47e --- /dev/null +++ b/src/app/ui/forms/confirm-mail-modal-window.tsx @@ -0,0 +1,80 @@ +import styles from '@/app/styles/module/login.module.scss'; +import { useTranslations } from 'next-intl'; +import { MouseEvent, useActionState } from 'react'; +import { resendConfirmEmail, confirmEmail } from '@/app/actions/auth'; +export default function ConfirmMailModalWindow({ userId }: any) { + const t = useTranslations('Login-register-form'); + + const [stateEmailConfrim, formActionEmailConfrim, isPendingEmailConfrim] = useActionState( + confirmEmail, + undefined, + ); + + async function reSendEmailConfirmCode(e: MouseEvent) { + e.preventDefault(); + console.log(userId ? userId : ''); + if (userId) { + await resendConfirmEmail(userId); + } + } + + return ( +
e.stopPropagation()} + > +
+
{ + formActionEmailConfrim(e); + }}> +
+

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

+ + { + }} + /> + +
+
+ {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 48f9d8a..d29fcf9 100644 --- a/src/app/ui/forms/register-form.tsx +++ b/src/app/ui/forms/register-form.tsx @@ -2,13 +2,14 @@ import styles from '@/app/styles/module/login.module.scss'; import { ChangeEvent, useActionState, useEffect, useRef, useState, MouseEvent } from 'react'; -import { registration, FormState, confirmEmail, resendConfirmEmail } from '@/app/actions/auth'; +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'; import { IconEye } from '@/app/ui/icons/icons'; import { SignupFormSchema } from '@/app/actions/definitions'; import * as z from 'zod' +import ConfirmMailModalWindow from '@/app/ui/forms/confirm-mail-modal-window'; export default function RegisterForm() { const [state, formAction, isPending] = useActionState( @@ -16,11 +17,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); @@ -113,14 +109,6 @@ export default function RegisterForm() { } } - async function reSendEmailConfirmCode(e: MouseEvent) { - e.preventDefault(); - console.log(state?.userId ? state?.userId : ''); - if (state?.userId) { - await resendConfirmEmail(state?.userId); - } - } - return ( <> - - - - - - + )}
{ -- 2.54.0 From bf9926f004bf97b9a8a2b16e85f7f7ba4015a162 Mon Sep 17 00:00:00 2001 From: smanylov Date: Mon, 26 Jan 2026 13:04:13 +0700 Subject: [PATCH 3/4] update confirm email code window --- src/app/actions/auth.ts | 4 +- src/app/styles/module/login.module.scss | 16 ++++ .../ui/forms/confirm-mail-modal-window.tsx | 89 ++++++++++++++----- src/app/ui/forms/register-form.tsx | 2 +- src/app/ui/icons/icons.tsx | 6 ++ src/i18n/messages/en.json | 5 +- src/i18n/messages/ru.json | 5 +- 7 files changed, 101 insertions(+), 26 deletions(-) diff --git a/src/app/actions/auth.ts b/src/app/actions/auth.ts index 8af2ee2..f9432f8 100644 --- a/src/app/actions/auth.ts +++ b/src/app/actions/auth.ts @@ -331,8 +331,8 @@ 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 || ''; diff --git a/src/app/styles/module/login.module.scss b/src/app/styles/module/login.module.scss index 0f62492..a868274 100644 --- a/src/app/styles/module/login.module.scss +++ b/src/app/styles/module/login.module.scss @@ -140,6 +140,22 @@ transition: all 0.3s; margin-bottom: 18px; margin: 20px 0 0 0; + + &:hover { + transform: translateY(-2px); + } + + &:disabled { + 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 index 81bb47e..427d02f 100644 --- a/src/app/ui/forms/confirm-mail-modal-window.tsx +++ b/src/app/ui/forms/confirm-mail-modal-window.tsx @@ -1,23 +1,57 @@ import styles from '@/app/styles/module/login.module.scss'; import { useTranslations } from 'next-intl'; -import { MouseEvent, useActionState } from 'react'; +import { ChangeEvent, MouseEvent, useActionState, useState, useEffect } from 'react'; import { resendConfirmEmail, confirmEmail } from '@/app/actions/auth'; -export default function ConfirmMailModalWindow({ userId }: any) { - const t = useTranslations('Login-register-form'); - +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(); - console.log(userId ? userId : ''); 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 (
-

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

+

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

{ + placeholder={t('confirmation-code')} + value={confirmCodeValue} + onChange={(e: ChangeEvent) => { + onChangeHandler(e) }} /> + {!stateEmailConfrim?.error && ( +

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

+ )}
{stateEmailConfrim?.error}
-
-
diff --git a/src/app/ui/forms/register-form.tsx b/src/app/ui/forms/register-form.tsx index d29fcf9..dd1c0f9 100644 --- a/src/app/ui/forms/register-form.tsx +++ b/src/app/ui/forms/register-form.tsx @@ -125,7 +125,7 @@ export default function RegisterForm() { setShowMailConfirmWindow(false); }} > - + )}
{ diff --git a/src/app/ui/icons/icons.tsx b/src/app/ui/icons/icons.tsx index d6af85d..3eafd88 100644 --- a/src/app/ui/icons/icons.tsx +++ b/src/app/ui/icons/icons.tsx @@ -145,4 +145,10 @@ export function IconBurgerMenu() { return ( ) +} + +export function IconRefresh() { + return ( + + ) } \ No newline at end of file diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 9199f79..9479042 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -263,6 +263,9 @@ "register-error-phone-not-allowed-symbols": "", "register-error-password-not-allowed-symbols": "Password contains invalid characters.", "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" } } \ No newline at end of file diff --git a/src/i18n/messages/ru.json b/src/i18n/messages/ru.json index 7ce8d55..5c5f60f 100644 --- a/src/i18n/messages/ru.json +++ b/src/i18n/messages/ru.json @@ -263,6 +263,9 @@ "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": "Выслать код заново" } } \ No newline at end of file -- 2.54.0 From 868ed7ca7ef7eddb7cd8609a2a7ee267c55a9dcc Mon Sep 17 00:00:00 2001 From: smanylov Date: Tue, 17 Feb 2026 18:32:45 +0700 Subject: [PATCH 4/4] set error message work correct --- src/app/ui/forms/confirm-mail-modal-window.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/ui/forms/confirm-mail-modal-window.tsx b/src/app/ui/forms/confirm-mail-modal-window.tsx index 427d02f..f2a300e 100644 --- a/src/app/ui/forms/confirm-mail-modal-window.tsx +++ b/src/app/ui/forms/confirm-mail-modal-window.tsx @@ -89,7 +89,7 @@ export default function ConfirmMailModalWindow({ userId, email }: { userId: numb style={{ display: 'none' }} defaultValue={userId ? userId : ''} /> - {!stateEmailConfrim?.error && ( + {stateEmailConfrim?.error && (

-- 2.54.0