diff --git a/apps/web/src/app/core/api/game-api.models.ts b/apps/web/src/app/core/api/game-api.models.ts index 3fd4052..23e3661 100644 --- a/apps/web/src/app/core/api/game-api.models.ts +++ b/apps/web/src/app/core/api/game-api.models.ts @@ -89,6 +89,13 @@ export interface LocationInteractionResult { title: string; text: string; img?: string; + /** + * Set only the first time an interaction reveals a route. Optional on the + * client although the API always sends it: every existing test fixture + * builds this object literally, and a required field would break them all + * for no gain. + */ + discoveredLocation?: { key: string; name: string } | null; } export interface CurrentLocationResponse { diff --git a/apps/web/src/app/features/world/local-location.store.spec.ts b/apps/web/src/app/features/world/local-location.store.spec.ts index 5f8680c..5ecd837 100644 --- a/apps/web/src/app/features/world/local-location.store.spec.ts +++ b/apps/web/src/app/features/world/local-location.store.spec.ts @@ -122,6 +122,38 @@ describe('LocalLocationStore', () => { expect(store.interactionResult()).toBeNull(); }); + it('reloads the location when the interaction reveals a route', async () => { + const load = vi.fn().mockResolvedValue(undefined); + const store = setup( + { + runLocationInteraction: vi.fn().mockReturnValue( + of({ ...trackResult, discoveredLocation: { key: 'ash-pit', name: 'Ash Pit' } }), + ), + }, + { load }, + ); + + await store.runInteraction('inspect-tracks'); + + expect(load).toHaveBeenCalledTimes(1); + }); + + it('does not reload the location when nothing new was revealed', async () => { + const load = vi.fn().mockResolvedValue(undefined); + const store = setup( + { + runLocationInteraction: vi.fn().mockReturnValue( + of({ ...trackResult, discoveredLocation: null }), + ), + }, + { load }, + ); + + await store.runInteraction('inspect-tracks'); + + expect(load).not.toHaveBeenCalled(); + }); + it('resolves the hotspot an action mirrors', () => { const store = setup(); diff --git a/apps/web/src/app/features/world/local-location.store.ts b/apps/web/src/app/features/world/local-location.store.ts index 7aea055..03a9231 100644 --- a/apps/web/src/app/features/world/local-location.store.ts +++ b/apps/web/src/app/features/world/local-location.store.ts @@ -74,9 +74,14 @@ export class LocalLocationStore { this.interactionErrorState.set(null); try { - this.interactionResultState.set( - await firstValueFrom(this.api.runLocationInteraction(interactionKey)), - ); + const result = await firstValueFrom(this.api.runLocationInteraction(interactionKey)); + this.interactionResultState.set(result); + + if (result.discoveredLocation) { + // The connection list is server-filtered, so a fresh reveal only + // shows up after the location is re-read. + await this.load(); + } } catch (error) { this.interactionErrorState.set(this.toErrorMessage(error)); } finally { diff --git a/apps/web/src/app/features/world/location-interaction-panel/location-interaction-panel.component.html b/apps/web/src/app/features/world/location-interaction-panel/location-interaction-panel.component.html index 660653d..d7387f5 100644 --- a/apps/web/src/app/features/world/location-interaction-panel/location-interaction-panel.component.html +++ b/apps/web/src/app/features/world/location-interaction-panel/location-interaction-panel.component.html @@ -20,6 +20,11 @@
{{ result.text }}
+ @if (result.discoveredLocation; as discovered) { ++ New route discovered: {{ discovered.name }}. +
+ }