Commit Graph

29 Commits

Author SHA1 Message Date
wasrusgen
8201fee9f2 client card D1: хронология + файлы + быстрые действия
Карточка клиента (#/clients/client/<key>) переработана:

1. Шапка с большой круглой кнопкой 📞 справа — звонок одним тапом
   через tel: ссылку.

2. Быстрые действия (3 в ряд):
   - 🤖 Подбор техники — переход в #/podbor с pre-fill ФИО/телефона
   - 📐 Заказать замер — переход в #/request с pre-fill (через sessionStorage)
   - 📋 Копировать ФИО+тел — clipboard для пересылки коллеге

3. Примечание менеджера (с голосовым вводом) — уже было.

4. 🕒 Хронология — единая лента событий:
   - Лиды (подборы) с датой создания и статусом
   - Заявки на замер
   - Назначенные замеры (на дату scheduled_at)
   - Завершённые замеры
   События отсортированы по дате desc, рядом крупная точка timeline,
   тап → переход к детали.

5. 📂 Файлы — группы по замерам с миниатюрами фото (до 6 в ряд +
   плашка «+N» если больше). Тап на миниатюру открывает в новом
   окне (фото открывается в полный размер).

6. Свёрнутые секции «Подборы» и «Замеры» внизу — для тех кому
   нужны плоские списки.

Cache bust v=20260513za.
2026-05-13 18:39:25 +03:00
wasrusgen
366625be66 flow: упрощённая заявка + 3 чёткие стадии у замерщика
По цепочке менеджер→замерщик→замер:

Менеджер «Заказать замер»:
  - ФИО, телефон, адрес, кому назначить
  - Одно поле «Примечание» (рекомендации по дате + особенности)
    Убраны radio-buttons specific/this_week/next_week — слишком сложно.
    Точную дату всё равно согласует замерщик с клиентом.

Замерщик в карточке заявки — 3 чёткие стадии:

  1. ЕСЛИ статус requested (дата не назначена):
     - Блок «📞 Согласовать дату с клиентом»
     - Подсказка «Позвоните клиенту и зафиксируйте»
     - datetime-local + кнопка «Назначить»

  2. ЕСЛИ статус scheduled (дата уже есть):
     - Блок «📅 Замер назначен» крупно (Newsreader 22pt italic)
     - Кнопка «Изменить дату» — разворачивает скрытую форму
     - ОСНОВНАЯ кнопка «📐 Начать замер» (большая, primary, 16pt)
     - До «Начать замер» чек-листа не видно

Чек-лист (📋 в шапке) теперь живёт ТОЛЬКО в мастере замера
(когда нажали «Начать замер»). До этого момента не отвлекает.

Backend: DM при создании заявки шлёт только примечание
(без расшифровки preferred_type).

Cache bust v=20260513z.
2026-05-13 18:12:18 +03:00
wasrusgen
9e23239f57 client note: примечание менеджера + голосовой ввод
Backend:
- Лист ClientNotes (auto-create через ensure_sheet) — колонки
  manager_tg_id, client_key, note, updated_at.
- Ключ клиента: «p:7XXXXXXXXXX» если есть телефон ≥10 цифр,
  иначе «n:<имя в lower>». Привязан к менеджеру.
- POST /api/client_note — без поля note читает текущую,
  с note — upsert (хард-кап 4000 символов).

Frontend в карточке клиента (#/clients/client/<key>):
- Новый блок «📝 Примечание» сверху над списком подборов
- Textarea + дата обновления в meta
- Кнопка «🎤 Диктовать» — Web Speech API (ru-RU)
  · interimResults показывает прямо во время речи
  · final-результаты добавляются к baseText
  · красная пульсация во время записи
  · graceful degrade если SR недоступен (Telegram WebApp на iOS)
- Кнопка «Сохранить» → PUT в /api/client_note + статус «✓ сохранено»

CSS: .client-note-block, .btn-mic, .btn-mic.rec (pulse animation),
.note-status.ok / .err.

Cache bust v=20260513y.
2026-05-13 18:06:45 +03:00
wasrusgen
7a5df7d011 checklist: 5 SVG-эскизов в стиле Editorial Calm
По аналогии с пиктограммами категорий техники добавил инструктивные
рисунки к чек-листу замера. Walnut stroke + cream fill + лёгкая тень.

1. topview — вид сверху, комната с пронумерованными стенами + компас.
2. clockwise — стрелка по часовой стрелке с точкой «старт».
3. openings — фронт стены с дверью / окном / балконом + размеры
   (ширина, высота, низ подоконника).
4. comms — стена с точками R1 / Sw1 / Wc1, двумя размерами на каждую
   (горизонталь до угла-базы + вертикаль до пола), указанная БАЗА: ПУ.
5. levels — разрез помещения с нулевым полом (волнистая стяжка),
   плитой +88, потолком и коробом справа, размеры H1/H2.

Реализация:
- Новый файл miniapp/assets/zamer-picts.js — экспортирует ZAMER_PICTS.
- renderMarkdown в measurements.js поддерживает директиву
  «@pict:KEY» на отдельной строке → подставляет SVG.
- Эскизы вставлены в ЧЕКЛИСТ_ЗАМЕРА.md в соответствующие разделы
  (1, 4, 6, 8). По часовой стрелке — после § 1.
- CSS .cl-pict — рамка пунктиром + цент., max-height 220.

Cache bust v=20260513x.
2026-05-13 18:00:43 +03:00
wasrusgen
e2e17fd5a6 measurement logistics: подъезд, GPS, парковка, заметки для логистов
Замерщик/сборщик/менеджер при выезде на объект может дополнить
адрес деталями. Эти же данные будут видны и при сборке —
существенно облегчает планирование подъезда и парковки.

Поля:
  - Подъезд + этаж
  - GPS-координаты (с кнопкой «Сейчас» — забирает с устройства через
    navigator.geolocation, ссылка на Google Maps в сводке)
  - Парковка: бесплатная / платная / на улице / нет + текст-уточнение
  - Заметки логистики: домофон, шлагбаум, размер лифта, узкий проезд

UX:
  - В карточке заявки секция «📍 Логистика» свёрнута по умолчанию,
    показывает сводку. Кнопка «Заполнить» / «Изменить» раскрывает форму.
  - Точка-индикатор после заголовка если есть данные.
  - Сводка собирается строкой: подъезд · этаж · GPS-ссылка · парковка · заметка.

Backend:
  - 7 новых колонок в Measurements (entrance, floor, gps_lat, gps_lng,
    parking_type, parking_note, delivery_notes).
  - POST /api/measurement_logistics — точечный апдейт. Право:
    назначенный замерщик / менеджер-владелец / любой сборщик.

Cache bust v=20260513v.
2026-05-13 17:46:53 +03:00
wasrusgen
fdce3b3c64 measurement workflow: приблизительная дата от менеджера
По процедуре пользователя: менеджер при создании заявки может не
знать точной даты. Указывает диапазон, замерщик потом созванивается
с клиентом и фиксирует точную дату.

Менеджер при «Заказать замер» — радио-выбор:
  ○ Конкретная дата       (открывает date + утром/днём/вечером)
  ○ Эта неделя
  ○ Следующая неделя
  ● Согласовать с клиентом (default)
  + поле «Уточнение по времени» (свободный текст)

Замерщик в инбоксе:
  - Если scheduled_at заполнено → 📅 точная дата
  - Иначе → 🕐 приблизительная (эта неделя / след. неделя / 15.05 утром)
  + Note выводится после ·
  - В DM-уведомлении строка «Когда: …» подсказывает что согласовать

Замерщик в карточке заявки:
  - Если нет точной даты — отдельный блок « Когда удобно клиенту»
    с подсказкой «позвоните клиенту и согласуйте точную дату»
  - После назначения через datetime-input → блок исчезает

Backend: 4 новые колонки preferred_type / preferred_date /
preferred_time_of_day / preferred_note, добавлены в schema,
serialize/deserialize в request + detail + inbox.

Cache bust v=20260513u.
2026-05-13 16:21:09 +03:00
wasrusgen
e37a5e723f slogan: убран с role-chooser, остался только на splash
Внутри кабинета и функциональных экранов слоган не нужен —
там акцент на действиях. Слоган живёт только на splash,
как бренд-приветствие при загрузке.

Cache bust v=20260513t.
2026-05-13 11:32:22 +03:00
wasrusgen
d8cb36703f slogan: переход с Caveat на Cormorant Garamond Italic (вариант 8)
Сдержанный serif-италик, не контрастирует с Editorial Calm стилем.
Убран наклон -2°, шрифт элегантный сам по себе.

Размеры:
- splash subtitle: 22pt (Caveat был 26pt — serif читается крупнее)
- role chooser: 28pt (Caveat был 34pt)

Loaded Cormorant Garamond italic from Google Fonts.
Cache bust v=20260513r.
2026-05-13 10:41:59 +03:00
wasrusgen
7f01c1e595 role-chooser: «Сделано с душой!» каллиграфическим Caveat
Заменили kicker «ЗОВ — кухня и техника» (моно-uppercase) на
рукописный tagline «Сделано с душой!» — Caveat 34pt walnut,
лёгкий поворот -2°.

Cache bust v=20260513p.
2026-05-13 10:23:44 +03:00
wasrusgen
b352c4927f universal entry: bot menu button + role chooser в MiniApp
Перешли на единый универсальный паттерн вместо reply/inline-keyboard:

1. Bot menu-button — постоянная кнопка «ЗОВ» слева от input в чате
   (set_chat_menu_button с WebAppInfo). Видна на ВСЕХ платформах:
   Telegram Desktop, iOS, Android, Web. Один тап — открывает MiniApp.

2. MiniApp без ?role= в URL показывает role chooser как первый экран:
   три большие карточки [Я менеджер] [Я клиент] [Я сотрудник].
   Тап → URL получает ?role=X → re-run init() → загрузка кабинета
   с правильно подписанным initData.

Решение универсальное — не зависит от reply/inline-кнопок и их
поведения с initData на разных клиентах Telegram.

Cache bust v=20260513n.
2026-05-13 07:36:55 +03:00
wasrusgen
a437b55447 measurements: auto-suggest № замера, активные галочки чек-листа, убрана стяжка
1. № замера подбирается автоматически:
   - POST /api/measurement_next_no возвращает max(zamer_no) + 1
   - Wizard при открытии вызывает endpoint и заполняет input
   - Менеджер может переписать вручную (поле редактируемое)
   - Подпись «Подобран автоматически — можно изменить»

2. Поле «Стяжка / нулевой пол» удалено из формы:
   - По логике пользователя — стяжка пишется на самих фото с замером
   - Backend колонка floor_base остаётся для backward compat (старые записи)

3. Чек-лист стал интерактивным:
   - Каждый [ ] item теперь .cl-item с cursor:pointer
   - Тап переключает галочку (☐ ↔ ☑) + страйкаут текста
   - Состояние сохраняется в localStorage по measurement_id (или draft)
   - Sticky прогресс-бар сверху: «N из M · X%» + градиентная полоса
   - Кнопка ↺ в шапке — сбросить все галочки
   - Hapt-фидбэк на каждый тап

Cache bust v=20260513m.
2026-05-13 07:29:18 +03:00
wasrusgen
121927ab2d measurements: структура фото + чек-лист + общая инфа
По чек-листу ЗАМЕРОВ (D:\!!! GOOGLE DISK\ЗАМЕРЫ\...\ЧЕКЛИСТ_ЗАМЕРА.md):
каждая стена снимается отдельно, имя файла отражает тип.

Wizard:
- Каждое фото получает dropdown «Что это»:
  Стена 1, 2, 3, 4 · План комнаты · Общий вид · Деталь
- Авто-предложение типа: w1 → w2 → w3 → w4 → plan → general
- Добавлены поля общей инфы:
  · № замера (опционально)
  · Дата замера (auto-сегодня)
  · Стяжка / нулевой пол (default «0,000 = +88 мм над плитой»)
- В шапке кнопка 📋 — открывает чек-лист отдельной страницей
- Inline-рендер markdown с поддержкой заголовков, списков, таблиц, code

Backend:
- _save_measurement_photo принимает kind+kind_seq → имена файлов
  структурные: w1.jpg, w2.jpg, plan.jpg, general_2.jpg, detail_1.jpg.
  Это упрощает дальнейшую обработку для генерации DWG.
- Расширена схема Measurements: zamer_no, zamer_date, floor_base, photos_meta.
- /api/measurement_detail отдаёт новые поля.

Cache bust v=20260513l.
2026-05-13 07:19:25 +03:00
wasrusgen
d859e9791c roles: multi-role foundation (manager / client / measurer / assembler)
Users.role теперь хранит CSV-список ролей: 'manager,measurer'.
Парсим, добавляем, отзываем — все через sheets.parse_roles / grant_role /
revoke_role / list_users_with_role. Старые однострочные значения работают
как раньше (legacy compat).

Backend:
- /api/me возвращает roles[] (массив), role (главная для legacy-UI),
  plus capabilities {measurer, assembler} для staff
- /api/grant_role (admin-only) — добавить/отозвать роль
- /api/staff_list (manager-only) — список сотрудников по роли
  (будет использоваться в dropdown «выбрать замерщика»)
- При role=staff отдаём отдельный кабинет; если у юзера нет measurer/
  assembler — возвращаем error=no_staff_role

Bot:
- /start — 3-я reply-кнопка [🔧 Я сотрудник]. При тапе MiniApp получает
  ?role=staff и решает кабинет по capabilities.
- /whoami — сотрудник присылает свой Telegram ID, пересылает куратору
  чтобы тот выдал роль через /api/grant_role.

MiniApp:
- renderStaff() — заглушка кабинета сотрудника с шапкой (имя, аватар,
  список ролей) и пустым inbox («Пока пусто»). Если есть measurer —
  быстрая кнопка «Сделать новый замер».
- При error=no_staff_role — экран с инструкцией как получить роль.
- CSS .staff-head / .staff-no-role.

Cache bust v=20260513f.
2026-05-12 19:14:39 +03:00
wasrusgen
a084542bbf measurements: photo upload + measurement detail page + PDF/print
Wizard: new 'photos' step (6 total) — camera/gallery input, client-side
canvas compression to 1600px @ ~78% JPEG, max 12 photos. Thumbnails
with delete in step; preview in summary.

Backend: POST /api/measurement now decodes data-URL photos and saves
to /app/photos/<id>/N.jpg (volume-mounted). New GET /api/photo/{id}/{n}
serves files with path-traversal protection. New POST /api/measurement_detail
returns full measurement record (walls/openings/photos/notes/...).

Clients page: measurement rows now clickable → renderMeasurement detail
view with key-value grid + photo gallery + 'Скачать PDF / Печать'.
Print stylesheet (@media print) hides navigation/buttons/uploaders and
prints clean A4-friendly layout.

Podbor report: existing 'Печать → PDF' now falls back to inline
window.print() inside Telegram WebApp (popups are blocked there).

Cache bust v=20260513a.
2026-05-12 18:11:29 +03:00
wasrusgen
c4f3016b56 miniapp: client profile tab — list + history + lead detail
NEW FILE assets/clients.js:
- Clients.mount(container) — hash-routed view
  - #/clients              — list of all clients (cards: avatar, name, phone, leads count, last date)
  - #/clients/client/<key> — single client history (all leads as items)
  - #/clients/lead/<id>    — full lead detail with re-rendered report

UI:
- Card style: avatar with initial, name + phone, footer with N подборов + дата
- Pluralization for Russian (1 подбор / 2 подбора / 5 подборов)
- Date format: 'сегодня · 14:30' or 'DD.MM.YYYY'
- Status pills: new / sent / viewed / ordered

PODBOR.JS:
- Exposed renderSavedReport(ai, leadId) for Clients module reuse
- Same renderer as live podbor — same matrix, pros/cons, links

APP.JS:
- Quick action 'Клиенты' added (icon: user)
- Hash router: #/clients → Clients.mount()

INDEX.HTML:
- clients.js script added
- Cache bumped to v=20260512a

CSS:
- .client-list, .client-card with avatar+meta+footer
- .client-detail-head (big card with avatar 56px)
- .leads-list with .lead-item (grid: date | id | status | arrow)
- .loader-inline for async fetch
- .ai-text-fallback for legacy text-only responses
2026-05-12 07:20:54 +03:00
wasrusgen
cecb8d3444 review screen: fix text wrap + cleanup stale answers from removed steps
CSS:
- .rev-val: flex:1, min-width:0, overflow-wrap:break-word — длинные значения
  больше не ломаются мид-словом ('энергоэффективнос·...')
- .rev-label: max-width:40% — лейбл не съедает всё место
- hyphens:auto для перенос длинных слов на дефис

JS (getCatState):
- При загрузке per_cat фильтруем answers — оставляем только ключи которые
  есть в текущем config.steps
- Это убирает stale-поля типа 'class' у ПММ, оставшиеся в localStorage
  после рефакторинга шагов
- Безопасно: меняет только в памяти, не перезаписывает state (renderReview
  всё равно итерирует config.steps)
2026-05-11 23:25:23 +03:00
wasrusgen
ef500fa446 user feedback batch: model count, specs, manual link, dimensions, export
1. MODEL COUNT SELECTOR (strategy step):
   - new PODBOR_MODEL_COUNTS [3/5/7]
   - state.model_count default '5'
   - UI on strategy page with description (быстро/оптимально/максимум)

2. AI PROMPT EXPANDED:
   - new field: manual_search_query — for Google search instruction PDF
   - new specs object per model: dimensions_mm/volume_l/weight_kg/noise_db/energy_class/color
   - 'specs ОБЯЗАТЕЛЬНЫ для проектирования кухни' explicit rule
   - reads checklist.model_count to determine how many models per category
   - max_tokens 4000 → 8000 (room for richer responses)

3. MODEL CARD RICHER:
   - _renderSpecsBlock — characteristics in 2-col grid, dimensions highlighted
   - _renderUtilityLinks — Google search buttons for инструкция (PDF) + Схема установки
   - Specs critical for ZOV kitchen design (manager needs to verify niche fits)

4. EXPORT BUTTONS:
   - 'Скачать HTML' — generates standalone HTML with inline styles, downloads as file
   - 'Печать → PDF' — opens new window with cleaned layout + auto-prints
   - User can save as PDF via system print dialog

5. PREVIEW updated with realistic specs/manual_query for all 3 fridges
2026-05-11 17:11:30 +03:00
wasrusgen
5ceffa4f69 miniapp: phone validation on intro — blocks transition with bad number
- New isValidPhone(raw): checks 11-digit Russian after normalization (8/7/+7/9-prefix)
- Intro 'Начать' button now custom click handler instead of data-go
- Validates name (non-empty) and phone (Russian format)
- Inline .field-error red message under invalid field
- .field-hint shows format help under phone input
- Haptic 'warning' feedback on invalid submit
- Phone is auto-normalized to '+7 900 123-45-67' before transition
2026-05-11 16:48:52 +03:00
wasrusgen
d7be644aed miniapp: price comparison matrix as PRIMARY view per category
WHAT CHANGED:
- New _renderPriceMatrix(models) — table with rows=models, columns=stores
- Inserted as PRIMARY view above model cards (was secondary accordion)
- Columns dynamically include only stores that returned data
- Sticky model column (left) — scrolls horizontally on mobile
- Best price per row highlighted: green bg + ✓ badge + green text
- Empty cells: '—' if no URL, 'смотреть →' if URL but no price yet
- 'Мин' column on far right — explicit cheapest price summary

CSS:
- .report-matrix-wrap with rounded card
- Sticky col-model with box-shadow on right edge
- Cell-price.best with rgba green background
- .best-mark circle badge

PREVIEW:
- Updated mock with 3 fridges + 3 hobs across multiple stores (real pricing spread)
- Demonstrates min-price highlighting working

UX:
- User can now visually compare 'where is it cheapest' at a glance
- Tap any cell with price → opens store page
- Tap empty cell with URL → opens search in store

NEXT: same matrix can become PDF/Excel export for client briefcase
2026-05-11 14:56:41 +03:00
wasrusgen
ca342c0641 ai+report: deeper analysis — required pros/cons, category insights, source visibility
AI PROMPT (ai.py):
- Requires minimum 3 pros + 2 cons per model with NUMBERS (36 dB, 463 L, A++, не 'тихий/большой')
- New field 'reasoning' — 1-sentence why-this-model justification
- New per-category 'analysis' — 2-3 sentences about trade-offs
- Strict rules: no fake article numbers, account for parallel-import price markup
- Russian market 2026 awareness: Haier/Korting up, Bosch/Siemens ⚠

TELEGRAM FORMAT (main.py):
- Renders category analysis as italic prelude
- Lists pros/cons as bullet lists (up to 4 pros, 3 cons)
- Shows '🛒 Нашли в: OZON · Citilink · WB' line listing successful sources
- Rating + reviews + stores count line: '📊 ★ 4.7 · 1242 отзыв. · 12 магаз.'
- Direct link to best store: '🔗 Открыть в магазине'

WB PARSER:
- Generates 3 query variants per request: full → brand+model → model only
- Increases hit rate when AI search_query is too verbose
- First non-empty variant wins

MINIAPP REPORT (podbor.js + podbor.css):
- Category analysis block above models (italic, walnut left-border)
- Pros block: green tinted bg, bullet list, header 'Плюсы'
- Cons block: terracotta tinted bg, bullet list, header 'Минусы'
- Reasoning chip: 💡 italic in warm background
- Source badges with per-store price '<store> · 89 990 ₽'
- Color-coded source links: OZON blue, Citilink yellow, WB pink, Я.Маркет red, DNS orange
- 'X магазинов нашли товар' header + plural fix
- '— не найден' fallback if 0 sources

PREVIEW (preview-report.html):
- Mock updated with Haier as flagship (more relevant for 2026 RF)
- Shows analysis, reasoning, source spread (4 stores with different prices)
2026-05-11 14:34:08 +03:00
wasrusgen
c2be5e846f miniapp: inline report after submit + standalone preview-report.html
REPORT RENDERER (podbor.js):
- New renderReport(ai, leadId) function — beautiful inline report after submit success
- Shows by_category with up to 5 models per category
- Model card: photo (88x88), brand · name, price range, rating + reviews + stores
- Highlights (with tech translations), pros (green), cons (orange)
- External links to WB / Я.Маркет / OZON / DNS (when enriched data present)
- Comparison table per category (accordion details)
- Total price block (dark theme contrast)
- Warnings block (when AI returns concerns)

CSS (podbor.css):
- .report-* classes: head, summary, cat, model, links, compare, total, warnings
- Editorial Calm palette — walnut accents, paper bg, Newsreader for titles
- Responsive: model card grid 88px image + 1fr body
- Placeholder gradient when no image (camera emoji)

STANDALONE PREVIEW (preview-report.html):
- Mock AI response with 3 fridges + 2 hobs
- Same render logic, runs without backend
- Visit: https://wasrusgen.github.io/zov-tech/preview-report.html

NEXT: integrate proxy6 token → real photos/prices instead of placeholders
2026-05-11 12:26:58 +03:00
wasrusgen
dd400b71ac miniapp: new pricing flow — brand strategy + budget presets + multi pick strategy
NEW STRUCTURE:
- Step 4 'Бренд' — ai/single/different + brand picker or per-cat chips (now 4-state with 'avoid')
- Step 5 'Бюджет' — Люкс/Премиум/Средний/Бюджет/Точные цифры presets
- Step 6 'Стратегия' — multi: Лучшее по отзывам / Цена-качество / Топ-бренды / Доступное / Tech / Стиль
- Step 7 'Инфра' — перенесено после стратегии
- Step 8 'Итог' — обновлённый summary с новыми полями

FIXES:
- Keyboard-disappearing bug in price inputs — removed render() on input, total recomputed locally
- localStorage merge with defaults for backward compat with new fields
- Bumped STORAGE_KEY to v4

REMAINING:
- Backend still reads checklist.priorities (old shape) — needs update to read pick_strategies + brand_strategy + budget_preset
2026-05-11 10:43:54 +03:00
wasrusgen
496ddf793c miniapp: persistent category strip with active highlight + tap-to-jump
- Visible on all steps after categories are selected
- Highlights current category when inside its wizard
- Filled categories show checkmark
- Tap chip jumps directly to that category's wizard
- Horizontal scroll if many categories don't fit
2026-05-11 00:46:43 +03:00
wasrusgen
d289f7601e miniapp: compact pin layout for wizard steps without pictograms
- Steps with pict (1-3 fridge: install/chamber/size) keep grid cards
- Steps without pict (4 features) render as flex-wrap pill pins
- Auto-detect via options.some(o => o.pict)
2026-05-11 00:02:25 +03:00
wasrusgen
17b112f061 miniapp: hierarchical wizard for fridge category (style D pictograms)
- New PODBOR_PARAMS schema with steps[] supporting single/multi + optionsBy branches
- 11 fridge SVG pictograms in podbor.picts.js (style D — 3D perspective with shadow)
- renderCategoryWizard with step-by-step flow, chips for prior answers, review screen
- Legacy renderCategoryDetail still used for other 7 categories until migrated
- Auto-advance on single-select, Дальше button for multi-select
- Backend-compatible: per_cat[catKey].answers replaces .params/.features
2026-05-10 23:57:03 +03:00
wasrusgen
cc28984122 feat(podbor iter2): per-category detail menu with primary params + accordion 'Подробнее' for tech features; updated AI prompt to require feature explanations 2026-05-09 15:21:05 +03:00
wasrusgen
129046de07 feat(podbor): drop niches; price-range from-to per cat; ventilation Y/N; priorities multi-select; brand tiers as color (no labels) 2026-05-09 15:10:23 +03:00
wasrusgen
571297c017 fix(podbor): niche inputs overflow — min-width:0 + shorter placeholders 2026-05-09 13:43:17 +03:00
wasrusgen
d1165d5e4f feat(miniapp): «Подбор техники» screen — 7-step picker (categories/niches/budget/infra/scenario/brands/summary) wired to /api/podbor 2026-05-09 13:34:46 +03:00