zahlzerlegung/src/lib/screens/ResultScreen.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>