Wave 2B: Offseason never-dark hub — NewsWire + FuturesBoard on /explore
Extend /explore (ExploreHub) into the 365-day never-dark hub. Two new self-hiding sections feed REAL always-available data into the offseason: - NewsWire (components/vyndr/NewsWire.tsx): real ESPN headlines from /api/news/:sport (newest-first, mono timestamps, type chips, player/team links) + real injuries from /api/schedule/:sport/injuries (OUT/GTD chips, token colors). Reuses the retired TerminalTemplates INJURY_WIRE layout but never routes its sample constants. Self-hides when both feeds are empty. - FuturesBoard (components/vyndr/FuturesBoard.tsx): real futures from /api/futures/:sport — championship/win-total/award markets, mono tabular prices + movement colored by the contract (shortening=green / drifting=amber / flat=dim, NEVER red; move shown ONLY when the backend supplies one). Carries the honest "TRACKED · NOT GRADED" label — no fabricated grades on futures. Self-hides when markets:[]. - ExploreHub is offseason-aware (via emptyState OFF_SEASON month check): the hub LEADS with futures + wire when the board is dark, COMPLEMENTS the live board in-season. Sport selector kept; each section self-hides independently. - Testable pure helpers: lib/futuresMove.js (move→color, never red) + lib/newsFormat.js (timeAgo mono-stamp, ESPN type labels). Contracts consumed (Wave 2A owns the proxy/service files); code self-hides on fetch failure if a proxy isn't present yet. Tests: tests/unit/newsWire.test.js + futuresBoard.test.js (26 new). Full suite 259 suites / 3144 green; web build exit 0. vyndrParityQA stays green (mono data, no glitch on data surfaces). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
/* ============================================================
|
||||
VYNDR — FUTURES MOVEMENT color/label (Wave 2B, Offseason Hub).
|
||||
|
||||
The color contract for a futures selection's price movement. HONESTY RULE:
|
||||
futures are TRACKED, not model-graded — a movement is only ever shown when
|
||||
the backend actually supplies a `move` (never fabricated). The color space
|
||||
is deliberately narrow and NEVER red:
|
||||
• shortening → the market moved TOWARD the selection → green (value/steam)
|
||||
• drifting → the market moved AWAY → amber (caution)
|
||||
• flat / absent → no movement to report → dim (say less)
|
||||
Red is reserved system-wide for settled-negative outcomes; a futures drift
|
||||
is NOT a miss, so it must never render red.
|
||||
|
||||
CommonJS so the .tsx surface imports it (allowJs) AND Jest exercises it.
|
||||
============================================================ */
|
||||
|
||||
// Canonical move → CSS custom-property token. No branch returns the red
|
||||
// (--miss) token — a normal drift is caution (amber), never a miss.
|
||||
const MOVE_COLOR = {
|
||||
shortening: 'var(--g-a)', // green — toward the selection (value)
|
||||
drifting: 'var(--amber)', // amber — away from the selection (caution)
|
||||
flat: 'var(--text-2)', // dim — no movement
|
||||
};
|
||||
|
||||
/** moveColor(move) — the token for a move, defaulting to dim for flat/absent. */
|
||||
function moveColor(move) {
|
||||
const m = String(move || '').toLowerCase();
|
||||
return MOVE_COLOR[m] || MOVE_COLOR.flat;
|
||||
}
|
||||
|
||||
/** moveLabel(move) — a short mono glyph+word, or '' when there is no move. */
|
||||
function moveLabel(move) {
|
||||
const m = String(move || '').toLowerCase();
|
||||
if (m === 'shortening') return '▼ SHORTENING';
|
||||
if (m === 'drifting') return '▲ DRIFTING';
|
||||
if (m === 'flat') return '— FLAT';
|
||||
return '';
|
||||
}
|
||||
|
||||
module.exports = { MOVE_COLOR, moveColor, moveLabel };
|
||||
Reference in New Issue
Block a user