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 8c1dd8f..cd93cda 100644
--- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor
@@ -1,45 +1,32 @@
@using GameIdeas.BlazorApp.Shared.Components.Select
@using GameIdeas.BlazorApp.Shared.Components.Select.Models
+@using GameIdeas.Shared.Dto
+
@ResourcesKey.Filters
-
+ Theme="Theme" />
-
+ @bind-Values=GameFilter.Tags
+ Theme="Theme" />
-
+ @bind-Values=GameFilter!.Publishers
+ Theme="Theme" />
-
-
-
-
-
-
-
+ @bind-Values=GameFilter!.Developers
+ Theme="Theme" />
@ResourcesKey.LastAdd
\ No newline at end of file
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 cb74ed4..2bc6859 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,10 +1,12 @@
using GameIdeas.BlazorApp.Shared.Components.Select.Models;
+using GameIdeas.Shared.Dto;
using Microsoft.AspNetCore.Components;
namespace GameIdeas.BlazorApp.Pages.Games.Filter;
public partial class AdvancedGameFilter
{
- [Parameter] public GameFilterParams? GameFilterParams { get; set; }
- [Parameter] public EventCallback GameFilterParamsChanged { get; set; }
+ [Parameter] public GameFilterDto? GameFilter { get; set; }
+ [Parameter] public EventCallback GameFilterChanged { get; set; }
+ private readonly SelectListTheme Theme = SelectListTheme.AdvancedFilter;
}
\ 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 414cda9..6f501d2 100644
--- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor
@@ -1,23 +1,22 @@
@using GameIdeas.BlazorApp.Shared.Components.Search
@using GameIdeas.BlazorApp.Shared.Components.Select
@using GameIdeas.BlazorApp.Shared.Components.Select.Models
+@using GameIdeas.BlazorApp.Shared.Components.SelectList
+@using GameIdeas.BlazorApp.Shared.Components.SelectList.Models
@using GameIdeas.BlazorApp.Shared.Components.SliderRange
@using GameIdeas.BlazorApp.Shared.Models
@using GameIdeas.Shared.Dto
-@using GameIdeas.Shared.Enum
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor.cs
index 8ffe951..b2e9a0c 100644
--- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor.cs
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor.cs
@@ -1,4 +1,4 @@
-using GameIdeas.BlazorApp.Shared.Components.Select.Models;
+using GameIdeas.BlazorApp.Shared.Components.SelectList.Models;
using GameIdeas.BlazorApp.Shared.Components.SliderRange;
using GameIdeas.BlazorApp.Shared.Models;
using GameIdeas.Shared.Dto;
@@ -10,19 +10,21 @@ namespace GameIdeas.BlazorApp.Pages.Games.Filter;
public partial class GameFilter
{
- [Parameter] public GameFilterParams GameFilterParams { get; set; } = new();
- [Parameter] public EventCallback GameFilterParamsChanged { get; set; }
+ [Parameter] public GameFilterDto Value { get; set; } = new();
+ [Parameter] public EventCallback ValueChanged { get; set; }
[Parameter] public DisplayType DisplayType { get; set; }
[Parameter] public EventCallback DisplayTypeChanged { get; set; }
- private readonly IEnumerable> SortTypes = [
- new(SortType.Ascending, "Ascendant") { IsSelected = true },
- new(SortType.Descending, "Descendant")
+ private SelectParams SelectParams = new();
+
+ private readonly IEnumerable SortTypes = [
+ new() { SortType = SortType.Ascending, Label = "Ascendant" },
+ new() { SortType = SortType.Descending, Label = "Descendant" }
];
-
- private readonly IEnumerable>> GameProperties = [
- new(game => game?.Title, "Nom") { IsSelected = true },
- new(game => game?.ReleaseDate, "Date de parution"),
+
+ private readonly IEnumerable GameProperties = [
+ new() { SortProperty = game => game.Title!, Label = "Titre" },
+ new() { SortProperty = game => game.ReleaseDate!, Label = "Date de parution" }
];
private EditContext? EditContext;
@@ -31,10 +33,20 @@ public partial class GameFilter
protected override void OnInitialized()
{
- EditContext = new EditContext(GameFilterParams);
+ EditContext = new EditContext(Value);
EditContext.OnFieldChanged += async (s, e) =>
{
- await GameFilterParamsChanged.InvokeAsync(GameFilterParams);
+ await ValueChanged.InvokeAsync(Value);
+ };
+
+ SelectParams = new()
+ {
+ Headers = SortTypes,
+ GetHeaderLabel = header => header.Label,
+ DefaultHeader = SortTypes.FirstOrDefault(h => h.SortType == SortType.Ascending),
+ Items = GameProperties,
+ GetItemLabel = item => item.Label,
+ DefaultItem = GameProperties.FirstOrDefault(p => p.Label == "Titre")
};
}
@@ -43,4 +55,14 @@ public partial class GameFilter
DisplayType = displayType;
await DisplayTypeChanged.InvokeAsync(displayType);
}
+ private async Task HandleSortTypeClicked(IEnumerable sortTypes)
+ {
+ Value.SortType = sortTypes.FirstOrDefault();
+ await ValueChanged.InvokeAsync(Value);
+ }
+ private async Task HandleSortPropertyClicked(IEnumerable sortProperties)
+ {
+ Value.SortProperty = sortProperties.FirstOrDefault();
+ await ValueChanged.InvokeAsync(Value);
+ }
}
\ No newline at end of file
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilterParams.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilterParams.cs
deleted file mode 100644
index d95d5c4..0000000
--- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilterParams.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using GameIdeas.Shared.Enum;
-using GameIdeas.Shared.Dto;
-
-namespace GameIdeas.BlazorApp.Pages.Games.Filter;
-
-public class GameFilterParams
-{
- public SortType SortType { get; set; } = SortType.Ascending;
- public Func? SortProperty { get; set; }
- public string? SearchName { get; set; }
- public IEnumerable? Platforms { get; set; }
- public IEnumerable? Properties { get; set; }
- public IEnumerable? Tags { get; set; }
- public IEnumerable? Publishers { get; set; }
- public IEnumerable? Developers { get; set; }
- public IEnumerable? StorageSizes { get; set; }
- public IEnumerable? LastModification { get; set; }
- public IEnumerable? ReleaseDates { get; set; }
- public int MaxRating { get; set; } = 5;
- public int MinRating { get; set; } = 1;
-}
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor
index b72d4b0..1bd2393 100644
--- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor
@@ -13,14 +13,14 @@
+ @bind-Value=GameFilter/>
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor.cs
index 92aff27..3844579 100644
--- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor.cs
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/GameBase.razor.cs
@@ -1,14 +1,15 @@
-using GameIdeas.BlazorApp.Pages.Games.Filter;
using GameIdeas.BlazorApp.Shared.Components.Popup;
using GameIdeas.BlazorApp.Shared.Models;
+using GameIdeas.Shared.Dto;
namespace GameIdeas.BlazorApp.Pages.Games;
public partial class GameBase ()
{
private DisplayType DisplayType = DisplayType.List;
- private GameFilterParams GameFilterParams = new();
+ private GameFilterDto GameFilter = new();
private Popup? ManualAddPopup;
+
private void HandleAddClicked(AddType addType)
{
switch (addType)
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/SelectList.razor.css b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/SelectList.razor.css
index 56150db..d979b9a 100644
--- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/SelectList.razor.css
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/SelectList.razor.css
@@ -18,7 +18,7 @@
flex-direction: column;
border-radius: var(--small-radius);
animation-name: fade-in;
- animation-duration: 0.4s;
+ animation-duration: 0.2s;
}
.select-button {
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Components/SelectRow.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Components/SelectRow.razor
new file mode 100644
index 0000000..3a55b84
--- /dev/null
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Components/SelectRow.razor
@@ -0,0 +1,16 @@
+@using GameIdeas.BlazorApp.Shared.Components.SelectList.Helpers
+
+
+
+ @if (IsSelected == true)
+ {
+
+ }
+
+
+ @Label
+
+
\ No newline at end of file
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Components/SelectRow.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Components/SelectRow.razor.cs
new file mode 100644
index 0000000..d5fbfe3
--- /dev/null
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Components/SelectRow.razor.cs
@@ -0,0 +1,16 @@
+using GameIdeas.BlazorApp.Shared.Components.SelectList.Models;
+using Microsoft.AspNetCore.Components;
+
+namespace GameIdeas.BlazorApp.Shared.Components.SelectList.Components;
+
+public partial class SelectRow
+{
+ [Parameter] public bool? IsSelected { get; set; }
+ [Parameter] public string? Label { get; set; }
+ [Parameter] public SelectTheme Theme { get; set; }
+ [Parameter] public EventCallback OnClick { get; set; }
+ private async Task HandleElementClicked()
+ {
+ await OnClick.InvokeAsync();
+ }
+}
\ No newline at end of file
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Components/SelectRow.razor.css b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Components/SelectRow.razor.css
new file mode 100644
index 0000000..a12a8b5
--- /dev/null
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Components/SelectRow.razor.css
@@ -0,0 +1,45 @@
+.select-element {
+ display: flex;
+ flex-direction: row;
+ width: auto;
+ gap: 6px;
+ height: 20px;
+ align-items: center;
+ padding: 2px 6px;
+}
+
+ .select-element:hover {
+ cursor: pointer;
+ background: var(--input-selected);
+ }
+
+.selected {
+ width: 12px;
+ min-width: 12px;
+ height: 12px;
+ min-height: 12px;
+ border: 1px solid var(--line);
+}
+
+ .selected svg {
+ display: block;
+ fill: var(--white)
+ }
+
+.label {
+ text-wrap: nowrap;
+ margin-right: 6px;
+}
+
+/***** Navigation Theme *****/
+.navigation {
+ padding: 4px 8px;
+}
+
+ .navigation:hover {
+ background: var(--violet-selected);
+ }
+
+ .navigation .selected {
+ display: none;
+ }
\ No newline at end of file
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Helpers/SelectHelper.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Helpers/SelectHelper.cs
new file mode 100644
index 0000000..7e15185
--- /dev/null
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Helpers/SelectHelper.cs
@@ -0,0 +1,19 @@
+using GameIdeas.BlazorApp.Shared.Components.SelectList.Models;
+
+namespace GameIdeas.BlazorApp.Shared.Components.SelectList.Helpers;
+
+public static class SelectHelper
+{
+ public static string GetClassFromTheme(SelectTheme selectTheme)
+ {
+ return selectTheme switch
+ {
+ SelectTheme.Navigation => "navigation",
+ SelectTheme.Sort => "sort",
+ SelectTheme.Filter => "filter",
+ SelectTheme.AdvancedFilter => "advenced-filter",
+ SelectTheme.Creation => "creation",
+ _ => string.Empty
+ };
+ }
+}
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Models/SelectParams.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Models/SelectParams.cs
new file mode 100644
index 0000000..d06f35e
--- /dev/null
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Models/SelectParams.cs
@@ -0,0 +1,12 @@
+namespace GameIdeas.BlazorApp.Shared.Components.SelectList.Models;
+
+public class SelectParams
+{
+ public IEnumerable Items { get; set; } = [];
+ public TItem? DefaultItem { get; set; }
+ public Func GetItemLabel { get; set; } = _ => string.Empty;
+ public IEnumerable Headers { get; set; } = [];
+ public THeader? DefaultHeader { get; set; }
+ public Func GetHeaderLabel { get; set; } = _ => string.Empty;
+
+}
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Models/SelectTheme.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Models/SelectTheme.cs
new file mode 100644
index 0000000..620118f
--- /dev/null
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Models/SelectTheme.cs
@@ -0,0 +1,10 @@
+namespace GameIdeas.BlazorApp.Shared.Components.SelectList.Models;
+
+public enum SelectTheme
+{
+ Navigation,
+ Sort,
+ Filter,
+ AdvancedFilter,
+ Creation
+}
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Models/SelectType.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Models/SelectType.cs
new file mode 100644
index 0000000..ef62f6d
--- /dev/null
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Models/SelectType.cs
@@ -0,0 +1,7 @@
+namespace GameIdeas.BlazorApp.Shared.Components.SelectList.Models;
+
+public enum SelectType
+{
+ Single,
+ Multiple
+}
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Select.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Select.razor
new file mode 100644
index 0000000..79c0cff
--- /dev/null
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Select.razor
@@ -0,0 +1,41 @@
+@using GameIdeas.BlazorApp.Shared.Components.BackdropFilter
+@using GameIdeas.BlazorApp.Shared.Components.SelectList.Components
+@using GameIdeas.BlazorApp.Shared.Components.SelectList.Helpers
+
+@typeparam TItem
+@typeparam THeader
+
+
+
+ @ChildContent
+
+
+
+ @if (IsContentOpen)
+ {
+
+ @foreach (var header in Params.Headers)
+ {
+
+ }
+
+ @if (Params.Headers.Any())
+ {
+
+ }
+
+ @foreach (var item in Params.Items)
+ {
+
+ }
+
+ }
+
+
+
+
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Select.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Select.razor.cs
new file mode 100644
index 0000000..7ca25af
--- /dev/null
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Select.razor.cs
@@ -0,0 +1,74 @@
+using GameIdeas.BlazorApp.Shared.Components.SelectList.Models;
+using Microsoft.AspNetCore.Components;
+
+namespace GameIdeas.BlazorApp.Shared.Components.SelectList;
+
+public partial class Select
+{
+ [Parameter] public RenderFragment? ChildContent { get; set; }
+ [Parameter] public List Values { get; set; } = [];
+ [Parameter] public EventCallback> ValuesChanged { get; set; }
+ [Parameter] public List HeaderValues { get; set; } = [];
+ [Parameter] public EventCallback> HeaderValuesChanged { get; set; }
+ [Parameter] public SelectParams Params { get; set; } = new();
+ [Parameter] public SelectTheme Theme { get; set; }
+ [Parameter] public SelectType Type { get; set; } = SelectType.Single;
+ [Parameter] public bool AlignRight { get; set; } = false;
+
+ private bool IsContentOpen = false;
+
+ public void Close() =>
+ IsContentOpen = false;
+
+ private void HandleButtonClicked() =>
+ IsContentOpen = !IsContentOpen;
+
+ private void HandleContentClosed() =>
+ IsContentOpen = false;
+
+ protected override void OnInitialized()
+ {
+ if (Params.DefaultItem != null)
+ {
+ Values.Add(Params.DefaultItem);
+ }
+
+ if (Params.DefaultHeader != null)
+ {
+ HeaderValues.Add(Params.DefaultHeader);
+ }
+ }
+
+ private async Task HandleValueClicked(TItem value)
+ {
+ if (Type != SelectType.Multiple)
+ {
+ Values?.Clear();
+ }
+
+ if (Values?.Contains(value) == true)
+ {
+ Values.Remove(value);
+ }
+
+ Values?.Add(value);
+ await ValuesChanged.InvokeAsync(Values);
+ StateHasChanged();
+ }
+
+ private async Task HandleHeaderClicked(THeader header)
+ {
+ if (Type != SelectType.Multiple)
+ {
+ HeaderValues?.Clear();
+ }
+
+ if (HeaderValues?.Contains(header) == true)
+ {
+ HeaderValues.Remove(header);
+ }
+
+ HeaderValues?.Add(header);
+ await HeaderValuesChanged.InvokeAsync(HeaderValues);
+ }
+}
\ No newline at end of file
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Select.razor.css b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Select.razor.css
new file mode 100644
index 0000000..da81379
--- /dev/null
+++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SelectList/Select.razor.css
@@ -0,0 +1,52 @@
+.select-container {
+ position: relative;
+}
+
+.button {
+ z-index: var(--index-component)
+}
+
+.dropdown {
+ overflow: auto;
+ margin-top: 4px;
+ position: absolute;
+ z-index: var(--index-dropdown);
+ border-radius: var(--small-radius);
+}
+
+ .dropdown.align-right {
+ right: 0;
+ }
+
+.content {
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+ animation-name: fade-in;
+ animation-duration: 0.2s;
+}
+
+.line {
+ display: none;
+}
+
+/***** Navigation Theme *****/
+.content.navigation {
+ background: var(--violet);
+ box-shadow: var(--drop-shadow);
+}
+
+/***** Sort Theme *****/
+.content.sort {
+ background: var(--dropdown-content);
+ box-shadow: var(--drop-shadow);
+ padding: 4px 0;
+}
+
+ .content.sort .line {
+ display: block;
+ margin: 2px 6px;
+ border-bottom: 2px solid var(--input-selected);
+ }
+
+
diff --git a/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs
index 25ba67c..1401e19 100644
--- a/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs
+++ b/src/GameIdeas/GameIdeas.Shared/Dto/GameFilterDto.cs
@@ -1,16 +1,19 @@
-namespace GameIdeas.Shared.Dto;
+
+namespace GameIdeas.Shared.Dto;
public class GameFilterDto
{
- public IEnumerable? Platforms { get; set; }
- public string? Name { get; set; }
- public IEnumerable? Tags { get; set; }
- public IEnumerable? Properties { get; set; }
- public int? MinInterest { get; set; }
- public int? MaxInterest { get; set; }
+ public SortTypeDto? SortType { get; set; }
+ public SortPropertyDto? SortProperty { get; set; }
+ public string? Title { get; set; }
+ public IEnumerable? Platforms { get; set; }
+ public IEnumerable? Properties { get; set; }
+ public IEnumerable? Tags { get; set; }
+ public IEnumerable? Publishers { get; set; }
+ public IEnumerable? Developers { get; set; }
+ public int MinInterest { get; set; } = 1;
+ public int MaxInterest { get; set; } = 5;
public IEnumerable? ReleaseYears { get; set; }
- public IEnumerable? PublisherIds { get; set; }
- public IEnumerable? DeveloperIds { get; set; }
- public IEnumerable? CreationUserIds { get; set; }
- public IEnumerable? ModificationUserIds { get; set; }
+ public int? MinStorageSize { get; set; }
+ public int? MaxStorageSize { get; set; }
}
diff --git a/src/GameIdeas/GameIdeas.Shared/Dto/SortPropertyDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/SortPropertyDto.cs
new file mode 100644
index 0000000..5f54704
--- /dev/null
+++ b/src/GameIdeas/GameIdeas.Shared/Dto/SortPropertyDto.cs
@@ -0,0 +1,7 @@
+namespace GameIdeas.Shared.Dto;
+
+public class SortPropertyDto
+{
+ public Func? SortProperty { get; set; }
+ public string Label { get; set; } = string.Empty;
+}
diff --git a/src/GameIdeas/GameIdeas.Shared/Dto/SortTypeDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/SortTypeDto.cs
new file mode 100644
index 0000000..6c7b927
--- /dev/null
+++ b/src/GameIdeas/GameIdeas.Shared/Dto/SortTypeDto.cs
@@ -0,0 +1,9 @@
+using GameIdeas.Shared.Enum;
+
+namespace GameIdeas.Shared.Dto;
+
+public class SortTypeDto
+{
+ public SortType SortType { get; set; } = SortType.Ascending;
+ public string Label { get; set; } = string.Empty;
+}