mirror of
https://github.com/AmanTahiliani/box-box.git
synced 2026-08-07 19:56:18 -04:00
fix(#73): consume canonical Weekend Context contract and repair navigation
Address the independent review blockers on PR #80 after rebasing onto the authoritative #72 Weekend Context API. - Replace the invented frontend WeekendContext with the exact backend contract (temporal_state, previous/focus/next meetings, previous_completed/active/next/ default_analysis sessions with availability). Every valid canonical payload now maps to a designed state via a total resolveViewState; a well-formed response can never fall through to the limited-data placeholder. - Make the canonical read the single source of truth: useWeekendContext no longer fans out to season/meetings/per-weekend/OpenF1/live queries. Only supplementary championship + news reads run, and only once the canonical context resolves. - Fix the Prepare/analysis flow: /preview is a stable alias that renders the preparation surface (PreSessionView) instead of redirecting back to the same between-races screen. - One primary navigation system per breakpoint: the mobile top-bar links are hidden so the bottom bar is the sole primary nav, and Admin is moved out of every Primary landmark into an operator-utilities toolbar. - Add Vitest coverage for the contract mapping, every temporal state, loading/ error/limited surfaces, the no-fanout guarantee, the /preview CTA, and the nav hierarchy; add hermetic Playwright journeys (seeded + injected canonical payloads), 390/768/1440 overflow checks, and Weekend visual snapshots. Retire the stale Command Center specs/snapshots. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,24 +4,52 @@ import { BetweenSessionsView } from '../components/weekend/BetweenSessionsView'
|
||||
import { LiveHandoffView } from '../components/weekend/LiveHandoffView'
|
||||
import { PreSessionView } from '../components/weekend/PreSessionView'
|
||||
import { WeekendError, WeekendLimited, WeekendLoading } from '../components/weekend/StatusViews'
|
||||
import type { WeekendContext } from '../types'
|
||||
import { resolveViewState } from '../lib/weekendContext'
|
||||
import type {
|
||||
WeekendBriefingItem,
|
||||
WeekendChampionshipImpact,
|
||||
WeekendContext,
|
||||
WeekendViewState,
|
||||
} from '../types'
|
||||
import '../styles/weekend.css'
|
||||
|
||||
function renderState(context: WeekendContext, now: Date) {
|
||||
switch (context.state) {
|
||||
case 'loading':
|
||||
return <WeekendLoading />
|
||||
case 'error':
|
||||
return <WeekendError message={context.message} />
|
||||
case 'limited_data':
|
||||
return <WeekendLimited message={context.message} season={context.season} />
|
||||
case 'between_races':
|
||||
interface RenderArgs {
|
||||
context: WeekendContext
|
||||
now: Date
|
||||
championship?: WeekendChampionshipImpact
|
||||
briefing: WeekendBriefingItem[]
|
||||
/** When true (the /preview alias), foreground the preparation surface. */
|
||||
preview: boolean
|
||||
}
|
||||
|
||||
function renderState(view: WeekendViewState, args: RenderArgs) {
|
||||
const { context, now, championship, briefing, preview } = args
|
||||
// The /preview alias always resolves to the preparation surface as long as
|
||||
// there is a next event to prepare for, regardless of the temporal state. This
|
||||
// keeps saved /preview links and the "Prepare for …" CTA meaningful instead of
|
||||
// redirecting straight back to the same between-races screen.
|
||||
if (preview && context.next_meeting) {
|
||||
return <PreSessionView context={context} now={now} />
|
||||
}
|
||||
|
||||
switch (view) {
|
||||
case 'no_season':
|
||||
return <WeekendLimited season={context.season} />
|
||||
case 'between_weekends':
|
||||
case 'post_weekend':
|
||||
case 'season_complete':
|
||||
return <BetweenRacesView context={context} now={now} />
|
||||
return (
|
||||
<BetweenRacesView
|
||||
context={context}
|
||||
now={now}
|
||||
view={view}
|
||||
championship={championship}
|
||||
briefing={briefing}
|
||||
/>
|
||||
)
|
||||
case 'between_sessions':
|
||||
case 'session_settling':
|
||||
return <BetweenSessionsView context={context} now={now} />
|
||||
return <BetweenSessionsView context={context} now={now} view={view} briefing={briefing} />
|
||||
case 'session_live':
|
||||
return <LiveHandoffView context={context} />
|
||||
case 'pre_session':
|
||||
@@ -31,12 +59,36 @@ function renderState(context: WeekendContext, now: Date) {
|
||||
}
|
||||
}
|
||||
|
||||
export function WeekendPage() {
|
||||
const { context, now } = useWeekendContext()
|
||||
export function WeekendPage({ preview = false }: { preview?: boolean }) {
|
||||
const { context, loadState, error, championship, briefing, now } = useWeekendContext()
|
||||
|
||||
if (loadState === 'loading') {
|
||||
return (
|
||||
<main className="wk-page" data-testid="weekend-page" data-state="loading">
|
||||
<WeekendLoading />
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
if (loadState === 'error' || context == null) {
|
||||
return (
|
||||
<main className="wk-page" data-testid="weekend-page" data-state="error">
|
||||
<WeekendError message={error?.message} />
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
const view = resolveViewState(context)
|
||||
|
||||
return (
|
||||
<main className="wk-page" data-testid="weekend-page" data-state={context.state}>
|
||||
{renderState(context, now)}
|
||||
<main
|
||||
className="wk-page"
|
||||
data-testid="weekend-page"
|
||||
data-state={view}
|
||||
data-temporal-state={context.temporal_state}
|
||||
data-preview={preview ? 'true' : undefined}
|
||||
>
|
||||
{renderState(view, { context, now, championship, briefing, preview })}
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user