giftcon_dev/resources/views/admin/log/MemberLoginLogController.blade.php
sungro815 b0545ab5b9 관리자 상품관리 완료
웹사이트 상품리스트 상세보기 작업중
2026-02-20 18:11:03 +09:00

249 lines
11 KiB
PHP

{{-- resources/views/admin/log/MemberLoginLogController.blade.php --}}
@extends('admin.layouts.app')
@section('title', '로그인 로그')
@section('page_title', '로그인 로그')
@section('page_desc', '연도별 로그인 이력을 조회합니다.')
@section('content_class', 'a-content--full')
@push('head')
<style>
.bar{display:flex;justify-content:space-between;align-items:flex-end;gap:12px;flex-wrap:wrap;}
.filters{display:flex;gap:8px;flex-wrap:wrap;align-items:flex-end;}
.filters .inp{width:160px;}
.filters .inpWide{width:200px;}
.filters .sel{width:140px;}
.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);text-decoration:none;}
.lbtn--ghost{background:transparent;}
.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);}
.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;display:inline-block;}
.muted{opacity:.8;font-size:12px;}
.nowrap{white-space:nowrap;}
.badge{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);}
.badge--ok{border-color:rgba(34,197,94,.35);background:rgba(34,197,94,.10);}
.badge--bad{border-color:rgba(244,63,94,.35);background:rgba(244,63,94,.10);}
.badge--muted{opacity:.9;}
.badge--mvno{border-color:rgba(245,158,11,.35);background:rgba(245,158,11,.10);}
/* mem link white */
a.memlink{color:#fff;text-decoration:none;}
a.memlink:hover{color:#fff;text-decoration:underline;}
</style>
@endpush
@section('content')
@php
$indexUrl = route('admin.systemlog.member-login-logs', [], false);
$f = $filters ?? [];
$years = $years ?? [];
$year = (int)($f['year'] ?? (int)date('Y'));
$dateFrom = (string)($f['date_from'] ?? '');
$dateTo = (string)($f['date_to'] ?? '');
$memNo = (string)($f['mem_no'] ?? '');
$sf = (string)($f['sf'] ?? '');
$conn = (string)($f['conn'] ?? '');
$ip4 = (string)($f['ip4'] ?? '');
$ip4c = (string)($f['ip4_c'] ?? '');
$err = (string)($f['error_code'] ?? '');
$platform = (string)($f['platform'] ?? '');
$browser = (string)($f['browser'] ?? '');
@endphp
<div class="a-card" style="padding:16px; margin-bottom:16px;">
<div class="bar">
<div>
<div style="font-weight:900;font-size:16px;">로그인 로그</div>
<div class="muted" style="margin-top:4px;">연도별(mem_login_YYYY) 테이블 조회 · 검색/페이징</div>
</div>
<form method="GET" action="{{ $indexUrl }}" class="filters" id="frmFilters">
<div>
<label class="muted">년도</label>
<select class="a-input sel" name="year" id="selYear">
@foreach($years as $y)
<option value="{{ $y }}" {{ (int)$y === (int)$year ? 'selected' : '' }}>{{ $y }}</option>
@endforeach
</select>
</div>
<div>
<label class="muted">From</label>
<input class="a-input inp" type="date" name="date_from" value="{{ $dateFrom }}">
</div>
<div>
<label class="muted">To</label>
<input class="a-input inp" type="date" name="date_to" value="{{ $dateTo }}">
</div>
<div>
<label class="muted">mem_no</label>
<input class="a-input inp" name="mem_no" value="{{ $memNo }}" inputmode="numeric" placeholder="ex) 70665">
</div>
<div>
<label class="muted">성공/실패</label>
<select class="a-input sel" name="sf">
<option value="">전체</option>
<option value="s" {{ $sf==='s'?'selected':'' }}>성공</option>
<option value="f" {{ $sf==='f'?'selected':'' }}>실패</option>
</select>
</div>
<div>
<label class="muted">PC/M</label>
<select class="a-input sel" name="conn">
<option value="">전체</option>
<option value="1" {{ $conn==='1'?'selected':'' }}>PC</option>
<option value="2" {{ $conn==='2'?'selected':'' }}>Mobile</option>
</select>
</div>
<div>
<label class="muted">ip4</label>
<input class="a-input inp" name="ip4" value="{{ $ip4 }}" placeholder="211.235.">
</div>
<div>
<label class="muted">ip4_c</label>
<input class="a-input inp" name="ip4_c" value="{{ $ip4c }}" placeholder="211.235.75">
</div>
<div>
<label class="muted">error_code</label>
<input class="a-input inp" name="error_code" value="{{ $err }}" placeholder="pw / E3">
</div>
<div>
<label class="muted">platform</label>
<input class="a-input inp" name="platform" value="{{ $platform }}" placeholder="Android / iOS">
</div>
<div>
<label class="muted">browser</label>
<input class="a-input inpWide" name="browser" value="{{ $browser }}" placeholder="Chrome / Safari">
</div>
<div style="display:flex;gap:8px;align-items:flex-end;">
<button class="lbtn lbtn--ghost" type="submit">검색</button>
<a class="lbtn lbtn--ghost" href="{{ $indexUrl }}">초기화</a>
</div>
</form>
</div>
</div>
<div class="a-card" style="padding:16px;">
<div class="a-muted" style="margin-bottom:10px;"> <b>{{ $page->total() }}</b></div>
<div style="overflow:auto;">
<table class="a-table table" style="width:100%; min-width:1200px;">
<thead>
<tr>
<th style="width:90px;">SEQ</th>
<th style="width:210px;">일시</th>
<th style="width:150px;">회원</th>
<th style="width:140px;">결과</th>
<th style="width:140px;">경로</th>
<th style="width:320px;">IP</th>
<th>플랫폼/브라우저</th>
<th style="width:160px;">실패코드</th>
</tr>
</thead>
<tbody>
@forelse(($items ?? []) as $r0)
@php
$r = is_array($r0) ? $r0 : (array)$r0;
$seq = (int)($r['seq'] ?? 0);
$memNoInt = (int)($r['mem_no_int'] ?? 0);
$memLink = $r['mem_link'] ?? null;
$sf = (string)($r['sf'] ?? 's');
$errCode = trim((string)($r['error_code'] ?? ''));
// 성공이면 실패코드는 비움(요구에 따라 여기서 제어)
$errShow = ($sf === 'f' && $errCode !== '') ? $errCode : '';
$ip4 = (string)($r['ip4'] ?? '');
$ip4c = (string)($r['ip4_c'] ?? '');
$plat = trim((string)($r['platform'] ?? ''));
$brow = trim((string)($r['browser'] ?? ''));
@endphp
<tr>
<td class="a-muted">{{ $seq }}</td>
<td class="a-muted nowrap">{{ $r['dt_reg'] ?? '-' }}</td>
<td>
@if($memNoInt > 0 && $memLink)
<a href="{{ $memLink }}" class="mono memlink" target="_blank" rel="noopener">{{ $memNoInt }}</a>
@else
<span class="mono">0</span>
@endif
</td>
<td>
<span class="badge {{ $r['sf_badge'] ?? 'badge--muted' }}">{{ $r['sf_label'] ?? '-' }}</span>
</td>
<td>
<span class="badge {{ $r['conn_badge'] ?? 'badge--muted' }}">{{ $r['conn_label'] ?? '-' }}</span>
</td>
<td class="nowrap">
<span class="mono">{{ $ip4 !== '' ? $ip4 : '-' }}</span>
@if($ip4c !== '')
<span class="mono" style="opacity:.75">{{ $ip4c }}</span>
@endif
</td>
<td>
<span class="mono">{{ $plat !== '' ? $plat : '-' }}</span>
<span class="mono" style="opacity:.85">{{ $brow !== '' ? $brow : '-' }}</span>
</td>
<td>
@if($errShow !== '')
<span class="mono">{{ $errShow }}</span>
@else
<span class="a-muted">-</span>
@endif
</td>
</tr>
@empty
<tr><td colspan="8" class="a-muted" style="padding:16px;">데이터가 없습니다.</td></tr>
@endforelse
</tbody>
</table>
</div>
<div style="margin-top:12px;">
{{ $page->onEachSide(1)->links('vendor.pagination.admin') }}
</div>
</div>
<script>
(function(){
const sel = document.getElementById('selYear');
const frm = document.getElementById('frmFilters');
if (!sel || !frm) return;
sel.addEventListener('change', () => {
// ✅ 선택 즉시 이동(= GET submit), page 파라미터는 자동 리셋
frm.submit();
});
})();
</script>
@endsection