strat-gameplay-webapp/frontend-sba/components/Decisions/DecisionPanel.vue
Cal Corum 187bd1ccae CLAUDE: Fix offensive action conditional rendering, remove emojis, always show hold pills
- OffensiveApproach: read game state from store (fix same prop-passing bug as DefensiveSetup),
  remove steal option (check_jump encompasses it), hide unavailable actions instead of disabling,
  fix conditions (sac/squeeze: <2 outs + runners, hit-and-run: R1/R3 not R2-only)
- Remove all emoji icons from decision components (OffensiveApproach, DefensiveSetup, DecisionPanel)
- RunnerCard: always show hold/not-held pills on occupied bases (status indicator in all phases)
- DecisionPanel: remove dead hasRunnersOnBase computed and prop pass-through
- Rewrite OffensiveApproach tests (32 new tests with Pinia store integration)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 15:47:33 -06:00

146 lines
4.1 KiB
Vue

<template>
<div class="space-y-4">
<!-- Decision Phase Content -->
<div v-if="phase !== 'idle'" class="space-y-4">
<!-- Defensive Phase -->
<template v-if="phase === 'defensive'">
<DefensiveSetup
:game-id="gameId"
:is-active="isMyTurn"
:current-setup="currentDefensiveSetup"
@submit="handleDefensiveSubmit"
/>
</template>
<!-- Offensive Phase -->
<template v-if="phase === 'offensive'">
<!-- Offensive Approach -->
<OffensiveApproach
:game-id="gameId"
:is-active="isMyTurn"
:current-decision="currentOffensiveDecision"
@submit="handleOffensiveSubmit"
/>
</template>
<!-- Decision History (Collapsible) -->
<div
v-if="decisionHistory.length > 0"
class="bg-white dark:bg-gray-800 rounded-xl shadow-lg overflow-hidden"
>
<button
type="button"
class="w-full px-6 py-3 flex items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors"
@click="historyExpanded = !historyExpanded"
>
<span class="font-semibold text-gray-900 dark:text-white">
Recent Decisions
</span>
<span class="text-gray-500 dark:text-gray-400">
{{ historyExpanded ? '▼' : '▶' }}
</span>
</button>
<div
v-show="historyExpanded"
class="border-t border-gray-200 dark:border-gray-700 p-4 space-y-2"
>
<div
v-for="(decision, index) in recentDecisions"
:key="index"
class="bg-gray-50 dark:bg-gray-700/50 rounded-lg p-3 text-sm"
>
<div class="flex items-start justify-between gap-2">
<div class="flex-1">
<div class="font-medium text-gray-900 dark:text-white">
{{ decision.type }} Decision
</div>
<div class="text-xs text-gray-500 dark:text-gray-400 mt-1">
{{ decision.summary }}
</div>
</div>
<div class="text-xs text-gray-400 dark:text-gray-500">
{{ decision.timestamp }}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Idle State -->
<div
v-else
class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-8 text-center"
>
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-2">
Waiting for Play
</h3>
<p class="text-sm text-gray-600 dark:text-gray-400">
No decisions required at this time
</p>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import type { DefensiveDecision, OffensiveDecision } from '~/types/game'
import DefensiveSetup from './DefensiveSetup.vue'
import OffensiveApproach from './OffensiveApproach.vue'
interface DecisionHistoryItem {
type: 'Defensive' | 'Offensive'
summary: string
timestamp: string
}
interface Props {
gameId: string
currentTeam: 'home' | 'away'
isMyTurn: boolean
phase: 'defensive' | 'offensive' | 'idle'
runners?: {
first: number | null
second: number | null
third: number | null
}
currentDefensiveSetup?: DefensiveDecision
currentOffensiveDecision?: Omit<OffensiveDecision, 'steal_attempts'>
decisionHistory?: DecisionHistoryItem[]
}
const props = withDefaults(defineProps<Props>(), {
phase: 'idle',
runners: () => ({
first: null,
second: null,
third: null,
}),
decisionHistory: () => [],
})
const emit = defineEmits<{
defensiveSubmit: [decision: DefensiveDecision]
offensiveSubmit: [decision: Omit<OffensiveDecision, 'steal_attempts'>]
}>()
// Local state
const historyExpanded = ref(false)
// Computed
const recentDecisions = computed(() => {
return props.decisionHistory.slice(0, 3)
})
// Event handlers
const handleDefensiveSubmit = (decision: DefensiveDecision) => {
emit('defensiveSubmit', decision)
}
const handleOffensiveSubmit = (decision: Omit<OffensiveDecision, 'steal_attempts'>) => {
emit('offensiveSubmit', decision)
}
</script>