From d3f0a5aa1f2b933ca0832ee264672148846e3c5a Mon Sep 17 00:00:00 2001 From: leandro Date: Sat, 21 Mar 2026 13:48:36 -0300 Subject: [PATCH] feat(sales): add delivery note detail drawer Closes #31 --- .../DeliveryNoteDetailDrawer.razor | 172 ++++++++++++++++++ .../Sales/DeliveryNotes/DeliveryNotes.razor | 50 ++++- 2 files changed, 218 insertions(+), 4 deletions(-) create mode 100644 phronCare.UIBlazor/Pages/Sales/DeliveryNotes/DeliveryNoteDetailDrawer.razor diff --git a/phronCare.UIBlazor/Pages/Sales/DeliveryNotes/DeliveryNoteDetailDrawer.razor b/phronCare.UIBlazor/Pages/Sales/DeliveryNotes/DeliveryNoteDetailDrawer.razor new file mode 100644 index 0000000..b9f1e0c --- /dev/null +++ b/phronCare.UIBlazor/Pages/Sales/DeliveryNotes/DeliveryNoteDetailDrawer.razor @@ -0,0 +1,172 @@ +@using Domain.Dtos.Sales + +@if (Visible && Summary != null) +{ +
+
+ +
+
+
+
Detalle Remito @HeaderNumber
+
+ @HeaderStatus +
+
+ +
+ +
+ + + @if (Loading) + { +
Cargando detalle...
+ } + else if (activeTab == "Datos") + { +
+
+ +
@HeaderNumber
+
+
+ +
@HeaderIssueDate.ToString("dd/MM/yyyy")
+
+
+ +
@HeaderCustomerName
+
+
+ +
@HeaderQuoteNumber
+
+
+ +
@HeaderStatus
+
+
+ +
@HeaderPrintCount
+
+
+ +
@(Detail?.SalesInvoiceId?.ToString() ?? "—")
+
+
+ +
@(Detail?.ModifiedAt?.ToString("dd/MM/yyyy HH:mm") ?? "—")
+
+
+ +
@(string.IsNullOrWhiteSpace(Detail?.Observations) ? "—" : Detail!.Observations)
+
+
+ } + else + { + @if (Detail?.Items == null || !Detail.Items.Any()) + { +

No hay ítems para este remito.

+ } + else + { +
+ + + + + + + + + + + + @foreach (var item in Detail.Items.OrderBy(i => i.LineNumber)) + { + + + + + + + + } + +
LíneaDescripciónCantidadOrigenNotas
@item.LineNumber@item.Description@item.Quantity@GetOriginLabel(item.OriginType)@(string.IsNullOrWhiteSpace(item.Notes) ? "—" : item.Notes)
+
+ } + } +
+
+} + +@code { + [Parameter] public bool Visible { get; set; } + [Parameter] public EventCallback VisibleChanged { get; set; } + [Parameter] public DeliveryNoteSummaryDto? Summary { get; set; } + [Parameter] public DeliveryNoteDto? Detail { get; set; } + [Parameter] public bool Loading { get; set; } + + private string activeTab = "Datos"; + private int? lastDeliveryNoteId; + + private string HeaderNumber => Detail?.DeliveryNoteNumber ?? Summary?.DeliveryNoteNumber ?? "—"; + private string HeaderStatus => Detail?.Status ?? Summary?.Status ?? "—"; + private DateTime HeaderIssueDate => Detail?.IssueDate ?? Summary?.IssueDate ?? DateTime.MinValue; + private string HeaderCustomerName => string.IsNullOrWhiteSpace(Summary?.CustomerName) ? "—" : Summary!.CustomerName; + private string HeaderQuoteNumber => string.IsNullOrWhiteSpace(Summary?.QuoteNumber) ? "—" : Summary!.QuoteNumber!; + private int HeaderPrintCount => Detail?.PrintCount ?? Summary?.PrintCount ?? 0; + + protected override void OnParametersSet() + { + if (Summary?.Id != lastDeliveryNoteId) + { + activeTab = "Datos"; + lastDeliveryNoteId = Summary?.Id; + } + } + + private async Task Close() + { + await VisibleChanged.InvokeAsync(false); + } + + private string GetStatusBadge(string status) => status switch + { + "Anulado" => "bg-danger text-white", + "Emitido" => "bg-primary text-white", + "Aprobado" => "bg-success", + "Cerrado" => "bg-dark text-white", + _ => "bg-light text-dark" + }; + + private string GetOriginLabel(byte originType) => originType switch + { + 1 => "Presupuesto", + 2 => "Manual", + _ => originType.ToString() + }; +} diff --git a/phronCare.UIBlazor/Pages/Sales/DeliveryNotes/DeliveryNotes.razor b/phronCare.UIBlazor/Pages/Sales/DeliveryNotes/DeliveryNotes.razor index b4ec088..1642223 100644 --- a/phronCare.UIBlazor/Pages/Sales/DeliveryNotes/DeliveryNotes.razor +++ b/phronCare.UIBlazor/Pages/Sales/DeliveryNotes/DeliveryNotes.razor @@ -1,4 +1,5 @@ -@page "/deliverynotes" +@page "/deliverynotes" +@using Domain.Dtos @using Domain.Dtos.Sales @using Domain.Generics @using phronCare.UIBlazor.Services.Sales.DeliveryNotes @@ -91,7 +92,7 @@ @(string.IsNullOrWhiteSpace(deliveryNote.Observations) ? "—" : deliveryNote.Observations) @deliveryNote.PrintCount - + } @@ -131,9 +132,19 @@ + + @code { private DeliveryNoteSearchParams Filters = new() { PageSize = 10 }; private PagedResult? PagedDeliveryNotes; + private DeliveryNoteSummaryDto? SelectedSummary; + private DeliveryNoteDto? SelectedDeliveryNote; + private bool IsDrawerOpen; + private bool IsDetailLoading; private bool IsLoading; private int PaginaDeseada = 1; @@ -209,9 +220,40 @@ _ => "bg-light text-dark" }; - private void ViewDetail(int id) + private async Task OpenDetailAsync(DeliveryNoteSummaryDto summary) { - toastService.ShowInfo($"El detalle del remito {id} se implementará en una próxima story."); + SelectedSummary = summary; + SelectedDeliveryNote = null; + IsDrawerOpen = true; + IsDetailLoading = true; + StateHasChanged(); + + try + { + var detail = await deliveryNoteService.GetByIdAsync(summary.Id); + if (detail is not null) + { + SelectedDeliveryNote = detail; + } + else + { + toastService.ShowError("No se pudo cargar el detalle del remito."); + } + } + catch (Exception ex) + { + toastService.ShowError(ex.Message); + } + finally + { + IsDetailLoading = false; + } + } + + private Task OnDrawerVisibleChanged(bool visible) + { + IsDrawerOpen = visible; + return Task.CompletedTask; } private void ExportarExcel()