mirror of
https://github.com/Shchoholiev/shopping-assistant-web-client.git
synced 2025-04-05 00:59:38 +00:00
Add login page
This commit is contained in:
parent
097377bb59
commit
a7be8dfa85
@ -1,8 +0,0 @@
|
|||||||
@page "/login"
|
|
||||||
@model ShoppingAssistantWebClient.Web.Pages.LoginModel
|
|
||||||
|
|
||||||
<h1>Login</h1>
|
|
||||||
|
|
||||||
@{
|
|
||||||
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
|
|
||||||
namespace ShoppingAssistantWebClient.Web.Pages
|
|
||||||
{
|
|
||||||
public class LoginModel : PageModel
|
|
||||||
{
|
|
||||||
public void OnGet()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
82
ShoppingAssistantWebClient.Web/Pages/Login.razor
Normal file
82
ShoppingAssistantWebClient.Web/Pages/Login.razor
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
@page "/login"
|
||||||
|
|
||||||
|
@using System.Text.RegularExpressions
|
||||||
|
@using Microsoft.AspNetCore.Components.Forms
|
||||||
|
@using ShoppingAssistantWebClient.Web.Models.Input;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="css/Login.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="login-container">
|
||||||
|
<div class="login-form">
|
||||||
|
@if (!string.IsNullOrWhiteSpace(errorMessage))
|
||||||
|
{
|
||||||
|
<div class="error-message-container">
|
||||||
|
<span class="validation-message error">@errorMessage</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<input type="tel" @bind="LoginInput.Phone" placeholder="Phone Number" pattern="\+?[0-9]{10,15}" required @bind:event="oninput" @onchange="ValidatePhone"/>
|
||||||
|
<span class="validation-message">@phoneValidationMessage</span>
|
||||||
|
<div class="or">or</div>
|
||||||
|
<input type="email" @bind="LoginInput.Email" placeholder="Email" required @bind:event="oninput" @onchange="ValidateEmail"/>
|
||||||
|
<span class="validation-message">@emailValidationMessage</span>
|
||||||
|
<input type="password" @bind="LoginInput.Password" placeholder="Password" />
|
||||||
|
<button class="login-button" @onclick="HandleLogin">Login</button>
|
||||||
|
<button class="back-button" @onclick="RedirectToNewChat">Back</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private string phoneValidationMessage = "";
|
||||||
|
private string emailValidationMessage = "";
|
||||||
|
private bool isPhoneInvalid = false;
|
||||||
|
private bool isEmailInvalid = false;
|
||||||
|
|
||||||
|
private LoginInputModel LoginInput = new LoginInputModel();
|
||||||
|
|
||||||
|
private void ValidatePhone()
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(LoginInput.Phone) && !Regex.IsMatch(LoginInput.Phone, @"^\+[0-9]{1,15}$"))
|
||||||
|
{
|
||||||
|
phoneValidationMessage = "Please enter a valid phone number";
|
||||||
|
isPhoneInvalid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
phoneValidationMessage = "";
|
||||||
|
isPhoneInvalid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ValidateEmail()
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(LoginInput.Email) && !Regex.IsMatch(LoginInput.Email, @"^[^@\s]+@[^@\s]+\.[^@\s]+$"))
|
||||||
|
{
|
||||||
|
emailValidationMessage = "Please enter a valid email address";
|
||||||
|
isEmailInvalid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emailValidationMessage = "";
|
||||||
|
isEmailInvalid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool HasValidationErrors()
|
||||||
|
{
|
||||||
|
return !string.IsNullOrWhiteSpace(phoneValidationMessage) || !string.IsNullOrWhiteSpace(emailValidationMessage);
|
||||||
|
}
|
||||||
|
private async Task HandleLogin()
|
||||||
|
{
|
||||||
|
if (HasValidationErrors())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await LoginUser(LoginInput);
|
||||||
|
}
|
||||||
|
}
|
43
ShoppingAssistantWebClient.Web/Pages/Login.razor.cs
Normal file
43
ShoppingAssistantWebClient.Web/Pages/Login.razor.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using ShoppingAssistantWebClient.Web.Network;
|
||||||
|
using ShoppingAssistantWebClient.Web.Models.Input;
|
||||||
|
|
||||||
|
|
||||||
|
namespace ShoppingAssistantWebClient.Web.Pages;
|
||||||
|
|
||||||
|
public partial class Login : ComponentBase
|
||||||
|
{
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
NavigationManager NavigationManager { get; set; }
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
private AuthenticationService _authenticationService { get; set; }
|
||||||
|
|
||||||
|
private string errorMessage = "";
|
||||||
|
|
||||||
|
|
||||||
|
private void RedirectToNewChat() {
|
||||||
|
var url = $"/";
|
||||||
|
NavigationManager.NavigateTo(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LoginUser(LoginInputModel login) {
|
||||||
|
if (login.IsEmailOrPhoneProvided)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _authenticationService.LoginAsync(login);
|
||||||
|
RedirectToNewChat();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
errorMessage = "Login failed. Please try again.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorMessage = "Please provide an email or phone number.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
@using ShoppingAssistantWebClient.Web.Models
|
@using ShoppingAssistantWebClient.Web.Models
|
||||||
|
|
||||||
@inject IHttpContextAccessor httpContextAccessor;
|
@inject IHttpContextAccessor httpContextAccessor;
|
||||||
|
@inject NavigationManager NavigationManager;
|
||||||
|
|
||||||
<div class="modal fade show d-block" tabindex="-1" role="dialog">
|
<div class="modal fade show d-block" tabindex="-1" role="dialog">
|
||||||
<div class="modal-backdrop fade show"></div>
|
<div class="modal-backdrop fade show"></div>
|
||||||
@ -46,7 +47,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|
||||||
<button type="button" class="btn btn-primary log-in-button-left">Log In</button>
|
<button type="button" class="btn btn-primary log-in-button-left" @onclick="RedirectToLogin">Log In</button>
|
||||||
<button type="submit" class="btn btn-primary" disabled="@isApplyDisabled" @onclick="Apply">Apply</button>
|
<button type="submit" class="btn btn-primary" disabled="@isApplyDisabled" @onclick="Apply">Apply</button>
|
||||||
<button type="button" class="btn btn-secondary" @onclick="Close">Cancle</button>
|
<button type="button" class="btn btn-secondary" @onclick="Close">Cancle</button>
|
||||||
</div>
|
</div>
|
||||||
@ -141,6 +142,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RedirectToLogin() {
|
||||||
|
var url = $"/login";
|
||||||
|
NavigationManager.NavigateTo(url);
|
||||||
|
}
|
||||||
|
|
||||||
private string ShowErrorDivClass()
|
private string ShowErrorDivClass()
|
||||||
{
|
{
|
||||||
return string.IsNullOrEmpty(errorMessage) ? "hidden" : "alert alert-danger";
|
return string.IsNullOrEmpty(errorMessage) ? "hidden" : "alert alert-danger";
|
||||||
|
112
ShoppingAssistantWebClient.Web/wwwroot/css/Login.css
Normal file
112
ShoppingAssistantWebClient.Web/wwwroot/css/Login.css
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
.page {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 96vh;
|
||||||
|
border: 1.5% solid;
|
||||||
|
padding: 1.25em;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-menu {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-frame {
|
||||||
|
position: absolute;
|
||||||
|
right: 1.25em;
|
||||||
|
left: 1.25em;
|
||||||
|
top: 1.25em;
|
||||||
|
bottom: 0em;
|
||||||
|
transition: 1s;
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
left: 1.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
height: 4vh;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.amazon-associate {
|
||||||
|
position: relative;
|
||||||
|
left: calc(50% - 12.5em);
|
||||||
|
transform: translateX(-50%);
|
||||||
|
bottom: 0;
|
||||||
|
font-size: 0.7em;
|
||||||
|
color: #000;
|
||||||
|
text-decoration: none;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: 0.5s;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 96vh;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form {
|
||||||
|
max-width: 570px;
|
||||||
|
background-color: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form input[type="tel"],
|
||||||
|
.login-form input[type="email"],
|
||||||
|
.login-form input[type="password"] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px 0;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.or {
|
||||||
|
text-align: center;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-button,
|
||||||
|
.back-button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px 0;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #007bff;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-button {
|
||||||
|
background-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-button:hover,
|
||||||
|
.back-button:hover {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.login-form {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-message-container {
|
||||||
|
text-align: center;
|
||||||
|
margin: 10px 0;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.validation-message.error {
|
||||||
|
color: red;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user