From 7d8f1c954489ff288193af063e7ca0e9a0ba16cf Mon Sep 17 00:00:00 2001 From: Maxime Adler Date: Tue, 11 Mar 2025 15:00:52 +0100 Subject: [PATCH] Add multiple select component --- .../Pages/Games/Filter/GameFilter.razor | 6 +++ .../Pages/Games/Filter/GameFilter.razor.cs | 9 +++- .../Pages/Games/Filter/GameFilterParams.cs | 3 ++ .../Properties/launchSettings.json | 2 + .../Components/Search/SearchInput.razor | 49 +++++++++--------- .../Components/Search/SearchInput.razor.cs | 29 +++++++---- .../Components/Search/SearchInput.razor.css | 5 ++ .../Components/SelectListElement.razor.cs | 2 + .../Components/SelectListElement.razor.css | 29 ++++++++--- .../Select/{ => Models}/SelectElement.cs | 2 +- .../Select/{ => Models}/SelectTheme.cs | 2 +- .../Select/MultipleSelectList.razor | 14 +++--- .../Select/MultipleSelectList.razor.cs | 30 ++++------- .../Select/MultipleSelectList.razor.css | 50 ++++++++++++++++++- .../Components/Select/SelectList.razor.cs | 3 +- .../Components/Select/SelectList.razor.css | 1 - .../Layouts/Header/HeaderLayout.razor.cs | 2 +- 17 files changed, 163 insertions(+), 75 deletions(-) rename src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/{ => Models}/SelectElement.cs (76%) rename src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/{ => Models}/SelectTheme.cs (51%) 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 d6718a2..4a6289b 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor @@ -35,6 +35,12 @@ + + + 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 36c0646..5444c3b 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,5 +1,5 @@ using GameIdeas.BlazorApp.Pages.Games.Models; -using GameIdeas.BlazorApp.Shared.Components.Select; +using GameIdeas.BlazorApp.Shared.Components.Select.Models; using GameIdeas.Shared.Dto; using GameIdeas.Shared.Enum; using Microsoft.AspNetCore.Components; @@ -24,6 +24,13 @@ public partial class GameFilter new() { Item = game => game?.ReleaseDate, Label = "Date de parution" } ]; + private readonly IEnumerable> Plateforms = [ + new() { Item = "Steam", Label = "Steam" }, + new() { Item = "GOG", Label = "GOG" }, + new() { Item = "Epic games", Label = "Epic games" }, + new() { Item = "Ubisoft", Label = "Ubisoft" }, + ]; + private EditContext? EditContext; protected override void OnInitialized() 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 8e2d3e8..6135664 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilterParams.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilterParams.cs @@ -8,4 +8,7 @@ public class GameFilterParams public SortType? SortType { get; set; } public Func? SortProperty { get; set; } public string? SearchName { get; set; } + public IEnumerable? Plateforms { get; set; } + public IEnumerable? Genres { get; set; } + } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Properties/launchSettings.json b/src/GameIdeas/Client/GameIdeas.BlazorApp/Properties/launchSettings.json index 8db20ce..fccd456 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Properties/launchSettings.json +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Properties/launchSettings.json @@ -7,6 +7,7 @@ "launchBrowser": true, "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", "applicationUrl": "http://localhost:5172", + "launchUrl": "http://localhost:5172/Games", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } @@ -17,6 +18,7 @@ "launchBrowser": true, "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", "applicationUrl": "https://localhost:7060;http://localhost:5172", + "launchUrl": "http://localhost:7060/Games", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor index 50b36d0..e921fb2 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor @@ -1,29 +1,30 @@ - -
- +
+ - @if (!string.IsNullOrEmpty(Text)) - { -
- - - -
- } - -
+ @if (!string.IsNullOrEmpty(Text)) + { +
- @if (Icon == SearchInputIcon.Search) - { - - } - else if (Icon == SearchInputIcon.Dropdown) - { - - } +
-
- + } + +
+ + @if (Icon == SearchInputIcon.Search) + { + + } + else if (Icon == SearchInputIcon.Dropdown) + { + + } + +
+
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 d9e601f..4d08c04 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,6 +1,4 @@ using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.Forms; -using System.Threading.Tasks; namespace GameIdeas.BlazorApp.Shared.Components.Search; @@ -8,23 +6,32 @@ public partial class SearchInput { [Parameter] public string? Text { get; set; } [Parameter] public EventCallback TextChanged { get; set; } + [Parameter] public EventCallback ClearClicked { get; set; } + [Parameter] public EventCallback SearchClicked { get; set; } [Parameter] public SearchInputIcon Icon { get; set; } - private EditContext? EditContext; - protected override void OnInitialized() { Text = string.Empty; - EditContext = new EditContext(Text); - - EditContext.OnFieldChanged += async (s, e) => - { - await TextChanged.InvokeAsync(Text); - }; } - private void HandleClearClicked() + public void SetText(string str) + { + Text = str; + } + + private async Task HandleTextChanged() + { + await TextChanged.InvokeAsync(Text); + } + + private async Task HandleClearClicked() { Text = string.Empty; + await ClearClicked.InvokeAsync(); + } + private async Task HandleSearchClicked() + { + await SearchClicked.InvokeAsync(); } } \ No newline at end of file diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor.css b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor.css index 552ef2f..17aca87 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor.css +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor.css @@ -51,3 +51,8 @@ .search-icon svg { fill: var(--white); } + + .search-icon.dropdown svg { + fill: var(--violet); + transform: scale(.8, .5); + } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Components/SelectListElement.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Components/SelectListElement.razor.cs index c37d70b..903d3e1 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Components/SelectListElement.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Components/SelectListElement.razor.cs @@ -1,3 +1,4 @@ +using GameIdeas.BlazorApp.Shared.Components.Select.Models; using Microsoft.AspNetCore.Components; namespace GameIdeas.BlazorApp.Shared.Components.Select.Components; @@ -11,6 +12,7 @@ public partial class SelectListElement { if (Value != null) { + Value.IsSelected = true; await ValueChanged.InvokeAsync(Value); } } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Components/SelectListElement.razor.css b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Components/SelectListElement.razor.css index 792c973..8f975aa 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Components/SelectListElement.razor.css +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Components/SelectListElement.razor.css @@ -28,15 +28,14 @@ .navigation { padding: 4px 8px; } - -.navigation .selected { - display: none; -} - .navigation:hover { background: var(--violet-selected); } + .navigation .selected { + display: none; + } + /***** Sort Theme *****/ .sort { padding: 2px 6px; @@ -46,9 +45,23 @@ background: var(--low-white); } -.sort .select-label { - text-wrap: nowrap; - margin-right: 6px; + .sort .select-label { + text-wrap: nowrap; + margin-right: 6px; + } + +/***** Filter Theme *****/ +.filter { + padding: 2px 6px; } + .filter:hover { + background: var(--low-white); + } + + .filter .select-label { + text-wrap: nowrap; + margin-right: 6px; + } + diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/SelectElement.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Models/SelectElement.cs similarity index 76% rename from src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/SelectElement.cs rename to src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Models/SelectElement.cs index 6815c78..5e0e8f4 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/SelectElement.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Models/SelectElement.cs @@ -1,4 +1,4 @@ -namespace GameIdeas.BlazorApp.Shared.Components.Select; +namespace GameIdeas.BlazorApp.Shared.Components.Select.Models; public class SelectElement { diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/SelectTheme.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Models/SelectTheme.cs similarity index 51% rename from src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/SelectTheme.cs rename to src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Models/SelectTheme.cs index f3bb87f..f0c1d1f 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/SelectTheme.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/Models/SelectTheme.cs @@ -1,4 +1,4 @@ -namespace GameIdeas.BlazorApp.Shared.Components.Select; +namespace GameIdeas.BlazorApp.Shared.Components.Select.Models; public enum SelectListTheme { diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/MultipleSelectList.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/MultipleSelectList.razor index 05e534f..8a5b730 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/MultipleSelectList.razor +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/MultipleSelectList.razor @@ -2,13 +2,15 @@ @using GameIdeas.BlazorApp.Shared.Components.Select.Components @typeparam TItem -
-
- +
+
+
-
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/MultipleSelectList.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/MultipleSelectList.razor.cs index 727513b..621f0d5 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/MultipleSelectList.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/MultipleSelectList.razor.cs @@ -1,3 +1,5 @@ +using GameIdeas.BlazorApp.Shared.Components.Search; +using GameIdeas.BlazorApp.Shared.Components.Select.Models; using Microsoft.AspNetCore.Components; namespace GameIdeas.BlazorApp.Shared.Components.Select; @@ -11,41 +13,31 @@ public partial class MultipleSelectList [Parameter] public bool AlignRight { get; set; } private bool ContentVisile = false; - private DateTime ContentLastFocusOut = DateTime.Now; - private ElementReference Container; - private string? Text; + private SearchInput? SearchInput; - public async Task OpenAsync() - { - if (DateTime.Now - ContentLastFocusOut >= TimeSpan.FromSeconds(0.2)) - { - await Container.FocusAsync(); - ContentVisile = true; - } - } + public void Open() => ContentVisile = true; public void Close() => ContentVisile = false; - private async Task HandleButtonClicked() => await OpenAsync(); + private void HandleFocusOut() => Close(); - private void HandleFocusOut() - { - ContentLastFocusOut = DateTime.Now; - ContentVisile = true; - } + private void HandleFocusIn() => Open(); private async Task HandleItemClicked(SelectElement selectedValue) { selectedValue.IsSelected = !selectedValue.IsSelected; Values = Items.Where(x => x.IsSelected && x.Item != null).Select(x => x.Item!); - Text = string.Join(", ", Values); + SearchInput?.SetText(string.Join(", ", Values)); await ValuesChanged.InvokeAsync(Values); } - private void HandleTextChanged(string args) + + private void HandleTextChanged() { foreach (var item in Items) { item.IsSelected = false; } + + Close(); } } \ No newline at end of file diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/MultipleSelectList.razor.css b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/MultipleSelectList.razor.css index 3c7930d..0884707 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/MultipleSelectList.razor.css +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/MultipleSelectList.razor.css @@ -1 +1,49 @@ -@import "SelectList.razor.css"; +.select-list { + position: relative; +} + +.select-container { + margin-top: 4px; + position: absolute; +} + +.align-right { + right: 0; +} + +.select-content { + overflow: hidden; + display: flex; + flex-direction: column; + border-radius: var(--small-radius); + animation-name: fade-in; + animation-duration: 0.4s; +} + +.line { + margin: 2px 6px; + border-bottom: 2px solid var(--low-white); +} + + +/***** Navigation Theme *****/ +.select-content.navigation { + background: var(--violet); + box-shadow: var(--drop-shadow); +} + +/***** Sort Theme *****/ +.select-content.sort { + background: var(--semi-black); + box-shadow: var(--drop-shadow); + padding: 4px 0; +} + +/***** Filter Theme *****/ +.select-content.filter { + background: var(--semi-black); + box-shadow: var(--drop-shadow); + padding: 4px 0; + min-width: 150px; +} + diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/SelectList.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/SelectList.razor.cs index 13e6254..59423dd 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/SelectList.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Select/SelectList.razor.cs @@ -1,3 +1,4 @@ +using GameIdeas.BlazorApp.Shared.Components.Select.Models; using Microsoft.AspNetCore.Components; namespace GameIdeas.BlazorApp.Shared.Components.Select; @@ -34,7 +35,7 @@ public partial class SelectList private void HandleFocusOut() { ContentLastFocusOut = DateTime.Now; - ContentVisile = true; + ContentVisile = false; } private async Task HandleItemClicked(SelectElement selectedValue) 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 facfbda..3e5473b 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 @@ -38,4 +38,3 @@ box-shadow: var(--drop-shadow); padding: 4px 0; } - diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Layouts/Header/HeaderLayout.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Layouts/Header/HeaderLayout.razor.cs index 7dd8fdc..f3e335a 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Layouts/Header/HeaderLayout.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Layouts/Header/HeaderLayout.razor.cs @@ -1,6 +1,6 @@ using GameIdeas.BlazorApp.Pages.Games.Models; using GameIdeas.BlazorApp.Shared.Components.Account; -using GameIdeas.BlazorApp.Shared.Components.Select; +using GameIdeas.BlazorApp.Shared.Components.Select.Models; using GameIdeas.Resources; using Microsoft.AspNetCore.Components;