120 lines
6.5 KiB
PHP
120 lines
6.5 KiB
PHP
@php
|
|
$colorMap = [
|
|
'primary' => ['bg' => 'bg-primary-soft', 'ink' => 'text-primary-ink'],
|
|
'rose' => ['bg' => 'bg-rose-soft', 'ink' => 'text-rose-ink'],
|
|
'violet' => ['bg' => 'bg-violet-soft', 'ink' => 'text-violet-ink'],
|
|
'green' => ['bg' => 'bg-green-soft', 'ink' => 'text-green-ink'],
|
|
'amber' => ['bg' => 'bg-amber-soft', 'ink' => 'text-amber-ink'],
|
|
];
|
|
@endphp
|
|
|
|
<div class="flex flex-col gap-6">
|
|
|
|
<header class="flex justify-between items-end gap-6">
|
|
<div>
|
|
<div class="text-[11px] uppercase tracking-[0.14em] text-ink-3 font-semibold mb-1.5">Heute</div>
|
|
<h1 class="text-[28px] leading-tight font-extrabold tracking-tight text-ink-1">Aufgaben</h1>
|
|
<p class="text-sm text-ink-2 mt-2 max-w-xl leading-relaxed">Deine offenen Aufgaben — sortiert nach Fälligkeit und Punkten.</p>
|
|
</div>
|
|
<x-btn variant="primary" size="lg">
|
|
<x-heroicon-s-play class="w-4 h-4" />
|
|
Alle starten
|
|
</x-btn>
|
|
</header>
|
|
|
|
{{-- Filter Pills (URL-synced via #[Url]) --}}
|
|
<div class="flex gap-2" wire:key="filter-bar">
|
|
@foreach(['open' => 'Offen', 'done' => 'Erledigt', 'all' => 'Alle'] as $key => $label)
|
|
<button
|
|
type="button"
|
|
wire:click="setFilter('{{ $key }}')"
|
|
wire:loading.attr="disabled"
|
|
class="inline-flex items-center gap-2 px-3 py-1.5 rounded-full border text-xs font-semibold transition-all cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-1 {{ $filter === $key ? 'bg-ink-1 text-bg-base border-ink-1' : 'bg-bg-soft text-ink-2 border-line hover:bg-bg-tint' }}"
|
|
data-testid="filter-{{ $key }}"
|
|
@if($filter === $key) aria-current="page" @endif
|
|
>
|
|
@if($key === 'open')
|
|
<x-heroicon-o-clock class="w-3.5 h-3.5" />
|
|
@elseif($key === 'done')
|
|
<x-heroicon-o-check-circle class="w-3.5 h-3.5" />
|
|
@endif
|
|
{{ $label }} <span class="font-mono tabular-nums">({{ $this->counts[$key] }})</span>
|
|
</button>
|
|
@endforeach
|
|
</div>
|
|
|
|
{{-- Skeleton during filter switch — bg-bg-tint container, bg-line bars for contrast --}}
|
|
<div wire:loading.flex wire:target="setFilter" class="hidden flex-col bg-bg-soft border border-line rounded-xl p-5 shadow-sm" data-testid="tasks-skeleton">
|
|
@for($i = 0; $i < 4; $i++)
|
|
<div class="grid grid-cols-[44px_1fr_auto] gap-3 items-center py-3 border-t border-line first:border-t-0 animate-pulse">
|
|
<div class="w-10 h-10 rounded-lg bg-line"></div>
|
|
<div class="flex flex-col gap-2">
|
|
<div class="h-3 bg-line rounded w-3/5"></div>
|
|
<div class="h-2 bg-line rounded w-2/5"></div>
|
|
</div>
|
|
<div class="flex items-center gap-3">
|
|
<div class="h-3 bg-line rounded w-16"></div>
|
|
<div class="h-7 bg-line rounded w-20"></div>
|
|
</div>
|
|
</div>
|
|
@endfor
|
|
</div>
|
|
|
|
{{-- Task list — modal triggered ONLY by Detail button, row itself is passive --}}
|
|
<x-card class="shadow-sm" wire:loading.remove wire:target="setFilter">
|
|
@if(empty($this->filteredTasks))
|
|
<div class="py-8 text-center text-sm text-ink-3">Keine Aufgaben in dieser Ansicht.</div>
|
|
@else
|
|
<div class="flex flex-col">
|
|
@foreach($this->filteredTasks as $t)
|
|
@php $c = $colorMap[$t['color']]; @endphp
|
|
<div
|
|
wire:key="task-{{ $t['key'] }}"
|
|
class="group grid grid-cols-[44px_1fr_auto] gap-3 items-center py-3 border-t border-line first:border-t-0"
|
|
data-testid="task-row"
|
|
>
|
|
<div class="w-10 h-10 rounded-lg {{ $c['bg'] }} {{ $c['ink'] }} grid place-items-center font-bold">
|
|
{{ $t['icon'] }}
|
|
</div>
|
|
<div class="min-w-0">
|
|
<div class="flex items-center gap-2">
|
|
<div class="font-semibold text-sm text-ink-1 truncate">{{ $t['title'] }}</div>
|
|
@if($t['status'] === 'done')
|
|
<x-heroicon-s-check-circle class="w-4 h-4 text-green-ink shrink-0" />
|
|
@endif
|
|
</div>
|
|
<div class="text-xs text-ink-3 mt-0.5 truncate">{{ $t['meta'] }} · {{ $t['due'] }}</div>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<span class="font-mono tabular-nums text-xs text-amber-ink font-bold">+{{ $t['points'] }} Pkt.</span>
|
|
<button
|
|
type="button"
|
|
wire:click="$dispatch('openModal', { component: 'tasks.modals.detail', arguments: { task: {{ \Illuminate\Support\Js::from($t) }} } })"
|
|
class="w-8 h-8 grid place-items-center rounded-lg border border-line bg-bg-soft text-ink-2 hover:bg-bg-tint hover:text-ink-1 transition-all cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-1"
|
|
aria-label="Details anzeigen"
|
|
data-testid="task-detail-btn"
|
|
>
|
|
<x-heroicon-o-information-circle class="w-4 h-4" />
|
|
</button>
|
|
@if($t['status'] === 'open')
|
|
<x-btn variant="primary" size="sm"
|
|
wire:click="startTask('{{ $t['key'] }}')"
|
|
data-testid="task-start-btn">
|
|
Starten
|
|
</x-btn>
|
|
@else
|
|
<x-btn size="sm"
|
|
wire:click="repeatTask('{{ $t['key'] }}')"
|
|
data-testid="task-repeat-btn">
|
|
Wiederholen
|
|
</x-btn>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
</x-card>
|
|
|
|
</div>
|