From 5eb3830895ab4d948fddcdeb14cb2921826d501e Mon Sep 17 00:00:00 2001 From: Bro Date: Thu, 23 Jul 2026 00:00:21 +0700 Subject: [PATCH] feat: replace attendance history list with interactive calendar - Calendar shows per-date student count badge (green=all hadir, red=ada alpha) - Click badge to go to attendance input for that date - Prev/next month navigation with API fetch - Controller passes initial month data inline (no flash on load) --- app/Http/Controllers/AttendanceController.php | 66 ++++++- resources/views/attendances/index.blade.php | 183 +++++++++++++++--- routes/web.php | 1 + 3 files changed, 211 insertions(+), 39 deletions(-) diff --git a/app/Http/Controllers/AttendanceController.php b/app/Http/Controllers/AttendanceController.php index 8f6cc27..c04edc2 100644 --- a/app/Http/Controllers/AttendanceController.php +++ b/app/Http/Controllers/AttendanceController.php @@ -6,6 +6,7 @@ use App\Models\Attendance; use App\Models\Student; use App\Models\ViolationType; use App\Services\ViolationService; +use Illuminate\Http\JsonResponse; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\View\View; @@ -46,16 +47,33 @@ class AttendanceController extends Controller ->distinct('student_id') ->count('student_id'); - $recentDates = \App\Models\Attendance::select('date') - ->distinct() - ->orderByDesc('date') - ->take(10) - ->get(); + // Calendar data for initial month + $calendarStart = now()->startOfMonth()->toDateString(); + $calendarEnd = now()->endOfMonth()->toDateString(); + + $totalRows = \App\Models\Attendance::selectRaw('date, COUNT(DISTINCT student_id) as total') + ->whereBetween('date', [$calendarStart, $calendarEnd]) + ->groupBy('date') + ->pluck('total', 'date'); + + $alphaRows = \App\Models\Attendance::selectRaw('date, COUNT(DISTINCT student_id) as alpha') + ->whereBetween('date', [$calendarStart, $calendarEnd]) + ->where('status', 'alpha') + ->groupBy('date') + ->pluck('alpha', 'date'); + + $calendarData = []; + foreach ($totalRows as $date => $total) { + $calendarData[$date] = [ + 'total' => $total, + 'alpha' => $alphaRows[$date] ?? 0, + ]; + } return view('attendances.index', compact( 'todayStudents', 'todayAlphaStudents', 'monthStudents', 'monthAlphaStudents', - 'recentDates' + 'calendarData' )); } @@ -237,4 +255,38 @@ class AttendanceController extends Controller return view('attendances.recap', compact('recap', 'month', 'year', 'className', 'classNames')); } -} + + public function calendarData(Request $request): JsonResponse + { + $year = (int) $request->input('year', now()->year); + $month = (int) $request->input('month', now()->month); + $daysInMonth = now()->setDate($year, $month, 1)->daysInMonth; + + $dateFrom = sprintf('%04d-%02d-01', $year, $month); + $dateTo = sprintf('%04d-%02d-%02d', $year, $month, $daysInMonth); + + // Total unique students per date + $totalRows = Attendance::selectRaw('date, COUNT(DISTINCT student_id) as total') + ->whereBetween('date', [$dateFrom, $dateTo]) + ->groupBy('date') + ->pluck('total', 'date'); + + // Alpha unique students per date + $alphaRows = Attendance::selectRaw('date, COUNT(DISTINCT student_id) as alpha') + ->whereBetween('date', [$dateFrom, $dateTo]) + ->where('status', 'alpha') + ->groupBy('date') + ->pluck('alpha', 'date'); + + $result = []; + foreach ($totalRows as $date => $total) { + $result[$date] = [ + 'total' => $total, + 'alpha' => $alphaRows[$date] ?? 0, + ]; + } + + return response()->json($result); + } + +} \ No newline at end of file diff --git a/resources/views/attendances/index.blade.php b/resources/views/attendances/index.blade.php index 1f01229..3518bb7 100644 --- a/resources/views/attendances/index.blade.php +++ b/resources/views/attendances/index.blade.php @@ -60,46 +60,165 @@ - {{-- Recent --}} -
-
+ {{-- Kalender Presensi --}} +
+
-
- +
+
-

Riwayat Presensi

-

10 hari terakhir

+

Kalender Presensi

+

+
+ + +
- @if($recentDates->count() > 0) - @endsection + +@push('scripts') + +@endpush diff --git a/routes/web.php b/routes/web.php index f60b1de..7e4e4a2 100644 --- a/routes/web.php +++ b/routes/web.php @@ -33,6 +33,7 @@ Route::middleware('auth')->group(function () { Route::get('/attendances/create', [\App\Http\Controllers\AttendanceController::class, 'create'])->name('attendances.create'); Route::post('/attendances', [\App\Http\Controllers\AttendanceController::class, 'store'])->name('attendances.store'); Route::get('/attendances/recap', [\App\Http\Controllers\AttendanceController::class, 'recap'])->name('attendances.recap'); + Route::get('/attendances/calendar-data', [\App\Http\Controllers\AttendanceController::class, 'calendarData'])->name('attendances.calendar-data'); Route::get('/notifications/recent', [DashboardController::class, 'getRecentNotifications'])->name('notifications.recent'); Route::post('/notifications/{id}/read', [DashboardController::class, 'markNotificationRead'])->name('notifications.read');