commit
cf687a6e41
@ -0,0 +1,49 @@
|
|||||||
|
using Dto;
|
||||||
|
using Model;
|
||||||
|
|
||||||
|
namespace ApiMappeur;
|
||||||
|
|
||||||
|
public static class ActivityMappeur
|
||||||
|
{
|
||||||
|
/*public static ActivityDto ToDto(this Activity activity)
|
||||||
|
{
|
||||||
|
return new ActivityDto
|
||||||
|
{
|
||||||
|
Id = activity.Id,
|
||||||
|
Name = activity.Name,
|
||||||
|
Type = activity.Type,
|
||||||
|
Date = activity.Date,
|
||||||
|
Duration = activity.EndTime - activity.StartTime,
|
||||||
|
Distance = activity.Distance,
|
||||||
|
Elevation = activity.Elevation,
|
||||||
|
AverageSpeed = activity.AverageSpeed,
|
||||||
|
AverageHeartRate = activity.AverageHeartRate,
|
||||||
|
Calories = activity.Calories,
|
||||||
|
Description = activity.Description,
|
||||||
|
Gpx = activity.Gpx,
|
||||||
|
Image = activity.Image,
|
||||||
|
AthleteId = activity.AthleteId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Activity ToModel(this ActivityDto activityDto)
|
||||||
|
{
|
||||||
|
return new Activity
|
||||||
|
{
|
||||||
|
Id = activityDto.Id,
|
||||||
|
Name = activityDto.Name,
|
||||||
|
Type = activityDto.Type,
|
||||||
|
Date = activityDto.Date,
|
||||||
|
Duration = activityDto.Duration,
|
||||||
|
Distance = activityDto.Distance,
|
||||||
|
Elevation = activityDto.Elevation,
|
||||||
|
AverageSpeed = activityDto.AverageSpeed,
|
||||||
|
AverageHeartRate = activityDto.AverageHeartRate,
|
||||||
|
Calories = activityDto.Calories,
|
||||||
|
Description = activityDto.Description,
|
||||||
|
Gpx = activityDto.Gpx,
|
||||||
|
Image = activityDto.Image,
|
||||||
|
AthleteId = activityDto.AthleteId
|
||||||
|
};
|
||||||
|
}*/
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
namespace Dto;
|
||||||
|
|
||||||
|
public class ActivityDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Type { get; set; }
|
||||||
|
public DateTime Date { get; set; }
|
||||||
|
public TimeSpan Duration { get; set; }
|
||||||
|
public float Distance { get; set; }
|
||||||
|
public float Elevation { get; set; }
|
||||||
|
public float AverageSpeed { get; set; }
|
||||||
|
public int AverageHeartRate { get; set; }
|
||||||
|
public int Calories { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public string? Gpx { get; set; }
|
||||||
|
public string? Image { get; set; }
|
||||||
|
public int AthleteId { get; set; }
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
using ApiMappeur;
|
||||||
|
using Dto;
|
||||||
|
using HeartTrackAPI.Request;
|
||||||
|
using HeartTrackAPI.Responce;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Shared;
|
||||||
|
using Model;
|
||||||
|
using Model.Repository;
|
||||||
|
|
||||||
|
namespace HeartTrackAPI.Controllers;
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/activities")]
|
||||||
|
public class ActivityController : Controller
|
||||||
|
{
|
||||||
|
private readonly IActivityRepository _activityService;
|
||||||
|
private readonly ILogger<ActivityController> _logger;
|
||||||
|
|
||||||
|
public ActivityController(IActivityRepository activityService, ILogger<ActivityController> logger)
|
||||||
|
{
|
||||||
|
_activityService = activityService;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
[HttpGet]
|
||||||
|
[ProducesResponseType(typeof(PageResponse<ActivityDto>), 200)]
|
||||||
|
[ProducesResponseType(400)]
|
||||||
|
[ProducesResponseType(500)]
|
||||||
|
public async Task<ActionResult<PageResponse<ActivityDto>>> GetActivities([FromQuery] PageRequest pageRequest)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var totalCount = await _activityService.GetNbItems();
|
||||||
|
if (pageRequest.Count * pageRequest.Index >= totalCount)
|
||||||
|
{
|
||||||
|
_logger.LogError("To many object is asked the max is {totalCount} but the request is superior of ", totalCount);
|
||||||
|
return BadRequest("To many object is asked the max is : " + totalCount);
|
||||||
|
}
|
||||||
|
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(GetActivities), pageRequest);
|
||||||
|
var activities = await _activityService.GetActivities(pageRequest.Index, pageRequest.Count, ActivityOrderCriteria.None, pageRequest.Descending ?? false);
|
||||||
|
var pageResponse = new PageResponse<ActivityDto>(pageRequest.Index, pageRequest.Count, totalCount, activities.Select(a => a.ToDto()));
|
||||||
|
return Ok(pageResponse);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError(e, "Error while getting all activities");
|
||||||
|
return StatusCode(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{id}")]
|
||||||
|
public async Task<ActionResult<ActivityDto>> GetActivity(int id)
|
||||||
|
{
|
||||||
|
var activity = await _activityService.GetActivityByIdAsync(id);
|
||||||
|
if (activity == null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
return Ok(activity.ToDto());
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult<ActivityDto>> PostActivity(ActivityDto activityDto)
|
||||||
|
{
|
||||||
|
var activity = activityDto.ToModel();
|
||||||
|
var result = await _activityService.AddActivity(activity);
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
return BadRequest();
|
||||||
|
}
|
||||||
|
return CreatedAtAction(nameof(GetActivity), new { id = result.Id }, result.ToDto());
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("{id}")]
|
||||||
|
public async Task<IActionResult> PutActivity(int id, ActivityDto activityDto)
|
||||||
|
{
|
||||||
|
if (id != activityDto.Id)
|
||||||
|
{
|
||||||
|
return BadRequest();
|
||||||
|
}
|
||||||
|
var activity = activityDto.ToModel();
|
||||||
|
var result = await _activityService.UpdateActivity(id, activity);
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("{id}")]
|
||||||
|
public async Task<IActionResult> DeleteActivity(int id)
|
||||||
|
{
|
||||||
|
var result = await _activityService.DeleteActivity(id);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
return NoContent();
|
||||||
|
}*/
|
||||||
|
}
|
@ -0,0 +1,160 @@
|
|||||||
|
using ApiMappeur;
|
||||||
|
using Dto;
|
||||||
|
using HeartTrackAPI.Request;
|
||||||
|
using HeartTrackAPI.Responce;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Model;
|
||||||
|
using Model.Manager;
|
||||||
|
using Model.Repository;
|
||||||
|
using Shared;
|
||||||
|
|
||||||
|
namespace HeartTrackAPI.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/users")]
|
||||||
|
public class UsersController : Controller
|
||||||
|
{
|
||||||
|
private readonly ILogger<UsersController> _logger;
|
||||||
|
private readonly IUserRepository _userService;
|
||||||
|
public UsersController(ILogger<UsersController> logger, IDataManager dataManager)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_userService = dataManager.UserRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
[ProducesResponseType(typeof(PageResponse<UserDto>), 200)]
|
||||||
|
[ProducesResponseType(400)]
|
||||||
|
[ProducesResponseType(500)]
|
||||||
|
public async Task<ActionResult<PageResponse<UserDto>>> Get([FromQuery] PageRequest request)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var totalCount = await _userService.GetNbItems();
|
||||||
|
if (request.Count * request.Index >= totalCount)
|
||||||
|
{
|
||||||
|
_logger.LogError("To many object is asked the max is {totalCount} but the request is superior of ", totalCount);
|
||||||
|
return BadRequest("To many object is asked the max is : " + totalCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(Get), null);
|
||||||
|
|
||||||
|
var athletes = await _userService.GetUsers(request.Index, request.Count, Enum.TryParse(request.OrderingPropertyName, out AthleteOrderCriteria result) ? result : AthleteOrderCriteria.None, request.Descending ?? false);
|
||||||
|
var pageResponse = new PageResponse<UserDto>(request.Index, request.Count, totalCount, athletes.Select(a => a.ToDto()));
|
||||||
|
return Ok(pageResponse);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError(e, "Error while getting all athletes");
|
||||||
|
return StatusCode(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{id}")]
|
||||||
|
[ProducesResponseType(typeof(UserDto), 200)]
|
||||||
|
[ProducesResponseType(404)]
|
||||||
|
[ProducesResponseType(500)]
|
||||||
|
public async Task<ActionResult<UserDto>> GetById(int id)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(GetById), id);
|
||||||
|
var athlete = await _userService.GetItemById(id);
|
||||||
|
if (athlete == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Athlete with id {id} not found", id);
|
||||||
|
return NotFound($"Athlete with id {id} not found");
|
||||||
|
}
|
||||||
|
return Ok(athlete.ToDto());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError(e, "Error while getting athlete by id {id}", id);
|
||||||
|
return StatusCode(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[HttpGet("count")]
|
||||||
|
[ProducesResponseType(typeof(int), 200)]
|
||||||
|
[ProducesResponseType(500)]
|
||||||
|
public async Task<ActionResult<int>> Count()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(Count), null);
|
||||||
|
var nbUsers = await _userService.GetNbItems();
|
||||||
|
return Ok(nbUsers);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError(e, "Error while getting the number of users");
|
||||||
|
return StatusCode(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("{id}")]
|
||||||
|
[ProducesResponseType(typeof(UserDto), 200)]
|
||||||
|
[ProducesResponseType(404)]
|
||||||
|
[ProducesResponseType(500)]
|
||||||
|
public async Task<ActionResult<UserDto>> Update(int id, [FromBody] UserDto user)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(Update), user,id);
|
||||||
|
var athlete = await _userService.GetItemById(id);
|
||||||
|
if (athlete == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Athlete with id {id} not found", id);
|
||||||
|
return NotFound($"Athlete with id {id} not found");
|
||||||
|
}
|
||||||
|
var updatedAthlete = await _userService.UpdateItem(id, user.ToModel());
|
||||||
|
if(updatedAthlete == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Error while updating athlete with id {id}", id);
|
||||||
|
return StatusCode(500);
|
||||||
|
}
|
||||||
|
return Ok(updatedAthlete.ToDto());
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError(e, "Error while getting the number of users");
|
||||||
|
return StatusCode(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("{id}")]
|
||||||
|
[ProducesResponseType(200)]
|
||||||
|
[ProducesResponseType(404)]
|
||||||
|
[ProducesResponseType(500)]
|
||||||
|
public async Task<IActionResult> Delete(int id)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(Delete), null,id);
|
||||||
|
|
||||||
|
|
||||||
|
var athlete = await _userService.GetItemById(id);
|
||||||
|
if (athlete == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Athlete with id {id} not found", id);
|
||||||
|
return NotFound($"Athlete with id {id} not found");
|
||||||
|
}
|
||||||
|
var isDeleted = await _userService.DeleteItem(id);
|
||||||
|
if(!isDeleted)
|
||||||
|
{
|
||||||
|
_logger.LogError("Error while deleting athlete with id {id}", id);
|
||||||
|
return StatusCode(500);
|
||||||
|
}
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError(e, "Error while getting the number of users");
|
||||||
|
return StatusCode(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\ApiMappeur\ApiMappeur.csproj" />
|
||||||
|
<ProjectReference Include="..\Dto\Dto.csproj" />
|
||||||
|
<ProjectReference Include="..\Model\Model.csproj" />
|
||||||
|
<ProjectReference Include="..\Shared\Shared.csproj" />
|
||||||
|
<ProjectReference Include="..\StubAPI\StubAPI.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
<HintPath>..\..\..\..\..\.nuget\packages\newtonsoft.json\13.0.1\lib\netstandard2.0\Newtonsoft.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,6 @@
|
|||||||
|
@HeartTrackAPI_HostAddress = http://localhost:5030
|
||||||
|
|
||||||
|
GET {{HeartTrackAPI_HostAddress}}/weatherforecast/
|
||||||
|
Accept: application/json
|
||||||
|
|
||||||
|
###
|
@ -0,0 +1,26 @@
|
|||||||
|
using Model;
|
||||||
|
using Model.Manager;
|
||||||
|
using Model.Repository;
|
||||||
|
using StubAPI;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
// Add services to the container.
|
||||||
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen();
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
builder.Services.AddSingleton<IDataManager, StubData>();
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
app.Run();
|
@ -0,0 +1,14 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
using Shared;
|
||||||
|
|
||||||
|
namespace HeartTrackAPI.Request;
|
||||||
|
|
||||||
|
public class PageRequest
|
||||||
|
{
|
||||||
|
|
||||||
|
public string? OrderingPropertyName { get; set; } = null;// need to be map on the dto OrderCriteria
|
||||||
|
public bool? Descending { get; set; } = false;
|
||||||
|
public int Index { get; set; } = 0;
|
||||||
|
public int Count { get; set; } = 5;
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
namespace HeartTrackAPI.Responce;
|
||||||
|
|
||||||
|
public class PageResponse<T>
|
||||||
|
{
|
||||||
|
// The index of the first item
|
||||||
|
public int Index { get; set; } = 1;
|
||||||
|
// The number of items
|
||||||
|
public int Count { get; set; } = 1;
|
||||||
|
// The total number of items
|
||||||
|
public int Total { get; set; } = 1;
|
||||||
|
// The items
|
||||||
|
public IEnumerable<T> Items { get; set; }
|
||||||
|
|
||||||
|
public PageResponse(int index, int count, int total, IEnumerable<T> items)
|
||||||
|
{
|
||||||
|
Index = index;
|
||||||
|
Count = count;
|
||||||
|
Total = total;
|
||||||
|
Items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Model;
|
||||||
|
public class Activity
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Type { get; set; }
|
||||||
|
public DateTime Date { get; set; }
|
||||||
|
public DateTime StartTime { get; set; }
|
||||||
|
public DateTime EndTime { get; set; }
|
||||||
|
|
||||||
|
private int _effort;
|
||||||
|
[Range(0, 5)]
|
||||||
|
public int Effort
|
||||||
|
{
|
||||||
|
get => _effort;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0 || value > 5)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Effort must be between 0 and 5.");
|
||||||
|
}
|
||||||
|
_effort = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public float Variability { get; set; }
|
||||||
|
public float Variance { get; set; }
|
||||||
|
public float StandardDeviation { get; set; }
|
||||||
|
public float Average { get; set; }
|
||||||
|
public int Maximum { get; set; }
|
||||||
|
public int Minimum { get; set; }
|
||||||
|
public float AverageTemperature { get; set; }
|
||||||
|
public bool HasAutoPause { get; set; }
|
||||||
|
|
||||||
|
public Activity(int idActivity ,string type, DateTime date, DateTime startTime, DateTime endTime,
|
||||||
|
int effort, float variability, float variance, float standardDeviation,
|
||||||
|
float average, int maximum, int minimum, float averageTemperature, bool hasAutoPause)
|
||||||
|
{
|
||||||
|
Id = idActivity;
|
||||||
|
Type = type;
|
||||||
|
Date = date;
|
||||||
|
StartTime = startTime;
|
||||||
|
EndTime = endTime;
|
||||||
|
Effort = effort;
|
||||||
|
Variability = variability;
|
||||||
|
Variance = variance;
|
||||||
|
StandardDeviation = standardDeviation;
|
||||||
|
Average = average;
|
||||||
|
Maximum = maximum;
|
||||||
|
Minimum = minimum;
|
||||||
|
AverageTemperature = averageTemperature;
|
||||||
|
HasAutoPause = hasAutoPause;
|
||||||
|
}
|
||||||
|
public Activity(){}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"Activity #{Id}: {Type} on {Date:d/M/yyyy} from {StartTime:HH:mm:ss} to {EndTime:HH:mm:ss}" +
|
||||||
|
$" with an effort of {Effort}/5 and an average temperature of {AverageTemperature}°C" +
|
||||||
|
$" and a heart rate variability of {Variability} bpm" +
|
||||||
|
$" and a variance of {Variance} bpm" +
|
||||||
|
$" and a standard deviation of {StandardDeviation} bpm" +
|
||||||
|
$" and an average of {Average} bpm" +
|
||||||
|
$" and a maximum of {Maximum} bpm" +
|
||||||
|
$" and a minimum of {Minimum} bpm" +
|
||||||
|
$" and auto pause is {(HasAutoPause ? "enabled" : "disabled")}.";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
namespace Model;
|
||||||
|
|
||||||
|
public class Coach : Role
|
||||||
|
{
|
||||||
|
public override bool CheckAdd(User user)
|
||||||
|
{
|
||||||
|
return user.Role is Athlete;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
using Model.Repository;
|
||||||
|
|
||||||
|
namespace Model;
|
||||||
|
|
||||||
|
public static class EnumMappeur
|
||||||
|
{
|
||||||
|
public static Shared.AthleteOrderCriteria ToEnum(this IUserRepository repository, string? value)
|
||||||
|
{
|
||||||
|
return value switch
|
||||||
|
{
|
||||||
|
"None" => Shared.AthleteOrderCriteria.None,
|
||||||
|
"ByUsername" => Shared.AthleteOrderCriteria.ByUsername,
|
||||||
|
"ByFirstName" => Shared.AthleteOrderCriteria.ByFirstName,
|
||||||
|
"ByLastName" => Shared.AthleteOrderCriteria.ByLastName,
|
||||||
|
"BySexe" => Shared.AthleteOrderCriteria.BySexe,
|
||||||
|
"ByLenght" => Shared.AthleteOrderCriteria.ByLenght,
|
||||||
|
"ByWeight" => Shared.AthleteOrderCriteria.ByWeight,
|
||||||
|
"ByDateOfBirth" => Shared.AthleteOrderCriteria.ByDateOfBirth,
|
||||||
|
"ByEmail" => Shared.AthleteOrderCriteria.ByEmail,
|
||||||
|
"ByIsCoach" => Shared.AthleteOrderCriteria.ByIsCoach,
|
||||||
|
_ => Shared.AthleteOrderCriteria.None
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
using Model.Repository;
|
||||||
|
|
||||||
|
namespace Model.Manager;
|
||||||
|
|
||||||
|
public interface IDataManager
|
||||||
|
{
|
||||||
|
IUserRepository UserRepository { get; }
|
||||||
|
IActivityRepository ActivityRepository { get; }
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
namespace Model;
|
||||||
|
|
||||||
|
public class Notification
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
namespace Model;
|
||||||
|
|
||||||
|
public class RelationshipRequest
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
using Shared;
|
||||||
|
|
||||||
|
namespace Model.Repository;
|
||||||
|
|
||||||
|
public interface IActivityRepository
|
||||||
|
{
|
||||||
|
public Task<IEnumerable<Activity>> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false);
|
||||||
|
public Task<Activity?> GetActivityByIdAsync(int id);
|
||||||
|
public Task<Activity?> AddActivity(Activity activity);
|
||||||
|
public Task<Activity?> UpdateActivity(int id, Activity activity);
|
||||||
|
public Task<bool> DeleteActivity(int id);
|
||||||
|
public Task<int> GetNbItems();
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
namespace Model;
|
||||||
|
|
||||||
|
public abstract class Role
|
||||||
|
{
|
||||||
|
protected List<User> UsersList { get; set; } = [];
|
||||||
|
protected List<RelationshipRequest> UsersRequests { get; set; } = [];
|
||||||
|
protected List<Training> TrainingList { get; set; } = [];
|
||||||
|
public abstract bool CheckAdd(User user);
|
||||||
|
|
||||||
|
public bool AddUser(User user)
|
||||||
|
{
|
||||||
|
if (!CheckAdd(user)) return false;
|
||||||
|
UsersList.Add(user);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RemoveUser(User user)
|
||||||
|
{
|
||||||
|
return UsersList.Remove(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddTraining(Training training)
|
||||||
|
{
|
||||||
|
TrainingList.Add(training);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RemoveTraining(Training training)
|
||||||
|
{
|
||||||
|
return TrainingList.Remove(training);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddUserRequest(RelationshipRequest request)
|
||||||
|
{
|
||||||
|
UsersRequests.Add(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RemoveUserRequest(RelationshipRequest request)
|
||||||
|
{
|
||||||
|
return UsersRequests.Remove(request);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
namespace Model;
|
||||||
|
|
||||||
|
public class Training
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
namespace Model;
|
||||||
|
|
||||||
|
public class User
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Username { get; set; }
|
||||||
|
public string ProfilePicture { get; set; }
|
||||||
|
public string LastName { get; set; }
|
||||||
|
public string FirstName { get; set; }
|
||||||
|
public string Email { get; set; }
|
||||||
|
public string MotDePasse { get; set; }
|
||||||
|
public string Sexe { get; set; }
|
||||||
|
public float Lenght { get; set; }
|
||||||
|
public float Weight { get; set; }
|
||||||
|
public DateTime DateOfBirth { get; set; }
|
||||||
|
public Role Role { get; set; }
|
||||||
|
|
||||||
|
protected List<Notification> Notifications { get; set; } = new List<Notification>();
|
||||||
|
|
||||||
|
public User( string username, string profilePicture, string nom, string prenom, string email, string motDePasse, string sexe, float taille, float poids, DateTime dateNaissance, Role role)
|
||||||
|
{
|
||||||
|
Username = username;
|
||||||
|
ProfilePicture = profilePicture;
|
||||||
|
LastName = nom;
|
||||||
|
FirstName = prenom;
|
||||||
|
Email = email;
|
||||||
|
MotDePasse = motDePasse;
|
||||||
|
Sexe = sexe;
|
||||||
|
Lenght = taille;
|
||||||
|
Weight = poids;
|
||||||
|
DateOfBirth = dateNaissance;
|
||||||
|
Role = role;
|
||||||
|
}
|
||||||
|
public User(){}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
namespace Shared;
|
||||||
|
|
||||||
|
public enum ActivityOrderCriteria
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
ByName,
|
||||||
|
ByType,
|
||||||
|
ByDate,
|
||||||
|
ByDuration,
|
||||||
|
ByDistance,
|
||||||
|
ByElevation,
|
||||||
|
ByAverageSpeed,
|
||||||
|
ByAverageHeartRate,
|
||||||
|
ByCalories,
|
||||||
|
ByDescription
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
namespace Shared;
|
||||||
|
|
||||||
|
public interface IGenericRepository<T>
|
||||||
|
{
|
||||||
|
Task<IEnumerable<T>> GetItems(int index, int count, string? orderingProperty = null, bool descending = false);
|
||||||
|
Task<T?> GetItemById(int id);
|
||||||
|
Task<T?> UpdateItem(int oldItem, T newItem);
|
||||||
|
Task<T?> AddItem(T item);
|
||||||
|
Task<bool> DeleteItem(int item);
|
||||||
|
Task<int> GetNbItems();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
using Model;
|
||||||
|
using Model.Repository;
|
||||||
|
using Shared;
|
||||||
|
|
||||||
|
namespace StubAPI;
|
||||||
|
|
||||||
|
public class ActivityService: IActivityRepository
|
||||||
|
{
|
||||||
|
public async Task<IEnumerable<Activity>> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Activity?> GetActivityByIdAsync(int id)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Activity?> AddActivity(Activity activity)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Activity?> UpdateActivity(int id, Activity activity)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> DeleteActivity(int id)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetNbItems()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
namespace StubAPI;
|
||||||
|
|
||||||
|
|
||||||
|
public static class Extensions
|
||||||
|
{
|
||||||
|
internal static Task<T?> AddItem<T>(this IList<T> collection, T? item)
|
||||||
|
{
|
||||||
|
if(item == null || collection.Contains(item))
|
||||||
|
{
|
||||||
|
return Task.FromResult<T?>(default(T));
|
||||||
|
}
|
||||||
|
collection.Add(item);
|
||||||
|
return Task.FromResult<T?>(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Task<bool> DeleteItem<T>(this IList<T> collection, T? item)
|
||||||
|
{
|
||||||
|
if(item == null)
|
||||||
|
{
|
||||||
|
return Task.FromResult(false);
|
||||||
|
}
|
||||||
|
bool result = collection.Remove(item!);
|
||||||
|
return Task.FromResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Task<T?> UpdateItem<T>(this IList<T> collection, T? oldItem, T? newItem)
|
||||||
|
{
|
||||||
|
if(oldItem == null || newItem == null) return Task.FromResult<T?>(default(T));
|
||||||
|
|
||||||
|
if(!collection.Contains(oldItem))
|
||||||
|
{
|
||||||
|
return Task.FromResult<T?>(default(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
collection.Remove(oldItem!);
|
||||||
|
collection.Add(newItem!);
|
||||||
|
return Task.FromResult<T?>(newItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<T> GetItemsWithFilterAndOrdering<T>(this IEnumerable<T> list, Func<T, bool> filter, int index, int count, Enum? orderCriterium, bool descending = false ) where T : class
|
||||||
|
{
|
||||||
|
var filteredList = list.Where(filter);
|
||||||
|
|
||||||
|
if(orderCriterium != null)
|
||||||
|
{
|
||||||
|
filteredList = filteredList.OrderByCriteria(orderCriterium, descending);
|
||||||
|
}
|
||||||
|
return filteredList
|
||||||
|
.Skip(index * count)
|
||||||
|
.Take(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IOrderedEnumerable<T> OrderByCriteria<T>(this IEnumerable<T> list, Enum orderCriterium, bool descending = false ) where T : class
|
||||||
|
{
|
||||||
|
var orderCriteriumString = orderCriterium.ToString();
|
||||||
|
if (orderCriteriumString.StartsWith("By"))
|
||||||
|
{
|
||||||
|
orderCriteriumString = orderCriteriumString.Substring(2);
|
||||||
|
}
|
||||||
|
var propertyInfo = typeof(T).GetProperty(orderCriteriumString);
|
||||||
|
if (propertyInfo == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"No property {orderCriterium} in type {typeof(T)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return descending ? list.OrderByDescending(x => propertyInfo.GetValue(x)) : list.OrderBy(x => propertyInfo.GetValue(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
using Model.Manager;
|
||||||
|
using Model.Repository;
|
||||||
|
|
||||||
|
namespace StubAPI;
|
||||||
|
|
||||||
|
public class StubData : IDataManager
|
||||||
|
{
|
||||||
|
public IUserRepository UserRepository { get; }
|
||||||
|
public IActivityRepository ActivityRepository { get; }
|
||||||
|
|
||||||
|
public StubData()
|
||||||
|
{
|
||||||
|
UserRepository = new UserService();
|
||||||
|
ActivityRepository = new ActivityService();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
global using Microsoft.VisualStudio.TestTools.UnitTesting;
|
@ -0,0 +1,26 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
|
||||||
|
<PackageReference Include="MSTest.TestAdapter" Version="3.0.4"/>
|
||||||
|
<PackageReference Include="MSTest.TestFramework" Version="3.0.4"/>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\HeartTrackAPI\HeartTrackAPI.csproj" />
|
||||||
|
<ProjectReference Include="..\..\Model\Model.csproj" />
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
<ProjectReference Include="..\..\StubAPI\StubAPI.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,12 @@
|
|||||||
|
namespace ClientTests;
|
||||||
|
|
||||||
|
public class HttpClientManager
|
||||||
|
{
|
||||||
|
protected readonly HttpClient _httpClient;
|
||||||
|
|
||||||
|
public HttpClientManager(HttpClient httpClient)
|
||||||
|
{
|
||||||
|
_httpClient = httpClient;
|
||||||
|
_httpClient.BaseAddress = new Uri("https://localhost:7252");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
global using Xunit;
|
@ -0,0 +1,25 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.4.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,10 @@
|
|||||||
|
namespace TestsXUnit;
|
||||||
|
|
||||||
|
public class UnitTest1
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Test1()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
global using Microsoft.VisualStudio.TestTools.UnitTesting;
|
@ -0,0 +1,24 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
|
||||||
|
<PackageReference Include="MSTest.TestAdapter" Version="3.0.4"/>
|
||||||
|
<PackageReference Include="MSTest.TestFramework" Version="3.0.4"/>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\HeartTrackAPI\HeartTrackAPI.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\Model\Model.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,124 @@
|
|||||||
|
using Dto;
|
||||||
|
using HeartTrackAPI.Controllers;
|
||||||
|
using HeartTrackAPI.Request;
|
||||||
|
using HeartTrackAPI.Responce;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
using Model.Manager;
|
||||||
|
using Model.Repository;
|
||||||
|
using StubAPI;
|
||||||
|
|
||||||
|
namespace UnitTestApi;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class UserControllerTest
|
||||||
|
{
|
||||||
|
private readonly IDataManager StubDataManager;
|
||||||
|
private readonly UsersController _usersController;
|
||||||
|
|
||||||
|
public UserControllerTest()
|
||||||
|
{
|
||||||
|
StubDataManager = new StubData();
|
||||||
|
_usersController = new UsersController(new NullLogger<UsersController>(), StubDataManager);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Get_ReturnsPageResponse_WhenRequestIsValid()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new PageRequest
|
||||||
|
{
|
||||||
|
Index = 0,
|
||||||
|
Count = 10,
|
||||||
|
OrderingPropertyName = "Id",
|
||||||
|
Descending = false
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
//var result = _usersController.Get(request).Result as OkObjectResult;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
// Assert.IsNotNull(result);
|
||||||
|
//Assert.IsInstanceOfType(result.Value, typeof(PageResponse<UserDto>));
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
[TestMethod]
|
||||||
|
public void GetById_ReturnsUserDto_WhenRequestIsValid()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var id = 1;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = _usersController.GetById(id).Result as OkObjectResult;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsNotNull(result);
|
||||||
|
Assert.IsInstanceOfType(result.Value, typeof(UserDto));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void GetById_Returns404_WhenIdIsInvalid()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var id = 0;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = _usersController.GetById(id).Result as NotFoundResult;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsNotNull(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void GetById_Returns500_WheExceptionIsThrown()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var id = 0;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = _usersController.GetById(id).Result as StatusCodeResult;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsNotNull(result);
|
||||||
|
Assert.AreEqual(500, result.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Count_ReturnsInt_WhenRequestIsValid()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var result = _usersController.Count().Result as OkObjectResult;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsNotNull(result);
|
||||||
|
Assert.IsInstanceOfType(result.Value, typeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Count_Returns500_WheExceptionIsThrown()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var result = _usersController.Count().Result as StatusCodeResult;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsNotNull(result);
|
||||||
|
Assert.AreEqual(500, result.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Update_ReturnsUserDto_WhenRequestIsValid()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var id = 1;
|
||||||
|
var user = new UserDto
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
FirstName = "John",
|
||||||
|
LastName = "Doe",
|
||||||
|
Email = "toto@eoeo.fr",
|
||||||
|
};
|
||||||
|
|
||||||
|
}*/
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in new issue