feat: render interactive ashen fields world

This commit is contained in:
Bastian Wagner
2026-08-19 08:25:42 +02:00
parent fce03e220d
commit 1e2bfe6e4b
21 changed files with 1933 additions and 17 deletions

View File

@@ -0,0 +1,64 @@
<section class="world-page" aria-label="Weltansicht">
@if (worldStore.currentLocation(); as location) {
<section
class="world-page__scene"
[style.background-image]="mapBackground"
[attr.aria-label]="'Weltkarte bei ' + location.name"
>
<div class="world-page__atmosphere" aria-hidden="true"></div>
<p class="world-page__location-title">{{ location.name }}</p>
<svg
class="world-page__path"
viewBox="0 0 100 100"
preserveAspectRatio="none"
aria-hidden="true"
>
<path d="M 21 62 C 36 64, 51 50, 68 43" pathLength="1" />
</svg>
<app-location-node
class="world-page__node world-page__node--current"
[location]="{ id: location.id, key: location.key, name: location.name }"
[current]="true"
[disabled]="true"
/>
@for (connection of location.connections; track connection.targetLocation.id) {
<app-location-node
class="world-page__node world-page__node--reachable"
[location]="connection.targetLocation"
[selected]="
worldStore.selectedConnection()?.targetLocation?.id === connection.targetLocation.id
"
[disabled]="worldStore.currentTravel()?.status === 'TRAVELLING'"
(choose)="selectConnection(connection)"
/>
}
<app-travel-panel
class="world-page__travel-panel"
[selectedConnection]="worldStore.selectedConnection()"
[currentTravel]="worldStore.currentTravel()"
[remainingSeconds]="worldStore.remainingSeconds()"
[busy]="worldStore.loading()"
(travelStart)="worldStore.startTravel()"
/>
</section>
} @else {
<section class="world-page__empty" aria-live="polite">
<p>Weltkarte wird vorbereitet.</p>
</section>
}
@if (worldStore.loading()) {
<p class="world-page__loading" role="status">Weltzustand wird geladen…</p>
}
@if (worldStore.error(); as error) {
<section class="world-page__error" role="alert">
<p>{{ error }}</p>
<button type="button" (click)="retry()">Erneut versuchen</button>
</section>
}
</section>