107 lines
3.0 KiB
Svelte
107 lines
3.0 KiB
Svelte
<script lang="ts">
|
|
import { fade, fly } from 'svelte/transition';
|
|
import type { Target } from '../game/tasks';
|
|
import { lastRun } from '../stores/progress';
|
|
import { startGame } from '../stores/game';
|
|
import { goHome, goGame } from '../stores/route';
|
|
import { play, unlockAudio } from '../audio/soundManager';
|
|
import Rainbow from '../components/svg/Rainbow.svelte';
|
|
import HighscoreColumn from '../components/home/HighscoreColumn.svelte';
|
|
|
|
type Props = { target: Target };
|
|
let { target }: Props = $props();
|
|
|
|
// Genau der gerade gespielte Lauf (kann auch ein nicht-bester Versuch sein).
|
|
const current = $derived($lastRun?.target === target ? $lastRun : null);
|
|
const lastRunDate = $derived(current?.date ?? null);
|
|
const lastStage = $derived(current?.stage ?? 0);
|
|
const isWin = $derived(lastStage >= 4);
|
|
|
|
function retry() {
|
|
unlockAudio();
|
|
play('tap');
|
|
startGame(target);
|
|
goGame(target);
|
|
}
|
|
|
|
function home() {
|
|
play('tap');
|
|
goHome();
|
|
}
|
|
</script>
|
|
|
|
<div class="screen" in:fade={{ duration: 240 }}>
|
|
<div class="celebration">
|
|
{#if isWin}
|
|
<div class="rainbow-wrap" in:fly={{ y: 30, duration: 600 }}>
|
|
<Rainbow size={300} />
|
|
</div>
|
|
{/if}
|
|
<div class="scores" in:fly={{ y: 40, duration: 500 }}>
|
|
<HighscoreColumn {target} highlightDate={lastRunDate} />
|
|
</div>
|
|
</div>
|
|
|
|
<footer class="actions">
|
|
<button class="action retry" type="button" onclick={retry} aria-label="Nochmal">
|
|
<svg width="44" height="44" viewBox="0 0 44 44" aria-hidden="true">
|
|
<path d="M10 22 A12 12 0 1 1 22 34" fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round" />
|
|
<path d="M22 34 L16 30 L18 38 Z" fill="currentColor" />
|
|
</svg>
|
|
</button>
|
|
<button class="action home" type="button" onclick={home} aria-label="Zurück zur Übersicht">
|
|
<svg width="44" height="44" viewBox="0 0 44 44" aria-hidden="true">
|
|
<path d="M6 22 L22 8 L38 22 L34 22 L34 36 L26 36 L26 26 L18 26 L18 36 L10 36 L10 22 Z" fill="currentColor" />
|
|
</svg>
|
|
</button>
|
|
</footer>
|
|
</div>
|
|
|
|
<style>
|
|
.screen {
|
|
height: 100%;
|
|
display: grid;
|
|
grid-template-rows: 1fr auto;
|
|
padding: 16px;
|
|
gap: 12px;
|
|
}
|
|
.celebration {
|
|
display: grid;
|
|
place-items: center;
|
|
position: relative;
|
|
min-height: 0;
|
|
}
|
|
.rainbow-wrap {
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
z-index: 1;
|
|
opacity: 0.85;
|
|
}
|
|
.scores {
|
|
position: relative;
|
|
z-index: 2;
|
|
width: 120px;
|
|
height: min(82%, 460px);
|
|
}
|
|
.actions {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 24px;
|
|
}
|
|
.action {
|
|
width: 96px;
|
|
height: 96px;
|
|
border-radius: 50%;
|
|
color: white;
|
|
display: grid;
|
|
place-items: center;
|
|
box-shadow: 0 6px 0 rgba(0,0,0,0.18);
|
|
transition: transform 0.1s ease;
|
|
}
|
|
.action:active { transform: translateY(4px); box-shadow: 0 2px 0 rgba(0,0,0,0.18); }
|
|
.action.retry { background: var(--c-correct); }
|
|
.action.home { background: var(--c-rocket-body); }
|
|
</style>
|