361 lines
13 KiB
PHP
361 lines
13 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use Illuminate\Http\Request;
|
|
use App\Models\Antrian;
|
|
use App\Models\User;
|
|
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())
|
|
->whereDate('created_at', today())
|
|
->orderBy('created_at', 'desc')
|
|
->get();
|
|
|
|
return view('dashboard.index', compact('antrianSaya'));
|
|
}
|
|
|
|
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'
|
|
]);
|
|
|
|
try {
|
|
DB::beginTransaction();
|
|
|
|
$user = Auth::user();
|
|
$poli = Poli::find($request->poli_id);
|
|
$poliName = $poli->nama_poli;
|
|
|
|
// Check if user already has an active queue today for the same poli
|
|
$existingQueue = Antrian::where('user_id', $user->id)
|
|
->where('poli_id', $request->poli_id)
|
|
->whereDate('created_at', today())
|
|
->whereIn('status', ['menunggu', 'dipanggil', 'sedang_diperiksa'])
|
|
->first();
|
|
|
|
if ($existingQueue) {
|
|
// Determine the appropriate message based on status
|
|
$statusMessage = '';
|
|
switch ($existingQueue->status) {
|
|
case 'menunggu':
|
|
$statusMessage = 'Anda masih memiliki antrian yang menunggu di ' . $poliName . '.';
|
|
break;
|
|
case 'dipanggil':
|
|
$statusMessage = 'Anda memiliki antrian yang sudah dipanggil di ' . $poliName . '. Silakan datang ke poli.';
|
|
break;
|
|
case 'sedang_diperiksa':
|
|
$statusMessage = 'Anda sedang dalam proses pemeriksaan di ' . $poliName . '. Tidak dapat mengambil antrian baru di poli yang sama.';
|
|
break;
|
|
}
|
|
|
|
// Check if request wants JSON response
|
|
if ($request->expectsJson()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'type' => 'existing_queue',
|
|
'message' => $statusMessage,
|
|
'existing_queue' => [
|
|
'id' => $existingQueue->id,
|
|
'no_antrian' => $existingQueue->no_antrian,
|
|
'status' => $existingQueue->status,
|
|
'created_at' => $existingQueue->created_at->format('H:i'),
|
|
'poli_name' => $poliName
|
|
]
|
|
]);
|
|
}
|
|
|
|
// Fallback to redirect for non-AJAX requests
|
|
return redirect()->back()->with('error', $statusMessage);
|
|
}
|
|
|
|
// Note: User CAN have multiple queues in different polis
|
|
// We only prevent duplicate queues in the same poli (checked above)
|
|
// Multi-queue cross-poli is allowed and encouraged
|
|
|
|
// Get poli info for prefix
|
|
$prefix = $this->getPoliPrefix($poli->nama_poli);
|
|
|
|
// Get next queue number for the poli - perbaikan logika
|
|
$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) {
|
|
// 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,
|
|
'poli_id' => $request->poli_id,
|
|
'no_antrian' => $nextQueueNumber,
|
|
'tanggal_antrian' => now()->toDateString(),
|
|
'status' => 'menunggu'
|
|
]);
|
|
|
|
DB::commit();
|
|
|
|
if ($request->expectsJson()) {
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Antrian berhasil diambil! Nomor antrian Anda di ' . $poliName . ': ' . $nextQueueNumber,
|
|
'antrian' => [
|
|
'id' => $antrian->id,
|
|
'no_antrian' => $nextQueueNumber,
|
|
'poli_name' => $poliName,
|
|
'status' => 'menunggu'
|
|
]
|
|
]);
|
|
}
|
|
|
|
return redirect()->back()->with('success', 'Antrian berhasil diambil! Nomor antrian Anda di ' . $poliName . ': ' . $nextQueueNumber);
|
|
|
|
} catch (\Exception $e) {
|
|
DB::rollback();
|
|
|
|
if ($request->expectsJson()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Terjadi kesalahan saat mengambil antrian: ' . $e->getMessage()
|
|
], 500);
|
|
}
|
|
|
|
return redirect()->back()->with('error', 'Terjadi kesalahan saat mengambil antrian: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function updateProfile(Request $request)
|
|
{
|
|
$request->validate([
|
|
'nama' => 'required|string|max:255',
|
|
'no_hp' => 'required|string|max:15',
|
|
'no_ktp' => 'required|string|max:16',
|
|
'jenis_kelamin' => 'required|in:laki-laki,perempuan',
|
|
'alamat' => 'required|string',
|
|
'pekerjaan' => 'required|string|max:100'
|
|
]);
|
|
|
|
try {
|
|
/** @var \App\Models\User $user */
|
|
$user = Auth::user();
|
|
|
|
// Check if KTP number is already used by another user
|
|
$existingUser = User::where('no_ktp', $request->no_ktp)
|
|
->where('id', '!=', $user->id)
|
|
->first();
|
|
|
|
if ($existingUser) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Nomor KTP sudah digunakan oleh user lain.'
|
|
]);
|
|
}
|
|
|
|
$user->nama = $request->nama;
|
|
$user->no_hp = $request->no_hp;
|
|
$user->no_ktp = $request->no_ktp;
|
|
$user->jenis_kelamin = $request->jenis_kelamin;
|
|
$user->alamat = $request->alamat;
|
|
$user->pekerjaan = $request->pekerjaan;
|
|
$user->save();
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Data diri berhasil diperbarui!'
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Terjadi kesalahan saat memperbarui data: ' . $e->getMessage()
|
|
]);
|
|
}
|
|
}
|
|
|
|
private function getPoliPrefix($namaPoli)
|
|
{
|
|
switch (strtolower($namaPoli)) {
|
|
case 'umum':
|
|
return 'U';
|
|
case 'gigi':
|
|
return 'G';
|
|
case 'kesehatan jiwa':
|
|
return 'J';
|
|
case 'kesehatan tradisional':
|
|
return 'T';
|
|
default:
|
|
return 'A'; // Default prefix
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Auto-batalkan antrian yang sudah dipanggil lebih dari 5 menit
|
|
* tetapi belum dikonfirmasi kehadirannya (belum ada waktu_hadir)
|
|
*/
|
|
private function autoBatalkanAntrianLama()
|
|
{
|
|
try {
|
|
// Cari antrian yang sudah dipanggil lebih dari 5 menit tapi belum konfirmasi hadir
|
|
$antrianLama = Antrian::where('status', 'dipanggil')
|
|
->where('waktu_panggil', '<=', now()->subMinutes(5))
|
|
->whereNull('waktu_hadir') // Hanya yang belum konfirmasi hadir
|
|
->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 tanpa konfirmasi kehadiran");
|
|
}
|
|
|
|
// Jika ada antrian yang dibatalkan, log jumlahnya
|
|
if ($antrianLama->count() > 0) {
|
|
Log::info("Total {$antrianLama->count()} antrian otomatis dibatalkan karena timeout tanpa konfirmasi kehadiran");
|
|
}
|
|
} catch (\Exception $e) {
|
|
// Log error jika terjadi masalah
|
|
Log::error("Error saat auto-batalkan antrian: " . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if user has active queue in specific poli today
|
|
* @param int $userId
|
|
* @param int $poliId
|
|
* @return array|null
|
|
*/
|
|
private function checkActiveQueue($userId, $poliId)
|
|
{
|
|
$activeQueue = Antrian::where('user_id', $userId)
|
|
->where('poli_id', $poliId)
|
|
->whereDate('created_at', today())
|
|
->whereIn('status', ['menunggu', 'dipanggil', 'sedang_diperiksa'])
|
|
->first();
|
|
|
|
if ($activeQueue) {
|
|
return [
|
|
'exists' => true,
|
|
'queue' => $activeQueue,
|
|
'message' => $this->getStatusMessage($activeQueue->status, $activeQueue->poli->nama_poli)
|
|
];
|
|
}
|
|
|
|
return ['exists' => false];
|
|
}
|
|
|
|
/**
|
|
* Get appropriate message based on queue status
|
|
* @param string $status
|
|
* @param string $poliName
|
|
* @return string
|
|
*/
|
|
private function getStatusMessage($status, $poliName)
|
|
{
|
|
switch ($status) {
|
|
case 'menunggu':
|
|
return "Anda masih memiliki antrian yang menunggu di {$poliName}.";
|
|
case 'dipanggil':
|
|
return "Anda memiliki antrian yang sudah dipanggil di {$poliName}. Silakan datang ke poli.";
|
|
case 'sedang_diperiksa':
|
|
return "Anda sedang dalam proses pemeriksaan di {$poliName}. Tidak dapat mengambil antrian baru di poli yang sama.";
|
|
default:
|
|
return "Anda sudah memiliki antrian aktif di {$poliName}.";
|
|
}
|
|
}
|
|
|
|
public function batalAntrian(Request $request)
|
|
{
|
|
try {
|
|
$request->validate([
|
|
'antrian_id' => 'required|exists:antrians,id'
|
|
]);
|
|
|
|
$antrian = Antrian::findOrFail($request->antrian_id);
|
|
|
|
// Check if the antrian belongs to the authenticated user
|
|
if ($antrian->user_id !== Auth::id()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Anda tidak memiliki akses untuk membatalkan antrian ini'
|
|
], 403);
|
|
}
|
|
|
|
if ($antrian->status === 'selesai') {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Antrian yang sudah selesai tidak dapat dibatalkan'
|
|
]);
|
|
}
|
|
|
|
// Update status to 'batal'
|
|
$antrian->update(['status' => 'batal']);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Antrian ' . $antrian->no_antrian . ' berhasil dibatalkan'
|
|
]);
|
|
} catch (\Exception $e) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Terjadi kesalahan: ' . $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function cetakAntrian(Antrian $antrian)
|
|
{
|
|
try {
|
|
// Check if the antrian belongs to the authenticated user
|
|
if ($antrian->user_id !== Auth::id()) {
|
|
abort(403, 'Anda tidak memiliki akses untuk mencetak antrian ini');
|
|
}
|
|
|
|
// Check if antrian can be printed (only 'menunggu' status can be printed)
|
|
if ($antrian->status !== 'menunggu') {
|
|
abort(400, 'Antrian dengan status "' . ucfirst($antrian->status) . '" tidak dapat dicetak');
|
|
}
|
|
|
|
$antrian->load(['user', 'poli']);
|
|
|
|
$pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('user.antrian.print', compact('antrian'));
|
|
return $pdf->stream('antrian-' . $antrian->no_antrian . '.pdf');
|
|
} catch (\Exception $e) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Terjadi kesalahan: ' . $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
}
|