questionnaire()->with('questionnaireSet.questions')->first(); $availableSets = QuestionnaireSet::where('status', 'published') ->withCount('questions') ->orderBy('title') ->get(); return view('admin.programs.questionnaire.show', compact('program', 'pq', 'availableSets')); } public function attach(Request $request, Program $program): RedirectResponse { $data = $request->validate([ 'questionnaire_set_id' => 'required|exists:questionnaire_sets,id', ]); if ($program->questionnaire()->exists()) { return back()->with('error', 'Program ini sudah ada soalselidik dilampirkan. Tanggalkan dahulu sebelum lampir yang baru.'); } $set = QuestionnaireSet::findOrFail($data['questionnaire_set_id']); if ($set->status !== 'published') { return back()->with('error', 'Hanya soalselidik yang diterbitkan boleh dilampirkan.'); } ProgramQuestionnaire::create([ 'program_id' => $program->id, 'questionnaire_set_id' => $set->id, 'is_confirmed' => false, ]); return back()->with('success', 'Soalselidik berjaya dilampirkan. Sila sahkan sebelum program bermula.'); } public function confirm(Request $request, Program $program): RedirectResponse { $pq = $program->questionnaire; if (! $pq) { return back()->with('error', 'Tiada soalselidik untuk disahkan.'); } $pq->update([ 'is_confirmed' => true, 'confirmed_at' => now(), 'confirmed_by' => auth()->id(), ]); AuditLogService::log('questionnaire.confirmed', $pq, [], ['program_id' => $program->id, 'questionnaire_set_id' => $pq->questionnaire_set_id]); return back()->with('success', 'Soalselidik telah disahkan untuk program ini.'); } public function preview(Program $program): View|\Illuminate\Http\RedirectResponse { $pq = $program->questionnaire()->with('questionnaireSet')->first(); if (! $pq || ! $pq->questionnaireSet) { return back()->with('error', 'Tiada soalselidik untuk dipratonton.'); } $questions = $pq->questionnaireSet->questions() ->whereNull('parent_id') ->with(['children' => fn($q) => $q->orderBy('sort_order')]) ->orderBy('sort_order') ->get(); return view('admin.programs.questionnaire.preview', compact('program', 'pq', 'questions')); } public function detach(Program $program): RedirectResponse { $pq = $program->questionnaire; if (! $pq) { return back()->with('error', 'Tiada soalselidik untuk ditanggalkan.'); } if ($pq->is_confirmed) { $hasResponses = \App\Models\QuestionnaireResponse::where('program_id', $program->id)->exists(); if ($hasResponses) { return back()->with('error', 'Soalselidik tidak boleh ditanggalkan kerana sudah ada respons diterima.'); } } $pq->delete(); return back()->with('success', 'Soalselidik berjaya ditanggalkan.'); } }