lernschiff/resources/views/livewire/tasks/run.blade.php

155 lines
8.4 KiB
PHP

@php
$colorMap = [
'primary' => ['bg' => 'bg-primary-soft', 'ink' => 'text-primary-ink', 'bar' => 'bg-primary-ink', 'ring' => 'focus-visible:ring-primary'],
'rose' => ['bg' => 'bg-rose-soft', 'ink' => 'text-rose-ink', 'bar' => 'bg-rose-ink', 'ring' => 'focus-visible:ring-rose-ink'],
'violet' => ['bg' => 'bg-violet-soft', 'ink' => 'text-violet-ink', 'bar' => 'bg-violet-ink', 'ring' => 'focus-visible:ring-violet-ink'],
'green' => ['bg' => 'bg-green-soft', 'ink' => 'text-green-ink', 'bar' => 'bg-green-ink', 'ring' => 'focus-visible:ring-green-ink'],
'amber' => ['bg' => 'bg-amber-soft', 'ink' => 'text-amber-ink', 'bar' => 'bg-amber-ink', 'ring' => 'focus-visible:ring-amber-ink'],
];
$c = $colorMap[$task['color']] ?? $colorMap['primary'];
$progressPercent = $totalSteps > 0 ? (int) round(($currentStep / $totalSteps) * 100) : 0;
@endphp
<div class="flex flex-col gap-6 max-w-3xl mx-auto w-full" data-testid="task-run-page">
{{-- Breadcrumb / back nav --}}
<div class="flex items-center justify-between">
<a href="{{ route('tasks') }}" wire:navigate class="inline-flex items-center gap-2 text-sm font-semibold text-ink-2 hover:text-ink-1 transition-colors">
<x-heroicon-o-arrow-left class="w-4 h-4" />
Zurück zu Aufgaben
</a>
<x-pill>{{ $task['meta'] ?? '' }}</x-pill>
</div>
{{-- Task header --}}
<div class="bg-bg-soft border border-line rounded-xl p-5 shadow-sm flex items-center gap-4">
<div class="w-14 h-14 rounded-lg {{ $c['bg'] }} {{ $c['ink'] }} grid place-items-center font-bold text-2xl shrink-0">
{{ $task['icon'] }}
</div>
<div class="flex-1 min-w-0">
<div class="text-[11px] uppercase tracking-[0.12em] text-ink-3 font-semibold">{{ $task['meta'] }}</div>
<h1 class="font-bold text-xl text-ink-1 leading-tight truncate">{{ $task['title'] }}</h1>
</div>
<div class="text-right shrink-0">
<div class="text-[10px] uppercase tracking-wider text-ink-3 font-semibold">Belohnung</div>
<div class="text-lg font-bold font-mono tabular-nums text-amber-ink">+{{ (int) $task['points'] }} Pkt.</div>
</div>
</div>
@if(! $finished)
{{-- Progress --}}
<div>
<div class="flex justify-between items-baseline mb-2">
<span class="text-xs font-semibold text-ink-2 font-mono tabular-nums" data-testid="run-progress-label">
Frage {{ $currentStep }} / {{ $totalSteps }}
</span>
<span class="text-xs font-semibold text-green-ink font-mono tabular-nums" data-testid="run-correct-count">
{{ $correctAnswers }} richtig
</span>
</div>
<div class="h-2 rounded-full bg-bg-tint overflow-hidden">
<div class="h-full rounded-full {{ $c['bar'] }} transition-all duration-500" style="width:{{ $progressPercent }}%;"></div>
</div>
</div>
{{-- Question --}}
@php $q = $this->currentQuestion(); @endphp
<div class="bg-bg-soft border border-line rounded-xl p-8 shadow-sm" wire:key="step-{{ $currentStep }}">
<div class="text-[11px] uppercase tracking-[0.12em] text-ink-3 font-semibold mb-3">Aufgabe</div>
<h2 class="text-2xl font-bold tracking-tight text-ink-1 mb-8 leading-snug" data-testid="run-question">
{{ $q['question'] }}
</h2>
<div class="grid grid-cols-2 gap-3">
@foreach($q['options'] as $i => $opt)
@php
$isLast = $lastAnswerIndex === $i;
$cls = 'group px-5 py-5 rounded-lg border-2 text-ink-1 font-semibold text-base text-left transition-all cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 ' . $c['ring'];
$cls .= $lastAnswerIndex === null
? ' bg-bg-soft border-line hover:border-primary hover:bg-primary-soft'
: ($isLast
? ($lastAnswerCorrect ? ' bg-green-soft border-green-ink' : ' bg-rose-soft border-rose-ink')
: ' bg-bg-soft border-line opacity-60');
@endphp
<button
type="button"
@if($lastAnswerIndex !== null) disabled @else wire:click="submitAnswer({{ $i }})" @endif
class="{{ $cls }}"
data-testid="run-option-{{ $i }}"
>
<span class="flex items-center gap-3">
<span class="w-7 h-7 rounded-full grid place-items-center text-xs font-bold font-mono tabular-nums shrink-0
{{ $isLast ? ($lastAnswerCorrect ? 'bg-green-ink text-white' : 'bg-rose-ink text-white') : 'bg-bg-tint text-ink-2' }}">
{{ chr(65 + $i) }}
</span>
<span>{{ $opt }}</span>
@if($isLast && $lastAnswerCorrect)
<x-heroicon-s-check-circle class="w-5 h-5 text-green-ink ml-auto shrink-0" />
@elseif($isLast)
<x-heroicon-s-x-circle class="w-5 h-5 text-rose-ink ml-auto shrink-0" />
@endif
</span>
</button>
@endforeach
</div>
@if($lastAnswerIndex !== null)
<div class="mt-6 flex justify-end">
<x-btn variant="primary" wire:click="nextStep" data-testid="run-next">
@if($currentStep < $totalSteps)
Nächste Frage
<x-heroicon-o-arrow-right class="w-4 h-4" />
@else
Aufgabe abschließen
<x-heroicon-o-check class="w-4 h-4" />
@endif
</x-btn>
</div>
@endif
</div>
@else
@php
$passed = $correctAnswers >= (int) ceil($totalSteps / 2);
$percent = $totalSteps > 0 ? (int) round(($correctAnswers / $totalSteps) * 100) : 0;
$pointsEarned = $passed ? (int) $task['points'] : 0;
@endphp
<div class="bg-bg-soft border border-line rounded-xl p-10 shadow-sm text-center" data-testid="run-finished">
<div class="w-20 h-20 rounded-full grid place-items-center mx-auto mb-5 {{ $passed ? 'bg-green-soft text-green-ink' : 'bg-amber-soft text-amber-ink' }}">
@if($passed)
<x-heroicon-s-trophy class="w-10 h-10" />
@else
<x-heroicon-s-arrow-path class="w-10 h-10" />
@endif
</div>
<h2 class="text-2xl font-bold text-ink-1 mb-2">
@if($passed) Super gemacht! @else Fast geschafft @endif
</h2>
<p class="text-sm text-ink-2 mb-1">
Du hast <span class="font-mono tabular-nums font-bold text-ink-1">{{ $correctAnswers }}</span>
von <span class="font-mono tabular-nums font-bold text-ink-1">{{ $totalSteps }}</span> Aufgaben richtig.
</p>
<p class="text-xs text-ink-3 mb-6 font-mono tabular-nums">{{ $percent }} % Erfolgsquote</p>
@if($pointsEarned > 0)
<div class="bg-amber-soft border border-amber-soft rounded-lg px-4 py-3 inline-flex items-center gap-2 mb-6">
<x-heroicon-s-star class="w-5 h-5 text-amber-ink" />
<span class="font-mono tabular-nums font-bold text-amber-ink">+{{ $pointsEarned }} Pkt.</span>
<span class="text-xs text-amber-ink font-semibold">verdient</span>
</div>
@endif
<div class="flex gap-2 justify-center">
<x-btn wire:click="restart" data-testid="run-restart">
<x-heroicon-o-arrow-path class="w-4 h-4" />
Nochmal
</x-btn>
<x-btn variant="primary" as="a" href="{{ route('tasks') }}" wire:navigate>
<x-heroicon-o-check class="w-4 h-4" />
Fertig zurück
</x-btn>
</div>
</div>
@endif
</div>