feature/apply-filter #18
@@ -25,8 +25,8 @@
|
|||||||
<SelectSearch TItem="int" Placeholder="@ResourcesKey.ReleaseDate" GetLabel="@(p => p.ToString())"
|
<SelectSearch TItem="int" Placeholder="@ResourcesKey.ReleaseDate" GetLabel="@(p => p.ToString())"
|
||||||
@bind-Values=GameFilter.ReleaseYears @bind-Values:after=HandleValueChanged Theme="Theme" Items="Categories?.ReleaseYears" />
|
@bind-Values=GameFilter.ReleaseYears @bind-Values:after=HandleValueChanged Theme="Theme" Items="Categories?.ReleaseYears" />
|
||||||
|
|
||||||
<SelectSearch TItem="StorageSpaceDto" Placeholder="@ResourcesKey.StorageSize" GetLabel="@GetStorageSpaceLabel"
|
<SelectSearch TItem="int" Placeholder="@ResourcesKey.StorageSize" GetLabel="@GetStorageSpaceLabel"
|
||||||
@bind-Values=GameFilter.StorageSpaces @bind-Values:after=HandleValueChanged Theme="Theme" Items="StorageSpaces" />
|
@bind-Values=GameFilter.StorageSpaceIds @bind-Values:after=HandleValueChanged Theme="Theme" Items="@(Categories?.StorageSpaces?.Select(stor => stor.Id).ToList())" />
|
||||||
|
|
||||||
<span class="title">@ResourcesKey.LastAdd</span>
|
<span class="title">@ResourcesKey.LastAdd</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,34 +14,27 @@ public partial class AdvancedGameFilter
|
|||||||
[Parameter] public EventCallback<GameFilterParams> GameFilterChanged { get; set; }
|
[Parameter] public EventCallback<GameFilterParams> GameFilterChanged { get; set; }
|
||||||
|
|
||||||
private readonly SelectTheme Theme = SelectTheme.AdvancedFilter;
|
private readonly SelectTheme Theme = SelectTheme.AdvancedFilter;
|
||||||
private readonly List<StorageSpaceDto> 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()
|
private async Task HandleValueChanged()
|
||||||
{
|
{
|
||||||
await GameFilterChanged.InvokeAsync(GameFilter);
|
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)
|
if (storageSpace.MinSize == null && storageSpace.MaxSize != null)
|
||||||
{
|
{
|
||||||
return string.Format(ResourcesKey.MinStorageSpaceFormat,
|
return string.Format(ResourcesKey.MinStorageSpaceFormat,
|
||||||
GameHelper.GetFormatedStorageSpace(storageSpace.MinSize));
|
GameHelper.GetFormatedStorageSpace(storageSpace.MaxSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (storageSpace.MinSize != null && storageSpace.MaxSize == null)
|
if (storageSpace.MinSize != null && storageSpace.MaxSize == null)
|
||||||
{
|
{
|
||||||
return string.Format(ResourcesKey.MaxStorageSpaceFormat,
|
return string.Format(ResourcesKey.MaxStorageSpaceFormat,
|
||||||
GameHelper.GetFormatedStorageSpace(storageSpace.MaxSize));
|
GameHelper.GetFormatedStorageSpace(storageSpace.MinSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (storageSpace.MinSize != null && storageSpace.MaxSize != null)
|
if (storageSpace.MinSize != null && storageSpace.MaxSize != null)
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ public class GameFilterParams
|
|||||||
public List<TagDto>? Tags { get; set; }
|
public List<TagDto>? Tags { get; set; }
|
||||||
public List<PublisherDto>? Publishers { get; set; }
|
public List<PublisherDto>? Publishers { get; set; }
|
||||||
public List<DeveloperDto>? Developers { get; set; }
|
public List<DeveloperDto>? Developers { get; set; }
|
||||||
public int? MinInterest { get; set; }
|
public int MinInterest { get; set; } = 1;
|
||||||
public int? MaxInterest { get; set; }
|
public int MaxInterest { get; set; } = 5;
|
||||||
public List<int>? ReleaseYears { get; set; }
|
public List<int>? ReleaseYears { get; set; }
|
||||||
public List<StorageSpaceDto>? StorageSpaces { get; set; }
|
public List<int>? StorageSpaceIds { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class GameGateway(IHttpClientService httpClientService) : IGameGateway
|
|||||||
Title = filterParams.Title,
|
Title = filterParams.Title,
|
||||||
MaxInterest = filterParams.MaxInterest,
|
MaxInterest = filterParams.MaxInterest,
|
||||||
MinInterest = filterParams.MinInterest,
|
MinInterest = filterParams.MinInterest,
|
||||||
StorageSpaces = filterParams.StorageSpaces,
|
StorageSpaces = filterParams.StorageSpaceIds,
|
||||||
DeveloperIds = filterParams.Developers?.Select(d => d.Id ?? 0).ToList(),
|
DeveloperIds = filterParams.Developers?.Select(d => d.Id ?? 0).ToList(),
|
||||||
PublisherIds = filterParams.Publishers?.Select(d => d.Id ?? 0).ToList(),
|
PublisherIds = filterParams.Publishers?.Select(d => d.Id ?? 0).ToList(),
|
||||||
PlatformIds = filterParams.Platforms?.Select(d => d.Id ?? 0).ToList(),
|
PlatformIds = filterParams.Platforms?.Select(d => d.Id ?? 0).ToList(),
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ namespace GameIdeas.BlazorApp.Shared.Components.SliderRange;
|
|||||||
public partial class SliderRange
|
public partial class SliderRange
|
||||||
{
|
{
|
||||||
[Parameter] public SliderRangeParams Params { get; set; } = new();
|
[Parameter] public SliderRangeParams Params { get; set; } = new();
|
||||||
[Parameter] public int? Max { get; set; }
|
[Parameter] public int Max { get; set; }
|
||||||
[Parameter] public EventCallback<int?> MaxChanged { get; set; }
|
[Parameter] public EventCallback<int> MaxChanged { get; set; }
|
||||||
[Parameter] public int? Min { get; set; }
|
[Parameter] public int Min { get; set; }
|
||||||
[Parameter] public EventCallback<int?> MinChanged { get; set; }
|
[Parameter] public EventCallback<int> MinChanged { get; set; }
|
||||||
|
|
||||||
private async Task HandleSlideTwoInput()
|
private async Task HandleSlideTwoInput()
|
||||||
{
|
{
|
||||||
@@ -33,12 +33,12 @@ public partial class SliderRange
|
|||||||
|
|
||||||
private string FillColor()
|
private string FillColor()
|
||||||
{
|
{
|
||||||
var percent1 = (double)(Min! - 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;
|
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}%)";
|
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});";
|
string str = "--thumb-color: var({0});";
|
||||||
|
|
||||||
|
|||||||
@@ -8,4 +8,5 @@ public class CategoriesDto
|
|||||||
public List<DeveloperDto>? Developers { get; set; }
|
public List<DeveloperDto>? Developers { get; set; }
|
||||||
public List<PublisherDto>? Publishers { get; set; }
|
public List<PublisherDto>? Publishers { get; set; }
|
||||||
public List<int>? ReleaseYears { get; set; }
|
public List<int>? ReleaseYears { get; set; }
|
||||||
|
public List<StorageSpaceDto>? StorageSpaces { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,5 +16,5 @@ public class GameFilterDto
|
|||||||
public int? MinInterest { get; set; }
|
public int? MinInterest { get; set; }
|
||||||
public int? MaxInterest { get; set; }
|
public int? MaxInterest { get; set; }
|
||||||
public List<int>? ReleaseYears { get; set; }
|
public List<int>? ReleaseYears { get; set; }
|
||||||
public List<StorageSpaceDto>? StorageSpaces { get; set; }
|
public List<int>? StorageSpaces { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ public class StorageSpaceDto
|
|||||||
{
|
{
|
||||||
public int? MinSize { get; set; }
|
public int? MinSize { get; set; }
|
||||||
public int? MaxSize { get; set; }
|
public int? MaxSize { get; set; }
|
||||||
|
public int Id { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
using GameIdeas.Shared.Dto;
|
using GameIdeas.Shared.Dto;
|
||||||
using GameIdeas.WebAPI.Services.Interfaces;
|
using GameIdeas.WebAPI.Services.Categories;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace GameIdeas.WebAPI.Controllers;
|
namespace GameIdeas.WebAPI.Controllers;
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
using GameIdeas.Resources;
|
using GameIdeas.Resources;
|
||||||
using GameIdeas.WebAPI.Context;
|
using GameIdeas.WebAPI.Context;
|
||||||
using GameIdeas.WebAPI.Profiles;
|
|
||||||
using GameIdeas.WebAPI.Services.Categories;
|
using GameIdeas.WebAPI.Services.Categories;
|
||||||
using GameIdeas.WebAPI.Services.Games;
|
using GameIdeas.WebAPI.Services.Games;
|
||||||
using GameIdeas.WebAPI.Services.Interfaces;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
var services = builder.Services;
|
var services = builder.Services;
|
||||||
|
|||||||
@@ -1,13 +1,23 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using GameIdeas.Shared.Dto;
|
using GameIdeas.Shared.Dto;
|
||||||
using GameIdeas.WebAPI.Context;
|
using GameIdeas.WebAPI.Context;
|
||||||
using GameIdeas.WebAPI.Services.Interfaces;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace GameIdeas.WebAPI.Services.Categories;
|
namespace GameIdeas.WebAPI.Services.Categories;
|
||||||
|
|
||||||
public class CategoryService(GameIdeasContext context, IMapper mapper) : ICategoryService
|
public class CategoryService(GameIdeasContext context, IMapper mapper) : ICategoryService
|
||||||
{
|
{
|
||||||
|
public List<StorageSpaceDto> 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<CategoriesDto> GetCategories()
|
public async Task<CategoriesDto> GetCategories()
|
||||||
{
|
{
|
||||||
var platforms = await context.Platforms.ToListAsync();
|
var platforms = await context.Platforms.ToListAsync();
|
||||||
@@ -26,7 +36,8 @@ public class CategoryService(GameIdeasContext context, IMapper mapper) : ICatego
|
|||||||
Tags = mapper.Map<List<TagDto>>(tags),
|
Tags = mapper.Map<List<TagDto>>(tags),
|
||||||
Developers = mapper.Map<List<DeveloperDto>>(developers),
|
Developers = mapper.Map<List<DeveloperDto>>(developers),
|
||||||
Publishers = mapper.Map<List<PublisherDto>>(publishers),
|
Publishers = mapper.Map<List<PublisherDto>>(publishers),
|
||||||
ReleaseYears = mapper.Map<List<int>>(releaseYears)
|
ReleaseYears = mapper.Map<List<int>>(releaseYears),
|
||||||
|
StorageSpaces = GetStorageSpaces()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
using GameIdeas.Shared.Dto;
|
using GameIdeas.Shared.Dto;
|
||||||
|
|
||||||
namespace GameIdeas.WebAPI.Services.Interfaces;
|
namespace GameIdeas.WebAPI.Services.Categories;
|
||||||
|
|
||||||
public interface ICategoryService
|
public interface ICategoryService
|
||||||
{
|
{
|
||||||
|
List<StorageSpaceDto> GetStorageSpaces();
|
||||||
Task<CategoriesDto> GetCategories();
|
Task<CategoriesDto> GetCategories();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ using GameIdeas.Shared.Dto;
|
|||||||
using GameIdeas.Shared.Exceptions;
|
using GameIdeas.Shared.Exceptions;
|
||||||
using GameIdeas.Shared.Model;
|
using GameIdeas.Shared.Model;
|
||||||
using GameIdeas.WebAPI.Context;
|
using GameIdeas.WebAPI.Context;
|
||||||
|
using GameIdeas.WebAPI.Services.Categories;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
namespace GameIdeas.WebAPI.Services.Games;
|
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<IEnumerable<GameDto>> GetGames(GameFilterDto filter)
|
public async Task<IEnumerable<GameDto>> GetGames(GameFilterDto filter)
|
||||||
{
|
{
|
||||||
@@ -30,10 +30,7 @@ public class GameReadService(GameIdeasContext context, IMapper mapper) : IGameRe
|
|||||||
.Take(GlobalConstants.NUMBER_PER_PAGE)
|
.Take(GlobalConstants.NUMBER_PER_PAGE)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(filter.Title))
|
ApplyStaticFilter(ref games, filter);
|
||||||
{
|
|
||||||
games = [.. ApplySearchGameFilter(games, filter)];
|
|
||||||
}
|
|
||||||
|
|
||||||
return mapper.Map<IEnumerable<GameDto>>(games);
|
return mapper.Map<IEnumerable<GameDto>>(games);
|
||||||
}
|
}
|
||||||
@@ -75,7 +72,7 @@ public class GameReadService(GameIdeasContext context, IMapper mapper) : IGameRe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ApplyFilter(ref IQueryable<Game> query, GameFilterDto filter)
|
private void ApplyFilter(ref IQueryable<Game> query, GameFilterDto filter)
|
||||||
{
|
{
|
||||||
if (filter.PlatformIds != null)
|
if (filter.PlatformIds != null)
|
||||||
{
|
{
|
||||||
@@ -117,12 +114,6 @@ public class GameReadService(GameIdeasContext context, IMapper mapper) : IGameRe
|
|||||||
query = query.Where(game => game.Interest <= filter.MaxInterest);
|
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)
|
if (filter.ReleaseYears != null)
|
||||||
{
|
{
|
||||||
query = query.Where(game => game.ReleaseDate != null &&
|
query = query.Where(game => game.ReleaseDate != null &&
|
||||||
@@ -130,22 +121,36 @@ public class GameReadService(GameIdeasContext context, IMapper mapper) : IGameRe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<Game> ApplySearchGameFilter(IEnumerable<Game> query, GameFilterDto filter)
|
private void ApplyStaticFilter(ref List<Game> games, GameFilterDto filter)
|
||||||
{
|
{
|
||||||
var keywords = filter.Title?
|
if (!string.IsNullOrWhiteSpace(filter.Title))
|
||||||
|
{
|
||||||
|
var keywords = filter.Title?
|
||||||
.Split([' '], StringSplitOptions.RemoveEmptyEntries)
|
.Split([' '], StringSplitOptions.RemoveEmptyEntries)
|
||||||
.Select(k => k.Trim())
|
.Select(k => k.Trim())
|
||||||
.ToArray() ?? [];
|
.ToArray() ?? [];
|
||||||
|
|
||||||
query = query
|
games = games
|
||||||
.Where(game => keywords.All(
|
.Where(game => keywords.All(
|
||||||
kw => game.Title.Contains(kw, StringComparison.OrdinalIgnoreCase)
|
kw => game.Title.Contains(kw, StringComparison.OrdinalIgnoreCase)
|
||||||
))
|
))
|
||||||
.OrderBy(game => keywords.Min(kw =>
|
.OrderBy(game => keywords.Min(kw =>
|
||||||
game.Title.IndexOf(kw, StringComparison.OrdinalIgnoreCase)
|
game.Title.IndexOf(kw, StringComparison.OrdinalIgnoreCase)
|
||||||
))
|
))
|
||||||
.ThenBy(game => game.Title.Length);
|
.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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user