done -> add aws save file

This commit is contained in:
JokoPrasetio 2026-02-03 11:40:21 +07:00
parent 3739cefbdd
commit a3fe338530
10 changed files with 334 additions and 208 deletions

View File

@ -154,9 +154,23 @@ class DashboardController extends Controller
->values()
->all();
$keyword = request('keyword');
$kategori = request('kategori');
$unitFilter = request('unit');
$kategoriIds = is_array($kategori)
? array_values(array_filter($kategori))
: array_values(array_filter(explode(',', (string) $kategori)));
$unitFilterIds = is_array($unitFilter)
? array_values(array_filter($unitFilter))
: array_values(array_filter(explode(',', (string) $unitFilter)));
if (!empty($unitFilterIds)) {
$unitIds = array_values(array_intersect($unitIds, $unitFilterIds));
}
$query = FileDirectory::where('statusenabled', true)
->where('status_action', 'approved')
->whereIn('id_unit_kerja', $unitIds)
->when(!empty($kategoriIds), function ($q) use ($kategoriIds) {
$q->whereIn('master_kategori_directory_id', $kategoriIds);
})
->when($keyword, function ($q) use ($keyword) {
$q->where(function ($sub) use ($keyword) {
$sub->where('nama_dokumen', 'ILIKE', "%{$keyword}%")
@ -274,6 +288,7 @@ class DashboardController extends Controller
]);
$rowIdx++;
$grandTotal = 0;
foreach ($recapData as $recap) {
$unitName = $recap['unit'] ?? '-';
$folders = $recap['data'] ?? [];
@ -281,6 +296,7 @@ class DashboardController extends Controller
foreach ($folders as $folderItem) {
$sheet->setCellValue("F{$rowIdx}", $folderItem['folder'] ?? '-');
$sheet->setCellValue("G{$rowIdx}", $folderItem['count'] ?? 0);
$grandTotal += (int) ($folderItem['count'] ?? 0);
$rowIdx++;
}
$unitEndRow = max($unitStartRow, $rowIdx - 1);
@ -289,6 +305,16 @@ class DashboardController extends Controller
$sheet->mergeCells("E{$unitStartRow}:E{$unitEndRow}");
}
}
$sheet->setCellValue("F{$rowIdx}", 'Total File');
$sheet->setCellValue("G{$rowIdx}", $grandTotal);
$sheet->getStyle("F{$rowIdx}:G{$rowIdx}")->applyFromArray([
'font' => ['bold' => true],
'borders' => [
'allBorders' => [
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN
]
]
]);
}
foreach(range('A', 'I') as $col){
@ -828,12 +854,14 @@ class DashboardController extends Controller
public function dataUmum(){
$katDok = MasterKategori::where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get();
$unitKerja = UnitKerja::where('statusenabled', true)->select('id', 'name')->orderBy('name')->get();
$authMapping = auth()->user()?->dataUser?->mappingUnitKerjaPegawai[0];
$authUnitKerja = $authMapping->objectunitkerjapegawaifk;
$authSubUnitKerja = $authMapping->objectsubunitkerjapegawaifk;
$data = [
'title' => 'Dashboard',
'katDok' => $katDok,
'unitKerja' => $unitKerja,
'authUnitKerja' => $authUnitKerja,
'authSubUnitKerja' => $authSubUnitKerja,
];
@ -847,6 +875,14 @@ class DashboardController extends Controller
// $entryPegawaiId = auth()->user()?->objectpegawaifk;
$akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first();
$keyword = request('keyword');
$unitId = request('unit');
$kategori = request('kategori');
$unitIds = is_array($unitId)
? array_values(array_filter($unitId))
: array_values(array_filter(explode(',', (string) $unitId)));
$kategoriIds = is_array($kategori)
? array_values(array_filter($kategori))
: array_values(array_filter(explode(',', (string) $kategori)));
$mapping = MappingUnitKerjaPegawai::where('statusenabled', true)
->where('objectpegawaifk', $user->id)
->get(['objectunitkerjapegawaifk', 'objectsubunitkerjapegawaifk']);
@ -863,6 +899,12 @@ class DashboardController extends Controller
// ->values()
// ->all();
$query = FileDirectory::where('statusenabled', true)->where('status_action', 'approved')
->when(!empty($unitIds), function ($q) use ($unitIds) {
$q->whereIn('id_unit_kerja', $unitIds);
})
->when(!empty($kategoriIds), function ($q) use ($kategoriIds) {
$q->whereIn('master_kategori_directory_id', $kategoriIds);
})
->when($keyword, function ($q) use ($keyword) {
$q->where(function ($sub) use ($keyword) {
$sub->where('nama_dokumen', 'ILIKE', "%{$keyword}%")
@ -970,6 +1012,7 @@ class DashboardController extends Controller
DB::connection('dbDirectory')->beginTransaction();
try {
$datas = request('data');
$maxUploadBytes = 10 * 1024 * 1024;
$mapping = MappingUnitKerjaPegawai::where('statusenabled', true)
->where('objectpegawaifk', auth()->user()?->dataUser?->id)
->first();
@ -986,15 +1029,13 @@ class DashboardController extends Controller
if(!$uploadedFile){
throw new \RuntimeException('File wajib diunggah pada baris ke-' . ($index+1));
}
// if(auth()->user()->masterPersetujuan){
// $unitPegawaiIds = auth()->user()->masterPersetujuan->details->pluck('unit_pegawai_id')->unique()->toArray();
// $status = in_array($id_unit_kerja, $unitPegawaiIds)
// ? 'approved'
// : null;
if (!$uploadedFile->isValid()) {
throw new \RuntimeException('Upload file gagal pada baris ke-' . ($index+1));
}
if ($uploadedFile->getSize() > $maxUploadBytes) {
throw new \RuntimeException('Ukuran file maksimal 10MB pada baris ke-' . ($index+1));
}
$status = $isAtasan ? 'approved' : null;
// }
$payload = [
'id_unit_kerja' => $id_unit_kerja,
@ -1011,9 +1052,15 @@ class DashboardController extends Controller
'action_by' => $status && $status === "approved" ? auth()->user()->objectpegawaifk : null,
'action_at' => $status && $status === "approved" ? now() : null
];
$imageName = $uploadedFile->getClientOriginalName();
$imageName = trim((string) $uploadedFile->getClientOriginalName());
if ($imageName === '') {
$ext = $uploadedFile->getClientOriginalExtension();
$imageName = $ext ? (Str::uuid()->toString() . '.' . $ext) : Str::uuid()->toString();
}
$path = "{$nama_unit_kerja}/{$nama_sub_unit_kerja}/{$nama_kategori}";
$uploadedFile->storeAs($path, $imageName, 'file_directory');
$disk = Storage::disk('file_directory');
$disk->makeDirectory($path);
$disk->putFileAs($path, $uploadedFile, $imageName);
$payload['file'] =$path .'/' .$imageName;
$fd = FileDirectory::create($payload);

View File

@ -267,7 +267,7 @@ function addForm(){
</div>
<div class="form-text text-muted">
Format yang didukung: <b>PDF</b>.
Format yang didukung: <b>PDF</b> Maksimal <b>10mb</b>.
</div>
</div>

View File

@ -73,7 +73,7 @@
<div class="mt-2 text-success fw-semibold d-none file-name"></div>
</div>
<div class="form-text text-muted">
Format yang didukung: <b>PDF</b>.
Format yang didukung: <b>PDF</b> Maksimal <b>10mb</b>.
</div>
</div>
<div id="col_add_file" class="col-12"></div>

View File

@ -7,7 +7,7 @@
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2">
<div>
<h4 class="mb-0">Rekap Dokumen</h4>
<small class="text-muted">Ringkasan jumlah file per Unit dan Folder</small>
<small class="text-muted">Ringkasan jumlah file per Unit dan Kategori</small>
</div>
</div>
</div>

View File

@ -1,118 +1,42 @@
@extends('layout.main')
<style>
.file-cell {
max-width: 420px;
/* --- SELECT2: teks terlihat (hitam) --- */
.select2-container--default .select2-selection--multiple {
background: #fff !important;
border: 1px solid #ced4da !important;
min-height: 31px; /* cocok form-select-sm */
}
.file-wrapper {
display: flex;
flex-direction: column;
gap: 2px;
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
color: #111 !important;
}
.file-title {
display: flex;
align-items: center;
gap: 6px;
font-weight: 600;
color: #1f2937;
.select2-container--default .select2-search--inline .select2-search__field {
color: #111 !important;
}
.file-title i {
font-size: 18px;
color: #6366f1;
.select2-container--default .select2-dropdown {
background: #fff !important;
border: 1px solid #ced4da !important;
}
.file-link {
color: #1f2937;
text-decoration: none;
line-height: 1.3;
.select2-container--default .select2-results__option {
color: #111 !important;
}
.file-link:hover {
color: #4f46e5;
text-decoration: underline;
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: #e9ecef !important;
color: #111 !important;
}
.file-meta {
font-size: 12px;
color: #6b7280;
/* tag chip */
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #f1f3f5 !important;
border: 1px solid #dee2e6 !important;
color: #111 !important;
}
.file-meta span {
margin-right: 4px;
}
/* status pending */
.file-pending {
font-style: italic;
color: #9ca3af !important;
}
.dataunit-tabs .nav-link {
border: 0;
color: #475569;
font-weight: 600;
padding: 0.6rem 1rem;
border-radius: 999px;
transition: background-color .15s ease, color .15s ease, box-shadow .15s ease;
position: relative;
overflow: hidden;
}
.dataunit-tabs .nav-link.active {
background: color-mix(in srgb, var(--bs-primary) 12%, #ffffff);
color: var(--bs-primary);
+}
.dataunit-tabs .nav-link:hover {
color: var(--bs-primary);
background: color-mix(in srgb, var(--bs-primary) 8%, #ffffff);
}
.dataunit-tabs .nav-link::after {
content: "";
position: absolute;
left: 18px;
right: 18px;
bottom: 6px;
height: 2px;
border-radius: 999px;
background: var(--bs-primary);
transform: scaleX(0);
transform-origin: center;
transition: transform .18s ease;
opacity: 0;
}
.dataunit-tabs .nav-link:hover::after {
transform: scaleX(1);
opacity: 0.7;
}
.dataunit-tab-wrap {
background: #f8fafc;
border-radius: 999px;
padding: 6px;
display: flex;
gap: 6px;
width: 100%;
}
.dataunit-tabs {
width: 100%;
}
.dataunit-tabs .nav-item {
flex: 1 1 0;
}
.dataunit-tabs .nav-link {
width: 100%;
justify-content: center;
}
</style>
@section('body_main')
<div class="row">
<div class="col-md-12">
@ -162,26 +86,25 @@
</div>
</div>
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 mb-3">
<div class="input-group input-group-sm flex-grow-1">
<span class="input-group-text bg-white border-end-0">
<i class="fa fa-search text-muted"></i>
</span>
<input type="search"
id="tableSearch"
class="form-control border-start-0"
placeholder="Cari nama file, No Dokumen atau folder"
oninput="debouncedTableSearch(this.value)">
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 flex-grow-1">
<select id="tableUnit" class="form-select form-select-sm unit_kerja_filter" style="max-width: 260px;" multiple></select>
<select id="tableKategori" class="form-select form-select-sm kategori_kerja_filter" style="max-width: 260px;" multiple>
@foreach ($katDok as $kat)
<option value="{{ $kat->master_kategori_directory_id }}">
{{ $kat->nama_kategori_directory }}
</option>
@endforeach
</select>
<input type="search"
id="tableSearch"
class="form-control"
placeholder="Cari nama dokumen atau No Dokumen"
autocomplete="off">
<button class="btn btn-outline-secondary" type="button" id="btnTableSearch">Cari</button>
</div>
<div class="d-flex align-items-center gap-2">
<select id="tablePageSize" class="form-select form-select-sm" style="width: auto;">
<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>
</div>
<div class="small text-muted ms-md-auto" id="tableSummary">Memuat data...</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">
@ -202,7 +125,26 @@
</tbody>
</table>
</div>
<div class="d-flex flex-column flex-md-row align-items-md-center justify-content-between gap-2 mt-3" id="paginationControls"></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>
@ -220,11 +162,15 @@
const authPegawai = @json(auth()->user()->objectpegawaifk);
const formCreate = $("#formFile")
const modalCreate = document.getElementById('modalCreateFile')
const tableState = { data: [], page: 1, pageSize: 8, search: '', lastPage: 1, total: 0 };
const tableState = { data: [], page: 1, pageSize: 8, search: '', unit: [], kategori: [], lastPage: 1, total: 0 };
const tbody = document.getElementById('tableDataUmum');
const paginationEl = document.getElementById('paginationControls');
const summaryEl = document.getElementById('tableSummary');
const pageSizeSelect = document.getElementById('tablePageSize');
const unitSelect = document.getElementById('tableUnit');
const kategoriSelect = document.getElementById('tableKategori');
const searchInput = document.getElementById('tableSearch');
const searchBtn = document.getElementById('btnTableSearch');
const downloadBtn = document.getElementById('btnDownloadMultiple');
const selectedCountEl = document.getElementById('selectedCount');
const checkAllEl = document.getElementById('checkAllRows');
@ -257,6 +203,47 @@
}
});
}
if (window.$ && $.fn.select2) {
if (unitSelect) {
$('#tableUnit').select2({
placeholder: 'Pilih Unit',
allowClear: true,
width: '100%',
closeOnSelect: false,
ajax: {
url: '/select-unit-kerja-option',
dataType: 'json',
delay: 250,
data: function (params) {
return { q: params.term };
},
processResults: function (data) {
return {
results: (data?.data || []).map(item => ({
id: item.id,
text: item.name
}))
};
},
cache: true
}
});
$('#tableUnit').on('change', function () {
tableState.unit = $(this).val() || [];
});
}
if (kategoriSelect) {
$('#tableKategori').select2({
placeholder: 'Pilih Kategori',
allowClear: true,
width: '100%',
closeOnSelect: false
});
$('#tableKategori').on('change', function () {
tableState.kategori = $(this).val() || [];
});
}
}
function resetCreateForm(){
colCount = 1;
@ -432,13 +419,13 @@
updateSelectedCount();
}
function debouncedTableSearch(value){
clearTimeout(window.tableSearchTimer);
window.tableSearchTimer = setTimeout(() => {
tableState.search = value.trim();
tableState.page = 1;
fetchData();
}, 250);
function applyTableSearch(){
const value = searchInput ? searchInput.value : '';
tableState.search = (value || '').trim();
tableState.unit = unitSelect && window.$ ? ($('#tableUnit').val() || []) : (tableState.unit || []);
tableState.kategori = kategoriSelect && window.$ ? ($('#tableKategori').val() || []) : (tableState.kategori || []);
tableState.page = 1;
fetchData();
}
function fetchData(){
@ -448,6 +435,12 @@
per_page: tableState.pageSize,
keyword: tableState.search
});
if (tableState.unit && tableState.unit.length > 0) {
tableState.unit.forEach(id => params.append('unit[]', id));
}
if (tableState.kategori && tableState.kategori.length > 0) {
tableState.kategori.forEach(kat => params.append('kategori[]', kat));
}
fetch(`/datatable-umum?${params.toString()}`)
.then(response => response.json())
.then(data => {
@ -462,6 +455,18 @@
})
}
if (searchBtn) {
searchBtn.addEventListener('click', applyTableSearch);
}
if (searchInput) {
searchInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
e.preventDefault();
applyTableSearch();
}
});
}
function formatTanggal(dateString) {
const d = new Date(dateString);

View File

@ -96,7 +96,7 @@
<div class="mt-2 text-success fw-semibold d-none file-name"></div>
</div>
<div class="form-text text-muted">
Format yang didukung: <b>PDF</b>.
Format yang didukung: <b>PDF</b> Maksimal <b>10mb</b>.
</div>
</div>
<div id="col_add_fileV2" class="col-12"></div>

View File

@ -1,54 +1,40 @@
@extends('layout.main')
<style>
.file-cell {
max-width: 420px;
/* --- SELECT2: teks terlihat (hitam) --- */
.select2-container--default .select2-selection--multiple {
background: #fff !important;
border: 1px solid #ced4da !important;
min-height: 31px; /* cocok form-select-sm */
}
.file-wrapper {
display: flex;
flex-direction: column;
gap: 2px;
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
color: #111 !important;
}
.file-title {
display: flex;
align-items: center;
gap: 6px;
font-weight: 600;
color: #1f2937;
.select2-container--default .select2-search--inline .select2-search__field {
color: #111 !important;
}
.file-title i {
font-size: 18px;
color: #6366f1;
.select2-container--default .select2-dropdown {
background: #fff !important;
border: 1px solid #ced4da !important;
}
.file-link {
color: #1f2937;
text-decoration: none;
line-height: 1.3;
.select2-container--default .select2-results__option {
color: #111 !important;
}
.file-link:hover {
color: #4f46e5;
text-decoration: underline;
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: #e9ecef !important;
color: #111 !important;
}
.file-meta {
font-size: 12px;
color: #6b7280;
/* tag chip */
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #f1f3f5 !important;
border: 1px solid #dee2e6 !important;
color: #111 !important;
}
.file-meta span {
margin-right: 4px;
}
/* status pending */
.file-pending {
font-style: italic;
color: #9ca3af !important;
}
</style>
@section('body_main')
<div class="row">
@ -98,27 +84,22 @@
</div>
</div>
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 mb-3">
<div class="input-group input-group-sm flex-grow-1">
<span class="input-group-text bg-white border-end-0">
<i class="fa fa-search text-muted"></i>
</span>
<input type="search"
id="tableSearch"
class="form-control border-start-0"
placeholder="Cari nama file, No Dokumen atau folder"
oninput="debouncedTableSearch(this.value)">
</div>
<div class="d-flex align-items-center gap-2">
<select id="tablePageSize" class="form-select form-select-sm" style="width: auto;">
<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>
<div class="d-flex flex-column flex-md-row align-items-md-center gap-2 flex-grow-1">
<select id="tableUnit" class="form-select form-select-sm unit_kerja_filter" style="max-width: 260px;" multiple></select>
<select id="tableKategori" class="form-select form-select-sm kategori_kerja_filter" style="max-width: 260px;" multiple>
@foreach ($katDok as $kat)
<option value="{{ $kat->master_kategori_directory_id }}">
{{ $kat->nama_kategori_directory }}
</option>
@endforeach
</select>
</div>
<div class="small text-muted ms-md-auto" id="tableSummary">Memuat data...</div>
<input type="search"
id="tableSearch"
class="form-control"
placeholder="Cari nama dokumen atau No Dokumen"
autocomplete="off">
</div>
<button class="btn btn-primary" type="button" id="btnTableSearch">Cari</button>
</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">
@ -140,6 +121,25 @@
</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 class="d-flex flex-column flex-md-row align-items-md-center justify-content-between gap-2 mt-3" id="paginationControls"></div>
<hr class="my-4">
@ -163,11 +163,15 @@
const authPegawai = @json(auth()->user()->objectpegawaifk);
const formCreate = $("#formFile");
const modalCreate = document.getElementById('modalCreateFile');
const tableState = { data: [], page: 1, pageSize: 8, search: '', lastPage: 1, total: 0 };
const tableState = { data: [], page: 1, pageSize: 8, search: '', unit: [], kategori: [], lastPage: 1, total: 0 };
const tbody = document.getElementById('tableDataUnit');
const paginationEl = document.getElementById('paginationControls');
const summaryEl = document.getElementById('tableSummary');
const pageSizeSelect = document.getElementById('tablePageSize');
const unitSelect = document.getElementById('tableUnit');
const kategoriSelect = document.getElementById('tableKategori');
const searchInput = document.getElementById('tableSearch');
const searchBtn = document.getElementById('btnTableSearch');
const downloadBtn = document.getElementById('btnDownloadMultiple');
const selectedCountEl = document.getElementById('selectedCount');
const checkAllEl = document.getElementById('checkAllRows');
@ -200,6 +204,51 @@
}
});
}
if (window.$ && $.fn.select2) {
if (unitSelect) {
$('#tableUnit').select2({
placeholder: 'Pilih Unit',
allowClear: true,
width: '100%',
closeOnSelect: false,
selectionCssClass: 'select2-filter-selection',
dropdownCssClass: 'select2-filter-dropdown',
ajax: {
url: '/select-unit-kerja-option',
dataType: 'json',
delay: 250,
data: function (params) {
return { q: params.term };
},
processResults: function (data) {
return {
results: (data?.data || []).map(item => ({
id: item.id,
text: item.name
}))
};
},
cache: true
}
});
$('#tableUnit').on('change', function () {
tableState.unit = $(this).val() || [];
});
}
if (kategoriSelect) {
$('#tableKategori').select2({
placeholder: 'Pilih Kategori',
allowClear: true,
width: '100%',
closeOnSelect: false,
selectionCssClass: 'select2-filter-selection',
dropdownCssClass: 'select2-filter-dropdown'
});
$('#tableKategori').on('change', function () {
tableState.kategori = $(this).val() || [];
});
}
}
function resetCreateForm(){
colCount = 1;
@ -361,13 +410,13 @@
updateSelectedCount();
}
function debouncedTableSearch(value){
clearTimeout(window.tableSearchTimer);
window.tableSearchTimer = setTimeout(() => {
tableState.search = value.trim();
tableState.page = 1;
fetchData();
}, 250);
function applyTableSearch(){
const value = searchInput ? searchInput.value : '';
tableState.search = (value || '').trim();
tableState.unit = unitSelect && window.$ ? ($('#tableUnit').val() || []) : (tableState.unit || []);
tableState.kategori = kategoriSelect && window.$ ? ($('#tableKategori').val() || []) : (tableState.kategori || []);
tableState.page = 1;
fetchData();
}
function fetchData(){
@ -377,6 +426,12 @@
per_page: tableState.pageSize,
keyword: tableState.search
});
if (tableState.unit && tableState.unit.length > 0) {
tableState.unit.forEach(id => params.append('unit[]', id));
}
if (tableState.kategori && tableState.kategori.length > 0) {
tableState.kategori.forEach(kat => params.append('kategori[]', kat));
}
fetch(`/data-internal?${params.toString()}`)
.then(response => response.json())
.then(data => {
@ -391,6 +446,18 @@
})
}
if (searchBtn) {
searchBtn.addEventListener('click', applyTableSearch);
}
if (searchInput) {
searchInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
e.preventDefault();
applyTableSearch();
}
});
}
function formatTanggal(dateString) {
const d = new Date(dateString);

View File

@ -96,7 +96,7 @@
<div class="mt-2 text-success fw-semibold d-none file-name"></div>
</div>
<div class="form-text text-muted">
Format yang didukung: <b>PDF</b>.
Format yang didukung: <b>PDF</b> Maksimal <b>10mb</b>.
</div>
</div>
<div id="col_add_fileV2" class="col-12"></div>

View File

@ -3,7 +3,7 @@
@if ($showRecapTitle)
<div>
<h4 class="mb-0">Rekap Dokumen</h4>
<small class="text-muted">Ringkasan jumlah file per Unit dan Folder</small>
<small class="text-muted">Ringkasan jumlah file per Unit dan Kategori</small>
</div>
@endif
<div class="{{ $showRecapTitle ? 'ms-md-auto' : '' }} d-flex gap-2 align-items-center">
@ -31,7 +31,7 @@
<tr>
<th style="width:5%;" class="text-center">#</th>
<th style="width:30%;">Unit</th>
<th style="width:20%;">Folder</th>
<th style="width:20%;">Kategori</th>
<th style="width:15%;" class="text-center">Jumlah File</th>
</tr>
</thead>
@ -86,6 +86,7 @@ function fetchRecap(){
tbody.innerHTML = `<tr><td colspan="4" class="text-center text-muted py-4">Tidak ada data</td></tr>`;
return;
}
let grandTotal = 0;
const html = rows.map((row, idx) => {
const folderRows = (row.data || []).map((f, i) => `
<tr>
@ -95,9 +96,15 @@ function fetchRecap(){
<td class="text-center fw-bold">${f.count || 0}</td>
</tr>
`).join('');
(row.data || []).forEach(f => { grandTotal += (parseInt(f.count, 10) || 0); });
return folderRows;
}).join('');
tbody.innerHTML = html;
tbody.innerHTML = html + `
<tr class="table-light">
<td colspan="3" class="text-end fw-semibold">Total File</td>
<td class="text-center fw-bold">${grandTotal}</td>
</tr>
`;
renderRecapPagination();
})
.catch(err => {

View File

@ -25,7 +25,7 @@
.modal-content,
.modal-body,
.message-body {
color-scheme: light;
color-scheme: black;
scrollbar-color: auto;
scrollbar-width: auto;
}