# Composables Directory

Vue 3 composables for shared logic. These handle WebSocket communication and game actions.

## Available Composables

### useWebSocket.ts
**Purpose**: Manages Socket.io connection with authentication and auto-reconnection.

**Key Exports**:
```typescript
const {
  socket,           // Computed<TypedSocket | null>
  isConnected,      // Readonly<Ref<boolean>>
  isConnecting,     // Readonly<Ref<boolean>>
  connectionError,  // Readonly<Ref<string | null>>
  connect,          // () => void
  disconnect,       // () => void
} = useWebSocket()
```

**Event Flow** (Backend → Store):
```
socketInstance.on('game_state_update') → gameStore.setGameState()
socketInstance.on('lineup_data')       → gameStore.updateLineup()
socketInstance.on('decision_required') → gameStore.setDecisionPrompt()
socketInstance.on('play_completed')    → gameStore.addPlayToHistory()
socketInstance.on('dice_rolled')       → gameStore.setPendingRoll()
```

**Singleton Pattern**: Socket instance is module-level, shared across all `useWebSocket()` calls.

**Auto-Connect Pattern**: Uses `onMounted` hook (not `immediate: true` watcher) to connect when already authenticated. This is safer for SSR hydration:
```typescript
// Watch for auth changes (not immediate)
watch(() => authStore.isAuthenticated, (authenticated) => {
  if (authenticated && !isConnected.value) {
    connect()
  } else if (!authenticated && isConnected.value) {
    disconnect()
  }
})

// Initial connection on client-side mount
onMounted(() => {
  if (authStore.isAuthenticated && !isConnected.value) {
    connect()
  }
})
```

**Why not `immediate: true`?** Using `immediate: true` with `import.meta.client` guard can cause SSR hydration issues. The `onMounted` hook only runs on client-side, making it safer.

### useGameActions.ts
**Purpose**: Wraps WebSocket emits with type safety and validation.

**Key Exports**:
```typescript
const {
  joinGame,           // (gameId: string) => void
  requestGameState,   // (gameId: string) => void
  setDefense,         // (gameId: string, decision: DefensiveDecision) => void
  setOffense,         // (gameId: string, decision: OffensiveDecision) => void
  rollDice,           // (gameId: string) => void
  submitOutcome,      // (gameId: string, outcome: PlayOutcome) => void
  // ... substitution methods
} = useGameActions()
```

**Usage Pattern**:
```typescript
// In component
const { setDefense } = useGameActions()

const handleSubmit = (decision: DefensiveDecision) => {
  setDefense(gameId, decision)
}
```

## Data Flow Architecture

```
User Action → useGameActions → socket.emit() → Backend
                                                  ↓
Component ← gameStore ← useWebSocket.on() ← socket event
```

**Why this separation?**
- `useWebSocket`: Low-level connection management, event routing
- `useGameActions`: High-level game operations, business logic validation
- `gameStore`: Centralized state, computed getters

## Common Issues

| Issue | Cause | Solution |
|-------|-------|----------|
| "Not connected" error | Socket disconnected | Check `isConnected` before actions |
| Events not firing | Listeners not set up | Ensure `useWebSocket()` called in component |
| Stale data | Missed reconnection | Call `requestGameState()` after reconnect |
