done -> next review pengembangan gizi

This commit is contained in:
JokoPrasetio 2026-03-16 13:18:55 +07:00
parent cf29cd2695
commit 258ba46cb7
19 changed files with 691 additions and 20 deletions

View File

@ -399,6 +399,7 @@ class CustomerController extends Controller
session()->flash('no_order', $noOrder); session()->flash('no_order', $noOrder);
return response([ return response([
'status' => true, 'status' => true,
'no_order' => $noOrder,
'message' => 'Terima kasih atas pesanan Anda. Mohon tunggu, kami sedang memprosesnya' 'message' => 'Terima kasih atas pesanan Anda. Mohon tunggu, kami sedang memprosesnya'
], 200); ], 200);
return back()->with('success', 'Bukti pembayaran berhasil diunggah.'); return back()->with('success', 'Bukti pembayaran berhasil diunggah.');

View File

@ -0,0 +1,178 @@
<?php
namespace App\Http\Controllers;
use App\Models\Survey;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Arr;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
class SurveyController extends Controller
{
public function index(Request $request){
if(!session()->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;
}
}

25
app/Models/Survey.php Normal file
View File

@ -0,0 +1,25 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Survey extends Model
{
protected $connection = 'dbOrderGizi';
protected $table = 'public.survey';
public $timestamps = false;
protected $primaryKey = "id";
protected $with = ['order'];
protected $fillable =[
'no_order',
'type',
'keterangan',
'kepuasan',
'created_at'
];
public function order(){
return $this->belongsTo(Order::class, 'no_order', 'no_order')->select('no_order', 'nama_pemesan');
}
}

View File

@ -3,7 +3,7 @@ APP_ENV=production
APP_KEY=base64:R54Pgs6qwWsP6eKZGCcHNd7rrsSSU0DsWSbFHwaT4Bc= APP_KEY=base64:R54Pgs6qwWsP6eKZGCcHNd7rrsSSU0DsWSbFHwaT4Bc=
APP_DEBUG=true APP_DEBUG=true
APP_URL=http://127.0.0.1:8000/ APP_URL=http://127.0.0.1:8000/
APP_TIMEZONE =Asia/Jakarta APP_TIMEZONE=Asia/Jakarta
APP_LOCALE=en APP_LOCALE=en
APP_FALLBACK_LOCALE=en APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US APP_FAKER_LOCALE=en_US
@ -23,7 +23,7 @@ LOG_LEVEL=debug
DB_CONNECTION_ORDER_GIZI= pgsql DB_CONNECTION_ORDER_GIZI= pgsql
DB_HOST_ORDER_GIZI = 172.16.88.22 DB_HOST_ORDER_GIZI = 172.16.88.22
DB_PORT_ORDER_GIZI = 5432 DB_PORT_ORDER_GIZI = 5432
DB_DATABASE_ORDER_GIZI = order_gizi DB_DATABASE_ORDER_GIZI = lms_mutu
DB_USERNAME_ORDER_GIZI = simrs DB_USERNAME_ORDER_GIZI = simrs
DB_PASSWORD_ORDER_GIZI = @S1mrs.3205@ DB_PASSWORD_ORDER_GIZI = @S1mrs.3205@

View File

@ -305,7 +305,7 @@ h6 {
} }
.header .logo img { .header .logo img {
max-height: 36px; max-height: 60px;
margin-right: 8px; margin-right: 8px;
} }
@ -347,6 +347,10 @@ h6 {
.header .navmenu { .header .navmenu {
order: 3; order: 3;
} }
.header .logo img {
max-height: 35px;
margin-right: 8px;
}
} }
.scrolled .header { .scrolled .header {

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

View File

@ -109,16 +109,41 @@ async function submitOrderToServer(){
}); });
const result = await response.json(); const result = await response.json();
if (result.status) { if (result.status) {
// ✅ Hapus sessionStorage di client // ✅ Hapus sessionStorage di client
clearSession() clearSession()
Swal.fire({ Swal.fire({
title: 'Pesanan Berhasil!', title: '<span style="color: #00796b;">Pesanan Berhasil!</span>',
text: 'Terima kasih, pesanan Anda sedang kami siapkan.',
icon: 'success', icon: 'success',
confirmButtonText: 'Berhasil!', iconColor: '#2e7d32', // Warna hijau Kemenkes
confirmButtonColor: '#28a745' html: `
<p class="text-muted mb-4">Terima kasih, pesanan Anda sedang kami siapkan.</p>
<div class="p-3 border-0 rounded-4 shadow-sm mb-3" style="background-color: #f1f8f7;">
<p class="small fw-bold mb-3 text-uppercase" style="color: #004d40; letter-spacing: 1px;">Bantu Kami Meningkatkan Layanan:</p>
<button type="button" onclick="location.href='/survey?no_order=${result.no_order}&type=pengguna_baru'"
class="btn w-100 mb-3 py-3 border-0 shadow-sm transition-hover"
style="background-color: #00a99d; color: white; border-radius: 12px;">
<div class="fw-bold px-2">Saya Pengguna Baru</div>
<div style="font-size: 0.75rem; opacity: 0.9;">Survei kemudahan aplikasi pemesanan</div>
</button>
<button type="button" onclick="location.href='/survey?no_order=${result.no_order}&type=pelanggan_setia'"
class="btn w-100 py-3 border-0 shadow-sm transition-hover"
style="background-color: #005eb8; color: white; border-radius: 12px;">
<div class="fw-bold px-2">Saya Pelanggan Setia</div>
<div style="font-size: 0.75rem; opacity: 0.9;">Survei rasa, variasi, dan penampilan menu</div>
</button>
</div>
`,
showConfirmButton: false,
showCancelButton: true,
cancelButtonText: 'Lewati & Selesai',
cancelButtonColor: '#6c757d',
customClass: {
popup: 'rounded-4',
cancelButton: 'px-4 py-2 rounded-3'
}
}).then(() => { }).then(() => {
window.location.href = "/success-page"; // kehalaman success window.location.href = "/success-page"; // kehalaman success
}); });

View File

@ -246,13 +246,28 @@ function toggleCustomerFields() {
$("#help_email_karyawan").removeClass('d-none') $("#help_email_karyawan").removeClass('d-none')
selectKaryawan(); // inisialisasi ulang selectize selectKaryawan(); // inisialisasi ulang selectize
break; break;
case 'Karyawan RSAB Harapan Kita (Rapat Internal, Seminar /Pelatihan)':
$('.karyawan').show();
$nama.val('')
$nama.removeClass('form-control')
$("#help_nama_pemesan").removeClass('d-none')
$("#help_email_karyawan").removeClass('d-none')
selectKaryawan(); // inisialisasi ulang selectize
break;
case 'Keluarga Pasien / Penunggu Pasien': case 'Keluarga Pasien / Penunggu Pasien':
$('.pasien').show(); $('.pasien').show();
$nama.addClass('form-control') $nama.addClass('form-control')
$("#help_nama_pemesan").addClass('d-none') $("#help_nama_pemesan").addClass('d-none')
$("#help_email_karyawan").addClass('d-none') $("#help_email_karyawan").addClass('d-none')
break; break;
case 'Masyarakat Umum' : case 'Masyarakat Umum (Corporate)' :
$('.umum').show();
$nama.addClass('form-control')
$("#help_nama_pemesan").addClass('d-none')
$("#help_email_karyawan").addClass('d-none')
$("#modalAttentionModeUmum").modal('show');
break;
case 'Masyarakat Umum (Personal)' :
$('.umum').show(); $('.umum').show();
$nama.addClass('form-control') $nama.addClass('form-control')
$("#help_nama_pemesan").addClass('d-none') $("#help_nama_pemesan").addClass('d-none')

BIN
public/logo/gizi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

BIN
public/logo/nice.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

BIN
public/logo/no_nice.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

View File

@ -109,6 +109,14 @@
<div data-i18n="User interface">Laporan Pesanan </div> <div data-i18n="User interface">Laporan Pesanan </div>
</a> </a>
</li> </li>
<li class="menu-item {{ Request::is('dashboard/survey') ? 'active' : '' }}">
<a href="/dashboard/survey" class="menu-link">
<i class="menu-icon tf-icons bx bx-box"></i>
<div data-i18n="User interface">Survei </div>
</a>
</li>
{{-- <li class="menu-item {{ Request::is('dashboard/laporan-pesanan') ? 'active' : '' }}"> {{-- <li class="menu-item {{ Request::is('dashboard/laporan-pesanan') ? 'active' : '' }}">

View File

@ -30,7 +30,7 @@
<li class="nav-item navbar-dropdown dropdown-user dropdown"> <li class="nav-item navbar-dropdown dropdown-user dropdown">
<a class="nav-link dropdown-toggle hide-arrow" href="javascript:void(0);" data-bs-toggle="dropdown"> <a class="nav-link dropdown-toggle hide-arrow" href="javascript:void(0);" data-bs-toggle="dropdown">
<div class="avatar avatar-online"> <div class="avatar avatar-online">
<img src="/assets/img/avatars/1.png" alt class="w-px-40 h-auto rounded-circle" /> <img src="/assets/img/avatars/8.jpg" alt class="w-px-40 h-auto rounded-circle" />
</div> </div>
</a> </a>
<ul class="dropdown-menu dropdown-menu-end"> <ul class="dropdown-menu dropdown-menu-end">
@ -39,12 +39,11 @@
<div class="d-flex"> <div class="d-flex">
<div class="flex-shrink-0 me-3"> <div class="flex-shrink-0 me-3">
<div class="avatar avatar-online"> <div class="avatar avatar-online">
<img src="/assets/img/avatars/1.png" alt class="w-px-40 h-auto rounded-circle" /> <img src="/assets/img/avatars/8.jpg" alt class="w-px-40 h-auto rounded-circle" />
</div> </div>
</div> </div>
<div class="flex-grow-1"> <div class="flex-grow-1">
<span class="fw-semibold d-block">John Doe</span> <span class="fw-semibold d-block">Admin</span>
<small class="text-muted">Admin</small>
</div> </div>
</div> </div>
</a> </a>

View File

@ -0,0 +1,183 @@
@extends('dashboard.layouts.main')
@section('body_main')
<div class="container-xxl flex-grow-1 container-p-y">
<h4 class="fw-bold py-3 mb-4">
<span class="text-muted fw-light">Dashboard /</span> Survei
</h4>
<div class="row mb-4">
<div class="col-md-6 mb-3">
<div class="card border-0 shadow-sm h-100" style="border-left: 5px solid #00a99d !important;">
<div class="card-header pb-0">
<h6 class=" fw-normal mb-0">Statistik Pengguna Baru Total <b id="confirm_pb_total"></b></h6>
</div>
<div class="card-body">
<canvas id="barChartBaru" style="max-height: 150px;"></canvas>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="card border-0 shadow-sm h-100" style="border-left: 5px solid #005eb8 !important;">
<div class="card-header pb-0">
<h6 class=" fw-normal mb-0">Statistik Pelanggan Setia Total <b id="confirm_ps_total"></b></h6>
</div>
<div class="card-body">
<canvas id="barChartLama" style="max-height: 150px;"></canvas>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">Data Detail Survei <strong id="confirm_date_survey"></strong></h5>
<div class="d-flex align-items-center gap-2">
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="exportSurvei()">
<i class="fa fa-download me-1"></i> Export
</button>
<div class="input-group input-group-sm" style="width: 240px;">
<span class="input-group-text bg-white"><i class="fa fa-calendar-alt"></i></span>
<input type="text" class="form-control tanggal-input" id="tanggal" placeholder="Pilih tanggal" readonly>
</div>
</div>
</div>
<div class="card-body">
<table class="table" id="datatableSurvey"></table>
</div>
</div>
</div>
@include('dashboard.survey.modal.export')
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
const datatable = $("#datatableSurvey");
const modalExport = document.getElementById('modalExportSurvei');
// Inisialisasi variabel Chart agar bisa di-destroy saat update
let chartBaruObj, chartLamaObj;
function initDt(selectDate = []) {
datatable.bootstrapTable('destroy');
datatable.bootstrapTable({
url: "/dashboard/datatable/survey",
method: 'get',
queryParams: function(params) {
params.tanggal = selectDate;
return params;
},
showColumns: true,
pagination: true,
serverSide: true,
pageSize: 10,
columns: [
{ title: "Nama Pelanggan", field: 'order.nama_pemesan' },
{
title: "Type Survei",
field: 'type',
formatter: (v, row) => row?.type === "pengguna_baru" ? "Pengguna Baru" : "Pelanggan Setia"
},
{ title: "Kepuasan", field: 'kepuasan' },
{ title: "Kritik dan Saran", field: 'keterangan' },
],
});
}
// Fungsi perbaikan untuk Bar Chart Horizontal
function updateBarChart(chartId, puas, tidakPuas) {
const ctx = document.getElementById(chartId).getContext('2d');
// Hancurkan instance lama agar tidak tumpang tindih saat hover
if (chartId === 'barChartBaru' && chartBaruObj) chartBaruObj.destroy();
if (chartId === 'barChartLama' && chartLamaObj) chartLamaObj.destroy();
const config = {
type: 'bar',
data: {
labels: ['Puas', 'Tidak Puas'],
datasets: [{
data: [puas, tidakPuas],
backgroundColor: [
chartId === 'barChartBaru' ? '#00a99d' : '#005eb8',
'#dc3545'
],
borderRadius: 5,
barThickness: 20
}]
},
options: {
indexAxis: 'y',
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: { enabled: true }
},
scales: {
x: {
beginAtZero: true,
grid: { display: false },
ticks: { stepSize: 1, precision: 0 }
},
y: { grid: { display: false } }
}
}
};
if (chartId === 'barChartBaru') chartBaruObj = new Chart(ctx, config);
else chartLamaObj = new Chart(ctx, config);
}
async function loadCharts(selectDate = []) {
try {
const dateParam = encodeURIComponent(JSON.stringify(selectDate));
const response = await fetch(`/dashboard/chart/survey?tanggal=${dateParam}`);
const data = await response.json();
console.log(data);
// 1. Update Statistik Bar Chart Pengguna Baru
if(data.kepuasan_baru) {
updateBarChart('barChartBaru', data.kepuasan_baru.puas, data.kepuasan_baru.tidak_puas);
$("#confirm_pb_total").text(data.kepuasan_baru.total);
}
// 2. Update Statistik Bar Chart Pelanggan Setia
if(data.kepuasan_lama) {
updateBarChart('barChartLama', data.kepuasan_lama.puas, data.kepuasan_lama.tidak_puas);
$("#confirm_ps_total").text(data.kepuasan_lama.total);
}
} catch (error) {
console.error("Error load chart:", error);
}
}
document.addEventListener('DOMContentLoaded', function() {
flatpickr('#tanggal', {
dateFormat: "Y-m-d",
mode: "multiple",
locale: "id",
onValueUpdate: function(selectedDates) {
const formatted = selectedDates.map(d => {
const year = d.getFullYear();
const month = String(d.getMonth() + 1).padStart(2, '0');
const day = String(d.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
});
initDt(formatted);
loadCharts(formatted);
let text = formatted.length > 0 ? ': ' + formatted.join(', ') : 'Hari Ini';
$("#confirm_date_survey").text(text);
}
});
$("#confirm_date_survey").text('Hari Ini');
initDt();
loadCharts();
});
function exportSurvei(){
new bootstrap.Modal(modalExport).show()
}
</script>
@endsection

View File

@ -0,0 +1,50 @@
<!-- Modal -->
<div class="modal fade" id="modalExportSurvei" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<h5 class="modal-title fs-5">Export Data</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<!-- Modal Form -->
<form action="/dashboard/survey/export" method="POST">
@csrf
<div class="modal-body">
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="exampleFormControlInput1">Start Date</label>
<input type="date" class="form-control" name="start_date" id="start_date" required>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="exampleFormControlInput1">End Date</label>
<input type="date" class="form-control" name="end_date" id="end_date" required>
</div>
</div>
</div>
</div>
</div>
<!-- Modal Footer -->
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Tutup</button>
<button type="submit" class="btn btn-primary">Export</button>
</div>
</form>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const today = new Date().toISOString().split('T')[0]; // Mendapatkan tanggal hari ini dalam format YYYY-MM-DD
$('#start_date').val(today);
$('#end_date').val(today);
});
</script>

View File

@ -3,12 +3,6 @@
<input type="hidden" name="cart_data" id="cart_data"> <input type="hidden" name="cart_data" id="cart_data">
<div class="col-md-6"> <div class="col-md-6">
<label for="exampleInputEmail1" class="form-label">Apakah Anda Seorang ? <span class="text-danger">*</span></label> <label for="exampleInputEmail1" class="form-label">Apakah Anda Seorang ? <span class="text-danger">*</span></label>
<div class="form-check">
<input class="form-check-input" type="radio" name="jenis_customer" id="radio_karyawan" value="Karyawan RSAB Harapan Kita" required>
<label class="form-check-label" for="radio_karyawan" >
Karyawan RSAB Harapan Kita
</label>
</div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="radio" name="jenis_customer" id="radio_kp" value="Keluarga Pasien / Penunggu Pasien" required> <input class="form-check-input" type="radio" name="jenis_customer" id="radio_kp" value="Keluarga Pasien / Penunggu Pasien" required>
<label class="form-check-label" for="radio_kp"> <label class="form-check-label" for="radio_kp">
@ -16,10 +10,34 @@
</label> </label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="radio" name="jenis_customer" id="radio_karyawan" value="Karyawan RSAB Harapan Kita" required>
<label class="form-check-label" for="radio_karyawan" >
Karyawan RSAB Harapan Kita
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="jenis_customer" id="radio_karyawan" value="Karyawan RSAB Harapan Kita (Rapat Internal, Seminar /Pelatihan)" required>
<label class="form-check-label" for="radio_karyawan" >
Karyawan RSAB Harapan Kita (Rapat Internal, Seminar /Pelatihan)
</label>
</div>
{{-- <div class="form-check">
<input class="form-check-input" type="radio" name="jenis_customer" id="radio_public" value="Masyarakat Umum" required> <input class="form-check-input" type="radio" name="jenis_customer" id="radio_public" value="Masyarakat Umum" required>
<label class="form-check-label" for="radio_public"> <label class="form-check-label" for="radio_public">
Masyarakat Umum Masyarakat Umum
</label> </label>
</div> --}}
<div class="form-check">
<input class="form-check-input" type="radio" name="jenis_customer" id="radio_public" value="Masyarakat Umum (Personal)" required>
<label class="form-check-label" for="radio_public">
Masyarakat Umum (Personal)
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="jenis_customer" id="radio_public" value="Masyarakat Umum (Corporate)" required>
<label class="form-check-label" for="radio_public">
Masyarakat Umum (Corporate)
</label>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">

View File

@ -5,6 +5,7 @@
<div class="container position-relative d-flex align-items-center justify-content-between"> <div class="container position-relative d-flex align-items-center justify-content-between">
<a href="/" class="logo d-flex align-items-center me-auto"> <a href="/" class="logo d-flex align-items-center me-auto">
<!-- Uncomment the line below if you also wish to use an image logo --> <!-- Uncomment the line below if you also wish to use an image logo -->
<img src="/logo/gizi.png" alt="Logo RSAB HARAPAN KITA" class="" style="height:125px;">
<img src="/logo/logo_rsabhk.png" alt="Logo RSAB HARAPAN KITA" class="logo-img"> <img src="/logo/logo_rsabhk.png" alt="Logo RSAB HARAPAN KITA" class="logo-img">
<h1 class="sitename"></h1> <h1 class="sitename"></h1>
</a> </a>
@ -16,7 +17,7 @@
MCU MCU
</button> </button>
@endif @endif
<button type="button" class="btn btn-outline-success position-relative me-1 d-flex" style="font-size:14px;" onclick="checkOrderHref()"> <button type="button" class="btn btn-outline-success position-relative d-flex lh-sm" style="font-size:14px;" onclick="checkOrderHref()">
Check Order Check Order
</button> </button>

View File

@ -0,0 +1,155 @@
@extends('guest.layout.main')
@section('body_main_guests')
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-md-8 col-lg-7">
<div class="text-center mb-5">
@if($type === "pengguna_baru")
<h2 class="fw-bold text-dark mb-3">Form Kepuasan Pelanggan Terkait Penggunaan Aplikasi Catering Gizi RSABHK</h2>
@else
<h2 class="fw-bold text-dark mb-3">Form Kepuasan Pelanggan Catering Instalasi Gizi RSAB HK </h2>
@endif
<p class="text-secondary mx-auto" style="max-width: 500px;">
Terima kasih telah memesan di <strong>Catering Instalasi Gizi RSAB HK</strong>. Masukan Anda sangat berarti bagi peningkatan kualitas layanan kami.
</p>
<div class="mx-auto mt-3"></div>
</div>
<form action="" method="POST" id="surveyForm">
@csrf
<div class="card border-0 shadow-sm mb-4 overflow-hidden" style="border-radius: 15px;">
{{-- <div class="card-body p-4">
<div class="d-flex align-items-center mb-3">
<div class="bg-light rounded-circle p-2 me-3">
<i class="fas fa-user text-primary"></i>
</div>
<label class="form-label fw-semibold mb-0">Nama Pelanggan <span class="text-danger">*</span></label>
</div>
<input type="text" name="nama_pelanggan" class="form-control custom-input" placeholder="Masukkan nama lengkap Anda..." required>
</div> --}}
</div>
<div class="card border-0 shadow-sm mb-4" style="border-radius: 15px;">
<div class="card-body p-4 text-center">
@if($type === "pengguna_baru")
<label class="form-label fw-semibold d-block mb-4">Menurut Anda apakah aplikasi pemesanan catering gizi saat ini mudah untuk digunakan? <span class="text-danger">*</span></label>
@else
<label class="form-label fw-semibold d-block mb-4">Bagaimana pelayanan catering gizi yang anda dapatkan ? <span class="text-danger">*</span></label>
@endif
<p class="text-muted small mb-4"><i class="fas fa-info-circle me-1"></i> Silakan pilih salah satu ikon di bawah ini</p>
<input type="hidden" name="type" value={{ $type }} />
<input type="hidden" name="no_order" value={{ $no_order }} />
<div class="row g-3">
<div class="col-6">
<input type="radio" class="btn-check" name="kepuasan" id="puas" value="Puas" required>
<label class="btn btn-outline-light w-100 p-4 emoji-card" for="puas">
<div class="emoji-icon mb-2"><img src="/logo/nice.png" style="height:120px;"/> </div>
<div class="fw-bold text-dark">Puas</div>
</label>
</div>
<div class="col-6">
<input type="radio" class="btn-check" name="kepuasan" id="tidak_puas" value="Tidak Puas">
<label class="btn btn-outline-light w-100 p-4 emoji-card" for="tidak_puas">
<div class="emoji-icon mb-2"><img src="/logo/no_nice.png" style="height:120px;"/></div>
<div class="fw-bold text-dark">Tidak Puas</div>
</label>
</div>
</div>
</div>
</div>
<div class="card border-0 shadow-sm mb-4" style="border-radius: 15px;">
<div class="card-body p-4">
<div class="d-flex align-items-center mb-3">
<div class="bg-light rounded-circle p-2 me-3">
<i class="fas fa-comment-dots text-primary"></i>
</div>
<label class="form-label fw-semibold mb-0">Kritik dan Saran <span class="text-danger">*</span></label>
</div>
<textarea name="kritik_saran" class="form-control custom-input" rows="3" placeholder="Tuliskan masukan atau saran Anda di sini..." required></textarea>
</div>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-md-end mb-5">
{{-- <button type="reset" class="btn btn-light px-4 fw-medium text-muted">Tutup</button> --}}
<button type="submit" class="btn btn-primary px-5 fw-bold shadow-sm">Kirim Masukan</button>
</div>
</form>
</div>
</div>
</div>
<style>
/* Emoji Card Selector */
.emoji-card {
border: 2px solid #9b9c9e !important;
border-radius: 15px !important;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
background: #fff;
}
.emoji-icon {
font-size: 2.5rem;
transition: transform 0.3s ease;
}
.btn-check:checked + .emoji-card {
background-color: #b8ddff !important;
transform: translateY(-5px);
}
.btn-check:checked + .emoji-card .emoji-icon {
transform: scale(1.2);
}
.emoji-card:hover {
border-color: #0c0c0c !important;
background: #0f0f0f;
}
/* Requirement text */
.text-danger {
font-size: 0.8rem;
}
</style>
<script>
$("#surveyForm").on('submit', async function(e){
e.preventDefault()
const buttonSubmit = $(this).find('button[type="submit"]')
if(buttonSubmit.prop('disabled')) return;
buttonSubmit.prop('disabled', true).html('<i class="fas fa-spinner fa-spin me-2"></i>Memperoses')
const formData = new FormData(this);
try {
const response = await fetch('/survey', {
method: 'POST',
body: formData,
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
}
});
const result = await response.json()
if(result.status){
Swal.fire({
title: 'Survei Berhasil!',
text: 'Terima kasih, Masukan anda sangat berarti bagi kami.',
icon: 'success',
confirmButtonText: 'Berhasil!',
confirmButtonColor: '#28a745'
}).then(() => {
window.location.href = "/success-page"; // kehalaman success
});
}
} catch (error) {
Swal.fire({
title: 'Gagal!',
text: "Terjadi kesalahan saat mengirim melakukan survei.",
icon: 'error',
confirmButtonText: 'Tutup!'
})
}finally{
buttonSubmit.prop('disabled', false).html('Selesaikan Survei')
}
})
</script>
@endsection

View File

@ -10,6 +10,7 @@ use App\Http\Controllers\KlasifikasiMenuController;
use App\Http\Controllers\MasterMcuController; use App\Http\Controllers\MasterMcuController;
use App\Http\Controllers\MenuController; use App\Http\Controllers\MenuController;
use App\Http\Controllers\PesananController; use App\Http\Controllers\PesananController;
use App\Http\Controllers\SurveyController;
use App\Mail\NotifikasiCustomer; use App\Mail\NotifikasiCustomer;
use Barryvdh\DomPDF\Facade\Pdf; use Barryvdh\DomPDF\Facade\Pdf;
use Barryvdh\Snappy\Facades\SnappyPdf; use Barryvdh\Snappy\Facades\SnappyPdf;
@ -83,6 +84,11 @@ Route::group(['middleware' => ['auth']], function(){
Route::get('/pekerjaan/detail/{id}', [PesananController::class, 'getPekerjaanDetail']); Route::get('/pekerjaan/detail/{id}', [PesananController::class, 'getPekerjaanDetail']);
Route::get('/pekerjaan/label', [PesananController::class, 'downloadLabel']); Route::get('/pekerjaan/label', [PesananController::class, 'downloadLabel']);
Route::get('/data/pending-pekerjaan', [PesananController::class, 'dataPekerjaanPending']); Route::get('/data/pending-pekerjaan', [PesananController::class, 'dataPekerjaanPending']);
Route::get('/survey', [SurveyController::class, 'dashboardSurvey']);
Route::get('/datatable/survey', [SurveyController::class, 'datatable']);
Route::get('/chart/survey', [SurveyController::class, 'chartDataSurvey']);
Route::post('/survey/export', [SurveyController::class, 'exportSurveyExcel']);
}); });
Route::post('/logout', [AuthController::class, 'logout']); Route::post('/logout', [AuthController::class, 'logout']);
@ -103,6 +109,9 @@ Route::get('/success-mcu', [CustomerController::class, 'successMcu']);
Route::get('/karyawan', [CustomerController::class, 'karyawan']); Route::get('/karyawan', [CustomerController::class, 'karyawan']);
Route::get('/unit-instalasi', [CustomerController::class, 'unitInstalasi']); Route::get('/unit-instalasi', [CustomerController::class, 'unitInstalasi']);
Route::get('/server-time', fn()=> response()->json(['now' => now()])); Route::get('/server-time', fn()=> response()->json(['now' => now()]));
Route::get('/survey', [SurveyController::class, 'index']);
Route::post('/survey', [SurveyController::class, 'store']);
// Route::get('/send-mail', function(){ // Route::get('/send-mail', function(){
// Mail::to('skyjok14@gmail.com')->queue(new NotifikasiCustomer('Test')); // Mail::to('skyjok14@gmail.com')->queue(new NotifikasiCustomer('Test'));