6c6dd26823
- Quizzes table with questions, answer options, attempts, answers - Question types: multiple_choice, exclusion, true_false, free_text - Progressive scoring: [1,1,2,2,3,3,4,6,8,10] = max 40 per quiz - Alpine.js countdown timer per question with auto-submit on timeout - Admin: CRUD for quizzes + per-question editor, JSON export/import - Child: quiz overview with best scores, question view, result breakdown - Nav: Quiz link in child header and admin sidebar
90 lines
3.7 KiB
PHP
90 lines
3.7 KiB
PHP
<?php
|
|
namespace App\Http\Controllers\Admin;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\{Quiz, QuizQuestion, QuizAnswerOption};
|
|
use Illuminate\Http\Request;
|
|
|
|
class QuizQuestionController extends Controller {
|
|
|
|
public function create(Quiz $quiz) {
|
|
return view('admin.quiz_questions.create', compact('quiz'));
|
|
}
|
|
|
|
public function store(Request $r, Quiz $quiz) {
|
|
$r->validate([
|
|
'type' => 'required|in:multiple_choice,exclusion,true_false,free_text',
|
|
'question_text' => 'required|string',
|
|
'time_limit' => 'nullable|integer|min:5|max:120',
|
|
'correct_answer' => 'nullable|string|max:200',
|
|
'correct_option' => 'nullable|integer|min:0|max:3',
|
|
'options' => 'array',
|
|
'options.*.text' => 'nullable|string|max:200',
|
|
]);
|
|
$q = QuizQuestion::create([
|
|
'quiz_id' => $quiz->id,
|
|
'sort_order' => ($quiz->questions()->max('sort_order') ?? -1) + 1,
|
|
'type' => $r->type,
|
|
'question_text' => $r->question_text,
|
|
'time_limit' => $r->time_limit ?: null,
|
|
'correct_answer' => $r->correct_answer,
|
|
]);
|
|
if (in_array($r->type,['multiple_choice','exclusion'])) {
|
|
$correctIdx = (int)$r->input('correct_option', 0);
|
|
foreach (($r->options ?? []) as $i => $opt) {
|
|
if (!empty($opt['text'])) {
|
|
QuizAnswerOption::create([
|
|
'quiz_question_id' => $q->id,
|
|
'text' => $opt['text'],
|
|
'is_correct' => $i === $correctIdx,
|
|
'sort_order' => $i,
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
return redirect()->route('admin.quizzes.edit', $quiz)->with('success','Frage hinzugefügt.');
|
|
}
|
|
|
|
public function edit(QuizQuestion $question) {
|
|
return view('admin.quiz_questions.edit', compact('question'));
|
|
}
|
|
|
|
public function update(Request $r, QuizQuestion $question) {
|
|
$r->validate([
|
|
'type' => 'required|in:multiple_choice,exclusion,true_false,free_text',
|
|
'question_text' => 'required|string',
|
|
'time_limit' => 'nullable|integer|min:5|max:120',
|
|
'correct_answer' => 'nullable|string|max:200',
|
|
'correct_option' => 'nullable|integer|min:0|max:3',
|
|
'options' => 'array',
|
|
'options.*.text' => 'nullable|string|max:200',
|
|
]);
|
|
$question->update([
|
|
'type' => $r->type,
|
|
'question_text' => $r->question_text,
|
|
'time_limit' => $r->time_limit ?: null,
|
|
'correct_answer' => $r->correct_answer,
|
|
]);
|
|
if (in_array($r->type,['multiple_choice','exclusion'])) {
|
|
$question->answerOptions()->delete();
|
|
$correctIdx = (int)$r->input('correct_option', 0);
|
|
foreach (($r->options ?? []) as $i => $opt) {
|
|
if (!empty($opt['text'])) {
|
|
QuizAnswerOption::create([
|
|
'quiz_question_id' => $question->id,
|
|
'text' => $opt['text'],
|
|
'is_correct' => $i === $correctIdx,
|
|
'sort_order' => $i,
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
return redirect()->route('admin.quizzes.edit', $question->quiz)->with('success','Frage gespeichert.');
|
|
}
|
|
|
|
public function destroy(QuizQuestion $question) {
|
|
$quiz = $question->quiz;
|
|
$question->delete();
|
|
return redirect()->route('admin.quizzes.edit', $quiz)->with('success','Frage gelöscht.');
|
|
}
|
|
}
|