diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor index 1657943..66d3f6f 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor @@ -25,8 +25,8 @@ - + @ResourcesKey.LastAdd diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor.cs index ac79f65..88f9655 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor.cs @@ -14,34 +14,27 @@ public partial class AdvancedGameFilter [Parameter] public EventCallback GameFilterChanged { get; set; } private readonly SelectTheme Theme = SelectTheme.AdvancedFilter; - private readonly List StorageSpaces = [ - new() { MaxSize = 100 }, - new() { MinSize = 100, MaxSize = 1000 }, - new() { MinSize = 1000, MaxSize = 5000 }, - new() { MinSize = 5000, MaxSize = 10000 }, - new() { MinSize = 10000, MaxSize = 20000 }, - new() { MinSize = 20000, MaxSize = 40000 }, - new() { MinSize = 40000, MaxSize = 100000 }, - new() { MinSize = 100000 }, - ]; private async Task HandleValueChanged() { await GameFilterChanged.InvokeAsync(GameFilter); } - private static string GetStorageSpaceLabel(StorageSpaceDto storageSpace) + private string GetStorageSpaceLabel(int storageSpaceId) { + var storageSpace = Categories?.StorageSpaces?.FirstOrDefault(c => c.Id == storageSpaceId) + ?? throw new ArgumentNullException(ResourcesKey.ErrorStorageSpaceLabel); + if (storageSpace.MinSize == null && storageSpace.MaxSize != null) { return string.Format(ResourcesKey.MinStorageSpaceFormat, - GameHelper.GetFormatedStorageSpace(storageSpace.MinSize)); + GameHelper.GetFormatedStorageSpace(storageSpace.MaxSize)); } if (storageSpace.MinSize != null && storageSpace.MaxSize == null) { return string.Format(ResourcesKey.MaxStorageSpaceFormat, - GameHelper.GetFormatedStorageSpace(storageSpace.MaxSize)); + GameHelper.GetFormatedStorageSpace(storageSpace.MinSize)); } if (storageSpace.MinSize != null && storageSpace.MaxSize != null) diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilterParams.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilterParams.cs index d756ebf..e2ae78a 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilterParams.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilterParams.cs @@ -12,8 +12,8 @@ public class GameFilterParams public List? Tags { get; set; } public List? Publishers { get; set; } public List? Developers { get; set; } - public int? MinInterest { get; set; } - public int? MaxInterest { get; set; } + public int MinInterest { get; set; } = 1; + public int MaxInterest { get; set; } = 5; public List? ReleaseYears { get; set; } - public List? StorageSpaces { get; set; } + public List? StorageSpaceIds { get; set; } } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Gateways/GameGateway.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Gateways/GameGateway.cs index e2823fb..21148a3 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Gateways/GameGateway.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Gateways/GameGateway.cs @@ -45,7 +45,7 @@ public class GameGateway(IHttpClientService httpClientService) : IGameGateway Title = filterParams.Title, MaxInterest = filterParams.MaxInterest, MinInterest = filterParams.MinInterest, - StorageSpaces = filterParams.StorageSpaces, + StorageSpaces = filterParams.StorageSpaceIds, DeveloperIds = filterParams.Developers?.Select(d => d.Id ?? 0).ToList(), PublisherIds = filterParams.Publishers?.Select(d => d.Id ?? 0).ToList(), PlatformIds = filterParams.Platforms?.Select(d => d.Id ?? 0).ToList(), diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SliderRange/SliderRange.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SliderRange/SliderRange.razor.cs index 7279766..2fee237 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SliderRange/SliderRange.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SliderRange/SliderRange.razor.cs @@ -6,10 +6,10 @@ namespace GameIdeas.BlazorApp.Shared.Components.SliderRange; public partial class SliderRange { [Parameter] public SliderRangeParams Params { get; set; } = new(); - [Parameter] public int? Max { get; set; } - [Parameter] public EventCallback MaxChanged { get; set; } - [Parameter] public int? Min { get; set; } - [Parameter] public EventCallback MinChanged { get; set; } + [Parameter] public int Max { get; set; } + [Parameter] public EventCallback MaxChanged { get; set; } + [Parameter] public int Min { get; set; } + [Parameter] public EventCallback MinChanged { get; set; } private async Task HandleSlideTwoInput() { @@ -33,12 +33,12 @@ public partial class SliderRange private string FillColor() { - var percent1 = (double)(Min! - Params.Min) / (Params.Max - Params.Min) * 100; - var percent2 = (double)(Max! - Params.Min) / (Params.Max - Params.Min) * 100; + var percent1 = (double)(Min - Params.Min) / (Params.Max - Params.Min) * 100; + var percent2 = (double)(Max - Params.Min) / (Params.Max - Params.Min) * 100; return $"background: linear-gradient(to right, var(--line) {percent1}% , var(--violet) {percent1}% , var(--violet) {percent2}%, var(--line) {percent2}%)"; } - private string StatusColor(int? value) + private string StatusColor(int value) { string str = "--thumb-color: var({0});"; diff --git a/src/GameIdeas/GameIdeas.Shared/Dto/CategoriesDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/CategoriesDto.cs index 0136301..54d6ada 100644 --- a/src/GameIdeas/GameIdeas.Shared/Dto/CategoriesDto.cs +++ b/src/GameIdeas/GameIdeas.Shared/Dto/CategoriesDto.cs @@ -8,4 +8,5 @@ public class CategoriesDto public List? Developers { get; set; } public List? Publishers { get; set; } public List? ReleaseYears { get; set; } + public List? StorageSpaces { get; set; } } diff --git a/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs index ef6f3fe..6af6be0 100644 --- a/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs +++ b/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs @@ -16,5 +16,5 @@ public class GameFilterDto public int? MinInterest { get; set; } public int? MaxInterest { get; set; } public List? ReleaseYears { get; set; } - public List? StorageSpaces { get; set; } + public List? StorageSpaces { get; set; } } diff --git a/src/GameIdeas/GameIdeas.Shared/Dto/StorageSpaceDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/StorageSpaceDto.cs index 1e0f96c..cb80975 100644 --- a/src/GameIdeas/GameIdeas.Shared/Dto/StorageSpaceDto.cs +++ b/src/GameIdeas/GameIdeas.Shared/Dto/StorageSpaceDto.cs @@ -4,4 +4,5 @@ public class StorageSpaceDto { public int? MinSize { get; set; } public int? MaxSize { get; set; } + public int Id { get; set; } } \ No newline at end of file diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/CategoryController.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/CategoryController.cs index b1a30ab..83da736 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/CategoryController.cs +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/CategoryController.cs @@ -1,5 +1,5 @@ using GameIdeas.Shared.Dto; -using GameIdeas.WebAPI.Services.Interfaces; +using GameIdeas.WebAPI.Services.Categories; using Microsoft.AspNetCore.Mvc; namespace GameIdeas.WebAPI.Controllers; diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Program.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Program.cs index 6cfe582..6357156 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Program.cs +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Program.cs @@ -1,11 +1,8 @@ using GameIdeas.Resources; using GameIdeas.WebAPI.Context; -using GameIdeas.WebAPI.Profiles; using GameIdeas.WebAPI.Services.Categories; using GameIdeas.WebAPI.Services.Games; -using GameIdeas.WebAPI.Services.Interfaces; using Microsoft.EntityFrameworkCore; -using System.Text.Json.Serialization; var builder = WebApplication.CreateBuilder(args); var services = builder.Services; diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Categories/CategoryService.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Categories/CategoryService.cs index 11562ac..80ddcc8 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Categories/CategoryService.cs +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Categories/CategoryService.cs @@ -1,13 +1,23 @@ using AutoMapper; using GameIdeas.Shared.Dto; using GameIdeas.WebAPI.Context; -using GameIdeas.WebAPI.Services.Interfaces; using Microsoft.EntityFrameworkCore; namespace GameIdeas.WebAPI.Services.Categories; public class CategoryService(GameIdeasContext context, IMapper mapper) : ICategoryService { + public List GetStorageSpaces() => [ + new() { Id = 1, MaxSize = 100 }, + new() { Id = 2, MinSize = 100, MaxSize = 1000 }, + new() { Id = 3, MinSize = 1000, MaxSize = 5000 }, + new() { Id = 4, MinSize = 5000, MaxSize = 10000 }, + new() { Id = 5, MinSize = 10000, MaxSize = 20000 }, + new() { Id = 6, MinSize = 20000, MaxSize = 40000 }, + new() { Id = 7, MinSize = 40000, MaxSize = 100000 }, + new() { Id = 8, MinSize = 100000 }, + ]; + public async Task GetCategories() { var platforms = await context.Platforms.ToListAsync(); @@ -26,7 +36,8 @@ public class CategoryService(GameIdeasContext context, IMapper mapper) : ICatego Tags = mapper.Map>(tags), Developers = mapper.Map>(developers), Publishers = mapper.Map>(publishers), - ReleaseYears = mapper.Map>(releaseYears) + ReleaseYears = mapper.Map>(releaseYears), + StorageSpaces = GetStorageSpaces() }; } } diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Categories/ICategoryService.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Categories/ICategoryService.cs index 1559cac..9d6c495 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Categories/ICategoryService.cs +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Categories/ICategoryService.cs @@ -1,8 +1,9 @@ using GameIdeas.Shared.Dto; -namespace GameIdeas.WebAPI.Services.Interfaces; +namespace GameIdeas.WebAPI.Services.Categories; public interface ICategoryService { + List GetStorageSpaces(); Task GetCategories(); } diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Games/GameReadService.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Games/GameReadService.cs index def9582..90a6dbf 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Games/GameReadService.cs +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Games/GameReadService.cs @@ -4,13 +4,13 @@ using GameIdeas.Shared.Dto; using GameIdeas.Shared.Exceptions; using GameIdeas.Shared.Model; using GameIdeas.WebAPI.Context; +using GameIdeas.WebAPI.Services.Categories; using Microsoft.EntityFrameworkCore; -using System.Linq; using System.Linq.Expressions; namespace GameIdeas.WebAPI.Services.Games; -public class GameReadService(GameIdeasContext context, IMapper mapper) : IGameReadService +public class GameReadService(GameIdeasContext context, IMapper mapper, ICategoryService categoryService) : IGameReadService { public async Task> GetGames(GameFilterDto filter) { @@ -30,10 +30,7 @@ public class GameReadService(GameIdeasContext context, IMapper mapper) : IGameRe .Take(GlobalConstants.NUMBER_PER_PAGE) .ToListAsync(); - if (!string.IsNullOrWhiteSpace(filter.Title)) - { - games = [.. ApplySearchGameFilter(games, filter)]; - } + ApplyStaticFilter(ref games, filter); return mapper.Map>(games); } @@ -75,7 +72,7 @@ public class GameReadService(GameIdeasContext context, IMapper mapper) : IGameRe } } - private static void ApplyFilter(ref IQueryable query, GameFilterDto filter) + private void ApplyFilter(ref IQueryable query, GameFilterDto filter) { if (filter.PlatformIds != null) { @@ -117,12 +114,6 @@ public class GameReadService(GameIdeasContext context, IMapper mapper) : IGameRe query = query.Where(game => game.Interest <= filter.MaxInterest); } - if (filter.StorageSpaces != null) - { - query = query.Where(game => filter.StorageSpaces.Where(stor => - stor.MinSize <= game.StorageSpace && stor.MaxSize > game.StorageSpace).Count() != 0); - } - if (filter.ReleaseYears != null) { query = query.Where(game => game.ReleaseDate != null && @@ -130,22 +121,36 @@ public class GameReadService(GameIdeasContext context, IMapper mapper) : IGameRe } } - private static IEnumerable ApplySearchGameFilter(IEnumerable query, GameFilterDto filter) + private void ApplyStaticFilter(ref List games, GameFilterDto filter) { - var keywords = filter.Title? + if (!string.IsNullOrWhiteSpace(filter.Title)) + { + var keywords = filter.Title? .Split([' '], StringSplitOptions.RemoveEmptyEntries) .Select(k => k.Trim()) .ToArray() ?? []; - query = query - .Where(game => keywords.All( - kw => game.Title.Contains(kw, StringComparison.OrdinalIgnoreCase) - )) - .OrderBy(game => keywords.Min(kw => - game.Title.IndexOf(kw, StringComparison.OrdinalIgnoreCase) - )) - .ThenBy(game => game.Title.Length); + games = games + .Where(game => keywords.All( + kw => game.Title.Contains(kw, StringComparison.OrdinalIgnoreCase) + )) + .OrderBy(game => keywords.Min(kw => + game.Title.IndexOf(kw, StringComparison.OrdinalIgnoreCase) + )) + .ThenBy(game => game.Title.Length) + .ToList(); - return query; + return; + } + + if (filter.StorageSpaces != null) + { + var storageSpaces = categoryService.GetStorageSpaces().Where(stor => filter.StorageSpaces.Contains(stor.Id)); + + games = games + .Where(game => storageSpaces.Any(stor => + (stor.MinSize ?? int.MinValue) <= game.StorageSpace && (stor.MaxSize ?? int.MaxValue) > game.StorageSpace)) + .ToList(); + } } }