From 26909d7e2a7c474e6910d16b884733067ac4cae5 Mon Sep 17 00:00:00 2001 From: Bastian Wagner Date: Wed, 19 Aug 2026 14:33:15 +0200 Subject: [PATCH] fix: load WorldStore on direct /hunt navigation HuntPageComponent never called WorldStore.load(), so opening /hunt directly (bookmark/hard refresh) without first visiting /world left currentLocation() at null forever, stranding the page and the context panel on their empty states with no recovery. Add ngOnInit that calls worldStore.load() only when no location is present yet, mirroring WorldPageComponent's existing call and avoiding a duplicate request. --- .../hunting/hunt-page/hunt-page.component.spec.ts | 15 ++++++++++++++- .../hunting/hunt-page/hunt-page.component.ts | 10 ++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/apps/web/src/app/features/hunting/hunt-page/hunt-page.component.spec.ts b/apps/web/src/app/features/hunting/hunt-page/hunt-page.component.spec.ts index 039ffb0..5452bc1 100644 --- a/apps/web/src/app/features/hunting/hunt-page/hunt-page.component.spec.ts +++ b/apps/web/src/app/features/hunting/hunt-page/hunt-page.component.spec.ts @@ -76,6 +76,7 @@ const threeEncounterHunt: HuntResult = { describe('HuntPageComponent', () => { let worldStore: { currentLocation: ReturnType>; + load: ReturnType; }; let huntingStore: { currentHunt: ReturnType>; @@ -89,7 +90,7 @@ describe('HuntPageComponent', () => { let router: Router; async function setup(location: CurrentLocationResponse | null, hunt: HuntResult | null = null) { - worldStore = { currentLocation: signal(location) }; + worldStore = { currentLocation: signal(location), load: vi.fn(() => Promise.resolve()) }; const currentHunt = signal(hunt); huntingStore = { currentHunt, @@ -196,6 +197,18 @@ describe('HuntPageComponent', () => { expect(huntingStore.startHunt).not.toHaveBeenCalled(); }); + it('loads the world state on init when no location has been loaded yet (direct navigation/hard refresh)', async () => { + await setup(null); + + expect(worldStore.load).toHaveBeenCalledOnce(); + }); + + it('does not call load again when a location is already present', async () => { + await setup(burnedRoad); + + expect(worldStore.load).not.toHaveBeenCalled(); + }); + it('shows a loading state and disables the triggering action', async () => { const fixture = await setup(burnedRoad); huntingStore.loading.set(true); diff --git a/apps/web/src/app/features/hunting/hunt-page/hunt-page.component.ts b/apps/web/src/app/features/hunting/hunt-page/hunt-page.component.ts index bda1567..0f60dfd 100644 --- a/apps/web/src/app/features/hunting/hunt-page/hunt-page.component.ts +++ b/apps/web/src/app/features/hunting/hunt-page/hunt-page.component.ts @@ -1,4 +1,4 @@ -import { Component, inject } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { Router } from '@angular/router'; import { EncounterCardComponent } from '../encounter-card/encounter-card.component'; import { HuntingStore } from '../hunting.store'; @@ -10,11 +10,17 @@ import { WorldStore } from '../../world/world.store'; templateUrl: './hunt-page.component.html', styleUrl: './hunt-page.component.scss', }) -export class HuntPageComponent { +export class HuntPageComponent implements OnInit { protected readonly worldStore = inject(WorldStore); protected readonly huntingStore = inject(HuntingStore); private readonly router = inject(Router); + ngOnInit(): void { + if (this.worldStore.currentLocation() === null) { + void this.worldStore.load(); + } + } + protected startHunt(): void { void this.huntingStore.startHunt(); }