toggle edit in customer view/edit page
This commit is contained in:
parent
1a0255a14a
commit
41eccd64bf
32 changed files with 1523 additions and 1483 deletions
|
@ -26,31 +26,30 @@ using Wonky.Entity.Views;
|
|||
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace Wonky.Client.Components
|
||||
namespace Wonky.Client.Components;
|
||||
|
||||
public partial class AdvisorCustomerListComponent
|
||||
{
|
||||
public partial class AdvisorCustomerListComponent
|
||||
[Parameter] public List<CompanyDto> CompanyList { get; set; } = new();
|
||||
[Parameter] public EventCallback<string> OnDelete { get; set; }
|
||||
[Parameter] public EventCallback<string> OnSelect { get; set; }
|
||||
[Inject] public NavigationManager Navigator { get; set; }
|
||||
[Inject] public IJSRuntime JsRuntime { get; set; }
|
||||
|
||||
private Lazy<IJSObjectReference> BsTooltip { get; set; } = new();
|
||||
|
||||
private InformationModal InformationModal { get; set; } = new();
|
||||
private string InfoMessage { get; set; } = "";
|
||||
private string CompanyId { get; set; } = "";
|
||||
|
||||
private void ViewCustomer(string companyId)
|
||||
{
|
||||
[Parameter] public List<CompanyDto> CompanyList { get; set; } = new();
|
||||
[Parameter] public EventCallback<string> OnDelete { get; set; }
|
||||
[Parameter] public EventCallback<string> OnSelect { get; set; }
|
||||
[Inject] public NavigationManager Navigator { get; set; }
|
||||
[Inject] public IJSRuntime JsRuntime { get; set; }
|
||||
Navigator.NavigateTo($"/advisor/customers/{companyId}");
|
||||
}
|
||||
|
||||
private Lazy<IJSObjectReference> BsTooltip { get; set; } = new();
|
||||
|
||||
private InformationModal InformationModal { get; set; } = new();
|
||||
private string InfoMessage { get; set; } = "";
|
||||
private string CompanyId { get; set; } = "";
|
||||
|
||||
private void ViewCustomer(string companyId)
|
||||
{
|
||||
Navigator.NavigateTo($"/advisor/customers/{companyId}");
|
||||
}
|
||||
|
||||
private void CallInformationModal(string info)
|
||||
{
|
||||
InfoMessage = info;
|
||||
InformationModal.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
private void CallInformationModal(string info)
|
||||
{
|
||||
InfoMessage = info;
|
||||
InformationModal.Show();
|
||||
}
|
||||
}
|
|
@ -17,35 +17,34 @@ using System.Timers;
|
|||
using Microsoft.AspNetCore.Components;
|
||||
using Timer = System.Timers.Timer;
|
||||
|
||||
namespace Wonky.Client.Components
|
||||
namespace Wonky.Client.Components;
|
||||
|
||||
public partial class CatalogSearchPhraseComponent
|
||||
{
|
||||
public partial class CatalogSearchPhraseComponent
|
||||
private Timer Timer { get; set; } = new();
|
||||
private string SearchTerm { get; set; } = "";
|
||||
[Parameter] public EventCallback<string> OnChanged { get; set; }
|
||||
|
||||
private void ClearSearch()
|
||||
{
|
||||
private Timer Timer { get; set; } = new();
|
||||
private string SearchTerm { get; set; } = "";
|
||||
[Parameter] public EventCallback<string> OnChanged { get; set; }
|
||||
|
||||
private void ClearSearch()
|
||||
{
|
||||
SearchTerm = "";
|
||||
OnChanged.InvokeAsync("");
|
||||
}
|
||||
SearchTerm = "";
|
||||
OnChanged.InvokeAsync("");
|
||||
}
|
||||
|
||||
private void OnSearchChanged()
|
||||
{
|
||||
Timer.Dispose();
|
||||
Timer = new Timer(500);
|
||||
Timer.AutoReset = false;
|
||||
Timer.Elapsed += OnTimerElapsed;
|
||||
Timer.Enabled = true;
|
||||
}
|
||||
private void OnSearchChanged()
|
||||
{
|
||||
Timer.Dispose();
|
||||
Timer = new Timer(500);
|
||||
Timer.AutoReset = false;
|
||||
Timer.Elapsed += OnTimerElapsed;
|
||||
Timer.Enabled = true;
|
||||
}
|
||||
|
||||
private void OnTimerElapsed(object? sender, ElapsedEventArgs e)
|
||||
{
|
||||
OnChanged.InvokeAsync(SearchTerm);
|
||||
Timer.Elapsed -= OnTimerElapsed;
|
||||
Timer.Enabled = false;
|
||||
Timer.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
private void OnTimerElapsed(object? sender, ElapsedEventArgs e)
|
||||
{
|
||||
OnChanged.InvokeAsync(SearchTerm);
|
||||
Timer.Elapsed -= OnTimerElapsed;
|
||||
Timer.Enabled = false;
|
||||
Timer.Dispose();
|
||||
}
|
||||
}
|
|
@ -19,48 +19,47 @@ using Wonky.Client.Services;
|
|||
using Timer = System.Timers.Timer;
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace Wonky.Client.Components
|
||||
namespace Wonky.Client.Components;
|
||||
|
||||
public partial class CustomerSearchPhraseComponent
|
||||
{
|
||||
public partial class CustomerSearchPhraseComponent
|
||||
private Timer InputTimer { get; set; } = new();
|
||||
private string SearchTerm { get; set; } = "";
|
||||
private UserProfile Profiles { get; set; } = new ();
|
||||
[Inject] public UserProfileService ProfileService { get; set; }
|
||||
[Parameter] public EventCallback<string> OnChanged { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
private Timer InputTimer { get; set; } = new();
|
||||
private string SearchTerm { get; set; } = "";
|
||||
private UserProfile Profiles { get; set; } = new ();
|
||||
[Inject] public UserProfileService ProfileService { get; set; }
|
||||
[Parameter] public EventCallback<string> OnChanged { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Profiles = await ProfileService.GetProfile();
|
||||
SearchTerm = string.IsNullOrWhiteSpace(Profiles.CompanyFilterPhrase) ? "" : Profiles.CompanyFilterPhrase.Trim();
|
||||
Profiles = await ProfileService.GetProfile();
|
||||
SearchTerm = string.IsNullOrWhiteSpace(Profiles.CompanyFilterPhrase) ? "" : Profiles.CompanyFilterPhrase.Trim();
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(SearchTerm))
|
||||
await OnChanged.InvokeAsync(SearchTerm);
|
||||
}
|
||||
|
||||
private async Task ClearSearch()
|
||||
{
|
||||
InputTimer.Dispose();
|
||||
SearchTerm = "";
|
||||
await ProfileService.SetCompanyFilterPhrase(SearchTerm.Trim());
|
||||
if(!string.IsNullOrWhiteSpace(SearchTerm))
|
||||
await OnChanged.InvokeAsync(SearchTerm);
|
||||
}
|
||||
|
||||
private async Task OnSearchChanged()
|
||||
{
|
||||
await ProfileService.SetCompanyFilterPhrase(SearchTerm.Trim());
|
||||
InputTimer.Dispose();
|
||||
InputTimer = new Timer(500);
|
||||
InputTimer.AutoReset = false;
|
||||
InputTimer.Elapsed += OnTimerElapsed;
|
||||
InputTimer.Enabled = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTimerElapsed(object? sender, ElapsedEventArgs e)
|
||||
{
|
||||
InputTimer.Dispose();
|
||||
OnChanged.InvokeAsync(SearchTerm);
|
||||
}
|
||||
}
|
||||
}
|
||||
private async Task ClearSearch()
|
||||
{
|
||||
InputTimer.Dispose();
|
||||
SearchTerm = "";
|
||||
await ProfileService.SetCompanyFilterPhrase(SearchTerm.Trim());
|
||||
await OnChanged.InvokeAsync(SearchTerm);
|
||||
}
|
||||
|
||||
private async Task OnSearchChanged()
|
||||
{
|
||||
await ProfileService.SetCompanyFilterPhrase(SearchTerm.Trim());
|
||||
InputTimer.Dispose();
|
||||
InputTimer = new Timer(500);
|
||||
InputTimer.AutoReset = false;
|
||||
InputTimer.Elapsed += OnTimerElapsed;
|
||||
InputTimer.Enabled = true;
|
||||
|
||||
}
|
||||
|
||||
private void OnTimerElapsed(object? sender, ElapsedEventArgs e)
|
||||
{
|
||||
InputTimer.Dispose();
|
||||
OnChanged.InvokeAsync(SearchTerm);
|
||||
}
|
||||
}
|
|
@ -20,38 +20,36 @@ using Microsoft.AspNetCore.Components;
|
|||
using Wonky.Client.Services;
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace Wonky.Client.Components
|
||||
{
|
||||
public partial class CustomerSortComponent : IDisposable
|
||||
{
|
||||
[Inject] public ILocalStorageService Storage { get; set; }
|
||||
[Inject] public UserProfileService ProfileService { get; set; }
|
||||
[Parameter] public EventCallback<string> OnChanged { get; set; }
|
||||
private Dictionary<string, string> Items { get; set; } = new();
|
||||
private UserProfile _profiles = new();
|
||||
private string SortCol { get; set; } = "name";
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ProfileService.OnChange += ProfileServiceOnOnChange;
|
||||
_profiles = await ProfileService.GetProfile();
|
||||
SortCol = _profiles.CompanySort;
|
||||
}
|
||||
private async Task OnSelectionChanged(ChangeEventArgs e)
|
||||
{
|
||||
var val = e.Value.ToString();
|
||||
if (val == "-1") return;
|
||||
await OnChanged.InvokeAsync(val);
|
||||
await ProfileService.SetCompanySort(val);
|
||||
}
|
||||
private void ProfileServiceOnOnChange(UserProfile newUserProfile)
|
||||
{
|
||||
_profiles = newUserProfile;
|
||||
StateHasChanged();
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
ProfileService.OnChange -= ProfileServiceOnOnChange;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Wonky.Client.Components;
|
||||
|
||||
public partial class CustomerSortComponent : IDisposable
|
||||
{
|
||||
[Inject] public ILocalStorageService Storage { get; set; }
|
||||
[Inject] public UserProfileService ProfileService { get; set; }
|
||||
[Parameter] public EventCallback<string> OnChanged { get; set; }
|
||||
private Dictionary<string, string> Items { get; set; } = new();
|
||||
private UserProfile _profiles = new();
|
||||
private string SortCol { get; set; } = "name";
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ProfileService.OnChange += ProfileServiceOnOnChange;
|
||||
_profiles = await ProfileService.GetProfile();
|
||||
SortCol = _profiles.CompanySort;
|
||||
}
|
||||
private async Task OnSelectionChanged(ChangeEventArgs e)
|
||||
{
|
||||
var val = e.Value.ToString();
|
||||
if (val == "-1") return;
|
||||
await OnChanged.InvokeAsync(val);
|
||||
await ProfileService.SetCompanySort(val);
|
||||
}
|
||||
private void ProfileServiceOnOnChange(UserProfile newUserProfile)
|
||||
{
|
||||
_profiles = newUserProfile;
|
||||
StateHasChanged();
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
ProfileService.OnChange -= ProfileServiceOnOnChange;
|
||||
}
|
||||
}
|
|
@ -27,77 +27,76 @@ using Utils = Wonky.Client.Helpers.Utils;
|
|||
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace Wonky.Client.Components
|
||||
namespace Wonky.Client.Components;
|
||||
|
||||
public partial class OfficeCountryCustomerListComponent
|
||||
{
|
||||
public partial class OfficeCountryCustomerListComponent
|
||||
// ******************************************************
|
||||
// parameters
|
||||
[Parameter] public string CountryCode { get; set; } = "";
|
||||
[Parameter] public List<CompanyDto> CompanyList { get; set; } = new();
|
||||
// [Parameter] public EventCallback<DraftItem> OnOrderItem { get; set; }
|
||||
[CascadingParameter] public DraftStateProvider DraftProvider { get; set; }
|
||||
|
||||
// ******************************************************
|
||||
// injects
|
||||
[Inject] public ICountryCustomerHistoryRepository HistoryRepo { get; set; }
|
||||
[Inject] public ICountryActivityRepository ActivityRepo { get; set; }
|
||||
|
||||
// ******************************************************
|
||||
// overlays
|
||||
private OfficeCustomerInvoiceListOverlay InvoiceListOverlay { get; set; } = new();
|
||||
private OfficeCustomerActivityListOverlay ActivityListOverlay { get; set; } = new();
|
||||
private OfficeCustomerProductListOverlay ProductListOverlay { get; set; } = new();
|
||||
|
||||
// ******************************************************
|
||||
// variables
|
||||
private InvoiceListView InvoiceList { get; set; } = new();
|
||||
private List<ReportItemView> ActivityList { get; set; } = new();
|
||||
private List<ProductInventoryView> ProductList { get; set; } = new();
|
||||
private CompanyDto SelectedCompany { get; set; } = new();
|
||||
|
||||
// ******************************************************
|
||||
// functions
|
||||
private async Task ShowInvoiceList(string companyId)
|
||||
{
|
||||
// ******************************************************
|
||||
// parameters
|
||||
[Parameter] public string CountryCode { get; set; } = "";
|
||||
[Parameter] public List<CompanyDto> CompanyList { get; set; } = new();
|
||||
// [Parameter] public EventCallback<DraftItem> OnOrderItem { get; set; }
|
||||
[CascadingParameter] public DraftStateProvider DraftProvider { get; set; }
|
||||
|
||||
// ******************************************************
|
||||
// injects
|
||||
[Inject] public ICountryCustomerHistoryRepository HistoryRepo { get; set; }
|
||||
[Inject] public ICountryActivityRepository ActivityRepo { get; set; }
|
||||
|
||||
// ******************************************************
|
||||
// overlays
|
||||
private OfficeCustomerInvoiceListOverlay InvoiceListOverlay { get; set; } = new();
|
||||
private OfficeCustomerActivityListOverlay ActivityListOverlay { get; set; } = new();
|
||||
private OfficeCustomerProductListOverlay ProductListOverlay { get; set; } = new();
|
||||
|
||||
// ******************************************************
|
||||
// variables
|
||||
private InvoiceListView InvoiceList { get; set; } = new();
|
||||
private List<ReportItemView> ActivityList { get; set; } = new();
|
||||
private List<ProductInventoryView> ProductList { get; set; } = new();
|
||||
private CompanyDto SelectedCompany { get; set; } = new();
|
||||
// check for console manipulation
|
||||
if (!Utils.Validate(VType.Id, companyId)) return;
|
||||
SelectedCompany = CompanyList.First(x => x.CompanyId == companyId);
|
||||
// call erp to crm sync before requesting invoices
|
||||
var newSyncDate = await HistoryRepo.RequestErpToCrmSync(CountryCode, companyId, SelectedCompany.HistorySync);
|
||||
await Task.Delay(500);
|
||||
InvoiceList = await HistoryRepo.RequestInvoiceList(CountryCode, companyId);
|
||||
if(!string.IsNullOrWhiteSpace(newSyncDate)) SelectedCompany.HistorySync = newSyncDate;
|
||||
InvoiceListOverlay.Show();
|
||||
}
|
||||
|
||||
// ******************************************************
|
||||
// functions
|
||||
private async Task ShowInvoiceList(string companyId)
|
||||
{
|
||||
// check for console manipulation
|
||||
if (!Utils.Validate(VType.Id, companyId)) return;
|
||||
SelectedCompany = CompanyList.First(x => x.CompanyId == companyId);
|
||||
// call erp to crm sync before requesting invoices
|
||||
var newSyncDate = await HistoryRepo.RequestErpToCrmSync(CountryCode, companyId, SelectedCompany.HistorySync);
|
||||
await Task.Delay(500);
|
||||
InvoiceList = await HistoryRepo.RequestInvoiceList(CountryCode, companyId);
|
||||
if(!string.IsNullOrWhiteSpace(newSyncDate)) SelectedCompany.HistorySync = newSyncDate;
|
||||
InvoiceListOverlay.Show();
|
||||
}
|
||||
private async Task ShowActivityList(string companyId)
|
||||
{
|
||||
// check for console manipulation
|
||||
if (!Utils.Validate(VType.Id, companyId)) return;
|
||||
SelectedCompany = CompanyList.First(x => x.CompanyId == companyId);
|
||||
ActivityList = await ActivityRepo.RequestActivityList(companyId);
|
||||
ActivityListOverlay.Show();
|
||||
}
|
||||
|
||||
private async Task ShowActivityList(string companyId)
|
||||
{
|
||||
// check for console manipulation
|
||||
if (!Utils.Validate(VType.Id, companyId)) return;
|
||||
SelectedCompany = CompanyList.First(x => x.CompanyId == companyId);
|
||||
ActivityList = await ActivityRepo.RequestActivityList(companyId);
|
||||
ActivityListOverlay.Show();
|
||||
}
|
||||
private async Task ShowInventory(string companyId)
|
||||
{
|
||||
// check for console manipulation
|
||||
if (!Utils.Validate(VType.Id, companyId)) return;
|
||||
SelectedCompany = CompanyList.First(x => x.CompanyId == companyId);
|
||||
// call erp to crm sync before requesting products
|
||||
var newSyncDate = await HistoryRepo.RequestErpToCrmSync(CountryCode, companyId, SelectedCompany.HistorySync);
|
||||
await Task.Delay(500);
|
||||
if(!string.IsNullOrWhiteSpace(newSyncDate)) SelectedCompany.HistorySync = newSyncDate;
|
||||
ProductList = await HistoryRepo.RequestInventory(SelectedCompany.CountryCode, SelectedCompany.CompanyId);
|
||||
ProductListOverlay.Show();
|
||||
}
|
||||
|
||||
private async Task ShowInventory(string companyId)
|
||||
{
|
||||
// check for console manipulation
|
||||
if (!Utils.Validate(VType.Id, companyId)) return;
|
||||
SelectedCompany = CompanyList.First(x => x.CompanyId == companyId);
|
||||
// call erp to crm sync before requesting products
|
||||
var newSyncDate = await HistoryRepo.RequestErpToCrmSync(CountryCode, companyId, SelectedCompany.HistorySync);
|
||||
await Task.Delay(500);
|
||||
if(!string.IsNullOrWhiteSpace(newSyncDate)) SelectedCompany.HistorySync = newSyncDate;
|
||||
ProductList = await HistoryRepo.RequestInventory(SelectedCompany.CountryCode, SelectedCompany.CompanyId);
|
||||
ProductListOverlay.Show();
|
||||
}
|
||||
|
||||
private async Task ShowOrder(string companyId)
|
||||
{
|
||||
// check for console manipulation
|
||||
if (!Utils.Validate(VType.Id, companyId)) return;
|
||||
SelectedCompany = CompanyList.First(x => x.CompanyId == companyId);
|
||||
}
|
||||
private async Task ShowOrder(string companyId)
|
||||
{
|
||||
// check for console manipulation
|
||||
if (!Utils.Validate(VType.Id, companyId)) return;
|
||||
SelectedCompany = CompanyList.First(x => x.CompanyId == companyId);
|
||||
}
|
||||
}
|
|
@ -20,41 +20,42 @@ using Microsoft.AspNetCore.Components;
|
|||
using Wonky.Client.Services;
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace Wonky.Client.Components
|
||||
namespace Wonky.Client.Components;
|
||||
|
||||
public partial class PageSizeComponent : IDisposable
|
||||
{
|
||||
public partial class PageSizeComponent : IDisposable
|
||||
[Inject] public ILocalStorageService Storage { get; set; }
|
||||
[Inject] public UserProfileService ProfileService { get; set; }
|
||||
[Parameter] public EventCallback<string> OnChanged { get; set; }
|
||||
private Dictionary<string, string> Items { get; set; } = new();
|
||||
private UserProfile Profile { get; set; } = new();
|
||||
private string PageSize { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
[Inject] public ILocalStorageService Storage { get; set; }
|
||||
[Inject] public UserProfileService ProfileService { get; set; }
|
||||
[Parameter] public EventCallback<string> OnChanged { get; set; }
|
||||
private Dictionary<string, string> Items { get; set; } = new();
|
||||
private UserProfile _profiles = new();
|
||||
private string PageSize { get; set; } = "";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ProfileService.OnChange += ProfileServiceOnOnChange;
|
||||
_profiles = await ProfileService.GetProfile();
|
||||
PageSize = _profiles.PageSize;
|
||||
}
|
||||
|
||||
private async Task OnSelectChanged(ChangeEventArgs e)
|
||||
{
|
||||
var val = e.Value.ToString();
|
||||
if (val == "-1") return;
|
||||
await OnChanged.InvokeAsync(val);
|
||||
await ProfileService.SetPageSize(val);
|
||||
}
|
||||
|
||||
private void ProfileServiceOnOnChange(UserProfile newUserProfile)
|
||||
{
|
||||
_profiles = newUserProfile;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ProfileService.OnChange -= ProfileServiceOnOnChange;
|
||||
}
|
||||
ProfileService.OnChange += ProfileServiceOnOnChange;
|
||||
Profile = await ProfileService.GetProfile();
|
||||
PageSize = Profile.PageSize;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnSelectChanged(ChangeEventArgs e)
|
||||
{
|
||||
var val = e.Value?.ToString();
|
||||
if (val == "-1") return;
|
||||
var cVal = Convert.ToInt32(val);
|
||||
if (cVal > 50) val = "50"; // mitigate variable manipulation
|
||||
await OnChanged.InvokeAsync(val);
|
||||
await ProfileService.SetPageSize(val);
|
||||
}
|
||||
|
||||
private void ProfileServiceOnOnChange(UserProfile newUserProfile)
|
||||
{
|
||||
Profile = newUserProfile;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ProfileService.OnChange -= ProfileServiceOnOnChange;
|
||||
}
|
||||
}
|
|
@ -19,44 +19,43 @@ using Microsoft.AspNetCore.Components;
|
|||
using Wonky.Client.Features;
|
||||
using Wonky.Entity.Requests;
|
||||
|
||||
namespace Wonky.Client.Components
|
||||
namespace Wonky.Client.Components;
|
||||
|
||||
public partial class PaginationComponent
|
||||
{
|
||||
public partial class PaginationComponent
|
||||
[Parameter] public MetaData MetaData { get; set; } = new();
|
||||
[Parameter] public int Spread { get; set; }
|
||||
[Parameter] public EventCallback<int> SelectedPage { get; set; }
|
||||
private List<PagingLink> Links { get; set; } = new();
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
[Parameter] public MetaData MetaData { get; set; } = new();
|
||||
[Parameter] public int Spread { get; set; }
|
||||
[Parameter] public EventCallback<int> SelectedPage { get; set; }
|
||||
private List<PagingLink> Links { get; set; } = new();
|
||||
CreatePaginationLinks();
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
private void CreatePaginationLinks()
|
||||
{
|
||||
Links = new List<PagingLink>
|
||||
{
|
||||
CreatePaginationLinks();
|
||||
}
|
||||
new(MetaData.CurrentPage - 1, MetaData.HasPrevious, "Forrige")
|
||||
};
|
||||
|
||||
private void CreatePaginationLinks()
|
||||
for (var i = 1; i <= MetaData.TotalPages; i++)
|
||||
{
|
||||
Links = new List<PagingLink>
|
||||
if (i >= MetaData.CurrentPage - Spread && i <= MetaData.CurrentPage + Spread)
|
||||
{
|
||||
new(MetaData.CurrentPage - 1, MetaData.HasPrevious, "Forrige")
|
||||
};
|
||||
|
||||
for (var i = 1; i <= MetaData.TotalPages; i++)
|
||||
{
|
||||
if (i >= MetaData.CurrentPage - Spread && i <= MetaData.CurrentPage + Spread)
|
||||
{
|
||||
Links.Add(new PagingLink(i, true, i.ToString()) {Active = MetaData.CurrentPage == i});
|
||||
}
|
||||
Links.Add(new PagingLink(i, true, i.ToString()) {Active = MetaData.CurrentPage == i});
|
||||
}
|
||||
|
||||
Links.Add(new PagingLink(MetaData.CurrentPage + 1, MetaData.HasNext, "Næste"));
|
||||
}
|
||||
|
||||
private async Task OnSelectedPage(PagingLink link)
|
||||
{
|
||||
if (link.Page == MetaData.CurrentPage || !link.Enabled)
|
||||
return;
|
||||
MetaData.CurrentPage = link.Page;
|
||||
await SelectedPage.InvokeAsync(link.Page);
|
||||
}
|
||||
Links.Add(new PagingLink(MetaData.CurrentPage + 1, MetaData.HasNext, "Næste"));
|
||||
}
|
||||
|
||||
private async Task OnSelectedPage(PagingLink link)
|
||||
{
|
||||
if (link.Page == MetaData.CurrentPage || !link.Enabled)
|
||||
return;
|
||||
MetaData.CurrentPage = link.Page;
|
||||
await SelectedPage.InvokeAsync(link.Page);
|
||||
}
|
||||
}
|
|
@ -21,57 +21,56 @@ using Wonky.Client.HttpRepository;
|
|||
using Wonky.Client.Shared;
|
||||
using Wonky.Entity.DTO;
|
||||
|
||||
namespace Wonky.Client.Components
|
||||
namespace Wonky.Client.Components;
|
||||
|
||||
public partial class TaskItemTableComponent
|
||||
{
|
||||
public partial class TaskItemTableComponent
|
||||
[Parameter] public List<TaskItemDto> TaskItemList { get; set; } = new();
|
||||
[Parameter] public EventCallback<string> OnDeleteTask { get; set; }
|
||||
[Parameter] public EventCallback<string> OnCompleteTask { get; set; }
|
||||
[Parameter] public EventCallback<string> OnTaskCompleted { get; set; }
|
||||
|
||||
private ConfirmationModal _confirmationModal = new ();
|
||||
private string _taskItemIdToDelete = "";
|
||||
|
||||
/// <summary>
|
||||
/// Complete task callback
|
||||
/// </summary>
|
||||
/// <param name="taskItemId"></param>
|
||||
private async Task CompleteTask(string taskItemId)
|
||||
{
|
||||
[Parameter] public List<TaskItemDto> TaskItemList { get; set; } = new();
|
||||
[Parameter] public EventCallback<string> OnDeleteTask { get; set; }
|
||||
[Parameter] public EventCallback<string> OnCompleteTask { get; set; }
|
||||
[Parameter] public EventCallback<string> OnTaskCompleted { get; set; }
|
||||
await OnCompleteTask.InvokeAsync(taskItemId);
|
||||
}
|
||||
|
||||
private ConfirmationModal _confirmationModal = new ();
|
||||
private string _taskItemIdToDelete = "";
|
||||
/// <summary>
|
||||
/// Task completed callback
|
||||
/// </summary>
|
||||
/// <param name="taskItemId"></param>
|
||||
private async Task TaskCompleted(string taskItemId)
|
||||
{
|
||||
await OnTaskCompleted.InvokeAsync(taskItemId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Complete task callback
|
||||
/// </summary>
|
||||
/// <param name="taskItemId"></param>
|
||||
private async Task CompleteTask(string taskItemId)
|
||||
{
|
||||
await OnCompleteTask.InvokeAsync(taskItemId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Task completed callback
|
||||
/// </summary>
|
||||
/// <param name="taskItemId"></param>
|
||||
private async Task TaskCompleted(string taskItemId)
|
||||
{
|
||||
await OnTaskCompleted.InvokeAsync(taskItemId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirm delete
|
||||
/// </summary>
|
||||
/// <param name="taskItemId"></param>
|
||||
private void CallConfirmationModal(string taskItemId)
|
||||
{
|
||||
_taskItemIdToDelete = taskItemId;
|
||||
_confirmationModal.Show();
|
||||
}
|
||||
/// <summary>
|
||||
/// Confirm delete
|
||||
/// </summary>
|
||||
/// <param name="taskItemId"></param>
|
||||
private void CallConfirmationModal(string taskItemId)
|
||||
{
|
||||
_taskItemIdToDelete = taskItemId;
|
||||
_confirmationModal.Show();
|
||||
}
|
||||
|
||||
private void OnCancelCallback()
|
||||
{
|
||||
_confirmationModal.Hide();
|
||||
}
|
||||
/// <summary>
|
||||
/// Delete task call back
|
||||
/// </summary>
|
||||
private async Task DeleteTask()
|
||||
{
|
||||
_confirmationModal.Hide();
|
||||
await OnDeleteTask.InvokeAsync(_taskItemIdToDelete);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void OnCancelCallback()
|
||||
{
|
||||
_confirmationModal.Hide();
|
||||
}
|
||||
/// <summary>
|
||||
/// Delete task call back
|
||||
/// </summary>
|
||||
private async Task DeleteTask()
|
||||
{
|
||||
_confirmationModal.Hide();
|
||||
await OnDeleteTask.InvokeAsync(_taskItemIdToDelete);
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
|
||||
using System.Globalization;
|
||||
using System.Text.Json;
|
||||
using Blazored.LocalStorage;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
|
@ -69,8 +70,8 @@ public partial class WorkDateComponent : IDisposable
|
|||
/// <param name="e"></param>
|
||||
private async Task OnDateChanged(ChangeEventArgs e)
|
||||
{
|
||||
var x = DateTime.TryParse(e.Value.ToString(), out var setDate);
|
||||
if (x)
|
||||
if (string.IsNullOrWhiteSpace(e.Value.ToString())) return;
|
||||
if (DateTime.TryParse(e.Value.ToString(), out var setDate))
|
||||
{
|
||||
await UserProfile.SetWorkDate(setDate);
|
||||
await OnChangedCallback.InvokeAsync($"{setDate:yyyy-MM-dd}");
|
||||
|
|
|
@ -26,337 +26,336 @@
|
|||
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Wonky.Client.Helpers
|
||||
namespace Wonky.Client.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Squid is guid string shortened and url safe
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{" + nameof(Value) + "}")]
|
||||
public readonly struct Squid : IEquatable<Squid>
|
||||
{
|
||||
/// <summary>
|
||||
/// Squid is guid string shortened and url safe
|
||||
/// Return Empty value
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{" + nameof(Value) + "}")]
|
||||
public readonly struct Squid : IEquatable<Squid>
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public static readonly Squid Empty = new(Guid.Empty);
|
||||
|
||||
/// <summary>
|
||||
/// Decode Squid to Guid
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public Squid(string value)
|
||||
{
|
||||
/// <summary>
|
||||
/// Return Empty value
|
||||
/// </summary>
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public static readonly Squid Empty = new(Guid.Empty);
|
||||
Value = value;
|
||||
Guid = DecodeSquid(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decode Squid to Guid
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public Squid(string value)
|
||||
/// <summary>
|
||||
/// Generate Squid from Guid object
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
public Squid(Guid obj)
|
||||
{
|
||||
Value = EncodeGuid(obj);
|
||||
Guid = obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Guid
|
||||
/// </summary>
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public Guid Guid { get; }
|
||||
|
||||
public string Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// ToString() function
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Equality
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is Squid other && Equals(other);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// EQuality
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public bool Equals(Squid obj)
|
||||
{
|
||||
return Guid.Equals(obj.Guid) && Value == obj.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get hashcode
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
Value = value;
|
||||
Guid = DecodeSquid(value);
|
||||
return (Guid.GetHashCode() * 397) ^ (Value != null ? Value.GetHashCode() : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate Squid from Guid object
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
public Squid(Guid obj)
|
||||
/// <summary>
|
||||
/// Create Squid from new Guid
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Squid NewGuid()
|
||||
{
|
||||
return new Squid(Guid.NewGuid());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encode string
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static string EncodeString(string value)
|
||||
{
|
||||
var guid = new Guid(value);
|
||||
return EncodeGuid(guid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encode Guid
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public static string EncodeGuid(Guid obj)
|
||||
{
|
||||
var encoded = Convert.ToBase64String(obj.ToByteArray());
|
||||
encoded = encoded
|
||||
.Replace("/", "_")
|
||||
.Replace("+", "-");
|
||||
return encoded.Substring(0, 22);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decode Squid
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public static Guid DecodeSquid(string value)
|
||||
{
|
||||
if (!value.Any()) return Empty;
|
||||
value = value
|
||||
.Replace("_", "/")
|
||||
.Replace("-", "+");
|
||||
var blob = Convert.FromBase64String(value + "==");
|
||||
return new Guid(blob);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Guid From Squid
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static Guid FromSquid(Squid obj)
|
||||
{
|
||||
return obj.Guid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Squid From String
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static Squid FromString(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return Empty;
|
||||
return TryParse(value, out Squid obj) ? obj : Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryDecode
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public static bool TryDecode(string value, out Guid obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
Value = EncodeGuid(obj);
|
||||
Guid = obj;
|
||||
// Decode as Squid
|
||||
obj = DecodeSquid(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Guid
|
||||
/// </summary>
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public Guid Guid { get; }
|
||||
|
||||
public string Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// ToString() function
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
catch (Exception)
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Equality
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is Squid other && Equals(other);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// EQuality
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public bool Equals(Squid obj)
|
||||
{
|
||||
return Guid.Equals(obj.Guid) && Value == obj.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get hashcode
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (Guid.GetHashCode() * 397) ^ (Value != null ? Value.GetHashCode() : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create Squid from new Guid
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Squid NewGuid()
|
||||
{
|
||||
return new Squid(Guid.NewGuid());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encode string
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static string EncodeString(string value)
|
||||
{
|
||||
var guid = new Guid(value);
|
||||
return EncodeGuid(guid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encode Guid
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public static string EncodeGuid(Guid obj)
|
||||
{
|
||||
var encoded = Convert.ToBase64String(obj.ToByteArray());
|
||||
encoded = encoded
|
||||
.Replace("/", "_")
|
||||
.Replace("+", "-");
|
||||
return encoded.Substring(0, 22);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decode Squid
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public static Guid DecodeSquid(string value)
|
||||
{
|
||||
if (!value.Any()) return Empty;
|
||||
value = value
|
||||
.Replace("_", "/")
|
||||
.Replace("-", "+");
|
||||
var blob = Convert.FromBase64String(value + "==");
|
||||
return new Guid(blob);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Guid From Squid
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static Guid FromSquid(Squid obj)
|
||||
{
|
||||
return obj.Guid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Squid From String
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static Squid FromString(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return Empty;
|
||||
return TryParse(value, out Squid obj) ? obj : Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryDecode
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public static bool TryDecode(string value, out Guid obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Decode as Squid
|
||||
obj = DecodeSquid(value);
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Return empty Guid
|
||||
obj = Guid.Empty;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryParse
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public static bool TryParse(string value, out Squid obj)
|
||||
{
|
||||
// Parse as Squid string.
|
||||
if (TryDecode(value, out var oGuid))
|
||||
{
|
||||
obj = oGuid;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parse as Guid string.
|
||||
if (Guid.TryParse(value, out oGuid))
|
||||
{
|
||||
obj = oGuid;
|
||||
return true;
|
||||
}
|
||||
|
||||
obj = Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryParse
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryParse(string value, out Guid obj)
|
||||
{
|
||||
// Try a Squid string.
|
||||
if (TryDecode(value, out obj))
|
||||
return true;
|
||||
// Try a Guid string.
|
||||
if (Guid.TryParse(value, out obj))
|
||||
return true;
|
||||
// Return empty Guid
|
||||
obj = Guid.Empty;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(Squid x, Squid y)
|
||||
/// <summary>
|
||||
/// TryParse
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
public static bool TryParse(string value, out Squid obj)
|
||||
{
|
||||
// Parse as Squid string.
|
||||
if (TryDecode(value, out var oGuid))
|
||||
{
|
||||
return x.Guid == y.Guid;
|
||||
obj = oGuid;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(Squid x, Guid y)
|
||||
// Parse as Guid string.
|
||||
if (Guid.TryParse(value, out oGuid))
|
||||
{
|
||||
return x.Guid == y;
|
||||
obj = oGuid;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(Guid x, Squid y)
|
||||
{
|
||||
return y == x; // NB: order of arguments
|
||||
}
|
||||
obj = Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(Squid x, Squid y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
/// <summary>
|
||||
/// TryParse
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryParse(string value, out Guid obj)
|
||||
{
|
||||
// Try a Squid string.
|
||||
if (TryDecode(value, out obj))
|
||||
return true;
|
||||
// Try a Guid string.
|
||||
if (Guid.TryParse(value, out obj))
|
||||
return true;
|
||||
obj = Guid.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(Squid x, Guid y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(Squid x, Squid y)
|
||||
{
|
||||
return x.Guid == y.Guid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(Guid x, Squid y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(Squid x, Guid y)
|
||||
{
|
||||
return x.Guid == y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="oSquid"></param>
|
||||
/// <returns></returns>
|
||||
public static implicit operator string(Squid oSquid)
|
||||
{
|
||||
return oSquid.Value;
|
||||
}
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(Guid x, Squid y)
|
||||
{
|
||||
return y == x; // NB: order of arguments
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="oSquid"></param>
|
||||
/// <returns></returns>
|
||||
public static implicit operator Guid(Squid oSquid)
|
||||
{
|
||||
return oSquid.Guid;
|
||||
}
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(Squid x, Squid y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static implicit operator Squid(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return Empty;
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(Squid x, Guid y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
return TryParse(value, out Squid oSquid) ? oSquid : Empty;
|
||||
}
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(Guid x, Squid y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="oGuid"></param>
|
||||
/// <returns></returns>
|
||||
public static implicit operator Squid(Guid oGuid)
|
||||
{
|
||||
return oGuid == Guid.Empty ? Empty : new Squid(oGuid);
|
||||
}
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="oSquid"></param>
|
||||
/// <returns></returns>
|
||||
public static implicit operator string(Squid oSquid)
|
||||
{
|
||||
return oSquid.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="oSquid"></param>
|
||||
/// <returns></returns>
|
||||
public static implicit operator Guid(Squid oSquid)
|
||||
{
|
||||
return oSquid.Guid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static implicit operator Squid(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return Empty;
|
||||
|
||||
return TryParse(value, out Squid oSquid) ? oSquid : Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operator
|
||||
/// </summary>
|
||||
/// <param name="oGuid"></param>
|
||||
/// <returns></returns>
|
||||
public static implicit operator Squid(Guid oGuid)
|
||||
{
|
||||
return oGuid == Guid.Empty ? Empty : new Squid(oGuid);
|
||||
}
|
||||
}
|
|
@ -23,104 +23,102 @@ using Wonky.Client.Services;
|
|||
using Microsoft.AspNetCore.Components;
|
||||
using Toolbelt.Blazor;
|
||||
|
||||
namespace Wonky.Client.HttpInterceptors
|
||||
namespace Wonky.Client.HttpInterceptors;
|
||||
|
||||
public class HttpInterceptorService
|
||||
{
|
||||
public class HttpInterceptorService
|
||||
private readonly HttpClientInterceptor _interceptor;
|
||||
private readonly NavigationManager _navigation;
|
||||
private readonly IToastService _toast;
|
||||
private readonly RefreshTokenService _refreshTokenService;
|
||||
private readonly ILogger<HttpInterceptorService> _logger;
|
||||
private readonly ILocalStorageService _storage;
|
||||
private readonly IAuthenticationService _authenticationService;
|
||||
|
||||
public HttpInterceptorService(HttpClientInterceptor interceptor,
|
||||
NavigationManager navigation, IToastService toast,
|
||||
RefreshTokenService refreshTokenService, ILogger<HttpInterceptorService> logger,
|
||||
ILocalStorageService storage, IAuthenticationService authenticationService)
|
||||
{
|
||||
private readonly HttpClientInterceptor _interceptor;
|
||||
private readonly NavigationManager _navigation;
|
||||
private readonly IToastService _toast;
|
||||
private readonly RefreshTokenService _refreshTokenService;
|
||||
private readonly ILogger<HttpInterceptorService> _logger;
|
||||
private readonly ILocalStorageService _storage;
|
||||
private readonly IAuthenticationService _authenticationService;
|
||||
_interceptor = interceptor;
|
||||
_navigation = navigation;
|
||||
_toast = toast;
|
||||
_refreshTokenService = refreshTokenService;
|
||||
_logger = logger;
|
||||
_storage = storage;
|
||||
_authenticationService = authenticationService;
|
||||
}
|
||||
|
||||
public HttpInterceptorService(HttpClientInterceptor interceptor,
|
||||
NavigationManager navigation, IToastService toast,
|
||||
RefreshTokenService refreshTokenService, ILogger<HttpInterceptorService> logger,
|
||||
ILocalStorageService storage, IAuthenticationService authenticationService)
|
||||
{
|
||||
_interceptor = interceptor;
|
||||
_navigation = navigation;
|
||||
_toast = toast;
|
||||
_refreshTokenService = refreshTokenService;
|
||||
_logger = logger;
|
||||
_storage = storage;
|
||||
_authenticationService = authenticationService;
|
||||
}
|
||||
public void RegisterEvent()
|
||||
{
|
||||
_interceptor.AfterSend += AfterSend;
|
||||
}
|
||||
|
||||
public void RegisterEvent()
|
||||
{
|
||||
_interceptor.AfterSend += AfterSend;
|
||||
}
|
||||
|
||||
public void RegisterBeforeSendEvent()
|
||||
{
|
||||
_interceptor.BeforeSendAsync += InterceptBeforeSend;
|
||||
}
|
||||
public void RegisterBeforeSendEvent()
|
||||
{
|
||||
_interceptor.BeforeSendAsync += InterceptBeforeSend;
|
||||
}
|
||||
|
||||
public void DisposeEvent()
|
||||
{
|
||||
_interceptor.AfterSend -= AfterSend;
|
||||
_interceptor.BeforeSendAsync -= InterceptBeforeSend;
|
||||
}
|
||||
public void DisposeEvent()
|
||||
{
|
||||
_interceptor.AfterSend -= AfterSend;
|
||||
_interceptor.BeforeSendAsync -= InterceptBeforeSend;
|
||||
}
|
||||
|
||||
private async Task InterceptBeforeSend(object sender, HttpClientInterceptorEventArgs e)
|
||||
private async Task InterceptBeforeSend(object sender, HttpClientInterceptorEventArgs e)
|
||||
{
|
||||
var absolutePath = e.Request.RequestUri.AbsolutePath;
|
||||
if (!absolutePath.Contains("token"))
|
||||
{
|
||||
var absolutePath = e.Request.RequestUri.AbsolutePath;
|
||||
if (!absolutePath.Contains("token"))
|
||||
// call TryRefreshToken
|
||||
var token = await _refreshTokenService.TryRefreshToken();
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
// call TryRefreshToken
|
||||
var token = await _refreshTokenService.TryRefreshToken();
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
// set new token
|
||||
e.Request.Headers.Authorization = new AuthenticationHeaderValue("bearer", token);
|
||||
}
|
||||
// set new token
|
||||
e.Request.Headers.Authorization = new AuthenticationHeaderValue("bearer", token);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void AfterSend (object sender, HttpClientInterceptorEventArgs e)
|
||||
private void AfterSend (object sender, HttpClientInterceptorEventArgs e)
|
||||
{
|
||||
if (e.Response == null || e.Response.IsSuccessStatusCode)
|
||||
return;
|
||||
|
||||
var message = $"En fejl er opstået \n {JsonSerializer.Serialize(e)}";
|
||||
var currDoc = _navigation.ToBaseRelativePath(_navigation.Uri);
|
||||
if (currDoc.Contains("login/"))
|
||||
currDoc = "";
|
||||
|
||||
switch (e.Response.StatusCode)
|
||||
{
|
||||
if (e.Response == null || e.Response.IsSuccessStatusCode)
|
||||
return;
|
||||
|
||||
var message = $"En fejl er opstået \n {JsonSerializer.Serialize(e)}";
|
||||
var currDoc = _navigation.ToBaseRelativePath(_navigation.Uri);
|
||||
if (currDoc.Contains("login/"))
|
||||
currDoc = "";
|
||||
|
||||
switch (e.Response.StatusCode)
|
||||
{
|
||||
case HttpStatusCode.NotFound:
|
||||
_logger.LogDebug("NotFound <= {}", currDoc);
|
||||
break;
|
||||
case HttpStatusCode.BadRequest:
|
||||
_logger.LogDebug("BadRequest <= {}", currDoc);
|
||||
_logger.LogDebug("{}", message);
|
||||
break;
|
||||
case HttpStatusCode.Unauthorized:
|
||||
_logger.LogDebug("Unauthorized <= {}", currDoc);
|
||||
_logger.LogDebug("{}", message);
|
||||
_authenticationService.Logout();
|
||||
_navigation.NavigateTo($"/login/{currDoc}");
|
||||
_toast.ShowInfo("Venligst Login. Tak.");
|
||||
break;
|
||||
case HttpStatusCode.Conflict:
|
||||
_logger.LogDebug("Conflict <= {}", currDoc);
|
||||
_logger.LogDebug("{}", message);
|
||||
break;
|
||||
case HttpStatusCode.InternalServerError:
|
||||
_logger.LogDebug("InternalServerError <= {}", currDoc);
|
||||
_logger.LogDebug("{}", message);
|
||||
break;
|
||||
default:
|
||||
_logger.LogDebug("{}", message);
|
||||
break;
|
||||
}
|
||||
// throw new HttpResponseException(message);
|
||||
case HttpStatusCode.NotFound:
|
||||
_logger.LogDebug("NotFound <= {}", currDoc);
|
||||
break;
|
||||
case HttpStatusCode.BadRequest:
|
||||
_logger.LogDebug("BadRequest <= {}", currDoc);
|
||||
_logger.LogDebug("{}", message);
|
||||
break;
|
||||
case HttpStatusCode.Unauthorized:
|
||||
_logger.LogDebug("Unauthorized <= {}", currDoc);
|
||||
_logger.LogDebug("{}", message);
|
||||
_authenticationService.Logout();
|
||||
_navigation.NavigateTo($"/login/{currDoc}");
|
||||
_toast.ShowInfo("Venligst Login. Tak.");
|
||||
break;
|
||||
case HttpStatusCode.Conflict:
|
||||
_logger.LogDebug("Conflict <= {}", currDoc);
|
||||
_logger.LogDebug("{}", message);
|
||||
break;
|
||||
case HttpStatusCode.InternalServerError:
|
||||
_logger.LogDebug("InternalServerError <= {}", currDoc);
|
||||
_logger.LogDebug("{}", message);
|
||||
break;
|
||||
default:
|
||||
_logger.LogDebug("{}", message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// throw new HttpResponseException(message);
|
||||
}
|
||||
}
|
|
@ -16,26 +16,25 @@
|
|||
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Wonky.Client.HttpInterceptors
|
||||
namespace Wonky.Client.HttpInterceptors;
|
||||
|
||||
[Serializable]
|
||||
public class HttpResponseException : Exception
|
||||
{
|
||||
[Serializable]
|
||||
public class HttpResponseException : Exception
|
||||
public HttpResponseException()
|
||||
{
|
||||
public HttpResponseException()
|
||||
{
|
||||
}
|
||||
public HttpResponseException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
public HttpResponseException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
public HttpResponseException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public HttpResponseException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
public HttpResponseException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
public HttpResponseException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
|
@ -30,7 +30,7 @@
|
|||
<div class="row g-3">
|
||||
<label for="date" class="col-form-label-sm col-sm-1">Dato</label>
|
||||
<div class="col-sm-3">
|
||||
<input id="date" class="form-control" type="text" value="@(DateTime.Parse(ReportItem.CreateTimestamp).ToShortDateString())" readonly/>
|
||||
<input id="date" class="form-control" type="text" value="@ReportItem.CreateTimestamp" readonly/>
|
||||
</div>
|
||||
|
||||
<label for="account" class="col-form-label-sm col-sm-1">Konto</label>
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
<div class="row bg-dark text-white rounded-2 mb-2 py-2 align-items-center">
|
||||
<div class="col">
|
||||
<WorkDateComponent OnChangedCallback="WorkDateComponentCallback" />
|
||||
<WorkDateComponent OnChangedCallback="WorkDateComponentCallback"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
|||
{
|
||||
<div class="alert alert-danger">
|
||||
<h4>Ring til kontoret. Denne konto er spærret med kode '@Company.Blocked'</h4>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row mb-2 bg-dark text-white rounded-3 p-3">
|
||||
<div class="col">
|
||||
|
@ -46,10 +46,9 @@
|
|||
{
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>Der kan ikke oprettes besøg når der findes rapport for @SelectedDate.ToShortDateString()</h3>
|
||||
<h3>Der kan ikke oprettes besøg når der findes rapport for @SelectedDate.ToShortDateString()</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -81,8 +80,8 @@ else
|
|||
{
|
||||
<option value="order">Bestilling</option>
|
||||
}
|
||||
|
||||
@if(DraftProvider.Draft.DraftType == "offer")
|
||||
|
||||
@if (DraftProvider.Draft.DraftType == "offer")
|
||||
{
|
||||
<option selected value="quote">Tilbud</option>
|
||||
}
|
||||
|
@ -137,7 +136,7 @@ else
|
|||
<InputText id="phone" class="form-control" @bind-Value="Activity.Phone"/>
|
||||
<ValidationMessage For="@(() => Activity.Phone)"></ValidationMessage>
|
||||
</div>
|
||||
|
||||
|
||||
<label for="orderMessage" class="col-sm-2 col-form-label-sm">Note /Kontor</label>
|
||||
<div class="col-sm-4">
|
||||
<InputTextArea id="orderMessage" class="form-control" @bind-Value="Activity.OrderMessage"/>
|
||||
|
@ -149,15 +148,15 @@ else
|
|||
<InputTextArea id="crmNote" class="form-control" @bind-Value="Activity.CrmNote"/>
|
||||
<ValidationMessage For="@(() => Activity.CrmNote)"></ValidationMessage>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6"></div>
|
||||
|
||||
<div class="col-sm-6"></div>
|
||||
<label for="vatNumber" class="col-sm-2 col-form-label-sm">Cvr/Org nr.</label>
|
||||
<div class="col-sm-4">
|
||||
<InputText id="vatNumber" class="form-control" @bind-Value="Activity.VatNumber" />
|
||||
<ValidationMessage For="@(() => Activity.VatNumber)" />
|
||||
<InputText id="vatNumber" class="form-control" @bind-Value="Activity.VatNumber"/>
|
||||
<ValidationMessage For="@(() => Activity.VatNumber)"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-sm-3 d-grid mx-auto">
|
||||
@*
|
||||
|
@ -178,7 +177,7 @@ else
|
|||
<button class="btn btn-success" disabled="@string.IsNullOrWhiteSpace(Activity.ActivityTypeEnum)" @onclick="ShowInventoryOverlay">Produkter</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="this-draft" style="@(Activity.ActivityStatusEnum is "order" or "quote" ? "display: block" : "display:none")">
|
||||
@* Draft lines in draft -----------------------------------------------------*@
|
||||
<div class="row">
|
||||
|
@ -275,7 +274,7 @@ else
|
|||
</td>
|
||||
<td class="align-middle" style="min-width:200px;">
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control" @bind-value="@Price"/>
|
||||
<input type="number" class="form-control" @bind-value="@Price"/>
|
||||
@*
|
||||
***************** Price history overlay button *****************************
|
||||
*@
|
||||
|
@ -285,10 +284,10 @@ else
|
|||
</div>
|
||||
</td>
|
||||
<td class="align-middle" style="min-width:100px;">
|
||||
<input type="number" class="form-control" @bind-value="@Discount"/>
|
||||
<input type="number" class="form-control" @bind-value="@Discount"/>
|
||||
</td>
|
||||
<td class="align-middle align-content-center justify-content-center">
|
||||
<input type="checkbox" class="form-check" @bind-value="@Sas"/>
|
||||
<input type="checkbox" class="form-check" @bind-value="@Sas"/>
|
||||
</td>
|
||||
<td class="align-middle">@SelectedItem.Sku</td>
|
||||
<td class="align-middle">
|
||||
|
@ -360,26 +359,27 @@ else
|
|||
***************** Confirm product check overlay button *****************************
|
||||
***************** Continue by submitton order to erp *****************************
|
||||
*@
|
||||
<button type="button" class="btn btn-warning" @onclick="CallConfirmCheckOverlay" disabled="@(PoFormInvalid || Working)"><i class="bi-cloud-arrow-up"></i> @ButtonText</button>
|
||||
<button type="button" class="btn btn-warning" @onclick="CallConfirmCheckOverlay" disabled="@(PoFormInvalid || Working)">
|
||||
<i class="bi-cloud-arrow-up"></i> @ButtonText
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<ProductCheckConfirmationOverlay BodyMessage="" CompanyId="@CompanyId" Products="CheckList"
|
||||
OnOkClicked="ConfirmProductCheckCallback" @ref="ConfirmationCheckOverlay" />
|
||||
<ConfirmWorkDateModal BodyMessage="@PromptDateConfirm"
|
||||
<ProductCheckConfirmationOverlay BodyMessage="" CompanyId="@CompanyId" Products="CheckList"
|
||||
OnOkClicked="ConfirmProductCheckCallback" @ref="ConfirmationCheckOverlay"/>
|
||||
<ConfirmWorkDateModal BodyMessage="@PromptDateConfirm"
|
||||
OnOkClicked="WorkDateConfirmCallback" @ref="ConfirmWorkDate"/>
|
||||
|
||||
<ProductHistoryOverlay CompanyId="@CompanyId" ItemSku="@SelectedItem.Sku" @ref="ProductOverlay"/>
|
||||
|
||||
<PriceCatalogOverlay CountryCode="@Company.CountryCode.ToLower()" OnSelected="PriceListCallback" @ref="CatalogOverlay"/>
|
||||
<PriceCatalogOverlay CountryCode="@Company.CountryCode.ToLower()" OnSelected="PriceListCallback" @ref="CatalogOverlay"/>
|
||||
|
||||
<ProductPriceHistoryOverlay CompanyId="@CompanyId" Sku="@SelectedItem.Sku" OnSelected="PriceHistoryCallback" @ref="PriceOverlay"/>
|
||||
|
||||
<CustomerInvoiceListOverlay CustomerInvoices="CompanyInvoices" @ref="InvoiceListOverlay" />
|
||||
<CustomerInvoiceListOverlay CustomerInvoices="CompanyInvoices" @ref="InvoiceListOverlay"/>
|
||||
|
||||
<CustomerActivityListOverlay Activities="Activities" CompanyName="@Company.Name" @ref="ActivityListOverlay" />
|
||||
<CustomerActivityListOverlay Activities="Activities" CompanyName="@Company.Name" @ref="ActivityListOverlay"/>
|
||||
|
||||
<CustomerInventoryListOverlay CompanyName="@Company.Name" CompanyId="@CompanyId" CountryCode="@Company.CountryCode"
|
||||
OnSelected="OnInventoryCallback" Inventory="Inventory" @ref="InventoryListOverlay" />
|
||||
|
||||
<CustomerInventoryListOverlay CompanyName="@Company.Name" CompanyId="@CompanyId" CountryCode="@Company.CountryCode"
|
||||
OnSelected="OnInventoryCallback" Inventory="Inventory" @ref="InventoryListOverlay"/>
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
// Copyright (C) 2022 FCS Frede's Computer Services.
|
||||
// Copyright (C) 2022 FCS Frede's Computer Services.
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
|
@ -30,6 +29,7 @@ using Wonky.Client.Services;
|
|||
using Wonky.Client.Shared;
|
||||
using Wonky.Entity.DTO;
|
||||
using Wonky.Entity.Views;
|
||||
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace Wonky.Client.Pages;
|
||||
|
@ -49,18 +49,22 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
[Inject] public IAdvisorActivityRepository ActivityRepo { get; set; }
|
||||
[Inject] public IAdvisorReportRepository ReportRepo { get; set; }
|
||||
[Inject] public IAdvisorCustomerHistoryRepository HistoryRepo { get; set; }
|
||||
[Inject] public IUserInfoService UserInfoService { get; set; }
|
||||
|
||||
[Inject] public IUserInfoService UserService { get; set; }
|
||||
|
||||
// *************************************************************
|
||||
// Parameters
|
||||
[CascadingParameter] private DraftStateProvider DraftProvider { get; set; } = new();
|
||||
|
||||
[Parameter] public string CompanyId { get; set; } = "";
|
||||
|
||||
// *************************************************************
|
||||
// Variables
|
||||
private readonly JsonSerializerOptions _options = new() {PropertyNameCaseInsensitive = true};
|
||||
private readonly JsonSerializerOptions _options = new() { PropertyNameCaseInsensitive = true };
|
||||
private SalesItemView SelectedItem { get; set; } = new();
|
||||
private UserProfile UserProfile { get; set; } = new();
|
||||
private ActivityDto Activity { get; set; } = new();
|
||||
private CompanyDto Company = new();
|
||||
private CompanyDto Company { get; set; } = new();
|
||||
private EditContext? ActivityContext { get; set; }
|
||||
private bool PoFormInvalid { get; set; } = true;
|
||||
private bool ShowItem { get; set; }
|
||||
|
@ -69,7 +73,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
private string Discount { get; set; } = "0";
|
||||
private bool Sas { get; set; }
|
||||
private bool InvalidActivityType { get; set; } = true;
|
||||
private bool InvalidActivity { get; set; } = true;
|
||||
private bool InvalidActivity { get; set; } = true;
|
||||
private bool ReportClosed { get; set; }
|
||||
private bool Working { get; set; } = true;
|
||||
private UserManagerEditView SalesRep { get; set; } = new();
|
||||
|
@ -78,7 +82,9 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
private string PromptDateConfirm { get; set; } = "";
|
||||
private string ButtonText { get; set; } = "Gem besøg";
|
||||
private bool OrgWarning { get; set; }
|
||||
|
||||
private const string PromptDemoForgotten = "Har du glemt demo?";
|
||||
|
||||
// *************************************************************
|
||||
// Overlays
|
||||
private PriceCatalogOverlay CatalogOverlay { get; set; } = new();
|
||||
|
@ -88,14 +94,16 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
private ProductCheckConfirmationOverlay ConfirmationCheckOverlay { get; set; } = new();
|
||||
private CustomerInvoiceListOverlay InvoiceListOverlay { get; set; } = new();
|
||||
private CustomerInventoryListOverlay InventoryListOverlay { get; set; } = new();
|
||||
|
||||
private CustomerActivityListOverlay ActivityListOverlay { get; set; } = new();
|
||||
|
||||
// *************************************************************
|
||||
// Lists
|
||||
private List<ProductInventoryView> Inventory { get; set; } = new();
|
||||
private List<ProductInventoryView> CheckList { get; set; } = new();
|
||||
private InvoiceListView CompanyInvoices { get; set; } = new();
|
||||
private List<ReportItemView> Activities { get; set; } = new();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Page initialization
|
||||
/// </summary>
|
||||
|
@ -110,13 +118,13 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
// User Preferences
|
||||
UserProfile = await ProfileService.GetProfile();
|
||||
// User Info
|
||||
SalesRep = await UserInfoService.GetUserInfo();
|
||||
SalesRep = await UserService.GetUserInfo();
|
||||
// Fetch Customer from http
|
||||
Company = await CompanyRepo.GetCompanyById(CompanyId);
|
||||
if (Company.HasFolded == 1)
|
||||
// Company has shutdown activities
|
||||
// Company has shut down
|
||||
Activity.OrderMessage = "BEMÆRK: CVR nummer er ophørt.";
|
||||
|
||||
|
||||
// variable to validate if customer needs phone number update
|
||||
OldPhone = Company.Phone;
|
||||
if (string.IsNullOrWhiteSpace(Company.Phone)
|
||||
|
@ -125,7 +133,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
{
|
||||
Company.Phone = Company.Account[..8];
|
||||
}
|
||||
|
||||
|
||||
// Populate base activity information
|
||||
Activity.BcId = Company.BcId;
|
||||
Activity.ActivityStatusEnum = "noSale";
|
||||
|
@ -141,7 +149,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
Activity.Mobile = Company.Mobile;
|
||||
Activity.Name = Company.Name;
|
||||
Activity.Address1 = Company.Address1;
|
||||
Activity.Address2 = Company.Address2;
|
||||
Activity.Address2 = Company.Address2;
|
||||
Activity.ZipCode = Company.ZipCode;
|
||||
Activity.City = Company.City;
|
||||
Activity.DlvName = Company.Name;
|
||||
|
@ -150,7 +158,10 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
Activity.DlvZipCode = Company.ZipCode;
|
||||
Activity.DlvCity = Company.City;
|
||||
// Initialize date variable
|
||||
SelectedDate = string.IsNullOrWhiteSpace(UserProfile.WorkDate) ? DateTime.Now : DateTime.Parse(UserProfile.WorkDate);
|
||||
Logger.LogDebug("AdvisorActivityCreatePage => DateTime parser => {}", UserProfile.WorkDate);
|
||||
SelectedDate = string.IsNullOrWhiteSpace(UserProfile.WorkDate)
|
||||
? DateTime.Now
|
||||
: DateTime.Parse(UserProfile.WorkDate);
|
||||
// raise flag if report is closed
|
||||
ReportClosed = await ReportRepo.ReportExist($"{SelectedDate:yyyy-MM-dd}");
|
||||
// Ask for confirmation of date
|
||||
|
@ -160,6 +171,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
PromptDateConfirm = $"Aktiviteter oprettes med dato {SelectedDate.ToShortDateString()}. Er dette OK?";
|
||||
ConfirmWorkDate.Show();
|
||||
}
|
||||
|
||||
// Lines may already have been added from the company inventory page
|
||||
if (DraftProvider.Draft.DraftType == "order")
|
||||
{
|
||||
|
@ -168,26 +180,27 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
Activity.ActivityStatusEnum = "order";
|
||||
PoFormInvalid = false;
|
||||
}
|
||||
|
||||
Working = false;
|
||||
}
|
||||
|
||||
private async Task ShowVisitOverlay()
|
||||
{
|
||||
Logger.LogDebug("ShowInventoryOverlay - wait for visits");
|
||||
|
||||
|
||||
ActivityListOverlay.Show();
|
||||
|
||||
Activities = await ActivityRepo.GetCustomerActivities(CompanyId);
|
||||
|
||||
|
||||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
|
||||
private async Task ShowInventoryOverlay()
|
||||
{
|
||||
Logger.LogDebug("ShowInventoryOverlay - wait for inventory");
|
||||
|
||||
|
||||
InventoryListOverlay.Show();
|
||||
|
||||
|
||||
Inventory = await HistoryRepo.FetchInventory(CompanyId);
|
||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
||||
await Task.Delay(500);
|
||||
|
@ -200,31 +213,32 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
DraftProvider.Draft.Items.Add(item);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
private async Task ShowInvoiceOverlay()
|
||||
{
|
||||
Logger.LogDebug("ShowInvoiceOverlay - wait for invoices");
|
||||
|
||||
|
||||
InvoiceListOverlay.Show();
|
||||
CompanyInvoices = await FetchCompanyInvoices();
|
||||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
|
||||
private async Task<InvoiceListView> FetchCompanyInvoices()
|
||||
{
|
||||
// fetch from storage
|
||||
var storage = await Storage.GetItemAsStringAsync($"{CompanyId}-invoices");
|
||||
await Task.Delay(500);
|
||||
var iDate = await Storage.GetItemAsStringAsync($"{CompanyId}-iDate");
|
||||
|
||||
|
||||
// if we have a list and iDate was today return the list
|
||||
if (!string.IsNullOrWhiteSpace(storage) && (!string.IsNullOrWhiteSpace(iDate) && DateTime.Parse(iDate.Replace("\"", "")) >= DateTime.Now))
|
||||
if (!string.IsNullOrWhiteSpace(storage) && (!string.IsNullOrWhiteSpace(iDate) &&
|
||||
DateTime.Parse(iDate.Replace("\"", "")) >= DateTime.Now))
|
||||
{
|
||||
Logger.LogDebug("fetching invoices from storage");
|
||||
Logger.LogDebug("storage contains <= {}", storage);
|
||||
return JsonSerializer.Deserialize<InvoiceListView>(storage);
|
||||
}
|
||||
|
||||
|
||||
Logger.LogDebug("pulling invoices from backend");
|
||||
// pull invoices
|
||||
var companyInvoices = await HistoryRepo.FetchInvoiceList(CompanyId);
|
||||
|
@ -236,30 +250,31 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
Logger.LogDebug("backend contains <= {}", JsonSerializer.Serialize(companyInvoices));
|
||||
return companyInvoices;
|
||||
}
|
||||
|
||||
|
||||
private void ShowOrgWarning()
|
||||
{
|
||||
if (OrgWarning)
|
||||
return;
|
||||
OrgWarning = true;
|
||||
if (Company.CountryCode.ToLower() == "se" && VatUtils.SanitizeVatNumber(Activity.VatNumber).Length < 10 && Activity.ActivityStatusEnum == "order")
|
||||
if (Company.CountryCode.ToLower() == "se" && VatUtils.SanitizeVatNumber(Activity.VatNumber).Length < 10 &&
|
||||
Activity.ActivityStatusEnum == "order")
|
||||
{
|
||||
Toaster.ShowWarning("Org nummer er ufuldstændig. Skal opdateres før bestilling kan sendes. ", "ADVARSEL");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async Task CallConfirmCheckOverlay()
|
||||
{
|
||||
// check if new account
|
||||
if (string.IsNullOrWhiteSpace(Company.Account)
|
||||
|| Company.Account.ToLower() == "ny"
|
||||
if (string.IsNullOrWhiteSpace(Company.Account)
|
||||
|| Company.Account.ToLower() == "ny"
|
||||
|| Activity.ActivityStatusEnum.ToLower() == "quote")
|
||||
{
|
||||
// proceed to create activity - as there is no product check to be done
|
||||
await CreateActivity();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// check if product has been checked
|
||||
// fetch products from storage
|
||||
var pStorage = await Storage.GetItemAsStringAsync($"{CompanyId}-products");
|
||||
|
@ -269,13 +284,15 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
if (string.IsNullOrWhiteSpace(pDate))
|
||||
pDate = $"{DateTime.Now.AddDays(-1):yyyy-MM-dd}";
|
||||
Logger.LogDebug("pDate => {}", pDate);
|
||||
|
||||
|
||||
// check if product data is valid and updated today
|
||||
if (string.IsNullOrWhiteSpace(pStorage) || pDate.Replace("\"", "") != $"{DateTime.Now:yyyy-MM-dd}")
|
||||
{
|
||||
Working = true;
|
||||
// pop a message
|
||||
Toaster.ShowError("Produkt gennemgang mangler. Vent mens produkt oversigt indlæses. Gå ikke væk fra siden!", "Produkt check ...");
|
||||
Toaster.ShowError(
|
||||
"Produkt gennemgang mangler. Vent mens produkt oversigt indlæses. Gå ikke væk fra siden!",
|
||||
"Produkt check ...");
|
||||
// product inventory has not been updated
|
||||
// send rpc call to sync ERP to CRM
|
||||
Toaster.ShowInfo("Vent mens data synkroniseres ...", "ERP til CRM ...");
|
||||
|
@ -286,11 +303,11 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
await Storage.SetItemAsync($"{CompanyId}-pDate", ts);
|
||||
// request products from backend
|
||||
Toaster.ShowInfo("Vent mens produkt oversigt hentes", "CRM produkt liste");
|
||||
|
||||
|
||||
CheckList = await HistoryRepo.FetchInventory(CompanyId);
|
||||
if(CheckList.Any())
|
||||
if (CheckList.Any())
|
||||
CheckList = CheckList.OrderBy(x => x.Description).ToList();
|
||||
|
||||
|
||||
await Storage.SetItemAsync($"{CompanyId}-products", CheckList);
|
||||
Working = false;
|
||||
}
|
||||
|
@ -298,14 +315,14 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
{
|
||||
// deserialize storage data
|
||||
CheckList = JsonSerializer.Deserialize<List<ProductInventoryView>>(pStorage);
|
||||
if(CheckList.Any())
|
||||
if (CheckList.Any())
|
||||
CheckList = CheckList.OrderBy(x => x.Description).ToList();
|
||||
}
|
||||
|
||||
|
||||
// Show CheckList modal
|
||||
ConfirmationCheckOverlay.Show();
|
||||
}
|
||||
|
||||
|
||||
private async Task ConfirmProductCheckCallback()
|
||||
{
|
||||
ConfirmationCheckOverlay.Hide();
|
||||
|
@ -314,10 +331,10 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
{
|
||||
item.Check = false;
|
||||
}
|
||||
|
||||
await Storage.SetItemAsync($"{CompanyId}-products", CheckList);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private async Task WorkDateConfirmCallback()
|
||||
{
|
||||
await ProfileService.SetDateConfirmed(true);
|
||||
|
@ -332,12 +349,12 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
SelectedDate = DateTime.Parse(workDate);
|
||||
Activity.ActivityDate = workDate;
|
||||
}
|
||||
|
||||
|
||||
private void ShowPriceListOverlay()
|
||||
{
|
||||
CatalogOverlay.Show();
|
||||
}
|
||||
|
||||
|
||||
private async Task PriceListCallback(SelectedSku sku)
|
||||
{
|
||||
// get selected item
|
||||
|
@ -349,13 +366,13 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
Quantity = sku.Quantity;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
private void ShowPriceHistoryOverlay()
|
||||
{
|
||||
if(ShowItem)
|
||||
if (ShowItem)
|
||||
PriceOverlay.Show();
|
||||
}
|
||||
|
||||
|
||||
private void PriceHistoryCallback(decimal price)
|
||||
{
|
||||
if (price == 0)
|
||||
|
@ -376,6 +393,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
Toaster.ShowError("Kunde adresse er ufuldstændig.");
|
||||
return;
|
||||
}
|
||||
|
||||
// validate org number
|
||||
// - this is a required input
|
||||
// - must validate according to country rules.
|
||||
|
@ -384,6 +402,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
Toaster.ShowError("Firma registreringsnummer er ikke korrekt.");
|
||||
return;
|
||||
}
|
||||
|
||||
// validate input according to status
|
||||
switch (Activity.ActivityStatusEnum)
|
||||
{
|
||||
|
@ -400,6 +419,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
Toaster.ShowError("Ved tilbud skal en gyldig email adresse angives.");
|
||||
return;
|
||||
}
|
||||
|
||||
// raise working flag
|
||||
Working = true;
|
||||
|
||||
|
@ -412,11 +432,12 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
Activity.OrderMessage = $"Telefonnr. opdateret.\n{Activity.OrderMessage}";
|
||||
await CompanyRepo.UpdateErpData(Company.CompanyId, Company);
|
||||
}
|
||||
|
||||
// begin assembling activity
|
||||
Activity.ActivityDate = $"{SelectedDate:yyyy-MM-dd}";
|
||||
Activity.OurRef = Activity.ActivityTypeEnum switch
|
||||
{
|
||||
"phone" => $"T:{SalesRep.FirstName}",
|
||||
"phone" => $"T:{SalesRep.FirstName}",
|
||||
"onSite" => $"B:{SalesRep.FirstName}",
|
||||
_ => ""
|
||||
};
|
||||
|
@ -443,6 +464,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
.ToList();
|
||||
Activity.Lines = lines;
|
||||
}
|
||||
|
||||
// debug logging
|
||||
Logger.LogDebug("CrmNewActivityPage => \n {}", JsonSerializer.Serialize(Activity));
|
||||
// post to api
|
||||
|
@ -458,18 +480,19 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
Navigator.NavigateTo($"/advisor/customers");
|
||||
return;
|
||||
}
|
||||
|
||||
// lower working flag
|
||||
Working = false;
|
||||
// show error message
|
||||
Toaster.ShowError(result.Message, "ORDRE FEJL");
|
||||
}
|
||||
|
||||
|
||||
private async Task DeleteDraft()
|
||||
{
|
||||
await DraftProvider.DeleteDraftAsync();
|
||||
Activity.ActivityStatusEnum = "noSale";
|
||||
}
|
||||
|
||||
|
||||
private async Task AddItem(SalesItemView salesItem)
|
||||
{
|
||||
ShowItem = false;
|
||||
|
@ -489,12 +512,12 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
Discount = "0";
|
||||
// add it to the cart
|
||||
DraftProvider.Draft.Items.Add(item);
|
||||
if(Activity.ActivityStatusEnum != "quote")
|
||||
if (Activity.ActivityStatusEnum != "quote")
|
||||
Activity.ActivityStatusEnum = "order";
|
||||
// save the item using the CartStateProvider's save method
|
||||
await DraftProvider.SaveChangesAsync();
|
||||
}
|
||||
|
||||
|
||||
private async Task RemoveItem(DraftItem item)
|
||||
{
|
||||
// remove item
|
||||
|
@ -504,10 +527,11 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
if (!DraftProvider.Draft.Items.Any())
|
||||
Activity.ActivityStatusEnum = "noSale";
|
||||
}
|
||||
|
||||
|
||||
private void HandleFieldChanged(object sender, FieldChangedEventArgs e)
|
||||
{
|
||||
Logger.LogDebug("ActivityNewPage => HandleFieldChanged => ActivityStatusEnum <= '{}'", Activity.ActivityStatusEnum);
|
||||
Logger.LogDebug("ActivityNewPage => HandleFieldChanged => ActivityStatusEnum <= '{}'",
|
||||
Activity.ActivityStatusEnum);
|
||||
DraftProvider.Draft.DraftType = Activity.ActivityStatusEnum;
|
||||
if (Activity.ActivityStatusEnum == "noSale")
|
||||
{
|
||||
|
@ -523,19 +547,20 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
};
|
||||
|
||||
// InvalidCanvas = InvalidActivityType;
|
||||
InvalidActivity = InvalidActivityType
|
||||
|| PoFormInvalid
|
||||
|| DraftProvider.Draft.Items.Count == 0
|
||||
|| (Activity.ActivityStatusEnum == "offer" && string.IsNullOrWhiteSpace(Activity.Email));
|
||||
if (Activity.YourRef.Length > 35 || Activity.ReferenceNumber.Length > 20 || InvalidActivity)
|
||||
InvalidActivity = InvalidActivityType
|
||||
|| PoFormInvalid
|
||||
|| DraftProvider.Draft.Items.Count == 0
|
||||
|| (Activity.ActivityStatusEnum == "offer" && string.IsNullOrWhiteSpace(Activity.Email));
|
||||
if (Activity.YourRef.Length > 35 || Activity.ReferenceNumber.Length > 20 || InvalidActivity)
|
||||
{
|
||||
PoFormInvalid = true;
|
||||
return;
|
||||
}
|
||||
|
||||
PoFormInvalid = !ActivityContext.Validate();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
private void ValidationChanged(object sender, ValidationStateChangedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Activity.ActivityTypeEnum) && !ReportClosed)
|
||||
|
@ -544,16 +569,16 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
PoFormInvalid = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Activity.ActivityStatusEnum.ToLower() is "order" or "quote"
|
||||
&& Company.CountryCode.ToLower() == "se"
|
||||
|
||||
if (Activity.ActivityStatusEnum.ToLower() is "order" or "quote"
|
||||
&& Company.CountryCode.ToLower() == "se"
|
||||
&& VatUtils.SanitizeVatNumber(Activity.VatNumber).Length < 10)
|
||||
{
|
||||
ShowOrgWarning();
|
||||
PoFormInvalid = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
PoFormInvalid = false;
|
||||
ActivityContext.OnFieldChanged -= HandleFieldChanged;
|
||||
ActivityContext.OnValidationStateChanged -= ValidationChanged;
|
||||
|
@ -561,7 +586,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
ActivityContext.OnFieldChanged += HandleFieldChanged;
|
||||
ActivityContext.OnValidationStateChanged += ValidationChanged;
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Interceptor.DisposeEvent();
|
||||
|
|
|
@ -45,4 +45,4 @@
|
|||
@if (Working)
|
||||
{
|
||||
<WorkingThreeDots/>
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// Copyright (C) 2022 FCS Frede's Computer Services.
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
|
@ -14,6 +13,7 @@
|
|||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
||||
//
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json;
|
||||
using Blazored.Toast.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
@ -21,6 +21,7 @@ using Wonky.Client.HttpInterceptors;
|
|||
using Wonky.Client.HttpRepository;
|
||||
using Wonky.Client.Services;
|
||||
using Wonky.Entity.Views;
|
||||
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace Wonky.Client.Pages;
|
||||
|
@ -34,7 +35,7 @@ public partial class AdvisorActivityTodayListPage : IDisposable
|
|||
[Inject] public IAdvisorActivityRepository ActivityRepo { get; set; }
|
||||
[Inject] public IAdvisorReportRepository ReportRepo { get; set; }
|
||||
[Inject] public IToastService Toaster { get; set; }
|
||||
private ReportStatusView ReportStatusView { get; set; } = new();
|
||||
private ReportStatusView ReportStatusView { get; set; } = new();
|
||||
private UserProfile UserProfile { get; set; } = new();
|
||||
private DateTime SelectedDate { get; set; }
|
||||
private bool ReportExist { get; set; }
|
||||
|
@ -45,12 +46,14 @@ public partial class AdvisorActivityTodayListPage : IDisposable
|
|||
Interceptor.RegisterEvent();
|
||||
Interceptor.RegisterBeforeSendEvent();
|
||||
UserProfile = await ProfileService.GetProfile();
|
||||
SelectedDate = string.IsNullOrWhiteSpace(UserProfile.WorkDate) ? DateTime.Now : DateTime.Parse(UserProfile.WorkDate);
|
||||
SelectedDate = string.IsNullOrWhiteSpace(UserProfile.WorkDate)
|
||||
? DateTime.Now
|
||||
: DateTime.Parse(UserProfile.WorkDate);
|
||||
ReportExist = await ReportRepo.ReportExist($"{SelectedDate:yyyy-MM-dd}");
|
||||
await GetActivities($"{SelectedDate:yyyy-MM-dd}");
|
||||
Working = false;
|
||||
}
|
||||
|
||||
|
||||
private async Task GetActivities(string workDate)
|
||||
{
|
||||
Working = true;
|
||||
|
@ -67,6 +70,5 @@ public partial class AdvisorActivityTodayListPage : IDisposable
|
|||
public void Dispose()
|
||||
{
|
||||
Interceptor.DisposeEvent();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -23,7 +23,6 @@
|
|||
@page "/advisor/customers/{CompanyId}/quotes/{OrderId}"
|
||||
|
||||
<PageTitle>@ReportItem.Company.Name @ReportItem.OrderDate</PageTitle>
|
||||
@* <ReportItemComponent ReportItem="@_item" /> *@
|
||||
|
||||
<table class="table table-sm table-striped d-print-table">
|
||||
<thead>
|
||||
|
@ -124,7 +123,9 @@
|
|||
{
|
||||
<tr>
|
||||
<td colspan="4"></td>
|
||||
<td colspan="2"><h5 class="fw-bold text-center"><i class="bi-lightning-charge the-fast" style="font-size: 2rem;"></i> HASTER</h5></td>
|
||||
<td colspan="2">
|
||||
<h5 class="fw-bold text-center"><i class="bi-lightning-charge the-fast" style="font-size: 2rem;"></i> HASTER</h5>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
|
@ -145,7 +146,7 @@
|
|||
<button class="btn btn-primary btn-lg" type="button" @onclick="UpdateOfficeNote" disabled="@Disabled">Opdater Note /Kontor</button>
|
||||
</div>
|
||||
</EditForm>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -159,4 +160,4 @@ else
|
|||
@if (Working)
|
||||
{
|
||||
<WorkingThreeDots/>
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// Copyright (C) 2022 FCS Frede's Computer Services.
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
|
@ -22,6 +21,7 @@ using Wonky.Client.HttpInterceptors;
|
|||
using Wonky.Client.HttpRepository;
|
||||
using Wonky.Entity.DTO;
|
||||
using Wonky.Entity.Views;
|
||||
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace Wonky.Client.Pages;
|
||||
|
@ -41,6 +41,7 @@ public partial class AdvisorActivityViewEditPage : IDisposable
|
|||
private bool Disabled { get; set; }
|
||||
private int GraceTime { get; set; } = 60;
|
||||
private bool Working { get; set; } = true;
|
||||
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
|
@ -59,7 +60,7 @@ public partial class AdvisorActivityViewEditPage : IDisposable
|
|||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
private async Task UpdateOfficeNote()
|
||||
{
|
||||
Working = true;
|
||||
|
@ -76,7 +77,7 @@ public partial class AdvisorActivityViewEditPage : IDisposable
|
|||
return false;
|
||||
return DateTime.UtcNow < createTs.AddMinutes(GraceTime);
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Interceptor.DisposeEvent();
|
||||
|
|
|
@ -35,10 +35,10 @@
|
|||
<a class="btn btn-primary d-block" href="/advisor/customers/@Company.CompanyId/activities/new"><i class="bi-arrow-right"></i> Besøg</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<CustomerActivityListComponent Activities="ActivityList" />
|
||||
|
||||
<CustomerActivityListComponent Activities="ActivityList"/>
|
||||
}
|
||||
@if (Working)
|
||||
{
|
||||
<WorkingThreeDots/>
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// Copyright (C) 2022 FCS Frede's Computer Services.
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
|
@ -20,6 +19,7 @@ using Wonky.Client.HttpInterceptors;
|
|||
using Wonky.Client.HttpRepository;
|
||||
using Wonky.Entity.DTO;
|
||||
using Wonky.Entity.Views;
|
||||
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace Wonky.Client.Pages;
|
||||
|
@ -33,12 +33,12 @@ public partial class AdvisorCustomerActivityListPage : IDisposable
|
|||
private List<ReportItemView> ActivityList { get; set; } = new();
|
||||
private CompanyDto Company { get; set; } = new();
|
||||
private bool Working { get; set; } = true;
|
||||
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Interceptor.RegisterEvent();
|
||||
Interceptor.RegisterBeforeSendEvent();
|
||||
|
||||
|
||||
Company = await CompanyRepo.GetCompanyById(CompanyId);
|
||||
await GetActivities();
|
||||
Working = false;
|
||||
|
@ -48,11 +48,11 @@ public partial class AdvisorCustomerActivityListPage : IDisposable
|
|||
{
|
||||
Working = true;
|
||||
ActivityList = await AdvisorActivityRepo.GetCustomerActivities(CompanyId);
|
||||
if(ActivityList.Any())
|
||||
if (ActivityList.Any())
|
||||
ActivityList = ActivityList.OrderByDescending(x => x.OrderDate).ToList();
|
||||
Working = false;
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Interceptor.DisposeEvent();
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
//
|
||||
|
||||
using System.Text.Json;
|
||||
using System.Xml;
|
||||
using Blazored.LocalStorage;
|
||||
using Blazored.Toast.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
@ -27,162 +26,161 @@ using Wonky.Client.Services;
|
|||
using Wonky.Client.Shared;
|
||||
using Wonky.Entity.DTO;
|
||||
using Wonky.Entity.Models;
|
||||
using Wonky.Entity.Views;
|
||||
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace Wonky.Client.Pages
|
||||
namespace Wonky.Client.Pages;
|
||||
|
||||
public partial class AdvisorCustomerCreatePage : IDisposable
|
||||
{
|
||||
public partial class AdvisorCustomerCreatePage : IDisposable
|
||||
[Inject] public IToastService Toaster { get; set; }
|
||||
[Inject] public ILogger<AdvisorCustomerCreatePage> Logger { get; set; }
|
||||
[Inject] public ILocalStorageService Storage { get; set; }
|
||||
[Inject] public NavigationManager Navigator { get; set; }
|
||||
[Inject] public IAdvisorCustomerRepository CompanyRepo { get; set; }
|
||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||
[Inject] public VatInfoLookupService VatService { get; set; }
|
||||
[Inject] public IUserInfoService UserInfoService { get; set; }
|
||||
|
||||
private EditContext CompanyContext { get; set; }
|
||||
private CompanyDto Company { get; set; } = new();
|
||||
private VatAddress CompanyVatAddress { get; set; } = new();
|
||||
private VatLookupDkModal VatLookupPopup { get; set; } = new();
|
||||
|
||||
private bool FormInvalid { get; set; } = true;
|
||||
private string RegState { get; set; } = "";
|
||||
private DateTime LastVisit { get; set; }
|
||||
private DateTime NextVisit { get; set; }
|
||||
private bool Dk { get; set; } = true;
|
||||
private bool Working { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
[Inject] public IToastService Toaster { get; set; }
|
||||
[Inject] public ILogger<AdvisorCustomerCreatePage> Logger { get; set; }
|
||||
[Inject] public ILocalStorageService Storage { get; set; }
|
||||
[Inject] public NavigationManager Navigator { get; set; }
|
||||
[Inject] public IAdvisorCustomerRepository CompanyRepo { get; set; }
|
||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||
[Inject] public VatInfoLookupService VatService { get; set; }
|
||||
[Inject] public IUserInfoService UserInfoService { get; set; }
|
||||
|
||||
private EditContext CompanyContext { get; set; }
|
||||
private CompanyDto Company { get; set; } = new();
|
||||
private VatAddress CompanyVatAddress { get; set; } = new();
|
||||
private VatLookupDkModal VatLookupPopup { get; set; } = new();
|
||||
CompanyContext = new EditContext(Company);
|
||||
|
||||
private bool FormInvalid { get; set; } = true;
|
||||
private string RegState { get; set; } = "";
|
||||
private DateTime LastVisit { get; set; }
|
||||
private DateTime NextVisit { get; set; }
|
||||
private bool Dk { get; set; } = true;
|
||||
private bool Working { get; set; }
|
||||
CompanyContext.OnFieldChanged += HandleFieldChanged;
|
||||
CompanyContext.OnValidationStateChanged += ValidationChanged;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
var xu = await UserInfoService.GetUserInfo();
|
||||
Dk = xu.CountryCode.ToLower() == "dk";
|
||||
|
||||
Company.SalesRepId = xu.UserId;
|
||||
Company.CountryCode = xu.CountryCode.ToLower();
|
||||
|
||||
LastVisit = DateTime.Now;
|
||||
NextVisit = DateTime.Now.AddDays(Company.Interval * 7);
|
||||
Company.LastVisit = $"{LastVisit:yyyy-MM-dd}";
|
||||
Company.NextVisit = $"{NextVisit:yyyy-MM-dd}";
|
||||
|
||||
Interceptor.RegisterEvent();
|
||||
Interceptor.RegisterBeforeSendEvent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show Vat Lookup modal
|
||||
/// </summary>
|
||||
private void CallVatLookupModal()
|
||||
{
|
||||
VatLookupPopup.Show();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modal callback to update company properties
|
||||
/// </summary>
|
||||
/// <param name="regInfo"></param>
|
||||
private void SelectCompanyCallback(VirkRegInfo regInfo)
|
||||
{
|
||||
Logger.LogDebug("CrmCompanyView => SelectCompanyCallback => {}", JsonSerializer.Serialize(regInfo));
|
||||
|
||||
// this can be removed in favor of the new data returned from updating the VatNumber
|
||||
RegState = regInfo.States[0].State.ToLower() == "normal" ? "the-good" : "the-dead";
|
||||
if (regInfo.SyncAll)
|
||||
{
|
||||
CompanyContext = new EditContext(Company);
|
||||
|
||||
CompanyContext.OnFieldChanged += HandleFieldChanged;
|
||||
CompanyContext.OnValidationStateChanged += ValidationChanged;
|
||||
|
||||
var xu = await UserInfoService.GetUserInfo();
|
||||
Dk = xu.CountryCode.ToLower() == "dk";
|
||||
|
||||
Company.SalesRepId = xu.UserId;
|
||||
Company.CountryCode = xu.CountryCode.ToLower();
|
||||
|
||||
LastVisit = DateTime.Now;
|
||||
NextVisit = DateTime.Now.AddDays(Company.Interval * 7);
|
||||
Company.LastVisit = $"{LastVisit:yyyy-MM-dd}";
|
||||
Company.NextVisit = $"{NextVisit:yyyy-MM-dd}";
|
||||
|
||||
Interceptor.RegisterEvent();
|
||||
Interceptor.RegisterBeforeSendEvent();
|
||||
Company.Name = regInfo.Name;
|
||||
Company.Address1 = regInfo.Address;
|
||||
Company.Address2 = regInfo.CoName;
|
||||
Company.ZipCode = regInfo.ZipCode;
|
||||
Company.City = regInfo.City;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show Vat Lookup modal
|
||||
/// </summary>
|
||||
private void CallVatLookupModal()
|
||||
Company.VatNumber = regInfo.VatNumber;
|
||||
Company.ValidVat = 1;
|
||||
FormInvalid = false;
|
||||
}
|
||||
|
||||
private async Task SubmitCompanyForm()
|
||||
{
|
||||
Working = true;
|
||||
FormInvalid = true;
|
||||
Company.LastVisit = $"{LastVisit:yyyy-MM-dd}";
|
||||
Company.NextVisit = $"{NextVisit:yyyy-MM-dd}";
|
||||
|
||||
var newId = await CompanyRepo.CreateCompany(Company);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(newId))
|
||||
{
|
||||
VatLookupPopup.Show();
|
||||
Toaster.ShowSuccess($"'{Company.Name}' er oprettet i CRM.");
|
||||
Navigator.NavigateTo($"/advisor/customers/{newId}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modal callback to update company properties
|
||||
/// </summary>
|
||||
/// <param name="regInfo"></param>
|
||||
private void SelectCompanyCallback(VirkRegInfo regInfo)
|
||||
else
|
||||
{
|
||||
Logger.LogDebug("CrmCompanyView => SelectCompanyCallback => {}", JsonSerializer.Serialize(regInfo));
|
||||
|
||||
// this can be removed in favor of the new data returned from updating the VatNumber
|
||||
RegState = regInfo.States[0].State.ToLower() == "normal" ? "the-good" : "the-dead";
|
||||
if (regInfo.SyncAll)
|
||||
{
|
||||
Company.Name = regInfo.Name;
|
||||
Company.Address1 = regInfo.Address;
|
||||
Company.Address2 = regInfo.CoName;
|
||||
Company.ZipCode = regInfo.ZipCode;
|
||||
Company.City = regInfo.City;
|
||||
}
|
||||
|
||||
Company.VatNumber = regInfo.VatNumber;
|
||||
Company.ValidVat = 1;
|
||||
Toaster.ShowWarning($"'{Company.Name}' IKKE oprettet.");
|
||||
FormInvalid = false;
|
||||
}
|
||||
|
||||
private async Task SubmitCompanyForm()
|
||||
|
||||
Working = false;
|
||||
}
|
||||
|
||||
private void HandleFieldChanged(object sender, FieldChangedEventArgs e)
|
||||
{
|
||||
NextVisit = LastVisit.AddDays(7 * Company.Interval);
|
||||
// invalid vat number id not accepted by the ERP system
|
||||
// but is removed without warning
|
||||
// it is necessary to validate if vat number has been added
|
||||
// as the format should conform to country rule of generation
|
||||
if (!string.IsNullOrWhiteSpace(Company.VatNumber))
|
||||
{
|
||||
Working = true;
|
||||
FormInvalid = true;
|
||||
Company.LastVisit = $"{LastVisit:yyyy-MM-dd}";
|
||||
Company.NextVisit = $"{NextVisit:yyyy-MM-dd}";
|
||||
|
||||
var newId = await CompanyRepo.CreateCompany(Company);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(newId))
|
||||
// validate vat number according to country
|
||||
if (!VatUtils.ValidateFormat(Company.CountryCode, Company.VatNumber))
|
||||
{
|
||||
Toaster.ShowSuccess($"'{Company.Name}' er oprettet i CRM.");
|
||||
Navigator.NavigateTo($"/advisor/customers/{newId}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Toaster.ShowWarning($"'{Company.Name}' IKKE oprettet.");
|
||||
FormInvalid = false;
|
||||
}
|
||||
|
||||
Working = false;
|
||||
}
|
||||
|
||||
private void HandleFieldChanged(object sender, FieldChangedEventArgs e)
|
||||
{
|
||||
NextVisit = LastVisit.AddDays(7 * Company.Interval);
|
||||
// invalid vat number id not accepted by the ERP system
|
||||
// but is removed without warning
|
||||
// it is necessary to validate if vat number has been added
|
||||
// as the format should conform to country rule of generation
|
||||
if (!string.IsNullOrWhiteSpace(Company.VatNumber))
|
||||
{
|
||||
// validate vat number according to country
|
||||
if (!VatUtils.ValidateFormat(Company.CountryCode, Company.VatNumber))
|
||||
{
|
||||
Toaster.ShowError("Momsnummber er ikke korrekt.");
|
||||
FormInvalid = true;
|
||||
Company.ValidVat = 0;
|
||||
RegState = "the-ugly";
|
||||
}
|
||||
}
|
||||
|
||||
if (!Company.ValidDateSpan())
|
||||
{
|
||||
Toaster.ShowError("Dato for næste besøg skal ligge efter sidste besøg.");
|
||||
Toaster.ShowError("Momsnummber er ikke korrekt.");
|
||||
FormInvalid = true;
|
||||
Company.ValidVat = 0;
|
||||
RegState = "the-ugly";
|
||||
}
|
||||
else
|
||||
{
|
||||
FormInvalid = !CompanyContext.Validate();
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void ValidationChanged(object sender, ValidationStateChangedEventArgs e)
|
||||
if (!Company.ValidDateSpan())
|
||||
{
|
||||
Toaster.ShowError("Dato for næste besøg skal ligge efter sidste besøg.");
|
||||
FormInvalid = true;
|
||||
|
||||
CompanyContext.OnFieldChanged -= HandleFieldChanged;
|
||||
|
||||
CompanyContext = new EditContext(Company);
|
||||
|
||||
FormInvalid = !CompanyContext.Validate();
|
||||
|
||||
CompanyContext.OnFieldChanged += HandleFieldChanged;
|
||||
CompanyContext.OnValidationStateChanged -= ValidationChanged;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
else
|
||||
{
|
||||
Interceptor.DisposeEvent();
|
||||
CompanyContext.OnFieldChanged -= HandleFieldChanged;
|
||||
CompanyContext.OnValidationStateChanged -= ValidationChanged;
|
||||
FormInvalid = !CompanyContext.Validate();
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void ValidationChanged(object sender, ValidationStateChangedEventArgs e)
|
||||
{
|
||||
FormInvalid = true;
|
||||
|
||||
CompanyContext.OnFieldChanged -= HandleFieldChanged;
|
||||
|
||||
CompanyContext = new EditContext(Company);
|
||||
|
||||
FormInvalid = !CompanyContext.Validate();
|
||||
|
||||
CompanyContext.OnFieldChanged += HandleFieldChanged;
|
||||
CompanyContext.OnValidationStateChanged -= ValidationChanged;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Interceptor.DisposeEvent();
|
||||
CompanyContext.OnFieldChanged -= HandleFieldChanged;
|
||||
CompanyContext.OnValidationStateChanged -= ValidationChanged;
|
||||
}
|
||||
}
|
|
@ -23,40 +23,42 @@
|
|||
<div class="sticky-top bg-dark text-light rounded-2 px-3">
|
||||
<div class="row g-3">
|
||||
<div class="col-sm-2">
|
||||
<CustomerSearchColumnComponent OnChanged="SetSearchCol" />
|
||||
<CustomerSearchColumnComponent OnChanged="SetSearchCol"/>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<CustomerSearchPhraseComponent OnChanged="SetSearchPhrase" />
|
||||
<CustomerSearchPhraseComponent OnChanged="SetSearchPhrase"/>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<CustomerSortComponent OnChanged="SetSortCol" />
|
||||
<CustomerSortComponent OnChanged="SetSortCol"/>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<PageSizeComponent OnChanged="SetPageSize" />
|
||||
<PageSizeComponent OnChanged="SetPageSize"/>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<button type button class="btn btn-warning @(ShowFolded ? "active" : "")"
|
||||
data-bs-toggle="button" aria-pressed="@ShowFolded" @onclick="OnFoldedClick">
|
||||
@ButtonFoldedText
|
||||
</button>
|
||||
<button type button class="btn btn-warning @(@ShowHidden ? "active" : "")"
|
||||
data-bs-toggle="button" aria-pressed="@ShowHidden" @onclick="OnHiddenClick">
|
||||
@ButtonHiddenText
|
||||
<div class="col-sm-2 mx-auto">
|
||||
<button type button class="btn btn-warning @(ShowFolded ? "active" : "")"
|
||||
data-bs-toggle="button" aria-pressed="@ShowFolded" @onclick="ToggleFolded">
|
||||
@ToggleFoldedText
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-7">
|
||||
<div class="col-sm-2 mx-auto">
|
||||
<button type button class="btn btn-warning @(@ShowHidden ? "active" : "")"
|
||||
data-bs-toggle="button" aria-pressed="@ShowHidden" @onclick="ToggleHidden">
|
||||
@ToggleHiddenText
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-5">
|
||||
<PaginationComponent MetaData="PageData" Spread="2" SelectedPage="SelectedPage"/>
|
||||
</div>
|
||||
<div class="col-sm-2 text-end">
|
||||
<div class="col-sm-1">@* placeholder *@</div>
|
||||
<div class="col-sm-2 mx-auto">
|
||||
<a class="btn btn-success text-nowrap" href="/advisor/customers/new">Opret kunde <i class="bi-plus"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<AdvisorCustomerListComponent CompanyList="CompanyList" OnDelete="DeleteCompany" />
|
||||
<AdvisorCustomerListComponent CompanyList="CompanyList" OnDelete="DeleteCompany"/>
|
||||
|
||||
@if (Working)
|
||||
{
|
||||
<WorkingThreeDots />
|
||||
}
|
||||
|
||||
<WorkingThreeDots/>
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// Copyright (C) 2022 FCS Frede's Computer Services.
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
|
@ -22,147 +21,147 @@ using Wonky.Client.Services;
|
|||
using Wonky.Entity.DTO;
|
||||
using Wonky.Entity.Requests;
|
||||
using Wonky.Entity.Views;
|
||||
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace Wonky.Client.Pages
|
||||
namespace Wonky.Client.Pages;
|
||||
|
||||
public partial class AdvisorCustomerListPage : IDisposable
|
||||
{
|
||||
public partial class AdvisorCustomerListPage : IDisposable
|
||||
[Inject] public ILocalStorageService Storage { get; set; }
|
||||
[Inject] public UserProfileService ProfileService { get; set; }
|
||||
[Inject] public IAdvisorCustomerRepository CompanyRepo { get; set; }
|
||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||
[Inject] public NavigationManager Navigator { get; set; }
|
||||
[Inject] public IUserInfoService UserInfoService { get; set; }
|
||||
|
||||
private List<CompanyDto> CompanyList { get; set; } = new();
|
||||
private UserProfile Profile { get; set; } = new();
|
||||
private UserManagerEditView UserInfo { get; set; } = new();
|
||||
private string SavedSearch { get; set; } = "";
|
||||
private bool Working { get; set; } = true;
|
||||
private MetaData PageData { get; set; } = new();
|
||||
private CustomerPaging Paging { get; set; } = new();
|
||||
private string ToggleFoldedText { get; set; } = "Vis Lukkede";
|
||||
private bool ShowFolded { get; set; }
|
||||
private string ToggleHiddenText { get; set; } = "Inkl. Skjulte";
|
||||
private bool ShowHidden { get; set; }
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
[Inject] public ILocalStorageService Storage { get; set; }
|
||||
[Inject] public UserProfileService ProfileService { get; set; }
|
||||
[Inject] public IAdvisorCustomerRepository CompanyRepo { get; set; }
|
||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||
[Inject] public NavigationManager Navigator { get; set; }
|
||||
[Inject] public IUserInfoService UserInfoService { get; set; }
|
||||
Interceptor.RegisterEvent();
|
||||
Interceptor.RegisterBeforeSendEvent();
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// set preferences
|
||||
Profile = await ProfileService.GetProfile();
|
||||
UserInfo = await UserInfoService.GetUserInfo();
|
||||
Paging.OrderBy = Profile.CompanySort;
|
||||
Paging.SearchColumn = Profile.CompanySearch;
|
||||
Paging.PageSize = Convert.ToInt32(Profile.PageSize);
|
||||
Paging.HasFolded = ShowFolded ? 1 : 0;
|
||||
|
||||
// load saved search
|
||||
SavedSearch = string.IsNullOrWhiteSpace(Profile.CompanyFilterPhrase) ? "" : Profile.CompanyFilterPhrase;
|
||||
Paging.SearchTerm = SavedSearch;
|
||||
|
||||
|
||||
private List<CompanyDto> CompanyList { get; set; } = new();
|
||||
private UserProfile Profiles { get; set; } = new();
|
||||
private UserManagerEditView XUserInfo { get; set; } = new();
|
||||
private string SavedSearch { get; set; } = "";
|
||||
private bool Working { get; set; } = true;
|
||||
private MetaData PageData { get; set; } = new();
|
||||
private CustomerPaging Paging { get; set; } = new();
|
||||
private string ButtonFoldedText { get; set; } = "Vis Ophørte";
|
||||
private bool ShowFolded { get; set; }
|
||||
private string ButtonHiddenText { get; set; } = "Vis Skjulte";
|
||||
private bool ShowHidden { get; set; }
|
||||
protected override void OnParametersSet()
|
||||
// get companies
|
||||
await FetchCustomers();
|
||||
Working = false;
|
||||
}
|
||||
|
||||
private async Task ToggleFolded()
|
||||
{
|
||||
Working = true;
|
||||
ShowFolded = !ShowFolded;
|
||||
ToggleFoldedText = ShowFolded ? "Normal Visning" : "Vis Lukkede";
|
||||
CompanyList = new List<CompanyDto>();
|
||||
Paging.PageNumber = 1;
|
||||
Paging.HasFolded = ShowFolded ? 1 : 0;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task ToggleHidden()
|
||||
{
|
||||
Working = true;
|
||||
ShowHidden = !ShowHidden;
|
||||
ToggleHiddenText = ShowHidden ? "Normal Visning" : "Inkl. Skjulte";
|
||||
CompanyList = new List<CompanyDto>();
|
||||
Paging.PageNumber = 1;
|
||||
Paging.IsHidden = ShowHidden ? 1 : 0;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task SelectedPage(int page)
|
||||
{
|
||||
CompanyList = new List<CompanyDto>();
|
||||
Paging.PageNumber = page;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task SetSearchCol(string searchColumn)
|
||||
{
|
||||
CompanyList = new List<CompanyDto>();
|
||||
Paging.SearchColumn = searchColumn;
|
||||
Paging.PageNumber = 1;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task SetPageSize(string pageSize)
|
||||
{
|
||||
CompanyList = new List<CompanyDto>();
|
||||
Paging.PageSize = Convert.ToInt32(pageSize);
|
||||
Paging.PageNumber = 1;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task SetSearchPhrase(string searchTerm)
|
||||
{
|
||||
CompanyList = new List<CompanyDto>();
|
||||
Paging.PageNumber = 1;
|
||||
Paging.SearchTerm = searchTerm;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task SetSortCol(string orderBy)
|
||||
{
|
||||
CompanyList = new List<CompanyDto>();
|
||||
Paging.OrderBy = orderBy;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a company from CRM
|
||||
/// </summary>
|
||||
/// <param name="companyId"></param>
|
||||
private async Task DeleteCompany(string companyId)
|
||||
{
|
||||
CompanyList = new List<CompanyDto>();
|
||||
await CompanyRepo.DeleteCompany(companyId);
|
||||
if (Paging.PageNumber > 1 && CompanyList.Count == 1)
|
||||
Paging.PageNumber--;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task FetchCustomers()
|
||||
{
|
||||
Working = true;
|
||||
var pageRes = await CompanyRepo.GetCompanies(Paging);
|
||||
Working = false;
|
||||
if (pageRes.Items.Any())
|
||||
{
|
||||
Interceptor.RegisterEvent();
|
||||
Interceptor.RegisterBeforeSendEvent();
|
||||
|
||||
CompanyList = pageRes.Items;
|
||||
PageData = pageRes.MetaData;
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// set preferences
|
||||
Profiles = await ProfileService.GetProfile();
|
||||
XUserInfo = await UserInfoService.GetUserInfo();
|
||||
Paging.OrderBy = Profiles.CompanySort;
|
||||
Paging.SearchColumn = Profiles.CompanySearch;
|
||||
Paging.PageSize = Convert.ToInt32(Profiles.PageSize);
|
||||
Paging.HasFolded = ShowFolded ? 1 : 0;
|
||||
|
||||
// load saved search
|
||||
SavedSearch = string.IsNullOrWhiteSpace(Profiles.CompanyFilterPhrase) ? "" : Profiles.CompanyFilterPhrase;
|
||||
Paging.SearchTerm = SavedSearch;
|
||||
|
||||
// get companies
|
||||
await FetchCustomers();
|
||||
Working = false;
|
||||
}
|
||||
|
||||
private async Task OnFoldedClick()
|
||||
{
|
||||
Working = true;
|
||||
ShowFolded = !ShowFolded;
|
||||
ButtonFoldedText = ShowFolded ? "Vis Aktive" : "Vis Ophørte";
|
||||
CompanyList = new List<CompanyDto>();
|
||||
Paging.PageNumber = 1;
|
||||
Paging.HasFolded = ShowFolded ? 1 : 0;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task OnHiddenClick()
|
||||
{
|
||||
Working = true;
|
||||
ShowHidden = !ShowHidden;
|
||||
ButtonHiddenText = ShowHidden ? "Vis Normale" : "Vis skjulte";
|
||||
CompanyList = new List<CompanyDto>();
|
||||
Paging.PageNumber = 1;
|
||||
Paging.IsHidden = ShowHidden ? 1 : 0;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task SelectedPage(int page)
|
||||
else
|
||||
{
|
||||
CompanyList = new List<CompanyDto>();
|
||||
Paging.PageNumber = page;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task SetSearchCol(string searchColumn)
|
||||
{
|
||||
CompanyList = new List<CompanyDto>();
|
||||
Paging.SearchColumn = searchColumn;
|
||||
Paging.PageNumber = 1;
|
||||
await FetchCustomers();
|
||||
}
|
||||
private async Task SetPageSize(string pageSize)
|
||||
{
|
||||
CompanyList = new List<CompanyDto>();
|
||||
Paging.PageSize = Convert.ToInt32(pageSize);
|
||||
Paging.PageNumber = 1;
|
||||
await FetchCustomers();
|
||||
PageData = new MetaData();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SetSearchPhrase(string searchTerm)
|
||||
{
|
||||
CompanyList = new List<CompanyDto>();
|
||||
Paging.PageNumber = 1;
|
||||
Paging.SearchTerm = searchTerm;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task SetSortCol(string orderBy)
|
||||
{
|
||||
CompanyList = new List<CompanyDto>();
|
||||
Paging.OrderBy = orderBy;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a company from CRM
|
||||
/// </summary>
|
||||
/// <param name="companyId"></param>
|
||||
private async Task DeleteCompany(string companyId)
|
||||
{
|
||||
CompanyList = new List<CompanyDto>();
|
||||
await CompanyRepo.DeleteCompany(companyId);
|
||||
if (Paging.PageNumber > 1 && CompanyList.Count == 1)
|
||||
Paging.PageNumber--;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task FetchCustomers()
|
||||
{
|
||||
Working = true;
|
||||
var pageRes = await CompanyRepo.GetCompanies(Paging);
|
||||
Working = false;
|
||||
if (pageRes.Items.Any())
|
||||
{
|
||||
CompanyList = pageRes.Items;
|
||||
PageData = pageRes.MetaData;
|
||||
}
|
||||
else
|
||||
{
|
||||
CompanyList = new List<CompanyDto>();
|
||||
PageData = new MetaData();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() => Interceptor.DisposeEvent();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Dispose() => Interceptor.DisposeEvent();
|
||||
}
|
|
@ -36,85 +36,86 @@
|
|||
// erp context
|
||||
<EditForm EditContext="ErpContext">
|
||||
<DataAnnotationsValidator/>
|
||||
<div class="row g-3">
|
||||
<div class="row g-1">
|
||||
@* Company Name *@
|
||||
<label for="name" class="col-sm-1 col-form-label-sm">Navn</label>
|
||||
<div class="col-sm-5">
|
||||
<InputText id="name" class="form-control" @bind-Value="Company.Name"/>
|
||||
<InputText id="name" class="form-control" @bind-Value="Company.Name" readonly="@(ErpEditDisabled)"/>
|
||||
<ValidationMessage For="@(() => Company.Name)"></ValidationMessage>
|
||||
</div>
|
||||
@* Company Attention *@
|
||||
<label for="attention" class="col-sm-1 col-form-label-sm">Att.</label>
|
||||
<div class="col-sm-5">
|
||||
<InputText id="attention" class="form-control" @bind-Value="Company.Attention"/>
|
||||
<InputText id="attention" class="form-control" @bind-Value="Company.Attention" readonly="@(ErpEditDisabled)"/>
|
||||
<ValidationMessage For="@(() => Company.Attention)"></ValidationMessage>
|
||||
</div>
|
||||
@* Address 1 *@
|
||||
<label for="address1" class="col-sm-1 col-form-label-sm">Adresse</label>
|
||||
<div class="col-sm-5">
|
||||
<InputText id="address1" class="form-control" @bind-Value="Company.Address1"/>
|
||||
<InputText id="address1" class="form-control" @bind-Value="Company.Address1" readonly="@(ErpEditDisabled)"/>
|
||||
<ValidationMessage For="@(() => Company.Address1)"></ValidationMessage>
|
||||
</div>
|
||||
@* Address 2 *@
|
||||
<label for="address2" class="col-sm-1 col-form-label-sm">Adresse</label>
|
||||
<div class="col-sm-5">
|
||||
<InputText id="address2" class="form-control" @bind-Value="Company.Address2"/>
|
||||
<InputText id="address2" class="form-control" @bind-Value="Company.Address2" readonly="@(ErpEditDisabled)"/>
|
||||
<ValidationMessage For="@(() => Company.Address2)"></ValidationMessage>
|
||||
</div>
|
||||
@* Post Code *@
|
||||
<label for="zipCode" class="col-sm-1 col-form-label-sm">PostNr</label>
|
||||
<div class="col-sm-2">
|
||||
<InputText id="zipCode" class="form-control" @bind-Value="Company.ZipCode"/>
|
||||
<InputText id="zipCode" class="form-control" @bind-Value="Company.ZipCode" readonly="@(ErpEditDisabled)"/>
|
||||
<ValidationMessage For="@(() => Company.ZipCode)"></ValidationMessage>
|
||||
</div>
|
||||
@* City Name *@
|
||||
<label for="city" class="col-sm-1 col-form-label-sm">Bynavn</label>
|
||||
<div class="col-sm-8">
|
||||
<InputText id="city" class="form-control" @bind-Value="Company.City"/>
|
||||
<InputText id="city" class="form-control" @bind-Value="Company.City" readonly="@(ErpEditDisabled)"/>
|
||||
<ValidationMessage For="@(() => Company.City)"></ValidationMessage>
|
||||
</div>
|
||||
@* Phone *@
|
||||
<label for="phone" class="col-sm-1 col-form-label-sm">Telefon</label>
|
||||
<div class="col-sm-3">
|
||||
<InputText id="phone" class="form-control" @bind-Value="Company.Phone"/>
|
||||
<div class="col-sm-2">
|
||||
<InputText id="phone" class="form-control" @bind-Value="Company.Phone" readonly="@(ErpEditDisabled)"/>
|
||||
<ValidationMessage For="@(() => Company.Phone)"></ValidationMessage>
|
||||
</div>
|
||||
@* Mobile *@
|
||||
<label for="mobile" class="col-sm-1 col-form-label-sm">Mobil</label>
|
||||
<div class="col-sm-3">
|
||||
<InputText id="mobile" class="form-control" @bind-Value="Company.Mobile"/>
|
||||
<div class="col-sm-2">
|
||||
<InputText id="mobile" class="form-control" @bind-Value="Company.Mobile" readonly="@(ErpEditDisabled)"/>
|
||||
<ValidationMessage For="@(() => Company.Mobile)"></ValidationMessage>
|
||||
</div>
|
||||
<div class="col-sm-4 d-grid mx-auto">
|
||||
<button type="button" class="btn btn-danger" @onclick="ToggleVisibility">@ToggleButtonText</button>
|
||||
</div>
|
||||
@* Email *@
|
||||
<label for="email" class="col-sm-1 col-form-label-sm">Epost</label>
|
||||
<div class="col-sm-5">
|
||||
<InputText id="email" class="form-control" @bind-Value="Company.Email"/>
|
||||
<InputText id="email" class="form-control" @bind-Value="Company.Email" readonly="@(ErpEditDisabled)"/>
|
||||
<ValidationMessage For="@(() => Company.Email)"></ValidationMessage>
|
||||
</div>
|
||||
<div class="col-sm-3 d-grid mx-auto">
|
||||
<button type="button" class="btn btn-primary d-block" disabled="@(Company.HasFolded == 0 || Company.Name == "ERROR")" onclick="@ForceActivity">Aktiver besøg</button>
|
||||
<div class="col-sm-4">@* ---- placeholder --- *@</div>
|
||||
<div class="col-sm-2 d-grid mx-auto">
|
||||
<button type="button" class="btn btn-edit" @onclick="ToggleErpEdit"><i class="bi-pencil"></i> STAM data</button>
|
||||
</div>
|
||||
<div class="col-sm-3 d-grid mx-auto">
|
||||
<button type="button" class="btn btn-danger d-block" onclick="@UpdateErpData" disabled="@(Working || Company.Name == "ERROR")"><i class="bi-cloud-arrow-up"></i> STAM data </button>
|
||||
<button type="button" class="btn btn-primary d-block" disabled="@(Company.HasFolded == 0 || Company.Name == "ERROR")" @onclick="ForceActivity">Aktiver besøg</button>
|
||||
</div>
|
||||
<div class="col-sm-3 d-grid mx-auto">
|
||||
<button type="button" class="btn btn-danger d-block" onclick="@UpdateErpData" disabled="@(Working || Company.Name == "ERROR" || ErpEditDisabled)"><i class="bi-cloud-arrow-up"></i> STAM data </button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="mb-3"/>
|
||||
<div class="row">
|
||||
@* vat number*@
|
||||
<label for="vatNumber" class="col-sm-2 col-form-label-sm">CVR/Org nr.</label>
|
||||
<div class="col-sm-4">
|
||||
<label for="vatNumber" class="col-sm-1 col-form-label-sm">CVR/Org nr.</label>
|
||||
<div class="col-sm-3">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<DisplayStateComponent StateClass="@VatState"/>
|
||||
</span>
|
||||
<InputText id="vatNumber" class="form-control" @bind-Value="Company.VatNumber"/>
|
||||
<InputText id="vatNumber" class="form-control" @bind-Value="Company.VatNumber" readonly="@(VatEditDisabled)"/>
|
||||
<ValidationMessage For="@(() => Company.VatNumber)"></ValidationMessage>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-2 d-grid mx-auto">
|
||||
<button type="button" class="btn btn-edit" @onclick="ToggleVatEdit"><i class="bi-pencil"></i> Moms/Org Nr.</button>
|
||||
</div>
|
||||
|
||||
@* vat lookup *@
|
||||
<div class="col-sm-3 d-grid mx-auto">
|
||||
@switch (CountryCode)
|
||||
|
@ -132,7 +133,7 @@
|
|||
</div>
|
||||
@* save vat number *@
|
||||
<div class="col-sm-3 d-grid mx-auto">
|
||||
<button type="button" class="btn btn-warning d-block" @onclick="UpdateVatNumber"><i class="bi-cloud-arrow-up"></i> Moms/Org Nr.</button>
|
||||
<button type="button" class="btn btn-warning d-block" @onclick="UpdateVatNumber" disabled="@(VatEditDisabled)"><i class="bi-cloud-arrow-up"></i> Moms/Org Nr.</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -240,6 +241,11 @@
|
|||
<InputTextArea id="crmNotes" class="form-control" @bind-Value="Company.CrmNotes"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row pt-3">
|
||||
<div class="col-sm-3 d-grid">
|
||||
<button type="button" class="btn btn-danger" @onclick="ToggleVisibility">@ToggleButtonText</button>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// Copyright (C) 2022 FCS Frede's Computer Services.
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
|
@ -28,7 +27,7 @@ using Wonky.Client.Services;
|
|||
using Wonky.Client.Shared;
|
||||
using Wonky.Entity.DTO;
|
||||
using Wonky.Entity.Models;
|
||||
using Wonky.Entity.Views;
|
||||
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace Wonky.Client.Pages;
|
||||
|
@ -46,8 +45,8 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
[Inject] public VatInfoLookupService VatService { get; set; }
|
||||
[Inject] public ILocalStorageService Storage { get; set; }
|
||||
[Inject] public IUserInfoService UserInfoService { get; set; }
|
||||
|
||||
private readonly JsonSerializerOptions _options = new () { PropertyNameCaseInsensitive = true };
|
||||
|
||||
private readonly JsonSerializerOptions _options = new() { PropertyNameCaseInsensitive = true };
|
||||
private CompanyDto Company { get; set; } = new();
|
||||
private EditContext ErpContext { get; set; }
|
||||
private DateTime LastVisit { get; set; }
|
||||
|
@ -63,6 +62,8 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
private string ActionLink { get; set; } = "";
|
||||
private bool Working { get; set; } = true;
|
||||
private bool CountryIsDk { get; set; } = true;
|
||||
private bool ErpEditDisabled { get; set; } = true;
|
||||
private bool VatEditDisabled { get; set; } = true;
|
||||
private List<ContactDto> Contacts { get; set; } = new();
|
||||
private VatLookupDkModal VatLookupPopup { get; set; } = new();
|
||||
private ContactDto SelectedContact { get; set; } = new();
|
||||
|
@ -70,7 +71,7 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
private ContactModal ContactPopup { get; set; } = new();
|
||||
private UserManagerEditView UserInfo { get; set; } = new();
|
||||
private string ToggleButtonText { get; set; } = "";
|
||||
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// setup interceptor
|
||||
|
@ -78,25 +79,26 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
Interceptor.RegisterBeforeSendEvent();
|
||||
|
||||
// initialize default contact
|
||||
DefaultContact = new ContactDto { CompanyId = CompanyId, ContactId = "", FirstName = ""};
|
||||
DefaultContact = new ContactDto { CompanyId = CompanyId, ContactId = "", FirstName = "" };
|
||||
// setup form context
|
||||
ErpContext = new EditContext(Company);
|
||||
|
||||
|
||||
// assign event handlers to context
|
||||
ErpContext.OnFieldChanged += HandleFieldChanged;
|
||||
ErpContext.OnValidationStateChanged += ValidationChanged;
|
||||
|
||||
|
||||
// fetch user info from local storage
|
||||
UserInfo = await UserInfoService.GetUserInfo();
|
||||
CountryCode = UserInfo.CountryCode.ToLower();
|
||||
CountryIsDk = CountryCode == "dk";
|
||||
|
||||
|
||||
Logger.LogDebug("companyId => {}", CompanyId);
|
||||
|
||||
|
||||
Company = await CustomerRepo.GetCompanyById(CompanyId);
|
||||
|
||||
|
||||
Logger.LogDebug("company => {}", JsonSerializer.Serialize(Company));
|
||||
ToggleButtonText = Company.IsHidden == 0 ? "Skjul kunde" : "Vis kunde";
|
||||
// toggle view button text
|
||||
ToggleButtonText = Company.IsHidden == 0 ? "Udelad kunde i oversigt" : "Brug Normal Visning";
|
||||
CurrentVat = Company.VatNumber;
|
||||
Company.CountryCode = UserInfo.CountryCode.ToLower();
|
||||
// internal flag
|
||||
|
@ -121,7 +123,7 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
// action link passed to activity button component
|
||||
ActionLink = $"/advisor/customers/{CompanyId}/activities/new"; // used when drawing visit button
|
||||
// handle company out of business case
|
||||
if(Company.HasFolded == 1)
|
||||
if (Company.HasFolded == 1)
|
||||
{
|
||||
// this is only used if user has selected to show closed companies
|
||||
HasFolded = true;
|
||||
|
@ -135,36 +137,49 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
// valid vat flag
|
||||
ValidVat = Company.ValidVat == 1; // true/false flag set if company has a valid vatNumber
|
||||
// vat state css class
|
||||
VatState = Company.ValidVat == 1 ? "the-good" : "no-vat"; // assign css class
|
||||
VatState = Company.ValidVat == 1 ? "the-good" : "no-vat"; // assign css class
|
||||
}
|
||||
|
||||
// create search address from address
|
||||
if (CountryIsDk)
|
||||
CompanyVatAddress = PrepareVatAddress(Company);
|
||||
|
||||
|
||||
await FetchContacts(CompanyId);
|
||||
|
||||
|
||||
// remove loading image
|
||||
Working = false;
|
||||
await Task.Delay(100);
|
||||
await RequestErpUpdate();
|
||||
}
|
||||
|
||||
private void ToggleErpEdit()
|
||||
{
|
||||
ErpEditDisabled = !ErpEditDisabled;
|
||||
}
|
||||
|
||||
private void ToggleVatEdit()
|
||||
{
|
||||
VatEditDisabled = !VatEditDisabled;
|
||||
}
|
||||
|
||||
private async Task ToggleVisibility()
|
||||
{
|
||||
Company.IsHidden = Company.IsHidden == 0 ? 1 : 0;
|
||||
ToggleButtonText = Company.IsHidden == 0 ? "Skjul kunde" : "Vis kunde";
|
||||
// toggle view button text
|
||||
ToggleButtonText = Company.IsHidden == 0 ? "Udelad kunde i oversigt" : "Brug Normal Visning";
|
||||
Logger.LogDebug("ToggleVisibility => Company.IsHidden == {}", Company.IsHidden);
|
||||
await CustomerRepo.UpdateCrmData(CompanyId, Company);
|
||||
}
|
||||
|
||||
private async Task RequestErpUpdate()
|
||||
{
|
||||
if(Working)
|
||||
if (Working)
|
||||
return;
|
||||
Working = true;
|
||||
Company.HistorySync = await HistoryRepo.InvoiceErpToCrmRpc(CompanyId, Company.HistorySync);
|
||||
Working = false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Fetch contacts from backend
|
||||
/// </summary>
|
||||
|
@ -173,7 +188,7 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
{
|
||||
// load contacts
|
||||
Contacts = await AdvisorContactRepo.GetContacts(companyId);
|
||||
if(Contacts.Any() && Contacts.Count > 1)
|
||||
if (Contacts.Any() && Contacts.Count > 1)
|
||||
Contacts = Contacts.OrderBy(x => x.FirstName).ToList();
|
||||
}
|
||||
|
||||
|
@ -183,8 +198,8 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
private void OpenVatLookupModal()
|
||||
{
|
||||
VatLookupPopup.Show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback to update company properties
|
||||
/// </summary>
|
||||
|
@ -206,9 +221,10 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
Company.ZipCode = regInfo.ZipCode;
|
||||
Company.City = regInfo.City;
|
||||
}
|
||||
|
||||
Company.VatNumber = regInfo.VatNumber;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Open contact edit popup
|
||||
/// </summary>
|
||||
|
@ -245,15 +261,16 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
// contact modified
|
||||
Logger.LogDebug("update => {}", jsonContact);
|
||||
// send put request to backend
|
||||
await AdvisorContactRepo.UpdateContact(contact);
|
||||
await AdvisorContactRepo.UpdateContact(contact);
|
||||
}
|
||||
|
||||
// reset selected contact
|
||||
SelectedContact = new ContactDto();
|
||||
// reload contacts from backend
|
||||
await FetchContacts(CompanyId);
|
||||
Working = false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Delete contact callback
|
||||
/// </summary>
|
||||
|
@ -270,7 +287,7 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
await FetchContacts(CompanyId);
|
||||
Working = false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Update CRM data
|
||||
/// </summary>
|
||||
|
@ -290,6 +307,7 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
Company = result;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
Working = false;
|
||||
Toaster.ClearAll();
|
||||
}
|
||||
|
@ -302,6 +320,7 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
{
|
||||
if (Working)
|
||||
return;
|
||||
ErpEditDisabled = true;
|
||||
Working = true;
|
||||
Toaster.ShowInfo("Vent venligst ...", "OPDATERER STAM DATA");
|
||||
var result = await CustomerRepo.UpdateErpData(CompanyId, Company);
|
||||
|
@ -310,6 +329,7 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
Company = result;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
Working = false;
|
||||
Toaster.ClearAll();
|
||||
}
|
||||
|
@ -326,8 +346,10 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
Toaster.ShowError($"Moms Nummer ugyldigt");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Working)
|
||||
return;
|
||||
VatEditDisabled = true;
|
||||
Working = true;
|
||||
Toaster.ShowInfo("Vent venligst ...", "OPDATERER MOMS NUMMER");
|
||||
var result = await CustomerRepo.UpdateCompanyVat(CompanyId, Company.VatNumber);
|
||||
|
@ -336,10 +358,11 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
Company = result;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
Toaster.ClearAll();
|
||||
Working = false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Prepare vat address from company model
|
||||
/// </summary>
|
||||
|
@ -359,6 +382,7 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
HouseNumber = Regex.Replace(model.Address1[pos1..], "[^0-9]", "").Trim()
|
||||
};
|
||||
}
|
||||
|
||||
// process address2
|
||||
var pos2 = model.Address2.IndexOfAny(digits);
|
||||
if (pos2 > 0)
|
||||
|
@ -370,10 +394,11 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
HouseNumber = Regex.Replace(model.Address2[pos2..], "[^0-9]", "").Trim()
|
||||
};
|
||||
}
|
||||
|
||||
// return empty model
|
||||
return new VatAddress();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Change activity enabled state
|
||||
/// </summary>
|
||||
|
@ -381,7 +406,7 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
{
|
||||
EnableActivity = EnableActivity == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Context field change event callback
|
||||
/// </summary>
|
||||
|
@ -398,9 +423,10 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
ValidVat = true;
|
||||
EnableActivity = 1;
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Context validation change event callback
|
||||
/// </summary>
|
||||
|
@ -410,13 +436,13 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
{
|
||||
ErpContext.OnFieldChanged -= HandleFieldChanged;
|
||||
ErpContext.OnValidationStateChanged -= ValidationChanged!;
|
||||
|
||||
|
||||
ErpContext = new EditContext(Company);
|
||||
|
||||
|
||||
ErpContext.OnFieldChanged += HandleFieldChanged;
|
||||
ErpContext.OnValidationStateChanged += ValidationChanged;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Dispose
|
||||
/// </summary>
|
||||
|
|
|
@ -16,13 +16,12 @@
|
|||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Wonky.Client.Pages
|
||||
{
|
||||
public partial class ErrorReportPage
|
||||
{
|
||||
[Parameter]
|
||||
public int ErrorCode { get; set; }
|
||||
namespace Wonky.Client.Pages;
|
||||
|
||||
[Parameter] public string ErrorDescription { get; set; } = "";
|
||||
}
|
||||
}
|
||||
public partial class ErrorReportPage
|
||||
{
|
||||
[Parameter]
|
||||
public int ErrorCode { get; set; }
|
||||
|
||||
[Parameter] public string ErrorDescription { get; set; } = "";
|
||||
}
|
|
@ -24,123 +24,120 @@ using Wonky.Entity.Requests;
|
|||
using Wonky.Entity.Views;
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace Wonky.Client.Pages
|
||||
namespace Wonky.Client.Pages;
|
||||
|
||||
public partial class OfficeCountryCustomerListPage : IDisposable
|
||||
{
|
||||
public partial class OfficeCountryCustomerListPage : IDisposable
|
||||
[Parameter] public string CountryCode { get; set; } = "";
|
||||
[Inject] public ILocalStorageService Storage { get; set; }
|
||||
[Inject] public UserProfileService ProfileService { get; set; }
|
||||
[Inject] public ICountryCustomerRepository CustomerRepo { get; set; }
|
||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||
[Inject] public NavigationManager Navigator { get; set; }
|
||||
[Inject] public IUserInfoService UserInfoService { get; set; }
|
||||
|
||||
private List<CompanyDto> Companies { get; set; } = new();
|
||||
private UserProfile Profiles { get; set; } = new();
|
||||
private UserManagerEditView XUserInfo { get; set; } = new();
|
||||
private string SavedSearch { get; set; } = "";
|
||||
private bool ShowFolded { get; set; }
|
||||
private bool Working { get; set; } = true;
|
||||
private MetaData PageData { get; set; } = new();
|
||||
private CustomerPaging Paging { get; set; } = new();
|
||||
private string ButtonFoldedText { get; set; } = "Vis Ophørte";
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
[Parameter] public string CountryCode { get; set; } = "";
|
||||
[Inject] public ILocalStorageService Storage { get; set; }
|
||||
[Inject] public UserProfileService ProfileService { get; set; }
|
||||
[Inject] public ICountryCustomerRepository CustomerRepo { get; set; }
|
||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||
[Inject] public NavigationManager Navigator { get; set; }
|
||||
[Inject] public IUserInfoService UserInfoService { get; set; }
|
||||
|
||||
private List<CompanyDto> Companies { get; set; } = new();
|
||||
private UserProfile Profiles { get; set; } = new();
|
||||
private UserManagerEditView XUserInfo { get; set; } = new();
|
||||
private string SavedSearch { get; set; } = "";
|
||||
private bool ShowFolded { get; set; }
|
||||
private bool Working { get; set; } = true;
|
||||
private MetaData PageData { get; set; } = new();
|
||||
private CustomerPaging Paging { get; set; } = new();
|
||||
private string ButtonFoldedText { get; set; } = "Vis Ophørte";
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
Working = true;
|
||||
Working = true;
|
||||
|
||||
Interceptor.RegisterEvent();
|
||||
Interceptor.RegisterBeforeSendEvent();
|
||||
Interceptor.RegisterEvent();
|
||||
Interceptor.RegisterBeforeSendEvent();
|
||||
|
||||
// set preferences
|
||||
Profiles = await ProfileService.GetProfile();
|
||||
XUserInfo = await UserInfoService.GetUserInfo();
|
||||
Paging.OrderBy = Profiles.CompanySort;
|
||||
Paging.SearchColumn = Profiles.CompanySearch;
|
||||
Paging.PageSize = Convert.ToInt32(Profiles.PageSize);
|
||||
Paging.HasFolded = ShowFolded ? 1 : 0;
|
||||
// set preferences
|
||||
Profiles = await ProfileService.GetProfile();
|
||||
XUserInfo = await UserInfoService.GetUserInfo();
|
||||
Paging.OrderBy = Profiles.CompanySort;
|
||||
Paging.SearchColumn = Profiles.CompanySearch;
|
||||
Paging.PageSize = Convert.ToInt32(Profiles.PageSize);
|
||||
Paging.HasFolded = ShowFolded ? 1 : 0;
|
||||
|
||||
// load saved search
|
||||
SavedSearch = string.IsNullOrWhiteSpace(Profiles.CompanyFilterPhrase) ? "" : Profiles.CompanyFilterPhrase;
|
||||
Paging.SearchTerm = SavedSearch;
|
||||
// load saved search
|
||||
SavedSearch = string.IsNullOrWhiteSpace(Profiles.CompanyFilterPhrase) ? "" : Profiles.CompanyFilterPhrase;
|
||||
Paging.SearchTerm = SavedSearch;
|
||||
|
||||
// get companies
|
||||
await FetchCustomers();
|
||||
}
|
||||
// get companies
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task OnFoldedClick()
|
||||
{
|
||||
Working = true;
|
||||
ShowFolded = !ShowFolded;
|
||||
ButtonFoldedText = ShowFolded ? "Vis Aktive" : "Vis Ophørte";
|
||||
Companies = new List<CompanyDto>();
|
||||
Paging.PageNumber = 1;
|
||||
Paging.HasFolded = ShowFolded ? 1 : 0;
|
||||
await FetchCustomers();
|
||||
}
|
||||
private async Task OnFoldedClick()
|
||||
{
|
||||
Working = true;
|
||||
ShowFolded = !ShowFolded;
|
||||
ButtonFoldedText = ShowFolded ? "Vis Aktive" : "Vis Ophørte";
|
||||
Companies = new List<CompanyDto>();
|
||||
Paging.PageNumber = 1;
|
||||
Paging.HasFolded = ShowFolded ? 1 : 0;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task SelectedPage(int page)
|
||||
{
|
||||
Working = true;
|
||||
Companies = new List<CompanyDto>();
|
||||
Paging.PageNumber = page;
|
||||
await FetchCustomers();
|
||||
}
|
||||
private async Task SelectedPage(int page)
|
||||
{
|
||||
Working = true;
|
||||
Companies = new List<CompanyDto>();
|
||||
Paging.PageNumber = page;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task SetSearchCol(string searchColumn)
|
||||
{
|
||||
Working = true;
|
||||
Companies = new List<CompanyDto>();
|
||||
Paging.SearchColumn = searchColumn;
|
||||
Paging.PageNumber = 1;
|
||||
await FetchCustomers();
|
||||
}
|
||||
private async Task SetPageSize(string pageSize)
|
||||
{
|
||||
Working = true;
|
||||
Companies = new List<CompanyDto>();
|
||||
Paging.PageSize = Convert.ToInt32(pageSize);
|
||||
Paging.PageNumber = 1;
|
||||
await FetchCustomers();
|
||||
}
|
||||
private async Task SetSearchCol(string searchColumn)
|
||||
{
|
||||
Working = true;
|
||||
Companies = new List<CompanyDto>();
|
||||
Paging.SearchColumn = searchColumn;
|
||||
Paging.PageNumber = 1;
|
||||
await FetchCustomers();
|
||||
}
|
||||
private async Task SetPageSize(string pageSize)
|
||||
{
|
||||
Working = true;
|
||||
Companies = new List<CompanyDto>();
|
||||
Paging.PageSize = Convert.ToInt32(pageSize);
|
||||
Paging.PageNumber = 1;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task SetSearchPhrase(string searchTerm)
|
||||
{
|
||||
Working = true;
|
||||
Companies = new List<CompanyDto>();
|
||||
Paging.PageNumber = 1;
|
||||
Paging.SearchTerm = searchTerm;
|
||||
await FetchCustomers();
|
||||
}
|
||||
private async Task SetSearchPhrase(string searchTerm)
|
||||
{
|
||||
Working = true;
|
||||
Companies = new List<CompanyDto>();
|
||||
Paging.PageNumber = 1;
|
||||
Paging.SearchTerm = searchTerm;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task SetSortCol(string orderBy)
|
||||
private async Task SetSortCol(string orderBy)
|
||||
{
|
||||
Working = true;
|
||||
Companies = new List<CompanyDto>();
|
||||
Paging.OrderBy = orderBy;
|
||||
await FetchCustomers();
|
||||
}
|
||||
|
||||
private async Task FetchCustomers()
|
||||
{
|
||||
Working = true;
|
||||
var response = await CustomerRepo.GetCompaniesPaged(CountryCode, Paging);
|
||||
Working = false;
|
||||
if (response.Items.Any())
|
||||
{
|
||||
Companies = response.Items;
|
||||
PageData = response.MetaData;
|
||||
}
|
||||
else
|
||||
{
|
||||
Working = true;
|
||||
Companies = new List<CompanyDto>();
|
||||
Paging.OrderBy = orderBy;
|
||||
await FetchCustomers();
|
||||
PageData = new MetaData();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task FetchCustomers()
|
||||
{
|
||||
Working = true;
|
||||
var response = await CustomerRepo.GetCompaniesPaged(CountryCode, Paging);
|
||||
Working = false;
|
||||
if (response.Items.Any())
|
||||
{
|
||||
Companies = response.Items;
|
||||
PageData = response.MetaData;
|
||||
}
|
||||
else
|
||||
{
|
||||
Companies = new List<CompanyDto>();
|
||||
PageData = new MetaData();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() => Interceptor.DisposeEvent();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Dispose() => Interceptor.DisposeEvent();
|
||||
}
|
|
@ -24,123 +24,121 @@ using Wonky.Entity.Configuration;
|
|||
using Wonky.Entity.DTO;
|
||||
using Wonky.Entity.Views;
|
||||
|
||||
namespace Wonky.Client.Services
|
||||
namespace Wonky.Client.Services;
|
||||
|
||||
public class AuthenticationService : IAuthenticationService
|
||||
{
|
||||
public class AuthenticationService : IAuthenticationService
|
||||
private readonly JsonSerializerOptions _options = new() { PropertyNameCaseInsensitive = true };
|
||||
private readonly HttpClient _client;
|
||||
private readonly AuthenticationStateProvider _authStateProvider;
|
||||
private readonly IOptions<ApiConfig> _apiConfig;
|
||||
private readonly ILogger<AuthenticationService> _logger;
|
||||
private readonly IUserInfoService _infoService;
|
||||
private readonly UserProfileService _profile;
|
||||
private readonly ILocalStorageService _localStorage;
|
||||
|
||||
public AuthenticationService(
|
||||
HttpClient client,
|
||||
AuthenticationStateProvider authStateProvider,
|
||||
IOptions<ApiConfig> apiConfig,
|
||||
ILogger<AuthenticationService> logger,
|
||||
IUserInfoService infoService,
|
||||
UserProfileService profile,
|
||||
ILocalStorageService localStorage
|
||||
)
|
||||
{
|
||||
private readonly JsonSerializerOptions _options = new() { PropertyNameCaseInsensitive = true };
|
||||
private readonly HttpClient _client;
|
||||
private readonly AuthenticationStateProvider _authStateProvider;
|
||||
private readonly IOptions<ApiConfig> _apiConfig;
|
||||
private readonly ILogger<AuthenticationService> _logger;
|
||||
private readonly IUserInfoService _infoService;
|
||||
private readonly UserProfileService _profile;
|
||||
private readonly ILocalStorageService _localStorage;
|
||||
|
||||
public AuthenticationService(
|
||||
HttpClient client,
|
||||
AuthenticationStateProvider authStateProvider,
|
||||
IOptions<ApiConfig> apiConfig,
|
||||
ILogger<AuthenticationService> logger,
|
||||
IUserInfoService infoService,
|
||||
UserProfileService profile,
|
||||
ILocalStorageService localStorage
|
||||
)
|
||||
{
|
||||
_client = client;
|
||||
_authStateProvider = authStateProvider;
|
||||
_apiConfig = apiConfig;
|
||||
_logger = logger;
|
||||
_infoService = infoService;
|
||||
_profile = profile;
|
||||
_localStorage = localStorage;
|
||||
}
|
||||
_client = client;
|
||||
_authStateProvider = authStateProvider;
|
||||
_apiConfig = apiConfig;
|
||||
_logger = logger;
|
||||
_infoService = infoService;
|
||||
_profile = profile;
|
||||
_localStorage = localStorage;
|
||||
}
|
||||
|
||||
public async Task<AuthResponseView> Login(CredentialDto credentials)
|
||||
public async Task<AuthResponseView> Login(CredentialDto credentials)
|
||||
{
|
||||
var credForm = new Dictionary<string, string>
|
||||
{
|
||||
var credForm = new Dictionary<string, string>
|
||||
["grant_type"] = "password",
|
||||
["username"] = credentials.Email,
|
||||
["password"] = credentials.Password
|
||||
};
|
||||
|
||||
var response = await _client
|
||||
.PostAsync(_apiConfig.Value.ServicesAuth, new FormUrlEncodedContent(credForm));
|
||||
|
||||
var resContent = await response.Content.ReadAsStringAsync();
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return new AuthResponseView
|
||||
{
|
||||
["grant_type"] = "password",
|
||||
["username"] = credentials.Email,
|
||||
["password"] = credentials.Password
|
||||
IsSuccess = false, ErrorMessage = $"Kontroller indtastning"
|
||||
};
|
||||
|
||||
var response = await _client
|
||||
.PostAsync(_apiConfig.Value.ServicesAuth, new FormUrlEncodedContent(credForm));
|
||||
// process response content
|
||||
var data = JsonSerializer.Deserialize<AuthResponseView>(resContent, _options);
|
||||
|
||||
await _infoService.SetAccessToken(data.AccessToken);
|
||||
await _infoService.SetRefreshToken(data.RefreshToken);
|
||||
await _infoService.SetExpiration((int)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds + data.ExpiresIn - 60);
|
||||
|
||||
var resContent = await response.Content.ReadAsStringAsync();
|
||||
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", data.AccessToken);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return new AuthResponseView
|
||||
{
|
||||
IsSuccess = false, ErrorMessage = $"Kontroller indtastning"
|
||||
};
|
||||
var userInfo = await UserInfo();
|
||||
|
||||
// process response content
|
||||
var data = JsonSerializer.Deserialize<AuthResponseView>(resContent, _options);
|
||||
await _infoService.SetUserInfo(userInfo);
|
||||
|
||||
await _infoService.SetAccessToken(data.AccessToken);
|
||||
await _infoService.SetRefreshToken(data.RefreshToken);
|
||||
await _infoService.SetExpiration((int)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds + data.ExpiresIn - 60);
|
||||
// notify system on state change
|
||||
((AuthStateProvider)_authStateProvider).NotifyUserAuthenticationAsync(data.AccessToken);
|
||||
data.IsSuccess = true;
|
||||
return data;
|
||||
}
|
||||
|
||||
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", data.AccessToken);
|
||||
|
||||
var userInfo = await UserInfo();
|
||||
|
||||
await _infoService.SetUserInfo(userInfo);
|
||||
|
||||
// notify system on state change
|
||||
((AuthStateProvider)_authStateProvider).NotifyUserAuthenticationAsync(data.AccessToken);
|
||||
data.IsSuccess = true;
|
||||
return data;
|
||||
}
|
||||
|
||||
public async Task<string> RefreshToken()
|
||||
public async Task<string> RefreshToken()
|
||||
{
|
||||
var refreshToken = await _infoService.GetRefreshToken();
|
||||
var credentials = new Dictionary<string, string>
|
||||
{
|
||||
var refreshToken = await _infoService.GetRefreshToken();
|
||||
var credentials = new Dictionary<string, string>
|
||||
{
|
||||
["grant_type"] = "refresh_token",
|
||||
["refresh_token"] = refreshToken
|
||||
};
|
||||
var response = await _client.PostAsync(_apiConfig.Value.ServicesAuth, new FormUrlEncodedContent(credentials));
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return string.Empty;
|
||||
["grant_type"] = "refresh_token",
|
||||
["refresh_token"] = refreshToken
|
||||
};
|
||||
var response = await _client.PostAsync(_apiConfig.Value.ServicesAuth, new FormUrlEncodedContent(credentials));
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return string.Empty;
|
||||
|
||||
var resContent = await response.Content.ReadAsStringAsync();
|
||||
var data = JsonSerializer.Deserialize<AuthResponseView>(resContent, _options);
|
||||
var resContent = await response.Content.ReadAsStringAsync();
|
||||
var data = JsonSerializer.Deserialize<AuthResponseView>(resContent, _options);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(data.AccessToken))
|
||||
return string.Empty;
|
||||
if (string.IsNullOrWhiteSpace(data.AccessToken))
|
||||
return string.Empty;
|
||||
|
||||
// set default request headers using access_token
|
||||
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", data.AccessToken);
|
||||
await _infoService.SetAccessToken(data.AccessToken);
|
||||
await _infoService.SetRefreshToken(data.RefreshToken);
|
||||
await _infoService.SetExpiration((int)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds + data.ExpiresIn - 60);
|
||||
return data.AccessToken;
|
||||
}
|
||||
// set default request headers using access_token
|
||||
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", data.AccessToken);
|
||||
await _infoService.SetAccessToken(data.AccessToken);
|
||||
await _infoService.SetRefreshToken(data.RefreshToken);
|
||||
await _infoService.SetExpiration((int)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds + data.ExpiresIn - 60);
|
||||
return data.AccessToken;
|
||||
}
|
||||
|
||||
public async Task Logout()
|
||||
{
|
||||
var profileBackup = await _profile.GetProfile();
|
||||
Task.Delay(150);
|
||||
await _localStorage.ClearAsync();
|
||||
Task.Delay(150);
|
||||
await _profile.SetProfile(profileBackup);
|
||||
_client.DefaultRequestHeaders.Authorization = null;
|
||||
((AuthStateProvider)_authStateProvider).NotifyUserLogout();
|
||||
}
|
||||
|
||||
public async Task<UserManagerEditView> UserInfo(bool write = false)
|
||||
{
|
||||
var response = await _client.GetAsync(_apiConfig.Value.UserInfo).ConfigureAwait(true);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
var userInfo = JsonSerializer.Deserialize<UserManagerEditView>(content, _options);
|
||||
if(write)
|
||||
await _infoService.SetUserInfo(userInfo);
|
||||
return userInfo ?? new UserManagerEditView();
|
||||
}
|
||||
}
|
||||
}
|
||||
public async Task Logout()
|
||||
{
|
||||
var profileBackup = await _profile.GetProfile();
|
||||
Task.Delay(150);
|
||||
await _localStorage.ClearAsync();
|
||||
Task.Delay(150);
|
||||
await _profile.SetProfile(profileBackup);
|
||||
_client.DefaultRequestHeaders.Authorization = null;
|
||||
((AuthStateProvider)_authStateProvider).NotifyUserLogout();
|
||||
}
|
||||
|
||||
public async Task<UserManagerEditView> UserInfo(bool write = false)
|
||||
{
|
||||
var response = await _client.GetAsync(_apiConfig.Value.UserInfo).ConfigureAwait(true);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
var userInfo = JsonSerializer.Deserialize<UserManagerEditView>(content, _options);
|
||||
if(write)
|
||||
await _infoService.SetUserInfo(userInfo);
|
||||
return userInfo ?? new UserManagerEditView();
|
||||
}
|
||||
}
|
|
@ -17,14 +17,12 @@
|
|||
using Wonky.Entity.DTO;
|
||||
using Wonky.Entity.Views;
|
||||
|
||||
namespace Wonky.Client.Services
|
||||
{
|
||||
public interface IAuthenticationService
|
||||
{
|
||||
Task<AuthResponseView> Login(CredentialDto credentials);
|
||||
Task Logout();
|
||||
Task<string> RefreshToken();
|
||||
Task<UserManagerEditView> UserInfo(bool write = false);
|
||||
}
|
||||
}
|
||||
namespace Wonky.Client.Services;
|
||||
|
||||
public interface IAuthenticationService
|
||||
{
|
||||
Task<AuthResponseView> Login(CredentialDto credentials);
|
||||
Task Logout();
|
||||
Task<string> RefreshToken();
|
||||
Task<UserManagerEditView> UserInfo(bool write = false);
|
||||
}
|
|
@ -22,86 +22,84 @@ using Wonky.Client.Services;
|
|||
using Wonky.Entity.DTO;
|
||||
using Wonky.Entity.Views;
|
||||
|
||||
namespace Wonky.Client.Shared
|
||||
namespace Wonky.Client.Shared;
|
||||
|
||||
public class AuthStateProvider : AuthenticationStateProvider
|
||||
{
|
||||
public class AuthStateProvider : AuthenticationStateProvider
|
||||
private readonly HttpClient _client;
|
||||
// private readonly ILocalStorageService _storage;
|
||||
private readonly AuthenticationState _anonymous;
|
||||
private readonly IUserInfoService _infoService;
|
||||
|
||||
public AuthStateProvider(HttpClient client, IUserInfoService infoService)
|
||||
{
|
||||
private readonly HttpClient _client;
|
||||
// private readonly ILocalStorageService _storage;
|
||||
private readonly AuthenticationState _anonymous;
|
||||
private readonly IUserInfoService _infoService;
|
||||
|
||||
public AuthStateProvider(HttpClient client, IUserInfoService infoService)
|
||||
{
|
||||
_client = client;
|
||||
_infoService = infoService;
|
||||
_anonymous = new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
|
||||
}
|
||||
|
||||
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
||||
{
|
||||
var token = await _infoService.GetAccessToken();
|
||||
if (string.IsNullOrEmpty(token))
|
||||
return _anonymous;
|
||||
|
||||
var userInfo = await _infoService.GetUserInfo();
|
||||
if (userInfo == null)
|
||||
return _anonymous;
|
||||
|
||||
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
|
||||
var exp = await _infoService.GetExpiration();
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new(ClaimTypes.Name, $"{userInfo.FirstName} {userInfo.LastName}"),
|
||||
new(ClaimTypes.Email, userInfo.Email),
|
||||
new(ClaimTypes.Country, userInfo.CountryCode),
|
||||
new(ClaimTypes.MobilePhone, userInfo.PhoneNumber),
|
||||
new(ClaimTypes.Expiration, exp.ToString())
|
||||
};
|
||||
claims.AddRange(
|
||||
from role in userInfo.AssignedRoles
|
||||
where role.Assigned select new Claim(ClaimTypes.Role, role.Name));
|
||||
|
||||
// return the authState for the user
|
||||
return new AuthenticationState(
|
||||
new ClaimsPrincipal(
|
||||
new ClaimsIdentity(claims, "token")));
|
||||
}
|
||||
|
||||
public async void NotifyUserAuthenticationAsync(string token)
|
||||
{
|
||||
if (string.IsNullOrEmpty(token))
|
||||
return;
|
||||
|
||||
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
|
||||
|
||||
var userInfo = await _infoService.GetUserInfo();
|
||||
var exp = await _infoService.GetExpiration();
|
||||
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new(ClaimTypes.Name, $"{userInfo.FirstName} {userInfo.LastName}"),
|
||||
new(ClaimTypes.Email, userInfo.Email),
|
||||
new(ClaimTypes.Country, userInfo.CountryCode),
|
||||
new(ClaimTypes.MobilePhone, userInfo.PhoneNumber),
|
||||
new(ClaimTypes.Expiration, exp.ToString())
|
||||
};
|
||||
claims.AddRange(
|
||||
from role in userInfo.AssignedRoles
|
||||
where role.Assigned select new Claim(ClaimTypes.Role, role.Name));
|
||||
|
||||
var authState = Task.FromResult(
|
||||
new AuthenticationState(
|
||||
new ClaimsPrincipal(
|
||||
new ClaimsIdentity(claims, "token"))));
|
||||
|
||||
NotifyAuthenticationStateChanged(authState);
|
||||
}
|
||||
public void NotifyUserLogout()
|
||||
{
|
||||
var authState = Task.FromResult(_anonymous);
|
||||
NotifyAuthenticationStateChanged(authState);
|
||||
}
|
||||
_client = client;
|
||||
_infoService = infoService;
|
||||
_anonymous = new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
||||
{
|
||||
var token = await _infoService.GetAccessToken();
|
||||
if (string.IsNullOrEmpty(token))
|
||||
return _anonymous;
|
||||
|
||||
var userInfo = await _infoService.GetUserInfo();
|
||||
if (userInfo == null)
|
||||
return _anonymous;
|
||||
|
||||
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
|
||||
var exp = await _infoService.GetExpiration();
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new(ClaimTypes.Name, $"{userInfo.FirstName} {userInfo.LastName}"),
|
||||
new(ClaimTypes.Email, userInfo.Email),
|
||||
new(ClaimTypes.Country, userInfo.CountryCode),
|
||||
new(ClaimTypes.MobilePhone, userInfo.PhoneNumber),
|
||||
new(ClaimTypes.Expiration, exp.ToString())
|
||||
};
|
||||
claims.AddRange(
|
||||
from role in userInfo.AssignedRoles
|
||||
where role.Assigned select new Claim(ClaimTypes.Role, role.Name));
|
||||
|
||||
// return the authState for the user
|
||||
return new AuthenticationState(
|
||||
new ClaimsPrincipal(
|
||||
new ClaimsIdentity(claims, "token")));
|
||||
}
|
||||
|
||||
public async void NotifyUserAuthenticationAsync(string token)
|
||||
{
|
||||
if (string.IsNullOrEmpty(token))
|
||||
return;
|
||||
|
||||
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
|
||||
|
||||
var userInfo = await _infoService.GetUserInfo();
|
||||
var exp = await _infoService.GetExpiration();
|
||||
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new(ClaimTypes.Name, $"{userInfo.FirstName} {userInfo.LastName}"),
|
||||
new(ClaimTypes.Email, userInfo.Email),
|
||||
new(ClaimTypes.Country, userInfo.CountryCode),
|
||||
new(ClaimTypes.MobilePhone, userInfo.PhoneNumber),
|
||||
new(ClaimTypes.Expiration, exp.ToString())
|
||||
};
|
||||
claims.AddRange(
|
||||
from role in userInfo.AssignedRoles
|
||||
where role.Assigned select new Claim(ClaimTypes.Role, role.Name));
|
||||
|
||||
var authState = Task.FromResult(
|
||||
new AuthenticationState(
|
||||
new ClaimsPrincipal(
|
||||
new ClaimsIdentity(claims, "token"))));
|
||||
|
||||
NotifyAuthenticationStateChanged(authState);
|
||||
}
|
||||
public void NotifyUserLogout()
|
||||
{
|
||||
var authState = Task.FromResult(_anonymous);
|
||||
NotifyAuthenticationStateChanged(authState);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"appInfo": {
|
||||
"name": "Wonky Online",
|
||||
"version": "0.117.1",
|
||||
"version": "0.118.0",
|
||||
"rc": true,
|
||||
"sandBox": false,
|
||||
"image": "grumpy-coder.png"
|
||||
|
@ -19,7 +19,7 @@
|
|||
}
|
||||
},
|
||||
"apiConfig": {
|
||||
"baseUrl": "https://dev.innotec.dk",
|
||||
"baseUrl": "https://zeta.innotec.dk",
|
||||
"catalog": "api/v2/catalog/country",
|
||||
"crmCustomers": "api/v2/crm/companies",
|
||||
"crmInventoryExt": "history/inventory",
|
||||
|
|
Loading…
Reference in a new issue