@extends('layouts.template') @section('title', 'Kuesioner Soal') @section('custom_css') @endsection @section('content') @php $listHal = $daftarHal ?? collect([$hal]); $posisiAktif = $listHal->search($hal); if ($posisiAktif === false) { $posisiAktif = 0; } $totalHalaman = $totalHal ?? $listHal->count(); $progressPercentage = $totalHalaman > 0 ? round((($posisiAktif + 1) / max($totalHalaman, 1)) * 100) : 100; $halSebelumnya = $posisiAktif > 0 ? $listHal[$posisiAktif - 1] : null; $halBerikut = ($posisiAktif < $listHal->count() - 1) ? $listHal[$posisiAktif + 1] : null; $isHalTerakhir = $halBerikut === null; $formLocked = $formLocked ?? false; $prefillJawaban = $prefillJawaban ?? []; $existingJawaban = $existingJawaban ?? []; @endphp

Kuesioner

{{ $soal->judul_soal ?? 'Daftar Soal' }}

← Daftar Judul Halaman {{ $hal }}
Progres Halaman {{ $progressPercentage }}%
@if ($hal === $halPertama)
{{ $soal->judul_soal ?? '-' }}
{!! $soal->keterangan_soal !!}
@endif @if ($errors->any()) @endif @if ($formLocked)
Anda sudah mengisi kuesioner ini. Jawaban di bawah ditampilkan dalam mode baca.
@endif
Daftar Pertanyaan
Halaman {{ $hal }} dari {{ $listHal->count() }}
@csrf @php $questionCounter = 0; $groupedQuestionDetails = []; $groupIndexMap = []; foreach ($soal->soalDetail as $detailItem) { $detailConfigItem = json_decode($detailItem->soal, true) ?? []; $detailHalValue = $detailItem->hal ?? $listHal->first(); $questionNumberValue = $detailConfigItem['no'] ?? null; $hasNumberValue = $questionNumberValue !== null && $questionNumberValue !== ''; $groupKey = $hasNumberValue ? $detailHalValue . '|' . $questionNumberValue : 'detail_' . $detailItem->id; if (!array_key_exists($groupKey, $groupIndexMap)) { $groupIndexMap[$groupKey] = count($groupedQuestionDetails); $groupedQuestionDetails[] = [ 'hal' => $detailHalValue, 'number' => $hasNumberValue ? $questionNumberValue : null, 'items' => [], ]; } $groupPosition = $groupIndexMap[$groupKey]; $groupedQuestionDetails[$groupPosition]['items'][] = [ 'detail' => $detailItem, 'config' => $detailConfigItem, ]; } @endphp @forelse ($groupedQuestionDetails as $groupData) @php $groupHal = $groupData['hal']; $groupNumber = $groupData['number']; $groupItems = $groupData['items']; $groupFirstDetail = $groupItems[0]['detail'] ?? null; $groupFirstConfig = $groupItems[0]['config'] ?? []; $groupType = $groupFirstConfig['type'] ?? 'option'; $groupHasConsent = false; foreach ($groupItems as $groupItemCheck) { if (!empty($groupItemCheck['config']['persetujuan_form'])) { $groupHasConsent = true; break; } } @endphp
@foreach ($groupItems as $groupItem) @php $detail = $groupItem['detail']; $detailConfig = $groupItem['config'] ?? []; $pertanyaan = $detailConfig['soal'] ?? 'Pertanyaan tidak tersedia'; $type = $detailConfig['type'] ?? 'option'; $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 = []; } $optionValues = collect($options)->map(function ($value) { return is_scalar($value) ? (string) $value : ''; })->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); $hasCurrentAnswer = $currentAnswer !== null && $currentAnswer !== ''; $isCustomCurrentAnswer = $hasCurrentAnswer && !in_array($currentAnswer, $optionValues, true); if (!$oldOtherAnswer && $isCustomCurrentAnswer) { $oldOtherAnswer = $currentAnswer; } $showLainnya = $isCustomCurrentAnswer || (is_string($currentAnswer) && stripos($currentAnswer, 'lainnya') !== false) || (!empty($oldOtherAnswer)); $detailHal = $detail->hal ?? $listHal->first(); $optionsCount = is_array($options) ? count($options) : 0; $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']); $shouldForceLainnyaSelection = $hasLainnyaOption && $showLainnya; $dualFormConfig = $detailConfig['dual_form'] ?? null; $useDualForm = $type === 'dual_form' || (!empty($dualFormConfig) && $dualFormConfig !== false); $dualYearOld = null; $dualMonthOld = null; $questionNumber = $detailConfig['no'] ?? ''; $hasGroupNumber = $groupNumber !== null && $groupNumber !== ''; $badgeNumber = $hasGroupNumber ? $groupNumber : $questionNumber; $shouldShowNumber = $badgeNumber !== null && $badgeNumber !== '' && (!$hasGroupNumber || $loop->first); $rangeMin = null; $rangeMax = null; $rangeStep = 1; $rangeDefault = null; $rangeTicks = []; $rangeSubTickCount = 4; $rangeMajorStep = 10; if ($useDualForm && $currentAnswer) { if (preg_match('/([0-9]+)\\s*\\(Tahun\\)/i', $currentAnswer, $matchYear)) { $dualYearOld = $matchYear[1]; } if (preg_match('/([0-9]+)\\s*\\(Bulan\\)/i', $currentAnswer, $matchMonth)) { $dualMonthOld = $matchMonth[1]; } } 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); $majorAnchors = [$rangeMin, $rangeMax]; if ($rangeMin <= 1 && $rangeMax >= 1) { $majorAnchors[] = 1; } $firstMajor = max($rangeMin, ($rangeMin <= 1 ? 10 : ceil($rangeMin / $rangeMajorStep) * $rangeMajorStep)); for ($v = $firstMajor; $v <= $rangeMax; $v += $rangeMajorStep) { $majorAnchors[] = $v; } sort($majorAnchors); $uniqueAnchors = []; foreach ($majorAnchors as $anchor) { if (empty($uniqueAnchors) || abs(end($uniqueAnchors) - $anchor) > 0.0001) { $uniqueAnchors[] = $anchor; } } $majorAnchors = array_values(array_filter($uniqueAnchors, function ($value) use ($rangeMin, $rangeMax) { return $value >= $rangeMin && $value <= $rangeMax; })); $ticks = []; $addTick = function ($value, $isMajor = false) use (&$ticks, $rangeMin, $rangeSpan, $rangeMajorStep) { $position = $rangeSpan > 0 ? (($value - $rangeMin) / $rangeSpan) * 100 : 0; $isOne = abs($value - 1) < 0.0001; $isMultiple = $rangeMajorStep > 0 ? abs(fmod($value, $rangeMajorStep)) < 0.0001 : false; $ticks[] = [ 'value' => $value, 'label' => ($isOne || $isMultiple) ? (int) round($value) : null, 'position' => max(0, min(100, $position)), 'is_major' => $isMajor, 'is_one' => $isOne, ]; }; $countAnchors = count($majorAnchors); if ($countAnchors === 0) { $addTick($rangeMin, true); } else { for ($i = 0; $i < $countAnchors; $i++) { $currentAnchor = $majorAnchors[$i]; $addTick($currentAnchor, true); if ($i === $countAnchors - 1) { continue; } $nextAnchor = $majorAnchors[$i + 1]; $segmentLength = $nextAnchor - $currentAnchor; if ($segmentLength <= 0 || $rangeSubTickCount <= 0) { continue; } for ($sub = 1; $sub <= $rangeSubTickCount; $sub++) { $fraction = $sub / ($rangeSubTickCount + 1); $value = $currentAnchor + ($segmentLength * $fraction); $addTick($value, false); } } } usort($ticks, function ($a, $b) { if ($a['value'] == $b['value']) { return 0; } return ($a['value'] < $b['value']) ? -1 : 1; }); $rangeTicks = $ticks; } } $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 @if (!$loop->first)
@endif
@if ($shouldShowNumber) {{ $badgeNumber }} @elseif($hasGroupNumber) @endif
{{ $pertanyaan }}
@if ($isConsentQuestion)

Pertanyaan persetujuan

@endif
@if ($useDualForm)
@elseif ($type === 'textarea') @elseif ($type === 'text') @elseif ($type === 'number') @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)) @php $lainnyaWrapperRendered = false; @endphp
@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
@if ($isLainnya) @php $lainnyaWrapperRendered = true; @endphp
@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')
@endif @else @endif @endif @error('jawaban.' . $detail->id)
{{ $message }}
@enderror @error('jawaban_lainnya.' . $detail->id)
{{ $message }}
@enderror
@endforeach
@empty
Belum ada pertanyaan pada halaman ini.
@endforelse @error('lms_mutu_soal_id')

{{ $message }}

@enderror @error('jawaban')

{{ $message }}

@enderror
@endsection @section('custom_js') @endsection