WIP: quote listing and status update
This commit is contained in:
parent
7afd67378c
commit
41ce336299
13 changed files with 297 additions and 145 deletions
99
Wonky.Client/Components/QuoteListComponent.razor
Normal file
99
Wonky.Client/Components/QuoteListComponent.razor
Normal file
|
@ -0,0 +1,99 @@
|
|||
@using Wonky.Entity.Views
|
||||
@using Wonky.Client.Models
|
||||
|
||||
<div class="list-group list-group-flush">
|
||||
<div class="list-group-item bg-dark text-white">
|
||||
<div class="row g-3">
|
||||
<div class="col-sm-2">
|
||||
Reference
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
Kunde
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
Dato
|
||||
</div>
|
||||
<div class="col-sm-1">
|
||||
Status
|
||||
</div>
|
||||
<div class="col-sm-3"></div>
|
||||
</div>
|
||||
</div>
|
||||
@if (Quotes.Any())
|
||||
{
|
||||
foreach (var quote in Quotes)
|
||||
{
|
||||
<div class="list-group-item list-group-item-action">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-sm-2">
|
||||
<a class="btn btn-outline-dark d-block" style="font-family:monospace;font-size: 14px;"
|
||||
href="/companies/@quote.Company.CompanyId/quotes/@quote.ActivityId">@quote.ESalesNumber</a>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
@quote.Company.Name
|
||||
</div>
|
||||
<di class="col-sm-2">
|
||||
@quote.OrderDate
|
||||
</di>
|
||||
<div class="col-sm-1">
|
||||
@switch (quote.QuoteStatusEnum)
|
||||
{
|
||||
case "None":
|
||||
<i class="bi-question-circle-fill"></i>
|
||||
break;
|
||||
case "Win":
|
||||
<span>Ordre</span>
|
||||
break;
|
||||
case "Lose":
|
||||
<i class="bi-trash"></i>
|
||||
break;
|
||||
case "Note":
|
||||
<i class="bi-tag-fill"></i>
|
||||
break;
|
||||
case "Archive":
|
||||
<i class="bi-archive-fill"></i>
|
||||
break;
|
||||
default:
|
||||
<i class="bi-question-circle-fill"></i>
|
||||
break;
|
||||
}
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<button type="button" class="btn btn-outline-dark me-2" @onclick="() => SetQuote(quote.ESalesNumber, QStatus.Lose)"><i class="bi-trash2-fill"></i></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>
|
||||
<button type="button" class="btn btn-success" @onclick="() => SetQuote(quote.ESalesNumber, QStatus.Win)"><i class="bi-cart-fill"></i> </button>
|
||||
</div>
|
||||
@if (!string.IsNullOrWhiteSpace(quote.OfficeNote))
|
||||
{
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-10">
|
||||
<i class="bi-pencil"></i> @quote.OfficeNote
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="list-group-item">Ingen data</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
|
||||
[Parameter]
|
||||
public List<ReportItemView> Quotes { get; set; } = new();
|
||||
[Parameter] public EventCallback<QuoteCallbackArgs> OnChangedCallback { get; set; }
|
||||
|
||||
private async Task SetQuote(string eSalesNumber, QStatus status)
|
||||
{
|
||||
var args = new QuoteCallbackArgs()
|
||||
{
|
||||
ESalesNumber = eSalesNumber,
|
||||
Status = status
|
||||
};
|
||||
await OnChangedCallback.InvokeAsync(args);
|
||||
}
|
||||
}
|
|
@ -35,7 +35,13 @@ public static class Utils
|
|||
catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string EnumToString(Enum value)
|
||||
{
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
public static int GetHashFromNow()
|
||||
{
|
||||
return DateTime.Now.ToFileTimeUtc().GetHashCode();
|
||||
|
|
|
@ -31,7 +31,7 @@ public interface ICrmActivityHttpRepository
|
|||
/// </summary>
|
||||
/// <param name="activity"></param>
|
||||
/// <returns></returns>
|
||||
Task<ApiResponseView> AcceptQuote(ReportItemView activity);
|
||||
Task<ApiResponseView> UpdateQuoteStatus(ReportItemView activity);
|
||||
|
||||
/// <summary>
|
||||
/// Get activities by date
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
||||
//
|
||||
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
@ -60,14 +61,13 @@ public class CrmActivityHttpRepository : ICrmActivityHttpRepository
|
|||
/// </summary>
|
||||
/// <param name="activity"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<ApiResponseView> AcceptQuote(ReportItemView activity)
|
||||
public async Task<ApiResponseView> UpdateQuoteStatus(ReportItemView activity)
|
||||
{
|
||||
var response = await _client.PutAsJsonAsync(
|
||||
$"{_api.CrmActivities}/{activity.ActivityId}/accept", activity, _options);
|
||||
|
||||
var response = await _client.PutAsJsonAsync(
|
||||
$"{_api.CrmActivities}/quote/{activity.ActivityId}", activity, _options);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonSerializer.Deserialize<ApiResponseView>(content);
|
||||
return result!;
|
||||
_logger.LogDebug("UpdateQuote Response Content <= {}", content);
|
||||
return JsonSerializer.Deserialize<ApiResponseView>(content, _options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -150,7 +150,9 @@ public class CrmActivityHttpRepository : ICrmActivityHttpRepository
|
|||
/// <returns>ApiResponseView</returns>
|
||||
public async Task<ApiResponseView> GetExpressState(string activityId)
|
||||
{
|
||||
var response = await _client.GetFromJsonAsync<ApiResponseView>($"{_api.CrmActivities}/express/{activityId}?status=Express", _options);
|
||||
var response =
|
||||
await _client.GetFromJsonAsync<ApiResponseView>($"{_api.CrmActivities}/express/{activityId}?status=Express",
|
||||
_options);
|
||||
return response ?? new ApiResponseView
|
||||
{
|
||||
Code = 404,
|
||||
|
|
11
Wonky.Client/Models/QStatus.cs
Normal file
11
Wonky.Client/Models/QStatus.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
namespace Wonky.Client.Models;
|
||||
|
||||
public enum QStatus
|
||||
{
|
||||
None,
|
||||
Win,
|
||||
Lose,
|
||||
Archive,
|
||||
Note,
|
||||
All
|
||||
}
|
7
Wonky.Client/Models/QuoteCallbackArgs.cs
Normal file
7
Wonky.Client/Models/QuoteCallbackArgs.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Wonky.Client.Models;
|
||||
|
||||
public class QuoteCallbackArgs
|
||||
{
|
||||
public string ESalesNumber { get; set; } = "";
|
||||
public QStatus Status { get; set; }
|
||||
}
|
|
@ -64,7 +64,7 @@ else
|
|||
<option value="noSale">Ingen salg</option>
|
||||
@if (!string.IsNullOrEmpty(Activity.VatNumber) && !string.IsNullOrWhiteSpace(Activity.Address1) && Company.HasFolded == 0)
|
||||
{
|
||||
@if (DraftStateProvider.Draft.DraftType == "order")
|
||||
@if (DraftProvider.Draft.DraftType == "order")
|
||||
{
|
||||
<option selected value="order">Bestilling</option>
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ else
|
|||
<option value="order">Bestilling</option>
|
||||
}
|
||||
|
||||
@if(DraftStateProvider.Draft.DraftType == "offer")
|
||||
@if(DraftProvider.Draft.DraftType == "offer")
|
||||
{
|
||||
<option selected value="quote">Tilbud</option>
|
||||
}
|
||||
|
@ -158,10 +158,10 @@ else
|
|||
<thead>
|
||||
<tr class="bg-dark text-white">
|
||||
<th scope="col" colspan="7">
|
||||
Ordrekladde <span class="mx-2 draft-expires-msg">Global kladde (udløber efter @(DraftStateProvider.Draft.TimeToLiveInSeconds / 60)m inaktivitet)</span>
|
||||
Ordrekladde <span class="mx-2 draft-expires-msg">Global kladde (udløber efter @(DraftProvider.Draft.TimeToLiveInSeconds / 60)m inaktivitet)</span>
|
||||
</th>
|
||||
<th scope="col" class="text-end">
|
||||
<button type="button" class="btn btn-danger btn-sm" @onclick="@DeleteDraft" disabled="@(DraftStateProvider.Draft.Items.Count == 0)"><i class="bi-trash"></i> Slet kladde</button>
|
||||
<button type="button" class="btn btn-danger btn-sm" @onclick="@DeleteDraft" disabled="@(DraftProvider.Draft.Items.Count == 0)"><i class="bi-trash"></i> Slet kladde</button>
|
||||
</th>
|
||||
</tr>
|
||||
<tr class="bg-dark opacity-75 text-white">
|
||||
|
@ -176,9 +176,9 @@ else
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (DraftStateProvider.Draft.Items.Count > 0)
|
||||
@if (DraftProvider.Draft.Items.Count > 0)
|
||||
{
|
||||
@foreach (var cartItem in DraftStateProvider.Draft.Items)
|
||||
@foreach (var cartItem in DraftProvider.Draft.Items)
|
||||
{
|
||||
<tr>
|
||||
<td class="align-middle">@cartItem.Item.Name</td>
|
||||
|
@ -199,7 +199,7 @@ else
|
|||
<tr>
|
||||
<td colspan="4"></td>
|
||||
<td class="align-middle text-black text-end fw-bold">Total</td>
|
||||
<td class="align-middle text-black text-end fw-bold">@($"{DraftStateProvider.Draft.Total:N2}")</td>
|
||||
<td class="align-middle text-black text-end fw-bold">@($"{DraftProvider.Draft.Total:N2}")</td>
|
||||
<td></td>
|
||||
<td class="align-middle text-end">
|
||||
<button class="btn btn-primary" type="button" @onclick="CallPriceListModal">
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace Wonky.Client.Pages;
|
|||
public partial class CrmActivityNewPage : IDisposable
|
||||
{
|
||||
// Parameters
|
||||
[CascadingParameter] DraftStateProvider DraftStateProvider { get; set; }
|
||||
[CascadingParameter] DraftStateProvider DraftProvider { get; set; }
|
||||
[Parameter] public string CompanyId { get; set; }
|
||||
// Services
|
||||
[Inject] public ILogger<CrmActivityNewPage> Logger { get; set; }
|
||||
|
@ -45,8 +45,8 @@ public partial class CrmActivityNewPage : IDisposable
|
|||
[Inject] public ILocalStorageService Storage { get; set; }
|
||||
[Inject] public ICatalogHttpRepository Catalog { get; set; }
|
||||
[Inject] public ICrmCompanyHttpRepository CompanyRepo { get; set; }
|
||||
[Inject] public ICrmActivityHttpRepository CrmActivityRepo { get; set; }
|
||||
[Inject] public ICrmReportHttpRepository CrmReportRepo { get; set; }
|
||||
[Inject] public ICrmActivityHttpRepository ActivityRepo { get; set; }
|
||||
[Inject] public ICrmReportHttpRepository ReportRepo { get; set; }
|
||||
// variables
|
||||
private readonly JsonSerializerOptions? _options = new() {PropertyNameCaseInsensitive = true};
|
||||
private SalesItemView SelectedItem { get; set; } = new();
|
||||
|
@ -132,7 +132,7 @@ public partial class CrmActivityNewPage : IDisposable
|
|||
// Initialize date variable
|
||||
SelectedDate = string.IsNullOrWhiteSpace(UserPrefs.WorkDate) ? DateTime.Now : DateTime.Parse(UserPrefs.WorkDate);
|
||||
// raise flag if report is closed
|
||||
ReportClosed = await CrmReportRepo.ReportExist($"{SelectedDate:yyyy-MM-dd}");
|
||||
ReportClosed = await ReportRepo.ReportExist($"{SelectedDate:yyyy-MM-dd}");
|
||||
// Ask for confirmation of date
|
||||
Logger.LogDebug("Preferences.DateConfirmed => {}", UserPrefs.DateConfirmed);
|
||||
if (!UserPrefs.DateConfirmed)
|
||||
|
@ -141,7 +141,7 @@ public partial class CrmActivityNewPage : IDisposable
|
|||
ConfirmWorkDate.Show();
|
||||
}
|
||||
// Lines may already have been added from the company inventory page
|
||||
if (DraftStateProvider.Draft.DraftType == "order")
|
||||
if (DraftProvider.Draft.DraftType == "order")
|
||||
{
|
||||
// set dropdown selection accordingly
|
||||
Activity.ActivityTypeEnum = "onSite";
|
||||
|
@ -168,7 +168,7 @@ public partial class CrmActivityNewPage : IDisposable
|
|||
/// <param name="workDate"></param>
|
||||
private async Task WorkDateComponentCallback(string workDate)
|
||||
{
|
||||
ReportClosed = await CrmReportRepo.ReportExist(workDate);
|
||||
ReportClosed = await ReportRepo.ReportExist(workDate);
|
||||
SelectedDate = DateTime.Parse(workDate);
|
||||
Activity.ActivityDate = workDate;
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ public partial class CrmActivityNewPage : IDisposable
|
|||
switch (Activity.ActivityStatusEnum)
|
||||
{
|
||||
// don't accept order with no lines
|
||||
case "order" when DraftStateProvider.Draft.Items.Count == 0:
|
||||
case "order" when DraftProvider.Draft.Items.Count == 0:
|
||||
Toast.ShowError("Ved bestilling skal der være en eller flere linjer i kladden.");
|
||||
return;
|
||||
// phone number is required if first time customer
|
||||
|
@ -272,9 +272,9 @@ public partial class CrmActivityNewPage : IDisposable
|
|||
// begin lines
|
||||
Activity.Lines = new List<ActivityLineDto>();
|
||||
var ln = 0;
|
||||
if (DraftStateProvider.Draft.Items.Count != 0)
|
||||
if (DraftProvider.Draft.Items.Count != 0)
|
||||
{
|
||||
var lines = DraftStateProvider.Draft.Items.Select(item => new ActivityLineDto
|
||||
var lines = DraftProvider.Draft.Items.Select(item => new ActivityLineDto
|
||||
{
|
||||
Price = item.Price,
|
||||
Discount = item.Discount,
|
||||
|
@ -293,14 +293,14 @@ public partial class CrmActivityNewPage : IDisposable
|
|||
// debug logging
|
||||
Logger.LogDebug("CrmNewActivityPage => \n {}", JsonSerializer.Serialize(Activity));
|
||||
// post to api
|
||||
var result = await CrmActivityRepo.CreateActivity(Activity);
|
||||
var result = await ActivityRepo.CreateActivity(Activity);
|
||||
// debug logging
|
||||
Logger.LogDebug("ApiResponseView => \n {}", JsonSerializer.Serialize(result));
|
||||
// show result message
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
Toast.ShowSuccess($"{result.Message}",
|
||||
DraftStateProvider.Draft.Items.Count == 0 ? "Besøg er oprettet" : "Bestilling/Tilbud er oprettet");
|
||||
DraftProvider.Draft.Items.Count == 0 ? "Besøg er oprettet" : "Bestilling/Tilbud er oprettet");
|
||||
await DeleteDraft();
|
||||
Navigator.NavigateTo($"/companies");
|
||||
return;
|
||||
|
@ -316,7 +316,7 @@ public partial class CrmActivityNewPage : IDisposable
|
|||
/// </summary>
|
||||
private async Task DeleteDraft()
|
||||
{
|
||||
await DraftStateProvider.DeleteDraftAsync();
|
||||
await DraftProvider.DeleteDraftAsync();
|
||||
Activity.ActivityStatusEnum = "noSale";
|
||||
}
|
||||
|
||||
|
@ -342,11 +342,11 @@ public partial class CrmActivityNewPage : IDisposable
|
|||
Price = "0";
|
||||
Discount = "0";
|
||||
// add it to the cart
|
||||
DraftStateProvider.Draft.Items.Add(item);
|
||||
DraftProvider.Draft.Items.Add(item);
|
||||
if(Activity.ActivityStatusEnum != "quote")
|
||||
Activity.ActivityStatusEnum = "order";
|
||||
// save the item using the CartStateProvider's save method
|
||||
await DraftStateProvider.SaveChangesAsync();
|
||||
await DraftProvider.SaveChangesAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -356,10 +356,10 @@ public partial class CrmActivityNewPage : IDisposable
|
|||
private async Task RemoveItem(DraftItem item)
|
||||
{
|
||||
// remove item
|
||||
DraftStateProvider.Draft.Items.Remove(item);
|
||||
DraftProvider.Draft.Items.Remove(item);
|
||||
// save the remaining draft
|
||||
await DraftStateProvider.SaveChangesAsync();
|
||||
if (!DraftStateProvider.Draft.Items.Any())
|
||||
await DraftProvider.SaveChangesAsync();
|
||||
if (!DraftProvider.Draft.Items.Any())
|
||||
Activity.ActivityStatusEnum = "noSale";
|
||||
}
|
||||
|
||||
|
@ -370,11 +370,20 @@ public partial class CrmActivityNewPage : IDisposable
|
|||
/// <param name="e"></param>
|
||||
private void HandleFieldChanged(object sender, FieldChangedEventArgs e)
|
||||
{
|
||||
DraftStateProvider.Draft.DraftType = Activity.ActivityStatusEnum;
|
||||
Logger.LogDebug("ActivityNewPage => HandleFieldChanged => ActivityStatusEnum <= '{}'", Activity.ActivityStatusEnum);
|
||||
DraftProvider.Draft.DraftType = Activity.ActivityStatusEnum;
|
||||
if (Activity.ActivityStatusEnum == "noSale")
|
||||
{
|
||||
Logger.LogDebug("ActivityNewPage => ActivityStatusEnum == 'noSale' <= remove items");
|
||||
DraftProvider.Draft.Items = new List<DraftItem>();
|
||||
|
||||
}
|
||||
|
||||
|
||||
// InvalidCanvas = InvalidActivityType;
|
||||
InvalidActivity = InvalidActivityType
|
||||
|| PoFormInvalid
|
||||
|| DraftStateProvider.Draft.Items.Count == 0
|
||||
|| DraftProvider.Draft.Items.Count == 0
|
||||
|| (Activity.ActivityStatusEnum == "offer" && string.IsNullOrWhiteSpace(Activity.Email));
|
||||
if (Activity.YourRef.Length > 35 || Activity.ReferenceNumber.Length > 20 || InvalidActivity)
|
||||
{
|
||||
|
@ -395,6 +404,7 @@ public partial class CrmActivityNewPage : IDisposable
|
|||
if (string.IsNullOrEmpty(Activity.ActivityTypeEnum) && !ReportClosed)
|
||||
{
|
||||
Toast.ShowWarning("Aktivitet type kan ikke være tom");
|
||||
PoFormInvalid = true;
|
||||
return;
|
||||
}
|
||||
PoFormInvalid = false;
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
@page "/open-quotes"
|
||||
@using Wonky.Client.Components
|
||||
<div class="row g-3">
|
||||
<div class="col-sm-12">
|
||||
<h3 class="text-center">Åbne tilbud</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group list-group-flush">
|
||||
<div class="list-group-item bg-dark text-white">
|
||||
<div class="row g-3">
|
||||
<div class="col-sm-2">
|
||||
Reference
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
Kunde
|
||||
</div>
|
||||
<div class="col-sm-1">
|
||||
Dato
|
||||
</div>
|
||||
<div class="col-sm-2 text-end">
|
||||
Tilbudssum
|
||||
</div>
|
||||
<div class="col-sm-3"></div>
|
||||
</div>
|
||||
</div>
|
||||
@if (Quotes.Any())
|
||||
{
|
||||
foreach (var quote in Quotes)
|
||||
{
|
||||
<div class="list-group-item list-group-item-action">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-sm-2" style="font-family: monospace;">
|
||||
<a class="btn btn-outline-dark d-block" href="/companies/@quote.Company.CompanyId/quotes/@quote.ActivityId">@quote.ESalesNumber</a>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
@quote.Company.Name
|
||||
</div>
|
||||
<di class="col-sm-1">
|
||||
@quote.OrderDate
|
||||
</di>
|
||||
<div class="col-sm-2 text-end">
|
||||
@($"{quote.OrderAmount:N2}")
|
||||
</div>
|
||||
<div class="col-sm-1"><button type="button" class="btn btn-outline-danger" @onclick="() => SetQuote(2)"><i class="bi-hand-thumbs-down-fill"></i> </button></div>
|
||||
<div class="col-sm-1"><button type="button" class="btn btn-outline-dark" @onclick="() => SetQuote(3)"><i class="bi-trash2-fill"></i> </button></div>
|
||||
<div class="col-sm-1"><button type="button" class="btn btn-outline-success" @onclick="() => SetQuote(1)"><i class="bi-hand-thumbs-up-fill"></i> </button></div>
|
||||
<div class="col-sm-1"></div>
|
||||
@if (!string.IsNullOrWhiteSpace(quote.OfficeNote))
|
||||
{
|
||||
<div class="col-sm-2"><i class="bi-pencil"></i> Note</div>
|
||||
<div class="col-sm-10">
|
||||
@quote.OfficeNote
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="list-group-item">Ingen data</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
@if (Working)
|
||||
{
|
||||
<WorkingThreeDots/>
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
using Microsoft.AspNetCore.Components;
|
||||
using Wonky.Client.HttpInterceptors;
|
||||
using Wonky.Client.HttpInterfaces;
|
||||
using Wonky.Entity.DTO;
|
||||
using Wonky.Entity.Views;
|
||||
|
||||
namespace Wonky.Client.Pages;
|
||||
|
||||
public partial class CrmQuotes : IDisposable
|
||||
{
|
||||
[Inject] public ICrmActivityHttpRepository ActivityRepo { get; set; }
|
||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||
private List<ReportItemView> Quotes { get; set; } = new();
|
||||
private bool Working { get; set; } = true;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Interceptor.RegisterEvent();
|
||||
Interceptor.RegisterBeforeSendEvent();
|
||||
Quotes = await ActivityRepo.GetQuotes();
|
||||
if (Quotes.Any())
|
||||
Quotes = Quotes.OrderBy(x => x.CreateTimestamp).ToList();
|
||||
Working = false;
|
||||
}
|
||||
|
||||
private void SetQuote(int status)
|
||||
{
|
||||
// todo - implement update quote from status
|
||||
// status matches QuoteStatusEnum
|
||||
// 0 - None
|
||||
// 1 - Win
|
||||
// 2 - Lose
|
||||
// 3 - Draw
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
Interceptor.DisposeEvent();
|
||||
}
|
||||
}
|
44
Wonky.Client/Pages/CrmQuotesListPage.razor
Normal file
44
Wonky.Client/Pages/CrmQuotesListPage.razor
Normal file
|
@ -0,0 +1,44 @@
|
|||
@page "/open-quotes"
|
||||
@using Wonky.Client.Components
|
||||
@using Wonky.Client.Models
|
||||
|
||||
<div class="row g-3 align-items-center">
|
||||
<div class="col-sm-9">
|
||||
<h2>Tilbud</h2>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<div class="btn-group btn-group" role="group" aria-label="Filter tilbud">
|
||||
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter1" autocomplete="off" @onchange="() => FilterQuotes(QStatus.Lose)"/>
|
||||
<label class="btn btn-dark" for="btn-filter1"><i class="bi-trash-fill"></i></label>
|
||||
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter2" autocomplete="off" @onchange="() => FilterQuotes(QStatus.Archive)"/>
|
||||
<label class="btn btn-dark" for="btn-filter2"><i class="bi-archive-fill"></i></label>
|
||||
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter3" autocomplete="off" @onchange="() => FilterQuotes(QStatus.Note)"/>
|
||||
<label class="btn btn-dark" for="btn-filter3"><i class="bi-tag-fill"></i></label>
|
||||
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter4" autocomplete="off" @onchange="() => FilterQuotes(QStatus.All)"/>
|
||||
<label class="btn btn-dark" for="btn-filter4"><i class="bi-list"></i></label>
|
||||
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter5" autocomplete="off" checked @onchange="() => FilterQuotes(QStatus.None)"/>
|
||||
<label class="btn btn-dark" for="btn-filter5"><i class="bi-question-circle-fill"></i></label>
|
||||
|
||||
</div>
|
||||
|
||||
@*
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="showAll"
|
||||
@bind-Value="Filtered" @bind-Value:event="onchange" @onclick="FilterQuotes" disabled="@(!Quotes.Any())"/>
|
||||
<label for="showAll" class="form-check-label">Vis alle</label>
|
||||
</div>
|
||||
*@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<QuoteListComponent Quotes="_quotes" OnChangedCallback="UpdateQuoteCallback" />
|
||||
|
||||
@if (Working)
|
||||
{
|
||||
<WorkingThreeDots/>
|
||||
}
|
81
Wonky.Client/Pages/CrmQuotesListPage.razor.cs
Normal file
81
Wonky.Client/Pages/CrmQuotesListPage.razor.cs
Normal file
|
@ -0,0 +1,81 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Security.Policy;
|
||||
using System.Text.Json;
|
||||
using Blazored.LocalStorage;
|
||||
using Blazored.Toast.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Wonky.Client.Helpers;
|
||||
using Wonky.Client.HttpInterceptors;
|
||||
using Wonky.Client.HttpInterfaces;
|
||||
using Wonky.Client.Models;
|
||||
using Wonky.Entity.DTO;
|
||||
using Wonky.Entity.Views;
|
||||
|
||||
namespace Wonky.Client.Pages;
|
||||
|
||||
public partial class CrmQuotesListPage : IDisposable
|
||||
{
|
||||
[Inject] public ICrmActivityHttpRepository ActivityRepo { get; set; }
|
||||
[Inject] public HttpInterceptorService Interceptor { get; set; }
|
||||
[Inject] public ILogger<CrmQuotesListPage> Logger { get; set; }
|
||||
[Inject] public IToastService Toaster { get; set; }
|
||||
[Inject] public ILocalStorageService Storage { get; set; }
|
||||
private List<ReportItemView> Quotes { get; set; } = new();
|
||||
private List<ReportItemView> _quotes { get; set; } = new();
|
||||
private bool Working { get; set; } = true;
|
||||
private QStatus QFilter { get; set; } = QStatus.None;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Interceptor.RegisterEvent();
|
||||
Interceptor.RegisterBeforeSendEvent();
|
||||
Quotes = await ActivityRepo.GetQuotes();
|
||||
await Storage.SetItemAsync("quotes", Quotes);
|
||||
if (Quotes.Any())
|
||||
_quotes = Quotes.Where(x => x.QuoteStatusEnum is "Note" or "None").ToList();
|
||||
Working = false;
|
||||
}
|
||||
|
||||
private async Task FilterQuotes(QStatus status)
|
||||
{
|
||||
QFilter = status;
|
||||
Quotes = await Storage.GetItemAsync<List<ReportItemView>>("quotes");
|
||||
_quotes = QFilter switch
|
||||
{
|
||||
QStatus.None => Quotes.Where(x => x.QuoteStatusEnum is "None").ToList(),
|
||||
QStatus.Win => Quotes.Where(x => x.QuoteStatusEnum is "Win").ToList(),
|
||||
QStatus.Lose => Quotes.Where(x => x.QuoteStatusEnum is "Lose").ToList(),
|
||||
QStatus.Archive => Quotes.Where(x => x.QuoteStatusEnum is "Archive").ToList(),
|
||||
QStatus.Note => Quotes.Where(x => x.QuoteStatusEnum is "Note").ToList(),
|
||||
_ => Quotes.ToList()
|
||||
};
|
||||
}
|
||||
|
||||
private async Task UpdateQuoteCallback(QuoteCallbackArgs args)
|
||||
{
|
||||
var quote = Quotes.First(x => x.ESalesNumber == args.ESalesNumber);
|
||||
if (args.Status == QStatus.Win)
|
||||
quote.OrderDate = $"{DateTime.Now:yyyy-MM-dd}";
|
||||
quote.QuoteStatusEnum = Utils.EnumToString(args.Status);
|
||||
var response = await ActivityRepo.UpdateQuoteStatus(quote);
|
||||
Toaster.ShowInfo($"{response.Message}", $"HTTP STATUS {response.Code}");
|
||||
|
||||
Quotes = new List<ReportItemView>();
|
||||
await Storage.RemoveItemAsync("quotes");
|
||||
Quotes = await ActivityRepo.GetQuotes();
|
||||
while (!Quotes.Any())
|
||||
await Task.Delay(1000);
|
||||
|
||||
await Storage.SetItemAsync("quotes", Quotes);
|
||||
|
||||
await FilterQuotes(QFilter);
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Storage.RemoveItemAsync("quotes");
|
||||
Interceptor.DisposeEvent();
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"appInfo": {
|
||||
"name": "Wonky Client",
|
||||
"version": "0.85.5",
|
||||
"version": "0.85.7",
|
||||
"rc": true,
|
||||
"sandBox": false,
|
||||
"image": "grumpy-coder.png"
|
||||
|
@ -34,7 +34,7 @@
|
|||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"Default": "Information",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue