code cleanup

This commit is contained in:
Frede Hundewadt 2023-02-10 14:58:09 +01:00
parent 54daf9c054
commit c13252da37
156 changed files with 2533 additions and 951 deletions

View file

@ -36,5 +36,4 @@ else
if (!string.IsNullOrWhiteSpace(CompanyId)) if (!string.IsNullOrWhiteSpace(CompanyId))
ActionLink = ActionLink.Replace("$ID$", CompanyId); ActionLink = ActionLink.Replace("$ID$", CompanyId);
} }
} }

View file

@ -21,6 +21,6 @@ namespace Wonky.Client.Components;
public partial class AdvisorActivityListComponent public partial class AdvisorActivityListComponent
{ {
[Parameter] public List<ReportItemView> ActivityList { get; set; } = new(); [Parameter] public List<ReportItemView> ActivityList { get; set; } = new();
[Inject] private NavigationManager Navigator { get; set; } // [Inject] private NavigationManager Navigator { get; set; }
} }

View file

@ -70,4 +70,5 @@ else
{ {
<div>Ingen data</div> <div>Ingen data</div>
} }
<InformationModal BodyMessage="@InfoMessage"/> <InformationModal BodyMessage="@InfoMessage"/>

View file

@ -24,6 +24,7 @@ using Wonky.Client.Shared;
using Wonky.Entity.DTO; using Wonky.Entity.DTO;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Components namespace Wonky.Client.Components
{ {
@ -33,9 +34,9 @@ namespace Wonky.Client.Components
[Parameter] public EventCallback<string> OnDelete { get; set; } [Parameter] public EventCallback<string> OnDelete { get; set; }
[Parameter] public EventCallback<string> OnSelect { get; set; } [Parameter] public EventCallback<string> OnSelect { get; set; }
[Inject] private NavigationManager Navigator { get; set; } [Inject] private NavigationManager Navigator { get; set; }
[Inject] private IJSRuntime Js { get; set; } [Inject] private IJSRuntime JsRuntime { get; set; }
private Lazy<IJSObjectReference> BsTooltip = new(); private Lazy<IJSObjectReference> BsTooltip { get; set; } = new();
private InformationModal InformationModal { get; set; } = new(); private InformationModal InformationModal { get; set; } = new();
private string InfoMessage { get; set; } = ""; private string InfoMessage { get; set; } = "";

View file

@ -30,7 +30,7 @@ using Wonky.Entity.Models;
using Wonky.Entity.Views; using Wonky.Entity.Views;
namespace Wonky.Client.Components; namespace Wonky.Client.Components;
public partial class LandingComponentAdvisor public partial class AdvisorLandingComponent
{ {
[Inject] private UserProfileService ProfileService { get; set; } [Inject] private UserProfileService ProfileService { get; set; }

View file

@ -13,10 +13,10 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// //
using System.Text.RegularExpressions;
using Blazored.LocalStorage; using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.Services; using Wonky.Client.Services;
#pragma warning disable CS8618
namespace Wonky.Client.Components; namespace Wonky.Client.Components;

View file

@ -13,10 +13,7 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// //
using Blazored.Toast.Services;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Entity.DTO;
using Wonky.Entity.Models;
using Wonky.Entity.Views; using Wonky.Entity.Views;
namespace Wonky.Client.Components; namespace Wonky.Client.Components;

View file

@ -13,9 +13,9 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// //
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.Services; using Wonky.Client.Services;
#pragma warning disable CS8618
namespace Wonky.Client.Components; namespace Wonky.Client.Components;

View file

@ -13,9 +13,9 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// //
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.Services; using Wonky.Client.Services;
#pragma warning disable CS8618
namespace Wonky.Client.Components; namespace Wonky.Client.Components;

View file

@ -14,7 +14,7 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// //
*@ *@
@using Wonky.Client.OverlayCustomer
<div class="list-group"> <div class="list-group">
<div class="list-group-item"> <div class="list-group-item">
<div class="row"> <div class="row">
@ -72,4 +72,4 @@
} }
</div> </div>
<CustomerActivityViewModalOverlay ReportItem="Activity" @ref="ActivityViewOverlay"/> <CustomerActivityViewOverlay ReportItem="Activity" @ref="ActivityViewOverlay"/>

View file

@ -13,22 +13,16 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// //
using System.Globalization;
using System.Runtime.InteropServices;
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterfaces; using Wonky.Client.OverlayCustomer;
using Wonky.Client.Models;
using Wonky.Client.Shared;
using Wonky.Entity.DTO;
using Wonky.Entity.Views; using Wonky.Entity.Views;
namespace Wonky.Client.Components; namespace Wonky.Client.Components;
public partial class CustomerVisitListComponent public partial class CustomerActivityListComponent
{ {
[Parameter] public List<ReportItemView> Activities { get; set; } = new(); [Parameter] public List<ReportItemView> Activities { get; set; } = new();
private CustomerActivityViewModalOverlay ActivityViewOverlay { get; set; } = new(); private CustomerActivityViewOverlay ActivityViewOverlay { get; set; } = new();
private ReportItemView Activity { get; set; } = new(); private ReportItemView Activity { get; set; } = new();
@ -37,5 +31,4 @@ public partial class CustomerVisitListComponent
Activity = Activities.First(x => x.ActivityId == activityId); Activity = Activities.First(x => x.ActivityId == activityId);
ActivityViewOverlay.Show(); ActivityViewOverlay.Show();
} }
} }

View file

@ -23,7 +23,7 @@
@if (Inventory.Any()) @if (Inventory.Any())
{ {
<div class="list-group mt-2"> <div class="list-group mt-2">
<div class="list-group-item bg-dark text-white"> <div class="list-group-item">
<div class="row"> <div class="row">
<div class="col-sm-4" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Desc)"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div> <div class="col-sm-4" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Desc)"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
<div class="col-sm-3" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Sku)"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div> <div class="col-sm-3" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Sku)"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
@ -45,7 +45,6 @@
<span class="visually-hidden">Produktet er udgået</span> <span class="visually-hidden">Produktet er udgået</span>
} }
</div> </div>
@* @product.Description <span class="fw-bold text-sm-start">@(product.Discontinued ? "(UDGÅET)" : "")</span> *@
</div> </div>
<div class="col-sm-3"> <div class="col-sm-3">
@product.Sku @product.Sku
@ -54,7 +53,7 @@
@product.Quantity @product.Quantity
</div> </div>
<div class="col-sm-2"> <div class="col-sm-2">
<a class="btn btn-info d-block" type="button" @onclick="() => CallShowReorderModal(product.Sku)"><i class="bi-cart"></i> Genbestil</a> <a class="btn btn-info d-block" type="button" @onclick="() => CallShowReorderModal(product.Sku)"><i class="bi-cart"></i> Genbestil</a>
</div> </div>
<div class="col-sm-1" @onclick="() => ProductCheck(product.Sku)"> <div class="col-sm-1" @onclick="() => ProductCheck(product.Sku)">
<input type="checkbox" class="btn-check" id="btn-@product.Sku.Replace(",", "")" autocomplete="off"/> <input type="checkbox" class="btn-check" id="btn-@product.Sku.Replace(",", "")" autocomplete="off"/>

View file

