feat(web): route hunt, combat and arrival back to the location
A finished journey now opens the location view instead of leaving the player on the map, and backing out of the hunt returns to the place the hunt happens in. The victory and defeat screens gain "Zum Ort" alongside "Weiter jagen", so the location is always reachable without costing the hunt loop its one-click rhythm. The store raises the arrival only after the server-owned current location has been re-read, and does not navigate itself — timers, arrival times and the server-side completion are untouched; only the screen that shows the result changed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -117,17 +117,37 @@
|
||||
</section>
|
||||
}
|
||||
|
||||
<button type="button" class="outcome__button" data-combat-to-hunt (click)="goToHunt()">
|
||||
Zur Jagd
|
||||
</button>
|
||||
<div class="outcome__buttons">
|
||||
<button type="button" class="outcome__button" data-combat-to-hunt (click)="goToHunt()">
|
||||
Weiter jagen
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="outcome__button outcome__button--secondary"
|
||||
data-combat-to-location
|
||||
(click)="goToLocation()"
|
||||
>
|
||||
Zum Ort
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
} @else if (combat.status === 'LOST') {
|
||||
<div class="outcome outcome--lost" data-combat-result="LOST">
|
||||
<h2 class="outcome__title">Niederlage</h2>
|
||||
<p>{{ combat.player.name }} wurde im Kampf besiegt.</p>
|
||||
<button type="button" class="outcome__button" data-combat-to-hunt (click)="goToHunt()">
|
||||
Zur Jagd
|
||||
</button>
|
||||
<div class="outcome__buttons">
|
||||
<button type="button" class="outcome__button" data-combat-to-hunt (click)="goToHunt()">
|
||||
Weiter jagen
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="outcome__button outcome__button--secondary"
|
||||
data-combat-to-location
|
||||
(click)="goToLocation()"
|
||||
>
|
||||
Zum Ort
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -490,6 +490,18 @@
|
||||
margin-block-start: var(--ar-space-2);
|
||||
}
|
||||
|
||||
.outcome__buttons {
|
||||
display: flex;
|
||||
gap: var(--ar-space-3);
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.outcome__button--secondary {
|
||||
border-color: var(--ar-border);
|
||||
color: var(--ar-text-muted);
|
||||
background: var(--ar-panel);
|
||||
}
|
||||
|
||||
.outcome__button:hover,
|
||||
.combat__notice--error button:hover {
|
||||
border-color: var(--ar-gold);
|
||||
|
||||
@@ -266,7 +266,7 @@ describe('CombatPageComponent', () => {
|
||||
expect(element.querySelector('[data-combat-attack]')).toBeNull();
|
||||
});
|
||||
|
||||
it('navigates to /hunt from the victory screen', async () => {
|
||||
it('keeps the one-click hunt loop from the victory screen', async () => {
|
||||
const fixture = await setup({ ...activeCombat, status: 'WON' });
|
||||
const element = fixture.nativeElement as HTMLElement;
|
||||
|
||||
@@ -275,6 +275,25 @@ describe('CombatPageComponent', () => {
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/hunt']);
|
||||
});
|
||||
|
||||
it('also offers the way back to the location from the victory screen', async () => {
|
||||
const fixture = await setup({ ...activeCombat, status: 'WON' });
|
||||
const element = fixture.nativeElement as HTMLElement;
|
||||
|
||||
element.querySelector<HTMLButtonElement>('[data-combat-to-location]')?.click();
|
||||
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/location']);
|
||||
});
|
||||
|
||||
it('offers the same two ways out after a defeat', async () => {
|
||||
const fixture = await setup({ ...activeCombat, status: 'LOST' });
|
||||
const element = fixture.nativeElement as HTMLElement;
|
||||
|
||||
expect(element.querySelector('[data-combat-to-hunt]')).not.toBeNull();
|
||||
element.querySelector<HTMLButtonElement>('[data-combat-to-location]')?.click();
|
||||
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/location']);
|
||||
});
|
||||
|
||||
it('shows an error and retries loading the combat', async () => {
|
||||
const fixture = await setup(null);
|
||||
combatStore.error.set('Dieser Kampf wurde nicht gefunden.');
|
||||
|
||||
@@ -161,6 +161,13 @@ export class CombatPageComponent implements OnInit {
|
||||
void this.router.navigate(['/hunt']);
|
||||
}
|
||||
|
||||
// The location is the screen a fight resolves back into. It sits beside
|
||||
// "Weiter jagen" rather than replacing it, so the hunt loop keeps its
|
||||
// one-click rhythm.
|
||||
protected goToLocation(): void {
|
||||
void this.router.navigate(['/location']);
|
||||
}
|
||||
|
||||
protected monsterSprite(monsterKey: string, artworkPath: string): string {
|
||||
return monsterCutoutPath(monsterKey) ?? runtimeMonsterArtworkPath(artworkPath) ?? artworkPath;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user