175 lines
8.0 KiB
PHP

@extends('admin.layouts.app')
@section('title', '관리자 계정 관리')
@section('page_title', '관리자 계정 관리')
@section('page_desc', '계정/2FA/최근로그인/역할 정보를 관리합니다.')
@section('content_class', 'a-content--full')
@push('head')
<style>
/* admins index only */
.bar{display:flex;justify-content:space-between;align-items:flex-end;gap:12px;flex-wrap:wrap;}
.bar__left .t{font-weight:900;font-size:16px;}
.bar__left .d{font-size:12px;margin-top:4px;}
.bar__right{display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end;}
.filters{display:flex;gap:8px;flex-wrap:wrap;align-items:flex-end;}
.filters .q{width:210px;}
.filters .st{width:150px;}
.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--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;}
.lbtn--sm{padding:7px 10px;font-size:12px;border-radius:11px;}
.lbtn--wide{padding:10px 14px;font-weight:800;}
.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--bad{border-color:rgba(244,63,94,.35);background:rgba(244,63,94,.10);}
.pill--warn{border-color:rgba(245,158,11,.35);background:rgba(245,158,11,.12);}
.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;}
.clip{max-width:230px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.muted12{font-size:12px;}
.row-disabled{opacity:.65;}
.table td{vertical-align:top;}
</style>
@endpush
@section('content')
<div class="a-card" style="padding:16px; margin-bottom:16px;">
<div class="bar">
<div class="bar__left">
<div class="t">관리자 계정 관리</div>
<div class="a-muted d">계정/2FA/최근로그인/역할 정보를 관리합니다.</div>
</div>
<div class="bar__right">
<a class="lbtn lbtn--primary lbtn--wide"
href="{{ route('admin.admins.create', request()->only(['q','status','page'])) }}">
+ 관리자 등록
</a>
<form method="GET" action="{{ route('admin.admins.index') }}" class="filters">
<div>
<input class="a-input q" name="q" value="{{ $filters['q'] ?? '' }}" placeholder="이메일/성명/닉네임">
</div>
<div>
<select class="a-input st" name="status">
<option value="">전체</option>
<option value="active" {{ (($filters['status'] ?? '')==='active')?'selected':'' }}>활성</option>
<option value="blocked" {{ (($filters['status'] ?? '')==='blocked')?'selected':'' }}>비활성</option>
</select>
</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="{{ route('admin.admins.index') }}">초기화</a>
</div>
</form>
</div>
</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:70px;">ID</th>
<th style="width:150px;">닉네임</th>
<th style="width:120px;">성명</th>
<th style="width:230px;">이메일</th>
<th style="width:110px;">상태</th>
<th style="width:120px;">잠금</th>
<th style="width:120px;">2FA 모드</th>
<th style="width:120px;">TOTP</th>
<th>역할</th>
<th style="width:170px;">최근 로그인</th>
<th style="width:90px;">관리</th>
</tr>
</thead>
<tbody>
@forelse($page as $u)
@php
$uid = (int)$u->id;
$roles = $roleMap[$uid] ?? [];
$st = (string)($u->status ?? '');
$isLocked = !empty($u->locked_until);
$stLabel = $st === 'active' ? '활성' : ($st === 'blocked' ? '비활성' : ($st ?: '-'));
$stPill = $st === 'active' ? 'pill--ok' : ($st === 'blocked' ? 'pill--bad' : 'pill--muted');
$twofa = (string)($u->two_factor_mode ?? 'sms');
$twofaLabel = ($twofa === 'totp' || $twofa === 'otp') ? 'OTP' : 'SMS';
$totpOn = (int)($u->totp_enabled ?? 0) === 1;
@endphp
<tr class="{{ $st === 'blocked' ? 'row-disabled' : '' }}">
<td class="a-muted">{{ $uid }}</td>
<td>{{ $u->nickname ?? '-' }}</td>
<td>{{ $u->name ?? '-' }}</td>
<td><span class="mono">{{ $u->email ?? '-' }}</span></td>
<td>
<span class="pill {{ $stPill }}"> {{ $stLabel }}</span>
</td>
<td style="font-weight:800;">
@if($isLocked)
<span class="pill pill--bad"> 잠김</span>
@else
<span class="pill pill--ok"> 정상</span>
@endif
</td>
<td><span class="mono">{{ $twofaLabel }}</span></td>
<td>
@if($totpOn)
<span class="pill pill--ok">On</span>
@else
<span class="pill pill--muted">Off</span>
@endif
</td>
<td>
@forelse($roles as $r)
<span class="a-chip">{{ $r['name'] ?? $r['code'] }}</span>
@empty
<span class="a-muted">-</span>
@endforelse
</td>
<td class="a-muted">{{ $u->last_login_at ?? '-' }}</td>
<td style="text-align:right;">
<a class="lbtn lbtn--ghost lbtn--sm"
href="{{ route('admin.admins.edit', ['id'=>$uid]) }}">
보기
</a>
</td>
</tr>
@empty
<tr><td colspan="11" class="a-muted" style="padding:18px;">데이터가 없습니다.</td></tr>
@endforelse
</tbody>
</table>
</div>
<div style="margin-top:14px;">
{{ $page->links() }}
</div>
</div>
@endsection