This commit is contained in:
Dwi Swandhana
2026-03-06 12:40:29 +07:00
parent 27ef021783
commit 3754ae3531
3 changed files with 244 additions and 114 deletions
@@ -114,6 +114,7 @@ class FrontpageController extends Controller
if ($sisaMenit <= 60) {
$earlyWarnings[] = [
'id' => $row->id,
'subpoli' => $row->subpoli ?? 'Tanpa Subpoli',
'nofoto' => $row->nofoto,
'noregister' => $row->noregister,
'nmpasien' => $row->nmpasien,
@@ -128,7 +129,21 @@ class FrontpageController extends Controller
];
}
}
$data['earlyWarnings'] = $earlyWarnings;
$earlyWarningGroups = collect($earlyWarnings)
->groupBy(function ($item) {
return !empty($item['subpoli']) ? $item['subpoli'] : 'Tanpa Subpoli';
})
->map(function ($items, $subpoli) {
return [
'subpoli' => $subpoli,
'total' => count($items),
'items' => array_values($items->toArray()),
];
})
->values()
->toArray();
$data['earlyWarningGroups'] = $earlyWarningGroups;
return view('dokter.dashborad', $data);
} else {
try {
@@ -47,84 +47,86 @@
<div class="ribbon ribbon-danger">Rekapitulasi Penerimaan Sample {{$tanggal}}</div>
<p></p>
<div class="table-responsive">
<div class="rekap-toolbar">
<button type="button" class="btn btn-primary" id="btnexport"><i class="fa fa-file-excel-o"></i> Export</button>
<select id="printOrientation" class="btn btn-default">
<option value="landscape">Landscape</option>
<option value="portrait">Portrait</option>
</select>
<button type="button" class="btn btn-success" id="btnprintselected"><i class="fa fa-print"></i> Cetak Terpilih</button>
</div>
<div class="rekap-toolbar">
<button type="button" class="btn btn-primary" id="btnexport"><i class="fa fa-file-excel-o"></i> Export</button>
<select id="printOrientation" class="btn btn-default">
<option value="landscape">Landscape</option>
<option value="portrait">Portrait</option>
</select>
<select id="sortStatus" class="btn btn-default">
<option value="default">Sort Status (Default)</option>
<option value="asc">Sort Status A-Z</option>
<option value="desc">Sort Status Z-A</option>
</select>
<select id="filterStatus" class="btn btn-default">
<option value="">Filter Status: Semua</option>
</select>
<button type="button" class="btn btn-success" id="btnprintselected"><i class="fa fa-print"></i> Cetak Terpilih</button>
</div>
<div class="rekap-table-wrap">
<table class="table table-bordered table-striped" id="penerimaansamplereport">
<thead>
<tr>
<th style="width: 40px; text-align:center;">
<input type="checkbox" id="checkAllRows">
</th>
<th>Keterangan Cetak</th>
<th>No.RM</th>
<th>Nama</th>
<th>No.Sample</th>
<th>Asal Pasien</th>
<th>Daftar</th>
<th>Order</th>
<th>Kode</th>
<th>Spesimen</th>
<th>Status</th>
<th>Tanggal Terima</th>
<th>Petugas</th>
</tr>
</thead>
<tbody>
@foreach($detail as $r)
@php
$isPrinted = !empty($r['ppdsjunior2']) && $r['ppdsjunior2'] != '0';
@endphp
<tr data-id="{{ $r['id'] }}" class="{{ $isPrinted ? 'printed-row' : '' }}">
<td style="text-align:center;">
<input type="checkbox" class="row-check">
</td>
<td>{{ $r['noregister'] }}</td>
<td>{{ $r['nmpasien'] }}</td>
<td>{{ $r['nofoto'] }}</td>
<td>{{ $r['asalpasien'] }}</td>
<td>{{ $r['daftar'] }}</td>
<td>{{ $r['reques'] }}</td>
<td>{{ $r['kd_spesimen'] }}</td>
<td>{{ $r['nm_spesimen'] }}</td>
<td>{{ $r['status'] }}</td>
<td class="print-status-cell">
@if($isPrinted)
<span class="status-print-badge done">Sudah Dicetak</span>
@else
<span class="status-print-badge pending">Belum Dicetak</span>
@endif
</td>
<td>{{ $r['tgldraft'] }}</td>
<td class="petugas-cell">
@php
$petugas = '';
if ($r['nmppdsmiddle2'] != '') {
$petugas = $r['nmppdsmiddle2'];
}
if ($r['nmppdsjunior2'] != '') {
$petugas = $petugas.' '.$r['nmppdsjunior2'];
}
echo $petugas;
@endphp
</td>
<div class="rekap-table-wrap">
<table class="table table-bordered table-striped" id="penerimaansamplereport">
<thead>
<tr>
<th style="width: 40px; text-align:center;">
<input type="checkbox" id="checkAllRows">
</th>
<th>Keterangan Cetak</th>
<th>No.RM</th>
<th>Nama</th>
<th>No.Sample</th>
<th>Asal Pasien</th>
<th>Daftar</th>
<th>Order</th>
<th>Kode</th>
<th>Spesimen</th>
<th>Status</th>
<th>Tanggal Terima</th>
<th>Petugas</th>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<div class="card-footer">
</thead>
<tbody>
@foreach($detail as $r)
@php
$isPrinted = !empty($r['ppdsjunior2']) && $r['ppdsjunior2'] != '0';
$statusValue = trim((string)($r['status'] ?? '-'));
$petugas = '';
if ($r['nmppdsmiddle2'] != '') {
$petugas = $r['nmppdsmiddle2'];
}
if ($r['nmppdsjunior2'] != '') {
$petugas = trim($petugas.' '.$r['nmppdsjunior2']);
}
@endphp
<tr data-id="{{ $r['id'] }}" data-status="{{ strtolower($statusValue) }}" data-order="{{ $loop->index }}" class="{{ $isPrinted ? 'printed-row' : '' }}">
<td style="text-align:center;">
<input type="checkbox" class="row-check" {{ $isPrinted ? 'disabled' : '' }}>
</td>
<td class="print-status-cell">
@if($isPrinted)
<span class="status-print-badge done">Sudah Dicetak</span>
@else
<span class="status-print-badge pending">Belum Dicetak</span>
@endif
</td>
<td>{{ $r['noregister'] }}</td>
<td>{{ $r['nmpasien'] }}</td>
<td>{{ $r['nofoto'] }}</td>
<td>{{ $r['asalpasien'] }}</td>
<td>{{ $r['daftar'] }}</td>
<td>{{ $r['reques'] }}</td>
<td>{{ $r['kd_spesimen'] }}</td>
<td>{{ $r['nm_spesimen'] }}</td>
<td>{{ $statusValue }}</td>
<td>{{ $r['tgldraft'] }}</td>
<td class="petugas-cell">{{ $petugas }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<div class="card-footer"></div>
</div>
</div>
</div>
@@ -138,8 +140,11 @@
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
var table = document.getElementById('penerimaansamplereport');
var tableBody = table ? table.querySelector('tbody') : null;
var checkAllRows = document.getElementById('checkAllRows');
var printOrientation = document.getElementById('printOrientation');
var sortStatus = document.getElementById('sortStatus');
var filterStatus = document.getElementById('filterStatus');
var token = document.getElementById('token').value;
var markPrintedUrl = @json(route('markRekapPenerimaanSamplePrinted'));
var appName = @json(config('global.namaapps'));
@@ -149,19 +154,85 @@
var appAddress = @json(config('global.addressapps'));
var petugasCetak = @json(Session('nama'));
function getEnabledVisibleChecks() {
return table ? table.querySelectorAll('tbody tr:not([style*="display: none"]) .row-check:not(:disabled)') : [];
}
function updateCheckAllState() {
if (!table || !checkAllRows) {
if (!checkAllRows) {
return;
}
var rowChecks = table.querySelectorAll('tbody .row-check:not(:disabled)');
var checkedRows = table.querySelectorAll('tbody .row-check:not(:disabled):checked');
checkAllRows.checked = rowChecks.length > 0 && rowChecks.length === checkedRows.length;
var rowChecks = getEnabledVisibleChecks();
var checkedCount = 0;
rowChecks.forEach(function(cb) {
if (cb.checked) {
checkedCount++;
}
});
checkAllRows.checked = rowChecks.length > 0 && rowChecks.length === checkedCount;
}
function initStatusFilterOptions() {
if (!table || !filterStatus) {
return;
}
var statusSet = new Set();
table.querySelectorAll('tbody tr').forEach(function(row) {
var statusText = (row.children[10] ? row.children[10].innerText : '').trim();
if (statusText !== '') {
statusSet.add(statusText);
}
});
Array.from(statusSet).sort().forEach(function(status) {
var opt = document.createElement('option');
opt.value = status.toLowerCase();
opt.textContent = 'Status: ' + status;
filterStatus.appendChild(opt);
});
}
function applyStatusSortFilter() {
if (!tableBody) {
return;
}
var rows = Array.from(tableBody.querySelectorAll('tr'));
var sortMode = sortStatus ? sortStatus.value : 'default';
var selectedStatus = filterStatus ? filterStatus.value : '';
rows.sort(function(a, b) {
if (sortMode === 'asc') {
return (a.dataset.status || '').localeCompare(b.dataset.status || '');
}
if (sortMode === 'desc') {
return (b.dataset.status || '').localeCompare(a.dataset.status || '');
}
return parseInt(a.dataset.order || '0', 10) - parseInt(b.dataset.order || '0', 10);
});
rows.forEach(function(row) {
tableBody.appendChild(row);
var rowStatus = row.dataset.status || '';
var show = selectedStatus === '' || rowStatus === selectedStatus;
row.style.display = show ? '' : 'none';
if (!show) {
var cb = row.querySelector('.row-check');
if (cb) {
cb.checked = false;
}
}
});
if (checkAllRows) {
checkAllRows.checked = false;
}
updateCheckAllState();
}
if (checkAllRows && table) {
checkAllRows.addEventListener('change', function() {
var rowChecks = table.querySelectorAll('tbody .row-check:not(:disabled)');
rowChecks.forEach(function(cb) {
getEnabledVisibleChecks().forEach(function(cb) {
cb.checked = checkAllRows.checked;
});
});
@@ -172,15 +243,22 @@
}
});
}
updateCheckAllState();
if (sortStatus) {
sortStatus.addEventListener('change', applyStatusSortFilter);
}
if (filterStatus) {
filterStatus.addEventListener('change', applyStatusSortFilter);
}
initStatusFilterOptions();
applyStatusSortFilter();
document.getElementById('btnexport').addEventListener('click', function() {
var table = document.getElementById('penerimaansamplereport');
if (table) {
var wb = XLSX.utils.table_to_book(table, { sheet: "Report" });
XLSX.writeFile(wb, "Rekap_Penerimaan_Sample_{{$tanggal}}.xlsx");
} else {
console.error('Tabel dengan ID "penerimaansamplereport" tidak ditemukan.');
}
});
@@ -195,6 +273,9 @@
var selectedRowElements = [];
selectedRows.forEach(function(row) {
if (row.style.display === 'none') {
return;
}
var rowCheck = row.querySelector('.row-check');
if (rowCheck && rowCheck.checked) {
var cells = row.querySelectorAll('td');
@@ -256,7 +337,9 @@
}
});
checkAllRows.checked = false;
if (checkAllRows) {
checkAllRows.checked = false;
}
updateCheckAllState();
var now = new Date();
@@ -116,43 +116,75 @@
<table class="table table-bordered table-striped table-sm">
<thead>
<tr>
<th>No</th>
<th>No.Sample</th>
<th>No.RM</th>
<th>Nama</th>
<th>Order</th>
<th>Asal Pasien</th>
<th>Status</th>
<th>Daftar</th>
<th>Target (Hari)</th>
<th>Estimasi Selesai</th>
<th>Warning</th>
<th style="width: 70px;">No</th>
<th>Subpoli</th>
<th style="width: 180px;">Jumlah Warning</th>
<th style="width: 160px;">Aksi</th>
</tr>
</thead>
<tbody>
@forelse($earlyWarnings as $i => $row)
@forelse($earlyWarningGroups as $i => $group)
<tr>
<td>{{ $i + 1 }}</td>
<td>{{ $row['nofoto'] }}</td>
<td>{{ $row['noregister'] }}</td>
<td>{{ $row['nmpasien'] }}</td>
<td>{{ $row['reques'] }}</td>
<td>{{ $row['asalpasien'] }}</td>
<td>{{ $row['status'] }}</td>
<td>{{ $row['daftar'] }}</td>
<td>{{ $row['target_hari'] }}</td>
<td>{{ $row['target_selesai'] }}</td>
<td>
@if($row['sisa_menit'] <= 0)
<span class="badge badge-danger">{{ $row['warning_label'] }}</span>
@else
<span class="badge badge-warning">{{ $row['warning_label'] }} ({{ $row['sisa_menit'] }} menit)</span>
@endif
<strong>{{ $group['subpoli'] }}</strong>
</td>
<td><span class="badge badge-danger">{{ $group['total'] }} kasus</span></td>
<td>
<button class="btn btn-sm btn-info" type="button" data-toggle="collapse" data-target="#ews-group-{{ $i }}" aria-expanded="false" aria-controls="ews-group-{{ $i }}">
Lihat Detail
</button>
</td>
</tr>
<tr class="collapse" id="ews-group-{{ $i }}">
<td colspan="4">
<div class="table-responsive">
<table class="table table-bordered table-striped table-sm mb-0">
<thead>
<tr>
<th>No</th>
<th>No.Sample</th>
<th>No.RM</th>
<th>Nama</th>
<th>Order</th>
<th>Asal Pasien</th>
<th>Status</th>
<th>Daftar</th>
<th>Target (Hari)</th>
<th>Estimasi Selesai</th>
<th>Warning</th>
</tr>
</thead>
<tbody>
@foreach($group['items'] as $j => $row)
<tr>
<td>{{ $j + 1 }}</td>
<td>{{ $row['nofoto'] }}</td>
<td>{{ $row['noregister'] }}</td>
<td>{{ $row['nmpasien'] }}</td>
<td>{{ $row['reques'] }}</td>
<td>{{ $row['asalpasien'] }}</td>
<td>{{ $row['status'] }}</td>
<td>{{ $row['daftar'] }}</td>
<td>{{ $row['target_hari'] }}</td>
<td>{{ $row['target_selesai'] }}</td>
<td>
@if($row['sisa_menit'] <= 0)
<span class="badge badge-danger">{{ $row['warning_label'] }}</span>
@else
<span class="badge badge-warning">{{ $row['warning_label'] }} ({{ $row['sisa_menit'] }} menit)</span>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="11" class="text-center">Tidak ada data Early Warning.</td>
<td colspan="4" class="text-center">Tidak ada data Early Warning.</td>
</tr>
@endforelse
</tbody>