DeutschLernen/GermanApp/Infrastructure/Data/Repositories/QuizRepository.cs
Lasse Rune Hansen 242d5ea60b feat(backend): Complete Quiz System implementation
- Add Quiz entity with full domain logic (Create, Update, Activate, Deactivate)
- Add QuizQuestion entity updated to use QuizId instead of LessonId
- Add QuizRepository with all CRUD and query methods
- Add QuizQuestionRepository with QuizId-based and LessonId-based (legacy) methods
- Add QuizDto, CreateQuizDto, UpdateQuizDto, QuizWithQuestionsDto, QuizListItemDto
- Add QuizQuestionDto updated with QuizId, LessonId, QuizTitle, Points fields
- Add CreateQuizCommand, UpdateQuizCommand, DeleteQuizCommand, GetQuizWithQuestionsCommand
- Add QuizService with full quiz management (CRUD, activate, deactivate, counts, queries)
- Add QuizQuestionService updated with QuizId-based methods
- Add QuizzesController with comprehensive endpoints (GET, POST, PUT, DELETE)
- Add QuizzesController endpoints for quiz questions (by-quiz, random, active)
- Update QuizQuestionsController with new QuizId-based endpoints (backward compatible)
- Register QuizRepository and QuizService in DI container
- Update IRepository interfaces with QuizId-based methods
- Add SubmitQuizDto for quiz answer submission

Clean Architecture layers maintained:
- Domain: Quiz, QuizQuestion entities with business logic
- Application: DTOs, Commands, Services
- Infrastructure: Repositories, DbContext
- Presentation: Controllers

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-13 07:41:46 +02:00

114 lines
3.9 KiB
C#

using GermanApp.Domain.Entities;
using GermanApp.Domain.Interfaces;
using GermanApp.Infrastructure.Data.DbContext;
using Microsoft.EntityFrameworkCore;
namespace GermanApp.Infrastructure.Data.Repositories;
/// <summary>
/// Entity Framework Core implementation of IQuizRepository.
/// This is part of the Infrastructure layer.
/// </summary>
public class QuizRepository : IQuizRepository
{
private readonly AppDbContext _context;
public QuizRepository(AppDbContext context)
{
_context = context;
}
public async Task<Quiz?> GetByIdAsync(int id, CancellationToken cancellationToken = default)
{
return await _context.Quizzes
.Include(q => q.Lesson)
.FirstOrDefaultAsync(q => q.Id == id, cancellationToken);
}
public async Task<IReadOnlyList<Quiz>> GetAllAsync(CancellationToken cancellationToken = default)
{
return await _context.Quizzes
.Include(q => q.Lesson)
.AsNoTracking()
.ToListAsync(cancellationToken);
}
public async Task<Quiz> AddAsync(Quiz entity, CancellationToken cancellationToken = default)
{
await _context.Quizzes.AddAsync(entity, cancellationToken);
await _context.SaveChangesAsync(cancellationToken);
return entity;
}
public async Task UpdateAsync(Quiz entity, CancellationToken cancellationToken = default)
{
_context.Quizzes.Update(entity);
await _context.SaveChangesAsync(cancellationToken);
}
public async Task DeleteAsync(Quiz entity, CancellationToken cancellationToken = default)
{
_context.Quizzes.Remove(entity);
await _context.SaveChangesAsync(cancellationToken);
}
public async Task<bool> ExistsAsync(int id, CancellationToken cancellationToken = default)
{
return await _context.Quizzes
.AnyAsync(q => q.Id == id, cancellationToken);
}
public async Task<IReadOnlyList<Quiz>> GetByLessonAsync(int lessonId, CancellationToken cancellationToken = default)
{
return await _context.Quizzes
.Include(q => q.Lesson)
.Where(q => q.LessonId == lessonId)
.OrderBy(q => q.Id)
.AsNoTracking()
.ToListAsync(cancellationToken);
}
public async Task<IReadOnlyList<Quiz>> GetAllOrderedAsync(CancellationToken cancellationToken = default)
{
return await _context.Quizzes
.Include(q => q.Lesson)
.OrderBy(q => q.Lesson.Order)
.ThenBy(q => q.Id)
.AsNoTracking()
.ToListAsync(cancellationToken);
}
public async Task<IReadOnlyList<Quiz>> GetActiveByLessonAsync(int lessonId, CancellationToken cancellationToken = default)
{
return await _context.Quizzes
.Include(q => q.Lesson)
.Where(q => q.LessonId == lessonId && q.IsActive)
.OrderBy(q => q.Id)
.AsNoTracking()
.ToListAsync(cancellationToken);
}
public async Task<Quiz?> GetWithQuestionsAsync(int id, CancellationToken cancellationToken = default)
{
return await _context.Quizzes
.Include(q => q.Lesson)
.Include(q => q.Questions.OrderBy(qq => qq.Order))
.ThenInclude(qq => qq.Options.OrderBy(o => o.Order))
.FirstOrDefaultAsync(q => q.Id == id, cancellationToken);
}
public async Task<Quiz?> GetFirstByLessonAsync(int lessonId, CancellationToken cancellationToken = default)
{
return await _context.Quizzes
.Include(q => q.Lesson)
.Where(q => q.LessonId == lessonId && q.IsActive)
.OrderBy(q => q.Id)
.FirstOrDefaultAsync(cancellationToken);
}
public async Task<bool> ExistsByLessonAsync(int lessonId, CancellationToken cancellationToken = default)
{
return await _context.Quizzes
.AnyAsync(q => q.LessonId == lessonId, cancellationToken);
}
}