226 lines
9.1 KiB
PHP
226 lines
9.1 KiB
PHP
@extends('admin.layouts.app')
|
|
|
|
@section('title', '관리자 정보 수정')
|
|
|
|
@section('content')
|
|
@php
|
|
$ip = !empty($admin->last_login_ip) ? inet_ntop($admin->last_login_ip) : '-';
|
|
|
|
$lockedUntil = $admin->locked_until ?? null;
|
|
$isLocked = false;
|
|
|
|
if (!empty($lockedUntil)) {
|
|
try {
|
|
$isLocked = \Carbon\Carbon::parse($lockedUntil)->isFuture();
|
|
} catch (\Throwable $e) {
|
|
$isLocked = true; // 파싱 실패 시 보수적으로 잠김 처리
|
|
}
|
|
}
|
|
|
|
$lockLabel = (string)($admin->locked_until ?? '');
|
|
$lockLabelLabel = $lockLabel === "" ? '계정정상' : '계정잠금';
|
|
$lockLabelColor = $lockLabel === "" ? '#2b7fff' : '#ff4d4f';
|
|
|
|
$st = (string)($admin->status ?? 'active');
|
|
$statusLabel = $st === 'active' ? '활성' : '비활성';
|
|
$statusColor = $st === 'active' ? '#2b7fff' : '#ff4d4f';
|
|
@endphp
|
|
|
|
{{-- ===== 상단 정보 패널 ===== --}}
|
|
<div class="a-kvgrid">
|
|
|
|
<div class="a-kv">
|
|
<div class="a-kv__k">관리자번호/이메일</div>
|
|
<div class="a-kv__v a-mono">{{ $admin->id ?? '-' }} / {{ $admin->email ?? '-' }}</div>
|
|
</div>
|
|
|
|
<div class="a-kv">
|
|
<div class="a-kv__k">현재 역할</div>
|
|
<div class="a-kv__v">
|
|
@forelse($roles as $rr)
|
|
<span class="a-chip">{{ $rr['name'] ?? ($rr['code'] ?? '-') }}</span>
|
|
@empty
|
|
<span class="a-muted">-</span>
|
|
@endforelse
|
|
</div>
|
|
</div>
|
|
|
|
<div class="a-kv">
|
|
<div class="a-kv__k">상태</div>
|
|
<div class="a-kv__v">
|
|
<span style="font-weight:900; color:{{ $statusColor }};">{{ $statusLabel }}</span>
|
|
@if($st !== 'active')
|
|
<span class="a-muted" style="margin-left:6px;">(관리자 로그인 불가)</span>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
<div class="a-kv">
|
|
<div class="a-kv__k">계정상태</div>
|
|
<div class="a-kv__v">
|
|
<span style="font-weight:900; color:{{ $lockLabelColor }};">{{ $lockLabelLabel }}</span>
|
|
</div>
|
|
<div class="a-muted" style="font-size:12px; margin-top:10px;">
|
|
※ 로그인 비밀번호 3회 연속 실패 시 계정이 잠깁니다.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="a-kv">
|
|
<div class="a-kv__k">로그인 실패 횟수</div>
|
|
<div class="a-kv__v">{{ (int)($admin->failed_login_count ?? 0) }}</div>
|
|
</div>
|
|
|
|
<div class="a-kv">
|
|
<div class="a-kv__k">마지막 로그인 아이피</div>
|
|
<div class="a-kv__v a-mono">{{ $ip }}</div>
|
|
</div>
|
|
|
|
<div class="a-kv">
|
|
<div class="a-kv__k">마지막 로그인 시간</div>
|
|
<div class="a-kv__v">{{ $admin->last_login_at ?? '-' }}</div>
|
|
</div>
|
|
|
|
<div class="a-kv">
|
|
<div class="a-kv__k">관리자 생성 일시</div>
|
|
<div class="a-kv__v">{{ $admin->created_at ?? '-' }}</div>
|
|
</div>
|
|
|
|
<div class="a-kv">
|
|
<div class="a-kv__k">최근 정보수정일</div>
|
|
<div class="a-kv__v">{{ $admin->updated_at ?? '-' }}</div>
|
|
</div>
|
|
|
|
<div class="a-kv">
|
|
<div class="a-kv__k">비활성화 처리자</div>
|
|
<div class="a-kv__v">{{ $admin->deleted_by ?? '-' }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="height:12px;"></div>
|
|
|
|
{{-- ===== 수정 폼(단 하나) ===== --}}
|
|
<form id="adminEditForm"
|
|
method="POST"
|
|
action="{{ route('admin.admins.update', ['id'=>$admin->id]) }}"
|
|
onsubmit="this.querySelector('button[type=submit][data-submit=save]')?.setAttribute('disabled','disabled');">
|
|
@csrf
|
|
|
|
<div class="a-panel">
|
|
<div class="a-field">
|
|
<label class="a-label">닉네임</label>
|
|
<input class="a-input" name="nickname" value="{{ old('nickname', $admin->nickname ?? '') }}">
|
|
</div>
|
|
|
|
<div class="a-field">
|
|
<label class="a-label">성명</label>
|
|
<input class="a-input" name="name" value="{{ old('name', $admin->name ?? '') }}">
|
|
</div>
|
|
|
|
<div class="a-field">
|
|
<label class="a-label">휴대폰(01055558888 숫자만 등록하세요)</label>
|
|
<input class="a-input" name="phone" value="{{ old('phone', $phone ?? '') }}" placeholder="01012345678">
|
|
<div class="a-muted" style="font-size:12px; margin-top:6px;">
|
|
※ 저장 시 phone_hash + phone_enc 갱신
|
|
</div>
|
|
</div>
|
|
|
|
<div class="a-field">
|
|
<label class="a-label">상태</label>
|
|
<select class="a-input" name="status">
|
|
@php $st = old('status', $admin->status ?? 'active'); @endphp
|
|
<option value="active" {{ $st==='active'?'selected':'' }}>활성</option>
|
|
<option value="blocked" {{ $st==='blocked'?'selected':'' }}>비활성</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="a-field">
|
|
<label class="a-label">
|
|
2차 인증방법
|
|
@if(!empty($admin->totp_secret_enc))
|
|
<span class="a-pill a-pill--ok">Google OTP 등록</span>
|
|
@else
|
|
<span class="a-pill a-pill--muted">Google OTP 미등록</span>
|
|
@endif
|
|
</label>
|
|
|
|
<select class="a-input" name="totp_enabled">
|
|
<option value="0" {{ (int)old('totp_enabled', $admin->totp_enabled ?? 0)===0 ? 'selected' : '' }}>SMS 인증</option>
|
|
<option value="1"
|
|
{{ (int)old('totp_enabled', $admin->totp_enabled ?? 0)===1 ? 'selected' : '' }}
|
|
{{ empty($admin->totp_secret_enc) ? 'disabled' : '' }}
|
|
>Google OTP 인증</option>
|
|
</select>
|
|
|
|
@if(empty($admin->totp_secret_enc))
|
|
<div class="a-muted" style="font-size:12px; margin-top:6px;">
|
|
※ Google OTP 미등록 상태라 선택할 수 없습니다. (등록은 ‘내 정보’에서만 가능)
|
|
</div>
|
|
@endif
|
|
</div>
|
|
|
|
<div class="a-field">
|
|
<label class="a-label">역할(Role)</label>
|
|
<div class="a-muted" style="font-size:12px; margin-bottom:8px;">여러 개 선택 가능</div>
|
|
|
|
<div style="display:flex; flex-wrap:wrap; gap:10px;">
|
|
@foreach($allRoles as $r)
|
|
@php $rid = (int)$r['id']; @endphp
|
|
<label class="a-check" style="margin:0;">
|
|
<input type="checkbox" name="role_ids[]" value="{{ $rid }}"
|
|
{{ in_array($rid, $roleIds ?? [], true) ? 'checked' : '' }}>
|
|
<span>{{ $r['name'] ?? $r['code'] }}</span>
|
|
</label>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
{{-- ===== 하단 액션바(폼 밖) ===== --}}
|
|
<div class="a-actions">
|
|
<a class="a-btn a-btn--white a-btn--sm"
|
|
href="{{ route('admin.admins.index', request()->only(['q','status','page'])) }}"
|
|
style="width:auto;">
|
|
뒤로가기
|
|
</a>
|
|
|
|
<div class="a-actions__right">
|
|
@if($lockLabel)
|
|
<form method="POST"
|
|
action="{{ route('admin.admins.unlock', $admin->id) }}"
|
|
style="display:inline;"
|
|
data-confirm="이 계정의 잠금을 해제할까요? (locked_until 초기화 + 실패횟수 0)"
|
|
onsubmit="this.querySelector('button[type=submit]')?.setAttribute('disabled','disabled');"
|
|
>
|
|
@csrf
|
|
<button class="a-btn a-btn--dangerSolid a-btn--sm" type="submit" style="width:auto;">
|
|
잠금해제
|
|
</button>
|
|
</form>
|
|
@endif
|
|
|
|
|
|
<form method="POST"
|
|
action="{{ route('admin.admins.reset_password', $admin->id) }}"
|
|
style="display:inline;"
|
|
data-confirm="비밀번호를 초기화할까요? 임시 비밀번호는 이메일로 설정됩니다. (다음 로그인 시 변경 강제)"
|
|
onsubmit="this.querySelector('button[type=submit]')?.setAttribute('disabled','disabled');"
|
|
>
|
|
@csrf
|
|
<button class="a-btn a-btn--dangerSolid a-btn--sm" type="submit" style="width:auto;">
|
|
비밀번호 초기화
|
|
</button>
|
|
</form>
|
|
|
|
<button class="a-btn a-btn--primary a-btn--sm"
|
|
form="adminEditForm"
|
|
type="submit"
|
|
data-submit="save"
|
|
style="width:auto;
|
|
">
|
|
저장
|
|
</button>
|
|
</div>
|
|
</div>
|
|
@endsection
|