Please I need help
Jan 6, 2024
6
Level 5
js affecting livewire option
i need help fixing this when the timer counts down it shuffles the quiz option and i dont want that
<div>
@if ($attempt)
<div class="bg-teal-200 py-3 rounded-md text-gray-600 text-center">
<p class="font-semibold">You have already attempted this quiz.</p>
<div class="mt-2">
<a href="{{route('results.show' , $attempt)}}" class="bg-teal-500 rounded-md px-4 py-2 text-white">Check Result</a>
</div>
</div>
@else
<div class="mb-2">
Time left for this quiz: <span class="font-bold">{{ $timer }}</span> sec.
</div>
<div>
<span class="text-bold">Question {{ $currentQuestionIndex + 1 }} of {{ $this->questionsCount }}:</span>
<h2 class="mb-4 text-2xl">{{ $currentQuestion->question_text }}</h2>
@foreach ($currentQuestion->questionOptions as $option)
<div wire:key="{{ $option->id }}">
<label for="option.{{ $option->id }}">
<input type="radio" id="option.{{ $option->id }}"
wire:model.defer="questionsAnswers.{{ $currentQuestionIndex }}"
name="questionsAnswers.{{ $currentQuestionIndex }}" value="{{ $option->id }}">
{{ $option->option }}
</label>
</div>
@endforeach
@if ($currentQuestionIndex < $this->questionsCount - 1)
<div class="mt-4">
<x-secondary-button wire:click="changeQuestion"
x-on:click="timer = {{ config('quiz.secondsPerQuestion') }};">
Next question
</x-secondary-button>
</div>
@else
<div class="mt-4">
<x-primary-button wire:click="submit">Submit</x-primary-button>
</div>
@endif
</div>
<script>
setInterval(() => {
@this.call('updateTimer');
}, 1000);
</script>
@endif
</div>
livewire component
<?php
namespace App\Http\Livewire\Front\Quizzes;
use App\Models\Quiz;
use App\Models\Test;
use Livewire\Component;
use App\Models\Question;
use App\Models\TestAnswer;
use App\Models\QuestionOption;
use Illuminate\Contracts\View\View;
use Illuminate\Database\Eloquent\Collection;
class Show extends Component
{
public Quiz $quiz;
public Collection $questions;
public Question $currentQuestion;
public int $currentQuestionIndex = 0;
public array $questionsAnswers = [];
public int $timer = 0;
public $attempt;
public function render(): View
{
// Check if the user has already attempted the quiz
return view('livewire.front.quizzes.show');
}
public function mount()
{
$this->attempt = Test::where('user_id', auth()->id())
->where('quiz_id', $this->quiz->id)
->first();
$this->timer = config('quiz.secondsPerQuestion');
// User hasn't attempted the quiz, proceed with initializing the quiz
$this->questions = Question::query()
->inRandomOrder()
->whereRelation('quizzes', 'quiz_id', $this->quiz->id)
->with('questionOptions')
->get();
$this->currentQuestion = $this->questions[$this->currentQuestionIndex];
for ($i = 0; $i < $this->questionsCount; $i++) {
$this->questionsAnswers[$i] = null;
}
}
public function getQuestionsCountProperty(): int
{
return $this->questions->count();
}
public function changeQuestion()
{
$this->currentQuestionIndex++;
if ($this->currentQuestionIndex >= $this->questionsCount) {
return $this->submit();
}
$this->currentQuestion = $this->questions[$this->currentQuestionIndex];
//$this->timer = config('quiz.secondsPerQuestion');
}
public function updateTimer()
{
if ($this->timer > 0) {
$this->timer--;
} else {
$this->submit();
}
}
public function submit()
{
$result = 0;
$test = Test::create([
'user_id' => auth()->id(),
'quiz_id' => $this->quiz->id,
'result' => 0,
'ip_address' => request()->ip(),
]);
foreach ($this->questionsAnswers as $key => $option) {
$status = 0;
if ($option !== null && QuestionOption::find($option)->correct) {
$status = 1;
$result++;
}
TestAnswer::create([
'user_id' => auth()->id(),
'test_id' => $test->id,
'question_id' => $this->questions[$key]->id,
'option_id' => $option,
'correct' => $status,
]);
}
$test->update([
'result' => $result,
]);
return redirect()->route('results.show', $test);
}
}
Please or to participate in this conversation.