# Исправления публичного сайта test.food-market.kz — круг 2 (11.10.2026) **Деплой:** только тестовый сайт через `~/.fm-watchdog/deploy-public-test.sh` (commit `6f229eb`, статус `OK`). Прод, gateway nginx, прод-БД — не трогались. **Образ отката:** `192.168.1.193:5001/food-market-public:test-pre-site-fixes-2` (создан из текущего `:test` ДО деплоя). Откат: перетегировать его в `:test` и `docker compose up -d public` на prod-vm. **Автопроверка (Playwright, как человек):** 44/44 — см. `index.html` (desktop 1440 @2x + mobile 390 @3x, 13 скриншотов), сырые данные — `verify.json`. --- ## Уточнение поручения владельца по брендам (важно) Было два сообщения владельца. Итоговая (уточнённая) трактовка, по которой сделано: - **Убрать со всего сайта — ТОЛЬКО чужие СИСТЕМЫ УЧЁТА** рознцы (конкуренты): «МойСклад» / «Мой склад» / MoySklad, «1С» / 1C. Grep по `dist`: **0 вхождений** вне `/legal/*` (в `/legal/*` их и нет — проверено). - **Платёжные системы, банки, маркетплейсы** (Kaspi Pay, Kaspi Magazin, Halyk, Jusan, Forte, Wildberries, Ozon, Visa, Mastercard) — **НЕ** чужие системы учёта, удалять не требовалось. Оставлены **только как честная пометка «в разработке»** на `/integrations` и главной (без дат и обещаний), нигде — как готовая функция. - Промежуточное (ошибочно расширенное) удаление Kaspi/маркетплейсов со страницы `/integrations` **откатил** — вернул их в блок «В разработке» в прежнем виде (Kaspi Pay, Kaspi Magazin, Ozon, Wildberries; ОФД РК). - Из KB/блога/FAQ обещания уже подключённых способов оплаты/интеграций всё равно убраны — но по причине «**этого нет в продукте**», а не «чужой бренд». Где Kaspi/маркетплейсы остались (проверено): `/integrations` (блок «В разработке») и главная (FAQ — «в планах, сроков не называем»). Больше нигде. --- ## Сделано — по пунктам круга 2 ### 1. Оставшиеся «ложные обещания» / честность текстов - **`/kb/pos-setup`** — касса для **Windows и Linux**; вход = адрес сервера + логин + PIN (не «ключ организации»); установка «скоро»; принтеры «58/80 мм (ESC/POS)». - **`/blog/quick-start`** — убран дубль `# H1`; «Импорт через API» → «Импорт из других систем учёта — в разработке»; шаги установки .msi/ключ → сервер+логин+PIN; меню лояльности/маркетинга → «раздел «Акции и скидки»», «лояльность — в расширенном режиме»; обложка — скриншот продукта (не чужое стоковое фото). - **`/blog/launch`** — убран дубль H1; «триал» → «честный бесплатный период»; «Касса для Windows» → «Windows и Linux … приложение — скоро»; маркетплейсы/оплаты → «в разработке» (без дат); «все возможности CRM/лояльность/…» → «без доплат за модули». - **`/kb/faq`** — бэкапы «каждые 24 ч» → «регулярные»; «TLS 1.3» → «TLS» (без версии); формулировка про ЗРК смягчена до «в соответствии с законодательством РК»; импорт — файлы Excel/CSV, из других систем «в разработке»; **«триал» → «бесплатный период»** (унифицировано); «с SLA» убрано. - **Унификация «триал» → «бесплатный период»** по сайту (og.mjs тоже). В `/legal/*` термин «Триал» оставлен как есть (юр. документы не трогаем). - **og-картинки** перегенерированы (`node scripts/og.mjs`): без чужих систем учёта; касса «Windows и Linux»; «90 дней бесплатно». ### 2. React #418 (hydration mismatch) на `/signup` `SignupForm.tsx`: `?plan=` и параметры конфигуратора теперь читаются в `useEffect` **после** гидрации, поэтому первый клиентский рендер совпадает с SSR-разметкой. Проверка консоли на `/`, `/pricing`, `/signup?plan=business&…` и `/signup?plan=business` — **ошибок нет, #418 отсутствует** (8/8 авто-проверок). ### 3. `/signup` без параметров конфигуратора - `plan=business` без параметров → выбран **«Бизнес»** с дефолтной конфигурацией **1/1/1/5 = 10 000 ₸** (показана карточка «Ваша конфигурация»). ✓ проверено. - `plan=network` → «Сеть»; неизвестный план → «Старт». ✓ - Клик по плитке тарифа обновляет URL (`history.replaceState`). - Плитка «Старт»: «5 000 ₸» → **«5 000 ₸/мес»**; цены плиток без переноса. ### 4. Типографика KB/блога - `.prose-md` (h2/h3, списки, таблицы, ссылки, код, цитаты) вынесена в `global.css` — грузится на всех страницах; `/kb/*` больше **не плоский текст** (раньше стиль был только на странице блога). ✓ проверено (`h2`, `ul li` в `.prose-md`). - Блог: убран дублирующий `

