- FCM 토큰 관리 페이지 (목록, 활성화/비활성화, 삭제) - 테스트 발송 페이지 (대상 필터, 미리보기, 발송) - 발송 이력 페이지 (필터링, 결과 확인) - FcmSender 서비스 (HTTP v1, 배치 처리) - fcm_send_logs 테이블 마이그레이션 - google/auth 패키지 추가
98 lines
4.4 KiB
PHP
98 lines
4.4 KiB
PHP
@extends('layouts.app')
|
|
|
|
@section('title', 'FCM 토큰 관리')
|
|
|
|
@section('content')
|
|
<div>
|
|
<!-- 페이지 헤더 -->
|
|
<div class="flex justify-between items-center mb-6">
|
|
<h1 class="text-2xl font-bold text-gray-800">FCM 토큰 관리</h1>
|
|
<div class="flex gap-2">
|
|
<a href="{{ route('fcm.send') }}" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition">
|
|
테스트 발송
|
|
</a>
|
|
<a href="{{ route('fcm.history') }}" class="bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-lg transition">
|
|
발송 이력
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 통계 카드 -->
|
|
<div id="stats-container"
|
|
hx-get="{{ route('fcm.tokens.stats') }}"
|
|
hx-trigger="tokenDeleted from:body">
|
|
@include('fcm.partials.token-stats', ['stats' => $stats])
|
|
</div>
|
|
|
|
<!-- 필터 영역 -->
|
|
<div class="bg-white rounded-lg shadow-sm p-4 mb-6">
|
|
<form id="filter-form"
|
|
hx-get="{{ route('fcm.tokens.list') }}"
|
|
hx-target="#table-container"
|
|
hx-trigger="submit, change from:select"
|
|
hx-push-url="true">
|
|
<div class="flex flex-wrap gap-4">
|
|
<!-- 테넌트 필터 -->
|
|
<div class="w-48">
|
|
<select name="tenant_id" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<option value="">전체 테넌트</option>
|
|
@foreach($tenants as $tenant)
|
|
<option value="{{ $tenant->id }}" {{ request('tenant_id') == $tenant->id ? 'selected' : '' }}>
|
|
{{ $tenant->company_name }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
|
|
<!-- 플랫폼 필터 -->
|
|
<div class="w-36">
|
|
<select name="platform" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<option value="">전체 플랫폼</option>
|
|
<option value="android" {{ request('platform') === 'android' ? 'selected' : '' }}>Android</option>
|
|
<option value="ios" {{ request('platform') === 'ios' ? 'selected' : '' }}>iOS</option>
|
|
<option value="web" {{ request('platform') === 'web' ? 'selected' : '' }}>Web</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- 상태 필터 -->
|
|
<div class="w-36">
|
|
<select name="is_active" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<option value="">전체 상태</option>
|
|
<option value="1" {{ request('is_active') === '1' ? 'selected' : '' }}>활성</option>
|
|
<option value="0" {{ request('is_active') === '0' ? 'selected' : '' }}>비활성</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- 에러 필터 -->
|
|
<div class="flex items-center">
|
|
<label class="flex items-center cursor-pointer">
|
|
<input type="checkbox" name="has_error" value="1" {{ request('has_error') ? 'checked' : '' }} class="mr-2">
|
|
<span class="text-sm text-gray-700">에러 토큰만</span>
|
|
</label>
|
|
</div>
|
|
|
|
<!-- 검색 -->
|
|
<div class="flex-1 min-w-[200px]">
|
|
<input type="text"
|
|
name="search"
|
|
value="{{ request('search') }}"
|
|
placeholder="토큰, 기기명, 사용자 검색..."
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
</div>
|
|
|
|
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition">
|
|
검색
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- 테이블 -->
|
|
<div class="bg-white rounded-lg shadow-sm overflow-hidden">
|
|
<div id="table-container">
|
|
@include('fcm.partials.token-table', ['tokens' => $tokens])
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endsection
|