163 lines
7.3 KiB
PHP
163 lines
7.3 KiB
PHP
@extends('admin.layouts.app')
|
|
|
|
@section('title', 'SMS 이력 상세')
|
|
@section('page_title', 'SMS 이력 상세')
|
|
@section('page_desc', '배치 및 수신자별 상세')
|
|
|
|
@push('head')
|
|
<style>
|
|
/* logs show page only */
|
|
.sbtn{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;}
|
|
.sbtn:hover{background:rgba(255,255,255,.10);}
|
|
.sbtn--primary{background:rgba(59,130,246,.88);border-color:rgba(59,130,246,.95);color:#fff;}
|
|
.sbtn--primary:hover{background:rgba(59,130,246,.98);}
|
|
.sbtn--ghost{background:transparent;}
|
|
|
|
.kv{display:grid;grid-template-columns:repeat(5, minmax(160px,1fr));gap:14px;align-items:start;}
|
|
@media (max-width: 1100px){.kv{grid-template-columns:repeat(2, minmax(160px,1fr));}}
|
|
.kv .k{font-size:12px;opacity:.75;}
|
|
.kv .v{font-weight:800;font-size:14px;margin-top:4px;}
|
|
.kv .v.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-weight:700;}
|
|
|
|
.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);}
|
|
|
|
.msgbox{white-space:pre-wrap;background:rgba(255,255,255,.03);padding:12px;border-radius:12px;border:1px solid rgba(255,255,255,.08);}
|
|
.clip{max-width:560px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
|
|
.table td{vertical-align:top;}
|
|
</style>
|
|
@endpush
|
|
|
|
@section('content')
|
|
@php
|
|
$STATUS_LABELS = $labels ?? [];
|
|
$MODE_LABELS = $modeLabels ?? [];
|
|
$ITEM_LABELS = $itemLabels ?? [];
|
|
$st = (string)$batch->status;
|
|
$pillClass = match ($st) {
|
|
'submitted' => 'pill--ok',
|
|
'partial','submitting','queued','scheduled' => 'pill--warn',
|
|
'failed','canceled' => 'pill--bad',
|
|
default => 'pill--warn',
|
|
};
|
|
@endphp
|
|
|
|
<div class="a-card" style="padding:16px; margin-bottom:16px;">
|
|
<div class="kv">
|
|
<div>
|
|
<div class="k">Batch ID</div>
|
|
<div class="v mono">#{{ $batch->id }}</div>
|
|
</div>
|
|
<div>
|
|
<div class="k">상태</div>
|
|
<span class="pill {{ $pillClass }}">● {{ $STATUS_LABELS[$st] ?? $st }}</span>
|
|
</div>
|
|
<div>
|
|
<div class="k">모드</div>
|
|
<div class="v mono">{{ $batch->send_mode }}</div>
|
|
</div>
|
|
<div>
|
|
<div class="k">예약</div>
|
|
<div class="v">{{ $batch->scheduled_at ?? '-' }}</div>
|
|
</div>
|
|
<div>
|
|
<div class="k">건수</div>
|
|
<div class="v">
|
|
유효 <b>{{ $batch->valid_count }}</b> /
|
|
전체 {{ $batch->total_count }} /
|
|
중복 {{ $batch->duplicate_count }} /
|
|
오류 {{ $batch->invalid_count }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<hr style="margin:14px 0; opacity:.15;">
|
|
|
|
<div class="a-muted" style="margin-bottom:6px;">문구</div>
|
|
<div class="msgbox">{{ $batch->message_raw }}</div>
|
|
|
|
<div style="margin-top:12px; display:flex; gap:8px; flex-wrap:wrap; justify-content:flex-end;">
|
|
<a class="sbtn" href="{{ route('admin.sms.logs') }}">목록</a>
|
|
<a class="sbtn sbtn--primary" href="{{ route('admin.sms.send') }}">새 발송</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="a-card" style="padding:16px;">
|
|
<form method="GET"
|
|
action="{{ route('admin.sms.logs.show', ['batchId'=>$batch->id]) }}"
|
|
style="display:flex; gap:10px; flex-wrap:wrap; align-items:end; margin-bottom:12px;">
|
|
|
|
<div style="min-width:160px;">
|
|
<div class="a-muted" style="margin-bottom:6px;">상태</div>
|
|
<select class="a-input" name="status">
|
|
<option value="">전체</option>
|
|
@foreach(array_keys($ITEM_LABELS) as $st)
|
|
<option value="{{ $st }}" @selected(request('status')===$st)>{{ $ITEM_LABELS[$st] }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
|
|
<div style="min-width:200px;">
|
|
<div class="a-muted" style="margin-bottom:6px;">수신번호</div>
|
|
<input class="a-input" name="to" value="{{ request('to') }}" placeholder="010...">
|
|
</div>
|
|
|
|
<div style="flex:1; min-width:240px;">
|
|
<div class="a-muted" style="margin-bottom:6px;">메시지 검색</div>
|
|
<input class="a-input" name="q" value="{{ request('q') }}" placeholder="치환된 메시지 내용">
|
|
</div>
|
|
|
|
<div style="display:flex; gap:8px;">
|
|
<button class="sbtn sbtn--primary" type="submit">필터</button>
|
|
<a class="sbtn sbtn--ghost" href="{{ route('admin.sms.logs.show', ['batchId'=>$batch->id]) }}">초기화</a>
|
|
</div>
|
|
</form>
|
|
|
|
<div style="overflow:auto;">
|
|
<table class="a-table table" style="width:100%; min-width:1100px;">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:90px;">Seq</th>
|
|
<th style="width:150px;">수신번호</th>
|
|
<th style="width:90px;">타입</th>
|
|
<th style="width:120px;">상태</th>
|
|
<th style="width:190px;">제출시간</th>
|
|
<th>메시지</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@forelse($items as $it)
|
|
@php
|
|
$ist = (string)$it->status;
|
|
$ic = match ($ist) {
|
|
'submitted' => 'pill--ok',
|
|
'failed' => 'pill--bad',
|
|
'canceled','skipped' => 'pill--bad',
|
|
default => 'pill--warn',
|
|
};
|
|
@endphp
|
|
<tr>
|
|
<td class="a-muted">{{ $it->seq }}</td>
|
|
<td style="font-weight:800;">{{ $it->to_number }}</td>
|
|
<td><span class="mono">{{ $it->sms_type }}</span></td>
|
|
<td><span class="pill {{ $ic }}">● {{ $ITEM_LABELS[$ist] ?? $ist }}</span></td>
|
|
<td class="a-muted">{{ $it->submitted_at ?? '-' }}</td>
|
|
<td><div class="clip">{{ $it->message_final }}</div></td>
|
|
</tr>
|
|
@empty
|
|
<tr><td colspan="6" class="a-muted">상세 데이터가 없습니다.</td></tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div style="margin-top:12px;">
|
|
{{ $items->onEachSide(1)->links('vendor.pagination.admin') }}
|
|
</div>
|
|
</div>
|
|
@endsection
|