Session 16: Live hero prop, sport-specific markets fix, soccer weather, Sentry CSP (1429 tests)

This commit is contained in:
Kev
2026-06-11 18:15:25 -04:00
parent 167996d99a
commit 73b65a0248
11 changed files with 1010 additions and 101 deletions
+14 -94
View File
@@ -1,6 +1,10 @@
'use client';
import { GradePill } from './GradeCard';
// Session 16 — the floating demo card on the right side of the hero
// is now driven by /api/hero-prop. Live prop + grade renders with a
// glitch/blur overlay on the reasoning. Falls back to the static
// Jokic layout when no live odds are available.
import LiveHeroProp from './LiveHeroProp';
export default function Hero() {
return (
@@ -75,7 +79,7 @@ export default function Hero() {
</p>
</div>
<FloatingDemoCard />
<LiveHeroProp />
</div>
<p
style={{
@@ -173,95 +177,11 @@ function SportBadgeStrip() {
);
}
function FloatingDemoCard() {
return (
<div
className="animate-fade-up stagger-3"
style={{
position: 'relative',
transform: 'rotate(-1deg)',
padding: 24,
background: 'var(--bg-elevated)',
border: '1px solid var(--border-focus)',
borderRadius: 20,
boxShadow: '0 24px 64px rgba(0,0,0,0.6), 0 0 0 1px var(--accent-glow)',
maxWidth: 380,
marginInline: 'auto',
}}
>
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 16 }}>
<div>
<span
className="mono"
style={{
fontSize: 11,
padding: '2px 8px',
borderRadius: 999,
background: 'rgba(233,75,60,0.15)',
color: '#E94B3C',
fontWeight: 700,
}}
>
NBA
</span>
<h3 style={{ fontSize: 16, fontWeight: 600, marginTop: 8 }}>Nikola Jokic</h3>
<p className="mono" style={{ fontSize: 12, color: 'var(--text-secondary)' }}>
Over 26.5 points
</p>
</div>
<GradePill grade="A-" confidence={73} />
</div>
<div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>
<Stat label="Projection" value="29.4 pts" />
<Stat label="Edge" value="+6.2%" tone="positive" />
</div>
<ul style={{ display: 'grid', gap: 6, fontSize: 12, color: 'var(--text-secondary)' }}>
<li style={row}>
<span>Matchup</span>
<span style={{ color: 'var(--text-primary)' }}>LAL · 26th vs C</span>
</li>
<li style={row}>
<span>L10 form</span>
<span style={{ color: 'var(--text-primary)' }}>27.4 / 7 of 10</span>
</li>
<li style={row}>
<span>Usage shift</span>
<span style={{ color: 'var(--grade-a)' }}>+3.2% w/o Murray</span>
</li>
</ul>
</div>
);
}
const row: React.CSSProperties = {
display: 'flex',
justifyContent: 'space-between',
paddingBlock: 4,
borderBottom: '1px solid var(--border)',
};
function Stat({ label, value, tone }: { label: string; value: string; tone?: 'positive' }) {
return (
<div
style={{
flex: 1,
padding: '8px 12px',
background: 'var(--bg-surface)',
borderRadius: 10,
textAlign: 'center',
}}
>
<div style={{ fontSize: 10, color: 'var(--text-tertiary)' }}>{label}</div>
<div
className="mono"
style={{
fontSize: 14,
fontWeight: 700,
color: tone === 'positive' ? 'var(--grade-a)' : 'var(--text-primary)',
}}
>
{value}
</div>
</div>
);
}
// Session 16 — FloatingDemoCard / Stat / row removed. The hero card
// is now a live, graded prop fetched on mount; see LiveHeroProp.tsx.
// The static Jokic layout lives ONCE inside that component as the
// cold-start fallback when /api/hero-prop returns isStatic:true.
//
// GradePill (re-exported by GradeCard) is still imported at the top
// of this file because the section header uses it elsewhere; if a
// future cleanup confirms no other usage, that import can drop too.