Files
fitness/resources/views/dashboard.blade.php
T

166 lines
12 KiB
PHP
Raw Normal View History

2025-10-02 22:52:13 +03:00
<x-app-layout>
<section class="bg-white dark:bg-gray-900 border-b border-gray-100 dark:border-gray-800">
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-8">
<div class="flex items-center justify-between">
<div>
<h1 class="text-2xl sm:text-3xl font-extrabold tracking-tight text-gray-900 dark:text-white">{{ __('app.dashboard.title') }}</h1>
<p class="mt-2 text-gray-600 dark:text-gray-300">{{ __('app.dashboard.subtitle') }}</p>
2025-10-02 22:52:13 +03:00
</div>
</div>
</div>
</section>
<section class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-6">
2026-08-10 12:44:24 +03:00
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-6">
<div class="rounded-2xl ring-1 ring-gray-200 dark:ring-gray-700 bg-gradient-to-br from-amber-500 to-orange-600 p-5 text-white">
<div class="text-sm text-white/80">{{ __('app.dashboard.metrics.streak') }}</div>
<div class="mt-2 text-3xl font-bold">{{ $gamification['current_streak'] }} <span class="text-base font-medium">{{ __('app.dashboard.days') }}</span></div>
@if($gamification['longest_streak'] > $gamification['current_streak'])
<div class="mt-1 text-xs text-white/80">{{ __('app.dashboard.best_streak') }}: {{ $gamification['longest_streak'] }} {{ __('app.dashboard.days') }}</div>
@endif
</div>
<div class="rounded-2xl ring-1 ring-gray-200 dark:ring-gray-700 bg-white dark:bg-gray-800 p-5">
<div class="text-sm text-gray-500">{{ __('app.dashboard.metrics.workouts') }}</div>
<div class="mt-2 text-3xl font-bold text-gray-900 dark:text-white">{{ $workoutsCount }}</div>
</div>
<div class="rounded-2xl ring-1 ring-gray-200 dark:ring-gray-700 bg-white dark:bg-gray-800 p-5">
<div class="text-sm text-gray-500">{{ __('app.dashboard.metrics.sessions') }}</div>
<div class="mt-2 text-3xl font-bold text-gray-900 dark:text-white">{{ $sessionsCount }}</div>
</div>
<div class="rounded-2xl ring-1 ring-gray-200 dark:ring-gray-700 bg-white dark:bg-gray-800 p-5">
<div class="text-sm text-gray-500">{{ __('app.dashboard.metrics.completed') }}</div>
<div class="mt-2 text-3xl font-bold text-gray-900 dark:text-white">{{ $completedSessions }}</div>
</div>
<div class="rounded-2xl ring-1 ring-gray-200 dark:ring-gray-700 bg-white dark:bg-gray-800 p-5">
<div class="flex items-center justify-between">
<div class="text-sm text-gray-500">{{ __('app.dashboard.metrics.completion_rate') }}</div>
<div class="text-sm font-semibold text-indigo-600">{{ $completionRate }}%</div>
</div>
<div class="mt-3 h-2 w-full rounded-full bg-gray-200 dark:bg-gray-700 overflow-hidden">
<div class="h-2 bg-gradient-to-r from-emerald-500 to-teal-500" style="width: {{ $completionRate }}%"></div>
</div>
</div>
</div>
<div class="mt-8 grid grid-cols-1 lg:grid-cols-12 gap-6">
<div class="lg:col-span-7 rounded-2xl ring-1 ring-gray-200 dark:ring-gray-700 bg-white dark:bg-gray-800 p-5">
<div class="flex items-center justify-between">
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">{{ __('app.dashboard.recent_sessions') }}</h2>
</div>
@if($recentSessions->isEmpty())
<div class="mt-3 rounded-xl border border-dashed border-gray-300 dark:border-gray-700 p-6 text-sm text-gray-600 dark:text-gray-300">{{ __('app.dashboard.no_sessions') }}</div>
@else
<ul class="mt-4 space-y-4">
@foreach($recentSessions as $s)
<li class="rounded-xl ring-1 ring-gray-200 dark:ring-gray-700 bg-white dark:bg-gray-900 p-4">
<div class="flex items-center justify-between gap-4">
<div>
<div class="text-base font-semibold text-gray-900 dark:text-white">{{ $s['workout_title'] }}</div>
<div class="mt-1 text-sm text-gray-600 dark:text-gray-300">
{{ $s['done'] }} / {{ $s['total'] }} · {{ $s['pct'] }}%
@if($s['completed_at'])
· <span class="text-emerald-600">{{ __('app.dashboard.completed') }}</span>
@endif
</div>
<div class="mt-2 h-2 w-56 rounded-full bg-gray-200 dark:bg-gray-700 overflow-hidden">
<div class="h-2 bg-indigo-500" style="width: {{ $s['pct'] }}%"></div>
</div>
</div>
<a href="{{ route('sessions.show', $s['id']) }}" class="text-sm font-semibold text-indigo-600 hover:text-indigo-500">{{ __('app.dashboard.view_session') }}</a>
</div>
</li>
@endforeach
</ul>
@endif
</div>
<div class="lg:col-span-5 rounded-2xl ring-1 ring-gray-200 dark:ring-gray-700 bg-white dark:bg-gray-800 p-5">
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">{{ __('app.dashboard.activity_30d') }}</h2>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-300">{{ __('app.dashboard.activity_30d_help') }}</p>
@php
$today = now()->startOfDay();
$days = [];
for ($i = 29; $i >= 0; $i--) { $d = $today->copy()->subDays($i)->format('Y-m-d'); $days[] = $d; }
$max = max(1, $dailyActivity->max() ?? 0);
@endphp
<div class="mt-4 grid grid-cols-10 gap-2">
@foreach($days as $d)
@php $count = $dailyActivity[$d] ?? 0; $pct = $max ? intval(($count / $max) * 100) : 0; @endphp
<div class="h-14 rounded-lg bg-gray-100 dark:bg-gray-900 ring-1 ring-gray-200 dark:ring-gray-700 flex items-center justify-center">
<div class="w-8 h-8 rounded-full bg-indigo-500/20 flex items-center justify-center">
<span class="text-xs font-semibold text-indigo-600">{{ $count }}</span>
</div>
</div>
@endforeach
</div>
</div>
</div>
<div class="mt-8 rounded-2xl ring-1 ring-gray-200 dark:ring-gray-700 bg-white dark:bg-gray-800 p-5">
<div class="flex items-center justify-between flex-wrap gap-3">
<div>
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">{{ __('app.weight_log.title') }}</h2>
@if($weightChange !== null)
<p class="mt-1 text-sm text-gray-600 dark:text-gray-300">
{{ __('app.weight_log.change_since_first') }}
<span class="font-semibold {{ $weightChange < 0 ? 'text-emerald-600' : ($weightChange > 0 ? 'text-amber-600' : 'text-gray-600') }}">
{{ $weightChange > 0 ? '+' : '' }}{{ $weightChange }} kg
</span>
</p>
@endif
</div>
<form method="POST" action="{{ route('weight-logs.store') }}" class="flex items-end gap-2">
@csrf
<div>
<label class="block text-xs font-medium text-gray-500 dark:text-gray-400">{{ __('app.weight_log.weight_kg') }}</label>
<input type="number" step="0.1" min="20" max="400" name="weight_kg" required class="mt-1 w-28 rounded-lg border-gray-300 dark:border-gray-700 bg-white/80 dark:bg-gray-900 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm">
</div>
<div>
<label class="block text-xs font-medium text-gray-500 dark:text-gray-400">{{ __('app.weight_log.date') }}</label>
<input type="date" name="logged_at" max="{{ now()->toDateString() }}" value="{{ now()->toDateString() }}" class="mt-1 rounded-lg border-gray-300 dark:border-gray-700 bg-white/80 dark:bg-gray-900 text-gray-900 dark:text-gray-100 px-3 py-2 text-sm">
</div>
<button type="submit" class="inline-flex items-center rounded-lg bg-indigo-600 px-3 py-2 text-sm font-semibold text-white hover:bg-indigo-500">{{ __('app.weight_log.log') }}</button>
</form>
</div>
@if($weightLogs->isEmpty())
<div class="mt-4 rounded-xl border border-dashed border-gray-300 dark:border-gray-700 p-6 text-sm text-gray-600 dark:text-gray-300">{{ __('app.weight_log.none') }}</div>
@else
<div class="mt-4 flex flex-wrap gap-2">
@foreach($weightLogs->reverse()->take(10) as $log)
<div class="inline-flex items-center gap-2 rounded-full bg-gray-100 dark:bg-gray-900 ring-1 ring-gray-200 dark:ring-gray-700 pl-3 pr-1.5 py-1 text-sm">
<span class="font-semibold text-gray-900 dark:text-white">{{ rtrim(rtrim(number_format($log->weight_kg, 1), '0'), '.') }} kg</span>
<span class="text-gray-500">{{ $log->logged_at->format('M j') }}</span>
<form method="POST" action="{{ route('weight-logs.destroy', $log) }}" onsubmit="return confirm('{{ __('app.weight_log.confirm_delete') }}');">
@csrf
@method('DELETE')
<button type="submit" class="text-gray-400 hover:text-red-500 rounded-full h-5 w-5 inline-flex items-center justify-center" aria-label="{{ __('app.weight_log.delete') }}">&times;</button>
</form>
</div>
@endforeach
</div>
@endif
</div>
2026-08-10 12:44:24 +03:00
<div class="mt-8 rounded-2xl ring-1 ring-gray-200 dark:ring-gray-700 bg-white dark:bg-gray-800 p-5">
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">{{ __('app.dashboard.badges') }}</h2>
<div class="mt-4 grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-4">
@foreach($gamification['badges'] as $badge)
<div class="rounded-xl p-4 text-center ring-1 {{ $badge['earned'] ? 'ring-amber-300 dark:ring-amber-700 bg-amber-50 dark:bg-amber-900/20' : 'ring-gray-200 dark:ring-gray-700 bg-gray-50 dark:bg-gray-900/40 opacity-60' }}" title="{{ $badge['description'] }}">
<div class="mx-auto flex h-10 w-10 items-center justify-center rounded-full {{ $badge['earned'] ? 'bg-amber-400 text-white' : 'bg-gray-200 dark:bg-gray-700 text-gray-400' }}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="h-5 w-5">
@if($badge['earned'])
<path d="M12 2l2.6 6.2L21 9l-5 4.4L17.4 20 12 16.6 6.6 20 8 13.4 3 9l6.4-.8L12 2z"/>
@else
<path fill-rule="evenodd" d="M12 1a4 4 0 00-4 4v2H7a2 2 0 00-2 2v9a2 2 0 002 2h10a2 2 0 002-2v-9a2 2 0 00-2-2h-1V5a4 4 0 00-4-4zm2 6V5a2 2 0 10-4 0v2h4z" clip-rule="evenodd"/>
@endif
</svg>
</div>
<div class="mt-2 text-xs font-semibold {{ $badge['earned'] ? 'text-amber-800 dark:text-amber-200' : 'text-gray-500' }}">{{ $badge['name'] }}</div>
</div>
@endforeach
</div>
</div>
</section>
2025-10-02 22:52:13 +03:00
</x-app-layout>