Files
database-kesiswaan/resources/views/maintenance/reset-data.blade.php
T

246 lines
20 KiB
PHP

<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.">
@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-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>
<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 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)
@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, histori akademik, prestasi, arsip keluar, mutasi, dan kelulusan.
@break
@case('classes')
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>
<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 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 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="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="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>