// payment.jsx — Checkout flow for mentor sessions, evaluations, and plan changes // Also includes the Admin Dashboard (insights + payouts). const { useState: useStateP, useEffect: useEffectP } = React; const { Card, Chip, DisplayHeading } = window.LAUNCH_SCREENS_1; // ──────────────────────────────────────────────────────── // Pricing catalog — what can be purchased // ──────────────────────────────────────────────────────── const PRICING = { 'mentor-jay': { label: '1:1 SESSION · JAY BRUNSWICK', sub: '60 min coaching · $100/hr', price: 100, kind: 'session' }, 'mentor-pg': { label: '1:1 SESSION · PG BANKER', sub: '60 min coaching · $100/hr', price: 100, kind: 'session' }, 'quick-score': { label: 'QUICK SCORE EVALUATION', sub: '5-category rubric · score /50 · 40+ unlocks rewards', price: 11, kind: 'eval' }, 'full-review': { label: 'IN-DEPTH EVALUATION', sub: 'Full written breakdown + revision notes · 5 days', price: 40, kind: 'eval' }, 'subscription': { label: 'LAUNCH ORBIT · MEMBERSHIP', sub: 'Update card on file · renews monthly', price: 99, kind: 'plan' }, 'sub-basic': { label: 'BASIC MEMBERSHIP', sub: 'Full Feed access + 1 free Quick review/mo · 30 days', price: 9.99, kind: 'sub', plan: 'basic' }, 'sub-vip': { label: 'VIP MEMBERSHIP', sub: '2 free In-Depth reviews + 1 coach class/mo · 30 days', price: 19.99, kind: 'sub', plan: 'vip' }, }; // ──────────────────────────────────────────────────────── // PaymentScreen — checkout / pay for services // ──────────────────────────────────────────────────────── function PaymentScreen({ theme, item = 'mentor-jay', bookingId = null, onBack, onSuccess }) { // Known catalog items resolve instantly. For a coach session booked with a // coach added in Supabase ('mentor-'), build the product from the // coaches table so the label/price are right. const isMentorItem = typeof item === 'string' && item.indexOf('mentor-') === 0; const [product, setProduct] = useStateP( PRICING[item] || (isMentorItem ? { label: '1:1 SESSION', sub: '60 min coaching', price: 100, kind: 'session' } : PRICING['mentor-jay']) ); useEffectP(() => { if (PRICING[item] || !isMentorItem) return; let alive = true; const apply = (c) => { if (c && alive) setProduct({ label: '1:1 SESSION · ' + String(c.name).toUpperCase(), sub: '60 min coaching · $' + (c.rate || 100) + '/hr', price: c.rate || 100, kind: 'session', }); }; // Try the in-memory cache first, then a fresh fetch. const cached = window.LAUNCH_USER.coachByItem && window.LAUNCH_USER.coachByItem(item); if (cached) { apply(cached); return; } if (window.LAUNCH_USER.fetchCoaches) { window.LAUNCH_USER.fetchCoaches().then(() => apply( window.LAUNCH_USER.coachByItem && window.LAUNCH_USER.coachByItem(item) )); } return () => { alive = false; }; }, [item]); const [method, setMethod] = useStateP('card'); const [card, setCard] = useStateP({ num: '4242 4242 4242 4242', exp: '08/28', cvc: '824', name: 'Maya Stokes' }); const [tip, setTip] = useStateP(0); const [processing, setProcessing] = useStateP(false); const [payErr, setPayErr] = useStateP(null); const subtotal = product.price; const total = subtotal + tip; const pay = async () => { setProcessing(true); setPayErr(null); // Subscription → activate the 30-day plan period (in Supabase / locally). if (product.kind === 'sub' && product.plan && window.LAUNCH_USER.subscribe) { const r = await window.LAUNCH_USER.subscribe(product.plan); setProcessing(false); if (r && r.ok) { onSuccess && onSuccess(product, total); } else { setPayErr((r && r.error) || 'Could not activate the plan.'); } return; } // Live mode → real Stripe Checkout (redirects to Stripe and back). if (window.LAUNCH_USER.isConfigured()) { const res = await window.LAUNCH_USER.startCheckout({ item, bookingId }); if (res && res.error) { setProcessing(false); setPayErr(res.error); return; } // Covered fully by account credit → no Stripe redirect; it's already done. if (res && res.done) { setProcessing(false); onSuccess && onSuccess(product, total); return; } return; // leaving the page for Stripe } // Demo mode → simulated charge. setTimeout(() => { setProcessing(false); onSuccess && onSuccess(product, total); }, 1400); }; return (
{/* Top bar */}
🔒 SECURE · STRIPE
★ CHECKOUT
CONFIRM
& PAY
{/* Order summary */}
{product.label}
{product.sub.toUpperCase()}
${Number(product.price).toFixed(2)}
{/* Payment method */}
PAYMENT METHOD
{[ { id: 'card', l: 'CARD' }, { id: 'apple', l: 'APPLE PAY' }, { id: 'paypal', l: 'PAYPAL' }, ].map(m => ( ))}
{method === 'card' && ( setCard({ ...card, num: e.target.value })} placeholder="Card number" style={{ padding: '12px 14px', borderRadius: 10, border: `1px solid ${theme.border}`, fontFamily: theme.fontMono, fontSize: 14, outline: 'none', letterSpacing: 1 }} />
setCard({ ...card, exp: e.target.value })} placeholder="MM/YY" style={{ flex: 1, padding: '12px 14px', borderRadius: 10, border: `1px solid ${theme.border}`, fontFamily: theme.fontMono, fontSize: 14, outline: 'none' }} /> setCard({ ...card, cvc: e.target.value })} placeholder="CVC" style={{ flex: 1, padding: '12px 14px', borderRadius: 10, border: `1px solid ${theme.border}`, fontFamily: theme.fontMono, fontSize: 14, outline: 'none' }} />
setCard({ ...card, name: e.target.value })} placeholder="Name on card" style={{ padding: '12px 14px', borderRadius: 10, border: `1px solid ${theme.border}`, fontFamily: theme.fontBody, fontSize: 14, outline: 'none' }} />
)} {method === 'apple' && (
Pay
FACE ID READY · TAP CONFIRM
)} {method === 'paypal' && (
PayPal
YOU'LL BE REDIRECTED TO PAYPAL
)}
{/* Tip for mentor */} {product.kind === 'session' && (
ADD A TIP · 100% TO YOUR MENTOR
{[0, 10, 20, 30].map(amt => ( ))}
)} {/* Total breakdown */}
{[ { l: 'Subtotal', v: `$${Number(subtotal).toFixed(2)}` }, { l: 'Platform fee', v: 'Included' }, tip > 0 && { l: 'Tip', v: `$${Number(tip).toFixed(2)}` }, ].filter(Boolean).map((r, i) => (
{r.l} {r.v}
))}
TOTAL DUE ${Number(total).toFixed(2)}
{/* Pay button */}
{payErr && (
⚠ {payErr}
)}
BY CONFIRMING YOU AGREE TO LAUNCH'S TERMS · CANCEL UP TO 24H BEFORE SESSION FOR FULL REFUND
); } // ──────────────────────────────────────────────────────── // AdminDashboard — insights + payout management // ──────────────────────────────────────────────────────── const ADMIN_INSIGHTS = { mtdRevenue: 48720, pendingPayout: 12340, totalUsers: 2487, activeSubs: 1124, evalsCompleted: 287, sessionsBooked: 142, revenueByService: [ { l: 'Subscriptions', v: 24800, pct: 51 }, { l: '1:1 Sessions', v: 14200, pct: 29 }, { l: 'A&R Panel', v: 4470, pct: 9 }, { l: 'In-Depth Evals', v: 3240, pct: 7 }, { l: 'Quick Scores', v: 2010, pct: 4 }, ], transactions: [ { id: 'tx-2487', user: 'kai.park', service: 'A&R Panel', amt: 149, date: 'TODAY · 2:14 PM', status: 'completed' }, { id: 'tx-2486', user: 'sasha.vee', service: '1:1 PG Banker', amt: 100, date: 'TODAY · 1:30 PM', status: 'completed' }, { id: 'tx-2485', user: 'maya.sounds', service: 'In-Depth Eval', amt: 40, date: 'TODAY · 11:42 AM', status: 'completed' }, { id: 'tx-2484', user: 'theo.m', service: 'Quick Score', amt: 11, date: 'YESTERDAY', status: 'completed' }, { id: 'tx-2483', user: 'isla.loop', service: 'Orbit subscription', amt: 99, date: 'YESTERDAY', status: 'completed' }, { id: 'tx-2482', user: 'jordan.ek', service: '1:1 Jay Brunswick', amt: 100, date: 'MAY 20', status: 'refunded' }, { id: 'tx-2481', user: 'nova.b', service: 'Stratosphere', amt: 1000,date: 'MAY 19', status: 'completed' }, ], payouts: [ { l: 'Stripe → Operating', amt: 36380, status: 'AVAILABLE NOW' }, { l: 'Mentor escrow · Jay', amt: 6420, status: 'HOLDING · CLEARS FRI' }, { l: 'Mentor escrow · PG', amt: 5920, status: 'HOLDING · CLEARS FRI' }, ], }; function AdminDashboard({ theme, onBack }) { const [tab, setTab] = useStateP('overview'); // overview | transactions | payouts const a = ADMIN_INSIGHTS; const fmt = (n) => '$' + n.toLocaleString(); return (
{/* Top bar */}
★ ADMIN · LAUNCH HQ
MAY 2026 · MTD
MISSION
CONTROL
{/* Tabs */}
{[ { id: 'overview', l: 'INSIGHTS' }, { id: 'transactions', l: 'TRANSACTIONS' }, { id: 'payouts', l: 'PAYOUTS' }, ].map(t => ( ))}
{tab === 'overview' && ( <> {/* KPI hero */}
★ MONTH-TO-DATE REVENUE
{fmt(a.mtdRevenue)}
↗ +18% VS LAST MONTH
AVAILABLE TO PAYOUT
{fmt(a.pendingPayout)}
{/* KPI grid */}
{[ { n: a.totalUsers.toLocaleString(), l: 'TOTAL USERS', d: '+124 THIS WEEK' }, { n: a.activeSubs.toLocaleString(), l: 'ACTIVE SUBS', d: '45% CONVERSION' }, { n: a.evalsCompleted, l: 'EVALUATIONS', d: 'AVG SCORE 32/50' }, { n: a.sessionsBooked, l: 'SESSIONS BOOKED', d: '94% SHOW RATE' }, ].map((s, i) => (
{s.n}
{s.l}
{s.d}
))}
{/* Revenue breakdown */}
REVENUE BY SERVICE
{a.revenueByService.map((r, i) => (
{r.l} {fmt(r.v)} · {r.pct}%
))}
)} {tab === 'transactions' && (
RECENT TRANSACTIONS · {a.transactions.length}
{a.transactions.map((t, i) => (
{t.user}
{t.service.toUpperCase()} · {t.date}
${t.amt}
{t.status === 'refunded' ? '↻ REFUNDED' : '✓ COMPLETED'}
))}
)} {tab === 'payouts' && ( <>
★ AVAILABLE TO WITHDRAW
{fmt(a.pendingPayout)}
NET OF MENTOR ESCROW · STRIPE FEES INCLUDED
FUND BREAKDOWN
{a.payouts.map((p, i) => (
{p.l}
{p.status}
{fmt(p.amt)}
))}
CONNECTED ACCOUNT
🏦
Chase Business ····8472
STRIPE CONNECT · VERIFIED
)}
); } window.LAUNCH_PAYMENT = { PaymentScreen, AdminDashboard, PRICING };