zov-tech/miniapp/index.html
wasrusgen 34b83899b5 fix client create — 7 багов + правило самопроверки
#7 — submit-flow:
  - При успехе скрываем CTA с «Сохраняем...» (style.display=none)
  - Обработчики «Ещё клиент» / «Открыть карточку» прикрепляются к
    result-блоку (был form.querySelector — там их нет)
  - Backend возвращает client_key = name.lower() — совместимо
    с тем как ищет _handle_clients
  - clientsCache = null после успеха

#3 — голос дублировался:
  - Переписан алгоритм: финальные транскрипты пересчитываются с нуля
    из ev.results[0..N] каждое событие (не аккумулируем дельтами).
  - confirmedFinal фиксируется в baseText только на onend.
  - Применено в measurements.js + clients.js

#2 — телефон:
  - Frontend normalizePhone: убирает не-цифры, +7/8 → +7, добавляет +7
    к 10-значным; auto-нормализация на blur
  - Backend _normalize_phone(): тот же алгоритм
  - Валидация: ровно 11 цифр начиная с 7
  - Field-error «Введите корректный российский номер...»

#1 — адрес:
  - Min 5 chars (улица + дом)
  - Backend проверка длины
  - Hint «Укажите город, улицу, дом, кв.»

#5 — номер клиента:
  - Новая колонка client_no
  - _next_client_no() — максимум для текущего менеджера + 1
  - Шильд #N рядом с именем в карточке клиента

#6 — номер договора:
  - Новые колонки contract_no, contract_date
  - Поля в форме «Новый клиент» (опционально)
  - Шильд «📋 договор N» в карточке клиента

#4 — удаление клиента:
  - Soft-delete через колонку archived_at
  - Endpoint /api/client_delete
  - «⚠️ Опасная зона» в карточке клиента (collapsible)
  - Confirm dialog через Telegram.WebApp.showConfirm
  - Архивированные клиенты не показываются в /api/clients

#8 — правило самопроверки:
  - docs/SELF_CHECK_RULE.md — 10 пунктов чек-листа перед «готово»
    (end-to-end, ключи, UI-состояния, валидация, голос, deploy, логи)

Cache bust v=20260514a.
2026-05-14 00:09:14 +03:00

49 lines
2.6 KiB
HTML

<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, user-scalable=no">
<meta name="theme-color" content="#2C3E50">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<title>WASRUSGEN1 · Кабинет</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Geist:wght@400;500;600&family=Newsreader:ital,wght@0,400..600;1,400..600&family=Instrument+Serif:ital@0;1&family=JetBrains+Mono:wght@400;500&family=Cormorant+Garamond:ital,wght@1,400;1,500;1,600&family=Caveat:wght@500;700&display=swap">
<script src="https://telegram.org/js/telegram-web-app.js"></script>
<link rel="stylesheet" href="assets/styles.css?v=20260514a">
<link rel="stylesheet" href="assets/podbor.css?v=20260514a">
</head>
<body>
<!-- Splash — лого @wasrusgen1 + опилки (16) + вращающийся диск -->
<div class="loader splash" id="splash">
<div class="brand-logo-wrap">
<img class="brand-logo" src="assets/wasrusgen-logo.svg?v=20260514a" alt="@wasrusgen1">
<div class="splash-dust" aria-hidden="true">
<span class="dust d1"></span> <span class="dust d2"></span>
<span class="dust d3"></span> <span class="dust d4"></span>
<span class="dust d5"></span> <span class="dust d6"></span>
<span class="dust d7"></span> <span class="dust d8"></span>
<span class="dust d9"></span> <span class="dust d10"></span>
<span class="dust d11"></span> <span class="dust d12"></span>
<span class="dust d13"></span> <span class="dust d14"></span>
<span class="dust d15"></span> <span class="dust d16"></span>
</div>
</div>
<div class="loader-bar"></div>
<div class="brand-tagline-gold">CRM</div>
</div>
<main id="app"></main>
<script src="assets/icons.js?v=20260514a"></script>
<script src="assets/podbor.config.js?v=20260514a"></script>
<script src="assets/podbor.picts.js?v=20260514a"></script>
<script src="assets/podbor.js?v=20260514a"></script>
<script src="assets/clients.js?v=20260514a"></script>
<script src="assets/zamer-picts.js?v=20260514a"></script>
<script src="assets/measurements.js?v=20260514a"></script>
<script src="assets/request.js?v=20260514a"></script>
<script src="assets/app.js?v=20260514a"></script>
</body>
</html>