From 724813be18a10dd0e6b7806f51592bf5bdece498 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:28:29 +0900 Subject: [PATCH 1/3] =?UTF-8?q?fix:=EC=88=98=EB=8F=99=EA=B1=B0=EB=9E=98=20?= =?UTF-8?q?=EA=B8=88=EC=95=A1=20input=20focus=20=EC=8B=9C=200=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0,=20blur=20=EC=8B=9C=20=EB=B3=B5=EC=9B=90=20(placehold?= =?UTF-8?q?er=20=ED=8C=A8=ED=84=B4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- resources/views/barobill/eaccount/index.blade.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/resources/views/barobill/eaccount/index.blade.php b/resources/views/barobill/eaccount/index.blade.php index 083c291e..30edf791 100644 --- a/resources/views/barobill/eaccount/index.blade.php +++ b/resources/views/barobill/eaccount/index.blade.php @@ -1024,6 +1024,7 @@ className="flex-1 py-2 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700 const [form, setForm] = useState({}); const [saving, setSaving] = useState(false); const [baseBalance, setBaseBalance] = useState(0); + const [focusedField, setFocusedField] = useState(null); const isEditMode = !!editData; @@ -1300,9 +1301,11 @@ className="text-red-600" handleAmountChange('amount', e.target.value)} - placeholder="0" + onFocus={() => setFocusedField('amount')} + onBlur={() => setFocusedField(null)} + placeholder="금액 입력" className="w-full px-3 py-2 border border-stone-200 rounded-lg text-sm focus:ring-2 focus:ring-emerald-500 outline-none text-right" /> @@ -1312,9 +1315,11 @@ className="w-full px-3 py-2 border border-stone-200 rounded-lg text-sm focus:rin handleAmountChange('balance', e.target.value)} - placeholder="0" + onFocus={() => setFocusedField('balance')} + onBlur={() => setFocusedField(null)} + placeholder="잔액" className="w-full px-3 py-2 border border-stone-200 rounded-lg text-sm focus:ring-2 focus:ring-emerald-500 outline-none text-right bg-stone-50" /> {baseBalance !== 0 && ( 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 2/3] =?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'); From 69ede238c6974d36fdecc65ede3ae2c63084cb10 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:43:07 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=EC=97=90=EB=9F=AC=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=20=EC=A0=84=EC=B2=B4=EC=82=AD=EC=A0=9C=20=EC=98=81=EA=B5=AC?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20(SoftDeletes?= =?UTF-8?q?=20bypass)?= 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 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/FcmController.php b/app/Http/Controllers/FcmController.php index 62f059bc..9ec9d15c 100644 --- a/app/Http/Controllers/FcmController.php +++ b/app/Http/Controllers/FcmController.php @@ -88,7 +88,9 @@ public function deleteErrorTokens(Request $request): Response } $count = $query->count(); - $query->delete(); + $query->toBase()->delete(); + + \Log::info("에러 토큰 전체삭제: {$count}건 영구 삭제"); return response('', 200) ->header('HX-Refresh', 'true');