add detail data path akreditasi
This commit is contained in:
parent
80edf77280
commit
d3b9cc3425
@ -2833,6 +2833,57 @@ class DashboardController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function dataAkreditasiRecap()
|
||||||
|
{
|
||||||
|
$rows = FileDirectory::query()
|
||||||
|
->select(['file'])
|
||||||
|
->where('statusenabled', true)
|
||||||
|
->where('status_action', 'approved')
|
||||||
|
->where('is_akre', true)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$folderCounts = [];
|
||||||
|
$totalFiles = 0;
|
||||||
|
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$filePath = trim((string) ($row->file ?? ''));
|
||||||
|
if ($filePath === '' || !str_contains($filePath, '/')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$folderPath = preg_replace('~/[^/]+$~', '', $filePath);
|
||||||
|
$folderPath = trim((string) $folderPath, '/');
|
||||||
|
if ($folderPath === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$folderCounts[$folderPath] = ($folderCounts[$folderPath] ?? 0) + 1;
|
||||||
|
$totalFiles++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$detailRows = collect($folderCounts)
|
||||||
|
->map(fn ($count, $path) => [
|
||||||
|
'path' => $path,
|
||||||
|
'total' => $count,
|
||||||
|
])
|
||||||
|
->sortBy([
|
||||||
|
['total', 'desc'],
|
||||||
|
['path', 'asc'],
|
||||||
|
])
|
||||||
|
->values()
|
||||||
|
->all();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'status' => true,
|
||||||
|
'message' => 'Berhasil mendapatkan rekap akreditasi',
|
||||||
|
'summary' => [
|
||||||
|
'total_files' => $totalFiles,
|
||||||
|
'total_folders' => count($folderCounts),
|
||||||
|
],
|
||||||
|
'data' => $detailRows,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function expDokumen(){
|
public function expDokumen(){
|
||||||
$katDok = MasterKategori::where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get();
|
$katDok = MasterKategori::where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get();
|
||||||
$authMapping = auth()->user()?->dataUser?->mappingUnitKerjaPegawai[0];
|
$authMapping = auth()->user()?->dataUser?->mappingUnitKerjaPegawai[0];
|
||||||
|
|||||||
@ -305,6 +305,19 @@
|
|||||||
.akre-selection-status {
|
.akre-selection-status {
|
||||||
color: #7b8aa0;
|
color: #7b8aa0;
|
||||||
}
|
}
|
||||||
|
.akre-recap-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border-top: 1px solid #edf2f7;
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.akre-recap-bar strong {
|
||||||
|
color: #1e293b;
|
||||||
|
}
|
||||||
.akre-parent-chip {
|
.akre-parent-chip {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -397,7 +410,7 @@
|
|||||||
<div class="col-lg-4 akre-column">
|
<div class="col-lg-4 akre-column">
|
||||||
<div class="akre-tree-panel">
|
<div class="akre-tree-panel">
|
||||||
<div class="akre-tree-header">
|
<div class="akre-tree-header">
|
||||||
<h5 class="mb-1">Struktur Akreditasi</h5>
|
<h5 class="mb-1">Struktur Dokumen</h5>
|
||||||
<p class="text-muted small mb-0">Pilih folder di kiri untuk memfilter dokumen di panel kanan.</p>
|
<p class="text-muted small mb-0">Pilih folder di kiri untuk memfilter dokumen di panel kanan.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="akre-tree-body" id="akreTreeContainer">
|
<div class="akre-tree-body" id="akreTreeContainer">
|
||||||
@ -489,6 +502,12 @@
|
|||||||
<div class="akre-browser-empty">Pilih folder pada struktur kiri untuk melihat isinya.</div>
|
<div class="akre-browser-empty">Pilih folder pada struktur kiri untuk melihat isinya.</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="akre-recap-bar">
|
||||||
|
<span id="akreRecapSummary">Memuat ringkasan dokumen akreditasi...</span>
|
||||||
|
<button type="button" class="btn btn-outline-secondary btn-sm" id="btnAkreRecapDetail">
|
||||||
|
Detail
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -542,6 +561,35 @@
|
|||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
<div class="modal fade" id="modalAkreRecapDetail" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5">Detail Rekap Dokumen Akreditasi</h1>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="small text-muted mb-3" id="akreRecapModalSummary">Memuat detail rekap...</div>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-sm table-hover align-middle mb-0">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th style="width: 70%;">Path</th>
|
||||||
|
<th class="text-center" style="width: 30%;">Total File</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="akreRecapDetailBody">
|
||||||
|
<tr>
|
||||||
|
<td colspan="2" class="text-center text-muted py-4">Memuat data...</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// === STATE MANAGEMENT ===
|
// === STATE MANAGEMENT ===
|
||||||
let currentData = [];
|
let currentData = [];
|
||||||
@ -562,6 +610,7 @@
|
|||||||
initEventListeners();
|
initEventListeners();
|
||||||
initTooltips();
|
initTooltips();
|
||||||
configureAkreModal('');
|
configureAkreModal('');
|
||||||
|
fetchAkreRecap();
|
||||||
});
|
});
|
||||||
|
|
||||||
function initTooltips() {
|
function initTooltips() {
|
||||||
@ -623,6 +672,15 @@
|
|||||||
clearSelectedFiles();
|
clearSelectedFiles();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const recapDetailBtn = document.getElementById('btnAkreRecapDetail');
|
||||||
|
if (recapDetailBtn) {
|
||||||
|
recapDetailBtn.addEventListener('click', function() {
|
||||||
|
const modalEl = document.getElementById('modalAkreRecapDetail');
|
||||||
|
if (!modalEl) return;
|
||||||
|
bootstrap.Modal.getOrCreateInstance(modalEl).show();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// === CORE FUNCTIONS ===
|
// === CORE FUNCTIONS ===
|
||||||
@ -824,11 +882,66 @@
|
|||||||
let activeAkreNodeKey = null;
|
let activeAkreNodeKey = null;
|
||||||
let activeAkrePath = '';
|
let activeAkrePath = '';
|
||||||
let pendingAkreFocusPath = '';
|
let pendingAkreFocusPath = '';
|
||||||
|
let akreRecapRows = [];
|
||||||
|
|
||||||
function loadAkreData(){
|
function loadAkreData(){
|
||||||
return Promise.resolve(akreData);
|
return Promise.resolve(akreData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderAkreRecapSummary(summary = {}) {
|
||||||
|
const summaryEl = document.getElementById('akreRecapSummary');
|
||||||
|
const modalSummaryEl = document.getElementById('akreRecapModalSummary');
|
||||||
|
const totalFiles = Number(summary.total_files || 0);
|
||||||
|
const totalFolders = Number(summary.total_folders || 0);
|
||||||
|
const html = totalFiles || totalFolders
|
||||||
|
? `Total <strong>${totalFiles}</strong> file di <strong>${totalFolders}</strong> folder akreditasi.`
|
||||||
|
: 'Belum ada file akreditasi yang tersimpan.';
|
||||||
|
|
||||||
|
if (summaryEl) summaryEl.innerHTML = html;
|
||||||
|
if (modalSummaryEl) {
|
||||||
|
modalSummaryEl.textContent = totalFiles || totalFolders
|
||||||
|
? `Total ${totalFiles} file di ${totalFolders} folder akreditasi.`
|
||||||
|
: 'Belum ada file akreditasi yang tersimpan.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderAkreRecapDetailRows(rows = []) {
|
||||||
|
const tbody = document.getElementById('akreRecapDetailBody');
|
||||||
|
if (!tbody) return;
|
||||||
|
|
||||||
|
if (!rows.length) {
|
||||||
|
tbody.innerHTML = '<tr><td colspan="2" class="text-center text-muted py-4">Belum ada data rekap akreditasi.</td></tr>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody.innerHTML = rows.map(row => `
|
||||||
|
<tr>
|
||||||
|
<td>${e(row.path || '-')}</td>
|
||||||
|
<td class="text-center fw-semibold">${Number(row.total || 0)}</td>
|
||||||
|
</tr>
|
||||||
|
`).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchAkreRecap() {
|
||||||
|
const summaryEl = document.getElementById('akreRecapSummary');
|
||||||
|
const tbody = document.getElementById('akreRecapDetailBody');
|
||||||
|
if (summaryEl) summaryEl.textContent = 'Memuat ringkasan dokumen akreditasi...';
|
||||||
|
if (tbody) tbody.innerHTML = '<tr><td colspan="2" class="text-center text-muted py-4">Memuat data...</td></tr>';
|
||||||
|
|
||||||
|
return fetch('/data-akreditasi/recap')
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(data => {
|
||||||
|
akreRecapRows = Array.isArray(data?.data) ? data.data : [];
|
||||||
|
renderAkreRecapSummary(data?.summary || {});
|
||||||
|
renderAkreRecapDetailRows(akreRecapRows);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
akreRecapRows = [];
|
||||||
|
if (summaryEl) summaryEl.textContent = 'Gagal memuat ringkasan dokumen akreditasi.';
|
||||||
|
if (tbody) tbody.innerHTML = '<tr><td colspan="2" class="text-center text-danger py-4">Gagal memuat data.</td></tr>';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function refreshAkreData(){
|
function refreshAkreData(){
|
||||||
akreFlat = [];
|
akreFlat = [];
|
||||||
return fetch('/json/akreditasi.jff')
|
return fetch('/json/akreditasi.jff')
|
||||||
@ -1645,6 +1758,7 @@
|
|||||||
} else {
|
} else {
|
||||||
renderAkreSubtree();
|
renderAkreSubtree();
|
||||||
}
|
}
|
||||||
|
fetchAkreRecap();
|
||||||
} else {
|
} else {
|
||||||
throw new Error(responseData.message || 'Terjadi kesalahan saat menyimpan data.');
|
throw new Error(responseData.message || 'Terjadi kesalahan saat menyimpan data.');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@ Route::middleware(['auth:admin,web'])->group(function(){
|
|||||||
Route::get('/datatable-umum', [DashboardController::class, 'datatableDataUmum']);
|
Route::get('/datatable-umum', [DashboardController::class, 'datatableDataUmum']);
|
||||||
Route::get('/data-akreditasi', [DashboardController::class, 'dataAkreditasi']);
|
Route::get('/data-akreditasi', [DashboardController::class, 'dataAkreditasi']);
|
||||||
Route::get('/datatable-akreditasi', [DashboardController::class, 'dataTableAkreditasi']);
|
Route::get('/datatable-akreditasi', [DashboardController::class, 'dataTableAkreditasi']);
|
||||||
|
Route::get('/data-akreditasi/recap', [DashboardController::class, 'dataAkreditasiRecap']);
|
||||||
|
|
||||||
// Kelola "folder/instrumen" akreditasi via file: public/json/akreditasi.jff (tanpa database)
|
// Kelola "folder/instrumen" akreditasi via file: public/json/akreditasi.jff (tanpa database)
|
||||||
Route::get('/akreditasi/instrumen', [AkreditasiInstrumenController::class, 'index']);
|
Route::get('/akreditasi/instrumen', [AkreditasiInstrumenController::class, 'index']);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user