Keep crew roster in a consistent sidebar
This commit is contained in:
@@ -162,20 +162,3 @@
|
||||
text-align: left;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.crew-epitaph-row {
|
||||
background: var(--well);
|
||||
padding: 0.75rem;
|
||||
border-radius: var(--radius-sm);
|
||||
margin-bottom: 0.5rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.crew-epitaph-row .objectives-summary {
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
@@ -70,6 +70,23 @@ input[type="checkbox"] {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.phase-view-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 180px minmax(0, 1fr);
|
||||
gap: 1.5rem;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.phase-main-column {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.phase-view-layout {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.dashboard-container {
|
||||
padding: 3.5rem 1rem 4rem;
|
||||
|
||||
@@ -104,22 +104,6 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Crew creation progress rows */
|
||||
.status-row {
|
||||
background: var(--well);
|
||||
border-left: 4px solid var(--edge);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 0.75rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.status-row.is-ready {
|
||||
border-left-color: var(--success);
|
||||
}
|
||||
|
||||
/* --- Character sheet layout --- */
|
||||
.character-sheet-details {
|
||||
text-align: left;
|
||||
|
||||
@@ -293,49 +293,6 @@
|
||||
color: color-mix(in srgb, var(--danger) 75%, var(--text));
|
||||
}
|
||||
|
||||
/* --- Player chips --- */
|
||||
.player-chips {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.player-chip {
|
||||
background: color-mix(in srgb, var(--text) 6%, transparent);
|
||||
border: 1px solid var(--edge);
|
||||
padding: 0.5rem 1.25rem;
|
||||
border-radius: var(--radius-md);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
transition: var(--transition-smooth);
|
||||
}
|
||||
|
||||
.player-chip.current-user {
|
||||
background: color-mix(in srgb, var(--accent) 14%, transparent);
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.player-chip.voted-chip {
|
||||
border-color: var(--success);
|
||||
background-color: color-mix(in srgb, var(--success) 6%, transparent);
|
||||
}
|
||||
|
||||
.player-chip.not-voted-chip {
|
||||
border-color: var(--edge);
|
||||
}
|
||||
|
||||
.list-chips {
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.list-chips .player-chip {
|
||||
padding: 0.4rem 1rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.deep-chip {
|
||||
border-color: var(--deep);
|
||||
background: color-mix(in srgb, var(--deep) 5%, transparent);
|
||||
@@ -346,24 +303,6 @@
|
||||
background: color-mix(in srgb, var(--pirat) 5%, transparent);
|
||||
}
|
||||
|
||||
.player-chip.is-ghost {
|
||||
border-color: var(--ghost);
|
||||
color: var(--ghost);
|
||||
background: color-mix(in srgb, var(--ghost) 10%, transparent);
|
||||
}
|
||||
|
||||
.player-chip.is-dead {
|
||||
border-color: var(--danger);
|
||||
color: var(--danger);
|
||||
background: color-mix(in srgb, var(--danger) 10%, transparent);
|
||||
}
|
||||
|
||||
.player-chip.is-captain {
|
||||
border-color: var(--accent);
|
||||
color: var(--accent);
|
||||
background: color-mix(in srgb, var(--accent) 10%, transparent);
|
||||
}
|
||||
|
||||
/* --- Badges --- */
|
||||
.creator-badge {
|
||||
background: var(--accent);
|
||||
|
||||
@@ -4,10 +4,6 @@
|
||||
margin: 2rem auto;
|
||||
}
|
||||
|
||||
.lobby-status-box {
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.links-box {
|
||||
text-align: left;
|
||||
margin-bottom: 2rem;
|
||||
|
||||
@@ -88,6 +88,15 @@
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
.crew-bubble.is-static {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.crew-bubble.is-static:hover {
|
||||
background: var(--surface-raised);
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.crew-bubble.is-deep {
|
||||
border-left-color: var(--deep);
|
||||
background: color-mix(in srgb, var(--deep) 12%, var(--surface-raised));
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.setup-grid.single {
|
||||
grid-template-columns: minmax(0, 700px);
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.setup-grid {
|
||||
grid-template-columns: 1fr;
|
||||
@@ -63,19 +68,3 @@
|
||||
border: 1px dashed var(--edge);
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.roster-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.roster-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
background: var(--well);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 0.6rem 0.9rem;
|
||||
}
|
||||
|
||||
@@ -566,39 +566,5 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- SECTION 5: Crew Creation Progress -->
|
||||
<div class="card glass-panel section-crew-status" style="grid-column: span 2;">
|
||||
<h3>V. Crew Creation Status</h3>
|
||||
<p class="section-desc">See the creation progress of the entire crew in real time.</p>
|
||||
<div class="crew-status-list">
|
||||
<ul class="space-y-2 mt-4">
|
||||
{#each state.players as p}
|
||||
<li class="status-row {p.tech_jack ? 'is-ready' : ''}">
|
||||
<span>{displayName(p)}</span>
|
||||
<span class="text-sm">
|
||||
{#if p.needs_reroll}
|
||||
<span class="text-muted">Spectating</span>
|
||||
{:else if phase === 'swap_techniques'}
|
||||
{#if p.is_ready}
|
||||
<span class="text-success">Done Swapping</span>
|
||||
{:else}
|
||||
{@const ownLeft = JSON.parse(p.held_techniques || '[]').filter(t => t.creator_id === p.id).length}
|
||||
<span class="text-warning">Swapping ({ownLeft} of their own left)</span>
|
||||
{/if}
|
||||
{:else if p.tech_jack}
|
||||
<span class="text-success">Ready</span>
|
||||
{:else if phase === 'assign_techniques'}
|
||||
<span class="text-warning">Assigning Face Cards</span>
|
||||
{:else if p.created_techniques && JSON.parse(p.created_techniques).length === 3}
|
||||
<span class="text-warning">Techniques Submitted</span>
|
||||
{:else}
|
||||
<span class="text-muted">Writing Sheet</span>
|
||||
{/if}
|
||||
</span>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
97
frontend/src/components/CrewSidebar.svelte
Normal file
97
frontend/src/components/CrewSidebar.svelte
Normal file
@@ -0,0 +1,97 @@
|
||||
<script>
|
||||
import { displayName, crewLabel } from '../lib/cards';
|
||||
import CharacterSheet from './scene/CharacterSheet.svelte';
|
||||
|
||||
export let state;
|
||||
|
||||
let openTargetId = null;
|
||||
|
||||
$: captainId = state.game.captain_player_id;
|
||||
$: crew = [...state.players].sort((a, b) => (a.role === 'deep' ? 1 : 0) - (b.role === 'deep' ? 1 : 0));
|
||||
$: openTarget = openTargetId ? state.players.find(p => p.id === openTargetId) : null;
|
||||
|
||||
function iconFor(p) {
|
||||
if (p.role === 'deep') return '🌊';
|
||||
if (p.is_ghost) return '👻';
|
||||
if (p.is_dead) return '💀';
|
||||
return '🐀';
|
||||
}
|
||||
|
||||
function safeArray(value) {
|
||||
try { return JSON.parse(value || '[]'); } catch { return []; }
|
||||
}
|
||||
|
||||
function statusFor(p) {
|
||||
const phase = state.game.phase;
|
||||
if (phase === 'lobby') {
|
||||
if (p.is_creator) return 'Creator';
|
||||
if (p.is_admin) return 'Admin';
|
||||
return 'Crew member';
|
||||
}
|
||||
if (phase === 'character_creation') {
|
||||
if (p.needs_reroll) return 'Spectating';
|
||||
return safeArray(p.created_techniques).length === 3 ? 'Techniques submitted' : 'Writing sheet';
|
||||
}
|
||||
if (phase === 'swap_techniques') {
|
||||
if (p.is_ready) return 'Done swapping';
|
||||
const ownLeft = safeArray(p.held_techniques).filter(t => t.creator_id === p.id).length;
|
||||
return `Swapping · ${ownLeft} own left`;
|
||||
}
|
||||
if (phase === 'assign_techniques') return p.tech_jack ? 'Ready' : 'Assigning face cards';
|
||||
if (phase === 'scene_setup') {
|
||||
if (p.needs_reroll) return 'Spectating';
|
||||
if (p.role === 'deep') return 'The Deep';
|
||||
if (p.role === 'pirat') return `Pi-Rat · Rank ${p.rank}`;
|
||||
return 'Choosing a role…';
|
||||
}
|
||||
if (phase === 'between_scenes') {
|
||||
const voted = (state.votes || []).some(v => v.voter_player_id === p.id);
|
||||
const canVote = state.players.some(candidate =>
|
||||
candidate.id !== p.id && candidate.role !== 'deep' && !candidate.is_dead && !candidate.needs_reroll
|
||||
);
|
||||
return `Rank ${p.rank} · ${voted ? 'Nomination done' : canVote ? 'Nominating…' : 'No vote'}`;
|
||||
}
|
||||
if (phase === 'deep_upkeep') return `Rank ${p.rank} · ${p.is_ready ? 'Ready' : 'Finishing upkeep…'}`;
|
||||
if (phase === 'recruit_creation') return p.needs_reroll ? 'Creating a new Pi-Rat' : `Rank ${p.rank} · Helping recruits`;
|
||||
if (phase === 'ended') {
|
||||
const story = p.completed_personal_3 ? 'Story complete' : 'Still sailing';
|
||||
return `Rank ${p.rank} · ${story}`;
|
||||
}
|
||||
return `Rank ${p.rank}`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<aside class="crew-column phase-crew-column" aria-label="Crew roster">
|
||||
<div class="crew-bubbles">
|
||||
{#each crew as p (p.id)}
|
||||
{#if state.game.phase === 'lobby'}
|
||||
<div
|
||||
class="crew-bubble is-static"
|
||||
class:is-you={p.id === state.player.id}
|
||||
>
|
||||
<span class="bubble-icon">{iconFor(p)}</span>
|
||||
<span class="bubble-name">{displayName(p)}</span>
|
||||
<span class="bubble-meta">{statusFor(p)}</span>
|
||||
</div>
|
||||
{:else}
|
||||
<button
|
||||
class="crew-bubble"
|
||||
class:is-you={p.id === state.player.id}
|
||||
class:is-deep={p.role === 'deep'}
|
||||
class:is-dead={p.is_dead}
|
||||
class:is-ghost={p.is_ghost}
|
||||
title="View {p.name}'s character sheet"
|
||||
on:click={() => openTargetId = p.id}
|
||||
>
|
||||
<span class="bubble-icon">{iconFor(p)}</span>
|
||||
<span class="bubble-name">{crewLabel(p, captainId)}</span>
|
||||
<span class="bubble-meta">{statusFor(p)}</span>
|
||||
</button>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
{#if openTarget}
|
||||
<CharacterSheet {state} target={openTarget} on:close={() => openTargetId = null} />
|
||||
{/if}
|
||||
@@ -1,9 +1,6 @@
|
||||
<script>
|
||||
import { displayName } from '../lib/cards';
|
||||
|
||||
export let state;
|
||||
|
||||
$: pirats = state.players;
|
||||
$: crewDone = state.game.completed_crew_1 && state.game.completed_crew_2 && state.game.completed_crew_3;
|
||||
</script>
|
||||
|
||||
@@ -29,24 +26,6 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="sheet-group">
|
||||
<h3 class="text-accent">The Crew</h3>
|
||||
{#each pirats as p}
|
||||
<div class="crew-epitaph-row">
|
||||
<span>
|
||||
{#if p.is_ghost}👻{:else if p.is_dead}💀{:else}🐀{/if}
|
||||
<strong>{displayName(p)}</strong> (Rank {p.rank})
|
||||
{#if p.id === state.game.captain_player_id}<span class="text-accent"> ⭐ Captain</span>{/if}
|
||||
</span>
|
||||
<span class="objectives-summary">
|
||||
{p.completed_personal_1 ? '🔫 Gat' : '— no gat'} ·
|
||||
{p.completed_personal_2 ? '📛 Named' : '— nameless'} ·
|
||||
{p.completed_personal_3 ? '⚰️ Story complete' : '⛵ Still sailing'}
|
||||
</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<p class="info-text" style="margin-top: 2rem;">Want more? Get the full game "The Magical Land of Yeld" at YeldStuff.com!</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -43,20 +43,6 @@
|
||||
<h2>{state.game.crew_name || "Ship's Hold"} (Lobby)</h2>
|
||||
<p class="description">Wait here as the mathematical mages gather stowaway rats for the spell. Once everyone is in, the captain will initiate the transformation.</p>
|
||||
|
||||
<div class="lobby-status-box glass-panel">
|
||||
<h3>Joined Crew members</h3>
|
||||
<div class="player-chips" id="lobby-player-list">
|
||||
{#each state.players as p}
|
||||
<div class="player-chip {p.id === state.player.id ? 'current-user' : ''}">
|
||||
<span class="avatar-icon">🐀</span>
|
||||
<span class="name">{p.name}</span>
|
||||
{#if p.is_creator}<span class="creator-badge">Creator</span>
|
||||
{:else if p.is_admin}<span class="creator-badge">Admin</span>{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="links-box glass-panel">
|
||||
{#if state.player.is_admin}
|
||||
<div class="link-item lobby-join-code-item">
|
||||
|
||||
@@ -135,16 +135,6 @@
|
||||
techSlots: incomingTechs(p).map((s, i) => ({ ...s, slot: i })).filter(s => s.from_id === me.id)
|
||||
})).filter(t => t.like || t.hate || t.techSlots.length > 0);
|
||||
|
||||
function recruitProgress(p) {
|
||||
const techs = incomingTechs(p);
|
||||
const parts = [];
|
||||
parts.push(p.avatar_look && p.avatar_smell && p.first_words && p.good_at_math ? '✅ Records' : '❌ Records');
|
||||
const likeOk = !p.other_like_from_player_id || p.other_like;
|
||||
const hateOk = !p.other_hate_from_player_id || p.other_hate;
|
||||
parts.push(likeOk && hateOk ? '✅ Like/Hate' : '❌ Like/Hate');
|
||||
parts.push(`${techs.filter(s => s.text).length}/3 Techniques`);
|
||||
return parts.join(' · ');
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="recruit-phase-view">
|
||||
@@ -321,22 +311,5 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- RECRUIT PROGRESS -->
|
||||
<div class="card glass-panel section-crew-status" style="grid-column: span 2;">
|
||||
<h3>{iAmRecruit ? 'V.' : 'II.'} Recruit Progress</h3>
|
||||
<div class="crew-status-list">
|
||||
<ul class="space-y-2 mt-4">
|
||||
{#each recruits as p}
|
||||
<li class="status-row">
|
||||
<span>{displayName(p)}</span>
|
||||
<span class="text-sm text-muted">{recruitProgress(p)}</span>
|
||||
</li>
|
||||
{/each}
|
||||
{#if recruits.length === 0}
|
||||
<li class="status-row"><span class="text-success">All recruits are aboard! Heading to the next scene...</span></li>
|
||||
{/if}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import { apiRequest } from '../lib/api';
|
||||
import { displayName } from '../lib/cards';
|
||||
|
||||
export let state;
|
||||
|
||||
@@ -64,7 +63,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="setup-grid">
|
||||
<div class="setup-grid single">
|
||||
<!-- Role Selection Card -->
|
||||
<div class="card glass-panel role-selection-card">
|
||||
<h3>Select Your Role</h3>
|
||||
@@ -107,24 +106,6 @@
|
||||
</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">{displayName(p)} <span class="text-sm text-muted">(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">
|
||||
|
||||
@@ -234,34 +234,6 @@
|
||||
</form>
|
||||
{/if}
|
||||
|
||||
<!-- Voting Roster Status -->
|
||||
{#if state.game.phase !== 'deep_upkeep'}
|
||||
<div class="vote-status-table margin-top">
|
||||
<h4>Nomination Progress:</h4>
|
||||
<div class="player-chips list-chips" id="voting-roster">
|
||||
{#each state.players as p}
|
||||
{@const voted = state.votes.some(v => v.voter_player_id === p.id)}
|
||||
{@const skips = eligibleNomineesFor(p).length === 0}
|
||||
<div class="player-chip {voted || skips ? 'voted-chip' : 'not-voted-chip'}">
|
||||
<span class="name">{displayName(p)}</span>
|
||||
<span class="status-badge">{voted ? 'Done' : skips ? 'No vote' : 'Voting...'}</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="roster-sheet-summary margin-top text-left glass-panel">
|
||||
<h4>Crew Rank Ledger:</h4>
|
||||
<ul class="ranks-ledger">
|
||||
{#each state.players as p}
|
||||
<li>
|
||||
<strong>{displayName(p)}:</strong> Rank {p.rank}
|
||||
{#if p.role === 'deep'}<span class="deep-badge">Deep</span>{:else if p.is_ghost}<span class="ghost-badge">Ghost</span>{:else}<span class="pirat-badge">Pi-Rat</span>{/if}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Resting Deep Player Card — only the actual hand refresh, during deep_upkeep -->
|
||||
|
||||
@@ -6,10 +6,17 @@
|
||||
// - Add a CHANGELOG entry only when a commit changes something players can
|
||||
// see. Skip refactors, tests, and tooling. Keep wording player-facing.
|
||||
|
||||
export const VERSION = 23;
|
||||
export const VERSION = 24;
|
||||
|
||||
// Newest first. Each entry: { version, date: 'YYYY-MM-DD', changes: [string, ...] }.
|
||||
export const CHANGELOG = [
|
||||
{
|
||||
version: 24,
|
||||
date: '2026-07-10',
|
||||
changes: [
|
||||
'The crew roster now stays in the same left-hand column throughout every phase of the game.',
|
||||
],
|
||||
},
|
||||
{
|
||||
version: 23,
|
||||
date: '2026-07-10',
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
import UpkeepPhase from '../components/UpkeepPhase.svelte';
|
||||
import RecruitPhase from '../components/RecruitPhase.svelte';
|
||||
import GameOverPhase from '../components/GameOverPhase.svelte';
|
||||
import CrewSidebar from '../components/CrewSidebar.svelte';
|
||||
import EventLog from '../components/EventLog.svelte';
|
||||
import NameModal from '../components/NameModal.svelte';
|
||||
import GatModal from '../components/GatModal.svelte';
|
||||
@@ -219,22 +220,29 @@
|
||||
|
||||
{#if state}
|
||||
<div class="dashboard-container {state.player.is_ghost ? 'ghost-world' : ''}">
|
||||
{#if state.game.phase === 'lobby'}
|
||||
<LobbyPhase {state} />
|
||||
{:else if state.game.phase === 'character_creation' || state.game.phase === 'swap_techniques' || state.game.phase === 'assign_techniques'}
|
||||
<CharacterCreationPhase {state} />
|
||||
{:else if state.game.phase === 'scene_setup'}
|
||||
<SceneSetupPhase {state} />
|
||||
{:else if state.game.phase === 'scene'}
|
||||
{#if state.game.phase === 'scene'}
|
||||
<ScenePhase {state} />
|
||||
{:else if state.game.phase === 'between_scenes' || state.game.phase === 'deep_upkeep'}
|
||||
<UpkeepPhase {state} />
|
||||
{:else if state.game.phase === 'recruit_creation'}
|
||||
<RecruitPhase {state} />
|
||||
{:else if state.game.phase === 'ended'}
|
||||
<GameOverPhase {state} />
|
||||
{:else}
|
||||
<div class="card p-4">Unknown phase: {state.game.phase}</div>
|
||||
<div class="phase-view-layout">
|
||||
<CrewSidebar {state} />
|
||||
<main class="phase-main-column">
|
||||
{#if state.game.phase === 'lobby'}
|
||||
<LobbyPhase {state} />
|
||||
{:else if state.game.phase === 'character_creation' || state.game.phase === 'swap_techniques' || state.game.phase === 'assign_techniques'}
|
||||
<CharacterCreationPhase {state} />
|
||||
{:else if state.game.phase === 'scene_setup'}
|
||||
<SceneSetupPhase {state} />
|
||||
{:else if state.game.phase === 'between_scenes' || state.game.phase === 'deep_upkeep'}
|
||||
<UpkeepPhase {state} />
|
||||
{:else if state.game.phase === 'recruit_creation'}
|
||||
<RecruitPhase {state} />
|
||||
{:else if state.game.phase === 'ended'}
|
||||
<GameOverPhase {state} />
|
||||
{:else}
|
||||
<div class="card p-4">Unknown phase: {state.game.phase}</div>
|
||||
{/if}
|
||||
</main>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user