mirror of
https://github.com/AmanTahiliani/box-box.git
synced 2026-08-08 04:06:18 -04:00
101 lines
3.1 KiB
TypeScript
101 lines
3.1 KiB
TypeScript
|
|
import type { WeekendSession } from '../types'
|
||
|
|
import { isSessionComplete } from './coverage'
|
||
|
|
import { sessionEndTime, sessionStartTime } from './schedule'
|
||
|
|
|
||
|
|
/**
|
||
|
|
* User-facing lifecycle state for a weekend session. Combines the schedule
|
||
|
|
* (has it started / finished) with local dataset coverage so the UI can speak
|
||
|
|
* in fan language instead of raw `x/11` coverage counts.
|
||
|
|
*
|
||
|
|
* - `upcoming` — starts in the future; render a pre-session view.
|
||
|
|
* - `live` — currently running (started, not yet finished).
|
||
|
|
* - `preparing` — finished (or unknown timing) but no local analysis yet.
|
||
|
|
* - `partial` — finished with some, but not all, local datasets.
|
||
|
|
* - `ready` — finished with full local coverage; analysis is trustworthy.
|
||
|
|
* - `cancelled` — session was cancelled.
|
||
|
|
*/
|
||
|
|
export type SessionState =
|
||
|
|
| 'upcoming'
|
||
|
|
| 'live'
|
||
|
|
| 'preparing'
|
||
|
|
| 'partial'
|
||
|
|
| 'ready'
|
||
|
|
| 'cancelled'
|
||
|
|
|
||
|
|
export function sessionState(session: WeekendSession, now: Date): SessionState {
|
||
|
|
if (session.source === 'cancelled') return 'cancelled'
|
||
|
|
|
||
|
|
const start = sessionStartTime(session.session)
|
||
|
|
const end = sessionEndTime(session.session)
|
||
|
|
|
||
|
|
if (start && start > now) return 'upcoming'
|
||
|
|
if (start && end && now >= start && now < end) return 'live'
|
||
|
|
|
||
|
|
// Session has started/finished (or timing unknown) — describe it by coverage.
|
||
|
|
if (isSessionComplete(session.datasets)) return 'ready'
|
||
|
|
if (session.source === 'none') return 'preparing'
|
||
|
|
return 'partial'
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Short label suitable for chips and the session switcher. */
|
||
|
|
export function sessionStateLabel(state: SessionState): string {
|
||
|
|
switch (state) {
|
||
|
|
case 'upcoming':
|
||
|
|
return 'Upcoming'
|
||
|
|
case 'live':
|
||
|
|
return 'Live'
|
||
|
|
case 'preparing':
|
||
|
|
return 'Preparing'
|
||
|
|
case 'partial':
|
||
|
|
return 'Partial'
|
||
|
|
case 'ready':
|
||
|
|
return 'Ready'
|
||
|
|
case 'cancelled':
|
||
|
|
return 'Cancelled'
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Longer, sentence-style description for headers and empty states. */
|
||
|
|
export function sessionStateDescription(state: SessionState): string {
|
||
|
|
switch (state) {
|
||
|
|
case 'upcoming':
|
||
|
|
return 'Session has not started yet.'
|
||
|
|
case 'live':
|
||
|
|
return 'Session is running now.'
|
||
|
|
case 'preparing':
|
||
|
|
return 'Analysis is being prepared — no local data ingested yet.'
|
||
|
|
case 'partial':
|
||
|
|
return 'Partial analysis available — some datasets are still missing.'
|
||
|
|
case 'ready':
|
||
|
|
return 'Full analysis is ready.'
|
||
|
|
case 'cancelled':
|
||
|
|
return 'This session was cancelled.'
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Class suffix used for the coverage dot, so the rail can colour a session by
|
||
|
|
* its lifecycle state rather than only by data source.
|
||
|
|
*/
|
||
|
|
export function sessionStateDotClass(state: SessionState): string {
|
||
|
|
switch (state) {
|
||
|
|
case 'ready':
|
||
|
|
return 'rh-state-ready'
|
||
|
|
case 'partial':
|
||
|
|
return 'rh-state-partial'
|
||
|
|
case 'live':
|
||
|
|
return 'rh-state-live'
|
||
|
|
case 'upcoming':
|
||
|
|
return 'rh-state-upcoming'
|
||
|
|
case 'cancelled':
|
||
|
|
return 'rh-state-cancelled'
|
||
|
|
default:
|
||
|
|
return 'rh-state-preparing'
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Whether a session should render the pre-session (expected availability) view. */
|
||
|
|
export function isPreSession(state: SessionState): boolean {
|
||
|
|
return state === 'upcoming'
|
||
|
|
}
|