822 lines
40 KiB
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 |