Раньше textarea для заметок жил в самом низу страницы, после фото-сетки
и списка меток — на плановом осмотре приходилось много скроллить чтобы
добраться до основного поля ввода.
Перенёс Card 'Заметки механика' сразу под Card 'Схема'. На плановом осмотре
текстовое поле теперь второе на странице — не надо листать.
Раньше textarea для заметок жил только в InspectionReview (завершённый
осмотр). При создании нового планового осмотра (через '/inspections/<id>/edit')
поля ввода не было — приходилось завершить осмотр, потом открыть карточку
и только там вводить.
Теперь блок есть в обеих страницах:
- InspectionEditor (in_progress): textarea + кнопки Сохранить/Отменить
- InspectionEditor (completed): read-only вывод текста
- InspectionReview: оставлен прежний редактор как был
Бонус: при нажатии «Завершить осмотр» текущий draft заметки коммитится
тем же PATCH вместе со status=completed — не теряется если механик
ввёл текст и сразу нажал завершение, не сохранив отдельно.
VehicleSummary.status (cars_v2.element_status) рендерится как цветной
pill справа от гос.номера. Палитра по семантике:
emerald — На линии (норма)
amber — Ремонтируется / Ждет ремонта
red — ДТП
blue — Бронь / Выкуп / На продаже / Подготовка на продажу / Ждет
доставки до офиса (admin-операции)
muted — Простой и неизвестные статусы
Чип появляется в Home (списке машин) и в шапке VehicleCard. Backend
сторона — PremiumCRM 92d4317.
TtStateSummary.driver_id + driver_name добавлены в TS-тип. В строке
каждого Element-state'а под датой/пробегом теперь выводится '👤 ФИО'
если backend подтянул водителя. Логика идентична нашим осмотрам — общий
helper drivers_at_dates на backend (см. PremiumCRM aa55431).
Под датой/пробегом каждого осмотра добавлена строка «👤 ФИО» если backend
вернул driver_name (рассчитан как rental, активный на момент started_at —
см. PremiumCRM 4700314). Раньше механик/менеджер не мог быстро понять, у
кого мы принимали машину — приходилось открывать VDS-карточку.
InspectionSummary.driver_id + driver_name добавлены в TS-тип.
1. Сверху на /inspections/<id> добавлена кликабельная карточка машины:
гос.номер крупно + марка/модель/год + VIN. Использует новое поле
ins.vehicle, которое backend теперь возвращает в InspectionDetail
(см. PremiumCRM коммит a9c94d0). Клик ведёт на /vehicles/<id>.
2. Блок «Заметки механика» — textarea с локальным draft'ом и кнопкой
«Сохранить» (видна только если draft отличается от ins.notes). Под
капотом — PATCH /api/v1/mechanic/inspections/<id> с {notes}.
TG-импортированные осмотры из «Подготовка авто» уже приезжают с
заполненными notes (caption сообщения становится телом заметки), и
теперь механик может дополнить/исправить их прямо в карточке.
3. Бонус: добавлен показ пробега (mileage) в первой info-карте.
Counter «Фото (N)» по-прежнему учитывает TT carry-over (поэтому на 84-м
осмотре всё ещё 16), но карточки в гриде остаются только для наших MinIO-
фото + PWA-маркерных фото. TT-thumbnail рисуется один раз — inline под
своим маркером в списке.
1. Photo counter теперь учитывает уникальные tt_image_id из markers, не только
ins.photos + photo_id. На осмотрах, где почти все маркеры пришли из Element
carry-over, счётчик показывал 1 вместо 15+ — теперь корректно.
2. В галерее «Фото» добавлена секция карточек для TT-image carry-over (label
«из Element»). Картинки тянутся через ttImageUrl(hash), кликабельны.
3. Lightbox state поменялся с `number | null` на дискриминированный union
{ kind: 'photo', id } | { kind: 'tt', ttId }. Полноразмерное превью
выбирает между AuthImg (наши MinIO-фото) и обычным <img> (Element).
4. Превью маркеров в секции «Метки» теперь кликабельны (раньше только грид
с основными фото открывал lightbox). Работает и для photo_id, и для
tt_image_id маркеров.
Backend-зависимость: MarkerOut.tt_image_id (Pydantic) и
MechanicDamageMarker.tt_image_id (ORM) добавлены в PremiumCRM коммитом
d405e17 на crm.pptaxi.ru — без них фронт получает tt_image_id=undefined.
Single-screen grid layout showing all 5 PNG views + 4 bumper corner sun-zones + decorative
wheels at once. Tap any view for precise AddMarkerDialog; tap bumper corners for center-point
marker; global Tire Wear button opens new TireWearDialog (4-level radio cards).
Deletes MultiViewVehicleScheme. No backend changes. humanizeMarkerSide covers bumper-* and tires.
Co-Authored-By: claude-flow <ruv@ruv.net>
- Replace SVG sedan zone-click model with 5-view PNG scheme (top/front/back/left/right)
- New MultiViewVehicleScheme: tab selector, tap-to-exact-coord marker placement,
touchAction:manipulation prevents iOS double-tap zoom, marker dots at normalized x/y
- New AddMarkerDialog: bottom-sheet modal with damage_type (16 opts), severity (4 opts),
description, optional CameraCapture → uploadPhoto(side="free") → photo_id on submit
- InspectionEditor: removes addZoneMarker mutation and zone-count machinery; wires
pendingTap state → dialog open/close → query invalidation
- InspectionReview: adds read-only MultiViewVehicleScheme; both pages show photo_id
thumbnails via AuthImg in the marker list
- humanizeMarkerSide updated for new view names; keeps zone-* legacy mapping
- Deletes VehicleScheme.tsx and sedan-top.svg (no remaining imports)
- No backend changes, no new dependencies
Co-Authored-By: claude-flow <ruv@ruv.net>
Wire frontend to backend 2FA contract: two-step state machine in Login.tsx
(credentials → totp), new login2fa() call to POST /api/auth/2fa, credentials:include
on both fetches so the 30-day trusted_device cookie travels correctly.
Co-Authored-By: claude-flow <ruv@ruv.net>
- api/auth.ts: OAuth2 password flow via form-urlencoded POST /api/auth/login (not mechanic prefix)
- api/me.ts: GET /api/v1/mechanic/me with Me interface
- api/vehicles.ts: listVehicles (unwraps {items:[]}), getVehicle with VehicleDetail + InspectionSummary
- api/inspections.ts: createInspection returning full InspectionDetail; 9-value InspectionType union
- Login.tsx: full form with Логин/Пароль labels, useMutation, toast feedback, navigate on success
- Home.tsx: vehicle list with search, /me header with user name, logout, TanStack Query
- VehicleCard.tsx: vehicle info card, all 9 inspection type buttons (ru labels), history list
Co-Authored-By: claude-flow <ruv@ruv.net>