mirror of
https://github.com/AmanTahiliani/box-box.git
synced 2026-08-08 04:06:18 -04:00
feat(#76): bound primary-route fetches and local-first driver summary
Add shared apiFetch timeouts/abort/typed errors with in-flight dedupe, a RouteState UI for loading/empty/timeout/error+retry, and wire it through Weekend (Data Health), Championship, Driver Profile, Briefing, Live, and Race Hub. Driver summary is local-first with bounded optional OpenF1 enrichment so a hung remote call cannot block the profile. Spike note: parseSourceMode defaults to openf1; driver summary now treats omitted ?source= as auto so local season data is preferred. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -24,6 +24,7 @@ import {
|
||||
} from '../lib/digest'
|
||||
import { stripHtml, timeAgo } from '../utils'
|
||||
import type { ArticleContent, NewsItem } from '../types'
|
||||
import { RouteState } from '../components/RouteState'
|
||||
import '../styles/digest.css'
|
||||
|
||||
type Category = 'all' | 'official' | 'news' | 'video'
|
||||
@@ -406,27 +407,27 @@ export function BriefingPage() {
|
||||
const queryClient = useQueryClient()
|
||||
const now = useMemo(() => new Date(), [])
|
||||
|
||||
const { data: allNews = [], isLoading, isError } = useQuery({
|
||||
const { data: allNews = [], isLoading, isError, error, refetch, isFetching } = useQuery({
|
||||
queryKey: ['news'],
|
||||
queryFn: () => fetchNews(100),
|
||||
queryFn: ({ signal }) => fetchNews(100, undefined, signal),
|
||||
staleTime: 60_000,
|
||||
})
|
||||
|
||||
const seasonsQuery = useQuery({
|
||||
queryKey: ['seasons'],
|
||||
queryFn: fetchSeasons,
|
||||
queryFn: ({ signal }) => fetchSeasons(signal),
|
||||
})
|
||||
const latestSeason = seasonsQuery.data?.[0] ?? null
|
||||
|
||||
const meetingsQuery = useQuery({
|
||||
queryKey: ['season-meetings', latestSeason],
|
||||
queryFn: () => fetchSeasonMeetings(latestSeason!),
|
||||
queryFn: ({ signal }) => fetchSeasonMeetings(latestSeason!, signal),
|
||||
enabled: latestSeason != null,
|
||||
})
|
||||
|
||||
const hubQuery = useQuery({
|
||||
queryKey: ['championship-hub', latestSeason],
|
||||
queryFn: () => fetchChampionshipHub(latestSeason!),
|
||||
queryFn: ({ signal }) => fetchChampionshipHub(latestSeason!, signal),
|
||||
enabled: latestSeason != null,
|
||||
})
|
||||
|
||||
@@ -524,8 +525,21 @@ export function BriefingPage() {
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{isLoading && <div className="loading-state">loading briefing…</div>}
|
||||
{isError && <div className="error-box">Failed to load paddock briefing.</div>}
|
||||
{isLoading && (
|
||||
<RouteState kind="loading" title="loading briefing…" testId="briefing-loading" />
|
||||
)}
|
||||
{isError && (
|
||||
<RouteState
|
||||
kind="error"
|
||||
title="Briefing unavailable"
|
||||
error={error}
|
||||
onRetry={() => {
|
||||
if (!isFetching) void refetch()
|
||||
}}
|
||||
retrying={isFetching}
|
||||
testId="briefing-error"
|
||||
/>
|
||||
)}
|
||||
|
||||
{!isLoading && !isError && (
|
||||
<>
|
||||
|
||||
Reference in New Issue
Block a user