` (в теле статей) — на странице ровно один H1. ✓ ### 5. Мелочи - **sitemap.xml** — канонические URL **со слэшем** (убраны 301), добавлены статьи KB и блога. ✓ - **Footer** «Status» → **«Статус»**. - **`/changelog`** — убран внутренний жаргон (Phase N, SuperAdmin, retention period, tenant, inline, Read-only/Edit-mode) → человеческие формулировки; заголовок «Что нового». ✓ - **`/pricing`** — на конструкторе «Бизнес» бейдж **«Популярный»** (как на главной) + **«90 дней бесплатно»**; у «Старт» убран ложный пункт «Импорт из других систем». - Шапка ~1050px: десктоп-меню переведено на `xl` (до 1280px — гамбургер), CTA без переноса → на ~1050px и на мобильном меню/кнопка **не ломаются в 2 строки**. ✓ - Инлайн-ссылки в тексте — увеличенная зона нажатия (padding без сдвига вёрстки). - Эмодзи-фолбэк-стек в `body` (чтобы эмодзи не были квадратами там, где нет цветного emoji-шрифта). ### 6. Не трогал `/legal/*` и контакты-плейсхолдеры («[НАЗВАНИЕ ТОО]», «[БИН]», «+7 (___)») — без изменений. Бренд ALL MARKET, цвета, шрифты — без изменений. --- ## Дополнение по тесту на Android (Firefox 157) — сделано 1. **Мобильное меню + кнопка «Назад» Android.** При открытии панели кладём запись в историю (`pushState`), закрываем по `popstate` → системная «Назад» закрывает меню, а не уводит со страницы. Esc/тап-вне/крестик остались. ✓ проверено (`m-after-back.png` — после «Назад» панель закрыта, остались на `/`). 2. **Состав мобильной панели.** Добавлены «Интеграции» (в основную навигацию) и внизу панели вторичные ссылки **«Статус»** и **«Что нового»** (раньше были только в футере). ✓ 3. **«Настроить тариф» (главная)** → `/pricing#configurator` со скроллом к конструктору (у блока `id="configurator"` + `scroll-mt-20`). ✓ якорь есть. 4. **Ползунки конструктора на тач.** Крупная ручка (28px), `touch-action: pan-y` на инпуте (вертикальный свайп скроллит страницу, а не двигает значение), и кнопки **«−/+»** у каждого значения (менять без перетаскивания). ✓ проверено. 5. **`/kb/billing`.** Проверено по коду `src/food-market.*`: биллинг/подписки в продукте **нет** (в вебе явная заглушка «до Phase 4 «Подписки»»; единственная сущность `Subscription` — это `WebPushSubscription`, push-уведомления). Поэтому убраны несуществующие: «Настройки → Подписка → История» (скачивание счетов/чеков), e-mail-напоминания, баннер в админке, формула кредита при понижении, SLA для «Сеть». Переписано честно: оплата на раннем доступе — вручную через поддержку, онлайн-оплата и личный кабинет «в разработке». Цены «тг» → **«₸»**. ✓ 6. **`/status`.** Убраны фиктивные зелёные «● Работает» (мониторинга нет) — честная страница «в разработке» + контакты для инцидентов (реальный `/health` не подключал: это требует серверной части, вне правки статического сайта). ✓ --- ## Решения, требующие внимания владельца 1. **Контракт API регистрации.** Форма отправляет `plan`, а для «Бизнес» ещё и `shops/cashes/warehouses/employees` (вперёд-совместимо). **Текущий серверный контракт `SignupInput` принимает только `plan`** — конфигурация конструктора на бэкенде пока игнорируется. Нужно решение: принимать ли её на сервере (тогда — отдельная задача по API) или оставить как сейчас. 2. **Оборудование на `/integrations`.** В «Уже работает» вернул конкретику «весы CAS, Масса-К и совместимые» (это производители **весов**, не системы учёта, — под уточнённое поручение не попадают). Если хотите — заменю на нейтральное «популярные протоколы». 3. **Юр. документы / реквизиты.** В `/legal/*` чужих систем учёта и брендов нет — список пуст, ничего выносить не требуется. Плейсхолдеры реквизитов не трогал. --- ## Проверка (как в задаче) | Критерий | Результат | |---|---| | Консоль чистая на `/`, `/pricing`, `/signup` (вариации), React #418 нет | ✓ | | `plan=business` без параметров → «Бизнес» 10 000 (1/1/1/5) | ✓ | | `dist`/живой сайт: 0 «МойСклад/Мой склад/moysklad/1С/1C» вне `/legal/*` | ✓ | | Kaspi/маркетплейсы — только «в разработке» на `/integrations` и главной | ✓ | | Унификация «бесплатный период»; «тг» → «₸» в KB | ✓ | | Типографика KB (h2/списки) + один H1 в блоге | ✓ | | sitemap — канонические URL со слэшем + KB/блог | ✓ | | Моб.: «Назад» закрывает меню; состав панели; ползунки −/+ | ✓ | | `/status` без фиктивного статуса; `/changelog` без жаргона; `/kb/billing` честный | ✓ | Итог авто-проверки: **44/44**. --- ## Догоняющие правки (сверка с канонической редакцией задачи) При повторной сверке с полным списком задачи закрыты оставшиеся хвосты (commit `28cc6a7`, передеплой на test — `OK`): - **`/kb/quickstart`** (отдельный файл от блога — его пропускал ранее): убраны `.msi`, «ключ организации», «импорт по API-токену» → импорт из файла Excel/CSV, из других систем «в разработке»; касса Windows и Linux «скоро», вход по адресу сервера + логин + PIN. - **`/blog/cash-with-scales`** — убран дублирующий `

` в теле (теперь во всех трёх статьях блога ровно один H1 — проверено в `dist`). - **«до 100 000 товаров»** (kb/faq + og) — в коде точного лимита нет (есть только `RequestSizeLimit(20MB)` на эндпоинте импорта), поэтому заменено на нейтральное «большие каталоги — тысячи позиций». - **Кнопка «Выбрать конфигурацию»** — цена «₸/мес» больше не переносится (`whitespace-nowrap`). - **Инлайн-ссылки «офертой»/«политикой»** в форме регистрации — увеличенная зона нажатия (`py-1`) без изменения вида. **ОС кассы — проверено по коду:** `food-market.pos.csproj` → `TargetFramework net8.0` (не `net8.0-windows`) + Avalonia (кроссплатформенный UI) → сборка под **Windows и Linux** реальна, формулировка на сайте честна (приложение для скачивания — «скоро»). **Живой grep (curl) по всем страницам `/kb/*` и `/blog/*`:** нет `.msi`, `API-токен`, `ОКП`, `Kaspi Magazin`, `Wildberries`, `Ozon`, `TLS 1.3`, `100 000`, `триал`, `SIN EXCEPCION`. Обложка `/blog/quick-start` = `/screenshots/catalog.webp` (скриншот продукта, без чужого фото). --- ## Круг 3 (финальный прогон этапа 1, 11.10 — Chrome/Win11 VM) Две мелкие правки, деплой только на тест (`test.food-market.kz`, commit `a25b940`, статус `OK`; образ отката `test-pre-site-fixes-3` создан до деплоя). 1. **Касса подаётся единообразно честно.** Раньше /status, /pos, /kb/pos-setup писали «скоро», а главная и /about — как готовую. Привёл к одному виду: касса для Windows и Linux, **приложение для скачивания — «скоро»** (как на /pos). - главная — карточка «Продажи и касса»: «…для Windows и Linux, работает без интернета. Приложение для скачивания — скоро.» - /about, «Что уже работает»: «Касса … для Windows и Linux, работает без интернета (приложение для скачивания — скоро).» Проверено живым grep и скриншотами (главная/ about) на 1280 и 390. 2. **Знак «₸» не переносится в тарифах.** `whitespace-nowrap` + неразрывные пробелы: «10 000 ₸» / «14 000 ₸» (конструктор «Бизнес»), «5 000 ₸/мес» («Старт»), CTA «… 10 000 ₸/мес». Проверка: высота строки цены конструктора 36px (одна строка) на 1280 и 390 — не разрывается. Скриншоты: `k3-pricing-1280.png`, `k3-pricing-390.png`, `k3-about-1280.png`. Автопроверка (Playwright): 5/5. Юридические реквизиты не трогал (отложены до продакшна). Прод-сайт не трогал. --- ## Круг 4 (прогон этапа 1 в Safari на iPhone 17, ширина 402 — 12.10) Круг 3 закрыл разрыв цены **только на /pricing**. Прогон в Safari (симулятор iPhone 17) нашёл ещё два места, где «сумма + ₸ + /мес» рвётся по строкам: 1. **Главная, строка под кнопками героя** — «Подписка от 5 000 ₸/мес»: «5» на одной строке, «000 ₸/мес» на следующей. 2. **/signup после конфигуратора «Бизнес»** — итог «14 000 ₸/мес» рвался после «₸/» (слэш — точка переноса), плитки тарифов — так же. Исправлено **системно**, а не точечно (commit `a0f9e0b`, деплой только на тест `test.food-market.kz`, статус `OK`): - **`lib/pricing.ts` — единый источник правды:** - `fmtKzt` теперь ставит неразрывные пробелы (U+00A0) между разрядами и перед «₸» → сумма с «₸» никогда не рвётся; - новый `fmtKztMonth` = сумма + «₸» + «/мес» одним куском: word-joiner (U+2060) вокруг «/» запрещает перенос на слэше. - **`SignupForm.tsx`** — плитки «Старт»/«Бизнес» и итог «Ваша конфигурация „Бизнес“» используют `fmtKztMonth` (+ `whitespace-nowrap` на итоге). - **`index.astro`** — hero-строка и карточки «Старт»/«Бизнес» (`whitespace-nowrap` + ` `); «от» в «Бизнес» остаётся переносимым, цена — нет. - **`BusinessTariffBuilder.tsx`** — подпись «База 10 000 ₸» обёрнута в `nowrap`. - **Контент `kb/billing.md`, `kb/faq.md`, `blog/launch.md`, `FAQ.tsx`** — суммы с nbsp + word-joiner, чтобы цена не рвалась и в тексте статей/ответов. **Автопроверка (Playwright, Safari-UA iPhone 17):** ширины **320, 375, 390, 402** × страницы **главная, /pricing, /signup?plan=start, /signup после «Бизнес»** — **44/44 passed**. Высоты строк цен: hero 15px, плитки 16px, итог «Бизнес» 20px, конструктор 36px — везде **одна строка**. Горизонтальной прокрутки нет ни на одной ширине. Текст итога «Бизнес» = `14 000 ₸⁠/⁠мес` (неразрывный). Скриншоты (`docs/site-fixes-2026-10-11/`): `k4-home-{320,375,390,402}.png`, `k4-pricing-*.png`, `k4-signup-start-*.png`, `k4-signup-biz-*.png`. Скрипт: `tests/e2e/tools/site-fixes-verify-4.mjs`. Остальное в прогоне владельца чисто (меню, «Назад», тарифы, выбор Старт/Бизнес/Сеть, нет горизонтальной прокрутки на 25 страницах) — не трогал. Юридические реквизиты не трогал. Прод-сайт не трогал. Весы — пауза в силе.