first
This commit is contained in:
@@ -9,6 +9,7 @@ use App\Models\QuestionnaireResponse;
|
||||
use App\Models\QuestionnaireAnswer;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class QuestionnaireController extends Controller
|
||||
@@ -20,27 +21,20 @@ class QuestionnaireController extends Controller
|
||||
|
||||
$participant = Participant::where('uuid', $participant_uuid)->firstOrFail();
|
||||
|
||||
// Verify participant belongs to this program
|
||||
$pp = $program->programParticipants()->where('participant_id', $participant->id)->first();
|
||||
abort_if(! $pp, 404);
|
||||
|
||||
$pq = $program->questionnaire()->with('questionnaireSet.questions')->first();
|
||||
$pq = $program->questionnaire()->with('questionnaireSet')->first();
|
||||
|
||||
if (! $pq || ! $pq->is_confirmed) {
|
||||
// No questionnaire — go straight to semak page
|
||||
return redirect()->route('public.semak.show', $qr_token);
|
||||
}
|
||||
|
||||
// Check already submitted
|
||||
$alreadySubmitted = QuestionnaireResponse::where('program_id', $program->id)
|
||||
->where('participant_id', $participant->id)
|
||||
->exists();
|
||||
|
||||
if ($alreadySubmitted) {
|
||||
if (QuestionnaireResponse::where('program_id', $program->id)->where('participant_id', $participant->id)->exists()) {
|
||||
return view('public.questionnaire.already', compact('program', 'participant', 'qrCode'));
|
||||
}
|
||||
|
||||
$questions = $pq->questionnaireSet->questions;
|
||||
$questions = $this->loadHierarchical($pq);
|
||||
|
||||
return view('public.questionnaire.show', compact('program', 'participant', 'qrCode', 'pq', 'questions'));
|
||||
}
|
||||
@@ -55,38 +49,27 @@ class QuestionnaireController extends Controller
|
||||
$pp = $program->programParticipants()->where('participant_id', $participant->id)->first();
|
||||
abort_if(! $pp, 404);
|
||||
|
||||
$pq = $program->questionnaire()->with('questionnaireSet.questions')->first();
|
||||
$pq = $program->questionnaire()->with('questionnaireSet')->first();
|
||||
abort_if(! $pq || ! $pq->is_confirmed, 404);
|
||||
|
||||
// Prevent double-submit
|
||||
$existing = QuestionnaireResponse::where('program_id', $program->id)
|
||||
->where('participant_id', $participant->id)
|
||||
->first();
|
||||
|
||||
if ($existing) {
|
||||
if (QuestionnaireResponse::where('program_id', $program->id)->where('participant_id', $participant->id)->exists()) {
|
||||
return view('public.questionnaire.already', compact('program', 'participant', 'qrCode'));
|
||||
}
|
||||
|
||||
$questions = $pq->questionnaireSet->questions;
|
||||
$questions = $this->loadHierarchical($pq);
|
||||
$answerable = $this->flatten($questions);
|
||||
|
||||
// Validate required questions
|
||||
$rules = [];
|
||||
foreach ($questions as $q) {
|
||||
if ($q->is_required) {
|
||||
$rules['q_' . $q->id] = 'required';
|
||||
} else {
|
||||
$rules['q_' . $q->id] = 'nullable';
|
||||
}
|
||||
foreach ($answerable as $q) {
|
||||
if ($q->question_type === 'multiple_choice') {
|
||||
$rules['q_' . $q->id] = ($q->is_required ? 'required|' : 'nullable|') . 'array';
|
||||
} else {
|
||||
$rules['q_' . $q->id] = $q->is_required ? 'required' : 'nullable';
|
||||
}
|
||||
}
|
||||
|
||||
$validated = $request->validate($rules, [
|
||||
'q_*.required' => 'Soalan ini wajib dijawab.',
|
||||
]);
|
||||
$request->validate($rules, ['q_*.required' => 'Soalan ini wajib dijawab.']);
|
||||
|
||||
// Save response
|
||||
$response = QuestionnaireResponse::create([
|
||||
'program_id' => $program->id,
|
||||
'participant_id' => $participant->id,
|
||||
@@ -96,7 +79,7 @@ class QuestionnaireController extends Controller
|
||||
'user_agent' => substr($request->userAgent() ?? '', 0, 500),
|
||||
]);
|
||||
|
||||
foreach ($questions as $q) {
|
||||
foreach ($answerable as $q) {
|
||||
$raw = $request->input('q_' . $q->id);
|
||||
|
||||
if ($raw === null && ! $q->is_required) {
|
||||
@@ -110,12 +93,39 @@ class QuestionnaireController extends Controller
|
||||
};
|
||||
|
||||
QuestionnaireAnswer::create([
|
||||
'questionnaire_response_id' => $response->id,
|
||||
'questionnaire_question_id' => $q->id,
|
||||
'answer_value' => $value,
|
||||
'questionnaire_response_id' => $response->id,
|
||||
'questionnaire_question_id' => $q->id,
|
||||
'answer_value' => $value,
|
||||
]);
|
||||
}
|
||||
|
||||
return view('public.questionnaire.thankyou', compact('program', 'participant', 'qrCode'));
|
||||
}
|
||||
|
||||
// ── Helpers ──────────────────────────────────────────────────────────────
|
||||
|
||||
private function loadHierarchical($pq): Collection
|
||||
{
|
||||
return $pq->questionnaireSet->questions()
|
||||
->whereNull('parent_id')
|
||||
->with(['children' => fn($q) => $q->orderBy('sort_order')])
|
||||
->orderBy('sort_order')
|
||||
->get();
|
||||
}
|
||||
|
||||
/** Return only answerable (non-tajuk) questions as a flat collection. */
|
||||
private function flatten(Collection $topLevel): Collection
|
||||
{
|
||||
$out = collect();
|
||||
foreach ($topLevel as $q) {
|
||||
if ($q->question_type === 'tajuk') {
|
||||
foreach ($q->children as $child) {
|
||||
$out->push($child);
|
||||
}
|
||||
} else {
|
||||
$out->push($q);
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user