diff --git a/src/food-market.public/src/components/SignupForm.tsx b/src/food-market.public/src/components/SignupForm.tsx index baa5a9b..64874d6 100644 --- a/src/food-market.public/src/components/SignupForm.tsx +++ b/src/food-market.public/src/components/SignupForm.tsx @@ -2,8 +2,6 @@ import { useState } from 'react' import { validateEmail, validatePassword, validatePhone } from '@/lib/validation' import { PhoneInput } from '@/components/PhoneInput' -// Админский / API endpoint — переключается через PUBLIC_APP_URL на этапе -// билда. Дефолт — admin.food-market.kz (там и API и админ-SPA). const APP_URL = (import.meta.env.PUBLIC_APP_URL as string | undefined) ?? 'https://admin.food-market.kz' const API_URL = APP_URL @@ -81,30 +79,77 @@ export default function SignupForm({ defaultPlan = 'start' }: Props) { {error && (
{error}
)} + - { setEmail(e.target.value); setFieldErrors(p => ({...p, email: undefined})) }} - onBlur={() => { const e = validateEmail(email); setFieldErrors(p => ({...p, email: e ?? undefined})) }} - autoComplete="email" placeholder="name@example.kz" className={inputCls(!!fieldErrors.email)} /> + { + const v = e.target.value + setEmail(v) + // Ре-валидируем только если ошибка уже показана (не мешаем первичному вводу) + setFieldErrors(p => p.email ? {...p, email: validateEmail(v) ?? undefined} : p) + }} + onBlur={(e) => { + // e.target.value — реальное DOM-значение, без stale closure + setFieldErrors(p => ({...p, email: validateEmail(e.target.value) ?? undefined})) + }} + autoComplete="email" + placeholder="name@example.kz" + className={inputCls(!!fieldErrors.email)} + /> + - { setPassword(e.target.value); setFieldErrors(p => ({...p, password: undefined})) }} - onBlur={() => { const e = validatePassword(password); setFieldErrors(p => ({...p, password: e ?? undefined})) }} - autoComplete="new-password" className={inputCls(!!fieldErrors.password)} /> + { + const v = e.target.value + setPassword(v) + setFieldErrors(p => p.password ? {...p, password: validatePassword(v) ?? undefined} : p) + }} + onBlur={(e) => { + setFieldErrors(p => ({...p, password: validatePassword(e.target.value) ?? undefined})) + }} + autoComplete="new-password" + className={inputCls(!!fieldErrors.password)} + /> + - { setOrgName(e.target.value); setFieldErrors(p => ({...p, orgName: undefined})) }} - onBlur={() => { setFieldErrors(p => ({...p, orgName: !orgName.trim() ? 'Название магазина обязательно для заполнения' : undefined})) }} - placeholder="Наименование организации" className={inputCls(!!fieldErrors.orgName)} /> + { + const v = e.target.value + setOrgName(v) + setFieldErrors(p => p.orgName ? {...p, orgName: !v.trim() ? 'Название магазина обязательно для заполнения' : undefined} : p) + }} + onBlur={(e) => { + setFieldErrors(p => ({...p, orgName: !e.target.value.trim() ? 'Название магазина обязательно для заполнения' : undefined})) + }} + placeholder="Наименование организации" + className={inputCls(!!fieldErrors.orgName)} + /> + - { setPhone(v); setFieldErrors(p => ({...p, phone: undefined})) }} - onBlur={() => { const e = validatePhone(phone); setFieldErrors(p => ({...p, phone: e ?? undefined})) }} - required className={inputCls(!!fieldErrors.phone)} /> + { + setPhone(v) + setFieldErrors(p => p.phone ? {...p, phone: validatePhone(v) ?? undefined} : p) + }} + onBlur={(e) => { + // e.target.value — display-формат "+7 7XX XXX XX XX", validatePhone его принимает + setFieldErrors(p => ({...p, phone: validatePhone((e as React.FocusEvent).target.value) ?? undefined})) + }} + required + className={inputCls(!!fieldErrors.phone)} + /> +
Тариф
@@ -121,6 +166,7 @@ export default function SignupForm({ defaultPlan = 'start' }: Props) { ))}
+
{fieldErrors.agree &&

{fieldErrors.agree}

}
+