diff --git a/htdocs/app/Http/Controllers/BiorepositoryController.php b/htdocs/app/Http/Controllers/BiorepositoryController.php
index 24a69bdf..41335a29 100644
--- a/htdocs/app/Http/Controllers/BiorepositoryController.php
+++ b/htdocs/app/Http/Controllers/BiorepositoryController.php
@@ -5,6 +5,7 @@ namespace App\Http\Controllers;
use App\BioCabinet;
use App\BioRack;
use App\BioSpecimen;
+use App\Periksa;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Session;
@@ -28,15 +29,6 @@ class BiorepositoryController extends Controller
->orderBy('id', 'DESC')
->get();
- $data['cabinets'] = BioCabinet::with([
- 'racks' => function ($query) {
- $query->orderBy('rack_number', 'ASC')->orderBy('code', 'ASC');
- },
- 'racks.specimens' => function ($query) {
- $query->orderBy('stored_at', 'ASC');
- },
- ])->orderBy('name', 'ASC')->get();
-
$data['oldestSpecimen'] = BioSpecimen::with(['cabinet', 'rack'])
->whereNotNull('stored_at')
->orderBy('stored_at', 'ASC')
@@ -79,7 +71,9 @@ class BiorepositoryController extends Controller
'cabinet_id' => 'required|exists:bio_cabinets,id',
'code' => 'required|max:50',
'name' => 'required|max:150',
+ 'slot_count' => 'required|integer|min:1|max:20',
'level' => 'required|integer|min:4|max:6',
+ 'box_number' => 'required|integer|min:1|max:20',
'capacity' => 'required|integer|min:16|max:100',
'notes' => 'nullable',
]);
@@ -102,9 +96,10 @@ class BiorepositoryController extends Controller
'cabinet_id' => $request->input('cabinet_id'),
'code' => $request->input('code'),
'name' => $request->input('name'),
+ 'slot_count' => $request->input('slot_count'),
'level' => $request->input('level'),
'rack_number' => $nextRackNumber,
- 'box_number' => 1,
+ 'box_number' => $request->input('box_number'),
'capacity' => $request->input('capacity'),
'notes' => $request->input('notes'),
]);
@@ -136,15 +131,23 @@ class BiorepositoryController extends Controller
$rack = BioRack::find($request->input('rack_id'));
$expectedRackNo = $rack->rack_number ?: $rack->id;
- $expectedBoxNo = $rack->box_number ?: 1;
+ $slotCount = (int) ($rack->slot_count ?: 1);
+ $boxCount = (int) ($rack->box_number ?: 1);
- if ((int) $request->input('raknomor') !== (int) $expectedRackNo ||
- (int) $request->input('boxnomor') !== (int) $expectedBoxNo) {
+ if ((int) $request->input('raknomor') !== (int) $expectedRackNo) {
return back()->withErrors(['slotnomor' => 'Posisi slot tidak sesuai dengan konfigurasi rack.'])->withInput();
}
+ if ((int) $request->input('slotnomor') < 1 || (int) $request->input('slotnomor') > $slotCount) {
+ return back()->withErrors(['slotnomor' => 'Slot melebihi konfigurasi rack.'])->withInput();
+ }
+
if ((int) $request->input('shelfnomor') < 1 || (int) $request->input('shelfnomor') > (int) $rack->level) {
- return back()->withErrors(['shelfnomor' => 'Shelf melebihi konfigurasi rack.'])->withInput();
+ return back()->withErrors(['shelfnomor' => 'Shelf melebihi konfigurasi slot.'])->withInput();
+ }
+
+ if ((int) $request->input('boxnomor') < 1 || (int) $request->input('boxnomor') > $boxCount) {
+ return back()->withErrors(['boxnomor' => 'Box melebihi konfigurasi shelf.'])->withInput();
}
if ((int) $request->input('tubenomor') < 1 || (int) $request->input('tubenomor') > (int) $rack->capacity) {
@@ -152,7 +155,9 @@ class BiorepositoryController extends Controller
}
$slotTaken = BioSpecimen::where('rack_id', $rack->id)
+ ->where('slot_number', $request->input('slotnomor'))
->where('shelf_number', $request->input('shelfnomor'))
+ ->where('box_number', $request->input('boxnomor'))
->where('tube_number', $request->input('tubenomor'))
->first();
@@ -209,7 +214,7 @@ class BiorepositoryController extends Controller
$sampleid = $request->input('sampleid');
if ($sampleid) {
$cekdata = Periksa::where('nofoto', $sampleid)->first();
- if (!$cekdata) {
+ if ($cekdata) {
$sampleid = $cekdata->id;
} else {
$sampleid = null;
@@ -226,7 +231,7 @@ class BiorepositoryController extends Controller
'category_storage' => $request->input('kategorisimpan'),
'shelf_number' => $request->input('shelfnomor'),
'rack_number' => $request->input('raknomor'),
- 'slot_number' => $request->input('shelfnomor'),
+ 'slot_number' => $request->input('slotnomor'),
'box_number' => $request->input('boxnomor'),
'tube_number' => $request->input('tubenomor'),
'bacteria_name' => $request->input('nmbakteri'),
diff --git a/htdocs/app/Http/Controllers/DokterController.php b/htdocs/app/Http/Controllers/DokterController.php
index 74f8adca..77f02d58 100644
--- a/htdocs/app/Http/Controllers/DokterController.php
+++ b/htdocs/app/Http/Controllers/DokterController.php
@@ -463,304 +463,298 @@ class DokterController extends Controller
if ($kerja == 'Draft'){
$iddokter = Session('id');
}
- if ($iddokter == 'Pilih' OR $iddokter == '' OR $iddokter == '0'){
- return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Error..!!', 'message' => 'Please Select Doctor Names']);
- return back();
- } else {
- $today = date('Y-m-d H:i:s');
- $periksa = Periksa::with(['getPasien', 'getPoli'])->find($idperiksa);
- $nm_spesimen = $periksa->nm_spesimen ?? '';
- $noregister = $periksa->noregister ?? '';
- $nmadendum = $periksa->nmadendum ?? '';
- $tglverifikasi = $periksa->verifikasi ?? $today;
-
- $cekganda = Periksa::where('noregister', $noregister)->where('nmadendum', $nmadendum)->where('nm_spesimen', 'SPUTUM')->where('id', '!=', $idperiksa)->get();
- $statusdraft = 'Proses Analisis Sampel';
- KomponenJawaban::where('accnumber', $nofoto)->where('template', $dlp)->delete();
- $data = $request->except(['_token', 'periksa_id', 'val01', 'val10', 'acc_number']);
- foreach ($data as $key => $value) {
- if ($value === "" || is_null($value) || $value === "Pilih Salah Satu") continue;
- if (is_array($value)) {
- KomponenJawaban::updateOrCreate(
- [
- 'accnumber' => $nofoto,
- 'komponen' => $key,
- ],
- [
- 'isidata' => json_encode($value),
- 'template' => $dlp,
- 'created_by' => session('nama'),
- ]
- );
+ $today = date('Y-m-d H:i:s');
+ $periksa = Periksa::with(['getPasien', 'getPoli'])->find($idperiksa);
+ $nm_spesimen = $periksa->nm_spesimen ?? '';
+ $noregister = $periksa->noregister ?? '';
+ $nmadendum = $periksa->nmadendum ?? '';
+ $tglverifikasi = $periksa->verifikasi ?? $today;
+
+ $cekganda = Periksa::where('noregister', $noregister)->where('nmadendum', $nmadendum)->where('nm_spesimen', 'SPUTUM')->where('id', '!=', $idperiksa)->get();
+ $statusdraft = 'Proses Analisis Sampel';
+ KomponenJawaban::where('accnumber', $nofoto)->where('template', $dlp)->delete();
+ $data = $request->except(['_token', 'periksa_id', 'val01', 'val10', 'acc_number']);
+ foreach ($data as $key => $value) {
+ if ($value === "" || is_null($value) || $value === "Pilih Salah Satu") continue;
+ if (is_array($value)) {
+ KomponenJawaban::updateOrCreate(
+ [
+ 'accnumber' => $nofoto,
+ 'komponen' => $key,
+ ],
+ [
+ 'isidata' => json_encode($value),
+ 'template' => $dlp,
+ 'created_by' => session('nama'),
+ ]
+ );
+ } else {
+ if ($key == 'id_statusmediatamlainnya' AND $value != ''){
+ $statusdraft = $value;
+ } else if ($key == 'id_statusmediasellainnya' AND $value != ''){
+ $statusdraft = $value;
+ } else if ($key == 'id_statusmediasda' AND $value != ''){
+ $statusdraft = $value;
+ } else if ($key == 'id_statusmediamcconkey' AND $value != ''){
+ $statusdraft = $value;
+ } else if ($key == 'id_statusmediacap' AND $value != ''){
+ $statusdraft = $value;
+ } else if ($key == 'id_statusmediabap' AND $value != ''){
+ $statusdraft = $value;
} else {
- if ($key == 'id_statusmediatamlainnya' AND $value != ''){
- $statusdraft = $value;
- } else if ($key == 'id_statusmediasellainnya' AND $value != ''){
- $statusdraft = $value;
- } else if ($key == 'id_statusmediasda' AND $value != ''){
- $statusdraft = $value;
- } else if ($key == 'id_statusmediamcconkey' AND $value != ''){
- $statusdraft = $value;
- } else if ($key == 'id_statusmediacap' AND $value != ''){
- $statusdraft = $value;
- } else if ($key == 'id_statusmediabap' AND $value != ''){
- $statusdraft = $value;
+ }
+ KomponenJawaban::updateOrCreate(
+ [
+ 'accnumber' => $nofoto,
+ 'komponen' => $key,
+ ],
+ [
+ 'isidata' => $value,
+ 'template' => $dlp,
+ 'created_by' => session('nama'),
+ ]
+ );
+ }
+ $yangperludicloning = '';
+ if ($dlp == 'Kultur'){
+ if ($key == 'id_selepitel'){ $yangperludicloning = 'lsg_selepitel'; }
+ if ($key == 'id_selradang'){ $yangperludicloning = 'lsg_selradang'; }
+ if ($key == 'id_mikroorganisme'){ $yangperludicloning = 'lsg_mikroorganisme'; }
+ if ($key == 'id_mikroorganismeoptional'){ $yangperludicloning = 'lsg_mikroorganismeoptional'; }
+ if ($key == 'id_pewarnaanziehlnielsen'){ $yangperludicloning = 'lsg_pewarnaanziehlnielsen'; }
+ if ($key == 'id_pewarnaanziehlnielsensewaktu'){ $yangperludicloning = 'lsg_pewarnaanziehlnielsensewaktu'; }
+ if ($key == 'id_pewarnaankoh'){ $yangperludicloning = 'lsg_pewarnaankoh'; }
+ if ($key == 'id_pewarnaankohoptional'){ $yangperludicloning = 'lsg_pewarnaankohoptional'; }
+ if ($key == 'id_pewarnaanneisser'){ $yangperludicloning = 'lsg_pewarnaanneisser'; }
+ if ($key == 'id_pewarnaannegatif'){ $yangperludicloning = 'lsg_pewarnaannegatif'; }
+ if ($key == 'id_pewarnaanspora'){ $yangperludicloning = 'lsg_pewarnaanspora'; }
+ if ($key == 'id_pewarnaangiesma'){ $yangperludicloning = 'lsg_pewarnaangiesma'; }
+ if ($key == 'id_pewarnaangiesmaoptional'){ $yangperludicloning = 'lsg_pewarnaangiesmaoptional'; }
+ } else {
+ if ($key == 'lsg_selepitel'){ $yangperludicloning = 'id_selepitel'; }
+ if ($key == 'lsg_selradang'){ $yangperludicloning = 'id_selradang'; }
+ if ($key == 'lsg_mikroorganisme'){ $yangperludicloning = 'id_mikroorganisme'; }
+ if ($key == 'lsg_mikroorganismeoptional'){ $yangperludicloning = 'id_mikroorganismeoptional'; }
+ if ($key == 'lsg_pewarnaanziehlnielsen'){ $yangperludicloning = 'id_pewarnaanziehlnielsen'; }
+ if ($key == 'lsg_pewarnaanziehlnielsensewaktu'){ $yangperludicloning = 'id_pewarnaanziehlnielsensewaktu'; }
+ if ($key == 'lsg_pewarnaankoh'){ $yangperludicloning = 'id_pewarnaankoh'; }
+ if ($key == 'lsg_pewarnaankohoptional'){ $yangperludicloning = 'id_pewarnaankohoptional'; }
+ if ($key == 'lsg_pewarnaanneisser'){ $yangperludicloning = 'id_pewarnaanneisser'; }
+ if ($key == 'lsg_pewarnaannegatif'){ $yangperludicloning = 'id_pewarnaannegatif'; }
+ if ($key == 'lsg_pewarnaanspora'){ $yangperludicloning = 'id_pewarnaanspora'; }
+ if ($key == 'lsg_pewarnaangiesma'){ $yangperludicloning = 'id_pewarnaangiesma'; }
+ if ($key == 'lsg_pewarnaangiesmaoptional'){ $yangperludicloning = 'id_pewarnaangiesmaoptional'; }
+ }
+ if ($nm_spesimen == 'SPUTUM' AND !empty($cekganda) AND $yangperludicloning != ''){
+ foreach($cekganda as $rcloning){
+ $nofotocloning = $rcloning->nofoto;
+ $dlpcloning = $rcloning->dlp ?? 'Kultur';
+ if (is_array($value)) {
+ KomponenJawaban::updateOrCreate(
+ [
+ 'accnumber' => $nofotocloning,
+ 'komponen' => $yangperludicloning,
+ ],
+ [
+ 'isidata' => json_encode($value),
+ 'template' => $dlpcloning,
+ 'created_by' => session('nama'),
+ ]
+ );
} else {
- }
- KomponenJawaban::updateOrCreate(
- [
- 'accnumber' => $nofoto,
- 'komponen' => $key,
- ],
- [
- 'isidata' => $value,
- 'template' => $dlp,
- 'created_by' => session('nama'),
- ]
- );
- }
- $yangperludicloning = '';
- if ($dlp == 'Kultur'){
- if ($key == 'id_selepitel'){ $yangperludicloning = 'lsg_selepitel'; }
- if ($key == 'id_selradang'){ $yangperludicloning = 'lsg_selradang'; }
- if ($key == 'id_mikroorganisme'){ $yangperludicloning = 'lsg_mikroorganisme'; }
- if ($key == 'id_mikroorganismeoptional'){ $yangperludicloning = 'lsg_mikroorganismeoptional'; }
- if ($key == 'id_pewarnaanziehlnielsen'){ $yangperludicloning = 'lsg_pewarnaanziehlnielsen'; }
- if ($key == 'id_pewarnaanziehlnielsensewaktu'){ $yangperludicloning = 'lsg_pewarnaanziehlnielsensewaktu'; }
- if ($key == 'id_pewarnaankoh'){ $yangperludicloning = 'lsg_pewarnaankoh'; }
- if ($key == 'id_pewarnaankohoptional'){ $yangperludicloning = 'lsg_pewarnaankohoptional'; }
- if ($key == 'id_pewarnaanneisser'){ $yangperludicloning = 'lsg_pewarnaanneisser'; }
- if ($key == 'id_pewarnaannegatif'){ $yangperludicloning = 'lsg_pewarnaannegatif'; }
- if ($key == 'id_pewarnaanspora'){ $yangperludicloning = 'lsg_pewarnaanspora'; }
- if ($key == 'id_pewarnaangiesma'){ $yangperludicloning = 'lsg_pewarnaangiesma'; }
- if ($key == 'id_pewarnaangiesmaoptional'){ $yangperludicloning = 'lsg_pewarnaangiesmaoptional'; }
- } else {
- if ($key == 'lsg_selepitel'){ $yangperludicloning = 'id_selepitel'; }
- if ($key == 'lsg_selradang'){ $yangperludicloning = 'id_selradang'; }
- if ($key == 'lsg_mikroorganisme'){ $yangperludicloning = 'id_mikroorganisme'; }
- if ($key == 'lsg_mikroorganismeoptional'){ $yangperludicloning = 'id_mikroorganismeoptional'; }
- if ($key == 'lsg_pewarnaanziehlnielsen'){ $yangperludicloning = 'id_pewarnaanziehlnielsen'; }
- if ($key == 'lsg_pewarnaanziehlnielsensewaktu'){ $yangperludicloning = 'id_pewarnaanziehlnielsensewaktu'; }
- if ($key == 'lsg_pewarnaankoh'){ $yangperludicloning = 'id_pewarnaankoh'; }
- if ($key == 'lsg_pewarnaankohoptional'){ $yangperludicloning = 'id_pewarnaankohoptional'; }
- if ($key == 'lsg_pewarnaanneisser'){ $yangperludicloning = 'id_pewarnaanneisser'; }
- if ($key == 'lsg_pewarnaannegatif'){ $yangperludicloning = 'id_pewarnaannegatif'; }
- if ($key == 'lsg_pewarnaanspora'){ $yangperludicloning = 'id_pewarnaanspora'; }
- if ($key == 'lsg_pewarnaangiesma'){ $yangperludicloning = 'id_pewarnaangiesma'; }
- if ($key == 'lsg_pewarnaangiesmaoptional'){ $yangperludicloning = 'id_pewarnaangiesmaoptional'; }
- }
- if ($nm_spesimen == 'SPUTUM' AND !empty($cekganda) AND $yangperludicloning != ''){
- foreach($cekganda as $rcloning){
- $nofotocloning = $rcloning->nofoto;
- $dlpcloning = $rcloning->dlp ?? 'Kultur';
- if (is_array($value)) {
- KomponenJawaban::updateOrCreate(
- [
- 'accnumber' => $nofotocloning,
- 'komponen' => $yangperludicloning,
- ],
- [
- 'isidata' => json_encode($value),
- 'template' => $dlpcloning,
- 'created_by' => session('nama'),
- ]
- );
- } else {
- KomponenJawaban::updateOrCreate(
- [
- 'accnumber' => $nofotocloning,
- 'komponen' => $yangperludicloning,
- ],
- [
- 'isidata' => $value,
- 'template' => $dlpcloning,
- 'created_by' => session('nama'),
- ]
- );
- }
+ KomponenJawaban::updateOrCreate(
+ [
+ 'accnumber' => $nofotocloning,
+ 'komponen' => $yangperludicloning,
+ ],
+ [
+ 'isidata' => $value,
+ 'template' => $dlpcloning,
+ 'created_by' => session('nama'),
+ ]
+ );
}
}
}
- $analis = $request->input('analis');
- $ppds3 = $request->input('ppds3');
- $cekdokter = optional(User::find($iddokter));
- $cekanalis = optional(User::find($analis));
- $cekppds3 = optional(User::find($ppds3));
- switch ($kerja) {
- case 'verifikasi':
- if ($periksa->status != 'Selesai'){
- $tglverifikasi = date('Y-m-d H:i:s');
- }
- $updateData = [
- 'keterangan' => $keterangan,
- 'dlp' => $dlp,
- 'analis' => $analis,
- 'nmanalis' => $cekanalis->nama ?? null,
- 'dokter_id' => Session('id'),
- 'nmdokter' => Session('nama'),
- 'ppdssenior' => $ppds3,
- 'nmppdssenior' => $cekppds3->nama ?? null,
- 'tandatangan' => '',
- 'verifikasi' => $tglverifikasi,
- 'akhir' => $tglverifikasi,
- 'nmexcutor' => Session('nama'),
- 'excutor' => Session('id'),
- 'status' => 'Selesai',
- ];
- $periksa->update($updateData);
- if ($this->shouldMarkAsCritical($request)) {
- $this->upsertCriticalValueSample($periksa);
- }
- $surat = self::genSurat($periksa->id, 'dengan kop');
+ }
+ $analis = $request->input('analis');
+ $ppds3 = $request->input('ppds3');
+ $cekdokter = optional(User::find($iddokter));
+ $cekanalis = optional(User::find($analis));
+ $cekppds3 = optional(User::find($ppds3));
+ switch ($kerja) {
+ case 'verifikasi':
+ if ($periksa->status != 'Selesai'){
+ $tglverifikasi = date('Y-m-d H:i:s');
+ }
+ $updateData = [
+ 'keterangan' => $keterangan,
+ 'dlp' => $dlp,
+ 'analis' => $analis,
+ 'nmanalis' => $cekanalis->nama ?? null,
+ 'dokter_id' => Session('id'),
+ 'nmdokter' => Session('nama'),
+ 'ppdssenior' => $ppds3,
+ 'nmppdssenior' => $cekppds3->nama ?? null,
+ 'tandatangan' => '',
+ 'verifikasi' => $tglverifikasi,
+ 'akhir' => $tglverifikasi,
+ 'nmexcutor' => Session('nama'),
+ 'excutor' => Session('id'),
+ 'status' => 'Selesai',
+ ];
+ $periksa->update($updateData);
+ if ($this->shouldMarkAsCritical($request)) {
+ $this->upsertCriticalValueSample($periksa);
+ }
+ $surat = self::genSurat($periksa->id, 'dengan kop');
+ Riwayat::create([
+ 'nofoto' => $nofoto,
+ 'jawaban' => $surat,
+ 'inputor' => Session('nama'),
+ 'verifikasi' => 'Accepted',
+ 'keterangan' => 'Expertise',
+ ]);
+ if (isset($addendumketerangan) AND $addendumketerangan != ''){
Riwayat::create([
'nofoto' => $nofoto,
- 'jawaban' => $surat,
+ 'jawaban' => $addendumketerangan,
'inputor' => Session('nama'),
'verifikasi' => 'Accepted',
- 'keterangan' => 'Expertise',
+ 'keterangan' => 'Addendum',
]);
- if (isset($addendumketerangan) AND $addendumketerangan != ''){
- Riwayat::create([
- 'nofoto' => $nofoto,
- 'jawaban' => $addendumketerangan,
- 'inputor' => Session('nama'),
- 'verifikasi' => 'Accepted',
- 'keterangan' => 'Addendum',
- ]);
- }
- if (is_null($nofoto)){
- return response()->json(['icon' => 'success', 'warna' => '#5ba035', 'status' => 'Sukses', 'message' => 'Expertise Verified']);
- } else {
- $pesan = 'Expertise Saved';
- return response()->json(['icon' => 'success', 'warna' => '#5ba035', 'status' => 'Sukses', 'message' => $pesan]);
- }
- case 'statuspewarnaanlsg':
- $periksa->update([
- 'keterangan' => $keterangan,
- 'dlp' => $dlp,
- 'analis' => $analis,
- 'nmanalis' => $cekanalis->nama ?? null,
- 'nmdrafter' => Session('nama'),
- 'nmexcutor' => Session('nama'),
- 'excutor' => Session('id'),
- 'status' => 'Pewarnaan Langsung'
- ]);
- return response()->json(['icon' => 'success', 'status' => 'Success', 'message' => 'Set Status Pewarnaan Langsung']);
- case 'preliminary':
- $updateData = [
- 'keterangan' => $keterangan,
- 'dlp' => $dlp,
- 'analis' => $analis,
- 'nmanalis' => $cekanalis->nama ?? null,
- 'dokter_id' => Session('id'),
- 'nmdokter' => Session('nama'),
- 'ppdssenior' => $ppds3,
- 'nmppdssenior' => $cekppds3->nama ?? null,
- 'tandatangan' => '',
- 'verifikasi' => $tglverifikasi,
- 'nmexcutor' => Session('nama'),
- 'excutor' => Session('id'),
- 'status' => 'Preliminary Results',
- ];
- $periksa->update($updateData);
- if ($this->shouldMarkAsCritical($request)) {
- $this->upsertCriticalValueSample($periksa);
- }
- $surat = self::genSurat($periksa->id, 'dengan kop');
- Riwayat::create([
- 'nofoto' => $nofoto,
- 'jawaban' => $surat,
- 'inputor' => Session('nama'),
- 'verifikasi' => 'Accepted',
- 'keterangan' => 'Preliminary Results',
- ]);
- $pesan = 'Preliminary Results Saved';
+ }
+ if (is_null($nofoto)){
+ return response()->json(['icon' => 'success', 'warna' => '#5ba035', 'status' => 'Sukses', 'message' => 'Expertise Verified']);
+ } else {
+ $pesan = 'Expertise Saved';
return response()->json(['icon' => 'success', 'warna' => '#5ba035', 'status' => 'Sukses', 'message' => $pesan]);
- case 'Permohonan Verifikasi':
- $updateData = [
- 'keterangan' => $keterangan,
- 'dlp' => $dlp,
- 'analis' => $analis,
- 'nmanalis' => $cekanalis->nama ?? null,
- 'dokter_id' => $iddokter,
- 'nmdokter' => $cekdokter->nama ?? null,
- 'ppdssenior' => $ppds3,
- 'nmppdssenior' => $cekppds3->nama ?? null,
- 'tandatangan' => '',
- 'baca' => $today,
- 'nmexcutor' => Session('nama'),
- 'excutor' => Session('id'),
- 'nmpembaca' => Session('nama'),
- 'status' => 'Expertise Saved (Un Verified)',
- ];
- $periksa->update($updateData);
- $surat = self::genSurat($periksa->id, 'dengan kop');
- Riwayat::create([
- 'nofoto' => $nofoto,
- 'jawaban' => $surat,
- 'inputor' => Session('nama'),
+ }
+ case 'statuspewarnaanlsg':
+ $periksa->update([
+ 'keterangan' => $keterangan,
+ 'dlp' => $dlp,
+ 'analis' => $analis,
+ 'nmanalis' => $cekanalis->nama ?? null,
+ 'nmdrafter' => Session('nama'),
+ 'nmexcutor' => Session('nama'),
+ 'excutor' => Session('id'),
+ ]);
+ return response()->json(['icon' => 'success', 'status' => 'Success', 'message' => 'Set Status Pewarnaan Langsung']);
+ case 'preliminary':
+ $updateData = [
+ 'keterangan' => $keterangan,
+ 'dlp' => $dlp,
+ 'analis' => $analis,
+ 'nmanalis' => $cekanalis->nama ?? null,
+ 'dokter_id' => Session('id'),
+ 'nmdokter' => Session('nama'),
+ 'ppdssenior' => $ppds3,
+ 'nmppdssenior' => $cekppds3->nama ?? null,
+ 'tandatangan' => '',
+ 'verifikasi' => $tglverifikasi,
+ 'nmexcutor' => Session('nama'),
+ 'excutor' => Session('id'),
+ 'status' => 'Preliminary Results',
+ ];
+ $periksa->update($updateData);
+ if ($this->shouldMarkAsCritical($request)) {
+ $this->upsertCriticalValueSample($periksa);
+ }
+ $surat = self::genSurat($periksa->id, 'dengan kop');
+ Riwayat::create([
+ 'nofoto' => $nofoto,
+ 'jawaban' => $surat,
+ 'inputor' => Session('nama'),
+ 'verifikasi' => 'Accepted',
+ 'keterangan' => 'Preliminary Results',
+ ]);
+ $pesan = 'Preliminary Results Saved';
+ return response()->json(['icon' => 'success', 'warna' => '#5ba035', 'status' => 'Sukses', 'message' => $pesan]);
+ case 'Permohonan Verifikasi':
+ $updateData = [
+ 'keterangan' => $keterangan,
+ 'dlp' => $dlp,
+ 'analis' => $analis,
+ 'nmanalis' => $cekanalis->nama ?? null,
+ 'dokter_id' => $iddokter,
+ 'nmdokter' => $cekdokter->nama ?? null,
+ 'ppdssenior' => $ppds3,
+ 'nmppdssenior' => $cekppds3->nama ?? null,
+ 'tandatangan' => '',
+ 'baca' => $today,
+ 'nmexcutor' => Session('nama'),
+ 'excutor' => Session('id'),
+ 'nmpembaca' => Session('nama'),
+ 'status' => 'Expertise Saved (Un Verified)',
+ ];
+ $periksa->update($updateData);
+ $surat = self::genSurat($periksa->id, 'dengan kop');
+ Riwayat::create([
+ 'nofoto' => $nofoto,
+ 'jawaban' => $surat,
+ 'inputor' => Session('nama'),
+ 'verifikasi' => 'Accepted',
+ 'keterangan' => 'Kirim ke SPV',
+ ]);
+ return response()->json(['icon' => 'success', 'warna' => '#5ba035', 'status' => 'Sukses', 'message' => 'Permohonan Verifikasi Terkirim']);
+ case 'tolakadendum':
+ Riwayat::where('nofoto', $nofoto)->whereNull('verifikasi')->update([
+ 'verifikasi' => 'Declined',
+ ]);
+ return response()->json(['icon' => 'success', 'status' => 'Success', 'message' => 'Addendum Declined']);
+ case 'Draft':
+ $periksa->update([
+ 'keterangan' => $keterangan,
+ 'dlp' => $dlp,
+ 'analis' => $analis,
+ 'nmanalis' => $cekanalis->nama ?? null,
+ 'nmdrafter' => Session('nama'),
+ 'nmexcutor' => Session('nama'),
+ 'excutor' => Session('id'),
+ 'status' => $statusdraft
+ ]);
+ $surat = self::genSurat($periksa->id, 'dengan kop');
+ Riwayat::create([
+ 'nofoto' => $nofoto,
+ 'jawaban' => $surat,
+ 'inputor' => Session('nama'),
+ 'verifikasi' => '',
+ 'keterangan' => 'Draft',
+ ]);
+ return response()->json(['icon' => 'success', 'status' => 'Success', 'message' => 'Draft Expertise Saved']);
+ case 'terimadendum':
+ $getid = Riwayat::where('keterangan', 'Adendum')->where('nofoto', $nofoto)->whereNull('verifikasi')->first();
+ if (isset($getid->id)){
+ Riwayat::where('id', $getid->id)->update([
'verifikasi' => 'Accepted',
- 'keterangan' => 'Kirim ke SPV',
]);
- return response()->json(['icon' => 'success', 'warna' => '#5ba035', 'status' => 'Sukses', 'message' => 'Permohonan Verifikasi Terkirim']);
- case 'tolakadendum':
- Riwayat::where('nofoto', $nofoto)->whereNull('verifikasi')->update([
- 'verifikasi' => 'Declined',
- ]);
- return response()->json(['icon' => 'success', 'status' => 'Success', 'message' => 'Addendum Declined']);
- case 'Draft':
- $periksa->update([
- 'keterangan' => $keterangan,
- 'dlp' => $dlp,
- 'analis' => $analis,
- 'nmanalis' => $cekanalis->nama ?? null,
- 'nmdrafter' => Session('nama'),
+ Periksa::where('nofoto', $getid->nofoto)->update([
'nmexcutor' => Session('nama'),
'excutor' => Session('id'),
- 'status' => $statusdraft
+ 'tgladendum' => now(),
+ 'keterangan' => $getid->jawaban
]);
- $surat = self::genSurat($periksa->id, 'dengan kop');
- Riwayat::create([
- 'nofoto' => $nofoto,
- 'jawaban' => $surat,
- 'inputor' => Session('nama'),
- 'verifikasi' => '',
- 'keterangan' => 'Draft',
- ]);
- return response()->json(['icon' => 'success', 'status' => 'Success', 'message' => 'Draft Expertise Saved']);
- case 'terimadendum':
- $getid = Riwayat::where('keterangan', 'Adendum')->where('nofoto', $nofoto)->whereNull('verifikasi')->first();
- if (isset($getid->id)){
- Riwayat::where('id', $getid->id)->update([
- 'verifikasi' => 'Accepted',
- ]);
- Periksa::where('nofoto', $getid->nofoto)->update([
- 'nmexcutor' => Session('nama'),
- 'excutor' => Session('id'),
- 'tgladendum' => now(),
- 'keterangan' => $getid->jawaban
- ]);
- return response()->json(['icon' => 'success', 'status' => 'Success', 'message' => 'Addendum Accepted']);
- } else {
- return response()->json(['icon' => 'error', 'status' => 'Gagal', 'message' => 'Addendum Data Cannot Be Found']);
- }
- default:
- $periksa->update([
- 'keterangan' => $keterangan,
- 'dlp' => $dlp,
- 'analis' => $analis,
- 'nmanalis' => $cekanalis->nama ?? null,
- 'dokter_id' => $iddokter,
- 'nmdokter' => $cekdokter->nama ?? null,
- 'ppdssenior' => $ppds3,
- 'nmppdssenior' => $cekppds3->nama ?? null,
- 'nmdrafter' => Session('nama'),
- 'nmexcutor' => Session('nama'),
- 'excutor' => Session('id'),
- 'status' => $statusdraft
- ]);
- return response()->json(['icon' => 'success', 'status' => 'Success', 'message' => 'Expertise Saved']);
- }
+ return response()->json(['icon' => 'success', 'status' => 'Success', 'message' => 'Addendum Accepted']);
+ } else {
+ return response()->json(['icon' => 'error', 'status' => 'Gagal', 'message' => 'Addendum Data Cannot Be Found']);
+ }
+ default:
+ $periksa->update([
+ 'keterangan' => $keterangan,
+ 'dlp' => $dlp,
+ 'analis' => $analis,
+ 'nmanalis' => $cekanalis->nama ?? null,
+ 'dokter_id' => $iddokter,
+ 'nmdokter' => $cekdokter->nama ?? null,
+ 'ppdssenior' => $ppds3,
+ 'nmppdssenior' => $cekppds3->nama ?? null,
+ 'nmdrafter' => Session('nama'),
+ 'nmexcutor' => Session('nama'),
+ 'excutor' => Session('id'),
+ 'status' => $statusdraft
+ ]);
+ return response()->json(['icon' => 'success', 'status' => 'Success', 'message' => 'Expertise Saved']);
}
}
protected function shouldMarkAsCritical(Request $request): bool
@@ -1245,64 +1239,59 @@ class DokterController extends Controller
$cekdatanmaddendum = Periksa::where('nofoto', $nofoto)->first();
$tgldaftarpasangan = $cekdatanmaddendum->daftar ?? '';
$nmadendum = $cekdatanmaddendum->nmadendum ?? '';
- /*
- sudah OK tinggal di uncoment saja klo perlu cloning data dari pasangan
- if ($nmadendum != ''){
- $getdatapasangannya = Periksa::where('nmadendum', $nmadendum)->where('nm_spesimen', 'SPUTUM')->where('nofoto', '!=', $nofoto)->get();
+ $getdatapasangannya = Periksa::where('nmadendum', $nmadendum)->where('nofoto', '!=', $nofoto)->get();
+ if (!empty($getdatapasangannya)){
foreach ($getdatapasangannya as $item){
$datayangperludicloning = KomponenJawaban::where('accnumber', $item->nofoto)->get();
foreach ($datayangperludicloning as $rclone){
- $ceksudahcloning = KomponenJawaban::where('accnumber', $nofoto)
- ->where('komponen', $rclone->komponen)
- ->where('template', $ruangan)->count();
- if ($ceksudahcloning == 0){
- $komponen = '';
- if ($rclone->komponen == 'lsg_selepitel'){
- $komponen = 'id_selepitel';
- }
- if ($rclone->komponen == 'id_selepitel'){
- $komponen = 'lsg_selepitel';
- }
- if ($rclone->komponen == 'lsg_selradang'){
- $komponen = 'id_selradang';
- }
- if ($rclone->komponen == 'id_selradang'){
- $komponen = 'lsg_selradang';
- }
- if ($rclone->komponen == 'lsg_mikroorganisme'){
- $komponen = 'id_mikroorganisme';
- }
- if ($rclone->komponen == 'id_mikroorganisme'){
- $komponen = 'lsg_mikroorganisme';
- }
- if ($rclone->komponen == 'lsg_mikroorganismeoptional'){
- $komponen = 'id_mikroorganismeoptional';
- }
- if ($rclone->komponen == 'id_mikroorganismeoptional'){
- $komponen = 'lsg_mikroorganismeoptional';
- }
- if ($rclone->komponen == 'lsg_mikroorganismeoptional'){
- $komponen = 'id_mikroorganismeoptional';
- }
- if ($rclone->komponen == 'id_mikroorganismeoptional'){
- $komponen = 'lsg_mikroorganismeoptional';
- }
- if ($komponen != ''){
- KomponenJawaban::create([
- 'accnumber' => $nofoto,
- 'template' => $ruangan,
- 'komponen' => $komponen,
- 'isidata' => $rclone->isidata,
- 'created_by' => Session('nama')
- ]);
- }
-
+ $komponenterclone = '';
+ if ($rclone->komponen == 'lsg_selepitel'){
+ $komponenterclone = 'id_selepitel';
+ }
+ if ($rclone->komponen == 'id_selepitel'){
+ $komponenterclone = 'lsg_selepitel';
+ }
+ if ($rclone->komponen == 'lsg_selradang'){
+ $komponenterclone = 'id_selradang';
+ }
+ if ($rclone->komponen == 'id_selradang'){
+ $komponenterclone = 'lsg_selradang';
+ }
+ if ($rclone->komponen == 'lsg_mikroorganisme'){
+ $komponenterclone = 'id_mikroorganisme';
+ }
+ if ($rclone->komponen == 'id_mikroorganisme'){
+ $komponenterclone = 'lsg_mikroorganisme';
+ }
+ if ($rclone->komponen == 'lsg_mikroorganismeoptional'){
+ $komponenterclone = 'id_mikroorganismeoptional';
+ }
+ if ($rclone->komponen == 'id_mikroorganismeoptional'){
+ $komponenterclone = 'lsg_mikroorganismeoptional';
+ }
+ if ($rclone->komponen == 'lsg_mikroorganismeoptional'){
+ $komponenterclone = 'id_mikroorganismeoptional';
+ }
+ $ceksudahcloning = KomponenJawaban::where('accnumber', $rclone->accnumber)->where('komponen', $komponenterclone)->count();
+ if ($ceksudahcloning == 0 AND $komponenterclone != ''){
+ KomponenJawaban::create([
+ 'accnumber' => $rclone->accnumber,
+ 'template' => $ruangan,
+ 'komponen' => $komponenterclone,
+ 'isidata' => $rclone->isidata,
+ 'created_by' => Session('nama')
+ ]);
+ Riwayat::create([
+ 'nofoto' => $rclone->accnumber,
+ 'jawaban' => $rclone->isidata,
+ 'inputor' => Session('nama'),
+ 'keterangan' => 'Clone Data '.$komponenterclone.' Dari ('.$nofoto.')',
+ 'verifikasi' => '',
+ ]);
}
}
}
}
-
- */
KomponenJawaban::where('accnumber', $nofoto)->where('template', 'all')->update([
'template' => $ruangan,
]);
@@ -2309,96 +2298,6 @@ class DokterController extends Controller
]);
}
return $pesan;
- } else if ($worklist == 'getbbachtect' OR $worklist == 'getmgit' OR $worklist == 'getabbot'){
- $isidata = $request->input('isi');
- try {
- $ketemu = '';
- $nomor = 1;
- $cekdatalangsung = DataListiner::where('no_id', $nofoto)->whereIn('alat', ['BD Mikro 1', 'BD Mikro 2'])->first();
- $ketemu = $cekdatalangsung->organisme ?? '';
- if ($ketemu == ''){
- $cekada = ResultSample::where('accession_number', 'LIKE', $nofoto.'%')->get();
- if (!empty($cekada)){
- foreach($cekada as $rows){
- $ketemu = $rows->test_status;
- }
- } else {
- $cekdata = DB::table('lis_phoenix')->where('no_id', $nofoto)->first();
- $ketemu = $cekdata->organisme ?? '';
- }
- }
-
- if ($ketemu != ''){
- if ($isidata == '' OR is_null($isidata)){
- $isidata = $ketemu;
- } else {
- $isidata = $isidata.'
'.$ketemu;
- }
- } else {
-
- }
- if ($isidata == '' OR is_null($isidata)){
-
- } else {
- KomponenJawaban::updateOrCreate(
- [
- 'accnumber' => $nofoto,
- 'template' => $request->input('jenis'),
- 'komponen' => $request->input('komponen'),
- ],
- [
- 'isidata' => $isidata,
- 'created_by' => Session('nama')
- ]
- );
- }
- $pesan = $isidata;
- }catch (Exception $e) {
- $pesan = $isidata.'
'.$e->getMessage();
- }
- return $pesan;
- } else if ($worklist == 'getgenexpert'){
- $isidata = $request->input('isi');
- try {
- $cekdata = Periksa::where('nofoto', $nofoto)->first();
- $noregister = $cekdata->noregister ?? '';
- $url = 'http://10.10.120.14:6002/api/genexpert/query-result';
-
- $response = Http::withHeaders([
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- ])->timeout(30)
- ->post($url, [
- 'accnumber' => $nofoto,
- 'register_no' => $noregister,
- ]);
- $body = $response->json();
- $errorMessage = $body['message'] ?? 'Unknown Error';
- $details = json_decode($errorMessage, true);
- if (json_last_error() === JSON_ERROR_NONE && isset($details['message'])) {
- $pesan = $details['message'];
- } else {
- $pesan = $errorMessage;
- }
- if ($response->successful()) {
- Log::info('requestResult.', [
- 'status' => $response->status(),
- 'message' => $response->json()
- ]);
- }
-
- Log::error('Exception dalam fungsi requestResult.', [
- 'status' => $response->status(),
- 'message' => 'Python Server Error: ' . $response->body()
- ]);
- } catch (Exception $e) {
- $pesan = (is_null($isidata) ? '' : $isidata . '
') . 'Error: ' . $e->getMessage();
- Log::error('Exception dalam fungsi requestResult.', [
- 'sample_id' => $nofoto,
- 'exception' => $e->getMessage()
- ]);
- }
- return response($pesan, 200);
} else if ($worklist == 'addviralload'){
$tabelawal = $request->input('tabelawal');
$idtabel = $request->input('idtabel');
@@ -2526,7 +2425,7 @@ class DokterController extends Controller
} else if ($worklist == 'generatetblpertumbuhankoloni'){
$orderid = $request->input('nofoto');
$media = $request->input('komponen');
- $sql = DB::table('pertumkolomni')->where('orderid', $orderid)->where('media', $media)->get();
+ $sql = DB::table('pertumkolomni')->where('orderid', $orderid)->where('media', $media)->orderBy('id', 'asc')->get();
return $sql;
} else {
$periksa = Periksa::where('id', $idperiksa)->first();
diff --git a/htdocs/app/Http/Controllers/ReportController.php b/htdocs/app/Http/Controllers/ReportController.php
index 6e6f67ea..5aae0f19 100644
--- a/htdocs/app/Http/Controllers/ReportController.php
+++ b/htdocs/app/Http/Controllers/ReportController.php
@@ -1136,7 +1136,6 @@ class ReportController extends Controller
}
public function genTATreport(Request $request) {
- $data = [];
$bulan = $request->input('bulan');
$tahun = $request->input('tahun');
if ($tahun == '' OR is_null($tahun)){
@@ -1146,59 +1145,55 @@ class ReportController extends Controller
$bulan = str_replace('bulan=', '', $bulan);
$tahun = str_replace('tahun=', '', $tahun);
}
- $query = Periksa::select('*');
- if ($bulan !== 'ALL') {
- $query->whereMonth('mulai', $bulan);
- }
- $periksa = $query->whereYear('mulai', $tahun)->orderBy('mulai', 'ASC')->get();
+ $startDate = $bulan === 'ALL'
+ ? Carbon::createFromDate((int) $tahun, 1, 1)->startOfYear()
+ : Carbon::createFromDate((int) $tahun, (int) $bulan, 1)->startOfMonth();
+ $endDate = $bulan === 'ALL'
+ ? Carbon::createFromDate((int) $tahun, 1, 1)->endOfYear()
+ : Carbon::createFromDate((int) $tahun, (int) $bulan, 1)->endOfMonth();
- if ($periksa->count() == 0) {
+ $query = DB::table('periksa')
+ ->leftJoin('poli', 'poli.id', '=', 'periksa.poli_id')
+ ->select('periksa.id', 'periksa.kd_spesimen', 'periksa.mulai', 'periksa.verifikasi', 'poli.modaliti2')
+ ->whereBetween('periksa.mulai', [$startDate->toDateTimeString(), $endDate->toDateTimeString()]);
+
+ $rekapRows = [];
+ $query->chunkById(1000, function ($rows) use (&$rekapRows) {
+ foreach ($rows as $row) {
+ $key = $row->kd_spesimen ?: '-';
+ if (!isset($rekapRows[$key])) {
+ $rekapRows[$key] = [
+ 'jenis_pemeriksaan' => $key,
+ 'memenuhi' => 0,
+ 'tidak_memenuhi' => 0,
+ 'tidak_ada_hasil' => 0,
+ 'total' => 0,
+ ];
+ }
+
+ if (empty($row->verifikasi)) {
+ $rekapRows[$key]['tidak_ada_hasil']++;
+ } else {
+ $target = $this->resolveTatTargetDays($row->modaliti2 ?? '1');
+ $status = $this->resolveTatStatus($row->mulai, $row->verifikasi, $target);
+ if ($status === 'MEMENUHI TARGET') {
+ $rekapRows[$key]['memenuhi']++;
+ } else {
+ $rekapRows[$key]['tidak_memenuhi']++;
+ }
+ }
+ $rekapRows[$key]['total']++;
+ }
+ }, 'periksa.id', 'id');
+
+ if (empty($rekapRows)) {
return response()->json([]);
}
- $accnumbers = $periksa->pluck('nofoto')->toArray();
- $komponen = DB::table('db_komponenjawaban')->whereIn('accnumber', $accnumbers)->whereIn('komponen', ['id_bakteri01','id_bakteri02','id_mikroorganisme'])->get()->groupBy('accnumber');
- $poli = DB::table('poli')->whereIn('id', $periksa->pluck('poli_id'))->get()->keyBy('id');
- $hasil = $periksa->map(function($row) use ($komponen, $poli){
- $k = $komponen[$row->nofoto] ?? collect([]);
- $row->id_bakteri01 = optional($k->firstWhere('komponen', 'id_bakteri01'))->isidata;
- $row->id_bakteri02 = optional($k->firstWhere('komponen', 'id_bakteri02'))->isidata;
- $row->bakteri = optional($k->firstWhere('komponen', 'bakteri'))->isidata;
- $row->filefoto = "nofoto)."'>$row->nofoto";
- $p = $poli[$row->poli_id] ?? null;
- $row->subpoli = $p->subpoli ?? null;
- $target = $p->modaliti2 ?? '1';
- $row->modaliti2 = $target;
- if (!empty($row->verifikasi)) {
- $selisih_hari = Carbon::parse($row->mulai)->diffInDays(Carbon::parse($row->verifikasi));
- $target = intval($target);
- $hari = intval($selisih_hari);
- $row->selisih_hari = $selisih_hari;
- if ($hari <= $target) {
- $row->status_target = "MEMENUHI TARGET";
- } else {
- $row->status_target = "TIDAK MEMENUHI TARGET";
- }
- } else {
- $row->selisih_hari = null;
- $row->status_target = "TIDAK ADA HASIL";
- }
- return $row;
- });
- $rekap = $hasil->groupBy('kd_spesimen')->map(function($group){
- return [
- 'jenis_pemeriksaan' => $group->first()->kd_spesimen,
- 'memenuhi' => $group->where('status_target', 'MEMENUHI TARGET')->count(),
- 'tidak_memenuhi' => $group->where('status_target', 'TIDAK MEMENUHI TARGET')->count(),
- 'tidak_ada_hasil' => $group->where('status_target', 'TIDAK ADA HASIL')->count(),
- 'total' => $group->count()
- ];
-
- })->values();
+ $rekap = collect(array_values($rekapRows));
return view('cetak.tatreport', [
'bulan' => $bulan,
'tahun' => $tahun,
- 'detail' => $hasil,
'rekap' => $rekap
]);
}
diff --git a/htdocs/app/Livewire/BiorepositoryVisual.php b/htdocs/app/Livewire/BiorepositoryVisual.php
new file mode 100644
index 00000000..a2c59350
--- /dev/null
+++ b/htdocs/app/Livewire/BiorepositoryVisual.php
@@ -0,0 +1,101 @@
+selectedCabinetId = BioCabinet::orderBy('name', 'ASC')->value('id');
+ }
+
+ public function selectCabinet(int $cabinetId): void
+ {
+ $this->selectedCabinetId = $cabinetId;
+ $this->selectedRackId = null;
+ $this->resetPosition();
+ }
+
+ public function selectRack(int $rackId): void
+ {
+ $this->selectedRackId = $rackId;
+ $this->resetPosition();
+ }
+
+ public function selectSlot(int $slot): void
+ {
+ $this->selectedSlot = $slot;
+ $this->selectedShelf = null;
+ $this->selectedBox = null;
+ }
+
+ public function selectShelf(int $shelf): void
+ {
+ $this->selectedShelf = $shelf;
+ $this->selectedBox = null;
+ }
+
+ public function selectBox(int $box): void
+ {
+ $this->selectedBox = $box;
+ }
+
+ public function render()
+ {
+ $cabinets = BioCabinet::withCount(['racks', 'specimens'])
+ ->orderBy('name', 'ASC')
+ ->get();
+
+ if (!$this->selectedCabinetId && $cabinets->isNotEmpty()) {
+ $this->selectedCabinetId = (int) $cabinets->first()->id;
+ }
+
+ $selectedCabinet = $this->selectedCabinetId
+ ? BioCabinet::with([
+ 'racks' => function ($query) {
+ $query->withCount('specimens')
+ ->orderBy('rack_number', 'ASC')
+ ->orderBy('code', 'ASC');
+ },
+ ])->find($this->selectedCabinetId)
+ : null;
+
+ $selectedRack = $this->selectedRackId
+ ? BioRack::with(['specimens' => function ($query) {
+ $query->orderBy('slot_number', 'ASC')
+ ->orderBy('shelf_number', 'ASC')
+ ->orderBy('box_number', 'ASC')
+ ->orderBy('tube_number', 'ASC');
+ }])->find($this->selectedRackId)
+ : null;
+
+ if ($selectedRack && (int) $selectedRack->cabinet_id !== (int) $this->selectedCabinetId) {
+ $selectedRack = null;
+ $this->selectedRackId = null;
+ $this->resetPosition();
+ }
+
+ return view('livewire.biorepository-visual', [
+ 'cabinets' => $cabinets,
+ 'selectedCabinet' => $selectedCabinet,
+ 'selectedRack' => $selectedRack,
+ ]);
+ }
+
+ private function resetPosition(): void
+ {
+ $this->selectedSlot = null;
+ $this->selectedShelf = null;
+ $this->selectedBox = null;
+ }
+}
diff --git a/htdocs/database/migrations/2026_06_25_000001_add_slot_count_to_bio_racks_table.php b/htdocs/database/migrations/2026_06_25_000001_add_slot_count_to_bio_racks_table.php
new file mode 100644
index 00000000..e7844732
--- /dev/null
+++ b/htdocs/database/migrations/2026_06_25_000001_add_slot_count_to_bio_racks_table.php
@@ -0,0 +1,40 @@
+integer('slot_count')->default(1)->after('name');
+ }
+ });
+
+ DB::table('bio_racks')
+ ->where(function ($query) {
+ $query->whereNull('slot_count')
+ ->orWhere('slot_count', '<=', 1);
+ })
+ ->orderBy('id')
+ ->get(['id', 'level'])
+ ->each(function ($rack) {
+ DB::table('bio_racks')
+ ->where('id', $rack->id)
+ ->update(['slot_count' => max((int) ($rack->level ?? 1), 1)]);
+ });
+ }
+
+ public function down(): void
+ {
+ Schema::table('bio_racks', function (Blueprint $table) {
+ if (Schema::hasColumn('bio_racks', 'slot_count')) {
+ $table->dropColumn('slot_count');
+ }
+ });
+ }
+};
diff --git a/htdocs/resources/views/admin/biorepository.blade.php b/htdocs/resources/views/admin/biorepository.blade.php
index 0736c671..998e7326 100644
--- a/htdocs/resources/views/admin/biorepository.blade.php
+++ b/htdocs/resources/views/admin/biorepository.blade.php
@@ -17,6 +17,72 @@
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 12px;
}
+ .bio-step-panel {
+ border: 1px solid #d7e3ef;
+ border-radius: 8px;
+ background: #ffffff;
+ padding: 12px;
+ margin-bottom: 14px;
+ }
+ .bio-step-title {
+ font-weight: 700;
+ color: #1b3a57;
+ margin-bottom: 10px;
+ }
+ .bio-choice-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
+ gap: 10px;
+ }
+ .bio-choice-wrap {
+ position: relative;
+ }
+ .bio-choice {
+ display: block;
+ width: 100%;
+ min-height: 92px;
+ border: 1px solid #d7e3ef;
+ border-radius: 6px;
+ background: #f8fbff;
+ color: #1b3a57;
+ text-align: left;
+ padding: 10px;
+ cursor: pointer;
+ }
+ .bio-choice strong,
+ .bio-choice span,
+ .bio-choice small {
+ display: block;
+ }
+ .bio-choice small {
+ color: #6c757d;
+ margin-top: 3px;
+ }
+ .bio-choice.active,
+ .bio-number.active {
+ border-color: #188ae2;
+ background: #eaf5ff;
+ box-shadow: inset 0 0 0 1px #188ae2;
+ }
+ .bio-delete-form {
+ position: absolute;
+ top: 8px;
+ right: 8px;
+ }
+ .bio-number-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
+ gap: 8px;
+ }
+ .bio-number {
+ border: 1px solid #d7e3ef;
+ border-radius: 6px;
+ background: #f8fbff;
+ color: #1b3a57;
+ padding: 9px 6px;
+ cursor: pointer;
+ text-align: center;
+ }
.rack-box {
border: 1px solid #d7e3ef;
border-radius: 10px;
@@ -58,6 +124,7 @@
cursor: pointer;
text-align: center;
width: 100%;
+ min-height: 34px;
}
.slot-btn.slot-filled {
background: #fce8e8;
@@ -65,6 +132,10 @@
color: #8d1f1f;
cursor: pointer;
}
+ .slot-btn span,
+ .slot-btn small {
+ display: block;
+ }
.oldest-highlight {
border: 1px solid #ffd58f;
background: #fff8ea;
@@ -163,94 +234,10 @@
Klik nomor tube berwarna biru untuk mengisi spesimen. Tube merah artinya sudah terisi.
+Pilih posisi dari lemari sampai box. Tube biru bisa diisi, tube merah sudah terisi.
- @forelse($cabinets as $cabinet) -| Kirby bauer | +|||||||
| AMC | +AK | +FOS | +SCF | +||||
| + + | ++ + | ++ + | ++ + | ++ + | ++ + | ++ + | ++ + | +
| Kirby bauer | +|||||||
| AMC | +AK | +FOS | +SCF | +||||
| + + | ++ + | ++ + | ++ + | ++ + | ++ + | ++ + | ++ + | +