Files
rf4-spotter/apps/web/src/pages/waterbodies/[slug]/[fish].astro
T
ik 2ad2bdcdff
CI / backend-and-migrations (push) Canceled after 0s
CI / astro-build (push) Canceled after 0s
CI / dependency-audit (push) Canceled after 0s
CI / compose-e2e (push) Canceled after 0s
fix: mark catalog outage pages as SEO errors
2026-09-11 07:49:58 +07:00

26 lines
3.0 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
import ActivityCard from "../../../components/ActivityCard.astro";
import Layout from "../../../layouts/Layout.astro";
import { api, plural, type Activity, type DictionaryItem, type PaginatedActivity } from "../../../lib/api";
const { slug, fish: fishSlug } = Astro.params;
let water: DictionaryItem | undefined, fish: DictionaryItem | undefined, items: Activity[] = [], unavailable = false;
try {
const [waters, fishes] = await Promise.all([api<DictionaryItem[]>("/api/v1/waterbodies?limit=500"), api<DictionaryItem[]>("/api/v1/fishes?limit=500")]);
water = waters.find(item => item.slug === slug); fish = fishes.find(item => item.slug === fishSlug);
if (water && fish) { const paginated = await api<PaginatedActivity>(`/api/v1/activity?hours=72&waterbody=${encodeURIComponent(water.slug)}&fish=${encodeURIComponent(fish.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 || !fish) && !unavailable) Astro.response.status = 404;
const valid = Boolean(water && fish);
const schema = valid ? { "@type":"CollectionPage", name:`${fish!.name_ru} на ${water!.name_ru} в RF4`, url:`https://rf4spotter.ru/waterbodies/${water!.slug}/${fish!.slug}` } : null;
---
<Layout title={valid ? `${fish!.name_ru} на ${water!.name_ru} в RF4 — точки и приманки` : "Страница не найдена — RF4 Spotter"} description={valid ? `Где ловить ${fish!.name_ru} на ${water!.name_ru} в Russian Fishing 4: свежие координаты, приманки, активность и источники.` : "Такого сочетания рыбы и водоёма нет в каталоге."} noindex={!valid || unavailable} structuredData={schema} errorPage={!valid || unavailable}>
<a class="back" href={water ? `/waterbodies/${water.slug}` : "/waterbodies"}>← К водоёму</a>
<section class="catalog-hero content-grid"><span class="overline">{water?.name_ru ?? "Каталог RF4"}</span><h1>{fish?.name_ru ?? "Данные не найдены"}</h1>{valid && <p>{items.length} {plural(items.length,["свежая точка","свежие точки","свежих точек"])} за последние 72 часа.</p>}</section>
{unavailable ? <div class="state content-grid"><h2>Данные временно недоступны</h2></div> : !valid ? <div class="state content-grid"><h2>Такого сочетания нет в справочнике</h2><a href="/">Вернуться на главную</a></div> : <section class="catalog-results catalog-results--single content-grid"><div>{items.length ? items.map(item => <ActivityCard item={item}/>) : <div class="state"><h2>Свежих точек пока нет</h2><p>Данные появятся после новых подтверждённых наблюдений.</p></div>}</div></section>}
</Layout>