All Stories
1-5-3-players-data-integrationDoneEpic 1.5
Story 1.5.3: Players Data Integration
Status: done
Tasks
- **Task 1: Add get_players() to API Client** (AC: #2)
- 1.1: Locate existing `OpticOddsAPIClient` in `/server/app/services/odds/optic_odds_api_client.py`
- 1.2: Add `get_players()` async method with filters: sport_id, league_id, team_id, player_ids, position, is_active
- 1.3: Validate at least one filter parameter provided (raise ValueError if none)
- 1.4: Call GET `/v3/players` endpoint with proper params
- 1.5: Handle player_ids (comma-separated, max 20 players)
- 1.6: Add logging for request and response
- 1.7: Return players data array from response
- **Task 2: Create Pydantic Models** (AC: #3)
- 2.1: Locate existing models in `/server/app/models/optic_odds.py`
- 2.2: Create `OpticOddsPlayer` model with all required fields
- 2.3: Add Field() descriptions for API documentation
- 2.4: Include optional fields: jersey_number, headshot, height, weight
- 2.5: Add model_config with JSON schema example (Patrick Mahomes example)
- 2.6: Create `OpticOddsPlayersResponse` model with data and meta
- 2.7: Test model validation with sample data
- **Task 3: Create FastAPI Endpoint** (AC: #1)
- 3.1: Locate existing endpoint file `/server/app/api/v1/endpoints/optic_odds.py`
- 3.2: Add GET `/players` route with response_model=OpticOddsPlayersResponse
- 3.3: Add query parameters: sport_id, league_id, team_id, player_ids, position, is_active, force_refresh
- 3.4: Add JWT authentication with get_current_user dependency
- 3.5: Validate at least one filter provided (400 error if missing)
- 3.6: Check Redis cache first (key format: `players:{league_id or team_id or 'ids'}`)
- 3.7: If cache miss, call client.get_players() and cache for 12 hours (43200 seconds)
- 3.8: Add error handling (400 for validation, 500 for API errors)
- 3.9: Test endpoint via /docs interface
- **Task 4: Create usePlayers Hook** (AC: #4)
- 4.1: Create new file `/client/src/hooks/usePlayers.ts`
- 4.2: Define Player and PlayersResponse TypeScript interfaces
- 4.3: Implement `usePlayers(leagueId?, teamId?, sportId?)` with TanStack Query
- 4.4: Build query params and fetch from `/api/v1/optic-odds/players`
- 4.5: Add JWT token from localStorage to Authorization header
- 4.6: Set staleTime to 12 hours (43200000ms, matches server cache)
- 4.7: Add enabled condition: only run if leagueId, teamId, or sportId provided
- 4.8: Add error handling for failed requests
- **Task 5: Redis Caching Strategy** (AC: #1)
- 5.1: Verify Redis client available in endpoint
- 5.2: Implement cache key format: `players:{league_id or team_id or 'ids'}`
- 5.3: Set TTL to 43200 seconds (12 hours - roster changes infrequent)
- 5.4: Store players as JSON string
- 5.5: Add cache metadata to response (cached: true/false, timestamp, cache_ttl_hours: 12)
- 5.6: Test force_refresh=true bypasses cache
- 5.7: Test cache expiration after 12 hours
- **Task 6: Testing & Validation** (AC: #5, #6)
- 6.1: Test API endpoint with league_id=nfl (should return all NFL players)
- 6.2: Test with team_id (should return players for specific team)
- 6.3: Test with position=QB (should return only quarterbacks)
- 6.4: Test with player_ids (comma-separated, max 20)
- 6.5: Test 400 error when no filters provided
- 6.6: Test cache hit (second request returns cached: true)
- 6.7: Test usePlayers hook with various filter combinations
- 6.8: Verify performance: <500ms API, <150ms client render
- **Task 7: Documentation & Foundation** (AC: #5)
- 7.1: Document players endpoint in API docs
- 7.2: Add examples for various filter combinations
- 7.3: Document data schema and fields
- 7.4: Note this is foundation for Epic 1.7 (Player Props)
- 7.5: Document cache TTL rationale (roster changes infrequent)
- 7.6: Add notes on position filtering (QB, RB, WR, TE, etc.)
Progress
Tasks7/7
Acceptance Criteria0
Total Tasks7