diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index b6318f3..7b710c9 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -4,26 +4,84 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use Illuminate\Http\Response; class AuthController extends Controller { + private int $loginDecaySeconds = 60; + private int $maxLoginAttempts = 10; + public function index(){ + $captcha = $this->generateCaptchaCode(6); + session(['login_captcha' => $captcha]); $data = [ - 'title' => 'Login Admin | Order Gizi' + 'title' => 'Login Admin | Order Gizi', ]; return view('auth.index', $data); } - public function authanticate(){ - $credentials = request()->validate([ + public function authanticate(Request $request){ + $validated = $request->validate([ 'username' => 'required', - 'password' => 'required' + 'password' => 'required', + 'captcha' => 'required', + 'website' => 'nullable', ]); + + if (trim((string) $request->input('website', '')) !== '') { + return back()->withInput($request->only('username')) + ->with(['alertError' => 'Gagal Login!']); + } + + $now = time(); + $rateKey = 'login:' . $request->ip() . ':' . strtolower((string) $request->input('username')); + $windowSeconds = 60; + $maxAttempts = 10; + $attempts = (array) $request->session()->get($rateKey, []); + $attempts = array_values(array_filter($attempts, fn($ts) => is_int($ts) && $ts > ($now - $windowSeconds))); + if(count($attempts) >= $maxAttempts){ + return back()->withInput($request->only('username')) + ->with(['alertError' => 'rate']); + } + + $backoffKey = $rateKey . ':backoff_until'; + $until = (int) $request->session()->get($backoffKey, 0); + if($until > $now){ + return back()->withInput($request->only('username')) + ->with(['alertError' => 'backoff']); + } + + $expectedCaptcha = (string) session('login_captcha', ''); + $givenCaptcha = strtoupper(preg_replace('/\s+/', '', (string) $request->input('captcha', ''))); + if($expectedCaptcha === '' || !hash_equals(strtoupper($expectedCaptcha), (string) $givenCaptcha)){ + return back()->withInput($request->only('username')) + ->with(['alertError' => 'captcha']); + } + $request->session()->forget('login_captcha'); + + + // IMPORTANT: only pass auth credentials to Auth::attempt + // (do not include captcha / honeypot fields, otherwise Laravel will query non-existent columns) + $credentials = [ + 'username' => (string) ($validated['username'] ?? ''), + 'password' => (string) ($validated['password'] ?? ''), + ]; + if(Auth::attempt($credentials)){ - request()->session()->regenerate(); + $request->session()->regenerate(); + $request->session()->forget($rateKey); + $request->session()->forget($backoffKey); return redirect()->intended('/dashboard'); } - return back()->with(['alertError' => 'Terdapat kesalahan disini!']); + // record failed attempt + $attempts[] = $now; + $request->session()->put($rateKey, $attempts); + + // set exponential backoff (1,2,4,8,16,30 seconds max) based on failures in window + $failCount = count($attempts); + $delay = min(30, (int) pow(2, max(0, $failCount - 1))); + $request->session()->put($backoffKey, $now + $delay); + return back()->with(['alertError' => 'Gagal Login!']); } public function logout() @@ -33,4 +91,63 @@ class AuthController extends Controller request()->session()->regenerateToken(); return redirect('/login'); } + + public function captcha(){ + $captcha = (string) session('login_captcha', ''); + if($captcha === ''){ + $captcha = $this->generateCaptchaCode(6); + session(['login_captcha' => $captcha]); + } + if(!function_exists('imagecreatetruecolor')){ + return response('GD extension is not available', Response::HTTP_INTERNAL_SERVER_ERROR)->header('Content-Type', 'text/plain'); + } + + $width=140; + $height=44; + $img = imagecreatetruecolor($width, $height); + $bg = imagecolorallocate($img, 245, 247, 250); + $fg = imagecolorallocate($img, 35, 45, 70); + $noise = imagecolorallocate($img, 120, 130, 150); + + imagefilledrectangle($img, 0, 0, $width, $height, $bg); + + for($i = 0; $i < 6; $i++){ + imageline( + $img, + random_int(0, $width), + random_int(0, $height), + random_int(0, $width), + random_int(0, $height), + $noise + ); + } + + for($i = 0; $i < 180; $i++){ + imagesetpixel($img, random_int(0, $width - 1), random_int(0, $height - 1), $noise); + } + + $font = 5; + $textWidth = imagefontwidth($font) * strlen($captcha); + $textHeight = imagefontwidth($font); + $x = (int) (($width - $textWidth) / 2); + $y = (int) (($height - $textHeight) / 2); + imagestring($img, $font, $x, $y, $captcha, $fg); + + ob_start(); + imagepng($img); + $png = ob_get_clean(); + imagedestroy($img); + return response($png, 200)->header('Content-Type', 'image/png')->header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0'); + } + + public function generateCaptchaCode(int $length = 6): string + { + $chars = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ'; + $out = ''; + $max = strlen($chars) - 1; + for ($i = 0; $i < $length; $i++){ + $out .= $chars[random_int(0, $max)]; + } + return $out; + } } diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index fe5487c..04e6750 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -6,22 +6,26 @@ use App\Mail\NotifikasiCustomer; use App\Mail\NotifikasiPembayaran; use App\Models\JadwalKonsul; use App\Models\Karbohidrat; +use App\Models\Karyawan; use App\Models\MasterMcu; use App\Models\Order; use App\Models\OrderDetail; +use App\Models\UnitInstalasi; use Carbon\Carbon; use Carbon\CarbonPeriod; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Mail; use Illuminate\Support\Str; +use Illuminate\Support\Facades\Validator; class CustomerController extends Controller { public function index(){ $payload = [ - 'title' => 'Halaman Utama' + 'title' => 'Halaman Utama', + 'mcu' => false, ]; return view('guest.index', $payload); } @@ -151,6 +155,7 @@ class CustomerController extends Controller return [ 'master_menu_id' => $menu->master_menu_id, 'nama' => $menu->nama_menu, + 'exist_foto' => file_exists(public_path('gambar/' . $menu->foto)) ? true : false, 'foto' => $menu->foto, 'jenis_menu' => $menu->jenis_menu, 'harga_public' => $menu->harga_public, @@ -183,7 +188,7 @@ class CustomerController extends Controller // Urutkan: someday → tgl_harian terdekat $sorted = $enriched->sortBy(function ($menu) { - $hariIni = now()->day; + $besok = now()->addDay()->day; $isSomeday = $menu['apakah_someday'] ? 0 : 1; if ($menu['apakah_someday']) { @@ -191,8 +196,11 @@ class CustomerController extends Controller } $tglTerdekat = collect($menu['dmph'])->pluck('tgl_harian') - ->map(function ($tgl) use ($hariIni) { - return $tgl >= $hariIni ? $tgl : $tgl + 31; + ->map(function ($tgl) use ($besok) { + if ($tgl == $besok) { + return 0; // Besok paling awal + } + return $tgl > $besok ? $tgl : $tgl + 31; }) ->sort() ->first() ?? 99; @@ -248,7 +256,8 @@ class CustomerController extends Controller $karbohidrat = Karbohidrat::where('statusenabled', true)->select('karbohidrat_id', 'nama_karbohidrat', 'nilai_kalori')->get(); $payload = [ 'title' => 'Checkout ', - 'karbohidrat' => $karbohidrat + 'karbohidrat' => $karbohidrat, + 'mcu' => false, ]; return view('guest.checkout.checkout_payment', $payload); } @@ -258,7 +267,7 @@ class CustomerController extends Controller $dataCart = request()->input('cartResult'); $biodataResult = request()->input('biodataResult'); $totalHarga = request()->input('totalHarga'); - DB::beginTransaction(); + DB::connection('dbOrderGizi')->beginTransaction(); try { $jenisCustomer = $biodataResult['jenis_customer']; $today = now()->toDateString(); @@ -274,18 +283,24 @@ class CustomerController extends Controller 'no_wa' => $biodataResult['no_whatsapp'], 'tinggi_badan' => $biodataResult['tinggi_badan'], 'berat_badan' => $biodataResult['berat_badan'], - 'nama_pasien' => $biodataResult['nama_pasien'], - 'ruang_perawatan' => $biodataResult['ruang_perawatan'], - 'no_kamar_perawatan' => $biodataResult['no_kamar'], - 'kelas_perawatan' => $biodataResult['kelas_perawatan'], - 'bagian_instalasi' => $biodataResult['bagian_instalasi'], - 'no_ekstensien' => $biodataResult['no_ekstensien'], 'total_harga' => $totalHarga, 'status_order' => "Belum Bayar", 'email' => $biodataResult['email'], - 'alamat' => $biodataResult['alamat'], 'entry_at' => Carbon::now()->format('Y-m-d H:i:s.u'), ]; + if($jenisCustomer === "Karyawan RSAB Harapan Kita"){ + $nip_pns = Karyawan::where('namalengkap',$biodataResult['nama_pemesan'])->first()?->nip_pns; + $payloadOrder['nip'] = $nip_pns ?? null; + $payloadOrder['bagian_instalasi'] = $biodataResult['bagian_instalasi'] ?? null; + $payloadOrder['no_ekstensien'] = $biodataResult['no_ekstensien'] ?? null; + }else if($jenisCustomer === "Keluarga Pasien / Penunggu Pasien"){ + $payloadOrder['nama_pasien'] = $biodataResult['nama_pasien'] ?? null; + $payloadOrder['ruang_perawatan'] = $biodataResult['ruang_perawatan'] ?? null; + $payloadOrder['no_kamar_perawatan'] = $biodataResult['no_kamar'] ?? null; + $payloadOrder['kelas_perawatan'] = $biodataResult['kelas_perawatan'] ?? null; + }else{ + $payloadOrder['alamat'] = $biodataResult['alamat'] ?? null; + } $order = Order::create($payloadOrder); foreach ($dataCart as $cart) { $payloadOrderDetail = [ @@ -300,14 +315,20 @@ class CustomerController extends Controller $payloadOrderDetail['karbohidrat_id'] = $value['karbohidrat_id'] ?? null; $payloadOrderDetail['catatan'] = $value['catatan'] ?? null; $payloadOrderDetail['master_menu_id'] = $cart['id_menu']; + $payloadOrderDetail['total_kalori'] = $value['resultKalori'] ?? ($cart['kalori'] ?? null); OrderDetail::create($payloadOrderDetail); } } //code... if($order->email){ - Mail::to($order->email)->queue(new NotifikasiCustomer($order->nama_pemesan, $order->no_order, $order->total_harga)); + try { + Mail::to($order->email)->send(new NotifikasiCustomer($order->nama_pemesan, $order->no_order, $order->total_harga)); + } catch (\Throwable $th) { + //throw $th; + } + } - DB::commit(); + DB::connection('dbOrderGizi')->commit(); return response()->json([ 'status' => true, 'data' => $order, @@ -315,7 +336,7 @@ class CustomerController extends Controller 'message' => 'Data berhasil disimpan' ]); } catch (\Throwable $th) { - DB::rollBack(); + DB::connection('dbOrderGizi')->rollBack(); return response()->json([ 'status' => false, 'message' => 'Data gagal disimpan ' . $th->getMessage() @@ -324,7 +345,7 @@ class CustomerController extends Controller } public function finishCheckout(){ - DB::beginTransaction(); + DB::connection('dbOrderGizi')->beginTransaction(); try { $noOrder = request('no_order_result'); @@ -363,18 +384,27 @@ class CustomerController extends Controller $order->update($payload); if($order->email){ - Mail::to($order->email)->queue(new NotifikasiPembayaran($order->nama_pemesan, $order->no_order)); + try { + Mail::to($order->email)->send( + new NotifikasiPembayaran($order->nama_pemesan, $order->no_order) + ); + } catch (\Exception $e) { + // log error biar bisa ditelusuri nanti + // \Log::error('Gagal mengirim email ke ' . $order->email . ': ' . $e->getMessage()); + // continue tanpa break flow + } } - DB::commit(); + DB::connection('dbOrderGizi')->commit(); session()->flash('payment_success', true); session()->flash('no_order', $noOrder); return response([ 'status' => true, + 'no_order' => $noOrder, 'message' => 'Terima kasih atas pesanan Anda. Mohon tunggu, kami sedang memprosesnya' ], 200); return back()->with('success', 'Bukti pembayaran berhasil diunggah.'); } catch (\Throwable $th) { - DB::rollBack(); + DB::connection('dbOrderGizi')->rollBack(); return response([ 'status' => false, 'message' => 'Gagal melakukan pesanan!' @@ -388,7 +418,8 @@ class CustomerController extends Controller } $payload = [ 'title' => 'Berhasil Melakukan Pembayaran ', - 'no_order' => session('no_order') + 'no_order' => session('no_order'), + 'mcu' => false, ]; return view('guest.success_page', $payload); } @@ -396,7 +427,8 @@ class CustomerController extends Controller public function checkOrder(){ $payload = [ - 'title' => 'Check Order' + 'title' => 'Check Order', + 'mcu' => false, ]; return view('guest.check_order.index', $payload); } @@ -407,6 +439,7 @@ class CustomerController extends Controller ->table('public.order as o') ->leftJoin('public.order_detail as od', 'od.order_id', '=', 'o.order_id') ->leftJoin('public.master_menu as mm', 'mm.master_menu_id', '=', 'od.master_menu_id') + ->leftJoin('public.menu_mcu as mcu', 'mcu.menu_mcu_id', '=', 'od.menu_mcu_id') ->where('o.no_order', 'ILIKE', '%' . $noOrder . '%') ->select( 'o.*', @@ -416,7 +449,10 @@ class CustomerController extends Controller 'od.harga_satuan', 'od.status_order as status_order_detail', 'od.catatan', - 'mm.nama_menu as nama_item', + 'od.total_kalori', + 'od.type', + 'od.jam_layanan', + DB::raw('COALESCE(mm.nama_menu, mcu.nama_mcu) as nama_item'), 'mm.foto as foto' ) ->get(); @@ -451,16 +487,22 @@ class CustomerController extends Controller // karyawan 'no_ekstensien' => $data->no_ekstensien, 'bagian_instalasi' => $data->bagian_instalasi, + // umum + 'alamat' => $data->alamat, 'items' => $order->map(function ($item) { return [ 'order_detail_id' => $item->order_detail_id, 'nama_item' => $item->nama_item, 'tgl_antar' => $item->tgl_antar, + 'exist_foto' => file_exists(public_path('gambar/' . $item->foto)) ? true : false, 'foto' => $item->foto, 'jumlah' => $item->jumlah, 'harga_satuan' => $item->harga_satuan, 'status_order' => $item->status_order_detail, - 'catatan' => $item->catatan ?? '-' + 'catatan' => $item->catatan ?? '-', + 'total_kalori' => $item->total_kalori, + 'type' => $item->type, + 'jam_layanan' => $item->jam_layanan, // tambahkan field tambahan jika diperlukan ]; })->values(), @@ -477,7 +519,8 @@ class CustomerController extends Controller $paketMcu = MasterMcu::where('statusenabled', true)->get(); $data = [ 'title' => 'Order Gizi MCU', - 'paketMcu' => $paketMcu + 'paketMcu' => $paketMcu, + 'mcu' => true, ]; return view('guest.mcu.index', $data); } @@ -487,6 +530,7 @@ class CustomerController extends Controller DB::connection('dbOrderGizi')->beginTransaction(); $today = now()->toDateString(); $jumlahHariIni = Order::whereDate('entry_at', $today)->count(); + $priceMcu = MasterMcu::where('menu_mcu_id', request('paket_mcu'))->first(); $urutan = $jumlahHariIni + 1; $noOrder = 'TX/CT/GIZI/' . now()->year .'/'. now()->month .'/' . now()->day .'/MCU/' . Str::random(6) .'/' . str_pad($urutan, 4, '0', STR_PAD_LEFT); $payload = [ @@ -499,17 +543,21 @@ class CustomerController extends Controller 'no_wa' => request('no_hp') ?? null, 'tinggi_badan' => request('tinggi_badan') ?? null, 'berat_badan' => request('berat_badan') ?? null, - 'status_order' =>'Menunggu Konfirmasi Pesanan MCU' + 'nama_institusi' => request('nama_institusi'), + 'status_order' =>'Menunggu Konfirmasi Pesanan MCU', + 'total_harga' => $priceMcu ? $priceMcu->harga : null, + 'cara_pembayaran' =>'MCU', ]; $order = Order::create($payload); + $payloadDetail = [ 'order_id' => $order->order_id, 'jumlah' => 1, 'tgl_antar' => request('tgl_mcu'), 'menu_mcu_id' => request('paket_mcu'), 'jam_layanan' => request('jam_layanan'), - 'cara_pembayaran' => 'MCU', - 'status_order' =>'Menunggu Konfirmasi' + 'status_order' =>'Pending', + 'harga_satuan' => $priceMcu ? $priceMcu->harga : null, ]; OrderDetail::create($payloadDetail); @@ -521,7 +569,7 @@ class CustomerController extends Controller 'message' => 'Pesanan Berhasil diproses' ]); } catch (\Throwable $th) { - DB::rollBack(); + DB::connection('dbOrderGizi')->rollBack(); return response()->json([ 'status' => false, 'message' => 'Pesanan gagal diproses ' . $th->getMessage() @@ -536,8 +584,57 @@ class CustomerController extends Controller $payload = [ 'title' => 'Berhasil Melakukan Pesanan ', 'no_order' => session('no_order'), - 'back_href' => '/order-mcu' + 'back_href' => '/order-mcu', + 'mcu' => false ]; return view('guest.success_page', $payload); } + + public function karyawan(Request $request) + { + $search = trim($request->input('search')); + + // 1. Validasi dulu + $validator = Validator::make( + ['search' => $search], + ['search' => 'required|string|min:2|max:50|regex:/^[a-zA-Z.\s]+$/'] + ); + if ($validator->fails()) { + return response()->json(['error' => 0, 'data' => []]); + } + + // 2. Baru query kalau ada keyword + $data =Karyawan::where('statusenabled', true)->where('kedudukanfk', 1) + ->where('namalengkap', 'ILIKE', "%{$search}%") + ->limit(5) + ->pluck('namalengkap') // langsung ambil string + ->map(fn($nama) => ['label' => $nama]); + + return response()->json(['error' => 0, 'data' => $data]); + } + + public function unitInstalasi(Request $request) + { + $search = trim($request->input('search')); + + // 1. Validasi dulu + $validator = Validator::make( + ['search' => $search], + ['search' => 'required|string|min:2|max:50|regex:/^[a-zA-Z.\s]+$/'] + ); + if ($validator->fails()) { + return response()->json(['error' => 0, 'data' => []]); + } + + // 2. Baru query kalau ada keyword + $data = UnitInstalasi::where('statusenabled', true) + ->select('name') + ->where('name', 'ILIKE', "%{$search}%") + ->limit(5) + ->get() + ->map(fn($row) => ['label' => $row->name]); + + return response()->json(['error' => 0, 'data' => $data]); + } } + diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 322e881..f9b3c8e 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -61,15 +61,15 @@ class DashboardController extends Controller 'note_dibatalkan' => $first->note_dibatalkan, ]; })->values(); - $pemasukanKaryawan = $grouped->where('jenis_customer', 'Karyawan RSAB Harapan Kita')->sum('total_harga'); - $pemasukanMasyarakat = $grouped->where('jenis_customer', 'Masyarakat Umum')->sum('total_harga'); - $pemasukanKeluargaPasien = $grouped->where('jenis_customer', 'Keluarga Pasien / Penunggu Pasien')->sum('total_harga'); + $pemasukanKaryawan = $grouped->where('jenis_customer', 'Karyawan RSAB Harapan Kita')->whereNotIn('status_order', ['Belum Bayar'])->sum('total_harga'); + $pemasukanMasyarakat = $grouped->where('jenis_customer', 'Masyarakat Umum')->whereNotIn('status_order', ['Belum Bayar'])->sum('total_harga'); + $pemasukanKeluargaPasien = $grouped->where('jenis_customer', 'Keluarga Pasien / Penunggu Pasien')->whereNotIn('status_order', ['Belum Bayar'])->sum('total_harga'); - $totalPemasukan = $grouped->sum('total_harga'); - $pesananPending = $grouped->whereNotIn('status_order', ['Lunas', 'Dibatalkan'])->count(); + $totalPemasukan = $grouped->whereNotIn('status_order', ['Belum Bayar'])->sum('total_harga'); + $pesananPending = $grouped->whereNotIn('status_order', ['Lunas', 'Dibatalkan', 'Belum Bayar'])->count(); $pesananLunas = $grouped->where('status_order', 'Lunas')->count(); $pesananBatal = $grouped->where('status_order', 'Dibatalkan')->count(); - $totalPesanan = $grouped->count(); + $totalPesanan = $grouped->whereNotIn('status_order', ['Belum Bayar'])->count(); $pesananSelesai = DB::connection('dbOrderGizi')->table('public.order as o') ->where('o.statusenabled', true) diff --git a/app/Http/Controllers/PesananController.php b/app/Http/Controllers/PesananController.php index 5313e07..128b0a8 100644 --- a/app/Http/Controllers/PesananController.php +++ b/app/Http/Controllers/PesananController.php @@ -37,6 +37,16 @@ class PesananController extends Controller }else{ $tanggalFormatted = [Carbon::now()->toDateString()]; } + + $dataPending = Order::where('statusenabled', true)->whereIn('status_order', [ + 'Menunggu Konfirmasi Pembayaran', + 'Menunggu Konfirmasi Pembayaran Via Billing', + 'Menunggu Konfirmasi Pesanan MCU' + ]) + ->select(DB::raw('COUNT(DISTINCT DATE(entry_at)) as total')) + ->value('total'); + + $orders = DB::connection('dbOrderGizi')->table('public.order as o') ->leftJoin('public.order_detail as od', 'od.order_id', '=', 'o.order_id') ->where('o.statusenabled', true) @@ -57,6 +67,7 @@ class PesananController extends Controller 'o.bukti_pembayaran', 'o.note_dibatalkan', 'o.medical_record', + 'o.nama_institusi', 'od.status_order as detail_status_order' )->get()->groupBy('order_id'); $grouped = $orders->map(function($items){ @@ -79,15 +90,18 @@ class PesananController extends Controller 'total_detail' => $totalDetail, 'selesai_detail' => $selesaiDetail, 'note_dibatalkan' => $first->note_dibatalkan, + 'nama_institusi' => $first->nama_institusi, ]; }) ->filter(function($item){ return $item['total_detail'] > 0 && $item['total_detail'] != $item['selesai_detail']; })->values(); + return response()->json([ 'status' => true, 'rows' => $grouped->values(), - 'total' => $grouped->count() + 'total' => $grouped->count(), + 'dataPending'=> $dataPending ]); } @@ -107,8 +121,13 @@ class PesananController extends Controller } $order->update($payload); - if($order->email){ - Mail::to($order->email)->queue(new NotifikasiKonfirmasiPembayaran($order->nama_pemesan, $order->no_order, $order->total_harga)); + if($order->email && $order->status_order === "Lunas"){ + try { + //code... + Mail::to($order->email)->send(new NotifikasiKonfirmasiPembayaran($order->nama_pemesan, $order->no_order, $order->total_harga)); + } catch (\Throwable $th) { + //throw $th; + } } DB::connection('dbOrderGizi')->commit(); @@ -136,7 +155,6 @@ class PesananController extends Controller 'pegawai_name_confirm_order' => auth()->user()->full_name, 'pegawai_at_confirm_order' => Carbon::now(), 'status_order' => 'Lunas', - 'cara_pembayaran' => 'Billing' ]; if($request->hasFile('evidence_medical_record')){ $file = $request->file('evidence_medical_record'); @@ -146,7 +164,7 @@ class PesananController extends Controller $order->update($payload); if($order->email){ - Mail::to($order->email)->queue(new NotifikasiKonfirmasiPembayaran($order->nama_pemesan, $order->no_order, $order->total_harga)); + Mail::to($order->email)->send(new NotifikasiKonfirmasiPembayaran($order->nama_pemesan, $order->no_order, $order->total_harga)); } DB::connection('dbOrderGizi')->commit(); return response()->json([ @@ -180,6 +198,24 @@ class PesananController extends Controller ]); } + public function dataPending(){ + $data = Order::selectRaw('DATE(entry_at) as tgl, COUNT(*) as total') + ->where('statusenabled', true) + ->whereIn('status_order', [ + 'Menunggu Konfirmasi Pembayaran', + 'Menunggu Konfirmasi Pembayaran Via Billing', + 'Menunggu Konfirmasi Pesanan MCU' + ]) + ->groupBy(DB::raw('DATE(entry_at)')) + ->orderBy('tgl', 'asc') + ->get(); + return response()->json([ + 'status' => true, + 'rows' => $data->values(), + 'total' => $data->count() + ]); + } + public function indexSelesai() { $payload = [ @@ -218,6 +254,7 @@ class PesananController extends Controller 'o.note_dibatalkan', 'o.medical_record', 'o.evidence_medical_record', + 'o.nama_institusi', 'od.status_order as detail_status_order' )->get()->groupBy('order_id'); @@ -242,6 +279,7 @@ class PesananController extends Controller 'total_detail' => $totalDetail, 'selesai_detail' => $selesaiDetail, 'note_dibatalkan' => $first->note_dibatalkan, + 'nama_institusi' => $first->nama_institusi, ]; }) ->filter(function($item){ @@ -264,7 +302,7 @@ class PesananController extends Controller } public function getPekerjaan(){ - $data = OrderDetail::with(['menu', 'paketMenu', 'order', 'karbohidrat'])->whereHas('order', function($q){ + $data = OrderDetail::with(['menu', 'masterMcu', 'order', 'karbohidrat'])->whereHas('order', function($q){ $q->where('status_order', 'Lunas'); }); $tanggal = request('tanggal'); @@ -279,16 +317,39 @@ class PesananController extends Controller // if($status !== "all"){ // $data->where('status_order', $status); // } + $dataPending = OrderDetail::whereHas('order', function($query) { + $query->where('status_order', 'Lunas'); + })->where('status_order', 'Pending') + ->select(DB::raw('COUNT(DISTINCT DATE(tgl_antar)) as total')) + ->value('total'); + $data = $data->get(); return response()->json([ + 'rows' => $data->values(), + 'total' => $data->count(), + 'dataPending' => $dataPending + ]); + } + + public function dataPekerjaanPending(){ + $data = OrderDetail::with('order')->where('status_order', 'Pending') + ->select(DB::raw('DATE(tgl_antar) as tgl'), DB::raw('COUNT(*) as total')) + ->whereHas('order', function($query) { + $query->where('status_order', 'Lunas'); // filter status di tabel orders + }) + ->groupBy(DB::raw('DATE(tgl_antar)')) + ->orderBy('tgl', 'asc') + ->get(); + return response()->json([ + 'status' => true, 'rows' => $data->values(), 'total' => $data->count() ]); } public function getPekerjaanDetail($order_detail_id){ - $data = OrderDetail::where('order_detail_id', $order_detail_id)->with(['order', 'menu', 'paketMenu'])->first(); + $data = OrderDetail::where('order_detail_id', $order_detail_id)->with(['order', 'menu', 'masterMcu'])->first(); return response()->json([ 'status' => true, 'data' => $data @@ -301,7 +362,7 @@ class PesananController extends Controller $type_customer = request('type_customer'); $type = request('type'); - $orderDetail = OrderDetail::with(['menu', 'paketMenu', 'order', 'karbohidrat'])->whereHas('order', function($q) use($type_customer){ + $orderDetail = OrderDetail::with(['menu', 'masterMcu', 'order', 'karbohidrat'])->whereHas('order', function($q) use($type_customer){ $q->where('status_order', 'Lunas'); if($type_customer !== 'all'){ $q->where('jenis_customer', $type_customer); @@ -338,18 +399,18 @@ class PesananController extends Controller $sheet = $spreadsheet->getActiveSheet(); $sheet->setCellValue('A1', "Menu Pesanan dari {$startDateFormatted} sampai {$endDateFormatted}"); - $sheet->mergeCells('A1:K1'); + $sheet->mergeCells('A1:P1'); $sheet->getStyle('A1')->getFont()->setBold(true)->setSize(14); $sheet->getStyle('A1')->getAlignment()->setHorizontal('center'); $sheet->setCellValue('A2', "Waktu Cetak: {$waktu_cetak}"); - $sheet->mergeCells('A2:K2'); + $sheet->mergeCells('A2:P2'); $sheet->getStyle('A2')->getAlignment()->setHorizontal('center'); // Header tabel - $headers = ["No", "Nomor Order", "Nama Pemesan", "Jenis Customer", "Status Pesanan", "Menu Pesanan", "Karbohidrat", "Jumlah", "Tanggal Antar", "Waktu Makan", "Catatan"]; + $headers = ["No", "Nomor Order", "Nama Pemesan", "Jenis Pembayaran", "Jenis Customer", "Ruangan", "Status Pesanan", "Jenis Menu", "Menu Pesanan", "Karbohidrat", "Total Kalori (kal)", "Jumlah", "Tanggal Antar", "Waktu Makan / Jam Layanan", "Harga Total", "Catatan"]; $sheet->fromArray($headers, null, 'A4'); - $sheet->getStyle('A4:K4')->applyFromArray([ + $sheet->getStyle('A4:P4')->applyFromArray([ 'font' => ['bold' => true], 'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER], 'borders' => [ @@ -358,36 +419,58 @@ class PesananController extends Controller ] ] ]); - $sheet->getStyle('A4:K4')->getFont()->setBold(true); - $sheet->getStyle('A4:K4')->getAlignment()->setHorizontal('center'); - $sheet->getStyle('A4:K4')->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); + $sheet->getStyle('A4:P4')->getFont()->setBold(true); + $sheet->getStyle('A4:P4')->getAlignment()->setHorizontal('center'); + $sheet->getStyle('A4:P4')->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); // Isi data $row = 5; + $totalPendapatan = 0; foreach ($orderDetail as $index => $item) { $sheet->setCellValue("A{$row}", $index + 1); $sheet->setCellValue("B{$row}", $item?->order?->no_order); $sheet->setCellValue("C{$row}", $item?->order?->nama_pemesan); - $sheet->setCellValue("D{$row}", $item?->order?->jenis_customer); - $sheet->setCellValue("E{$row}", $item?->status_order ?? "-"); - $sheet->setCellValue("F{$row}", $item?->menu?->nama_menu ?? '-'); + $sheet->setCellValue("D{$row}", $item?->order?->cara_pembayaran); + $sheet->setCellValue("E{$row}", $item?->order?->jenis_customer === "MCU" ? $item?->order?->nama_institusi . '- MCU' : $item?->order?->jenis_customer); + if($item->order?->jenis_customer === "Keluarga Pasien / Penunggu Pasien"){ + $sheet->setCellValue("F{$row}", $item?->order?->kelas_perawatan . '/' . $item?->order?->no_kamar_perawatan . '/' . $item?->order?->ruang_perawatan); + }else if($item->order?->jenis_customer === "Karyawan RSAB Harapan Kita"){ + $sheet->setCellValue("F{$row}", $item?->order?->bagian_instalasi ?? '-'); + }else{ + $sheet->setCellValue("F{$row}", '-'); + } + $sheet->setCellValue("G{$row}", $item?->status_order ?? "-"); + if($item->menu?->masterMcu){ + $sheet->setCellValue("H{$row}", 'Menu MCU'); + }else{ + $sheet->setCellValue("H{$row}", $item?->menu?->apakah_someday ? "Menu Sameday" : "Menu Normal"); + } + $sheet->setCellValue("I{$row}", $item?->menu?->nama_menu ?? $item?->masterMcu?->nama_mcu); $karbohidratNama = $item?->karbohidrat?->nama_karbohidrat ?? '-'; $karbohidratNilai = $item?->karbohidrat?->nilai_kalori ?? '-'; - $sheet->setCellValue("G{$row}", $karbohidratNama . ($karbohidratNilai !== '-' ? " ({$karbohidratNilai} kal)" : '')); - $sheet->setCellValue("H{$row}", $item?->jumlah ?? '-'); - $sheet->setCellValue("I{$row}", $item?->tgl_antar ? Carbon::parse($item->tgl_antar)->translatedFormat('d F Y') : "Tanggal Antar"); - $sheet->setCellValue("J{$row}", $item?->type ?? "-"); - $sheet->setCellValue("K{$row}", $item?->catatan ?? "-"); + $sheet->setCellValue("J{$row}", $karbohidratNama . ($karbohidratNilai !== '-' ? " ({$karbohidratNilai} kal)" : '')); + $sheet->setCellValue("K{$row}", $item?->total_kalori ?? '-'); + $sheet->setCellValue("L{$row}", $item?->jumlah ?? '-'); + $sheet->setCellValue("M{$row}", $item?->tgl_antar ? Carbon::parse($item->tgl_antar)->translatedFormat('d F Y') : "Tanggal Antar"); + $sheet->setCellValue("N{$row}", $item?->type ?? $item->jam_layanan); + $sheet->setCellValue("O{$row}", $item?->order?->total_harga); + $sheet->setCellValue("P{$row}", $item?->catatan ?? "-"); // Border tiap baris - $sheet->getStyle("A{$row}:K{$row}")->getBorders()->getAllBorders() + $sheet->getStyle("A{$row}:P{$row}")->getBorders()->getAllBorders() ->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); + $totalPendapatan += $item?->order?->total_harga; $row++; } + $sheet->getStyle("L{$row}:O{$row}")->getFont()->setBold(true); + $sheet->getStyle("L{$row}:O{$row}")->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); + $sheet->setCellValue("M{$row}", 'Total Pendapatan'); + $sheet->setCellValue("O{$row}", $totalPendapatan); + // Auto size kolom - foreach(range('A', 'K') as $col){ + foreach(range('A', 'P') as $col){ $sheet->getColumnDimension($col)->setAutoSize(true); } $lastRow = $row - 1; - $sheet->setAutoFilter("A4:K{$lastRow}"); + $sheet->setAutoFilter("A4:P{$lastRow}"); // Download file $fileName = 'menu-pesanan' . now()->format('Ymd-His') . '.xlsx'; $writer = new Xlsx($spreadsheet); @@ -409,7 +492,7 @@ class PesananController extends Controller $type_customer = request('type_customer'); $query = Order::where('statusenabled', true) ->whereBetween('entry_at', [$startDate, $endDate]) - ->whereIn('status_order', ['Menunggu Konfirmasi Pembayaran', 'Menunggu Konfirmasi Pembayaran Via Billing']); + ->whereIn('status_order', ['Menunggu Konfirmasi Pembayaran', 'Menunggu Konfirmasi Pembayaran Via Billing', 'Menunggu Konfirmasi Pesanan MCU']); if($type_customer !== 'all'){ $query->where('jenis_customer', $type_customer); } @@ -447,20 +530,19 @@ class PesananController extends Controller $waktu_cetak = Carbon::now()->locale('id')->translatedFormat('d F Y'); $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); - $sheet->setCellValue('A1', "Laporan Pesanan dari {$startDateFormatted} sampai {$endDateFormatted}"); - $sheet->mergeCells('A1:P1'); + $sheet->mergeCells('A1:T1'); $sheet->getStyle('A1')->getFont()->setBold(true)->setSize(14); $sheet->getStyle('A1')->getAlignment()->setHorizontal('center'); $sheet->setCellValue('A2', "Waktu Cetak: {$waktu_cetak}"); - $sheet->mergeCells('A2:P2'); + $sheet->mergeCells('A2:T2'); $sheet->getStyle('A2')->getAlignment()->setHorizontal('center'); // Header tabel - $headers = ["No", "Nomor Order", "Nama Pemesan", "Jenis Customer", "Status Pembayaran", "Jenis Kelamin", "NO.HP/WA", "Email" , "Cara Pembayaran", "Tanggal Pesan", "Harga Total", "Menu Pesanan", "Jumlah", "Status Pesanan", "Tanggal Antar", "Waktu Makan", "Catatan"]; + $headers = ["No", "Nomor Order", "Nama Pemesan", "Jenis Customer", "Ruangan", "Status Pembayaran", "Jenis Kelamin", "NO.HP/WA", "Email" , "Jenis Pembayaran", "Tanggal Pesan", "Harga Total", "Jenis Menu", "Menu Pesanan", "Total Kalori", "Jumlah", "Status Pesanan", "Tanggal Antar", "Waktu Makan / Jam Layanan", "Catatan"]; $sheet->fromArray($headers, null, 'A4'); - $sheet->getStyle('A4:Q4')->applyFromArray([ + $sheet->getStyle('A4:T4')->applyFromArray([ 'font' => ['bold' => true], 'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER], 'borders' => [ @@ -469,46 +551,64 @@ class PesananController extends Controller ] ] ]); - $sheet->getStyle('A4:Q4')->getFont()->setBold(true); - $sheet->getStyle('A4:Q4')->getAlignment()->setHorizontal('center'); - $sheet->getStyle('A4:Q4')->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); - + $sheet->getStyle('A4:T4')->getFont()->setBold(true); + $sheet->getStyle('A4:T4')->getAlignment()->setHorizontal('center'); + $sheet->getStyle('A4:T4')->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); // Isi data + $totalPendapatan = 0; $row = 5; foreach ($order as $index => $item) { foreach($item->orderDetail as $detail){ + $sheet->setCellValue("A{$row}", $index + 1); $sheet->setCellValue("B{$row}", $item->no_order); $sheet->setCellValue("C{$row}", $item->nama_pemesan); - $sheet->setCellValue("D{$row}", $item->jenis_customer); - $sheet->setCellValue("E{$row}", $item->status_order); - $sheet->setCellValue("F{$row}", $item->jenis_kelamin); - $sheet->setCellValue("G{$row}", $item->no_wa); - $sheet->setCellValue("H{$row}", $item->email); - $sheet->setCellValue("I{$row}", $item->cara_pembayaran); - $sheet->setCellValue("J{$row}", Carbon::parse($item->entry_at)->translatedFormat('d F Y H:i')); - $sheet->setCellValue("K{$row}", $item->total_harga); - - $sheet->setCellValue("L{$row}", $detail?->menu?->nama_menu ?? '-'); - $sheet->setCellValue("M{$row}", $detail?->jumlah ?? '-'); - $sheet->setCellValue("N{$row}", $detail?->status_order ?? "-"); - $sheet->setCellValue("O{$row}", $detail?->tgl_antar ? Carbon::parse($item->tgl_antar)->translatedFormat('d F Y') : "Tanggal Antar"); - $sheet->setCellValue("P{$row}", $detail?->type ?? "-"); - $sheet->setCellValue("Q{$row}", $detail?->catatan ?? "-"); + $sheet->setCellValue("D{$row}", $item->jenis_customer === "MCU" ? $item->nama_institusi . '-' . $item->jenis_customer : $item->jenis_customer); + if($item->jenis_customer === "Keluarga Pasien / Penunggu Pasien"){ + $sheet->setCellValue("E{$row}", $item->kelas_perawatan . '/' . $item->no_kamar_perawatan . '/' . $item->ruang_perawatan); + }else if($item->jenis_customer === "Karyawan RSAB Harapan Kita"){ + $sheet->setCellValue("E{$row}", $item->bagian_instalasi ?? '-'); + }else{ + $sheet->setCellValue("E{$row}", '-'); + } + $sheet->setCellValue("F{$row}", $item->status_order); + $sheet->setCellValue("G{$row}", $item->jenis_kelamin); + $sheet->setCellValue("H{$row}", $item->no_wa); + $sheet->setCellValue("I{$row}", $item->email); + $sheet->setCellValue("J{$row}", $item->cara_pembayaran); + $sheet->setCellValue("K{$row}", Carbon::parse($item->entry_at)->translatedFormat('d F Y H:i')); + $sheet->setCellValue("L{$row}", $item->total_harga); + if($detail?->masterMcu){ + $sheet->setCellValue("M{$row}", 'Menu MCU'); + }else{ + $sheet->setCellValue("M{$row}", $detail?->menu?->apakah_someday ? "Menu Sameday" : "Menu Normal"); + } + $sheet->setCellValue("N{$row}", $detail?->menu?->nama_menu ?? $detail?->masterMcu?->nama_mcu); + $sheet->setCellValue("O{$row}", $detail?->total_kalori ?? '-'); + $sheet->setCellValue("P{$row}", $detail?->jumlah ?? '-'); + $sheet->setCellValue("Q{$row}", $detail?->status_order ?? "-"); + $sheet->setCellValue("R{$row}", $detail?->tgl_antar ? Carbon::parse($item->tgl_antar)->translatedFormat('d F Y') : "Tanggal Antar"); + $sheet->setCellValue("S{$row}", $detail?->type ?? $detail->jam_layanan); + $sheet->setCellValue("T{$row}", $detail?->catatan ?? "-"); // Border tiap baris - $sheet->getStyle("A{$row}:Q{$row}")->getBorders()->getAllBorders() + $sheet->getStyle("A{$row}:T{$row}")->getBorders()->getAllBorders() ->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); - + if($item->status_order === "Lunas"){ + $totalPendapatan += $item?->total_harga; + } $row++; } } - + $sheet->getStyle("K{$row}:L{$row}")->getFont()->setBold(true); + $sheet->getStyle("K{$row}:L{$row}")->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); + $sheet->setCellValue("K{$row}", 'Total Pendapatan'); + $sheet->setCellValue("L{$row}", $totalPendapatan); // Auto size kolom - foreach(range('A', 'Q') as $col){ + foreach(range('A', 'T') as $col){ $sheet->getColumnDimension($col)->setAutoSize(true); } $lastRow = $row - 1; - $sheet->setAutoFilter("A4:Q{$lastRow}"); + $sheet->setAutoFilter("A4:T{$lastRow}"); // Download file $fileName = $title . now()->format('Ymd-His') . '.xlsx'; $writer = new Xlsx($spreadsheet); @@ -600,6 +700,7 @@ class PesananController extends Controller 'total_detail' => $totalDetail, 'selesai_detail' => $selesaiDetail, 'note_dibatalkan' => $first->note_dibatalkan, + 'nama_institusi' => $first->nama_institusi, ]; }) ->values(); @@ -632,6 +733,7 @@ class PesananController extends Controller 'o.note_dibatalkan', 'o.medical_record', 'o.evidence_medical_record', + 'o.nama_institusi', 'od.status_order as detail_status_order' )->get()->groupBy('order_id'); return $data; @@ -682,18 +784,18 @@ class PesananController extends Controller $sheet = $spreadsheet->getActiveSheet(); $sheet->setCellValue('A1', "Laporan Pesanan dari {$startDateFormatted} sampai {$endDateFormatted}"); - $sheet->mergeCells('A1:P1'); + $sheet->mergeCells('A1:R1'); $sheet->getStyle('A1')->getFont()->setBold(true)->setSize(14); $sheet->getStyle('A1')->getAlignment()->setHorizontal('center'); $sheet->setCellValue('A2', "Waktu Cetak: {$waktu_cetak}"); - $sheet->mergeCells('A2:P2'); + $sheet->mergeCells('A2:S2'); $sheet->getStyle('A2')->getAlignment()->setHorizontal('center'); // Header tabel - $headers = ["No", "Nomor Order", "Nama Pemesan", "Jenis Customer", "Jenis Kelamin", "NO.HP/WA", "Email" , "Cara Pembayaran", "Tanggal Pesan", "Harga Total", "Menu Pesanan", "Jumlah", "Status Pesanan", "Tanggal Antar", "Waktu Makan", "Catatan"]; + $headers = ["No", "Nomor Order", "Nama Pemesan", "Jenis Customer", "Ruangan", "Jenis Kelamin", "NO.HP/WA", "Email" , "Jenis Pembayaran", "Tanggal Pesan", "Harga Total", "Jenis Menu", "Menu Pesanan", "Total Kalori (kal)", "Jumlah", "Status Pesanan", "Tanggal Antar", "Waktu Makan / Jam Layanan", "Catatan"]; $sheet->fromArray($headers, null, 'A4'); - $sheet->getStyle('A4:P4')->applyFromArray([ + $sheet->getStyle('A4:S4')->applyFromArray([ 'font' => ['bold' => true], 'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER], 'borders' => [ @@ -702,45 +804,63 @@ class PesananController extends Controller ] ] ]); - $sheet->getStyle('A4:P4')->getFont()->setBold(true); - $sheet->getStyle('A4:P4')->getAlignment()->setHorizontal('center'); - $sheet->getStyle('A4:P4')->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); + $sheet->getStyle('A4:S4')->getFont()->setBold(true); + $sheet->getStyle('A4:S4')->getAlignment()->setHorizontal('center'); + $sheet->getStyle('A4:S4')->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); // Isi data $row = 5; + $totalPendapatan = 0; foreach ($order as $index => $item) { foreach($item->orderDetail as $detail){ $sheet->setCellValue("A{$row}", $index + 1); $sheet->setCellValue("B{$row}", $item->no_order); $sheet->setCellValue("C{$row}", $item->nama_pemesan); - $sheet->setCellValue("D{$row}", $item->jenis_customer); - $sheet->setCellValue("E{$row}", $item->jenis_kelamin); - $sheet->setCellValue("F{$row}", $item->no_wa); - $sheet->setCellValue("G{$row}", $item->email); - $sheet->setCellValue("H{$row}", $item->cara_pembayaran); - $sheet->setCellValue("I{$row}", Carbon::parse($item->entry_at)->translatedFormat('d F Y H:i')); - $sheet->setCellValue("J{$row}", $item->total_harga); + $sheet->setCellValue("D{$row}", $item->jenis_customer === "MCU" ? $item->nama_institusi . '-' . $item->jenis_customer : $item->jenis_customer); + if($item->jenis_customer === "Keluarga Pasien / Penunggu Pasien"){ + $sheet->setCellValue("E{$row}", $item->kelas_perawatan . '/' . $item->no_kamar_perawatan . '/' . $item->ruang_perawatan); + }else if($item->jenis_customer === "Karyawan RSAB Harapan Kita"){ + $sheet->setCellValue("E{$row}", $item->bagian_instalasi ?? '-'); + }else{ + $sheet->setCellValue("E{$row}", '-'); + } + $sheet->setCellValue("F{$row}", $item->jenis_kelamin); + $sheet->setCellValue("G{$row}", $item->no_wa); + $sheet->setCellValue("H{$row}", $item->email); + $sheet->setCellValue("I{$row}", $item->cara_pembayaran); + $sheet->setCellValue("J{$row}", Carbon::parse($item->entry_at)->translatedFormat('d F Y H:i')); + $sheet->setCellValue("K{$row}", $item->total_harga); - $sheet->setCellValue("K{$row}", $detail?->menu?->nama_menu ?? '-'); - $sheet->setCellValue("L{$row}", $detail?->jumlah ?? '-'); - $sheet->setCellValue("M{$row}", $detail?->status_order ?? "-"); - $sheet->setCellValue("N{$row}", $detail?->tgl_antar ? Carbon::parse($item->tgl_antar)->translatedFormat('d F Y') : "Tanggal Antar"); - $sheet->setCellValue("O{$row}", $detail?->type ?? "-"); - $sheet->setCellValue("P{$row}", $detail?->catatan ?? "-"); + if($detail?->masterMcu){ + $sheet->setCellValue("L{$row}", 'Menu MCU'); + }else{ + $sheet->setCellValue("L{$row}", $detail?->menu?->apakah_someday ? "Menu Sameday" : "Menu Normal"); + } + $sheet->setCellValue("M{$row}", $detail?->menu?->nama_menu ?? $detail?->masterMcu?->nama_mcu); + $sheet->setCellValue("N{$row}", $detail?->total_kalori ?? '-'); + $sheet->setCellValue("O{$row}", $detail?->jumlah ?? '-'); + $sheet->setCellValue("P{$row}", $detail?->status_order ?? "-"); + $sheet->setCellValue("Q{$row}", $detail?->tgl_antar ? Carbon::parse($item->tgl_antar)->translatedFormat('d F Y') : "-"); + $sheet->setCellValue("R{$row}", $detail?->type ?? $detail->jam_layanan); + $sheet->setCellValue("S{$row}", $detail?->catatan ?? "-"); // Border tiap baris - $sheet->getStyle("A{$row}:P{$row}")->getBorders()->getAllBorders() + $sheet->getStyle("A{$row}:S{$row}")->getBorders()->getAllBorders() ->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); - + $totalPendapatan += $item->total_harga; $row++; } } - + $sheet->getStyle("I{$row}:K{$row}")->getFont()->setBold(true); + $sheet->getStyle("I{$row}:K{$row}")->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); + $sheet->setCellValue("I{$row}", 'Total Pendapatan'); + $sheet->setCellValue("K{$row}", $totalPendapatan); + // dd($totalPendapatan); // Auto size kolom - foreach(range('A', 'P') as $col){ + foreach(range('A', 'S') as $col){ $sheet->getColumnDimension($col)->setAutoSize(true); } $lastRow = $row - 1; - $sheet->setAutoFilter("A4:P{$lastRow}"); + $sheet->setAutoFilter("A4:S{$lastRow}"); // Download file $fileName = 'laporan-pesanan-' . now()->format('Ymd-His') . '.xlsx'; $writer = new Xlsx($spreadsheet); @@ -847,7 +967,7 @@ class PesananController extends Controller $sheet->setCellValue("A{$row}", $index + 1); $sheet->setCellValue("B{$row}", $item->no_order); $sheet->setCellValue("C{$row}", $item->nama_pemesan); - $sheet->setCellValue("D{$row}", $item->jenis_customer); + $sheet->setCellValue("D{$row}", $item->jenis_customer === "MCU" ? $item->nama_institusi . ' - ' . $item->jenis_customer : $item->jenis_customer); $sheet->setCellValue("E{$row}", $item->cara_pembayaran); $sheet->setCellValue("F{$row}", Carbon::parse($item->entry_at)->translatedFormat('d F Y H:i')); $sheet->setCellValue("G{$row}", $item->total_harga); @@ -924,6 +1044,7 @@ class PesananController extends Controller 'o.note_dibatalkan', 'o.medical_record', 'o.evidence_medical_record', + 'o.nama_institusi', 'od.status_order as detail_status_order' )->get()->groupBy('order_id'); @@ -948,6 +1069,7 @@ class PesananController extends Controller 'total_detail' => $totalDetail, 'selesai_detail' => $selesaiDetail, 'note_dibatalkan' => $first->note_dibatalkan, + 'nama_institusi' => $first->nama_institusi, ]; }) ->values(); @@ -958,6 +1080,15 @@ class PesananController extends Controller 'total' => $grouped->count() ]); } + + public function downloadLabel(){ + $data = request('data'); + $dataArray = explode(',', $data); + $orderDetail = OrderDetail::whereIn('order_detail_id', $dataArray)->with(['masterMcu', 'menu', 'order'])->get(); + $pdf = Pdf::loadView('dashboard.label.multi', compact('orderDetail')); + + return $pdf->stream('label_.pdf'); + } /** * Show the form for creating a new resource. */ diff --git a/app/Http/Controllers/SurveyController.php b/app/Http/Controllers/SurveyController.php new file mode 100644 index 0000000..22fd4ce --- /dev/null +++ b/app/Http/Controllers/SurveyController.php @@ -0,0 +1,178 @@ +has('payment_success')){ + return redirect('/'); + } + $no_order = $request->query('no_order'); + $type = $request->query('type'); + $data = [ + 'title' => 'Survey Gizi', + 'mcu' => false, + 'no_order' => $no_order, + 'type' => $type + ]; + return view('guest.survey.index', $data); + } + + public function store(){ + DB::connection('dbOrderGizi')->beginTransaction(); + try { + $payload =[ + 'no_order' => request('no_order'), + 'type' => request('type'), + 'keterangan' => request('kritik_saran'), + 'kepuasan' => request('kepuasan'), + 'created_at' => now() + ]; + Survey::create($payload); + DB::connection('dbOrderGizi')->commit(); + session()->flash('payment_success', true); + session()->flash('no_order', $payload['no_order']); + return response()->json([ + 'status' => true, + 'message' => 'Survei berhasil disimpan' + ]); + } catch (\Throwable $th) { + DB::connection('dbOrderGizi')->rollBack(); + return response()->json([ + 'status' => false, + 'message' => 'Data gagal disimpan ' . $th->getMessage() + ]); + } + + } + + public function datatable(){ + $data = Survey::query(); + $tanggal = request('tanggal'); + if(!empty($tanggal)){ + $flattened = is_array($tanggal[0]) ? Arr::flatten($tanggal) : $tanggal; + $data->whereIn(DB::raw('DATE(created_at)'), $flattened); + }else{ + $now = Carbon::now()->format('Y-m-d'); + $data->whereDate('created_at', $now); + } + $data = $data->get(); + return response()->json([ + 'rows' => $data->values(), + 'total' => $data->count(), + ]); + } + + public function chartDataSurvey(Request $request) + { + $tanggal = $request->query('tanggal'); + if(is_string($tanggal)) $tanggal = json_decode($tanggal, true); + + $query = Survey::query(); + if (!empty($tanggal) && is_array($tanggal)) { + $query->whereIn(DB::raw('DATE(created_at)'), $tanggal); + } else { + $query->whereDate('created_at', Carbon::today()); + } + + $allData = $query->get(); + + // Pisahkan data untuk perhitungan Card + $dataBaru = $allData->where('type', 'pengguna_baru'); + $dataLama = $allData->where('type', 'pelanggan_setia'); + + return response()->json([ + 'responden' => [ + 'baru' => $dataBaru->count(), + 'lama' => $dataLama->count(), + ], + 'kepuasan_baru' => [ + 'total' => $dataBaru->count(), + 'puas' => $dataBaru->where('kepuasan', 'Puas')->count(), + 'tidak_puas' => $dataBaru->where('kepuasan', 'Tidak Puas')->count(), + ], + 'kepuasan_lama' => [ + 'total' => $dataLama->count(), + 'puas' => $dataLama->where('kepuasan', 'Puas')->count(), + 'tidak_puas' => $dataLama->where('kepuasan', 'Tidak Puas')->count(), + ] + ]); + } + + + public function dashboardSurvey(){ + $data = [ + 'title' => 'List Survey Order Gizi' + ]; + return view('dashboard.survey.index', $data); + } + + public function exportSurveyExcel(){ + $startDate = Carbon::parse(request('start_date'))->startOfDay(); + $endDate = Carbon::parse(request('end_date'))->endOfDay(); + $data = Survey::whereBetween('created_at', [$startDate, $endDate])->get(); + $waktu_cetak = Carbon::now()->locale('id')->translatedFormat('d F Y'); + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('A1', "Laporan Survei dari {$startDate->format('Y-m-d')} sampai {$endDate->format('Y-m-d')}"); + $sheet->mergeCells('A1:E1'); + $sheet->getStyle('A1')->getFont()->setBold(true)->setSize(14); + $sheet->getStyle('A1')->getAlignment()->setHorizontal('center'); + + $sheet->setCellValue('A2', "Waktu Cetak: {$waktu_cetak}"); + $sheet->mergeCells('A2:E2'); + $sheet->getStyle('A2')->getAlignment()->setHorizontal('center'); + + // Header tabel + $headers = ["No", "Nama", "Tipe Survei", "Kepuasan", "Kritik dan Saran"]; + $sheet->fromArray($headers, null, 'A4'); + $sheet->getStyle('A4:E4')->applyFromArray([ + 'font' => ['bold' => true], + 'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER], + 'borders' => [ + 'allBorders' => [ + 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN + ] + ] + ]); + $sheet->getStyle('A4:E4')->getFont()->setBold(true); + $sheet->getStyle('A4:E4')->getAlignment()->setHorizontal('center'); + $sheet->getStyle('A4:E4')->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); + // Isi data + $row = 5; + foreach ($data as $index => $item) { + $sheet->setCellValue("A{$row}", $index + 1); + $sheet->setCellValue("B{$row}", $item->order->nama_pemesan); + $sheet->setCellValue("C{$row}", $item->type === "pelanggan_setia" ? "Pelanggan Setia" : "Pengguna Baru"); + $sheet->setCellValue("D{$row}", $item->kepuasan); + $sheet->setCellValue("E{$row}", $item->keterangan); + $row++; + } + // Auto size kolom + foreach(range('A', 'E') as $col){ + $sheet->getColumnDimension($col)->setAutoSize(true); + } + $lastRow = $row - 1; + $sheet->setAutoFilter("A4:E{$lastRow}"); + // Download file + $fileName = "Laporan Survei {$startDate->format('Y-m-d')} sampai {$endDate->format('Y-m-d')} ". '.xlsx'; + $writer = new Xlsx($spreadsheet); + + // Output ke browser + header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); + header("Content-Disposition: attachment; filename=\"{$fileName}\""); + header('Cache-Control: max-age=0'); + + $writer->save('php://output'); + exit; + } +} diff --git a/app/Models/Karyawan.php b/app/Models/Karyawan.php new file mode 100644 index 0000000..7a3a0d4 --- /dev/null +++ b/app/Models/Karyawan.php @@ -0,0 +1,16 @@ +hasMany(OrderDetail::class, 'order_id')->with('paketMenu', 'menu'); + return $this->hasMany(OrderDetail::class, 'order_id')->with('masterMcu', 'menu'); } } diff --git a/app/Models/OrderDetail.php b/app/Models/OrderDetail.php index 6560000..e75af14 100644 --- a/app/Models/OrderDetail.php +++ b/app/Models/OrderDetail.php @@ -15,7 +15,7 @@ class OrderDetail extends Model 'modified_at', 'statusenabled', 'master_menu_id', - 'paket_mcu_id', + 'menu_mcu_id', 'harga_satuan', 'jumlah', 'tgl_antar', @@ -24,13 +24,14 @@ class OrderDetail extends Model 'status_order', 'karbohidrat_id', 'catatan', - 'jam_layanan' + 'jam_layanan', + 'total_kalori' ]; public function menu(){ - return $this->belongsTo(Menu::class, 'master_menu_id', 'master_menu_id')->select('master_menu_id', 'nama_menu', 'foto'); + return $this->belongsTo(Menu::class, 'master_menu_id', 'master_menu_id')->select('master_menu_id', 'nama_menu', 'foto', 'apakah_someday', 'apakah_mcu'); } public function karbohidrat(){ return $this->belongsTo(Karbohidrat::class, 'karbohidrat_id', 'karbohidrat_id')->select('karbohidrat_id', 'nama_karbohidrat', 'nilai_kalori'); @@ -38,4 +39,7 @@ class OrderDetail extends Model public function order(){ return $this->belongsTo(Order::class, 'order_id', 'order_id'); } + public function masterMcu(){ + return $this->belongsTo(MasterMcu::class, 'menu_mcu_id', 'menu_mcu_id'); + } } diff --git a/app/Models/Survey.php b/app/Models/Survey.php new file mode 100644 index 0000000..ff55e61 --- /dev/null +++ b/app/Models/Survey.php @@ -0,0 +1,25 @@ +belongsTo(Order::class, 'no_order', 'no_order')->select('no_order', 'nama_pemesan'); + } +} diff --git a/app/Models/UnitInstalasi.php b/app/Models/UnitInstalasi.php new file mode 100644 index 0000000..a9fe49e --- /dev/null +++ b/app/Models/UnitInstalasi.php @@ -0,0 +1,16 @@ +by($request->ip()); + }); + Blade::component('dashboard.pesanan.components.modalExport', 'modalExport'); Blade::component('dashboard.pesanan.components.infoPesanan', 'infoPesanan'); + if ($this->app->environment('production')) { + URL::forceScheme('https'); + } } } diff --git a/composer.json b/composer.json index ceae8c3..4375997 100644 --- a/composer.json +++ b/composer.json @@ -8,6 +8,7 @@ "require": { "php": "^8.2", "barryvdh/laravel-dompdf": "^3.1", + "barryvdh/laravel-snappy": "^1.0", "laravel/framework": "^12.0", "laravel/tinker": "^2.10.1", "phpoffice/phpspreadsheet": "^4.5" diff --git a/composer.lock b/composer.lock index 4bf5e89..e0b5412 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "696ae0d1187bc1634529f1760a11ffd0", + "content-hash": "9d83b6a45b530b893999cf984c08fde5", "packages": [ { "name": "barryvdh/laravel-dompdf", @@ -83,6 +83,84 @@ ], "time": "2025-02-13T15:07:54+00:00" }, + { + "name": "barryvdh/laravel-snappy", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/barryvdh/laravel-snappy.git", + "reference": "5b8668e4a54be630973fd309b4cb1abe75a8afbb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/barryvdh/laravel-snappy/zipball/5b8668e4a54be630973fd309b4cb1abe75a8afbb", + "reference": "5b8668e4a54be630973fd309b4cb1abe75a8afbb", + "shasum": "" + }, + "require": { + "illuminate/filesystem": "^9|^10|^11|^12", + "illuminate/support": "^9|^10|^11|^12", + "knplabs/knp-snappy": "^1.4.4", + "php": "^8.1" + }, + "require-dev": { + "orchestra/testbench": "^7|^8|^9|^10" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "PDF": "Barryvdh\\Snappy\\Facades\\SnappyPdf", + "SnappyImage": "Barryvdh\\Snappy\\Facades\\SnappyImage" + }, + "providers": [ + "Barryvdh\\Snappy\\ServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Barryvdh\\Snappy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "Snappy PDF/Image for Laravel", + "keywords": [ + "image", + "laravel", + "pdf", + "snappy", + "wkhtmltoimage", + "wkhtmltopdf" + ], + "support": { + "issues": "https://github.com/barryvdh/laravel-snappy/issues", + "source": "https://github.com/barryvdh/laravel-snappy/tree/v1.0.4" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2025-02-24T15:20:06+00:00" + }, { "name": "brick/math", "version": "0.13.1", @@ -1365,6 +1443,73 @@ ], "time": "2025-02-03T10:55:03+00:00" }, + { + "name": "knplabs/knp-snappy", + "version": "v1.5.1", + "source": { + "type": "git", + "url": "https://github.com/KnpLabs/snappy.git", + "reference": "3dd138e9e47de91cd2e056c5e6e1a0dd72547ee7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/KnpLabs/snappy/zipball/3dd138e9e47de91cd2e056c5e6e1a0dd72547ee7", + "reference": "3dd138e9e47de91cd2e056c5e6e1a0dd72547ee7", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^2.0||^3.0", + "symfony/process": "^5.0||^6.0||^7.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.0", + "pedrotroller/php-cs-custom-fixer": "^2.19", + "phpstan/phpstan": "^1.0.0", + "phpstan/phpstan-phpunit": "^1.0.0", + "phpunit/phpunit": "^8.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Knp\\Snappy\\": "src/Knp/Snappy" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "KNP Labs Team", + "homepage": "http://knplabs.com" + }, + { + "name": "Symfony Community", + "homepage": "http://github.com/KnpLabs/snappy/contributors" + } + ], + "description": "PHP library allowing thumbnail, snapshot or PDF generation from a url or a html page. Wrapper for wkhtmltopdf/wkhtmltoimage.", + "homepage": "http://github.com/KnpLabs/snappy", + "keywords": [ + "knp", + "knplabs", + "pdf", + "snapshot", + "thumbnail", + "wkhtmltopdf" + ], + "support": { + "issues": "https://github.com/KnpLabs/snappy/issues", + "source": "https://github.com/KnpLabs/snappy/tree/v1.5.1" + }, + "time": "2025-01-06T16:53:26+00:00" + }, { "name": "laravel/framework", "version": "v12.20.0", diff --git a/config/database.php b/config/database.php index c3004ca..6f02fa6 100644 --- a/config/database.php +++ b/config/database.php @@ -16,7 +16,7 @@ return [ | */ - 'default' => env('DB_CONNECTION', 'sqlite'), + 'default' => env('DB_CONNECTION', 'pgsql'), /* |-------------------------------------------------------------------------- @@ -152,6 +152,28 @@ return [ 'timezone' => env('APP_TIMEZONE', 'utc' ), ], + 'dbKaryawan' => [ + 'driver' => 'pgsql', + 'url' => env('DB_URL'), + 'host' => env('DB_HOST_KARYAWAN', '127.0.0.1'), + 'port' => env('DB_PORT_KARYAWAN', '3306'), + 'database' => env('DB_DATABASE_KARYAWAN', 'laravel'), + 'username' => env('DB_USERNAME_KARYAWAN', 'root'), + 'password' => env('DB_PASSWORD_KARYAWAN', ''), + 'charset' => env('DB_CHARSET', 'utf8'), + 'prefix' => '', + 'prefix_indexes' => true, + 'search_path' => 'public', + 'sslmode' => 'prefer', + 'prefix' => '', + 'prefix_indexes' => true, + 'search_path' => 'public', + 'sslmode' => 'prefer', + 'timezone' => env('APP_TIMEZONE', 'utc' ), + ], + + + ], /* diff --git a/config/snappy.php b/config/snappy.php new file mode 100644 index 0000000..cc28fbc --- /dev/null +++ b/config/snappy.php @@ -0,0 +1,52 @@ + [ + 'enabled' => true, + 'binary' => env('WKHTML_PDF_BINARY', '/usr/local/bin/wkhtmltopdf'), + 'timeout' => false, + 'options' => [], + 'env' => [], + ], + + 'image' => [ + 'enabled' => true, + 'binary' => env('WKHTML_IMG_BINARY', '/usr/local/bin/wkhtmltoimage'), + 'timeout' => false, + 'options' => [], + 'env' => [], + ], + +]; diff --git a/env_prod b/env_prod index ce41865..5d2f816 100644 --- a/env_prod +++ b/env_prod @@ -1,9 +1,9 @@ APP_NAME=Laravel -APP_ENV=local +APP_ENV=production APP_KEY=base64:R54Pgs6qwWsP6eKZGCcHNd7rrsSSU0DsWSbFHwaT4Bc= APP_DEBUG=true APP_URL=http://127.0.0.1:8000/ -APP_TIMEZONE =Asia/Jakarta +APP_TIMEZONE=Asia/Jakarta APP_LOCALE=en APP_FALLBACK_LOCALE=en APP_FAKER_LOCALE=en_US @@ -23,16 +23,16 @@ LOG_LEVEL=debug DB_CONNECTION_ORDER_GIZI= pgsql DB_HOST_ORDER_GIZI = 172.16.88.22 DB_PORT_ORDER_GIZI = 5432 -DB_DATABASE_ORDER_GIZI = order_gizi +DB_DATABASE_ORDER_GIZI = lms_mutu DB_USERNAME_ORDER_GIZI = simrs DB_PASSWORD_ORDER_GIZI = @S1mrs.3205@ -DB_CONNECTION_ORDER_GIZI= pgsql -DB_HOST_ORDER_GIZI = 172.16.88.22 -DB_PORT_ORDER_GIZI = 5432 -DB_DATABASE_ORDER_GIZI = order_gizi -DB_USERNAME_ORDER_GIZI = simrs -DB_PASSWORD_ORDER_GIZI = @S1mrs.3205@ +DB_CONNECTION_AUTH_KARYAWAN = pgsql +DB_HOST_KARYAWAN = psql1.rsabhk.lan +DB_PORT_KARYAWAN = 5432 +DB_DATABASE_KARYAWAN = rsab_hk_production +DB_USERNAME_KARYAWAN = postgres +DB_PASSWORD_KARYAWAN = postgres DB_CONNECTION_AUTH_DEV = pgsql DB_HOST_AUTH_DEV = 172.16.88.22 diff --git a/public/asset_guests/css/main.css b/public/asset_guests/css/main.css index 4e48dca..bc9731f 100644 --- a/public/asset_guests/css/main.css +++ b/public/asset_guests/css/main.css @@ -305,7 +305,7 @@ h6 { } .header .logo img { - max-height: 36px; + max-height: 60px; margin-right: 8px; } @@ -347,6 +347,10 @@ h6 { .header .navmenu { order: 3; } + .header .logo img { + max-height: 35px; + margin-right: 8px; + } } .scrolled .header { diff --git a/public/asset_guests/vendor/js/checkOrderHref.js b/public/asset_guests/vendor/js/checkOrderHref.js index 24f0faa..bf98f58 100644 --- a/public/asset_guests/vendor/js/checkOrderHref.js +++ b/public/asset_guests/vendor/js/checkOrderHref.js @@ -1,3 +1,6 @@ function checkOrderHref(){ window.location.href = '/check-order' } +function mcu(){ + window.location.href = '/order-mcu' +} diff --git a/public/assets/img/avatars/8.jpg b/public/assets/img/avatars/8.jpg new file mode 100644 index 0000000..1129ea7 Binary files /dev/null and b/public/assets/img/avatars/8.jpg differ diff --git a/public/cara_pesan/order_karyawan.png b/public/cara_pesan/order_karyawan.png new file mode 100644 index 0000000..037baaf Binary files /dev/null and b/public/cara_pesan/order_karyawan.png differ diff --git a/public/cara_pesan/order_keluarga_pasien.png b/public/cara_pesan/order_keluarga_pasien.png new file mode 100644 index 0000000..820f7ab Binary files /dev/null and b/public/cara_pesan/order_keluarga_pasien.png differ diff --git a/public/cara_pesan/order_masyarakat_umum.png b/public/cara_pesan/order_masyarakat_umum.png new file mode 100644 index 0000000..5299ae6 Binary files /dev/null and b/public/cara_pesan/order_masyarakat_umum.png differ diff --git a/public/gambar/1NLtrcy20GE5m8e.jpg b/public/gambar/1NLtrcy20GE5m8e.jpg new file mode 100644 index 0000000..1aea8f5 Binary files /dev/null and b/public/gambar/1NLtrcy20GE5m8e.jpg differ diff --git a/public/gambar/1VhHxJmuroGL7z6.jpg b/public/gambar/1VhHxJmuroGL7z6.jpg new file mode 100644 index 0000000..8d6d04c Binary files /dev/null and b/public/gambar/1VhHxJmuroGL7z6.jpg differ diff --git a/public/gambar/3Y3Ez9eazDjltwU.jpg b/public/gambar/3Y3Ez9eazDjltwU.jpg new file mode 100644 index 0000000..f2484da Binary files /dev/null and b/public/gambar/3Y3Ez9eazDjltwU.jpg differ diff --git a/public/gambar/608,577,598,602,606.pdf b/public/gambar/608,577,598,602,606.pdf new file mode 100644 index 0000000..c0481fa Binary files /dev/null and b/public/gambar/608,577,598,602,606.pdf differ diff --git a/public/gambar/6cphK0gBVbdDpy7.jpg b/public/gambar/6cphK0gBVbdDpy7.jpg new file mode 100644 index 0000000..f7d8215 Binary files /dev/null and b/public/gambar/6cphK0gBVbdDpy7.jpg differ diff --git a/public/gambar/BDyQv2C3ZJstYk5.jpg b/public/gambar/BDyQv2C3ZJstYk5.jpg new file mode 100644 index 0000000..98d1c32 Binary files /dev/null and b/public/gambar/BDyQv2C3ZJstYk5.jpg differ diff --git a/public/gambar/BcQLFyCRKbD7fGm.jpg b/public/gambar/BcQLFyCRKbD7fGm.jpg new file mode 100644 index 0000000..65c49f2 Binary files /dev/null and b/public/gambar/BcQLFyCRKbD7fGm.jpg differ diff --git a/public/gambar/BhVLQcmU0pVMzQ5.jpg b/public/gambar/BhVLQcmU0pVMzQ5.jpg new file mode 100644 index 0000000..524daf2 Binary files /dev/null and b/public/gambar/BhVLQcmU0pVMzQ5.jpg differ diff --git a/public/gambar/CXtFH1srSvubaRK.jpg b/public/gambar/CXtFH1srSvubaRK.jpg new file mode 100644 index 0000000..3bdccb2 Binary files /dev/null and b/public/gambar/CXtFH1srSvubaRK.jpg differ diff --git a/public/gambar/DA1gXOOK4cMnL65.jpg b/public/gambar/DA1gXOOK4cMnL65.jpg new file mode 100644 index 0000000..ce2830e Binary files /dev/null and b/public/gambar/DA1gXOOK4cMnL65.jpg differ diff --git a/public/gambar/DX8Ev2haNMqhqgq.jpg b/public/gambar/DX8Ev2haNMqhqgq.jpg new file mode 100644 index 0000000..37dc734 Binary files /dev/null and b/public/gambar/DX8Ev2haNMqhqgq.jpg differ diff --git a/public/gambar/EcyHylUTMAVohMF.jpg b/public/gambar/EcyHylUTMAVohMF.jpg new file mode 100644 index 0000000..8d6d04c Binary files /dev/null and b/public/gambar/EcyHylUTMAVohMF.jpg differ diff --git a/public/gambar/GaQjbwEteuivk8G.jpg b/public/gambar/GaQjbwEteuivk8G.jpg new file mode 100644 index 0000000..d2a5bea Binary files /dev/null and b/public/gambar/GaQjbwEteuivk8G.jpg differ diff --git a/public/gambar/Lh5maoUqSTSHPpk.jpg b/public/gambar/Lh5maoUqSTSHPpk.jpg new file mode 100644 index 0000000..ceff63d Binary files /dev/null and b/public/gambar/Lh5maoUqSTSHPpk.jpg differ diff --git a/public/gambar/MIBkGAo6Wsv5U8J.jpg b/public/gambar/MIBkGAo6Wsv5U8J.jpg new file mode 100644 index 0000000..a664e84 Binary files /dev/null and b/public/gambar/MIBkGAo6Wsv5U8J.jpg differ diff --git a/public/gambar/MonkDUcZnb2adsT.jpg b/public/gambar/MonkDUcZnb2adsT.jpg new file mode 100644 index 0000000..19b0722 Binary files /dev/null and b/public/gambar/MonkDUcZnb2adsT.jpg differ diff --git a/public/gambar/NWj9s7XJsEznf32.jpg b/public/gambar/NWj9s7XJsEznf32.jpg new file mode 100644 index 0000000..4acf3d8 Binary files /dev/null and b/public/gambar/NWj9s7XJsEznf32.jpg differ diff --git a/public/gambar/Nmq2csw3jlvDbFn.jpg b/public/gambar/Nmq2csw3jlvDbFn.jpg new file mode 100644 index 0000000..ff5288c Binary files /dev/null and b/public/gambar/Nmq2csw3jlvDbFn.jpg differ diff --git a/public/gambar/OfSOkI4v8QOFLDQ.jpg b/public/gambar/OfSOkI4v8QOFLDQ.jpg new file mode 100644 index 0000000..1fe92ed Binary files /dev/null and b/public/gambar/OfSOkI4v8QOFLDQ.jpg differ diff --git a/public/gambar/S1D5M5yyMNxmKWO.jpg b/public/gambar/S1D5M5yyMNxmKWO.jpg new file mode 100644 index 0000000..bb0f3de Binary files /dev/null and b/public/gambar/S1D5M5yyMNxmKWO.jpg differ diff --git a/public/gambar/T3ykjc5sLJCJ3ys.jpg b/public/gambar/T3ykjc5sLJCJ3ys.jpg new file mode 100644 index 0000000..2023f0c Binary files /dev/null and b/public/gambar/T3ykjc5sLJCJ3ys.jpg differ diff --git a/public/gambar/Ukd0oblLPOj2gGk.jpg b/public/gambar/Ukd0oblLPOj2gGk.jpg new file mode 100644 index 0000000..bb812ac Binary files /dev/null and b/public/gambar/Ukd0oblLPOj2gGk.jpg differ diff --git a/public/gambar/V47AjynduyGYBKJ.jpg b/public/gambar/V47AjynduyGYBKJ.jpg new file mode 100644 index 0000000..a1877fb Binary files /dev/null and b/public/gambar/V47AjynduyGYBKJ.jpg differ diff --git a/public/gambar/ZyRXajWB3BFyCIJ.jpg b/public/gambar/ZyRXajWB3BFyCIJ.jpg new file mode 100644 index 0000000..d7fdf6b Binary files /dev/null and b/public/gambar/ZyRXajWB3BFyCIJ.jpg differ diff --git a/public/gambar/bt6RNaVgLohDg74.jpg b/public/gambar/bt6RNaVgLohDg74.jpg new file mode 100644 index 0000000..20bfa61 Binary files /dev/null and b/public/gambar/bt6RNaVgLohDg74.jpg differ diff --git a/public/gambar/c8RrP9pmbFQ5wPd.jpg b/public/gambar/c8RrP9pmbFQ5wPd.jpg new file mode 100644 index 0000000..ab98a02 Binary files /dev/null and b/public/gambar/c8RrP9pmbFQ5wPd.jpg differ diff --git a/public/gambar/cG1OGeEi5XzhUOK.jpg b/public/gambar/cG1OGeEi5XzhUOK.jpg new file mode 100644 index 0000000..7d8f1d1 Binary files /dev/null and b/public/gambar/cG1OGeEi5XzhUOK.jpg differ diff --git a/public/gambar/clLvziFQZnHVnMq.jpg b/public/gambar/clLvziFQZnHVnMq.jpg new file mode 100644 index 0000000..891abf5 Binary files /dev/null and b/public/gambar/clLvziFQZnHVnMq.jpg differ diff --git a/public/gambar/cs79vVJJbFkAV1C.jpg b/public/gambar/cs79vVJJbFkAV1C.jpg new file mode 100644 index 0000000..03dee42 Binary files /dev/null and b/public/gambar/cs79vVJJbFkAV1C.jpg differ diff --git a/public/gambar/d8ASQ3mkBbAkjPR.jpg b/public/gambar/d8ASQ3mkBbAkjPR.jpg new file mode 100644 index 0000000..65c49f2 Binary files /dev/null and b/public/gambar/d8ASQ3mkBbAkjPR.jpg differ diff --git a/public/gambar/dAVbOJQeJnGogUg.jpg b/public/gambar/dAVbOJQeJnGogUg.jpg new file mode 100644 index 0000000..98d1c32 Binary files /dev/null and b/public/gambar/dAVbOJQeJnGogUg.jpg differ diff --git a/public/gambar/default.png b/public/gambar/default.png new file mode 100644 index 0000000..a4f6704 Binary files /dev/null and b/public/gambar/default.png differ diff --git a/public/gambar/iJCWE840NZ8CPrD.jpg b/public/gambar/iJCWE840NZ8CPrD.jpg new file mode 100644 index 0000000..126122d Binary files /dev/null and b/public/gambar/iJCWE840NZ8CPrD.jpg differ diff --git a/public/gambar/m0UEA7GZ3eqH6yZ.jpg b/public/gambar/m0UEA7GZ3eqH6yZ.jpg new file mode 100644 index 0000000..322ca31 Binary files /dev/null and b/public/gambar/m0UEA7GZ3eqH6yZ.jpg differ diff --git a/public/gambar/sKEpPVmmXHGH42e.jpg b/public/gambar/sKEpPVmmXHGH42e.jpg new file mode 100644 index 0000000..7502f24 Binary files /dev/null and b/public/gambar/sKEpPVmmXHGH42e.jpg differ diff --git a/public/gambar/sjFBBFhx2wpSuE8.jpg b/public/gambar/sjFBBFhx2wpSuE8.jpg new file mode 100644 index 0000000..c42d79b Binary files /dev/null and b/public/gambar/sjFBBFhx2wpSuE8.jpg differ diff --git a/public/gambar/teCc2Q88QGhBUQL.jpg b/public/gambar/teCc2Q88QGhBUQL.jpg new file mode 100644 index 0000000..7502f24 Binary files /dev/null and b/public/gambar/teCc2Q88QGhBUQL.jpg differ diff --git a/public/gambar/ui9A9mjwVaZq2hj.jpg b/public/gambar/ui9A9mjwVaZq2hj.jpg new file mode 100644 index 0000000..013d276 Binary files /dev/null and b/public/gambar/ui9A9mjwVaZq2hj.jpg differ diff --git a/public/gambar/vajeyxcmaRf6JR3.jpg b/public/gambar/vajeyxcmaRf6JR3.jpg new file mode 100644 index 0000000..f4729a6 Binary files /dev/null and b/public/gambar/vajeyxcmaRf6JR3.jpg differ diff --git a/public/gambar/yugmkzUNtvyoKXG.jpg b/public/gambar/yugmkzUNtvyoKXG.jpg new file mode 100644 index 0000000..bb812ac Binary files /dev/null and b/public/gambar/yugmkzUNtvyoKXG.jpg differ diff --git a/public/gambar/zc8vn0ZMLirPaAJ.jpg b/public/gambar/zc8vn0ZMLirPaAJ.jpg new file mode 100644 index 0000000..deacad0 Binary files /dev/null and b/public/gambar/zc8vn0ZMLirPaAJ.jpg differ diff --git a/public/js/checkout/action.js b/public/js/checkout/action.js index 2dc891d..3602fb6 100644 --- a/public/js/checkout/action.js +++ b/public/js/checkout/action.js @@ -1,8 +1,7 @@ - async function submitOrderToServer(){ const totalHarga = hitungTotalHarga(); - if (sessionStorage.getItem('order_id')) { + if (sessionStorage.getItem('order_id')) { currentStep = 2; showStep(currentStep); return; @@ -33,7 +32,12 @@ async function submitOrderToServer(){ } } catch (error) { console.error('message '+error); - alert('Terdapat kesalahan coba lagi nanti!') + Swal.fire({ + title: 'Gagal!', + text: 'Terdapat kesalahan coba lagi nanti!', + icon: 'error', + confirmButtonText: 'Tutup!' + }) } } @@ -65,6 +69,11 @@ async function submitOrderToServer(){ $("#checkoutFormFinal").on('submit', async function(e){ e.preventDefault() + const buttonSubmit = $(this).find('button[type="submit"]') + if(buttonSubmit.prop('disabled')) return; + buttonSubmit.prop('disabled', true) + .html('Memproses...') + const cara_pembayaran = document.getElementById('cara_pembayaran').value; const bukti_pembayaran = document.querySelector('input[name="bukti_pembayaran"]').value; @@ -74,6 +83,7 @@ async function submitOrderToServer(){ text: 'Silahkan upload bukti pembayaran jika metode yang dipakai transfer.', icon: 'warning', }) + buttonSubmit.prop('disabled', false).html('Selesaikan Pesanan'); return; } @@ -81,6 +91,12 @@ async function submitOrderToServer(){ const form = this; const formData = new FormData(form); + const clearSession = () => { + sessionStorage.removeItem('cart'); + sessionStorage.removeItem('checkout_biodata'); + sessionStorage.removeItem('order_id'); + sessionStorage.removeItem('time_order'); + }; try { const response = await fetch('/finish-checkout', { @@ -92,29 +108,41 @@ async function submitOrderToServer(){ }); const result = await response.json(); - if (result.status) { // ✅ Hapus sessionStorage di client - sessionStorage.removeItem('cart'); - sessionStorage.removeItem('checkout_biodata'); - sessionStorage.removeItem('order_id'); - sessionStorage.removeItem('time_order'); - + clearSession() Swal.fire({ - title: 'Pesanan Berhasil!', - text: 'Terima kasih, pesanan Anda sedang kami siapkan.', + title: 'Pesanan Berhasil!', icon: 'success', - confirmButtonText: 'Berhasil!', - confirmButtonColor: '#28a745' - }).then(() => { - window.location.href = "/success-page"; // kehalaman success - }); + iconColor: '#2e7d32', // Warna hijau Kemenkes + html: ` +
Terima kasih, pesanan Anda sedang kami siapkan.
+Bantu Kami Meningkatkan Layanan:
+ + + + +
- ${item.deskripsi}
` : ''} -
+ ${item.deskripsi}
` : ''} + + +
Nama Menu: ${detail?.menu?.nama_menu || '-'}
+Nama Menu: ${detail?.menu?.nama_menu || detail?.master_mcu?.nama_mcu}
Jumlah: ${detail?.jumlah || 0}
-Tanggal Pesan: ${detail?.tgl_antar || 0}
+ ${detail?.total_kalori ? `Total Kalori: ${detail?.total_kalori } kal
` : ''} + +Tanggal Antar: ${detail?.tgl_antar || 0}
Harga: Rp ${parseInt(detail?.harga_satuan || 0).toLocaleString('id-ID')}
Status Pesanan:
-Catatan : ${detail?.catatan || '-'}
+ ${detail?.catatan ? `Catatan : ${detail?.catatan || '-'}
` : ''}Alamat: ${data.alamat || '-'}
Bagian / Instalasi: ${data.bagian_instalasi}
Ekstensien: ${data.no_ekstensien || '-'}
+
+ | Tanggal Pemeriksaan + | +: {{ $label?->tgl_antar ? \Carbon\Carbon::parse($label->tgl_antar)->translatedFormat('d F Y') : '-' }} + | +
| {{ $label->order?->jenis_customer !== 'MCU' ? 'Nama Pemesan' : 'Nama Pasien'}} + {{ $label?->order?->jenis_customer === "Keluarga Pasien / Penunggu Pasien" ? '/ Pasien' : ''}} + | +: + + {{ $label?->order?->nama_pemesan }} {{ $label?->order?->jenis_customer === "Keluarga Pasien / Penunggu Pasien" ? '/ ' . $label?->order?->nama_pasien : ''}} + + | +
| Ruang Perawatan/No Kamar | +: + + {{ $label?->order?->ruang_perawatan ?? '-'}} / {{ $label?->order?->no_kamar_perawatan ?? '-'}} + + | +
| Bagian/No Ekstensien | +: + + {{ $label?->order?->bagian_instalasi ?? '-'}} / {{ $label?->order?->no_ekstensien ?? '-'}} + + | +
| Nama Institusi | +: + + {{ $label?->order?->nama_institusi }} + + + | +
| {{ $label->order?->jenis_customer !== 'MCU' ? 'Pesanan' : 'Jenis MCU'}} | ++ : + + {{ $label?->masterMcu?->nama_mcu ?? $label?->menu?->nama_menu }} + + | +
| Total Kalori | : {{ $label->total_kalori }} |
| Catatan | +: + + {{ $label?->catatan ?? '-' }} + | +
| Tanggal Produksi | : {{ $label?->tgl_antar ? \Carbon\Carbon::parse($label->tgl_antar)->translatedFormat('d F Y') : '-' }} |
| No. Telp | : {{ $label?->order?->no_wa ?? '-' }} |
| Alamat | +: + + {{ $label?->order?->alamat }} + + + | +