diff --git a/public/assets/js/admin-notifications.js b/public/assets/js/admin-notifications.js index 35db5b1..4020e0a 100644 --- a/public/assets/js/admin-notifications.js +++ b/public/assets/js/admin-notifications.js @@ -58,3 +58,20 @@ function confirmDelete(id, title) { }) .catch(() => showToast('error', 'Failed to delete notification')); } + +function confirmResend(id) { + const csrf = document.querySelector('meta[name="csrf-token"]')?.content || ''; + fetch('/admin/notifications/' + id + '/resend', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'X-CSRF-Token': csrf, + }, + body: '_csrf_token=' + encodeURIComponent(csrf), + }) + .then(r => r.json()) + .then(data => { + showToast(data.success ? 'success' : 'error', data.message); + }) + .catch(() => showToast('error', 'Failed to resend notification')); +} diff --git a/routes/web.php b/routes/web.php index 0d5f359..c813489 100755 --- a/routes/web.php +++ b/routes/web.php @@ -116,6 +116,7 @@ $router->group(['prefix' => 'admin', 'middleware' => [AuthMiddleware::class, Rol $router->get('/notifications', [AdminController::class, 'notifications']); $router->post('/notifications/send', [AdminController::class, 'sendNotification'], [CSRFMiddleware::class]); $router->post('/notifications/:id/delete', [AdminController::class, 'deleteNotification'], [CSRFMiddleware::class]); + $router->post('/notifications/:id/resend', [AdminController::class, 'resendNotification'], [CSRFMiddleware::class]); $router->get('/policies', [AdminController::class, 'policies']); $router->post('/policies', [AdminController::class, 'savePolicies'], [CSRFMiddleware::class]); diff --git a/src/Controllers/AdminController.php b/src/Controllers/AdminController.php index 036edc2..00912e1 100755 --- a/src/Controllers/AdminController.php +++ b/src/Controllers/AdminController.php @@ -315,6 +315,41 @@ class AdminController $this->view->json(['success' => true, 'message' => 'Notification deleted.']); } + public function resendNotification(int $id): void + { + $this->requireSuperAdmin(); + + $notificationModel = new Notification(); + $note = $notificationModel->findById($id); + + if (!$note) { + $this->view->json(['success' => false, 'message' => 'Notification not found.'], 404); + } + + $title = $note['title']; + $message = $note['message']; + $type = $note['type'] ?? 'info'; + $userId = $note['user_id'] ? (int) $note['user_id'] : null; + + $fcm = new FCMService(); + $pushResult = ''; + if ($userId) { + $sent = $fcm->sendToUser($userId, $title, $message, $type, $id); + $pushResult = $sent ? ' (push sent)' : ($fcm->isConfigured() ? ' (push failed)' : ''); + } else { + $count = $fcm->sendToAll($title, $message, $type, $id); + $pushResult = $fcm->isConfigured() ? " (push sent to {$count} devices)" : ''; + } + + $this->auditService->log('notification_resent', 'notification', $id, [ + 'title' => $title, + 'target' => $userId ? "user #{$userId}" : 'all users', + 'push' => $fcm->isConfigured() ? 'sent' : 'not_configured', + ]); + + $this->view->json(['success' => true, 'message' => 'Notification resent successfully.' . $pushResult]); + } + public function sendNotification(): void { $this->requireSuperAdmin(); diff --git a/views/admin/notifications.php b/views/admin/notifications.php index eb9b659..88d5dcd 100644 --- a/views/admin/notifications.php +++ b/views/admin/notifications.php @@ -67,11 +67,18 @@ $data = $notifications['data'] ?? []; - +
+ + +