strat-gameplay-webapp/frontend-sba/types/api.ts
Cal Corum a87d149788 CLAUDE: Implement game creation and lineup submission workflow
Complete implementation of pre-game setup flow allowing players to create games
and submit lineups before gameplay starts.

Backend Changes:
- Extended games.py with create game, lineup submission, and game start endpoints
- Added teams.py roster endpoint with season filtering
- Enhanced SBA API client with player data fetching and caching
- Comprehensive validation for lineup submission (position conflicts, DH rules)

Frontend Changes:
- Redesigned create.vue with improved team selection and game options
- Enhanced index.vue with active/pending game filtering and navigation
- Added lineup/[id].vue for interactive lineup builder with drag-and-drop
- Implemented auth.client.ts plugin for client-side auth initialization
- Added comprehensive TypeScript types for API contracts
- Updated middleware for better auth handling

Key Features:
- Game creation with home/away team selection
- Full lineup builder with position assignment and batting order
- DH rule validation (pitcher can be excluded from batting order)
- Season-based roster filtering (Season 3)
- Auto-start game when both lineups submitted
- Real-time game list updates

Workflow:
1. Create game → select teams → set options
2. Submit home lineup → validate positions/order
3. Submit away lineup → validate positions/order
4. Game auto-starts → navigates to game page
5. WebSocket connection → loads game state

Ready for Phase F4 - connecting gameplay UI to complete the at-bat loop.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 23:57:03 -06:00

223 lines
4.0 KiB
TypeScript

/**
* REST API Types
*
* TypeScript definitions for HTTP API requests and responses.
* These complement the WebSocket events for non-real-time operations.
*/
import type { GameListItem, CreateGameRequest, CreateGameResponse } from './game'
/**
* API error response
*/
export interface ApiError {
message: string
code?: string
field?: string
errors?: Array<{
loc: string[]
msg: string
type: string
}>
}
/**
* Paginated response wrapper
*/
export interface PaginatedResponse<T> {
items: T[]
total: number
page: number
per_page: number
has_next: boolean
has_prev: boolean
}
/**
* Game filters for list queries
*/
export interface GameFilters {
status?: 'pending' | 'active' | 'completed'
league_id?: 'sba' | 'pd'
team_id?: number
date_from?: string
date_to?: string
page?: number
per_page?: number
}
/**
* Discord OAuth callback response
*/
export interface DiscordAuthResponse {
access_token: string
refresh_token: string
expires_in: number
user: DiscordUser
}
/**
* Discord user data
*/
export interface DiscordUser {
id: string // Discord snowflake ID (gmid)
username: string
discriminator: string
avatar: string | null
email?: string
}
/**
* JWT token payload
*/
export interface JwtPayload {
user_id: string
exp: number
iat: number
}
/**
* Team data (from league API)
*/
export interface Team {
id: number
name: string
owner_id: string
league_id: 'sba' | 'pd'
}
/**
* SBA Team data (from /api/teams endpoint)
*/
export interface SbaTeam {
id: number
abbrev: string
sname: string // Short name (e.g., "Geese")
lname: string // Long name (e.g., "Everett Geese")
color: string // Hex color code
manager_legacy: string
gmid: string | null
gmid2: string | null
division: {
id: number
division_name: string
division_abbrev: string
league_name: string
league_abbrev: string
season: number
}
}
/**
* User's teams response
*/
export interface UserTeamsResponse {
teams: Team[]
}
// ============================================================================
// API Endpoint Types
// ============================================================================
/**
* POST /api/games
*/
export type CreateGameRequestData = CreateGameRequest
export type CreateGameResponseData = CreateGameResponse
/**
* GET /api/games/:id
*/
export interface GetGameResponse {
game: GameListItem
}
/**
* GET /api/games/active
*/
export type GetActiveGamesResponse = PaginatedResponse<GameListItem>
/**
* GET /api/games/completed
*/
export type GetCompletedGamesResponse = PaginatedResponse<GameListItem>
/**
* GET /api/games/:id/history
*/
export interface PlayHistoryItem {
play_number: number
inning: number
half: 'top' | 'bottom'
outs_before: number
batter_id: number
pitcher_id: number
result_description: string
runs_scored: number
outs_recorded: number
created_at: string
}
export interface GetPlayHistoryResponse {
plays: PlayHistoryItem[]
total: number
}
/**
* DELETE /api/games/:id
*/
export interface DeleteGameResponse {
message: string
game_id: string
}
/**
* POST /api/auth/discord/callback
*/
export type DiscordCallbackRequest = {
code: string
state: string
}
export type DiscordCallbackResponse = DiscordAuthResponse
/**
* GET /api/auth/me
*/
export interface GetCurrentUserResponse {
user: DiscordUser
teams: Team[]
}
/**
* POST /api/auth/refresh
*/
export interface RefreshTokenRequest {
refresh_token: string
}
export interface RefreshTokenResponse {
access_token: string
expires_in: number
}
/**
* POST /api/games/:id/lineups
*/
export interface LineupPlayerRequest {
player_id: number
position: string
batting_order: number | null // null for pitcher in DH lineup
}
export interface SubmitLineupsRequest {
home_lineup: LineupPlayerRequest[] // 9-10 players
away_lineup: LineupPlayerRequest[] // 9-10 players
}
export interface SubmitLineupsResponse {
game_id: string
message: string
home_lineup_count: number
away_lineup_count: number
}