Add frontend creation game #13
@@ -5,8 +5,8 @@
|
|||||||
@Body
|
@Body
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="background">
|
||||||
<span class="orb red"></span>
|
<span class="orb red"></span>
|
||||||
<span class="orb blue"></span>
|
<span class="orb blue"></span>
|
||||||
<span class="orb green"></span>
|
<span class="orb green"></span>
|
||||||
|
</div>
|
||||||
<div class="background"></div>
|
|
||||||
@@ -37,10 +37,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.background {
|
.background {
|
||||||
height: 100%;
|
height: 100vh;
|
||||||
width: 100%;
|
width: 100vw;
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
overflow: hidden;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: var(--index-background);
|
z-index: var(--index-background);
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
@using GameIdeas.BlazorApp.Shared.Components.Select
|
||||||
|
@using GameIdeas.BlazorApp.Shared.Components.Select.Models
|
||||||
|
@using GameIdeas.BlazorApp.Shared.Components.Slider
|
||||||
|
@using GameIdeas.Shared.Dto
|
||||||
|
|
||||||
|
<EditForm EditContext="EditContext" OnSubmit="HandleOnSubmit">
|
||||||
|
<div class="game-form">
|
||||||
|
<div class="container">
|
||||||
|
<div class="input-game">
|
||||||
|
<div id="first-label" class="label">@ResourcesKey.Title :</div>
|
||||||
|
<input type="text" class="title" @bind=GameDto.Title>
|
||||||
|
</div>
|
||||||
|
<div class="input-game">
|
||||||
|
<div class="label">@ResourcesKey.ReleaseDate :</div>
|
||||||
|
<input type="date" class="date" @bind=GameDto.ReleaseDate>
|
||||||
|
</div>
|
||||||
|
<div class="input-game">
|
||||||
|
<div class="label">@ResourcesKey.StorageSizeMo :</div>
|
||||||
|
<input type="number" class="storage" @bind=GameDto.StorageSpace>
|
||||||
|
</div>
|
||||||
|
<div class="input-game">
|
||||||
|
<div class="label">@ResourcesKey.Developers :</div>
|
||||||
|
<MultipleSelectList TItem="DeveloperDto" Theme="SelectListTheme" @bind-Values=GameDto.Developers
|
||||||
|
Items="CategoriesDto?.Developers?.Select(d => new SelectElement<DeveloperDto>(d, d.Name))" />
|
||||||
|
</div>
|
||||||
|
<div class="input-game">
|
||||||
|
<div class="label">@ResourcesKey.Publishers :</div>
|
||||||
|
<MultipleSelectList TItem="PublisherDto" Theme="SelectListTheme" @bind-Values=GameDto.Publishers
|
||||||
|
Items="CategoriesDto?.Publishers?.Select(p => new SelectElement<PublisherDto>(p, p.Name))" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container">
|
||||||
|
<div class="input-game">
|
||||||
|
<div class="label">@ResourcesKey.Interest :</div>
|
||||||
|
<div class="slider">
|
||||||
|
<Slider Params="SliderParams" @bind-Value="GameDto.Interest" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input-game">
|
||||||
|
<div class="label">@ResourcesKey.Properties :</div>
|
||||||
|
<MultipleSelectList TItem="PropertyDto" Theme="SelectListTheme" @bind-Values=GameDto.Properties
|
||||||
|
Items="CategoriesDto?.Properties?.Select(p => new SelectElement<PropertyDto>(p, p.Label))" />
|
||||||
|
</div>
|
||||||
|
<div class="input-game">
|
||||||
|
<div class="label">@ResourcesKey.Genres :</div>
|
||||||
|
<MultipleSelectList TItem="TagDto" Theme="SelectListTheme" @bind-Values=GameDto.Tags
|
||||||
|
Items="CategoriesDto?.Tags?.Select(t => new SelectElement<TagDto>(t, t.Label))" />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="input-game">
|
||||||
|
<div class="label">@ResourcesKey.Platforms :</div>
|
||||||
|
<MultipleSelectList TItem="PlatformDto" Theme="SelectListTheme" @bind-Values=GameDto.Platforms
|
||||||
|
Items="CategoriesDto?.Platforms?.Select(p => new SelectElement<PlatformDto>(p, p.Label))" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="description-container">
|
||||||
|
<div id="label-description">@ResourcesKey.Description :</div>
|
||||||
|
<input type="text" class="description" @bind-value=GameDto.Description>
|
||||||
|
</div>
|
||||||
|
<div class="buttons">
|
||||||
|
<button type="reset" class="cancel" @onclick=HandleOnCancel>
|
||||||
|
@ResourcesKey.Reset
|
||||||
|
</button>
|
||||||
|
<button type="submit" class="submit">
|
||||||
|
@ResourcesKey.Save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</EditForm>
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
using GameIdeas.BlazorApp.Pages.Games.Gateways;
|
||||||
|
using GameIdeas.BlazorApp.Shared.Components.Popup;
|
||||||
|
using GameIdeas.BlazorApp.Shared.Components.Select.Models;
|
||||||
|
using GameIdeas.BlazorApp.Shared.Components.Slider;
|
||||||
|
using GameIdeas.Shared.Dto;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Microsoft.AspNetCore.Components.Forms;
|
||||||
|
using Microsoft.JSInterop;
|
||||||
|
|
||||||
|
namespace GameIdeas.BlazorApp.Pages.Games.Components;
|
||||||
|
|
||||||
|
public partial class GameCreationForm
|
||||||
|
{
|
||||||
|
[Inject] private IJSRuntime Js { get; set; } = default!;
|
||||||
|
[Inject] private IGameGateway GameGateway { get; set; } = default!;
|
||||||
|
[CascadingParameter] private Popup? Popup { get; set; }
|
||||||
|
|
||||||
|
private GameDto GameDto = new();
|
||||||
|
private CategoriesDto CategoriesDto = new();
|
||||||
|
private EditContext? EditContext;
|
||||||
|
private readonly SelectListTheme SelectListTheme = SelectListTheme.Creation;
|
||||||
|
private readonly SliderParams SliderParams = new() { Gap = 1, Min = 1, Max = 5 };
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
EditContext = new(GameDto);
|
||||||
|
CategoriesDto = await GameGateway.FetchCategories();
|
||||||
|
|
||||||
|
if (Popup != null)
|
||||||
|
{
|
||||||
|
Popup.StateChanged += async (_, isOpen) => await HandlePopupStateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandlePopupStateChanged()
|
||||||
|
{
|
||||||
|
await Js.InvokeVoidAsync("resizeGameForm");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleOnCancel()
|
||||||
|
{
|
||||||
|
Popup?.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandleOnSubmit(EditContext args)
|
||||||
|
{
|
||||||
|
if (EditContext?.Validate() == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
.game-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-game {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 200px;
|
||||||
|
grid-gap: 8px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
text-wrap: nowrap;
|
||||||
|
align-content: center;
|
||||||
|
font-weight: bold;
|
||||||
|
grid-column: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
background: var(--input-secondary);
|
||||||
|
border: solid 1px var(--input-selected);
|
||||||
|
outline: none;
|
||||||
|
border-radius: var(--small-radius);
|
||||||
|
grid-column: 2;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: var(--white);
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="date"]::-webkit-calendar-picker-indicator {
|
||||||
|
filter: invert(1);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description-container {
|
||||||
|
margin-top: 8px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
grid-gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
min-height: 140px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#label-description {
|
||||||
|
text-wrap: nowrap;
|
||||||
|
align-content: center;
|
||||||
|
font-weight: bold;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider {
|
||||||
|
padding: 0 20px;
|
||||||
|
align-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"]::-webkit-inner-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
window.resizeGameForm = () => {
|
||||||
|
const label = document.getElementById('first-label');
|
||||||
|
const targetLabel = document.getElementById('label-description');
|
||||||
|
targetLabel.style.width = window.getComputedStyle(label).getPropertyValue("width");
|
||||||
|
};
|
||||||
@@ -5,46 +5,39 @@
|
|||||||
|
|
||||||
<div class="duplicate">
|
<div class="duplicate">
|
||||||
<MultipleSelectList TItem="string"
|
<MultipleSelectList TItem="string"
|
||||||
Items="Plateforms"
|
@bind-Values=GameFilterParams!.Platforms
|
||||||
@bind-Values=GameFilterParams!.Plateforms
|
|
||||||
Placeholder="@ResourcesKey.Platforms"
|
Placeholder="@ResourcesKey.Platforms"
|
||||||
Theme="SelectListTheme.AdvancedFilter" />
|
Theme="SelectListTheme.AdvancedFilter" />
|
||||||
|
|
||||||
<MultipleSelectList TItem="string"
|
<MultipleSelectList TItem="string"
|
||||||
Items="Genres"
|
|
||||||
Placeholder="@ResourcesKey.Genres"
|
Placeholder="@ResourcesKey.Genres"
|
||||||
@bind-Values=GameFilterParams!.Genres
|
@bind-Values=GameFilterParams!.Tags
|
||||||
Theme="SelectListTheme.AdvancedFilter" />
|
Theme="SelectListTheme.AdvancedFilter" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<MultipleSelectList TItem="string"
|
<MultipleSelectList TItem="string"
|
||||||
Items="Publishers"
|
|
||||||
Placeholder="@ResourcesKey.Publishers"
|
Placeholder="@ResourcesKey.Publishers"
|
||||||
@bind-Values=GameFilterParams!.Publishers
|
@bind-Values=GameFilterParams!.Publishers
|
||||||
Theme="SelectListTheme.AdvancedFilter" />
|
Theme="SelectListTheme.AdvancedFilter" />
|
||||||
|
|
||||||
<MultipleSelectList TItem="string"
|
<MultipleSelectList TItem="string"
|
||||||
Items="Developers"
|
|
||||||
Placeholder="@ResourcesKey.Developers"
|
Placeholder="@ResourcesKey.Developers"
|
||||||
@bind-Values=GameFilterParams!.Developers
|
@bind-Values=GameFilterParams!.Developers
|
||||||
Theme="SelectListTheme.AdvancedFilter" />
|
Theme="SelectListTheme.AdvancedFilter" />
|
||||||
|
|
||||||
<MultipleSelectList TItem="string"
|
<MultipleSelectList TItem="string"
|
||||||
Items="StorageSizes"
|
Placeholder="@ResourcesKey.StorageSize"
|
||||||
Placeholder="@ResourcesKey.StorageSizes"
|
|
||||||
@bind-Values=GameFilterParams!.StorageSizes
|
@bind-Values=GameFilterParams!.StorageSizes
|
||||||
Theme="SelectListTheme.AdvancedFilter" />
|
Theme="SelectListTheme.AdvancedFilter" />
|
||||||
|
|
||||||
<MultipleSelectList TItem="string"
|
<MultipleSelectList TItem="string"
|
||||||
Items="LastModifiedDates"
|
|
||||||
Placeholder="@ResourcesKey.LastModification"
|
Placeholder="@ResourcesKey.LastModification"
|
||||||
@bind-Values=GameFilterParams!.LastModification
|
@bind-Values=GameFilterParams!.LastModification
|
||||||
Theme="SelectListTheme.AdvancedFilter" />
|
Theme="SelectListTheme.AdvancedFilter" />
|
||||||
|
|
||||||
<MultipleSelectList TItem="string"
|
<MultipleSelectList TItem="string"
|
||||||
Items="ReleaseDates"
|
Placeholder="@ResourcesKey.ReleaseDate"
|
||||||
Placeholder="@ResourcesKey.ReleaseDates"
|
|
||||||
@bind-Values=GameFilterParams!.ReleaseDates
|
@bind-Values=GameFilterParams!.ReleaseDates
|
||||||
Theme="SelectListTheme.AdvancedFilter" />
|
Theme="SelectListTheme.AdvancedFilter" />
|
||||||
|
|
||||||
|
|||||||
@@ -7,56 +7,4 @@ public partial class AdvancedGameFilter
|
|||||||
{
|
{
|
||||||
[Parameter] public GameFilterParams? GameFilterParams { get; set; }
|
[Parameter] public GameFilterParams? GameFilterParams { get; set; }
|
||||||
[Parameter] public EventCallback<GameFilterParams> GameFilterParamsChanged { get; set; }
|
[Parameter] public EventCallback<GameFilterParams> GameFilterParamsChanged { get; set; }
|
||||||
|
|
||||||
|
|
||||||
private readonly IEnumerable<SelectElement<string>> Plateforms = [
|
|
||||||
new() { Item = "Steam", Label = "Steam" },
|
|
||||||
new() { Item = "GOG", Label = "GOG" },
|
|
||||||
new() { Item = "Epic games", Label = "Epic games" },
|
|
||||||
new() { Item = "Ubisoft", Label = "Ubisoft" },
|
|
||||||
];
|
|
||||||
|
|
||||||
private readonly IEnumerable<SelectElement<string>> Genres = [
|
|
||||||
new() { Item = "Rogue Like", Label = "Rogue Like" },
|
|
||||||
new() { Item = "Aventure", Label = "Aventure" },
|
|
||||||
new() { Item = "RPG", Label = "RPG" },
|
|
||||||
new() { Item = "Fast FPS", Label = "Fast FPS" },
|
|
||||||
];
|
|
||||||
|
|
||||||
private readonly IEnumerable<SelectElement<string>> Publishers = [
|
|
||||||
new() { Item = "Electronic Arts", Label = "Electronic Arts" },
|
|
||||||
new() { Item = "Ubisoft", Label = "Ubisoft" },
|
|
||||||
new() { Item = "Activision Blizzard", Label = "Activision Blizzard" },
|
|
||||||
new() { Item = "Bethesda", Label = "Bethesda" }
|
|
||||||
];
|
|
||||||
|
|
||||||
private readonly IEnumerable<SelectElement<string>> Developers = [
|
|
||||||
new() { Item = "CD Projekt Red", Label = "CD Projekt Red" },
|
|
||||||
new() { Item = "Naughty Dog", Label = "Naughty Dog" },
|
|
||||||
new() { Item = "Rockstar Games", Label = "Rockstar Games" },
|
|
||||||
new() { Item = "FromSoftware", Label = "FromSoftware" },
|
|
||||||
];
|
|
||||||
|
|
||||||
private readonly IEnumerable<SelectElement<string>> StorageSizes = [
|
|
||||||
new() { Item = "1 Go", Label = "1 Go" },
|
|
||||||
new() { Item = "10 Go", Label = "10 Go" },
|
|
||||||
new() { Item = "50 Go", Label = "50 Go" },
|
|
||||||
new() { Item = "100 Go", Label = "100 Go" },
|
|
||||||
];
|
|
||||||
|
|
||||||
private readonly IEnumerable<SelectElement<string>> LastModifiedDates = [
|
|
||||||
new() { Item = "2023-12-15", Label = "15 D<>cembre 2023" },
|
|
||||||
new() { Item = "2024-01-20", Label = "20 Janvier 2024" },
|
|
||||||
new() { Item = "2024-02-05", Label = "5 F<>vrier 2024" },
|
|
||||||
new() { Item = "2024-03-10", Label = "10 Mars 2024" },
|
|
||||||
];
|
|
||||||
|
|
||||||
private readonly IEnumerable<SelectElement<string>> ReleaseDates = [
|
|
||||||
new() { Item = "2023-11-11", Label = "11 Novembre 2023" },
|
|
||||||
new() { Item = "2024-01-25", Label = "25 Janvier 2024" },
|
|
||||||
new() { Item = "2024-03-03", Label = "3 Mars 2024" },
|
|
||||||
new() { Item = "2024-04-15", Label = "15 Avril 2024" },
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4,13 +4,13 @@
|
|||||||
@using GameIdeas.BlazorApp.Shared.Components.SliderRange
|
@using GameIdeas.BlazorApp.Shared.Components.SliderRange
|
||||||
@using GameIdeas.BlazorApp.Shared.Models
|
@using GameIdeas.BlazorApp.Shared.Models
|
||||||
@using GameIdeas.Shared.Dto
|
@using GameIdeas.Shared.Dto
|
||||||
|
@using GameIdeas.Shared.Enum
|
||||||
|
|
||||||
<div class="form-filter">
|
<div class="form-filter">
|
||||||
<SelectList TItem="Func<GameDto, object>"
|
<SelectList TItem="Func<GameDto, object>" Items="GameProperties"
|
||||||
Headers="SortTypes"
|
@bind-Value=GameFilterParams.SortProperty
|
||||||
Items="GameProperties"
|
THeader="SortType" Headers="SortTypes"
|
||||||
@bind-Value=GameFilterParams!.SortProperty
|
@bind-Header=GameFilterParams.SortType
|
||||||
HeaderChanged=HandleSortTypeChanged
|
|
||||||
Theme="SelectListTheme.Sort">
|
Theme="SelectListTheme.Sort">
|
||||||
<div class="square-button">
|
<div class="square-button">
|
||||||
<svg class="sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
<svg class="sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
@@ -38,17 +38,15 @@
|
|||||||
|
|
||||||
<div class="select-container">
|
<div class="select-container">
|
||||||
<MultipleSelectList TItem="string"
|
<MultipleSelectList TItem="string"
|
||||||
Items="Plateforms"
|
|
||||||
Placeholder="@ResourcesKey.Platforms"
|
Placeholder="@ResourcesKey.Platforms"
|
||||||
@bind-Values=GameFilterParams.Plateforms
|
@bind-Values=GameFilterParams.Platforms
|
||||||
Theme="SelectListTheme.Filter" />
|
Theme="SelectListTheme.Filter" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="select-container">
|
<div class="select-container">
|
||||||
<MultipleSelectList TItem="string"
|
<MultipleSelectList TItem="string"
|
||||||
Items="Genres"
|
|
||||||
Placeholder="@ResourcesKey.Genres"
|
Placeholder="@ResourcesKey.Genres"
|
||||||
@bind-Values=GameFilterParams.Genres
|
@bind-Values=GameFilterParams.Tags
|
||||||
Theme="SelectListTheme.Filter" />
|
Theme="SelectListTheme.Filter" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -15,33 +15,19 @@ public partial class GameFilter
|
|||||||
[Parameter] public DisplayType DisplayType { get; set; }
|
[Parameter] public DisplayType DisplayType { get; set; }
|
||||||
[Parameter] public EventCallback<DisplayType> DisplayTypeChanged { get; set; }
|
[Parameter] public EventCallback<DisplayType> DisplayTypeChanged { get; set; }
|
||||||
|
|
||||||
private readonly IEnumerable<SelectElement<Func<GameDto?, object?>>> SortTypes = [
|
private readonly IEnumerable<SelectElement<SortType>> SortTypes = [
|
||||||
new() { Item = _ => SortType.Ascending, Label = "Ascendant", IsSelected = true },
|
new(SortType.Ascending, "Ascendant") { IsSelected = true },
|
||||||
new() { Item = _ => SortType.Descending, Label = "Descendant" }
|
new(SortType.Descending, "Descendant")
|
||||||
];
|
];
|
||||||
|
|
||||||
private readonly IEnumerable<SelectElement<Func<GameDto?, object?>>> GameProperties = [
|
private readonly IEnumerable<SelectElement<Func<GameDto?, object?>>> GameProperties = [
|
||||||
new() { Item = game => game?.Title, Label = "Nom", IsSelected = true },
|
new(game => game?.Title, "Nom") { IsSelected = true },
|
||||||
new() { Item = game => game?.ReleaseDate, Label = "Date de parution" }
|
new(game => game?.ReleaseDate, "Date de parution"),
|
||||||
];
|
|
||||||
|
|
||||||
private readonly IEnumerable<SelectElement<string>> Plateforms = [
|
|
||||||
new() { Item = "Steam", Label = "Steam" },
|
|
||||||
new() { Item = "GOG", Label = "GOG" },
|
|
||||||
new() { Item = "Epic games", Label = "Epic games" },
|
|
||||||
new() { Item = "Ubisoft", Label = "Ubisoft" },
|
|
||||||
];
|
|
||||||
|
|
||||||
private readonly IEnumerable<SelectElement<string>> Genres = [
|
|
||||||
new() { Item = "Rogue Like", Label = "Rogue Like" },
|
|
||||||
new() { Item = "Aventure", Label = "Aventure" },
|
|
||||||
new() { Item = "RPG", Label = "RPG" },
|
|
||||||
new() { Item = "Fast FPS", Label = "Fast FPS" },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
private EditContext? EditContext;
|
private EditContext? EditContext;
|
||||||
private readonly SliderRangeParams SliderRangeParams =
|
private readonly SliderRangeParams SliderRangeParams =
|
||||||
new() { Min = 1, ValueMin = 1, ValueMax = 5, Max = 5 };
|
new() { Min = 1, Max = 5 };
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
@@ -52,11 +38,6 @@ public partial class GameFilter
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleSortTypeChanged(Func<GameDto?, object?> getHeader)
|
|
||||||
{
|
|
||||||
GameFilterParams.SortType = (SortType?)getHeader(null) ?? SortType.Ascending;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task HandleDisplayClicked(DisplayType displayType)
|
private async Task HandleDisplayClicked(DisplayType displayType)
|
||||||
{
|
{
|
||||||
DisplayType = displayType;
|
DisplayType = displayType;
|
||||||
|
|||||||
@@ -5,16 +5,17 @@ namespace GameIdeas.BlazorApp.Pages.Games.Filter;
|
|||||||
|
|
||||||
public class GameFilterParams
|
public class GameFilterParams
|
||||||
{
|
{
|
||||||
public SortType? SortType { get; set; }
|
public SortType SortType { get; set; } = SortType.Ascending;
|
||||||
public Func<GameDto?, object?>? SortProperty { get; set; }
|
public Func<GameDto?, object?>? SortProperty { get; set; }
|
||||||
public string? SearchName { get; set; }
|
public string? SearchName { get; set; }
|
||||||
public IEnumerable<string>? Plateforms { get; set; }
|
public IEnumerable<string>? Platforms { get; set; }
|
||||||
public IEnumerable<string>? Genres { get; set; }
|
public IEnumerable<string>? Properties { get; set; }
|
||||||
|
public IEnumerable<string>? Tags { get; set; }
|
||||||
public IEnumerable<string>? Publishers { get; set; }
|
public IEnumerable<string>? Publishers { get; set; }
|
||||||
public IEnumerable<string>? Developers { get; set; }
|
public IEnumerable<string>? Developers { get; set; }
|
||||||
public IEnumerable<string>? StorageSizes { get; set; }
|
public IEnumerable<string>? StorageSizes { get; set; }
|
||||||
public IEnumerable<string>? LastModification { get; set; }
|
public IEnumerable<string>? LastModification { get; set; }
|
||||||
public IEnumerable<string>? ReleaseDates { get; set; }
|
public IEnumerable<string>? ReleaseDates { get; set; }
|
||||||
public int MaxRating { get; set; }
|
public int MaxRating { get; set; } = 5;
|
||||||
public int MinRating { get; set; }
|
public int MinRating { get; set; } = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,28 @@
|
|||||||
@page "/Games"
|
@page "/Games"
|
||||||
@using GameIdeas.BlazorApp.Layouts
|
@using GameIdeas.BlazorApp.Layouts
|
||||||
|
@using GameIdeas.BlazorApp.Pages.Games.Components
|
||||||
@using GameIdeas.BlazorApp.Pages.Games.Filter
|
@using GameIdeas.BlazorApp.Pages.Games.Filter
|
||||||
@using GameIdeas.BlazorApp.Pages.Games.Header
|
@using GameIdeas.BlazorApp.Pages.Games.Header
|
||||||
@using GameIdeas.BlazorApp.Shared.Components
|
@using GameIdeas.BlazorApp.Shared.Components
|
||||||
|
@using GameIdeas.BlazorApp.Shared.Components.Popup
|
||||||
@using GameIdeas.Resources
|
@using GameIdeas.Resources
|
||||||
|
|
||||||
@layout MainLayout
|
@layout MainLayout
|
||||||
|
|
||||||
<PageTitle>@ResourcesKey.GamesIdeas</PageTitle>
|
<PageTitle>@ResourcesKey.GamesIdeas</PageTitle>
|
||||||
|
|
||||||
<GameHeader>
|
<GameHeader AddTypeChanged="HandleAddClicked">
|
||||||
<GameFilter @bind-DisplayType=DisplayType
|
<GameFilter @bind-DisplayType=DisplayType
|
||||||
@bind-GameFilterParams=GameFilterParams />
|
@bind-GameFilterParams=GameFilterParams />
|
||||||
</GameHeader>
|
</GameHeader>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<AdvancedGameFilter @bind-GameFilterParams=GameFilterParams />
|
<AdvancedGameFilter @bind-GameFilterParams=GameFilterParams />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Popup @ref=ManualAddPopup BackdropFilterClicked="HandleBackdropManualAddClicked">
|
||||||
|
<GameCreationForm />
|
||||||
|
</Popup>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using GameIdeas.BlazorApp.Pages.Games.Filter;
|
using GameIdeas.BlazorApp.Pages.Games.Filter;
|
||||||
|
using GameIdeas.BlazorApp.Shared.Components.Popup;
|
||||||
using GameIdeas.BlazorApp.Shared.Models;
|
using GameIdeas.BlazorApp.Shared.Models;
|
||||||
|
|
||||||
namespace GameIdeas.BlazorApp.Pages.Games;
|
namespace GameIdeas.BlazorApp.Pages.Games;
|
||||||
@@ -7,4 +8,22 @@ public partial class GameBase ()
|
|||||||
{
|
{
|
||||||
private DisplayType DisplayType = DisplayType.List;
|
private DisplayType DisplayType = DisplayType.List;
|
||||||
private GameFilterParams GameFilterParams = new();
|
private GameFilterParams GameFilterParams = new();
|
||||||
|
private Popup? ManualAddPopup;
|
||||||
|
private void HandleAddClicked(AddType addType)
|
||||||
|
{
|
||||||
|
switch (addType)
|
||||||
|
{
|
||||||
|
case AddType.Manual:
|
||||||
|
ManualAddPopup?.Open();
|
||||||
|
break;
|
||||||
|
case AddType.Auto:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void HandleBackdropManualAddClicked()
|
||||||
|
{
|
||||||
|
ManualAddPopup?.Close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using GameIdeas.BlazorApp.Services;
|
||||||
|
using GameIdeas.BlazorApp.Shared.Constants;
|
||||||
|
using GameIdeas.BlazorApp.Shared.Exceptions;
|
||||||
|
using GameIdeas.Resources;
|
||||||
|
using GameIdeas.Shared.Dto;
|
||||||
|
|
||||||
|
namespace GameIdeas.BlazorApp.Pages.Games.Gateways;
|
||||||
|
|
||||||
|
public class GameGateway(IHttpClientService httpClientService) : IGameGateway
|
||||||
|
{
|
||||||
|
public async Task<CategoriesDto> FetchCategories()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await httpClientService.FetchDataAsync<CategoriesDto>(Endpoints.Category.AllCategories);
|
||||||
|
|
||||||
|
return result ?? throw new InvalidOperationException(ResourcesKey.ErrorFetchCategories);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
throw new CategoryNotFoundException(ResourcesKey.ErrorFetchCategories);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using GameIdeas.Shared.Dto;
|
||||||
|
|
||||||
|
namespace GameIdeas.BlazorApp.Pages.Games.Gateways;
|
||||||
|
|
||||||
|
public interface IGameGateway
|
||||||
|
{
|
||||||
|
Task<CategoriesDto> FetchCategories();
|
||||||
|
}
|
||||||
@@ -22,11 +22,9 @@
|
|||||||
<path d="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" />
|
<path d="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<SelectList TItem="AddType"
|
<SelectList @ref="SelectListAdd" TItem="AddType" Items="SelectElements"
|
||||||
Items="SelectElements"
|
ValueChanged=HandleAddTypeClickedAsync THeader="object"
|
||||||
ValueChanged=HandleAddTypeClickedAsync
|
Theme="SelectListTheme.Navigation" AlignRight=true>
|
||||||
Theme="SelectListTheme.Navigation"
|
|
||||||
AlignRight=true>
|
|
||||||
<div class="second-button button">
|
<div class="second-button button">
|
||||||
<svg class="button-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
<svg class="button-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M1 3H23L12 22" />
|
<path d="M1 3H23L12 22" />
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using GameIdeas.BlazorApp.Shared.Components.Account;
|
using GameIdeas.BlazorApp.Shared.Components.Account;
|
||||||
|
using GameIdeas.BlazorApp.Shared.Components.Select;
|
||||||
using GameIdeas.BlazorApp.Shared.Components.Select.Models;
|
using GameIdeas.BlazorApp.Shared.Components.Select.Models;
|
||||||
using GameIdeas.BlazorApp.Shared.Models;
|
using GameIdeas.BlazorApp.Shared.Models;
|
||||||
using GameIdeas.Resources;
|
using GameIdeas.Resources;
|
||||||
@@ -13,11 +14,12 @@ public partial class GameHeader : ComponentBase
|
|||||||
|
|
||||||
|
|
||||||
private readonly IEnumerable<SelectElement<AddType>> SelectElements = [
|
private readonly IEnumerable<SelectElement<AddType>> SelectElements = [
|
||||||
new SelectElement<AddType> { Item = AddType.Manual, Label = ResourcesKey.ManualAdd },
|
new SelectElement<AddType>(AddType.Manual, ResourcesKey.ManualAdd),
|
||||||
new SelectElement<AddType> { Item = AddType.Auto, Label = ResourcesKey.AutoAdd }
|
new SelectElement<AddType> (AddType.Auto, ResourcesKey.AutoAdd)
|
||||||
];
|
];
|
||||||
|
|
||||||
private AccountSettings? AccountSettings;
|
private AccountSettings? AccountSettings;
|
||||||
|
private SelectList<AddType, object>? SelectListAdd;
|
||||||
|
|
||||||
private void HandleIconClicked()
|
private void HandleIconClicked()
|
||||||
{
|
{
|
||||||
@@ -26,6 +28,7 @@ public partial class GameHeader : ComponentBase
|
|||||||
|
|
||||||
private async Task HandleAddTypeClickedAsync(AddType value)
|
private async Task HandleAddTypeClickedAsync(AddType value)
|
||||||
{
|
{
|
||||||
|
SelectListAdd?.Close();
|
||||||
await AddTypeChanged.InvokeAsync(value);
|
await AddTypeChanged.InvokeAsync(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using GameIdeas.BlazorApp;
|
using GameIdeas.BlazorApp;
|
||||||
|
using GameIdeas.BlazorApp.Pages.Games.Gateways;
|
||||||
using GameIdeas.BlazorApp.Services;
|
using GameIdeas.BlazorApp.Services;
|
||||||
using GameIdeas.Resources;
|
using GameIdeas.Resources;
|
||||||
using Microsoft.AspNetCore.Components.Web;
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
@@ -22,7 +23,8 @@ builder.Services.AddHttpClient(
|
|||||||
client.Timeout = TimeSpan.FromMinutes(3);
|
client.Timeout = TimeSpan.FromMinutes(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.Services.AddScoped<AuthentificationService>();
|
builder.Services.AddScoped<IHttpClientService, HttpClientService>();
|
||||||
|
builder.Services.AddScoped<IGameGateway, GameGateway>();
|
||||||
|
|
||||||
builder.Services.AddSingleton<TranslationService>();
|
builder.Services.AddSingleton<TranslationService>();
|
||||||
builder.Services.AddSingleton<Translations>();
|
builder.Services.AddSingleton<Translations>();
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
namespace GameIdeas.BlazorApp.Services;
|
|
||||||
|
|
||||||
public class AuthentificationService
|
|
||||||
{
|
|
||||||
private bool isLogin;
|
|
||||||
|
|
||||||
public bool IsLogin
|
|
||||||
{
|
|
||||||
get { return isLogin; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Login()
|
|
||||||
{
|
|
||||||
isLogin = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Logout()
|
|
||||||
{
|
|
||||||
isLogin = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
using GameIdeas.Resources;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace GameIdeas.BlazorApp.Services;
|
||||||
|
|
||||||
|
public class HttpClientService(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory) : IHttpClientService
|
||||||
|
{
|
||||||
|
private readonly HttpClient httpClient = httpClientFactory.CreateClient("GameIdeas.WebAPI");
|
||||||
|
private readonly ILogger<HttpClientService> logger = loggerFactory.CreateLogger<HttpClientService>();
|
||||||
|
|
||||||
|
private readonly JsonSerializerOptions _optionsCamelCase = new()
|
||||||
|
{
|
||||||
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly JsonSerializerOptions _optionsCaseInsensitive = new()
|
||||||
|
{
|
||||||
|
PropertyNameCaseInsensitive = true,
|
||||||
|
ReferenceHandler = ReferenceHandler.Preserve
|
||||||
|
};
|
||||||
|
|
||||||
|
public async Task<T?> PostAsync<T>(string url, object data)
|
||||||
|
{
|
||||||
|
var jsonContent = JsonSerializer.Serialize(data, _optionsCamelCase);
|
||||||
|
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
|
||||||
|
var response = await httpClient.PostAsync(url, content);
|
||||||
|
|
||||||
|
return await GetResultValue<T>(response, ResourcesKey.ErrorWhenPostingData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<T?> PutAsync<T>(string url, object data)
|
||||||
|
{
|
||||||
|
var jsonContent = JsonSerializer.Serialize(data, _optionsCamelCase);
|
||||||
|
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
|
||||||
|
var response = await httpClient.PutAsync(url, content);
|
||||||
|
|
||||||
|
return await GetResultValue<T>(response, ResourcesKey.ErrorWhenPutingData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<T?> DeleteAsync<T>(string? url)
|
||||||
|
{
|
||||||
|
var response = await httpClient.DeleteAsync(url);
|
||||||
|
|
||||||
|
return await GetResultValue<T>(response, ResourcesKey.ErrorWhenDeletingData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<T?> FetchDataAsync<T>(string? url)
|
||||||
|
{
|
||||||
|
var response = await httpClient.GetAsync(url);
|
||||||
|
|
||||||
|
return await GetResultValue<T>(response, ResourcesKey.ErrorWhenFetchingData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<byte[]?> FetchBytesAsync(string? url)
|
||||||
|
{
|
||||||
|
var response = await httpClient.GetAsync(url);
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
return await response.Content.ReadAsByteArrayAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new HttpRequestException(
|
||||||
|
$"{ResourcesKey.ErrorWhenFetchingData} + StatusCode: {response.StatusCode} " +
|
||||||
|
$"+ Reason: {response.ReasonPhrase}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Stream?> FetchStreamAsync(string? url)
|
||||||
|
{
|
||||||
|
var response = await httpClient.GetAsync(url);
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
return await response.Content.ReadAsStreamAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new HttpRequestException($"{ResourcesKey.ErrorWhenFetchingData} + StatusCode: {response.StatusCode} " +
|
||||||
|
$"+ Reason: {response.ReasonPhrase}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<T?> PostFileAsync<T>(string? url, Stream fileStream, string fileName, string contentType)
|
||||||
|
{
|
||||||
|
using var content = new MultipartFormDataContent();
|
||||||
|
|
||||||
|
var streamContent = new StreamContent(fileStream);
|
||||||
|
streamContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);
|
||||||
|
content.Add(streamContent, "file", fileName);
|
||||||
|
|
||||||
|
var response = await httpClient.PostAsync(url, content);
|
||||||
|
|
||||||
|
return await GetResultValue<T>(response, ResourcesKey.ErrorWhenPostingData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<T?> GetResultValue<T>(HttpResponseMessage response, string errorMessage)
|
||||||
|
{
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var responseContent = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(responseContent))
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = JsonSerializer.Deserialize<T>(responseContent, _optionsCaseInsensitive);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new JsonException(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogError(ResourcesKey.RequestFailedStatusFormat, response.StatusCode);
|
||||||
|
throw new HttpRequestException(
|
||||||
|
$"{errorMessage} + StatusCode: {response.StatusCode} + Reason: {response.ReasonPhrase}");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace GameIdeas.BlazorApp.Services;
|
||||||
|
|
||||||
|
public interface IHttpClientService
|
||||||
|
{
|
||||||
|
Task<T?> PostAsync<T>(string url, object data);
|
||||||
|
Task<T?> PutAsync<T>(string url, object data);
|
||||||
|
Task<T?> DeleteAsync<T>(string? url);
|
||||||
|
Task<T?> FetchDataAsync<T>(string? url);
|
||||||
|
Task<byte[]?> FetchBytesAsync(string? url);
|
||||||
|
Task<Stream?> FetchStreamAsync(string? url);
|
||||||
|
Task<T?> PostFileAsync<T>(string? url, Stream fileStream, string fileName, string contentType);
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
<div class="account-setting-container" tabindex="1000">
|
<div class="account-setting-container" tabindex="1000">
|
||||||
<div class="account-setting-content @(ContentVisile ? string.Empty : "invisible")">
|
<div class="account-setting-content @(ContentVisile ? string.Empty : "invisible")">
|
||||||
@if (!AuthentificationService.IsLogin)
|
@if (!IsLogin)
|
||||||
{
|
{
|
||||||
<EditForm EditContext="EditContext" OnSubmit="HandleLoginSubmit">
|
<EditForm EditContext="EditContext" OnSubmit="HandleLoginSubmit">
|
||||||
<FluentValidationValidator />
|
<FluentValidationValidator />
|
||||||
|
|||||||
@@ -1,28 +1,21 @@
|
|||||||
using GameIdeas.BlazorApp.Services;
|
|
||||||
using GameIdeas.Shared.Dto;
|
using GameIdeas.Shared.Dto;
|
||||||
using Microsoft.AspNetCore.Components.Forms;
|
using Microsoft.AspNetCore.Components.Forms;
|
||||||
|
|
||||||
namespace GameIdeas.BlazorApp.Shared.Components.Account;
|
namespace GameIdeas.BlazorApp.Shared.Components.Account;
|
||||||
|
|
||||||
public partial class AccountSettings (
|
public partial class AccountSettings
|
||||||
AuthentificationService AuthentificationService)
|
|
||||||
{
|
{
|
||||||
private bool ContentVisile = false;
|
private bool ContentVisile = false;
|
||||||
private EditContext? EditContext;
|
private EditContext? EditContext;
|
||||||
private LoginDto LoginDto = new();
|
private LoginDto LoginDto = new();
|
||||||
private bool IsLoading = false;
|
private bool IsLoading = false;
|
||||||
|
private bool IsLogin = true;
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
EditContext = new EditContext(LoginDto);
|
EditContext = new EditContext(LoginDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Open()
|
|
||||||
{
|
|
||||||
ContentVisile = true;
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
ContentVisile = false;
|
ContentVisile = false;
|
||||||
@@ -45,15 +38,10 @@ public partial class AccountSettings (
|
|||||||
IsLoading = true;
|
IsLoading = true;
|
||||||
await Task.Delay(TimeSpan.FromSeconds(5));
|
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||||
Close();
|
Close();
|
||||||
AuthentificationService.Login();
|
|
||||||
IsLoading = false;
|
IsLoading = false;
|
||||||
|
|
||||||
LoginDto = new();
|
|
||||||
EditContext = new EditContext(LoginDto);
|
|
||||||
}
|
}
|
||||||
private void HandleLogoutClicked()
|
private void HandleLogoutClicked()
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
AuthentificationService.Logout();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.backdrop-filter.overlay {
|
.backdrop-filter.overlay {
|
||||||
background-color: var(--grey-filter);
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.backdrop-filter.transparent {
|
.backdrop-filter.transparent {
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
window.setBodyOverflow = (overflow) => {
|
window.setBodyOverflow = (overflow) => {
|
||||||
document.getElementsByTagName('html')[0].style.overflow = overflow;
|
document.getElementsByClassName('page')[0].style.overflow = overflow;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
@using GameIdeas.BlazorApp.Shared.Components.BackdropFilter
|
||||||
|
@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
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CascadingValue>
|
||||||
|
|
||||||
|
|
||||||
|
<BackdropFilter @ref="BackdropFilter" OnClick="HandleBackdropFilterClicked" CloseOnClick="@Closable"
|
||||||
|
AllowBodyScroll="false" Color="BackdropFilterColor.Overlay" />
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
protected override async Task OnParametersSetAsync()
|
||||||
|
{
|
||||||
|
await base.OnParametersSetAsync();
|
||||||
|
if (BackdropFilter?.IsVisible == true && IsOpen)
|
||||||
|
{
|
||||||
|
await BackdropFilter.Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackdropFilter?.IsVisible == false && IsOpen)
|
||||||
|
{
|
||||||
|
await BackdropFilter.Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Open()
|
||||||
|
{
|
||||||
|
IsOpen = true;
|
||||||
|
await BackdropFilter?.Show()!;
|
||||||
|
StateChanged?.Invoke(null, IsOpen);
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Close()
|
||||||
|
{
|
||||||
|
IsOpen = false;
|
||||||
|
await BackdropFilter?.Hide()!;
|
||||||
|
StateChanged?.Invoke(null, IsOpen);
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandleBackdropFilterClicked()
|
||||||
|
{
|
||||||
|
await BackdropFilterClicked.InvokeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetDisplayStyle() => IsOpen ? "display: flex;" : "display: none;";
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
.popup-wrapper {
|
||||||
|
display: none;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: var(--index-popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-content {
|
||||||
|
position: relative;
|
||||||
|
background-color: var(--dropdown-content);
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: var(--big-radius);
|
||||||
|
box-shadow: var(--drop-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-content button {
|
||||||
|
top: 4px;
|
||||||
|
right: 4px;
|
||||||
|
position: absolute;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
padding: 0;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::deep .popup-content button svg {
|
||||||
|
height: 18px;
|
||||||
|
fill: var(--white);
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-content button:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background: var(--input-selected);
|
||||||
|
border-radius: var(--small-radius);
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
@using GameIdeas.Shared.Constants
|
@using GameIdeas.BlazorApp.Shared.Constants
|
||||||
|
@using GameIdeas.Shared.Constants
|
||||||
|
|
||||||
<div class="search-container">
|
<div class="search-container">
|
||||||
<input @ref=InputText
|
<input @ref=InputText
|
||||||
type="text"
|
type="text"
|
||||||
@@ -13,7 +15,7 @@
|
|||||||
@if (!string.IsNullOrEmpty(Text))
|
@if (!string.IsNullOrEmpty(Text))
|
||||||
{
|
{
|
||||||
<div class="clear-icon" @onclick=HandleClearClicked>
|
<div class="clear-icon" @onclick=HandleClearClicked>
|
||||||
@ClearIcon
|
@Icons.Shared.Close;
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using GameIdeas.BlazorApp.Shared.Constants;
|
||||||
using GameIdeas.Shared.Constants;
|
using GameIdeas.Shared.Constants;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
@@ -14,7 +15,6 @@ public partial class SearchInput
|
|||||||
[Parameter] public SearchInputIcon Icon { get; set; }
|
[Parameter] public SearchInputIcon Icon { get; set; }
|
||||||
|
|
||||||
private ElementReference InputText;
|
private ElementReference InputText;
|
||||||
private readonly MarkupString ClearIcon = new(Icons.Search.Clear);
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
@@ -52,8 +52,8 @@ public partial class SearchInput
|
|||||||
{
|
{
|
||||||
return Icon switch
|
return Icon switch
|
||||||
{
|
{
|
||||||
SearchInputIcon.Dropdown => new MarkupString(Icons.Search.Triangle),
|
SearchInputIcon.Dropdown => Icons.Search.Triangle,
|
||||||
SearchInputIcon.Search => new MarkupString(Icons.Search.Glass),
|
SearchInputIcon.Search => Icons.Search.Glass,
|
||||||
_ => new MarkupString()
|
_ => new MarkupString()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
background: none !important;
|
background: none !important;
|
||||||
color: var(--white);
|
color: var(--white);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
namespace GameIdeas.BlazorApp.Shared.Components.Select.Models;
|
namespace GameIdeas.BlazorApp.Shared.Components.Select.Models;
|
||||||
|
|
||||||
public class SelectElement<TItem>
|
public class SelectElement<TItem>(TItem item, string? label)
|
||||||
{
|
{
|
||||||
public TItem? Item { get; set; }
|
public TItem Item { get; set; } = item;
|
||||||
public string? Label { get; set; }
|
public string? Label { get; set; } = label;
|
||||||
public bool IsSelected { get; set; } = false;
|
public bool IsSelected { get; set; } = false;
|
||||||
public bool IsNew { get; set; } = false;
|
public bool IsNew { get; set; } = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,6 @@ public enum SelectListTheme
|
|||||||
Navigation,
|
Navigation,
|
||||||
Sort,
|
Sort,
|
||||||
Filter,
|
Filter,
|
||||||
AdvancedFilter
|
AdvancedFilter,
|
||||||
|
Creation
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
margin: 2px 6px;
|
margin: 2px 6px;
|
||||||
border-bottom: 2px solid var(--input-selected);
|
border-bottom: 2px solid var(--input-selected);
|
||||||
}
|
}
|
||||||
|
/* Advanced filter */
|
||||||
::deep .select-button.advancedfilter .search-container {
|
::deep .select-button.advancedfilter .search-container {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
background: var(--input-secondary);
|
background: var(--input-secondary);
|
||||||
@@ -40,6 +40,14 @@
|
|||||||
color: #bbb;
|
color: #bbb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Creation */
|
||||||
|
::deep .select-button.creation .search-container {
|
||||||
|
height: 24px;
|
||||||
|
background: var(--input-secondary);
|
||||||
|
border: solid 1px var(--input-selected);
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
/* width */
|
/* width */
|
||||||
.select-container::-webkit-scrollbar {
|
.select-container::-webkit-scrollbar {
|
||||||
width: 10px;
|
width: 10px;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
@using GameIdeas.BlazorApp.Shared.Components.BackdropFilter
|
@using GameIdeas.BlazorApp.Shared.Components.BackdropFilter
|
||||||
@using GameIdeas.BlazorApp.Shared.Components.Select.Components
|
@using GameIdeas.BlazorApp.Shared.Components.Select.Components
|
||||||
@typeparam TItem
|
@typeparam TItem
|
||||||
|
@typeparam THeader
|
||||||
|
|
||||||
<div class="select-list">
|
<div class="select-list">
|
||||||
<div class="select-button" @onclick=HandleButtonClicked>
|
<div class="select-button" @onclick=HandleButtonClicked>
|
||||||
@@ -11,10 +12,10 @@
|
|||||||
@if (IsContentOpen)
|
@if (IsContentOpen)
|
||||||
{
|
{
|
||||||
<div class="select-content @(Enum.GetName(Theme)?.ToLower())">
|
<div class="select-content @(Enum.GetName(Theme)?.ToLower())">
|
||||||
@foreach (var item in Headers)
|
@foreach (var header in Headers)
|
||||||
{
|
{
|
||||||
<SelectListElement TItem="TItem"
|
<SelectListElement TItem="THeader"
|
||||||
Value="item"
|
Value="header"
|
||||||
ValueChanged="HandleHeaderClicked"
|
ValueChanged="HandleHeaderClicked"
|
||||||
Theme="Theme" />
|
Theme="Theme" />
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,24 +3,25 @@ using Microsoft.AspNetCore.Components;
|
|||||||
|
|
||||||
namespace GameIdeas.BlazorApp.Shared.Components.Select;
|
namespace GameIdeas.BlazorApp.Shared.Components.Select;
|
||||||
|
|
||||||
public partial class SelectList<TItem>
|
public partial class SelectList<TItem, THeader>
|
||||||
{
|
{
|
||||||
[Parameter] public RenderFragment? ChildContent { get; set; }
|
[Parameter] public RenderFragment? ChildContent { get; set; }
|
||||||
[Parameter] public TItem? Value { get; set; }
|
[Parameter] public TItem? Value { get; set; }
|
||||||
[Parameter] public EventCallback<TItem?> ValueChanged { get; set; }
|
[Parameter] public EventCallback<TItem?> ValueChanged { get; set; }
|
||||||
[Parameter] public TItem? Header { get; set; }
|
[Parameter] public THeader? Header { get; set; }
|
||||||
[Parameter] public EventCallback<TItem?> HeaderChanged { get; set; }
|
[Parameter] public EventCallback<THeader?> HeaderChanged { get; set; }
|
||||||
[Parameter] public IEnumerable<SelectElement<TItem>> Items { get; set; } = [];
|
[Parameter] public IEnumerable<SelectElement<TItem>> Items { get; set; } = [];
|
||||||
[Parameter] public IEnumerable<SelectElement<TItem>> Headers { get; set; } = [];
|
[Parameter] public IEnumerable<SelectElement<THeader>> Headers { get; set; } = [];
|
||||||
[Parameter] public SelectListTheme Theme { get; set; }
|
[Parameter] public SelectListTheme Theme { get; set; }
|
||||||
[Parameter] public bool AlignRight { get; set; }
|
[Parameter] public bool AlignRight { get; set; }
|
||||||
|
|
||||||
private bool IsContentOpen = false;
|
private bool IsContentOpen = false;
|
||||||
|
|
||||||
private void HandleButtonClicked()
|
public void Close() =>
|
||||||
{
|
IsContentOpen = false;
|
||||||
|
|
||||||
|
private void HandleButtonClicked() =>
|
||||||
IsContentOpen = !IsContentOpen;
|
IsContentOpen = !IsContentOpen;
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleContentClosed()
|
private void HandleContentClosed()
|
||||||
{
|
{
|
||||||
@@ -40,7 +41,7 @@ public partial class SelectList<TItem>
|
|||||||
await ValueChanged.InvokeAsync(Value);
|
await ValueChanged.InvokeAsync(Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleHeaderClicked(SelectElement<TItem> selectedValue)
|
private async Task HandleHeaderClicked(SelectElement<THeader> selectedValue)
|
||||||
{
|
{
|
||||||
foreach (var header in Headers)
|
foreach (var header in Headers)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<div class="container">
|
||||||
|
<div class="slider-track"></div>
|
||||||
|
|
||||||
|
<input type="range" id="min-range" style="@StatusColor(Value)" min="@Params.Min" max="@Params.Max"
|
||||||
|
@bind="@Value" @bind:event="oninput" @bind:after=HandleSlideOnInput />
|
||||||
|
|
||||||
|
<div class="values">
|
||||||
|
<span class="value">@Params.Min</span>
|
||||||
|
<span class="value">@Params.Max</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace GameIdeas.BlazorApp.Shared.Components.Slider;
|
||||||
|
|
||||||
|
public partial class Slider
|
||||||
|
{
|
||||||
|
[Parameter] public SliderParams Params { get; set; } = new();
|
||||||
|
[Parameter] public int Value { get; set; }
|
||||||
|
[Parameter] public EventCallback<int> ValueChanged { get; set; }
|
||||||
|
|
||||||
|
private async Task HandleSlideOnInput()
|
||||||
|
{
|
||||||
|
await ValueChanged.InvokeAsync(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string StatusColor(int value)
|
||||||
|
{
|
||||||
|
string str = "--thumb-color: var({0});";
|
||||||
|
|
||||||
|
int firstTier = (int)Math.Floor(0.33 * Params.Max);
|
||||||
|
int secondTier = (int)Math.Ceiling(0.66 * Params.Max);
|
||||||
|
|
||||||
|
return value switch
|
||||||
|
{
|
||||||
|
int x when x <= firstTier => string.Format(str, "--red"),
|
||||||
|
int x when x >= secondTier => string.Format(str, "--green"),
|
||||||
|
_ => string.Format(str, "--yellow"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
.container {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
z-index: var(--index-component)
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="range"] {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
width: 100%;
|
||||||
|
outline: none;
|
||||||
|
margin: auto;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-track {
|
||||||
|
width: 100%;
|
||||||
|
height: 2px;
|
||||||
|
margin: auto;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: var(--input-primary);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="range"]::-webkit-slider-runnable-track {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
height: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="range"]::-moz-range-track {
|
||||||
|
-moz-appearance: none;
|
||||||
|
height: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="range"]::-ms-track {
|
||||||
|
appearance: none;
|
||||||
|
height: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="range"]::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
height: 1em;
|
||||||
|
width: 1em;
|
||||||
|
background-color: var(--thumb-color);
|
||||||
|
cursor: pointer;
|
||||||
|
margin-top: -6px;
|
||||||
|
pointer-events: auto;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="range"]::-moz-range-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
height: 1em;
|
||||||
|
width: 1em;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: var(--thumb-color);
|
||||||
|
pointer-events: auto;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="range"]::-ms-thumb {
|
||||||
|
appearance: none;
|
||||||
|
height: 1em;
|
||||||
|
width: 1em;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: var(--thumb-color);
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.values {
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
margin-top: 2px;
|
||||||
|
width: 100%;
|
||||||
|
font-weight: bold;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
width: 1em;
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace GameIdeas.BlazorApp.Shared.Components.Slider;
|
||||||
|
|
||||||
|
public class SliderParams
|
||||||
|
{
|
||||||
|
public int Min{ get; set; }
|
||||||
|
public int Max { get; set; }
|
||||||
|
public int Gap { get; set; } = 0;
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="slider-track" style="@FillColor()"></div>
|
<div class="slider-track" style="@FillColor()"></div>
|
||||||
|
|
||||||
<input type="range" id="min-range" style="@StatusColor(Params.ValueMin)" min="@Params.Min" max="@Params.Max"
|
<input type="range" id="min-range" style="@StatusColor(Min)" min="@Params.Min" max="@Params.Max"
|
||||||
@bind="@Params.ValueMin" @bind:event="oninput" @bind:after=HandleSlideOnInput />
|
@bind="@Min" @bind:event="oninput" @bind:after=HandleSlideOnInput />
|
||||||
<input type="range" id="max-range" style="@StatusColor(Params.ValueMax)" min="@Params.Min" max="@Params.Max"
|
<input type="range" id="max-range" style="@StatusColor(Max)" min="@Params.Min" max="@Params.Max"
|
||||||
@bind="@Params.ValueMax" @bind:event="oninput" @bind:after=HandleSlideTwoInput />
|
@bind="@Max" @bind:event="oninput" @bind:after=HandleSlideTwoInput />
|
||||||
|
|
||||||
<div class="values">
|
<div class="values">
|
||||||
<span class="value">@Params.ValueMin</span>
|
<span class="value">@Min</span>
|
||||||
<span class="value">@Params.ValueMax</span>
|
<span class="value">@Max</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,30 +13,28 @@ public partial class SliderRange
|
|||||||
|
|
||||||
private async Task HandleSlideTwoInput()
|
private async Task HandleSlideTwoInput()
|
||||||
{
|
{
|
||||||
if (Params.ValueMax - Params.ValueMin <= Params.Gap)
|
if (Max - Min <= Params.Gap)
|
||||||
{
|
{
|
||||||
Params.ValueMin = Params.ValueMax - Params.Gap;
|
Min = Max - Params.Gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
Max = Params.Max;
|
await MaxChanged.InvokeAsync(Max);
|
||||||
await MaxChanged.InvokeAsync(Params.Max);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleSlideOnInput()
|
private async Task HandleSlideOnInput()
|
||||||
{
|
{
|
||||||
if (Params.ValueMax - Params.ValueMin <= Params.Gap)
|
if (Max - Min <= Params.Gap)
|
||||||
{
|
{
|
||||||
Params.ValueMax = Params.ValueMin + Params.Gap;
|
Max = Min + Params.Gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
Min = Params.Min;
|
await MinChanged.InvokeAsync(Min);
|
||||||
await MinChanged.InvokeAsync(Params.Min);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string FillColor()
|
private string FillColor()
|
||||||
{
|
{
|
||||||
var percent1 = (double)(Params.ValueMin - Params.Min) / (Params.Max - Params.Min) * 100;
|
var percent1 = (double)(Min - Params.Min) / (Params.Max - Params.Min) * 100;
|
||||||
var percent2 = (double)(Params.ValueMax - Params.Min) / (Params.Max - Params.Min) * 100;
|
var percent2 = (double)(Max - Params.Min) / (Params.Max - Params.Min) * 100;
|
||||||
return $"background: linear-gradient(to right, var(--line) {percent1}% , var(--violet) {percent1}% , var(--violet) {percent2}%, var(--line) {percent2}%)";
|
return $"background: linear-gradient(to right, var(--line) {percent1}% , var(--violet) {percent1}% , var(--violet) {percent2}%, var(--line) {percent2}%)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,5 @@ public class SliderRangeParams
|
|||||||
{
|
{
|
||||||
public int Min{ get; set; }
|
public int Min{ get; set; }
|
||||||
public int Max { get; set; }
|
public int Max { get; set; }
|
||||||
public int ValueMin { get; set; }
|
|
||||||
public int ValueMax { get; set; }
|
|
||||||
public int Gap { get; set; } = 0;
|
public int Gap { get; set; } = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace GameIdeas.BlazorApp.Shared.Constants;
|
||||||
|
|
||||||
|
public static class Endpoints
|
||||||
|
{
|
||||||
|
public static class Game
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Category
|
||||||
|
{
|
||||||
|
public static readonly string AllCategories = "api/Category/All";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace GameIdeas.Shared.Constants;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace GameIdeas.BlazorApp.Shared.Constants;
|
||||||
|
|
||||||
public static class Icons
|
public static class Icons
|
||||||
{
|
{
|
||||||
@@ -8,16 +10,19 @@ public static class Icons
|
|||||||
|
|
||||||
public static class Search
|
public static class Search
|
||||||
{
|
{
|
||||||
public const string Clear = OpenBraket +
|
public readonly static MarkupString Glass = new(OpenBraket +
|
||||||
"<path d=\"M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z\" />" +
|
|
||||||
CloseBraket;
|
|
||||||
|
|
||||||
public const string Glass = OpenBraket +
|
|
||||||
"<path d=\"M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z\" />" +
|
"<path d=\"M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z\" />" +
|
||||||
CloseBraket;
|
CloseBraket);
|
||||||
|
|
||||||
public const string Triangle = OpenBraket +
|
public readonly static MarkupString Triangle = new(OpenBraket +
|
||||||
"<path d=\"M1 3H23L12 22\" />" +
|
"<path d=\"M1 3H23L12 22\" />" +
|
||||||
CloseBraket;
|
CloseBraket);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Shared
|
||||||
|
{
|
||||||
|
public readonly static MarkupString Close = new(OpenBraket +
|
||||||
|
"<path d=\"M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z\" />" +
|
||||||
|
CloseBraket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace GameIdeas.BlazorApp.Shared.Exceptions;
|
||||||
|
|
||||||
|
public class CategoryNotFoundException(string message) : Exception(message);
|
||||||
@@ -33,7 +33,6 @@ html {
|
|||||||
font-family: 'Noto Sans', sans-serif;
|
font-family: 'Noto Sans', sans-serif;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: var(--white);
|
color: var(--white);
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body, #app {
|
html, body, #app {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
<script src="_framework/blazor.webassembly.js"></script>
|
<script src="_framework/blazor.webassembly.js"></script>
|
||||||
<script src="Shared/Components/BackdropFilter/BackdropFilter.razor.js"></script>
|
<script src="Shared/Components/BackdropFilter/BackdropFilter.razor.js"></script>
|
||||||
<script src="Shared/Components/Select/MultipleSelectList.razor.js"></script>
|
<script src="Shared/Components/Select/MultipleSelectList.razor.js"></script>
|
||||||
|
<script src="Pages/Games/Components/GameCreationForm.razor.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -18,9 +18,22 @@ public class Translations (TranslationService translationService)
|
|||||||
public string Genres => translationService.Translate(nameof(Genres));
|
public string Genres => translationService.Translate(nameof(Genres));
|
||||||
public string Publishers => translationService.Translate(nameof(Publishers));
|
public string Publishers => translationService.Translate(nameof(Publishers));
|
||||||
public string Developers => translationService.Translate(nameof(Developers));
|
public string Developers => translationService.Translate(nameof(Developers));
|
||||||
public string StorageSizes => translationService.Translate(nameof(StorageSizes));
|
public string StorageSize => translationService.Translate(nameof(StorageSize));
|
||||||
|
public string StorageSizeMo => translationService.Translate(nameof(StorageSizeMo));
|
||||||
public string LastModification => translationService.Translate(nameof(LastModification));
|
public string LastModification => translationService.Translate(nameof(LastModification));
|
||||||
public string ReleaseDates => translationService.Translate(nameof(ReleaseDates));
|
public string ReleaseDate => translationService.Translate(nameof(ReleaseDate));
|
||||||
|
public string Title => translationService.Translate(nameof(Title));
|
||||||
|
public string Interest => translationService.Translate(nameof(Interest));
|
||||||
|
public string Properties => translationService.Translate(nameof(Properties));
|
||||||
|
public string Description => translationService.Translate(nameof(Description));
|
||||||
|
public string Save => translationService.Translate(nameof(Save));
|
||||||
|
public string Reset => translationService.Translate(nameof(Reset));
|
||||||
|
public string ErrorWhenPostingData => translationService.Translate(nameof(ErrorWhenPostingData));
|
||||||
|
public string ErrorWhenPutingData => translationService.Translate(nameof(ErrorWhenPutingData));
|
||||||
|
public string ErrorWhenDeletingData => translationService.Translate(nameof(ErrorWhenDeletingData));
|
||||||
|
public string ErrorWhenFetchingData => translationService.Translate(nameof(ErrorWhenFetchingData));
|
||||||
|
public string RequestFailedStatusFormat => translationService.Translate(nameof(RequestFailedStatusFormat));
|
||||||
|
public string ErrorFetchCategories => translationService.Translate(nameof(ErrorFetchCategories));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ResourcesKey
|
public static class ResourcesKey
|
||||||
@@ -47,7 +60,20 @@ public static class ResourcesKey
|
|||||||
public static string Genres => _instance?.Genres ?? throw new InvalidOperationException("ResourcesKey.Genres is not initialized.");
|
public static string Genres => _instance?.Genres ?? throw new InvalidOperationException("ResourcesKey.Genres is not initialized.");
|
||||||
public static string Publishers => _instance?.Publishers ?? throw new InvalidOperationException("ResourcesKey.Publishers is not initialized.");
|
public static string Publishers => _instance?.Publishers ?? throw new InvalidOperationException("ResourcesKey.Publishers is not initialized.");
|
||||||
public static string Developers => _instance?.Developers ?? throw new InvalidOperationException("ResourcesKey.Developers is not initialized.");
|
public static string Developers => _instance?.Developers ?? throw new InvalidOperationException("ResourcesKey.Developers is not initialized.");
|
||||||
public static string StorageSizes => _instance?.StorageSizes ?? throw new InvalidOperationException("ResourcesKey.StorageSizes is not initialized.");
|
public static string StorageSize => _instance?.StorageSize ?? throw new InvalidOperationException("ResourcesKey.StorageSize is not initialized.");
|
||||||
|
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 LastModification => _instance?.LastModification ?? throw new InvalidOperationException("ResourcesKey.LastModification is not initialized.");
|
||||||
public static string ReleaseDates => _instance?.ReleaseDates ?? throw new InvalidOperationException("ResourcesKey.ReleaseDates is not initialized.");
|
public static string ReleaseDate => _instance?.ReleaseDate ?? throw new InvalidOperationException("ResourcesKey.ReleaseDate 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.");
|
||||||
|
public static string Description => _instance?.Description ?? throw new InvalidOperationException("ResourcesKey.Description is not initialized.");
|
||||||
|
public static string Save => _instance?.Save ?? throw new InvalidOperationException("ResourcesKey.Save is not initialized.");
|
||||||
|
public static string Reset => _instance?.Reset ?? throw new InvalidOperationException("ResourcesKey.Reset is not initialized.");
|
||||||
|
public static string ErrorWhenPostingData => _instance?.ErrorWhenPostingData ?? throw new InvalidOperationException("ResourcesKey.ErrorWhenPostingData is not initialized.");
|
||||||
|
public static string ErrorWhenPutingData => _instance?.ErrorWhenPutingData ?? throw new InvalidOperationException("ResourcesKey.ErrorWhenPutingData is not initialized.");
|
||||||
|
public static string ErrorWhenDeletingData => _instance?.ErrorWhenDeletingData ?? throw new InvalidOperationException("ResourcesKey.ErrorWhenDeletingData is not initialized.");
|
||||||
|
public static string ErrorWhenFetchingData => _instance?.ErrorWhenFetchingData ?? throw new InvalidOperationException("ResourcesKey.ErrorWhenFetchingData is not initialized.");
|
||||||
|
public static string RequestFailedStatusFormat => _instance?.RequestFailedStatusFormat ?? throw new InvalidOperationException("ResourcesKey.RequestFailedStatusFormat is not initialized.");
|
||||||
|
public static string ErrorFetchCategories => _instance?.ErrorFetchCategories ?? throw new InvalidOperationException("ResourcesKey.ErrorFetchCategories is not initialized.");
|
||||||
}
|
}
|
||||||
10
src/GameIdeas/GameIdeas.Shared/Dto/CategoriesDto.cs
Normal file
10
src/GameIdeas/GameIdeas.Shared/Dto/CategoriesDto.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace GameIdeas.Shared.Dto;
|
||||||
|
|
||||||
|
public class CategoriesDto
|
||||||
|
{
|
||||||
|
public IEnumerable<PlatformDto>? Platforms { get; set; }
|
||||||
|
public IEnumerable<PropertyDto>? Properties { get; set; }
|
||||||
|
public IEnumerable<TagDto>? Tags { get; set; }
|
||||||
|
public IEnumerable<DeveloperDto>? Developers { get; set; }
|
||||||
|
public IEnumerable<PublisherDto>? Publishers { get; set; }
|
||||||
|
}
|
||||||
@@ -7,13 +7,13 @@ public class GameDto
|
|||||||
public DateTime? ReleaseDate { get; set; }
|
public DateTime? ReleaseDate { get; set; }
|
||||||
public DateTime? CreationDate { get; set; }
|
public DateTime? CreationDate { get; set; }
|
||||||
public UserDto? CreationUser { get; set; }
|
public UserDto? CreationUser { get; set; }
|
||||||
public int? CreationUserId { get; set; }
|
public int CreationUserId { get; set; }
|
||||||
public DateTime? ModificationDate { get; set; }
|
public DateTime? ModificationDate { get; set; }
|
||||||
public UserDto? ModificationUser { get; set; }
|
public UserDto? ModificationUser { get; set; }
|
||||||
public int? ModificationUserId { get; set; }
|
public int? ModificationUserId { get; set; }
|
||||||
public double? StorageSpace { get; set; }
|
public double? StorageSpace { get; set; }
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
public int? Interest { get; set; }
|
public int Interest { get; set; } = 3;
|
||||||
public IEnumerable<PlatformDto>? Platforms { get; set; }
|
public IEnumerable<PlatformDto>? Platforms { get; set; }
|
||||||
public IEnumerable<PropertyDto>? Properties { get; set; }
|
public IEnumerable<PropertyDto>? Properties { get; set; }
|
||||||
public IEnumerable<TagDto>? Tags { get; set; }
|
public IEnumerable<TagDto>? Tags { get; set; }
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using GameIdeas.Shared.Dto;
|
||||||
|
using GameIdeas.WebAPI.Services.Interfaces;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace GameIdeas.WebAPI.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class CategoryController(ICategoryService categoryService, ILoggerFactory loggerFactory) : Controller
|
||||||
|
{
|
||||||
|
private readonly ILogger<CategoryController> logger = loggerFactory.CreateLogger<CategoryController>();
|
||||||
|
|
||||||
|
[HttpGet("All")]
|
||||||
|
public async Task<ActionResult<CategoriesDto>> FetchAllCategories()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Ok(await categoryService.GetCategories());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError(e, "Internal error while fetching categories");
|
||||||
|
return StatusCode(500, e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
using GameIdeas.Shared.Dto;
|
using GameIdeas.Shared.Dto;
|
||||||
using GameIdeas.WebAPI.Services;
|
using GameIdeas.WebAPI.Services.Interfaces;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace GameIdeas.WebAPI.Controllers;
|
namespace GameIdeas.WebAPI.Controllers;
|
||||||
@@ -7,7 +7,7 @@ namespace GameIdeas.WebAPI.Controllers;
|
|||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
|
|
||||||
public class GameController(GameService gameService, ILoggerFactory loggerFactory) : Controller
|
public class GameController(IGameService gameService, ILoggerFactory loggerFactory) : Controller
|
||||||
{
|
{
|
||||||
private readonly ILogger<GameController> logger = loggerFactory.CreateLogger<GameController>();
|
private readonly ILogger<GameController> logger = loggerFactory.CreateLogger<GameController>();
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,20 @@
|
|||||||
"Genres": "Genres",
|
"Genres": "Genres",
|
||||||
"Publishers": "Editeurs",
|
"Publishers": "Editeurs",
|
||||||
"Developers": "Développeurs",
|
"Developers": "Développeurs",
|
||||||
"StorageSizes": "Taille d'espace",
|
"StorageSize": "Taille d'espace",
|
||||||
|
"StorageSizeMo": "Taille d'espace en Mo",
|
||||||
"LastModification": "Dernière modifications",
|
"LastModification": "Dernière modifications",
|
||||||
"ReleaseDates": "Dates de parution"
|
"ReleaseDate": "Date de parution",
|
||||||
|
"Title": "Titre",
|
||||||
|
"Interest": "Intérêt",
|
||||||
|
"Properties": "Propriétés",
|
||||||
|
"Description": "Description",
|
||||||
|
"Save": "Enregister",
|
||||||
|
"Reset": "Annuler",
|
||||||
|
"ErrorWhenPostingData": "Erreur lors de la requête POST",
|
||||||
|
"ErrorWhenPutingData": "Erreur lors de la requête PUT",
|
||||||
|
"ErrorWhenDeletingData": "Erreur lors de la requête DELETE",
|
||||||
|
"ErrorWhenFetchingData": "Erreur lors de la requête GET",
|
||||||
|
"RequestFailedStatusFormat": "Erreur lors de la réponse, code {0}",
|
||||||
|
"ErrorFetchCategories": "Erreur lors de la récupération des catégories"
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ using GameIdeas.Resources;
|
|||||||
using GameIdeas.WebAPI.Context;
|
using GameIdeas.WebAPI.Context;
|
||||||
using GameIdeas.WebAPI.Profiles;
|
using GameIdeas.WebAPI.Profiles;
|
||||||
using GameIdeas.WebAPI.Services;
|
using GameIdeas.WebAPI.Services;
|
||||||
|
using GameIdeas.WebAPI.Services.Interfaces;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
@@ -31,11 +32,10 @@ services.AddDbContext<GameIdeasContext>(dbContextOptions);
|
|||||||
services.AddSingleton<TranslationService>();
|
services.AddSingleton<TranslationService>();
|
||||||
services.AddSingleton<Translations>();
|
services.AddSingleton<Translations>();
|
||||||
|
|
||||||
services.AddScoped<GameService>();
|
services.AddScoped<IGameService, GameService>();
|
||||||
|
services.AddScoped<ICategoryService, CategoryService>();
|
||||||
|
|
||||||
services.AddAutoMapper(typeof(GameProfile).Assembly);
|
services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
|
||||||
services.AddAutoMapper(typeof(UserProfile).Assembly);
|
|
||||||
services.AddAutoMapper(typeof(CategoryProfile).Assembly);
|
|
||||||
|
|
||||||
services.AddControllers();
|
services.AddControllers();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using AutoMapper;
|
||||||
|
using GameIdeas.Shared.Dto;
|
||||||
|
using GameIdeas.WebAPI.Context;
|
||||||
|
using GameIdeas.WebAPI.Services.Interfaces;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace GameIdeas.WebAPI.Services;
|
||||||
|
|
||||||
|
public class CategoryService(GameIdeasContext context, IMapper mapper) : ICategoryService
|
||||||
|
{
|
||||||
|
public async Task<CategoriesDto> GetCategories()
|
||||||
|
{
|
||||||
|
var platforms = await context.Platforms.ToListAsync();
|
||||||
|
var properties = await context.Properties.ToListAsync();
|
||||||
|
var tags = await context.Tags.ToListAsync();
|
||||||
|
var developers = await context.Developers.ToListAsync();
|
||||||
|
var publishers = await context.Publishers.ToListAsync();
|
||||||
|
|
||||||
|
return new()
|
||||||
|
{
|
||||||
|
Platforms = mapper.Map<IEnumerable<PlatformDto>>(platforms),
|
||||||
|
Properties = mapper.Map<IEnumerable<PropertyDto>>(properties),
|
||||||
|
Tags = mapper.Map<IEnumerable<TagDto>>(tags),
|
||||||
|
Developers = mapper.Map<IEnumerable<DeveloperDto>>(developers),
|
||||||
|
Publishers = mapper.Map<IEnumerable<PublisherDto>>(publishers)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,11 +3,12 @@ using GameIdeas.Shared.Dto;
|
|||||||
using GameIdeas.Shared.Exceptions;
|
using GameIdeas.Shared.Exceptions;
|
||||||
using GameIdeas.Shared.Model;
|
using GameIdeas.Shared.Model;
|
||||||
using GameIdeas.WebAPI.Context;
|
using GameIdeas.WebAPI.Context;
|
||||||
|
using GameIdeas.WebAPI.Services.Interfaces;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace GameIdeas.WebAPI.Services;
|
namespace GameIdeas.WebAPI.Services;
|
||||||
|
|
||||||
public class GameService(GameIdeasContext context, IMapper mapper)
|
public class GameService(GameIdeasContext context, IMapper mapper) : IGameService
|
||||||
{
|
{
|
||||||
public async Task<IEnumerable<GameDto>> GetGames(PaggingDto pagging)
|
public async Task<IEnumerable<GameDto>> GetGames(PaggingDto pagging)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using GameIdeas.Shared.Dto;
|
||||||
|
|
||||||
|
namespace GameIdeas.WebAPI.Services.Interfaces;
|
||||||
|
|
||||||
|
public interface ICategoryService
|
||||||
|
{
|
||||||
|
Task<CategoriesDto> GetCategories();
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using GameIdeas.Shared.Dto;
|
||||||
|
|
||||||
|
namespace GameIdeas.WebAPI.Services.Interfaces;
|
||||||
|
|
||||||
|
public interface IGameService
|
||||||
|
{
|
||||||
|
Task<IEnumerable<GameDto>> GetGames(PaggingDto pagging);
|
||||||
|
Task<GameDto> GetGameById(int gameId);
|
||||||
|
Task<GameDto> CreateGame(GameDto gameDto);
|
||||||
|
Task<GameDto> UpdateGame(GameDto gameDto);
|
||||||
|
Task<bool> DeleteGame(int gameId);
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
namespace GameIdeas.WebAPI.Services;
|
|
||||||
|
|
||||||
public class UserService
|
|
||||||
{
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user