Create game from form (#15)
Co-authored-by: Maxime Adler <madler@sqli.com> Reviewed-on: #15
This commit was merged in pull request #15.
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
.backdrop-filter {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
inset: 0;
|
||||
z-index: var(--index-backdrop);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<div class="overlay"> <div class="loader"></div> </div>
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: var(--overlay);
|
||||
}
|
||||
|
||||
.loader {
|
||||
border: 8px solid var(--violet-selected);
|
||||
border-top: 8px solid var(--violet);
|
||||
border-radius: 50%;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@@ -2,17 +2,20 @@
|
||||
@using GameIdeas.BlazorApp.Shared.Constants
|
||||
|
||||
<CascadingValue Value="this">
|
||||
<div class="popup-wrapper" style="@GetDisplayStyle()">
|
||||
<div class="popup-content">
|
||||
@if (Closable)
|
||||
{
|
||||
<button @onclick="HandleBackdropFilterClicked">@Icons.Shared.Close</button>
|
||||
}
|
||||
@ChildContent
|
||||
@if (IsOpen)
|
||||
{
|
||||
<div class="popup-wrapper">
|
||||
<div class="popup-content">
|
||||
@if (Closable)
|
||||
{
|
||||
<button @onclick="HandleBackdropFilterClicked">@Icons.Shared.Close</button>
|
||||
}
|
||||
@ChildContent
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</CascadingValue>
|
||||
|
||||
|
||||
<BackdropFilter @ref="BackdropFilter" OnClick="HandleBackdropFilterClicked" CloseOnClick="@Closable"
|
||||
AllowBodyScroll="false" Color="BackdropFilterColor.Overlay" />
|
||||
AllowBodyScroll="true" Color="BackdropFilterColor.Overlay" />
|
||||
@@ -5,11 +5,9 @@ namespace GameIdeas.BlazorApp.Shared.Components.Popup;
|
||||
public partial class Popup
|
||||
{
|
||||
[Parameter] public RenderFragment? ChildContent { get; set; }
|
||||
[Parameter] public bool IsDrawerOpen { get; set; }
|
||||
[Parameter] public EventCallback BackdropFilterClicked { get; set; }
|
||||
[Parameter] public bool Closable { get; set; } = true;
|
||||
public bool IsOpen { get; set; }
|
||||
public EventHandler<bool>? StateChanged { get; set; }
|
||||
|
||||
private BackdropFilter.BackdropFilter? BackdropFilter;
|
||||
|
||||
@@ -31,7 +29,6 @@ public partial class Popup
|
||||
{
|
||||
IsOpen = true;
|
||||
await BackdropFilter?.Show()!;
|
||||
StateChanged?.Invoke(null, IsOpen);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
@@ -39,7 +36,6 @@ public partial class Popup
|
||||
{
|
||||
IsOpen = false;
|
||||
await BackdropFilter?.Hide()!;
|
||||
StateChanged?.Invoke(null, IsOpen);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
@@ -47,6 +43,4 @@ public partial class Popup
|
||||
{
|
||||
await BackdropFilterClicked.InvokeAsync();
|
||||
}
|
||||
|
||||
private string GetDisplayStyle() => IsOpen ? "display: flex;" : "display: none;";
|
||||
}
|
||||
@@ -1,15 +1,13 @@
|
||||
.popup-wrapper {
|
||||
display: none;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
display: flex;
|
||||
justify-self: anchor-center;
|
||||
align-self: anchor-center;
|
||||
position: absolute;
|
||||
z-index: var(--index-popup);
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background-color: var(--dropdown-content);
|
||||
padding: 10px;
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
type="text"
|
||||
class="search-field"
|
||||
placeholder="@Placeholder"
|
||||
disabled="@IsDisable"
|
||||
style="@(IsDisable ? "pointer-events: none" : "")"
|
||||
@bind=@Text
|
||||
@bind:event="oninput"
|
||||
@bind:after=HandleTextChanged
|
||||
|
||||
@@ -8,6 +8,7 @@ public partial class SearchInput
|
||||
{
|
||||
[Parameter] public string? Text { get; set; }
|
||||
[Parameter] public string? Placeholder { get; set; }
|
||||
[Parameter] public bool IsDisable { get; set; }
|
||||
[Parameter] public EventCallback<string> TextChanged { get; set; }
|
||||
[Parameter] public EventCallback ClearClicked { get; set; }
|
||||
[Parameter] public EventCallback SearchClicked { get; set; }
|
||||
@@ -39,13 +40,17 @@ public partial class SearchInput
|
||||
}
|
||||
private async Task HandleSearchClicked()
|
||||
{
|
||||
await TextChanged.InvokeAsync(Text);
|
||||
await SearchClicked.InvokeAsync();
|
||||
await InputText.FocusAsync();
|
||||
if (!IsDisable)
|
||||
{
|
||||
await SearchClicked.InvokeAsync();
|
||||
}
|
||||
}
|
||||
private async Task HandleFocusIn()
|
||||
{
|
||||
await FocusIn.InvokeAsync();
|
||||
if (!IsDisable)
|
||||
{
|
||||
await FocusIn.InvokeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private MarkupString GetSearchIcon()
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
height: 20px;
|
||||
align-items: center;
|
||||
padding: 2px 6px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.select-element:hover {
|
||||
cursor: pointer;
|
||||
background: var(--input-selected);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
public class SelectParams<TItem, THeader>
|
||||
{
|
||||
public List<TItem> Items { get; set; } = [];
|
||||
public TItem? DefaultItem { get; set; }
|
||||
public List<TItem> DefaultItems { get; set; } = [];
|
||||
public Func<TItem, string> GetItemLabel { get; set; } = _ => string.Empty;
|
||||
public List<THeader> Headers { get; set; } = [];
|
||||
public THeader? DefaultHeader { get; set; }
|
||||
public List<THeader> DefaultHeaders { get; set; } = [];
|
||||
public Func<THeader, string> GetHeaderLabel { get; set; } = _ => string.Empty;
|
||||
public Func<string, TItem>? AddItem { get; set; }
|
||||
|
||||
}
|
||||
|
||||
@@ -14,9 +14,20 @@
|
||||
@if (IsContentOpen)
|
||||
{
|
||||
<div class="content">
|
||||
@if (QuickAdd)
|
||||
{
|
||||
<div class="add-item">
|
||||
<EditForm EditContext="QuickAddEditContext" OnSubmit="HandleSubmitAdd">
|
||||
<input type="text" placeholder="@ResourcesKey.PlaceholderAdd" @bind=AddLabel>
|
||||
</EditForm>
|
||||
</div>
|
||||
|
||||
<span class="line"></span>
|
||||
}
|
||||
|
||||
@if (Params.Headers != null)
|
||||
{
|
||||
@foreach (var header in Params.Headers)
|
||||
@foreach (var header in Params.Headers.Union(HeaderValues ?? []))
|
||||
{
|
||||
<SelectRow IsSelected=HeaderValues?.Contains(header)
|
||||
Label="@Params.GetHeaderLabel(header)" Theme=Theme
|
||||
@@ -24,14 +35,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
@if (Params.Headers?.Any() == true)
|
||||
@if (Params.Headers?.Count != 0)
|
||||
{
|
||||
<span class="line"></span>
|
||||
}
|
||||
|
||||
@if (Params.Items != null)
|
||||
{
|
||||
@foreach (var item in Params.Items)
|
||||
@foreach (var item in Params.Items.Union(Values ?? []))
|
||||
{
|
||||
<SelectRow IsSelected=Values?.Contains(item)
|
||||
Label="@Params.GetItemLabel(item)" Theme=Theme
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
using GameIdeas.BlazorApp.Shared.Components.Select.Models;
|
||||
using GameIdeas.Resources;
|
||||
using GameIdeas.Shared.Constants;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace GameIdeas.BlazorApp.Shared.Components.Select;
|
||||
|
||||
@@ -14,37 +18,48 @@ public partial class Select<TItem, THeader>
|
||||
[Parameter] public SelectTheme Theme { get; set; }
|
||||
[Parameter] public SelectType Type { get; set; } = SelectType.Single;
|
||||
[Parameter] public bool DisableClicked { get; set; } = false;
|
||||
[Parameter] public bool QuickAdd { get; set; } = false;
|
||||
|
||||
private bool IsContentOpen = false;
|
||||
private string AddLabel = string.Empty;
|
||||
private EditContext? QuickAddEditContext;
|
||||
|
||||
public void Close() =>
|
||||
IsContentOpen = false;
|
||||
|
||||
public void Open() =>
|
||||
IsContentOpen = true;
|
||||
|
||||
private void HandleButtonClicked()
|
||||
public void Close()
|
||||
{
|
||||
if (!DisableClicked)
|
||||
IsContentOpen = !IsContentOpen;
|
||||
IsContentOpen = false;
|
||||
}
|
||||
|
||||
private void HandleContentClosed() =>
|
||||
IsContentOpen = false;
|
||||
public void Open()
|
||||
{
|
||||
IsContentOpen = true;
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
if (Params.DefaultItem != null)
|
||||
QuickAddEditContext = new EditContext(AddLabel);
|
||||
|
||||
if (Params.DefaultItems.Count != 0)
|
||||
{
|
||||
Values.Add(Params.DefaultItem);
|
||||
Values.AddRange(Params.DefaultItems);
|
||||
}
|
||||
|
||||
if (Params.DefaultHeader != null)
|
||||
if (Params.DefaultHeaders.Count != 0)
|
||||
{
|
||||
HeaderValues.Add(Params.DefaultHeader);
|
||||
HeaderValues.AddRange(Params.DefaultHeaders);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleButtonClicked()
|
||||
{
|
||||
if (!DisableClicked && IsContentOpen)
|
||||
Close();
|
||||
|
||||
if (!DisableClicked && !IsContentOpen)
|
||||
Open();
|
||||
}
|
||||
|
||||
private void HandleContentClosed() => Close();
|
||||
|
||||
private async Task HandleValueClicked(TItem value)
|
||||
{
|
||||
if (Type != SelectType.Multiple || Values == null)
|
||||
@@ -82,4 +97,16 @@ public partial class Select<TItem, THeader>
|
||||
|
||||
await HeaderValuesChanged.InvokeAsync(HeaderValues);
|
||||
}
|
||||
private async Task HandleSubmitAdd()
|
||||
{
|
||||
if (Params.AddItem != null)
|
||||
{
|
||||
Values ??= [];
|
||||
Values.Add(Params.AddItem(AddLabel));
|
||||
|
||||
AddLabel = string.Empty;
|
||||
|
||||
await ValuesChanged.InvokeAsync(Values);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,8 @@
|
||||
}
|
||||
|
||||
.button {
|
||||
z-index: var(--index-component)
|
||||
z-index: var(--index-component);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
@@ -29,6 +30,20 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.add-item {
|
||||
align-content: center;
|
||||
height: 24px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.add-item input {
|
||||
width: 100%;
|
||||
color: var(--white);
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.dropdown::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
@@ -72,4 +87,16 @@
|
||||
border-bottom: 2px solid var(--input-selected);
|
||||
}
|
||||
|
||||
/***** Sort Theme *****/
|
||||
.creation .content {
|
||||
border-radius: var(--small-radius);
|
||||
box-sizing: border-box;
|
||||
border: solid 1px var(--violet);
|
||||
}
|
||||
|
||||
.creation .content .line {
|
||||
display: block;
|
||||
margin: 2px 6px;
|
||||
border-bottom: 2px solid var(--input-selected);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
@typeparam TItem
|
||||
|
||||
<Select @ref=Select TItem="TItem" THeader="string" Theme="Theme" Type="SelectType.Multiple" DisableClicked=true
|
||||
Params="SelectParams" Values=Values ValuesChanged="HandleValuesChanged">
|
||||
<Select @ref=Select TItem="TItem" THeader="string" Theme="Theme" Type="SelectType.Multiple"
|
||||
Params="SelectParams" Values=Values ValuesChanged="HandleValuesChanged" QuickAdd=QuickAdd>
|
||||
|
||||
<div class="@SelectHelper.GetClassFromTheme(Theme)">
|
||||
<SearchInput @ref=SearchInput Icon="SearchInputIcon.Dropdown" Placeholder="@Placeholder"
|
||||
TextChanged="HandleClearClicked" ClearClicked="HandleClearClicked"
|
||||
TextChanged="HandleClearClicked" ClearClicked="HandleClearClicked" IsDisable=QuickAdd
|
||||
FocusIn="HandleFocusIn" SearchClicked="HandleFocusIn" />
|
||||
</div>
|
||||
|
||||
|
||||
@@ -13,16 +13,20 @@ public partial class SelectSearch<TItem>
|
||||
[Parameter] public List<TItem> Values { get; set; } = [];
|
||||
[Parameter] public EventCallback<List<TItem>> ValuesChanged { get; set; }
|
||||
[Parameter] public string Placeholder { get; set; } = string.Empty;
|
||||
[Parameter] public bool QuickAdd { get; set; } = false;
|
||||
[Parameter] public Func<string, TItem>? AddItem { get; set; }
|
||||
|
||||
private SelectParams<TItem, string> SelectParams = new();
|
||||
private SearchInput? SearchInput;
|
||||
private Select<TItem, string>? Select;
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
SelectParams = new()
|
||||
{
|
||||
Items = Items,
|
||||
GetItemLabel = GetLabel
|
||||
GetItemLabel = GetLabel,
|
||||
AddItem = AddItem
|
||||
};
|
||||
|
||||
base.OnParametersSet();
|
||||
@@ -31,12 +35,13 @@ public partial class SelectSearch<TItem>
|
||||
{
|
||||
Values = values.ToList();
|
||||
SearchInput?.SetText(string.Join(", ", Values.Select(GetLabel)));
|
||||
await ValuesChanged.InvokeAsync(values.ToList());
|
||||
await ValuesChanged.InvokeAsync(Values.ToList());
|
||||
}
|
||||
|
||||
private void HandleClearClicked()
|
||||
private async Task HandleClearClicked()
|
||||
{
|
||||
Values = [];
|
||||
await ValuesChanged.InvokeAsync(Values.ToList());
|
||||
}
|
||||
|
||||
private void HandleFocusIn()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
z-index: var(--index-component)
|
||||
z-index: 0
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
z-index: var(--index-component)
|
||||
z-index: 0
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
|
||||
@@ -4,7 +4,7 @@ public static class Endpoints
|
||||
{
|
||||
public static class Game
|
||||
{
|
||||
|
||||
public static readonly string Create = "api/Game/Create";
|
||||
}
|
||||
|
||||
public static class Category
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace GameIdeas.BlazorApp.Shared.Exceptions;
|
||||
|
||||
public class GameCreationException(string message) : Exception(message);
|
||||
Reference in New Issue
Block a user