update
This commit is contained in:
@@ -885,4 +885,63 @@ class ReportController extends Controller
|
||||
'detail' => $periksa
|
||||
]);
|
||||
}
|
||||
public function markRekapPenerimaanSamplePrinted(Request $request) {
|
||||
$userId = Session::get('id');
|
||||
$userNama = Session::get('nama');
|
||||
if (empty($userId)) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Session login tidak valid.'
|
||||
], 401);
|
||||
}
|
||||
|
||||
$ids = $request->input('ids', []);
|
||||
if (!is_array($ids) || count($ids) === 0) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data yang dipilih tidak valid.'
|
||||
], 422);
|
||||
}
|
||||
|
||||
$ids = collect($ids)
|
||||
->filter(function ($id) {
|
||||
return is_numeric($id);
|
||||
})
|
||||
->map(function ($id) {
|
||||
return intval($id);
|
||||
})
|
||||
->unique()
|
||||
->values()
|
||||
->toArray();
|
||||
|
||||
if (count($ids) === 0) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Data yang dipilih tidak valid.'
|
||||
], 422);
|
||||
}
|
||||
|
||||
$printableIds = Periksa::whereIn('id', $ids)
|
||||
->where(function ($query) {
|
||||
$query->whereNull('ppdsjunior2')
|
||||
->orWhere('ppdsjunior2', '')
|
||||
->orWhere('ppdsjunior2', '0');
|
||||
})
|
||||
->pluck('id')
|
||||
->toArray();
|
||||
|
||||
if (count($printableIds) > 0) {
|
||||
Periksa::whereIn('id', $printableIds)->update([
|
||||
'ppdsjunior2' => $userId,
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Status cetak berhasil diperbarui.',
|
||||
'affected_ids'=> $printableIds,
|
||||
'printed_by' => $userNama
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,44 @@
|
||||
@extends('base.layout')
|
||||
@section('content')
|
||||
<style>
|
||||
.rekap-toolbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 5;
|
||||
background: #fff;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.rekap-table-wrap {
|
||||
max-height: 65vh;
|
||||
overflow: auto;
|
||||
border: 1px solid #dee2e6;
|
||||
}
|
||||
#penerimaansamplereport thead th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
background: #f8f9fa;
|
||||
}
|
||||
.status-print-badge {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.status-print-badge.pending {
|
||||
background: #e9ecef;
|
||||
color: #495057;
|
||||
}
|
||||
.status-print-badge.done {
|
||||
background: #d4edda;
|
||||
color: #155724;
|
||||
}
|
||||
tr.printed-row {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
</style>
|
||||
<div class="wrapper">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
@@ -8,19 +47,23 @@
|
||||
<div class="ribbon ribbon-danger">Rekapitulasi Penerimaan Sample {{$tanggal}}</div>
|
||||
<p></p>
|
||||
<div class="table-responsive">
|
||||
<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 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-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>
|
||||
@@ -37,9 +80,19 @@
|
||||
|
||||
<tbody>
|
||||
@foreach($detail as $r)
|
||||
<tr>
|
||||
@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">
|
||||
<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>
|
||||
@@ -51,7 +104,7 @@
|
||||
<td>{{ $r['nm_spesimen'] }}</td>
|
||||
<td>{{ $r['status'] }}</td>
|
||||
<td>{{ $r['tgldraft'] }}</td>
|
||||
<td>
|
||||
<td class="petugas-cell">
|
||||
@php
|
||||
$petugas = '';
|
||||
if ($r['nmppdsmiddle2'] != '') {
|
||||
@@ -68,6 +121,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
</div>
|
||||
</div>
|
||||
@@ -85,6 +139,8 @@
|
||||
var table = document.getElementById('penerimaansamplereport');
|
||||
var checkAllRows = document.getElementById('checkAllRows');
|
||||
var printOrientation = document.getElementById('printOrientation');
|
||||
var token = document.getElementById('token').value;
|
||||
var markPrintedUrl = @json(route('markRekapPenerimaanSamplePrinted'));
|
||||
var appName = @json(config('global.namaapps'));
|
||||
var appDomain = @json(config('global.domainapps'));
|
||||
var appSubDomain = @json(config('global.subdomainapps'));
|
||||
@@ -92,14 +148,30 @@
|
||||
var appAddress = @json(config('global.addressapps'));
|
||||
var petugasCetak = @json(Session('nama'));
|
||||
|
||||
function updateCheckAllState() {
|
||||
if (!table || !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;
|
||||
}
|
||||
|
||||
if (checkAllRows && table) {
|
||||
checkAllRows.addEventListener('change', function() {
|
||||
var rowChecks = table.querySelectorAll('tbody .row-check');
|
||||
var rowChecks = table.querySelectorAll('tbody .row-check:not(:disabled)');
|
||||
rowChecks.forEach(function(cb) {
|
||||
cb.checked = checkAllRows.checked;
|
||||
});
|
||||
});
|
||||
|
||||
table.addEventListener('change', function(e) {
|
||||
if (e.target && e.target.classList.contains('row-check')) {
|
||||
updateCheckAllState();
|
||||
}
|
||||
});
|
||||
}
|
||||
updateCheckAllState();
|
||||
|
||||
document.getElementById('btnexport').addEventListener('click', function() {
|
||||
var table = document.getElementById('penerimaansamplereport');
|
||||
@@ -118,13 +190,19 @@
|
||||
|
||||
var selectedRows = table.querySelectorAll('tbody tr');
|
||||
var printedRows = [];
|
||||
var selectedIds = [];
|
||||
var selectedRowElements = [];
|
||||
|
||||
selectedRows.forEach(function(row) {
|
||||
var rowCheck = row.querySelector('.row-check');
|
||||
if (rowCheck && rowCheck.checked) {
|
||||
var cells = row.querySelectorAll('td');
|
||||
var rowId = parseInt(row.getAttribute('data-id'), 10);
|
||||
if (!isNaN(rowId)) {
|
||||
selectedIds.push(rowId);
|
||||
selectedRowElements.push(row);
|
||||
}
|
||||
printedRows.push([
|
||||
cells[1] ? cells[1].innerText : '',
|
||||
cells[2] ? cells[2].innerText : '',
|
||||
cells[3] ? cells[3].innerText : '',
|
||||
cells[4] ? cells[4].innerText : '',
|
||||
@@ -134,89 +212,133 @@
|
||||
cells[8] ? cells[8].innerText : '',
|
||||
cells[9] ? cells[9].innerText : '',
|
||||
cells[10] ? cells[10].innerText : '',
|
||||
cells[11] ? cells[11].innerText : ''
|
||||
cells[11] ? cells[11].innerText : '',
|
||||
cells[12] ? cells[12].innerText : ''
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
if (printedRows.length === 0) {
|
||||
if (printedRows.length === 0 || selectedIds.length === 0) {
|
||||
alert('Pilih minimal satu baris untuk dicetak.');
|
||||
return;
|
||||
}
|
||||
|
||||
var now = new Date();
|
||||
var orientation = printOrientation ? printOrientation.value : 'landscape';
|
||||
var tanggalCetak = now.toLocaleString('id-ID', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
});
|
||||
$.post(markPrintedUrl, { ids: selectedIds, _token: token }, function(resp) {
|
||||
if (!resp || resp.status !== 'success') {
|
||||
alert((resp && resp.message) ? resp.message : 'Gagal memperbarui status cetak.');
|
||||
return;
|
||||
}
|
||||
|
||||
var printWindow = window.open('', '_blank');
|
||||
if (!printWindow) {
|
||||
alert('Pop-up diblokir browser. Izinkan pop-up untuk mencetak.');
|
||||
return;
|
||||
}
|
||||
|
||||
var rowsHtml = '';
|
||||
printedRows.forEach(function(rowData) {
|
||||
rowsHtml += '<tr>';
|
||||
rowData.forEach(function(value) {
|
||||
rowsHtml += '<td>' + value + '</td>';
|
||||
var affectedIds = Array.isArray(resp.affected_ids) ? resp.affected_ids : [];
|
||||
var affectedMap = {};
|
||||
affectedIds.forEach(function(id) {
|
||||
affectedMap[String(id)] = true;
|
||||
});
|
||||
rowsHtml += '</tr>';
|
||||
|
||||
selectedRowElements.forEach(function(row) {
|
||||
var id = row.getAttribute('data-id');
|
||||
if (affectedMap[id]) {
|
||||
row.classList.add('printed-row');
|
||||
var rowCheck = row.querySelector('.row-check');
|
||||
if (rowCheck) {
|
||||
rowCheck.checked = false;
|
||||
rowCheck.disabled = true;
|
||||
}
|
||||
var statusCell = row.querySelector('.print-status-cell');
|
||||
if (statusCell) {
|
||||
statusCell.innerHTML = '<span class="status-print-badge done">Sudah Dicetak</span>';
|
||||
}
|
||||
var petugasCell = row.querySelector('.petugas-cell');
|
||||
if (petugasCell && (!petugasCell.innerText || petugasCell.innerText.trim() === '')) {
|
||||
petugasCell.innerText = resp.printed_by || petugasCetak || '-';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
checkAllRows.checked = false;
|
||||
updateCheckAllState();
|
||||
|
||||
var now = new Date();
|
||||
var orientation = printOrientation ? printOrientation.value : 'landscape';
|
||||
var tanggalCetak = now.toLocaleString('id-ID', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
});
|
||||
|
||||
var printWindow = window.open('', '_blank');
|
||||
if (!printWindow) {
|
||||
alert('Pop-up diblokir browser. Izinkan pop-up untuk mencetak.');
|
||||
return;
|
||||
}
|
||||
|
||||
var rowsHtml = '';
|
||||
printedRows.forEach(function(rowData) {
|
||||
rowsHtml += '<tr>';
|
||||
rowData.forEach(function(value) {
|
||||
rowsHtml += '<td>' + value + '</td>';
|
||||
});
|
||||
rowsHtml += '</tr>';
|
||||
});
|
||||
|
||||
var html = ''
|
||||
+ '<!DOCTYPE html>'
|
||||
+ '<html><head><title>Cetak Rekap Penerimaan Sample</title>'
|
||||
+ '<style>'
|
||||
+ '@page { size: A4 ' + orientation + '; margin: 10mm; }'
|
||||
+ 'body { font-family: Arial, sans-serif; margin: 0; color: #111; }'
|
||||
+ '.header { text-align: center; margin-bottom: 8px; }'
|
||||
+ '.header h2 { margin: 0; font-size: 16px; }'
|
||||
+ '.header .line { margin: 2px 0; font-size: 12px; }'
|
||||
+ '.meta { display: flex; justify-content: space-between; margin: 8px 0 10px; font-size: 11px; }'
|
||||
+ '.title { text-align: center; font-weight: 700; margin-bottom: 8px; font-size: 12px; }'
|
||||
+ 'table { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 10px; }'
|
||||
+ 'th, td { border: 1px solid #000; padding: 3px; word-break: break-word; vertical-align: top; }'
|
||||
+ 'th { background: #f1f1f1; }'
|
||||
+ '</style></head><body>'
|
||||
+ '<div class="header">'
|
||||
+ '<h2>' + (appName || '') + '</h2>'
|
||||
+ '<div class="line">' + (appDomain || '') + '</div>'
|
||||
+ '<div class="line">' + (appSubDomain || '') + ', ' + (appSubSubDomain || '') + '</div>'
|
||||
+ '<div class="line">' + (appAddress || '') + '</div>'
|
||||
+ '</div>'
|
||||
+ '<div class="title">Rekapitulasi Penerimaan Sample {{$tanggal}}</div>'
|
||||
+ '<div class="meta">'
|
||||
+ '<div>Tanggal Cetak: ' + tanggalCetak + '</div>'
|
||||
+ '<div>Petugas: ' + (petugasCetak || '-') + '</div>'
|
||||
+ '</div>'
|
||||
+ '<table>'
|
||||
+ '<thead><tr>'
|
||||
+ '<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>' + rowsHtml + '</tbody>'
|
||||
+ '</table>'
|
||||
+ '<script>window.onload = function(){ window.print(); window.close(); };<\/script>'
|
||||
+ '</body></html>';
|
||||
|
||||
printWindow.document.open();
|
||||
printWindow.document.write(html);
|
||||
printWindow.document.close();
|
||||
}).fail(function(xhr) {
|
||||
var err = 'Gagal memperbarui status cetak.';
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) {
|
||||
err = xhr.responseJSON.message;
|
||||
}
|
||||
alert(err);
|
||||
});
|
||||
|
||||
var html = ''
|
||||
+ '<!DOCTYPE html>'
|
||||
+ '<html><head><title>Cetak Rekap Penerimaan Sample</title>'
|
||||
+ '<style>'
|
||||
+ '@page { size: A4 ' + orientation + '; margin: 10mm; }'
|
||||
+ 'body { font-family: Arial, sans-serif; margin: 0; color: #111; }'
|
||||
+ '.header { text-align: center; margin-bottom: 8px; }'
|
||||
+ '.header h2 { margin: 0; font-size: 16px; }'
|
||||
+ '.header .line { margin: 2px 0; font-size: 12px; }'
|
||||
+ '.meta { display: flex; justify-content: space-between; margin: 8px 0 10px; font-size: 11px; }'
|
||||
+ '.title { text-align: center; font-weight: 700; margin-bottom: 8px; font-size: 12px; }'
|
||||
+ 'table { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 10px; }'
|
||||
+ 'th, td { border: 1px solid #000; padding: 3px; word-break: break-word; vertical-align: top; }'
|
||||
+ 'th { background: #f1f1f1; }'
|
||||
+ '</style></head><body>'
|
||||
+ '<div class="header">'
|
||||
+ '<h2>' + (appName || '') + '</h2>'
|
||||
+ '<div class="line">' + (appDomain || '') + '</div>'
|
||||
+ '<div class="line">' + (appSubDomain || '') + ', ' + (appSubSubDomain || '') + '</div>'
|
||||
+ '</div>'
|
||||
+ '<div class="title">Rekapitulasi Penerimaan Sample {{$tanggal}}</div>'
|
||||
+ '<div class="meta">'
|
||||
+ '<div>Tanggal Cetak: ' + tanggalCetak + '</div>'
|
||||
+ '<div>Petugas: ' + (petugasCetak || '-') + '</div>'
|
||||
+ '</div>'
|
||||
+ '<table>'
|
||||
+ '<thead><tr>'
|
||||
+ '<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>' + rowsHtml + '</tbody>'
|
||||
+ '</table>'
|
||||
+ '<script>window.onload = function(){ window.print(); window.close(); };<\/script>'
|
||||
+ '</body></html>';
|
||||
|
||||
printWindow.document.open();
|
||||
printWindow.document.write(html);
|
||||
printWindow.document.close();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -138,6 +138,7 @@ Route::group(['middleware' => 'project.ipg'], function() {
|
||||
Route::get('znreport', [ReportController::class, 'genZNreport']);
|
||||
Route::get('tatreport', [ReportController::class, 'genTATreport']);
|
||||
Route::get('reportpenerimaansample', [ReportController::class, 'genRekapPenerimaanSample']);
|
||||
Route::post('reportpenerimaansample/mark-printed', [ReportController::class, 'markRekapPenerimaanSamplePrinted'])->name('markRekapPenerimaanSamplePrinted');
|
||||
Route::get('/glass-report/export', [ReportController::class, 'exportGlassReport'])->name('exportGlassReport');
|
||||
Route::get('rekap-antibiotik/export', [ReportController::class, 'exportRekapAntibiotik'])->name('exportRekapAntibiotik');
|
||||
Route::get('list', [ListController::class, 'index']);
|
||||
|
||||
Reference in New Issue
Block a user