feat(ui): app-shell core — single-route dispatcher, route collapse, nav→state
Collapse the game UI to one route (`/`): a screen dispatcher renders login/lobby/lobby-create/game from `appScreen`/`activeView` state instead of URL routes. Move screen components to lib/screens & lib/game; the game shell reads the game id from `appScreen.gameId` and re-inits per-game stores via an $effect; in-game views render from `activeView`. Flip ~23 goto/href nav sites to store mutations; drop the `?sidebar=` URL coupling. Auth gate is now state-based. WIP: browser-history (Back→lobby), restore-validation, the return-to-lobby button, push deep-links, and the test migration are follow-ups on this branch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,16 +11,14 @@ The four tech proportions are stored on the wire as fractions in
|
||||
`[0, 1]` and surfaced here as percentages with one decimal so the
|
||||
table matches the designer's input units.
|
||||
|
||||
The component sits inside the active-view slot owned by
|
||||
`routes/games/[id]/+layout.svelte`, so it inherits the per-game
|
||||
The component sits inside the active-view area owned by
|
||||
`lib/game/game-shell.svelte`, so it inherits the per-game
|
||||
`OrderDraftStore` and `RenderedReportSource` through context. No
|
||||
data fetching is performed here — the layout is responsible.
|
||||
data fetching is performed here — the shell is responsible.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { withBase } from "$lib/paths";
|
||||
import { getContext } from "svelte";
|
||||
import { goto } from "$app/navigation";
|
||||
import { page } from "$app/state";
|
||||
import { activeView } from "$lib/app-nav.svelte";
|
||||
|
||||
import type { ScienceSummary } from "../../api/game-state";
|
||||
import { i18n, type TranslationKey } from "$lib/i18n/index.svelte";
|
||||
@@ -60,8 +58,6 @@ data fetching is performed here — the layout is responsible.
|
||||
ORDER_DRAFT_CONTEXT_KEY,
|
||||
);
|
||||
|
||||
const gameId = $derived(page.params.id ?? "");
|
||||
|
||||
let sortColumn: SortColumn = $state("name");
|
||||
let sortDirection: SortDirection = $state("asc");
|
||||
let filter: string = $state("");
|
||||
@@ -118,11 +114,11 @@ data fetching is performed here — the layout is responsible.
|
||||
}
|
||||
|
||||
function openDesigner(name: string): void {
|
||||
void goto(withBase(`/games/${gameId}/designer/science/${encodeURIComponent(name)}`));
|
||||
activeView.select("designer-science", { scienceId: name });
|
||||
}
|
||||
|
||||
function newScience(): void {
|
||||
void goto(withBase(`/games/${gameId}/designer/science`));
|
||||
activeView.select("designer-science");
|
||||
}
|
||||
|
||||
async function deleteScience(name: string): Promise<void> {
|
||||
|
||||
Reference in New Issue
Block a user