mirror of
https://github.com/Shchoholiev/shopping-assistant-web-client.git
synced 2025-04-05 00:59:38 +00:00
Merge branch 'develop' into SA-217-deliting-chat-confirmation
This commit is contained in:
commit
8a3c9be4a0
14
ShoppingAssistantWebClient.Web/Models/Role.cs
Normal file
14
ShoppingAssistantWebClient.Web/Models/Role.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ShoppingAssistantWebClient.Web.Models
|
||||||
|
{
|
||||||
|
public class Role
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
}
|
17
ShoppingAssistantWebClient.Web/Models/User.cs
Normal file
17
ShoppingAssistantWebClient.Web/Models/User.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using ShoppingAssistantWebClient.Web.Models;
|
||||||
|
|
||||||
|
namespace ShoppingAssistantWebClient.Web.Models
|
||||||
|
{
|
||||||
|
public class User
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
public string GuestId { get; set; }
|
||||||
|
|
||||||
|
public List<Role>? Roles { get; set; } = new List<Role>();
|
||||||
|
|
||||||
|
public string Email { get; set; }
|
||||||
|
|
||||||
|
public string Phone { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -2,8 +2,6 @@ using Microsoft.AspNetCore.Components;
|
|||||||
using ShoppingAssistantWebClient.Web.Models;
|
using ShoppingAssistantWebClient.Web.Models;
|
||||||
using ShoppingAssistantWebClient.Web.Network;
|
using ShoppingAssistantWebClient.Web.Network;
|
||||||
using GraphQL;
|
using GraphQL;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Microsoft.JSInterop;
|
|
||||||
using ShoppingAssistantWebClient.Web.Services;
|
using ShoppingAssistantWebClient.Web.Services;
|
||||||
|
|
||||||
namespace ShoppingAssistantWebClient.Web.Pages;
|
namespace ShoppingAssistantWebClient.Web.Pages;
|
||||||
|
152
ShoppingAssistantWebClient.Web/Pages/Settings.razor
Normal file
152
ShoppingAssistantWebClient.Web/Pages/Settings.razor
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
@using System.Text.RegularExpressions
|
||||||
|
@using Models.GlobalInstances
|
||||||
|
@using ShoppingAssistantWebClient.Web.Models
|
||||||
|
|
||||||
|
@inject IHttpContextAccessor httpContextAccessor;
|
||||||
|
|
||||||
|
<div class="modal fade show d-block" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-backdrop fade show"></div>
|
||||||
|
<div class="modal-dialog" style="z-index: 1050">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">User Settings</h5>
|
||||||
|
<button type="button" class="close" aria-label="Close" @onclick="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="@ShowErrorDivClass()" role="alert">
|
||||||
|
@errorMessage
|
||||||
|
</div>
|
||||||
|
<div class="@ShowUpdateDivClass()" role="alert">
|
||||||
|
@updateMessage
|
||||||
|
</div>
|
||||||
|
<form>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="phone">Phone</label>
|
||||||
|
<input type="tel" class="form-control" id="phone" placeholder="Enter new phone" pattern="\+?[0-9]{10,15}" required @onchange="ValidatePhone" data-toggle="tooltip" data-placement="top" title="Use format: +xxxxxxxx">
|
||||||
|
<div class="validation-message @(isPhoneInvalid ? "active" : "")" id="phone-validation" style="color: red;">@phoneValidationMessage</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="email">Email</label>
|
||||||
|
<input type="email" class="form-control" id="email" placeholder="Enter new email" required @onchange="ValidateEmail" data-toggle="tooltip" data-placement="top" title="Use format: example@domain.com">
|
||||||
|
<div class="validation-message @(isEmailInvalid ? "active" : "")" id="email-validation" style="color: red;">@emailValidationMessage</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (!user.Roles.Any(role => role.Name == "User"))
|
||||||
|
{
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password">New Password</label>
|
||||||
|
<input type="password" class="form-control" id="password" placeholder="Enter new password" @onchange="OnPasswordInput">
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-primary log-in-button-left">Log In</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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
$('[data-toggle="tooltip"]').tooltip();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[CascadingParameter] BlazoredModalInstance BlazoredModal { get; set; }
|
||||||
|
|
||||||
|
private string phoneValidationMessage = "";
|
||||||
|
private string emailValidationMessage = "";
|
||||||
|
private bool isPhoneInvalid = false;
|
||||||
|
private bool isEmailInvalid = false;
|
||||||
|
private bool isApplyDisabled = true;
|
||||||
|
private string phone = "";
|
||||||
|
private string email = "";
|
||||||
|
private string password = "";
|
||||||
|
|
||||||
|
private void ValidatePhone(ChangeEventArgs e)
|
||||||
|
{
|
||||||
|
errorMessage = "";
|
||||||
|
phone = e.Value.ToString();
|
||||||
|
if (!string.IsNullOrWhiteSpace(phone) && !Regex.IsMatch(phone, @"^\+[0-9]{1,15}$"))
|
||||||
|
{
|
||||||
|
phoneValidationMessage = "Please enter a valid phone number";
|
||||||
|
isPhoneInvalid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
phoneValidationMessage = "";
|
||||||
|
isPhoneInvalid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateApplyButtonState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ValidateEmail(ChangeEventArgs e)
|
||||||
|
{
|
||||||
|
errorMessage = "";
|
||||||
|
email = e.Value.ToString();
|
||||||
|
if (!string.IsNullOrWhiteSpace(email) && !Regex.IsMatch(email, @"^[^@\s]+@[^@\s]+\.[^@\s]+$"))
|
||||||
|
{
|
||||||
|
emailValidationMessage = "Please enter a valid email address.";
|
||||||
|
isEmailInvalid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emailValidationMessage = "";
|
||||||
|
isEmailInvalid = false;
|
||||||
|
}
|
||||||
|
UpdateApplyButtonState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateApplyButtonState()
|
||||||
|
{
|
||||||
|
if(user.Roles.Any(role => role.Name == "User"))
|
||||||
|
isApplyDisabled = (string.IsNullOrWhiteSpace(phone) && string.IsNullOrWhiteSpace(email)) || isPhoneInvalid || isEmailInvalid;
|
||||||
|
else
|
||||||
|
isApplyDisabled = string.IsNullOrWhiteSpace(password) || (string.IsNullOrWhiteSpace(phone) && string.IsNullOrWhiteSpace(email)) || isPhoneInvalid || isEmailInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPasswordInput(ChangeEventArgs e)
|
||||||
|
{
|
||||||
|
errorMessage = "";
|
||||||
|
password = e.Value.ToString();
|
||||||
|
UpdateApplyButtonState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Close() => await BlazoredModal.CloseAsync(ModalResult.Ok(true));
|
||||||
|
private async Task Cancel() => await BlazoredModal.CancelAsync();
|
||||||
|
|
||||||
|
private async Task Apply() {
|
||||||
|
|
||||||
|
await UpdateUser();
|
||||||
|
isApplyDisabled = true;
|
||||||
|
await GetUser();
|
||||||
|
StateHasChanged();
|
||||||
|
|
||||||
|
if(user.Roles.Any(role => role.Name == "User")) {
|
||||||
|
await Task.Delay(3000);
|
||||||
|
await InvokeAsync(() => {
|
||||||
|
updateMessage = "";
|
||||||
|
StateHasChanged();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ShowErrorDivClass()
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(errorMessage) ? "hidden" : "alert alert-danger";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ShowUpdateDivClass() {
|
||||||
|
return string.IsNullOrEmpty(updateMessage) ? "hidden" : "alert alert-success";
|
||||||
|
}
|
||||||
|
}
|
118
ShoppingAssistantWebClient.Web/Pages/Settings.razor.cs
Normal file
118
ShoppingAssistantWebClient.Web/Pages/Settings.razor.cs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using ShoppingAssistantWebClient.Web.Network;
|
||||||
|
using ShoppingAssistantWebClient.Web.Models;
|
||||||
|
using ShoppingAssistantWebClient.Web.Models.GlobalInstances;
|
||||||
|
using GraphQL;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
|
||||||
|
namespace ShoppingAssistantWebClient.Web.Pages;
|
||||||
|
|
||||||
|
public partial class Settings : ComponentBase
|
||||||
|
{
|
||||||
|
[Inject]
|
||||||
|
private ApiClient _apiClient { get; set; }
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
private IHttpContextAccessor _httpContextAccessor { get; set; }
|
||||||
|
|
||||||
|
public User user = new User();
|
||||||
|
|
||||||
|
private string errorMessage = "";
|
||||||
|
|
||||||
|
private string updateMessage = "";
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
await GetUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task GetUser() {
|
||||||
|
try {
|
||||||
|
var request = new GraphQLRequest {
|
||||||
|
Query = @"
|
||||||
|
query User($id: String!) {
|
||||||
|
user(id: $id) {
|
||||||
|
roles {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
phone
|
||||||
|
email
|
||||||
|
}
|
||||||
|
}",
|
||||||
|
Variables = new
|
||||||
|
{
|
||||||
|
id = GlobalUser.Id,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await _apiClient.QueryAsync(request);
|
||||||
|
var responseData = response.Data;
|
||||||
|
//System.Console.WriteLine(responseData);
|
||||||
|
|
||||||
|
var jsonCategoriesResponse = JsonConvert.SerializeObject(responseData.user);
|
||||||
|
this.user = JsonConvert.DeserializeObject<User>(jsonCategoriesResponse);
|
||||||
|
user.GuestId = _httpContextAccessor.HttpContext.Request.Cookies["guestId"];
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error in GetUser: {ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateUser()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if(user.Roles.Any(role => role.Name == "User"))
|
||||||
|
{
|
||||||
|
updateMessage = "Your data has been successfully updated";
|
||||||
|
}
|
||||||
|
if(phone == "") {
|
||||||
|
phone = user.Phone;
|
||||||
|
}
|
||||||
|
if(email == "") {
|
||||||
|
email = user.Email;
|
||||||
|
}
|
||||||
|
var request = new GraphQLRequest
|
||||||
|
{
|
||||||
|
Query = @"
|
||||||
|
mutation UpdateUser($userDto: UserDtoInput!) {
|
||||||
|
updateUser(userDto: $userDto) {
|
||||||
|
tokens { accessToken, refreshToken },
|
||||||
|
user { email, phone }
|
||||||
|
}
|
||||||
|
}",
|
||||||
|
Variables = new
|
||||||
|
{
|
||||||
|
userDto = new
|
||||||
|
{
|
||||||
|
id = GlobalUser.Id,
|
||||||
|
guestId = user.GuestId,
|
||||||
|
roles = user.Roles.Select(r => new { id = r.Id, name = r.Name }),
|
||||||
|
email = email,
|
||||||
|
phone = phone,
|
||||||
|
password = password
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await _apiClient.QueryAsync(request);
|
||||||
|
var responseData = response.Data;
|
||||||
|
System.Console.WriteLine(responseData);
|
||||||
|
errorMessage = "";
|
||||||
|
phone = "";
|
||||||
|
email = "";
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
if (ex.Message.Contains("The HTTP request failed with status code InternalServerError")) {
|
||||||
|
errorMessage = "This user is already registered.";
|
||||||
|
} else {
|
||||||
|
errorMessage = "Something went wrong, please try again.";
|
||||||
|
}
|
||||||
|
Console.WriteLine($"Error in UpdateUser: {ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
260
ShoppingAssistantWebClient.Web/Pages/Settings.razor.css
Normal file
260
ShoppingAssistantWebClient.Web/Pages/Settings.razor.css
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
.modal-dialog {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close span {
|
||||||
|
display: block;
|
||||||
|
color: #000;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
background-color: white;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
width: 120px;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#phone, #email {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.validation-message {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -20px;
|
||||||
|
left: 0;
|
||||||
|
color: red;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.validation-message.active {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #007bff;
|
||||||
|
border-color: #007bff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background-color: #6c757d;
|
||||||
|
border-color: #6c757d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary:hover {
|
||||||
|
background-color: #545b62;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:focus {
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header, .modal-footer, .modal-body {
|
||||||
|
padding: 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-in-button-left {
|
||||||
|
margin-right: auto;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-in-button-left-hidden {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 320px) {
|
||||||
|
.modal-dialog {
|
||||||
|
max-width: 90%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header, .modal-footer, .modal-body {
|
||||||
|
padding: 6px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.375rem 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
width: 80px;
|
||||||
|
height: 28px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#phone, #email {
|
||||||
|
margin-bottom: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 321px) and (max-width: 376px) {
|
||||||
|
.modal-dialog {
|
||||||
|
max-width: 300px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header, .modal-footer, .modal-body {
|
||||||
|
padding: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.375rem 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
width: 70px;
|
||||||
|
height: 28px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#phone, #email {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#phone-validation, #email-validation{
|
||||||
|
margin-top: -1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 376px) and (max-width: 426px) {
|
||||||
|
.modal-dialog {
|
||||||
|
max-width: 300px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header, .modal-footer, .modal-body {
|
||||||
|
padding: 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
padding: 0.375rem 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
width: 80px;
|
||||||
|
height: 28px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#phone, #email {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#phone-validation, #email-validation{
|
||||||
|
margin-top: -1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 426px) and (max-width: 768px) {
|
||||||
|
.modal-dialog {
|
||||||
|
width: 60%;
|
||||||
|
max-width: 400px;
|
||||||
|
min-width: 330px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header, .modal-footer, .modal-body {
|
||||||
|
padding: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
padding: 0.375rem 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
width: 100px;
|
||||||
|
height: 30px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#phone, #email {
|
||||||
|
margin-bottom: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#phone-validation, #email-validation{
|
||||||
|
margin-top: -1.3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 426px) and (max-width: 582px) {
|
||||||
|
.btn {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
width: 80px !important;
|
||||||
|
height: 28px !important;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ using ShoppingAssistantWebClient.Web.Configurations;
|
|||||||
using ShoppingAssistantWebClient.Web.Data;
|
using ShoppingAssistantWebClient.Web.Data;
|
||||||
using ShoppingAssistantWebClient.Web.Network;
|
using ShoppingAssistantWebClient.Web.Network;
|
||||||
using ShoppingAssistantWebClient.Web.Services;
|
using ShoppingAssistantWebClient.Web.Services;
|
||||||
|
using Blazored.Modal;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
@ -16,6 +17,7 @@ builder.Services.AddApiClient(builder.Configuration);
|
|||||||
builder.Services.AddSingleton<SearchService>();
|
builder.Services.AddSingleton<SearchService>();
|
||||||
builder.Services.AddBlazoredModal();
|
builder.Services.AddBlazoredModal();
|
||||||
|
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
@inherits LayoutComponentBase
|
@inherits LayoutComponentBase
|
||||||
@using ShoppingAssistantWebClient.Web.Pages
|
@using ShoppingAssistantWebClient.Web.Pages
|
||||||
@using Blazored.Modal
|
@using Blazored.Modal
|
||||||
|
|
||||||
<PageTitle>CARTAID</PageTitle>
|
<PageTitle>CARTAID</PageTitle>
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" href="css/MainLayout.css" />
|
<link rel="stylesheet" href="css/MainLayout.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<CascadingBlazoredModal/>
|
<CascadingBlazoredModal/>
|
||||||
|
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<div class="sidebar-menu">
|
<div class="sidebar-menu">
|
||||||
<NavMenu/>
|
<NavMenu/>
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
<div class="line"></div>
|
<div class="line"></div>
|
||||||
<div class="elements">
|
<div class="elements">
|
||||||
<div class="info_user">
|
<div class="info_user" @onclick="ShowModal" style="cursor: pointer;">
|
||||||
<img src="/images/avatar.svg" alt="Avatar user">
|
<img src="/images/avatar.svg" alt="Avatar user">
|
||||||
<span class="user_name">User Settings</span>
|
<span class="user_name">User Settings</span>
|
||||||
</div>
|
</div>
|
||||||
@ -157,6 +157,17 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ShowModal()
|
||||||
|
{
|
||||||
|
var options = new ModalOptions()
|
||||||
|
{
|
||||||
|
DisableBackgroundCancel = true,
|
||||||
|
UseCustomLayout = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var modalRef = Modal.Show<Settings>("Settings", options);
|
||||||
|
}
|
||||||
|
|
||||||
[JSInvokable]
|
[JSInvokable]
|
||||||
public static void Update(string wishlistId)
|
public static void Update(string wishlistId)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user