Files
database-kesiswaan/resources/views/graduated-students/bulk-upload.blade.php
T

136 lines
10 KiB
PHP

<x-master-page title="Bulk Upload Dokumen Kelulusan" description="Upload SKL atau ijazah dalam jumlah besar dengan pencocokan otomatis berdasarkan NIS atau NISN.">
<div class="space-y-6">
<x-master-card title="Bulk Upload Dokumen Kelulusan" subtitle="Gunakan nama file sesuai NIS atau NISN agar sistem dapat mencocokkan dokumen secara otomatis ke siswa lulus.">
<div class="mb-6 rounded-2xl border border-sky-200 bg-sky-50 px-4 py-4 text-sm text-sky-700">
<p class="font-semibold">Aturan nama file yang disarankan</p>
<ul class="mt-2 list-disc space-y-1 pl-5 text-sky-700/90">
<li>Jika memilih pencocokan <strong>NIS</strong>, nama file harus berupa NIS siswa. Contoh: <code>2024001.pdf</code></li>
<li>Jika memilih pencocokan <strong>NISN</strong>, nama file harus berupa NISN siswa. Contoh: <code>9988776655.pdf</code></li>
<li>Upload dipisah per jenis dokumen: jalankan batch <strong>SKL</strong> dan <strong>Ijazah</strong> secara terpisah agar lebih aman.</li>
<li>Untuk meminimalkan error, gunakan maksimal <strong>10 file</strong> per batch dengan ukuran maksimal <strong>2 MB</strong> per file.</li>
</ul>
</div>
<form method="POST" action="{{ route('graduated-students.bulk-upload.preview') }}" enctype="multipart/form-data" class="space-y-6">
@csrf
<div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
<div>
<label for="document_type" class="mb-2 block text-sm font-medium text-slate-700">Jenis Dokumen</label>
<select id="document_type" name="document_type" class="h-12 w-full rounded-2xl border border-slate-200 bg-white px-4 text-sm text-slate-700 focus:border-indigo-300 focus:outline-none focus:ring-4 focus:ring-indigo-100" required>
<option value="">Pilih jenis dokumen</option>
@foreach ($documentTypes as $value => $label)
<option value="{{ $value }}" @selected(old('document_type') === $value)>{{ $label }}</option>
@endforeach
</select>
<x-input-error :messages="$errors->get('document_type')" class="mt-2" />
</div>
<div>
<label for="match_by" class="mb-2 block text-sm font-medium text-slate-700">Cocokkan Berdasarkan</label>
<select id="match_by" name="match_by" class="h-12 w-full rounded-2xl border border-slate-200 bg-white px-4 text-sm text-slate-700 focus:border-indigo-300 focus:outline-none focus:ring-4 focus:ring-indigo-100" required>
@foreach ($matchByOptions as $value => $label)
<option value="{{ $value }}" @selected(old('match_by', 'student_number') === $value)>{{ $label }}</option>
@endforeach
</select>
<x-input-error :messages="$errors->get('match_by')" class="mt-2" />
</div>
</div>
<div>
<label for="documents" class="mb-2 block text-sm font-medium text-slate-700">Pilih Banyak Dokumen Sekaligus</label>
<input id="documents" name="documents[]" type="file" accept=".pdf,.jpg,.jpeg,.png" multiple class="block w-full rounded-2xl border border-slate-200 bg-white px-4 py-3 text-sm text-slate-700 file:mr-4 file:rounded-xl file:border-0 file:bg-slate-100 file:px-4 file:py-2 file:text-sm file:font-semibold file:text-slate-700 hover:file:bg-slate-200">
<p class="mt-2 text-xs text-slate-500">Format yang didukung: PDF, JPG, JPEG, PNG. Maksimal 2 MB per file dan 10 file per batch upload.</p>
<x-input-error :messages="$errors->get('documents')" class="mt-2" />
<x-input-error :messages="$errors->get('documents.*')" class="mt-2" />
</div>
<div class="flex flex-wrap items-center gap-3">
<button type="submit" class="inline-flex items-center rounded-2xl bg-indigo-600 px-5 py-3 text-sm font-semibold text-white shadow-lg shadow-indigo-200 transition hover:bg-indigo-700">
Preview Mapping Dokumen
</button>
<a href="{{ route('graduated-students.index') }}" class="inline-flex items-center rounded-2xl border border-slate-200 px-5 py-3 text-sm font-semibold text-slate-700 transition hover:bg-slate-50">
Kembali ke Data Siswa Lulus
</a>
</div>
</form>
</x-master-card>
@if ($preview)
<x-master-card title="Preview Hasil Mapping" :subtitle="'Periksa hasil pencocokan file ' . $preview['document_label'] . ' sebelum diproses permanen.'">
<div class="mb-6 grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-5">
<div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-4">
<div class="text-xs font-semibold uppercase tracking-[0.16em] text-slate-500">Jenis Dokumen</div>
<div class="mt-2 text-lg font-bold text-slate-900">{{ $preview['document_label'] }}</div>
</div>
<div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-4">
<div class="text-xs font-semibold uppercase tracking-[0.16em] text-slate-500">Pencocokan</div>
<div class="mt-2 text-lg font-bold text-slate-900">{{ $preview['match_by_label'] }}</div>
</div>
<div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-4">
<div class="text-xs font-semibold uppercase tracking-[0.16em] text-slate-500">Total File</div>
<div class="mt-2 text-lg font-bold text-slate-900">{{ $preview['summary']['total_files'] }}</div>
</div>
<div class="rounded-2xl border border-emerald-200 bg-emerald-50 px-4 py-4">
<div class="text-xs font-semibold uppercase tracking-[0.16em] text-emerald-700">Cocok</div>
<div class="mt-2 text-lg font-bold text-emerald-800">{{ $preview['summary']['matched'] }}</div>
</div>
<div class="rounded-2xl border border-amber-200 bg-amber-50 px-4 py-4">
<div class="text-xs font-semibold uppercase tracking-[0.16em] text-amber-700">Akan Replace</div>
<div class="mt-2 text-lg font-bold text-amber-800">{{ $preview['summary']['will_replace'] }}</div>
</div>
</div>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-slate-200 text-sm">
<thead class="bg-slate-50 text-left text-slate-500">
<tr>
<th class="px-4 py-3 font-semibold">Nama File</th>
<th class="px-4 py-3 font-semibold">Key Terdeteksi</th>
<th class="px-4 py-3 font-semibold">Siswa Lulus</th>
<th class="px-4 py-3 font-semibold">Status</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-100 bg-white">
@foreach ($preview['rows'] as $row)
<tr>
<td class="px-4 py-3 text-slate-700">{{ $row['original_name'] }}</td>
<td class="px-4 py-3 text-slate-600">{{ $row['match_key'] ?: '-' }}</td>
<td class="px-4 py-3 text-slate-700">
@if ($row['graduation_id'])
<div class="font-semibold text-slate-900">{{ $row['student_name'] }}</div>
<div class="text-xs text-slate-500">{{ $preview['match_by_label'] }}: {{ $row['identifier_value'] ?: '-' }}</div>
@else
<span class="text-slate-400">Tidak ditemukan</span>
@endif
</td>
<td class="px-4 py-3">
@if ($row['status'] === 'matched')
<div class="flex flex-wrap gap-2">
<span class="inline-flex rounded-full bg-emerald-100 px-3 py-1 text-xs font-semibold text-emerald-700">Siap Diproses</span>
@if ($row['will_replace'])
<span class="inline-flex rounded-full bg-amber-100 px-3 py-1 text-xs font-semibold text-amber-700">Replace Dokumen Lama</span>
@endif
</div>
@else
<span class="inline-flex rounded-full bg-rose-100 px-3 py-1 text-xs font-semibold text-rose-700">Tidak Cocok</span>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<form method="POST" action="{{ route('graduated-students.bulk-upload.store') }}" class="mt-6 flex flex-wrap items-center gap-3">
@csrf
<input type="hidden" name="preview_token" value="{{ $preview['token'] }}">
<button type="submit" class="inline-flex items-center rounded-2xl bg-emerald-600 px-5 py-3 text-sm font-semibold text-white shadow-lg shadow-emerald-200 transition hover:bg-emerald-700">
Proses Bulk Upload
</button>
</form>
</x-master-card>
@endif
</div>
</x-master-page>