@ -13,17 +13,13 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// //
using System.Globalization;
using System.Runtime.InteropServices;
using Blazored.LocalStorage; using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterfaces;
using Wonky.Client.Models; using Wonky.Client.Models;
using Wonky.Client.Shared;
using Wonky.Entity.DTO;
using Wonky.Entity.Views; using Wonky.Entity.Views;
namespace Wonky.Client.Components; namespace Wonky.Client.Components;
#pragma warning disable CS8618
public partial class CustomerInventoryListComponent public partial class CustomerInventoryListComponent
{ {

View file

@ -15,7 +15,6 @@
// //
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.Shared;
using Wonky.Entity.Views; using Wonky.Entity.Views;
namespace Wonky.Client.Components; namespace Wonky.Client.Components;

View file

@ -22,7 +22,7 @@
@if (ProductList.Any()) @if (ProductList.Any())
{ {
<div class="list-group mt-2"> <div class="list-group mt-2">
<div class="list-group-item bg-dark text-white"> <div class="list-group-item">
<div class="row"> <div class="row">
<div class="col-sm-4" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Desc)"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div> <div class="col-sm-4" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Desc)"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
<div class="col-sm-3" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Sku)"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div> <div class="col-sm-3" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Sku)"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>

View file

@ -13,15 +13,11 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// //
using System.Globalization;
using System.Runtime.InteropServices;
using Blazored.LocalStorage; using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterfaces;
using Wonky.Client.Models; using Wonky.Client.Models;
using Wonky.Client.Shared;
using Wonky.Entity.DTO;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Components; namespace Wonky.Client.Components;
public partial class CustomerProductCheckListComponent public partial class CustomerProductCheckListComponent

View file

@ -19,7 +19,7 @@
{ {
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>
<tr class="bg-black text-white rounded-2 opacity-75"> <tr class="rounded-2 border border-1">
<th scope="col"> <th scope="col">
Dato Dato
</th> </th>

View file

@ -15,10 +15,10 @@
// //
using System.Security.AccessControl;
using Blazored.LocalStorage; using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.Services; using Wonky.Client.Services;
#pragma warning disable CS8618
namespace Wonky.Client.Components; namespace Wonky.Client.Components;

View file

@ -17,6 +17,7 @@ using System.Timers;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.Services; using Wonky.Client.Services;
using Timer = System.Timers.Timer; using Timer = System.Timers.Timer;
#pragma warning disable CS8618
namespace Wonky.Client.Components namespace Wonky.Client.Components
{ {

View file

@ -18,6 +18,7 @@
using Blazored.LocalStorage; using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.Services; using Wonky.Client.Services;
#pragma warning disable CS8618
namespace Wonky.Client.Components namespace Wonky.Client.Components
{ {

View file

@ -15,7 +15,6 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Entity.DTO; using Wonky.Entity.DTO;
using Wonky.Entity.Views;
namespace Wonky.Client.Components; namespace Wonky.Client.Components;

View file

@ -17,7 +17,7 @@
@using Wonky.Client.Components; @using Wonky.Client.Components;
@using Wonky.Client.Helpers; @using Wonky.Client.Helpers;
@using Wonky.Client.OverlayOffice
@if (CompanyList.Any()) @if (CompanyList.Any())
{ {
<div class="row d-flex g-3"> <div class="row d-flex g-3">
@ -52,16 +52,16 @@
<div class="card-footer"> <div class="card-footer">
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<button class="btn btn-danger" disabled>Faktura</button> <button class="btn btn-danger" @onclick="() => ShowInvoiceList(company.CompanyId)" >Faktura</button>
</div> </div>
<div class="col"> <div class="col">
<button class="btn btn-warning" disabled>Aktivitet</button> <button class="btn btn-warning" @onclick="() => ShowActivityList(company.CompanyId)" >Aktivitet</button>
</div> </div>
<div class="col"> <div class="col">
<button class="btn btn-success" disabled>Produkt</button> <button class="btn btn-success" @onclick="() => ShowProductList(company.CompanyId)">Produkt</button>
</div> </div>
<div class="col"> <div class="col">
<button class="btn btn-primary" disabled>Bestilling</button> <button class="btn btn-primary" disabled >Bestilling</button>
</div> </div>
</div> </div>
</div> </div>
@ -74,12 +74,8 @@ else
{ {
<div>Ingen data</div> <div>Ingen data</div>
} }
@*
<CustomerInvoiceListModalOverlay CustomerInvoices="Invoices" @ref="InvoiceListOverlay" />
<CustomerActivityListModalOverlay Activities="Activities" CompanyName="@CompanyName" @ref="ActivityListOverlay" /> <OfficeCustomerInvoiceListOverlay Company="@SelectedCompany" CustomerInvoices="@InvoiceViewList" @ref="InvoiceListOverlay" />
<OfficeCustomerActivityListOverlay Activities="ActivityList" Company="SelectedCompany" @ref="ActivityListOverlay" />
<CustomerInventoryListModalOverlay CompanyName="@CompanyName" CompanyId="@CompanyId" CountryCode="@CountryCode" <OfficeCustomerProductListOverlay Company="SelectedCompany" ProductList="ProductList" @ref="ProductListOverlay" />
OnInventorySelected="OnInventoryCallback" Inventory="Inventory" @ref="InventoryListOverlay" />
*@

View file

@ -1,4 +1,3 @@
// 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 // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as // it under the terms of the GNU Affero General Public License as
@ -14,13 +13,12 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// //
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.Helpers; using Wonky.Client.HttpInterfaces;
using Wonky.Client.Services; using Wonky.Client.OverlayOffice;
using Wonky.Client.Shared;
using Wonky.Entity.DTO; using Wonky.Entity.DTO;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Components namespace Wonky.Client.Components
{ {
@ -29,19 +27,54 @@ namespace Wonky.Client.Components
[Parameter] public List<CompanyDto> CompanyList { get; set; } = new(); [Parameter] public List<CompanyDto> CompanyList { get; set; } = new();
[Parameter] public string CountryCode { get; set; } = ""; [Parameter] public string CountryCode { get; set; } = "";
private CustomerInvoiceListModalOverlay InvoiceListOverlay { get; set; } = new(); [Inject] public ICountryCustomerHistoryRepository HistoryRepo { get; set; }
private CustomerInventoryListModalOverlay InventoryListOverlay { get; set; } = new(); [Inject] public ICountryActivityRepository ActivityRepo { get; set; }
private CustomerActivityListModalOverlay ActivityListOverlay { get; set; } = new();
private OfficeCustomerInvoiceListOverlay InvoiceListOverlay { get; set; } = new();
private OfficeCustomerActivityListOverlay ActivityListOverlay { get; set; } = new();
private OfficeCustomerProductListOverlay ProductListOverlay { get; set; } = new();
private string CompanyName { get; set; } = ""; private string CompanyName { get; set; } = "";
private string CompanyId { get; set; } = ""; private string CompanyId { get; set; } = "";
private InvoiceListView Invoices { get; set; } = new(); private string LastSync { get; set; } = "";
private List<ReportItemView> Activities { get; set; } = new();
private List<ProductHistoryView> Inventory { get; set; } = new(); private InvoiceListView InvoiceViewList { get; set; } = new();
private List<ReportItemView> ActivityList { get; set; } = new();
private List<ProductInventoryView> ProductList { get; set; } = new();
private CompanyDto SelectedCompany { get; set; } = new();
private void OnInventoryCallback() private void OnInventoryCallback()
{ {
}
private async Task ShowInvoiceList(string companyId)
{
// call erp to crm sync before requesting invoices
// get company last sync from company list
SelectedCompany = CompanyList.Find(x => x.CompanyId == companyId);
var newSyncDate = await HistoryRepo.InvoiceErpToCrmRpc(CountryCode, companyId, SelectedCompany.HistorySync);
await Task.Delay(500);
InvoiceViewList = await HistoryRepo.FetchInvoiceList(CountryCode, companyId);
SelectedCompany.HistorySync = newSyncDate;
InvoiceListOverlay.Show();
}
private async Task ShowActivityList(string companyId)
{
// call erp to crm sync before requesting invoices
// get company last sync from company list
SelectedCompany = CompanyList.Find(x => x.CompanyId == companyId);
ActivityList = await ActivityRepo.GetCustomerActivities(companyId);
ActivityListOverlay.Show();
}
private async Task ShowProductList(string companyId)
{
// call erp to crm sync before requesting invoices
// get company last sync from company list
SelectedCompany = CompanyList.Find(x => x.CompanyId == companyId);
ProductList = await HistoryRepo.FetchInventory(SelectedCompany.CountryCode, SelectedCompany.CompanyId);
ProductListOverlay.Show();
} }
} }
} }

View file

@ -0,0 +1,75 @@
@*
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
*@
@using Wonky.Client.OverlayOffice
<div class="list-group">
<div class="list-group-item">
<div class="row">
<div class="col">
<h4>Dato</h4>
</div>
<div class="col">
<h4>Demo</h4>
</div>
<div class="col">
<h4>Salg</h4>
</div>
<div class="col">
<h4>Ordre Note</h4>
</div>
<div class="col">
<h4>Ordre Note</h4>
</div>
</div>
</div>
@if (Activities.Any())
{
@foreach (var activity in Activities)
{
<div class="list-group-item list-group-item-action" style="cursor: pointer" @onclick="() => ShowVisitOverlay(activity.ActivityId)">
<div class="row">
<div class="col">
@activity.OrderDate
</div>
<div class="col">
@activity.Demo
</div>
<div class="col">
@activity.Sales
</div>
<div class="col">
@activity.OfficeNote
</div>
<div class="col">
@activity.CrmNote
</div>
</div>
</div>
}
}
else
{
<div class="list-group-item">
<div class="row">
<div class="col">
Ingen data
</div>
</div>
</div>
}
</div>
<OfficeCustomerActivityViewOverlay Activity="Activity" @ref="ActivityViewOverlay"/>

View file

@ -0,0 +1,34 @@
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using Microsoft.AspNetCore.Components;
using Wonky.Client.OverlayOffice;
using Wonky.Entity.Views;
namespace Wonky.Client.Components;
public partial class OfficeCustomerActivityListComponent
{
[Parameter] public List<ReportItemView> Activities { get; set; } = new();
private OfficeCustomerActivityViewOverlay ActivityViewOverlay { get; set; } = new();
private ReportItemView Activity { get; set; } = new();
private void ShowVisitOverlay(string activityId)
{
Activity = Activities.First(x => x.ActivityId == activityId);
ActivityViewOverlay.Show();
}
}

View file

@ -0,0 +1,82 @@
@*
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
*@
@using Wonky.Client.Models
@using System.ComponentModel.Design
<div class="row">
@if (Inventory.Any())
{
<div class="list-group mt-2">
<div class="list-group-item bg-dark text-white">
<div class="row">
<div class="col-sm-4" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Desc)"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
<div class="col-sm-3" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Sku)"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
<div class="col-sm-2 text-center" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Qty)"><i class="bi-sort-numeric-down"></i> Antal <i class="bi-sort-numeric-up-alt"></i></div>
<div class="col-sm-2"></div>
<div class="col-sm-1"></div>
</div>
</div>
@foreach (var product in Inventory)
{
<div class="list-group-item">
<div class="row align-items-center">
<div class="col-sm-4">
<div class="position-relative">
@product.Description
@if (product.Discontinued)
{
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">Udgået</span>
<span class="visually-hidden">Produktet er udgået</span>
}
</div>
</div>
<div class="col-sm-3">
@product.Sku
</div>
<div class="col-sm-2 text-center">
@product.Quantity
</div>
<div class="col-sm-2">
<a class="btn btn-info d-block" type="button" @onclick="() => CallShowReorderModal(product.Sku)"><i class="bi-cart"></i> Genbestil</a>
</div>
<div class="col-sm-1" @onclick="() => ProductCheck(product.Sku)">
<input type="checkbox" class="btn-check" id="btn-@product.Sku.Replace(",", "")" autocomplete="off"/>
@if (product.Check)
{
<label class="btn btn-success" for="btn-@product.Sku.Replace(",", "")">
<i class="bi-check"></i>
</label>
}
else
{
<label class="btn btn-warning" for="btn-@product.Sku.Replace(",", "")">
<i class="bi-dash"></i>
</label>
}
</div>
</div>
</div>
}
</div>
}
else
{
<div>Ingen data</div>
}
</div>

View file

@ -0,0 +1,86 @@
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components;
using Wonky.Client.Models;
using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Components;
public partial class OfficeCustomerInventoryListComponent
{
[Inject] private ILocalStorageService Storage { get; set; }
// Parameters
[Parameter] public List<ProductInventoryView> Inventory { get; set; } = new();
[Parameter] public string CompanyId { get; set; } = "";
[Parameter] public EventCallback<string> OnReorderSelected { get; set; }
// private variables
private bool Descending { get; set; }
private void SortProducts(PSort column)
{
Descending = !Descending;
switch (column)
{
case PSort.Desc:
if (Descending)
{
Inventory = Inventory.OrderByDescending(x => x.Description).ToList();
break;
}
Inventory = Inventory.OrderBy(x => x.Description).ToList();
break;
case PSort.Sku:
if (Descending)
{
Inventory = Inventory.OrderByDescending(x => x.Sku).ToList();
break;
}
Inventory = Inventory.OrderBy(x => x.Sku).ToList();
break;
case PSort.Qty:
if (Descending)
{
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
break;
}
Inventory = Inventory.OrderBy(x => x.Quantity).ToList();
break;
case PSort.None:
break;
case PSort.Abbr:
break;
default:
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
break;
}
}
private async Task CallShowReorderModal(string sku)
{
await ProductCheck(sku);
await OnReorderSelected.InvokeAsync(sku);
}
private async Task ProductCheck(string sku)
{
var x = Inventory.First(x => x.Sku == sku);
x.Check = !x.Check;
await Storage.SetItemAsync($"{CompanyId}-products", Inventory);
}
}

View file

@ -29,11 +29,9 @@
<i class="bi-activity"></i> Sælgere <i class="bi-activity"></i> Sælgere
</a> </a>
</AuthorizeView> </AuthorizeView>
@*
<a class="list-group-item list-group-item-action list-group-item-success" href="/office/customers/dk"> <a class="list-group-item list-group-item-action list-group-item-success" href="/office/customers/dk">
<i class="bi-building"></i> Tlf.Ordre <i class="bi-building"></i> Tlf.Ordre
</a> </a>
*@
<a class="list-group-item list-group-item-action list-group-item-info" href="/catalog/dk"> <a class="list-group-item list-group-item-action list-group-item-info" href="/catalog/dk">
<i class="bi-file-spreadsheet"></i> Priser <i class="bi-file-spreadsheet"></i> Priser
</a> </a>
@ -52,11 +50,9 @@
<i class="bi-activity"></i> Sælgere <i class="bi-activity"></i> Sælgere
</a> </a>
</AuthorizeView> </AuthorizeView>
@*
<a class="list-group-item list-group-item-action list-group-item-success" href="/office/customers/no"> <a class="list-group-item list-group-item-action list-group-item-success" href="/office/customers/no">
<i class="bi-phone"></i> Tlf.Ordre <i class="bi-phone"></i> Tlf.Ordre
</a> </a>
*@
<a class="list-group-item list-group-item-action list-group-item-info" href="/catalog/no"> <a class="list-group-item list-group-item-action list-group-item-info" href="/catalog/no">
<i class="bi-file-spreadsheet"></i> Priser <i class="bi-file-spreadsheet"></i> Priser
</a> </a>
@ -75,11 +71,9 @@
<i class="bi-activity"></i> Sælgere <i class="bi-activity"></i> Sælgere
</a> </a>
</AuthorizeView> </AuthorizeView>
@*
<a class="list-group-item list-group-item-action list-group-item-success" href="/office/customers/se"> <a class="list-group-item list-group-item-action list-group-item-success" href="/office/customers/se">
<i class="bi-phone"></i> Tlf.Ordre <i class="bi-phone"></i> Tlf.Ordre
</a> </a>
*@
<a class="list-group-item list-group-item-action list-group-item-info" href="/catalog/se"> <a class="list-group-item list-group-item-action list-group-item-info" href="/catalog/se">
<i class="bi-file-spreadsheet"></i> Priser <i class="bi-file-spreadsheet"></i> Priser
</a> </a>

View file

@ -28,9 +28,10 @@ using Wonky.Client.Shared;
using Wonky.Entity.DTO; using Wonky.Entity.DTO;
using Wonky.Entity.Models; using Wonky.Entity.Models;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Components; namespace Wonky.Client.Components;
public partial class LandingComponentOffice public partial class OfficeLandingComponent
{ {
[Inject] private UserProfileService ProfileService { get; set; } [Inject] private UserProfileService ProfileService { get; set; }

View file

@ -15,6 +15,7 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Components; namespace Wonky.Client.Components;

View file

@ -18,6 +18,7 @@
using Blazored.LocalStorage; using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.Services; using Wonky.Client.Services;
#pragma warning disable CS8618
namespace Wonky.Client.Components namespace Wonky.Client.Components
{ {

View file

@ -15,15 +15,15 @@
// //
*@ *@
<i style="font-size:1.3em;" class="bi-@_icon @StateClass"></i> <i style="font-size:1.3em;" class="bi-@Icon @StateClass"></i>
@code{ @code{
[Parameter] public string StateClass { get; set; } = ""; [Parameter] public string StateClass { get; set; } = "";
private string _icon { get; set; } = ""; private string Icon { get; set; } = "";
protected override void OnParametersSet() protected override void OnParametersSet()
{ {
_icon = StateClass switch Icon = StateClass switch
{ {
"the-fast" => "lightning-charge", "the-fast" => "lightning-charge",
"the-good" => "file-earmark", "the-good" => "file-earmark",

View file

@ -15,13 +15,12 @@
using Blazored.Toast.Services; using Blazored.Toast.Services;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Entity.DTO;
using Wonky.Entity.Models;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Components; namespace Wonky.Client.Components;
public partial class CatalogListComponent public partial class ProductPriceListComponent
{ {
[Parameter] public List<SalesItemView> ItemList { get; set; } = new(); [Parameter] public List<SalesItemView> ItemList { get; set; } = new();
[Inject] private IToastService ToastService { get; set; } [Inject] private IToastService ToastService { get; set; }

View file

@ -42,44 +42,56 @@
foreach (var quote in Quotes) foreach (var quote in Quotes)
{ {
<div class="list-group-item list-group-item-action"> <div class="list-group-item list-group-item-action">
<div class="row">
<div class="col-sm-4"> <div class="col-sm-4">
@quote.Company.Name @quote.Company.Name
</div> </div>
<di class="col-sm-2"> <div class="col-sm-2">
@quote.OrderDate @quote.OrderDate
</di> </div>
<div class="col-sm-3"> <div class="col-sm-3">
<button type="button" class="btn btn-outline-dark me-2" @onclick="() => SetQuote(quote.ESalesNumber, QStatus.Lose)"><i class="bi-trash-fill"></i></button> <button type="button" class="btn btn-outline-dark me-2" @onclick="() => SetQuote(quote.ESalesNumber, QStatus.Lose)">
<button type="button" class="btn btn-outline-dark me-2" @onclick="() => SetQuote(quote.ESalesNumber, QStatus.Archive)"><i class="bi-archive-fill"></i></button> <i class="bi-trash-fill"></i>
<button type="button" class="btn btn-outline-dark me-2" @onclick="() => SetQuote(quote.ESalesNumber, QStatus.Note)"><i class="bi-tag-fill"></i></button> </button>
<button type="button" class="btn btn-outline-dark me-2" @onclick="() => SetQuote(quote.ESalesNumber, QStatus.Archive)">
<i class="bi-archive-fill"></i>
</button>
<button type="button" class="btn btn-outline-dark me-2" @onclick="() => SetQuote(quote.ESalesNumber, QStatus.Note)">
<i class="bi-tag-fill"></i>
</button>
@if (quote.QuoteStatusEnum == "None") @if (quote.QuoteStatusEnum == "None")
{ {
<button type="button" class="btn btn-success" @onclick="() => SetQuote(quote.ESalesNumber, QStatus.Win)"><i class="bi-cart-fill"></i></button> <button type="button" class="btn btn-success" @onclick="() => SetQuote(quote.ESalesNumber, QStatus.Win)">
<i class="bi-cart-fill"></i>
</button>
} }
</div> </div>
<div class="col-sm-1 text-center"> <div class="col-sm-1 text-center">
@switch (quote.QuoteStatusEnum) @switch (quote.QuoteStatusEnum)
{ {
case "None": case "None":
<i class="bi-question-circle-fill"style="font-size: 1.2rem"></i> <i class="bi-question-circle-fill" style="font-size: 1.2rem"></i>
break; break;
case "Lose": case "Lose":
<i class="bi-trash-fill"style="font-size: 1.2rem"></i> <i class="bi-trash-fill" style="font-size: 1.2rem"></i>
break; break;
case "Note": case "Note":
<i class="bi-tag-fill"style="font-size: 1.2rem"></i> <i class="bi-tag-fill" style="font-size: 1.2rem"></i>
break; break;
case "Archive": case "Archive":
<i class="bi-archive-fill"style="font-size: 1.2rem"></i> <i class="bi-archive-fill" style="font-size: 1.2rem"></i>
break; break;
default: default:
<i class="bi-question-circle-fill"style="font-size: 1.2rem"></i> <i class="bi-question-circle-fill" style="font-size: 1.2rem"></i>
break; break;
} }
</div> </div>
<div class="col-sm-2 text-center"> <div class="col-sm-2 text-center">
<a class="btn btn-outline-dark d-block" style="font-family:monospace;font-size: 14px;" <a class="btn btn-outline-dark d-block" style="font-family:monospace;font-size: 14px;"
href="/advisor/customers/@quote.Company.CompanyId/quotes/@quote.ActivityId">@quote.ESalesNumber</a> href="/advisor/customers/@quote.Company.CompanyId/quotes/@quote.ActivityId">
@quote.ESalesNumber
</a>
</div> </div>
@if (!string.IsNullOrWhiteSpace(quote.OfficeNote)) @if (!string.IsNullOrWhiteSpace(quote.OfficeNote))
{ {
@ -103,5 +115,4 @@
{ {
<div class="list-group-item">Ingen data</div> <div class="list-group-item">Ingen data</div>
} }
</div> </div>

View file

@ -23,11 +23,11 @@ public partial class QuoteListComponent
{ {
[Parameter] [Parameter]
public List<ReportItemView> Quotes { get; set; } = new(); public List<ReportItemView> Quotes { get; set; } = new();
[Parameter] public EventCallback<QCallbackArgs> OnChangedCallback { get; set; } [Parameter] public EventCallback<QuoteCallbackArgs> OnChangedCallback { get; set; }
private async Task SetQuote(string eSalesNumber, QStatus status) private async Task SetQuote(string eSalesNumber, QStatus status)
{ {
var args = new QCallbackArgs() var args = new QuoteCallbackArgs()
{ {
ESalesNumber = eSalesNumber, ESalesNumber = eSalesNumber,
Status = status Status = status

View file

@ -15,7 +15,7 @@
// //
*@ *@
<EditForm EditContext="_editContext"> <EditForm EditContext="VatAddressContext">
<DataAnnotationsValidator/> <DataAnnotationsValidator/>
<div class="row mb-2"> <div class="row mb-2">
<label for="streetName" class="col-sm-1 col-form-label-sm">Vejnavn</label> <label for="streetName" class="col-sm-1 col-form-label-sm">Vejnavn</label>

View file

@ -17,22 +17,24 @@ using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms; using Microsoft.AspNetCore.Components.Forms;
using Wonky.Client.Models; using Wonky.Client.Models;
#pragma warning disable CS8618
namespace Wonky.Client.Components; namespace Wonky.Client.Components;
public partial class VatAddressInputComponent public partial class VatAddressInputComponent
{ {
[Parameter] public VatAddress Address { get; set; } [Parameter] public VatAddress Address { get; set; } = new();
private EditContext _editContext { get; set; }
private VatAddress _address { get; set; }
[Parameter] public EventCallback<VatAddress> OnValidSubmit { get; set; } [Parameter] public EventCallback<VatAddress> OnValidSubmit { get; set; }
private EditContext VatAddressContext { get; set; }
private VatAddress VatAddress { get; set; } = new();
protected override void OnParametersSet() protected override void OnParametersSet()
{ {
_address = Address; VatAddress = Address;
_editContext = new EditContext(_address); VatAddressContext = new EditContext(VatAddress);
} }
private async Task SubmitForm() private async Task SubmitForm()
{ {
await OnValidSubmit.InvokeAsync(_address); await OnValidSubmit.InvokeAsync(VatAddress);
} }
} }

View file

@ -15,13 +15,13 @@
// //
*@ *@
<EditForm Model="_companyName"> <EditForm Model="ThisCompanyName">
<DataAnnotationsValidator/> <DataAnnotationsValidator/>
<div class="row mb-2"> <div class="row mb-2">
<label for="companyName" class="col-sm-1 col-form-label-sm">Navn</label> <label for="companyName" class="col-sm-1 col-form-label-sm">Navn</label>
<div class="col-sm-9"> <div class="col-sm-9">
<InputText id="companyName" class="form-control" @bind-Value="@_companyName"/> <InputText id="companyName" class="form-control" @bind-Value="@ThisCompanyName"/>
<ValidationMessage For="@(() => _companyName)"/> <ValidationMessage For="@(() => ThisCompanyName)"/>
</div> </div>
<div class="col-sm-2 text-end"> <div class="col-sm-2 text-end">
<button class="btn btn-primary" type="button" @onclick="SubmitForm">HENT</button> <button class="btn btn-primary" type="button" @onclick="SubmitForm">HENT</button>

View file

@ -22,15 +22,15 @@ namespace Wonky.Client.Components;
public partial class VatCompanyNameInputComponent public partial class VatCompanyNameInputComponent
{ {
[Parameter] public string CompanyName { get; set; } = ""; [Parameter] public string CompanyName { get; set; } = "";
[Required(ErrorMessage = "Navn kan ikke være tomt")] private string _companyName { get; set; } = ""; [Required(ErrorMessage = "Navn kan ikke være tomt")] private string ThisCompanyName { get; set; } = "";
[Parameter] public EventCallback<string> OnValidSubmit { get; set; } [Parameter] public EventCallback<string> OnValidSubmit { get; set; }
protected override void OnParametersSet() protected override void OnParametersSet()
{ {
_companyName = CompanyName; ThisCompanyName = CompanyName;
} }
private async Task SubmitForm() private async Task SubmitForm()
{ {
await OnValidSubmit.InvokeAsync(_companyName); await OnValidSubmit.InvokeAsync(ThisCompanyName);
} }
} }

View file

@ -22,7 +22,7 @@ namespace Wonky.Client.Components;
public partial class WarehouseListComponent public partial class WarehouseListComponent
{ {
[Parameter] public string Header { get; set; } = ""; [Parameter] public string Header { get; set; } = "";
[Parameter] public List<WarehouseOrderView>? OrderList { get; set; } [Parameter] public List<WarehouseOrderView> OrderList { get; set; } = new();
[Parameter] public bool ReadyToShip { get; set; } [Parameter] public bool ReadyToShip { get; set; }
[Parameter] public EventCallback<PStatus> OnGetStatus { get; set; } [Parameter] public EventCallback<PStatus> OnGetStatus { get; set; }
[Parameter] public EventCallback OnSetShipped { get; set; } [Parameter] public EventCallback OnSetShipped { get; set; }

View file

@ -19,6 +19,7 @@ using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms; using Microsoft.AspNetCore.Components.Forms;
using Wonky.Client.Services; using Wonky.Client.Services;
#pragma warning disable CS8618
namespace Wonky.Client.Components; namespace Wonky.Client.Components;
@ -27,14 +28,12 @@ public partial class WorkDateComponent : IDisposable
/// <summary> /// <summary>
/// User preference service /// User preference service
/// </summary> /// </summary>
[Inject] [Inject] public UserProfileService Profiles { get; set; }
public UserProfileService Profiles { get; set; }
/// <summary> /// <summary>
/// OnChanged callback function /// OnChanged callback function
/// </summary> /// </summary>
[Parameter] [Parameter] public EventCallback<string> OnChangedCallback { get; set; }
public EventCallback<string> OnChangedCallback { get; set; }
/// <summary> /// <summary>
/// work date context holding the edit value /// work date context holding the edit value
@ -49,7 +48,7 @@ public partial class WorkDateComponent : IDisposable
/// <summary> /// <summary>
/// user preferences /// user preferences
/// </summary> /// </summary>
private UserProfile _profiles = new(); private UserProfile Profile { get; set; } = new();
/// <summary> /// <summary>
/// Component Initialization /// Component Initialization
@ -58,10 +57,10 @@ public partial class WorkDateComponent : IDisposable
{ {
WorkDateContext = new EditContext(SelectedDate); WorkDateContext = new EditContext(SelectedDate);
Profiles.OnChange += ProfileServiceOnOnChange; Profiles.OnChange += ProfileServiceOnOnChange;
_profiles = await Profiles.GetPreferences(); Profile = await Profiles.GetPreferences();
SelectedDate = string.IsNullOrWhiteSpace(_profiles.WorkDate) SelectedDate = string.IsNullOrWhiteSpace(Profile.WorkDate)
? DateTime.Now ? DateTime.Now
: DateTime.Parse(_profiles.WorkDate); : DateTime.Parse(Profile.WorkDate);
} }
/// <summary> /// <summary>
@ -84,7 +83,7 @@ public partial class WorkDateComponent : IDisposable
/// <param name="newUserProfile"></param> /// <param name="newUserProfile"></param>
private void ProfileServiceOnOnChange(UserProfile newUserProfile) private void ProfileServiceOnOnChange(UserProfile newUserProfile)
{ {
_profiles = newUserProfile; Profile = newUserProfile;
StateHasChanged(); StateHasChanged();
} }

View file

@ -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 // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as // it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the // published by the Free Software Foundation, either version 3 of the
@ -23,6 +22,35 @@ namespace Wonky.Client.Helpers;
/// </summary> /// </summary>
public static class Utils public static class Utils
{ {
/// <summary>
/// validate password to contain a-z and A-Z and 0-9
/// </summary>
/// <param name="toValidate"></param>
/// <returns></returns>
public static bool ValidatePasswd(string toValidate, int length)
{
if (toValidate.Length < length)
return false;
var validConditions = 0;
if (toValidate.Any(c => c is >= 'a' and <= 'z'))
{
validConditions++;
}
if (toValidate.Any(c => c is >= 'A' and <= 'Z'))
{
validConditions++;
}
if (toValidate.Any(c => c is >= '0' and <= '9'))
{
validConditions++;
}
return validConditions == 3;
}
/// <summary> /// <summary>
/// return Country Name from countryCode /// return Country Name from countryCode
/// </summary> /// </summary>

View file

@ -0,0 +1,40 @@
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
namespace Wonky.Client.HttpInterfaces;
/// <summary>
/// Interface Activity CRM Http repository
/// </summary>
public interface ICountryActivityRepository
{
/// <summary>
/// Get activity data by id
/// </summary>
/// <param name="activityId"></param>
/// <returns></returns>
Task<ActivityDto> GetActivity(string activityId);
/// <summary>
/// Get activities for customer Id
/// </summary>
/// <param name="customerId"></param>
/// <returns></returns>
Task<List<ReportItemView>> GetCustomerActivities(string customerId);
}

View file

@ -28,43 +28,36 @@ public interface ISystemUserRepository
/// Get Advisors (Office) /// Get Advisors (Office)
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
Task<List<UserManagerListView>> GetAdvisors(); Task<List<UserManagerListView>> GetUsers();
/// <summary> /// <summary>
/// Get Advisor Info for given userId /// Get Advisor Info for given userId
/// </summary> /// </summary>
/// <param name="userId"></param> /// <param name="userId"></param>
/// <returns></returns> /// <returns></returns>
Task<WebUserInfoView> GetAdvisorInfo(string userId); Task<UserManagerEditView> GetUserInfo(string userId);
/// <summary>
/// Update Advisor using userId and updated data
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
Task<UserManagerEditView> CreateUser(UserManagerEditView model);
/// <summary> /// <summary>
/// Update Advisor using userId and updated data /// Update Advisor using userId and updated data
/// </summary> /// </summary>
/// <param name="userId"></param> /// <param name="userId"></param>
/// <param name="model"></param> /// <param name="model"></param>
/// <returns></returns> /// <returns></returns>
Task UpdateAdvisor(string userId, UserUpdateDto model); Task UpdateUserInfo(string userId, UserManagerEditView model);
/// <summary> /// <summary>
/// Get Administrative Users /// Delete the user with id
/// </summary>
/// <returns></returns>
Task<List<UserManagerListView>> GetAdminUsers();
/// <summary>
/// Get Admin Info for giver userId
/// </summary> /// </summary>
/// <param name="userId"></param> /// <param name="userId"></param>
/// <returns></returns> /// <returns></returns>
Task<UserInfoDto> GetAdminUserInfo(string userId); Task DeleteUser(string userId);
/// <summary>
/// Update Admin user using userId and updated data
/// </summary>
/// <param name="userId"></param>
/// <param name="model"></param>
/// <returns></returns>
Task UpdateAdminUser(string userId, UserUpdateDto model);
/// <summary> /// <summary>
/// Set new user password /// Set new user password

View file

@ -0,0 +1,77 @@
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
namespace Wonky.Client.HttpInterfaces;
/// <summary>
/// Interface for User handling over http
/// </summary>
public interface ISystemUserRepositoryGen1
{
/// <summary>
/// Get Advisors (Office)
/// </summary>
/// <returns></returns>
Task<List<UserManagerListView>> GetUsers();
/// <summary>
/// Get Advisor Info for given userId
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
Task<WebUserInfoView> GetAdvisorInfo(string userId);
/// <summary>
/// Update Advisor using userId and updated data
/// </summary>
/// <param name="userId"></param>
/// <param name="model"></param>
/// <returns></returns>
Task UpdateAdvisor(string userId, UserUpdateDto model);
/// <summary>
/// Get Administrative Users
/// </summary>
/// <returns></returns>
Task<List<UserManagerListView>> GetAdminUsers();
/// <summary>
/// Get Admin Info for giver userId
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
Task<UserInfoDto> GetAdminUserInfo(string userId);
/// <summary>
/// Update Admin user using userId and updated data
/// </summary>
/// <param name="userId"></param>
/// <param name="model"></param>
/// <returns></returns>
Task UpdateAdminUser(string userId, UserUpdateDto model);
/// <summary>
/// Set new user password
/// </summary>
/// <param name="userId"></param>
/// <param name="newPasswd"></param>
/// <param name="confirmPasswd"></param>
/// <returns></returns>
Task ResetUserPassword(string userId, string newPasswd, string confirmPasswd);
}

View file

@ -0,0 +1,80 @@
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using System.Net.Http.Json;
using System.Text.Json;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Options;
using Wonky.Client.HttpInterfaces;
using Wonky.Entity.Configuration;
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
namespace Wonky.Client.HttpRepository;
/// <summary>
/// Implementing Interface Activity CRM Http repository
/// </summary>
public class CountryActivityRepository : ICountryActivityRepository
{
private readonly JsonSerializerOptions? _options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
private readonly NavigationManager _navigation;
private readonly ILogger<CountryActivityRepository> _logger;
private readonly HttpClient _client;
private readonly ApiConfig _api;
public CountryActivityRepository(HttpClient client,
ILogger<CountryActivityRepository> logger,
NavigationManager navigation, IOptions<ApiConfig> configuration)
{
_client = client;
_logger = logger;
_navigation = navigation;
_api = configuration.Value;
}
/// <summary>
/// Get activity data by id
/// </summary>
/// <param name="activityId"></param>
/// <returns></returns>
public async Task<ActivityDto> GetActivity(string activityId)
{
var activity = await _client
.GetFromJsonAsync<ActivityDto>($"{_api.CrmActivities}/{activityId}");
return activity ?? new ActivityDto();
}
/// <summary>
/// Get activities for customer Id
/// </summary>
/// <param name="customerId"></param>
/// <returns></returns>
public async Task<List<ReportItemView>> GetCustomerActivities(string customerId)
{
var response = await _client.GetAsync($"{_api.CrmActivities}/company/{customerId}");
var content = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
return new List<ReportItemView>();
return string.IsNullOrWhiteSpace(content)
? new List<ReportItemView>()
: JsonSerializer.Deserialize<List<ReportItemView>>(content, _options);
}
}

View file

@ -73,13 +73,20 @@ public class CountryCustomerHistoryRepository : ICountryCustomerHistoryRepositor
/// <returns></returns> /// <returns></returns>
public async Task<InvoiceView> FetchInvoice(string countryCode, string companyId, string invoiceId) public async Task<InvoiceView> FetchInvoice(string countryCode, string companyId, string invoiceId)
{ {
return await _client var response = await _client
.GetFromJsonAsync<InvoiceView>($"{_api.OfficeCustomers}/{countryCode}/{companyId}/invoices/{invoiceId}", _options); .GetAsync($"{_api.OfficeCustomers}/{countryCode}/{companyId}/invoices/{invoiceId}");
if (!response.IsSuccessStatusCode) return new InvoiceView();
var content = await response.Content.ReadAsStringAsync();
return response.IsSuccessStatusCode
? JsonSerializer.Deserialize<InvoiceView>(content, _options)
: new InvoiceView();
} }
/// <summary> /// <summary>
/// Fetch inventory from given customer /// Fetch inventory from given customer
/// </summary> /// </summary>
/// <param name="countryCode"></param>
/// <param name="companyId"></param> /// <param name="companyId"></param>
/// <returns></returns> /// <returns></returns>
public async Task<List<ProductInventoryView>> FetchInventory(string countryCode, string companyId) public async Task<List<ProductInventoryView>> FetchInventory(string countryCode, string companyId)
@ -92,10 +99,11 @@ public class CountryCustomerHistoryRepository : ICountryCustomerHistoryRepositor
? new List<ProductInventoryView>() ? new List<ProductInventoryView>()
: JsonSerializer.Deserialize<List<ProductInventoryView>>(content, _options); : JsonSerializer.Deserialize<List<ProductInventoryView>>(content, _options);
} }
/// <summary> /// <summary>
/// Fetch History for given customer /// Fetch History for given customer
/// </summary> /// </summary>
/// <param name="countryCode"></param>
/// <param name="companyId"></param> /// <param name="companyId"></param>
/// <returns></returns> /// <returns></returns>
public async Task<List<ProductHistoryView>> FetchHistory(string countryCode, string companyId) public async Task<List<ProductHistoryView>> FetchHistory(string countryCode, string companyId)
@ -113,6 +121,7 @@ public class CountryCustomerHistoryRepository : ICountryCustomerHistoryRepositor
/// <summary> /// <summary>
/// Fetch history for given customer and a given product /// Fetch history for given customer and a given product
/// </summary> /// </summary>
/// <param name="countryCode"></param>
/// <param name="companyId"></param> /// <param name="companyId"></param>
/// <param name="sku"></param> /// <param name="sku"></param>
/// <returns></returns> /// <returns></returns>
@ -130,6 +139,7 @@ public class CountryCustomerHistoryRepository : ICountryCustomerHistoryRepositor
/// <summary> /// <summary>
/// RPC call to initiate remote server sync for given customer /// RPC call to initiate remote server sync for given customer
/// </summary> /// </summary>
/// <param name="countryCode"></param>
/// <param name="companyId"></param> /// <param name="companyId"></param>
/// <param name="syncDate"></param> /// <param name="syncDate"></param>
/// <returns></returns> /// <returns></returns>

View file

@ -50,60 +50,58 @@ public class SystemUserRepository : ISystemUserRepository
/// Get Advisors (Office) /// Get Advisors (Office)
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public async Task<List<UserManagerListView>> GetAdvisors() public async Task<List<UserManagerListView>> GetUsers()
{ {
return await _client.GetFromJsonAsync<List<UserManagerListView>>(_api.OfficeAdvisors); return await _client.GetFromJsonAsync<List<UserManagerListView>>(_api.UserManager);
} }
/// <summary> /// <summary>
/// Get Advisor Info for given userId /// Get Advisor Info for given userId
/// </summary> /// </summary>
/// <param name="userId"></param> /// <param name="userId"></param>
/// <returns></returns> /// <returns></returns>
public async Task<WebUserInfoView> GetAdvisorInfo(string userId) public async Task<UserManagerEditView> GetUserInfo(string userId)
{ {
return await _client.GetFromJsonAsync<WebUserInfoView>($"{_api.OfficeAdvisors}/{userId}"); return await _client.GetFromJsonAsync<UserManagerEditView>($"{_api.UserManager}/{userId}");
} }
/// <summary>
/// Update Advisor using userId and updated data
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public async Task<UserManagerEditView> CreateUser(UserManagerEditView model)
{
var result = await _client.PostAsJsonAsync($"{_api.UserManager}", model, _options);
if (!result.IsSuccessStatusCode)
return new UserManagerEditView();
try
{
return await result.Content.ReadFromJsonAsync<UserManagerEditView>();
}
catch
{
return new UserManagerEditView();
}
}
/// <summary> /// <summary>
/// Update Advisor using userId and updated data /// Update Advisor using userId and updated data
/// </summary> /// </summary>
/// <param name="userId"></param> /// <param name="userId"></param>
/// <param name="model"></param> /// <param name="model"></param>
/// <returns></returns> /// <returns></returns>
public async Task UpdateAdvisor(string userId, UserUpdateDto model) public async Task UpdateUserInfo(string userId, UserManagerEditView model)
{ {
await _client.PutAsJsonAsync($"{_api.OfficeAdvisors}/{userId}", model, _options); await _client.PutAsJsonAsync($"{_api.UserManager}/{userId}", model, _options);
} }
/// <summary> /// <summary>
/// Get Administrative Users
/// </summary>
/// <returns></returns>
public async Task<List<UserManagerListView>> GetAdminUsers()
{
return await _client.GetFromJsonAsync<List<UserManagerListView>>(_api.OfficeUsers);
}
/// <summary>
/// Get Admin Info for giver userId
/// </summary> /// </summary>
/// <param name="userId"></param> /// <param name="userId"></param>
/// <returns></returns> public async Task DeleteUser(string userId)
public async Task<UserInfoDto> GetAdminUserInfo(string userId)
{ {
return await _client.GetFromJsonAsync<UserInfoDto>($"{_api.OfficeUsers}/{userId}"); await _client.DeleteAsync($"{_api.UserManager}/{userId}");
}
/// <summary>
/// Update Admin user using userId and updated data
/// </summary>
/// <param name="userId"></param>
/// <param name="model"></param>
/// <returns></returns>
public async Task UpdateAdminUser(string userId, UserUpdateDto model)
{
await _client.PutAsJsonAsync($"{_api.OfficeUsers}/{userId}", model, _options);
} }
/// <summary> /// <summary>
@ -117,6 +115,6 @@ public class SystemUserRepository : ISystemUserRepository
{ {
var passwd = new Dictionary<string, string> var passwd = new Dictionary<string, string>
{ { "newPassword", newPasswd }, { "confirmPassword", confirmPasswd } }; { { "newPassword", newPasswd }, { "confirmPassword", confirmPasswd } };
await _client.PostAsJsonAsync($"{_api.OfficeUserPasswd}/{userId}", passwd, _options); await _client.PostAsJsonAsync($"{_api.UserManager}/passwd/{userId}", passwd, _options);
} }
} }

View file

@ -0,0 +1,122 @@
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using System.Net.Http.Json;
using System.Text.Json;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Options;
using Wonky.Client.HttpInterfaces;
using Wonky.Entity.Configuration;
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
namespace Wonky.Client.HttpRepository;
public class SystemUserRepositoryGen1 : ISystemUserRepositoryGen1
{
private readonly JsonSerializerOptions? _options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
private readonly NavigationManager _navigation;
private ILogger<SystemUserRepositoryGen1> _logger;
private readonly HttpClient _client;
private readonly ApiConfig _api;
public SystemUserRepositoryGen1(HttpClient client, ILogger<SystemUserRepositoryGen1> logger,
NavigationManager navigation, IOptions<ApiConfig> configuration)
{
_client = client;
_logger = logger;
_navigation = navigation;
_api = configuration.Value;
}
/// <summary>
/// Get Advisors (Office)
/// </summary>
/// <returns></returns>
public async Task<List<UserManagerListView>> GetUsers()
{
return await _client.GetFromJsonAsync<List<UserManagerListView>>(_api.OfficeAdvisors);
}
/// <summary>
/// Get Advisor Info for given userId
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public async Task<WebUserInfoView> GetAdvisorInfo(string userId)
{
return await _client.GetFromJsonAsync<WebUserInfoView>($"{_api.OfficeAdvisors}/{userId}");
}
/// <summary>
/// Update Advisor using userId and updated data
/// </summary>
/// <param name="userId"></param>
/// <param name="model"></param>
/// <returns></returns>
public async Task UpdateAdvisor(string userId, UserUpdateDto model)
{
await _client.PutAsJsonAsync($"{_api.OfficeAdvisors}/{userId}", model, _options);
}
/// <summary>
/// Get Administrative Users
/// </summary>
/// <returns></returns>
public async Task<List<UserManagerListView>> GetAdminUsers()
{
return await _client.GetFromJsonAsync<List<UserManagerListView>>(_api.OfficeUsers);
}
/// <summary>
/// Get Admin Info for giver userId
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public async Task<UserInfoDto> GetAdminUserInfo(string userId)
{
return await _client.GetFromJsonAsync<UserInfoDto>($"{_api.OfficeUsers}/{userId}");
}
/// <summary>
/// Update Admin user using userId and updated data
/// </summary>
/// <param name="userId"></param>
/// <param name="model"></param>
/// <returns></returns>
public async Task UpdateAdminUser(string userId, UserUpdateDto model)
{
await _client.PutAsJsonAsync($"{_api.OfficeUsers}/{userId}", model, _options);
}
/// <summary>
/// Set new user password
/// </summary>
/// <param name="userId"></param>
/// <param name="newPasswd"></param>
/// <param name="confirmPasswd"></param>
/// <returns></returns>
public async Task ResetUserPassword(string userId, string newPasswd, string confirmPasswd)
{
var passwd = new Dictionary<string, string>
{ { "newPassword", newPasswd }, { "confirmPassword", confirmPasswd } };
await _client.PostAsJsonAsync($"{_api.UserManagerSetPasswd}/{userId}", passwd, _options);
}
}

View file

@ -16,7 +16,7 @@
namespace Wonky.Client.Models; namespace Wonky.Client.Models;
public class QCallbackArgs public class QuoteCallbackArgs
{ {
/// <summary> /// <summary>
/// ESalesNumber /// ESalesNumber

View file

@ -15,7 +15,6 @@
// //
*@ *@
@using Wonky.Client.Components @using Wonky.Client.Components
<div class="modal" tabindex="-1" role="dialog" style="display:@_modalDisplay"> <div class="modal" tabindex="-1" role="dialog" style="display:@_modalDisplay">
<div class="modal-dialog modal-dialog-scrollable modal-fullscreen"> <div class="modal-dialog modal-dialog-scrollable modal-fullscreen">
<div class="modal-content"> <div class="modal-content">
@ -24,7 +23,7 @@
<button type="button" class="btn-close" @onclick="Hide" data-bs-dismiss="modal" aria-label="Luk"></button> <button type="button" class="btn-close" @onclick="Hide" data-bs-dismiss="modal" aria-label="Luk"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<CustomerVisitListComponent Activities="Activities"/> <CustomerActivityListComponent Activities="Activities"/>
</div> </div>
</div> </div>
</div> </div>

View file

@ -14,18 +14,12 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// //
using System.Text.Json;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces;
using Wonky.Client.Models;
using Wonky.Client.Shared;
using Wonky.Entity.DTO;
using Wonky.Entity.Views; using Wonky.Entity.Views;
namespace Wonky.Client.Shared; namespace Wonky.Client.OverlayCustomer;
public partial class CustomerActivityListModalOverlay public partial class CustomerActivityListOverlay
{ {
[Parameter] public string CompanyName { get; set; } = ""; [Parameter] public string CompanyName { get; set; } = "";
[Parameter] public List<ReportItemView> Activities { get; set; } = new(); [Parameter] public List<ReportItemView> Activities { get; set; } = new();

View file

@ -14,19 +14,12 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// //
using System.Text.Json;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces;
using Wonky.Client.HttpRepository;
using Wonky.Client.Models;
using Wonky.Client.Services;
using Wonky.Entity.Requests;
using Wonky.Entity.Views; using Wonky.Entity.Views;
namespace Wonky.Client.Shared; namespace Wonky.Client.OverlayCustomer;
public partial class CustomerActivityViewModalOverlay public partial class CustomerActivityViewOverlay
{ {
[Parameter] public ReportItemView ReportItem { get; set; } = new(); [Parameter] public ReportItemView ReportItem { get; set; } = new();
private string _modalDisplay = ""; private string _modalDisplay = "";

View file

@ -33,4 +33,5 @@
{ {
<div class="modal-backdrop fade show"></div> <div class="modal-backdrop fade show"></div>
} }
<CustomerInventoryReorderModalOverlay CompanyId="@CompanyId" SalesItem="SalesItem" OnSelected="OnInventorySelected" @ref="CustomerInventoryReorderOverlay" />
<CustomerInventoryReorderOverlay CompanyId="@CompanyId" SalesItem="SalesItem" OnSelected="OnInventorySelected" @ref="ReorderOverlay" />

View file

@ -0,0 +1,86 @@
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces;
using Wonky.Client.Models;
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.OverlayCustomer;
public partial class CustomerInventoryListOverlay : IDisposable
{
[Inject] private HttpInterceptorService Interceptor { get; set; }
[Inject] private ICountryCatalogRepository CatalogRepo { get; set; }
[Inject] private ILogger<CustomerInventoryListOverlay> Logger { get; set; }
[Parameter] public string CompanyName { get; set; } = "";
[Parameter] public string CompanyId { get; set; } = "";
[Parameter] public string CountryCode { get; set; } = "";
[Parameter] public List<ProductInventoryView> Inventory { get; set; } = new();
[Parameter] public EventCallback<DraftItem> OnInventorySelected { get; set; }
private string _modalDisplay = "";
private bool _showBackdrop;
private CompanyDto Company { get; set; } = new();
private List<ProductInventoryView> ProductList { get; set; } = new();
private DraftItem DraftItem { get; set; } = new();
private SalesItemView SalesItem { get; set; } = new();
private CustomerInventoryReorderOverlay ReorderOverlay { get; set; } = new();
protected override void OnInitialized()
{
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
StateHasChanged();
}
private async Task OnReorderCallback(string sku)
{
SalesItem = await CatalogRepo.GetSalesItemSku(CountryCode.ToLower(), sku);
ReorderOverlay.Show();
}
private async Task OnSelectedItem(DraftItem draftItem)
{
await OnInventorySelected.InvokeAsync(draftItem);
Hide();
}
public void Show()
{
_modalDisplay = "block;";
_showBackdrop = true;
StateHasChanged();
}
private void Hide()
{
_modalDisplay = "none;";
_showBackdrop = false;
StateHasChanged();
}
public void Dispose()
{
Interceptor.DisposeEvent();
}
}

View file

@ -16,17 +16,14 @@
using System.Globalization; using System.Globalization;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces; using Wonky.Client.HttpInterfaces;
using Wonky.Client.HttpRepository;
using Wonky.Client.Models; using Wonky.Client.Models;
using Wonky.Client.Services;
using Wonky.Entity.Requests;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Shared; namespace Wonky.Client.OverlayCustomer;
public partial class CustomerInventoryReorderModalOverlay public partial class CustomerInventoryReorderOverlay
{ {
[Parameter] public string CompanyId { get; set; } = ""; [Parameter] public string CompanyId { get; set; } = "";
[Parameter] public SalesItemView SalesItem { get; set; } = new(); [Parameter] public SalesItemView SalesItem { get; set; } = new();

View file

@ -32,7 +32,6 @@
</div> </div>
</div> </div>
<CustomerInvoiceListComponent OnShowInvoice="@CallInvoiceModal" CompanyId="@Company.CompanyId" InvoiceList="@Invoices"/> <CustomerInvoiceListComponent OnShowInvoice="@CallInvoiceModal" CompanyId="@Company.CompanyId" InvoiceList="@Invoices"/>
<CustomerInvoiceViewModalOverlay CompanyId="@Company.CompanyId" InvoiceId="@InvoiceId" @ref="CustomerInvoiceView" />
</div> </div>
</div> </div>
</div> </div>
@ -40,4 +39,6 @@
@if (_showBackdrop) @if (_showBackdrop)
{ {
<div class="modal-backdrop fade show"></div> <div class="modal-backdrop fade show"></div>
} }
<CustomerInvoiceViewOverlay CompanyId="@Company.CompanyId" InvoiceId="@InvoiceId" @ref="CustomerInvoiceView" />

View file

@ -16,17 +16,17 @@
using System.Text.Json; using System.Text.Json;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Entity.DTO;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Shared; namespace Wonky.Client.OverlayCustomer;
public partial class CustomerInvoiceListModalOverlay public partial class CustomerInvoiceListOverlay
{ {
[Parameter] public InvoiceListView CustomerInvoices { get; set; } = new(); [Parameter] public InvoiceListView CustomerInvoices { get; set; } = new();
[Inject] private ILogger<CustomerInvoiceListModalOverlay> Logger { get; set; } [Inject] private ILogger<CustomerInvoiceListOverlay> Logger { get; set; }
private CustomerInvoiceViewModalOverlay CustomerInvoiceView { get; set; } = new(); private CustomerInvoiceViewOverlay CustomerInvoiceView { get; set; } = new();
private string InvoiceId { get; set; } = ""; private string InvoiceId { get; set; } = "";
private string _modalDisplay = ""; private string _modalDisplay = "";
private bool _showBackdrop; private bool _showBackdrop;

View file

@ -14,19 +14,15 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// //
using System.Text.Json;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors; using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces; using Wonky.Client.HttpInterfaces;
using Wonky.Client.HttpRepository;
using Wonky.Client.Models;
using Wonky.Client.Services;
using Wonky.Entity.Requests;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Shared; namespace Wonky.Client.OverlayCustomer;
public partial class CustomerInvoiceViewModalOverlay : IDisposable public partial class CustomerInvoiceViewOverlay : IDisposable
{ {
[Parameter] public string CompanyId { get; set; } = ""; [Parameter] public string CompanyId { get; set; } = "";
[Parameter] public string InvoiceId { get; set; } = ""; [Parameter] public string InvoiceId { get; set; } = "";

View file

@ -0,0 +1,36 @@
@*
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
*@
@using Wonky.Client.Components
<div class="modal" tabindex="-1" role="dialog" style="display:@_modalDisplay">
<div class="modal-dialog modal-dialog-scrollable modal-fullscreen">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">@Company.Name - Aktivitet oversigt</h3>
<button type="button" class="btn-close" @onclick="Hide" data-bs-dismiss="modal" aria-label="Luk"></button>
</div>
<div class="modal-body">
@* activity list *@
<OfficeCustomerActivityListComponent Activities="Activities"/>
</div>
</div>
</div>
</div>
@if (_showBackdrop)
{
<div class="modal-backdrop fade show"></div>
}

View file

@ -0,0 +1,44 @@
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using Microsoft.AspNetCore.Components;
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
namespace Wonky.Client.OverlayOffice;
public partial class OfficeCustomerActivityListOverlay
{
[Parameter] public CompanyDto Company { get; set; } = new();
[Parameter] public List<ReportItemView> Activities { get; set; } = new();
private string _modalDisplay = "";
private bool _showBackdrop;
public void Show()
{
_modalDisplay = "block;";
_showBackdrop = true;
StateHasChanged();
}
private void Hide()
{
_modalDisplay = "none;";
_showBackdrop = false;
StateHasChanged();
}
}

View file

@ -0,0 +1,109 @@
@*
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
*@
<div class="modal" tabindex="-1" role="dialog" style="display:@_modalDisplay">
<div class="modal-dialog modal-dialog-scrollable modal-fullscreen">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="btn-close" @onclick="Hide" data-bs-dismiss="modal" aria-label="Luk"></button>
</div>
<div class="modal-body">
<div class="card">
<div class="card-body">
<div class="card-title mb-2">
<h3>Besøg - @Activity.Company.Name</h3>
</div>
<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="@Activity.CreateTimestamp" readonly/>
</div>
<label for="account" class="col-form-label-sm col-sm-1">Konto</label>
<div class="col-sm-3">
<input id="account" class="form-control" type="text" value="@Activity.Company.Account" readonly/>
</div>
<label for="vatNumber" class="col-form-label-sm col-sm-1">Cvr Org</label>
<div class="col-sm-3">
<input id="vatNumber" class="form-control" type="text" value="@Activity.Company.VatNumber" readonly/>
</div>
<label for="eSalesNumber" class="col-form-label-sm col-sm-1">EOrdre</label>
<div class="col-sm-3">
<input id="eSalesNumber" class="form-control" type="text" value="@Activity.ESalesNumber" readonly/>
</div>
<label for="ourRef" class="col-form-label-sm col-sm-1">Vor Ref.</label>
<div class="col-sm-3">
<input id="ourRef" class="form-control" type="text" value="@Activity.OurRef" readonly/>
</div>
<hr/>
<label for="referenceNumber" class="col-form-label-sm col-sm-1">Rekv.</label>
<div class="col-sm-3">
<input id="referenceNumber" class="form-control" type="text" value="@Activity.ReferenceNumber" readonly/>
</div>
<label for="yourRef" class="col-form-label-sm col-sm-1">Kunde Ref.</label>
<div class="col-sm-7">
<input id="yourRef" class="form-control" type="text" value="@Activity.YourRef" readonly/>
</div>
<label for="officeNote" class="col-form-label-sm col-sm-1">Ordre Note</label>
<div class="col-sm-5">
<textarea id="officeNote" class="form-control" value="@Activity.OfficeNote" readonly=""/>
</div>
<label for="crmNote" class="col-form-label-sm col-sm-1">Crm Note</label>
<div class="col-sm-5">
<textarea id="crmNote" class="form-control" value="@Activity.CrmNote" readonly=""/>
</div>
<hr/>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Varenr</th>
<th scope="col">Beskrivelse</th>
<th class="text-end" scope="col">Antal</th>
<th class="text-end" scope="col">Pris</th>
<th class="text-end" scope="col">Rabat</th>
</tr>
</thead>
<tbody>
@foreach (var line in Activity.Lines)
{
<tr>
<td>@line.Sku</td>
<td>@line.Description</td>
<td class="text-end">@line.Quantity</td>
<td class="text-end">@line.Price</td>
<td class="text-end">@line.Discount</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@if (_showBackdrop)
{
<div class="modal-backdrop fade show"></div>
}

View file

@ -0,0 +1,42 @@
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using Microsoft.AspNetCore.Components;
using Wonky.Entity.Views;
namespace Wonky.Client.OverlayOffice;
public partial class OfficeCustomerActivityViewOverlay
{
[Parameter] public ReportItemView Activity { get; set; } = new();
private string _modalDisplay = "";
private bool _showBackdrop;
public void Show()
{
_modalDisplay = "block;";
_showBackdrop = true;
StateHasChanged();
}
private void Hide()
{
_modalDisplay = "none;";
_showBackdrop = false;
StateHasChanged();
}
}

View file

@ -0,0 +1,38 @@
@*
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
*@
@using Wonky.Client.Components
<div class="modal" tabindex="-1" role="dialog" style="display:@_modalDisplay">
<div class="modal-dialog modal-dialog-scrollable modal-fullscreen">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">@CompanyName - Produktoversigt</h3>
<button type="button" class="btn-close" @onclick="Hide" data-bs-dismiss="modal" aria-label="Luk"></button>
</div>
<div class="modal-body">
@* product list *@
<OfficeCustomerInventoryListComponent OnReorderSelected="OnReorderCallback" CompanyId="@CompanyId" Inventory="@Inventory"/>
</div>
</div>
</div>
</div>
@if (_showBackdrop)
{
<div class="modal-backdrop fade show"></div>
}
@* reorder overlay *@
<OfficeCustomerInventoryReorderOverlay CompanyId="@CompanyId" SalesItem="SalesItem" OnSelected="OnInventorySelected" @ref="ReorderOverlay" />

View file

@ -1,4 +1,3 @@
// 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 // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as // it under the terms of the GNU Affero General Public License as
@ -14,37 +13,37 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// //
using System.Text.Json;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors; using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces; using Wonky.Client.HttpInterfaces;
using Wonky.Client.Models; using Wonky.Client.Models;
using Wonky.Client.Shared;
using Wonky.Entity.DTO; using Wonky.Entity.DTO;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Shared; namespace Wonky.Client.OverlayOffice;
public partial class CustomerInventoryListModalOverlay : IDisposable public partial class OfficeCustomerInventoryListOverlay : IDisposable
{ {
[Inject] private HttpInterceptorService Interceptor { get; set; } [Inject] private HttpInterceptorService Interceptor { get; set; }
[Inject] private ICountryCatalogRepository Catalog { get; set; } [Inject] private ICountryCatalogRepository CatalogRepo { get; set; }
[Inject] private ILogger<CustomerInventoryListModalOverlay> Logger { get; set; } [Inject] private ILogger<OfficeCustomerInventoryListOverlay> Logger { get; set; }
[Parameter] public string CompanyName { get; set; } = ""; [Parameter] public string CompanyName { get; set; } = "";
[Parameter] public string CompanyId { get; set; } = ""; [Parameter] public string CompanyId { get; set; } = "";
[Parameter] public string CountryCode { get; set; } = ""; [Parameter] public string CountryCode { get; set; } = "";
[Parameter] public List<ProductInventoryView> Inventory { get; set; } = new(); [Parameter] public List<ProductInventoryView> Inventory { get; set; } = new();
[Parameter] public EventCallback<DraftItem> OnInventorySelected { get; set; } [Parameter] public EventCallback<DraftItem> OnInventorySelected { get; set; }
private string _modalDisplay = ""; private string _modalDisplay = "";
private bool _showBackdrop; private bool _showBackdrop;
private CompanyDto _company { get; set; } = new(); private CompanyDto _company { get; set; } = new();
private List<ProductInventoryView> _inventory { get; set; } = new(); private List<ProductInventoryView> _inventory { get; set; } = new();
private DraftItem DraftItem { get; set; } = new(); private DraftItem DraftItem { get; set; } = new();
private SalesItemView SalesItem { get; set; } = new(); private SalesItemView SalesItem { get; set; } = new();
private CustomerInventoryReorderModalOverlay CustomerInventoryReorderOverlay { get; set; } = new(); private OfficeCustomerInventoryReorderOverlay ReorderOverlay { get; set; } = new();
protected override void OnInitialized() protected override void OnInitialized()
{ {
@ -52,36 +51,35 @@ public partial class CustomerInventoryListModalOverlay : IDisposable
Interceptor.RegisterBeforeSendEvent(); Interceptor.RegisterBeforeSendEvent();
StateHasChanged(); StateHasChanged();
} }
private async Task OnReorderCallback(string sku) private async Task OnReorderCallback(string sku)
{ {
SalesItem = await Catalog.GetSalesItemSku(CountryCode.ToLower(), sku); SalesItem = await CatalogRepo.GetSalesItemSku(CountryCode.ToLower(), sku);
CustomerInventoryReorderOverlay.Show(); ReorderOverlay.Show();
} }
private async Task OnSelectedItem(DraftItem draftItem) private async Task OnSelectedItem(DraftItem draftItem)
{ {
await OnInventorySelected.InvokeAsync(draftItem); await OnInventorySelected.InvokeAsync(draftItem);
Hide(); Hide();
} }
public void Show() public void Show()
{ {
_modalDisplay = "block;"; _modalDisplay = "block;";
_showBackdrop = true; _showBackdrop = true;
StateHasChanged(); StateHasChanged();
} }
private void Hide() private void Hide()
{ {
_modalDisplay = "none;"; _modalDisplay = "none;";
_showBackdrop = false; _showBackdrop = false;
StateHasChanged(); StateHasChanged();
} }
public void Dispose() public void Dispose()
{ {
Interceptor.DisposeEvent(); Interceptor.DisposeEvent();
} }
} }

View file

@ -0,0 +1,126 @@
@*
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
*@
@using Wonky.Client.Components
@using Wonky.Client.Helpers
<div class="modal" tabindex="-1" role="dialog" style="display:@_modalDisplay">
@* <div class="modal-dialog modal-dialog-scrollable modal-fullscreen-lg-down modal-xl modal-lg"> *@
<div class="modal-dialog modal-dialog-scrollable modal-fullscreen">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">@SalesItem.Name @SalesItem.Sku (@SalesItem.BoxSize stk/colli)</h4>
<button type="button" class="btn-close" @onclick="Hide" data-bs-dismiss="modal" aria-label="Luk"></button>
</div>
<div class="modal-body">
@if (SalesItem.Discontinued)
{
<h3>Udgået produkt</h3>
}
else
{
@* draft line ----------------------------------------------------- *@
<div class="row">
<div class="col">
<table id="draft-line" class="table table-bordered">
<thead>
<tr class="bg-dark text-white">
<th scope="col" colspan="6">BESTILLING</th>
</tr>
<tr>
<th scope="col">Antal</th>
<th scope="col">Pris</th>
<th scope="col">Rabat</th>
<th class="align-content-center justify-content-center" scope="col">SAS</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr>
<td class="align-middle">
<input type="number" class="form-control" @bind-value="@SelectedItem.Quantity"/>
</td>
<td class="align-middle">
<div class="input-group">
<input type="number" class="form-control" @bind-value="@SelectedItem.Price"/>
</div>
</td>
<td class="align-middle">
<input type="number" class="form-control" @bind-value="@SelectedItem.Discount"/>
</td>
<td class="align-middle align-content-center justify-content-center">
<input type="checkbox" class="form-check" @bind-value="@SelectedItem.Sas"/>
</td>
<td class="align-middle">
<button type="button" class="btn btn-warning text-nowrap d-block" @onclick="@(() => SendToOrder(SelectedItem))">BESTIL</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
@* end draft line ------------------------------------------------- *@
@* price list item ------------------------------------------------ *@
<div class="row align-middle">
@foreach (var rate in SalesItem.Rates)
{
<div class="col">
<a type="button" class="btn btn-primary btn-sm" data-bs-dismiss="modal" @onclick="@(() => SelectPrice(rate.Quantity, rate.Rate))">
@rate.Quantity <i class="bi-at"></i> @rate.Rate/stk
</a>
</div>
}
</div>
@* end price list item -------------------------------------------- *@
}
@* product history ------------------------------------------------ *@
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Dato</th>
<th scope="col">Antal</th>
<th scope="col">Rabat</th>
<th scope="col">Pris</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
@foreach (var entry in History)
{
<tr>
<td class="align-middle">@entry.DeliveryDate</td>
<td class="align-middle">@entry.Quantity</td>
<td class="align-middle">@entry.Discount</td>
<td class="align-middle">@entry.Price</td>
<td class="align-middle">
@if (!SalesItem.Discontinued)
{
<button type="button" class="btn btn-primary btn-sm" data-bs-dismiss="modal" @onclick="() => SelectHistory(entry)"><i class="bi-plus"></i> VÆLG</button>
}
</td>
</tr>
}
</tbody>
</table>
@* end product history -------------------------------------------- *@
</div>
</div>
</div>
</div>
@if (_showBackdrop)
{
<div class="modal-backdrop fade show"></div>
}

View file

@ -0,0 +1,91 @@
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using System.Globalization;
using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterfaces;
using Wonky.Client.Models;
using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.OverlayOffice;
public partial class OfficeCustomerInventoryReorderOverlay
{
[Parameter] public string CompanyId { get; set; } = "";
[Parameter] public SalesItemView SalesItem { get; set; } = new();
[Inject] private IAdvisorCustomerHistoryRepository HistoryRepo { get; set; }
[Parameter] public EventCallback<DraftItem> OnSelected { get; set; }
private List<ProductHistoryView>? History { get; set; } = new();
private DraftItem SelectedItem { get; set; } = new();
private string ProductName { get; set; } = "";
private string _modalDisplay = "";
private bool _showBackdrop;
private bool ShowDraft { get; set; }
protected override async Task OnParametersSetAsync()
{
if (string.IsNullOrWhiteSpace(SalesItem.Sku))
return;
History = await HistoryRepo.FetchHistory(CompanyId, SalesItem.Sku);
if (!History.Any())
await Task.Delay(1000);
SelectedItem.Item = SalesItem;
SelectedItem.Discount = 0;
SelectedItem.Quantity = 1;
if(SalesItem.Rates.Any())
SelectedItem.Price = decimal.Parse(SalesItem.Rates[0].Rate, CultureInfo.InvariantCulture);
}
private async Task SendToOrder(DraftItem item)
{
SelectedItem = new DraftItem();
await OnSelected.InvokeAsync(item);
Hide();
}
private void SelectPrice(string quantity, string rate)
{
SelectedItem.Discount = 0;
SelectedItem.Price = decimal.Parse(rate, CultureInfo.InvariantCulture);
SelectedItem.Quantity = int.Parse(quantity);
StateHasChanged();
}
private void SelectHistory(ProductHistoryView item)
{
SelectedItem.Discount = item.Discount;
SelectedItem.Price = item.Price;
SelectedItem.Quantity = item.Quantity;
StateHasChanged();
}
public void Show()
{
_modalDisplay = "block;";
_showBackdrop = true;
StateHasChanged();
}
private void Hide()
{
SelectedItem = new DraftItem();
_modalDisplay = "none;";
_showBackdrop = false;
StateHasChanged();
}
}

View file

@ -0,0 +1,46 @@
@*
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
*@
@using Wonky.Client.Components
<div class="modal" tabindex="-1" role="dialog" style="display:@_modalDisplay">
<div class="modal-dialog modal-dialog-scrollable modal-fullscreen">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Faktura</h5>
<button type="button" class="btn-close" @onclick="Hide" data-bs-dismiss="modal" aria-label="Luk"></button>
</div>
<div class="modal-body">
<div class="row pt-2 pb-1 rounded-2 bg-dark text-white">
<div class="col-sm-6">
<h4 class="pt-1">@Company.Name</h4>
</div>
</div>
@* component listing invoices*@
<CustomerInvoiceListComponent OnShowInvoice="@CallInvoiceModal" CompanyId="@Company.CompanyId" InvoiceList="@Invoices"/>
</div>
</div>
</div>
</div>
@if (_showBackdrop)
{
<div class="modal-backdrop fade show"></div>
}
@* overlay showing one invoice*@
<OfficeCustomerInvoiceViewOverlay CountryCode="@Company.CountryCode" CompanyId="@Company.CompanyId" InvoiceId="@InvoiceId" @ref="OfficeCustomerInvoiceView" />

View file

@ -0,0 +1,72 @@
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using System.Text.Json;
using Microsoft.AspNetCore.Components;
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.OverlayOffice;
public partial class OfficeCustomerInvoiceListOverlay
{
[Parameter] public InvoiceListView CustomerInvoices { get; set; } = new();
[Parameter] public CompanyDto Company { get; set; } = new();
// dependency injection
[Inject] private ILogger<OfficeCustomerInvoiceListOverlay> Logger { get; set; }
private string InvoiceId { get; set; } = "";
private string _modalDisplay = "";
private bool _showBackdrop;
private OfficeCustomerInvoiceViewOverlay OfficeCustomerInvoiceView { get; set; } = new();
private List<InvoiceListItemView> Invoices { get; set; } = new();
protected override async Task OnParametersSetAsync()
{
// extract company from customer invoices
Logger.LogDebug("CustomerInvoiceListOverlay => company => {}", JsonSerializer.Serialize(Company));
// if there is invoices -> order by document date
if (CustomerInvoices.Invoices.Any())
Invoices = CustomerInvoices.Invoices.OrderByDescending(x => x.DocumentDate).ToList();
Logger.LogDebug("invoices => {}", JsonSerializer.Serialize(Invoices));
}
protected override void OnInitialized()
{
StateHasChanged();
}
private void CallInvoiceModal(string invoiceId)
{
InvoiceId = invoiceId;
OfficeCustomerInvoiceView.Show();
}
public void Show()
{
_modalDisplay = "block;";
_showBackdrop = true;
StateHasChanged();
}
private void Hide()
{
_modalDisplay = "none;";
_showBackdrop = false;
StateHasChanged();
}
}

View file

@ -0,0 +1,103 @@
@*
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
*@
@using Wonky.Client.Components
@using Wonky.Client.Helpers
<div class="modal" tabindex="-1" role="dialog" style="display:@_modalDisplay">
<div class="modal-dialog modal-dialog-scrollable modal-fullscreen">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Faktura</h5>
<button type="button" class="btn-close" @onclick="Hide" data-bs-dismiss="modal" aria-label="Luk"></button>
</div>
<div class="modal-body">
@if (!string.IsNullOrWhiteSpace(Invoice.Company.Name))
{
<table class="table table-striped">
<thead>
</thead>
<tbody>
<tr>
<th scope="row">Dato</th>
<td>@Invoice.DocumentDate</td>
<th scope="row">Faktura nr.</th>
<td>@Invoice.DocumentNumber</td>
<td colspan="2"></td>
</tr>
<tr>
<th scope="row">Konto</th>
<td>@Invoice.Account</td>
<th scope="row">Moms Nr.</th>
<td>@Invoice.VatNumber</td>
<td colspan="2"></td>
</tr>
<tr>
<th scope="row">Eordre</th>
<td>@Invoice.ESalesNumber</td>
<th scope="row">Vores Ref.</th>
<td>@Invoice.OurRef</td>
<td colspan="2"></td>
</tr>
<tr>
<th scope="row">Rekv.</th>
<td>@Invoice.ReferenceNumber</td>
<th scope="row">Deres Ref.</th>
<td>@Invoice.YourRef</td>
<th scope="row">Pakke nr.</th>
<td>@Invoice.TrackingNumber</td>
</tr>
<tr>
<th scope="row">Notat</th>
<td class="fw-bold" colspan="5">@Invoice.OrderNote</td>
</tr>
</tbody>
</table>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Varenr</th>
<th scope="col">Beskrivelse</th>
<th class="text-end" scope="col">Antal</th>
<th class="text-end" scope="col">Pris</th>
<th class="text-end" scope="col">Rabat</th>
</tr>
</thead>
<tbody>
@foreach (var line in Invoice.Lines)
{
<tr>
<td>@line.Sku</td>
<td>@line.Text</td>
<td class="text-end">@line.Qty</td>
<td class="text-end">@line.Price</td>
<td class="text-end">@line.Discount</td>
</tr>
}
</tbody>
</table>
}
else
{
<span>Ingen data</span>
}
</div>
</div>
</div>
</div>
@if (_showBackdrop)
{
<div class="modal-backdrop fade show"></div>
}

View file

@ -0,0 +1,63 @@
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces;
using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.OverlayOffice;
public partial class OfficeCustomerInvoiceViewOverlay : IDisposable
{
[Parameter] public string CompanyId { get; set; } = "";
[Parameter] public string InvoiceId { get; set; } = "";
[Parameter] public string CountryCode { get; set; } = "";
[Inject] private HttpInterceptorService Interceptor { get; set; }
[Inject] private ICountryCustomerHistoryRepository HistoryRepo { get; set; }
private string _modalDisplay = "";
private bool _showBackdrop;
private InvoiceView Invoice { get; set; } = new();
protected override async Task OnParametersSetAsync()
{
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
if (!string.IsNullOrWhiteSpace(InvoiceId))
{
Invoice = await HistoryRepo.FetchInvoice( CountryCode, CompanyId, InvoiceId);
}
}
public void Show()
{
_modalDisplay = "block;";
_showBackdrop = true;
StateHasChanged();
}
private void Hide()
{
_modalDisplay = "none;";
_showBackdrop = false;
StateHasChanged();
}
public void Dispose() => Interceptor.DisposeEvent();
}

View file

@ -0,0 +1,38 @@
@*
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
*@
@using Wonky.Client.Components
<div class="modal" tabindex="-1" role="dialog" style="display:@_modalDisplay">
<div class="modal-dialog modal-dialog-scrollable modal-fullscreen">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">@Company.Name - Produktoversigt</h3>
<button type="button" class="btn-close" @onclick="Hide" data-bs-dismiss="modal" aria-label="Luk"></button>
</div>
<div class="modal-body">
@* product list *@
<CustomerInventoryListComponent OnReorderSelected="OnReorderCallback" CompanyId="@Company.CompanyId" Inventory="@ProductList"/>
</div>
</div>
</div>
</div>
@if (_showBackdrop)
{
<div class="modal-backdrop fade show"></div>
}
@* reorder overlay *@
<OfficeCustomerInventoryReorderOverlay CompanyId="@Company.CompanyId" SalesItem="SalesItem" OnSelected="OnInventorySelected" @ref="ReorderOverlay" />

View file

@ -0,0 +1,83 @@
// 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
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces;
using Wonky.Client.Models;
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.OverlayOffice;
public partial class OfficeCustomerProductListOverlay : IDisposable
{
[Inject] private HttpInterceptorService Interceptor { get; set; }
[Inject] private ICountryCatalogRepository CatalogRepo { get; set; }
[Inject] private ILogger<OfficeCustomerProductListOverlay> Logger { get; set; }
[Parameter] public CompanyDto Company { get; set; }
[Parameter] public List<ProductInventoryView> ProductList { get; set; } = new();
[Parameter] public EventCallback<DraftItem> OnInventorySelected { get; set; }
private string _modalDisplay = "";
private bool _showBackdrop;
private CompanyDto _company { get; set; } = new();
private List<ProductInventoryView> _inventory { get; set; } = new();
private DraftItem DraftItem { get; set; } = new();
private SalesItemView SalesItem { get; set; } = new();
private OfficeCustomerInventoryReorderOverlay ReorderOverlay { get; set; } = new();
protected override void OnInitialized()
{
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
StateHasChanged();
}
private async Task OnReorderCallback(string sku)
{
SalesItem = await CatalogRepo.GetSalesItemSku(Company.CountryCode.ToLower(), sku);
ReorderOverlay.Show();
}
private async Task OnSelectedItem(DraftItem draftItem)
{
await OnInventorySelected.InvokeAsync(draftItem);
Hide();
}
public void Show()
{
_modalDisplay = "block;";
_showBackdrop = true;
StateHasChanged();
}
private void Hide()
{
_modalDisplay = "none;";
_showBackdrop = false;
StateHasChanged();
}
public void Dispose()
{
Interceptor.DisposeEvent();
}
}

View file

@ -17,6 +17,7 @@
@using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Authorization
@using Wonky.Client.Components @using Wonky.Client.Components
@using Wonky.Client.OverlayCustomer
@attribute [Authorize(Roles = "Advisor")] @attribute [Authorize(Roles = "Advisor")]
@page "/advisor/customers/{CompanyId}/activities/new" @page "/advisor/customers/{CompanyId}/activities/new"
@ -336,23 +337,23 @@ else
</div> </div>
} }
<ConfirmWorkDateModalOverlay BodyMessage="@PromptDateConfirm" <ConfirmWorkDateModal BodyMessage="@PromptDateConfirm"
OnOkClicked="WorkDateConfirmCallback" @ref="WorkDateOverlay"/> OnOkClicked="WorkDateConfirmCallback" @ref="ConfirmWorkDate"/>
<PriceCatalogModalOverlay CountryCode="@Company.CountryCode.ToLower()" <PriceCatalogOverlay CountryCode="@Company.CountryCode.ToLower()"
OnSelected="PriceListCallback" @ref="CatalogOverlay"/> OnSelected="PriceListCallback" @ref="CatalogOverlay"/>
<ProductHistoryModalOverlay CompanyId="@CompanyId" ItemSku="@SelectedItem.Sku" @ref="ProductOverlay"/> <ProductHistoryOverlay CompanyId="@CompanyId" ItemSku="@SelectedItem.Sku" @ref="ProductOverlay"/>
<ProductPriceHistoryModal CompanyId="@CompanyId" Sku="@SelectedItem.Sku" <ProductPriceHistoryOverlay CompanyId="@CompanyId" Sku="@SelectedItem.Sku"
OnSelected="PriceHistoryCallback" @ref="PriceModalOverlay"/> OnSelected="PriceHistoryCallback" @ref="PriceOverlay"/>
<ConfirmProductCheckModalOverlay BodyMessage="" CompanyId="@CompanyId" Products="CheckList" <ProductCheckConfirmationOverlay BodyMessage="" CompanyId="@CompanyId" Products="CheckList"
OnOkClicked="ConfirmProductCheckCallback" @ref="ProductCheckOverlay" /> OnOkClicked="ConfirmProductCheckCallback" @ref="ConfirmationCheckOverlay" />
<CustomerInvoiceListModalOverlay CustomerInvoices="CompanyInvoices" @ref="InvoiceListOverlay" /> <CustomerInvoiceListOverlay CustomerInvoices="CompanyInvoices" @ref="InvoiceListOverlay" />
<CustomerInventoryListModalOverlay CompanyName="@Company.Name" CompanyId="@CompanyId" CountryCode="@Company.CountryCode" <CustomerInventoryListOverlay CompanyName="@Company.Name" CompanyId="@CompanyId" CountryCode="@Company.CountryCode"
OnInventorySelected="OnInventoryCallback" Inventory="Inventory" @ref="InventoryListOverlay" /> OnInventorySelected="OnInventoryCallback" Inventory="Inventory" @ref="InventoryListOverlay" />
<CustomerActivityListModalOverlay Activities="Activities" CompanyName="@Company.Name" @ref="ActivityListOverlay" /> <CustomerActivityListOverlay Activities="Activities" CompanyName="@Company.Name" @ref="ActivityListOverlay" />

View file

@ -18,36 +18,38 @@ using System.Globalization;
using System.Text.Json; using System.Text.Json;
using Blazored.LocalStorage; using Blazored.LocalStorage;
using Blazored.Toast.Services; using Blazored.Toast.Services;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.Models;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms; using Microsoft.AspNetCore.Components.Forms;
using Wonky.Client.Helpers; using Wonky.Client.Helpers;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces; using Wonky.Client.HttpInterfaces;
using Wonky.Client.Models;
using Wonky.Client.OverlayCustomer;
using Wonky.Client.Services; using Wonky.Client.Services;
using Wonky.Client.Shared; using Wonky.Client.Shared;
using Wonky.Entity.DTO; using Wonky.Entity.DTO;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Pages; namespace Wonky.Client.Pages;
public partial class AdvisorActivityCreatePage : IDisposable public partial class AdvisorActivityCreatePage : IDisposable
{ {
// Services // Services
[Inject] private ILogger<AdvisorActivityCreatePage> Logger { get; set; } [Inject] public ILogger<AdvisorActivityCreatePage> Logger { get; set; }
[Inject] private HttpInterceptorService Interceptor { get; set; } [Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] private UserProfileService Profiles { get; set; } [Inject] public UserProfileService ProfileService { get; set; }
[Inject] private IToastService Toaster { get; set; } [Inject] public IToastService Toaster { get; set; }
[Inject] private NavigationManager Navigator { get; set; } [Inject] public NavigationManager Navigator { get; set; }
[Inject] private ILocalStorageService Storage { get; set; } [Inject] public ILocalStorageService Storage { get; set; }
[Inject] private ICountryCatalogRepository CatalogRepo { get; set; } [Inject] public ICountryCatalogRepository CatalogRepo { get; set; }
[Inject] private IAdvisorCustomerRepository CompanyRepo { get; set; } [Inject] public IAdvisorCustomerRepository CompanyRepo { get; set; }
[Inject] private IAdvisorActivityRepository ActivityRepo { get; set; } [Inject] public IAdvisorActivityRepository ActivityRepo { get; set; }
[Inject] private IAdvisorReportRepository ReportRepo { get; set; } [Inject] public IAdvisorReportRepository ReportRepo { get; set; }
[Inject] private IAdvisorCustomerHistoryRepository HistoryRepo { get; set; } [Inject] public IAdvisorCustomerHistoryRepository HistoryRepo { get; set; }
[CascadingParameter] private DraftStateProvider DraftProvider { get; set; } = new(); [CascadingParameter] private DraftStateProvider DraftProvider { get; set; } = new();
[Parameter] public string CompanyId { get; set; } [Parameter] public string CompanyId { get; set; } = "";
// variables // variables
private readonly JsonSerializerOptions _options = new() {PropertyNameCaseInsensitive = true}; private readonly JsonSerializerOptions _options = new() {PropertyNameCaseInsensitive = true};
@ -72,14 +74,14 @@ public partial class AdvisorActivityCreatePage : IDisposable
private string PromptDateConfirm { get; set; } = ""; private string PromptDateConfirm { get; set; } = "";
// OVERLAY PAGES // OVERLAY PAGES
private PriceCatalogModalOverlay CatalogOverlay { get; set; } = new(); private PriceCatalogOverlay CatalogOverlay { get; set; } = new();
private ProductHistoryModalOverlay ProductOverlay { get; set; } = new(); private ProductHistoryOverlay ProductOverlay { get; set; } = new();
private ProductPriceHistoryModalOverlay PriceModalOverlay { get; set; } = new(); private ProductPriceHistoryOverlay PriceOverlay { get; set; } = new();
private ConfirmWorkDateModalOverlay WorkDateOverlay { get; set; } = new(); private ConfirmWorkDateModal ConfirmWorkDate { get; set; } = new();
private ConfirmProductCheckModalOverlay ProductCheckOverlay { get; set; } = new(); private ProductCheckConfirmationOverlay ConfirmationCheckOverlay { get; set; } = new();
private CustomerInvoiceListModalOverlay InvoiceListOverlay { get; set; } = new(); private CustomerInvoiceListOverlay InvoiceListOverlay { get; set; } = new();
private CustomerInventoryListModalOverlay InventoryListOverlay { get; set; } = new(); private CustomerInventoryListOverlay InventoryListOverlay { get; set; } = new();
private CustomerActivityListModalOverlay ActivityListOverlay { get; set; } = new(); private CustomerActivityListOverlay ActivityListOverlay { get; set; } = new();
private List<ProductInventoryView> Inventory { get; set; } = new(); private List<ProductInventoryView> Inventory { get; set; } = new();
private List<ProductInventoryView> CheckList { get; set; } = new(); private List<ProductInventoryView> CheckList { get; set; } = new();
private InvoiceListView CompanyInvoices { get; set; } = new(); private InvoiceListView CompanyInvoices { get; set; } = new();
@ -102,7 +104,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
Interceptor.RegisterEvent(); Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent(); Interceptor.RegisterBeforeSendEvent();
// User Preferences // User Preferences
UserProfile = await Profiles.GetPreferences(); UserProfile = await ProfileService.GetPreferences();
// User Info // User Info
SalesRep = await Storage.GetItemAsync<UserInfoView>("_xu"); SalesRep = await Storage.GetItemAsync<UserInfoView>("_xu");
// Fetch Customer from http // Fetch Customer from http
@ -152,7 +154,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
if (!UserProfile.DateConfirmed) if (!UserProfile.DateConfirmed)
{ {
PromptDateConfirm = $"Aktiviteter oprettes med dato {SelectedDate.ToShortDateString()}. Er dette OK?"; PromptDateConfirm = $"Aktiviteter oprettes med dato {SelectedDate.ToShortDateString()}. Er dette OK?";
WorkDateOverlay.Show(); ConfirmWorkDate.Show();
} }
// Lines may already have been added from the company inventory page // Lines may already have been added from the company inventory page
if (DraftProvider.Draft.DraftType == "order") if (DraftProvider.Draft.DraftType == "order")
@ -297,12 +299,12 @@ public partial class AdvisorActivityCreatePage : IDisposable
} }
// Show CheckList modal // Show CheckList modal
ProductCheckOverlay.Show(); ConfirmationCheckOverlay.Show();
} }
private async Task ConfirmProductCheckCallback() private async Task ConfirmProductCheckCallback()
{ {
ProductCheckOverlay.Hide(); ConfirmationCheckOverlay.Hide();
await CreateActivity(); await CreateActivity();
foreach (var item in CheckList) foreach (var item in CheckList)
{ {
@ -317,8 +319,8 @@ public partial class AdvisorActivityCreatePage : IDisposable
/// </summary> /// </summary>
private async Task WorkDateConfirmCallback() private async Task WorkDateConfirmCallback()
{ {
await Profiles.SetDateConfirmed(true); await ProfileService.SetDateConfirmed(true);
WorkDateOverlay.Hide(); ConfirmWorkDate.Hide();
StateHasChanged(); StateHasChanged();
} }
@ -363,7 +365,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
private void ShowPriceHistoryOverlay() private void ShowPriceHistoryOverlay()
{ {
if(ShowItem) if(ShowItem)
PriceModalOverlay.Show(); PriceOverlay.Show();
} }
/// <summary> /// <summary>

View file

@ -21,19 +21,20 @@ using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces; using Wonky.Client.HttpInterfaces;
using Wonky.Client.Services; using Wonky.Client.Services;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Pages; namespace Wonky.Client.Pages;
public partial class AdvisorActivityTodayListPage : IDisposable public partial class AdvisorActivityTodayListPage : IDisposable
{ {
[Inject] private UserProfileService UserProfileService { get; set; } [Inject] private UserProfileService ProfileService { get; set; }
[Inject] private ILogger<AdvisorActivityTodayListPage> Logger { get; set; } [Inject] private ILogger<AdvisorActivityTodayListPage> Logger { get; set; }
[Inject] private HttpInterceptorService Interceptor { get; set; } [Inject] private HttpInterceptorService Interceptor { get; set; }
[Inject] private NavigationManager Navigator { get; set; } [Inject] private NavigationManager Navigator { get; set; }
[Inject] private IAdvisorActivityRepository AdvisorActivityRepo { get; set; } [Inject] private IAdvisorActivityRepository ActivityRepo { get; set; }
[Inject] private IAdvisorReportRepository AdvisorReportRepo { get; set; } [Inject] private IAdvisorReportRepository ReportRepo { get; set; }
[Inject] private IToastService Toaster { get; set; } [Inject] private IToastService Toaster { get; set; }
private ReportStatusView? ReportStatusView { get; set; } = new(); private ReportStatusView ReportStatusView { get; set; } = new();
private UserProfile UserProfile { get; set; } = new(); private UserProfile UserProfile { get; set; } = new();
private DateTime SelectedDate { get; set; } private DateTime SelectedDate { get; set; }
private bool ReportExist { get; set; } private bool ReportExist { get; set; }
@ -43,9 +44,9 @@ public partial class AdvisorActivityTodayListPage : IDisposable
{ {
Interceptor.RegisterEvent(); Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent(); Interceptor.RegisterBeforeSendEvent();
UserProfile = await UserProfileService.GetPreferences(); UserProfile = await ProfileService.GetPreferences();
SelectedDate = string.IsNullOrWhiteSpace(UserProfile.WorkDate) ? DateTime.Now : DateTime.Parse(UserProfile.WorkDate); SelectedDate = string.IsNullOrWhiteSpace(UserProfile.WorkDate) ? DateTime.Now : DateTime.Parse(UserProfile.WorkDate);
ReportExist = await AdvisorReportRepo.ReportExist($"{SelectedDate:yyyy-MM-dd}"); ReportExist = await ReportRepo.ReportExist($"{SelectedDate:yyyy-MM-dd}");
await GetActivities($"{SelectedDate:yyyy-MM-dd}"); await GetActivities($"{SelectedDate:yyyy-MM-dd}");
Working = false; Working = false;
} }
@ -56,8 +57,8 @@ public partial class AdvisorActivityTodayListPage : IDisposable
Toaster.ShowInfo("Vent nogle sekunder for data", "HENTER DATA"); Toaster.ShowInfo("Vent nogle sekunder for data", "HENTER DATA");
SelectedDate = DateTime.Parse(workDate); SelectedDate = DateTime.Parse(workDate);
ReportStatusView = new ReportStatusView(); ReportStatusView = new ReportStatusView();
ReportExist = await AdvisorReportRepo.ReportExist($"{SelectedDate:yyyy-MM-dd}"); ReportExist = await ReportRepo.ReportExist($"{SelectedDate:yyyy-MM-dd}");
ReportStatusView = await AdvisorActivityRepo.GetActivities($"{SelectedDate:yyyy-MM-dd}"); ReportStatusView = await ActivityRepo.GetActivities($"{SelectedDate:yyyy-MM-dd}");
Logger.LogDebug("Activities => {}", JsonSerializer.Serialize(ReportStatusView)); Logger.LogDebug("Activities => {}", JsonSerializer.Serialize(ReportStatusView));
Working = false; Working = false;
Toaster.ClearAll(); Toaster.ClearAll();

View file

@ -22,6 +22,7 @@ using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces; using Wonky.Client.HttpInterfaces;
using Wonky.Entity.DTO; using Wonky.Entity.DTO;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Pages; namespace Wonky.Client.Pages;

View file

@ -36,7 +36,7 @@
</div> </div>
</div> </div>
<CustomerVisitListComponent Activities="Activities" /> <CustomerActivityListComponent Activities="ActivityList" />
} }
@if (Working) @if (Working)
{ {

View file

@ -20,23 +20,24 @@ using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces; using Wonky.Client.HttpInterfaces;
using Wonky.Entity.DTO; using Wonky.Entity.DTO;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Pages; namespace Wonky.Client.Pages;
public partial class AdvisorCustomerActivityListPage : IDisposable public partial class AdvisorCustomerActivityListPage : IDisposable
{ {
[Parameter] public string CompanyId { get; set; } = ""; [Parameter] public string CompanyId { get; set; } = "";
[Inject] private HttpInterceptorService _interceptor { get; set; } [Inject] private HttpInterceptorService Interceptor { get; set; }
[Inject] private IAdvisorActivityRepository AdvisorActivityRepo { get; set; } [Inject] private IAdvisorActivityRepository AdvisorActivityRepo { get; set; }
[Inject] private IAdvisorCustomerRepository CompanyRepo { get; set; } [Inject] private IAdvisorCustomerRepository CompanyRepo { get; set; }
private List<ReportItemView> Activities { get; set; } = new(); private List<ReportItemView> ActivityList { get; set; } = new();
private CompanyDto Company { get; set; } = new(); private CompanyDto Company { get; set; } = new();
private bool Working { get; set; } = true; private bool Working { get; set; } = true;
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
_interceptor.RegisterEvent(); Interceptor.RegisterEvent();
_interceptor.RegisterBeforeSendEvent(); Interceptor.RegisterBeforeSendEvent();
Company = await CompanyRepo.GetCompanyById(CompanyId); Company = await CompanyRepo.GetCompanyById(CompanyId);
await GetActivities(); await GetActivities();
@ -46,14 +47,14 @@ public partial class AdvisorCustomerActivityListPage : IDisposable
private async Task GetActivities() private async Task GetActivities()
{ {
Working = true; Working = true;
Activities = await AdvisorActivityRepo.GetCustomerActivities(CompanyId); ActivityList = await AdvisorActivityRepo.GetCustomerActivities(CompanyId);
if(Activities.Any()) if(ActivityList.Any())
Activities = Activities.OrderByDescending(x => x.OrderDate).ToList(); ActivityList = ActivityList.OrderByDescending(x => x.OrderDate).ToList();
Working = false; Working = false;
} }
public void Dispose() public void Dispose()
{ {
_interceptor.DisposeEvent(); Interceptor.DisposeEvent();
} }
} }

View file

@ -143,12 +143,13 @@
</div> </div>
</EditForm> </EditForm>
<VatLookupDkModal VatAddress="CompanyVatAddress" EntityName="@Company.Name" VatNumber="@Company.VatNumber"
@ref="VatLookupPopup" OnSelectedCompany="SelectCompanyCallback"/>
@if (Working) @if (Working)
{ {
<WorkingThreeDots /> <WorkingThreeDots />
} }
<VatLookupDkModal VatAddress="CompanyVatAddress" EntityName="@Company.Name" VatNumber="@Company.VatNumber"
@ref="VatLookupPopup" OnSelectedCompany="SelectCompanyCallback"/>

View file

@ -1,4 +1,3 @@
// 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 // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as // it under the terms of the GNU Affero General Public License as
@ -17,17 +16,18 @@
using System.Text.Json; using System.Text.Json;
using Blazored.LocalStorage; using Blazored.LocalStorage;
using Blazored.Toast.Services; using Blazored.Toast.Services;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.Services;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms; using Microsoft.AspNetCore.Components.Forms;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces; using Wonky.Client.HttpInterfaces;
using Wonky.Client.Models; using Wonky.Client.Models;
using Wonky.Client.Services;
using Wonky.Client.Shared; using Wonky.Client.Shared;
using Wonky.Entity.DTO; using Wonky.Entity.DTO;
using Wonky.Entity.Models; using Wonky.Entity.Models;
using Wonky.Entity.Requests; using Wonky.Entity.Requests;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Pages namespace Wonky.Client.Pages
{ {
@ -40,42 +40,41 @@ namespace Wonky.Client.Pages
[Inject] private IAdvisorCustomerRepository CompanyRepo { get; set; } [Inject] private IAdvisorCustomerRepository CompanyRepo { get; set; }
[Inject] private HttpInterceptorService Interceptor { get; set; } [Inject] private HttpInterceptorService Interceptor { get; set; }
[Inject] private VatInfoLookupService VatService { get; set; } [Inject] private VatInfoLookupService VatService { get; set; }
private EditContext CompanyContext { get; set; } private EditContext CompanyContext { get; set; }
private CompanyDto Company { get; set; } = new(); private CompanyDto Company { get; set; } = new();
private VirkRegInfo CompanyRegInfo { get; set; } = new(); private VirkRegInfo CompanyRegInfo { get; set; } = new();
private List<VirkRegInfo> VatInfos { get; set; } = new(); private List<VirkRegInfo> VatInfos { get; set; } = new();
private VatAddress CompanyVatAddress { get; set; } = new(); private VatAddress CompanyVatAddress { get; set; } = new();
private VatLookupDkModal VatLookupPopup { get; set; } = new(); private VatLookupDkModal VatLookupPopup { get; set; } = new();
private bool FormInvalid = true; private bool FormInvalid { get; set; } = true;
private string RegState = ""; private string RegState { get; set; } = "";
private DateTime LastVisit { get; set; } private DateTime LastVisit { get; set; }
private DateTime NextVisit { get; set; } private DateTime NextVisit { get; set; }
private bool Dk { get; set; } = true; private bool Dk { get; set; } = true;
private bool ShowInfos = true;
private bool Working { get; set; } private bool Working { get; set; }
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
CompanyContext = new EditContext(Company); CompanyContext = new EditContext(Company);
CompanyContext.OnFieldChanged += HandleFieldChanged; CompanyContext.OnFieldChanged += HandleFieldChanged;
CompanyContext.OnValidationStateChanged += ValidationChanged; CompanyContext.OnValidationStateChanged += ValidationChanged;
var ux = await Storage.GetItemAsync<UserInfoView>("_xu"); var ux = await Storage.GetItemAsync<UserInfoView>("_xu");
Dk = ux.CountryCode.ToLower() == "dk"; Dk = ux.CountryCode.ToLower() == "dk";
Company.SalesRepId = ux.Id; Company.SalesRepId = ux.Id;
Company.CountryCode = ux.CountryCode.ToLower(); Company.CountryCode = ux.CountryCode.ToLower();
LastVisit = DateTime.Now; LastVisit = DateTime.Now;
NextVisit = DateTime.Now.AddDays(Company.Interval * 7); NextVisit = DateTime.Now.AddDays(Company.Interval * 7);
Company.LastVisit = $"{LastVisit:yyyy-MM-dd}"; Company.LastVisit = $"{LastVisit:yyyy-MM-dd}";
Company.NextVisit = $"{NextVisit:yyyy-MM-dd}"; Company.NextVisit = $"{NextVisit:yyyy-MM-dd}";
Interceptor.RegisterEvent(); Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent(); Interceptor.RegisterBeforeSendEvent();
} }
/// <summary> /// <summary>
@ -84,44 +83,6 @@ namespace Wonky.Client.Pages
private void CallVatLookupModal() private void CallVatLookupModal()
{ {
VatLookupPopup.Show(); VatLookupPopup.Show();
}
private async Task GetInfoFromName(string entityName)
{
Toaster.ShowInfo("Vent for firma info ...");
VatInfos = await VatService
.QueryVirkRegistry(new VirkParams {EntityName = entityName});
if (!VatInfos.Any())
{
Toaster.ShowError($"Firma med navn '{entityName}' findes ikke.");
}
}
private async Task GetInfoFromAddress(VatAddress address)
{
ShowInfos = true;
Toaster.ShowInfo("Vent for adresse info ...");
VatInfos = await VatService.QueryVirkRegistry(
new VirkParams
{
StreetName = address.StreetName,
HouseNumber = address.HouseNumber,
ZipCode = address.ZipCode
});
if (!VatInfos.Any())
{
Toaster.ShowWarning($"Ingen data for adresse ...");
}
}
private async Task GetInfoFromVat(string vatNumber)
{
ShowInfos = true;
Toaster.ShowInfo("Vent for firma info ...");
VatInfos = await VatService
.QueryVirkRegistry(new VirkParams {VatNumber = vatNumber});
if (!VatInfos.Any())
{
Toaster.ShowError($"Firma med CVR '{vatNumber}' findes ikke.");
}
} }
/// <summary> /// <summary>
@ -131,7 +92,7 @@ namespace Wonky.Client.Pages
private void SelectCompanyCallback(VirkRegInfo regInfo) private void SelectCompanyCallback(VirkRegInfo regInfo)
{ {
Logger.LogDebug("CrmCompanyView => SelectCompanyCallback => {}", JsonSerializer.Serialize(regInfo)); Logger.LogDebug("CrmCompanyView => SelectCompanyCallback => {}", JsonSerializer.Serialize(regInfo));
// this can be removed in favor of the new data returned from updating the VatNumber // 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"; RegState = regInfo.States[0].State.ToLower() == "normal" ? "the-good" : "the-dead";
if (regInfo.SyncAll) if (regInfo.SyncAll)
@ -142,32 +103,19 @@ namespace Wonky.Client.Pages
Company.ZipCode = regInfo.ZipCode; Company.ZipCode = regInfo.ZipCode;
Company.City = regInfo.City; Company.City = regInfo.City;
} }
Company.VatNumber = regInfo.VatNumber; Company.VatNumber = regInfo.VatNumber;
} }
private void SelectCompany(string vatNumber)
{
ShowInfos = false;
CompanyRegInfo = (from x in VatInfos where x.VatNumber == vatNumber select x).First();
RegState = CompanyRegInfo.States[^1].State == "NORMAL" ? "the-good" : "the-ugly";
Company.Name = CompanyRegInfo.Name;
Company.Address1 = CompanyRegInfo.Address;
Company.Address2 = CompanyRegInfo.CoName;
Company.ZipCode = CompanyRegInfo.ZipCode;
Company.City = CompanyRegInfo.City;
Company.VatNumber = CompanyRegInfo.VatNumber;
Company.ValidVat = 1;
StateHasChanged();
}
private async Task SubmitCompanyForm() private async Task SubmitCompanyForm()
{ {
Working = true; Working = true;
FormInvalid = true; FormInvalid = true;
Company.LastVisit = $"{LastVisit:yyyy-MM-dd}"; Company.LastVisit = $"{LastVisit:yyyy-MM-dd}";
Company.NextVisit = $"{NextVisit:yyyy-MM-dd}"; Company.NextVisit = $"{NextVisit:yyyy-MM-dd}";
var newId = await CompanyRepo.CreateCompany(Company); var newId = await CompanyRepo.CreateCompany(Company);
if (!string.IsNullOrWhiteSpace(newId)) if (!string.IsNullOrWhiteSpace(newId))
{ {
Toaster.ShowSuccess($"'{Company.Name}' er oprettet i CRM."); Toaster.ShowSuccess($"'{Company.Name}' er oprettet i CRM.");
@ -181,7 +129,7 @@ namespace Wonky.Client.Pages
Working = false; Working = false;
} }
private void HandleFieldChanged(object sender, FieldChangedEventArgs e) private void HandleFieldChanged(object sender, FieldChangedEventArgs e)
{ {
NextVisit = LastVisit.AddDays(7 * Company.Interval); NextVisit = LastVisit.AddDays(7 * Company.Interval);
@ -193,20 +141,22 @@ namespace Wonky.Client.Pages
} }
else else
{ {
FormInvalid = !CompanyContext.Validate(); FormInvalid = !CompanyContext.Validate();
} }
StateHasChanged(); StateHasChanged();
} }
private void ValidationChanged(object sender, ValidationStateChangedEventArgs e) private void ValidationChanged(object sender, ValidationStateChangedEventArgs e)
{ {
FormInvalid = true; FormInvalid = true;
CompanyContext.OnFieldChanged -= HandleFieldChanged; CompanyContext.OnFieldChanged -= HandleFieldChanged;
CompanyContext = new EditContext(Company); CompanyContext = new EditContext(Company);
FormInvalid = !CompanyContext.Validate(); FormInvalid = !CompanyContext.Validate();
CompanyContext.OnFieldChanged += HandleFieldChanged; CompanyContext.OnFieldChanged += HandleFieldChanged;
CompanyContext.OnValidationStateChanged -= ValidationChanged; CompanyContext.OnValidationStateChanged -= ValidationChanged;
} }
@ -218,5 +168,4 @@ namespace Wonky.Client.Pages
CompanyContext.OnValidationStateChanged -= ValidationChanged; CompanyContext.OnValidationStateChanged -= ValidationChanged;
} }
} }
} }

View file

@ -16,6 +16,7 @@
*@ *@
@using Wonky.Client.Components @using Wonky.Client.Components
@using Wonky.Client.OverlayCustomer
@using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Authorization
@page "/advisor/customers/{CompanyId}/h/i" @page "/advisor/customers/{CompanyId}/h/i"
@attribute [Authorize(Roles = "Advisor")] @attribute [Authorize(Roles = "Advisor")]
@ -34,9 +35,9 @@
<CustomerInventoryListComponent OnReorderSelected="OnReorderCallback" CompanyId="@CompanyId" Inventory="@Inventory"/> <CustomerInventoryListComponent OnReorderSelected="OnReorderCallback" CompanyId="@CompanyId" Inventory="@Inventory"/>
<CustomerInventoryReorderModalOverlay OnSelected="@OnSelectedItem" CompanyId="@CompanyId" SalesItem="@SalesItem" @ref="CustomerInventoryReorderOverlay"/>
@if (Working) @if (Working)
{ {
<WorkingThreeDots/> <WorkingThreeDots/>
} }
<CustomerInventoryReorderOverlay OnSelected="@OnSelectedItem" CompanyId="@CompanyId" SalesItem="@SalesItem" @ref="ReorderOverlay"/>

View file

@ -21,21 +21,23 @@ using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors; using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces; using Wonky.Client.HttpInterfaces;
using Wonky.Client.Models; using Wonky.Client.Models;
using Wonky.Client.OverlayCustomer;
using Wonky.Client.Shared; using Wonky.Client.Shared;
using Wonky.Entity.DTO; using Wonky.Entity.DTO;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Pages; namespace Wonky.Client.Pages;
public partial class AdvisorCustomerInventoryListPage : IDisposable public partial class AdvisorCustomerInventoryListPage : IDisposable
{ {
[Inject] private IAdvisorCustomerHistoryRepository CustomerHistory { get; set; } [Inject] private IAdvisorCustomerHistoryRepository HistoryRepo { get; set; }
[Inject] private IAdvisorCustomerRepository Customers { get; set; } [Inject] private IAdvisorCustomerRepository CustomerREpo { get; set; }
[Inject] private HttpInterceptorService Interceptor { get; set; } [Inject] private HttpInterceptorService Interceptor { get; set; }
[Inject] private IToastService Toaster { get; set; } [Inject] private IToastService Toaster { get; set; }
[Inject] private ILogger<AdvisorCustomerInventoryListPage> Logger { get; set; } [Inject] private ILogger<AdvisorCustomerInventoryListPage> Logger { get; set; }
[Inject] private ILocalStorageService Storage { get; set; } [Inject] private ILocalStorageService Storage { get; set; }
[Inject] private ICountryCatalogRepository Catalog { get; set; } [Inject] private ICountryCatalogRepository CatalogRepo { get; set; }
[CascadingParameter] public DraftStateProvider DraftStateProvider { get; set; } = new(); [CascadingParameter] public DraftStateProvider DraftStateProvider { get; set; } = new();
[Parameter] public string CompanyId { get; set; } = ""; [Parameter] public string CompanyId { get; set; } = "";
@ -45,7 +47,7 @@ public partial class AdvisorCustomerInventoryListPage : IDisposable
private CompanyDto Company { get; set; } = new(); private CompanyDto Company { get; set; } = new();
private bool Working { get; set; } = true; private bool Working { get; set; } = true;
private SalesItemView SalesItem { get; set; } = new(); private SalesItemView SalesItem { get; set; } = new();
private CustomerInventoryReorderModalOverlay CustomerInventoryReorderOverlay { get; set; } = new(); private CustomerInventoryReorderOverlay ReorderOverlay { get; set; } = new();
private List<ProductInventoryView> Inventory { get; set; } = new(); private List<ProductInventoryView> Inventory { get; set; } = new();
@ -54,7 +56,7 @@ public partial class AdvisorCustomerInventoryListPage : IDisposable
Interceptor.RegisterEvent(); Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent(); Interceptor.RegisterBeforeSendEvent();
Company = await Customers.GetCompanyById(CompanyId); Company = await CustomerREpo.GetCompanyById(CompanyId);
// fetch product inventory // fetch product inventory
await FetchProductInventory(); await FetchProductInventory();
@ -65,8 +67,8 @@ public partial class AdvisorCustomerInventoryListPage : IDisposable
private async Task OnReorderCallback(string sku) private async Task OnReorderCallback(string sku)
{ {
// fetch item from http repo // fetch item from http repo
SalesItem = await Catalog.GetSalesItemSku(Company.CountryCode.ToLower(), sku); SalesItem = await CatalogRepo.GetSalesItemSku(Company.CountryCode.ToLower(), sku);
CustomerInventoryReorderOverlay.Show(); ReorderOverlay.Show();
} }
private async Task OnSelectedItem(DraftItem draftItem) private async Task OnSelectedItem(DraftItem draftItem)
@ -93,7 +95,7 @@ public partial class AdvisorCustomerInventoryListPage : IDisposable
} }
Logger.LogDebug("pulling products from backend"); Logger.LogDebug("pulling products from backend");
// fetch product history // fetch product history
Inventory = await CustomerHistory.FetchInventory(CompanyId); Inventory = await HistoryRepo.FetchInventory(CompanyId);
// default sort order by description // default sort order by description
if (Inventory.Any()) if (Inventory.Any())
Inventory = Inventory.OrderBy(x => x.Description).ToList(); Inventory = Inventory.OrderBy(x => x.Description).ToList();

View file

@ -16,6 +16,7 @@
*@ *@
@using Wonky.Client.Components @using Wonky.Client.Components
@using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Authorization
@using Wonky.Client.OverlayCustomer
@page "/advisor/customers/{CompanyId}/invoices" @page "/advisor/customers/{CompanyId}/invoices"
@attribute [Authorize(Roles = "Advisor")] @attribute [Authorize(Roles = "Advisor")]
<PageTitle>Faktura Oversigt for @Company.Name</PageTitle> <PageTitle>Faktura Oversigt for @Company.Name</PageTitle>
@ -33,10 +34,11 @@
</div> </div>
</div> </div>
<CustomerInvoiceListComponent OnShowInvoice="CallInvoiceModal" CompanyId="@_companyId" InvoiceList="@CompanyInvoices.Invoices"/> <CustomerInvoiceListComponent OnShowInvoice="CallInvoiceModal" CompanyId="@_companyId" InvoiceList="@CompanyInvoices.Invoices"/>
<CustomerInvoiceViewModalOverlay CompanyId="@_companyId" InvoiceId="@InvoiceId" @ref="CustomerInvoiceView" />
} }
@if (Working) @if (Working)
{ {
<WorkingThreeDots /> <WorkingThreeDots />
} }
<CustomerInvoiceViewOverlay CompanyId="@_companyId" InvoiceId="@InvoiceId" @ref="CustomerInvoiceView" />

View file

@ -20,9 +20,10 @@ using Blazored.Toast.Services;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors; using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces; using Wonky.Client.HttpInterfaces;
using Wonky.Client.Shared; using Wonky.Client.OverlayCustomer;
using Wonky.Entity.DTO; using Wonky.Entity.DTO;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Pages; namespace Wonky.Client.Pages;
@ -37,7 +38,7 @@ public partial class AdvisorCustomerInvoiceListPage : IDisposable
[Inject] private ILogger<AdvisorCustomerInvoiceListPage> Logger { get; set; } [Inject] private ILogger<AdvisorCustomerInvoiceListPage> Logger { get; set; }
private InvoiceListView CompanyInvoices { get; set; } = new(); private InvoiceListView CompanyInvoices { get; set; } = new();
private CompanyDto Company { get; set; } = new(); private CompanyDto Company { get; set; } = new();
private CustomerInvoiceViewModalOverlay CustomerInvoiceView { get; set; } = new(); private CustomerInvoiceViewOverlay CustomerInvoiceView { get; set; } = new();
private string InvoiceId { get; set; } = ""; private string InvoiceId { get; set; } = "";
private bool Working { get; set; } private bool Working { get; set; }
private bool AllSet { get; set; } private bool AllSet { get; set; }

View file

@ -39,13 +39,6 @@
data-bs-toggle="button" aria-pressed="@IncludeFolded" @onclick="OnFoldedClick"> data-bs-toggle="button" aria-pressed="@IncludeFolded" @onclick="OnFoldedClick">
@ButtonFoldedText @ButtonFoldedText
</button> </button>
@*
<div class="form-check">
<input type="checkbox" id="folded" class="form-check-input" checked="@IncludeFolded" @onclick="OnFoldedClick" >
<label for="folded" class="form-check-label">Ophørte</label>
</div>
*@
</div> </div>
<div class="col-sm-8"> <div class="col-sm-8">
<PaginationComponent MetaData="PageData" Spread="2" SelectedPage="SelectedPage"/> <PaginationComponent MetaData="PageData" Spread="2" SelectedPage="SelectedPage"/>
@ -56,7 +49,7 @@
</div> </div>
</div> </div>
<AdvisorCustomerListComponent CompanyList="Companies" OnDelete="DeleteCompany" /> <AdvisorCustomerListComponent CompanyList="CompanyList" OnDelete="DeleteCompany" />
@if (Working) @if (Working)
{ {

View file

@ -15,13 +15,14 @@
// //
using Blazored.LocalStorage; using Blazored.LocalStorage;
using Wonky.Client.HttpInterceptors;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces; using Wonky.Client.HttpInterfaces;
using Wonky.Client.Services; using Wonky.Client.Services;
using Wonky.Entity.DTO; using Wonky.Entity.DTO;
using Wonky.Entity.Requests; using Wonky.Entity.Requests;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Pages namespace Wonky.Client.Pages
{ {
@ -32,7 +33,7 @@ namespace Wonky.Client.Pages
[Inject] private IAdvisorCustomerRepository CompanyRepo { get; set; } [Inject] private IAdvisorCustomerRepository CompanyRepo { get; set; }
[Inject] private HttpInterceptorService Interceptor { get; set; } [Inject] private HttpInterceptorService Interceptor { get; set; }
[Inject] private NavigationManager Navigator { get; set; } [Inject] private NavigationManager Navigator { get; set; }
private List<CompanyDto> Companies { get; set; } = new(); private List<CompanyDto> CompanyList { get; set; } = new();
private UserProfile Profiles { get; set; } = new(); private UserProfile Profiles { get; set; } = new();
private UserInfoView UserInfo { get; set; } = new(); private UserInfoView UserInfo { get; set; } = new();
private string SavedSearch { get; set; } = ""; private string SavedSearch { get; set; } = "";
@ -73,7 +74,7 @@ namespace Wonky.Client.Pages
Working = true; Working = true;
IncludeFolded = !IncludeFolded; IncludeFolded = !IncludeFolded;
ButtonFoldedText = IncludeFolded ? "Vis Aktive" : "Vis Ophørte"; ButtonFoldedText = IncludeFolded ? "Vis Aktive" : "Vis Ophørte";
Companies = new List<CompanyDto>(); CompanyList = new List<CompanyDto>();
Paging.PageNumber = 1; Paging.PageNumber = 1;
Paging.HasFolded = IncludeFolded ? 1 : 0; Paging.HasFolded = IncludeFolded ? 1 : 0;
await FetchCustomers(); await FetchCustomers();
@ -81,21 +82,21 @@ namespace Wonky.Client.Pages
private async Task SelectedPage(int page) private async Task SelectedPage(int page)
{ {
Companies = new List<CompanyDto>(); CompanyList = new List<CompanyDto>();
Paging.PageNumber = page; Paging.PageNumber = page;
await FetchCustomers(); await FetchCustomers();
} }
private async Task SetSearchCol(string searchColumn) private async Task SetSearchCol(string searchColumn)
{ {
Companies = new List<CompanyDto>(); CompanyList = new List<CompanyDto>();
Paging.SearchColumn = searchColumn; Paging.SearchColumn = searchColumn;
Paging.PageNumber = 1; Paging.PageNumber = 1;
await FetchCustomers(); await FetchCustomers();
} }
private async Task SetPageSize(string pageSize) private async Task SetPageSize(string pageSize)
{ {
Companies = new List<CompanyDto>(); CompanyList = new List<CompanyDto>();
Paging.PageSize = Convert.ToInt32(pageSize); Paging.PageSize = Convert.ToInt32(pageSize);
Paging.PageNumber = 1; Paging.PageNumber = 1;
await FetchCustomers(); await FetchCustomers();
@ -103,7 +104,7 @@ namespace Wonky.Client.Pages
private async Task SetSearchPhrase(string searchTerm) private async Task SetSearchPhrase(string searchTerm)
{ {
Companies = new List<CompanyDto>(); CompanyList = new List<CompanyDto>();
Paging.PageNumber = 1; Paging.PageNumber = 1;
Paging.SearchTerm = searchTerm; Paging.SearchTerm = searchTerm;
await FetchCustomers(); await FetchCustomers();
@ -111,7 +112,7 @@ namespace Wonky.Client.Pages
private async Task SetSortCol(string orderBy) private async Task SetSortCol(string orderBy)
{ {
Companies = new List<CompanyDto>(); CompanyList = new List<CompanyDto>();
Paging.OrderBy = orderBy; Paging.OrderBy = orderBy;
await FetchCustomers(); await FetchCustomers();
} }
@ -122,9 +123,9 @@ namespace Wonky.Client.Pages
/// <param name="companyId"></param> /// <param name="companyId"></param>
private async Task DeleteCompany(string companyId) private async Task DeleteCompany(string companyId)
{ {
Companies = new List<CompanyDto>(); CompanyList = new List<CompanyDto>();
await CompanyRepo.DeleteCompany(companyId); await CompanyRepo.DeleteCompany(companyId);
if (Paging.PageNumber > 1 && Companies.Count == 1) if (Paging.PageNumber > 1 && CompanyList.Count == 1)
Paging.PageNumber--; Paging.PageNumber--;
await FetchCustomers(); await FetchCustomers();
} }
@ -136,12 +137,12 @@ namespace Wonky.Client.Pages
Working = false; Working = false;
if (pageRes.Items.Any()) if (pageRes.Items.Any())
{ {
Companies = pageRes.Items; CompanyList = pageRes.Items;
PageData = pageRes.MetaData; PageData = pageRes.MetaData;
} }
else else
{ {
Companies = new List<CompanyDto>(); CompanyList = new List<CompanyDto>();
PageData = new MetaData(); PageData = new MetaData();
} }
} }

View file

@ -242,12 +242,12 @@
</EditForm> </EditForm>
} }
<VatLookupDkModal VatAddress="CompanyVatAddress" EntityName="@Company.Name" VatNumber="@Company.VatNumber"
@ref="VatLookupPopup" OnSelectedCompany="SelectedCompanyCallback" />
<ContactModal ParamContact="@SelectedContact" CompanyName="@Company.Name"
@ref="ContactPopup" OnSaveClicked="WriteContactCallback" OnDeleteClicked="DeleteContactCallback"/>
@if (Working) @if (Working)
{ {
<WorkingThreeDots /> <WorkingThreeDots />
} }
<VatLookupDkModal VatAddress="CompanyVatAddress" EntityName="@Company.Name" VatNumber="@Company.VatNumber"
@ref="VatLookupPopup" OnSelectedCompany="SelectedCompanyCallback" />
<ContactModal ParamContact="@SelectedContact" CompanyName="@Company.Name"
@ref="ContactPopup" OnSaveClicked="WriteContactCallback" OnDeleteClicked="DeleteContactCallback"/>

View file

@ -18,10 +18,10 @@ using System.Text.Json;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Blazored.LocalStorage; using Blazored.LocalStorage;
using Blazored.Toast.Services; using Blazored.Toast.Services;
using Wonky.Client.HttpInterceptors;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms; using Microsoft.AspNetCore.Components.Forms;
using Wonky.Client.Helpers; using Wonky.Client.Helpers;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces; using Wonky.Client.HttpInterfaces;
using Wonky.Client.Models; using Wonky.Client.Models;
using Wonky.Client.Services; using Wonky.Client.Services;
@ -29,6 +29,7 @@ using Wonky.Client.Shared;
using Wonky.Entity.DTO; using Wonky.Entity.DTO;
using Wonky.Entity.Models; using Wonky.Entity.Models;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Pages; namespace Wonky.Client.Pages;
@ -44,6 +45,7 @@ public partial class AdvisorCustomerViewPage : IDisposable
[Inject] private HttpInterceptorService Interceptor { get; set; } [Inject] private HttpInterceptorService Interceptor { get; set; }
[Inject] private VatInfoLookupService VatService { get; set; } [Inject] private VatInfoLookupService VatService { get; set; }
[Inject] private ILocalStorageService Storage { get; set; } [Inject] private ILocalStorageService Storage { get; set; }
private readonly JsonSerializerOptions _options = new () { PropertyNameCaseInsensitive = true }; private readonly JsonSerializerOptions _options = new () { PropertyNameCaseInsensitive = true };
private CompanyDto Company { get; set; } = new(); private CompanyDto Company { get; set; } = new();
private EditContext ErpContext { get; set; } private EditContext ErpContext { get; set; }
@ -142,7 +144,7 @@ public partial class AdvisorCustomerViewPage : IDisposable
// remove loading image // remove loading image
Working = false; Working = false;
await Task.Delay(100);
await RequestErpUpdate(); await RequestErpUpdate();
} }
@ -151,7 +153,7 @@ public partial class AdvisorCustomerViewPage : IDisposable
if(Working) if(Working)
return; return;
Working = true; Working = true;
await HistoryRepo.InvoiceErpToCrmRpc(CompanyId, Company.HistorySync); Company.HistorySync = await HistoryRepo.InvoiceErpToCrmRpc(CompanyId, Company.HistorySync);
Working = false; Working = false;
} }

View file

@ -56,7 +56,7 @@
</div> </div>
</div> </div>
<QuoteListComponent Quotes="_quotes" OnChangedCallback="UpdateQuoteCallback" /> <QuoteListComponent Quotes="FilteredQuotes" OnChangedCallback="UpdateQuoteCallback" />
@if (Working) @if (Working)
{ {

View file

@ -22,6 +22,7 @@ using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpInterfaces; using Wonky.Client.HttpInterfaces;
using Wonky.Client.Models; using Wonky.Client.Models;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Pages; namespace Wonky.Client.Pages;
@ -32,8 +33,8 @@ public partial class AdvisorQuoteListPage : IDisposable
[Inject] private ILogger<AdvisorQuoteListPage> Logger { get; set; } [Inject] private ILogger<AdvisorQuoteListPage> Logger { get; set; }
[Inject] private IToastService Toaster { get; set; } [Inject] private IToastService Toaster { get; set; }
[Inject] private ILocalStorageService Storage { get; set; } [Inject] private ILocalStorageService Storage { get; set; }
private List<ReportItemView> Quotes { get; set; } = new(); private List<ReportItemView> QuoteList { get; set; } = new();
private List<ReportItemView> _quotes { get; set; } = new(); private List<ReportItemView> FilteredQuotes { get; set; } = new();
private bool Working { get; set; } private bool Working { get; set; }
private QStatus QFilter { get; set; } = QStatus.NoteOpen; private QStatus QFilter { get; set; } = QStatus.NoteOpen;
@ -42,34 +43,34 @@ public partial class AdvisorQuoteListPage : IDisposable
Interceptor.RegisterEvent(); Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent(); Interceptor.RegisterBeforeSendEvent();
Working = true; Working = true;
Quotes = await AdvisorActivityRepo.GetQuotes(); QuoteList = await AdvisorActivityRepo.GetQuotes();
await Storage.SetItemAsync("quotes", Quotes.OrderBy(x => x.Company.Name)); await Storage.SetItemAsync("quotes", QuoteList.OrderBy(x => x.Company.Name));
Working = false; Working = false;
// filter quotes - if any - default to QStatus.NoteOpen // filter quotes - if any - default to QStatus.NoteOpen
if (Quotes.Any()) if (QuoteList.Any())
await FilterQuotes(QFilter); await FilterQuotes(QFilter);
} }
private async Task FilterQuotes(QStatus status) private async Task FilterQuotes(QStatus status)
{ {
QFilter = status; QFilter = status;
Quotes = await Storage.GetItemAsync<List<ReportItemView>>("quotes"); QuoteList = await Storage.GetItemAsync<List<ReportItemView>>("quotes");
_quotes = QFilter switch FilteredQuotes = QFilter switch
{ {
QStatus.None => Quotes.Where(x => x.QuoteStatusEnum is "None").ToList(), QStatus.None => QuoteList.Where(x => x.QuoteStatusEnum is "None").ToList(),
QStatus.Lose => Quotes.Where(x => x.QuoteStatusEnum is "Lose").ToList(), QStatus.Lose => QuoteList.Where(x => x.QuoteStatusEnum is "Lose").ToList(),
QStatus.Archive => Quotes.Where(x => x.QuoteStatusEnum is "Archive").ToList(), QStatus.Archive => QuoteList.Where(x => x.QuoteStatusEnum is "Archive").ToList(),
QStatus.Note => Quotes.Where(x => x.QuoteStatusEnum is "Note").ToList(), QStatus.Note => QuoteList.Where(x => x.QuoteStatusEnum is "Note").ToList(),
QStatus.NoteOpen => Quotes.Where(x => x.QuoteStatusEnum is "Note" or "None").ToList(), QStatus.NoteOpen => QuoteList.Where(x => x.QuoteStatusEnum is "Note" or "None").ToList(),
_ => Quotes.ToList() _ => QuoteList.ToList()
}; };
} }
private async Task UpdateQuoteCallback(QCallbackArgs args) private async Task UpdateQuoteCallback(QuoteCallbackArgs args)
{ {
Working = true; Working = true;
// find the quote to update // find the quote to update
var quote = Quotes.First(x => x.ESalesNumber == args.ESalesNumber); var quote = QuoteList.First(x => x.ESalesNumber == args.ESalesNumber);
if (args.Status == QStatus.Win) if (args.Status == QStatus.Win)
quote.OrderDate = $"{DateTime.Now:yyyy-MM-dd}"; quote.OrderDate = $"{DateTime.Now:yyyy-MM-dd}";
quote.QuoteStatusEnum = Utils.EnumToString(args.Status); quote.QuoteStatusEnum = Utils.EnumToString(args.Status);
@ -77,13 +78,13 @@ public partial class AdvisorQuoteListPage : IDisposable
var response = await AdvisorActivityRepo.UpdateQuoteStatus(quote); var response = await AdvisorActivityRepo.UpdateQuoteStatus(quote);
Toaster.ShowInfo($"{response.Message}", $"HTTP STATUS {response.Code}"); Toaster.ShowInfo($"{response.Message}", $"HTTP STATUS {response.Code}");
// clear and reload quotes // clear and reload quotes
Quotes = new List<ReportItemView>(); QuoteList = new List<ReportItemView>();
await Storage.RemoveItemAsync("quotes"); await Storage.RemoveItemAsync("quotes");
Quotes = await AdvisorActivityRepo.GetQuotes(); QuoteList = await AdvisorActivityRepo.GetQuotes();
// store quotes in local storage // store quotes in local storage
await Storage.SetItemAsync("quotes", Quotes.OrderBy(x => x.Company.Name)); await Storage.SetItemAsync("quotes", QuoteList.OrderBy(x => x.Company.Name));
// filter quotes - if any - based on active filter // filter quotes - if any - based on active filter
if(Quotes.Any()) if(QuoteList.Any())
await FilterQuotes(QFilter); await FilterQuotes(QFilter);
Working = false; Working = false;
// signal page state changed // signal page state changed

View file

@ -20,7 +20,7 @@
@attribute [Authorize(Roles = "Advisor")] @attribute [Authorize(Roles = "Advisor")]
@page "/advisor/reports/new" @page "/advisor/reports/new"
<PageTitle>Opret Dagsrapport for @_workDate</PageTitle> <PageTitle>Opret Dagsrapport for @ThisWorkDate</PageTitle>
@* report header *@ @* report header *@
<div class="row sticky-top bg-dark text-white rounded-2 mb-2 py-2 align-items-center"> <div class="row sticky-top bg-dark text-white rounded-2 mb-2 py-2 align-items-center">
@ -34,167 +34,168 @@
@* report form *@ @* report form *@
<EditForm EditContext="ReportContext"> <EditForm EditContext="ReportContext">
@* Day info row *@ @* Day info row *@
<div class="row">
<table class="table">
<thead>
<tr class="bg-black opacity-75 text-white">
<th scope="col">Dag / Periode</th>
<th scope="col">Begyndt</th>
<th scope="col">Afsluttet</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<select id="dayType" class="form-select text-bg-primary bg-primary"
@bind-Value="Report.DayTypeEnum" @bind-Value:event="onchange">
<option value="">&rarr; TAG MIG &larr;</option>
<option value="sales">Salgsdag</option>
<option value="meeting">Salgsmøde</option>
<option value="office">Kontordag</option>
<option value="supervisor">Medkørende Supervisor</option>
<option value="sickLeave">Sygdom</option>
<option value="leave">Ferie</option>
</select>
<ValidationMessage For="@(() => Report.DayTypeEnum)"/>
</td>
@if (Report.DayTypeEnum.ToLower().Contains("leave"))
{
Report.Figures.KmMorning = 0;
<td>
<InputDate class="form-control" @bind-Value="BeginLeave"/>
</td>
<td>
<InputDate class="form-control" @bind-Value="EndLeave"/>
</td>
}
else
{
Report.Figures.KmMorning = Profiles.KmMorning;
<td>
<input type="time" id="checkIn" class="form-control"
@bind-Value="_checkIn" @bind-Value:event="oninput" @onchange="OnTimeChanged"/>
</td>
<td>
<input type="time" id="checkOut" class="form-control"
@bind-Value="_checkOut" @bind-Value:event="oninput" @onchange="OnTimeChanged"/>
</td>
}
<td class="text-end">
<button type="button" class="btn btn-warning"
@onclick="GetKeyFigures" disabled="@(!NoFigures)">
Nøgletal
</button>
</td>
<td class="text-end">
<button type="button" class="btn btn-primary"
@onclick="SubmitReport" disabled="@(NoFigures || Working)">
Gem Rapport
</button>
</td>
</tr>
</tbody>
</table>
</div>
@* report details for everything but leave *@
@if (!Report.DayTypeEnum.ToLower().Contains("leave"))
{
<div class="row"> <div class="row">
@* details input *@
<table class="table"> <table class="table">
<thead> <thead>
<tr class="bg-black opacity-75 text-white"> <tr class="bg-black opacity-75 text-white">
<th scope="col" style="width:50%">Beskrivelse</th> <th scope="col">Dag / Periode</th>
<th scope="col">Min medkørende supervisor</th> <th scope="col">Begyndt</th>
<th scope="col">Afsluttet</th>
<th></th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td> <td>
<InputTextArea id="description" class="form-control" @bind-Value="Report.Description"/> <select id="dayType" class="form-select text-bg-primary bg-primary"
<ValidationMessage For="@(() => Report.Description)"/> @bind-Value="Report.DayTypeEnum" @bind-Value:event="onchange">
<option value="">&rarr; TAG MIG &larr;</option>
<option value="sales">Salgsdag</option>
<option value="meeting">Salgsmøde</option>
<option value="office">Kontordag</option>
<option value="supervisor">Medkørende Supervisor</option>
<option value="sickLeave">Sygdom</option>
<option value="leave">Ferie</option>
</select>
<ValidationMessage For="@(() => Report.DayTypeEnum)"/>
</td> </td>
<td> @if (Report.DayTypeEnum.ToLower().Contains("leave"))
<InputText id="supervisedBy" class="form-control" @bind-Value="Report.SupervisedBy"/> {
<ValidationMessage For="@(() => Report.SupervisedBy)"/> Report.Figures.KmMorning = 0;
<td>
<InputDate class="form-control" @bind-Value="BeginLeave"/>
</td>
<td>
<InputDate class="form-control" @bind-Value="EndLeave"/>
</td>
}
else
{
Report.Figures.KmMorning = Profiles.KmMorning;
<td>
<input type="time" id="checkIn" class="form-control"
@bind-Value="CheckIn" @bind-Value:event="oninput" @onchange="OnTimeChanged"/>
</td>
<td>
<input type="time" id="checkOut" class="form-control"
@bind-Value="CheckOut" @bind-Value:event="oninput" @onchange="OnTimeChanged"/>
</td>
}
<td class="text-end">
<button type="button" class="btn btn-warning"
@onclick="GetKeyFigures" disabled="@(!NoFigures)">
Nøgletal
</button>
</td>
<td class="text-end">
<button type="button" class="btn btn-primary"
@onclick="SubmitReport" disabled="@(NoFigures || Working)">
Gem Rapport
</button>
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="row"> @* report details for everything but leave *@
@* distance ledger input *@ @if (!Report.DayTypeEnum.ToLower().Contains("leave"))
<table class="table">
<thead>
<tr class="bg-black opacity-75 text-white">
<th scope="col">Km aften</th>
<th scope="col">Km morgen</th>
<th scope="col">Km dag</th>
<th scope="col">Km måned</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.KmEvening"
disabled="@(NoFigures)"/>
</td>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.KmMorning"
disabled="@(NoFigures)"/>
</td>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.Distance"
disabled />
</td>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.DistanceMonth"
disabled />
</td>
</tr>
</tbody>
</table>
<table class="table">
<thead>
<tr class="bg-black opacity-75 text-white">
<th scope="col">Km privat</th>
<th scope="col">Km privat måned</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.DistancePrivate"
disabled="@(NoFigures)"/>
</td>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.DistancePrivateMonth"
disabled />
</td>
</tr>
</tbody>
</table>
</div>
@if (Activities.Any())
{ {
<div class="row"> <div class="row">
<AdvisorActivityListComponent ActivityList="Activities" /> @* details input *@
<table class="table">
<thead>
<tr class="bg-black opacity-75 text-white">
<th scope="col" style="width:50%">Beskrivelse</th>
<th scope="col">Min medkørende supervisor</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<InputTextArea id="description" class="form-control" @bind-Value="Report.Description"/>
<ValidationMessage For="@(() => Report.Description)"/>
</td>
<td>
<InputText id="supervisedBy" class="form-control" @bind-Value="Report.SupervisedBy"/>
<ValidationMessage For="@(() => Report.SupervisedBy)"/>
</td>
</tr>
</tbody>
</table>
</div> </div>
<div class="row">
@* distance ledger input *@
<table class="table">
<thead>
<tr class="bg-black opacity-75 text-white">
<th scope="col">Km aften</th>
<th scope="col">Km morgen</th>
<th scope="col">Km dag</th>
<th scope="col">Km måned</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.KmEvening"
disabled="@(NoFigures)"/>
</td>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.KmMorning"
disabled="@(NoFigures)"/>
</td>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.Distance"
disabled />
</td>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.DistanceMonth"
disabled />
</td>
</tr>
</tbody>
</table>
<table class="table">
<thead>
<tr class="bg-black opacity-75 text-white">
<th scope="col">Km privat</th>
<th scope="col">Km privat måned</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.DistancePrivate"
disabled="@(NoFigures)"/>
</td>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.DistancePrivateMonth"
disabled />
</td>
</tr>
</tbody>
</table>
</div>
@if (Activities.Any())
{
<div class="row">
<AdvisorActivityListComponent ActivityList="Activities" />
</div>
}
} }
} <div class="row">
<div class="row"> @* ledger summaries calculated *@
@* ledger summaries calculated *@ <AdvisorReportActivityLedgerComponent ReportData="Report.Figures" />
<AdvisorReportActivityLedgerComponent ReportData="Report.Figures" /> </div>
</div>
</EditForm> </EditForm>
<ConfirmationModal BodyMessage="@Prompt" OnOkClicked="ConfirmReportCallback" OnCancelClicked="OnCancelCallback" @ref="ConfirmReportModal"/>
@if (Working) @if (Working)
{ {
<WorkingThreeDots /> <WorkingThreeDots />
} }
<ConfirmationModal BodyMessage="@Prompt" OnOkClicked="ConfirmReportCallback" OnCancelClicked="OnCancelCallback" @ref="ConfirmReportModal"/>

View file

@ -25,6 +25,7 @@ using Wonky.Client.Services;
using Wonky.Client.Shared; using Wonky.Client.Shared;
using Wonky.Entity.DTO; using Wonky.Entity.DTO;
using Wonky.Entity.Views; using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Pages; namespace Wonky.Client.Pages;
@ -40,21 +41,21 @@ public partial class AdvisorReportCreatePage : IDisposable
private EditContext ReportContext { get; set; } private EditContext ReportContext { get; set; }
private ReportDto Report { get; set; } = new(); private ReportDto Report { get; set; } = new();
private List<ReportItemView> Activities { get; set; } = new(); private List<ReportItemView> Activities { get; set; } = new();
private ReportFiguresDto InitialValues { get; set; } private ReportFiguresDto InitialValues { get; set; } = new();
private UserProfile Profiles { get; set; } = new(); private UserProfile Profiles { get; set; } = new();
private bool FormInvalid { get; set; } = true; private bool FormInvalid { get; set; } = true;
private bool NoFigures { get; set; } = true; private bool NoFigures { get; set; } = true;
private bool Working { get; set; } private bool Working { get; set; }
private DateTime _workDate { get; set; } private DateTime ThisWorkDate { get; set; }
private TimeOnly _checkIn { get; set; } = new(12, 0); private TimeOnly CheckIn { get; set; } = new(12, 0);
private TimeOnly _checkOut { get; set; } = new(12, 0); private TimeOnly CheckOut { get; set; } = new(12, 0);
private DateTime BeginLeave { get; set; } = DateTime.Now; private DateTime BeginLeave { get; set; } = DateTime.Now;
private DateTime EndLeave { get; set; } = DateTime.Now; private DateTime EndLeave { get; set; } = DateTime.Now;
private ConfirmationModal ConfirmReportModal { get; set; } private ConfirmationModal ConfirmReportModal { get; set; }
private string Prompt { get; set; } = ""; private string Prompt { get; set; } = "";
private string WorkDate { get; set; } = ""; private string WorkDate { get; set; } = "";
private int currKmMonth { get; set; } private int CurrKmMonth { get; set; }
private int currKmPrivate { get; set; } private int CurrKmPrivate { get; set; }
/// <summary> /// <summary>
/// OnInitialized /// OnInitialized
@ -75,23 +76,23 @@ public partial class AdvisorReportCreatePage : IDisposable
WorkDate = Profiles.WorkDate; WorkDate = Profiles.WorkDate;
if (string.IsNullOrWhiteSpace(WorkDate)) if (string.IsNullOrWhiteSpace(WorkDate))
{ {
_workDate = DateTime.Now; ThisWorkDate = DateTime.Now;
WorkDate = $"{_workDate:yyyy-MM-dd}"; WorkDate = $"{ThisWorkDate:yyyy-MM-dd}";
await ProfileService.SetWorkDate(_workDate); await ProfileService.SetWorkDate(ThisWorkDate);
} }
else else
{ {
_workDate = DateTime.Parse(WorkDate); ThisWorkDate = DateTime.Parse(WorkDate);
} }
if(await AdvisorReportRepo.ReportExist(WorkDate)) if(await AdvisorReportRepo.ReportExist(WorkDate))
Navigator.NavigateTo($"/advisor/reports/view/{_workDate:yyyy-MM-dd}"); Navigator.NavigateTo($"/advisor/reports/view/{ThisWorkDate:yyyy-MM-dd}");
BeginLeave = _workDate; BeginLeave = ThisWorkDate;
EndLeave = _workDate; EndLeave = ThisWorkDate;
Report.FromDateTime = $"{_workDate:yyyy-MM-dd'T'12:00:00}"; Report.FromDateTime = $"{ThisWorkDate:yyyy-MM-dd'T'12:00:00}";
Report.ToDateTime = $"{_workDate:yyyy-MM-dd'T'12:00:00}"; Report.ToDateTime = $"{ThisWorkDate:yyyy-MM-dd'T'12:00:00}";
Report.Figures.KmMorning = 0; Report.Figures.KmMorning = 0;
Report.Figures.KmEvening = 0; Report.Figures.KmEvening = 0;
@ -122,13 +123,13 @@ public partial class AdvisorReportCreatePage : IDisposable
var data = await AdvisorReportRepo.InitializeReportData(WorkDate); var data = await AdvisorReportRepo.InitializeReportData(WorkDate);
if(data.ReportClosed) if(data.ReportClosed)
Navigator.NavigateTo($"/advisor/reports/view/{_workDate:yyyy-MM-dd}"); Navigator.NavigateTo($"/advisor/reports/view/{ThisWorkDate:yyyy-MM-dd}");
Report.Figures = data.ReportData; Report.Figures = data.ReportData;
InitialValues = data.ReportData; InitialValues = data.ReportData;
Activities = data.ReportItems; Activities = data.ReportItems;
currKmMonth = data.ReportData.DistanceMonth; CurrKmMonth = data.ReportData.DistanceMonth;
currKmPrivate = data.ReportData.DistancePrivate; CurrKmPrivate = data.ReportData.DistancePrivate;
if (Report.DayTypeEnum.ToLower().Contains("leave")) if (Report.DayTypeEnum.ToLower().Contains("leave"))
{ {
// ensure no distances in calculation // ensure no distances in calculation
@ -154,8 +155,8 @@ public partial class AdvisorReportCreatePage : IDisposable
// Console.WriteLine($"e FieldName => {e.FieldIdentifier.FieldName}"); // Console.WriteLine($"e FieldName => {e.FieldIdentifier.FieldName}");
FormInvalid = !ReportContext.Validate(); FormInvalid = !ReportContext.Validate();
Report.Figures.Distance = Report.Figures.KmEvening - Report.Figures.KmMorning; Report.Figures.Distance = Report.Figures.KmEvening - Report.Figures.KmMorning;
Report.Figures.DistanceMonth = Report.Figures.Distance + currKmMonth; Report.Figures.DistanceMonth = Report.Figures.Distance + CurrKmMonth;
Report.Figures.DistancePrivateMonth = Report.Figures.DistancePrivate + currKmPrivate; Report.Figures.DistancePrivateMonth = Report.Figures.DistancePrivate + CurrKmPrivate;
if (Report.Figures.Distance is > 1000 or < 0) if (Report.Figures.Distance is > 1000 or < 0)
{ {
Toaster.ShowError($"Kørte km for rapporten er '{Report.Figures.Distance}'. Er du sikker på at det er rigtigt?", "KM tal"); Toaster.ShowError($"Kørte km for rapporten er '{Report.Figures.Distance}'. Er du sikker på at det er rigtigt?", "KM tal");
@ -195,7 +196,7 @@ public partial class AdvisorReportCreatePage : IDisposable
await ProfileService.SetKmMorning(0); await ProfileService.SetKmMorning(0);
// reset date confirmed // reset date confirmed
await ProfileService.SetDateConfirmed(false); await ProfileService.SetDateConfirmed(false);
Navigator.NavigateTo($"/advisor/reports/view/{_workDate:yyyy-MM-dd}"); Navigator.NavigateTo($"/advisor/reports/view/{ThisWorkDate:yyyy-MM-dd}");
} }
/// <summary> /// <summary>
@ -229,8 +230,8 @@ public partial class AdvisorReportCreatePage : IDisposable
} }
else else
{ {
checkIn = new DateTime(_workDate.Year, _workDate.Month, _workDate.Day, _checkIn.Hour, _checkIn.Minute, 0); checkIn = new DateTime(ThisWorkDate.Year, ThisWorkDate.Month, ThisWorkDate.Day, CheckIn.Hour, CheckIn.Minute, 0);
checkOut = new DateTime(_workDate.Year, _workDate.Month, _workDate.Day, _checkOut.Hour, _checkOut.Minute, 0); checkOut = new DateTime(ThisWorkDate.Year, ThisWorkDate.Month, ThisWorkDate.Day, CheckOut.Hour, CheckOut.Minute, 0);
} }
// assign a workday number if the day is marked as salesDay // assign a workday number if the day is marked as salesDay
Report.SalesDayNumber = Report.DayTypeEnum == "sales" ? Report.Figures.SalesDayCount + 1 : 0; Report.SalesDayNumber = Report.DayTypeEnum == "sales" ? Report.Figures.SalesDayCount + 1 : 0;
@ -238,7 +239,7 @@ public partial class AdvisorReportCreatePage : IDisposable
Report.FromDateTime = checkIn.ToString("yyyy-MM-dd'T'HH:mm:ss", CultureInfo.InvariantCulture); Report.FromDateTime = checkIn.ToString("yyyy-MM-dd'T'HH:mm:ss", CultureInfo.InvariantCulture);
Report.ToDateTime = checkOut.ToString("yyyy-MM-dd'T'HH:mm:ss", CultureInfo.InvariantCulture); Report.ToDateTime = checkOut.ToString("yyyy-MM-dd'T'HH:mm:ss", CultureInfo.InvariantCulture);
Logger.LogDebug("_workDate => {workDate}", $"{_workDate:yyyy-MM-dd}"); Logger.LogDebug("_workDate => {workDate}", $"{ThisWorkDate:yyyy-MM-dd}");
Logger.LogDebug("_report => {report}", JsonSerializer.Serialize(Report)); Logger.LogDebug("_report => {report}", JsonSerializer.Serialize(Report));
if (Report.DayTypeEnum is "leave" or "sickLeave") if (Report.DayTypeEnum is "leave" or "sickLeave")
@ -246,8 +247,8 @@ public partial class AdvisorReportCreatePage : IDisposable
// reset distance calculation // reset distance calculation
Report.Figures.KmEvening = 0; Report.Figures.KmEvening = 0;
Report.Figures.KmMorning = 0; Report.Figures.KmMorning = 0;
Report.Figures.DistanceMonth = currKmMonth; Report.Figures.DistanceMonth = CurrKmMonth;
Report.Figures.DistancePrivateMonth = currKmPrivate; Report.Figures.DistancePrivateMonth = CurrKmPrivate;
} }
// pop confirmation // pop confirmation
@ -255,7 +256,7 @@ public partial class AdvisorReportCreatePage : IDisposable
var warning = Report.Figures.KmEvening - Report.Figures.KmMorning > 1000 ? var warning = Report.Figures.KmEvening - Report.Figures.KmMorning > 1000 ?
$"Kørte km for rapporten er '{Report.Figures.KmEvening - Report.Figures.KmMorning}'. Er du sikker på at det er rigtigt?<br/>" : ""; $"Kørte km for rapporten er '{Report.Figures.KmEvening - Report.Figures.KmMorning}'. Er du sikker på at det er rigtigt?<br/>" : "";
Prompt = $"{warning}<br/>Gem rapport for {_workDate.ToLongDateString()}?"; Prompt = $"{warning}<br/>Gem rapport for {ThisWorkDate.ToLongDateString()}?";
ConfirmReportModal.Show(); ConfirmReportModal.Show();
} }
@ -265,10 +266,10 @@ public partial class AdvisorReportCreatePage : IDisposable
/// </summary> /// </summary>
private void OnTimeChanged() private void OnTimeChanged()
{ {
var f = new DateTime(_workDate.Year, _workDate.Month, _workDate.Day, _checkIn.Hour, _checkIn.Minute,0); var f = new DateTime(ThisWorkDate.Year, ThisWorkDate.Month, ThisWorkDate.Day, CheckIn.Hour, CheckIn.Minute,0);
Report.FromDateTime = $"{f:yyyy-MM-dd'T'HH:mm}"; Report.FromDateTime = $"{f:yyyy-MM-dd'T'HH:mm}";
var t = new DateTime(_workDate.Year, _workDate.Month, _workDate.Day, _checkOut.Hour, _checkOut.Minute,0); var t = new DateTime(ThisWorkDate.Year, ThisWorkDate.Month, ThisWorkDate.Day, CheckOut.Hour, CheckOut.Minute,0);
Report.ToDateTime = $"{t:yyyy-MM-dd'T'HH:mm}"; Report.ToDateTime = $"{t:yyyy-MM-dd'T'HH:mm}";
} }
@ -279,7 +280,7 @@ public partial class AdvisorReportCreatePage : IDisposable
private void SetWorkDateCallback(string workDate) private void SetWorkDateCallback(string workDate)
{ {
WorkDate = workDate; WorkDate = workDate;
_workDate = DateTime.Parse(workDate); ThisWorkDate = DateTime.Parse(workDate);
NoFigures = true; NoFigures = true;
Report.Figures = new ReportFiguresDto(); Report.Figures = new ReportFiguresDto();
@ -292,8 +293,8 @@ public partial class AdvisorReportCreatePage : IDisposable
Report.Figures.DistanceMonth = 0; Report.Figures.DistanceMonth = 0;
Report.Figures.DistancePrivate = 0; Report.Figures.DistancePrivate = 0;
Report.Figures.DistancePrivateMonth = 0; Report.Figures.DistancePrivateMonth = 0;
Report.FromDateTime = $"{_workDate:yyyy-MM-dd'T'12:00}"; Report.FromDateTime = $"{ThisWorkDate:yyyy-MM-dd'T'12:00}";
Report.ToDateTime = $"{_workDate:yyyy-MM-dd'T'12:00}"; Report.ToDateTime = $"{ThisWorkDate:yyyy-MM-dd'T'12:00}";
} }
private void OnCancelCallback() private void OnCancelCallback()

Some files were not shown because too many files have changed in this diff Show more