on progress
This commit is contained in:
parent
cf427020d9
commit
6fa55f083b
@ -1060,22 +1060,23 @@ class DashboardController extends Controller
|
||||
foreach ($datas as $index => $data) {
|
||||
list($id_unit_kerja, $nama_unit_kerja) = explode('/', $data['id_unit_kerja'],2);
|
||||
list($id_sub_unit_kerja, $nama_sub_unit_kerja) = explode('/', $data['id_sub_unit_kerja'],2);
|
||||
if($data['is_akre'] === "1"){
|
||||
$path = "{$data['akre_type']}/{$data['akre_segment']}/{$data['akre_item']}";
|
||||
if(isset($data['akre'])){
|
||||
$path = $data['akre'];
|
||||
}else{
|
||||
list($master_kategori_directory_id, $nama_kategori) = explode('/', $data['master_kategori_directory_id'],2);
|
||||
$path = "{$nama_unit_kerja}/{$nama_sub_unit_kerja}/{$nama_kategori}";
|
||||
if(isset($data['master_kategori_directory_id'])){
|
||||
list($master_kategori_directory_id, $nama_kategori) = explode('/', $data['master_kategori_directory_id'],2);
|
||||
$path = "{$nama_unit_kerja}/{$nama_sub_unit_kerja}/{$nama_kategori}";
|
||||
}else{
|
||||
$path = "{$nama_unit_kerja}/{$nama_sub_unit_kerja}";
|
||||
}
|
||||
}
|
||||
|
||||
$uploadedFile = request()->file("data.$index.file");
|
||||
if(!$uploadedFile){
|
||||
throw new \RuntimeException('File wajib diunggah pada baris ke-' . ($index+1));
|
||||
throw new \RuntimeException('File wajib diunggah pada segment ke-' . ($index+1));
|
||||
}
|
||||
if (!$uploadedFile->isValid()) {
|
||||
throw new \RuntimeException('Upload file gagal pada baris ke-' . ($index+1));
|
||||
}
|
||||
if ($uploadedFile->getSize() > $maxUploadBytes) {
|
||||
throw new \RuntimeException('Ukuran file maksimal 10MB pada baris ke-' . ($index+1));
|
||||
throw new \RuntimeException('Upload file gagal pada segment ke-' . ($index+1));
|
||||
}
|
||||
$status = $isAtasan ? 'approved' : null;
|
||||
|
||||
@ -1093,7 +1094,8 @@ class DashboardController extends Controller
|
||||
'status_action' => $status,
|
||||
'action_by' => $status && $status === "approved" ? auth()->user()->objectpegawaifk : null,
|
||||
'action_at' => $status && $status === "approved" ? now() : null,
|
||||
'is_akre' => ($data['is_akre'] ?? null) == "1"
|
||||
'is_akre' => isset($data['akre']),
|
||||
'kategori_hukum' => isset($data['kategori_hukum']) ? $data['kategori_hukum'] : null
|
||||
];
|
||||
$fd = FileDirectory::create($payload);
|
||||
|
||||
@ -1112,7 +1114,6 @@ class DashboardController extends Controller
|
||||
$fd->update([
|
||||
'file' => $path . '/' . $imageName
|
||||
]);
|
||||
|
||||
if(!$isAtasan){
|
||||
$uploaderName = auth()->user()?->dataUser?->namalengkap ?? 'Pengguna';
|
||||
$docNumber = $fd->no_dokumen ? 'nomor '. $fd->no_dokumen : $imageName;
|
||||
@ -1146,6 +1147,7 @@ class DashboardController extends Controller
|
||||
'status_action' => $isAtasan ? 'approved' : null
|
||||
], 200);
|
||||
} catch (\Throwable $th) {
|
||||
dd($th);
|
||||
DB::connection('dbDirectory')->rollback();
|
||||
return response()->json([
|
||||
'status' => false,
|
||||
@ -1522,7 +1524,7 @@ class DashboardController extends Controller
|
||||
'pegawai_nama_entry' => $item->pegawai_nama_entry,
|
||||
'part' => $dataSlice[0],
|
||||
'folder' => $dataSlice[2],
|
||||
'fileName' =>$dataSlice[3],
|
||||
'fileName' => isset($dataSlice[3]) ? $dataSlice[3] : null,
|
||||
'file' => $item->file,
|
||||
'nama_dokumen' => $item->nama_dokumen ?? '-',
|
||||
'tgl_expired' => $item->tgl_expired,
|
||||
@ -1530,7 +1532,10 @@ class DashboardController extends Controller
|
||||
'entry_at' => $item->entry_at,
|
||||
'tanggal_terbit' => $item->tanggal_terbit,
|
||||
'permission_file' => $item->permission_file,
|
||||
'status_action' => $item->status_action
|
||||
'status_action' => $item->status_action,
|
||||
'id_unit_kerja' => $item->id_unit_kerja,
|
||||
'id_sub_unit_kerja' => $item->id_sub_unit_kerja,
|
||||
'master_kategori_directory_id' => $item->master_kategori_directory_id
|
||||
];
|
||||
});
|
||||
return response()->json([
|
||||
@ -1903,7 +1908,7 @@ class DashboardController extends Controller
|
||||
'pegawai_nama_entry' => $item->pegawai_nama_entry,
|
||||
'part' => $dataSlice[0],
|
||||
'folder' => $dataSlice[2],
|
||||
'fileName' =>$dataSlice[3],
|
||||
'fileName' => isset($dataSlice[3]) ? $dataSlice[3] : null,
|
||||
'file' => $item->file,
|
||||
'no_dokumen' => $item->no_dokumen,
|
||||
'nama_dokumen' => $item->nama_dokumen,
|
||||
@ -1916,7 +1921,8 @@ class DashboardController extends Controller
|
||||
'id_unit_kerja' => $item->id_unit_kerja,
|
||||
'id_sub_unit_kerja' => $item->id_sub_unit_kerja,
|
||||
'master_kategori_directory_id' => $item->master_kategori_directory_id,
|
||||
'is_akre' => $item->is_akre
|
||||
'is_akre' => $item->is_akre,
|
||||
'kategori_hukum' => $item->kategori_hukum
|
||||
];
|
||||
});
|
||||
return response()->json([
|
||||
@ -2255,8 +2261,12 @@ class DashboardController extends Controller
|
||||
}
|
||||
|
||||
public function dataAkreditasi(){
|
||||
$katDok = MasterKategori::where('statusenabled', true)
|
||||
->select('master_kategori_directory_id', 'nama_kategori_directory')
|
||||
->get();
|
||||
$data = [
|
||||
'title' => 'Akreditasi',
|
||||
'katDok' => $katDok
|
||||
];
|
||||
return view('dataAkreditasi.index', $data);
|
||||
}
|
||||
|
||||
@ -62,8 +62,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
|
||||
function buildRow(item){
|
||||
console.log(item);
|
||||
|
||||
let tanggal = item.entry_at ? formatTanggal(item.entry_at) : '-';
|
||||
let tanggalExp = item.tgl_expired ? formatTanggal(item.tgl_expired) : '-';
|
||||
let tanggalTerbit = item.tanggal_terbit ? formatTanggal(item.tanggal_terbit) : '-';
|
||||
@ -370,6 +368,47 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
}
|
||||
|
||||
function byId(id){
|
||||
return document.getElementById(id);
|
||||
}
|
||||
|
||||
function setInputValue(el, value){
|
||||
if (!el) return;
|
||||
el.value = value ?? '';
|
||||
}
|
||||
|
||||
function setTextValue(el, value){
|
||||
if (!el) return;
|
||||
el.textContent = value || '';
|
||||
}
|
||||
|
||||
function setChecked(el, value){
|
||||
if (!el) return;
|
||||
el.checked = !!value;
|
||||
}
|
||||
|
||||
function setSelectValue(selectEl, value, label){
|
||||
if (!selectEl) return;
|
||||
if (value === undefined || value === null || value === '') {
|
||||
selectEl.value = '';
|
||||
return;
|
||||
}
|
||||
const exists = Array.from(selectEl.options).some(opt => opt.value === value);
|
||||
if (!exists) {
|
||||
selectEl.append(new Option(label || value, value, true, true));
|
||||
}
|
||||
selectEl.value = value;
|
||||
}
|
||||
|
||||
function triggerSelect2(selectEl){
|
||||
if (window.$ && $.fn.select2) $(selectEl).trigger('change');
|
||||
}
|
||||
|
||||
function initSelect2($el, options){
|
||||
if (!$el || !$el.length || !window.$ || !$.fn.select2) return;
|
||||
$el.select2(options);
|
||||
}
|
||||
|
||||
function initEditSelects(){
|
||||
if (editUnitSelect.length) {
|
||||
editUnitSelect.select2({
|
||||
@ -415,6 +454,37 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
}
|
||||
|
||||
let akreData = [];
|
||||
let akreLoaded = false;
|
||||
let akreFlat = [];
|
||||
|
||||
function initEditExtraSelects(){
|
||||
const akreSelect = byId('edit_akre_select');
|
||||
if (akreSelect) {
|
||||
loadAkreData().then(() => {
|
||||
fillAkreSelect(akreSelect);
|
||||
initSelect2($(akreSelect), {
|
||||
dropdownParent: $('#modalEditPengajuanFile'),
|
||||
placeholder: 'Pilih Instrumen',
|
||||
allowClear: true
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const editKat = $('#edit_kategori');
|
||||
const editHukum = $('#edit_kategori_hukum');
|
||||
initSelect2(editKat, {
|
||||
dropdownParent: $('#modalEditPengajuanFile'),
|
||||
placeholder: 'Pilih Kategori',
|
||||
allowClear: true
|
||||
});
|
||||
initSelect2(editHukum, {
|
||||
dropdownParent: $('#modalEditPengajuanFile'),
|
||||
placeholder: 'Pilih Kategori Hukum',
|
||||
allowClear: true
|
||||
});
|
||||
}
|
||||
|
||||
function loadEditSubUnit(unitId, selectedSubId, selectedSubName){
|
||||
editSubUnitSelect.empty().append('<option value="" disabled selected>-- Pilih Sub Unit Kerja --</option>');
|
||||
if (!unitId) return;
|
||||
@ -438,69 +508,71 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
}
|
||||
|
||||
function setEditAkreValue(value){
|
||||
const akreEl = byId('edit_akre_select');
|
||||
if (!akreEl) return;
|
||||
loadAkreData().then(() => {
|
||||
fillAkreSelect(akreEl);
|
||||
setSelectValue(akreEl, value, value);
|
||||
triggerSelect2(akreEl);
|
||||
});
|
||||
}
|
||||
|
||||
function setEditKategoriHukum(value){
|
||||
const hukumEl = byId('edit_kategori_hukum');
|
||||
if (!hukumEl) return;
|
||||
setSelectValue(hukumEl, value, value);
|
||||
triggerSelect2(hukumEl);
|
||||
}
|
||||
|
||||
function setEditKategoriDir(item, kategoriName){
|
||||
const katEl = byId('edit_kategori');
|
||||
if (!katEl || !item.master_kategori_directory_id) return;
|
||||
const katVal = `${item.master_kategori_directory_id}/${kategoriName}`;
|
||||
setSelectValue(katEl, katVal, kategoriName || 'Kategori');
|
||||
triggerSelect2(katEl);
|
||||
}
|
||||
|
||||
window.editFileReject = function(id){
|
||||
const item = getItemById(id);
|
||||
if (!item) {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal', text: 'Data tidak ditemukan.' });
|
||||
return;
|
||||
}
|
||||
const idEl = document.getElementById('edit_file_directory_id');
|
||||
const noEl = document.getElementById('edit_no_dokumen');
|
||||
const namaEl = document.getElementById('edit_nama_dokumen');
|
||||
const tglEl = document.getElementById('edit_tanggal_terbit');
|
||||
const tglExpiredEl = document.getElementById('edit_tgl_expired');
|
||||
const hasExpiredEl = document.getElementById('edit_has_expired');
|
||||
const currentFileEl = document.getElementById('edit_current_file');
|
||||
const permYes = document.getElementById('edit_perm_yes');
|
||||
const permNo = document.getElementById('edit_perm_no');
|
||||
const katEl = document.getElementById('edit_kategori');
|
||||
setInputValue(byId('edit_file_directory_id'), item.file_directory_id);
|
||||
setInputValue(byId('edit_no_dokumen'), item.no_dokumen);
|
||||
setInputValue(byId('edit_nama_dokumen'), item.nama_dokumen);
|
||||
setInputValue(byId('edit_tanggal_terbit'), item.tanggal_terbit);
|
||||
setInputValue(byId('edit_tgl_expired'), item.tgl_expired);
|
||||
|
||||
if (idEl) idEl.value = item.file_directory_id || '';
|
||||
if (noEl) noEl.value = item.no_dokumen || '';
|
||||
if (namaEl) namaEl.value = item.nama_dokumen || '';
|
||||
if (tglEl) tglEl.value = item.tanggal_terbit || '';
|
||||
if (tglExpiredEl) tglExpiredEl.value = item.tgl_expired || '';
|
||||
if (permYes && permNo) {
|
||||
const isPublic = item.permission_file === true || item.permission_file === 1 || item.permission_file === '1';
|
||||
permYes.checked = isPublic;
|
||||
permNo.checked = !isPublic;
|
||||
}
|
||||
if (hasExpiredEl && tglExpiredEl) {
|
||||
const hasExpired = !!item.tgl_expired;
|
||||
hasExpiredEl.checked = hasExpired;
|
||||
syncEditExpiredField();
|
||||
}
|
||||
if (currentFileEl) {
|
||||
const displayName = item.fileName || (item.file ? String(item.file).split('/').pop() : '');
|
||||
currentFileEl.textContent = displayName ? `File saat ini: ${displayName}` : '';
|
||||
}
|
||||
const isPublic = item.permission_file === true || item.permission_file === 1 || item.permission_file === '1';
|
||||
setChecked(byId('edit_perm_yes'), isPublic);
|
||||
setChecked(byId('edit_perm_no'), !isPublic);
|
||||
|
||||
const hasExpired = !!item.tgl_expired;
|
||||
setChecked(byId('edit_has_expired'), hasExpired);
|
||||
syncEditExpiredField();
|
||||
|
||||
const displayName = item.fileName || (item.file ? String(item.file).split('/').pop() : '');
|
||||
setTextValue(byId('edit_current_file'), displayName ? `File saat ini: ${displayName}` : '');
|
||||
|
||||
const parts = (item.file || '').split('/');
|
||||
const unitName = parts[0] || '';
|
||||
const subName = parts[1] || '';
|
||||
const kategoriName = parts[2] || '';
|
||||
const unitName = item.unit_kerja_name || item.nama_unit_kerja || item.unit_name || item.unit_kerja || '';
|
||||
|
||||
if (editUnitSelect.length && item.id_unit_kerja) {
|
||||
const unitVal = `${item.id_unit_kerja}/${unitName}`;
|
||||
editUnitSelect.append(new Option(unitName || 'Unit', unitVal, true, true)).trigger('change');
|
||||
const unitId = String(item.id_unit_kerja);
|
||||
loadEditSubUnit(unitId, item.id_sub_unit_kerja, subName);
|
||||
const unitLabel = unitName || `Unit ${item.id_unit_kerja}`;
|
||||
const unitVal = `${item.id_unit_kerja}/${unitLabel}`;
|
||||
setSelectValue(editUnitSelect[0], unitVal, unitLabel);
|
||||
editUnitSelect.trigger('change');
|
||||
loadEditSubUnit(String(item.id_unit_kerja), item.id_sub_unit_kerja, null);
|
||||
}
|
||||
|
||||
if (katEl && item.master_kategori_directory_id) {
|
||||
const katVal = `${item.master_kategori_directory_id}/${kategoriName}`;
|
||||
if (katEl.querySelector(`option[value="${katVal}"]`)) {
|
||||
katEl.value = katVal;
|
||||
} else {
|
||||
katEl.append(new Option(kategoriName || 'Kategori', katVal, true, true));
|
||||
katEl.value = katVal;
|
||||
}
|
||||
}
|
||||
setEditKategoriDir(item, kategoriName);
|
||||
if (item.kategori_hukum) setEditKategoriHukum(item.kategori_hukum);
|
||||
setEditAkreValue(item.akre || '');
|
||||
|
||||
const modalEl = document.getElementById('modalEditPengajuanFile');
|
||||
if (modalEl) {
|
||||
$("#modalEditPengajuanFile").modal('show');
|
||||
}
|
||||
$("#modalEditPengajuanFile").modal('show');
|
||||
}
|
||||
|
||||
function syncEditExpiredField() {
|
||||
@ -559,6 +631,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
|
||||
initEditSelects();
|
||||
initEditExtraSelects();
|
||||
updateTabUI();
|
||||
fetchData();
|
||||
|
||||
@ -586,10 +659,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
enableAkreFields(0);
|
||||
}
|
||||
|
||||
let akreData = [];
|
||||
let akreLoaded = false;
|
||||
let akreFlat = [];
|
||||
|
||||
function loadAkreData(){
|
||||
if(akreLoaded) return Promise.resolve(akreData);
|
||||
return fetch('/json/akreditasi.json')
|
||||
@ -616,7 +685,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const children = Array.isArray(seg.turunan) ? seg.turunan : [];
|
||||
return children.map(child => ({
|
||||
value: `${type.name}/${seg.name}/${child.name}`,
|
||||
label: `${type.name} / ${seg.name} / ${child.name}`,
|
||||
label: `${type.name} / ${child.name}`,
|
||||
type: type.name,
|
||||
segment: seg.name,
|
||||
item: child.name
|
||||
@ -628,7 +697,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
function fillAkreSelect(selectEl){
|
||||
if(!selectEl) return;
|
||||
selectEl.innerHTML = '<option value="" disabled selected>Pilih Instrumen</option>';
|
||||
selectEl.innerHTML = '<option value="">Pilih Instrumen</option>';
|
||||
getAkreFlat().forEach(optData => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = optData.value;
|
||||
@ -664,17 +733,18 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
function enableAkreFields(index){
|
||||
const selectEl = document.getElementById(`akre_select_${index}`);
|
||||
if(selectEl){
|
||||
selectEl.disabled = false;
|
||||
selectEl.required = true;
|
||||
}
|
||||
// if(selectEl){
|
||||
// selectEl.disabled = false;
|
||||
// selectEl.required = true;
|
||||
// }
|
||||
setKategoriRequired(index, false);
|
||||
loadAkreData().then(() => {
|
||||
fillAkreSelect(selectEl);
|
||||
if(window.$ && $.fn.select2){
|
||||
$(selectEl).select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder: 'Pilih Instrumen'
|
||||
placeholder: 'Pilih Instrumen',
|
||||
allowClear:true
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -687,7 +757,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if(katSelect.length){
|
||||
katSelect.select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder:'Pilih Kategori'
|
||||
placeholder:'Pilih Kategori',
|
||||
allowClear:true
|
||||
});
|
||||
}
|
||||
if(hukumSelect.length){
|
||||
@ -854,13 +925,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Instrumen Akreditasi </label>
|
||||
<select class="form-select akre-select" id="akre_select_${colCount}" style="width: 350px;">
|
||||
<option value="" disabled selected>Pilih Instrumen</option>
|
||||
<select class="form-select akre-select" id="akre_select_${colCount}" name="data[${colCount}][akre]" style="width: 350px;">
|
||||
<option value="">Pilih Instrumen</option>
|
||||
</select>
|
||||
<input type="hidden" name="data[${colCount}][akre_type]" id="akre_type_${colCount}">
|
||||
<input type="hidden" name="data[${colCount}][akre_segment]" id="akre_segment_${colCount}">
|
||||
<input type="hidden" name="data[${colCount}][akre_item]" id="akre_item_${colCount}">
|
||||
<input type="hidden" name="data[${colCount}][is_akre]" value="1">
|
||||
<div class="form-text text-muted">Isi form ini bila dokumen yang diunggah merupakan dokumen <strong>akreditasi</strong>.</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
@ -887,7 +954,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][master_kategori_directory_id]"
|
||||
id="select_kategori_${colCount}" style="width: 350px;">
|
||||
<option value="" disabled selected>Pilih Kategori</option>
|
||||
<option value="">Pilih Kategori</option>
|
||||
${katOptions}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@ -1,4 +1,42 @@
|
||||
@extends('layout.main')
|
||||
<style>
|
||||
/* Baris Folder */
|
||||
.tree-folder {
|
||||
background-color: #fcfcfc;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
.tree-folder:hover {
|
||||
background-color: #f4f7fb;
|
||||
}
|
||||
|
||||
/* Container Indentasi */
|
||||
.indent-container {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Garis Pandu Vertikal */
|
||||
.tree-line {
|
||||
display: inline-block;
|
||||
width: 24px;
|
||||
height: 40px; /* Sesuaikan dengan tinggi row */
|
||||
border-left: 1px solid #e0e0e0;
|
||||
margin-left: 12px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Menghilangkan garis terakhir agar lebih rapi */
|
||||
.tree-file:last-child .tree-line {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
/* Ikon dan Teks */
|
||||
.folder-icon { color: #ffc107; font-size: 1.2rem; }
|
||||
.file-icon { color: #6c757d; font-size: 1.1rem; }
|
||||
|
||||
.badge-pdf { background-color: #fff0f0; color: #e44d26; border: 1px solid #ffcccc; }
|
||||
</style>
|
||||
@section('body_main')
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
@ -7,16 +45,8 @@
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade show active">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<h4 class="mb-0">Dokumen Umum</h4>
|
||||
<h4 class="mb-0">Dokumen Akreditasi</h4>
|
||||
<div class="d-flex align-items-start gap-3">
|
||||
<!-- DOWNLOAD + COUNT -->
|
||||
{{-- <a
|
||||
href="/download-excel/data-umum"
|
||||
class="btn btn-success btn-sm"
|
||||
>
|
||||
<i class="ti ti-download me-1"></i>
|
||||
Download Excel
|
||||
</a> --}}
|
||||
<div class="d-flex flex-column align-items-start">
|
||||
<button
|
||||
type="button"
|
||||
@ -50,7 +80,7 @@
|
||||
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 mb-3">
|
||||
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 flex-grow-1">
|
||||
<input type="search" id="tableSearch" class="form-control"
|
||||
placeholder="Cari nama dokumen atau No Dokumen" autocomplete="off">
|
||||
placeholder="Cari Dokumen / Folder" autocomplete="off">
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
|
||||
@ -60,13 +90,13 @@
|
||||
<table class="table table-sm table-hover align-middle mb-0 table-fixed" id="lastUpdatedTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center" style="width: 36px;">
|
||||
<th class="text-center" style="width: 45px;">
|
||||
<input type="checkbox" id="checkAllRows" class="form-check-input">
|
||||
</th>
|
||||
<th>Aksi</th>
|
||||
<th>Nama Dokumen</th>
|
||||
<th>Tipe Dokumen</th>
|
||||
<th>Tanggal Unggah</th>
|
||||
<th style="width: 80px;">Aksi</th>
|
||||
<th style="width: 40%;">Nama Dokumen / Folder</th>
|
||||
<th>Tipe</th>
|
||||
<th>Tgl Unggah</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tableDataAkreditasi">
|
||||
@ -102,13 +132,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@include('dataUnit.modal.create')
|
||||
|
||||
<script>
|
||||
// === STATE MANAGEMENT ===
|
||||
let currentData = [];
|
||||
let selectedIds = [];
|
||||
let currentPath = "";
|
||||
let expandedFolders = new Set();
|
||||
let searchTimer;
|
||||
|
||||
const btn = document.getElementById('btnDownloadMultiple');
|
||||
// === INITIALIZATION ===
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
fetchData();
|
||||
@ -151,8 +183,8 @@
|
||||
function fetchData(keyword = '', page = 1) {
|
||||
const tbody = document.getElementById('tableDataAkreditasi');
|
||||
const perPage = document.getElementById('tablePageSize').value;
|
||||
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="text-center">Memuat data...</td></tr>';
|
||||
|
||||
tbody.innerHTML = '<tr><td colspan="6" class="text-center">Memuat data...</td></tr>';
|
||||
|
||||
fetch(`/datatable-akreditasi?keyword=${encodeURIComponent(keyword)}&per_page=${perPage}&page=${page}`)
|
||||
.then(res => res.json())
|
||||
@ -162,12 +194,12 @@
|
||||
renderTable(keyword);
|
||||
updateSummary(response.pagination.total);
|
||||
} else {
|
||||
tbody.innerHTML = `<tr><td colspan="5" class="text-center text-danger">${response.message}</td></tr>`;
|
||||
tbody.innerHTML = `<tr><td colspan="6" class="text-center text-danger">${response.message}</td></tr>`;
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Error fetching data:', err);
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="text-center text-danger">Gagal memuat data dari server.</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="6" class="text-center text-danger">Gagal memuat data dari server.</td></tr>';
|
||||
});
|
||||
}
|
||||
|
||||
@ -179,7 +211,7 @@
|
||||
tbody.innerHTML = '';
|
||||
|
||||
if (currentData.length === 0) {
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="text-center">Tidak ada data ditemukan</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="6" class="text-center">Tidak ada data ditemukan</td></tr>';
|
||||
return;
|
||||
}
|
||||
|
||||
@ -189,69 +221,12 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// MODE 2: EXPLORER VIEW (Folder Navigation)
|
||||
|
||||
// Tombol Kembali
|
||||
if (currentPath !== "") {
|
||||
const displayPath = currentPath
|
||||
.replace(/\/$/, "")
|
||||
.replace(/\//g, ' <i class="ti ti-chevron-right mx-1 text-muted"></i> ');
|
||||
|
||||
tbody.innerHTML += `
|
||||
<tr class="table-light">
|
||||
<td></td>
|
||||
<td colspan="4">
|
||||
<div class="d-flex small">
|
||||
|
||||
<!-- Kembali -->
|
||||
<div class="text-primary d-flex align-items-center cursor-pointer"
|
||||
onclick="goBack()">
|
||||
<i class="ti ti-arrow-back-up me-1"></i>
|
||||
<span class="fw-semibold">Kembali</span>
|
||||
</div>
|
||||
|
||||
<!-- Lokasi -->
|
||||
<div class="d-flex align-items-center text-muted">
|
||||
<i class="ti ti-folder-open me-1"></i>
|
||||
<span class="fw-semibold me-1">Lokasi:</span>
|
||||
<span>${displayPath}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
|
||||
const folders = new Set();
|
||||
const filesInCurrentPath = [];
|
||||
|
||||
currentData.forEach(item => {
|
||||
if (item.file && item.file.startsWith(currentPath)) {
|
||||
const relativePath = item.file.substring(currentPath.length);
|
||||
const parts = relativePath.split('/');
|
||||
|
||||
if (parts.length > 1) {
|
||||
folders.add(parts[0]); // Ini Folder
|
||||
} else {
|
||||
filesInCurrentPath.push(item); // Ini File
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Render Folder
|
||||
folders.forEach(folderName => {
|
||||
tbody.innerHTML += `
|
||||
<tr style="cursor:pointer" onclick="openFolder('${folderName}')">
|
||||
<td></td>
|
||||
<td><i class="ti ti-folder text-warning fs-5"></i></td>
|
||||
<td><strong>${folderName}</strong></td>
|
||||
<td colspan="2">Folder</td>
|
||||
</tr>`;
|
||||
});
|
||||
|
||||
// Render File
|
||||
filesInCurrentPath.forEach(item => renderFileRow(tbody, item));
|
||||
// MODE 2: TREE VIEW (All folders & files)
|
||||
const tree = buildTree(currentData);
|
||||
if (expandedFolders.size === 0) {
|
||||
expandAllFolders(tree, '');
|
||||
}
|
||||
renderTree(tbody, tree, '', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -265,12 +240,12 @@
|
||||
targetTbody.innerHTML += `
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<input type="checkbox" class="form-check-input row-checkbox"
|
||||
<input type="checkbox" class="form-check-input row-checkbox"
|
||||
value="${item.file_directory_id}" ${isChecked} onchange="handleRowCheck(this)">
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a href="/file-download/${item.file_directory_id}" target="_blank"
|
||||
<a href="/file-download/${item.file_directory_id}" target="_blank"
|
||||
class="btn btn-sm btn-outline-primary" download title="Download">
|
||||
<i class="ti ti-download"></i>
|
||||
</a>
|
||||
@ -278,7 +253,7 @@
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<strong>${item.nama_dokumen || fileName}</strong>
|
||||
<strong>${item.nama_dokumen}</strong>
|
||||
<small class="text-muted" style="font-size: 10px;">Path: ${item.file}</small>
|
||||
</div>
|
||||
</td>
|
||||
@ -287,18 +262,144 @@
|
||||
</tr>`;
|
||||
}
|
||||
|
||||
// === NAVIGATION FUNCTIONS ===
|
||||
// === TREE FUNCTIONS ===
|
||||
|
||||
function openFolder(name) {
|
||||
currentPath += name + "/";
|
||||
renderTable();
|
||||
function buildTree(items) {
|
||||
const root = { folders: {}, files: [] };
|
||||
(items || []).forEach(item => {
|
||||
const path = (item.file || '').split('/').filter(Boolean);
|
||||
if (path.length === 0) {
|
||||
root.files.push(item);
|
||||
return;
|
||||
}
|
||||
const fileName = path.pop();
|
||||
let node = root;
|
||||
path.forEach(part => {
|
||||
if (!node.folders[part]) {
|
||||
node.folders[part] = { folders: {}, files: [] };
|
||||
}
|
||||
node = node.folders[part];
|
||||
});
|
||||
node.files.push({ ...item, __fileName: fileName });
|
||||
});
|
||||
return root;
|
||||
}
|
||||
|
||||
function goBack() {
|
||||
const parts = currentPath.split('/').filter(p => p !== "");
|
||||
parts.pop();
|
||||
currentPath = parts.length > 0 ? parts.join('/') + "/" : "";
|
||||
renderTable();
|
||||
function expandAllFolders(node, basePath) {
|
||||
Object.keys(node.folders || {}).forEach(folder => {
|
||||
const folderPath = basePath ? `${basePath}/${folder}` : folder;
|
||||
expandedFolders.add(folderPath);
|
||||
expandAllFolders(node.folders[folder], folderPath);
|
||||
});
|
||||
}
|
||||
|
||||
function renderTree(tbody, node, basePath, level) {
|
||||
const folderNames = Object.keys(node.folders || {}).sort();
|
||||
|
||||
folderNames.forEach(folder => {
|
||||
const folderPath = basePath ? `${basePath}/${folder}` : folder;
|
||||
const isExpanded = expandedFolders.has(folderPath);
|
||||
const folderNode = node.folders[folder];
|
||||
|
||||
let lines = '';
|
||||
for (let i = 0; i < level; i++) {
|
||||
lines += '<span class="tree-line"></span>';
|
||||
}
|
||||
|
||||
tbody.innerHTML += `
|
||||
<tr class="tree-folder" onclick="toggleFolder('${folderPath}')">
|
||||
<td></td> <td></td> <td>
|
||||
<div class="indent-container">
|
||||
${lines}
|
||||
<span class="folder-toggle me-1">
|
||||
<i class="ti ${isExpanded ? 'ti-chevron-down' : 'ti-chevron-right'} text-muted" style="font-size: 12px;"></i>
|
||||
</span>
|
||||
<i class="ti ti-folder-filled folder-icon me-2"></i>
|
||||
<strong class="text-dark">${folder}</strong>
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="badge bg-light text-muted border-0">FOLDER</span></td>
|
||||
<td class="text-muted small">-</td> <td class="text-muted small">-</td> </tr>
|
||||
`;
|
||||
|
||||
if (isExpanded) {
|
||||
renderTree(tbody, folderNode, folderPath, level + 1);
|
||||
}
|
||||
});
|
||||
|
||||
// Bagian ini akan memanggil renderTreeFileRow yang menampilkan tanggal
|
||||
(node.files || []).forEach(item => {
|
||||
renderTreeFileRow(tbody, item, level);
|
||||
});
|
||||
}
|
||||
|
||||
function getFolderMaxDate(node) {
|
||||
let dates = [];
|
||||
|
||||
// Ambil tanggal dari file di level ini
|
||||
(node.files || []).forEach(f => {
|
||||
if (f.entry_at) dates.push(new Date(f.entry_at));
|
||||
});
|
||||
|
||||
// Ambil tanggal dari sub-folder (rekursif)
|
||||
Object.values(node.folders || {}).forEach(subNode => {
|
||||
const subDate = getFolderMaxDate(subNode);
|
||||
if (subDate) dates.push(new Date(subDate));
|
||||
});
|
||||
|
||||
if (dates.length === 0) return null;
|
||||
|
||||
// Cari tanggal paling besar (terbaru)
|
||||
const maxDate = new Date(Math.max(...dates));
|
||||
|
||||
// Format balik ke YYYY-MM-DD
|
||||
return maxDate.toISOString().split('T')[0];
|
||||
}
|
||||
|
||||
function renderTreeFileRow(targetTbody, item, level){
|
||||
const fileName = item.__fileName || (item.file ? item.file.split('/').pop() : 'Unknown');
|
||||
const typeDok = fileName.split('.').pop().toUpperCase();
|
||||
const isChecked = selectedIds.includes(String(item.file_directory_id)) ? 'checked' : '';
|
||||
|
||||
let lines = '';
|
||||
for (let i = 0; i < level; i++) {
|
||||
lines += '<span class="tree-line"></span>';
|
||||
}
|
||||
|
||||
targetTbody.innerHTML += `
|
||||
<tr class="tree-file">
|
||||
<td class="text-center">
|
||||
<input type="checkbox" class="form-check-input row-checkbox"
|
||||
value="${item.file_directory_id}" ${isChecked} onchange="handleRowCheck(this)">
|
||||
</td>
|
||||
<td>
|
||||
<a href="/file-download/${item.file_directory_id}" target="_blank"
|
||||
class="btn btn-sm btn-primary text-white border">
|
||||
<i class="ti ti-download"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<div class="indent-container">
|
||||
${lines}
|
||||
<span style="width: 24px;"></span> <i class="ti ti-file-text file-icon me-2"></i>
|
||||
<div class="d-flex flex-column">
|
||||
<span class="text-dark fw-medium">${item.nama_dokumen}</span>
|
||||
<small class="text-muted" style="font-size: 10px;">${fileName}</small>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="badge bg-danger">${typeDok}</span></td>
|
||||
<td class="text-muted small">${formatDateTime(item.entry_at)}</td>
|
||||
</tr>`;
|
||||
}
|
||||
// Tambahkan fungsi ini di dalam <script>
|
||||
function toggleFolder(folderPath) {
|
||||
if (expandedFolders.has(folderPath)) {
|
||||
expandedFolders.delete(folderPath);
|
||||
} else {
|
||||
expandedFolders.add(folderPath);
|
||||
}
|
||||
renderTable(document.getElementById('tableSearch').value || '');
|
||||
}
|
||||
|
||||
// === UTILITY FUNCTIONS ===
|
||||
@ -315,7 +416,7 @@
|
||||
}
|
||||
|
||||
function updateDownloadButton() {
|
||||
const btn = document.getElementById('btnDownloadMultiple');
|
||||
|
||||
const countLabel = document.getElementById('selectedCount');
|
||||
btn.disabled = selectedIds.length === 0;
|
||||
countLabel.innerText = `${selectedIds.length} dipilih`;
|
||||
@ -325,5 +426,487 @@
|
||||
const summary = document.getElementById('tableSummary');
|
||||
if (summary) summary.innerText = `Total: ${total} data`;
|
||||
}
|
||||
|
||||
const downloadBtn = document.getElementById('btnDownloadMultiple');
|
||||
if (downloadBtn) {
|
||||
downloadBtn.addEventListener('click', function(){
|
||||
if(selectedIds.length === 0){
|
||||
return;
|
||||
}
|
||||
const payload = { ids: Array.from(selectedIds) };
|
||||
downloadBtn.disabled = true;
|
||||
downloadBtn.textContent = 'Menyiapkan...';
|
||||
fetch('/download-multiple', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
},
|
||||
body: JSON.stringify(payload)
|
||||
})
|
||||
.then(async (res) => {
|
||||
const contentType = res.headers.get('content-type') || '';
|
||||
if(!res.ok || contentType.includes('application/json')){
|
||||
const err = await res.json().catch(() => ({}));
|
||||
throw new Error(err?.message || 'Gagal download file');
|
||||
}
|
||||
const blob = await res.blob();
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
const disposition = res.headers.get('content-disposition') || '';
|
||||
const match = disposition.match(/filename="?([^"]+)"?/);
|
||||
a.href = url;
|
||||
a.download = match?.[1] || 'files.zip';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
window.URL.revokeObjectURL(url);
|
||||
})
|
||||
.catch(err => {
|
||||
Swal.fire({ icon: 'error', title: 'Gagal', text: err.message || 'Gagal download file' });
|
||||
})
|
||||
.finally(() => {
|
||||
downloadBtn.disabled = selectedIds.length === 0;
|
||||
downloadBtn.textContent = 'Download Terpilih';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('click', function(e){
|
||||
const toggle = e.target.closest('.folder-toggle');
|
||||
if (!toggle) return;
|
||||
const folderPath = toggle.getAttribute('data-folder');
|
||||
if (!folderPath) return;
|
||||
if (expandedFolders.has(folderPath)) {
|
||||
expandedFolders.delete(folderPath);
|
||||
} else {
|
||||
expandedFolders.add(folderPath);
|
||||
}
|
||||
renderTable(document.getElementById('tableSearch').value || '');
|
||||
});
|
||||
|
||||
function formatDateTime(value) {
|
||||
if (!value) return '—';
|
||||
const d = new Date(value);
|
||||
if (isNaN(d)) return value;
|
||||
const pad = n => String(n).padStart(2, '0');
|
||||
return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} `
|
||||
+ `${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
||||
}
|
||||
const katDok = @json($katDok);
|
||||
const formCreate = document.getElementById('formFile');
|
||||
const modalCreate = document.getElementById('modalCreateFile');
|
||||
let colCount = 1;
|
||||
|
||||
document.addEventListener('change', function(e){
|
||||
if(!e.target.classList.contains('toggle-expired')) return;
|
||||
const targetId = e.target.getAttribute('data-target');
|
||||
if(!targetId) return;
|
||||
const fieldWrap = document.getElementById(targetId);
|
||||
const input = fieldWrap?.querySelector('input');
|
||||
if (input) input.disabled = !e.target.checked;
|
||||
});
|
||||
|
||||
let akreData = [];
|
||||
let akreLoaded = false;
|
||||
let akreFlat = [];
|
||||
|
||||
function loadAkreData(){
|
||||
if(akreLoaded) return Promise.resolve(akreData);
|
||||
return fetch('/json/akreditasi.json')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
akreData = Array.isArray(data) ? data : [];
|
||||
akreFlat = [];
|
||||
akreLoaded = true;
|
||||
return akreData;
|
||||
})
|
||||
.catch(() => {
|
||||
akreData = [];
|
||||
akreFlat = [];
|
||||
akreLoaded = true;
|
||||
return akreData;
|
||||
});
|
||||
}
|
||||
|
||||
function getAkreFlat(){
|
||||
if(akreFlat.length) return akreFlat;
|
||||
akreFlat = (akreData || []).flatMap(type => {
|
||||
const segments = Array.isArray(type.segment) ? type.segment : [];
|
||||
return segments.flatMap(seg => {
|
||||
const children = Array.isArray(seg.turunan) ? seg.turunan : [];
|
||||
return children.map(child => ({
|
||||
value: `${type.name}/${seg.name}/${child.name}`,
|
||||
label: `${type.name} / ${child.name}`,
|
||||
type: type.name,
|
||||
segment: seg.name,
|
||||
item: child.name
|
||||
}));
|
||||
});
|
||||
});
|
||||
return akreFlat;
|
||||
}
|
||||
|
||||
function fillAkreSelect(selectEl){
|
||||
if(!selectEl) return;
|
||||
selectEl.innerHTML = '<option value="">Pilih Instrumen</option>';
|
||||
getAkreFlat().forEach(optData => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = optData.value;
|
||||
opt.textContent = optData.label;
|
||||
selectEl.appendChild(opt);
|
||||
});
|
||||
}
|
||||
|
||||
function setKategoriRequired(index, isRequired){
|
||||
const katSelect = document.getElementById(`select_kategori_${index}`);
|
||||
if (!katSelect) return;
|
||||
if (isRequired) {
|
||||
katSelect.setAttribute('required', 'required');
|
||||
} else {
|
||||
katSelect.removeAttribute('required');
|
||||
}
|
||||
}
|
||||
|
||||
function resetAkreFields(index){
|
||||
const selectEl = document.getElementById(`akre_select_${index}`);
|
||||
const typeInput = document.getElementById(`akre_type_${index}`);
|
||||
const segmentInput = document.getElementById(`akre_segment_${index}`);
|
||||
const itemInput = document.getElementById(`akre_item_${index}`);
|
||||
if(selectEl){
|
||||
selectEl.value = '';
|
||||
if(window.$ && $.fn.select2) $(selectEl).val(null).trigger('change');
|
||||
}
|
||||
if(typeInput) typeInput.value = '';
|
||||
if(segmentInput) segmentInput.value = '';
|
||||
if(itemInput) itemInput.value = '';
|
||||
setKategoriRequired(index, false);
|
||||
}
|
||||
|
||||
function enableAkreFields(index){
|
||||
const selectEl = document.getElementById(`akre_select_${index}`);
|
||||
setKategoriRequired(index, false);
|
||||
loadAkreData().then(() => {
|
||||
fillAkreSelect(selectEl);
|
||||
if(window.$ && $.fn.select2){
|
||||
$(selectEl).select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder: 'Pilih Instrumen',
|
||||
allowClear: true
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initKategoriSelect2(index){
|
||||
if(!window.$ || !$.fn.select2) return;
|
||||
const katSelect = $(`#select_kategori_${index}`);
|
||||
const hukumSelect = $(`#select_kategori_hukum_${index}`);
|
||||
if(katSelect.length){
|
||||
katSelect.select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder:'Pilih Kategori',
|
||||
allowClear: true
|
||||
});
|
||||
}
|
||||
if(hukumSelect.length){
|
||||
hukumSelect.select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder:'Pilih Kategori Hukum',
|
||||
allowClear:true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function selectOptionUnitKerjaV1(localCol){
|
||||
const selectUnit = $(`#select_id_unit_kerja_${localCol}`);
|
||||
const selectSubUnit = $(`#select_id_sub_unit_kerja_${localCol}`);
|
||||
|
||||
selectUnit.select2({
|
||||
placeholder: '-- Pilih Unit Kerja --',
|
||||
allowClear:true,
|
||||
width: '100%',
|
||||
dropdownParent: selectUnit.parent(),
|
||||
ajax:{
|
||||
url : '/select-unit-kerja-mapping',
|
||||
dataType: 'json',
|
||||
delay: 250,
|
||||
data: function(params){
|
||||
return { q: params.term }
|
||||
},
|
||||
processResults: function(data){
|
||||
return {
|
||||
results : (data?.data || []).map(item => ({
|
||||
id: item.id+'/'+item.name,
|
||||
text: item.name,
|
||||
sub_units: item.sub_unit_kerja
|
||||
}))
|
||||
}
|
||||
},
|
||||
cache: true,
|
||||
},
|
||||
minimumInputLength: 0,
|
||||
});
|
||||
|
||||
selectSubUnit.select2({
|
||||
placeholder: '-- Pilih Sub Unit Kerja --',
|
||||
allowClear: true,
|
||||
width: '100%',
|
||||
dropdownParent: selectSubUnit.parent()
|
||||
});
|
||||
|
||||
selectUnit.on('select2:select', function (e) {
|
||||
const data = e.params.data;
|
||||
selectSubUnit.empty().append('<option value="" disabled selected>-- Pilih Sub Unit Kerja --</option>');
|
||||
if (data.sub_units && data.sub_units.length > 0) {
|
||||
data.sub_units.forEach(sub => {
|
||||
selectSubUnit.append(`<option value="${sub.id}/${sub.name}">${sub.name}</option>`);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.addFormV2 = function(){
|
||||
const col = document.getElementById('col_add_fileV2');
|
||||
if (!col) return;
|
||||
const katOptions = (Array.isArray(katDok) ? katDok : [])
|
||||
.map(k => `<option value="${k.master_kategori_directory_id}/${k.nama_kategori_directory}">${k.nama_kategori_directory}</option>`)
|
||||
.join('');
|
||||
|
||||
let html = `
|
||||
<div class="row g-3 align-items-start" id="col-${colCount}">
|
||||
<hr class="my-3" />
|
||||
<div class="col-12 d-flex justify-content-end">
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-danger"
|
||||
onclick="removeCol(${colCount})">
|
||||
<i class="fa-solid fa-trash"></i> Hapus
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][id_unit_kerja]"
|
||||
id="select_id_unit_kerja_${colCount}"
|
||||
required>
|
||||
<option value="" disabled selected>Pilih Unit</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Sub Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][id_sub_unit_kerja]"
|
||||
id="select_id_sub_unit_kerja_${colCount}"
|
||||
required>
|
||||
<option value="" disabled selected>Pilih Sub Unit</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Nomor Dokumen</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">#</span>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="data[${colCount}][no_dokumen]"
|
||||
placeholder="Contoh: 001/RS/IT/I/2026">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Nama Dokumen<span class="text-danger">*</span></label>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="data[${colCount}][nama_dokumen]"
|
||||
placeholder="Contoh: Panduan Mencuci Tangan" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Tanggal Terbit</label>
|
||||
<input class="form-control"
|
||||
type="date"
|
||||
name="data[${colCount}][date_active]">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input toggle-expired"
|
||||
type="checkbox"
|
||||
id="hasExpired_${colCount}"
|
||||
data-target="expiredField_${colCount}">
|
||||
<label class="form-check-label" for="hasExpired_${colCount}">Masa Berlaku Dokumen?</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-5" id="expiredField_${colCount}">
|
||||
<label class="form-label fw-semibold">Tanggal Kedaluwarsa Dokumen</label>
|
||||
<input class="form-control"
|
||||
type="date"
|
||||
name="data[${colCount}][tgl_expired]" disabled>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Boleh dilihat unit lain? <span class="text-danger">*</span></label>
|
||||
<div class="border rounded-3 p-2 bg-light">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input"
|
||||
type="radio"
|
||||
name="data[${colCount}][is_permission]"
|
||||
id="perm_yes_${colCount}"
|
||||
value="1"
|
||||
required>
|
||||
<label class="form-check-label" for="perm_yes_${colCount}">Iya</label>
|
||||
</div>
|
||||
<div class="form-check mt-1">
|
||||
<input class="form-check-input"
|
||||
type="radio"
|
||||
name="data[${colCount}][is_permission]"
|
||||
id="perm_no_${colCount}"
|
||||
value="2"
|
||||
required>
|
||||
<label class="form-check-label" for="perm_no_${colCount}">Tidak</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Instrumen Akreditasi </label>
|
||||
<select class="form-select akre-select" id="akre_select_${colCount}" name="data[${colCount}][akre]" style="width: 350px;">
|
||||
<option value="">Pilih Instrumen</option>
|
||||
</select>
|
||||
<div class="form-text text-muted">Isi form ini bila dokumen yang diunggah merupakan dokumen <strong>akreditasi</strong>.</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Hukum</label>
|
||||
<select class="form-select select-kat-hukum" name="data[${colCount}][kategori_hukum]" id="select_kategori_hukum_${colCount}" style="width: 350px;">
|
||||
<option value="">Pilih Kategori Hukum</option>
|
||||
<option value="Pedir - Kebijakan">Kebijakan - Peraturan Direktur</option>
|
||||
<option value="Keputusan Dirut - Kebijakan">Kebijakan - Keputusan Direktur Utama</option>
|
||||
<option value="Surat Edaran - Kebijakan">Kebijakan - Surat Edaran</option>
|
||||
<option value="Pengumuman - Kebijakan">Pengumuman - Kebijakan</option>
|
||||
<option value="Pelayanan Kesehatan - Kerjasama">Pelayanan Kesehatan - Kerjasama</option>
|
||||
<option value="Management - Kerjasama">Management - Kerjasama</option>
|
||||
<option value="Pemeliharan - Kerjasama">Pemeliharan - Kerjasama</option>
|
||||
<option value="iklat - Kerjasama">Diklat - Kerjasama</option>
|
||||
<option value="Luar Negeri - Kerjasama">Luar Negeri - Kerjasama</option>
|
||||
<option value="Area Bisnis - Kerjasama">Area Bisnis - Kerjasama</option>
|
||||
<option value="Pendidikan - Kerjasama">Pendidikan - Kerjasama</option>
|
||||
<option value="Pengampuan KIA">Pengampuan KIA</option>
|
||||
</select>
|
||||
<div class="form-text text-muted">Isi form ini bila dokumen yang diunggah merupakan dokumen <strong>akreditasi</strong>.</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Lainnya</label>
|
||||
<select class="form-select"
|
||||
name="data[${colCount}][master_kategori_directory_id]"
|
||||
id="select_kategori_${colCount}" style="width: 350px;">
|
||||
<option value="">Pilih Kategori</option>
|
||||
${katOptions}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<label for="fileUpload_${colCount}" class="form-label fw-semibold">📂 Upload Dokumen (PDF)</label>
|
||||
<div class="border rounded-3 p-3 bg-white shadow-sm">
|
||||
<input class="form-control"
|
||||
type="file"
|
||||
id="fileUpload_${colCount}"
|
||||
accept=".pdf"
|
||||
name="data[${colCount}][file]">
|
||||
<div class="mt-2 text-success fw-semibold d-none file-name" id="fileName_${colCount}"></div>
|
||||
</div>
|
||||
<div class="form-text text-muted">Format yang didukung: <b>PDF</b>.</div>
|
||||
</div>
|
||||
</div>`;
|
||||
col.insertAdjacentHTML('beforeend', html);
|
||||
selectOptionUnitKerjaV1(colCount);
|
||||
initKategoriSelect2(colCount);
|
||||
enableAkreFields(colCount);
|
||||
setKategoriRequired(colCount, false);
|
||||
colCount++;
|
||||
}
|
||||
|
||||
window.removeCol = function(count){
|
||||
const el = document.getElementById(`col-${count}`);
|
||||
if (el) el.remove();
|
||||
}
|
||||
|
||||
function resetCreateForm(){
|
||||
colCount = 1;
|
||||
const colAdd = document.getElementById('col_add_fileV2');
|
||||
if (colAdd) colAdd.innerHTML = '';
|
||||
if (formCreate) {
|
||||
formCreate.reset();
|
||||
$(formCreate).find('select').val(null).trigger('change');
|
||||
$(formCreate).find('input[type="file"]').val('');
|
||||
$(formCreate).find('.file-name').addClass('d-none').text('');
|
||||
}
|
||||
resetAkreFields(0);
|
||||
enableAkreFields(0);
|
||||
}
|
||||
|
||||
if (formCreate) {
|
||||
const select0 = $('#select_id_unit_kerja_0');
|
||||
if (select0.length) selectOptionUnitKerjaV1(0);
|
||||
initKategoriSelect2(0);
|
||||
enableAkreFields(0);
|
||||
|
||||
formCreate.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
const submitBtn = formCreate.querySelector('button[type="submit"]');
|
||||
if (submitBtn) submitBtn.disabled = true;
|
||||
if (submitBtn) submitBtn.textContent = 'menyimpan...';
|
||||
const formData = new FormData(formCreate);
|
||||
|
||||
fetch(`/uploadv2`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('input[name="_token"]')?.value || ''
|
||||
},
|
||||
body: formData
|
||||
}).then(async(res) => {
|
||||
const responseData = await res.json();
|
||||
if(responseData.status){
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Berhasil',
|
||||
text: responseData.message || 'Data berhasil disimpan.',
|
||||
timer: 1500,
|
||||
showConfirmButton: false
|
||||
});
|
||||
const modalInstance = bootstrap.Modal.getInstance(modalCreate);
|
||||
modalInstance?.hide();
|
||||
resetCreateForm();
|
||||
fetchData();
|
||||
} else {
|
||||
throw new Error(responseData.message || 'Terjadi kesalahan saat menyimpan data.');
|
||||
}
|
||||
}).catch(err => {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Gagal',
|
||||
text: err.message || 'Terjadi kesalahan.'
|
||||
});
|
||||
}).finally(() => {
|
||||
if (submitBtn) submitBtn.disabled = false;
|
||||
if (submitBtn) submitBtn.textContent = 'Simpan';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('change', function(e){
|
||||
if(e.target.classList.contains('akre-select')){
|
||||
const id = e.target.id || '';
|
||||
const idx = id.split('_').pop();
|
||||
const [typeVal = '', segmentVal = '', itemVal = ''] = (e.target.value || '').split('/');
|
||||
const typeInput = document.getElementById(`akre_type_${idx}`);
|
||||
const segmentInput = document.getElementById(`akre_segment_${idx}`);
|
||||
const itemInput = document.getElementById(`akre_item_${idx}`);
|
||||
if(typeInput) typeInput.value = typeVal;
|
||||
if(segmentInput) segmentInput.value = segmentVal;
|
||||
if(itemInput) itemInput.value = itemVal;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
@endsection
|
||||
|
||||
@ -35,6 +35,13 @@
|
||||
border: 1px solid #dee2e6 !important;
|
||||
color: #111 !important;
|
||||
}
|
||||
|
||||
.table-header-filter .dropdown-menu {
|
||||
z-index: 1080;
|
||||
}
|
||||
.table-fixed-height {
|
||||
min-height: 70vh;
|
||||
}
|
||||
</style>
|
||||
|
||||
@section('body_main')
|
||||
@ -88,12 +95,11 @@
|
||||
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 mb-3">
|
||||
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 flex-grow-1">
|
||||
<select id="tableUnit" class="form-select form-select-sm unit_kerja_filter" style="max-width: 260px;" multiple></select>
|
||||
<select id="tableKategori" class="form-select form-select-sm kategori_kerja_filter" style="max-width: 260px;" multiple>
|
||||
@foreach ($katDok as $kat)
|
||||
<option value="{{ $kat->master_kategori_directory_id }}">
|
||||
{{ $kat->nama_kategori_directory }}
|
||||
</option>
|
||||
@endforeach
|
||||
<select id="tableKategori" class="form-select form-select-sm kategori_kerja_filter" style="max-width: 260px;">
|
||||
<option value="">Kategori (Semua)</option>
|
||||
<option value="akreditasi">Kategori Akreditasi</option>
|
||||
<option value="hukum">Kategori Hukum</option>
|
||||
<option value="lainnya">Kategori Lainnya</option>
|
||||
</select>
|
||||
<input type="search"
|
||||
id="tableSearch"
|
||||
@ -106,7 +112,7 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive" style="max-height: 70vh; overflow-y:auto;">
|
||||
<div class="table-responsive table-fixed-height" style="max-height: 70vh; overflow-y:auto;">
|
||||
<table class="table table-sm table-hover align-middle mb-0 table-fixed" id="lastUpdatedTable">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -116,7 +122,21 @@
|
||||
<th>Aksi</th>
|
||||
<th>No Dokumen</th>
|
||||
<th>Nama Dokumen</th>
|
||||
<th>Kategori</th>
|
||||
<th>
|
||||
<div class="d-flex align-items-center gap-2 table-header-filter">
|
||||
<span>Kategori</span>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-light btn-sm border" type="button" id="tableKategoriHeaderBtn" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="ti ti-filter"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu p-2" id="tableKategoriHeaderMenu" style="min-width: 220px;">
|
||||
<div class="small text-muted px-1">Filter kategori</div>
|
||||
<div class="dropdown-divider"></div>
|
||||
<div class="kategori-header-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
<th>Unit</th>
|
||||
<th>Tanggal Unggah</th>
|
||||
</tr>
|
||||
@ -162,13 +182,19 @@
|
||||
const authPegawai = @json(auth()->user()->objectpegawaifk);
|
||||
const formCreate = $("#formFile")
|
||||
const modalCreate = document.getElementById('modalCreateFile')
|
||||
const tableState = { data: [], page: 1, pageSize: 8, search: '', unit: [], kategori: [], lastPage: 1, total: 0 };
|
||||
const tableState = { data: [], page: 1, pageSize: 8, search: '', unit: [], kategori: [], kategoriType: [], lastPage: 1, total: 0 };
|
||||
const tbody = document.getElementById('tableDataUmum');
|
||||
const paginationEl = document.getElementById('paginationControls');
|
||||
const summaryEl = document.getElementById('tableSummary');
|
||||
const pageSizeSelect = document.getElementById('tablePageSize');
|
||||
const unitSelect = document.getElementById('tableUnit');
|
||||
const kategoriSelect = document.getElementById('tableKategori');
|
||||
const kategoriHeaderMenu = document.getElementById('tableKategoriHeaderMenu');
|
||||
const kategoriTypeOptions = [
|
||||
{ id: 'akreditasi', label: 'Kategori Akreditasi' },
|
||||
{ id: 'hukum', label: 'Kategori Hukum' },
|
||||
{ id: 'lainnya', label: 'Kategori Lainnya' }
|
||||
];
|
||||
const searchInput = document.getElementById('tableSearch');
|
||||
const searchBtn = document.getElementById('btnTableSearch');
|
||||
const downloadBtn = document.getElementById('btnDownloadMultiple');
|
||||
@ -234,16 +260,32 @@
|
||||
}
|
||||
if (kategoriSelect) {
|
||||
$('#tableKategori').select2({
|
||||
placeholder: 'Pilih Kategori',
|
||||
placeholder: 'Kategori (Semua)',
|
||||
allowClear: true,
|
||||
width: '100%',
|
||||
closeOnSelect: false
|
||||
width: '100%'
|
||||
});
|
||||
$('#tableKategori').on('change', function () {
|
||||
tableState.kategori = $(this).val() || [];
|
||||
const val = $(this).val() || '';
|
||||
tableState.kategoriType = val ? [val] : [];
|
||||
tableState.page = 1;
|
||||
renderTable();
|
||||
});
|
||||
}
|
||||
}
|
||||
if (kategoriHeaderMenu) {
|
||||
kategoriHeaderMenu.addEventListener('change', function(e){
|
||||
const checkbox = e.target.closest('input[type="checkbox"]');
|
||||
if (!checkbox) return;
|
||||
const selected = Array.from(kategoriHeaderMenu.querySelectorAll('input[type="checkbox"]:checked'))
|
||||
.map(el => el.value);
|
||||
tableState.kategoriType = selected;
|
||||
if (kategoriSelect && window.$ && $.fn.select2) {
|
||||
const single = selected.length === 1 ? selected[0] : '';
|
||||
$('#tableKategori').val(single).trigger('change');
|
||||
}
|
||||
renderTable();
|
||||
});
|
||||
}
|
||||
|
||||
function resetCreateForm(){
|
||||
colCount = 1;
|
||||
@ -420,7 +462,7 @@
|
||||
}
|
||||
|
||||
function renderTable(){
|
||||
const pageData = tableState.data || [];
|
||||
const pageData = filterByKategoriType(tableState.data || []);
|
||||
|
||||
if(pageData.length === 0){
|
||||
tbody.innerHTML = `
|
||||
@ -449,11 +491,48 @@
|
||||
const value = searchInput ? searchInput.value : '';
|
||||
tableState.search = (value || '').trim();
|
||||
tableState.unit = unitSelect && window.$ ? ($('#tableUnit').val() || []) : (tableState.unit || []);
|
||||
tableState.kategori = kategoriSelect && window.$ ? ($('#tableKategori').val() || []) : (tableState.kategori || []);
|
||||
const katVal = kategoriSelect && window.$ ? ($('#tableKategori').val() || '') : (kategoriSelect?.value || '');
|
||||
tableState.kategoriType = katVal ? [katVal] : (tableState.kategoriType || []);
|
||||
tableState.page = 1;
|
||||
fetchData();
|
||||
}
|
||||
|
||||
function filterByKategoriType(items){
|
||||
const types = tableState.kategoriType || [];
|
||||
if (!types.length) return items;
|
||||
return items.filter(item => {
|
||||
return types.some(type => {
|
||||
if (type === 'akreditasi') {
|
||||
return item.is_akre === true || item.is_akre === 1 || item.is_akre === '1';
|
||||
}
|
||||
if (type === 'hukum') {
|
||||
return !!item.kategori_hukum;
|
||||
}
|
||||
if (type === 'lainnya') {
|
||||
return !!item.master_kategori_directory_id;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function renderKategoriHeaderOptions(){
|
||||
if (!kategoriHeaderMenu) return;
|
||||
const list = kategoriHeaderMenu.querySelector('.kategori-header-list');
|
||||
if (!list) return;
|
||||
const selected = (tableState.kategoriType || []).map(v => String(v));
|
||||
list.innerHTML = kategoriTypeOptions.map(opt => {
|
||||
const checked = selected.includes(opt.id) ? 'checked' : '';
|
||||
return `
|
||||
<label class="dropdown-item d-flex align-items-center gap-2">
|
||||
<input type="checkbox" class="form-check-input m-0" value="${opt.id}" ${checked}>
|
||||
<span>${opt.label}</span>
|
||||
</label>
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
|
||||
function fetchData(){
|
||||
if(summaryEl) summaryEl.textContent = 'Memuat data...';
|
||||
const params = new URLSearchParams({
|
||||
@ -464,9 +543,6 @@
|
||||
if (tableState.unit && tableState.unit.length > 0) {
|
||||
tableState.unit.forEach(id => params.append('unit[]', id));
|
||||
}
|
||||
if (tableState.kategori && tableState.kategori.length > 0) {
|
||||
tableState.kategori.forEach(kat => params.append('kategori[]', kat));
|
||||
}
|
||||
fetch(`/datatable-umum?${params.toString()}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
@ -502,6 +578,7 @@
|
||||
year: 'numeric'
|
||||
});
|
||||
}
|
||||
renderKategoriHeaderOptions();
|
||||
fetchData()
|
||||
|
||||
function updateSelectedCount(){
|
||||
|
||||
@ -34,6 +34,13 @@
|
||||
border: 1px solid #dee2e6 !important;
|
||||
color: #111 !important;
|
||||
}
|
||||
|
||||
.table-header-filter .dropdown-menu {
|
||||
z-index: 1080;
|
||||
}
|
||||
.table-fixed-height {
|
||||
min-height: 70vh;
|
||||
}
|
||||
</style>
|
||||
@section('body_main')
|
||||
<div class="row">
|
||||
@ -85,12 +92,11 @@
|
||||
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 mb-3">
|
||||
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 flex-grow-1">
|
||||
<select id="tableUnit" class="form-select form-select-sm unit_kerja_filter" style="max-width: 260px;"></select>
|
||||
<select id="tableKategori" class="form-select form-select-sm kategori_kerja_filter" style="max-width: 260px;" multiple>
|
||||
@foreach ($katDok as $kat)
|
||||
<option value="{{ $kat->master_kategori_directory_id }}">
|
||||
{{ $kat->nama_kategori_directory }}
|
||||
</option>
|
||||
@endforeach
|
||||
<select id="tableKategori" class="form-select form-select-sm kategori_kerja_filter" style="max-width: 260px;">
|
||||
<option value="">Kategori (Semua)</option>
|
||||
<option value="akreditasi">Kategori Akreditasi</option>
|
||||
<option value="hukum">Kategori Hukum</option>
|
||||
<option value="lainnya">Kategori Lainnya</option>
|
||||
</select>
|
||||
<input type="search"
|
||||
id="tableSearch"
|
||||
@ -100,7 +106,7 @@
|
||||
</div>
|
||||
<button class="btn btn-primary" type="button" id="btnTableSearch">Cari</button>
|
||||
</div>
|
||||
<div class="table-responsive" style="max-height: 70vh; overflow-y:auto;">
|
||||
<div class="table-responsive table-fixed-height" style="max-height: 70vh; overflow-y:auto;">
|
||||
<table class="table table-sm table-hover align-middle mb-0 table-fixed" id="lastUpdatedTable">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -110,7 +116,21 @@
|
||||
<th>Aksi</th>
|
||||
<th>No Dokumen</th>
|
||||
<th>Nama Dokumen</th>
|
||||
<th>Kategori</th>
|
||||
<th>
|
||||
<div class="d-flex align-items-center gap-2 table-header-filter">
|
||||
<span>Kategori</span>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-light btn-sm border" type="button" id="tableKategoriHeaderBtn" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="ti ti-filter"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu p-2" id="tableKategoriHeaderMenu" style="min-width: 220px;">
|
||||
<div class="small text-muted px-1">Filter kategori</div>
|
||||
<div class="dropdown-divider"></div>
|
||||
<div class="kategori-header-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
<th>Unit</th>
|
||||
<th>Tanggal Unggah</th>
|
||||
<th>Pengunggah</th>
|
||||
@ -163,13 +183,19 @@
|
||||
const authPegawai = @json(auth()->user()->objectpegawaifk);
|
||||
const formCreate = $("#formFile");
|
||||
const modalCreate = document.getElementById('modalCreateFile');
|
||||
const tableState = { data: [], page: 1, pageSize: 8, search: '', unit: [], kategori: [], lastPage: 1, total: 0 };
|
||||
const tableState = { data: [], page: 1, pageSize: 8, search: '', unit: [], kategori: [], kategoriType: [], lastPage: 1, total: 0 };
|
||||
const tbody = document.getElementById('tableDataUnit');
|
||||
const paginationEl = document.getElementById('paginationControls');
|
||||
const summaryEl = document.getElementById('tableSummary');
|
||||
const pageSizeSelect = document.getElementById('tablePageSize');
|
||||
const unitSelect = document.getElementById('tableUnit');
|
||||
const kategoriSelect = document.getElementById('tableKategori');
|
||||
const kategoriHeaderMenu = document.getElementById('tableKategoriHeaderMenu');
|
||||
const kategoriTypeOptions = [
|
||||
{ id: 'akreditasi', label: 'Kategori Akreditasi' },
|
||||
{ id: 'hukum', label: 'Kategori Hukum' },
|
||||
{ id: 'lainnya', label: 'Kategori Lainnya' }
|
||||
];
|
||||
const searchInput = document.getElementById('tableSearch');
|
||||
const searchBtn = document.getElementById('btnTableSearch');
|
||||
const downloadBtn = document.getElementById('btnDownloadMultiple');
|
||||
@ -231,18 +257,34 @@
|
||||
}
|
||||
if (kategoriSelect) {
|
||||
$('#tableKategori').select2({
|
||||
placeholder: 'Pilih Kategori',
|
||||
placeholder: 'Kategori (Semua)',
|
||||
allowClear: true,
|
||||
width: '100%',
|
||||
closeOnSelect: false,
|
||||
selectionCssClass: 'select2-filter-selection',
|
||||
dropdownCssClass: 'select2-filter-dropdown'
|
||||
});
|
||||
$('#tableKategori').on('change', function () {
|
||||
tableState.kategori = $(this).val() || [];
|
||||
const val = $(this).val() || '';
|
||||
tableState.kategoriType = val ? [val] : [];
|
||||
tableState.page = 1;
|
||||
renderTable();
|
||||
});
|
||||
}
|
||||
}
|
||||
if (kategoriHeaderMenu) {
|
||||
kategoriHeaderMenu.addEventListener('change', function(e){
|
||||
const checkbox = e.target.closest('input[type="checkbox"]');
|
||||
if (!checkbox) return;
|
||||
const selected = Array.from(kategoriHeaderMenu.querySelectorAll('input[type="checkbox"]:checked'))
|
||||
.map(el => el.value);
|
||||
tableState.kategoriType = selected;
|
||||
if (kategoriSelect && window.$ && $.fn.select2) {
|
||||
const single = selected.length === 1 ? selected[0] : '';
|
||||
$('#tableKategori').val(single).trigger('change');
|
||||
}
|
||||
renderTable();
|
||||
});
|
||||
}
|
||||
|
||||
function resetCreateForm(){
|
||||
colCount = 1;
|
||||
@ -285,7 +327,7 @@
|
||||
const children = Array.isArray(seg.turunan) ? seg.turunan : [];
|
||||
return children.map(child => ({
|
||||
value: `${type.name}/${seg.name}/${child.name}`,
|
||||
label: `${type.name} / ${seg.name} / ${child.name}`,
|
||||
label: `${type.name} / ${child.name}`,
|
||||
type: type.name,
|
||||
segment: seg.name,
|
||||
item: child.name
|
||||
@ -333,17 +375,18 @@
|
||||
|
||||
function enableAkreFields(index){
|
||||
const selectEl = document.getElementById(`akre_select_${index}`);
|
||||
if(selectEl){
|
||||
selectEl.disabled = false;
|
||||
selectEl.required = true;
|
||||
}
|
||||
// if(selectEl){
|
||||
// selectEl.disabled = false;
|
||||
// selectEl.required = true;
|
||||
// }
|
||||
setKategoriRequired(index, false);
|
||||
loadAkreData().then(() => {
|
||||
fillAkreSelect(selectEl);
|
||||
if(window.$ && $.fn.select2){
|
||||
$(selectEl).select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder: 'Pilih Instrumen'
|
||||
placeholder: 'Pilih Instrumen',
|
||||
allowClear: true
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -356,7 +399,8 @@
|
||||
if(katSelect.length){
|
||||
katSelect.select2({
|
||||
dropdownParent: $('#modalCreateFile'),
|
||||
placeholder:'Pilih Kategori'
|
||||
placeholder:'Pilih Kategori',
|
||||
allowClear: true
|
||||
});
|
||||
}
|
||||
if(hukumSelect.length){
|
||||
@ -536,7 +580,7 @@
|
||||
}
|
||||
|
||||
function renderTable(){
|
||||
const pageData = tableState.data || [];
|
||||
const pageData = filterByKategoriType(tableState.data || []);
|
||||
|
||||
if(pageData.length === 0){
|
||||
tbody.innerHTML = `
|
||||
@ -565,11 +609,48 @@
|
||||
const value = searchInput ? searchInput.value : '';
|
||||
tableState.search = (value || '').trim();
|
||||
tableState.unit = unitSelect && window.$ ? ($('#tableUnit').val() || []) : (tableState.unit || []);
|
||||
tableState.kategori = kategoriSelect && window.$ ? ($('#tableKategori').val() || []) : (tableState.kategori || []);
|
||||
const katVal = kategoriSelect && window.$ ? ($('#tableKategori').val() || '') : (kategoriSelect?.value || '');
|
||||
tableState.kategoriType = katVal ? [katVal] : (tableState.kategoriType || []);
|
||||
tableState.page = 1;
|
||||
fetchData();
|
||||
}
|
||||
|
||||
function filterByKategoriType(items){
|
||||
const types = tableState.kategoriType || [];
|
||||
if (!types.length) return items;
|
||||
return items.filter(item => {
|
||||
return types.some(type => {
|
||||
if (type === 'akreditasi') {
|
||||
return item.is_akre === true || item.is_akre === 1 || item.is_akre === '1';
|
||||
}
|
||||
if (type === 'hukum') {
|
||||
return !!item.kategori_hukum;
|
||||
}
|
||||
if (type === 'lainnya') {
|
||||
return !!item.master_kategori_directory_id;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function renderKategoriHeaderOptions(){
|
||||
if (!kategoriHeaderMenu) return;
|
||||
const list = kategoriHeaderMenu.querySelector('.kategori-header-list');
|
||||
if (!list) return;
|
||||
const selected = (tableState.kategoriType || []).map(v => String(v));
|
||||
list.innerHTML = kategoriTypeOptions.map(opt => {
|
||||
const checked = selected.includes(opt.id) ? 'checked' : '';
|
||||
return `
|
||||
<label class="dropdown-item d-flex align-items-center gap-2">
|
||||
<input type="checkbox" class="form-check-input m-0" value="${opt.id}" ${checked}>
|
||||
<span>${opt.label}</span>
|
||||
</label>
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
|
||||
function fetchData(){
|
||||
if(summaryEl) summaryEl.textContent = 'Memuat data...';
|
||||
const params = new URLSearchParams({
|
||||
@ -580,9 +661,6 @@
|
||||
if (tableState.unit && tableState.unit.length > 0) {
|
||||
tableState.unit.forEach(id => params.append('unit[]', id));
|
||||
}
|
||||
if (tableState.kategori && tableState.kategori.length > 0) {
|
||||
tableState.kategori.forEach(kat => params.append('kategori[]', kat));
|
||||
}
|
||||
fetch(`/data-internal?${params.toString()}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
@ -617,6 +695,7 @@
|
||||
year: 'numeric'
|
||||
});
|
||||
}
|
||||
renderKategoriHeaderOptions();
|
||||
fetchData()
|
||||
|
||||
function updateSelectedCount(){
|
||||
@ -897,13 +976,9 @@
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Instrumen Akreditasi </label>
|
||||
<select class="form-select akre-select" id="akre_select_${colCount}" style="width: 350px;">
|
||||
<select class="form-select akre-select" id="akre_select_${colCount}" name="data[${colCount}][akre]" style="width: 350px;">
|
||||
<option value="" disabled selected>Pilih Instrumen</option>
|
||||
</select>
|
||||
<input type="hidden" name="data[${colCount}][akre_type]" id="akre_type_${colCount}">
|
||||
<input type="hidden" name="data[${colCount}][akre_segment]" id="akre_segment_${colCount}">
|
||||
<input type="hidden" name="data[${colCount}][akre_item]" id="akre_item_${colCount}">
|
||||
<input type="hidden" name="data[${colCount}][is_akre]" value="1">
|
||||
<div class="form-text text-muted">Isi form ini bila dokumen yang diunggah merupakan dokumen <strong>akreditasi</strong>.</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
|
||||
@ -78,13 +78,9 @@
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Instrumen Akreditasi</label>
|
||||
<select class="form-select akre-select" id="akre_select_0" style="width: 350px;">
|
||||
<select class="form-select akre-select" name="data[0][akre]" id="akre_select_0" style="width: 350px;">
|
||||
<option value="">Pilih Instrumen</option>
|
||||
</select>
|
||||
<input type="hidden" name="data[0][akre_type]" id="akre_type_0">
|
||||
<input type="hidden" name="data[0][akre_segment]" id="akre_segment_0">
|
||||
<input type="hidden" name="data[0][akre_item]" id="akre_item_0">
|
||||
<input type="hidden" name="data[0][is_akre]" value="1">
|
||||
<div class="form-text text-muted">Isi form ini bila dokumen yang diunggah merupakan dokumen <strong>akreditasi</strong>.</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<a class="sidebar-link" href="{{ url('/data-akreditasi') }}" aria-expanded="false">
|
||||
<i class="ti ti-layout-dashboard"></i>
|
||||
<i class="fa-solid fa-sliders"></i>
|
||||
<span class="hide-menu">Dokumen Akreditasi</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@ -18,27 +18,18 @@
|
||||
<div class="small text-muted">Perbarui detail dokumen sebelum mengirim ulang.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-control unit_kerja" name="id_unit_kerja" id="edit_id_unit_kerja" required>
|
||||
<option value="" disabled selected>Pilih Unit</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold">Sub Unit <span class="text-danger">*</span></label>
|
||||
<select class="form-control sub_unit_kerja" name="id_sub_unit_kerja" id="edit_id_sub_unit_kerja" required>
|
||||
<option value="" disabled selected>Pilih Sub Unit</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Dokumen</label>
|
||||
<select class="form-control" name="master_kategori_directory_id" id="edit_kategori">
|
||||
<option value="" disabled selected>Pilih Kategori</option>
|
||||
@foreach ($katDok as $kat)
|
||||
<option value="{{ $kat->master_kategori_directory_id }}/{{ $kat->nama_kategori_directory }}">{{ $kat->nama_kategori_directory }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Nomor Dokumen</label>
|
||||
@ -55,17 +46,17 @@
|
||||
<label class="form-label fw-semibold">Tanggal Terbit</label>
|
||||
<input class="form-control" type="date" name="tanggal_terbit" id="edit_tanggal_terbit">
|
||||
</div>
|
||||
<div class="col-md-2 d-flex align-items-end">
|
||||
<div class="col-md-4">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="edit_has_expired" data-target="edit_expired_field">
|
||||
<label class="form-check-label" for="edit_has_expired">Ada Expired?</label>
|
||||
<input class="form-check-input toggle-expired" type="checkbox" id="edit_has_expired" data-target="edit_expired_field">
|
||||
<label class="form-check-label" for="edit_has_expired">Masa Berlaku Dokumen?</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5" id="edit_expired_field">
|
||||
<div class="col-md-4" id="edit_expired_field">
|
||||
<label class="form-label fw-semibold">Tanggal Kedaluwarsa Dokumen</label>
|
||||
<input class="form-control" type="date" name="tgl_expired" id="edit_tgl_expired" disabled>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Boleh dilihat unit lain? <span class="text-danger">*</span></label>
|
||||
<div class="border rounded-3 p-2 bg-light">
|
||||
<div class="form-check">
|
||||
@ -79,6 +70,42 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Instrumen Akreditasi</label>
|
||||
<select class="form-select akre-select" id="edit_akre_select" name="akre" style="width: 350px;">
|
||||
<option value="">Pilih Instrumen</option>
|
||||
</select>
|
||||
<div class="form-text text-muted">Isi form ini bila dokumen yang diunggah merupakan dokumen <strong>akreditasi</strong>.</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori Hukum</label>
|
||||
<select class="form-select select-kat-hukum" name="kategori_hukum" id="edit_kategori_hukum" style="width: 350px;">
|
||||
<option value="">Pilih Kategori Hukum</option>
|
||||
<option value="Pedir - Kebijakan">Pedir - Kebijakan</option>
|
||||
<option value="Keputusan Dirut - Kebijakan">Keputusan Dirut - Kebijakan</option>
|
||||
<option value="Surat Edaran - Kebijakan">Surat Edaran - Kebijakan</option>
|
||||
<option value="Pengumuman - Kebijakan">Pengumuman - Kebijakan</option>
|
||||
<option value="Pelayanan Kesehatan - Kerjasama">Pelayanan Kesehatan - Kerjasama</option>
|
||||
<option value="Management - Kerjasama">Management - Kerjasama</option>
|
||||
<option value="Pemeliharan - Kerjasama">Pemeliharan - Kerjasama</option>
|
||||
<option value="iklat - Kerjasama">Diklat - Kerjasama</option>
|
||||
<option value="Luar Negeri - Kerjasama">Luar Negeri - Kerjasama</option>
|
||||
<option value="Area Bisnis - Kerjasama">Area Bisnis - Kerjasama</option>
|
||||
<option value="Pendidikan - Kerjasama">Pendidikan - Kerjasama</option>
|
||||
<option value="Pengampuan KIA">Pengampuan KIA</option>
|
||||
</select>
|
||||
<div class="form-text text-muted">Isi form ini bila dokumen yang diunggah merupakan dokumen <strong>akreditasi</strong>.</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-semibold">Kategori lainnya</label>
|
||||
<select class="form-select" name="master_kategori_directory_id" id="edit_kategori" style="width: 350px;">
|
||||
<option value="">Pilih Kategori</option>
|
||||
@foreach ($katDok as $kat)
|
||||
<option value="{{ $kat->master_kategori_directory_id }}/{{ $kat->nama_kategori_directory }}">{{ $kat->nama_kategori_directory }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 mb-2">
|
||||
<label for="edit_file_upload" class="form-label fw-semibold">📂 Upload Dokumen (PDF)</label>
|
||||
<div class="border rounded-3 p-3 bg-white shadow-sm">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user