From eeef4bb53648f2f10224e28c0b058a3c6299e765 Mon Sep 17 00:00:00 2001 From: IK Date: Mon, 21 Sep 2026 07:42:43 +0700 Subject: [PATCH] feat: show catch method on spot detail --- apps/api/tests/test_api.py | 4 ++++ apps/web/src/components/CatchList.astro | 3 ++- docs/ROADMAP.md | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/api/tests/test_api.py b/apps/api/tests/test_api.py index 2f701cd..6087e0d 100644 --- a/apps/api/tests/test_api.py +++ b/apps/api/tests/test_api.py @@ -270,6 +270,10 @@ def test_spot_detail_and_catches() -> None: assert len(catches.json()) == 3 assert catches.json()[0]["source_system"] == "manual-import" assert catches.json()[0]["fishing_method"] == "spinning" + fixture = client.get("/api/v1/spots/resolve?waterbody=test-lake&x=10&y=20") + assert fixture.status_code == 200 + fixture_catches = client.get(f"/api/v1/spots/{fixture.json()['id']}/catches") + assert fixture_catches.json()[0]["fishing_method"] == "spinning" resolved = client.get("/api/v1/spots/resolve?waterbody=test-lake&x=10&y=20") assert resolved.status_code == 200 assert resolved.json()["id"] == spot_id diff --git a/apps/web/src/components/CatchList.astro b/apps/web/src/components/CatchList.astro index 1359ac0..6c2bfe1 100644 --- a/apps/web/src/components/CatchList.astro +++ b/apps/web/src/components/CatchList.astro @@ -3,12 +3,13 @@ import SourceBadge from "./SourceBadge.astro"; import { ago, kg, type Catch } from "../lib/api"; import TackleGlyph from "./TackleGlyph.astro"; const { catches } = Astro.props as { catches: Catch[] }; +const methodLabels: Record = { spinning: "Спиннинг", bottom: "Донная", float: "Поплавочная" }; ---
{catches.map(item => { const timestamp = item.caught_at ?? item.reported_at; return
-
{item.fish}{item.bait ?? "Приманка не указана"}
+
{item.fish}{item.bait ?? "Приманка не указана"}{item.fishing_method && Метод: {methodLabels[item.fishing_method] ?? item.fishing_method}}{item.retrieve_method && Проводка: {item.retrieve_method}{item.retrieve_speed != null ? ` · скорость ${item.retrieve_speed}` : ""}}
{kg(item.weight_g)}{item.player_name ?? "Анонимно"}{item.caught_at ? "Время улова" : "Получено · время улова неизвестно"}
; })} diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 79d3fb7..988066b 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -97,7 +97,7 @@ - [ ] **U03 · Evidence/trust card.** Общий evidence-контракт используется на activity-карточках, detail точки, водоёма и карточках снастей: freshness с текстовым `Свежо`/`Устарело`, явный период расчёта, completeness, confidence/статус, source badges и доступные доменные поля; при выборке меньше 3 явно показано отдельное состояние `Недостаточно данных`, ограниченный источник не смешивается с неполными полями, а явно переданные provenance-конфликты видны текстом. Targeted E2E и API-тест проверяют публичные пути, период, 48-часовой порог и конфликт источников. - [ ] **U04 · List/map и progressive disclosure.** List остаётся честным базовым режимом: фильтры, сортировка, URL-состояние и evidence-карточки уже работают без имитации координатной карты. Следующий шаг — единый list/map-контракт после подтверждения геометрии; на mobile карта должна открываться отдельным действием. Вторичные raw/provenance-поля не исчезают и раскрываются по запросу. - [ ] **U05 · Mobile-first и сохранённый план рыбалки.** `/plan` поддерживает список до 5 локальных вариантов, удаление, очистку, переход к точке, print/PDF и восстановление из shareable URL; кнопка «Поделиться планом» использует native share или clipboard fallback. Detail-кнопка сохраняет данные с `aria-pressed` и восстанавливается после reload. Print/mobile-контракт проверяет 320/390 px, лимит импорта и отсутствие горизонтального overflow; карточка плана теперь сравнивает подтверждённые метод/проводку и явно показывает риск по выборке/уверенности. -- [ ] **U06 · Контентная и визуальная иерархия.** Для detail точки действие «Что взять» выделено отдельным заголовком, а provenance и качество собраны в общем паспорте данных; статусы дополнительно передаются текстом, малая выборка не маркируется как готовая рекомендация, а дублирующие catches/players/confidence убраны из вторичной колонки activity-карточки. Осталось провести ручной review на 5 ключевых маршрутах. +- [ ] **U06 · Контентная и визуальная иерархия.** Для detail точки действие «Что взять» выделено отдельным заголовком, provenance и качество собраны в общем паспорте данных, а подтверждённые метод/проводка видны рядом с последними уловами; статусы дополнительно передаются текстом, малая выборка не маркируется как готовая рекомендация, а дублирующие catches/players/confidence убраны из вторичной колонки activity-карточки. Осталось провести ручной review на 5 ключевых маршрутах. - [ ] **U07 · UX-приёмка и измерения.** Playwright-контракты уже покрывают query journey, сквозной task journey, evidence states, saved plan, share/print, accessibility и visual matrix; unit-контракт добавил детерминированные stale- и blocked-подписи, а insufficient-data теперь отделён от incomplete в публичном паспорте. `/status` явно сообщает, что при ограничении источника опубликованные данные сохранены. Осталось сохранить reference screenshots и получить production Lighthouse/CLS/INP/time-to-first-useful-answer после пилота. - [ ] **Q01 · Документы источников — реестр готов, нужны первичные подтверждения.** Создан единый production-gate с атрибуцией, общим лимитом 30 минут, хранением и процедурой отзыва для RF4DB, RF4-STAT, RF4MAP, RF4 Posts и официального RF4. До открытой публикации приложить устойчивые ссылки/копии первичных разрешений, контакты, даты и отдельно подтвердить право на изображения; пустое поле блокирует соответствующий источник.