update
This commit is contained in:
@@ -726,6 +726,7 @@ class DokterController extends Controller
|
|||||||
$criticalSample = CriticalValueSample::firstOrNew(['periksa_id' => $periksa->id]);
|
$criticalSample = CriticalValueSample::firstOrNew(['periksa_id' => $periksa->id]);
|
||||||
$criticalSample->nofoto = $periksa->nofoto;
|
$criticalSample->nofoto = $periksa->nofoto;
|
||||||
$criticalSample->noregister = $periksa->noregister;
|
$criticalSample->noregister = $periksa->noregister;
|
||||||
|
$criticalSample->asalpasien = $periksa->asalpasien;
|
||||||
$criticalSample->nmpasien = $periksa->nmpasien;
|
$criticalSample->nmpasien = $periksa->nmpasien;
|
||||||
$criticalSample->nm_spesimen = $periksa->nm_spesimen;
|
$criticalSample->nm_spesimen = $periksa->nm_spesimen;
|
||||||
|
|
||||||
@@ -766,19 +767,74 @@ class DokterController extends Controller
|
|||||||
'highlightId' => $highlightId,
|
'highlightId' => $highlightId,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
public function criticalValueNotificationSummary()
|
||||||
|
{
|
||||||
|
if (Session::get('id') === null) {
|
||||||
|
return response()->json([
|
||||||
|
'count' => 0,
|
||||||
|
'menu_html' => view('notifications.partials.critical-bell', [
|
||||||
|
'count' => 0,
|
||||||
|
'items' => collect(),
|
||||||
|
])->render(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$count = CriticalValueSample::whereNull('followed_up_at')->count();
|
||||||
|
$items = CriticalValueSample::whereNull('followed_up_at')
|
||||||
|
->orderBy('critical_set_at', 'asc')
|
||||||
|
->limit(8)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'count' => (int) $count,
|
||||||
|
'menu_html' => view('notifications.partials.critical-bell', [
|
||||||
|
'count' => (int) $count,
|
||||||
|
'items' => $items,
|
||||||
|
])->render(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
public function criticalValueNotificationOpen($id)
|
public function criticalValueNotificationOpen($id)
|
||||||
{
|
{
|
||||||
$criticalSample = CriticalValueSample::findOrFail($id);
|
|
||||||
$this->markCriticalValueAsRead($criticalSample);
|
|
||||||
|
|
||||||
return redirect()
|
return redirect()
|
||||||
->route('criticalValueNotifications', ['highlight' => $criticalSample->id])
|
->route('criticalValueNotifications', ['highlight' => $id]);
|
||||||
->with('success', 'Sample nilai kritis sudah ditandai sudah ditindaklanjuti.');
|
|
||||||
}
|
}
|
||||||
public function criticalValueNotificationMarkRead($id)
|
public function criticalValueNotificationMarkRead($id)
|
||||||
{
|
{
|
||||||
$criticalSample = CriticalValueSample::findOrFail($id);
|
$criticalSample = CriticalValueSample::findOrFail($id);
|
||||||
$this->markCriticalValueAsRead($criticalSample);
|
if (!empty($criticalSample->followed_up_at)) {
|
||||||
|
return redirect()
|
||||||
|
->route('criticalValueNotifications', ['highlight' => $criticalSample->id])
|
||||||
|
->with('success', 'Sample nilai kritis ini sudah ditindaklanjuti sebelumnya.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$followUpMethod = trim((string) request('caratindaklanjut', ''));
|
||||||
|
$followUpRecipient = trim((string) request('penerima_laporan', ''));
|
||||||
|
$followUpReason = trim((string) request('alasan_belum_laporkan', ''));
|
||||||
|
|
||||||
|
// If method is empty -> not reported, reason is required.
|
||||||
|
// If method is filled -> reported, recipient is required.
|
||||||
|
if ($followUpMethod === '') {
|
||||||
|
if ($followUpReason === '') {
|
||||||
|
return back()->with('error', 'Alasan belum dilaporkan wajib diisi jika belum dilaporkan.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$allowed = ['Telpon', 'Whatshap', 'Email', 'Ketemu di Jalan'];
|
||||||
|
if (!in_array($followUpMethod, $allowed, true)) {
|
||||||
|
return back()->with('error', 'Cara tindak lanjut tidak valid.');
|
||||||
|
}
|
||||||
|
if ($followUpRecipient === '') {
|
||||||
|
return back()->with('error', 'Penerima laporan wajib diisi jika sudah dilaporkan.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$criticalSample->followed_up_at = Carbon::now();
|
||||||
|
$criticalSample->followed_up_by_user_id = Session('id');
|
||||||
|
$criticalSample->followed_up_by_name = Session('nama');
|
||||||
|
$criticalSample->follow_up_status = $followUpMethod === '' ? 'not_reported' : 'reported';
|
||||||
|
$criticalSample->follow_up_method = $followUpMethod !== '' ? $followUpMethod : null;
|
||||||
|
$criticalSample->follow_up_recipient = $followUpRecipient !== '' ? $followUpRecipient : null;
|
||||||
|
$criticalSample->follow_up_reason = $followUpReason !== '' ? $followUpReason : null;
|
||||||
|
$criticalSample->save();
|
||||||
|
|
||||||
return redirect()
|
return redirect()
|
||||||
->route('criticalValueNotifications', ['highlight' => $criticalSample->id])
|
->route('criticalValueNotifications', ['highlight' => $criticalSample->id])
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ class ListController extends Controller
|
|||||||
} else {
|
} else {
|
||||||
return redirect('/pendaftaran');
|
return redirect('/pendaftaran');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public function getList(Request $request) {
|
public function getList(Request $request) {
|
||||||
$jenis = $request->input('jenis');
|
$jenis = $request->input('jenis');
|
||||||
@@ -737,7 +736,13 @@ class ListController extends Controller
|
|||||||
</button>
|
</button>
|
||||||
</div>';
|
</div>';
|
||||||
})
|
})
|
||||||
->rawColumns(['aksi', 'tlsstatus', 'tlsnofoto', 'tlsnoregister', 'tlsnama', 'tlsreques'])
|
->addColumn('batalaksi', function ($row) {
|
||||||
|
return '
|
||||||
|
<button type="button" class="btn btn-sm btn-danger waves-effect" onClick="btnBatal('.$row->id.')">
|
||||||
|
<i class="me-50 fa fa-ban"></i> Kembalikan ke Loket
|
||||||
|
</button>';
|
||||||
|
})
|
||||||
|
->rawColumns(['aksi', 'tlsstatus', 'tlsnofoto', 'tlsnoregister', 'tlsnama', 'tlsreques', 'batalaksi'])
|
||||||
->make(true);
|
->make(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('critical_value_samples', function (Blueprint $table) {
|
||||||
|
// Snapshot from periksa for easier listing.
|
||||||
|
$table->string('asalpasien', 250)->nullable()->after('noregister');
|
||||||
|
|
||||||
|
// Follow-up details recorded when marking as read.
|
||||||
|
$table->string('follow_up_status', 25)->nullable()->after('followed_up_by_name'); // reported|not_reported
|
||||||
|
$table->string('follow_up_method', 50)->nullable()->after('follow_up_status');
|
||||||
|
$table->string('follow_up_recipient', 250)->nullable()->after('follow_up_method');
|
||||||
|
$table->string('follow_up_reason', 250)->nullable()->after('follow_up_recipient');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('critical_value_samples', function (Blueprint $table) {
|
||||||
|
$table->dropColumn([
|
||||||
|
'asalpasien',
|
||||||
|
'follow_up_status',
|
||||||
|
'follow_up_method',
|
||||||
|
'follow_up_recipient',
|
||||||
|
'follow_up_reason',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -37,31 +37,7 @@
|
|||||||
<span class="badge badge-danger badge-pill noti-icon-badge" id="notificationcount">{{ $criticalNotificationCount }}</span>
|
<span class="badge badge-danger badge-pill noti-icon-badge" id="notificationcount">{{ $criticalNotificationCount }}</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu dropdown-menu-right dropdown-lg" id="notifikasi-verifikasi-bell">
|
<div class="dropdown-menu dropdown-menu-right dropdown-lg" id="notifikasi-verifikasi-bell">
|
||||||
<div class="dropdown-item noti-title">
|
@include('notifications.partials.critical-bell', ['count' => $criticalNotificationCount, 'items' => $criticalNotificationItems])
|
||||||
<h5 class="m-0">
|
|
||||||
<span class="float-right">
|
|
||||||
<a href="{{ route('criticalValueNotifications') }}" class="text-dark"><small>Lihat Semua</small></a>
|
|
||||||
</span>
|
|
||||||
Nilai Kritis
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
<div style="max-height: 320px; overflow-y: auto;">
|
|
||||||
@if($criticalNotificationItems->isEmpty())
|
|
||||||
<div class="dropdown-item text-muted">Tidak ada sample nilai kritis yang perlu dilaporkan.</div>
|
|
||||||
@else
|
|
||||||
@foreach($criticalNotificationItems as $criticalItem)
|
|
||||||
<a href="{{ route('criticalValueNotificationOpen', $criticalItem->id) }}" class="dropdown-item notify-item">
|
|
||||||
<div class="notify-icon bg-warning"><i class="fa fa-exclamation-triangle"></i></div>
|
|
||||||
<p class="notify-details">
|
|
||||||
{{ $criticalItem->nofoto ?? '-' }} - {{ $criticalItem->nmpasien ?? 'Tanpa Nama' }}
|
|
||||||
<small class="text-muted">
|
|
||||||
Set: {{ $criticalItem->critical_set_at ? \Carbon\Carbon::parse($criticalItem->critical_set_at)->format('d-m-Y H:i:s') : '-' }}
|
|
||||||
</small>
|
|
||||||
</p>
|
|
||||||
</a>
|
|
||||||
@endforeach
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@if(Session::get('id') !== null)
|
@if(Session::get('id') !== null)
|
||||||
@@ -272,3 +248,48 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
@if(Session::get('id') !== null)
|
||||||
|
@push('script')
|
||||||
|
<script type="text/javascript">
|
||||||
|
(function () {
|
||||||
|
var refreshUrl = "{{ route('criticalValueNotificationSummary') }}";
|
||||||
|
var refreshIntervalMs = 20000;
|
||||||
|
var inFlight = null;
|
||||||
|
|
||||||
|
function setBadge(count) {
|
||||||
|
var $badge = $('#notificationcount');
|
||||||
|
$badge.text(count);
|
||||||
|
if (count > 0) $badge.show();
|
||||||
|
else $badge.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshCriticalBell() {
|
||||||
|
if (inFlight && inFlight.readyState !== 4) {
|
||||||
|
try { inFlight.abort(); } catch (e) {}
|
||||||
|
}
|
||||||
|
inFlight = $.ajax({
|
||||||
|
url: refreshUrl,
|
||||||
|
type: 'GET',
|
||||||
|
dataType: 'json',
|
||||||
|
cache: false,
|
||||||
|
success: function (data) {
|
||||||
|
var count = parseInt((data && data.count) ? data.count : 0, 10) || 0;
|
||||||
|
setBadge(count);
|
||||||
|
if (data && typeof data.menu_html === 'string') {
|
||||||
|
$('#notifikasi-verifikasi-bell').html(data.menu_html);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
setBadge(parseInt($('#notificationcount').text(), 10) || 0);
|
||||||
|
refreshCriticalBell();
|
||||||
|
setInterval(refreshCriticalBell, refreshIntervalMs);
|
||||||
|
$('#notification-bell-icon').closest('.dropdown').on('shown.bs.dropdown', refreshCriticalBell);
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
@endif
|
||||||
|
|||||||
@@ -18,6 +18,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
@if (session('error'))
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="alert alert-danger">{{ session('error') }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
@@ -36,6 +43,7 @@
|
|||||||
<th>No Foto</th>
|
<th>No Foto</th>
|
||||||
<th>No Register</th>
|
<th>No Register</th>
|
||||||
<th>Pasien</th>
|
<th>Pasien</th>
|
||||||
|
<th>Asal Pasien</th>
|
||||||
<th>Spesimen</th>
|
<th>Spesimen</th>
|
||||||
<th>Waktu Set Nilai Kritis</th>
|
<th>Waktu Set Nilai Kritis</th>
|
||||||
<th>Waktu Ditindaklanjuti</th>
|
<th>Waktu Ditindaklanjuti</th>
|
||||||
@@ -49,6 +57,7 @@
|
|||||||
<td>{{ $item->nofoto ?? '-' }}</td>
|
<td>{{ $item->nofoto ?? '-' }}</td>
|
||||||
<td>{{ $item->noregister ?? '-' }}</td>
|
<td>{{ $item->noregister ?? '-' }}</td>
|
||||||
<td>{{ $item->nmpasien ?? '-' }}</td>
|
<td>{{ $item->nmpasien ?? '-' }}</td>
|
||||||
|
<td>{{ $item->asalpasien ?? '-' }}</td>
|
||||||
<td>{{ $item->nm_spesimen ?? '-' }}</td>
|
<td>{{ $item->nm_spesimen ?? '-' }}</td>
|
||||||
<td>
|
<td>
|
||||||
{{ $item->critical_set_at ? \Carbon\Carbon::parse($item->critical_set_at)->format('d-m-Y H:i:s') : '-' }}
|
{{ $item->critical_set_at ? \Carbon\Carbon::parse($item->critical_set_at)->format('d-m-Y H:i:s') : '-' }}
|
||||||
@@ -60,6 +69,24 @@
|
|||||||
<td>
|
<td>
|
||||||
<form action="{{ route('criticalValueNotificationMarkRead', $item->id) }}" method="POST" class="mb-0">
|
<form action="{{ route('criticalValueNotificationMarkRead', $item->id) }}" method="POST" class="mb-0">
|
||||||
@csrf
|
@csrf
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="caratindaklanjut" class="col-form-label">Melalui <font color="red">*</font></label>
|
||||||
|
<select class="form-control" id="caratindaklanjut" name="caratindaklanjut">
|
||||||
|
<option value="">Belum di Laporkan</option>
|
||||||
|
<option value="Telpon">Telpon</option>
|
||||||
|
<option value="Whatshap">Whatshap</option>
|
||||||
|
<option value="Email">Email</option>
|
||||||
|
<option value="Ketemu di Jalan">Ketemu di Jalan</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="penerima_laporan" class="col-form-label">Penerima Laporan <font color="red">*</font></label>
|
||||||
|
<input type="text" id="penerima_laporan" name="penerima_laporan" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="alasan_belum_laporkan" class="col-form-label">Alasan Belum di Laporkan <font color="red">*</font></label>
|
||||||
|
<input type="text" id="alasan_belum_laporkan" name="alasan_belum_laporkan" class="form-control" placeholder="Isi jika belum di laporkan (Meninggal / Pindah Rumah Sakit / dll)">
|
||||||
|
</div>
|
||||||
<button type="submit" class="btn btn-sm btn-warning">Mark as Read</button>
|
<button type="submit" class="btn btn-sm btn-warning">Mark as Read</button>
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<div class="dropdown-item noti-title">
|
||||||
|
<h5 class="m-0">
|
||||||
|
<span class="float-right">
|
||||||
|
<a href="{{ route('criticalValueNotifications') }}" class="text-dark"><small>Lihat Semua</small></a>
|
||||||
|
</span>
|
||||||
|
Nilai Kritis
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div style="max-height: 320px; overflow-y: auto;">
|
||||||
|
@if(($items ?? collect())->isEmpty())
|
||||||
|
<div class="dropdown-item text-muted">Tidak ada sample nilai kritis yang perlu dilaporkan.</div>
|
||||||
|
@else
|
||||||
|
@foreach($items as $criticalItem)
|
||||||
|
<a href="{{ route('criticalValueNotificationOpen', $criticalItem->id) }}" class="dropdown-item notify-item">
|
||||||
|
<div class="notify-icon bg-warning"><i class="fa fa-exclamation-triangle"></i></div>
|
||||||
|
<p class="notify-details">
|
||||||
|
{{ $criticalItem->nofoto ?? '-' }} - {{ $criticalItem->nmpasien ?? 'Tanpa Nama' }}
|
||||||
|
<small class="text-muted">
|
||||||
|
Set: {{ $criticalItem->critical_set_at ? \Carbon\Carbon::parse($criticalItem->critical_set_at)->format('d-m-Y H:i:s') : '-' }}
|
||||||
|
</small>
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
@endforeach
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
@@ -58,6 +58,7 @@
|
|||||||
<th>Kode</th>
|
<th>Kode</th>
|
||||||
<th>Spesimen</th>
|
<th>Spesimen</th>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
|
<th>Batal Aksi</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody></tbody>
|
<tbody></tbody>
|
||||||
@@ -130,6 +131,11 @@
|
|||||||
$('#gridkiriman').DataTable().ajax.reload();
|
$('#gridkiriman').DataTable().ajax.reload();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function btnBatal(id){
|
||||||
|
$.post('{{ route("batalPeriksa") }}', { id: id, _token: '{{ csrf_token() }}'},function(data){
|
||||||
|
$('#gridkiriman').DataTable().ajax.reload();
|
||||||
|
});
|
||||||
|
}
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$("#tglreport").datepicker({format: 'yyyy-mm-dd'});
|
$("#tglreport").datepicker({format: 'yyyy-mm-dd'});
|
||||||
$("#mulai").datepicker({format: 'yyyy-mm-dd'});
|
$("#mulai").datepicker({format: 'yyyy-mm-dd'});
|
||||||
@@ -213,6 +219,8 @@
|
|||||||
{ data: 'kd_spesimen', name: 'kd_spesimen' },
|
{ data: 'kd_spesimen', name: 'kd_spesimen' },
|
||||||
{ data: 'nm_spesimen', name: 'nm_spesimen' },
|
{ data: 'nm_spesimen', name: 'nm_spesimen' },
|
||||||
{ data: 'tlsstatus', name: 'status' },
|
{ data: 'tlsstatus', name: 'status' },
|
||||||
|
{ data: 'batalaksi', name: 'batalaksi', orderable: false, searchable: false },
|
||||||
|
|
||||||
],
|
],
|
||||||
language: {
|
language: {
|
||||||
lengthMenu : "Tampilkan _MENU_ data per halaman",
|
lengthMenu : "Tampilkan _MENU_ data per halaman",
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ Route::group(['middleware' => 'project.ipg'], function() {
|
|||||||
Route::post('dokter/getListadendum', [DokterController::class, 'getListadendum'])->name('getListadendum');
|
Route::post('dokter/getListadendum', [DokterController::class, 'getListadendum'])->name('getListadendum');
|
||||||
Route::post('dokter/exprinttandaterima', [DokterController::class, 'exTandaTerima'])->name('exTandaTerima');
|
Route::post('dokter/exprinttandaterima', [DokterController::class, 'exTandaTerima'])->name('exTandaTerima');
|
||||||
Route::get('notifikasi/nilai-kritis', [DokterController::class, 'criticalValueNotifications'])->name('criticalValueNotifications');
|
Route::get('notifikasi/nilai-kritis', [DokterController::class, 'criticalValueNotifications'])->name('criticalValueNotifications');
|
||||||
|
Route::get('notifikasi/nilai-kritis/summary', [DokterController::class, 'criticalValueNotificationSummary'])->name('criticalValueNotificationSummary');
|
||||||
Route::get('notifikasi/nilai-kritis/{id}', [DokterController::class, 'criticalValueNotificationOpen'])->name('criticalValueNotificationOpen');
|
Route::get('notifikasi/nilai-kritis/{id}', [DokterController::class, 'criticalValueNotificationOpen'])->name('criticalValueNotificationOpen');
|
||||||
Route::post('notifikasi/nilai-kritis/{id}/mark-read', [DokterController::class, 'criticalValueNotificationMarkRead'])->name('criticalValueNotificationMarkRead');
|
Route::post('notifikasi/nilai-kritis/{id}/mark-read', [DokterController::class, 'criticalValueNotificationMarkRead'])->name('criticalValueNotificationMarkRead');
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user