30 lines
3.5 KiB
Plaintext
30 lines
3.5 KiB
Plaintext
---
|
|
import ActivityCard from "../../components/ActivityCard.astro";
|
|
import AtlasBreadcrumbs from "../../components/AtlasBreadcrumbs.astro";
|
|
import AtlasEntityLink from "../../components/AtlasEntityLink.astro";
|
|
import PageHero from "../../components/PageHero.astro";
|
|
import StatePanel from "../../components/StatePanel.astro";
|
|
import Layout from "../../layouts/Layout.astro";
|
|
import { api, plural, type Activity, type DictionaryItem, type PaginatedActivity } from "../../lib/api";
|
|
const { slug } = Astro.params;
|
|
let water: DictionaryItem | undefined, items: Activity[] = [], unavailable = false;
|
|
try {
|
|
const waters = await api<DictionaryItem[]>("/api/v1/waterbodies?limit=500");
|
|
water = waters.find(item => item.slug === slug);
|
|
if (water) { const paginated = await api<PaginatedActivity>(`/api/v1/activity?hours=72&waterbody=${encodeURIComponent(water.slug)}&limit=100`); items = paginated.items; }
|
|
} catch { unavailable = true; }
|
|
if (unavailable) {
|
|
Astro.response.status = 503;
|
|
Astro.response.headers.set("Retry-After", "60");
|
|
Astro.response.headers.set("Cache-Control", "no-store");
|
|
}
|
|
if (!water && !unavailable) Astro.response.status = 404;
|
|
const fishes = [...new Map(items.map(item => [item.fish_slug, item.fish])).entries()];
|
|
const schema = water ? { "@context":"https://schema.org", "@type":"CollectionPage", name:`Что ловить на ${water.name_ru} в RF4`, url:`https://rf4spotter.ru/waterbodies/${water.slug}` } : null;
|
|
---
|
|
<Layout title={water ? `${water.name_ru} в RF4 — рыба и свежие точки` : "Водоём не найден — RF4 Spotter"} description={water ? `${water.name_ru} в Russian Fishing 4: свежие координаты, активные виды рыб, приманки и источники наблюдений.` : "Такого водоёма нет в каталоге RF4 Spotter."} noindex={!water || unavailable} structuredData={schema} errorPage={!water || unavailable}>
|
|
<AtlasBreadcrumbs items={[{ label: "Водоёмы", href: "/waterbodies" }, { label: water?.name_ru ?? "Не найдено" }]} />
|
|
<PageHero eyebrow="Свежие данные за 72 часа" title={water?.name_ru ?? "Водоём не найден"} description={water ? `${items.length} ${plural(items.length,["активная точка","активные точки","активных точек"])} для ${fishes.length} ${plural(fishes.length,["вида рыбы","видов рыб","видов рыб"])}.` : undefined} variant={water ? "water" : undefined} identity={water?.slug} />
|
|
{unavailable ? <StatePanel tone="unavailable" title="Данные временно недоступны" description="Каталог сохранён, но свежие наблюдения сейчас не получены." /> : !water ? <StatePanel tone="error" title="Такого водоёма нет в справочнике" actionHref="/waterbodies" actionLabel="Открыть каталог" /> : <section class="catalog-results content-grid"><aside><span class="overline">Рыбы</span>{fishes.length ? <nav>{fishes.map(([fishSlug,name]) => <AtlasEntityLink href={`/waterbodies/${water!.slug}/${fishSlug}`} label={name} kind="fish" identity={name} />)}</nav> : <p>Свежих подтверждённых видов пока нет.</p>}</aside><div>{items.length ? items.map(item => <ActivityCard item={item}/>) : <StatePanel contained={false} title="Свежих точек пока нет" description="Проверьте позже или посмотрите полевые сигналы на главной." />}</div></section>}
|
|
</Layout>
|