From 30de2850f7fa626bd49c0c294957172c313fb180 Mon Sep 17 00:00:00 2001 From: Novy San87 Date: Thu, 6 Aug 2026 18:39:02 +0700 Subject: [PATCH] feat: is_read di violation_notifications + unread count + mark all read --- .../Api/ParentNotificationController.php | 29 +++++++++++++++---- ...add_is_read_to_violation_notifications.php | 23 +++++++++++++++ routes/api.php | 1 + 3 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 database/migrations/2026_08_06_000003_add_is_read_to_violation_notifications.php diff --git a/app/Http/Controllers/Api/ParentNotificationController.php b/app/Http/Controllers/Api/ParentNotificationController.php index 85ab1d0..dd69bb6 100644 --- a/app/Http/Controllers/Api/ParentNotificationController.php +++ b/app/Http/Controllers/Api/ParentNotificationController.php @@ -44,6 +44,7 @@ class ParentNotificationController extends Controller 'recipient' => $n->recipient, 'message' => $n->message, 'status' => $n->status, + 'is_read' => (bool) $n->is_read, 'created_at' => $n->created_at?->toISOString(), ]; }); @@ -55,13 +56,11 @@ class ParentNotificationController extends Controller } /** - * Jumlah notifikasi penting (pelanggaran/SP) 7 hari terakhir — untuk badge. + * Jumlah notifikasi penting (pelanggaran/SP) yang BELUM dibaca — untuk badge. */ public function unreadCount(Request $request): JsonResponse { - $user = $request->user(); - - $studentIds = ParentStudent::where('user_id', $user->id) + $studentIds = ParentStudent::where('user_id', $request->user()->id) ->where('status', 'active') ->pluck('student_id') ->all(); @@ -72,12 +71,32 @@ class ParentNotificationController extends Controller $count = ViolationNotification::whereIn('student_id', $studentIds) ->where('channel', 'push') // pelanggaran & SP (bukan kehadiran) - ->where('created_at', '>=', now()->subDays(7)) + ->where('is_read', false) ->count(); return response()->json(['count' => $count]); } + /** + * Tandai semua notifikasi putra/putri sebagai sudah dibaca. + */ + public function markAllRead(Request $request): JsonResponse + { + $studentIds = ParentStudent::where('user_id', $request->user()->id) + ->where('status', 'active') + ->pluck('student_id') + ->all(); + + $updated = 0; + if (! empty($studentIds)) { + $updated = ViolationNotification::whereIn('student_id', $studentIds) + ->where('is_read', false) + ->update(['is_read' => true, 'read_at' => now()]); + } + + return response()->json(['updated' => $updated, 'count' => 0]); + } + /** * Daftarkan perangkat (token FCM) untuk push notification. */ diff --git a/database/migrations/2026_08_06_000003_add_is_read_to_violation_notifications.php b/database/migrations/2026_08_06_000003_add_is_read_to_violation_notifications.php new file mode 100644 index 0000000..44863e2 --- /dev/null +++ b/database/migrations/2026_08_06_000003_add_is_read_to_violation_notifications.php @@ -0,0 +1,23 @@ +boolean('is_read')->default(false)->after('status'); + $table->timestamp('read_at')->nullable()->after('is_read'); + }); + } + + public function down(): void + { + Schema::table('violation_notifications', function (Blueprint $table) { + $table->dropColumn(['is_read', 'read_at']); + }); + } +}; diff --git a/routes/api.php b/routes/api.php index 0627bc9..a490da8 100644 --- a/routes/api.php +++ b/routes/api.php @@ -44,6 +44,7 @@ Route::middleware('auth:sanctum')->prefix('parent')->group(function () { // Notifikasi & perangkat Route::get('/notifications', [ParentNotificationController::class, 'index'])->name('api.parent.notifications'); Route::get('/notifications/unread', [ParentNotificationController::class, 'unreadCount'])->name('api.parent.notifications.unread'); + Route::post('/notifications/read', [ParentNotificationController::class, 'markAllRead'])->name('api.parent.notifications.read'); Route::get('/school-informations', [ParentSchoolInformationController::class, 'index'])->name('api.parent.school-informations'); Route::get('/academic-calendar', [ParentSchoolInformationController::class, 'calendar'])->name('api.parent.academic-calendar'); Route::post('/devices', [ParentNotificationController::class, 'registerDevice'])->name('api.parent.devices');