Switch to Svelte
This commit is contained in:
131
frontend/src/components/SceneSetupPhase.svelte
Normal file
131
frontend/src/components/SceneSetupPhase.svelte
Normal file
@@ -0,0 +1,131 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import { apiRequest } from '../lib/api';
|
||||
|
||||
export let state;
|
||||
|
||||
let settingRole = false;
|
||||
let starting = false;
|
||||
let error = '';
|
||||
let allowedRoles = ['pirat', 'deep'];
|
||||
|
||||
onMount(async () => {
|
||||
try {
|
||||
const res = await apiRequest(`/game/${state.game.id}/player/${state.player.id}/allowed-roles`, 'GET');
|
||||
allowedRoles = res.allowed_roles;
|
||||
} catch(e) {
|
||||
console.error("Failed to load allowed roles", e);
|
||||
}
|
||||
});
|
||||
|
||||
async function setRole(role) {
|
||||
settingRole = true;
|
||||
try {
|
||||
await apiRequest(`/game/${state.game.id}/player/${state.player.id}/set-role`, 'POST', { role });
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
settingRole = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function startScene() {
|
||||
starting = true;
|
||||
error = '';
|
||||
try {
|
||||
await apiRequest(`/game/${state.game.id}/scene/start`, 'POST');
|
||||
} catch(e) {
|
||||
error = e.message;
|
||||
starting = false;
|
||||
}
|
||||
}
|
||||
|
||||
$: allRolesAssigned = state.players.every(p => p.role !== null);
|
||||
$: deepPlayer = state.players.find(p => p.role === 'deep');
|
||||
$: piratPlayer = state.players.find(p => p.role === 'pirat');
|
||||
$: canStart = allRolesAssigned && deepPlayer && piratPlayer && (state.player.is_creator || state.player.role === 'deep');
|
||||
</script>
|
||||
|
||||
<div class="scene-setup-view text-center">
|
||||
<h2>Scene Setup (Scene #{state.game.current_scene_number})</h2>
|
||||
<p class="description">Select your role for the upcoming scene. There must be at least one Pi-Rat and one Deep player. If you played the Deep in the last scene, you must play a Pi-Rat this scene!</p>
|
||||
|
||||
<div class="setup-grid">
|
||||
<!-- Role Selection Card -->
|
||||
<div class="card glass-panel role-selection-card">
|
||||
<h3>Select Your Role</h3>
|
||||
|
||||
<div class="role-buttons">
|
||||
<button on:click={() => setRole('pirat')}
|
||||
disabled={settingRole || !allowedRoles.includes('pirat')}
|
||||
class="btn btn-large role-btn pirat-btn {state.player.role === 'pirat' ? 'active' : ''}">
|
||||
🐀 Play Pi-Rat
|
||||
</button>
|
||||
|
||||
<button on:click={() => setRole('deep')}
|
||||
disabled={settingRole || !allowedRoles.includes('deep')}
|
||||
class="btn btn-large role-btn deep-btn {state.player.role === 'deep' ? 'active' : ''}">
|
||||
🌊 Play the Deep
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="role-restrictions mt-4">
|
||||
{#if !allowedRoles.includes('pirat')}
|
||||
{#if state.game.current_scene_number === 1}
|
||||
<p class="text-red-400 text-sm italic">You are the highest ranked player, so you must play The Deep for the first scene!</p>
|
||||
{:else}
|
||||
<p class="text-red-400 text-sm italic">You are the only eligible player for The Deep this scene!</p>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if !allowedRoles.includes('deep')}
|
||||
{#if state.game.current_scene_number === 1}
|
||||
<p class="text-red-400 text-sm italic">Only the highest ranked player(s) can play The Deep in the first scene!</p>
|
||||
{:else}
|
||||
<p class="text-red-400 text-sm italic">You played The Deep last scene, so you must play a Pi-Rat!</p>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Live Roster Card -->
|
||||
<div class="card glass-panel roster-card">
|
||||
<h3>Live Roster Selection</h3>
|
||||
<div class="roster-list" id="scene-roster-list">
|
||||
{#each state.players as p}
|
||||
<div class="roster-item">
|
||||
<span class="player-name">{p.name} <span class="text-sm text-gray-400">(Rank {p.rank})</span></span>
|
||||
{#if p.role === 'pirat'}
|
||||
<span class="role-badge pirat">Pi-Rat</span>
|
||||
{:else if p.role === 'deep'}
|
||||
<span class="role-badge deep">The Deep</span>
|
||||
{:else}
|
||||
<span class="role-badge unassigned">Choosing...</span>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="action-box margin-top">
|
||||
{#if error}
|
||||
<div class="alert alert-danger">{error}</div>
|
||||
{/if}
|
||||
|
||||
{#if canStart}
|
||||
<button on:click={startScene}
|
||||
disabled={starting}
|
||||
class="btn btn-primary btn-large glow-effect">
|
||||
{starting ? 'Starting Scene...' : 'Confirm Roles & Shuffle Deck'}
|
||||
</button>
|
||||
{:else if !allRolesAssigned}
|
||||
<p class="text-gray-400 italic mt-4">Waiting for all players to choose a role...</p>
|
||||
{:else if !deepPlayer}
|
||||
<p class="text-red-400 italic mt-4">Someone must play as The Deep!</p>
|
||||
{:else if !piratPlayer}
|
||||
<p class="text-red-400 italic mt-4">Someone must play as a Pi-Rat!</p>
|
||||
{:else}
|
||||
<p class="text-gray-400 italic mt-4">Waiting for The Deep or Creator to start the scene...</p>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user