diff --git a/README.md b/README.md index 468cb1c..ce29c51 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ RF4DB/RF4-STAT/RF4MAP/RF4 Posts сначала принимаются в изо Базовый SEO-контур готов для `rf4spotter.ru`: страницы имеют уникальные метаданные, canonical, Open Graph/Twitter Card, фирменное изображение 1200×630 и JSON-LD; доступны динамические `/robots.txt` и `/sitemap.xml`, административные и ошибочные страницы закрыты от индексации, добавлена собственная страница 404. Индексируемые каталоги рыб и водоёмов, detail-страницы и сочетания водоём + рыба строятся из актуального разрешённого справочника и включаются в sitemap. Подключены фирменные favicon/app icons, web manifest и production-кэширование статических ресурсов. Карточки активности показывают единый паспорт данных: источники, свежесть, полноту и уровень доверия. На `/status` опубликована легенда цветов всех источников и статусов качества. -Публичные точки используют постоянные читаемые адреса вида `/spots/kuori-85x92`; старые UUID-адреса остаются совместимыми и перенаправляются на канонический URL. На странице точки координаты дополнительно показаны фирменным радаром, который не имитирует отсутствующую географию водоёма, а уловы за 72 часа — шкалой-леской с 12-часовым шагом. Карточки активности и каталог дополнены лёгкими SVG-силуэтами рыб без внешних графических зависимостей. Пустые и аварийные состояния используют собственную CSS-иллюстрацию поплавка; анимация учитывает системное ограничение движения. +Публичные точки используют постоянные читаемые адреса вида `/spots/kuori-85x92`; старые UUID-адреса остаются совместимыми и перенаправляются на канонический URL. На странице точки координаты дополнительно показаны фирменным радаром, который не имитирует отсутствующую географию водоёма, а уловы за 72 часа — шкалой-леской с 12-часовым шагом. Каждый улов показывает источник, относительную свежесть и точную дату в подсказке. Карточки активности и каталог дополнены лёгкими SVG-силуэтами рыб без внешних графических зависимостей. Пустые и аварийные состояния используют собственную CSS-иллюстрацию поплавка; анимация учитывает системное ограничение движения. Все пять community-парсеров подключены к отдельному scheduler-процессу. Состояние запусков и ошибок хранится в PostgreSQL, параллельный запуск одного источника блокируется, минимальный интервал жёстко ограничен 1800 секундами. Локально процесс включается профилем `docker compose --profile scheduler up -d`; detail-URL RF4MAP/RF4 Posts задаются переменными окружения. diff --git a/apps/web/src/components/CatchList.astro b/apps/web/src/components/CatchList.astro new file mode 100644 index 0000000..3203a8d --- /dev/null +++ b/apps/web/src/components/CatchList.astro @@ -0,0 +1,17 @@ +--- +import SourceBadge from "./SourceBadge.astro"; +import { ago, kg, type Catch } from "../lib/api"; +const { catches } = Astro.props as { catches: Catch[] }; +--- +
+ {catches.map(item => { + const timestamp = item.caught_at ?? item.reported_at; + return
+
{item.fish}{item.bait ?? "Приманка не указана"}
+
{kg(item.weight_g)}{item.player_name ?? "Анонимно"}
+
; + })} +
+ diff --git a/apps/web/src/pages/spots/[id].astro b/apps/web/src/pages/spots/[id].astro index 9f458dc..db45f7e 100644 --- a/apps/web/src/pages/spots/[id].astro +++ b/apps/web/src/pages/spots/[id].astro @@ -3,7 +3,8 @@ import Layout from "../../layouts/Layout.astro"; import SourceBadge from "../../components/SourceBadge.astro"; import CoordinateRadar from "../../components/CoordinateRadar.astro"; import ActivityTimeline from "../../components/ActivityTimeline.astro"; -import { activityLevel, api, kg, plural, type Activity, type Catch, type Spot } from "../../lib/api"; +import CatchList from "../../components/CatchList.astro"; +import { activityLevel, api, plural, type Activity, type Catch, type Spot } from "../../lib/api"; const { id } = Astro.params; let spot: Spot | null = null, catches: Catch[] = [], activity: Activity | null = null, unavailable = false; try { @@ -28,6 +29,12 @@ const breadcrumbs = spot ? { "@context": "https://schema.org", "@type": "Breadcr
{spot.waterbody}

Точка {spot.x}:{spot.y}

{spot.description}

{spot.catches_24h}за 24 часа
{spot.catches_3d}за 3 дня
{spot.catches_7d}за 7 дней
-

Последние уловы

{catches.length ?
{catches.map(item =>
{item.fish}{item.bait ?? "Приманка не указана"}
{kg(item.weight_g)}{item.player_name ?? "Анонимно"}
)}
:

Уловов пока нет

Для этой точки нет одобренных наблюдений.

}
+
+
+

Последние уловы

+ {catches.length ? :

Уловов пока нет

Для этой точки нет одобренных наблюдений.

} +
+ +
} diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 8b3cad9..0d5c66d 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -124,6 +124,7 @@ ### Графические элементы и объяснение данных - [x] Не показывать дублирующий sidebar лидера при единственной найденной точке (7 сентября 2026). +- [x] Показывать у каждого улова на detail-странице источник, относительную свежесть и точную дату в подсказке (7 сентября 2026). - [x] Подготовить фирменный знак «крючок + поплавок + координатная сетка» и согласованный набор favicon/app icons (7 сентября 2026). - [x] Добавить честный координатный радар без имитации отсутствующей карты на страницу точки (7 сентября 2026). - [x] Добавить временную шкалу активности 72 часа с 12-часовым шагом в виде лески с поплавками (7 сентября 2026). diff --git a/docs/UI_UX_AUDIT.md b/docs/UI_UX_AUDIT.md index 7600ad3..4f90211 100644 --- a/docs/UI_UX_AUDIT.md +++ b/docs/UI_UX_AUDIT.md @@ -74,7 +74,7 @@ - [x] Заменить slug-input фильтрами из справочников и добавить сброс. - [x] Сделать мобильную выдачу рекордов самодостаточной с подписями значений. - [x] Убрать CLI-команду из публичного empty state. -- [ ] Добавить к уловам detail-страницы дату/свежесть и происхождение, если API их отдаёт. +- [x] Добавить к уловам detail-страницы семантическую дату, относительную свежесть и происхождение (7 сентября 2026). - [x] Устранить дублирование карточки и sidebar на малой выборке: блок лидера показывается только при двух и более результатах (7 сентября 2026). Критерий: фильтрация не требует технических терминов; каждая мобильная запись читается без заголовка таблицы; источник и свежесть понятны.