-
Notifications
You must be signed in to change notification settings - Fork 0
✨ Add functionality for managing user favorite activities #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -51,7 +51,7 @@ public List<ActivityEntity> GetPendingActivities(int editionId) | |||||||||||
| } | ||||||||||||
|
|
||||||||||||
| public IEnumerable<ActivityEntity> GetActiveActivitiesFiltered(int typeId, int editionId, | ||||||||||||
| List<int> timeFrames, string title, int skipByPagination, int activitiesPerPage, int userFav = default) | ||||||||||||
| List<int> timeFrames, string title, int userFav = default) | ||||||||||||
| { | ||||||||||||
| IEnumerable<ActivityEntity> query; | ||||||||||||
|
|
||||||||||||
|
|
@@ -67,6 +67,98 @@ public IEnumerable<ActivityEntity> GetActiveActivitiesFiltered(int typeId, int e | |||||||||||
| return query; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| public List<ActivityEntity> GetFavouriteActivitiesByUser(int userId, int editionId) | ||||||||||||
| { | ||||||||||||
| if (userId == default || editionId == default) | ||||||||||||
| { | ||||||||||||
| return new List<ActivityEntity>(); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| return GetFavActivitiesFiltered(0, editionId, null, null, userId).ToList(); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| public bool AddFavouriteActivity(int activityId, int userId) | ||||||||||||
| { | ||||||||||||
| try | ||||||||||||
| { | ||||||||||||
| var user = _unitOfWork.UserRepository.GetById(userId); | ||||||||||||
| var activity = _unitOfWork.ActivityRepository.GetById(activityId); | ||||||||||||
|
|
||||||||||||
| if (user == null || activity == null) | ||||||||||||
| { | ||||||||||||
| return false; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| activity = _unitOfWork.ActivityRepository.GetAllIncludeFavs(activity.EditionId) | ||||||||||||
| .FirstOrDefault(a => a.Id == activityId); | ||||||||||||
|
|
||||||||||||
| if (activity == null) | ||||||||||||
| { | ||||||||||||
| return false; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| if (activity.UsersFav == null) | ||||||||||||
| { | ||||||||||||
| activity.UsersFav = new List<UserEntity>(); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| if (activity.UsersFav.Any(u => u.Id == userId)) | ||||||||||||
| { | ||||||||||||
| return false; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| activity.UsersFav.Add(user); | ||||||||||||
|
|
||||||||||||
| _unitOfWork.ActivityRepository.Update(activity); | ||||||||||||
| _unitOfWork.ActivityRepository.Save(); | ||||||||||||
|
|
||||||||||||
| return true; | ||||||||||||
| } | ||||||||||||
| catch (Exception) | ||||||||||||
| { | ||||||||||||
| return false; | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| public bool RemoveFavouriteActivity(int activityId, int userId) | ||||||||||||
| { | ||||||||||||
| try | ||||||||||||
| { | ||||||||||||
| var activity = _unitOfWork.ActivityRepository.GetById(activityId); | ||||||||||||
|
|
||||||||||||
| if (activity == null) | ||||||||||||
| { | ||||||||||||
| return false; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| activity = _unitOfWork.ActivityRepository.GetAllIncludeFavs(activity.EditionId) | ||||||||||||
| .FirstOrDefault(a => a.Id == activityId); | ||||||||||||
|
|
||||||||||||
| if (activity?.UsersFav == null) | ||||||||||||
|
Comment on lines
+134
to
+137
|
||||||||||||
| activity = _unitOfWork.ActivityRepository.GetAllIncludeFavs(activity.EditionId) | |
| .FirstOrDefault(a => a.Id == activityId); | |
| if (activity?.UsersFav == null) | |
| if (activity.UsersFav == null) |
Copilot
AI
Mar 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GetFavActivitiesFiltered starts from GetAllIncludeFavs(editionId), which already applies an edition filter when editionId is non-default, and then immediately filters a.EditionId == editionId again. This redundancy makes the intent harder to read and risks diverging if repository filtering logic changes. Consider removing the duplicate edition predicate (or, more broadly, pushing the whole filter down into the repository so it runs in the database).
| .Where(a => a.EditionId == editionId | |
| && a.StatusId == activeStatus.Id | |
| .Where(a => a.StatusId == activeStatus.Id |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| using FluentAssertions; | ||
| using Moq; | ||
| using System.Collections.Generic; | ||
| using System.Diagnostics.CodeAnalysis; | ||
| using System.Linq; | ||
| using TaleEngine.API.Contracts.Dtos.Requests; | ||
| using TaleEngine.CQRS.Queries; | ||
| using TaleEngine.Data.Contracts.Entities; | ||
| using TaleEngine.Services.Contracts; | ||
| using Xunit; | ||
|
|
||
| namespace TaleEngine.CQRS.Testing | ||
| { | ||
| [ExcludeFromCodeCoverage] | ||
| public class ActivityQueriesPaginationTests | ||
| { | ||
| [Fact] | ||
| public void ActiveActivitiesFilteredQuery_ShouldApplyPaginationAndCalculateTotalPages() | ||
| { | ||
| // Arrange | ||
| const int editionId = 1; | ||
| const int userId = 10; | ||
|
|
||
| var request = new ActivityFilterRequest | ||
| { | ||
| EditionId = editionId, | ||
| Page = 1, | ||
| Title = string.Empty, | ||
| TimeFrames = new List<int>() | ||
| }; | ||
|
|
||
| var editionServiceMock = new Mock<IEditionService>(); | ||
| var activityServiceMock = new Mock<IActivityService>(); | ||
|
|
||
| var allFilteredActivities = Enumerable.Range(1, 7) | ||
| .Select(i => new ActivityEntity | ||
| { | ||
| Id = i, | ||
| Title = $"Activity {i}", | ||
| EditionId = editionId | ||
| }) | ||
| .ToList(); | ||
|
|
||
| editionServiceMock.Setup(x => x.GetById(editionId)) | ||
| .Returns(new EditionEntity { Id = editionId }); | ||
|
|
||
| activityServiceMock.Setup(x => x.GetActiveActivitiesFiltered( | ||
| request.TypeId, | ||
| editionId, | ||
| request.TimeFrames, | ||
| request.Title, | ||
| userId)) | ||
| .Returns(allFilteredActivities); | ||
|
|
||
| var target = new ActivityQueries(activityServiceMock.Object, editionServiceMock.Object); | ||
|
|
||
| // Act | ||
| var result = target.ActiveActivitiesFilteredQuery(request, userId); | ||
|
|
||
| // Assert | ||
| result.Should().NotBeNull(); | ||
| result.CurrentPage.Should().Be(1); | ||
| result.TotalPages.Should().Be(3); | ||
| result.Activities.Should().NotBeNull(); | ||
| result.Activities.Should().HaveCount(3); | ||
| result.Activities.Select(a => a.Id).Should().Equal(new[] { 4, 5, 6 }); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AddFavouriteActivityloads the full list of activities (withUsersFavincluded) for the edition viaGetAllIncludeFavs(...)and then filters in-memory withFirstOrDefault. This can become expensive as activities/users grow and is unnecessary when you only need a single activity. Prefer a repository method that fetches a single activity by id withUsersFavincluded (or changeGetAllIncludeFavsto return anIQueryableso the filter runs in SQL).