diff --git a/src/app/actions/auth.ts b/src/app/actions/auth.ts index a72c6b3..83d2fd7 100644 --- a/src/app/actions/auth.ts +++ b/src/app/actions/auth.ts @@ -83,7 +83,7 @@ export async function authorization( let parsed = await response.json(); await createSession(parsed.token, parsed.email); } else { - throw new Error(`Something went wrong. Status from server ${response.status}`); + throw (`Запрос завершился с ошибкой: ${response.status}`); } } catch (error) { @@ -113,6 +113,7 @@ type FormState = { confirm_password: string; phone: string; company: string; + agree: string; } error: Record }; @@ -127,12 +128,15 @@ export async function registration( const confirm_password = formData.get('confirm_password') as string || ''; const phone = formData.get('phone') as string || ''; const company = formData.get('company') as string || ''; + const agree = formData.get('agree') as string || ''; const validatedFields = SignupFormSchema.safeParse({ full_name, email, + phone: phone.replace(/[-\(\)\s]/g, ''), password, confirm_password, + agree, }); if (!validatedFields.success) { @@ -155,17 +159,18 @@ export async function registration( password, confirm_password, phone, - company + company, + agree }, error: errors }; } try { - const { full_name, email, password } = validatedFields.data; + const { full_name, email, password, phone } = validatedFields.data; const response = await fetch(`${API_BASE_URL}/v1/api/auth/register`, { method: 'POST', - body: JSON.stringify({ fullName: full_name, email, password, phone, company }), + body: JSON.stringify({ fullName: full_name, email, password, companyName: company, phone: phone}), headers: { "Content-Type": "application/json", "Accept": "application/json" @@ -176,14 +181,12 @@ export async function registration( let parsed = await response.json(); await createSession(parsed.token, email); } else { - throw new Error(` - -error-1. status: ${response.status} - `); + throw (`${response.status}`); } } catch (error) { if (error) { - const errors: Record = {} - errors['server'] = `-error-2 -> ${error}` + const errors: Record = {}; + errors['server'] = `Запрос завершился с ошибкой: ${error}` return { previousState: { @@ -192,7 +195,8 @@ export async function registration( password, confirm_password, phone, - company + company, + agree }, error: errors }; diff --git a/src/app/lib/definitions.ts b/src/app/lib/definitions.ts index 01212c7..8c39fa0 100644 --- a/src/app/lib/definitions.ts +++ b/src/app/lib/definitions.ts @@ -23,6 +23,9 @@ export const SignupFormSchema = z .min(3, { error: 'Имя должно содержать не менее 3 символов.' }) .trim(), email: z.email({ error: 'Пожалуйста, введите правильный адрес электронной почты.' }).trim(), + phone: z + .string() + .min(12, { error: 'Пожалуйста, введите телефонный номер' }), password: z .string() .min(8, { error: 'Длина пароля должна быть не менее 8 символов.' }) @@ -30,7 +33,10 @@ export const SignupFormSchema = z .regex(/[0-9]/, { error: 'Пароль должен содержать как минимум 1 цифру.' }) .trim(), confirm_password: z + .string(), + agree: z .string() + .min(2, { error: 'Вы должны ознакомиться с условиями использования и политикой конфиденциальности' }) }) .refine((data) => data.password === data.confirm_password, { message: 'Повторите пароль', diff --git a/src/app/ui/inputs/phone-input.tsx b/src/app/ui/inputs/phone-input.tsx new file mode 100644 index 0000000..9c0faf0 --- /dev/null +++ b/src/app/ui/inputs/phone-input.tsx @@ -0,0 +1,79 @@ +'use client' + +import { useState, ChangeEvent } from 'react'; +import styles from '@/app/styles/login.module.scss'; + +interface PhoneInputProps { + phoneState: string | undefined; +} + +export default function PhoneInput({ phoneState }: PhoneInputProps) { + const [phone, setPhone] = useState(phoneState ? phoneState : ''); + + const formatPhoneNumber = (value: string, isBackspace: boolean): string => { + if (value === '+') { + return value; + } + + const digitsOnly = value.replace(/\D/g, ''); + + if (!digitsOnly) { + return ''; + } + + const limitedDigits = digitsOnly.slice(0, 11); + const countryCode = limitedDigits.startsWith('8') ? '8' : '7'; + const phoneNumber = limitedDigits.startsWith('8') || limitedDigits.startsWith('7') + ? limitedDigits.slice(1) + : limitedDigits; + + let formatted = `+${countryCode}`; + + if (phoneNumber.length > 0) { + formatted += ` (${phoneNumber.slice(0, 3)}`; + } + if (phoneNumber.length >= 3) { + formatted += `) ${phoneNumber.slice(3, 6)}`; + } + if (phoneNumber.length >= 6) { + formatted += `-${phoneNumber.slice(6, 8)}`; + } + if (phoneNumber.length >= 8) { + formatted += `-${phoneNumber.slice(8, 10)}`; + } + + if (isBackspace) { + const lastChar = formatted[formatted.length - 1]; + const specialChars = ['-', '(', ')', ' ']; + + if (specialChars.includes(lastChar)) { + if (lastChar === ' ' && formatted[formatted.length - 2] === ')') { + return formatted.slice(0, -2); + } + return formatted.slice(0, -1); + } + } + + return formatted; + }; + + const handleChange = (e: ChangeEvent): void => { + const input = e.target.value; + //@ts-ignore + const isBackspace = e.nativeEvent.inputType === 'deleteContentBackward'; + const formatted = formatPhoneNumber(input, isBackspace); + setPhone(formatted); + }; + + return ( + + ) +} \ No newline at end of file diff --git a/src/app/ui/register-form.tsx b/src/app/ui/register-form.tsx index 7a8d37e..28132ab 100644 --- a/src/app/ui/register-form.tsx +++ b/src/app/ui/register-form.tsx @@ -3,6 +3,7 @@ import styles from '@/app/styles/login.module.scss'; import { useActionState } from 'react'; import { registration } from '@/app/actions/auth'; +import PhoneInput from '@/app/ui/inputs/phone-input'; export default function RegisterForm() { const [state, formAction, isPending] = useActionState( @@ -48,15 +49,11 @@ export default function RegisterForm() { )}
- - + + + {state?.error?.phone && ( +

{state?.error?.phone}

+ )}
@@ -103,11 +100,22 @@ export default function RegisterForm() { )}
-
- - + - - + {state?.error?.agree && ( +

{state?.error?.agree}

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

{state?.error?.server}

+ )} + + ) } \ No newline at end of file