diff --git a/app/Http/Controllers/SoalController.php b/app/Http/Controllers/SoalController.php index 6b48997..9e06ae1 100644 --- a/app/Http/Controllers/SoalController.php +++ b/app/Http/Controllers/SoalController.php @@ -2,16 +2,182 @@ namespace App\Http\Controllers; +use App\Models\Jawaban; +use App\Models\JawabanDetail; use App\Models\Soal; +use App\Models\SoalDetail; +use Carbon\Carbon; use Illuminate\Http\Request; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Validator; +use Illuminate\Support\Str; class SoalController extends Controller { - public function index(){ - $soal = Soal::first(); - $payload = [ - 'soal' => $soal - ]; - return view('soal.index', $payload); - } + public function index(Request $request) + { + $daftarSoal = Soal::orderBy('judul_soal')->get(); + + if ($daftarSoal->isEmpty()) { + abort(404, 'Data soal tidak ditemukan.'); + } + + $selectedSoalId = (int) $request->query('soal_id', $daftarSoal->first()->id); + + if (!$request->boolean('start')) { + return view('soal.list', [ + 'daftarSoal' => $daftarSoal, + ]); + } + + $soal = Soal::with('soalDetail')->find($selectedSoalId); + + if (!$soal) { + abort(404, 'Data soal tidak ditemukan.'); + } + + $detailSoal = $soal->soalDetail() + ->orderBy('hal') + ->orderBy('id') + ->get(); + + $daftarHal = $detailSoal->pluck('hal') + ->map(function ($value) { + return is_null($value) ? null : (int) $value; + }) + ->filter(function ($value) { + return !is_null($value); + }) + ->unique() + ->sort() + ->values(); + + if ($daftarHal->isEmpty()) { + $daftarHal = collect([1]); + } + + $hal = (int) $request->query('hal', $daftarHal->first()); + + if (!$daftarHal->contains($hal)) { + $hal = $daftarHal->first(); + } + + $detailSoal = $detailSoal->map(function ($detail) use ($daftarHal) { + $detail->hal = $detail->hal ?? $daftarHal->first(); + return $detail; + }); + + $soal->setRelation('soalDetail', $detailSoal); + + $halPertama = $daftarHal->first() ?? $hal; + + return view('soal.index', [ + 'soal' => $soal, + 'hal' => $hal, + 'halPertama' => $halPertama, + 'daftarHal' => $daftarHal, + 'totalHal' => $daftarHal->count(), + 'soalId' => $soal->id, + ]); + } + + public function store(Request $request) + { + $validator = Validator::make($request->all(), [ + 'lms_mutu_soal_id' => 'required|integer', + 'hal' => 'nullable|integer|min:1', + 'jawaban' => 'required|array', + 'jawaban.*' => 'required', + 'jawaban_lainnya' => 'nullable|array', + 'jawaban_lainnya.*' => 'nullable|string', + ]); + + $validator->after(function ($validator) use ($request) { + $jawabanUtama = $request->input('jawaban', []); + $jawabanLainnya = $request->input('jawaban_lainnya', []); + + foreach ($jawabanUtama as $detailId => $answer) { + if ($answer === 'Lainnya') { + $jawabanIsian = $jawabanLainnya[$detailId] ?? null; + if (!$jawabanIsian) { + $validator->errors()->add("jawaban_lainnya.$detailId", 'Jawaban lainnya wajib diisi.'); + } + } + } + }); + + $validated = $validator->validate(); + + $detailIds = array_map('intval', array_keys($validated['jawaban'])); + $detailMeta = SoalDetail::whereIn('id', $detailIds) + ->get(['id', 'soal']) + ->keyBy('id'); + + $jawabanBaru = null; + $jawabanLainnya = $validated['jawaban_lainnya'] ?? []; + $namaResponden = null; + $unitKerja = null; + + DB::connection('dbLmsMutu')->transaction(function () use (&$jawabanBaru, $validated, $jawabanLainnya, $detailMeta, &$namaResponden, &$unitKerja) { + $jawabanBaru = Jawaban::create([ + 'lms_mutu_soal_id' => $validated['lms_mutu_soal_id'], + 'pegawai_id' => 1, + 'tanggal_isi' => Carbon::now()->addHour(7), + ]); + + foreach ($validated['jawaban'] as $detailId => $answer) { + if (is_array($answer)) { + $answer = json_encode($answer); + } + + if ($answer === 'Lainnya' && !empty($jawabanLainnya[$detailId])) { + $answer = $jawabanLainnya[$detailId]; + } + + if ($answer === null || $answer === '') { + continue; + } + + $detailIdInt = (int) $detailId; + $pertanyaan = null; + if ($detailMeta->has($detailIdInt)) { + $decoded = json_decode($detailMeta[$detailIdInt]->soal, true); + $pertanyaan = Str::lower(trim($decoded['soal'] ?? '')); + } + + if ($pertanyaan) { + if (Str::contains($pertanyaan, 'nama/inisial responden')) { + $namaResponden = $answer; + } + + if (Str::contains($pertanyaan, 'unit/area kerja anda saat ini')) { + $unitKerja = $answer; + } + } + + JawabanDetail::create([ + 'lms_mutu_jawaban_id' => $jawabanBaru->id, + 'lms_mutu_soal_detail_id' => $detailIdInt, + 'jawaban' => $answer, + ]); + } + + $updatePayload = []; + + if (!empty($namaResponden)) { + $updatePayload['nama'] = $namaResponden; + } + + if (!empty($unitKerja)) { + $updatePayload['unit'] = $unitKerja; + } + + if (!empty($updatePayload)) { + $jawabanBaru->update($updatePayload); + } + }); + + return redirect('/') + ->with('success', 'Jawaban berhasil disimpan.'); + } } diff --git a/app/Models/Jawaban.php b/app/Models/Jawaban.php index 5f32f6b..2fb7819 100644 --- a/app/Models/Jawaban.php +++ b/app/Models/Jawaban.php @@ -11,6 +11,8 @@ class Jawaban extends Model protected $guarded = ['id']; protected $with = ['jawabanDetail']; + public $timestamps = false; + public function jawabanDetail(){ return $this->hasMany(JawabanDetail::class, 'lms_mutu_jawaban_id', 'id'); } diff --git a/app/Models/JawabanDetail.php b/app/Models/JawabanDetail.php index a65ebe1..c76d0d6 100644 --- a/app/Models/JawabanDetail.php +++ b/app/Models/JawabanDetail.php @@ -9,4 +9,5 @@ class JawabanDetail extends Model protected $connection = 'dbLmsMutu'; protected $table = 'public.lms_mutu_jawaban_detail'; protected $guarded = ['id']; + public $timestamps = false; } diff --git a/resources/views/layouts/template.blade.php b/resources/views/layouts/template.blade.php index 9b28fff..443afc5 100644 --- a/resources/views/layouts/template.blade.php +++ b/resources/views/layouts/template.blade.php @@ -38,7 +38,7 @@ - + @yield('custom_css') @@ -96,7 +96,7 @@ Authorization: `bearer ${token}`, "x-klien": 1 }; - + $(document).ready(function(){ setNameAccount(); $('#btn_logout').click(function(){ @@ -114,7 +114,7 @@ buttonsStyling: false }).then(function(result) { if (result.value) { - $.removeCookie('token'); + $.removeCookie('token'); window.location.href = "/logout"; } }); @@ -129,17 +129,17 @@ const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); - + return JSON.parse(jsonPayload); } catch(e) { - console.error("Invalid JWT:", e); + // console.error("Invalid JWT:", e); return null; } } function setNameAccount() { const decode = parseJwt(); - + if(decode){ $('#name_account').html(decode.nama_pegawai); } @@ -148,4 +148,4 @@ @yield('custom_js') - \ No newline at end of file + diff --git a/resources/views/soal/index.blade.php b/resources/views/soal/index.blade.php index d92b4e3..f9985d5 100644 --- a/resources/views/soal/index.blade.php +++ b/resources/views/soal/index.blade.php @@ -1,4 +1,452 @@ @extends('layouts.template') -@section('content') +@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; +@endphp + +
+
+
+
+
+

Kuesioner

+

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

+
+
+ + ← Daftar Judul + + Halaman {{ $hal }} +
+
+ + + +
+
+
+ Progres Halaman + {{ $progressPercentage }}% +
+
+
+
+
+
+ + @if ($hal === $halPertama) +
+
+

Judul Soal

+
{{ $soal->judul_soal ?? '-' }}
+

Keterangan

+
+ {!! $soal->keterangan_soal !!} +
+
+
+ @endif + + + + @if ($errors->any()) + + @endif + +
+
Daftar Pertanyaan
+ Halaman {{ $hal }} dari {{ $listHal->count() }} +
+ +
+ @csrf + + + + @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'] ?? []; + $oldAnswer = old('jawaban.' . $detail->id); + $oldOtherAnswer = old('jawaban_lainnya.' . $detail->id); + $showLainnya = $oldAnswer === 'Lainnya' || (!empty($oldOtherAnswer)); + $detailHal = $detail->hal ?? $listHal->first(); + $isVisible = $detailHal == $hal; + @endphp + +
+
+
+ {{ $loop->iteration }} +
+
+
{{ $pertanyaan }}
+ +
+ @if ($type === 'textarea') + + @elseif ($type === 'text') + + @else + @if (!empty($options)) +
+ @foreach ($options as $optionIndex => $option) + @php + $optionId = 'jawaban-' . $detail->id . '-' . $optionIndex; + $isLainnya = strtolower(trim($option)) === 'lainnya'; + @endphp +
+ + +
+ @if ($isLainnya) +
+ +
+ @endif + @endforeach +
+ @else + + @endif + @endif + + @error('jawaban.' . $detail->id) +
{{ $message }}
+ @enderror + @error('jawaban_lainnya.' . $detail->id) +
{{ $message }}
+ @enderror +
+
+ @empty +
+ Belum ada pertanyaan pada halaman ini. +
+ @endforelse + + @error('lms_mutu_soal_id') +

{{ $message }}

+ @enderror + @error('jawaban') +

{{ $message }}

+ @enderror + +
+
+ + +
+ +
+
+
+
+
+@endsection + +@section('custom_js') + @endsection diff --git a/resources/views/soal/list.blade.php b/resources/views/soal/list.blade.php new file mode 100644 index 0000000..8e57938 --- /dev/null +++ b/resources/views/soal/list.blade.php @@ -0,0 +1,59 @@ +@extends('layouts.template') + +@section('title', 'Daftar Kuesioner') + +@section('custom_css') + +@endsection + +@section('content') +
+
+

Selamat Datang di Survei Mutu

+

Silakan pilih kuesioner yang ingin Anda isi. Pastikan data yang diberikan sesuai kondisi unit kerja Anda.

+
+ @if (session('success')) + + @endif +
+ @foreach ($daftarSoal as $soal) +
+
+
+
+ Kuesioner +
+
{{ $soal->judul_soal ?? 'Tanpa Judul' }}
+

{{ \Illuminate\Support\Str::limit(strip_tags($soal->keterangan_soal ?? 'Belum ada keterangan'), 120) }}

+ +
+
+
+ @endforeach +
+
+@endsection diff --git a/routes/web.php b/routes/web.php index fedd5eb..dcb8569 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,9 +1,7 @@ name('soal.index'); +Route::post('/jawaban', [SoalController::class, 'store'])->name('soal.store');