199 lines
8.9 KiB
PHP
199 lines
8.9 KiB
PHP
@extends('siswa.layouts.app')
|
|
|
|
@section('title', 'Leaderboard')
|
|
|
|
@push('styles')
|
|
<style>
|
|
.page-title { font-size: 28px; font-weight: 800; margin-top: -20px; margin-bottom: 6px; }
|
|
.page-subtitle { font-size: 14px; color: #64748b; margin-bottom: 24px; }
|
|
|
|
.podium-wrap { display: flex; align-items: flex-end; justify-content: center; gap: 12px; margin-bottom: 32px; }
|
|
.podium-item { display: flex; flex-direction: column; align-items: center; gap: 8px; }
|
|
|
|
.podium-avatar {
|
|
border-radius: 50%;
|
|
display: flex; align-items: center; justify-content: center;
|
|
font-size: 22px; font-weight: 800; color: white;
|
|
position: relative; overflow: hidden; flex-shrink: 0;
|
|
width: 56px; height: 56px;
|
|
}
|
|
|
|
.podium-avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
|
|
.podium-crown { position: absolute; top: -16px; font-size: 18px; z-index: 1; }
|
|
|
|
.rank-1 .podium-avatar { background: linear-gradient(135deg,#f59e0b,#d97706); width:68px; height:68px; font-size:26px; }
|
|
.rank-2 .podium-avatar { background: linear-gradient(135deg,#94a3b8,#64748b); }
|
|
.rank-3 .podium-avatar { background: linear-gradient(135deg,#f97316,#ea580c); }
|
|
|
|
.podium-name { font-size:13px; font-weight:700; color:#1e293b; text-align:center; max-width:90px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
|
.podium-exp { font-size:12px; color:#64748b; }
|
|
|
|
.podium-bar { border-radius:12px 12px 0 0; width:80px; display:flex; align-items:center; justify-content:center; font-size:20px; font-weight:800; color:white; }
|
|
.rank-1 .podium-bar { height:80px; background:linear-gradient(135deg,#f59e0b,#d97706); }
|
|
.rank-2 .podium-bar { height:60px; background:linear-gradient(135deg,#94a3b8,#64748b); }
|
|
.rank-3 .podium-bar { height:44px; background:linear-gradient(135deg,#f97316,#ea580c); }
|
|
|
|
.my-rank-banner { background:linear-gradient(135deg,#667eea,#764ba2); border-radius:16px; padding:16px 20px; color:white; display:flex; align-items:center; gap:16px; margin-bottom:20px; }
|
|
.my-rank-avatar { width:48px; height:48px; border-radius:50%; object-fit:cover; border:2px solid rgba(255,255,255,0.5); flex-shrink:0; }
|
|
.my-rank-avatar-placeholder { width:48px; height:48px; border-radius:50%; background:rgba(255,255,255,0.2); display:flex; align-items:center; justify-content:center; font-size:20px; font-weight:800; flex-shrink:0; }
|
|
.my-rank-num { font-size:36px; font-weight:800; line-height:1; }
|
|
.my-rank-info { flex:1; }
|
|
.my-rank-label { font-size:12px; opacity:0.8; margin-bottom:2px; }
|
|
.my-rank-nama { font-size:16px; font-weight:700; }
|
|
.my-rank-exp { font-size:13px; opacity:0.9; }
|
|
|
|
.custom-card { background:white; border-radius:20px; border:2px solid #e5e5e5; padding:22px; }
|
|
.section-title { font-size:15px; font-weight:700; color:#1e293b; margin-bottom:16px; }
|
|
|
|
.lb-row { display:flex; align-items:center; gap:12px; padding:10px 14px; border-radius:12px; margin-bottom:8px; transition:background 0.15s; }
|
|
.lb-row:hover { background:#f8fafc; }
|
|
.lb-row.highlight { background:#f0eeff; border:2px solid #c4b5fd; }
|
|
|
|
.lb-rank { width:32px; height:32px; border-radius:50%; background:#e2e8f0; display:flex; align-items:center; justify-content:center; font-size:13px; font-weight:700; color:#64748b; flex-shrink:0; }
|
|
.lb-rank.gold { background:#fef3c7; color:#d97706; }
|
|
.lb-rank.silver { background:#f1f5f9; color:#64748b; }
|
|
.lb-rank.bronze { background:#ffedd5; color:#ea580c; }
|
|
|
|
.lb-avatar { width:36px; height:36px; border-radius:50%; object-fit:cover; flex-shrink:0; border:2px solid #e2e8f0; }
|
|
.lb-avatar-placeholder { width:36px; height:36px; border-radius:50%; background:#e6f0ff; display:flex; align-items:center; justify-content:center; font-size:14px; font-weight:700; color:#2b8ef3; flex-shrink:0; }
|
|
|
|
.lb-nama { flex:1; font-size:14px; font-weight:600; color:#1e293b; }
|
|
.lb-nisn { font-size:12px; color:#94a3b8; }
|
|
.lb-exp { font-size:14px; font-weight:700; color:#667eea; }
|
|
|
|
.semester-badge { display:inline-block; background:#f0eeff; color:#667eea; font-size:12px; font-weight:700; padding:4px 12px; border-radius:99px; margin-bottom:20px; }
|
|
.empty-state { text-align:center; padding:40px 20px; color:#94a3b8; }
|
|
</style>
|
|
@endpush
|
|
|
|
@section('content')
|
|
|
|
@php $siswaLogin = Auth::guard('siswa')->user(); @endphp
|
|
|
|
<h3 class="page-title">🏅 Leaderboard</h3>
|
|
<p class="page-subtitle">Peringkat siswa berdasarkan total EXP yang dikumpulkan.</p>
|
|
|
|
<span class="semester-badge">Semester {{ $semester }} · {{ $tahunAjaran }}</span>
|
|
|
|
@if($leaderboard->isEmpty())
|
|
<div class="empty-state">
|
|
<div style="font-size:52px;margin-bottom:12px">📊</div>
|
|
<p style="font-size:15px;font-weight:600;color:#475569">Belum ada data leaderboard.</p>
|
|
<p style="font-size:13px">Kerjakan challenge untuk masuk leaderboard!</p>
|
|
</div>
|
|
@else
|
|
|
|
@php
|
|
$top3 = $leaderboard->take(3);
|
|
$first = $top3->firstWhere('ranking', 1);
|
|
$second = $top3->firstWhere('ranking', 2);
|
|
$third = $top3->firstWhere('ranking', 3);
|
|
@endphp
|
|
|
|
@if($first)
|
|
<div class="podium-wrap">
|
|
|
|
@if($second)
|
|
<div class="podium-item rank-2">
|
|
<div class="podium-avatar">
|
|
@if(!empty($second['foto_profil']))
|
|
<img src="{{ Storage::url($second['foto_profil']) }}" alt="">
|
|
@else
|
|
{{ strtoupper(substr($second['nama'], 0, 1)) }}
|
|
@endif
|
|
</div>
|
|
<div class="podium-name">{{ $second['nama'] }}</div>
|
|
<div class="podium-exp">⭐ {{ number_format($second['exp']) }}</div>
|
|
<div class="podium-bar">2</div>
|
|
</div>
|
|
@endif
|
|
|
|
<div class="podium-item rank-1">
|
|
<div class="podium-avatar">
|
|
<span class="podium-crown">👑</span>
|
|
@if(!empty($first['foto_profil']))
|
|
<img src="{{ Storage::url($first['foto_profil']) }}" alt="">
|
|
@else
|
|
{{ strtoupper(substr($first['nama'], 0, 1)) }}
|
|
@endif
|
|
</div>
|
|
<div class="podium-name">{{ $first['nama'] }}</div>
|
|
<div class="podium-exp">⭐ {{ number_format($first['exp']) }}</div>
|
|
<div class="podium-bar">1</div>
|
|
</div>
|
|
|
|
@if($third)
|
|
<div class="podium-item rank-3">
|
|
<div class="podium-avatar">
|
|
@if(!empty($third['foto_profil']))
|
|
<img src="{{ Storage::url($third['foto_profil']) }}" alt="">
|
|
@else
|
|
{{ strtoupper(substr($third['nama'], 0, 1)) }}
|
|
@endif
|
|
</div>
|
|
<div class="podium-name">{{ $third['nama'] }}</div>
|
|
<div class="podium-exp">⭐ {{ number_format($third['exp']) }}</div>
|
|
<div class="podium-bar">3</div>
|
|
</div>
|
|
@endif
|
|
|
|
</div>
|
|
@endif
|
|
|
|
@if($myRank)
|
|
<div class="my-rank-banner">
|
|
@if(!empty($myRank['foto_profil']))
|
|
<img src="{{ Storage::url($myRank['foto_profil']) }}" class="my-rank-avatar" alt="">
|
|
@else
|
|
<div class="my-rank-avatar-placeholder">{{ strtoupper(substr($myRank['nama'], 0, 1)) }}</div>
|
|
@endif
|
|
<div class="my-rank-num">#{{ $myRank['ranking'] }}</div>
|
|
<div class="my-rank-info">
|
|
<div class="my-rank-label">Posisimu saat ini</div>
|
|
<div class="my-rank-nama">{{ $myRank['nama'] }}</div>
|
|
<div class="my-rank-exp">⭐ {{ number_format($myRank['exp']) }} EXP</div>
|
|
</div>
|
|
<div style="font-size:32px">🎯</div>
|
|
</div>
|
|
@endif
|
|
|
|
<div class="custom-card">
|
|
<p class="section-title">📋 Semua Peringkat</p>
|
|
|
|
@foreach($leaderboard as $item)
|
|
@php
|
|
$isMe = $item['id_siswa'] === $siswaLogin->id_siswa;
|
|
$rankClass = match($item['ranking']) { 1=>'gold', 2=>'silver', 3=>'bronze', default=>'' };
|
|
@endphp
|
|
<div class="lb-row {{ $isMe ? 'highlight' : '' }}">
|
|
<div class="lb-rank {{ $rankClass }}">
|
|
@if($item['ranking'] === 1) 🥇
|
|
@elseif($item['ranking'] === 2) 🥈
|
|
@elseif($item['ranking'] === 3) 🥉
|
|
@else {{ $item['ranking'] }}
|
|
@endif
|
|
</div>
|
|
|
|
@if(!empty($item['foto_profil']))
|
|
<img src="{{ Storage::url($item['foto_profil']) }}" class="lb-avatar" alt="">
|
|
@else
|
|
<div class="lb-avatar-placeholder">{{ strtoupper(substr($item['nama'], 0, 1)) }}</div>
|
|
@endif
|
|
|
|
<div style="flex:1">
|
|
<div class="lb-nama">
|
|
{{ $item['nama'] }}
|
|
@if($isMe)
|
|
<span style="background:#c4b5fd;color:#4c1d95;font-size:10px;padding:2px 7px;border-radius:99px;font-weight:700;margin-left:4px">Kamu</span>
|
|
@endif
|
|
</div>
|
|
<div class="lb-nisn">{{ $item['nisn'] }}</div>
|
|
</div>
|
|
<div class="lb-exp">⭐ {{ number_format($item['exp']) }}</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
|
|
@endif
|
|
|
|
@endsection |