diff --git a/SteUp.Data/LocalDb/AppDbContext.cs b/SteUp.Data/LocalDb/AppDbContext.cs index 3a2ab28..305c8ee 100644 --- a/SteUp.Data/LocalDb/AppDbContext.cs +++ b/SteUp.Data/LocalDb/AppDbContext.cs @@ -8,6 +8,7 @@ public class AppDbContext(DbContextOptions options) : DbContext(op { public DbSet Ispezioni => Set(); public DbSet Schede => Set(); + public DbSet SchedaArticoli => Set(); protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -15,7 +16,7 @@ public class AppDbContext(DbContextOptions options) : DbContext(op modelBuilder.Entity() .HasKey(x => new { x.CodMdep, x.Data, x.Rilevatore }); - + modelBuilder.Entity() .HasOne(x => x.Ispezione) .WithMany(x => x.Schede) @@ -31,5 +32,15 @@ public class AppDbContext(DbContextOptions options) : DbContext(op v => JsonSerializer.Serialize(v, (JsonSerializerOptions?)null), v => JsonSerializer.Deserialize>(v, (JsonSerializerOptions?)null) ?? new List() ); + + modelBuilder.Entity() + .HasOne(a => a.Scheda) + .WithMany(s => s.Articoli) + .HasForeignKey(a => a.SchedaId) + .OnDelete(DeleteBehavior.Cascade); + + modelBuilder.Entity() + .HasIndex(a => new { a.SchedaId, a.Barcode }) + .IsUnique(); } } \ No newline at end of file diff --git a/SteUp.Data/LocalDb/EntityServices/IspezioniService.cs b/SteUp.Data/LocalDb/EntityServices/IspezioniService.cs index 44548e0..17a9c97 100644 --- a/SteUp.Data/LocalDb/EntityServices/IspezioniService.cs +++ b/SteUp.Data/LocalDb/EntityServices/IspezioniService.cs @@ -9,6 +9,7 @@ public class IspezioniService(AppDbContext db) : IIspezioniService public Task GetIspezioneAsync(string codMdep, DateOnly data, string rilevatore) => db.Ispezioni .Include(x => x.Schede) + .ThenInclude(s => s.Articoli) .FirstOrDefaultAsync(x => x.CodMdep == codMdep && x.Data == data && @@ -17,6 +18,7 @@ public class IspezioniService(AppDbContext db) : IIspezioniService public Task> GetAllIspezioniWithSchedeAsync() => db.Ispezioni .Include(x => x.Schede) + .ThenInclude(s => s.Articoli) .AsNoTracking() .OrderByDescending(x => x.Data) .ToListAsync(); @@ -48,7 +50,7 @@ public class IspezioniService(AppDbContext db) : IIspezioniService db.Ispezioni.Add(created); await db.SaveChangesAsync(); - + return await db.Ispezioni .AsNoTracking() .FirstAsync(x => @@ -65,7 +67,7 @@ public class IspezioniService(AppDbContext db) : IIspezioniService } /// - /// Cancella l'ispezione e tutte le schede collegate. + /// Cancella l'ispezione e tutte le schede collegate (e relativi articoli via cascade). /// public async Task DeleteIspezioneAsync(string codMdep, DateOnly data, string rilevatore) { @@ -85,13 +87,20 @@ public class IspezioniService(AppDbContext db) : IIspezioniService public async Task AddSchedaAsync(string codMdep, DateOnly data, string rilevatore, Scheda scheda) { - // assicura che il parent esista await GetOrCreateIspezioneAsync(codMdep, data, rilevatore); scheda.CodMdep = codMdep; scheda.Data = data; scheda.Rilevatore = rilevatore; + if (scheda.Articoli is { Count: > 0 }) + { + foreach (var a in scheda.Articoli) + { + a.SchedaId = scheda.Id; + } + } + db.Schede.Add(scheda); await db.SaveChangesAsync(); } @@ -99,6 +108,7 @@ public class IspezioniService(AppDbContext db) : IIspezioniService public Task> GetAllSchedeOfIspezioneAsync(string codMdep, DateOnly data, string rilevatore) => db.Schede .AsNoTracking() + .Include(s => s.Articoli) .Where(x => x.CodMdep == codMdep && x.Data == data && x.Rilevatore == rilevatore) @@ -107,11 +117,13 @@ public class IspezioniService(AppDbContext db) : IIspezioniService public Task GetSchedaAsync(int schedaId) => db.Schede .AsNoTracking() + .Include(s => s.Articoli) .FirstOrDefaultAsync(x => x.Id == schedaId); public Task GetSchedaWithIspezioneAsync(int schedaId) => db.Schede .Include(x => x.Ispezione) + .Include(x => x.Articoli) .AsNoTracking() .FirstOrDefaultAsync(x => x.Id == schedaId); @@ -128,11 +140,56 @@ public class IspezioniService(AppDbContext db) : IIspezioniService public async Task UpdateSchedaAsync(Scheda scheda) { - var exists = await db.Schede.AnyAsync(x => x.Id == scheda.Id); - if (!exists) + var existing = await db.Schede + .Include(s => s.Articoli) + .FirstOrDefaultAsync(s => s.Id == scheda.Id); + + if (existing is null) return false; - db.Schede.Update(scheda); + db.Entry(existing).CurrentValues.SetValues(scheda); + + var incoming = scheda.Articoli; + + foreach (var toRemove in existing.Articoli + .Where(ea => incoming.All(ia => ia.Id != ea.Id)) + .ToList()) + { + existing.Articoli.Remove(toRemove); + } + + foreach (var ia in incoming) + { + if (ia.Id == 0) + { + existing.Articoli.Add(new SchedaArticolo + { + Barcode = ia.Barcode, + Descrizione = ia.Descrizione, + SchedaId = existing.Id + }); + } + else + { + var ea = existing.Articoli.FirstOrDefault(x => x.Id == ia.Id); + if (ea is null) + { + existing.Articoli.Add(new SchedaArticolo + { + Id = ia.Id, + Barcode = ia.Barcode, + Descrizione = ia.Descrizione, + SchedaId = existing.Id + }); + } + else + { + ea.Barcode = ia.Barcode; + ea.Descrizione = ia.Descrizione; + } + } + } + await db.SaveChangesAsync(); return true; } diff --git a/SteUp.Data/Migrations/20260225104013_AddListArticoli.Designer.cs b/SteUp.Data/Migrations/20260225104013_AddListArticoli.Designer.cs new file mode 100644 index 0000000..77eb4a0 --- /dev/null +++ b/SteUp.Data/Migrations/20260225104013_AddListArticoli.Designer.cs @@ -0,0 +1,148 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SteUp.Data.LocalDb; + +#nullable disable + +namespace SteUp.Data.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20260225104013_AddListArticoli")] + partial class AddListArticoli + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.3"); + + modelBuilder.Entity("SteUp.Shared.Core.Entities.Ispezione", b => + { + b.Property("CodMdep") + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("TEXT"); + + b.Property("Rilevatore") + .HasColumnType("TEXT"); + + b.Property("Stato") + .HasColumnType("INTEGER"); + + b.HasKey("CodMdep", "Data", "Rilevatore"); + + b.ToTable("Ispezioni"); + }); + + modelBuilder.Entity("SteUp.Shared.Core.Entities.Scheda", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ActivityTypeId") + .HasColumnType("TEXT"); + + b.Property("CodJfas") + .HasColumnType("TEXT"); + + b.Property("CodMdep") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("TEXT"); + + b.Property("DescrizioneReparto") + .HasColumnType("TEXT"); + + b.Property("ImageNames") + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("Responsabile") + .HasColumnType("TEXT"); + + b.Property("Rilevatore") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Scadenza") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("CodMdep", "Data", "Rilevatore"); + + b.ToTable("Schede"); + }); + + modelBuilder.Entity("SteUp.Shared.Core.Entities.SchedaArticolo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Barcode") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("SchedaId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("SchedaId", "Barcode") + .IsUnique(); + + b.ToTable("SchedaArticoli"); + }); + + modelBuilder.Entity("SteUp.Shared.Core.Entities.Scheda", b => + { + b.HasOne("SteUp.Shared.Core.Entities.Ispezione", "Ispezione") + .WithMany("Schede") + .HasForeignKey("CodMdep", "Data", "Rilevatore") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ispezione"); + }); + + modelBuilder.Entity("SteUp.Shared.Core.Entities.SchedaArticolo", b => + { + b.HasOne("SteUp.Shared.Core.Entities.Scheda", "Scheda") + .WithMany("Articoli") + .HasForeignKey("SchedaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scheda"); + }); + + modelBuilder.Entity("SteUp.Shared.Core.Entities.Ispezione", b => + { + b.Navigation("Schede"); + }); + + modelBuilder.Entity("SteUp.Shared.Core.Entities.Scheda", b => + { + b.Navigation("Articoli"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SteUp.Data/Migrations/20260225104013_AddListArticoli.cs b/SteUp.Data/Migrations/20260225104013_AddListArticoli.cs new file mode 100644 index 0000000..ef09b84 --- /dev/null +++ b/SteUp.Data/Migrations/20260225104013_AddListArticoli.cs @@ -0,0 +1,48 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace SteUp.Data.Migrations +{ + /// + public partial class AddListArticoli : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "SchedaArticoli", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + SchedaId = table.Column(type: "INTEGER", nullable: false), + Barcode = table.Column(type: "TEXT", maxLength: 64, nullable: false), + Descrizione = table.Column(type: "TEXT", maxLength: 256, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SchedaArticoli", x => x.Id); + table.ForeignKey( + name: "FK_SchedaArticoli_Schede_SchedaId", + column: x => x.SchedaId, + principalTable: "Schede", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_SchedaArticoli_SchedaId_Barcode", + table: "SchedaArticoli", + columns: new[] { "SchedaId", "Barcode" }, + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "SchedaArticoli"); + } + } +} diff --git a/SteUp.Data/Migrations/AppDbContextModelSnapshot.cs b/SteUp.Data/Migrations/AppDbContextModelSnapshot.cs index 98888ab..6c39e20 100644 --- a/SteUp.Data/Migrations/AppDbContextModelSnapshot.cs +++ b/SteUp.Data/Migrations/AppDbContextModelSnapshot.cs @@ -81,6 +81,33 @@ namespace SteUp.Data.Migrations b.ToTable("Schede"); }); + modelBuilder.Entity("SteUp.Shared.Core.Entities.SchedaArticolo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Barcode") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("Descrizione") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("SchedaId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("SchedaId", "Barcode") + .IsUnique(); + + b.ToTable("SchedaArticoli"); + }); + modelBuilder.Entity("SteUp.Shared.Core.Entities.Scheda", b => { b.HasOne("SteUp.Shared.Core.Entities.Ispezione", "Ispezione") @@ -92,10 +119,26 @@ namespace SteUp.Data.Migrations b.Navigation("Ispezione"); }); + modelBuilder.Entity("SteUp.Shared.Core.Entities.SchedaArticolo", b => + { + b.HasOne("SteUp.Shared.Core.Entities.Scheda", "Scheda") + .WithMany("Articoli") + .HasForeignKey("SchedaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scheda"); + }); + modelBuilder.Entity("SteUp.Shared.Core.Entities.Ispezione", b => { b.Navigation("Schede"); }); + + modelBuilder.Entity("SteUp.Shared.Core.Entities.Scheda", b => + { + b.Navigation("Articoli"); + }); #pragma warning restore 612, 618 } } diff --git a/SteUp.Shared/Components/Layout/Spinner/LoaderLayout.razor b/SteUp.Shared/Components/Layout/Spinner/LoaderLayout.razor new file mode 100644 index 0000000..dd2b055 --- /dev/null +++ b/SteUp.Shared/Components/Layout/Spinner/LoaderLayout.razor @@ -0,0 +1,13 @@ + +
+ @(Text ?? "Caricamento") + + +
+
+ +@code +{ + [Parameter] public bool Visible { get; set; } + [Parameter] public string? Text { get; set; } +} \ No newline at end of file diff --git a/SteUp.Shared/Components/Layout/Spinner/LoaderLayout.razor.css b/SteUp.Shared/Components/Layout/Spinner/LoaderLayout.razor.css new file mode 100644 index 0000000..6ef8793 --- /dev/null +++ b/SteUp.Shared/Components/Layout/Spinner/LoaderLayout.razor.css @@ -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; +} \ No newline at end of file diff --git a/SteUp.Shared/Components/SingleElements/Modal/ExceptionModal/ModalError.razor b/SteUp.Shared/Components/SingleElements/Modal/ExceptionModal/ModalError.razor new file mode 100644 index 0000000..94cd262 --- /dev/null +++ b/SteUp.Shared/Components/SingleElements/Modal/ExceptionModal/ModalError.razor @@ -0,0 +1,23 @@ + + +
+ + Ops +
+
+ @ErrorMessage +
+
+ + + Chiudi + + +
+ +@code { + [CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = null!; + [Parameter] public string ErrorMessage { get; set; } = string.Empty; + + private void Cancel() => MudDialog.Cancel(); +} \ No newline at end of file diff --git a/SteUp.Shared/Components/SingleElements/Modal/ExceptionModal/ModalError.razor.css b/SteUp.Shared/Components/SingleElements/Modal/ExceptionModal/ModalError.razor.css new file mode 100644 index 0000000..fcb2236 --- /dev/null +++ b/SteUp.Shared/Components/SingleElements/Modal/ExceptionModal/ModalError.razor.css @@ -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); +} \ No newline at end of file diff --git a/SteUp.Shared/Components/SingleElements/Modal/ModalFormScheda.razor b/SteUp.Shared/Components/SingleElements/Modal/ModalFormScheda.razor index 56c1b95..d0b7bdc 100644 --- a/SteUp.Shared/Components/SingleElements/Modal/ModalFormScheda.razor +++ b/SteUp.Shared/Components/SingleElements/Modal/ModalFormScheda.razor @@ -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 @@ -27,7 +29,7 @@ @foreach (var fasi in SteupDataService.Reparti) { @@ -103,10 +105,29 @@
- +
+ @if (!Scheda.Articoli.IsNullOrEmpty()) + { +
+ @foreach (var articolo in Scheda.Articoli) + { + + + + @articolo.Descrizione + + + Barcode: @articolo.Barcode + + + + } +
+ }
- + @if (!IsView) {
@@ -114,7 +135,7 @@ FullWidth="true" StartIcon="@Icons.Material.Rounded.Balance" Size="Size.Medium" - OnClick="@OpenAddAttached" + OnClick="@OpenSelectArt" Variant="Variant.Outlined"> Consulta articoli @@ -161,6 +182,7 @@ + @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 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? 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 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; + } + } \ No newline at end of file diff --git a/SteUp.Shared/Components/SingleElements/Modal/ModalFormScheda.razor.css b/SteUp.Shared/Components/SingleElements/Modal/ModalFormScheda.razor.css index a1b5b7b..0df5574 100644 --- a/SteUp.Shared/Components/SingleElements/Modal/ModalFormScheda.razor.css +++ b/SteUp.Shared/Components/SingleElements/Modal/ModalFormScheda.razor.css @@ -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; } \ No newline at end of file diff --git a/SteUp.Shared/Components/SingleElements/Modal/ModalSelectArt.razor b/SteUp.Shared/Components/SingleElements/Modal/ModalSelectArt.razor new file mode 100644 index 0000000..274205f --- /dev/null +++ b/SteUp.Shared/Components/SingleElements/Modal/ModalSelectArt.razor @@ -0,0 +1,59 @@ +@using SteUp.Shared.Components.Layout +@using SteUp.Shared.Core.Dto + + + + + + @if (!Articoli.IsNullOrEmpty()) + { + + } + else + { +
+ + Nessun articolo trovato +
+ } +
+ + @if (!Articoli.IsNullOrEmpty()) + { + + Seleziona + + } + +
+ +@code { + [CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = null!; + [Parameter] public List? Articoli { get; set; } + + private IEnumerable? 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 arg) => + $"{arg.Count} selezionat{(arg.Count == 1 ? "o" : "i")}"; + +} \ No newline at end of file diff --git a/SteUp.Shared/Core/Dto/ArticoliInGrigliaDto.cs b/SteUp.Shared/Core/Dto/ArticoliInGrigliaDto.cs new file mode 100644 index 0000000..09bf504 --- /dev/null +++ b/SteUp.Shared/Core/Dto/ArticoliInGrigliaDto.cs @@ -0,0 +1,18 @@ +using System.Text.Json.Serialization; + +namespace SteUp.Shared.Core.Dto; + +public class ArticoliInGrigliaDto +{ + [JsonPropertyName("codMart")] + public string CodMart { get; set; } = string.Empty; + + [JsonPropertyName("descrizione")] + public string Descrizione { get; set; } = string.Empty; + + [JsonPropertyName("barcode")] + public string Barcode { get; set; } = string.Empty; + + [JsonPropertyName("codMsgr")] + public string CodMsgr { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/SteUp.Shared/Core/Dto/RetrieveGrigliaPluRequestDto.cs b/SteUp.Shared/Core/Dto/RetrieveGrigliaPluRequestDto.cs new file mode 100644 index 0000000..a3b5eae --- /dev/null +++ b/SteUp.Shared/Core/Dto/RetrieveGrigliaPluRequestDto.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace SteUp.Shared.Core.Dto; + +public class RetrieveGrigliaPluRequestDto +{ + [JsonPropertyName("codMdep")] + public string? CodMdep { get; set; } + + [JsonPropertyName("codJfas")] + public string? CodJfas { get; set; } + + [JsonPropertyName("activityTypeId")] + public string? ActivityTypeId { get; set; } +} \ No newline at end of file diff --git a/SteUp.Shared/Core/Entities/Scheda.cs b/SteUp.Shared/Core/Entities/Scheda.cs index 664ac5c..75d34a5 100644 --- a/SteUp.Shared/Core/Entities/Scheda.cs +++ b/SteUp.Shared/Core/Entities/Scheda.cs @@ -17,6 +17,7 @@ public class Scheda : EntityBase public string Rilevatore { get; set; } = string.Empty; public Ispezione? Ispezione { get; set; } + public List Articoli { get; set; } = []; public List? ImageNames { get; set; } public string? DescrizioneReparto { get; set; } diff --git a/SteUp.Shared/Core/Entities/SchedaArticolo.cs b/SteUp.Shared/Core/Entities/SchedaArticolo.cs new file mode 100644 index 0000000..2d3fc23 --- /dev/null +++ b/SteUp.Shared/Core/Entities/SchedaArticolo.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace SteUp.Shared.Core.Entities; + +public class SchedaArticolo +{ + [Key] + public int Id { get; set; } + + [Required] + public int SchedaId { get; set; } + + [ForeignKey(nameof(SchedaId))] + public Scheda Scheda { get; set; } = null!; + + [Required] + [MaxLength(64)] + public string Barcode { get; set; } = string.Empty; + + [Required] + [MaxLength(256)] + public string Descrizione { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/SteUp.Shared/Core/Helpers/ModalHelper.cs b/SteUp.Shared/Core/Helpers/ModalHelper.cs index 8ae1ded..b3f8de5 100644 --- a/SteUp.Shared/Core/Helpers/ModalHelper.cs +++ b/SteUp.Shared/Core/Helpers/ModalHelper.cs @@ -1,5 +1,6 @@ using MudBlazor; using SteUp.Shared.Components.SingleElements.Modal; +using SteUp.Shared.Components.SingleElements.Modal.ExceptionModal; using SteUp.Shared.Core.Dto; using SteUp.Shared.Core.Entities; @@ -86,4 +87,48 @@ public abstract class ModalHelper return await modal.Result; } + + public static async Task OpenSelectArt(IDialogService dialog, List? articoli) + { + var modal = await dialog.ShowAsync( + "ModalSelectArt", + new DialogParameters + { + { x => x.Articoli, articoli } + }, + new DialogOptions + { + FullScreen = false, + CloseButton = false, + NoHeader = true, + BackdropClick = true, + FullWidth = true, + MaxWidth = MaxWidth.ExtraLarge + } + ); + + return await modal.Result; + } + + public static async Task ShowError(IDialogService dialog, string message) + { + var modal = await dialog.ShowAsync( + "ModalError", + new DialogParameters + { + { x => x.ErrorMessage, message } + }, + new DialogOptions + { + FullScreen = false, + CloseButton = false, + NoHeader = true, + BackdropClick = true, + FullWidth = true, + MaxWidth = MaxWidth.ExtraLarge + } + ); + + await modal.Result; + } } \ No newline at end of file diff --git a/SteUp.Shared/Core/Interface/IntegryApi/IIntegrySteupService.cs b/SteUp.Shared/Core/Interface/IntegryApi/IIntegrySteupService.cs index fb26aca..429343f 100644 --- a/SteUp.Shared/Core/Interface/IntegryApi/IIntegrySteupService.cs +++ b/SteUp.Shared/Core/Interface/IntegryApi/IIntegrySteupService.cs @@ -8,4 +8,6 @@ public interface IIntegrySteupService Task> RetrievePuntiVendita(); Task> RetrieveReparti(); Task> RetrieveActivityType(); + Task?> RetrieveGrigliaPlu(RetrieveGrigliaPluRequestDto request); + Task RetrieveArtFromBarcode(string barcode); } \ No newline at end of file diff --git a/SteUp.Shared/Core/Services/IntegrySteupService.cs b/SteUp.Shared/Core/Services/IntegrySteupService.cs index cb054d9..efa8f93 100644 --- a/SteUp.Shared/Core/Services/IntegrySteupService.cs +++ b/SteUp.Shared/Core/Services/IntegrySteupService.cs @@ -19,5 +19,17 @@ public class IntegrySteupService(IIntegryApiRestClient integryApiRestClient) : I public Task> RetrieveActivityType() => integryApiRestClient.AuthorizedGet>($"{BaseRequest}/retrieveActivityType")!; + public Task?> RetrieveGrigliaPlu(RetrieveGrigliaPluRequestDto request) => + integryApiRestClient.AuthorizedPost?>($"{BaseRequest}/retrieveGrigliaPlu", request); + + public Task RetrieveArtFromBarcode(string barcode) => + integryApiRestClient.AuthorizedGet( + $"{BaseRequest}/retrieveArtFromBarcode", + new Dictionary + { + { "barcode", barcode } + } + ); + #endregion } \ No newline at end of file diff --git a/SteUp.Shared/wwwroot/css/app.css b/SteUp.Shared/wwwroot/css/app.css index 4b254af..e0e31c1 100644 --- a/SteUp.Shared/wwwroot/css/app.css +++ b/SteUp.Shared/wwwroot/css/app.css @@ -25,6 +25,7 @@ html, body { html ::-webkit-scrollbar { width: 3px; + height: 3px; } html ::-webkit-scrollbar-thumb {