Session 23: All-day intelligence layer — schedule, game lines, streaks, hot lists, stat filtering, ParlayAPI dead (1567 tests)

This commit is contained in:
Kev
2026-06-12 11:16:58 -04:00
parent 6ab49d4c37
commit 0538205fab
32 changed files with 2276 additions and 2 deletions
+23
View File
@@ -5,6 +5,12 @@ import { useRouter } from 'next/navigation';
import GameCard, { SlateSport } from '@/components/GameCard';
import { PropRowProp, PropRowResult, propRowKey, Tier } from '@/components/PropRow';
import { useAuth } from '@/contexts/AuthContext';
// Session 23 — all-day intelligence layer. The stat filter is the
// navigation system; streaks + hot lists layer ON TOP of the odds the
// Slate already shows, never replacing them.
import StatFilterPills from '@/components/StatFilterPills';
import StreaksPanel from '@/components/StreaksPanel';
import HotListPanel from '@/components/HotListPanel';
/**
* The Slate (Session 13).
@@ -181,6 +187,10 @@ export default function Slate({ initialTab = 'all', tier = 'free' }: SlateProps)
const router = useRouter();
const { session } = useAuth();
const [tab, setTab] = useState<SlateTab>(initialTab);
// Session 23 — active stat category for the intelligence panels. 'all'
// shows everything; selecting one narrows streaks + hot list. Schedule
// and game lines stay visible regardless (handled inside GameCard).
const [activeStat, setActiveStat] = useState<string>('all');
const [games, setGames] = useState<SlateGame[]>([]);
const [loading, setLoading] = useState(false);
const [fetchError, setFetchError] = useState<string | null>(null);
@@ -416,6 +426,13 @@ export default function Slate({ initialTab = 'all', tier = 'free' }: SlateProps)
);
})}
</div>
{/* Session 23 — stat filter pills, below the sport tabs and above
all content. Narrows the streaks + hot list panels. */}
<StatFilterPills
sport={tab === 'all' ? 'nba' : tab}
activeStat={activeStat}
onChange={setActiveStat}
/>
</div>
{/* Body */}
@@ -525,6 +542,12 @@ export default function Slate({ initialTab = 'all', tier = 'free' }: SlateProps)
))}
</div>
{/* Session 23 — intelligence layer. These coexist WITH the odds
above; they never replace games. Both self-hide when empty, so
an off-hours slate with no warm logs simply shows the games. */}
<StreaksPanel sport={tab === 'all' ? 'nba' : tab} tier={tier} stat={activeStat} />
<HotListPanel sport={tab === 'all' ? 'mlb' : tab} tier={tier} stat={activeStat} />
{unsupportedSports.length > 0 && !loading && (
<p
className="mono"