strat-gameplay-webapp/frontend-sba/components/CLAUDE.md
Cal Corum cbdd8cf903 CLAUDE: Fix critical game engine issues and refactor CLAUDE.md docs
Critical fixes in game_engine.py:
- Fix silent error swallowing in _batch_save_inning_rolls (re-raise)
- Add per-game asyncio.Lock for race condition prevention
- Add _cleanup_game_resources() for memory leak prevention
- All 739 tests passing

Documentation refactoring:
- Created CODE_REVIEW_GAME_ENGINE.md documenting 24 identified issues
- Trimmed backend/app/core/CLAUDE.md from 1371 to 143 lines
- Trimmed frontend-sba/CLAUDE.md from 696 to 110 lines
- Created focused subdirectory CLAUDE.md files:
  - frontend-sba/components/CLAUDE.md (105 lines)
  - frontend-sba/composables/CLAUDE.md (79 lines)
  - frontend-sba/store/CLAUDE.md (116 lines)
  - frontend-sba/types/CLAUDE.md (95 lines)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 16:05:26 -06:00

3.1 KiB

Components Directory

Vue 3 components organized by feature domain. All use <script setup lang="ts"> with Composition API.

Directory Structure

Game/ - Core Game Display

Component Purpose Key Props
ScoreBoard.vue Sticky header with inning/score/count gameState
GameBoard.vue Baseball diamond with runners gameState
CurrentSituation.vue Pitcher vs Batter cards currentPitcher, currentBatter
PlayByPlay.vue Animated play history feed plays

Data Pattern: These receive LineupPlayerState from gameStore, then use findPlayerInLineup() to get full player data (name, headshot).

Decisions/ - Strategic Decision Input

Component Purpose Emits
DecisionPanel.vue Container for decision workflow -
DefensiveSetup.vue Infield/outfield positioning submit
OffensiveApproach.vue Batting action selection submit
StolenBaseInputs.vue Per-runner steal attempts submit

Data Pattern: Read currentDecisionPrompt from store, emit decisions to parent which calls useGameActions.

Substitutions/ - Player Replacement

Component Purpose Emits
SubstitutionPanel.vue Main substitution container close
PinchHitterSelector.vue Replace batter substitute
PitchingChangeSelector.vue Replace pitcher substitute
DefensiveReplacementSelector.vue Position switch substitute

Data Pattern: Filter homeLineup/awayLineup for active vs bench players.

UI/ - Reusable Primitives

Component Purpose
ActionButton.vue Styled action button with loading state
ButtonGroup.vue Radio-button style group selector
ToggleSwitch.vue Boolean toggle with labels

Component Standards

<template>
  <!-- Always wrap in single root -->
  <div class="component-name">
    <!-- Content -->
  </div>
</template>

<script setup lang="ts">
// 1. Imports
import { computed } from 'vue'
import { useGameStore } from '~/store/game'

// 2. Props/Emits with TypeScript
interface Props {
  gameId: string
}
const props = defineProps<Props>()

const emit = defineEmits<{
  submit: [data: SomeType]
}>()

// 3. Store access
const gameStore = useGameStore()

// 4. Computed/methods
</script>

<style scoped>
/* Tailwind @apply preferred */
</style>

Common Patterns

Two-Step Player Lookup

// GameState has LineupPlayerState (minimal)
const batterState = computed(() => gameStore.currentBatter)

// Get full Lineup with player details
const batterLineup = computed(() => {
  if (!batterState.value) return null
  return gameStore.findPlayerInLineup(batterState.value.lineup_id)
})

// Access player data
const batterName = computed(() => batterLineup.value?.player.name ?? 'Unknown')
const batterHeadshot = computed(() => batterLineup.value?.player.headshot)

Conditional Rendering by Team

const isMyTurn = computed(() => {
  // Check if current user's team needs to act
  return gameStore.battingTeamId === myTeamId
})