diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Helpers/GameHelper.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Helpers/GameHelper.cs index 8f830c2..9673b84 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Helpers/GameHelper.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Helpers/GameHelper.cs @@ -4,7 +4,7 @@ namespace GameIdeas.BlazorApp.Helpers; public static class GameHelper { - public static void WriteTrackingDto(GameDto game) + public static void WriteTrackingDto(GameDetailDto game) { game.CreationUserId = 100000; game.CreationDate = DateTime.Now; @@ -22,4 +22,19 @@ public static class GameHelper _ => "--yellow", }; } + + public static string GetFormatedStorageSpace(double? storageValue) + { + if (storageValue == null) + { + return string.Empty; + } + + return storageValue switch + { + >= 1000000 => $"{storageValue / 1000000:f1} To", + >= 1000 => $"{storageValue / 1000:f1} Go", + _ => $"{storageValue:f1} Mo" + }; + } } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Helpers/UrlHelper.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Helpers/UrlHelper.cs new file mode 100644 index 0000000..2ffd849 --- /dev/null +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Helpers/UrlHelper.cs @@ -0,0 +1,38 @@ +using System.Collections; + +namespace GameIdeas.BlazorApp.Helpers; + +public static class UrlHelper +{ + public static string BuildUrlParams(object? model) + { + if (model == null) + return string.Empty; + + var properties = model.GetType().GetProperties(); + var queryParams = properties + .Select(p => + { + var value = p.GetValue(model); + + switch (value) + { + case null: + return null; + case DateTime dateTime: + return $"{p.Name}={Uri.EscapeDataString(dateTime.ToString("yyyy-MM-dd HH:mm:ss"))}"; + } + + if (value is IEnumerable enumerable and not string) + { + var items = enumerable.Cast() + .Select(item => $"{p.Name}={Uri.EscapeDataString(item?.ToString() ?? string.Empty)}"); + return string.Join("&", items); + } + + return $"{p.Name}={Uri.EscapeDataString(value.ToString() ?? string.Empty)}"; + }) + .ToArray(); + return string.Join("&", queryParams.Where(p => p != null)); + } +} diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameBase.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameBase.cs index efc56cf..14e4339 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameBase.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameBase.cs @@ -12,19 +12,4 @@ public class GameBase : ComponentBase { NavigationManager.NavigateTo($"/Games/Detail/{GameDto.Id}"); } - - protected string GetFormatedStorageSpace() - { - if (GameDto.StorageSpace == null) - { - return string.Empty; - } - - return GameDto.StorageSpace switch - { - >= 1000000 => $"{GameDto.StorageSpace / 1000000:f1} To", - >= 1000 => $"{GameDto.StorageSpace / 1000:f1} Go", - _ => $"{GameDto.StorageSpace:f1} Mo" - }; - } } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameCreationForm.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameCreationForm.razor.cs index 358d442..895fb72 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameCreationForm.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameCreationForm.razor.cs @@ -18,7 +18,7 @@ public partial class GameCreationForm [Parameter] public CategoriesDto? Categories { get; set; } [Parameter] public EventCallback OnSubmit { get; set; } - private GameDto GameDto = new(); + private GameDetailDto GameDto = new(); private EditContext? EditContext; private readonly SelectTheme Theme = SelectTheme.Creation; private readonly SliderParams SliderParams = new() { Gap = 1, Min = 1, Max = 5 }; diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameRow.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameRow.razor index a2309f2..b31104c 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameRow.razor +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameRow.razor @@ -28,7 +28,7 @@ } - @GetFormatedStorageSpace() + @GameHelper.GetFormatedStorageSpace(GameDto.StorageSpace)
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameValidation.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameValidation.cs index 12eff58..34de4ed 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameValidation.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameValidation.cs @@ -4,7 +4,7 @@ using GameIdeas.Shared.Dto; namespace GameIdeas.BlazorApp.Pages.Games.Components; -public class GameValidation : AbstractValidator +public class GameValidation : AbstractValidator { public GameValidation() { 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 460ecf6..66d3f6f 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor @@ -22,5 +22,11 @@ + + + + @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 9447fe8..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 @@ -1,4 +1,7 @@ +using GameIdeas.BlazorApp.Helpers; +using GameIdeas.BlazorApp.Pages.Games.Header; using GameIdeas.BlazorApp.Shared.Components.Select.Models; +using GameIdeas.Resources; using GameIdeas.Shared.Dto; using Microsoft.AspNetCore.Components; @@ -6,9 +9,9 @@ namespace GameIdeas.BlazorApp.Pages.Games.Filter; public partial class AdvancedGameFilter { - [Parameter] public GameFilterDto GameFilter { get; set; } = new(); + [Parameter] public GameFilterParams GameFilter { get; set; } = new(); [Parameter] public CategoriesDto? Categories { get; set; } - [Parameter] public EventCallback GameFilterChanged { get; set; } + [Parameter] public EventCallback GameFilterChanged { get; set; } private readonly SelectTheme Theme = SelectTheme.AdvancedFilter; @@ -16,4 +19,31 @@ public partial class AdvancedGameFilter { await GameFilterChanged.InvokeAsync(GameFilter); } + + 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.MaxSize)); + } + + if (storageSpace.MinSize != null && storageSpace.MaxSize == null) + { + return string.Format(ResourcesKey.MaxStorageSpaceFormat, + GameHelper.GetFormatedStorageSpace(storageSpace.MinSize)); + } + + if (storageSpace.MinSize != null && storageSpace.MaxSize != null) + { + return string.Format(ResourcesKey.MinMaxStorageSpaceFormat, + GameHelper.GetFormatedStorageSpace(storageSpace.MinSize), + GameHelper.GetFormatedStorageSpace(storageSpace.MaxSize)); + } + + throw new ArgumentNullException(ResourcesKey.ErrorStorageSpaceLabel); + } } \ No newline at end of file diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor index 0f2b88a..d128e8f 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor @@ -7,8 +7,8 @@ @using GameIdeas.Shared.Dto
-
@@ -25,5 +25,4 @@ @GetSearchIcon()
- - + \ No newline at end of file diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor.cs index fd0f42e..f6521df 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor.cs @@ -1,5 +1,4 @@ using GameIdeas.BlazorApp.Shared.Constants; -using GameIdeas.Shared.Constants; using Microsoft.AspNetCore.Components; namespace GameIdeas.BlazorApp.Shared.Components.Search; @@ -15,21 +14,31 @@ public partial class SearchInput [Parameter] public EventCallback FocusIn { get; set; } [Parameter] public SearchInputIcon Icon { get; set; } - private ElementReference InputText; + private System.Timers.Timer? Timer; protected override void OnInitialized() { Text = string.Empty; + Timer = new() + { + Interval = 500, + AutoReset = false, + }; + + Timer.Elapsed += async (_, _) => await TextChanged.InvokeAsync(Text); + + base.OnInitialized(); } public void SetText(string str) { Text = str; } - - private async Task HandleTextChanged() + + private void HandleTextChanged() { - await TextChanged.InvokeAsync(Text); + Timer?.Stop(); + Timer?.Start(); } private async Task HandleClearClicked() diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Models/SelectParams.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Models/SelectParams.cs index 2fea69c..24b788a 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Models/SelectParams.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Models/SelectParams.cs @@ -3,10 +3,8 @@ public class SelectParams { public List Items { get; set; } = []; - public List DefaultItems { get; set; } = []; public Func GetItemLabel { get; set; } = _ => string.Empty; public List Headers { get; set; } = []; - public List DefaultHeaders { get; set; } = []; public Func GetHeaderLabel { get; set; } = _ => string.Empty; public Func? AddItem { get; set; } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Select.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Select.razor.cs index a494c97..dc6f86f 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Select.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Select.razor.cs @@ -37,16 +37,6 @@ public partial class Select protected override void OnInitialized() { QuickAddEditContext = new EditContext(AddLabel); - - if (Params.DefaultItems.Count != 0) - { - Values.AddRange(Params.DefaultItems); - } - - if (Params.DefaultHeaders.Count != 0) - { - HeaderValues.AddRange(Params.DefaultHeaders); - } } private void HandleButtonClicked() diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Constants/Endpoints.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Constants/Endpoints.cs index 3e6289d..0665ffa 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Constants/Endpoints.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Constants/Endpoints.cs @@ -1,4 +1,5 @@ -using GameIdeas.Shared.Dto; +using GameIdeas.BlazorApp.Helpers; +using GameIdeas.Shared.Dto; namespace GameIdeas.BlazorApp.Shared.Constants; @@ -7,8 +8,7 @@ public static class Endpoints public static class Game { public static readonly string Create = "api/Game/Create"; - public static string Fetch(PaggingDto pagging) => - $"api/Game?{nameof(pagging.CurrentPage)}={pagging.CurrentPage}&{nameof(pagging.NumberPerPage)}={pagging.NumberPerPage}"; + public static string Fetch(GameFilterDto filter) => $"api/Game?{UrlHelper.BuildUrlParams(filter)}"; } public static class Category diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/wwwroot/index.html b/src/GameIdeas/Client/GameIdeas.BlazorApp/wwwroot/index.html index bc8684e..4400e66 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/wwwroot/index.html +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/wwwroot/index.html @@ -27,7 +27,6 @@ - diff --git a/src/GameIdeas/GameIdeas.Resources/CreateStaticResourceKey.cs b/src/GameIdeas/GameIdeas.Resources/CreateStaticResourceKey.cs index 6cc5cc8..288e791 100644 --- a/src/GameIdeas/GameIdeas.Resources/CreateStaticResourceKey.cs +++ b/src/GameIdeas/GameIdeas.Resources/CreateStaticResourceKey.cs @@ -22,6 +22,8 @@ public class Translations (TranslationService translationService) public string StorageSizeMo => translationService.Translate(nameof(StorageSizeMo)); public string LastModification => translationService.Translate(nameof(LastModification)); public string ReleaseDate => translationService.Translate(nameof(ReleaseDate)); + public string CreateDate => translationService.Translate(nameof(CreateDate)); + public string UpdateDate => translationService.Translate(nameof(UpdateDate)); public string Title => translationService.Translate(nameof(Title)); public string Interest => translationService.Translate(nameof(Interest)); public string Properties => translationService.Translate(nameof(Properties)); @@ -40,6 +42,12 @@ public class Translations (TranslationService translationService) public string InvalidInterest => translationService.Translate(nameof(InvalidInterest)); public string Unknown => translationService.Translate(nameof(Unknown)); public string ErrorFetchGames => translationService.Translate(nameof(ErrorFetchGames)); + public string Ascending => translationService.Translate(nameof(Ascending)); + public string Descending => translationService.Translate(nameof(Descending)); + public string ErrorStorageSpaceLabel => translationService.Translate(nameof(ErrorStorageSpaceLabel)); + public string MinStorageSpaceFormat => translationService.Translate(nameof(MinStorageSpaceFormat)); + public string MaxStorageSpaceFormat => translationService.Translate(nameof(MaxStorageSpaceFormat)); + public string MinMaxStorageSpaceFormat => translationService.Translate(nameof(MinMaxStorageSpaceFormat)); } public static class ResourcesKey @@ -70,6 +78,8 @@ public static class ResourcesKey public static string StorageSizeMo => _instance?.StorageSizeMo ?? throw new InvalidOperationException("ResourcesKey.StorageSizeMo is not initialized."); public static string LastModification => _instance?.LastModification ?? throw new InvalidOperationException("ResourcesKey.LastModification is not initialized."); public static string ReleaseDate => _instance?.ReleaseDate ?? throw new InvalidOperationException("ResourcesKey.ReleaseDate is not initialized."); + public static string CreateDate => _instance?.CreateDate ?? throw new InvalidOperationException("ResourcesKey.CreateDate is not initialized."); + public static string UpdateDate => _instance?.UpdateDate ?? throw new InvalidOperationException("ResourcesKey.UpdateDate is not initialized."); public static string Title => _instance?.Title ?? throw new InvalidOperationException("ResourcesKey.Title is not initialized."); public static string Interest => _instance?.Interest ?? throw new InvalidOperationException("ResourcesKey.Interest is not initialized."); public static string Properties => _instance?.Properties ?? throw new InvalidOperationException("ResourcesKey.Properties is not initialized."); @@ -88,4 +98,10 @@ public static class ResourcesKey public static string InvalidInterest => _instance?.InvalidInterest ?? throw new InvalidOperationException("ResourcesKey.InvalidInterest is not initialized."); public static string Unknown => _instance?.Unknown ?? throw new InvalidOperationException("ResourcesKey.Unknown is not initialized."); public static string ErrorFetchGames => _instance?.ErrorFetchGames ?? throw new InvalidOperationException("ResourcesKey.ErrorFetchGames is not initialized."); + public static string Ascending => _instance?.Ascending ?? throw new InvalidOperationException("ResourcesKey.Ascending is not initialized."); + public static string Descending => _instance?.Descending ?? throw new InvalidOperationException("ResourcesKey.Descending is not initialized."); + public static string ErrorStorageSpaceLabel => _instance?.ErrorStorageSpaceLabel ?? throw new InvalidOperationException("ResourcesKey.ErrorStorageSpaceLabel is not initialized."); + public static string MinStorageSpaceFormat => _instance?.MinStorageSpaceFormat ?? throw new InvalidOperationException("ResourcesKey.MinStorageSpaceFormat is not initialized."); + public static string MaxStorageSpaceFormat => _instance?.MaxStorageSpaceFormat ?? throw new InvalidOperationException("ResourcesKey.MaxStorageSpaceFormat is not initialized."); + public static string MinMaxStorageSpaceFormat => _instance?.MinMaxStorageSpaceFormat ?? throw new InvalidOperationException("ResourcesKey.MinMaxStorageSpaceFormat is not initialized."); } \ No newline at end of file diff --git a/src/GameIdeas/GameIdeas.Shared/Constants/GlobalConstants.cs b/src/GameIdeas/GameIdeas.Shared/Constants/GlobalConstants.cs index 373c8b2..ff8ddf9 100644 --- a/src/GameIdeas/GameIdeas.Shared/Constants/GlobalConstants.cs +++ b/src/GameIdeas/GameIdeas.Shared/Constants/GlobalConstants.cs @@ -2,6 +2,6 @@ public class GlobalConstants { - + public static int NUMBER_PER_PAGE = 50; } \ No newline at end of file diff --git a/src/GameIdeas/GameIdeas.Shared/Dto/CategoriesDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/CategoriesDto.cs index 4d6583f..54d6ada 100644 --- a/src/GameIdeas/GameIdeas.Shared/Dto/CategoriesDto.cs +++ b/src/GameIdeas/GameIdeas.Shared/Dto/CategoriesDto.cs @@ -7,4 +7,6 @@ public class CategoriesDto public List? Tags { get; set; } 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/GameDetailDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/GameDetailDto.cs new file mode 100644 index 0000000..6510480 --- /dev/null +++ b/src/GameIdeas/GameIdeas.Shared/Dto/GameDetailDto.cs @@ -0,0 +1,20 @@ +namespace GameIdeas.Shared.Dto; + +public class GameDetailDto +{ + public int? Id { get; set; } + public string? Title { get; set; } + public DateTime? ReleaseDate { get; set; } + public DateTime? CreationDate { get; set; } + public int CreationUserId { get; set; } + public DateTime? ModificationDate { get; set; } + public int? ModificationUserId { get; set; } + public double? StorageSpace { get; set; } + public string? Description { get; set; } + public int Interest { get; set; } = 3; + public List? Platforms { get; set; } + public List? Properties { get; set; } + public List? Tags { get; set; } + public List? Publishers { get; set; } + public List? Developers { get; set; } +} \ No newline at end of file diff --git a/src/GameIdeas/GameIdeas.Shared/Dto/GameDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/GameDto.cs index dd2afe0..aa87436 100644 --- a/src/GameIdeas/GameIdeas.Shared/Dto/GameDto.cs +++ b/src/GameIdeas/GameIdeas.Shared/Dto/GameDto.cs @@ -5,18 +5,8 @@ public class GameDto public int? Id { get; set; } public string? Title { get; set; } public DateTime? ReleaseDate { get; set; } - public DateTime? CreationDate { get; set; } - public UserDto? CreationUser { get; set; } - public int CreationUserId { get; set; } - public DateTime? ModificationDate { get; set; } - public UserDto? ModificationUser { get; set; } - public int? ModificationUserId { get; set; } + public IEnumerable? Platforms { get; set; } + public IEnumerable? Tags { get; set; } public double? StorageSpace { get; set; } - public string? Description { get; set; } public int Interest { get; set; } = 3; - public List? Platforms { get; set; } - public List? Properties { get; set; } - public List? Tags { get; set; } - public List? Publishers { get; set; } - public List? Developers { get; set; } } \ No newline at end of file diff --git a/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs index d2922c2..6af6be0 100644 --- a/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs +++ b/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs @@ -1,19 +1,20 @@ - +using GameIdeas.Shared.Enum; + namespace GameIdeas.Shared.Dto; public class GameFilterDto { - public SortTypeDto? SortType { get; set; } - public SortPropertyDto? SortProperty { get; set; } + public int CurrentPage { get; set; } = 1; + public SortType? SortType { get; set; } + public string? SortPropertyName { get; set; } public string? Title { get; set; } - public List? Platforms { get; set; } - public List? Properties { get; set; } - public List? Tags { get; set; } - public List? Publishers { get; set; } - public List? Developers { get; set; } - public int MinInterest { get; set; } = 1; - public int MaxInterest { get; set; } = 5; + public List? PlatformIds { get; set; } + public List? PropertyIds { get; set; } + public List? TagIds { get; set; } + public List? PublisherIds { get; set; } + public List? DeveloperIds { get; set; } + public int? MinInterest { get; set; } + public int? MaxInterest { get; set; } public List? ReleaseYears { get; set; } - public int? MinStorageSize { get; set; } - public int? MaxStorageSize { get; set; } + public List? StorageSpaces { get; set; } } diff --git a/src/GameIdeas/GameIdeas.Shared/Dto/PaggingDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/PaggingDto.cs deleted file mode 100644 index c006966..0000000 --- a/src/GameIdeas/GameIdeas.Shared/Dto/PaggingDto.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace GameIdeas.Shared.Dto; - -public class PaggingDto -{ - public int CurrentPage { get; set; } - public int NumberPerPage { get; set; } -} diff --git a/src/GameIdeas/GameIdeas.Shared/Dto/SortPropertyDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/SortPropertyDto.cs index 5f54704..1261e67 100644 --- a/src/GameIdeas/GameIdeas.Shared/Dto/SortPropertyDto.cs +++ b/src/GameIdeas/GameIdeas.Shared/Dto/SortPropertyDto.cs @@ -2,6 +2,6 @@ public class SortPropertyDto { - public Func? SortProperty { get; set; } + public string PropertyName { get; set; } = string.Empty; public string Label { get; set; } = string.Empty; } diff --git a/src/GameIdeas/GameIdeas.Shared/Dto/StorageSpaceDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/StorageSpaceDto.cs new file mode 100644 index 0000000..cb80975 --- /dev/null +++ b/src/GameIdeas/GameIdeas.Shared/Dto/StorageSpaceDto.cs @@ -0,0 +1,8 @@ +namespace GameIdeas.Shared.Dto; + +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/Controllers/GameController.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/GameController.cs index 0db432b..9b0e15f 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/GameController.cs +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Controllers/GameController.cs @@ -1,5 +1,5 @@ using GameIdeas.Shared.Dto; -using GameIdeas.WebAPI.Services.Interfaces; +using GameIdeas.WebAPI.Services.Games; using Microsoft.AspNetCore.Mvc; namespace GameIdeas.WebAPI.Controllers; @@ -7,16 +7,19 @@ namespace GameIdeas.WebAPI.Controllers; [ApiController] [Route("api/[controller]")] -public class GameController(IGameService gameService, ILoggerFactory loggerFactory) : Controller +public class GameController( + IGameReadService gameReadService, + IGameWriteService gameWriteService, + ILoggerFactory loggerFactory) : Controller { private readonly ILogger logger = loggerFactory.CreateLogger(); [HttpGet] - public async Task>> GetGames([FromQuery] PaggingDto pagging) + public async Task>> SearchGames([FromQuery] GameFilterDto filter) { try { - return Ok(await gameService.GetGames(pagging)); + return Ok(await gameReadService.GetGames(filter)); } catch (Exception e) { @@ -26,11 +29,11 @@ public class GameController(IGameService gameService, ILoggerFactory loggerFacto } [HttpGet("{id:int}")] - public async Task> GetGameById(int id) + public async Task> GetGameById(int id) { try { - return Ok(await gameService.GetGameById(id)); + return Ok(await gameReadService.GetGameById(id)); } catch (Exception e) { @@ -40,11 +43,11 @@ public class GameController(IGameService gameService, ILoggerFactory loggerFacto } [HttpPost("Create")] - public async Task> CreateGame([FromBody] GameDto game) + public async Task> CreateGame([FromBody] GameDetailDto game) { try { - var gameResult = await gameService.CreateGame(game); + var gameResult = await gameWriteService.CreateGame(game); return Created("/Create", gameResult.Id); } catch (Exception e) @@ -55,11 +58,11 @@ public class GameController(IGameService gameService, ILoggerFactory loggerFacto } [HttpPut("Update")] - public async Task> UpdateGame([FromBody] GameDto game) + public async Task> UpdateGame([FromBody] GameDetailDto game) { try { - var gameResult = await gameService.UpdateGame(game); + var gameResult = await gameWriteService.UpdateGame(game); return Created($"/Update", gameResult.Id); } catch (Exception e) @@ -74,7 +77,7 @@ public class GameController(IGameService gameService, ILoggerFactory loggerFacto { try { - return Ok(await gameService.DeleteGame(id)); + return Ok(await gameWriteService.DeleteGame(id)); } catch (Exception e) { diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Files/GameIdeas.fr.json b/src/GameIdeas/Server/GameIdeas.WebAPI/Files/GameIdeas.fr.json index fd9dd3a..c0bffdf 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Files/GameIdeas.fr.json +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Files/GameIdeas.fr.json @@ -18,6 +18,8 @@ "StorageSizeMo": "Taille d'espace en Mo", "LastModification": "Dernière modifications", "ReleaseDate": "Date de parution", + "CreateDate": "Date de création", + "UpdateDate": "Date de modification", "Title": "Titre", "Interest": "Intérêt", "Properties": "Propriétés", @@ -35,6 +37,11 @@ "InvalidTitle": "Le titre est incorrect", "InvalidInterest": "L'interêt est incorrect", "Unknown": "Inconnu", - "ErrorFetchGames": "Erreur lors de la récupération des jeux" - + "ErrorFetchGames": "Erreur lors de la récupération des jeux", + "Ascending": "Ascendant", + "Descending": "Descendant", + "ErrorStorageSpaceLabel": "Erreur lors de la génération des label de l'espace de stockage", + "MinStorageSpaceFormat": "Jusqu'à {0}", + "MaxStorageSpaceFormat": "Plus de {0}", + "MinMaxStorageSpaceFormat": "{0} à {1}" } \ No newline at end of file diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Profiles/GameProfile.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Profiles/GameProfile.cs index e87e187..e0e5d73 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Profiles/GameProfile.cs +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Profiles/GameProfile.cs @@ -8,16 +8,14 @@ public class GameProfile : Profile { public GameProfile() { - CreateMap() + CreateMap() .ForMember(d => d.Id, o => o.MapFrom(s => s.Id)) .ForMember(d => d.Title, o => o.MapFrom(s => s.Title)) .ForMember(d => d.ReleaseDate, o => o.MapFrom(s => s.ReleaseDate)) .ForMember(d => d.CreationDate, o => o.MapFrom(s => s.CreationDate)) .ForMember(d => d.CreationUserId, o => o.MapFrom(s => s.CreationUserId)) - .ForMember(d => d.CreationUser, o => o.MapFrom(s => s.CreationUser)) .ForMember(d => d.ModificationDate, o => o.MapFrom(s => s.ModificationDate)) .ForMember(d => d.ModificationUserId, o => o.MapFrom(s => s.ModificationUserId)) - .ForMember(d => d.ModificationUser, o => o.MapFrom(s => s.ModificationUser)) .ForMember(d => d.StorageSpace, o => o.MapFrom(s => s.StorageSpace)) .ForMember(d => d.Description, o => o.MapFrom(s => s.Description)) .ForMember(d => d.Interest, o => o.MapFrom(s => s.Interest)) @@ -27,5 +25,15 @@ public class GameProfile : Profile .ForMember(d => d.Publishers, o => o.MapFrom(s => s.GamePublishers.Select(p => p.Publisher))) .ForMember(d => d.Developers, o => o.MapFrom(s => s.GameDevelopers.Select(gd => gd.Developer))) .ReverseMap(); + + CreateMap() + .ForMember(d => d.Id, o => o.MapFrom(s => s.Id)) + .ForMember(d => d.Title, o => o.MapFrom(s => s.Title)) + .ForMember(d => d.ReleaseDate, o => o.MapFrom(s => s.ReleaseDate)) + .ForMember(d => d.Platforms, o => o.MapFrom(s => s.GamePlatforms.Select(p => new PlatformDto() { Id = p.Platform.Id, Label = p.Platform.Label, Url = p.Url }))) + .ForMember(d => d.Tags, o => o.MapFrom(s => s.GameTags.Select(t => t.Tag))) + .ForMember(d => d.StorageSpace, o => o.MapFrom(s => s.StorageSpace)) + .ForMember(d => d.Interest, o => o.MapFrom(s => s.Interest)) + .ReverseMap(); } } diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Program.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Program.cs index e78e427..6357156 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Program.cs +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Program.cs @@ -1,10 +1,8 @@ using GameIdeas.Resources; using GameIdeas.WebAPI.Context; -using GameIdeas.WebAPI.Profiles; -using GameIdeas.WebAPI.Services; -using GameIdeas.WebAPI.Services.Interfaces; +using GameIdeas.WebAPI.Services.Categories; +using GameIdeas.WebAPI.Services.Games; using Microsoft.EntityFrameworkCore; -using System.Text.Json.Serialization; var builder = WebApplication.CreateBuilder(args); var services = builder.Services; @@ -32,7 +30,8 @@ services.AddDbContext(dbContextOptions); services.AddSingleton(); services.AddSingleton(); -services.AddScoped(); +services.AddScoped(); +services.AddScoped(); services.AddScoped(); services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/CategoryService.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Categories/CategoryService.cs similarity index 52% rename from src/GameIdeas/Server/GameIdeas.WebAPI/Services/CategoryService.cs rename to src/GameIdeas/Server/GameIdeas.WebAPI/Services/Categories/CategoryService.cs index f3650a1..80ddcc8 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/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; +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(); @@ -15,6 +25,9 @@ public class CategoryService(GameIdeasContext context, IMapper mapper) : ICatego var tags = await context.Tags.ToListAsync(); var developers = await context.Developers.ToListAsync(); var publishers = await context.Publishers.ToListAsync(); + var releaseYears = await context.Games + .Where(game => game.ReleaseDate != null) + .Select(game => game.ReleaseDate!.Value.Year).Distinct().ToListAsync(); return new() { @@ -22,7 +35,9 @@ public class CategoryService(GameIdeasContext context, IMapper mapper) : ICatego Properties = mapper.Map>(properties), Tags = mapper.Map>(tags), Developers = mapper.Map>(developers), - Publishers = mapper.Map>(publishers) + Publishers = mapper.Map>(publishers), + ReleaseYears = mapper.Map>(releaseYears), + StorageSpaces = GetStorageSpaces() }; } } diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Interfaces/ICategoryService.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Categories/ICategoryService.cs similarity index 54% rename from src/GameIdeas/Server/GameIdeas.WebAPI/Services/Interfaces/ICategoryService.cs rename to src/GameIdeas/Server/GameIdeas.WebAPI/Services/Categories/ICategoryService.cs index 1559cac..9d6c495 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Interfaces/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 new file mode 100644 index 0000000..90a6dbf --- /dev/null +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Games/GameReadService.cs @@ -0,0 +1,156 @@ +using AutoMapper; +using GameIdeas.Shared.Constants; +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.Expressions; + +namespace GameIdeas.WebAPI.Services.Games; + +public class GameReadService(GameIdeasContext context, IMapper mapper, ICategoryService categoryService) : IGameReadService +{ + public async Task> GetGames(GameFilterDto filter) + { + var query = context.Games + .Include(g => g.GamePlatforms).ThenInclude(gp => gp.Platform) + .Include(g => g.GameProperties) + .Include(g => g.GameTags).ThenInclude(gt => gt.Tag) + .Include(g => g.GamePublishers) + .Include(g => g.GameDevelopers) + .AsQueryable(); + + ApplyFilter(ref query, filter); + + ApplyOrder(ref query, filter); + + var games = await query.Skip((filter.CurrentPage - 1) * GlobalConstants.NUMBER_PER_PAGE) + .Take(GlobalConstants.NUMBER_PER_PAGE) + .ToListAsync(); + + ApplyStaticFilter(ref games, filter); + + return mapper.Map>(games); + } + + public async Task GetGameById(int gameId) + { + var game = await context.Games + .Include(g => g.CreationUser) + .Include(g => g.ModificationUser) + .Include(g => g.GamePlatforms).ThenInclude(p => p.Platform) + .Include(g => g.GameProperties).ThenInclude(p => p.Property) + .Include(g => g.GameTags).ThenInclude(p => p.Tag) + .Include(g => g.GamePublishers).ThenInclude(p => p.Publisher) + .Include(g => g.GameDevelopers).ThenInclude(p => p.Developer) + .FirstOrDefaultAsync(g => g.Id == gameId); + + return game == null + ? throw new NotFoundException($"[{typeof(Game).FullName}] with ID {gameId} has not been found in context") + : mapper.Map(game); + } + + private static void ApplyOrder(ref IQueryable query, GameFilterDto filter) + { + if (filter.SortType != null && filter.SortPropertyName != null) + { + var param = Expression.Parameter(typeof(Game), "x"); + Expression propertyAccess = Expression.PropertyOrField(param, filter.SortPropertyName); + var converted = Expression.Convert(propertyAccess, typeof(object)); + var lambda = Expression.Lambda>(converted, param); + + if (filter.SortType == Shared.Enum.SortType.Ascending) + { + query = Queryable.OrderBy(query, lambda); + } + else + { + query = Queryable.OrderByDescending(query, lambda); + } + } + } + + private void ApplyFilter(ref IQueryable query, GameFilterDto filter) + { + if (filter.PlatformIds != null) + { + query = query.Where(game => filter.PlatformIds.All(plat => + game.GamePlatforms.Any(gp => gp.PlatformId == plat))); + } + + if (filter.PropertyIds != null) + { + query = query.Where(game => filter.PropertyIds.All(prop => + game.GameProperties.Any(gp => gp.PropertyId == prop))); + } + + if (filter.TagIds != null) + { + query = query.Where(game => filter.TagIds.All(tag => + game.GameTags.Any(gt => gt.TagId == tag))); + } + + if (filter.PublisherIds != null) + { + query = query.Where(game => filter.PublisherIds.All(pub => + game.GamePublishers.Any(gp => gp.PublisherId == pub))); + } + + if (filter.DeveloperIds != null) + { + query = query.Where(game => filter.DeveloperIds.All(dev => + game.GameDevelopers.Any(gd => gd.DeveloperId == dev))); + } + + if (filter.MinInterest != null) + { + query = query.Where(game => game.Interest >= filter.MinInterest); + } + + if (filter.MaxInterest != null) + { + query = query.Where(game => game.Interest <= filter.MaxInterest); + } + + if (filter.ReleaseYears != null) + { + query = query.Where(game => game.ReleaseDate != null && + filter.ReleaseYears.Contains(game.ReleaseDate.Value.Year)); + } + } + + private void ApplyStaticFilter(ref List games, GameFilterDto filter) + { + if (!string.IsNullOrWhiteSpace(filter.Title)) + { + var keywords = filter.Title? + .Split([' '], StringSplitOptions.RemoveEmptyEntries) + .Select(k => k.Trim()) + .ToArray() ?? []; + + 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; + } + + 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(); + } + } +} diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/GameService.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Games/GameWriteService.cs similarity index 72% rename from src/GameIdeas/Server/GameIdeas.WebAPI/Services/GameService.cs rename to src/GameIdeas/Server/GameIdeas.WebAPI/Services/Games/GameWriteService.cs index a00b216..b1b05b1 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/GameService.cs +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Games/GameWriteService.cs @@ -1,37 +1,16 @@ using AutoMapper; +using GameIdeas.Shared.Constants; using GameIdeas.Shared.Dto; using GameIdeas.Shared.Exceptions; using GameIdeas.Shared.Model; using GameIdeas.WebAPI.Context; -using GameIdeas.WebAPI.Services.Interfaces; using Microsoft.EntityFrameworkCore; -namespace GameIdeas.WebAPI.Services; +namespace GameIdeas.WebAPI.Services.Games; -public class GameService(GameIdeasContext context, IMapper mapper) : IGameService +public class GameWriteService(GameIdeasContext context, IMapper mapper) : IGameWriteService { - public async Task> GetGames(PaggingDto pagging) - { - var games = await SelectGames() - .OrderBy(g => g.Title) - .Skip((pagging.CurrentPage - 1) * pagging.NumberPerPage) - .Take(pagging.NumberPerPage) - .ToListAsync(); - - return mapper.Map>(games); - } - - public async Task GetGameById(int gameId) - { - var game = await SelectGames() - .FirstOrDefaultAsync(g => g.Id == gameId); - - return game == null - ? throw new NotFoundException($"[{typeof(Game).FullName}] with ID {gameId} has not been found in context") - : mapper.Map(game); - } - - public async Task CreateGame(GameDto gameDto) + public async Task CreateGame(GameDetailDto gameDto) { var gameToCreate = mapper.Map(gameDto); @@ -46,10 +25,10 @@ public class GameService(GameIdeasContext context, IMapper mapper) : IGameServic await context.SaveChangesAsync(); - return mapper.Map(gameToCreate); + return mapper.Map(gameToCreate); } - public async Task UpdateGame(GameDto gameDto) + public async Task UpdateGame(GameDetailDto gameDto) { if (await context.Games.CountAsync(g => g.Id == gameDto.Id) == 0) { @@ -67,7 +46,7 @@ public class GameService(GameIdeasContext context, IMapper mapper) : IGameServic context.Games.Update(gameToUpdate); await context.SaveChangesAsync(); - return mapper.Map(gameToUpdate); + return mapper.Map(gameToUpdate); } public async Task DeleteGame(int gameId) @@ -80,19 +59,6 @@ public class GameService(GameIdeasContext context, IMapper mapper) : IGameServic return await context.SaveChangesAsync() != 0; } - private IQueryable SelectGames() - { - return context.Games - .Include(g => g.CreationUser) - .Include(g => g.ModificationUser) - .Include(g => g.GamePlatforms).ThenInclude(p => p.Platform) - .Include(g => g.GameProperties).ThenInclude(p => p.Property) - .Include(g => g.GameTags).ThenInclude(p => p.Tag) - .Include(g => g.GamePublishers).ThenInclude(p => p.Publisher) - .Include(g => g.GameDevelopers).ThenInclude(p => p.Developer) - .AsQueryable(); - } - private async Task HandlePlatformsCreation(IEnumerable? categoriesToCreate, int gameId) { if (categoriesToCreate != null) diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Games/IGameReadService.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Games/IGameReadService.cs new file mode 100644 index 0000000..4c814d3 --- /dev/null +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Games/IGameReadService.cs @@ -0,0 +1,9 @@ +using GameIdeas.Shared.Dto; + +namespace GameIdeas.WebAPI.Services.Games; + +public interface IGameReadService +{ + Task> GetGames(GameFilterDto filter); + Task GetGameById(int gameId); +} diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Games/IGameWriteService.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Games/IGameWriteService.cs new file mode 100644 index 0000000..d7fcc92 --- /dev/null +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Games/IGameWriteService.cs @@ -0,0 +1,10 @@ +using GameIdeas.Shared.Dto; + +namespace GameIdeas.WebAPI.Services.Games; + +public interface IGameWriteService +{ + Task CreateGame(GameDetailDto gameDto); + Task UpdateGame(GameDetailDto gameDto); + Task DeleteGame(int gameId); +} diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Interfaces/IGameService.cs b/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Interfaces/IGameService.cs deleted file mode 100644 index efc11cc..0000000 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/Services/Interfaces/IGameService.cs +++ /dev/null @@ -1,12 +0,0 @@ -using GameIdeas.Shared.Dto; - -namespace GameIdeas.WebAPI.Services.Interfaces; - -public interface IGameService -{ - Task> GetGames(PaggingDto pagging); - Task GetGameById(int gameId); - Task CreateGame(GameDto gameDto); - Task UpdateGame(GameDto gameDto); - Task DeleteGame(int gameId); -}