user(); $now = Carbon::now(); $semester = $now->month >= 7 ? '1' : '2'; $tahunAjaran = $now->month >= 7 ? $now->year . '/' . ($now->year + 1) : ($now->year - 1) . '/' . $now->year; $leaderboard = Leaderboard::with('siswa') ->where('id_kelas', $siswa->id_kelas) ->where('semester', $semester) ->where('tahun_ajaran', $tahunAjaran) ->orderBy('total_exp', 'desc') ->get() ->map(function ($item, $i) { $fotoProfil = optional($item->siswa)->foto_profil; return [ 'ranking' => $i + 1, 'nama' => optional($item->siswa)->nama ?? '-', 'nisn' => optional($item->siswa)->nisn ?? '-', 'exp' => $item->total_exp, 'id_siswa' => $item->id_siswa, 'foto_profil' => $fotoProfil, 'foto_url' => $fotoProfil ? Storage::url($fotoProfil) : null, ]; }); $myRank = $leaderboard->firstWhere('id_siswa', $siswa->id_siswa); return compact('leaderboard', 'myRank', 'semester', 'tahunAjaran', 'siswa'); } public function index() { $data = $this->getData(); unset($data['siswa']); return view('siswa.leaderboard.index', $data); } /** * Endpoint JSON untuk polling real-time. * Mengevaluasi badge leaderboard siswa, lalu return badge yang dimiliki * saat ini agar JS bisa mendeteksi badge baru via localStorage. */ public function json() { $data = $this->getData(); $siswa = $data['siswa']; // Evaluasi badge leaderboard (grant/revoke) app(BadgeService::class)->checkLeaderboardBadges( $siswa->id_siswa, $siswa->id_kelas ); // Ambil semua badge leaderboard yang dimiliki siswa saat ini // beserta detail badge (icon, nama, deskripsi) untuk ditampilkan di pop-up $badgeSiswa = SiswaBadge::with('badge') ->where('id_siswa', $siswa->id_siswa) ->whereHas('badge', fn($q) => $q->whereIn('syarat', ['leaderboard_top5', 'leaderboard_top1'])) ->get() ->map(fn($sb) => [ 'id_badge' => $sb->id_badge, 'nama_badge' => $sb->badge->nama_badge, 'deskripsi' => $sb->badge->deskripsi, 'icon_url' => asset($sb->badge->icon_badge), ]); unset($data['siswa']); $data['badgeSiswa'] = $badgeSiswa; return response()->json($data); } }