From 0a39e7d7441ab54b47dd90e08e30ff6abc291eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Wed, 11 Feb 2026 15:39:26 +0900 Subject: [PATCH] =?UTF-8?q?feat:FCM=20=EC=97=90=EB=9F=AC=20=ED=86=A0?= =?UTF-8?q?=ED=81=B0=20=EC=A0=84=EC=B2=B4=EC=82=AD=EC=A0=9C=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- app/Http/Controllers/FcmController.php | 18 ++++++++++++++++++ resources/views/fcm/tokens.blade.php | 16 ++++++++++++++++ routes/web.php | 1 + 3 files changed, 35 insertions(+) diff --git a/app/Http/Controllers/FcmController.php b/app/Http/Controllers/FcmController.php index 851a7e32..62f059bc 100644 --- a/app/Http/Controllers/FcmController.php +++ b/app/Http/Controllers/FcmController.php @@ -76,6 +76,24 @@ public function deleteToken(int $id): Response ->header('HX-Trigger', 'tokenDeleted'); } + /** + * 에러 토큰 전체 삭제 + */ + public function deleteErrorTokens(Request $request): Response + { + $query = PushDeviceToken::withoutGlobalScopes()->whereNotNull('last_error'); + + if ($tenantId = $request->get('tenant_id')) { + $query->where('tenant_id', $tenantId); + } + + $count = $query->count(); + $query->delete(); + + return response('', 200) + ->header('HX-Refresh', 'true'); + } + /** * FCM 테스트 발송 페이지 */ diff --git a/resources/views/fcm/tokens.blade.php b/resources/views/fcm/tokens.blade.php index 755642c6..93ab806d 100644 --- a/resources/views/fcm/tokens.blade.php +++ b/resources/views/fcm/tokens.blade.php @@ -87,6 +87,22 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc + + @if($stats['has_error'] > 0) +
+ + 에러 토큰 {{ $stats['has_error'] }}건이 있습니다. + + +
+ @endif +
diff --git a/routes/web.php b/routes/web.php index d4b9e510..a9503986 100644 --- a/routes/web.php +++ b/routes/web.php @@ -672,6 +672,7 @@ Route::get('/tokens/stats', [FcmController::class, 'tokenStats'])->name('tokens.stats'); Route::post('/tokens/{id}/toggle', [FcmController::class, 'toggleToken'])->name('tokens.toggle'); Route::delete('/tokens/{id}', [FcmController::class, 'deleteToken'])->name('tokens.delete'); + Route::delete('/tokens-error/bulk', [FcmController::class, 'deleteErrorTokens'])->name('tokens.deleteError'); // 테스트 발송 Route::get('/send', [FcmController::class, 'send'])->name('send');