diff --git a/Server/Controller/v1/ExercicesController.cs b/Server/Controller/v1/ExercicesController.cs index 4b7daf7..ef44e5a 100644 --- a/Server/Controller/v1/ExercicesController.cs +++ b/Server/Controller/v1/ExercicesController.cs @@ -24,7 +24,6 @@ public class ExercicesController : ControllerBase [HttpGet] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status204NoContent)] - [RequireHttps] [AllowAnonymous] public async Task GetExercices([FromQuery] int pageIndex = 1, [FromQuery] int pageSize = 5, [FromQuery] bool ascending = true) { @@ -35,7 +34,6 @@ public class ExercicesController : ControllerBase [HttpGet("{id}")] [ProducesResponseType(typeof(ResponseExerciceDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - [RequireHttps] [AllowAnonymous] public async Task GetExerciceById(string id) { @@ -59,7 +57,6 @@ public class ExercicesController : ControllerBase [ProducesResponseType(typeof(ResponseExerciceDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status400BadRequest)] - [RequireHttps] [AllowAnonymous] public async Task UpdateExercice(string id, [FromBody] RequestExerciceDto request) { diff --git a/Server/Controller/v1/SessionsController.cs b/Server/Controller/v1/SessionsController.cs index b7b348d..04d7511 100644 --- a/Server/Controller/v1/SessionsController.cs +++ b/Server/Controller/v1/SessionsController.cs @@ -1,6 +1,79 @@ -namespace Server.Controller.v1; +using Asp.Versioning; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Server.Dto.Request; +using Server.Dto.Response; +using Server.IServices; -public class SessionsController +namespace Server.Controller.v1 { - + [ApiController] + [ApiVersion("1.0")] + [Route("api/v{version:apiVersion}/[controller]")] + public class SessionsController : ControllerBase + { + private readonly ILogger _logger; + private readonly ISessionService _dataServices; + + public SessionsController(ILogger logger, ISessionService dataServices) + { + _logger = logger; + _dataServices = dataServices; + } + + [HttpGet] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [AllowAnonymous] + public async Task GetSessions([FromQuery] int pageIndex = 1, [FromQuery] int pageSize = 5, [FromQuery] bool ascending = true) + { + var sessions = await _dataServices.GetSessions(pageIndex, pageSize, ascending); + return sessions.TotalCount == 0 ? NoContent() : Ok(sessions); + } + + [HttpGet("{id}")] + [ProducesResponseType(typeof(ResponseSessionDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [AllowAnonymous] + public async Task GetSessionById(string id) + { + var session = await _dataServices.GetSessionById(id); + return session == null ? NotFound() : Ok(session); + } + + [HttpPost] + [ProducesResponseType(typeof(ResponseSessionDto), StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [AllowAnonymous] + public async Task CreateSession([FromBody] RequestSessionDto request) + { + if (!ModelState.IsValid) return BadRequest(ModelState); + + var createdSession = await _dataServices.CreateSession(request); + return CreatedAtAction(nameof(GetSessionById), new { id = createdSession.Id }, createdSession); + } + + [HttpPut("{id}")] + [ProducesResponseType(typeof(ResponseSessionDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [AllowAnonymous] + public async Task UpdateSession(string id, [FromBody] RequestSessionDto request) + { + if (!ModelState.IsValid) return BadRequest(ModelState); + + var updatedSession = await _dataServices.UpdateSession(id, request); + return updatedSession == null ? NotFound() : Ok(updatedSession); + } + + [HttpDelete("{id}")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [AllowAnonymous] + public async Task DeleteSession(string id) + { + var deleted = await _dataServices.DeleteSession(id); + return deleted ? NoContent() : NotFound(); + } + } } \ No newline at end of file diff --git a/Server/Controller/v1/TrainingProgramController.cs b/Server/Controller/v1/TrainingProgramController.cs index 83d978e..cd6cd5f 100644 --- a/Server/Controller/v1/TrainingProgramController.cs +++ b/Server/Controller/v1/TrainingProgramController.cs @@ -1,6 +1,79 @@ -namespace Server.Controller.v1; +using Asp.Versioning; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Server.Dto.Request; +using Server.Dto.Response; +using Server.IServices; -public class TrainingProgramController +namespace Server.Controller.v1 { - + [ApiController] + [ApiVersion("1.0")] + [Route("api/v{version:apiVersion}/[controller]")] + public class TrainingProgramsController : ControllerBase + { + private readonly ILogger _logger; + private readonly ITrainingProgramService _dataServices; + + public TrainingProgramsController(ILogger logger, ITrainingProgramService dataServices) + { + _logger = logger; + _dataServices = dataServices; + } + + [HttpGet] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [AllowAnonymous] + public async Task GetTrainingPrograms([FromQuery] int pageIndex = 1, [FromQuery] int pageSize = 5, [FromQuery] bool ascending = true) + { + var programs = await _dataServices.GetTrainingPrograms(pageIndex, pageSize, ascending); + return programs.TotalCount == 0 ? NoContent() : Ok(programs); + } + + [HttpGet("{id}")] + [ProducesResponseType(typeof(ResponseTrainingProgramDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [AllowAnonymous] + public async Task GetTrainingProgramById(string id) + { + var program = await _dataServices.GetTrainingProgramById(id); + return program == null ? NotFound() : Ok(program); + } + + [HttpPost] + [ProducesResponseType(typeof(ResponseTrainingProgramDto), StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [AllowAnonymous] + public async Task CreateTrainingProgram([FromBody] RequestTrainingProgramDto request) + { + if (!ModelState.IsValid) return BadRequest(ModelState); + + var createdProgram = await _dataServices.CreateTrainingProgram(request); + return CreatedAtAction(nameof(GetTrainingProgramById), new { id = createdProgram.Id }, createdProgram); + } + + [HttpPut("{id}")] + [ProducesResponseType(typeof(ResponseTrainingProgramDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [AllowAnonymous] + public async Task UpdateTrainingProgram(string id, [FromBody] RequestTrainingProgramDto request) + { + if (!ModelState.IsValid) return BadRequest(ModelState); + + var updatedProgram = await _dataServices.UpdateTrainingProgram(id, request); + return updatedProgram == null ? NotFound() : Ok(updatedProgram); + } + + [HttpDelete("{id}")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [AllowAnonymous] + public async Task DeleteTrainingProgram(string id) + { + var deleted = await _dataServices.DeleteTrainingProgram(id); + return deleted ? NoContent() : NotFound(); + } + } } \ No newline at end of file diff --git a/Server/Controller/v1/UsersController.cs b/Server/Controller/v1/UsersController.cs index 6bc7875..4209c78 100644 --- a/Server/Controller/v1/UsersController.cs +++ b/Server/Controller/v1/UsersController.cs @@ -23,7 +23,6 @@ public class UsersController : ControllerBase [HttpGet] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status204NoContent)] - [RequireHttps] public IActionResult GetUsers([FromQuery] int pageIndex = 1, [FromQuery] int pageSize = 5, [FromQuery] bool ascending = true) { var users = _dataServices.GetUsers(pageIndex, pageSize, ascending); @@ -35,8 +34,6 @@ public class UsersController : ControllerBase [HttpGet("{id}")] [ProducesResponseType(typeof(ResponseUserDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - - [RequireHttps] public IActionResult GetAlumniById(string id) { var alumni = _dataServices.GetUserById(id); diff --git a/Server/Dto/Request/RequestSessionDto.cs b/Server/Dto/Request/RequestSessionDto.cs index ad334a6..b2d2910 100644 --- a/Server/Dto/Request/RequestSessionDto.cs +++ b/Server/Dto/Request/RequestSessionDto.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace Server.Dto.Request @@ -12,6 +11,6 @@ namespace Server.Dto.Request public float Duration { get; set; } - public List Exercices { get; set; } = new List(); + public List ExerciceIds { get; set; } = new List(); } } \ No newline at end of file diff --git a/Server/Dto/Response/ResponseSessionDto.cs b/Server/Dto/Response/ResponseSessionDto.cs index 351a206..aff29c4 100644 --- a/Server/Dto/Response/ResponseSessionDto.cs +++ b/Server/Dto/Response/ResponseSessionDto.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; - namespace Server.Dto.Response { public class ResponseSessionDto diff --git a/Server/FirstTest.db b/Server/FirstTest.db new file mode 100644 index 0000000..10fd111 Binary files /dev/null and b/Server/FirstTest.db differ diff --git a/Server/IServices/ISessionService.cs b/Server/IServices/ISessionService.cs index 7975f0c..104c5bc 100644 --- a/Server/IServices/ISessionService.cs +++ b/Server/IServices/ISessionService.cs @@ -1,6 +1,15 @@ -namespace Server.IServices; +using Server.Dto.Request; +using Server.Dto.Response; +using Shared; -public class ISessionService +namespace Server.IServices { - + public interface ISessionService + { + Task> GetSessions(int page, int size, bool ascending = true); + Task GetSessionById(string id); + Task CreateSession(RequestSessionDto request); + Task UpdateSession(string id, RequestSessionDto request); + Task DeleteSession(string id); + } } \ No newline at end of file diff --git a/Server/IServices/ITrainingProgramService.cs b/Server/IServices/ITrainingProgramService.cs index 4137677..3d78d23 100644 --- a/Server/IServices/ITrainingProgramService.cs +++ b/Server/IServices/ITrainingProgramService.cs @@ -1,6 +1,15 @@ -namespace Server.IServices; +using Server.Dto.Request; +using Server.Dto.Response; +using Shared; -public class ITrainingProgramService +namespace Server.IServices { - + public interface ITrainingProgramService + { + Task> GetTrainingPrograms(int page, int size, bool ascending = true); + Task GetTrainingProgramById(string id); + Task CreateTrainingProgram(RequestTrainingProgramDto request); + Task UpdateTrainingProgram(string id, RequestTrainingProgramDto request); + Task DeleteTrainingProgram(string id); + } } \ No newline at end of file diff --git a/Server/Mappers/PaginatedResultProfile.cs b/Server/Mappers/PaginatedResultProfile.cs index 3f1ec90..abbef06 100644 --- a/Server/Mappers/PaginatedResultProfile.cs +++ b/Server/Mappers/PaginatedResultProfile.cs @@ -1,6 +1,16 @@ -namespace Server.Mappers; +using AutoMapper; +using Shared; +using Infrastructure.Entities; +using Server.Dto.Response; -public class PaginatedResultProfile +namespace Server.Mappers { - + public class PaginatedResultProfile : Profile + { + public PaginatedResultProfile() + { + CreateMap, PaginatedResult>() + .ForMember(dest => dest.Data, opt => opt.MapFrom(src => src.Data)); + } + } } \ No newline at end of file diff --git a/Server/Mappers/SessionProfile.cs b/Server/Mappers/SessionProfile.cs index 16d5291..e57cb4e 100644 --- a/Server/Mappers/SessionProfile.cs +++ b/Server/Mappers/SessionProfile.cs @@ -1,6 +1,19 @@ -namespace Server.Mappers; +using AutoMapper; +using Infrastructure.Entities; +using Server.Dto.Request; +using Server.Dto.Response; -public class SessionProfile +namespace Server.Mappers { - + public class SessionProfile : Profile + { + public SessionProfile() + { + CreateMap() + .ForMember(dest => dest.Exercices, opt => opt.MapFrom(src => src.Exercices)); + + CreateMap() + .ForMember(dest => dest.Exercices, opt => opt.Ignore()); + } + } } \ No newline at end of file diff --git a/Server/Mappers/TrainingProgramProfile.cs b/Server/Mappers/TrainingProgramProfile.cs index c9c241a..3eb1a08 100644 --- a/Server/Mappers/TrainingProgramProfile.cs +++ b/Server/Mappers/TrainingProgramProfile.cs @@ -1,6 +1,19 @@ -namespace Server.Mappers; +using AutoMapper; +using Infrastructure.Entities; +using Server.Dto.Request; +using Server.Dto.Response; -public class TrainingProgramProfile +namespace Server.Mappers { - + public class TrainingProgramProfile : Profile + { + public TrainingProgramProfile() + { + CreateMap() + .ForMember(dest => dest.Sessions, opt => opt.MapFrom(src => src.Sessions)); + + CreateMap() + .ForMember(dest => dest, opt => opt.Ignore()); + } + } } \ No newline at end of file diff --git a/Server/Program.cs b/Server/Program.cs index e4ecf5d..9640653 100644 --- a/Server/Program.cs +++ b/Server/Program.cs @@ -13,18 +13,26 @@ var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddControllers(); builder.Services.AddDbContext(options => - options.UseSqlite("Data Source=FirstTest.db")); + options.UseSqlite("Data Source=../Server/FirstTest.db", b => b.MigrationsAssembly("Infrastructure"))); // Register AutoMapper builder.Services.AddAutoMapper(typeof(UserProfile)); builder.Services.AddAutoMapper(typeof(ExerciceProfile)); +builder.Services.AddAutoMapper(typeof(SessionProfile)); +builder.Services.AddAutoMapper(typeof(PaginatedResultProfile)); +builder.Services.AddAutoMapper(typeof(TrainingProgramProfile)); + // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); diff --git a/Server/Services/SessionService.cs b/Server/Services/SessionService.cs index eb953b5..35dd57f 100644 --- a/Server/Services/SessionService.cs +++ b/Server/Services/SessionService.cs @@ -1,6 +1,71 @@ -namespace Server.Services; +using AutoMapper; +using Infrastructure; +using Infrastructure.Entities; +using Infrastructure.Repositories; +using Server.Dto.Request; +using Server.Dto.Response; +using Server.IServices; +using Shared; -public class SessionService +namespace Server.Services { - + public class SessionService : ISessionService + { + private readonly OptifitDbContext _context; + private readonly ISessionRepository _sessionRepository; + private readonly IExerciceRepository _exerciceRepository; + private readonly IMapper _mapper; + + public SessionService(OptifitDbContext context, ISessionRepository sessionRepository, IExerciceRepository exerciceRepository, IMapper mapper) + { + _context = context; + _sessionRepository = sessionRepository; + _exerciceRepository = exerciceRepository; + _mapper = mapper; + } + + public async Task> GetSessions(int page, int size, bool ascending = true) + { + var sessions = await _sessionRepository.GetPaginatedListAsync(page - 1, size, null, null); + var result = _mapper.Map>(sessions); + return result; + } + + public async Task GetSessionById(string id) + { + var session = await _sessionRepository.GetByIdAsync(id, s => s.Exercices); + return session == null ? null : _mapper.Map(session); + } + + public async Task CreateSession(RequestSessionDto request) + { + var session = _mapper.Map(request); + session.Exercices = (ICollection)await _exerciceRepository.GetAllAsync(e => request.ExerciceIds.Contains(e.Id)); + await _sessionRepository.InsertAsync(session); + await _context.SaveChangesAsync(); + return _mapper.Map(session); + } + + public async Task UpdateSession(string id, RequestSessionDto request) + { + var session = await _sessionRepository.GetByIdAsync(id, s => s.Exercices); + if (session == null) return null; + + _mapper.Map(request, session); + session.Exercices = (ICollection)await _exerciceRepository.GetAllAsync(e => request.ExerciceIds.Contains(e.Id)); + _sessionRepository.Update(session); + await _context.SaveChangesAsync(); + return _mapper.Map(session); + } + + public async Task DeleteSession(string id) + { + var session = await _sessionRepository.GetByIdAsync(id); + if (session == null) return false; + + _sessionRepository.Delete(id); + await _context.SaveChangesAsync(); + return true; + } + } } \ No newline at end of file diff --git a/Server/Services/TrainingProgramService.cs b/Server/Services/TrainingProgramService.cs index 33c8a68..8ab11a9 100644 --- a/Server/Services/TrainingProgramService.cs +++ b/Server/Services/TrainingProgramService.cs @@ -1,6 +1,67 @@ -namespace Server.Services; +using AutoMapper; +using Infrastructure; +using Infrastructure.Entities; +using Infrastructure.Repositories; +using Server.Dto.Request; +using Server.Dto.Response; +using Server.IServices; +using Shared; -public class TrainingProgramService +namespace Server.Services { - + public class TrainingProgramService : ITrainingProgramService + { + private readonly OptifitDbContext _context; + private readonly ITrainingProgramRepository _trainingProgramRepository; + private readonly IMapper _mapper; + + public TrainingProgramService(OptifitDbContext context, ITrainingProgramRepository trainingProgramRepository, IMapper mapper) + { + _context = context; + _trainingProgramRepository = trainingProgramRepository; + _mapper = mapper; + } + + public async Task> GetTrainingPrograms(int page, int size, bool ascending = true) + { + var programs = await _trainingProgramRepository.GetPaginatedListAsync(page - 1, size, null, null); + var result = _mapper.Map>(programs); + return result; + } + + public async Task GetTrainingProgramById(string id) + { + var program = await _trainingProgramRepository.GetByIdAsync(id, p => p.Sessions); + return program == null ? null : _mapper.Map(program); + } + + public async Task CreateTrainingProgram(RequestTrainingProgramDto request) + { + var program = _mapper.Map(request); + await _trainingProgramRepository.InsertAsync(program); + await _context.SaveChangesAsync(); + return _mapper.Map(program); + } + + public async Task UpdateTrainingProgram(string id, RequestTrainingProgramDto request) + { + var program = await _trainingProgramRepository.GetByIdAsync(id, p => p.Sessions); + if (program == null) return null; + + _mapper.Map(request, program); + _trainingProgramRepository.Update(program); + await _context.SaveChangesAsync(); + return _mapper.Map(program); + } + + public async Task DeleteTrainingProgram(string id) + { + var program = await _trainingProgramRepository.GetByIdAsync(id); + if (program == null) return false; + + _trainingProgramRepository.Delete(id); + await _context.SaveChangesAsync(); + return true; + } + } } \ No newline at end of file