DeutschLernen/GermanApp/Application/Services/LevelService.cs
Lasse Rune Hansen be8c58671d feat(backend/application): add DTOs and services for Lesson Management
- Created LevelDto.cs with LevelDto, CreateLevelDto, UpdateLevelDto
- Created UserProgressDto.cs with UserProgressDto, UpdateUserProgressDto, LevelCompletionDto
- Created LevelService.cs with CRUD operations for CEFR levels
- Created LessonService.cs with CRUD operations and filtering by level
- Created ProgressService.cs with user progress tracking, completion percentage, and lesson unlocking logic
- Registered all new services in Program.cs
- Fixed UserProgressDto ToEntity/UpdateFromDto to use domain entity methods

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-08 20:51:38 +02:00

101 lines
3.3 KiB
C#

using GermanApp.Application.DTOs;
using GermanApp.Domain.Entities;
using GermanApp.Domain.Interfaces;
namespace GermanApp.Application.Services;
/// <summary>
/// Application service for managing CEFR levels.
/// This is part of the Application layer.
/// </summary>
public class LevelService
{
private readonly ILevelRepository _levelRepository;
public LevelService(ILevelRepository levelRepository)
{
_levelRepository = levelRepository;
}
/// <summary>
/// Gets all CEFR levels ordered by their sort order.
/// </summary>
public async Task<IReadOnlyList<LevelDto>> GetAllLevelsAsync(CancellationToken cancellationToken = default)
{
var levels = await _levelRepository.GetAllOrderedAsync(cancellationToken);
return levels.Select(l => l.ToDto()).ToList();
}
/// <summary>
/// Gets a level by its ID.
/// </summary>
public async Task<LevelDto?> GetLevelByIdAsync(int id, CancellationToken cancellationToken = default)
{
var level = await _levelRepository.GetByIdAsync(id, cancellationToken);
return level?.ToDto();
}
/// <summary>
/// Gets a level by its code (e.g., "A1", "B2").
/// </summary>
public async Task<LevelDto?> GetLevelByCodeAsync(string code, CancellationToken cancellationToken = default)
{
var level = await _levelRepository.GetByCodeAsync(code, cancellationToken);
return level?.ToDto();
}
/// <summary>
/// Creates a new CEFR level.
/// </summary>
public async Task<LevelDto> CreateLevelAsync(CreateLevelDto dto, CancellationToken cancellationToken = default)
{
var level = dto.ToEntity();
var createdLevel = await _levelRepository.AddAsync(level, cancellationToken);
return createdLevel.ToDto();
}
/// <summary>
/// Updates an existing CEFR level.
/// </summary>
public async Task<LevelDto?> UpdateLevelAsync(int id, UpdateLevelDto dto, CancellationToken cancellationToken = default)
{
var level = await _levelRepository.GetByIdAsync(id, cancellationToken);
if (level == null)
return null;
level.UpdateFromDto(dto);
await _levelRepository.UpdateAsync(level, cancellationToken);
return level.ToDto();
}
/// <summary>
/// Deletes a CEFR level by its ID.
/// </summary>
public async Task<bool> DeleteLevelAsync(int id, CancellationToken cancellationToken = default)
{
var level = await _levelRepository.GetByIdAsync(id, cancellationToken);
if (level == null)
return false;
await _levelRepository.DeleteAsync(level, cancellationToken);
return true;
}
/// <summary>
/// Gets the first level (lowest order number) - typically A1.
/// </summary>
public async Task<LevelDto?> GetFirstLevelAsync(CancellationToken cancellationToken = default)
{
var level = await _levelRepository.GetFirstLevelAsync(cancellationToken);
return level?.ToDto();
}
/// <summary>
/// Gets the next level after the specified one.
/// </summary>
public async Task<LevelDto?> GetNextLevelAsync(int currentLevelId, CancellationToken cancellationToken = default)
{
var level = await _levelRepository.GetNextLevelAsync(currentLevelId, cancellationToken);
return level?.ToDto();
}
}