diff --git a/app/Http/Controllers/SoalController.php b/app/Http/Controllers/SoalController.php index abcbeff..ea238ed 100644 --- a/app/Http/Controllers/SoalController.php +++ b/app/Http/Controllers/SoalController.php @@ -92,7 +92,7 @@ class SoalController extends Controller $formLocked = true; } } - $prefillJawaban = $this->generatePrefillJawaban($detailSoal, $pegawai); + $prefillJawaban = []; return view('soal.index', [ 'soal' => $soal, 'hal' => $hal, @@ -100,7 +100,7 @@ class SoalController extends Controller 'daftarHal' => $daftarHal, 'totalHal' => $daftarHal->count(), 'soalId' => $soal->id, - 'pegawai' => $pegawai, + 'pegawai' => [], 'prefillJawaban' => $prefillJawaban, 'existingJawaban' => $existingJawaban, 'formLocked' => $formLocked, @@ -112,8 +112,8 @@ class SoalController extends Controller $validator = Validator::make($request->all(), [ 'lms_mutu_soal_id' => 'required|integer', 'hal' => 'nullable|integer|min:1', - 'jawaban' => 'required|array', - 'jawaban.*' => 'required', + 'jawaban' => 'nullable|array', + 'jawaban.*' => 'nullable', 'jawaban_lainnya' => 'nullable|array', 'jawaban_lainnya.*' => 'nullable|string', ]); @@ -133,8 +133,9 @@ class SoalController extends Controller }); $validated = $validator->validate(); + $jawabanUtama = $validated['jawaban'] ?? []; - $detailIds = array_map('intval', array_keys($validated['jawaban'])); + $detailIds = array_map('intval', array_keys($jawabanUtama)); $detailMeta = SoalDetail::whereIn('id', $detailIds) ->get(['id', 'soal']) ->keyBy('id'); @@ -144,16 +145,16 @@ class SoalController extends Controller $namaResponden = null; $unitKerja = null; $pegawai = session('pegawai') ?? []; - $pegawaiId = is_array($pegawai) ? ($pegawai['id'] ?? null) : null; + $pegawaiId = is_array($pegawai) ? ($pegawai['id'] ?? null) : 1; - DB::connection('dbLmsMutu')->transaction(function () use (&$jawabanBaru, $validated, $jawabanLainnya, $detailMeta, &$namaResponden, &$unitKerja, $pegawaiId) { + DB::connection('dbLmsMutu')->transaction(function () use (&$jawabanBaru, $validated, $jawabanUtama, $jawabanLainnya, $detailMeta, &$namaResponden, &$unitKerja, $pegawaiId) { $jawabanBaru = Jawaban::create([ 'lms_mutu_soal_id' => $validated['lms_mutu_soal_id'], 'pegawai_id' => $pegawaiId, 'tanggal_isi' => Carbon::now()->addHour(7), ]); - foreach ($validated['jawaban'] as $detailId => $answer) { + foreach ($jawabanUtama as $detailId => $answer) { if (is_array($answer)) { $answer = json_encode($answer); } @@ -205,9 +206,15 @@ class SoalController extends Controller } }); - return redirect('/') + return redirect()->route('soal.thankyou') ->with('success', 'Jawaban berhasil disimpan.'); } + + public function thankYou() + { + return view('soal.thank-you'); + } + public function redirectSmart() { $data = request()->input('data'); diff --git a/resources/views/soal/index.blade.php b/resources/views/soal/index.blade.php index da2b21f..45cf152 100644 --- a/resources/views/soal/index.blade.php +++ b/resources/views/soal/index.blade.php @@ -3,88 +3,165 @@ @section('title', 'Kuesioner Soal') @section('custom_css') - @endsection @@ -170,12 +247,23 @@ + @php + $questionCounter = 0; + @endphp @forelse ($soal->soalDetail as $detail) @php $detailConfig = json_decode($detail->soal, true) ?? []; $pertanyaan = $detailConfig['soal'] ?? 'Pertanyaan tidak tersedia'; $type = $detailConfig['type'] ?? 'option'; - $options = $detailConfig['options'] ?? []; + $optionsRaw = $detailConfig['options'] ?? []; + if (is_array($optionsRaw)) { + $options = $optionsRaw; + } elseif ($type === 'option_with_range' && is_string($optionsRaw)) { + $options = [$optionsRaw]; + } else { + $options = []; + } + $autoSelect = ($type === 'option' && count($options) == 1) ? true : false; if (!is_array($options)) { $options = []; } @@ -184,7 +272,12 @@ })->all(); $existingAnswer = $existingJawaban[$detail->id] ?? null; $prefillAnswer = $prefillJawaban[$detail->id] ?? null; + $hasDefaultAnswer = array_key_exists('default', $detailConfig); + $defaultAnswer = $hasDefaultAnswer ? $detailConfig['default'] : null; $currentAnswer = old('jawaban.' . $detail->id, $existingAnswer ?? $prefillAnswer); + if (($currentAnswer === null || $currentAnswer === '') && $hasDefaultAnswer) { + $currentAnswer = $defaultAnswer; + } $existingOtherAnswer = $existingAnswer && !in_array($existingAnswer, $optionValues, true) ? $existingAnswer : null; $prefillOtherAnswer = $prefillAnswer && !in_array($prefillAnswer, $optionValues, true) ? $prefillAnswer : null; $oldOtherAnswer = old('jawaban_lainnya.' . $detail->id, $existingOtherAnswer ?? $prefillOtherAnswer); @@ -199,11 +292,12 @@ $detailHal = $detail->hal ?? $listHal->first(); $isVisible = $detailHal == $hal; $optionsCount = is_array($options) ? count($options) : 0; - $useSelectSearch = $optionsCount > 4; $hasLainnyaOption = collect($options)->contains(function ($optionItem) { return is_string($optionItem) && stripos($optionItem, 'lainnya') !== false; }); if (!$hasLainnyaOption && $type === 'option_with_other') { + $options[] = 'Lainnya'; + $optionsCount = count($options); $hasLainnyaOption = true; } $isConsentQuestion = !empty($detailConfig['persetujuan_form']); @@ -212,6 +306,12 @@ $useDualForm = $type === 'dual_form' || (!empty($dualFormConfig) && $dualFormConfig !== false); $dualYearOld = null; $dualMonthOld = null; + $questionNumber = $detailConfig['no'] ?? ''; + $rangeMin = null; + $rangeMax = null; + $rangeStep = 1; + $rangeDefault = null; + $rangeTicks = []; if ($useDualForm && $currentAnswer) { if (preg_match('/([0-9]+)\\s*\\(Tahun\\)/i', $currentAnswer, $matchYear)) { $dualYearOld = $matchYear[1]; @@ -220,8 +320,48 @@ $dualMonthOld = $matchMonth[1]; } } - @endphp + if ($type === 'option_with_range' && !empty($options)) { + $rangeSource = $options[0]; + if (is_array($rangeSource)) { + $rangeSource = $rangeSource['range'] ?? (isset($rangeSource['min'], $rangeSource['max']) ? $rangeSource['min'] . '-' . $rangeSource['max'] : null); + } + if (is_string($rangeSource) && preg_match('/(-?[0-9]+(?:[\\.,][0-9]+)?)\\s*-\\s*(-?[0-9]+(?:[\\.,][0-9]+)?)/', $rangeSource, $rangeMatch)) { + $rangeMin = (float) str_replace(',', '.', $rangeMatch[1]); + $rangeMax = (float) str_replace(',', '.', $rangeMatch[2]); + if ($rangeMin > $rangeMax) { + [$rangeMin, $rangeMax] = [$rangeMax, $rangeMin]; + } + $rangeUsesDecimal = (fmod($rangeMin, 1) !== 0.0) || (fmod($rangeMax, 1) !== 0.0); + $rangeStep = $rangeUsesDecimal ? 0.1 : 1; + if (is_numeric($currentAnswer)) { + $numericAnswer = (float) $currentAnswer; + $rangeDefault = min(max($numericAnswer, $rangeMin), $rangeMax); + } else { + $rangeDefault = $rangeMin; + } + if ($rangeDefault === null) { + $rangeDefault = $rangeMin; + } + $rangeSpan = max($rangeMax - $rangeMin, 1); + $startTick = (int) ceil($rangeMin); + $endTick = (int) floor($rangeMax); + + for ($v = $startTick; $v <= $endTick; $v++) { + $position = (($v - $rangeMin) / $rangeSpan) * 100; + + $rangeTicks[] = [ + 'value' => $v, // nilai asli + 'label' => ($v === 1 || $v % 10 === 0) ? $v : null, // label hanya 1 & kelipatan 10 + 'position' => max(0, min(100, $position)), + ]; + } + } + } + $rangeMinDisplay = ($rangeMin !== null && floor($rangeMin) == $rangeMin) ? (int) $rangeMin : $rangeMin; + $rangeMaxDisplay = ($rangeMax !== null && floor($rangeMax) == $rangeMax) ? (int) $rangeMax : $rangeMax; + $rangeDefaultDisplay = ($rangeDefault !== null && floor($rangeDefault) == $rangeDefault) ? (int) $rangeDefault : $rangeDefault; + @endphp
- {{ $loop->iteration }} + @if ($questionNumber !== null) + {{ $questionNumber }} + @endif
{{ $pertanyaan }}
@if ($isConsentQuestion) @@ -269,134 +411,169 @@ data-dual-hidden="{{ $detail->id }}" data-field-hal="{{ $detailHal }}" @if ($isConsentQuestion) data-consent-input="1" @endif - @if($formLocked) disabled @endif - required> + @if($formLocked) disabled @endif>
@elseif ($type === 'textarea') @elseif ($type === 'text') + @elseif ($type === 'option_with_range') + @if ($rangeMin !== null && $rangeMax !== null) +
+ + + + {{-- Track warna + slider --}} +
+ +
+ +
+ Nilai saat ini: + {{ $rangeDefaultDisplay ?? $rangeMinDisplay }} +
+
+ Atau isi manual + +
+
+ @else + + @endif @else @if (!empty($options)) - @if ($useSelectSearch) - + @endif +
+
+ @foreach ($options as $optionIndex => $option) + @php + $optionId = 'jawaban-' . $detail->id . '-' . $optionIndex; + $optionLabel = is_scalar($option) ? (string) $option : ''; + $isLainnya = stripos($optionLabel, 'lainnya') !== false; + $optionValue = $isLainnya && $oldOtherAnswer ? $oldOtherAnswer : $optionLabel; + $shouldCheck = $currentAnswer === $optionValue || ($isLainnya && $shouldForceLainnyaSelection); + @endphp +
+ - {{ $optionLabel }} - - @endforeach - @if ($type === 'option_with_other' && !$hasLainnyaOption) - - @endif - - @if ($hasLainnyaOption || $type === 'option_with_other') -
- + {{ $shouldCheck || $autoSelect ? 'checked' : '' }}> +
- @endif - @else - @php - $lainnyaWrapperRendered = false; - @endphp -
- @foreach ($options as $optionIndex => $option) + + @if ($isLainnya) @php - $optionId = 'jawaban-' . $detail->id . '-' . $optionIndex; - $optionLabel = is_scalar($option) ? (string) $option : ''; - $isLainnya = stripos($optionLabel, 'lainnya') !== false; - $optionValue = $isLainnya && $oldOtherAnswer ? $oldOtherAnswer : $optionLabel; - $shouldCheck = $currentAnswer === $optionValue || ($isLainnya && $shouldForceLainnyaSelection); + $lainnyaWrapperRendered = true; @endphp -
- + - + placeholder="Tuliskan jawaban lainnya">
- @if ($isLainnya) - @php - $lainnyaWrapperRendered = true; - @endphp -
- -
- @endif - @endforeach + @endif + @endforeach +
+ @if ($hasLainnyaOption || $type === 'option_with_other') + + Jika jawaban yang Anda cari tidak ada di daftar, pilih opsi "Lainnya" lalu isi sesuai kebutuhan. + + @endif + + @if (!$lainnyaWrapperRendered && $type === 'option_with_other') +
+
- @if (!$lainnyaWrapperRendered && $type === 'option_with_other') -
- -
- @endif @endif @else + @endsection diff --git a/resources/views/soal/thank-you.blade.php b/resources/views/soal/thank-you.blade.php new file mode 100644 index 0000000..fd95850 --- /dev/null +++ b/resources/views/soal/thank-you.blade.php @@ -0,0 +1,32 @@ +@extends('layouts.template') + +@section('title', 'Terima Kasih') + +@section('content') +
+
+
+
+
+
+ +
+

Terima kasih sudah mengisi halaman ini

+

+ @if (session('success')) + {{ session('success') }} + @else + Jawaban Anda sudah kami terima dan akan dipergunakan untuk pengembangan layanan terbaik. + @endif +

+ + Kembali ke daftar kuesioner + +
+
+
+
+
+@endsection diff --git a/routes/web.php b/routes/web.php index 66672cd..1527f24 100644 --- a/routes/web.php +++ b/routes/web.php @@ -8,8 +8,9 @@ use Illuminate\Support\Facades\Route; Route::get('/login', [AuthController::class, 'login']); Route::get('/', [SoalController::class, 'index'])->name('soal.index'); Route::post('/jawaban', [SoalController::class, 'store'])->name('soal.store'); +Route::get('/jawaban/terima-kasih', [SoalController::class, 'thankYou'])->name('soal.thankyou'); Route::get('/admin', [AdminController::class, 'index']); Route::post('/admin/get_data_pegawai_sudah_survey', [AdminController::class, 'get_data_pegawai_sudah_survey']); Route::get('/admin/dashboard_jawaban', [AdminController::class, 'dashboard_analisis']); Route::post('/admin/get_data_dashboard_jawaban', [AdminController::class, 'get_data_dashboard_analisis']); -Route::get('/redirect-smart', [SoalController::class, 'redirectSmart']); \ No newline at end of file +Route::get('/redirect-smart', [SoalController::class, 'redirectSmart']);