179 lines
8.3 KiB
PHP

@extends('admin.layouts.app')
@section('title', '메일 발송 이력')
@section('page_title', '메일 발송 이력')
@section('page_desc', '배치 단위로 조회합니다.')
@push('head')
<style>
.logbar{display:flex; gap:10px; flex-wrap:wrap; align-items:end;}
.logbar__grow{flex:1; min-width:220px;}
.logbar__actions{display:flex; gap:8px; align-items:center;}
.lbtn{padding:8px 12px;font-size:13px;border-radius:12px;line-height:1.1;text-decoration:none;display:inline-flex;align-items:center;justify-content:center;gap:6px;
border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.06);color:inherit;cursor:pointer;}
.lbtn:hover{background:rgba(255,255,255,.10);}
.lbtn--primary{background:rgba(59,130,246,.88);border-color:rgba(59,130,246,.95);color:#fff;}
.lbtn--primary:hover{background:rgba(59,130,246,.98);}
.lbtn--ghost{background:transparent;}
.pill{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border-radius:999px;font-size:12px;
border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.06);}
.pill--ok{border-color:rgba(34,197,94,.35);background:rgba(34,197,94,.12);}
.pill--warn{border-color:rgba(245,158,11,.35);background:rgba(245,158,11,.12);}
.pill--bad{border-color:rgba(244,63,94,.35);background:rgba(244,63,94,.10);}
.pill--muted{opacity:.9}
.mono{padding:4px 8px;border-radius:10px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.10);
font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:12px;}
.msg-clip{max-width:520px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; opacity:.95;}
.table td{vertical-align:top;}
</style>
@endpush
@section('content')
@php
$statusLabel = [
'scheduled' => '예약',
'queued' => '대기',
'submitting' => '발송중',
'submitted' => '완료',
'partial' => '부분성공',
'failed' => '실패',
'canceled' => '취소',
];
$modeLabel = [
'one' => '단건',
'many' => '여러건',
'template' => '템플릿CSV',
'db' => 'DB검색',
];
@endphp
<div class="a-card" style="padding:16px; margin-bottom:16px;">
<form method="GET" action="{{ route('admin.mail.logs') }}" class="logbar" id="logFilterForm">
<div style="min-width:150px;">
<div class="a-muted" style="margin-bottom:6px;">상태</div>
<select class="a-input" name="status" style="width:150px;">
<option value="">전체</option>
@foreach(array_keys($statusLabel) as $st)
<option value="{{ $st }}" @selected(request('status')===$st)>{{ $statusLabel[$st] }}</option>
@endforeach
</select>
</div>
<div style="min-width:140px;">
<div class="a-muted" style="margin-bottom:6px;">모드</div>
<select class="a-input" name="send_mode" style="width:140px;">
<option value="">전체</option>
@foreach(array_keys($modeLabel) as $m)
<option value="{{ $m }}" @selected(request('send_mode')===$m)>{{ $modeLabel[$m] }}</option>
@endforeach
</select>
</div>
<div style="min-width:230px;">
<div class="a-muted" style="margin-bottom:6px;">기간</div>
<div style="display:flex; gap:8px; align-items:center; flex-wrap:wrap;">
<input class="a-input" type="date" name="date_from" id="dateFrom" value="{{ request('date_from') }}" style="width:140px;">
<span class="a-muted">~</span>
<input class="a-input" type="date" name="date_to" id="dateTo" value="{{ request('date_to') }}" style="width:140px;">
<button type="button" class="lbtn lbtn--ghost" id="dateClear">초기화</button>
</div>
</div>
<div class="logbar__grow">
<div class="a-muted" style="margin-bottom:6px;">검색</div>
<input class="a-input" name="q" value="{{ request('q') }}" placeholder="제목/내용/발신자/IP/작성자 등" style="max-width:360px;">
</div>
<div class="logbar__actions">
<button class="lbtn lbtn--primary" type="submit">조회</button>
<a class="lbtn" href="{{ route('admin.mail.send') }}">발송</a>
<a class="lbtn lbtn--ghost" href="{{ route('admin.mail.logs') }}">필터 초기화</a>
</div>
</form>
</div>
<div class="a-card" style="padding:16px;">
<div style="display:flex; justify-content:space-between; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:10px;">
<div class="a-muted"> <b>{{ $batches->total() }}</b></div>
</div>
<div style="overflow:auto;">
<table class="a-table table" style="width:100%; min-width:1120px;">
<thead>
<tr>
<th style="width:90px;">Batch</th>
<th style="width:160px;">생성일시</th>
<th style="width:160px;">작성자</th>
<th style="width:110px;">모드</th>
<th style="width:170px;">예약</th>
<th style="width:130px;">진행률</th>
<th style="width:140px;">상태</th>
<th>제목</th>
</tr>
</thead>
<tbody>
@forelse($batches as $b)
@php
$st = (string)$b->status;
$pillClass = match ($st) {
'submitted' => 'pill--ok',
'partial','submitting','queued','scheduled' => 'pill--warn',
'failed','canceled' => 'pill--bad',
default => 'pill--muted',
};
$stK = $statusLabel[$st] ?? $st;
$modeK = $modeLabel[(string)$b->send_mode] ?? $b->send_mode;
$sent = (int)($b->sent_count ?? 0);
$total = (int)($b->valid_count ?? $b->total_count ?? 0);
@endphp
<tr>
<td>
<a class="mono" style="text-decoration:none;"
href="{{ route('admin.mail.logs.show', ['batchId'=>$b->id]) }}">#{{ $b->id }}</a>
</td>
<td class="a-muted">{{ $b->created_at }}</td>
<td style="font-weight:700;">{{ $b->admin_name ?? ('#'.$b->admin_user_id) }}</td>
<td><span class="mono">{{ $modeK }}</span></td>
<td class="a-muted">{{ $b->scheduled_at ?? '-' }}</td>
<td><b>{{ $sent }}</b>/{{ $total }}</td>
<td><span class="pill {{ $pillClass }}"> {{ $stK }}</span></td>
<td><div class="msg-clip">{{ $b->subject_raw ?? '-' }}</div></td>
</tr>
@empty
<tr><td colspan="8" class="a-muted">데이터가 없습니다.</td></tr>
@endforelse
</tbody>
</table>
</div>
<div style="margin-top:12px;">
{{ $batches->links() }}
</div>
</div>
@push('scripts')
<script>
(() => {
const from = document.getElementById('dateFrom');
const to = document.getElementById('dateTo');
const clear= document.getElementById('dateClear');
if (!from || !to) return;
from.addEventListener('change', () => {
if (from.value && !to.value) to.value = from.value;
});
clear?.addEventListener('click', () => {
from.value = '';
to.value = '';
});
})();
</script>
@endpush
@endsection