Files
pirats/frontend/src/components/ScenePhase.svelte
2026-06-11 21:32:00 -07:00

104 lines
6.2 KiB
Svelte

<script>
import Card from './Card.svelte';
import ChallengePanel from './scene/ChallengePanel.svelte';
import ObstacleBoard from './scene/ObstacleBoard.svelte';
import DeepControlPanel from './scene/DeepControlPanel.svelte';
import CharacterSheet from './scene/CharacterSheet.svelte';
import EventLog from './EventLog.svelte';
export let state;
$: hand = state.player.hand_cards ? JSON.parse(state.player.hand_cards) : [];
$: captain = state.players.find(p => p.id === state.game.captain_player_id) || null;
$: isCaptain = state.game.captain_player_id === state.player.id;
$: playerTechs = { J: state.player.tech_jack, Q: state.player.tech_queen, K: state.player.tech_king };
</script>
<div class="scene-view-layout" id="scene-layout-container" data-game-id={state.game.id} data-player-id={state.player.id}>
<!-- LEFT COLUMN: The Shared Table -->
<div class="table-column">
<!-- Game Deck and Obstacles Roster -->
<div class="card glass-panel obstacle-list-card">
<div class="card-header">
<h3>🌊 The Obstacle List</h3>
<span class="deck-counter">🎴 Deck: {state.game.deck_cards ? JSON.parse(state.game.deck_cards).length : 0} cards left</span>
</div>
<div class="obstacles-container" id="scene-obstacles-container">
<!-- TOP STATUS BAR: Scene Info and Captain -->
<div class="scene-status-banner glass-panel" style="margin-bottom: 1.5rem; padding: 1rem; background: rgba(7, 11, 18, 0.6); border: 1px solid rgba(212, 175, 55, 0.2); border-radius: 8px;">
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1rem;">
<!-- Captain Badge -->
<div>
{#if captain}
<span class="captain-badge" style="background: rgba(212, 175, 55, 0.15); border: 1px solid var(--gold); color: var(--gold); padding: 0.4rem 1rem; border-radius: 20px; font-size: 1rem; font-weight: 700; font-family: var(--font-heading); display: inline-flex; align-items: center; gap: 0.5rem;">
🏴‍☠️ Captain: {captain.name} (Rank {captain.rank}){isCaptain ? ' — You!' : ''}
</span>
{:else}
<span class="captain-badge" style="background: rgba(255, 255, 255, 0.05); border: 1px dashed rgba(255, 255, 255, 0.2); color: var(--text-muted); padding: 0.4rem 1rem; border-radius: 20px; font-size: 1rem; display: inline-flex; align-items: center; gap: 0.5rem;">
🏴‍☠️ Captain: None{state.game.completed_crew_1 ? '' : ' (steal a ship first!)'}
</span>
{/if}
</div>
<!-- Active Scene Roster Mini-list -->
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center;">
<span style="font-size: 0.85rem; color: var(--text-muted); font-family: var(--font-heading); margin-right: 0.25rem;">Active Roster:</span>
{#each state.players as p}
{#if p.role === 'deep'}
<span class="player-chip deep-chip" style="font-size: 0.8rem; padding: 0.25rem 0.6rem; border-radius: 12px; margin: 0; display: inline-flex; align-items: center; gap: 0.25rem;">
🌊 {p.name} (Deep)
</span>
{:else if p.role === 'pirat'}
<span class="player-chip pirat-chip" style="font-size: 0.8rem; padding: 0.25rem 0.6rem; border-radius: 12px; margin: 0; display: inline-flex; align-items: center; gap: 0.25rem; {p.is_ghost ? 'border-color: #7890a8; color: #a0b0c0; background: rgba(120, 150, 180, 0.1);' : ''} {p.is_dead ? 'border-color: var(--red-suit); color: var(--red-suit); background: rgba(255, 42, 95, 0.1);' : ''} {p.id === state.game.captain_player_id ? 'border-color: var(--gold); color: var(--gold); background: rgba(212, 175, 55, 0.1);' : ''}">
{#if p.is_ghost}👻{:else if p.is_dead}💀{:else}🐀{/if} {p.name} (Rank {p.rank}){p.id === state.game.captain_player_id ? ' ⭐' : ''}
</span>
{/if}
{/each}
</div>
</div>
</div>
<ChallengePanel {state} />
<ObstacleBoard {state} />
</div>
</div>
</div>
<!-- RIGHT COLUMN: Private Hand & Character Sheet -->
<div class="private-column">
{#if state.player.role === "deep"}
<DeepControlPanel {state} />
{/if}
<!-- Player Hand Card -->
<div class="card glass-panel hand-card">
<h3>🃏 Your Hand</h3>
<p class="section-desc">Keep your cards secret! {#if state.player.role !== "deep"}When the Deep challenges you (or you assist a crewmate), drag a card onto an applied obstacle to play it. Jokers can hit any obstacle, any time.{/if}</p>
<div class="hand-flex">
{#each hand as card}
<Card {card} techs={playerTechs}
draggable={state.player.role !== "deep"}
on:dragstart={(e) => {
e.dataTransfer.setData('text/plain', card);
e.currentTarget.classList.add("dragging");
}}
on:dragend={(e) => {
e.currentTarget.classList.remove("dragging");
}} />
{:else}
<p class="empty-text text-center">Your hand is empty! (You draw cards when playing cards that match the suit color of the obstacle.)</p>
{/each}
</div>
</div>
{#if state.player.role !== "deep"}
<CharacterSheet {state} />
{/if}
</div>
</div>
<EventLog {state} />