Sessions 5-7a: 955 tests, deployment ready

This commit is contained in:
Kev
2026-06-08 18:35:13 -04:00
parent 06b82624a2
commit 1fa04dc776
371 changed files with 49366 additions and 955 deletions
+251
View File
@@ -0,0 +1,251 @@
'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import { useAuth } from '@/contexts/AuthContext';
import { trackUpgradeClicked } from '@/lib/analytics';
type Cadence = 'monthly' | 'annual';
const PRICES: Record<Cadence, { display: string; sub: string; checkoutParam: string }> = {
monthly: { display: '$44.99', sub: '/mo', checkoutParam: '' },
annual: { display: '$449.99', sub: '/yr · save 17%', checkoutParam: '&cadence=annual' },
};
const EARLY_FEATURES = [
'Unlimited reads',
'Full factor analysis (40+ signals)',
'Kill conditions surfaced inline',
'Cascade alerts when lineups shift',
'Parlay leg history with grades',
'Sportsbook deep links',
];
const DESK_EXTRAS = [
'Real-time multi-book odds screen',
'Live probability tracker during games',
'Middles detection',
'Correlation explorer',
'Fair odds comparison (VYNDR vs book)',
'Kelly sizing recommendations',
'Cascade alerts with full detail',
'Priority support',
];
export default function DeskUpgradePage() {
const router = useRouter();
const { tier } = useAuth();
const [cadence, setCadence] = useState<Cadence>('monthly');
const price = PRICES[cadence];
const upgrade = () => {
trackUpgradeClicked({ current_tier: tier, target_tier: 'desk', trigger_location: 'desk_upgrade_page' });
router.push(`/api/checkout?tier=desk${price.checkoutParam}`);
};
return (
<section style={{ maxWidth: 980, margin: '0 auto', padding: '40px 16px 120px' }}>
<header style={{ textAlign: 'center', marginBottom: 32 }}>
<p className="lbl" style={{ color: 'var(--grade-a)', marginBottom: 12 }}>UPGRADE</p>
<h1 style={{ fontSize: 'clamp(28px, 4vw, 40px)', fontWeight: 700, letterSpacing: '-0.02em' }}>
The full terminal.
</h1>
<p style={{ marginTop: 8, color: 'var(--text-1)', fontSize: 16, maxWidth: 620, marginInline: 'auto' }}>
Everything in Early Intelligence, plus real-time odds, live probability, and the tools the sharps use.
</p>
</header>
<div
className="surface diagonal-cut tex-scan"
style={{
padding: 24,
marginBottom: 24,
textAlign: 'center',
display: 'grid',
gap: 4,
}}
>
<p className="lbl" style={{ color: 'var(--text-1)' }}>BLOOMBERG ODDS SCREEN · PREVIEW</p>
<div
aria-hidden
style={{
margin: '8px auto 0',
display: 'grid',
gridTemplateColumns: 'repeat(6, 1fr)',
gap: 4,
maxWidth: 720,
}}
>
{Array.from({ length: 24 }, (_, i) => {
const sample = ['—', '2.5', '+108', '-120', 'A-', 'A+'][i % 6];
const isGrade = sample === 'A-' || sample === 'A+';
return (
<div
key={i}
className="num"
style={{
padding: '8px 4px',
fontSize: 12,
background: i % 6 === 5 ? 'rgba(0, 212, 160, 0.08)' : 'var(--bg-1)',
border: '1px solid var(--border)',
borderRadius: 4,
color: isGrade ? 'var(--grade-a)' : 'var(--text-1)',
textShadow: isGrade ? '0 0 8px rgba(0, 212, 160, 0.55)' : 'none',
}}
>
{sample}
</div>
);
})}
</div>
</div>
<div
style={{
display: 'grid',
gap: 16,
gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))',
marginBottom: 24,
}}
>
<TierCard
label="Early Intelligence"
price="$14.99"
period="/mo"
subtitle="Your current plan"
features={EARLY_FEATURES}
subdued
/>
<TierCard
label="Desk"
price={price.display}
period={price.sub}
subtitle="Everything above, plus:"
features={DESK_EXTRAS}
highlight
/>
</div>
<div
className="surface"
style={{
padding: 24,
textAlign: 'center',
display: 'grid',
gap: 12,
justifyItems: 'center',
}}
>
<div role="tablist" aria-label="Billing cadence" style={{ display: 'inline-flex', gap: 4, background: 'var(--bg-2)', borderRadius: 999, padding: 4 }}>
{(['monthly', 'annual'] as Cadence[]).map((c) => (
<button
key={c}
role="tab"
aria-selected={cadence === c}
onClick={() => setCadence(c)}
style={{
padding: '6px 16px',
borderRadius: 999,
border: 'none',
background: cadence === c ? 'var(--bg-3)' : 'transparent',
color: cadence === c ? 'var(--text-0)' : 'var(--text-1)',
fontFamily: 'IBM Plex Mono, monospace',
fontSize: 12,
fontWeight: 700,
letterSpacing: '0.08em',
cursor: 'pointer',
}}
>
{c.toUpperCase()}
</button>
))}
</div>
<p
className="num"
style={{
fontSize: 40,
color: 'var(--grade-a)',
textShadow: '0 0 18px rgba(0, 212, 160, 0.7)',
lineHeight: 1,
marginTop: 4,
}}
>
{price.display}
<span style={{ fontSize: 14, color: 'var(--text-1)' }}>{price.sub}</span>
</p>
{tier !== 'desk' && (
<p className="lbl" style={{ color: 'var(--text-1)' }}>
You&apos;re currently on {tier === 'analyst' ? 'Early Intelligence' : 'Free'}.
</p>
)}
<button
type="button"
className="btn-primary"
style={{ padding: '14px 32px', fontSize: 15, marginTop: 4 }}
onClick={upgrade}
>
Upgrade to Desk
</button>
<p style={{ color: 'var(--text-2)', fontSize: 12 }}>
Questions? <a href="mailto:support@vyndr.app" style={{ color: 'var(--text-1)' }}>support@vyndr.app</a>
</p>
</div>
</section>
);
}
function TierCard({
label,
price,
period,
subtitle,
features,
subdued,
highlight,
}: {
label: string;
price: string;
period: string;
subtitle: string;
features: string[];
subdued?: boolean;
highlight?: boolean;
}) {
return (
<div
className={highlight ? 'surface diagonal-cut tex-scan' : 'surface'}
style={{
padding: 24,
opacity: subdued ? 0.85 : 1,
borderColor: highlight ? 'var(--grade-a)' : undefined,
boxShadow: highlight ? '0 0 0 1px rgba(0,212,160,0.25), 0 12px 40px rgba(0,212,160,0.15)' : undefined,
}}
>
<p className="lbl" style={{ color: highlight ? 'var(--grade-a)' : 'var(--text-1)' }}>{label.toUpperCase()}</p>
<p
className="num"
style={{
fontSize: 28,
marginTop: 6,
color: highlight ? 'var(--grade-a)' : 'var(--text-0)',
textShadow: highlight ? '0 0 14px rgba(0, 212, 160, 0.55)' : 'none',
}}
>
{price}<span style={{ fontSize: 13, color: 'var(--text-1)' }}>{period}</span>
</p>
<p style={{ fontSize: 13, color: 'var(--text-1)', marginTop: 4 }}>{subtitle}</p>
<ul style={{ listStyle: 'none', padding: 0, margin: '14px 0 0', display: 'grid', gap: 8 }}>
{features.map((f) => (
<li key={f} style={{ display: 'flex', gap: 8, alignItems: 'flex-start', fontSize: 14, color: 'var(--text-0)' }}>
<span aria-hidden style={{ color: 'var(--grade-a)', fontFamily: 'IBM Plex Mono, monospace' }}></span>
<span>{f}</span>
</li>
))}
</ul>
</div>
);
}