Files
vyndr/specs/feature-3-2-scan-ui.md
T

6.7 KiB

Feature 3.2 — Scan UI

Overview

The parlay scanner interface. Users input legs via a manual form builder, submit for analysis, and see color-coded grades with full reasoning. Displays scan count for free tier users, upgrade prompts at the limit.

Dependencies

  • Feature 2.1 — Parlay Scan API (POST /api/scan/parlay)
  • Feature 3.1 — Landing Page (shared layout, auth, design system)

Page: /scan

Layout

┌─────────────────────────────────────────────┐
│  Header: VYNDR logo + nav + scan counter │
├─────────────────────────────────────────────┤
│                                             │
│  ┌─── Leg Builder ────────────────────────┐ │
│  │  Player: [___________] (autocomplete)  │ │
│  │  Stat:   [points ▼]   Line: [26.5]    │ │
│  │  Direction: [Over ▼]  Book: [DK ▼]    │ │
│  │  [+ Add Leg]                           │ │
│  └────────────────────────────────────────┘ │
│                                             │
│  Legs: ┌──┐ ┌──┐ ┌──┐                      │
│        │L1│ │L2│ │L3│  (removable chips)    │
│        └──┘ └──┘ └──┘                      │
│                                             │
│  [🔍 Scan Parlay]                           │
│                                             │
├─────────────────────────────────────────────┤
│  Results (after scan):                      │
│                                             │
│  ┌─ Overall ──────────────────────────────┐ │
│  │  PARLAY GRADE: [B]  Confidence: 68%    │ │
│  │  Correlations: 1 flag                  │ │
│  └────────────────────────────────────────┘ │
│                                             │
│  ┌─ Leg 1 ────────────────────────────────┐ │
│  │  Jokic Over 26.5 pts  [A] 85%         │ │
│  │  Season: 26.3 | Last 10: 28.1         │ │
│  │  Home: 27.8 | vs LAL: 30.5            │ │
│  │  Kill conditions: none                 │ │
│  └────────────────────────────────────────┘ │
│                                             │
│  ┌─ Leg 2 ────────────────────────────────┐ │
│  │  LeBron Over 8.5 reb  [C] 52%         │ │
│  │  ...                                   │ │
│  └────────────────────────────────────────┘ │
│                                             │
│  ┌─ Correlations ─────────────────────────┐ │
│  │  ⚠ Same game, same team: LeBron + AD  │ │
│  └────────────────────────────────────────┘ │
│                                             │
│  [📋 Save to Bet Tracker] [🔄 New Scan]    │
│                                             │
└─────────────────────────────────────────────┘

Components

ScanCounter (header)

  • Shows "3 of 5 scans used" for free tier
  • Shows "Unlimited" for paid tiers
  • Progress bar visual

LegBuilder

  • Player input with autocomplete (calls GET /players/search on NBA stats service)
  • Stat type dropdown: points, rebounds, assists, threes, blocks, steals, pra, turnovers
  • Line: numeric input
  • Direction: over/under toggle
  • Book: DraftKings, FanDuel, BetMGM dropdown
  • "Add Leg" button → adds to legs list (2-12 legs)

LegChip

  • Compact display: "Jokic O26.5 pts DK"
  • Remove button (X)
  • Reorderable (nice-to-have)

ScanButton

  • Disabled until 2+ legs added
  • Loading state during API call
  • Calls POST /api/scan/parlay with auth token

ResultsPanel

  • Overall parlay grade card (large, color-coded)
  • Individual leg cards with grade, confidence, edge, reasoning summary
  • Correlation flags section with icons
  • Kill conditions listed per leg

UpgradePitch (modal or inline)

  • Appears at scan 5 (from API response upgrade_pitch)
  • Shows personalized hook, insight, CTA
  • "Subscribe" button → Stripe checkout
  • "Maybe Later" dismisses

GradeCard (shared component from 3.1)

  • Letter grade (A/B/C/D) with background color
  • Confidence percentage
  • Edge percentage

State Management

scanState = {
  legs: [],           // array of leg objects
  isScanning: false,  // loading state
  results: null,      // API response
  error: null,        // error message
  scanCount: 0,       // from user profile
  scansRemaining: 5,  // computed
  upgradePitch: null,  // from API when applicable
}

API Integration

1. Player search: GET http://localhost:8000/players/search?name=...
   → Autocomplete results (debounced, 300ms)

2. Scan: POST /api/scan/parlay
   Headers: { Authorization: Bearer <jwt> }
   Body: { legs: [...] }
   → Full parlay analysis response

3. Save to tracker: POST /api/bets/quickslip
   → Creates bet from scan results

Acceptance Criteria

  1. Leg builder allows adding 2-12 legs with all required fields
  2. Player autocomplete searches as user types (debounced)
  3. Scan button calls API and displays results with grades
  4. Grade cards show correct colors (A=green, B=yellow, C=orange, D=red)
  5. Correlation flags displayed with appropriate severity icons
  6. Kill conditions listed per leg
  7. Scan counter shows remaining scans for free tier
  8. Upgrade pitch modal appears at scan 5 with personalized content
  9. "Save to Bet Tracker" creates a bet via quickslip API
  10. Error states handled: API down, invalid input, auth expired
  11. Responsive: works on mobile and desktop
  12. Loading states during API calls

Test Plan

  • Component tests: LegBuilder adds/removes legs correctly
  • Component tests: GradeCard renders correct color per grade
  • Integration: full scan flow → results displayed
  • Upgrade pitch: appears at correct scan count
  • Error handling: API error → user-friendly message
  • Responsive: mobile leg builder usable