I have a code where the code is displayed like a quiz, but the strange thing is that the first question is the question and the answer choices match but the next question the questions and answer choices don't match and the next questions are the same, only the first question matches, and questions 2, 3 .4 and so on don't even match.
for example : The question asks for year xxxx but the answer option displays the street location answer The next question is the same, only the first question and answer choice match
displays the question according to the answer choices so that the questions and answer choices in the next question match.
here the code for mount():
public function mount($uid)
{
$sessionKey = 'quiz_' . auth()->user()->id;
if (session()->has($sessionKey)) {
$sessionData = session($sessionKey);
$this->questionIndex = $sessionData['questionIndex'] ?? 0;
} else {
$this->questionIndex = 0;
}
// get exams id
$getid = Exams::where('uid', $uid)->firstorFail();
// get data
$this->getExamName = $getid->name;
$this->getDuration = $getid->duration;
$this->getExamDescription = $getid->short_description;
$this->getTypeExam = $getid->type;
$this->getFinalAssessmentExams = $getid->final_assessment;
// take exams
$takeExams = TakeExams::where('exams_id', $getid->id)->first();
$this->get_id_expire = $takeExams->id;
// get questions
$questions = Questions::where('exam_id', $getid->id)->inRandomOrder()->get();
// check question if it answered or not, if answered skip then show next question
$answeredQuestions = Answers::where('user_id', Auth::user()->id)
->where('exam_id', $getid->id)
->pluck('question_id')
->toArray();
$this->questions = $questions->whereNotIn('id', $answeredQuestions);
// Set nilai $questionIndex ke pertanyaan terakhir yang dijawab
$lastAnsweredQuestion = Answers::where('user_id', Auth::user()->id)
->where('exam_id', $getid->id)
->orderBy('id', 'desc')
->first();
// check last answer
if ($lastAnsweredQuestion) {
$lastAnsweredQuestionIndex = $this->questions->pluck('id')->search($lastAnsweredQuestion->question_id);
if ($lastAnsweredQuestionIndex !== false) {
$this->questionIndex = $lastAnsweredQuestionIndex + 1;
}
}
// get data
$this->exams_id = $getid->id;
$this->takeExams = $takeExams->id;
foreach ($this->questions as $key => $questionOption) {
$this->questionOption[$key]['options'] = QuestionsOption::where('questions_id', $questionOption->id)->get();
// return $this->questions[$key]['options'];
// If the current question matches the desired question index, assign its name to $name
if ($key === $this->questionIndex) {
$this->answer = $questionOption['question_option_id'];
$this->exams_id = $getid->id;
$this->takeExams = $takeExams->id;
}
}
}
here the code for submitQuiz
public function submitQuiz()
{
$validated = $this->validate([
'answer' => 'required',
]);
session(['quiz_' . auth()->user()->id => [
'questionIndex' => $this->questionIndex,
// Simpan status kuis lainnya yang perlu Anda pertahankan di sini
]]);
// get record question option by id
$getOption = QuestionsOption::where('id', $this->answer)->first();
// dd($getOption);
if ($validated) {
// creating answer
Answers::create([
'user_id' => Auth::user()->id,
'question_id' => $getOption->questions_id,
'question_option_id' => $this->answer,
'exam_id' => $this->exams_id,
'take_exam_id' => $this->takeExams,
'multiple_choice_answer' => $getOption->name,
'is_correct' => $getOption->is_correct_answer,
]);
}
// quiz
$this->questionIndex++;
if ($this->questionIndex >= count($this->questions)) {
$this->finished = true;
// session
$sessionKey = 'quiz_' . auth()->user()->id;
session()->forget($sessionKey);
$this->dispatch('remove-from-local-storage', ['key' => 'expiry']);
// count the correct answer
$correctAnswersCount = Answers::where('take_exam_id', $this->takeExams)
->where('is_correct', '1')
->count();
// update number of correct answer from take_exams so late can be use to make score
TakeExams::where('id', $this->takeExams)
->update(['number_of_correct_answer' => $correctAnswersCount]);
} else {
$this->question = $this->questions[$this->questionIndex];
$this->answer = null;
$this->resetRadioOptions();
// count the correct answer
$correctAnswersCount = Answers::where('take_exam_id', $this->takeExams)
->where('is_correct', '1')
->count();
// update number of correct answer from take_exams so late can be use to make score
TakeExams::where('id', $this->takeExams)
->update(['number_of_correct_answer' => $correctAnswersCount]);
}
}
and for last, the code for view
<form wire:submit.prevent="submitQuiz">
@csrf
<div class="">
@if (isset($questions[$questionIndex]))
<span class="text-sm text-gray-400 italic ">{{ __('Question :') }}</span>
<div class="text-3xl w-full">
<div class="text-3xl w-full">
{{ $questions[$questionIndex]['name'] }}
</div>
</div>
@endif
<div class="shadow-md rounded-md bg-gray-200">
@foreach ($questionOption[$questionIndex]['options'] as $option)
<label for="answer-{{ $option->id }}"
class="flex text-gray-700 rounded-md px-3 py-2 my-3 hover:bg-indigo-300 cursor-pointer ">
<input type="radio" wire:model="answer" name="answer"
value="{{ $option->id }}" id="answer-{{ $option->id }}"
@if ($this->answer == $option->id) checked @endif>
<span class="-mt-1 px-3">
{{ $option->name }}
</span>
</label>
<p class="text-xs italic text-red-500 ml-7">
@error('answer')
{!! "<span class='superscript'>* </span>" . $message !!}
@enderror
</p>
@endforeach
</div>
</div>
<div class="mt-4">
@if ($questionIndex >= count($questions))
<div>
<div class="bg-white p-3 ">
{{ __('If you refreshed the page, ') }} <span class="text-red-500">
{{ __('refresh') }} </span>
{{ __('again until get the question left, or best you do') }} <span
class="text-red-500"> {{ __('re-take') }}</span>
{{ __('the exams from begining again.') }}
</div>
<div class="bg-white p-3 mt-4 ">
{{ __('If the question reach ') }} <span class="text-red-500">
{{ __('0') }} </span>
{{ __('then you have finish the exams.') }}
</div>
<div class="my-3">
<x-green-button
wire:click="redirectToRoute('{{ route('student.exams-list') }}')"
class="w-full justify-center">{{ __('View Score') }}</x-green-button>
</div>
<div class="my-3">
<div class="w-full justify-center">
<x-primary-button onclick="goBack()"
class="w-full justify-center">{{ __('Back to Course') }}</x-primary-button>
</div>
</div>
<div class="my-3">
<x-indigo-button
wire:click="redirectToRoute('{{ route('student.dashboard') }}')"
class="w-full justify-center">{{ __('Back To Student Panel') }}</x-indigo-button>
</div>
</div>
@else
@if (isset($questions[$questionIndex]))
<x-sky-button>
{{ __('Next Question') }}
</x-sky-button>
@else
<div class="bg-white p-3 ">
{{ __('If you refreshed the page') }}
<span class="text-red-500">
{{ __('refresh') }} </span>
{{ __('again until get the question left. event you get error just refresh the page untiil finis the exams or do re-take the exams') }}
</div>
@endif
@endif
</div>
</form>
Add a unique wire:key to the contents of the @foreach loop to allow Livewire to correctly update the page fragment, it is also advisable to enclose all contents in a root tag like a <div>
Here some reference