From 47c349818f9631573defadbbe99167c771c60045 Mon Sep 17 00:00:00 2001 From: nurdotnet <278048682+nurdotnet@users.noreply.github.com> Date: Sun, 3 May 2026 15:56:27 +0500 Subject: [PATCH] =?UTF-8?q?fix(phone):=20=D0=BD=D0=B5=20=D1=81=D1=87=D0=B8?= =?UTF-8?q?=D1=82=D0=B0=D1=82=D1=8C=20=C2=AB7=C2=BB=20=D0=B8=D0=B7=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B5=D1=84=D0=B8=D0=BA=D1=81=D0=B0=20=D0=BA=D0=B0?= =?UTF-8?q?=D0=BA=20=D0=B2=D0=B2=D0=B5=D0=B4=D1=91=D0=BD=D0=BD=D1=83=D1=8E?= =?UTF-8?q?=20=D1=86=D0=B8=D1=84=D1=80=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Баг: при нажатии любой не-цифры (буквы, пробела) поле подставляло «7». Корень: extractDigits парсил полное e.target.value включая префикс «+7», и его «7» попадала в d, добавляясь как введённый юзером символ. Backspace на пустом поле не работал по той же причине. Фикс: новая функция parseRawInput отделяет префикс «+7 » ДО извлечения цифр. Применена в handleChange обоих PhoneInput (web + public). Кейс paste без префикса (8XXXXXXXXXX / 7XXXXXXXXXX из 11 цифр) сохранён. --- .../src/components/PhoneInput.tsx | 13 ++++++++++- .../src/components/PhoneInput.tsx | 23 +++++++++++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/food-market.public/src/components/PhoneInput.tsx b/src/food-market.public/src/components/PhoneInput.tsx index 2cfd641..3a146cc 100644 --- a/src/food-market.public/src/components/PhoneInput.tsx +++ b/src/food-market.public/src/components/PhoneInput.tsx @@ -7,6 +7,17 @@ function extractDigits(value: string): string { return d.slice(0, 10) } +/** Парсит сырой ввод инпута, отбрасывая префикс «+7 ». Без этого «7» из + * префикса попадает в подсчёт и при нажатии не-цифры появляется лишняя «7». */ +function parseRawInput(raw: string): string { + if (raw.startsWith('+7 ')) raw = raw.slice(3) + else if (raw.startsWith('+7')) raw = raw.slice(2) + else if (raw.startsWith('+')) raw = raw.slice(1) + let d = raw.replace(/\D/g, '') + if (d.length === 11 && (d[0] === '7' || d[0] === '8')) d = d.slice(1) + return d.slice(0, 10) +} + function formatLocal(d: string): string { if (d.length === 0) return '' if (d.length <= 3) return d @@ -27,7 +38,7 @@ export function PhoneInput({ value, onChange, className, disabled, ...rest }: Ph const display = `+7 ${formatLocal(digits)}`.trimEnd() const handleChange = (e: React.ChangeEvent) => { - const d = extractDigits(e.target.value) + const d = parseRawInput(e.target.value) onChange(d.length > 0 ? `+7${d}` : '') } diff --git a/src/food-market.web/src/components/PhoneInput.tsx b/src/food-market.web/src/components/PhoneInput.tsx index 4bd8bb0..7ecabd1 100644 --- a/src/food-market.web/src/components/PhoneInput.tsx +++ b/src/food-market.web/src/components/PhoneInput.tsx @@ -3,12 +3,25 @@ import { cn } from '@/lib/utils' const inputClass = 'w-full h-10 rounded-md border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-900 px-3 text-sm leading-none focus:outline-none focus:ring-2 focus:ring-[var(--color-brand)] disabled:opacity-60 disabled:bg-slate-50 dark:disabled:bg-slate-800/60 tabular-nums' -/** Извлекает 10 цифр KZ-номера (после +7) из любого формата. - * "+7 700 123 45 67" → "7001234567", "8(707)1234567" → "0712345670"… */ +/** Извлекает 10 цифр KZ-номера (после +7) из каноничного значения «+7XXXXXXXXXX». */ function extractDigits(value: string): string { if (!value) return '' let d = value.replace(/\D/g, '') - // 11 цифр и ведущая 7 или 8 — это код страны, отрезаем. + if (d.length === 11 && (d[0] === '7' || d[0] === '8')) d = d.slice(1) + return d.slice(0, 10) +} + +/** Парсит сырой ввод инпута (то что показано на экране, например «+7 700 1») + * и достаёт реально введённые юзером цифры (после «+7 »). Критично: «+7 » + * префикс отбрасывается ДО извлечения цифр, иначе «7» из префикса попадает + * в подсчёт и при нажатии не-цифры на пустом поле появляется «7». */ +function parseRawInput(raw: string): string { + // Снимаем именно наш префикс — в любом из трёх возможных промежуточных видов. + if (raw.startsWith('+7 ')) raw = raw.slice(3) + else if (raw.startsWith('+7')) raw = raw.slice(2) + else if (raw.startsWith('+')) raw = raw.slice(1) + let d = raw.replace(/\D/g, '') + // Кейс paste «8 700 …» или «7 700 …» без нашего префикса. if (d.length === 11 && (d[0] === '7' || d[0] === '8')) d = d.slice(1) return d.slice(0, 10) } @@ -41,8 +54,8 @@ export function PhoneInput({ value, onChange, className, disabled, ...rest }: Ph const display = `+7 ${formatLocal(digits)}`.trimEnd() const handleChange = (e: React.ChangeEvent) => { - const d = extractDigits(e.target.value) - onChange(d.length === 10 ? `+7${d}` : d.length > 0 ? `+7${d}` : '') + const d = parseRawInput(e.target.value) + onChange(d.length > 0 ? `+7${d}` : '') } const handleKeyDown = (e: React.KeyboardEvent) => {