MIF_E31222658/resources/views/admin/pengajuan/detail.blade.php

822 lines
40 KiB
PHP

@extends('layouts.app')
@section('title', 'Detail Pengajuan UKT - ' . $pengajuan->mahasiswa->nama)
@section('content')
<div class="container-fluid">
<div class="row mb-4">
<div class="col-12">
<div class="d-flex justify-content-between align-items-center">
<h2 class="h3 text-primary mb-0">
<i class="fas fa-file-alt mr-2"></i>Detail Pengajuan UKT
</h2>
<a href="{{ route('admin.pengajuan') }}" class="btn btn-secondary">
<i class="fas fa-arrow-left mr-2"></i>Kembali
</a>
</div>
</div>
</div>
@if($pengajuan->status_validasi == 'tidak valid')
<div class="row">
<div class="col-12">
<div class="alert alert-danger">
<h5><i class="fas fa-exclamation-triangle mr-2"></i>Alasan Penolakan</h5>
@foreach($pengajuan->details as $detail)
@if($detail->rejection_reason)
<p class="mb-1">
<strong>{{ $detail->kriteria }}:</strong>
@if(strpos($detail->rejection_reason, 'Lainnya:') === 0)
{{ substr($detail->rejection_reason, 8) }}
@else
{{ $detail->rejection_reason }}
@endif
</p>
@endif
@endforeach
</div>
</div>
</div>
@endif
@if(auth()->user()->role == 'admin' && $pengajuan->status_validasi != 'menunggu')
<div class="row mb-3">
<div class="col-12">
<div class="alert alert-warning">
<i class="fas fa-exclamation-circle mr-2"></i> Anda sedang berada dalam mode admin untuk revalidasi
</div>
</div>
</div>
@endif
<div class="row">
<div class="col-lg-6 mb-4">
<div class="card shadow-sm">
<div class="card-header bg-primary text-white">
<h5 class="mb-0">
<i class="fas fa-user-graduate mr-2"></i>Informasi Mahasiswa
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-8">
<table class="table table-sm table-borderless">
<tr>
<th width="35%">Nama Lengkap</th>
<td>{{ $pengajuan->mahasiswa->user->name ?? '-' }}</td>
</tr>
<tr>
<th>NIM</th>
<td>{{ $pengajuan->mahasiswa->nim }}</td>
</tr>
<tr>
<th>Program Studi</th>
<td>{{ $pengajuan->mahasiswa->program_studi ?? '-' }}</td>
</tr>
<tr>
<th>Jurusan</th>
<td>{{ $pengajuan->mahasiswa->jurusan ?? '-' }}</td>
</tr>
<tr>
<th>UKT Saat Ini</th>
<td>
@if($pengajuan->ukt_saat_ini)
Rp {{ number_format($pengajuan->ukt_saat_ini, 0, ',', '.') }}
@else
-
@endif
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-4">
<div class="card shadow-sm">
<div class="card-header bg-primary text-white">
<h5 class="mb-0">
<i class="fas fa-file-signature mr-2"></i>Detail Pengajuan
</h5>
</div>
<div class="card-body">
<table class="table table-sm table-borderless">
<tr>
<th width="35%">Jenis Pengajuan</th>
<td>
<span class="badge {{ $pengajuan->jenis_pengajuan == 'penurunan' ? 'badge-primary' : 'badge-info' }}">
{{ ucfirst($pengajuan->jenis_pengajuan) }}
</span>
</td>
</tr>
<tr>
<th>Tanggal Pengajuan</th>
<td>{{ \Carbon\Carbon::parse($pengajuan->created_at)->locale('id')->translatedFormat('d F Y H:i') }}</td>
</tr>
<tr>
<th>Alasan Pengajuan</th>
<td>
@if($pengajuan->alasan_pengajuan && trim($pengajuan->alasan_pengajuan) !== '')
{{ $pengajuan->alasan_pengajuan }}
@else
<span class="text-muted">Tidak ada alasan yang dicantumkan</span>
@endif
</td>
</tr>
<tr>
<th>Status</th>
<td>
@if($pengajuan->status_validasi == 'menunggu')
<span class="badge badge-warning">
<i class="fas fa-clock mr-1"></i>Menunggu
</span>
@elseif($pengajuan->status_validasi == 'valid')
<span class="badge badge-success">
<i class="fas fa-check-circle mr-1"></i>Valid
</span>
@else
<span class="badge badge-danger">
<i class="fas fa-times-circle mr-1"></i>Tidak Valid
</span>
@endif
@if($pengajuan->status_validasi != 'menunggu')
<div class="small text-dark mt-1">
@if($pengajuan->validator_id == auth()->id() && $pengajuan->status_validasi != 'menunggu')
<i class="fas fa-info-circle"></i> Diupdate oleh Anda (Admin) pada {{ $pengajuan->updated_at->format('d/m/Y H:i') }}
@elseif($pengajuan->verified_by)
<i class="fas fa-info-circle"></i> Divalidasi oleh {{ $pengajuan->verified_by->name }} pada {{ $pengajuan->updated_at->format('d/m/Y H:i') }}
@endif
</div>
@endif
</td>
</tr>
@if($pengajuan->status_validasi != 'menunggu')
<tr>
<th>Tanggal Validasi</th>
<td>{{ \Carbon\Carbon::parse($pengajuan->updated_at)->locale('id')->translatedFormat('l, d F Y H:i') }}</td>
</tr>
@endif
</table>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card shadow-sm">
<div class="card-header bg-primary text-white d-flex justify-content-between align-items-center">
<h5 class="mb-0">
<i class="fas fa-file-upload mr-2"></i>Dokumen Pendukung dan Validasi
</h5>
</div>
<div class="alert alert-info mb-3">
<i class="fas fa-info-circle mr-2"></i> Centang terlebih dahulu untuk mengubah status validasi dokumen
</div>
<div class="card-body">
@php
$role = auth()->user()->role;
$formAction = '';
if ($role === 'karyawan' && $pengajuan->status_validasi === 'menunggu') {
$formAction = route('karyawan.pengajuan.verify', $pengajuan->id);
} elseif ($role === 'admin' && $pengajuan->status_validasi !== 'menunggu') {
$formAction = route('admin.pengajuan.revalidate', $pengajuan->id);
}
@endphp
<form action="{{ $formAction }}" method="POST" id="revalidationForm" {{ $formAction ? '' : 'onsubmit=return false;' }}>
@csrf
@if(auth()->user()->role === 'admin' && $pengajuan->status_validasi !== 'menunggu')
@method('PUT')
@endif
<div class="table-responsive">
<table class="table table-bordered">
<thead style="background-color: #f8f9fa; color: #212529;">
<tr>
<th width="5%">No</th>
<th width="20%">Kriteria</th>
<th width="20%">Subkriteria Dipilih</th>
<th width="20%">Dokumen</th>
<th width="20%">Status Validasi</th>
@if(in_array(auth()->user()->role, ['admin', 'karyawan']))
<th width="20%">Alasan (jika tidak valid)</th>
@endif
</tr>
</thead>
<tbody>
@foreach($pengajuan->details as $index => $detail)
<tr class="{{ auth()->user()->role == 'karyawan' && $pengajuan->status_validasi != 'menunggu' ? 'bg-warning-light' : '' }}">
<td>{{ $index + 1 }}</td>
<td>{{ $detail->kriteria }}</td>
<td>{{ $detail->subkriteria_text ?? '-' }}</td>
<td>
@if($detail->file_dokumen)
<button class="btn btn-sm btn-primary view-document"
data-url="{{ route('pengajuan.document.view', [
'pengajuanId' => $pengajuan->id,
'docType' => Str::slug($detail->kriteria)
])}}"
data-title="Dokumen {{ $detail->kriteria }}">
<i class="fas fa-eye"></i> Lihat Dokumen
</button>
@else
<span class="badge badge-danger">
<i class="fas fa-times-circle"></i> Tidak ada dokumen
</span>
@endif
</td>
<td>
@if(auth()->user()->role == 'admin' && $pengajuan->status_validasi != 'menunggu')
{{-- Mode revalidasi admin --}}
<div class="d-flex align-items-center gap-2">
<div class="form-check form-switch mb-0">
<input class="form-check-input status-toggle"
type="checkbox"
id="status_{{ $detail->id }}"
name="valid[{{ $detail->id }}]"
value="1"
data-detail-id="{{ $detail->id }}"
{{ $detail->verified && !$detail->rejection_reason ? 'checked' : '' }}>
</div>
<span class="status-text" id="status_text_{{ $detail->id }}">
@if($detail->verified && !$detail->rejection_reason)
<span class="badge bg-success text-white">Valid</span>
@elseif(!$detail->verified && $detail->rejection_reason)
<span class="badge bg-danger text-white">Tidak Valid</span>
@else
<span class="badge bg-secondary text-white">Belum Diverifikasi</span>
@endif
</span>
</div>
@if($detail->verifier)
<div class="small text-muted mt-1">
<i class="fas fa-user-check"></i> {{ $detail->verifier->name }}
</div>
@endif
@elseif($pengajuan->status_validasi == 'menunggu' && in_array(auth()->user()->role, ['admin', 'karyawan']))
{{-- Mode validasi awal --}}
<div class="d-flex align-items-center gap-2">
<div class="form-check form-switch mb-0">
<input class="form-check-input status-toggle"
type="checkbox"
id="status_{{ $detail->id }}"
name="valid[{{ $detail->id }}]"
value="1"
data-detail-id="{{ $detail->id }}"
{{ $detail->verified && !$detail->rejection_reason ? 'checked' : '' }}>
</div>
<span class="status-text" id="status_text_{{ $detail->id }}">
@if($detail->verified && !$detail->rejection_reason)
<span class="badge bg-success text-white">Valid</span>
@elseif(!$detail->verified && $detail->rejection_reason)
<span class="badge bg-danger text-white">Tidak Valid</span>
@else
<span class="badge bg-secondary text-white">Belum Diverifikasi</span>
@endif
</span>
</div>
@else
{{-- Mode view only --}}
@if($detail->verified && !$detail->rejection_reason)
<span class="badge bg-success text-white">Valid</span>
@elseif(!$detail->verified && $detail->rejection_reason)
<span class="badge bg-danger text-white">Tidak Valid</span>
@else
<span class="badge bg-secondary text-white">Belum Diverifikasi</span>
@endif
@endif
</td>
@if(in_array(auth()->user()->role, ['admin', 'karyawan']))
<td>
@if(auth()->user()->role == 'admin' && $pengajuan->status_validasi != 'menunggu')
{{-- Mode edit alasan untuk revalidasi admin --}}
<div class="d-flex flex-column">
<select class="form-select form-select-sm alasan-select mb-2"
name="alasan[{{ $detail->id }}]"
id="alasan_select_{{ $detail->id }}"
data-detail-id="{{ $detail->id }}"
{{ $detail->verified && !$detail->rejection_reason ? 'disabled' : '' }}
style="{{ $detail->verified && !$detail->rejection_reason ? 'display:none;' : '' }}">
<option value="">Pilih Alasan</option>
@php
$reasons = App\Http\Controllers\AdminPengajuanController::REJECTION_REASONS_BY_CRITERIA[$detail->kriteria] ?? [];
$hasLainnya = collect($reasons)->map(function ($item) {
return strtolower(trim($item));
})->contains('lainnya');
@endphp
@foreach($reasons as $reason)
<option value="{{ $reason }}"
{{ ($detail->rejection_reason == $reason || (strpos($detail->rejection_reason ?? '', 'Lainnya:') !== false && $reason == 'Lainnya')) ? 'selected' : '' }}>
{{ $reason }}
</option>
@endforeach
</select>
<textarea class="form-control form-control-sm alasan-lainnya text-dark fw-bold"
name="alasan_lainnya[{{ $detail->id }}]"
id="alasan_lainnya_{{ $detail->id }}"
placeholder="Isi alasan lainnya"
style="{{ strpos($detail->rejection_reason ?? '', 'Lainnya:') !== false ? '' : 'display:none;' }}"
{{ $detail->verified && !$detail->rejection_reason ? 'disabled' : '' }}>{{ strpos($detail->rejection_reason ?? '', 'Lainnya:') !== false ? substr($detail->rejection_reason, 8) : '' }}</textarea>
</div>
{{-- Tampilkan info verifikasi awal --}}
@if($detail->verifier && $detail->verifier->id != auth()->id())
<div class="small text-muted mt-2">
<i class="fas fa-info-circle"></i>
Awalnya divalidasi oleh {{ $detail->verifier->name }}
</div>
@endif
@elseif($pengajuan->status_validasi == 'menunggu')
{{-- Mode validasi awal untuk admin/karyawan --}}
<div class="d-flex flex-column">
<select class="form-select form-select-sm alasan-select mb-2"
name="alasan[{{ $detail->id }}]"
id="alasan_select_{{ $detail->id }}"
data-detail-id="{{ $detail->id }}"
{{ $detail->verified && !$detail->rejection_reason ? 'disabled' : '' }}
style="{{ $detail->verified && !$detail->rejection_reason ? 'display:none;' : '' }}">
<option value="">Pilih Alasan</option>
@php
$reasons = App\Http\Controllers\AdminPengajuanController::REJECTION_REASONS_BY_CRITERIA[$detail->kriteria] ?? [];
@endphp
@foreach($reasons as $reason)
<option value="{{ $reason }}"
{{ ($detail->rejection_reason == $reason || (strpos($detail->rejection_reason ?? '', 'Lainnya:') !== false && $reason == 'Lainnya')) ? 'selected' : '' }}>
{{ $reason }}
</option>
@endforeach
</select>
<textarea class="form-control form-control-sm alasan-lainnya"
name="alasan_lainnya[{{ $detail->id }}]"
id="alasan_lainnya_{{ $detail->id }}"
placeholder="Isi alasan lainnya"
style="{{ strpos($detail->rejection_reason ?? '', 'Lainnya:') !== false ? '' : 'display:none;' }}"
{{ $detail->verified && !$detail->rejection_reason ? 'disabled' : '' }}>{{ strpos($detail->rejection_reason ?? '', 'Lainnya:') !== false ? substr($detail->rejection_reason, 8) : '' }}</textarea>
</div>
@else
{{-- Mode view only --}}
@if($detail->rejection_reason)
<span class="text-danger fw-semibold">
@if(strpos($detail->rejection_reason, 'Lainnya:') === 0)
{{ substr($detail->rejection_reason, 8) }}
@else
{{ $detail->rejection_reason }}
@endif
</span>
@else
-
@endif
{{-- Tampilkan info verifikasi --}}
@if($detail->verifier)
<div class="small text-dark mt-1">
<i class="fas fa-user-check"></i>
{{ $detail->verifier->name }}
{{ $detail->updated_at ? $detail->updated_at->format('d/m/Y H:i') : '-' }}
</div>
@endif
@endif
</td>
@endif
</tr>
@endforeach
</tbody>
</table>
</div>
@if(auth()->user()->role == 'admin' && $pengajuan->status_validasi != 'menunggu')
<button type="submit" class="btn btn-primary" id="submitButton">
<i class="fas fa-save mr-1"></i> Simpan Revalidasi
</button>
@elseif(auth()->user()->role == 'karyawan' && $pengajuan->status_validasi == 'menunggu')
<button type="submit" class="btn btn-primary" id="submitButton">
<i class="fas fa-save mr-1"></i> Simpan Validasi
</button>
@endif
<div id="loadingOverlay" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 9999;">
<div class="d-flex justify-content-center align-items-center flex-column h-100">
<div class="spinner-border text-primary" style="width:3rem; height:3rem;"></div>
<span class="ms-2 text-white my-3" id="loadingText">Memproses...</span>
<button id="forceCloseLoading" class="btn btn-danger">
<i class="fas fa-times mr-1"></i> Batalkan Proses
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="documentModal" tabindex="-1" aria-labelledby="documentModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header bg-primary text-white">
<h5 class="modal-title" id="documentModalLabel">Lihat Dokumen</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body p-0">
<div class="ratio ratio-1x1">
<iframe id="documentFrame" src="" allowfullscreen style="border: none;"></iframe>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
<i class="fas fa-times mr-2"></i>Tutup
</button>
<a id="downloadDocument" href="#" class="btn btn-primary" download>
<i class="fas fa-download mr-2"></i>Unduh Dokumen
</a>
</div>
</div>
</div>
</div>
<style>
.table-responsive {
margin-bottom: 1rem;
}
.card {
border: 1px solid rgba(0,0,0,0.125);
}
.card:hover {
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
.badge-success {
background-color: #28a745;
color: white;
}
.badge-danger {
background-color: #dc3545;
color: white;
}
.badge-warning {
background-color: #ffc107;
color: #212529;
}
.badge-primary {
background-color: #007bff;
color: white;
}
.badge-secondary {
background-color: #6c757d;
color: white;
}
#documentFrame {
width: 100%;
height: 70vh;
}
.is-invalid {
border-color: #dc3545;
}
.invalid-feedback {
color: #dc3545;
font-size: 0.8rem;
margin-top: 0.25rem;
}
.form-switch {
width: 2.8em;
height: 1.5em;
margin-left: 0;
}
.form-switch .form-check-input:checked {
background-color: #28a745;
border-color: #28a745;
}
.form-switch .form-check-input:focus {
box-shadow: 0 0 0 0.25rem rgba(40, 167, 69, 0.25);
}
.status-text {
font-size: 0.85rem;
font-weight: 500;
line-height: 1;
margin-bottom: 0;
color: #212529;
}
.status-text i {
font-size: 0.9rem;
vertical-align: middle;
}
.form-check-input {
width: 2em;
height: 1em;
margin-top: 0.1rem;
cursor: pointer;
}
.status-text .text-success {
color: #28a745;
}
.status-text .text-danger {
color: #dc3545;
}
.badge {
font-size: 0.85rem;
padding: 0.4em 0.75em;
font-weight: 500;
letter-spacing: 0.5px;
}
.table td {
vertical-align: middle;
padding: 0.75rem;
}
.gap-2 {
gap: 0.5rem;
}
.alert-warning {
background-color: #fff3cd;
border-color: #ffeeba;
}
.required-reason:invalid {
border-color: #dc3545;
}
.is-invalid {
border-color: #dc3545 !important;
}
.invalid-feedback {
color: #dc3545;
font-size: 0.8rem;
margin-top: 0.25rem;
display: block;
}
#loadingOverlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.7);
z-index: 9999;
justify-content: center;
align-items: center;
}
</style>
@section('js')
<script>
$(document).ready(function() {
let documentModal = new bootstrap.Modal(document.getElementById('documentModal'));
// Initialize status and reason fields based on current state
$('.status-toggle').each(function() {
const detailId = $(this).data('detail-id');
const isChecked = $(this).is(':checked');
toggleReasonFields(detailId, isChecked);
});
// Document viewer
$(document).on('click', '.view-document', function(e) {
e.preventDefault();
const docUrl = $(this).data('url');
const docTitle = $(this).data('title');
$('#documentModalLabel').text(docTitle);
$('#documentFrame').attr('src', docUrl);
$('#downloadDocument').attr('href', docUrl);
documentModal.show();
});
// Track if alert has been shown
let hasShownAlert = false;
// Handle status toggle
$(document).on('change', '.status-toggle', function() {
const isChecked = $(this).is(':checked');
const detailId = $(this).data('detail-id');
const statusText = $(`#status_text_${detailId}`);
// Get initial status text
const initialStatus = statusText.text().trim();
// Update status text
if (isChecked) {
statusText.html('<span class="badge bg-success text-white">Valid</span>');
} else {
statusText.html('<span class="badge bg-danger text-white">Tidak Valid</span>');
}
// Toggle reason fields
toggleReasonFields(detailId, isChecked);
// Show notification only once when first interacting with any criteria
if (initialStatus === 'Belum Diverifikasi' && !hasShownAlert) {
Swal.fire({
title: 'Petunjuk Validasi',
html: `<div class="text-start">
<p>Untuk memvalidasi dokumen:</p>
<div class="mb-2">
<strong>✓ Centang</strong> - Dokumen valid<br>
<span class="text-muted small">Status akan berubah menjadi Valid</span>
</div>
<div class="mb-2">
<strong>✗ Tidak centang</strong> - Dokumen tidak valid<br>
<span class="text-muted small">Harap pilih alasan penolakan dan bisa mengisi alasan khusus jika diperlukan</span>
</div>
<div class="mt-2 small text-muted">
<strong> Pesan ini hanya muncul sekali </strong>
</div>
</div>`,
icon: 'info',
confirmButtonText: 'Mengerti',
customClass: {
popup: 'text-start'
}
});
hasShownAlert = true;
}
});
// Function to toggle reason fields based on checkbox state
function toggleReasonFields(detailId, isChecked) {
const alasanSelect = $(`#alasan_select_${detailId}`);
const alasanLainnya = $(`#alasan_lainnya_${detailId}`);
if (isChecked) {
alasanSelect.prop('disabled', true).hide();
alasanLainnya.prop('disabled', true).hide();
alasanSelect.val('');
alasanLainnya.val('').hide();
} else {
alasanSelect.prop('disabled', false).show();
if (alasanSelect.val() === 'Lainnya') {
alasanLainnya.prop('disabled', false).show();
}
}
}
// Handle alasan select change
$(document).on('change', '.alasan-select', function() {
const value = $(this).val();
const detailId = $(this).data('detail-id');
const lainnyaContainer = $(`#alasan_lainnya_${detailId}`);
if (value === 'Lainnya') {
lainnyaContainer.show();
} else {
lainnyaContainer.hide().val('');
}
// Update status text if unchecked
if (!$(`#status_${detailId}`).is(':checked')) {
$(`#status_text_${detailId}`).html('<span class="badge bg-danger text-white">Tidak Valid</span>');
}
});
// Form submission
// Form submission
$('#revalidationForm').on('submit', function(e) {
e.preventDefault();
// Set loading text based on role
const isAdmin = {{ auth()->user()->role === 'admin' ? 'true' : 'false' }};
$('#loadingText').text(isAdmin ? 'Memproses revalidasi...' : 'Memproses validasi...');
// Disable button and show loading
const submitButton = $('#submitButton');
const originalHtml = submitButton.html();
submitButton.prop('disabled', true).html('<i class="fas fa-spinner fa-spin mr-1"></i> Memproses...');
$('#loadingOverlay').show();
// Prepare form data manually to ensure all fields are included
let formData = new FormData(this);
// Manually add checkboxes that might be unchecked
$('.status-toggle').each(function() {
const detailId = $(this).data('detail-id');
formData.append(`valid[${detailId}]`, $(this).is(':checked') ? '1' : '0');
});
// Debug: log the form data being sent
console.log('Form data:', Object.fromEntries(formData));
// Validate form
let isValid = true;
$('.status-toggle').each(function() {
const detailId = $(this).data('detail-id');
if (!$(this).is(':checked')) {
const alasanSelect = $(`#alasan_select_${detailId}`);
const alasanLainnya = $(`#alasan_lainnya_${detailId}`);
// Reset validation
alasanSelect.removeClass('is-invalid');
alasanSelect.next('.invalid-feedback').remove();
alasanLainnya.removeClass('is-invalid');
alasanLainnya.next('.invalid-feedback').remove();
// Check if reason is selected
if (!alasanSelect.val()) {
isValid = false;
alasanSelect.addClass('is-invalid')
.after('<div class="invalid-feedback">Harap pilih alasan penolakan</div>');
}
// Check if "Lainnya" is selected and the field is empty
else if (alasanSelect.val() === 'Lainnya' && !alasanLainnya.val().trim()) {
isValid = false;
alasanLainnya.addClass('is-invalid')
.after('<div class="invalid-feedback">Harap isi alasan lainnya</div>');
}
}
});
if (!isValid) {
submitButton.prop('disabled', false).html(originalHtml);
$('#loadingOverlay').hide();
$('html, body').animate({
scrollTop: $('.is-invalid').first().offset().top - 100
}, 500);
return false;
}
// Submit form via AJAX
$.ajax({
url: $(this).attr('action'),
type: $(this).attr('method'),
data: formData,
processData: false,
contentType: false,
success: function(response) {
if (response.success) {
// Show success message before redirect
Swal.fire({
title: 'Berhasil!',
text: isAdmin ? 'Revalidasi berhasil disimpan' : 'Validasi berhasil disimpan',
icon: 'success',
confirmButtonText: 'OK',
willClose: () => {
window.location.href = response.redirect;
}
});
} else {
Swal.fire('Error', response.message || 'Terjadi kesalahan', 'error');
}
},
error: function(xhr) {
let errorMessage = 'Terjadi kesalahan saat menyimpan validasi';
if (xhr.status === 422) {
const errors = xhr.responseJSON.errors;
errorMessage = Object.values(errors).join('\n');
// Highlight invalid fields
$.each(errors, function(field, messages) {
const fieldParts = field.split('.');
if (fieldParts[0] === 'valid' || fieldParts[0] === 'alasan') {
const detailId = fieldParts[1];
if (fieldParts[0] === 'valid') {
$(`#status_${detailId}`).addClass('is-invalid');
} else {
$(`#alasan_select_${detailId}`).addClass('is-invalid')
.after(`<div class="invalid-feedback">${messages.join(', ')}</div>`);
}
}
});
}
Swal.fire('Error', errorMessage, 'error');
},
complete: function() {
$('#loadingOverlay').hide();
submitButton.prop('disabled', false).html(originalHtml);
}
});
});
// Force close loading overlay
$('#forceCloseLoading').on('click', function() {
$('#loadingOverlay').hide();
$('#submitButton').prop('disabled', false).html('<i class="fas fa-save mr-1"></i> Simpan Validasi');
});
// Close modal cleanup
$('#documentModal').on('hidden.bs.modal', function() {
$('#documentFrame').attr('src', '');
});
});
</script>
@endsection
@endsection