Initial skills documentation — 25 categories, all SKILL.md + references + scripts

This commit is contained in:
root
2026-07-15 17:42:20 -04:00
commit 1b4fcd4427
976 changed files with 188344 additions and 0 deletions
@@ -0,0 +1,83 @@
# 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.