fix: R02 activity API contract — PaginatedActivity + all consumers (#1788956171115)

This commit is contained in:
ik
2026-09-09 20:58:42 +07:00
parent a37f9c4696
commit d962ba2f90
9 changed files with 85 additions and 45 deletions
+2 -2
View File
@@ -1,13 +1,13 @@
---
import ActivityCard from "../../components/ActivityCard.astro";
import Layout from "../../layouts/Layout.astro";
import { api, plural, type Activity, type DictionaryItem } from "../../lib/api";
import { api, plural, type Activity, type DictionaryItem, type PaginatedActivity } from "../../lib/api";
const { slug } = Astro.params;
let fish: DictionaryItem | undefined, items: Activity[] = [], unavailable = false;
try {
const fishes = await api<DictionaryItem[]>("/api/v1/fishes?limit=500");
fish = fishes.find(item => item.slug === slug);
if (fish) items = await api<Activity[]>(`/api/v1/activity?hours=72&fish=${encodeURIComponent(fish.slug)}&limit=100`);
if (fish) { const paginated = await api<PaginatedActivity>(`/api/v1/activity?hours=72&fish=${encodeURIComponent(fish.slug)}&limit=100`); items = paginated.items; }
} catch { unavailable = true; }
if (unavailable) {
Astro.response.status = 503;
+3 -3
View File
@@ -4,7 +4,7 @@ import SourceBadge from "../../components/SourceBadge.astro";
import CoordinateRadar from "../../components/CoordinateRadar.astro";
import ActivityTimeline from "../../components/ActivityTimeline.astro";
import CatchList from "../../components/CatchList.astro";
import { activityLevel, api, ApiError, plural, type Activity, type Catch, type Spot } from "../../lib/api";
import { activityLevel, api, ApiError, plural, type Activity, type Catch, type PaginatedActivity, type Spot } from "../../lib/api";
const { id } = Astro.params;
let spot: Spot | null = null, catches: Catch[] = [], activity: Activity | null = null, unavailable = false;
let timeline: { start: string; end: string; count: number }[] = [];
@@ -14,8 +14,8 @@ try {
? await api<Spot>(`/api/v1/spots/resolve?waterbody=${encodeURIComponent(readable[1])}&x=${readable[2]}&y=${readable[3]}`)
: await api<Spot>(`/api/v1/spots/${id}`);
if (!readable) return Astro.redirect(`/spots/${spotResult.waterbody_slug}-${spotResult.x}x${spotResult.y}`, 301);
const [catchResult, activityRows] = await Promise.all([api<Catch[]>(`/api/v1/spots/${spotResult.id}/catches`), api<Activity[]>(`/api/v1/activity?hours=24&waterbody=${encodeURIComponent(spotResult.waterbody_slug)}&limit=100`)]);
spot = spotResult; catches = catchResult; activity = activityRows.find(item => item.spot_id === spotResult.id) ?? null;
const [catchResult, activityPaginated] = await Promise.all([api<Catch[]>(`/api/v1/spots/${spotResult.id}/catches`), api<PaginatedActivity>(`/api/v1/activity?hours=24&waterbody=${encodeURIComponent(spotResult.waterbody_slug)}&limit=100`)]);
spot = spotResult; catches = catchResult; activity = activityPaginated.items.find(item => item.spot_id === spotResult.id) ?? null;
timeline = await api<typeof timeline>(`/api/v1/spots/${spotResult.id}/timeline`);
} catch (error) {
unavailable = true;
+2 -2
View File
@@ -1,13 +1,13 @@
---
import ActivityCard from "../../components/ActivityCard.astro";
import Layout from "../../layouts/Layout.astro";
import { api, plural, type Activity, type DictionaryItem } from "../../lib/api";
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) items = await api<Activity[]>(`/api/v1/activity?hours=72&waterbody=${encodeURIComponent(water.slug)}&limit=100`);
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;
@@ -1,13 +1,13 @@
---
import ActivityCard from "../../../components/ActivityCard.astro";
import Layout from "../../../layouts/Layout.astro";
import { api, plural, type Activity, type DictionaryItem } from "../../../lib/api";
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) items = await api<Activity[]>(`/api/v1/activity?hours=72&waterbody=${encodeURIComponent(water.slug)}&fish=${encodeURIComponent(fish.slug)}&limit=100`);
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;