# PWA Frontend Integration for Fantasy Draft Games

## Auth flow (index.html)

1. **Dual-mode form:** Registration + Login toggled by `isLoginMode` boolean
2. **On success:** Store token in `localStorage.getItem('shark_token')`, user in `localStorage.setItem('shark_user')`
3. **Post-auth:** `GET /api/leagues` — branch by count:
   - 0 leagues → show create/join UI
   - 1 league → auto-redirect `draft-room.html?league_id=X`
   - Multiple → show league picker
4. **Auth guard** on every protected page: `if (!getToken()) window.location.href = 'index.html'`
5. **Register response:** `{user_id, token, display_name}` — backend must pass `display_name` from request

## League management (index.html)

- **Create:** `POST /api/leagues {name}` → returns `{id, invite_code}`
- **Join:** `POST /api/leagues/join {invite_code}` → returns `{league_id, league_name}`
- **Redirect after create/join:** `window.location.href = 'draft-room.html?league_id=' + result.id`

## Draft room (draft-room.html)

### League picker overlay
- GET `/api/leagues` on load
- If no `league_id` URL param, show overlay with league cards
- On select: `history.replaceState(null, '', '?league_id=' + id)` + `loadAll()`

### Data loading
```javascript
async function loadAll() {
  const [league, board, scores, regions] = await Promise.all([
    apiCall('/api/leagues/' + leagueId),
    apiCall('/api/leagues/' + leagueId + '/draft'),
    apiCall('/api/leagues/' + leagueId + '/scores'),
    apiCall('/api/regions'),
  ]);
  renderAll();
}
```

### Draft board tabs
- **Draft tab:** Region cards grid + status bar (round/turn info)
- **Team tab:** User's drafted regions + cumulative points
- **Leaderboard tab:** Ranked user list with scores
- **League info tab:** Invite code (copyable), member list, start draft (commissioner only)

### Card states
- Available: teal border, "DRAFT" button
- Your pick: amber glow border + "⭐ YOUR PICK"
- Taken: grayed out, "Drafted by [player]"
- WAITING (draft not started): dimmed, "WAITING" label

### Pitfalls
- **`league_id` from URL vs API:** After creating a league, the API returns `result.id`, not `result.league_id`. Use `result.id` in redirect URL.
- **`.hidden` CSS class:** Every standalone page MUST define `.hidden { display: none !important; }` in its own `<style>` block. Sibling pages don't inherit it.
- **Overlay staying visible:** Missing `.hidden` class causes the league picker overlay to remain on screen after selecting a league — the JS adds the class but the browser has no matching CSS rule.
- **API calls that work from curl** may fail from the browser if CORS headers are missing on the backend. FastAPI's `CORSMiddleware` with `allow_origins=["*"]` fixes this during development.
- **Token expiry:** JWT tokens set for 30 days. The frontend doesn't handle token refresh — if the token expires, the user gets "Invalid token" error and must re-login.

## HTML table templates (score charts, stats)

When rendering leaderboard/team data as HTML inside JS template literals, use inline `<table>` elements matching the game's dark theme:

```javascript
function renderLeaderboard(data) {
  return `<table style="width:100%;border-collapse:collapse;font-size:13px;">
    <tr style="background:rgba(15,23,42,0.8);">
      <th style="padding:8px;text-align:left;font-weight:600;">Player</th>
      <th style="padding:8px;text-align:center;font-weight:600;">Points</th>
    </tr>
    ${data.map(p => `<tr>
      <td style="padding:8px 10px;border-bottom:1px solid rgba(255,255,255,0.05);">${p.display_name}</td>
      <td style="padding:8px 10px;text-align:center;border-bottom:1px solid rgba(255,255,255,0.05);color:var(--amber);">${p.total_points}</td>
    </tr>`).join('')}
  </table>`;
}
```

## Common pitfalls

- **Registration displays name as null** — backend must include `display_name=req.display_name` in AuthResponse (fix at `/api/auth/register` endpoint)
- **Mobile Safari caching** — after updating frontend files, users may see cached versions. Hard refresh or clear Safari cache is needed.
- **League creation redirect** — API returns `id`, not `league_id`. Use `result.id`.
- **API call errors** — Use try/catch + user-facing error messages. The `apiCall()` helper throws on non-ok status codes.
