This commit captures work from multiple sessions building the statistics system and frontend component library. Backend - Phase 3.5: Statistics System - Box score statistics with materialized views - Play stat calculator for real-time updates - Stat view refresher service - Alembic migration for materialized views - Test coverage: 41 new tests (all passing) Frontend - Phase F1: Foundation - Composables: useGameState, useGameActions, useWebSocket - Type definitions and interfaces - Store setup with Pinia Frontend - Phase F2: Game Display - ScoreBoard, GameBoard, CurrentSituation, PlayByPlay components - Demo page at /demo Frontend - Phase F3: Decision Inputs - DefensiveSetup, OffensiveApproach, StolenBaseInputs components - DecisionPanel orchestration - Demo page at /demo-decisions - Test coverage: 213 tests passing Frontend - Phase F4: Dice & Manual Outcome - DiceRoller component - ManualOutcomeEntry with validation - PlayResult display - GameplayPanel orchestration - Demo page at /demo-gameplay - Test coverage: 119 tests passing Frontend - Phase F5: Substitutions - PinchHitterSelector, DefensiveReplacementSelector, PitchingChangeSelector - SubstitutionPanel with tab navigation - Demo page at /demo-substitutions - Test coverage: 114 tests passing Documentation: - PHASE_3_5_HANDOFF.md - Statistics system handoff - PHASE_F2_COMPLETE.md - Game display completion - Frontend phase planning docs - NEXT_SESSION.md updated for Phase F6 Configuration: - Package updates (Nuxt 4 fixes) - Tailwind config enhancements - Game store updates Test Status: - Backend: 731/731 passing (100%) - Frontend: 446/446 passing (100%) - Total: 1,177 tests passing Next Phase: F6 - Integration (wire all components into game page) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
18 KiB
Next Session Plan - Frontend Phase F6: Integration & Game Page
Current Status: Phase F5 Complete - Substitutions & Lineup Management with 100% Test Coverage Last Session: 2025-01-13 - Phase F5 completion with comprehensive testing Date: 2025-01-13 Progress: Frontend ~85% complete (Phases F1-F5 complete)
Quick Start for Next AI Agent
🎯 Where to Begin
- Read this entire document first
- Review recent commits - Phase F4 and F5 completions with 326 tests
- Visit demos to see completed components:
- http://localhost:3005/demo-gameplay - Phase F4 dice & outcome
- http://localhost:3005/demo-substitutions - Phase F5 substitutions
- http://localhost:3005/demo-decisions - Phase F3 decisions
- http://localhost:3005/demo - Phase F2 game display
- Start Phase F6 - Integrate all components into game page
- Test frequently with
npm run dev
📍 Current Context
Phase F5 COMPLETE ✅ - Substitution workflow with comprehensive testing
- ✅ 4 production components built (~1,400 lines)
- ✅ 3 substitution selectors (PinchHitter, DefensiveReplacement, PitchingChange)
- ✅ 1 container panel (SubstitutionPanel)
- ✅ 114 unit tests written and passing (100% coverage)
- ✅ WebSocket integration complete (3 substitution events)
- ✅ Interactive demo page at /demo-substitutions
- ✅ Mobile-first responsive design
- ✅ Dark mode support
All Previous Phases Complete:
- ✅ Phase F1: Foundation (composables, stores, types)
- ✅ Phase F2: Game Display (ScoreBoard, GameBoard, CurrentSituation, PlayByPlay)
- ✅ Phase F3: Decision Inputs (DefensiveSetup, OffensiveApproach, StolenBaseInputs, DecisionPanel) - 213 tests
- ✅ Phase F4: Dice & Outcome (DiceRoller, ManualOutcomeEntry, PlayResult, GameplayPanel) - 119 tests
- ✅ Phase F5: Substitutions (3 selectors + SubstitutionPanel) - 114 tests
Backend Status: 100% ready (731/731 tests, all WebSocket handlers)
What We Just Completed ✅
Phase F5 Summary (2025-01-13)
Major Accomplishment: Complete substitution workflow with production-ready quality and 100% test coverage
Components Created (4 files, ~1,400 lines):
Substitution Selectors (3 files, 1,120 lines)
components/Substitutions/PinchHitterSelector.vue(~380 lines) - Bench player selection for battingcomponents/Substitutions/DefensiveReplacementSelector.vue(~420 lines) - Position + player selectioncomponents/Substitutions/PitchingChangeSelector.vue(~320 lines) - Relief pitcher selection with fatigue
Container Component (1 file, 350 lines)
components/Substitutions/SubstitutionPanel.vue(~350 lines) - Tab navigation orchestrating all selectors
Demo & Integration
pages/demo-substitutions.vue(~420 lines) - Interactive component previewcomposables/useGameActions.ts- Already had substitution actions wired
Test Suite Created (4 files, ~1,900 lines, 114 tests):
tests/unit/components/Substitutions/PinchHitterSelector.spec.ts(~410 lines, 25 tests)tests/unit/components/Substitutions/DefensiveReplacementSelector.spec.ts(~540 lines, 30 tests)tests/unit/components/Substitutions/PitchingChangeSelector.spec.ts(~470 lines, 28 tests)tests/unit/components/Substitutions/SubstitutionPanel.spec.ts(~480 lines, 31 tests)
Test Results: 114/114 passing (100%)
Design Features:
- Tab-based navigation between substitution types
- Position eligibility filtering (checks pos_1 through pos_8)
- Fatigue status display and prevention
- Active/bench player filtering
- Real-time validation
- Success/error messages
- Loading states
- Cancel/reset functionality
Next Steps: Phase F6 - Integration & Game Page
Goal: Wire all Phase F2-F5 components into the main game page and create complete gameplay flow
Priority: Critical (final integration before polish) Estimated Time: 6-8 hours Dependencies: All previous phases (F1-F5) - all complete
What Phase F6 Delivers
A fully functional game page where users can:
- View live game state (scores, outs, runners, situation)
- Submit strategic decisions (defensive/offensive)
- Roll dice and enter manual outcomes
- Make substitutions (pinch hitter, defensive, pitching)
- See play-by-play updates in real-time
- Experience complete turn-based gameplay
Components to Build/Update
1. Main Game Page Integration
File: pages/games/[id].vue
Current State: Basic structure exists but not fully wired
Changes Needed: ~400 lines of integration code
Time: 3-4 hours
Major Sections to Add:
<template>
<div class="game-page">
<!-- Top: Score & Game State -->
<ScoreBoard :game-state="gameState" />
<!-- Main Content Area -->
<div class="game-content">
<!-- Left Column: Game Visualization -->
<div class="game-visual-column">
<GameBoard :runners="gameState.runners" :outs="gameState.outs" />
<CurrentSituation :batter="currentBatter" :pitcher="currentPitcher" />
</div>
<!-- Right Column: Play-by-Play -->
<div class="plays-column">
<PlayByPlay :plays="plays" />
</div>
</div>
<!-- Action Panels (conditional based on game state) -->
<div class="action-panels">
<!-- Phase: Strategic Decisions -->
<DecisionPanel
v-if="showDecisions"
:game-id="gameId"
:current-team="currentTeam"
:is-my-turn="isMyTurn"
:phase="decisionPhase"
:runners="gameState.runners"
@defensive-submit="handleDefensiveDecision"
@offensive-submit="handleOffensiveDecision"
@steal-attempts-submit="handleStealAttempts"
/>
<!-- Phase: Dice Rolling & Outcome Entry -->
<GameplayPanel
v-if="showGameplay"
:game-id="gameId"
:is-my-turn="isMyTurn"
:can-roll-dice="canRollDice"
:pending-roll="pendingRoll"
:last-play-result="lastPlayResult"
:can-submit-outcome="canSubmitOutcome"
@roll-dice="handleRollDice"
@submit-outcome="handleSubmitOutcome"
@dismiss-result="handleDismissResult"
/>
<!-- Phase: Substitutions (modal/sidebar) -->
<SubstitutionPanel
v-if="showSubstitutions"
:game-id="gameId"
:team-id="myTeamId"
:current-lineup="currentLineup"
:bench-players="benchPlayers"
:current-pitcher="currentPitcher"
:current-batter="currentBatter"
@pinch-hitter="handlePinchHitter"
@defensive-replacement="handleDefensiveReplacement"
@pitching-change="handlePitchingChange"
@cancel="hideSubstitutions"
/>
</div>
<!-- Floating Action Button for Substitutions -->
<button
v-if="isMyTurn && canMakeSubstitutions"
class="fab-substitutions"
@click="showSubstitutions = true"
>
Substitutions
</button>
</div>
</template>
State Management:
- Use
useGameStatecomposable for reactive game data - Use
useGameActionsfor WebSocket event emission - Use
useWebSocketfor event handling - Use game store for centralized state
Conditional Rendering Logic:
const showDecisions = computed(() => {
return isMyTurn.value &&
(gameStore.phase === 'defensive_decision' ||
gameStore.phase === 'offensive_decision')
})
const showGameplay = computed(() => {
return isMyTurn.value &&
gameStore.phase === 'gameplay' &&
gameStore.decisionsComplete
})
const canMakeSubstitutions = computed(() => {
return isMyTurn.value &&
gameStore.phase !== 'game_over'
})
2. Game State Composable Enhancement
File: composables/useGameState.ts
Changes: Add phase management and conditional logic
Time: 1 hour
New Features:
currentPhase- Track which panel to show (decisions/gameplay/substitutions)isMyTurn- Determine if current user is active playercanRollDice- Check if ready to roll dicecanSubmitOutcome- Check if ready to submit outcomedecisionsComplete- Both teams have submitted decisions
3. WebSocket Event Integration
File: composables/useGameEvents.ts or inline in game page
Changes: Wire all event handlers to UI updates
Time: 1 hour
Events to Handle:
game_state_update→ Update all reactive statedefensive_decision_accepted→ Show confirmation, move to next phaseoffensive_decision_accepted→ Show confirmation, move to next phasedice_rolled→ Display dice results, show outcome entryoutcome_accepted→ Show loadingplay_completed→ Show result, update game statesubstitution_accepted→ Update lineup, show confirmationerror→ Display error message
4. Layout & Responsive Design
Time: 1 hour
Mobile Layout (< 768px):
- Stack vertically: ScoreBoard → GameBoard → CurrentSituation → PlayByPlay
- Full-width action panels
- Fixed bottom position for active panel
- Floating action button for substitutions
Tablet Layout (768px - 1024px):
- Two-column: Game visual left, Play-by-play right
- Action panels below
- Substitutions in modal overlay
Desktop Layout (> 1024px):
- Three-column: Game visual left, Play-by-play center, Actions right
- Substitutions in sidebar drawer
5. Error Handling & Loading States
Time: 1 hour
Scenarios to Handle:
- WebSocket disconnection → Show reconnecting message
- Failed decisions → Display error, allow retry
- Failed dice roll → Show error message
- Failed outcome submission → Allow re-submission
- Failed substitution → Show reason, keep form open
- Game not found → Redirect to games list
- Not authorized → Redirect to login
Testing Strategy
Manual Testing Checklist
- Can join game as player
- Can join game as spectator
- Game state displays correctly
- Decision panels appear at correct times
- Can submit defensive decisions
- Can submit offensive decisions
- Can submit stolen base attempts
- Gameplay panel appears after decisions
- Can roll dice
- Dice results display correctly
- Can select and submit outcome
- Play result displays after submission
- Game state updates after play (scores, outs, runners)
- Can open substitution panel
- Can make pinch hitter substitution
- Can make defensive replacement
- Can make pitching change
- Substitutions reflect in lineup immediately
- Play-by-play updates in real-time
- Can play multiple complete turns
- Mobile layout works (375px)
- Tablet layout works (768px)
- Desktop layout works (1024px+)
- Error messages display correctly
- Reconnection works after disconnect
Integration Tests (Optional for F6)
Could add some integration tests, but main focus is ensuring all components work together manually.
E2E Tests (Future - Phase F7+)
End-to-end tests with Playwright/Cypress for complete game flows.
File Structure After Phase F6
frontend-sba/
├── components/
│ ├── Game/ ✅ Phase F2
│ │ ├── ScoreBoard.vue
│ │ ├── GameBoard.vue
│ │ ├── CurrentSituation.vue
│ │ └── PlayByPlay.vue
│ ├── Decisions/ ✅ Phase F3
│ │ ├── DefensiveSetup.vue
│ │ ├── StolenBaseInputs.vue
│ │ ├── OffensiveApproach.vue
│ │ └── DecisionPanel.vue
│ ├── Gameplay/ ✅ Phase F4
│ │ ├── DiceRoller.vue
│ │ ├── ManualOutcomeEntry.vue
│ │ ├── PlayResult.vue
│ │ └── GameplayPanel.vue
│ ├── Substitutions/ ✅ Phase F5
│ │ ├── PinchHitterSelector.vue
│ │ ├── DefensiveReplacementSelector.vue
│ │ ├── PitchingChangeSelector.vue
│ │ └── SubstitutionPanel.vue
│ └── UI/ ✅ Phase F3
│ ├── ActionButton.vue
│ ├── ButtonGroup.vue
│ └── ToggleSwitch.vue
├── pages/
│ ├── games/
│ │ └── [id].vue 🎯 Phase F6 (INTEGRATE ALL)
│ ├── demo.vue ✅ Phase F2
│ ├── demo-decisions.vue ✅ Phase F3
│ ├── demo-gameplay.vue ✅ Phase F4
│ └── demo-substitutions.vue ✅ Phase F5
├── composables/
│ ├── useGameState.ts 🔄 Enhance for F6
│ ├── useGameEvents.ts 🔄 Wire all events
│ ├── useGameActions.ts ✅ Complete
│ └── useWebSocket.ts ✅ Complete
└── store/
└── game.ts 🔄 Add phase management
Success Criteria for Phase F6
Phase F6 will be COMPLETE when:
Integration:
- ✅ All Phase F2-F5 components wired into game page
- ✅ Proper conditional rendering based on game phase
- ✅ State management working across all panels
- ✅ WebSocket events handled correctly
Functionality:
- ✅ Can play complete game turn from start to finish
- ✅ Decisions → Dice Roll → Outcome → Result flow works
- ✅ Substitutions can be made at any point
- ✅ Game state updates in real-time
- ✅ Multiple turns work in sequence
User Experience:
- ✅ Clear workflow progression
- ✅ Intuitive panel transitions
- ✅ Loading states during async operations
- ✅ Error messages helpful and actionable
- ✅ Mobile, tablet, desktop layouts all work
Testing:
- ✅ Manual testing checklist complete
- ✅ No TypeScript errors
- ✅ No console errors during gameplay
- ✅ WebSocket connection stable
Phase F6 → F7 Transition
After Phase F6, we'll have:
- Complete game display (Phase F2)
- Complete decision inputs (Phase F3)
- Complete dice rolling and outcome entry (Phase F4)
- Complete substitutions (Phase F5)
- Fully integrated game page (Phase F6)
Phase F7 Preview (Polish & Advanced Features):
- Game lobby system
- Game creation flow
- Spectator mode improvements
- Advanced analytics display
- Box score view
- Game history
- User preferences
- Performance optimization
- Accessibility improvements
- Final polish and bug fixes
Known Issues to Address
From Previous Phases
- Toast positioning bug (Phase F2) - Still using workaround
- Can implement proper UI store toast system in F6
- Not blocking work
- All 446 tests passing - Excellent test coverage maintained
Potential Phase F6 Issues
- State synchronization - Multiple panels updating same state
- Use Pinia store as single source of truth
- Ensure proper reactivity
- WebSocket event ordering - Events arriving out of sequence
- Already handled in composable with queuing
- Verify during integration
- Mobile performance - Multiple large components on one page
- Use v-if for conditional rendering (unmounts unused panels)
- Lazy load heavy components if needed
- Panel transitions - Smooth UX when switching phases
- Add transition animations
- Clear feedback for state changes
Quick Commands Reference
# Start dev server
cd /mnt/NV2/Development/strat-gameplay-webapp/frontend-sba
npm run dev
# Visit: http://localhost:3005
# View Phase F2 demo (Game Display)
# Visit: http://localhost:3005/demo
# View Phase F3 demo (Decisions)
# Visit: http://localhost:3005/demo-decisions
# View Phase F4 demo (Dice & Outcome)
# Visit: http://localhost:3005/demo-gameplay
# View Phase F5 demo (Substitutions)
# Visit: http://localhost:3005/demo-substitutions
# Run all tests
npm run test
# Run specific test suite
npm run test -- "tests/unit/components/Game"
# Type check
npm run type-check
# Build for production
npm run build
Test Summary
Total Tests: 446 passing (100%)
By Phase:
- Phase F3 (Decisions): 213 tests
- Phase F4 (Gameplay): 119 tests
- Phase F5 (Substitutions): 114 tests
- Total: 446 tests, all passing
Test Files:
tests/unit/
├── components/
│ ├── Decisions/
│ │ ├── DefensiveSetup.spec.ts (21 tests)
│ │ ├── StolenBaseInputs.spec.ts (29 tests)
│ │ ├── OffensiveApproach.spec.ts (22 tests)
│ │ └── DecisionPanel.spec.ts (68 tests)
│ ├── Gameplay/
│ │ ├── DiceRoller.spec.ts (27 tests)
│ │ ├── ManualOutcomeEntry.spec.ts (35 tests)
│ │ ├── PlayResult.spec.ts (21 tests)
│ │ └── GameplayPanel.spec.ts (36 tests)
│ ├── Substitutions/
│ │ ├── PinchHitterSelector.spec.ts (25 tests)
│ │ ├── DefensiveReplacementSelector.spec.ts (30 tests)
│ │ ├── PitchingChangeSelector.spec.ts (28 tests)
│ │ └── SubstitutionPanel.spec.ts (31 tests)
│ └── UI/
│ ├── ActionButton.spec.ts (23 tests)
│ ├── ButtonGroup.spec.ts (22 tests)
│ └── ToggleSwitch.spec.ts (23 tests)
└── store/
└── game-decisions.spec.ts (15 tests)
Context for AI Agent
You are continuing work on the SBa frontend (Strat-O-Matic Baseball Association web app).
Current State:
- Backend: 100% complete (731/731 tests, all WebSocket handlers)
- Phase F1: Foundation complete (composables, stores, types)
- Phase F2: Game display complete (4 components)
- Phase F3: Decision workflow complete (213 tests)
- Phase F4: Dice & outcome complete (119 tests)
- Phase F5: Substitutions complete (114 tests)
- Phase F6: Integration - Next to build
Your job: Integrate all Phase F2-F5 components into the main game page to create a fully functional gameplay experience.
Key Principles:
- Mobile-first design (60% of traffic expected)
- Type safety (TypeScript strict mode)
- Composition API (
<script setup>) - Explicit imports (Nuxt 4 requirement)
- State-driven UI (reactive to WebSocket events)
- No emojis unless user requests
Start Here:
- Review
pages/games/[id].vuecurrent state - Plan layout structure (mobile/tablet/desktop)
- Wire in DecisionPanel, GameplayPanel, SubstitutionPanel
- Connect all WebSocket event handlers
- Test complete game flow manually
Testing Approach:
- Focus on integration testing manually
- Verify all components work together
- Test on multiple screen sizes
- Ensure WebSocket events trigger correct UI updates
Document Version: 3.0 Last Updated: 2025-01-13 Phase: F6 (Integration & Game Page) - Starting Previous Phase: F5 Complete (114 tests passing) Total Tests: 446 passing (100%) Contributors: Claude (Jarvis), Cal Corum