diff --git a/src/Entities/AthleteEntity.cs b/src/Entities/AthleteEntity.cs index dbb60ae..199d635 100644 --- a/src/Entities/AthleteEntity.cs +++ b/src/Entities/AthleteEntity.cs @@ -87,7 +87,7 @@ namespace Entities /// public bool IsCoach { get; set; } - // [TODO] [DAVE] Pourquoi c'est un byte[] ? et pas un string ? it's me so should change it to string + // [TODO] [DAVE] Check Image public string? ProfilPicture { get; set; } public LargeImageEntity? Image { get; set; } @@ -106,7 +106,6 @@ namespace Entities public ICollection NotificationsSent { get; set; } = new List(); public int? DataSourceId { get; set; } - // [TODO] [DAVE] Pourquoi c'est un one to one ? et pas un one to many ? public DataSourceEntity? DataSource { get; set; } public ICollection Followers { get; set; } = []; diff --git a/src/HeartTrackAPI/Controllers/UsersController.cs b/src/HeartTrackAPI/Controllers/UsersController.cs index 644664b..6780d6c 100644 --- a/src/HeartTrackAPI/Controllers/UsersController.cs +++ b/src/HeartTrackAPI/Controllers/UsersController.cs @@ -334,8 +334,6 @@ public class UsersController : Controller } } - - // #[TODO] [Dave] ou faire un get qui si le role est coach resend les athletes et si le role est athlete resend les coach /// /// Obtient la liste des athlètes d'un coach spécifique. /// @@ -414,13 +412,6 @@ public class UsersController : Controller return Problem(); } } - /* [TODO] [Dave] - [HttpGet("{userId}/trainings")] - [ProducesResponseType(typeof(PageResponse), 200)] - [ProducesResponseType(404)] - [ProducesResponseType(500)] - public async Task> GetTrainings(int userId, [FromQuery] PageRequest request) - */ /// /// Déconnecte l'utilisateur actuel. diff --git a/src/HeartTrackAPI/Program.cs b/src/HeartTrackAPI/Program.cs index b8f6cc5..b0010a6 100644 --- a/src/HeartTrackAPI/Program.cs +++ b/src/HeartTrackAPI/Program.cs @@ -1,4 +1,4 @@ -using HeartTrackAPI; +using HeartTrackAPI.Utils; var builder = WebApplication.CreateBuilder(args); diff --git a/src/HeartTrackAPI/AppBootstrap.cs b/src/HeartTrackAPI/Utils/AppBootstrap.cs similarity index 99% rename from src/HeartTrackAPI/AppBootstrap.cs rename to src/HeartTrackAPI/Utils/AppBootstrap.cs index daa7193..c629f5e 100644 --- a/src/HeartTrackAPI/AppBootstrap.cs +++ b/src/HeartTrackAPI/Utils/AppBootstrap.cs @@ -14,7 +14,7 @@ using StubAPI; using StubbedContextLib; using Swashbuckle.AspNetCore.SwaggerGen; -namespace HeartTrackAPI; +namespace HeartTrackAPI.Utils; public class AppBootstrap(IConfiguration configuration) { diff --git a/src/Model/Manager/ActivityManager.cs b/src/Model/Manager/ActivityManager.cs deleted file mode 100644 index 6cd1ef1..0000000 --- a/src/Model/Manager/ActivityManager.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Model.Manager; - -public class ActivityManager : IActivityManager -{ - public void AddActivityFromFitFile(byte filePath) - { - throw new NotImplementedException(); - } -} \ No newline at end of file diff --git a/src/Model/Manager/Contract/IActivityManager.cs b/src/Model/Manager/Contract/IActivityManager.cs deleted file mode 100644 index 2be28cc..0000000 --- a/src/Model/Manager/Contract/IActivityManager.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Model.Manager; - -public interface IActivityManager -{ - public void AddActivityFromFitFile(byte filePath); -} \ No newline at end of file diff --git a/src/Model/Manager/UserManager.cs b/src/Model/Manager/UserManager.cs deleted file mode 100644 index d1b697a..0000000 --- a/src/Model/Manager/UserManager.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Model.Manager; - -public class UserManager -{ - -} \ No newline at end of file diff --git a/src/Model/Repository/IUserRepository.cs b/src/Model/Repository/IUserRepository.cs index 6ba01b9..dddc19d 100644 --- a/src/Model/Repository/IUserRepository.cs +++ b/src/Model/Repository/IUserRepository.cs @@ -5,13 +5,11 @@ namespace Model.Repository; public interface IUserRepository : IGenericRepository { public Task?> GetUsers(int index, int count, AthleteOrderCriteria? criteria , bool descending = false); - public Task AddFriend(User user, User friend); - public Task RemoveFriend(User user, User friend); - - // should be removed cause i just have to call the GetItem then get the friends public Task?> GetFriends(User user, int index, int count, AthleteOrderCriteria? criteria, bool descending = false); - public Task GetNbFriends(User user); + public Task?> GetAllAthletes(int index, int count, AthleteOrderCriteria? criteria, bool descending = false); + public Task?> GetAllCoaches(int index, int count, AthleteOrderCriteria? criteria, bool descending = false); + } \ No newline at end of file diff --git a/src/Model2Entities/Extension.cs b/src/Model2Entities/Extension.cs index 559f776..6838b1d 100644 --- a/src/Model2Entities/Extension.cs +++ b/src/Model2Entities/Extension.cs @@ -99,6 +99,12 @@ public static class Extensions .Include(a => a.Athlete) .Include(a => a.DataSource); } + public static IQueryable IncludeStandardProperties(this IQueryable query) + { + return query.Include(a => a.DataSource) + .Include(a => a.Activities) + .Include(a => a.Image); + } // public static Activity ToModel(this ActivityEntity entity) // { // return new Activity ( diff --git a/src/Model2Entities/UserRepository.cs b/src/Model2Entities/UserRepository.cs index b3a782f..f4ec148 100644 --- a/src/Model2Entities/UserRepository.cs +++ b/src/Model2Entities/UserRepository.cs @@ -4,6 +4,7 @@ using Model.Repository; using Shared; using EFMappers; using Entities; +using Microsoft.EntityFrameworkCore; namespace Model2Entities; @@ -16,66 +17,71 @@ public partial class DbDataManager public UserRepository(DbDataManager dbDataManager, ILogger logger) { - this._dataManager = dbDataManager; - this._logger = logger; + _dataManager = dbDataManager; + _logger = logger; } - public async Task> GetItems(int index, int count, AthleteOrderCriteria? orderingProperty = null, bool descending = false) + public async Task> GetItems(int index, int count, string? orderingProperty = null, + bool descending = false) + => await GetUsers(index, count, this.ToEnum(orderingProperty), descending); + + public async Task> GetUsers(int index, int count, + AthleteOrderCriteria? orderingProperty = null, bool descending = false) { - try { + _logger.LogInformation($"GetItems with index {index} and count {count}", index, count); - _logger.LogInformation($"GetItems with orderingProperty {orderingProperty} and descending {descending}", orderingProperty, descending); - var users = _dataManager.DbContext.AthletesSet.GetItemsWithFilterAndOrdering(b => true, index, count, orderingProperty, descending).ToModels(); + _logger.LogInformation($"GetItems with orderingProperty {orderingProperty} and descending {descending}", + orderingProperty, descending); + var users = _dataManager.DbContext.AthletesSet.IncludeStandardProperties().GetItemsWithFilterAndOrdering(b => true, index, count, + orderingProperty != AthleteOrderCriteria.None ? orderingProperty : null, descending).ToModels(); _logger.LogInformation($"Retrieved {users.Count()} users"); return await Task.FromResult(users); - } - catch (Exception ex) - { - _logger.LogError(ex.Message, ex.InnerException, ex.StackTrace); - return await Task.FromResult>(new List()); - } + } public async Task GetItemById(int id) { - try { + _logger.LogInformation($"GetItemById with id {id}", id); - var user = _dataManager.DbContext.AthletesSet.GetItemsWithFilterAndOrdering(b => b.IdAthlete == id, 0, 1, AthleteOrderCriteria.None, false).First().ToModel(); + var userEntity = await _dataManager.DbContext.AthletesSet.IncludeStandardProperties() + .SingleOrDefaultAsync(a => a.IdAthlete == id); + var user = userEntity != null ? userEntity.ToModel() : null; if (user != null) _logger.LogInformation($"Retrieved user with ID {id}"); else _logger.LogWarning($"No user found with ID {id}"); return await Task.FromResult(user); - } - catch (Exception ex) - { - _logger.LogError(ex.Message, ex.InnerException, ex.StackTrace); - return await Task.FromResult(null); - } + } public async Task UpdateItem(int oldItem, User newItem) { - // try { - // _logger.LogInformation($"UpdateItem with id {oldItem}", oldItem); - // var updatedUser = (await _dataManager.DbContext.UpdateItem(oldItem, newItem, (user, entity) => user.ToEntity(entity)))?.ToModel(); - // if (updatedUser != null) - // _logger.LogInformation($"Updated user with ID {oldItem}"); - // else - // _logger.LogWarning($"No user found with ID {oldItem}"); - // return await Task.FromResult(updatedUser); - // } - // catch (Exception ex) - // { - // _logger.LogError(ex.Message, ex.InnerException, ex.StackTrace); - // return await Task.FromResult(null); - // } - throw new NotImplementedException(); + _logger.LogInformation($"UpdateItem with id {oldItem}", oldItem); + + var originalEntity = _dataManager.DbContext.AthletesSet.Find(oldItem); + if (originalEntity == null) + { + _logger.LogWarning($"No user found with ID {oldItem}"); + return await Task.FromResult(null); + } + var originalEntry = _dataManager.DbContext.Entry(originalEntity); + var values = typeof(AthleteEntity).GetProperties().Where(ppty => ppty.Name != "IdAthlete") + .ToDictionary(ppty => ppty.Name, ppty => ppty.GetValue(newItem.ToEntity())); + originalEntry.CurrentValues.SetValues(values); + _dataManager.DbContext.AthletesSet.Attach(originalEntity); + _dataManager.DbContext.Entry(originalEntity).State = EntityState.Modified; + _dataManager.DbContext.SaveChanges(); + var updatedUser = originalEntity.ToModel(); + if (updatedUser != null) + _logger.LogInformation($"Updated user with ID {oldItem}"); + else + _logger.LogWarning($"No user found with ID {oldItem}"); + return await Task.FromResult(updatedUser); } public async Task AddItem(User item) { - try { + _logger.LogInformation("Adding new user"); var addedUser = (await _dataManager.DbContext.AddItem(item.ToEntity()))?.ToModel(); if (addedUser != null) @@ -83,17 +89,12 @@ public partial class DbDataManager else _logger.LogError("Failed to add user"); return await Task.FromResult(addedUser); - } - catch (Exception ex) - { - _logger.LogError(ex.Message, ex.InnerException, ex.StackTrace); - return await Task.FromResult(null); - } + } public async Task DeleteItem(int item) { - try { + _logger.LogInformation($"DeleteItem with id {item}", item); var deleted = await _dataManager.DbContext.DeleteItem(item); if (deleted) @@ -101,61 +102,107 @@ public partial class DbDataManager else _logger.LogWarning($"No user found with ID {item}"); return await Task.FromResult(deleted); - } - catch (Exception ex) - { - _logger.LogError(ex.Message, ex.InnerException, ex.StackTrace); - return await Task.FromResult(false); - } + } public async Task GetNbItems() { - try { + _logger.LogInformation("GetNbItems"); var nbItems = _dataManager.DbContext.AthletesSet.Count(); _logger.LogInformation($"Retrieved {nbItems} users"); return await Task.FromResult(nbItems); - } - catch (Exception ex) - { - _logger.LogError(ex.Message, ex.InnerException, ex.StackTrace); - return await Task.FromResult(0); - } + + } + + public async Task> GetAllAthletes(int index, int count, AthleteOrderCriteria? criteria, + bool descending = false) + { + + _logger.LogInformation($"GetAllAthletes with index {index} and count {count}", index, count); + _logger.LogInformation($"GetAllAthletes with criteria {criteria} and descending {descending}", criteria, + descending); + var athletes = _dataManager.DbContext.AthletesSet.IncludeStandardProperties() + .GetItemsWithFilterAndOrdering(a => a.IsCoach == false, index, count, + criteria != AthleteOrderCriteria.None ? criteria : null, descending).ToModels(); + _logger.LogInformation($"Retrieved {athletes.Count()} athletes"); + return await Task.FromResult(athletes); + } + + public async Task> GetAllCoaches(int index, int count, AthleteOrderCriteria? criteria, + bool descending = false) + { + + _logger.LogInformation($"GetAllCoaches with index {index} and count {count}", index, count); + _logger.LogInformation($"GetAllCoaches with criteria {criteria} and descending {descending}", criteria, + descending); + var coaches = _dataManager.DbContext.AthletesSet.IncludeStandardProperties() + .GetItemsWithFilterAndOrdering(a => a.IsCoach, index, count, + criteria != AthleteOrderCriteria.None ? criteria : null, descending).ToModels(); + _logger.LogInformation($"Retrieved {coaches.Count()} coaches"); + return await Task.FromResult(coaches); + } - public async Task> GetUsers(int index, int count, AthleteOrderCriteria? criteria, bool descending = false) + public async Task AddFriend(User user, User friend) { - try { - _logger.LogInformation($"GetUsers with index {index} and count {count}", index, count); - _logger.LogInformation($"GetUsers with criteria {criteria} and descending {descending}", criteria, descending); - var users = _dataManager.DbContext.AthletesSet.GetItemsWithFilterAndOrdering(a => a.IsCoach == false, index, count, criteria, descending).ToModels(); - _logger.LogInformation($"Retrieved {users.Count()} users"); - return await Task.FromResult(users); + _logger.LogInformation($"Attempting to add friend: User {user.Id} adding Friend {friend.Id}"); + var userEntity = _dataManager.DbContext.AthletesSet.IncludeStandardProperties().FirstOrDefault(a => a.IdAthlete == user.Id); + var friendEntity = _dataManager.DbContext.AthletesSet.IncludeStandardProperties().FirstOrDefault(a => a.IdAthlete == friend.Id); + if (userEntity == null || friendEntity == null) + { + _logger.LogWarning($"User or friend not found: User {user.Id}, Friend {friend.Id}"); + return false; } - catch (Exception ex) + + if (userEntity.Followings.All(f => f.FollowingId != friend.Id)) { - _logger.LogError(ex.Message, ex.InnerException, ex.StackTrace); - return await Task.FromResult>(new List()); + userEntity.Followings.Add(new FriendshipEntity + { FollowingId = friend.Id, FollowerId = user.Id, StartDate = DateTime.Now }); + await _dataManager.DbContext.SaveChangesAsync(); + _logger.LogInformation($"Successfully added friend: User {user.Id} added Friend {friend.Id}"); + return true; } - } - public async Task AddFriend(User user, User friend) - { - throw new NotImplementedException(); + _logger.LogInformation($"Friendship already exists: User {user.Id} and Friend {friend.Id}"); + return false; } public async Task RemoveFriend(User user, User friend) { - throw new NotImplementedException(); + _logger.LogInformation($"Attempting to remove friend: User {user.Id} removing Friend {friend.Id}"); + var userEntity = user.ToEntity(); + var friendEntity = friend.ToEntity(); + if (userEntity == null || friendEntity == null) + { + _logger.LogWarning($"User or friend not found: User {user.Id}, Friend {friend.Id}"); + return false; + } + + var friendship = userEntity.Followings.FirstOrDefault(f => f.FollowingId == friend.Id); + if (friendship != null) + { + userEntity.Followings.Remove(friendship); + await _dataManager.DbContext.SaveChangesAsync(); + _logger.LogInformation($"Successfully removed friend: User {user.Id} removed Friend {friend.Id}"); + return true; + } + + _logger.LogInformation($"Friendship does not exist: User {user.Id} and Friend {friend.Id}"); + return false; } - public Task> GetFriends(User user, int index, int count, AthleteOrderCriteria? criteria, bool descending = false) + public Task> GetFriends(User user, int index, int count, AthleteOrderCriteria? criteria, + bool descending = false) { - try { + try + { _logger.LogInformation($"GetFriends with index {index} and count {count}", index, count); - _logger.LogInformation($"GetFriends with criteria {criteria} and descending {descending}", criteria, descending); - var friends = _dataManager.DbContext.AthletesSet.GetItemsWithFilterAndOrdering(a => a.IdAthlete == user.Id, index, count, criteria, descending).ToModels(); + _logger.LogInformation($"GetFriends with criteria {criteria} and descending {descending}", criteria, + descending); + var friends = _dataManager.DbContext.AthletesSet.IncludeStandardProperties() + .GetItemsWithFilterAndOrdering(a => a.Followers.Any(f => f.FollowingId == user.Id), index, count, + criteria, descending).ToModels(); _logger.LogInformation($"Retrieved {friends.Count()} friends"); return Task.FromResult(friends); } @@ -168,38 +215,13 @@ public partial class DbDataManager public Task GetNbFriends(User user) { - try { + _logger.LogInformation($"GetNbFriends with user {user}", user); - var nbFriends = _dataManager.DbContext.AthletesSet.Count(a => a.IdAthlete == user.Id); + var nbFriends = _dataManager.DbContext.AthletesSet + .GetItemsWithFilterAndOrdering(a => a.IdAthlete == user.Id, 0, int.MaxValue, + AthleteOrderCriteria.None, false).First().Followings.Count(); _logger.LogInformation($"Retrieved {nbFriends} friends"); return Task.FromResult(nbFriends); - } - catch (Exception ex) - { - _logger.LogError(ex.Message, ex.InnerException, ex.StackTrace); - return Task.FromResult(0); - } - } - - public Task> GetItems(int index, int count, AthleteOrderCriteria orderingProperty, bool descending = false) - { - try { - _logger.LogInformation($"GetItems with index {index} and count {count}", index, count); - _logger.LogInformation($"GetItems with orderingProperty {orderingProperty} and descending {descending}", orderingProperty, descending); - var users = _dataManager.DbContext.AthletesSet.GetItemsWithFilterAndOrdering(b => true, index, count, orderingProperty, descending).ToModels(); - _logger.LogInformation($"Retrieved {users.Count()} users"); - return Task.FromResult(users); - } - catch (Exception ex) - { - _logger.LogError(ex.Message, ex.InnerException, ex.StackTrace); - return Task.FromResult>(new List()); - } - } - - public Task> GetItems(int index, int count, string? orderingProperty = null, bool descending = false) - { - throw new NotImplementedException(); } } } \ No newline at end of file diff --git a/src/StubAPI/AthleteService.cs b/src/StubAPI/AthleteService.cs index 7729296..4d8bf29 100644 --- a/src/StubAPI/AthleteService.cs +++ b/src/StubAPI/AthleteService.cs @@ -108,4 +108,14 @@ public class UserService : IUserRepository { return await Task.FromResult(athletes.Count); } + + public async Task> GetAllAthletes(int index, int count, AthleteOrderCriteria? criteria, bool descending = false) + { + return await Task.FromResult(athletes.GetItemsWithFilterAndOrdering(c=>c.Role is Athlete,index, count,criteria, descending)); + } + + public async Task> GetAllCoaches(int index, int count, AthleteOrderCriteria? criteria, bool descending = false) + { + return await Task.FromResult(athletes.GetItemsWithFilterAndOrdering(c=>c.Role is Coach,index, count,criteria, descending)); + } } \ No newline at end of file