Implentata scansione barcode e lista articoli nel form scheda
This commit is contained in:
13
SteUp.Shared/Components/Layout/Spinner/LoaderLayout.razor
Normal file
13
SteUp.Shared/Components/Layout/Spinner/LoaderLayout.razor
Normal file
@@ -0,0 +1,13 @@
|
||||
<MudOverlay Visible="Visible" DarkBackground="false">
|
||||
<div class="overlay-container">
|
||||
<span>@(Text ?? "Caricamento")</span>
|
||||
|
||||
<MudProgressLinear Color="Color.Primary" Rounded="true" Size="Size.Medium" Indeterminate="true" />
|
||||
</div>
|
||||
</MudOverlay>
|
||||
|
||||
@code
|
||||
{
|
||||
[Parameter] public bool Visible { get; set; }
|
||||
[Parameter] public string? Text { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
.overlay-container {
|
||||
background: var(--mud-palette-background);
|
||||
width: 20rem;
|
||||
height: 6rem;
|
||||
padding: 0 1rem;
|
||||
display: flex;
|
||||
gap: .5rem;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
border-radius: 20px;
|
||||
box-shadow: var(--custom-box-shadow);
|
||||
}
|
||||
|
||||
.overlay-container > span {
|
||||
text-align: center;
|
||||
font-size: medium;
|
||||
font-weight: 600;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<MudDialog OnBackdropClick="Cancel">
|
||||
<DialogContent>
|
||||
<div class="exception-header mb-2">
|
||||
<i class="ri-emotion-unhappy-line"></i>
|
||||
<span>Ops</span>
|
||||
</div>
|
||||
<div class="text">
|
||||
<code>@ErrorMessage</code>
|
||||
</div>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudButton Variant="Variant.Text" OnClick="@Cancel" Size="Size.Small" Color="Color.Primary">
|
||||
Chiudi
|
||||
</MudButton>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
|
||||
@code {
|
||||
[CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = null!;
|
||||
[Parameter] public string ErrorMessage { get; set; } = string.Empty;
|
||||
|
||||
private void Cancel() => MudDialog.Cancel();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
.exception-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.exception-header > i {
|
||||
font-size: 3rem;
|
||||
line-height: normal;
|
||||
color: var(--bs-danger);
|
||||
}
|
||||
|
||||
.exception-header > span {
|
||||
font-size: x-large;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: medium;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
code {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
color: var(--bs-gray-dark);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
@using SteUp.Shared.Components.Layout
|
||||
@using SteUp.Shared.Components.Layout.Overlay
|
||||
@using SteUp.Shared.Components.Layout.Spinner
|
||||
@using SteUp.Shared.Components.SingleElements.Card.ModalForm
|
||||
@using SteUp.Shared.Components.SingleElements.MessageBox
|
||||
@using SteUp.Shared.Core.Dto
|
||||
@@ -14,6 +15,7 @@
|
||||
@inject IIntegryApiService IntegryApiService
|
||||
@inject IAttachedService AttachedService
|
||||
@inject IIspezioniService IspezioniService
|
||||
@inject IIntegrySteupService IntegrySteupService
|
||||
@inject OnScannerService OnScannerService
|
||||
|
||||
<MudDialog Class="customDialog-form">
|
||||
@@ -27,7 +29,7 @@
|
||||
<CardFormModal Title="Reparto" Loading="SteupDataService.Reparti.IsNullOrEmpty()">
|
||||
<MudSelectExtended ReadOnly="IsView" T="JtbFasiDto?" Variant="Variant.Text"
|
||||
@bind-Value="Scheda.Reparto" ToStringFunc="@(x => x?.Descrizione)"
|
||||
@bind-Value:after="OnAfterChangeValue" Required="true"
|
||||
@bind-Value:after="OnAfterChangeReparto" Required="true"
|
||||
RequiredError="Reparto obbligatorio">
|
||||
@foreach (var fasi in SteupDataService.Reparti)
|
||||
{
|
||||
@@ -103,10 +105,29 @@
|
||||
<div class="input-manual-barcode">
|
||||
<MudTextField FullWidth="true" ReadOnly="IsView" T="string?" Variant="Variant.Text"
|
||||
@bind-Value="ManualBarcode" Placeholder="Digita manualmente il codice"/>
|
||||
<MudIconButton Color="Color.Primary" Size="Size.Small" Icon="@Icons.Material.Rounded.Send" />
|
||||
<MudIconButton Color="Color.Primary" OnClick="@OnManualBarcodeSet"
|
||||
Size="Size.Small" Icon="@Icons.Material.Rounded.Send"/>
|
||||
</div>
|
||||
@if (!Scheda.Articoli.IsNullOrEmpty())
|
||||
{
|
||||
<div class="art-list">
|
||||
@foreach (var articolo in Scheda.Articoli)
|
||||
{
|
||||
<MudChip T="string" OnClose="@(() => RemoveArt(articolo.Barcode))" style="height: auto;">
|
||||
<MudStack Direction="Column" Spacing="0" class="py-1">
|
||||
<MudText Typo="Typo.subtitle2" Style="line-height: 1.1; font-weight: 700;">
|
||||
@articolo.Descrizione
|
||||
</MudText>
|
||||
<MudText Typo="Typo.body2" Style="line-height: 1.5;">
|
||||
Barcode: @articolo.Barcode
|
||||
</MudText>
|
||||
</MudStack>
|
||||
</MudChip>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</CardFormModal>
|
||||
|
||||
|
||||
@if (!IsView)
|
||||
{
|
||||
<div class="container-button ripple-container">
|
||||
@@ -114,7 +135,7 @@
|
||||
FullWidth="true"
|
||||
StartIcon="@Icons.Material.Rounded.Balance"
|
||||
Size="Size.Medium"
|
||||
OnClick="@OpenAddAttached"
|
||||
OnClick="@OpenSelectArt"
|
||||
Variant="Variant.Outlined">
|
||||
Consulta articoli
|
||||
</MudButton>
|
||||
@@ -161,6 +182,7 @@
|
||||
</MudDialog>
|
||||
|
||||
<SpinnerOverlay VisibleOverlay="VisibleOverlay" SuccessAnimation="SuccessAnimation"/>
|
||||
<LoaderLayout Visible="OnLoading" Text="@TextLoading"/>
|
||||
|
||||
@code {
|
||||
[CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = null!;
|
||||
@@ -171,11 +193,13 @@
|
||||
|
||||
private bool IsView => !NetworkService.ConnectionAvailable;
|
||||
|
||||
private string ManualBarcode { get; set; }
|
||||
private string? ManualBarcode { get; set; }
|
||||
|
||||
//Overlay
|
||||
private bool VisibleOverlay { get; set; }
|
||||
private bool SuccessAnimation { get; set; }
|
||||
private bool OnLoading { get; set; }
|
||||
private string? TextLoading { get; set; }
|
||||
|
||||
private bool FileLoading { get; set; }
|
||||
|
||||
@@ -189,7 +213,9 @@
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
OnScannerService.OnNewScanSuccessful += OnNewScanSuccessful;
|
||||
Snackbar.Configuration.PositionClass = Defaults.Classes.Position.TopCenter;
|
||||
|
||||
OnScannerService.OnNewScanSuccessful += HandleNewScanSuccessful;
|
||||
OnScannerService.OnErrorScan += OnErrorScan;
|
||||
|
||||
_originalScheda = Scheda.Clone();
|
||||
@@ -238,6 +264,7 @@
|
||||
StateHasChanged();
|
||||
|
||||
await Task.Delay(1250);
|
||||
DisposeMessage();
|
||||
MudDialog.Close(Scheda);
|
||||
}
|
||||
|
||||
@@ -305,12 +332,19 @@
|
||||
if (await CheckSavePreAction())
|
||||
{
|
||||
await AttachedService.CleanTempStorageAsync();
|
||||
DisposeMessage();
|
||||
MudDialog.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
#region Form
|
||||
|
||||
private void OnAfterChangeReparto()
|
||||
{
|
||||
Scheda.ActivityTypeId = null;
|
||||
OnAfterChangeValue();
|
||||
}
|
||||
|
||||
private void OnAfterChangeValue()
|
||||
{
|
||||
RecalcDirty();
|
||||
@@ -374,7 +408,7 @@
|
||||
var result = await ModalHelper.OpenAddAttached(Dialog);
|
||||
if (result is not { Canceled: false, Data: List<AttachedDto> attachedList }) return;
|
||||
|
||||
VisibleOverlay = true;
|
||||
OnLoading = true;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
await Task.Yield();
|
||||
|
||||
@@ -408,12 +442,77 @@
|
||||
|
||||
await InvokeAsync(() =>
|
||||
{
|
||||
VisibleOverlay = false;
|
||||
OnLoading = false;
|
||||
StateHasChanged();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void OpenSelectArt()
|
||||
{
|
||||
if (Scheda.CodJfas.IsNullOrEmpty())
|
||||
{
|
||||
Snackbar.Clear();
|
||||
Snackbar.Add("Selezionare prima il reparto", Severity.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
OnLoading = true;
|
||||
TextLoading = "Download articoli in griglia";
|
||||
StateHasChanged();
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
List<ArticoliInGrigliaDto>? articoli;
|
||||
try
|
||||
{
|
||||
articoli = await IntegrySteupService.RetrieveGrigliaPlu(
|
||||
new RetrieveGrigliaPluRequestDto
|
||||
{
|
||||
CodMdep = CodMdep,
|
||||
ActivityTypeId = Scheda.ActivityTypeId,
|
||||
CodJfas = Scheda.CodJfas
|
||||
}
|
||||
);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await InvokeAsync(() =>
|
||||
{
|
||||
OnLoading = false;
|
||||
TextLoading = null;
|
||||
StateHasChanged();
|
||||
|
||||
OnError(e.Message);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var modal = await ModalHelper.OpenSelectArt(Dialog, articoli);
|
||||
|
||||
await InvokeAsync(() =>
|
||||
{
|
||||
OnLoading = false;
|
||||
TextLoading = null;
|
||||
|
||||
StateHasChanged();
|
||||
});
|
||||
|
||||
if (modal is { Canceled: false, Data: List<ArticoliInGrigliaDto> articoliSelezionati })
|
||||
{
|
||||
Scheda.Articoli.AddRange(articoliSelezionati.ConvertAll(x => new SchedaArticolo
|
||||
{
|
||||
Barcode = x.Barcode,
|
||||
Descrizione = x.Descrizione
|
||||
})
|
||||
);
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void OnRemoveAttached(int index)
|
||||
{
|
||||
if (AttachedList is null || index < 0 || index >= AttachedList.Count) return;
|
||||
@@ -455,16 +554,89 @@
|
||||
|
||||
#region Scanner
|
||||
|
||||
public static void OnNewScanSuccessful(string? value)
|
||||
private void OnManualBarcodeSet()
|
||||
{
|
||||
//To be implemented
|
||||
if (ManualBarcode == null) return;
|
||||
|
||||
HandleNewScanSuccessful(ManualBarcode);
|
||||
ManualBarcode = null;
|
||||
}
|
||||
|
||||
private static void OnErrorScan(string? value)
|
||||
private async void HandleNewScanSuccessful(string? value)
|
||||
{
|
||||
//To be implemented
|
||||
try
|
||||
{
|
||||
if (value is null) return;
|
||||
if (Scheda.Articoli.Any(x => x.Barcode.Equals(value))) return;
|
||||
|
||||
await InvokeAsync(() =>
|
||||
{
|
||||
OnLoading = true;
|
||||
StateHasChanged();
|
||||
});
|
||||
|
||||
var art = await IntegrySteupService.RetrieveArtFromBarcode(value);
|
||||
|
||||
await InvokeAsync(() =>
|
||||
{
|
||||
OnLoading = false;
|
||||
StateHasChanged();
|
||||
|
||||
if (art != null)
|
||||
{
|
||||
RecalcDirty(true);
|
||||
|
||||
Scheda.Articoli.Add(new SchedaArticolo
|
||||
{
|
||||
Barcode = art.Barcode,
|
||||
Descrizione = art.Descrizione
|
||||
});
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
OnError("Nessun articolo trovato");
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await InvokeAsync(() =>
|
||||
{
|
||||
OnLoading = false;
|
||||
StateHasChanged();
|
||||
});
|
||||
|
||||
OnError(e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnErrorScan(string? value) => OnError(value);
|
||||
|
||||
#endregion
|
||||
|
||||
private void OnError(string? errorMessage)
|
||||
{
|
||||
if (errorMessage == null) return;
|
||||
|
||||
_ = ModalHelper.ShowError(Dialog, errorMessage);
|
||||
}
|
||||
|
||||
private void RemoveArt(string barcode)
|
||||
{
|
||||
var index = Scheda.Articoli.FindIndex(x => x.Barcode.Equals(barcode));
|
||||
if (index < 0) return;
|
||||
|
||||
RecalcDirty(true);
|
||||
Scheda.Articoli.RemoveAt(index);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void DisposeMessage()
|
||||
{
|
||||
OnScannerService.OnNewScanSuccessful -= HandleNewScanSuccessful;
|
||||
OnScannerService.OnErrorScan -= OnErrorScan;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,6 +11,8 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
margin-top: .5rem;
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
.scroll-attached {
|
||||
@@ -35,4 +37,13 @@
|
||||
|
||||
.input-card {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.art-list {
|
||||
max-height: 150px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.art-list ::deep p {
|
||||
white-space: normal;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
@using SteUp.Shared.Components.Layout
|
||||
@using SteUp.Shared.Core.Dto
|
||||
|
||||
<MudDialog OnBackdropClick="Cancel">
|
||||
<DialogContent>
|
||||
<HeaderLayout SmallHeader="true" Cancel="true" OnCancel="@(() => MudDialog.Cancel())"
|
||||
Title="Seleziona articoli"/>
|
||||
|
||||
@if (!Articoli.IsNullOrEmpty())
|
||||
{
|
||||
<MudSelectExtended MultiSelection="true" ItemCollection="Articoli" SearchBox="true"
|
||||
SearchBoxAutoFocus="true" @bind-SelectedValues="ArticoliSelected"
|
||||
SearchFunc="SearchFunc" T="ArticoliInGrigliaDto" Virtualize="true"
|
||||
Label="Articoli" AnchorOrigin="Origin.BottomCenter" Variant="Variant.Outlined"
|
||||
SearchBoxPlaceholder="Descrizione articolo" SearchBoxClearable="true"
|
||||
MultiSelectionTextFunc="MultiSelectionTextFunc" ToStringFunc="ToStringFunc"/>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="spinner-container" style="height: unset !important; margin-bottom: 1rem;">
|
||||
<MudIcon Size="Size.Large" Color="Color.Error" Icon="@Icons.Material.Rounded.Close"/>
|
||||
<MudText>Nessun articolo trovato</MudText>
|
||||
</div>
|
||||
}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
@if (!Articoli.IsNullOrEmpty())
|
||||
{
|
||||
<MudButton Variant="Variant.Filled" OnClick="@Submit" Size="Size.Small" Color="Color.Primary">
|
||||
Seleziona
|
||||
</MudButton>
|
||||
}
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
|
||||
@code {
|
||||
[CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = null!;
|
||||
[Parameter] public List<ArticoliInGrigliaDto>? Articoli { get; set; }
|
||||
|
||||
private IEnumerable<ArticoliInGrigliaDto>? ArticoliSelected { get; set; }
|
||||
|
||||
private void Cancel() => MudDialog.Cancel();
|
||||
|
||||
private void Submit() =>
|
||||
MudDialog.Close(DialogResult.Ok(ArticoliSelected?.ToList()));
|
||||
|
||||
private static bool SearchFunc(ArticoliInGrigliaDto? obj, string? searchString)
|
||||
{
|
||||
if (searchString.IsNullOrEmpty() || obj == null) return true;
|
||||
|
||||
return obj.Descrizione.ContainsIgnoreCase(searchString!);
|
||||
}
|
||||
|
||||
private static string? ToStringFunc(ArticoliInGrigliaDto? arg) => arg?.Descrizione;
|
||||
|
||||
private static string MultiSelectionTextFunc(List<ArticoliInGrigliaDto?> arg) =>
|
||||
$"{arg.Count} selezionat{(arg.Count == 1 ? "o" : "i")}";
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user