Improve reset data module safety and UI

This commit is contained in:
2026-05-02 14:03:52 +07:00
parent a57b17720f
commit cb87dd2f9a
2 changed files with 356 additions and 68 deletions
+126 -5
View File
@@ -7,11 +7,14 @@ use App\Models\Department;
use App\Models\DocumentType;
use App\Models\SchoolClass;
use App\Models\Student;
use App\Models\StudentAchievement;
use App\Models\StudentDocument;
use App\Models\StudentExit;
use App\Models\StudentGraduation;
use App\Models\StudentTransfer;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Illuminate\View\View;
@@ -28,6 +31,10 @@ class MaintenanceController extends Controller
'student_parents' => 'Orang Tua / Wali',
'student_documents' => 'Dokumen Siswa + file storage',
'student_academic_histories' => 'Histori Akademik Siswa',
'student_achievements' => 'Prestasi Siswa + file storage',
'student_exits' => 'Arsip Siswa Keluar + file storage',
'student_transfers' => 'Arsip Mutasi Siswa + file storage',
'student_graduations' => 'Arsip Kelulusan Siswa + file storage',
];
public function index(): View
@@ -42,8 +49,13 @@ class MaintenanceController extends Controller
'studentParents' => DB::table('student_parents')->count(),
'studentDocuments' => StudentDocument::withTrashed()->count(),
'studentAcademicHistories' => DB::table('student_academic_histories')->count(),
'studentAchievements' => StudentAchievement::count(),
'studentExits' => StudentExit::count(),
'studentTransfers' => StudentTransfer::count(),
'studentGraduations' => StudentGraduation::count(),
],
'targets' => $this->availableTargets,
'resolvedTargetsPreview' => $this->buildResolvedTargetPreview(),
]);
}
@@ -76,6 +88,52 @@ class MaintenanceController extends Controller
$resolvedTargets = $this->resolveTargets($targets->all());
DB::transaction(function () use ($resolvedTargets) {
if (in_array('student_achievements', $resolvedTargets, true)) {
StudentAchievement::query()->get()->each(function (StudentAchievement $achievement) {
foreach ([$achievement->certificate_file, $achievement->activity_photo] as $path) {
if ($path && Storage::disk('public')->exists($path)) {
Storage::disk('public')->delete($path);
}
}
});
DB::table('student_achievements')->delete();
}
if (in_array('student_exits', $resolvedTargets, true)) {
StudentExit::query()->get()->each(function (StudentExit $studentExit) {
if ($studentExit->exit_letter_file_path && Storage::disk('public')->exists($studentExit->exit_letter_file_path)) {
Storage::disk('public')->delete($studentExit->exit_letter_file_path);
}
});
DB::table('student_exits')->delete();
}
if (in_array('student_transfers', $resolvedTargets, true)) {
StudentTransfer::query()->get()->each(function (StudentTransfer $studentTransfer) {
if ($studentTransfer->transfer_letter_file_path && Storage::disk('public')->exists($studentTransfer->transfer_letter_file_path)) {
Storage::disk('public')->delete($studentTransfer->transfer_letter_file_path);
}
});
DB::table('student_transfers')->delete();
}
if (in_array('student_graduations', $resolvedTargets, true)) {
StudentGraduation::query()->get()->each(function (StudentGraduation $graduation) {
foreach ([
$graduation->skl_file_path,
$graduation->ijazah_file_path,
$graduation->transcript_file_path,
$graduation->ukk_certificate_file_path,
$graduation->lsp_certificate_file_path,
] as $path) {
if ($path && Storage::disk('public')->exists($path)) {
Storage::disk('public')->delete($path);
}
}
});
DB::table('student_graduations')->delete();
}
if (in_array('students', $resolvedTargets, true)) {
Student::withTrashed()->get()->each->forceDelete();
}
@@ -122,6 +180,22 @@ class MaintenanceController extends Controller
Storage::disk('public')->deleteDirectory('student-documents');
}
if (in_array('student_achievements', $resolvedTargets, true)) {
Storage::disk('public')->deleteDirectory('student-achievements');
}
if (in_array('student_exits', $resolvedTargets, true)) {
Storage::disk('public')->deleteDirectory('student-exit-letters');
}
if (in_array('student_transfers', $resolvedTargets, true)) {
Storage::disk('public')->deleteDirectory('student-transfer-letters');
}
if (in_array('student_graduations', $resolvedTargets, true)) {
Storage::disk('public')->deleteDirectory('student-graduation-documents');
}
$labels = collect($resolvedTargets)
->map(fn ($target) => $this->availableTargets[$target] ?? $target)
->implode(', ');
@@ -136,11 +210,26 @@ class MaintenanceController extends Controller
$resolved = collect($targets);
if ($resolved->contains('students')) {
$resolved = $resolved->merge(['student_documents', 'student_parents', 'student_academic_histories']);
$resolved = $resolved->merge([
'student_documents',
'student_parents',
'student_academic_histories',
'student_achievements',
'student_exits',
'student_transfers',
'student_graduations',
]);
}
if ($resolved->contains('classes')) {
$resolved = $resolved->merge(['students', 'student_academic_histories']);
$resolved = $resolved->merge([
'students',
'student_academic_histories',
'student_achievements',
'student_exits',
'student_transfers',
'student_graduations',
]);
}
if ($resolved->contains('document_types')) {
@@ -148,14 +237,46 @@ class MaintenanceController extends Controller
}
if ($resolved->contains('departments')) {
$resolved = $resolved->merge(['classes', 'students', 'student_academic_histories']);
$resolved = $resolved->merge([
'classes',
'students',
'student_academic_histories',
'student_achievements',
'student_exits',
'student_transfers',
'student_graduations',
]);
}
if ($resolved->contains('academic_years')) {
$resolved = $resolved->merge(['classes', 'students', 'student_academic_histories']);
$resolved = $resolved->merge([
'classes',
'students',
'student_academic_histories',
'student_achievements',
'student_exits',
'student_transfers',
'student_graduations',
]);
}
return $resolved->unique()->values()->all();
}
protected function buildResolvedTargetPreview(): array
{
return collect(array_keys($this->availableTargets))
->mapWithKeys(function (string $target) {
$resolved = $this->resolveTargets([$target]);
return [
$target => collect($resolved)
->map(fn (string $resolvedTarget) => $this->availableTargets[$resolvedTarget] ?? $resolvedTarget)
->values()
->all(),
];
})
->all();
}
}
+202 -35
View File
@@ -1,78 +1,245 @@
<x-master-page title="Kosongkan Data Aplikasi" description="Pilih kelompok data yang ingin dikosongkan. Sistem akan menyesuaikan dependensi relasi agar proses aman dari konflik foreign key.">
<x-master-card title="Reset Data Selektif" subtitle="Gunakan fitur ini dengan hati-hati. Data yang dikosongkan dari menu ini tidak bisa dipulihkan dari UI.">
<div class="rounded-3xl border border-amber-200 bg-amber-50 px-5 py-4 text-sm text-amber-700">
<div class="font-semibold">Catatan penting:</div>
<ul class="mt-3 list-disc space-y-1 pl-5">
<li>Mas bisa memilih tabel/kelompok data tertentu saja.</li>
<li>Backend akan menambahkan dependensi yang wajib ikut dibersihkan supaya tidak bentrok foreign key.</li>
<li>Untuk dokumen siswa, file fisik di storage juga ikut dibersihkan.</li>
<li>Konfirmasi memakai password admin yang sedang login.</li>
</ul>
@php
$statCards = [
['label' => 'Tahun', 'value' => $stats['academicYears'], 'icon' => 'fa-solid fa-calendar-days', 'accent' => 'slate'],
['label' => 'Jurusan', 'value' => $stats['departments'], 'icon' => 'fa-solid fa-layer-group', 'accent' => 'indigo'],
['label' => 'Kelas', 'value' => $stats['classes'], 'icon' => 'fa-solid fa-school', 'accent' => 'sky'],
['label' => 'Jenis Dokumen', 'value' => $stats['documentTypes'], 'icon' => 'fa-solid fa-file-lines', 'accent' => 'violet'],
['label' => 'Siswa', 'value' => $stats['students'], 'icon' => 'fa-solid fa-user-graduate', 'accent' => 'rose'],
['label' => 'Ortu/Wali', 'value' => $stats['studentParents'], 'icon' => 'fa-solid fa-people-roof', 'accent' => 'amber'],
['label' => 'Dokumen', 'value' => $stats['studentDocuments'], 'icon' => 'fa-solid fa-folder-open', 'accent' => 'emerald'],
['label' => 'Histori', 'value' => $stats['studentAcademicHistories'], 'icon' => 'fa-solid fa-clock-rotate-left', 'accent' => 'cyan'],
['label' => 'Prestasi', 'value' => $stats['studentAchievements'], 'icon' => 'fa-solid fa-trophy', 'accent' => 'yellow'],
['label' => 'Keluar', 'value' => $stats['studentExits'], 'icon' => 'fa-solid fa-right-from-bracket', 'accent' => 'orange'],
['label' => 'Mutasi', 'value' => $stats['studentTransfers'], 'icon' => 'fa-solid fa-arrow-right-arrow-left', 'accent' => 'fuchsia'],
['label' => 'Kelulusan', 'value' => $stats['studentGraduations'], 'icon' => 'fa-solid fa-award', 'accent' => 'teal'],
];
$accentClasses = [
'slate' => 'border-slate-200 bg-gradient-to-br from-white via-slate-50 to-slate-100/70 text-slate-700 shadow-slate-200/50 ring-slate-100',
'indigo' => 'border-indigo-200 bg-gradient-to-br from-white via-indigo-50/60 to-indigo-100/60 text-indigo-700 shadow-indigo-100/50 ring-indigo-100',
'sky' => 'border-sky-200 bg-gradient-to-br from-white via-sky-50/60 to-sky-100/60 text-sky-700 shadow-sky-100/50 ring-sky-100',
'violet' => 'border-violet-200 bg-gradient-to-br from-white via-violet-50/60 to-violet-100/60 text-violet-700 shadow-violet-100/50 ring-violet-100',
'rose' => 'border-rose-200 bg-gradient-to-br from-white via-rose-50/60 to-rose-100/60 text-rose-700 shadow-rose-100/50 ring-rose-100',
'amber' => 'border-amber-200 bg-gradient-to-br from-white via-amber-50/60 to-amber-100/60 text-amber-700 shadow-amber-100/50 ring-amber-100',
'emerald' => 'border-emerald-200 bg-gradient-to-br from-white via-emerald-50/60 to-emerald-100/60 text-emerald-700 shadow-emerald-100/50 ring-emerald-100',
'cyan' => 'border-cyan-200 bg-gradient-to-br from-white via-cyan-50/60 to-cyan-100/60 text-cyan-700 shadow-cyan-100/50 ring-cyan-100',
'yellow' => 'border-yellow-200 bg-gradient-to-br from-white via-yellow-50/60 to-yellow-100/60 text-yellow-700 shadow-yellow-100/50 ring-yellow-100',
'orange' => 'border-orange-200 bg-gradient-to-br from-white via-orange-50/60 to-orange-100/60 text-orange-700 shadow-orange-100/50 ring-orange-100',
'fuchsia' => 'border-fuchsia-200 bg-gradient-to-br from-white via-fuchsia-50/60 to-fuchsia-100/60 text-fuchsia-700 shadow-fuchsia-100/50 ring-fuchsia-100',
'teal' => 'border-teal-200 bg-gradient-to-br from-white via-teal-50/60 to-teal-100/60 text-teal-700 shadow-teal-100/50 ring-teal-100',
];
$selectedTargets = old('targets', []);
@endphp
<div class="space-y-6">
<div class="rounded-3xl border border-rose-200 bg-gradient-to-r from-rose-50 via-white to-amber-50 p-6 shadow-sm shadow-rose-100/40 ring-1 ring-white/70">
<div class="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
<div class="max-w-3xl">
<div class="inline-flex items-center gap-2 rounded-full bg-rose-100 px-3 py-1 text-xs font-semibold uppercase tracking-[0.16em] text-rose-700">
<i class="fa-solid fa-triangle-exclamation"></i>
Zona Sensitif
</div>
<h2 class="mt-3 text-2xl font-bold text-slate-900">Reset data selektif untuk bersih-bersih aplikasi</h2>
<p class="mt-2 text-sm leading-6 text-slate-600">Gunakan halaman ini saat Mas memang ingin mengosongkan data tertentu tanpa mengutak-atik struktur aplikasi. Sistem akan menambahkan dependensi penting agar proses hapus tidak mentok foreign key dan file storage terkait ikut dibersihkan.</p>
</div>
<div class="grid min-w-[220px] grid-cols-1 gap-3 sm:grid-cols-2 lg:w-[280px] lg:grid-cols-1">
<div class="rounded-2xl border border-white/70 bg-white/90 px-4 py-3 shadow-sm ring-1 ring-rose-100/70 backdrop-blur-sm">
<div class="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-500">Target Tersedia</div>
<div class="mt-2 text-2xl font-bold text-slate-900">{{ count($targets) }}</div>
</div>
<div class="rounded-2xl border border-white/70 bg-white/90 px-4 py-3 shadow-sm ring-1 ring-amber-100/70 backdrop-blur-sm">
<div class="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-500">Perlu Konfirmasi</div>
<div class="mt-2 text-sm font-semibold text-amber-700">Password admin aktif</div>
</div>
</div>
</div>
<div class="mt-6 grid grid-cols-1 gap-4 md:grid-cols-4 xl:grid-cols-8">
<div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-600"><div class="text-xs uppercase tracking-[0.14em] text-slate-400">Tahun</div><div class="mt-1 text-2xl font-bold text-slate-800">{{ $stats['academicYears'] }}</div></div>
<div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-600"><div class="text-xs uppercase tracking-[0.14em] text-slate-400">Jurusan</div><div class="mt-1 text-2xl font-bold text-slate-800">{{ $stats['departments'] }}</div></div>
<div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-600"><div class="text-xs uppercase tracking-[0.14em] text-slate-400">Kelas</div><div class="mt-1 text-2xl font-bold text-slate-800">{{ $stats['classes'] }}</div></div>
<div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-600"><div class="text-xs uppercase tracking-[0.14em] text-slate-400">Jenis Dokumen</div><div class="mt-1 text-2xl font-bold text-slate-800">{{ $stats['documentTypes'] }}</div></div>
<div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-600"><div class="text-xs uppercase tracking-[0.14em] text-slate-400">Siswa</div><div class="mt-1 text-2xl font-bold text-slate-800">{{ $stats['students'] }}</div></div>
<div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-600"><div class="text-xs uppercase tracking-[0.14em] text-slate-400">Ortu/Wali</div><div class="mt-1 text-2xl font-bold text-slate-800">{{ $stats['studentParents'] }}</div></div>
<div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-600"><div class="text-xs uppercase tracking-[0.14em] text-slate-400">Dokumen</div><div class="mt-1 text-2xl font-bold text-slate-800">{{ $stats['studentDocuments'] }}</div></div>
<div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-600"><div class="text-xs uppercase tracking-[0.14em] text-slate-400">Histori</div><div class="mt-1 text-2xl font-bold text-slate-800">{{ $stats['studentAcademicHistories'] }}</div></div>
<div class="mt-5 grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-4">
<div class="rounded-2xl border border-amber-200 bg-amber-50/90 px-4 py-4 text-sm text-amber-800 shadow-sm shadow-amber-100/40">
<div class="font-semibold">Aman dari relasi putus</div>
<div class="mt-1 text-xs leading-5 text-amber-700">Dependensi wajib dibersihkan otomatis supaya data yatim tidak tertinggal.</div>
</div>
<div class="rounded-2xl border border-rose-200 bg-rose-50/90 px-4 py-4 text-sm text-rose-800 shadow-sm shadow-rose-100/40">
<div class="font-semibold">Tidak ada undo dari UI</div>
<div class="mt-1 text-xs leading-5 text-rose-700">Kalau sudah diproses, pemulihan harus lewat backup atau input ulang data.</div>
</div>
<div class="rounded-2xl border border-emerald-200 bg-emerald-50/90 px-4 py-4 text-sm text-emerald-800 shadow-sm shadow-emerald-100/40">
<div class="font-semibold">Storage ikut dibersihkan</div>
<div class="mt-1 text-xs leading-5 text-emerald-700">Dokumen dan lampiran terkait target reset akan ikut dihapus dari disk publik.</div>
</div>
<div class="rounded-2xl border border-sky-200 bg-sky-50/90 px-4 py-4 text-sm text-sky-800 shadow-sm shadow-sky-100/40">
<div class="font-semibold">Pilih seperlunya</div>
<div class="mt-1 text-xs leading-5 text-sky-700">Mas bisa kosongkan satu area saja tanpa harus reset semuanya sekaligus.</div>
</div>
</div>
</div>
<form method="POST" action="{{ route('settings.reset-data.execute') }}" class="mt-6 space-y-6">
<div class="grid grid-cols-1 gap-4 md:grid-cols-3 xl:grid-cols-6">
@foreach ($statCards as $card)
@php
$cardClasses = $accentClasses[$card['accent']] ?? $accentClasses['slate'];
@endphp
<div class="group rounded-3xl border p-5 shadow-sm ring-1 ring-white/70 transition hover:-translate-y-0.5 hover:shadow-lg {{ $cardClasses }}">
<div class="flex items-start justify-between gap-3">
<div>
<div class="text-xs font-semibold uppercase tracking-[0.16em] opacity-75">{{ $card['label'] }}</div>
<div class="mt-3 text-3xl font-bold text-slate-900">{{ $card['value'] }}</div>
</div>
<div class="rounded-2xl bg-white/85 p-3 text-base shadow-sm ring-1 backdrop-blur-sm {{ $accentClasses[$card['accent']] ?? '' }}">
<i class="{{ $card['icon'] }}"></i>
</div>
</div>
</div>
@endforeach
</div>
<x-master-card title="Pilih Kelompok Data" subtitle="Centang area yang ingin dikosongkan. Keterangan di tiap kartu menjelaskan dampak dan dependensi yang ikut dibersihkan.">
<form method="POST" action="{{ route('settings.reset-data.execute') }}" class="space-y-6" x-data="{ selected: @js($selectedTargets) }">
@csrf
<div>
<div class="mb-3 text-sm font-medium text-slate-700">Pilih data yang ingin dikosongkan</div>
<div class="grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3">
<div class="flex flex-col gap-4 rounded-3xl border border-slate-200 bg-gradient-to-br from-white via-slate-50 to-rose-50/20 p-4 shadow-sm ring-1 ring-white/70 lg:flex-row lg:items-center lg:justify-between">
<div class="max-w-2xl">
<div class="text-sm font-semibold text-slate-800">Pilih target reset</div>
<div class="mt-1 text-xs leading-5 text-slate-500">Gunakan pilihan ini dengan hati-hati. Beberapa target akan menarik dependensi tambahan secara otomatis.</div>
</div>
<div class="flex flex-wrap items-center gap-2 lg:justify-end">
<button
type="button"
@click="selected = @js(array_keys($targets))"
class="inline-flex min-h-[44px] items-center gap-2 rounded-2xl border border-slate-200 bg-white px-4 py-2.5 text-sm font-semibold text-slate-700 transition hover:bg-slate-50"
>
<i class="fa-solid fa-check-double"></i>
<span>Pilih Semua</span>
</button>
<button
type="button"
@click="selected = []"
class="inline-flex min-h-[44px] items-center gap-2 rounded-2xl border border-slate-200 bg-white px-4 py-2.5 text-sm font-semibold text-slate-700 transition hover:bg-slate-50"
>
<i class="fa-solid fa-eraser"></i>
<span>Kosongkan Pilihan</span>
</button>
<div class="inline-flex min-h-[44px] items-center gap-2 rounded-2xl bg-slate-900 px-4 py-2.5 text-sm font-semibold text-white shadow-sm">
<i class="fa-solid fa-list-check"></i>
<span x-text="selected.length + ' dipilih'"></span>
</div>
</div>
</div>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3">
@foreach ($targets as $key => $label)
<label class="flex items-start gap-3 rounded-2xl border border-slate-200 bg-white px-4 py-3 transition hover:border-rose-200 hover:bg-rose-50/40">
<input type="checkbox" name="targets[]" value="{{ $key }}" class="mt-1 rounded border-slate-300 text-rose-600 focus:ring-rose-500" @checked(in_array($key, old('targets', []), true))>
@php
$isSelected = in_array($key, $selectedTargets, true);
@endphp
<label
class="group relative flex cursor-pointer items-start gap-4 rounded-3xl border bg-white p-5 shadow-sm shadow-slate-200/40 ring-1 ring-white/70 transition hover:-translate-y-0.5 hover:shadow-lg"
:class="selected.includes('{{ $key }}') ? 'border-rose-300 bg-rose-50/40 shadow-rose-100/60 ring-rose-100' : 'border-slate-200 hover:border-rose-200'"
>
<input
type="checkbox"
name="targets[]"
value="{{ $key }}"
x-model="selected"
class="mt-1 rounded border-slate-300 text-rose-600 focus:ring-rose-500"
@checked($isSelected)
>
<div class="flex-1">
<div class="flex flex-wrap items-start justify-between gap-3">
<div>
<div class="text-sm font-semibold text-slate-800">{{ $label }}</div>
<div class="mt-1 text-xs text-slate-500">
@switch($key)
@case('students')
Menghapus data siswa; sistem otomatis ikut membersihkan dokumen, orang tua/wali, dan histori akademik.
Menghapus data siswa; sistem otomatis ikut membersihkan dokumen, orang tua/wali, histori akademik, prestasi, arsip keluar, mutasi, dan kelulusan.
@break
@case('classes')
Menghapus master kelas; sistem akan ikut memaksa pembersihan data siswa dan histori yang bergantung.
Menghapus master kelas; sistem akan ikut memaksa pembersihan data siswa dan seluruh data turunan yang bergantung.
@break
@case('document_types')
Menghapus master jenis dokumen; sistem akan ikut membersihkan dokumen siswa yang masih memakai jenis dokumen.
@break
@case('student_achievements')
Menghapus data prestasi siswa beserta file sertifikat dan foto kegiatan yang tersimpan.
@break
@case('student_exits')
Menghapus arsip siswa keluar beserta file surat keluar yang tersimpan.
@break
@case('student_transfers')
Menghapus arsip mutasi siswa beserta file surat mutasi yang tersimpan.
@break
@case('student_graduations')
Menghapus arsip kelulusan siswa beserta dokumen kelulusan yang tersimpan.
@break
@default
Data pada kelompok ini akan dikosongkan sesuai relasi yang diperlukan.
@endswitch
</div>
</div>
</label>
<span
class="inline-flex items-center rounded-full px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.14em]"
:class="selected.includes('{{ $key }}') ? 'bg-rose-100 text-rose-700' : 'bg-slate-100 text-slate-500'"
>
<span x-text="selected.includes('{{ $key }}') ? 'Dipilih' : 'Opsional'"></span>
</span>
</div>
@if (!empty($resolvedTargetsPreview[$key]))
<div class="mt-3 rounded-2xl border border-slate-200 bg-slate-50/90 px-4 py-3 text-[11px] text-slate-600">
<div class="font-semibold uppercase tracking-[0.14em] text-slate-500">Ikut dibersihkan</div>
<div class="mt-2 flex flex-wrap gap-2">
@foreach ($resolvedTargetsPreview[$key] as $resolvedLabel)
<span class="rounded-full bg-white px-3 py-1 font-medium text-slate-600 ring-1 ring-slate-200">{{ $resolvedLabel }}</span>
@endforeach
</div>
</div>
@endif
</div>
</label>
@endforeach
</div>
<div>
<label for="admin_password" class="mb-2 block text-sm font-medium text-slate-700">Password Admin</label>
<div class="grid grid-cols-1 gap-6 xl:grid-cols-[1.15fr_0.85fr]">
<div class="rounded-3xl border border-slate-200 bg-gradient-to-br from-white via-slate-50 to-indigo-50/20 p-5 shadow-sm ring-1 ring-white/70">
<label for="admin_password" class="mb-2 block text-sm font-semibold text-slate-800">Password Admin</label>
<div class="text-xs text-slate-500">Masukkan password akun admin yang sedang login untuk konfirmasi akhir sebelum proses reset dijalankan.</div>
<div class="mt-4 relative">
<span class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-4 text-slate-400">
<i class="fa-solid fa-lock"></i>
</span>
<input
id="admin_password"
name="admin_password"
type="password"
autocomplete="current-password"
class="w-full rounded-2xl border border-slate-200 bg-white px-4 py-3 text-sm text-slate-700 placeholder:text-slate-400 focus:border-rose-300 focus:outline-none focus:ring-2 focus:ring-rose-100"
class="w-full min-h-[48px] rounded-2xl border border-slate-200 bg-white py-3 pl-12 pr-4 text-sm text-slate-700 placeholder:text-slate-400 focus:border-rose-300 focus:outline-none focus:ring-2 focus:ring-rose-100"
placeholder="Masukkan password admin untuk konfirmasi"
>
</div>
</div>
<div class="flex flex-wrap items-center gap-3">
<button type="submit" class="inline-flex items-center rounded-2xl bg-rose-600 px-5 py-3 text-sm font-semibold text-white shadow-lg shadow-rose-200 transition hover:bg-rose-700">
Proses Kosongkan Data
<div class="rounded-3xl border border-rose-200 bg-gradient-to-br from-rose-50 via-white to-rose-100/60 p-5 shadow-sm shadow-rose-100/40 ring-1 ring-white/70">
<div class="text-sm font-semibold text-slate-800">Konfirmasi sebelum eksekusi</div>
<ul class="mt-3 space-y-2 text-xs leading-5 text-slate-600">
<li class="flex gap-2"><i class="fa-solid fa-check mt-0.5 text-rose-500"></i><span>Pastikan target yang dipilih memang ingin dikosongkan sekarang.</span></li>
<li class="flex gap-2"><i class="fa-solid fa-check mt-0.5 text-rose-500"></i><span>Kalau perlu rollback, siapkan backup database dan storage lebih dulu.</span></li>
<li class="flex gap-2"><i class="fa-solid fa-check mt-0.5 text-rose-500"></i><span>File dokumen/lampiran yang terkait juga akan hilang dari storage publik.</span></li>
</ul>
<div class="mt-5 flex flex-wrap items-center gap-3">
<button type="submit" onclick="this.disabled=true; this.innerText='Memproses...'; this.form.submit();" class="inline-flex min-h-[48px] items-center gap-2 rounded-2xl bg-rose-600 px-5 py-3 text-sm font-semibold text-white shadow-lg shadow-rose-200 transition hover:bg-rose-700 disabled:cursor-not-allowed disabled:opacity-70">
<i class="fa-solid fa-trash-can"></i>
<span>Proses Kosongkan Data</span>
</button>
<a href="{{ route('dashboard') }}" class="rounded-2xl border border-slate-200 px-5 py-3 text-sm font-semibold text-slate-700 transition hover:bg-slate-50">
Batal
<a href="{{ route('dashboard') }}" class="inline-flex min-h-[48px] items-center gap-2 rounded-2xl border border-slate-200 bg-white px-5 py-3 text-sm font-semibold text-slate-700 transition hover:bg-slate-50">
<i class="fa-solid fa-arrow-left"></i>
<span>Batal</span>
</a>
</div>
</div>
</div>
</form>
</x-master-card>
</div>
</x-master-page>