1235 lines
51 KiB
PHP
1235 lines
51 KiB
PHP
@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; }
|
||
|
||
/* Aksi Folder (lebih user-friendly) */
|
||
.folder-actions {
|
||
display: inline-flex;
|
||
gap: 6px;
|
||
margin-left: 8px;
|
||
opacity: 0;
|
||
transform: translateY(-1px);
|
||
transition: opacity 0.15s ease, transform 0.15s ease;
|
||
}
|
||
.tree-folder:hover .folder-actions {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
.btn-folder-action {
|
||
padding: 1px 2px;
|
||
font-size: 11px;
|
||
line-height: 1.2;
|
||
border-radius: 999px;
|
||
}
|
||
</style>
|
||
@section('body_main')
|
||
<div class="row">
|
||
<div class="col-md-12">
|
||
<div class="card">
|
||
<div class="card-body p-3">
|
||
<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 Akreditasi</h4>
|
||
<div class="d-flex align-items-start gap-3">
|
||
<div class="d-flex flex-column align-items-start">
|
||
<button
|
||
type="button"
|
||
class="btn btn-primary btn-sm"
|
||
id="btnDownloadMultiple"
|
||
disabled
|
||
>
|
||
<i class="ti ti-download me-1"></i>
|
||
Download Terpilih
|
||
</button>
|
||
|
||
<span
|
||
id="selectedCount"
|
||
class="small text-muted mt-1"
|
||
>
|
||
0 dipilih
|
||
</span>
|
||
</div>
|
||
@if(Auth::guard('admin')->check())
|
||
<button
|
||
type="button"
|
||
class="btn btn-outline-primary btn-sm"
|
||
data-bs-toggle="modal"
|
||
data-bs-target="#modalAkreInstrumen"
|
||
>
|
||
<i class="ti ti-folder-plus me-1"></i>
|
||
Tambah Folder Akreditasi
|
||
</button>
|
||
@endif
|
||
<!-- Tambah Dokumen -->
|
||
@if(!Auth::guard('admin')->check())
|
||
<button
|
||
type="button"
|
||
class="btn btn-success btn-sm"
|
||
data-bs-toggle="modal"
|
||
data-bs-target="#modalCreateFile"
|
||
>
|
||
<i class="ti ti-plus me-1"></i>
|
||
Tambah Dokumen
|
||
</button>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
<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 Dokumen / Folder" autocomplete="off">
|
||
</div>
|
||
<div class="d-flex align-items-center gap-2">
|
||
|
||
</div>
|
||
</div>
|
||
<div class="table-responsive" style="max-height: 70vh; overflow-y:auto;">
|
||
<table class="table table-sm table-hover align-middle mb-0 table-fixed" id="lastUpdatedTable">
|
||
<thead>
|
||
<tr>
|
||
<th class="text-center" style="width: 45px;">
|
||
<input type="checkbox" id="checkAllRows" class="form-check-input">
|
||
</th>
|
||
<th style="width: 80px;">Aksi</th>
|
||
<th style="width: 40%;">Nama Dokumen / Folder</th>
|
||
<th>Tipe</th>
|
||
<th>Unit</th>
|
||
<th>Tgl Unggah</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="tableDataAkreditasi">
|
||
<!-- data dari fetch masuk sini -->
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="d-flex flex-wrap align-items-center gap-2 mt-3">
|
||
<div class="d-flex align-items-center gap-1">
|
||
<span class="small text-muted">Tampilkan</span>
|
||
<select id="tablePageSize" class="form-select form-select-sm" style="width: 80px;">
|
||
<option value="5">5</option>
|
||
<option value="10" selected>10</option>
|
||
<option value="20">20</option>
|
||
<option value="50">50</option>
|
||
<option value="100">100</option>
|
||
</select>
|
||
<span class="small text-muted">data</span>
|
||
</div>
|
||
|
||
<div id="paginationControls" class="ms-auto"></div>
|
||
|
||
<div class="small text-muted text-nowrap" id="tableSummary">
|
||
Memuat data...
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
@include('dataUnit.modal.create')
|
||
|
||
@if(Auth::guard('admin')->check())
|
||
<div class="modal fade" id="modalAkreInstrumen" tabindex="-1" aria-hidden="true">
|
||
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h1 class="modal-title fs-5">Tambah Folder/Instrumen Akreditasi</h1>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||
</div>
|
||
<form id="formAkreInstrumen" autocomplete="off">
|
||
<div class="modal-body">
|
||
<div class="alert alert-info small mb-3">
|
||
Isi <strong>Type</strong> untuk membuat folder utama. Isi <strong>Segment</strong> untuk membuat sub-folder di dalam type.
|
||
Isi <strong>Item</strong> untuk membuat item di dalam segment.
|
||
</div>
|
||
<div class="row g-3">
|
||
<div class="col-12">
|
||
<label class="form-label fw-semibold">Type <span class="text-danger">*</span></label>
|
||
<input type="text" class="form-control" name="type" id="akreTypeInput" placeholder="Contoh: Tata Kelola Rumah Sakit (TKRS)" required>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label class="form-label fw-semibold">Segment</label>
|
||
<textarea class="form-control" name="segment" id="akreSegmentInput" rows="3" placeholder="Contoh: TKRS 7, TKRS 8, TKRS 9"></textarea>
|
||
<div class="form-text text-muted">Opsional. Bisa isi banyak (pisahkan dengan koma atau baris baru).</div>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label class="form-label fw-semibold">Item</label>
|
||
<textarea class="form-control" name="item" id="akreItemInput" rows="3" placeholder="Contoh: TKRS 7.a, TKRS 7.b, TKRS 7.c" disabled></textarea>
|
||
<div class="form-text text-muted">Aktif jika segment diisi. Bisa isi banyak (pisahkan dengan koma atau baris baru).</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Tutup</button>
|
||
<button type="submit" class="btn btn-primary" id="btnSaveAkreInstrumen">Simpan</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
@endif
|
||
|
||
<script>
|
||
// === STATE MANAGEMENT ===
|
||
let currentData = [];
|
||
let selectedIds = [];
|
||
let expandedFolders = new Set();
|
||
let searchTimer;
|
||
const isAdminUser = @json(Auth::guard('admin')->check());
|
||
const btn = document.getElementById('btnDownloadMultiple');
|
||
const tableState = { page: 1, pageSize: 10, lastPage: 1, total: 0, from: 0, to: 0, search: '' };
|
||
const paginationEl = document.getElementById('paginationControls');
|
||
// === INITIALIZATION ===
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
fetchData();
|
||
initEventListeners();
|
||
initTooltips();
|
||
});
|
||
|
||
function initTooltips() {
|
||
try {
|
||
if (!window.bootstrap?.Tooltip) return;
|
||
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => {
|
||
const existing = bootstrap.Tooltip.getInstance(el);
|
||
if (existing) existing.dispose();
|
||
new bootstrap.Tooltip(el);
|
||
});
|
||
} catch (_) {}
|
||
}
|
||
|
||
// === EVENT LISTENERS ===
|
||
function initEventListeners() {
|
||
// Search dengan Debounce
|
||
document.getElementById('tableSearch').addEventListener('input', (e) => {
|
||
clearTimeout(searchTimer);
|
||
searchTimer = setTimeout(() => {
|
||
tableState.page = 1;
|
||
fetchData(e.target.value, 1);
|
||
}, 500);
|
||
});
|
||
|
||
// Per Page Change
|
||
document.getElementById('tablePageSize').addEventListener('change', (e) => {
|
||
const keyword = document.getElementById('tableSearch').value;
|
||
tableState.page = 1;
|
||
fetchData(keyword, 1);
|
||
});
|
||
|
||
// Check All Rows
|
||
document.getElementById('checkAllRows').addEventListener('change', function() {
|
||
const checkboxes = document.querySelectorAll('.row-checkbox');
|
||
selectedIds = [];
|
||
checkboxes.forEach(cb => {
|
||
cb.checked = this.checked;
|
||
if (this.checked) selectedIds.push(cb.value);
|
||
});
|
||
updateDownloadButton();
|
||
});
|
||
}
|
||
|
||
// === CORE FUNCTIONS ===
|
||
|
||
/**
|
||
* Mengambil data dari server
|
||
*/
|
||
function fetchData(keyword = '', page = 1) {
|
||
const tbody = document.getElementById('tableDataAkreditasi');
|
||
const perPage = parseInt(document.getElementById('tablePageSize').value, 10) || 10;
|
||
|
||
tableState.search = keyword;
|
||
tableState.pageSize = perPage;
|
||
tableState.page = page;
|
||
|
||
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())
|
||
.then(response => {
|
||
if (response.status) {
|
||
currentData = response.data || [];
|
||
renderTable(keyword);
|
||
const pag = response.pagination || {};
|
||
tableState.total = pag.total || 0;
|
||
tableState.lastPage = pag.last_page || 1;
|
||
tableState.from = pag.from || 0;
|
||
tableState.to = pag.to || 0;
|
||
renderPagination(tableState.lastPage);
|
||
updateSummary();
|
||
} else {
|
||
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="6" class="text-center text-danger">Gagal memuat data dari server.</td></tr>';
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Merender tabel berdasarkan mode (Folder vs Search)
|
||
*/
|
||
function renderTable(keyword = '') {
|
||
const tbody = document.getElementById('tableDataAkreditasi');
|
||
tbody.innerHTML = '';
|
||
|
||
if (currentData.length === 0) {
|
||
tbody.innerHTML = '<tr><td colspan="6" class="text-center">Tidak ada data ditemukan</td></tr>';
|
||
return;
|
||
}
|
||
|
||
// MODE 1: SEARCH VIEW (Flat View - Langsung tampilkan semua file)
|
||
if (keyword.length > 0) {
|
||
currentData.forEach(item => renderFileRow(tbody, item));
|
||
return;
|
||
}
|
||
|
||
// MODE 2: TREE VIEW (All folders & files)
|
||
const tree = buildTree(currentData);
|
||
if (expandedFolders.size === 0) {
|
||
expandAllFolders(tree, '');
|
||
}
|
||
renderTree(tbody, tree, '', 0);
|
||
initTooltips();
|
||
}
|
||
|
||
/**
|
||
* Render Baris File (Digunakan di kedua mode)
|
||
*/
|
||
function renderFileRow(targetTbody, item) {
|
||
const fileName = item.file ? item.file.split('/').pop() : 'Unknown';
|
||
const typeDok = fileName.split('.').pop().toUpperCase();
|
||
const isChecked = selectedIds.includes(String(item.file_directory_id)) ? 'checked' : '';
|
||
|
||
targetTbody.innerHTML += `
|
||
<tr>
|
||
<td class="text-center">
|
||
<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"
|
||
class="btn btn-sm btn-outline-primary" download title="Download">
|
||
<i class="ti ti-download"></i>
|
||
</a>
|
||
</div>
|
||
</td>
|
||
<td>
|
||
<div class="d-flex flex-column">
|
||
<strong>${item.nama_dokumen}</strong>
|
||
<small class="text-muted" style="font-size: 10px;">Path: ${item.file}</small>
|
||
</div>
|
||
</td>
|
||
<td><span class="badge bg-light text-primary border">${typeDok}</span></td>
|
||
<td></td>
|
||
<td>${item.entry_at || '-'}</td>
|
||
</tr>`;
|
||
}
|
||
|
||
// === TREE FUNCTIONS ===
|
||
|
||
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 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];
|
||
const depth = folderPath.split('/').filter(Boolean).length;
|
||
const canAddChild = isAdminUser && (depth === 1 || depth === 2);
|
||
|
||
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>
|
||
${canAddChild ? `
|
||
<span class="folder-actions">
|
||
<button type="button"
|
||
class="badge bg-primary"
|
||
data-bs-toggle="tooltip"
|
||
data-bs-title="${depth === 1 ? 'Tambah Segment' : 'Tambah Item'}"
|
||
onclick="event.stopPropagation(); openAddAkreFromFolder('${folderPath.replace(/'/g, "\\\\'")}')">
|
||
<i class="ti ti-plus me-1"></i>${depth === 1 ? 'Segment' : 'Item'}
|
||
</button>
|
||
</span>
|
||
` : ''}
|
||
</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>${item.unit?.name || '-'}</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 ===
|
||
|
||
function handleRowCheck(checkbox) {
|
||
const val = String(checkbox.value);
|
||
if (checkbox.checked) {
|
||
if (!selectedIds.includes(val)) selectedIds.push(val);
|
||
} else {
|
||
selectedIds = selectedIds.filter(id => id !== val);
|
||
document.getElementById('checkAllRows').checked = false;
|
||
}
|
||
updateDownloadButton();
|
||
}
|
||
|
||
function updateDownloadButton() {
|
||
|
||
const countLabel = document.getElementById('selectedCount');
|
||
btn.disabled = selectedIds.length === 0;
|
||
countLabel.innerText = `${selectedIds.length} dipilih`;
|
||
}
|
||
|
||
function updateSummary() {
|
||
const summary = document.getElementById('tableSummary');
|
||
if (!summary) return;
|
||
|
||
if (!tableState.total) {
|
||
summary.innerText = 'Tidak ada data';
|
||
return;
|
||
}
|
||
|
||
const from = tableState.from || 0;
|
||
const to = tableState.to || 0;
|
||
summary.innerText = `Menampilkan ${from} - ${to} dari ${tableState.total} data`;
|
||
}
|
||
|
||
function renderPagination(totalPages){
|
||
if(!paginationEl) return;
|
||
if(totalPages <= 1){
|
||
paginationEl.innerHTML = '';
|
||
return;
|
||
}
|
||
|
||
const maxButtons = 5;
|
||
let start = Math.max(1, tableState.page - Math.floor(maxButtons/2));
|
||
let end = Math.min(totalPages, start + maxButtons - 1);
|
||
start = Math.max(1, end - maxButtons + 1);
|
||
|
||
let buttons = '';
|
||
buttons += `<button class="btn btn-outline-secondary btn-sm" data-page="prev" ${tableState.page === 1 ? 'disabled' : ''}>‹ Sebelumnya</button>`;
|
||
|
||
for(let i=start; i<=end; i++){
|
||
buttons += `<button class="btn btn-sm ${i === tableState.page ? 'btn-primary' : 'btn-outline-secondary'}" data-page="${i}">${i}</button>`;
|
||
}
|
||
|
||
buttons += `<button class="btn btn-outline-secondary btn-sm" data-page="next" ${tableState.page === totalPages ? 'disabled' : ''}>Berikutnya ›</button>`;
|
||
|
||
paginationEl.innerHTML = `
|
||
<div class="d-flex align-items-center gap-2 flex-wrap">
|
||
<div class="btn-group" role="group">${buttons}</div>
|
||
<span class="small text-muted">Halaman ${tableState.page} dari ${totalPages}</span>
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
if(paginationEl){
|
||
paginationEl.addEventListener('click', (e) => {
|
||
const page = e.target.getAttribute('data-page');
|
||
if(!page) return;
|
||
|
||
if(page === 'prev' && tableState.page > 1) tableState.page--;
|
||
else if(page === 'next'){
|
||
if(tableState.page < tableState.lastPage) tableState.page++;
|
||
}else{
|
||
tableState.page = parseInt(page, 10) || 1;
|
||
}
|
||
|
||
fetchData(tableState.search || '', tableState.page);
|
||
});
|
||
}
|
||
|
||
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.jff')
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
akreData = Array.isArray(data) ? data : [];
|
||
akreFlat = [];
|
||
akreLoaded = true;
|
||
return akreData;
|
||
})
|
||
.catch(() => {
|
||
akreData = [];
|
||
akreFlat = [];
|
||
akreLoaded = true;
|
||
return akreData;
|
||
});
|
||
}
|
||
|
||
function refreshAkreData(){
|
||
akreLoaded = false;
|
||
akreData = [];
|
||
akreFlat = [];
|
||
return loadAkreData();
|
||
}
|
||
|
||
function refreshAkreSelects(){
|
||
return refreshAkreData().then(() => {
|
||
document.querySelectorAll('select.akre-select').forEach(selectEl => {
|
||
const current = selectEl.value;
|
||
fillAkreSelect(selectEl);
|
||
if(current) {
|
||
// restore selection if still exists
|
||
selectEl.value = current;
|
||
}
|
||
if(window.$ && $.fn.select2){
|
||
$(selectEl).trigger('change');
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
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}">Ya</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="Kebijakan - Peraturan Direktur">Kebijakan - Peraturan Direktur</option>
|
||
<option value="Kebijakan - Keputusan Direktur Utama">Kebijakan - Keputusan Direktur Utama</option>
|
||
<option value="Kebijakan - Surat Edaran">Kebijakan - Surat Edaran</option>
|
||
<option value="Kebijakan - Pengumuman">Kebijakan - Pengumuman</option>
|
||
<option value="Kerjasama - Pelayanan Kesehatan">Kerjasama - Pelayanan Kesehatan</option>
|
||
<option value="Kerjasama - Management">Kerjasama - Management</option>
|
||
<option value="Kerjasama - Pemeliharan">Kerjasama - Pemeliharan</option>
|
||
<option value="Kerjasama - Diklat">Kerjasama - Diklat</option>
|
||
<option value="Kerjasama - Luar Negeri">Kerjasama - Luar Negeri</option>
|
||
<option value="Kerjasama - Area Bisnis">Kerjasama - Area Bisnis</option>
|
||
<option value="Kerjasama - Pendidikan">Kerjasama - Pendidikan</option>
|
||
<option value="Kerjasama - Pengampuan KIA">Kerjasama- Pengampuan KIA</option>
|
||
</select>
|
||
</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';
|
||
});
|
||
});
|
||
}
|
||
|
||
// Admin: tambah folder/instrumen akreditasi (disimpan di public/json/akreditasi.jff)
|
||
const formAkreInstrumen = document.getElementById('formAkreInstrumen');
|
||
const akreSegmentInput = document.getElementById('akreSegmentInput');
|
||
const akreItemInput = document.getElementById('akreItemInput');
|
||
|
||
if (akreSegmentInput && akreItemInput) {
|
||
const updateItemEnabled = () => {
|
||
const hasSegment = String(akreSegmentInput.value || '').trim().length > 0;
|
||
akreItemInput.disabled = !hasSegment;
|
||
if (!hasSegment) akreItemInput.value = '';
|
||
};
|
||
akreSegmentInput.addEventListener('input', updateItemEnabled);
|
||
updateItemEnabled();
|
||
}
|
||
|
||
if (formAkreInstrumen) {
|
||
formAkreInstrumen.addEventListener('submit', (e) => {
|
||
e.preventDefault();
|
||
const btn = document.getElementById('btnSaveAkreInstrumen');
|
||
if (btn) btn.disabled = true;
|
||
if (btn) btn.textContent = 'menyimpan...';
|
||
|
||
const payload = {
|
||
type: String(document.getElementById('akreTypeInput')?.value || '').trim(),
|
||
segment: String(document.getElementById('akreSegmentInput')?.value || '').trim(),
|
||
item: String(document.getElementById('akreItemInput')?.value || '').trim(),
|
||
};
|
||
if (!payload.segment) delete payload.segment;
|
||
if (!payload.item) delete payload.item;
|
||
|
||
fetch('/akreditasi/instrumen', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRF-TOKEN': document.querySelector('input[name="_token"]')?.value || '',
|
||
},
|
||
body: JSON.stringify(payload),
|
||
})
|
||
.then(async (res) => {
|
||
const data = await res.json().catch(() => ({}));
|
||
if (!res.ok) {
|
||
const msg = data?.message || (data?.errors ? Object.values(data.errors).flat().join(' ') : '') || 'Terjadi kesalahan.';
|
||
throw new Error(msg);
|
||
}
|
||
if (data?.status === false) {
|
||
throw new Error(data?.message || 'Terjadi kesalahan.');
|
||
}
|
||
Swal.fire({
|
||
icon: 'success',
|
||
title: 'Berhasil',
|
||
text: data?.message || 'Folder akreditasi berhasil ditambahkan.',
|
||
timer: 1500,
|
||
showConfirmButton: false,
|
||
});
|
||
|
||
const modalEl = document.getElementById('modalAkreInstrumen');
|
||
const modalInstance = modalEl ? bootstrap.Modal.getInstance(modalEl) : null;
|
||
modalInstance?.hide();
|
||
|
||
formAkreInstrumen.reset();
|
||
if (akreItemInput) akreItemInput.disabled = true;
|
||
|
||
// refresh dropdown instrumen di form upload
|
||
return refreshAkreSelects();
|
||
})
|
||
.catch((err) => {
|
||
Swal.fire({
|
||
icon: 'error',
|
||
title: 'Gagal',
|
||
text: err?.message || 'Terjadi kesalahan.',
|
||
});
|
||
})
|
||
.finally(() => {
|
||
if (btn) btn.disabled = false;
|
||
if (btn) btn.textContent = 'Simpan';
|
||
});
|
||
});
|
||
}
|
||
|
||
// Klik tombol "+" di samping folder (tree view) untuk menambah sub-folder sesuai level:
|
||
// - depth 1 (Type) -> tambah Segment
|
||
// - depth 2 (Type/Segment) -> tambah Item
|
||
window.openAddAkreFromFolder = function(folderPath){
|
||
const modalEl = document.getElementById('modalAkreInstrumen');
|
||
if (!modalEl) return;
|
||
|
||
const typeInput = document.getElementById('akreTypeInput');
|
||
const segmentInput = document.getElementById('akreSegmentInput');
|
||
const itemInput = document.getElementById('akreItemInput');
|
||
if (!typeInput || !segmentInput || !itemInput) return;
|
||
|
||
const parts = String(folderPath || '').split('/').filter(Boolean);
|
||
const depth = parts.length;
|
||
|
||
// reset state
|
||
typeInput.readOnly = false;
|
||
segmentInput.readOnly = false;
|
||
itemInput.disabled = true;
|
||
itemInput.readOnly = false;
|
||
|
||
if (depth >= 1) {
|
||
typeInput.value = parts[0] || '';
|
||
typeInput.readOnly = true;
|
||
} else {
|
||
typeInput.value = '';
|
||
}
|
||
|
||
if (depth >= 2) {
|
||
segmentInput.value = parts[1] || '';
|
||
segmentInput.readOnly = true;
|
||
itemInput.disabled = false;
|
||
itemInput.value = '';
|
||
} else {
|
||
segmentInput.value = '';
|
||
itemInput.value = '';
|
||
}
|
||
|
||
const instance = bootstrap.Modal.getOrCreateInstance(modalEl);
|
||
instance.show();
|
||
|
||
// fokus ke field yang tepat
|
||
if (depth >= 2) {
|
||
itemInput.focus();
|
||
} else {
|
||
segmentInput.focus();
|
||
}
|
||
}
|
||
|
||
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
|