fix: refactor store to singleton class pattern (s.subscribe fix)
All checks were successful
CI/CD — Build & Deploy / Build & Deploy (push) Successful in 21s

Exported $state proxies were confused with Svelte stores by SvelteKit
runtime, causing "s.subscribe is not a function" on /jeu.

Fix: encapsulate all $state fields in a Game class, export singleton.
Components import { game } and access game.state, game.click(), etc.
Class fields are proper $state — no raw proxy exported.
This commit is contained in:
2026-03-28 20:39:21 +01:00
parent cce7fa3190
commit 67931eeadb
16 changed files with 277 additions and 325 deletions

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import { fly } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
import { state, equipCosmetic, unequipCosmetic } from '$lib/stores/game.svelte';
import { game } from '$lib/stores/game.svelte';
import { COSMETICS, type CosmeticSlot } from '$lib/core/cosmetics';
import CollapsiblePanel from './CollapsiblePanel.svelte';
@@ -13,8 +13,8 @@
};
const SLOT_ORDER: CosmeticSlot[] = ['hat', 'eyes', 'body', 'tail', 'accessory'];
let inventory = $derived(state.cosmeticInventory);
let equipped = $derived(state.cosmeticEquipped);
let inventory = $derived(game.state.cosmeticInventory);
let equipped = $derived(game.state.cosmeticEquipped);
let ownedCosmetics = $derived(COSMETICS.filter((c) => inventory.includes(c.id)));
</script>
@@ -40,7 +40,7 @@
<span class="gp-label">{cos.description}</span>
</div>
<button
onclick={() => isEquipped ? unequipCosmetic(slot) : equipCosmetic(cos.id)}
onclick={() => isEquipped ? game.unequipCosmetic(slot) : game.equipCosmetic(cos.id)}
class="gp-btn {isEquipped ? 'gp-btn--disabled' : 'gp-btn--buy'}"
>
{isEquipped ? 'Retirer' : 'Equiper'}