Add header for game list #3
@@ -1,11 +1,13 @@
|
||||
<Router AppAssembly="@typeof(App).Assembly">
|
||||
@using GameIdeas.BlazorApp.Layouts
|
||||
|
||||
<Router AppAssembly="@typeof(App).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(GamesBase)" />
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
|
||||
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
|
||||
</Found>
|
||||
<NotFound>
|
||||
<PageTitle>Not found</PageTitle>
|
||||
<LayoutView Layout="@typeof(GamesBase)">
|
||||
<LayoutView Layout="@typeof(MainLayout)">
|
||||
<p role="alert">Sorry, there's nothing at this address.</p>
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Blazored.FluentValidation" Version="2.2.0" />
|
||||
<PackageReference Include="FluentValidation" Version="11.11.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.2" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.2" />
|
||||
@@ -15,6 +17,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\GameIdeas.Resources\GameIdeas.Resources.csproj" />
|
||||
<ProjectReference Include="..\..\GameIdeas.Shared\GameIdeas.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
@using GameIdeas.BlazorApp.Shared.Components
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<div class="page">
|
||||
@Body
|
||||
</div>
|
||||
|
||||
<span class="orb red"></span>
|
||||
<span class="orb blue"></span>
|
||||
<span class="orb green"></span>
|
||||
|
||||
<div class="background"></div>
|
||||
@@ -0,0 +1,46 @@
|
||||
.page {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.orb {
|
||||
position: absolute;
|
||||
border-radius: 100%;
|
||||
z-index: -999;
|
||||
}
|
||||
|
||||
.green {
|
||||
width: 80vh;
|
||||
height: 80vh;
|
||||
top: -20vh;
|
||||
background: #315941;
|
||||
filter: blur(30vh);
|
||||
}
|
||||
|
||||
.blue {
|
||||
width: 80vw;
|
||||
height: 80vw;
|
||||
left: 10vw;
|
||||
top: 50vh;
|
||||
background: #3A4156;
|
||||
filter: blur(30vh);
|
||||
}
|
||||
|
||||
.red {
|
||||
width: 100vh;
|
||||
height: 100vh;
|
||||
left: 60vw;
|
||||
top: -40vh;
|
||||
background: #593533;
|
||||
filter: blur(30vh);
|
||||
}
|
||||
|
||||
.background {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: var(--background);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: -1000;
|
||||
}
|
||||
@@ -1,5 +1,15 @@
|
||||
@page "/"
|
||||
@page "/Games"
|
||||
@using GameIdeas.BlazorApp.Layouts
|
||||
@using GameIdeas.BlazorApp.Shared.Components
|
||||
@using GameIdeas.BlazorApp.Shared.Headers
|
||||
@using GameIdeas.Resources
|
||||
|
||||
@inherits LayoutComponentBase
|
||||
@layout MainLayout
|
||||
|
||||
<PageTitle>@ResourcesKey.GamesIdeas</PageTitle>
|
||||
|
||||
<HeaderBase>
|
||||
<Body>
|
||||
<div>PROUT</div>
|
||||
</Body>
|
||||
</HeaderBase>
|
||||
|
||||
@@ -1,24 +1,6 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Net.Http.Json;
|
||||
using GameIdeas.Resources;
|
||||
|
||||
namespace GameIdeas.BlazorApp.Pages.Games;
|
||||
|
||||
public partial class GamesBase (
|
||||
IHttpClientFactory HttpClientFactory,
|
||||
TranslationService TranslationService,
|
||||
Translations Translations) : LayoutComponentBase
|
||||
public partial class GamesBase ()
|
||||
{
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var client = HttpClientFactory.CreateClient("GameIdeas.WebAPI");
|
||||
var response = await client.GetAsync("api/Translations");
|
||||
var dictionary = await response.Content.ReadFromJsonAsync<Dictionary<string, string>>();
|
||||
if (dictionary != null)
|
||||
{
|
||||
TranslationService.Initialize(dictionary);
|
||||
ResourcesKey.Initialize(Translations);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace GameIdeas.BlazorApp.Pages.Games.Models;
|
||||
|
||||
public enum AccountSetting
|
||||
{
|
||||
Logout
|
||||
}
|
||||
|
||||
public class AccountSettingParams
|
||||
{
|
||||
public string Label { get; set; }
|
||||
public AccountSetting AccountSetting { get; set; }
|
||||
public bool ForConnected { get; set; }
|
||||
|
||||
public AccountSettingParams(string label, AccountSetting accountSetting, bool forConnected)
|
||||
{
|
||||
Label = label;
|
||||
AccountSetting = accountSetting;
|
||||
ForConnected = forConnected;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace GameIdeas.BlazorApp.Pages.Games.Models;
|
||||
|
||||
public enum AddType
|
||||
{
|
||||
Manual,
|
||||
Auto
|
||||
}
|
||||
|
||||
public class AddTypeParams(AddType addType, string label)
|
||||
{
|
||||
public AddType AddType { get; set; } = addType;
|
||||
public string? Label { get; set; } = label;
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Net.Http.Json;
|
||||
using GameIdeas.BlazorApp;
|
||||
using GameIdeas.BlazorApp.Services;
|
||||
using GameIdeas.Resources;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||
@@ -20,7 +22,22 @@ builder.Services.AddHttpClient(
|
||||
client.Timeout = TimeSpan.FromMinutes(3);
|
||||
});
|
||||
|
||||
builder.Services.AddScoped<AuthentificationService>();
|
||||
|
||||
builder.Services.AddSingleton<TranslationService>();
|
||||
builder.Services.AddSingleton<Translations>();
|
||||
|
||||
await builder.Build().RunAsync();
|
||||
var app = builder.Build();
|
||||
|
||||
var client = app.Services.GetService<IHttpClientFactory>()?.CreateClient("GameIdeas.WebAPI") ??
|
||||
throw new Exception("Http client not found");
|
||||
var response = await client.GetAsync("api/Translations");
|
||||
var dictionary = await response.Content.ReadFromJsonAsync<Dictionary<string, string>>();
|
||||
|
||||
if (dictionary != null)
|
||||
{
|
||||
app.Services.GetService<TranslationService>()!.Initialize(dictionary);
|
||||
ResourcesKey.Initialize(app.Services.GetService<Translations>()!);
|
||||
}
|
||||
|
||||
await app.RunAsync();
|
||||
@@ -0,0 +1,21 @@
|
||||
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,13 @@
|
||||
@typeparam TItem
|
||||
|
||||
<div @ref=Content class="dropdown-container" tabindex="1000"
|
||||
@onfocusout=HandleDropdownAddFocusOut>
|
||||
<div class="dropdown-content @(ContentVisile ? string.Empty : "invisible") @(Enum.GetName(Theme)?.ToLower())">
|
||||
@foreach (var item in Items)
|
||||
{
|
||||
<div class="drowdown-element @(Enum.GetName(Theme)?.ToLower())" @onclick=HandleItemClicked>
|
||||
@(LabelSelector != null ? LabelSelector.Invoke(item) : item?.ToString())
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,36 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace GameIdeas.BlazorApp.Shared.Components.Dropdown;
|
||||
|
||||
public partial class DropdownContent<TItem>
|
||||
{
|
||||
[Parameter] public TItem? Value { get; set; }
|
||||
[Parameter] public EventCallback<TItem?> ValueChanged { get; set; }
|
||||
[Parameter] public IEnumerable<TItem> Items { get; set; } = [];
|
||||
[Parameter] public Func<TItem, string>? LabelSelector { get; set; }
|
||||
[Parameter] public DropdownTheme Theme { get; set; }
|
||||
|
||||
private bool ContentVisile = false;
|
||||
private DateTime ContentLastFocusOut = DateTime.Now;
|
||||
private ElementReference Content;
|
||||
|
||||
public async Task OpenAsync()
|
||||
{
|
||||
if (DateTime.Now - ContentLastFocusOut >= TimeSpan.FromSeconds(0.2))
|
||||
{
|
||||
await Content.FocusAsync();
|
||||
ContentVisile = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Close() => ContentVisile = false;
|
||||
|
||||
private void HandleDropdownAddFocusOut()
|
||||
{
|
||||
ContentLastFocusOut = DateTime.Now;
|
||||
ContentVisile = false;
|
||||
}
|
||||
|
||||
private async Task HandleItemClicked() => await ValueChanged.InvokeAsync(Value);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
.dropdown-content {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: var(--small-radius);
|
||||
position: fixed;
|
||||
animation-name: fade-in;
|
||||
animation-duration: 0.4s;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.drowdown-element {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.drowdown-element:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dropdown-content.navigation {
|
||||
gap: 4px;
|
||||
background: var(--violet);
|
||||
box-shadow: var(--drop-shadow);
|
||||
padding: 4px 6px;
|
||||
}
|
||||
|
||||
.drowdown-element.navigation:hover {
|
||||
color: var(--light-grey);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace GameIdeas.BlazorApp.Shared.Components.Dropdown;
|
||||
|
||||
public enum DropdownTheme
|
||||
{
|
||||
Navigation,
|
||||
Account
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
@using GameIdeas.Resources
|
||||
@using Blazored.FluentValidation;
|
||||
|
||||
<div class="account-setting-container" tabindex="1001">
|
||||
<div class="account-setting-content @(ContentVisile ? string.Empty : "invisible")">
|
||||
@if (!AuthentificationService.IsLogin)
|
||||
{
|
||||
<EditForm EditContext="EditContext" OnSubmit="HandleLoginSubmit">
|
||||
<FluentValidationValidator />
|
||||
<div class="login-form">
|
||||
<div class="login-field">
|
||||
<div class="input-title">@ResourcesKey.EnterUsername</div>
|
||||
<InputText class="input-text"
|
||||
@bind-Value="LoginDto.Username" />
|
||||
</div>
|
||||
<div class="login-field">
|
||||
<div class="input-title">@ResourcesKey.EnterPassword</div>
|
||||
<InputText class="input-text"
|
||||
@bind-Value="LoginDto.Password" />
|
||||
</div>
|
||||
<div class="login-field">
|
||||
<button class="login-button" type="submit" disabled="@IsLoading">
|
||||
@if (IsLoading)
|
||||
{
|
||||
<div class="loading"></div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@ResourcesKey.Login
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="settings-list">
|
||||
<div class="settings-element" @onclick="HandleLogoutClicked">
|
||||
@ResourcesKey.Logout
|
||||
</div>
|
||||
@* <span class="line"></span> *@
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,59 @@
|
||||
using GameIdeas.BlazorApp.Services;
|
||||
using GameIdeas.Shared.Dto;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
|
||||
namespace GameIdeas.BlazorApp.Shared.Headers;
|
||||
|
||||
public partial class AccountSettings (
|
||||
AuthentificationService AuthentificationService)
|
||||
{
|
||||
private bool ContentVisile = false;
|
||||
private EditContext? EditContext;
|
||||
private LoginDto LoginDto = new();
|
||||
private bool IsLoading = false;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
EditContext = new EditContext(LoginDto);
|
||||
}
|
||||
|
||||
public void Open()
|
||||
{
|
||||
ContentVisile = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
ContentVisile = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public void Toggle()
|
||||
{
|
||||
ContentVisile = !ContentVisile;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task HandleLoginSubmit()
|
||||
{
|
||||
if (EditContext?.Validate() == false)
|
||||
{
|
||||
LoginDto.Password = string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
IsLoading = true;
|
||||
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||
IsLoading = false;
|
||||
|
||||
LoginDto = new();
|
||||
Close();
|
||||
AuthentificationService.Login();
|
||||
}
|
||||
private void HandleLogoutClicked()
|
||||
{
|
||||
Close();
|
||||
AuthentificationService.Logout();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
.account-setting-content {
|
||||
overflow: hidden;
|
||||
border-radius: var(--big-radius);
|
||||
position: fixed;
|
||||
animation-name: fade-in;
|
||||
animation-duration: 0.4s;
|
||||
border: 2px solid var(--light-grey);
|
||||
background: var(--black);
|
||||
right: 10px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.login-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px 6px;
|
||||
gap: 20px;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.login-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
::deep .input-text {
|
||||
background: var(--light-grey);
|
||||
border: 2px solid rgb(255, 255, 255, 0.3);
|
||||
border-radius: var(--small-radius);
|
||||
padding: 6px;
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
::deep .input-text:focus-visible {
|
||||
border: 2px solid var(--violet) !important;
|
||||
}
|
||||
|
||||
.login-button {
|
||||
background: var(--violet);
|
||||
border: none;
|
||||
border-radius: 100px;
|
||||
height: 32px;
|
||||
color: var(--white);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.login-button:hover {
|
||||
background: var(--violet-selected);
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.login-button:disabled {
|
||||
background: var(--violet-selected);
|
||||
cursor: wait;
|
||||
}
|
||||
|
||||
.loading {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid var(--line-black);
|
||||
border-top-color: var(--white);
|
||||
animation: loading 1s linear infinite;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.settings-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.line {
|
||||
margin: 0 6px;
|
||||
border-bottom: 2px solid var(--light-grey);
|
||||
}
|
||||
|
||||
.settings-element {
|
||||
max-width: 140px;
|
||||
height: 40px;
|
||||
padding: 0 26px;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.settings-element:hover {
|
||||
background: var(--light-grey)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
@using GameIdeas.BlazorApp.Pages.Games
|
||||
@using GameIdeas.BlazorApp.Pages.Games.Models
|
||||
@using GameIdeas.BlazorApp.Shared.Components.Dropdown
|
||||
@using GameIdeas.Resources
|
||||
|
||||
<div class="header-tab">
|
||||
<div class="icon-container" @onclick="HandleIconClicked">
|
||||
<img src="icon.png" alt="Game Ideas">
|
||||
</div>
|
||||
|
||||
@Body
|
||||
|
||||
<div class="account-add-container">
|
||||
<div class="add-container">
|
||||
<div class="add-buttons">
|
||||
<div class="first-button button">
|
||||
<svg class="button-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path d="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="second-button button" @onclick=HandleMoreButton>
|
||||
<svg class="button-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path d="M1 3H23L12 22" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<DropdownContent @ref="DropdownAdd"
|
||||
TItem="AddTypeParams"
|
||||
ValueChanged=HandleAddTypeClickedAsync
|
||||
Items="AddTypes"
|
||||
LabelSelector="(addtype => addtype.Label)"
|
||||
Theme="DropdownTheme.Navigation" />
|
||||
</div>
|
||||
<div class="account-container">
|
||||
<div class="icon-container">
|
||||
<svg class="account-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path d="M12,19.2C9.5,19.2 7.29,17.92 6,16C6.03,14 10,12.9 12,12.9C14,12.9 17.97,14 18,16C16.71,17.92 14.5,19.2 12,19.2M12,5A3,3 0 0,1 15,8A3,3 0 0,1 12,11A3,3 0 0,1 9,8A3,3 0 0,1 12,5M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z" />
|
||||
</svg>
|
||||
</div>
|
||||
<AccountSettings @ref="AccountSettings" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,46 @@
|
||||
using GameIdeas.BlazorApp.Pages.Games.Models;
|
||||
using GameIdeas.BlazorApp.Shared.Components.Dropdown;
|
||||
using GameIdeas.Resources;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace GameIdeas.BlazorApp.Shared.Headers;
|
||||
|
||||
public partial class HeaderBase
|
||||
{
|
||||
[Parameter] public RenderFragment? Body { get; set; }
|
||||
[Parameter] public EventCallback<AddType> AddTypeChanged { get; set; }
|
||||
|
||||
private DropdownContent<AddTypeParams>? DropdownAdd;
|
||||
private readonly IEnumerable<AddTypeParams> AddTypes =
|
||||
[
|
||||
new AddTypeParams(AddType.Manual, ResourcesKey.ManualAdd),
|
||||
new AddTypeParams(AddType.Auto, ResourcesKey.AutoAdd)
|
||||
];
|
||||
|
||||
private AccountSettings? AccountSettings;
|
||||
|
||||
private void HandleIconClicked()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private async Task HandleMoreButton()
|
||||
{
|
||||
if (DropdownAdd != null)
|
||||
{
|
||||
await DropdownAdd.OpenAsync();
|
||||
}
|
||||
|
||||
AccountSettings?.Close();
|
||||
}
|
||||
|
||||
private async Task HandleAddTypeClickedAsync(AddTypeParams value)
|
||||
{
|
||||
await AddTypeChanged.InvokeAsync(value.AddType);
|
||||
}
|
||||
|
||||
private void HandleAccountClicked()
|
||||
{
|
||||
AccountSettings?.Toggle();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
.header-tab {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
padding: 0px 10px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.icon-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 40px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.icon-container img {
|
||||
max-height: 85%;
|
||||
max-width: 85%;
|
||||
}
|
||||
|
||||
.icon-container:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.account-add-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.add-container {
|
||||
overflow: visible;
|
||||
margin-right: 40px;
|
||||
}
|
||||
|
||||
.add-buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
background: var(--violet);
|
||||
border-radius: var(--small-radius);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.first-button {
|
||||
border-right: 2px solid var(--line-black);
|
||||
}
|
||||
|
||||
.second-button .button-icon {
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.button-icon {
|
||||
fill: var(--white);
|
||||
}
|
||||
|
||||
.button-icon:hover {
|
||||
background: var(--line-black);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.account-icon {
|
||||
fill: var(--light-grey);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using FluentValidation;
|
||||
using GameIdeas.Shared.Dto;
|
||||
|
||||
namespace GameIdeas.BlazorApp.Shared.Headers;
|
||||
|
||||
public class LoginValidator : AbstractValidator<LoginDto>
|
||||
{
|
||||
public LoginValidator()
|
||||
{
|
||||
RuleFor(dto => dto.Username)
|
||||
.NotNull()
|
||||
.NotEmpty();
|
||||
|
||||
RuleFor(dto => dto.Password)
|
||||
.NotNull()
|
||||
.NotEmpty();
|
||||
}
|
||||
}
|
||||
@@ -6,4 +6,3 @@
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.AspNetCore.Components.WebAssembly.Http
|
||||
@using Microsoft.JSInterop
|
||||
@using GameIdeas.BlazorApp.Pages.Games
|
||||
|
||||
@@ -1,97 +1,51 @@
|
||||
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:wght@300;400;700&display=swap');
|
||||
|
||||
html, body {
|
||||
:root {
|
||||
--background: linear-gradient(180deg, #2B1D3D 0%, #171229 100%);
|
||||
--violet: #A380D1;
|
||||
--violet-selected: #8266a7;
|
||||
--red: #FF5E51;
|
||||
--yellow: #FFC107;
|
||||
--green: #43F8C0;
|
||||
--light-grey: #5C5C5E;
|
||||
--black: rgba(44, 43, 46, 0.8);
|
||||
--white: #fff;
|
||||
--semi-black: rgba(0, 0, 0, 0.5);
|
||||
--line-black: rgba(0, 0, 0, 0.2);
|
||||
--small-radius: 4px;
|
||||
--big-radius: 10px;
|
||||
--radius: 6px;
|
||||
--drop-shadow: 0px 0px 20px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: 'Noto Sans', sans-serif;
|
||||
font-size: 12px;
|
||||
color: var(--white)
|
||||
}
|
||||
|
||||
html, body, #app {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
|
||||
font-family: 'Noto Sans', sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background: linear-gradient(180deg, #2B1D3D 0%, #171229 100%);
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
html::before,
|
||||
body::before,
|
||||
body::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
html::before {
|
||||
/*Green orb*/
|
||||
position: absolute;
|
||||
width: 80vh;
|
||||
height: 80vh;
|
||||
top: -20vh;
|
||||
background: #315941;
|
||||
filter: blur(30vh);
|
||||
z-index: -999;
|
||||
}
|
||||
|
||||
body::before {
|
||||
/*Blue orb*/
|
||||
position: absolute;
|
||||
width: 80vw;
|
||||
height: 80vw;
|
||||
left: 10vw;
|
||||
top: 50vh;
|
||||
background: #3A4156;
|
||||
filter: blur(30vh);
|
||||
z-index: -999;
|
||||
}
|
||||
|
||||
body::after {
|
||||
/*Reb orb*/
|
||||
position: absolute;
|
||||
width: 100vh;
|
||||
height: 100vh;
|
||||
left: 60vw;
|
||||
top: -30vh;
|
||||
background: #593533;
|
||||
filter: blur(30vh);
|
||||
z-index: -999;
|
||||
}
|
||||
|
||||
h1:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
a, .btn-link {
|
||||
color: #0071c1;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
}
|
||||
|
||||
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
|
||||
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-top: 1.1rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.valid.modified:not([type=checkbox]) {
|
||||
outline: 1px solid #26b050;
|
||||
border: 2px solid var(--green);
|
||||
}
|
||||
|
||||
.invalid {
|
||||
outline: 1px solid red;
|
||||
border: 2px solid var(--red) !important;
|
||||
}
|
||||
|
||||
.validation-message {
|
||||
color: red;
|
||||
color: var(--red);
|
||||
}
|
||||
|
||||
#blazor-error-ui {
|
||||
color-scheme: light only;
|
||||
color: #000;
|
||||
background: lightyellow;
|
||||
bottom: 0;
|
||||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
|
||||
@@ -144,6 +98,7 @@ a, .btn-link {
|
||||
}
|
||||
|
||||
.loading-progress-text {
|
||||
color: #000;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
@@ -165,4 +120,19 @@ code {
|
||||
|
||||
.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
0% {opacity: 0}
|
||||
100% {opacity: 1}
|
||||
}
|
||||
|
||||
@keyframes loading {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -4,6 +4,12 @@ namespace GameIdeas.Resources;
|
||||
public class Translations (TranslationService translationService)
|
||||
{
|
||||
public string GamesIdeas => translationService.Translate(nameof(GamesIdeas));
|
||||
public string ManualAdd => translationService.Translate(nameof(ManualAdd));
|
||||
public string AutoAdd => translationService.Translate(nameof(AutoAdd));
|
||||
public string Login => translationService.Translate(nameof(Login));
|
||||
public string Logout => translationService.Translate(nameof(Logout));
|
||||
public string EnterUsername => translationService.Translate(nameof(EnterUsername));
|
||||
public string EnterPassword => translationService.Translate(nameof(EnterPassword));
|
||||
}
|
||||
|
||||
public static class ResourcesKey
|
||||
@@ -16,4 +22,10 @@ public static class ResourcesKey
|
||||
}
|
||||
|
||||
public static string GamesIdeas => _instance?.GamesIdeas ?? throw new InvalidOperationException("ResourcesKey.GamesIdeas is not initialized.");
|
||||
public static string ManualAdd => _instance?.ManualAdd ?? throw new InvalidOperationException("ResourcesKey.ManualAdd is not initialized.");
|
||||
public static string AutoAdd => _instance?.AutoAdd ?? throw new InvalidOperationException("ResourcesKey.AutoAdd is not initialized.");
|
||||
public static string Login => _instance?.Login ?? throw new InvalidOperationException("ResourcesKey.Login is not initialized.");
|
||||
public static string Logout => _instance?.Logout ?? throw new InvalidOperationException("ResourcesKey.Logout is not initialized.");
|
||||
public static string EnterUsername => _instance?.EnterUsername ?? throw new InvalidOperationException("ResourcesKey.EnterUsername is not initialized.");
|
||||
public static string EnterPassword => _instance?.EnterPassword ?? throw new InvalidOperationException("ResourcesKey.EnterPassword is not initialized.");
|
||||
}
|
||||
7
src/GameIdeas/GameIdeas.Shared/Dto/LoginDto.cs
Normal file
7
src/GameIdeas/GameIdeas.Shared/Dto/LoginDto.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace GameIdeas.Shared.Dto;
|
||||
|
||||
public class LoginDto
|
||||
{
|
||||
public string? Username { get; set; }
|
||||
public string? Password { get; set; }
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.12.35506.116 d17.12
|
||||
VisualStudioVersion = 17.12.35506.116
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameIdeas.BlazorApp", "Client\GameIdeas.BlazorApp\GameIdeas.BlazorApp.csproj", "{ABBADA2F-9017-49A2-AEB9-AC2DB7D70831}"
|
||||
EndProject
|
||||
@@ -45,4 +45,7 @@ Global
|
||||
{ABBADA2F-9017-49A2-AEB9-AC2DB7D70831} = {9598BBAF-CC9F-4F43-82B2-40F57296C9F0}
|
||||
{61C3985E-15DF-4127-9D1F-CAE39F0ADD17} = {F59BED34-9473-436A-A91A-23510A4E0E87}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {6380DD77-53E4-4F3B-BB45-FAD2263D1511}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
{
|
||||
"GamesIdeas": "Game Ideas"
|
||||
"GamesIdeas": "Game Ideas",
|
||||
"ManualAdd": "Manuel",
|
||||
"AutoAdd": "Automatique",
|
||||
"Login": "Se connecter",
|
||||
"Logout": "Se déconnecter",
|
||||
"EnterUsername": "Nom d'utilisateur",
|
||||
"EnterPassword": "Mot de passe"
|
||||
}
|
||||
Reference in New Issue
Block a user