178 lines
4.2 KiB
Plaintext
178 lines
4.2 KiB
Plaintext
@page "/login"
|
|
@layout LoginLayout
|
|
|
|
@using AntDesign
|
|
@using JSMR.UI.Blazor.Services
|
|
@using MudBlazor.Charts
|
|
@using System.ComponentModel.DataAnnotations
|
|
|
|
@inject SessionState Session
|
|
@inject NavigationManager Nav
|
|
|
|
@* <h3>Login</h3> *@
|
|
|
|
<PageTitle>Sign In - JSMR</PageTitle>
|
|
|
|
@if (Session.IsAuthenticated)
|
|
{
|
|
<p>You're already logged in as <b>@Session.Me?.Name</b>.</p>
|
|
<button @onclick="Logout">Logout</button>
|
|
}
|
|
else
|
|
{
|
|
<div class="login-container">
|
|
<AntDesign.Card Title=@("Sign In") Class="ant-blurred-card">
|
|
<Body>
|
|
<AntDesign.Form Model="@loginModel" Layout="FormLayout.Vertical">
|
|
<AntDesign.FormItem Label="Username">
|
|
<AntDesign.Input @bind-Value="context.Username"></AntDesign.Input>
|
|
</AntDesign.FormItem>
|
|
<AntDesign.FormItem Label="Password">
|
|
<AntDesign.InputPassword @bind-Value="context.Password"></AntDesign.InputPassword>
|
|
</AntDesign.FormItem>
|
|
<AntDesign.Button Class="login-button" OnClick="Login2Async" Disabled="@(busy)" Type="AntDesign.ButtonType.Primary">Sign In</AntDesign.Button>
|
|
</AntDesign.Form>
|
|
</Body>
|
|
</AntDesign.Card>
|
|
@if (!string.IsNullOrWhiteSpace(error))
|
|
{
|
|
<Alert Type="AlertType.Error" Message="@error" ShowIcon="false" />
|
|
}
|
|
</div>
|
|
}
|
|
|
|
<style>
|
|
body {
|
|
background-image: url(https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*ETkNSJ-oUGwAAAAAQ_AAAAgAegCCAQ/original);
|
|
background-size: cover;
|
|
}
|
|
|
|
.ant-card-head-title {
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
|
|
.ant-form-item-required {
|
|
display: flex;
|
|
flex-direction: row-reverse;
|
|
gap: .25rem;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.login-container {
|
|
max-width: 450px;
|
|
padding: 1rem;
|
|
margin: auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: .5rem;
|
|
}
|
|
|
|
.login-button {
|
|
width: 100%;
|
|
}
|
|
|
|
.ant-blurred-card {
|
|
background-color: color-mix(in srgb, #141414 70%, transparent);
|
|
-webkit-backdrop-filter: blur(12px);
|
|
backdrop-filter: blur(12px);
|
|
}
|
|
</style>
|
|
|
|
@code {
|
|
private string username = "";
|
|
private string password = "";
|
|
private bool busy;
|
|
private string? error;
|
|
|
|
private LoginModel loginModel = new();
|
|
|
|
public class LoginModel
|
|
{
|
|
[Required]
|
|
public string? Username { get; set; }
|
|
|
|
[Required]
|
|
public string? Password { get; set; }
|
|
}
|
|
|
|
private async Task LoginAsync()
|
|
{
|
|
busy = true;
|
|
error = null;
|
|
try
|
|
{
|
|
var ok = await Session.LoginAsync(username, password);
|
|
if (!ok)
|
|
{
|
|
error = "Invalid username or password.";
|
|
return;
|
|
}
|
|
|
|
Nav.NavigateTo("/");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
error = ex.Message;
|
|
}
|
|
finally
|
|
{
|
|
busy = false;
|
|
}
|
|
}
|
|
|
|
private async Task Login2Async()
|
|
{
|
|
busy = true;
|
|
error = null;
|
|
try
|
|
{
|
|
if (string.IsNullOrWhiteSpace(loginModel.Username))
|
|
{
|
|
error = "Username is required.";
|
|
return;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(loginModel.Password))
|
|
{
|
|
error = "Password is required.";
|
|
return;
|
|
}
|
|
|
|
var ok = await Session.LoginAsync(loginModel.Username, loginModel.Password);
|
|
if (!ok)
|
|
{
|
|
error = "Invalid username or password.";
|
|
return;
|
|
}
|
|
|
|
Nav.NavigateTo("/");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
error = ex.Message;
|
|
}
|
|
finally
|
|
{
|
|
busy = false;
|
|
}
|
|
}
|
|
|
|
private async Task Logout()
|
|
{
|
|
busy = true;
|
|
error = null;
|
|
try
|
|
{
|
|
await Session.LogoutAsync();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
error = ex.Message;
|
|
}
|
|
finally
|
|
{
|
|
busy = false;
|
|
}
|
|
}
|
|
} |