withCount('questions')->latest()->get(); return view('admin.quizzes.index', compact('quizzes')); } public function create() { $subjects = Subject::all(); return view('admin.quizzes.create', compact('subjects')); } public function store(Request $r) { $r->validate(['title'=>'required|string|max:120','subject_id'=>'required|exists:subjects,id','description'=>'nullable|string|max:500']); $quiz = Quiz::create($r->only('title','subject_id','description') + ['active'=>true]); return redirect()->route('admin.quizzes.edit', $quiz)->with('success','Quiz erstellt – jetzt Fragen hinzufügen.'); } public function edit(Quiz $quiz) { $subjects = Subject::all(); $questions = $quiz->questions()->with('answerOptions')->get(); return view('admin.quizzes.edit', compact('quiz','subjects','questions')); } public function update(Request $r, Quiz $quiz) { $r->validate(['title'=>'required|string|max:120','subject_id'=>'required|exists:subjects,id','description'=>'nullable|string|max:500']); $quiz->update($r->only('title','subject_id','description') + ['active'=>$r->boolean('active')]); return back()->with('success','Quiz gespeichert.'); } public function destroy(Quiz $quiz) { $quiz->delete(); return redirect()->route('admin.quizzes.index')->with('success','Quiz gelöscht.'); } public function export(Quiz $quiz) { $quiz->load('subject','questions.answerOptions'); $data = [ 'subject' => $quiz->subject->slug, 'title' => $quiz->title, 'description' => $quiz->description, 'questions' => $quiz->questions->map(fn($q) => [ 'type' => $q->type, 'question_text' => $q->question_text, 'time_limit' => $q->time_limit, 'correct_answer' => $q->correct_answer, 'options' => $q->answerOptions->map(fn($o) => [ 'text' => $o->text, 'is_correct' => (bool)$o->is_correct, ])->values(), ])->values(), ]; $filename = 'quiz-'.now()->format('Y-m-d').'-'.str($quiz->title)->slug().'.json'; return response()->streamDownload( fn() => print(json_encode($data, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE)), $filename, ['Content-Type'=>'application/json'] ); } public function import(Request $r) { $r->validate(['file'=>'required|file|mimes:json|max:4096']); $raw = json_decode(file_get_contents($r->file('file')->getRealPath()), true); if (!is_array($raw) || !isset($raw['title'],$raw['subject'],$raw['questions'])) { return back()->with('error','Ungültiges JSON-Format. Felder: title, subject, questions erwartet.'); } $subject = Subject::where('slug',$raw['subject'])->first(); if (!$subject) return back()->with('error','Unbekanntes Fach: '.$raw['subject']); DB::transaction(function() use ($raw,$subject) { $quiz = Quiz::create([ 'subject_id' => $subject->id, 'title' => $raw['title'], 'description' => $raw['description'] ?? null, 'active' => true, ]); foreach (array_slice($raw['questions'],0,10) as $i => $item) { $q = QuizQuestion::create([ 'quiz_id' => $quiz->id, 'sort_order' => $i, 'type' => $item['type'] ?? 'multiple_choice', 'question_text' => $item['question_text'], 'time_limit' => $item['time_limit'] ?? null, 'correct_answer' => $item['correct_answer'] ?? null, ]); foreach (($item['options'] ?? []) as $j => $opt) { QuizAnswerOption::create([ 'quiz_question_id' => $q->id, 'text' => $opt['text'], 'is_correct' => $opt['is_correct'] ?? false, 'sort_order' => $j, ]); } } }); return redirect()->route('admin.quizzes.index')->with('success','Quiz "'.$raw['title'].'" importiert.'); } }