document.addEventListener('DOMContentLoaded', () => {
const tableState = { data: [], page: 1, pageSize: 10, search: '', lastPage: 1, total: 0, startDate: '', endDate: '', mode: 'pengajuan' };
const historyState = { data: [], page: 1, pageSize: 10, search: '', lastPage: 1, total: 0, startDate: '', endDate: '', mode: 'history' };
const tbodyPending = document.getElementById('tablePendingFile');
const tbodyHistory = document.getElementById('tableHistoryFile');
const paginationPendingEl = document.getElementById('paginationControls');
const paginationHistoryEl = document.getElementById('paginationHistory');
const summaryEl = document.getElementById('tableSummary');
const pageSizeSelect = document.getElementById('tablePageSize');
const startDateInput = document.getElementById('startDate');
const endDateInput = document.getElementById('endDate');
const selectAllCheckbox = document.getElementById('selectAllPending');
const bulkApproveBtn = document.getElementById('bulkApproveBtn');
const clearSelectionBtn = document.getElementById('clearSelectionBtn');
const selectedCountEl = document.getElementById('selectedCount');
const pendingBulkActionsEl = document.getElementById('pendingBulkActions');
const tabsEl = document.getElementById('pengajuanTabs');
const titleEl = document.getElementById('pendingTitle');
const tabPendingEl = document.getElementById('tabPengajuan');
const tabHistoryEl = document.getElementById('tabHistory');
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
const selectedIds = new Set();
if (pageSizeSelect) {
const initialSize = parseInt(pageSizeSelect.value);
if (!isNaN(initialSize)) {
tableState.pageSize = initialSize;
historyState.pageSize = initialSize;
}
pageSizeSelect.addEventListener('change', (e) => {
const val = parseInt(e.target.value);
if (!isNaN(val) && val > 0) {
tableState.pageSize = val;
historyState.pageSize = val;
tableState.page = 1;
historyState.page = 1;
fetchData();
}
});
}
window.applyDateFilter = function(){
const start = startDateInput.value || '';
const end = endDateInput.value || '';
tableState.startDate = start;
tableState.endDate = end;
historyState.startDate = start;
historyState.endDate = end;
tableState.page = 1;
historyState.page = 1;
fetchData();
}
function formatTanggal(dateString) {
if (!dateString) return '-';
const d = new Date(dateString);
return d.toLocaleDateString('id-ID', {
day: '2-digit',
month: 'short',
year: 'numeric'
});
}
function statusBadge(status){
if (status === 'rejected') return 'Rejected';
if (status === 'revised') return 'Revised';
return 'Pending';
}
function aksesBadge(akses){
if (akses){
return 'Umum';
}
return 'Internal Unit';
}
function safeText(val){
return val ? String(val) : '-';
}
function isRejected(item){
return item?.status_action === 'rejected';
}
function getSelectableIdsOnPage(){
return (tableState.data || [])
.filter((item) => !isRejected(item))
.map((item) => String(item.file_directory_id));
}
function updateSelectAllState(){
if (!selectAllCheckbox) return;
if (tableState.mode === 'history') {
selectAllCheckbox.checked = false;
selectAllCheckbox.indeterminate = false;
selectAllCheckbox.disabled = true;
return;
}
const selectableIds = getSelectableIdsOnPage();
if (selectableIds.length === 0) {
selectAllCheckbox.checked = false;
selectAllCheckbox.indeterminate = false;
selectAllCheckbox.disabled = true;
return;
}
selectAllCheckbox.disabled = false;
const selectedOnPage = selectableIds.filter((id) => selectedIds.has(id)).length;
selectAllCheckbox.checked = selectedOnPage > 0 && selectedOnPage === selectableIds.length;
selectAllCheckbox.indeterminate = selectedOnPage > 0 && selectedOnPage < selectableIds.length;
}
function updateSelectionUI(){
const count = selectedIds.size;
if (selectedCountEl) selectedCountEl.textContent = String(count);
if (bulkApproveBtn) bulkApproveBtn.disabled = count === 0 || tableState.mode === 'history';
if (clearSelectionBtn) clearSelectionBtn.disabled = count === 0 || tableState.mode === 'history';
updateSelectAllState();
}
function buildPendingRow(item){
const tanggal = item.entry_at ? formatTanggal(item.entry_at) : '-';
const tanggalExp = item.tgl_expired ? formatTanggal(item.tgl_expired) : '-';
const tanggalTerbit = item.tanggal_terbit ? formatTanggal(item.tanggal_terbit) : '-';
const id = String(item.file_directory_id);
const rejected = isRejected(item);
const checked = selectedIds.has(id);
const aksi = `
`;
return `
|
|
${rejected ? '' : aksi} |
${safeText(item.no_dokumen)} |
${statusBadge(item?.status_action)} |
${aksesBadge(item?.permission_file)} |
${item.nama_dokumen} |
${safeText(item.folder)} |
${safeText(item.part)} |
${tanggalTerbit} |
${tanggalExp} |
${tanggal} |
${safeText(item.pegawai_nama_entry)} |
`;
}
function buildHistoryRow(item){
const tanggal = item.entry_at ? formatTanggal(item.entry_at) : '-';
const tanggalExp = item.tgl_expired ? formatTanggal(item.tgl_expired) : '-';
const tanggalTerbit = item.tanggal_terbit ? formatTanggal(item.tanggal_terbit) : '-';
const actionType = item?.action_type || '-';
return `
| ${safeText(item.no_dokumen)} |
${aksesBadge(item?.permission_file)} |
${safeText(item.nama_dokumen)} |
${safeText(item.folder)} |
${safeText(item.part)} |
${actionType} |
${tanggalTerbit} |
${tanggalExp} |
${tanggal} |
`;
}
function renderPagination(totalPages){
const activeState = tableState.mode === 'history' ? historyState : tableState;
const paginationEl = tableState.mode === 'history' ? paginationHistoryEl : paginationPendingEl;
if (!paginationEl) return;
if (totalPages <= 1) {
paginationEl.innerHTML = '';
return;
}
const maxButtons = 5;
let start = Math.max(1, activeState.page - Math.floor(maxButtons/2));
let end = Math.min(totalPages, start + maxButtons - 1);
start = Math.max(1, end - maxButtons + 1);
let buttons = '';
buttons += ``;
for (let i = start; i <= end; i++) {
buttons += ``;
}
buttons += ``;
paginationEl.innerHTML = `
${buttons}
Halaman ${activeState.page} dari ${totalPages}
`;
}
function bindPagination(paginationEl, state){
if (!paginationEl) return;
paginationEl.addEventListener('click', (e) => {
const page = e.target.getAttribute('data-page');
if (!page) return;
if (page === 'prev' && state.page > 1) state.page--;
else if (page === 'next') {
if (state.page < state.lastPage) state.page++;
} else {
state.page = parseInt(page);
}
fetchData();
});
}
bindPagination(paginationPendingEl, tableState);
bindPagination(paginationHistoryEl, historyState);
function renderTable(){
const isHistoryMode = tableState.mode === 'history';
const activeState = isHistoryMode ? historyState : tableState;
const pageData = activeState.data || [];
const targetBody = isHistoryMode ? tbodyHistory : tbodyPending;
const rowBuilder = isHistoryMode ? buildHistoryRow : buildPendingRow;
const colSpan = isHistoryMode ? 9 : 12;
if (!targetBody) return;
if (pageData.length === 0) {
targetBody.innerHTML = `
|
Tidak ada data
|
`;
} else {
targetBody.innerHTML = pageData.map(rowBuilder).join('');
}
const from = activeState.total === 0 ? 0 : ((activeState.page - 1) * activeState.pageSize) + 1;
const to = Math.min(((activeState.page - 1) * activeState.pageSize) + pageData.length, activeState.total);
if (summaryEl) {
summaryEl.textContent = activeState.total ? `Menampilkan ${from} - ${to} dari ${activeState.total} data` : 'Tidak ada data';
}
renderPagination(activeState.lastPage || 1);
updateSelectionUI();
}
let searchDebounce;
window.debouncedTableSearch = function(value){
clearTimeout(searchDebounce);
searchDebounce = setTimeout(() => {
const keyword = value.trim();
tableState.search = keyword;
historyState.search = keyword;
tableState.page = 1;
historyState.page = 1;
fetchData();
}, 250);
}
window.refreshLog = function(){
tableState.search = '';
tableState.startDate = '';
tableState.endDate = '';
historyState.search = '';
historyState.startDate = '';
historyState.endDate = '';
const tableSearch = document.getElementById('tableSearch');
if (tableSearch) tableSearch.value = '';
if (startDateInput) startDateInput.value = '';
if (endDateInput) endDateInput.value = '';
selectedIds.clear();
tableState.page = 1;
historyState.page = 1;
fetchData();
}
function updateTabUI(){
if (tabsEl) {
tabsEl.querySelectorAll('.nav-link').forEach((btn) => {
btn.classList.toggle('active', btn.getAttribute('data-mode') === tableState.mode);
});
}
if (titleEl) {
titleEl.textContent = tableState.mode === 'history' ? 'Log History' : 'Data Persetujuan';
}
if (tabPendingEl && tabHistoryEl) {
tabPendingEl.classList.toggle('d-none', tableState.mode === 'history');
tabHistoryEl.classList.toggle('d-none', tableState.mode !== 'history');
}
if (pendingBulkActionsEl) {
pendingBulkActionsEl.classList.toggle('d-none', tableState.mode === 'history');
}
updateSelectionUI();
}
if (tabsEl) {
tabsEl.addEventListener('click', (e) => {
const btn = e.target.closest('[data-mode]');
if (!btn) return;
const mode = btn.getAttribute('data-mode');
if (!mode || mode === tableState.mode) return;
tableState.mode = mode;
if (mode === 'history') {
historyState.page = 1;
} else {
tableState.page = 1;
}
updateTabUI();
fetchData();
});
}
function fetchData(){
if (summaryEl) summaryEl.textContent = 'Memuat data...';
const activeState = tableState.mode === 'history' ? historyState : tableState;
const params = new URLSearchParams({
page: activeState.page,
per_page: activeState.pageSize,
keyword: activeState.search || '',
start_date: activeState.startDate || '',
end_date: activeState.endDate || ''
});
const endpoint = tableState.mode === 'history'
? `/data/log-dokumen?${params.toString()}`
: `/datatable/pending-file?${params.toString()}`;
fetch(endpoint)
.then(res => res.json())
.then(data => {
activeState.data = data?.data || [];
activeState.lastPage = data?.pagination?.last_page || 1;
activeState.total = data?.pagination?.total || 0;
renderTable();
})
.catch(err => {
console.error(err);
if (summaryEl) summaryEl.textContent = 'Gagal memuat data';
});
}
window.approvePending = function(id, fileName){
Swal.fire({
title: 'Approve dokumen?',
text: fileName || 'Dokumen akan disetujui.',
icon: 'question',
showCancelButton: true,
confirmButtonText: 'Approve',
cancelButtonText: 'Batal',
}).then((result) => {
if (!result.isConfirmed) return;
fetch(`/pending-file/${id}/approve`, {
method: 'POST',
headers: {
'X-CSRF-TOKEN': csrfToken,
'Content-Type': 'application/json'
},
}).then(async(res) => {
const data = await res.json();
if (!res.ok || !data?.status) {
throw new Error(data?.message || 'Gagal approve.');
}
Swal.fire({
icon: 'success',
title: 'Berhasil',
text: data.message || 'Dokumen disetujui.',
timer: 1500,
showConfirmButton: false
});
selectedIds.delete(String(id));
countData();
fetchData();
}).catch((err) => {
Swal.fire({
icon: 'error',
title: 'Gagal',
text: err.message || 'Terjadi kesalahan.'
});
});
});
}
window.rejectPending = function(id, fileName){
Swal.fire({
title: 'Reject dokumen?',
text: fileName || 'Dokumen akan ditolak.',
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Reject',
cancelButtonText: 'Batal',
input: 'textarea',
inputLabel: 'Catatan',
inputPlaceholder: 'Tulis alasan atau catatan revisi...',
inputAttributes: {
'aria-label': 'Catatan'
},
preConfirm: (value) => {
const revision = (value || '').trim();
if (!revision) {
Swal.showValidationMessage('Catatan revisi wajib diisi.');
}
return revision;
}
}).then((result) => {
if (!result.isConfirmed) return;
fetch(`/pending-file/${id}/reject`, {
method: 'POST',
headers: {
'X-CSRF-TOKEN': csrfToken,
'Content-Type': 'application/json'
},
body: JSON.stringify({
revision: result.value
})
}).then(async(res) => {
const data = await res.json();
if (!res.ok || !data?.status) {
throw new Error(data?.message || 'Gagal reject.');
}
Swal.fire({
icon: 'success',
title: 'Berhasil',
text: data.message || 'Dokumen ditolak.',
timer: 1500,
showConfirmButton: false
});
selectedIds.delete(String(id));
countData();
fetchData();
}).catch((err) => {
Swal.fire({
icon: 'error',
title: 'Gagal',
text: err.message || 'Terjadi kesalahan.'
});
});
});
}
window.infoDok = function(e){
let fileUrl =$(e).data('file');
let noDokumen = $(e).data('no_dokumen');
let tanggalTerbit = $(e).data('tanggal_terbit');
let permissionFile = $(e).data('permission_file');
let fileName = $(e).data('fileName');
currentFile = fileUrl;
idDirectory = $(e).data('id');
const titleEl = document.getElementById('confirm_preview_file');
if (titleEl) titleEl.textContent = fileName;
const noEl = document.getElementById('confirm-upload-dokumen');
if (noEl) noEl.textContent = noDokumen;
const tglEl = document.getElementById('confirm-time-dokumen');
if (tglEl) tglEl.textContent = tanggalTerbit;
const permEl = document.getElementById('confirm-permission');
if (permEl) {
const publicDoc = isPublic(permissionFile);
permEl.textContent = publicDoc ? 'Umum' : 'Internal Unit';
permEl.className = 'badge ' + (publicDoc ? 'bg-success' : 'bg-secondary');
}
let previewBox = document.getElementById('file-preview');
previewBox.innerHTML = ``;
openPreview(idDirectory);
$("#previewModal").modal('show');
}
if (tbodyPending) {
tbodyPending.addEventListener('change', (e) => {
const target = e.target;
if (!target.classList.contains('row-select')) return;
const id = target.getAttribute('data-id');
if (!id) return;
if (target.checked) selectedIds.add(id);
else selectedIds.delete(id);
const row = target.closest('tr');
if (row) row.classList.toggle('table-active', target.checked);
updateSelectionUI();
});
}
if (selectAllCheckbox) {
selectAllCheckbox.addEventListener('change', () => {
const selectableIds = getSelectableIdsOnPage();
if (selectableIds.length === 0) return;
if (selectAllCheckbox.checked) {
selectableIds.forEach((id) => selectedIds.add(id));
} else {
selectableIds.forEach((id) => selectedIds.delete(id));
}
renderTable();
});
}
if (clearSelectionBtn) {
clearSelectionBtn.addEventListener('click', () => {
selectedIds.clear();
renderTable();
});
}
if (bulkApproveBtn) {
bulkApproveBtn.addEventListener('click', () => {
if (selectedIds.size === 0) return;
const ids = Array.from(selectedIds);
Swal.fire({
title: 'Approve dokumen terpilih?',
text: `Total ${ids.length} dokumen akan disetujui.`,
icon: 'question',
showCancelButton: true,
confirmButtonText: 'Approve',
cancelButtonText: 'Batal',
}).then((result) => {
if (!result.isConfirmed) return;
fetch(`/pending-file/approve-multiple`, {
method: 'POST',
headers: {
'X-CSRF-TOKEN': csrfToken,
'Content-Type': 'application/json'
},
body: JSON.stringify({ ids })
}).then(async(res) => {
const data = await res.json();
if (!res.ok || !data?.status) {
throw new Error(data?.message || 'Gagal approve dokumen.');
}
ids.forEach((id) => selectedIds.delete(String(id)));
Swal.fire({
icon: 'success',
title: 'Berhasil',
text: data.message || 'Dokumen disetujui.',
timer: 1500,
showConfirmButton: false
});
countData();
fetchData();
}).catch((err) => {
Swal.fire({
icon: 'error',
title: 'Gagal',
text: err.message || 'Terjadi kesalahan.'
});
});
});
});
}
updateTabUI();
fetchData();
});
document.addEventListener('click', function(e){
if(e.target.matches('.file-link')){
e.preventDefault();
let fileUrl = e.target.getAttribute('data-file');
let noDokumen = e.target.getAttribute('data-no_dokumen');
let tanggalTerbit = e.target.getAttribute('data-tanggal_terbit');
let permissionFile = e.target.getAttribute('data-permission_file');
let fileName = e.target.getAttribute('data-fileName');
currentFile = fileUrl;
idDirectory = e.target.getAttribute('data-id');
const titleEl = document.getElementById('confirm_preview_file');
if (titleEl) titleEl.textContent = fileName;
const noEl = document.getElementById('confirm-upload-dokumen');
if (noEl) noEl.textContent = noDokumen;
const tglEl = document.getElementById('confirm-time-dokumen');
if (tglEl) tglEl.textContent = tanggalTerbit;
const permEl = document.getElementById('confirm-permission');
if (permEl) {
const publicDoc = isPublic(permissionFile);
permEl.textContent = publicDoc ? 'Umum' : 'Internal Unit';
permEl.className = 'badge ' + (publicDoc ? 'bg-success' : 'bg-secondary');
}
let previewBox = document.getElementById('file-preview');
previewBox.innerHTML = ``;
openPreview(idDirectory);
$("#previewModal").modal('show');
}
if(e.target.matches('#btn-view-full')){
window.open(`/full-preview/${idDirectory}`, '_blank');
}
});
function isPublic(permissionVal){
if(permissionVal === null || permissionVal === undefined) return false;
const val = String(permissionVal).toLowerCase();
return val === '1' || val === 'true' || val === 'iya' || val === 'yes';
}