PokeR/src/lib/components/PlayerSeat.svelte
Veit F. bcb5465247 feat: implement foundational poker table with game engine and UI
Add complete Texas Hold'em poker gameplay including:
- Pure function game engine (deck, dealing, betting, showdown)
- Hand evaluator supporting all 10 poker hand ranks
- Animated card components with 3D flip transitions
- CSS Grid oval poker table layout for up to 9 seats
- Player seat components with chip tracking and turn indicators
- Bet controls with conditional button visibility
- Basic AI opponents with random valid action selection
- Turn advancement, all-in auto-advance, and dealer rotation

Sync delta specs to main specs: poker-table, card-components,
game-engine, player-state.
2026-05-17 17:28:38 +02:00

104 lines
2.0 KiB
Svelte

<script lang="ts">
import Card from './Card.svelte';
import type { PlayerSeat as PlayerSeatType } from '$lib/types/player';
let { player, isCurrentTurn = false, isHuman = false }: {
player: PlayerSeatType;
isCurrentTurn?: boolean;
isHuman?: boolean;
} = $props();
const showCards = $derived(isHuman || player.holeCards.length === 0);
</script>
<div class="seat" class:active={isCurrentTurn} class:folded={player.status === 'folded'}>
{#if player.holeCards.length > 0}
<div class="hole-cards">
{#each player.holeCards as card (card.rank + card.suit)}
<Card {card} flipped={!showCards} />
{/each}
</div>
{/if}
<div class="info">
<span class="name">{player.name}</span>
<span class="chips">${player.chips}</span>
{#if player.currentBet > 0}
<span class="bet">${player.currentBet}</span>
{/if}
</div>
{#if player.status === 'folded'}
<span class="status-badge">FOLD</span>
{/if}
{#if player.status === 'all-in'}
<span class="status-badge all-in">ALL-IN</span>
{/if}
</div>
<style>
.seat {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
padding: 8px;
border-radius: 8px;
transition: all 0.3s ease;
position: relative;
}
.seat.active {
background: rgba(255, 255, 0, 0.1);
box-shadow: 0 0 12px rgba(255, 255, 0, 0.4);
}
.seat.folded {
opacity: 0.4;
}
.hole-cards {
display: flex;
gap: 4px;
}
.info {
text-align: center;
font-size: 12px;
color: #ecf0f1;
}
.name {
font-weight: 600;
display: block;
margin-bottom: 2px;
}
.chips {
background: rgba(0, 0, 0, 0.5);
padding: 2px 8px;
border-radius: 10px;
font-size: 11px;
}
.bet {
display: block;
color: #f1c40f;
font-weight: 600;
margin-top: 2px;
}
.status-badge {
font-size: 9px;
font-weight: 700;
padding: 1px 6px;
border-radius: 4px;
background: #e74c3c;
color: white;
}
.status-badge.all-in {
background: #f39c12;
}
</style>