diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index c651d53..fb8f535 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -5,6 +5,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Facades\DB; use App\Models\User; use App\Models\Admin; use App\Models\Antrian; @@ -76,7 +77,7 @@ public function manageUsers(Request $request) }); } - $users = $query->orderBy('created_at', 'desc')->get(); + $users = $query->orderBy('created_at', 'desc')->paginate(15); return view('admin.users.index', compact('users')); } @@ -527,6 +528,119 @@ public function batalAntrian(Request $request) } } + public function tambahAntrian() + { + $polis = Poli::all(); + return view('admin.antrian.tambah', compact('polis')); + } + + public function cariUser(Request $request) + { + $request->validate([ + 'search' => 'required|string|min:3' + ]); + + $users = User::where('nama', 'like', "%{$request->search}%") + ->orWhere('no_ktp', 'like', "%{$request->search}%") + ->orWhere('no_hp', 'like', "%{$request->search}%") + ->limit(10) + ->get(['id', 'nama', 'no_ktp', 'no_hp', 'jenis_kelamin', 'alamat']); + + return response()->json([ + 'success' => true, + 'users' => $users + ]); + } + + public function storeAntrianAdmin(Request $request) + { + $request->validate([ + 'user_id' => 'required|exists:users,id', + 'poli_id' => 'required|exists:polis,id' + ]); + + try { + DB::beginTransaction(); + + $user = User::findOrFail($request->user_id); + $poli = Poli::findOrFail($request->poli_id); + + // Check if user already has active queue in this poli today + $existingQueue = Antrian::where('user_id', $request->user_id) + ->where('poli_id', $request->poli_id) + ->whereDate('created_at', today()) + ->whereIn('status', ['menunggu', 'dipanggil']) + ->first(); + + if ($existingQueue) { + return response()->json([ + 'success' => false, + 'message' => 'User ini sudah memiliki antrian aktif di ' . $poli->nama_poli . ' hari ini.' + ]); + } + + // Get poli prefix + $prefix = $this->getPoliPrefix($poli->nama_poli); + + // Get next queue number for the poli + $lastQueue = Antrian::where('poli_id', $request->poli_id) + ->whereDate('created_at', today()) + ->orderBy('id', 'desc') + ->first(); + + // Extract number from last queue (remove prefix) + $lastNumber = 0; + if ($lastQueue && $lastQueue->no_antrian) { + $lastNumber = (int) preg_replace('/^[A-Z]+/', '', $lastQueue->no_antrian); + } + + $nextNumber = $lastNumber + 1; + $nextQueueNumber = $prefix . $nextNumber; + + // Create new queue + $antrian = Antrian::create([ + 'user_id' => $request->user_id, + 'poli_id' => $request->poli_id, + 'no_antrian' => $nextQueueNumber, + 'tanggal_antrian' => now()->toDateString(), + 'status' => 'menunggu' + ]); + + DB::commit(); + + return response()->json([ + 'success' => true, + 'message' => 'Antrian berhasil dibuat untuk ' . $user->nama . ' di ' . $poli->nama_poli . ' dengan nomor ' . $nextQueueNumber, + 'antrian' => [ + 'id' => $antrian->id, + 'no_antrian' => $nextQueueNumber, + 'poli_name' => $poli->nama_poli, + 'user_name' => $user->nama, + 'status' => 'menunggu' + ] + ]); + + } catch (\Exception $e) { + DB::rollback(); + return response()->json([ + 'success' => false, + 'message' => 'Terjadi kesalahan: ' . $e->getMessage() + ], 500); + } + } + + private function getPoliPrefix($namaPoli) + { + $prefixMap = [ + 'umum' => 'U', + 'gigi' => 'G', + 'kesehatan jiwa' => 'J', + 'kesehatan tradisional' => 'T' + ]; + + return $prefixMap[strtolower($namaPoli)] ?? 'A'; + } + public function cetakAntrian(Antrian $antrian) { try { diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 1721c25..a2725af 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -8,11 +8,15 @@ use App\Models\Poli; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Log; class DashboardController extends Controller { public function index() { + // Auto-batalkan antrian yang sudah dipanggil lebih dari 5 menit + $this->autoBatalkanAntrianLama(); + // Get user's own queues $antrianSaya = Antrian::with(['user', 'poli']) ->where('user_id', Auth::id()) @@ -25,6 +29,9 @@ public function index() public function addQueue(Request $request) { + // Auto-batalkan antrian yang sudah dipanggil lebih dari 5 menit + $this->autoBatalkanAntrianLama(); + $request->validate([ 'poli_id' => 'required|exists:polis,id' ]); @@ -71,20 +78,28 @@ public function addQueue(Request $request) // Get poli info for prefix $prefix = $this->getPoliPrefix($poli->nama_poli); - // Get next queue number for the poli + // Get next queue number for the poli - perbaikan logika $lastQueue = Antrian::where('poli_id', $request->poli_id) ->whereDate('created_at', today()) - ->max('no_antrian'); + ->orderBy('id', 'desc') + ->first(); // Extract number from last queue (remove prefix) $lastNumber = 0; - if ($lastQueue) { - $lastNumber = (int) preg_replace('/[^0-9]/', '', $lastQueue); + if ($lastQueue && $lastQueue->no_antrian) { + // Extract only the numeric part after the prefix + $lastNumber = (int) preg_replace('/^[A-Z]+/', '', $lastQueue->no_antrian); + + // Debug log + \Log::info("Last queue: {$lastQueue->no_antrian}, Extracted number: {$lastNumber}"); } $nextNumber = $lastNumber + 1; $nextQueueNumber = $prefix . $nextNumber; + // Debug log + \Log::info("Generated next queue number: {$nextQueueNumber} for poli: {$poliName}"); + // Create new queue using current user's data $antrian = Antrian::create([ 'user_id' => $user->id, @@ -188,6 +203,36 @@ private function getPoliPrefix($namaPoli) } } + /** + * Auto-batalkan antrian yang sudah dipanggil lebih dari 5 menit + * tanpa dikonfirmasi selesai oleh admin + */ + private function autoBatalkanAntrianLama() + { + try { + // Cari antrian yang sudah dipanggil lebih dari 5 menit + $antrianLama = Antrian::where('status', 'dipanggil') + ->where('waktu_panggil', '<=', now()->subMinutes(5)) + ->get(); + + foreach ($antrianLama as $antrian) { + // Update status menjadi 'batal' + $antrian->update(['status' => 'batal']); + + // Log untuk tracking (optional) + \Log::info("Antrian {$antrian->no_antrian} otomatis dibatalkan karena lewat 5 menit sejak dipanggil"); + } + + // Jika ada antrian yang dibatalkan, log jumlahnya + if ($antrianLama->count() > 0) { + \Log::info("Total {$antrianLama->count()} antrian otomatis dibatalkan karena timeout"); + } + } catch (\Exception $e) { + // Log error jika terjadi masalah + \Log::error("Error saat auto-batalkan antrian: " . $e->getMessage()); + } + } + public function batalAntrian(Request $request) { try { diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 452e6b6..cdf5020 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -19,6 +19,7 @@ public function register(): void */ public function boot(): void { - // + // Set pagination to use Tailwind CSS styling + \Illuminate\Pagination\Paginator::useTailwind(); } } diff --git a/config/app.php b/config/app.php index 423eed5..c74a68d 100644 --- a/config/app.php +++ b/config/app.php @@ -65,7 +65,7 @@ | */ - 'timezone' => 'UTC', + 'timezone' => 'Asia/Jakarta', /* |-------------------------------------------------------------------------- diff --git a/resources/views/admin/antrian/tambah.blade.php b/resources/views/admin/antrian/tambah.blade.php new file mode 100644 index 0000000..28fad1c --- /dev/null +++ b/resources/views/admin/antrian/tambah.blade.php @@ -0,0 +1,263 @@ +@extends('layouts.app') + +@section('content') +
Bantu pasien yang tidak bisa antri online dengan membuat antrian manual
+- No. Antrian | -- Nama | -- Poli | -- Status | -- Waktu | -
---|---|---|---|---|
- {{ $antrian->no_antrian ?? 'N/A' }} - | -
-
- {{ $antrian->user?->nama ?? 'N/A' }}
-
- {{ $antrian->user?->no_hp ?? 'N/A' }}
-
- |
- - - {{ $antrian->poli->nama_poli ?? 'N/A' }} - - | -- @if (($antrian->status ?? '') == 'menunggu') - - Menunggu - - @elseif(($antrian->status ?? '') == 'dipanggil') - - Dipanggil - - @elseif(($antrian->status ?? '') == 'selesai') - - Selesai - - @else - - Batal - - @endif - | -- {{ $antrian->created_at?->format('H:i') ?? 'N/A' }} - | -
-
- Belum ada antrian hari ini -Antrian akan muncul di sini setelah ada - pendaftaran - |
-
No. - Antrian
- {{ $antrian->no_antrian ?? 'N/A' }} -Nama
-Poli
- - {{ $antrian->poli->nama_poli ?? 'N/A' }} - -Status -
- @if (($antrian->status ?? '') == 'menunggu') - - Menunggu - - @elseif(($antrian->status ?? '') == 'dipanggil') - - Dipanggil - - @elseif(($antrian->status ?? '') == 'selesai') - - Selesai - - @else - - Batal - - @endif -Kelola pengaturan Text-to-Speech Indonesia
-Checking...
-Checking...
-Checking...
-Checking...
-Indonesian TTS memerlukan instalasi Coqui TTS dan model files. Ikuti - langkah-langkah di bawah ini.
-Kelola data pengguna sistem antrian Puskesmas
-