diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index f569764..073f857 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -628,7 +628,6 @@ class DashboardController extends Controller 'pegawai_id_entry' => auth()->user()->dataUser->id ?? 1, 'pegawai_nama_entry' => auth()->user()->dataUser->namalengkap ?? 'tes', ]; - dd($payload); if($file){ $imageName = $file->getClientOriginalName(); $path = "{$nama_unit_kerja}/{$nama_sub_unit_kerja}/{$nama_kategori}/{$nama_klasifikasi}"; @@ -714,85 +713,138 @@ class DashboardController extends Controller ], 200); } - public function deleteFile(string $id){ + public function deleteFile(string $id) + { DB::connection('dbDirectory')->beginTransaction(); try { - $mapping = MappingUnitKerjaPegawai::where('statusenabled', true) - ->where('objectpegawaifk', auth()->user()?->dataUser?->id) - ->first(); + $mapping = $this->getDeleteNotificationMapping(); $data = FileDirectory::where('file_directory_id', $id)->first(); - if(!$data){ + + if (!$data) { return response()->json([ 'success' => false, 'message' => 'File tidak ditemukan' - ]); - } - $fileInfo = pathinfo($data->file); - $newFileName = $fileInfo['filename'] . '_deleted.' . ($fileInfo['extension'] ?? ''); - $dirName = $fileInfo['dirname'] ?? ''; - $newPath = ($dirName && $dirName !== '.') ? ($dirName . '/' . $newFileName) : $newFileName; - $disk = Storage::disk('s3'); - if ($disk->exists($data->file)) { - // S3 tidak bisa rename langsung, jadi copy lalu delete - $disk->copy($data->file, $newPath); - $disk->delete($data->file); + ], 404); } - $data->update([ - 'statusenabled' => false, - 'file' => $newPath - ]); + $this->deleteFileRecord($data, $mapping); - $uploaderName = auth()->user()?->dataUser?->namalengkap ?? 'Pengguna'; - $docNumber = $data->no_dokumen ? 'nomor '. $data->no_dokumen : $data->nama_dokumen; - $payloadNotification = [ - 'created_at' => now(), - 'text_notifikasi' => "Dokumen {$docNumber} . dihapus oleh {$uploaderName}.", - 'url' => '/pending-file', - 'is_read' => false, - 'pegawai_id' => $mapping?->objectatasanlangsungfk, - ]; - - Notifkasi::create($payloadNotification); - if($mapping->objectpejabatpenilaifk){ - $payloadNotification = [ - 'created_at' => now(), - 'text_notifikasi' => "Dokumen {$docNumber}. dihapus oleh {$uploaderName}.", - 'url' => '/pending-file', - 'is_read' => false, - 'pegawai_id' => $mapping?->objectpejabatpenilaifk, - ]; - Notifkasi::create($payloadNotification); - } - - $payloadLog = [ - 'file_directory_id' => $data->file_directory_id, - 'pegawai_id_entry' => $data->pegawai_id_entry, - 'pegawai_nama_entry' => $data->pegawai_nama_entry, - 'entry_at' => now(), - 'file' => $data->file, - 'statusenabled' => true, - 'nama_dokumen' => $data->nama_dokumen ?? null, - 'no_dokumen' => $data->no_dokumen ?? null, - 'mod_change' => null, - 'id_unit_kerja' => $data ? $data->id_unit_kerja : null, - 'id_sub_unit_kerja' => $data ? $data->id_sub_unit_kerja : null, - 'action_type' => 'Menghapus Dokumen', - ]; - LogActivity::create($payloadLog); DB::connection('dbDirectory')->commit(); + return response()->json([ 'success' => true, 'message' => 'Berhasil menghapus data' ]); } catch (\Throwable $th) { DB::connection('dbDirectory')->rollBack(); - return response()->json([ + return response()->json([ 'success' => false, 'message' => 'Gagal menghapus data' + ], 500); + } + } + + public function deleteFiles(Request $request) + { + $ids = collect($request->input('ids', [])) + ->filter(fn ($id) => filled($id)) + ->map(fn ($id) => (string) $id) + ->unique() + ->values(); + + if ($ids->isEmpty()) { + return response()->json([ + 'success' => false, + 'message' => 'Tidak ada dokumen yang dipilih' + ], 422); + } + + DB::connection('dbDirectory')->beginTransaction(); + try { + $mapping = $this->getDeleteNotificationMapping(); + $files = FileDirectory::whereIn('file_directory_id', $ids)->get()->keyBy('file_directory_id'); + + foreach ($ids as $id) { + $data = $files->get($id); + if (!$data) { + throw new \RuntimeException("File {$id} tidak ditemukan"); + } + + $this->deleteFileRecord($data, $mapping); + } + + DB::connection('dbDirectory')->commit(); + + return response()->json([ + 'success' => true, + 'message' => 'Berhasil menghapus ' . $ids->count() . ' dokumen' + ]); + } catch (\Throwable $th) { + DB::connection('dbDirectory')->rollBack(); + return response()->json([ + 'success' => false, + 'message' => 'Gagal menghapus dokumen' + ], 500); + } + } + + private function getDeleteNotificationMapping(): ?MappingUnitKerjaPegawai + { + return MappingUnitKerjaPegawai::where('statusenabled', true) + ->where('objectpegawaifk', auth()->user()?->dataUser?->id) + ->first(); + } + + private function deleteFileRecord(FileDirectory $data, ?MappingUnitKerjaPegawai $mapping): void + { + $fileInfo = pathinfo((string) $data->file); + $extension = $fileInfo['extension'] ?? ''; + $newFileName = ($fileInfo['filename'] ?? 'dokumen') . '_deleted' . ($extension !== '' ? '.' . $extension : ''); + $dirName = $fileInfo['dirname'] ?? ''; + $newPath = ($dirName && $dirName !== '.') ? ($dirName . '/' . $newFileName) : $newFileName; + $disk = Storage::disk('s3'); + + if ($disk->exists($data->file)) { + $disk->copy($data->file, $newPath); + $disk->delete($data->file); + } + + $data->update([ + 'statusenabled' => false, + 'file' => $newPath + ]); + + $uploaderName = auth()->user()?->dataUser?->namalengkap ?? 'Pengguna'; + $docNumber = $data->no_dokumen ? 'nomor ' . $data->no_dokumen : $data->nama_dokumen; + $notifiedPegawaiIds = collect([ + $mapping?->objectatasanlangsungfk, + $mapping?->objectpejabatpenilaifk, + ])->filter()->unique(); + + foreach ($notifiedPegawaiIds as $pegawaiId) { + Notifkasi::create([ + 'created_at' => now(), + 'text_notifikasi' => "Dokumen {$docNumber}. dihapus oleh {$uploaderName}.", + 'url' => '/pending-file', + 'is_read' => false, + 'pegawai_id' => $pegawaiId, ]); } + LogActivity::create([ + 'file_directory_id' => $data->file_directory_id, + 'pegawai_id_entry' => $data->pegawai_id_entry, + 'pegawai_nama_entry' => $data->pegawai_nama_entry, + 'entry_at' => now(), + 'file' => $data->file, + 'statusenabled' => true, + 'nama_dokumen' => $data->nama_dokumen ?? null, + 'no_dokumen' => $data->no_dokumen ?? null, + 'mod_change' => null, + 'id_unit_kerja' => $data->id_unit_kerja, + 'id_sub_unit_kerja' => $data->id_sub_unit_kerja, + 'action_type' => 'Menghapus Dokumen', + ]); } public function optionSubUnitKerja(string $id){ @@ -969,68 +1021,76 @@ class DashboardController extends Controller public function downloadFile(string $id) { - $data = FileDirectory::where('file_directory_id', $id) + try { + $data = FileDirectory::where('file_directory_id', $id) ->where('statusenabled', true) ->first(); - if (!$data) { - abort(404, 'File tidak ditemukan'); - } - $disk = Storage::disk('s3'); - if (!$data->file || !$disk->exists($data->file)) { - abort(404, 'File tidak ditemukan'); - } - - $user = auth()->user()->dataUser; - if($user){ - $mapping = MappingUnitKerjaPegawai::where('statusenabled', true) - ->where('objectpegawaifk', $user->id)->where('isprimary', true) - ->first(); - LogActivity::create([ - 'file_directory_id' => $id, - 'pegawai_id_entry' => $user->id, - 'pegawai_nama_entry' => $user->namalengkap, - 'entry_at' => now(), - 'action_type' => 'Download Dokumen', - 'no_dokumen' => $data->no_dokumen, - 'file' => $data->file, - 'statusenabled' => true, - 'mod_change' => null, - 'id_unit_kerja' => $mapping ? $mapping->objectunitkerjapegawaifk : null, - 'id_sub_unit_kerja' => $mapping ? $mapping->objectsubunitkerjapegawaifk : null, - ]); - } - - - $tempDir = storage_path('app/temp'); - if (!is_dir($tempDir)) { - @mkdir($tempDir, 0777, true); - } - $ext = pathinfo((string) $data->file, PATHINFO_EXTENSION); - $ext = $ext ? strtolower($ext) : 'bin'; - $localPath = $tempDir . '/' . uniqid('s3_') . '.' . $ext; - file_put_contents($localPath, $disk->get($data->file)); - - $tempFiles = []; - $fileToSend = $this->prepareFileWithWatermark($localPath, $tempFiles); - $downloadName = basename($data->file); - - $response = response()->download($fileToSend, $downloadName); - $response->deleteFileAfterSend(true); - $cleanup = array_merge($tempFiles, [$localPath]); - $cleanup = array_values(array_unique(array_filter($cleanup))); - // cleanup after response is sent - register_shutdown_function(function () use ($cleanup, $fileToSend) { - foreach ($cleanup as $file) { - if ($file === $fileToSend) { - continue; - } - if (is_string($file) && $file !== '' && file_exists($file)) { - @unlink($file); - } + if (!$data) { + abort(404, 'File tidak ditemukan'); + } + $disk = Storage::disk('s3'); + if (!$data->file || !$disk->exists($data->file)) { + abort(404, 'File tidak ditemukan'); } - }); - return $response; + $user = auth()->user()->dataUser; + if($user){ + $mapping = MappingUnitKerjaPegawai::where('statusenabled', true) + ->where('objectpegawaifk', $user->id)->where('isprimary', true) + ->first(); + LogActivity::create([ + 'file_directory_id' => $id, + 'pegawai_id_entry' => $user->id, + 'pegawai_nama_entry' => $user->namalengkap, + 'entry_at' => now(), + 'action_type' => 'Download Dokumen', + 'no_dokumen' => $data->no_dokumen, + 'file' => $data->file, + 'statusenabled' => true, + 'mod_change' => null, + 'id_unit_kerja' => $mapping ? $mapping->objectunitkerjapegawaifk : null, + 'id_sub_unit_kerja' => $mapping ? $mapping->objectsubunitkerjapegawaifk : null, + ]); + } + + + $tempDir = storage_path('app/temp'); + if (!is_dir($tempDir)) { + @mkdir($tempDir, 0777, true); + } + $ext = pathinfo((string) $data->file, PATHINFO_EXTENSION); + $ext = $ext ? strtolower($ext) : 'bin'; + $localPath = $tempDir . '/' . uniqid('s3_') . '.' . $ext; + file_put_contents($localPath, $disk->get($data->file)); + + $tempFiles = []; + $fileToSend = $this->prepareFileWithWatermark($localPath, $tempFiles); + $downloadName = basename($data->file); + + $response = response()->download($fileToSend, $downloadName); + $response->deleteFileAfterSend(true); + $cleanup = array_merge($tempFiles, [$localPath]); + $cleanup = array_values(array_unique(array_filter($cleanup))); + // cleanup after response is sent + register_shutdown_function(function () use ($cleanup, $fileToSend) { + foreach ($cleanup as $file) { + if ($file === $fileToSend) { + continue; + } + if (is_string($file) && $file !== '' && file_exists($file)) { + @unlink($file); + } + } + }); + + return $response; + } catch (\Throwable $th) { + return back()->with([ + 'status' => false, + 'message' => 'terdapat kesalahan coba lagi nanti' + ]); + } + } public function dataUmum(){ @@ -2002,6 +2062,76 @@ class DashboardController extends Controller } } + public function recommendDeleteFile(Request $request, string $id) + { + try { + DB::connection('dbDirectory')->beginTransaction(); + $data = FileDirectory::where('file_directory_id', $id) + ->where('statusenabled', true) + ->first(); + + if (!$data) { + return response()->json([ + 'status' => false, + 'message' => 'Data tidak ditemukan' + ], 404); + } + + $note = trim((string) $request->input('note', '')); + if ($note === '') { + return response()->json([ + 'status' => false, + 'message' => 'Catatan rekomendasi wajib diisi' + ], 422); + } + + $actionName = auth()->user()?->dataUser?->namalengkap ?? 'Pengguna'; + $docNumber = $data->no_dokumen ? 'nomor ' . $data->no_dokumen : ($data->nama_dokumen ?? 'dokumen'); + + Notifkasi::create([ + 'created_at' => now(), + 'text_notifikasi' => "Dokumen {$docNumber} direkomendasikan untuk dihapus oleh {$actionName}. Catatan: {$note}", + 'url' => '/pengajuan-file', + 'is_read' => false, + 'pegawai_id' => $data->pegawai_id_entry, + ]); + + LogActivity::create([ + 'file_directory_id' => $data->file_directory_id, + 'pegawai_id_entry' => $data->pegawai_id_entry, + 'pegawai_nama_entry' => $data->pegawai_nama_entry, + 'entry_at' => now(), + 'file' => $data->file, + 'statusenabled' => true, + 'nama_dokumen' => $data->nama_dokumen ?? null, + 'no_dokumen' => $data->no_dokumen ?? null, + 'id_unit_kerja' => $data->id_unit_kerja, + 'id_sub_unit_kerja' => $data->id_sub_unit_kerja, + 'action_type' => 'Rekomendasi Hapus Dokumen', + ]); + + $data->update([ + 'hapus_turt' => true, + 'note_hapus_turt' => $note, + 'turt_by' => auth()->user()->objectpegawaifk, + 'turt_at' => now() + ]); + + DB::connection('dbDirectory')->commit(); + + return response()->json([ + 'status' => true, + 'message' => 'Rekomendasi hapus berhasil dikirim' + ], 200); + } catch (\Throwable $th) { + DB::connection('dbDirectory')->rollBack(); + return response()->json([ + 'status' => false, + 'message' => $th->getMessage() + ], 500); + } + } + public function countDataPending(){ try { $objectpegawaifk = MappingUnitKerjaPegawai::query() diff --git a/app/Http/Middleware/EnsureMasterPersetujuan.php b/app/Http/Middleware/EnsureMasterPersetujuan.php index 0bc99f1..877ab6f 100644 --- a/app/Http/Middleware/EnsureMasterPersetujuan.php +++ b/app/Http/Middleware/EnsureMasterPersetujuan.php @@ -12,7 +12,6 @@ class EnsureMasterPersetujuan { $user = $request->user(); $hasAccess = $user && $user->masterPersetujuan; - if (!$hasAccess) { abort(403, 'Tidak memiliki akses.'); } diff --git a/app/Models/SubUnitKerja.php b/app/Models/SubUnitKerja.php index f70ddc6..5f3509a 100644 --- a/app/Models/SubUnitKerja.php +++ b/app/Models/SubUnitKerja.php @@ -11,9 +11,9 @@ class SubUnitKerja extends Model public $timestamps = false; protected $primaryKey = 'id'; protected $guarded = ['id']; - protected $with = ['fileDirectory']; + // protected $with = ['fileDirectory']; - public function fileDirectory(){ - return $this->hasMany(FileDirectory::class, 'id_sub_unit_kerja', 'id')->where('statusenabled', true); - } + // public function fileDirectory(){ + // return $this->hasMany(FileDirectory::class, 'id_sub_unit_kerja', 'id')->where('statusenabled', true); + // } } diff --git a/app/Models/UnitKerja.php b/app/Models/UnitKerja.php index 3019e71..a3e1d44 100644 --- a/app/Models/UnitKerja.php +++ b/app/Models/UnitKerja.php @@ -11,10 +11,10 @@ class UnitKerja extends Model public $timestamps = false; protected $primaryKey = 'id'; protected $guarded = ['id']; - protected $with = ['subUnitKerja']; + // protected $with = ['subUnitKerja']; - public function subUnitKerja(){ - return $this->hasMany(SubUnitKerja::class, 'objectunitkerjapegawaifk', 'id')->where('statusenabled', true)->select('id', 'objectunitkerjapegawaifk', 'name'); - } + // public function subUnitKerja(){ + // return $this->hasMany(SubUnitKerja::class, 'objectunitkerjapegawaifk', 'id')->where('statusenabled', true)->select('id', 'objectunitkerjapegawaifk', 'name'); + // } } diff --git a/public/js/pengajuanFile/index.js b/public/js/pengajuanFile/index.js index bb095c5..eb22d4a 100644 --- a/public/js/pengajuanFile/index.js +++ b/public/js/pengajuanFile/index.js @@ -13,6 +13,12 @@ document.addEventListener('DOMContentLoaded', () => { const titleEl = document.getElementById('pengajuanTitle'); const tabPengajuanEl = document.getElementById('tabPengajuan'); const tabHistoryEl = document.getElementById('tabHistory'); + const selectAllCheckbox = document.getElementById('selectAllPengajuan'); + const bulkDeleteBtn = document.getElementById('bulkDeleteBtn'); + const clearSelectionBtn = document.getElementById('clearSelectionBtn'); + const selectedCountEl = document.getElementById('selectedCount'); + const bulkActionsEl = document.getElementById('pengajuanBulkActions'); + const deleteDataEl = document.getElementById('deleteData'); const formCreate = document.getElementById('formFile'); const modalCreate = document.getElementById('modalCreateFile'); let colCount = 1; @@ -20,6 +26,7 @@ document.addEventListener('DOMContentLoaded', () => { const editForm = document.getElementById('formEditPengajuanFile'); const editUnitSelect = $('#edit_id_unit_kerja'); const editSubUnitSelect = $('#edit_id_sub_unit_kerja'); + const selectedIds = new Set(); if (pageSizeSelect) { const initialSize = parseInt(pageSizeSelect.value); @@ -61,6 +68,41 @@ document.addEventListener('DOMContentLoaded', () => { }); } + function getSelectableIdsOnPage(){ + return (tableState.data || []).map((row) => String(row.file_directory_id)); + } + + function updateSelectAllState(){ + if (!selectAllCheckbox) return; + if (tableState.mode === 'history') { + selectAllCheckbox.checked = false; + selectAllCheckbox.indeterminate = false; + selectAllCheckbox.disabled = true; + return; + } + + const pageIds = getSelectableIdsOnPage(); + if (pageIds.length === 0) { + selectAllCheckbox.checked = false; + selectAllCheckbox.indeterminate = false; + selectAllCheckbox.disabled = true; + return; + } + + selectAllCheckbox.disabled = false; + const selectedOnPage = pageIds.filter((id) => selectedIds.has(id)).length; + selectAllCheckbox.checked = selectedOnPage > 0 && selectedOnPage === pageIds.length; + selectAllCheckbox.indeterminate = selectedOnPage > 0 && selectedOnPage < pageIds.length; + } + + function updateSelectionUI(){ + const count = selectedIds.size; + if (selectedCountEl) selectedCountEl.textContent = String(count); + if (bulkDeleteBtn) bulkDeleteBtn.disabled = count === 0 || tableState.mode === 'history'; + if (clearSelectionBtn) clearSelectionBtn.disabled = count === 0 || tableState.mode === 'history'; + updateSelectAllState(); + } + function buildRow(item){ let tanggal = item.entry_at ? formatTanggal(item.entry_at) : '-'; let tanggalExp = item.tgl_expired ? formatTanggal(item.tgl_expired) : '-'; @@ -69,6 +111,8 @@ document.addEventListener('DOMContentLoaded', () => { const isRejected = item?.status_action === 'rejected'; const showEdit = !isApproved; const showInfo = isRejected; + const id = String(item.file_directory_id); + const checked = selectedIds.has(id); const aksi = `
`; return ` - + + + + ${aksi} ${item.no_dokumen || '-'} @@ -168,6 +218,41 @@ document.addEventListener('DOMContentLoaded', () => { return (tableState.data || []).find((row) => String(row.file_directory_id) === String(id)); } + function deleteDocuments(ids, successMessage){ + return fetch('/delete-file/bulk', { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + 'X-CSRF-TOKEN': csrfToken + }, + body: JSON.stringify({ ids }) + }).then(async(res) => { + const data = await res.json(); + if (!res.ok || !data?.success) { + throw new Error(data?.message || 'Gagal menghapus dokumen.'); + } + + ids.forEach((id) => selectedIds.delete(String(id))); + if (window.idDirectory && ids.includes(String(window.idDirectory))) { + window.idDirectory = null; + window.currentFile = null; + if (deleteDataEl) deleteDataEl.classList.add('d-none'); + const modalEl = document.getElementById('previewModal'); + const modalInstance = modalEl ? bootstrap.Modal.getInstance(modalEl) : null; + modalInstance?.hide(); + } + + Swal.fire({ + icon: 'success', + title: 'Berhasil', + text: data.message || successMessage, + timer: 1500, + showConfirmButton: false + }); + fetchData(); + }); + } + function renderPagination(totalPages){ const activeState = tableState.mode === 'history' ? historyState : tableState; const paginationEl = tableState.mode === 'history' ? paginationHistory : paginationPengajuan; @@ -218,7 +303,7 @@ document.addEventListener('DOMContentLoaded', () => { const activeState = isHistoryMode ? historyState : tableState; const pageData = activeState.data || []; const targetBody = isHistoryMode ? tbodyHistory : tbodyPengajuan; - const colSpan = isHistoryMode ? 9 : 10; + const colSpan = isHistoryMode ? 9 : 11; const rowBuilder = isHistoryMode ? buildHistoryRow : buildRow; if (pageData.length === 0) { targetBody.innerHTML = ` @@ -239,6 +324,7 @@ document.addEventListener('DOMContentLoaded', () => { } renderPagination(activeState.lastPage || 1); + updateSelectionUI(); } let searchDebounce; @@ -264,6 +350,7 @@ document.addEventListener('DOMContentLoaded', () => { document.getElementById('tableSearch').value = ''; startDateInput.value = ''; endDateInput.value = ''; + selectedIds.clear(); tableState.page = 1; historyState.page = 1; fetchData(); @@ -278,10 +365,18 @@ document.addEventListener('DOMContentLoaded', () => { if (titleEl) { titleEl.textContent = tableState.mode === 'history' ? 'Log History' : 'Data Pengajuan'; } + document.body.dataset.pengajuanMode = tableState.mode; if (tabPengajuanEl && tabHistoryEl) { tabPengajuanEl.classList.toggle('d-none', tableState.mode === 'history'); tabHistoryEl.classList.toggle('d-none', tableState.mode !== 'history'); } + if (bulkActionsEl) { + bulkActionsEl.classList.toggle('d-none', tableState.mode === 'history'); + } + if (deleteDataEl && tableState.mode === 'history') { + deleteDataEl.classList.add('d-none'); + } + updateSelectionUI(); } if (tabsEl) { @@ -297,6 +392,63 @@ document.addEventListener('DOMContentLoaded', () => { }); } + if (tbodyPengajuan) { + tbodyPengajuan.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 pageIds = getSelectableIdsOnPage(); + if (selectAllCheckbox.checked) { + pageIds.forEach((id) => selectedIds.add(id)); + } else { + pageIds.forEach((id) => selectedIds.delete(id)); + } + renderTable(); + }); + } + + if (clearSelectionBtn) { + clearSelectionBtn.addEventListener('click', () => { + selectedIds.clear(); + renderTable(); + }); + } + + if (bulkDeleteBtn) { + bulkDeleteBtn.addEventListener('click', () => { + if (selectedIds.size === 0) return; + const ids = Array.from(selectedIds); + Swal.fire({ + title: 'Hapus dokumen terpilih?', + text: `Total ${ids.length} dokumen akan dihapus.`, + icon: 'warning', + showCancelButton: true, + confirmButtonText: 'Hapus', + cancelButtonText: 'Batal' + }).then((result) => { + if (!result.isConfirmed) return; + deleteDocuments(ids, 'Dokumen berhasil dihapus.').catch((err) => { + Swal.fire({ + icon: 'error', + title: 'Gagal', + text: err.message || 'Terjadi kesalahan.' + }); + }); + }); + }); + } + function fetchData(){ if (summaryEl) summaryEl.textContent = 'Memuat data...'; const activeState = tableState.mode === 'history' ? historyState : tableState; @@ -360,6 +512,9 @@ document.addEventListener('DOMContentLoaded', () => { permEl.textContent = publicDoc ? 'Umum' : 'Internal Unit'; permEl.className = 'badge ' + (publicDoc ? 'bg-success' : 'bg-secondary'); } + if (deleteDataEl) { + deleteDataEl.classList.remove('d-none'); + } let previewBox = document.getElementById('file-preview'); previewBox.innerHTML = `
`; @@ -1076,6 +1231,7 @@ document.addEventListener('DOMContentLoaded', () => { return; } }); + }); document.addEventListener('click', function(e){ if(e.target.matches('.file-link')){ @@ -1105,6 +1261,10 @@ document.addEventListener('click', function(e){ const publicDoc = isPublic(permissionFile); permEl.textContent = publicDoc ? 'Umum' : 'Internal Unit'; permEl.className = 'badge ' + (publicDoc ? 'bg-success' : 'bg-secondary'); + } + const deleteDataEl = document.getElementById('deleteData'); + if (deleteDataEl) { + deleteDataEl.classList.toggle('d-none', document.body.dataset.pengajuanMode !== 'pengajuan'); } let previewBox = document.getElementById('file-preview'); previewBox.innerHTML = `
@@ -1119,6 +1279,56 @@ document.addEventListener('click', function(e){ if(e.target.matches('#btn-view-full')){ window.open(`/full-preview/${idDirectory}`, '_blank'); } + + if(e.target.matches('#delete-file')){ + if(!idDirectory){ + Swal.fire({ + icon: 'warning', + title: 'Pilih dokumen', + text: 'Dokumen belum dipilih.' + }); + return; + } + + Swal.fire({ + title: 'Hapus dokumen ini?', + text: 'Dokumen yang dihapus tidak akan tampil lagi.', + icon: 'warning', + showCancelButton: true, + confirmButtonText: 'Hapus', + cancelButtonText: 'Batal' + }).then((result) => { + if (!result.isConfirmed) return; + fetch('/delete-file/bulk', { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '' + }, + body: JSON.stringify({ ids: [String(idDirectory)] }) + }).then(async(res) => { + const data = await res.json(); + if (!res.ok || !data?.success) { + throw new Error(data?.message || 'Gagal menghapus dokumen.'); + } + Swal.fire({ + icon: 'success', + title: 'Berhasil', + text: data.message || 'Dokumen berhasil dihapus.', + timer: 1500, + showConfirmButton: false + }).then(() => { + window.location.reload(); + }); + }).catch((err) => { + Swal.fire({ + icon: 'error', + title: 'Gagal', + text: err.message || 'Terjadi kesalahan.' + }); + }); + }); + } }) function isPublic(permissionVal){ if(permissionVal === null || permissionVal === undefined) return false; diff --git a/resources/views/dataUmum/index.blade.php b/resources/views/dataUmum/index.blade.php index cffe564..cd876fe 100644 --- a/resources/views/dataUmum/index.blade.php +++ b/resources/views/dataUmum/index.blade.php @@ -226,7 +226,8 @@ @endsection diff --git a/resources/views/dataUnit/index.blade.php b/resources/views/dataUnit/index.blade.php index 863afbc..d67e6c4 100644 --- a/resources/views/dataUnit/index.blade.php +++ b/resources/views/dataUnit/index.blade.php @@ -308,7 +308,7 @@ cache: true } }); - + } if (kategoriSelect) { $('#tableKategori').select2({ @@ -607,6 +607,23 @@ > + ${authUnitKerja.id === 22 ? ` + + ` : ''} +
${item.no_dokumen || '-'} @@ -1020,6 +1037,8 @@ url: `/select-sub-unit-kerja-mapping/${unitId}`, method: 'GET', success: function(response) { + console.log(response); + if (response?.data) { response.data.forEach(unit => { let selected = (authSubUnitKerja && unit.id === authSubUnitKerja.objectsubunitkerjapegawaifk); @@ -1228,7 +1247,7 @@ processResults: function(data){ return { results : data?.data.map(item => ({ - id: item.id+'/'+item.name, + id: item.id, text: item.name, sub_units: item.sub_unit_kerja // kirim ke front })) @@ -1482,5 +1501,67 @@ } $("#previewModal").modal('show') } + + function rekomendasiDelete(button){ + const id = $(button).data('id'); + const fileName = $(button).data('filename') || 'dokumen'; + const noDokumen = $(button).data('no_dokumen') || '-'; + + Swal.fire({ + title: 'Rekomendasi hapus dokumen?', + text: `${fileName} (${noDokumen})`, + icon: 'warning', + input: 'textarea', + inputLabel: 'Catatan rekomendasi', + inputPlaceholder: 'Tulis alasan kenapa dokumen ini direkomendasikan untuk dihapus...', + inputAttributes: { + 'aria-label': 'Catatan rekomendasi' + }, + showCancelButton: true, + confirmButtonText: 'Kirim rekomendasi', + cancelButtonText: 'Batal', + preConfirm: (value) => { + const note = (value || '').trim(); + if (!note) { + Swal.showValidationMessage('Catatan rekomendasi wajib diisi.'); + } + return note; + } + }).then((result) => { + if (!result.isConfirmed) return; + + fetch(`/recommend-delete-file/${id}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content + }, + body: JSON.stringify({ + note: result.value + }) + }) + .then(res => res.json()) + .then(data => { + if (data.status) { + Swal.fire({ + icon: 'success', + title: 'Berhasil', + text: data.message || 'Rekomendasi hapus berhasil dikirim.', + timer: 1800, + showConfirmButton: false + }); + } else { + throw new Error(data.message || 'Gagal mengirim rekomendasi hapus.'); + } + }) + .catch(err => { + Swal.fire({ + icon: 'error', + title: 'Gagal', + text: err.message || 'Terjadi kesalahan.' + }); + }); + }); + } @endsection diff --git a/resources/views/layout/partials/sidenav.blade.php b/resources/views/layout/partials/sidenav.blade.php index 0aaeebb..bed5a92 100644 --- a/resources/views/layout/partials/sidenav.blade.php +++ b/resources/views/layout/partials/sidenav.blade.php @@ -114,7 +114,7 @@ @if(!Auth::guard('admin')->check()) - @if(auth()->user()->dataUser->mappingUnitKerjaPegawai()->where('objectunitkerjapegawaifk', 43)->exists()) + @if(auth()->user()->dataUser->mappingUnitKerjaPegawai()->whereIn('objectunitkerjapegawaifk', [43, 22])->exists())