Files
sam-manage/resources/views/archived-records/restore-check.blade.php
hskwon 5c892c1ed9 브라우저 alert/confirm을 SweetAlert2로 전환
- layouts/app.blade.php에 SweetAlert2 CDN 및 전역 헬퍼 함수 추가
  - showToast(): 토스트 알림 (success, error, warning, info)
  - showConfirm(): 확인 대화상자
  - showDeleteConfirm(): 삭제 확인 (경고 아이콘)
  - showPermanentDeleteConfirm(): 영구 삭제 확인 (빨간색 경고)
  - showSuccess(), showError(): 성공/에러 알림

- 변환된 파일 목록 (48개 Blade 파일):
  - menus/* (6개), boards/* (2개), posts/* (3개)
  - daily-logs/* (3개), project-management/* (6개)
  - dev-tools/flow-tester/* (6개)
  - quote-formulas/* (4개), permission-analyze/* (1개)
  - archived-records/* (1개), profile/* (1개)
  - roles/* (3개), permissions/* (3개)
  - departments/* (3개), tenants/* (3개), users/* (3개)

- 주요 개선사항:
  - Tailwind CSS 테마와 일관된 디자인
  - 비동기 콜백 패턴으로 리팩토링
  - 삭제/복원/영구삭제 각각 다른 스타일 적용
2025-12-05 09:49:56 +09:00

182 lines
10 KiB
PHP

@extends('layouts.app')
@section('title', '데이터 복원 확인')
@section('content')
<!-- 페이지 헤더 -->
<div class="flex justify-between items-center mb-6">
<div class="flex items-center gap-4">
<a href="{{ route('archived-records.show', $batchInfo['batch_id']) }}"
class="text-gray-500 hover:text-gray-700 transition">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
</svg>
</a>
<h1 class="text-2xl font-bold text-gray-800">데이터 복원 확인</h1>
</div>
</div>
<!-- 복원 가능 여부 확인 -->
@if($restoreCheck['can_restore'])
<div class="mb-6 p-4 bg-green-50 border border-green-200 rounded-lg">
<div class="flex items-start">
<svg class="w-6 h-6 text-green-600 mr-3 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div>
<h3 class="text-lg font-semibold text-green-800">복원 가능</h3>
<p class="text-green-700 mt-1"> 데이터는 복원할 있습니다. 아래 내용을 확인 복원을 진행해 주세요.</p>
</div>
</div>
</div>
@else
<div class="mb-6 p-4 bg-red-50 border border-red-200 rounded-lg">
<div class="flex items-start">
<svg class="w-6 h-6 text-red-600 mr-3 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div>
<h3 class="text-lg font-semibold text-red-800">복원 불가</h3>
<p class="text-red-700 mt-1">다음 이유로 복원할 없습니다:</p>
<ul class="list-disc list-inside mt-2 text-red-700">
@foreach($restoreCheck['issues'] as $issue)
<li>{{ $issue }}</li>
@endforeach
</ul>
</div>
</div>
</div>
@endif
<!-- 작업 요약 정보 -->
<div class="bg-white rounded-lg shadow-sm mb-6">
<div class="px-6 py-4 border-b border-gray-200">
<h2 class="text-lg font-semibold text-gray-800">복원할 데이터 요약</h2>
</div>
<div class="p-6">
<dl class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<div>
<dt class="text-sm font-medium text-gray-500">작업 설명</dt>
<dd class="mt-1 text-sm text-gray-900 font-medium">{{ $batchInfo['batch_description'] ?? '삭제 작업' }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">복원 대상 레코드 </dt>
<dd class="mt-1">
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
{{ $restoreCheck['record_count'] ?? $batchInfo['record_count'] }}
</span>
</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">삭제자</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $batchInfo['deleted_by'] }}</dd>
</div>
<div>
<dt class="text-sm font-medium text-gray-500">삭제일시</dt>
<dd class="mt-1 text-sm text-gray-900">{{ $batchInfo['deleted_at']?->format('Y-m-d H:i:s') ?? '-' }}</dd>
</div>
</dl>
</div>
</div>
<!-- 복원될 레코드 목록 -->
<div class="bg-white rounded-lg shadow-sm mb-6">
<div class="px-6 py-4 border-b border-gray-200">
<h2 class="text-lg font-semibold text-gray-800">복원될 레코드 목록</h2>
</div>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">#</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">타입</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">원본 ID</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">주요 정보</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">관련 데이터</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
@foreach($records as $index => $record)
@php
$mainData = is_array($record->main_data) ? $record->main_data : json_decode($record->main_data, true);
$displayName = $mainData['name'] ?? $mainData['company_name'] ?? $mainData['title'] ?? $mainData['email'] ?? '-';
@endphp
<tr class="hover:bg-gray-50">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ $index + 1 }}</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium
{{ $record->record_type === 'tenant' ? 'bg-blue-100 text-blue-800' : '' }}
{{ $record->record_type === 'user' ? 'bg-green-100 text-green-800' : '' }}
{{ $record->record_type === 'department' ? 'bg-yellow-100 text-yellow-800' : '' }}
{{ $record->record_type === 'role' ? 'bg-purple-100 text-purple-800' : '' }}
{{ $record->record_type === 'menu' ? 'bg-pink-100 text-pink-800' : '' }}
">
{{ $record->record_type_label }}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ $record->original_id }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 font-medium">{{ $displayName }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
@if($record->relations->isNotEmpty())
{{ $record->relations->count() }} 테이블
@else
-
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<!-- 복원 주의사항 -->
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-6 mb-6">
<div class="flex items-start">
<svg class="w-6 h-6 text-yellow-600 mr-3 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
<div>
<h3 class="text-lg font-semibold text-yellow-800">복원 주의사항</h3>
<ul class="list-disc list-inside mt-2 text-yellow-700 space-y-1">
<li>복원된 데이터는 <strong>새로운 ID</strong> 할당됩니다.</li>
<li>테넌트 복원 관련 부서, 메뉴, 역할이 함께 복원됩니다.</li>
<li>사용자 복원 테넌트 관계가 복원됩니다. (해당 테넌트가 존재하는 경우)</li>
<li>복원 완료 아카이브 레코드는 삭제됩니다.</li>
<li>복원 작업은 트랜잭션으로 처리되며, 오류 롤백됩니다.</li>
</ul>
</div>
</div>
</div>
<!-- 액션 버튼 -->
<div class="flex justify-end gap-4">
<a href="{{ route('archived-records.show', $batchInfo['batch_id']) }}"
class="inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-gray-700 font-medium text-sm rounded-lg hover:bg-gray-50 transition">
취소
</a>
@if($restoreCheck['can_restore'])
<form id="restoreForm" action="{{ route('archived-records.restore', $batchInfo['batch_id']) }}" method="POST">
@csrf
<button type="button"
onclick="confirmRestore()"
class="inline-flex items-center px-6 py-2 bg-green-600 hover:bg-green-700 text-white font-medium text-sm rounded-lg transition">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
복원 실행
</button>
</form>
@endif
</div>
@endsection
@push('scripts')
<script>
function confirmRestore() {
showConfirm('정말로 이 데이터를 복원하시겠습니까?\n\n복원된 데이터는 새로운 ID가 할당되며, 아카이브 레코드는 삭제됩니다.', () => {
document.getElementById('restoreForm').submit();
}, { title: '데이터 복원', icon: 'question' });
}
</script>
@endpush