done -> testing besok

This commit is contained in:
JokoPrasetio 2026-02-02 16:53:13 +07:00
parent fb656e6aad
commit 3739cefbdd
6 changed files with 171 additions and 56 deletions

View File

@ -203,8 +203,8 @@ class DashboardController extends Controller
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('A1', "List Dokumen");
$sheet->mergeCells('A1:F1');
$sheet->setCellValue('A1', "List Dokumen Unit");
$sheet->mergeCells('A1:I1');
$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(14);
$sheet->getStyle('A1')->getAlignment()->setHorizontal('center');
$headers = [
@ -213,11 +213,13 @@ class DashboardController extends Controller
'Kategori',
'Unit',
'Sub Unit',
'Tanggal Terbit',
'Tanggal Expired',
'Tanggal Upload',
'Pengunggah'
];
$sheet->fromArray($headers, null, 'A4');
$sheet->getStyle('A4:G4')->applyFromArray([
$sheet->getStyle('A4:I4')->applyFromArray([
'font' => ['bold' => true],
'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER],
'borders' => [
@ -226,9 +228,9 @@ class DashboardController extends Controller
]
]
]);
$sheet->getStyle('A4:G4')->getFont()->setBold(true);
$sheet->getStyle('A4:G4')->getAlignment()->setHorizontal('center');
$sheet->getStyle('A4:G4')->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
$sheet->getStyle('A4:I4')->getFont()->setBold(true);
$sheet->getStyle('A4:I4')->getAlignment()->setHorizontal('center');
$sheet->getStyle('A4:I4')->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
$rowIdx = 5;
foreach ($rows as $item) {
$parts = array_values(array_filter(explode('/', (string) $item->file)));
@ -242,6 +244,8 @@ class DashboardController extends Controller
$kategoriName,
$unitName,
$subUnitName,
$item->tanggal_terbit ? Carbon::parse($item->tanggal_terbit)->format('d/m/Y') : '-',
$item->tgl_expired ? Carbon::parse($item->tgl_expired)->format('d/m/Y') : '-',
$item->entry_at ? Carbon::parse($item->entry_at)->format('d/m/Y') : '-',
$item->pegawai_nama_entry ?? '-'
], null, "A{$rowIdx}");
@ -287,7 +291,7 @@ class DashboardController extends Controller
}
}
foreach(range('A', 'G') as $col){
foreach(range('A', 'I') as $col){
$sheet->getColumnDimension($col)->setAutoSize(true);
}
$fileName = 'data-unit-' . now()->format('Ymd-His') . '.xlsx';
@ -515,6 +519,46 @@ class DashboardController extends Controller
], 200);
}
public function OptionUnitKerjaByMapping(){
$q = request()->get('q');
$pegawaiId = auth()->user()?->dataUser?->id;
$mapping = MappingUnitKerjaPegawai::where('statusenabled', true)
->where('objectpegawaifk', $pegawaiId)
->get(['objectunitkerjapegawaifk', 'objectsubunitkerjapegawaifk']);
$unitIds = $mapping->pluck('objectunitkerjapegawaifk')->filter()->unique()->values();
$subIds = $mapping->pluck('objectsubunitkerjapegawaifk')->filter()->unique()->values();
$units = UnitKerja::where('statusenabled', true)
->when($unitIds->isNotEmpty(), fn($q2) => $q2->whereIn('id', $unitIds))
->when($q, fn($q2) => $q2->where('name', 'ILIKE', '%' . $q . '%'))
->select('id', 'name')
->get();
$subUnits = $subIds->isNotEmpty()
? SubUnitKerja::where('statusenabled', true)
->whereIn('id', $subIds)
->get(['id', 'name', 'objectunitkerjapegawaifk'])
: collect();
$subMap = $subUnits->groupBy('objectunitkerjapegawaifk')->map(function($items){
return $items->map(fn($s) => ['id' => $s->id, 'name' => $s->name])->values();
});
$data = $units->map(function($u) use ($subMap){
return [
'id' => $u->id,
'name' => $u->name,
'sub_unit_kerja' => $subMap[$u->id] ?? []
];
})->values();
return response()->json([
'status' => true,
'data' => $data
], 200);
}
public function deleteFile(string $id){
DB::connection('dbDirectory')->beginTransaction();
try {
@ -586,6 +630,27 @@ class DashboardController extends Controller
'data' => $data,
]);
}
public function optionSubUnitKerjaByMapping(string $id){
$pegawaiId = auth()->user()?->dataUser?->id;
$subIds = MappingUnitKerjaPegawai::where('statusenabled', true)
->where('objectpegawaifk', $pegawaiId)
->where('objectunitkerjapegawaifk', $id)
->pluck('objectsubunitkerjapegawaifk')
->filter()
->unique()
->values();
$data = SubUnitKerja::where('statusenabled', true)
->where('objectunitkerjapegawaifk', $id)
->when($subIds->isNotEmpty(), fn($q) => $q->whereIn('id', $subIds))
->get();
return response()->json([
'status' => true,
'data' => $data,
]);
}
public function getFile($id_unit_kerja, $id_sub_unit_kerja, $master_kategori_directory_id){
$klasifikasi = request('klasifikasi');
$klaArray = explode(',', $klasifikasi);
@ -834,26 +899,17 @@ class DashboardController extends Controller
public function downloadDataUmumExcel()
{
$user = auth()->user()?->dataUser;
$akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first();
$keyword = request('keyword');
$query = FileDirectory::where('statusenabled', true)
$rows = FileDirectory::where('statusenabled', true)
->where('status_action', 'approved')
->when($keyword, function ($q) use ($keyword) {
$q->where(function ($sub) use ($keyword) {
$sub->where('nama_dokumen', 'ILIKE', "%{$keyword}%")
->orWhere('no_dokumen', 'ILIKE', "%{$keyword}%");
});
});
if (!$akses || !$akses->all_akses) {
$query->where('permission_file', true);
}
$rows = $query->orderBy('entry_at', 'desc')->get();
->where('permission_file', true)
->orderBy('entry_at', 'desc')->get();
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('A1', "List Dokumen Umum");
$sheet->mergeCells('A1:H1');
$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(14);
$sheet->getStyle('A1')->getAlignment()->setHorizontal('center');
$headers = [
'No Dokumen',
'Nama Dokumen',
@ -861,19 +917,28 @@ class DashboardController extends Controller
'Unit',
'Sub Unit',
'Tanggal Terbit',
'Tanggal Expired',
'Tanggal Upload',
'Pengunggah',
'Akses'
];
$sheet->fromArray($headers, null, 'A1');
$rowIdx = 2;
$sheet->fromArray($headers, null, 'A4');
$sheet->getStyle('A4:H4')->applyFromArray([
'font' => ['bold' => true],
'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER],
'borders' => [
'allBorders' => [
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN
]
]
]);
$sheet->getStyle('A4:H4')->getFont()->setBold(true);
$sheet->getStyle('A4:H4')->getAlignment()->setHorizontal('center');
$sheet->getStyle('A4:H4')->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
$rowIdx = 5;
foreach ($rows as $item) {
$parts = array_values(array_filter(explode('/', (string) $item->file)));
$unitName = $parts[0] ?? '-';
$subName = $parts[1] ?? '-';
$kategoriName = $parts[2] ?? '-';
$aksesLabel = $item->permission_file ? 'Umum' : 'Internal Unit';
$sheet->fromArray([
$item->no_dokumen ?? '-',
@ -882,13 +947,14 @@ class DashboardController extends Controller
$unitName,
$subName,
$item->tanggal_terbit ? Carbon::parse($item->tanggal_terbit)->format('d/m/Y') : '-',
$item->entry_at ? Carbon::parse($item->entry_at)->format('d/m/Y H:i') : '-',
$item->pegawai_nama_entry ?? '-',
$aksesLabel
$item->tgl_expired ? Carbon::parse($item->tgl_expired)->format('d/m/Y') : '-',
$item->entry_at ? Carbon::parse($item->entry_at)->format('d/m/Y') : '-'
], null, "A{$rowIdx}");
$rowIdx++;
}
foreach(range('A', 'H') as $col){
$sheet->getColumnDimension($col)->setAutoSize(true);
}
$fileName = 'data-umum-' . now()->format('Ymd-His') . '.xlsx';
$tempPath = storage_path('app/temp');
if (!is_dir($tempPath)) {

View File

@ -102,10 +102,10 @@ document.addEventListener('DOMContentLoaded', () => {
const checked = selectedIds.has(id);
const aksi = `
<div class="d-flex gap-1">
<button class="btn btn-sm btn-success" onclick="approvePending('${item.file_directory_id}', '${item.fileName || ''}')">
<button class="btn btn-sm btn-success" onclick="approvePending('${item.file_directory_id}', '${item.nama_dokumen || ''}')">
<i class="fa-solid fa-check"></i>
</button>
<button class="btn btn-sm btn-danger" onclick="rejectPending('${item.file_directory_id}', '${item.fileName || ''}')">
<button class="btn btn-sm btn-danger" onclick="rejectPending('${item.file_directory_id}', '${item.nama_dokumen || ''}')">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
@ -123,13 +123,13 @@ document.addEventListener('DOMContentLoaded', () => {
<td>${safeText(item.no_dokumen)}</td>
<td>${statusBadge(item?.status_action)}</td>
<td>${aksesBadge(item?.permission_file)}</td>
<td><a href="#" class="file-link doc-title text-decoration-none"
<td><a href="#" class="file-link"
data-file="${item.file}"
data-fileName="${item.fileName}"
data-fileName="${item.nama_dokumen}"
data-id="${item.file_directory_id}"
data-no_dokumen="${safeText(item.no_dokumen)}"
data-tanggal_terbit="${safeText(item.tanggal_terbit)}"
data-permission_file="${safeText(item.permission_file)}"><span class="cell-wrap">${safeText(item.nama_dokumen)}</span></a></td>
data-no_dokumen="${item.no_dokumen || '-'}"
data-tanggal_terbit="${item.tanggal_terbit || '-'}"
data-permission_file="${item.permission_file || '-'}">${item.nama_dokumen}</a></td>
<td class="col-kategori"><div class="cell-wrap">${safeText(item.folder)}</div></td>
<td class="col-unit"><div class="cell-wrap">${safeText(item.part)}</div></td>
<td class="text-nowrap">${tanggalTerbit}</td>
@ -443,6 +443,7 @@ document.addEventListener('DOMContentLoaded', () => {
});
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')
@ -471,7 +472,11 @@ document.addEventListener('click', function(e){
permEl.className = 'badge ' + (publicDoc ? 'bg-success' : 'bg-secondary');
}
let previewBox = document.getElementById('file-preview');
previewBox.innerHTML = `<iframe src="/file-preview/${idDirectory}" width="100%" height="500px" style="border:none;"></iframe>`;
previewBox.innerHTML = `<div id="pdfWrap" style="height:500px; overflow:auto; background:#f7f7f7; padding:8px;">
<div id="pdfPages"></div>
</div>
`;
openPreview(idDirectory);
$("#previewModal").modal('show')
}

View File

@ -73,7 +73,7 @@ document.addEventListener('DOMContentLoaded', () => {
<td>${aksesBadge(item?.permission_file)}</td>
<td><a href="#" class="file-link"
data-file="${item.file}"
data-fileName="${item.fileName}"
data-fileName="${item.nama_dokumen}"
data-id="${item.file_directory_id}"
data-no_dokumen="${item.no_dokumen || '-'}"
data-tanggal_terbit="${item.tanggal_terbit || '-'}"
@ -225,7 +225,7 @@ document.addEventListener('DOMContentLoaded', () => {
width: '100%',
dropdownParent: $('#modalEditPengajuanFile'),
ajax: {
url: '/select-unit-kerja',
url: '/select-unit-kerja-mapping',
dataType: 'json',
delay: 250,
data: function (params) {
@ -266,7 +266,7 @@ document.addEventListener('DOMContentLoaded', () => {
editSubUnitSelect.empty().append('<option value="" disabled selected>-- Pilih Sub Unit Kerja --</option>');
if (!unitId) return;
$.ajax({
url: `/select-sub-unit-kerja/${unitId}`,
url: `/select-sub-unit-kerja-mapping/${unitId}`,
method: 'GET',
success: function(response) {
if (response?.data) {
@ -437,8 +437,12 @@ document.addEventListener('click', function(e){
permEl.textContent = publicDoc ? 'Umum' : 'Internal Unit';
permEl.className = 'badge ' + (publicDoc ? 'bg-success' : 'bg-secondary');
}
let previewBox = document.getElementById('file-preview');
previewBox.innerHTML = `<iframe src="/file-preview/${idDirectory}" width="100%" height="500px" style="border:none;"></iframe>`;
let previewBox = document.getElementById('file-preview');
previewBox.innerHTML = `<div id="pdfWrap" style="height:500px; overflow:auto; background:#f7f7f7; padding:8px;">
<div id="pdfPages"></div>
</div>
`;
openPreview(idDirectory);
$("#previewModal").modal('show')
}

View File

@ -273,6 +273,19 @@
return val === '1' || val === 'true' || val === 'iya' || val === 'yes';
}
function getExpiryStatus(dateStr){
if (!dateStr) return false;
const d = new Date(dateStr);
if (Number.isNaN(d.getTime())) return null;
const today = new Date();
today.setHours(0, 0, 0, 0);
d.setHours(0, 0, 0, 0);
if (d < today) return 'expired';
const diffDays = Math.ceil((d - today) / 86400000);
if (diffDays <= 7) return 'soon';
return null;
}
function buildRow(item){
const parts = (item.file || '').split('/');
const fileName = parts.pop() || '-';
@ -281,6 +294,7 @@
const unitName = parts[0] || '';
const subName = parts[1] || '';
const kategoriName = parts[2] || '';
const expiryStatus = getExpiryStatus(item.tgl_expired);
let statusLabel = '';
let statusClass = '';
let badge
@ -292,8 +306,12 @@
statusClass = 'bg-secondary';
}
const checked = selectedIds.has(String(item.file_directory_id)) ? 'checked' : '';
const rowClass = expiryStatus === 'expired' ? 'table-danger' : (expiryStatus === 'soon' ? 'table-warning' : '');
const expiryBadge = expiryStatus === 'expired'
? `<span class="badge bg-danger" style="font-size:10px;">Expired</span>`
: (expiryStatus === 'soon' ? `<span class="badge bg-warning text-dark" style="font-size:10px;">Akan Expired</span>` : '');
return `
<tr>
<tr class="${rowClass}">
<td class="text-center">
<input type="checkbox"
class="form-check-input row-check"
@ -328,6 +346,7 @@
>
${item.nama_dokumen || '-'}
</a>
${expiryBadge}
</div>
</div>
@ -588,7 +607,7 @@
allowClear: true,
width: '100%',
ajax: {
url : '/select-unit-kerja',
url : '/select-unit-kerja-mapping',
dataType: 'json',
delay: 250,
data: function(params){
@ -645,7 +664,7 @@
$('.sub_unit_kerja').empty().append('<option value="" disabled>-- Pilih Sub Unit Kerja --</option>');
$.ajax({
url: `/select-sub-unit-kerja/${unitId}`,
url: `/select-sub-unit-kerja-mapping/${unitId}`,
method: 'GET',
success: function(response) {
if (response?.data) {
@ -813,7 +832,7 @@
width: '100%',
dropdownParent: selectUnit.parent(),
ajax:{
url : '/select-unit-kerja',
url : '/select-unit-kerja-mapping',
dataType: 'json',
delay: 250,
data: function(params){
@ -830,7 +849,7 @@
},
cache: true,
},
minimumInputLength: 1,
minimumInputLength: 0,
});
selectSubUnit.select2({

View File

@ -216,6 +216,19 @@
return val === '1' || val === 'true' || val === 'iya' || val === 'yes';
}
function getExpiryStatus(dateStr){
if (!dateStr) return false;
const d = new Date(dateStr);
if (Number.isNaN(d.getTime())) return null;
const today = new Date();
today.setHours(0, 0, 0, 0);
d.setHours(0, 0, 0, 0);
if (d < today) return 'expired';
const diffDays = Math.ceil((d - today) / 86400000);
if (diffDays <= 7) return 'soon';
return null;
}
function buildRow(item){
const parts = (item.file || '').split('/');
const fileName = parts.pop() || '-';
@ -224,6 +237,7 @@
const unitName = parts[0] || '';
const subName = parts[1] || '';
const kategoriName = parts[2] || '';
const expiryStatus = getExpiryStatus(item.tgl_expired);
let statusLabel = '';
let statusClass = '';
@ -235,8 +249,12 @@
statusClass = 'bg-secondary';
}
const checked = selectedIds.has(String(item.file_directory_id)) ? 'checked' : '';
const rowClass = expiryStatus === 'expired' ? 'table-danger' : (expiryStatus === 'soon' ? 'table-warning' : '');
const expiryBadge = expiryStatus === 'expired'
? `<span class="badge bg-danger" style="font-size:10px;">Expired</span>`
: (expiryStatus === 'soon' ? `<span class="badge bg-warning text-dark" style="font-size:10px;">Akan Expired</span>` : '');
return `
<tr>
<tr class="${rowClass}">
<td class="text-center">
<input type="checkbox"
class="form-check-input row-check"
@ -259,6 +277,7 @@
>
${item.nama_dokumen || '-'}
</a>
${expiryBadge}
</div>
</td>
<td>
@ -517,7 +536,7 @@
allowClear: true,
width: '100%',
ajax: {
url : '/select-unit-kerja',
url : '/select-unit-kerja-mapping',
dataType: 'json',
delay: 250,
data: function(params){
@ -574,7 +593,7 @@
$('.sub_unit_kerja').empty().append('<option value="" disabled>-- Pilih Sub Unit Kerja --</option>');
$.ajax({
url: `/select-sub-unit-kerja/${unitId}`,
url: `/select-sub-unit-kerja-mapping/${unitId}`,
method: 'GET',
success: function(response) {
if (response?.data) {
@ -748,7 +767,7 @@
width: '100%',
dropdownParent: selectUnit.parent(),
ajax:{
url : '/select-unit-kerja',
url : '/select-unit-kerja-mapping',
dataType: 'json',
delay: 250,
data: function(params){
@ -765,7 +784,7 @@
},
cache: true,
},
minimumInputLength: 1,
minimumInputLength: 0,
});
selectSubUnit.select2({

View File

@ -39,7 +39,9 @@ Route::middleware(['auth'])->group(function(){
});
Route::get('/select-unit-kerja', [DashboardController::class, 'OptionUnitKerja']);
Route::get('/select-unit-kerja-mapping', [DashboardController::class, 'OptionUnitKerjaByMapping']);
Route::get('/select-sub-unit-kerja/{id}', [DashboardController::class, 'optionSubUnitKerja']);
Route::get('/select-sub-unit-kerja-mapping/{id}', [DashboardController::class, 'optionSubUnitKerjaByMapping']);
Route::delete('/delete-file/{id}', [DashboardController::class, 'deleteFile']);
Route::get('/getFile/{id_unit_kerja}/{id_sub_unit_kerja}/{master_kategori_directory_id}', [DashboardController::class, 'getFile']);