feat: smart product autocomplete for inventory dialogs
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 8m14s
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 8m14s
- DiscountProductsAutoComplete: new autocomplete component for discount products with search/debounce (mirrors ProductsAutoComplete pattern) - AddStockDialog: replace manual product ID input with smart autocomplete - When 'regular product' selected → shows ProductsAutoComplete - When 'discount product' selected → shows DiscountProductsAutoComplete - Admin never has to type product IDs manually - Product type selector controls which autocomplete is shown - Validates product selection before submit
This commit is contained in:
@@ -0,0 +1,14 @@
|
|||||||
|
@using CMSMicroservice.Protobuf.Protos.DiscountProduct
|
||||||
|
|
||||||
|
<MudAutocomplete T="DiscountProductDto"
|
||||||
|
Label="@Label"
|
||||||
|
Value="@_item"
|
||||||
|
DebounceInterval="700"
|
||||||
|
ValueChanged="@((e) => OnSelected(e))"
|
||||||
|
ToStringFunc="@(e => e == null ? null : e.Title)"
|
||||||
|
SearchFunc="@Search"
|
||||||
|
Variant="Variant.Outlined"
|
||||||
|
Clearable="true"
|
||||||
|
ShowProgressIndicator="true"
|
||||||
|
CoerceText="false"
|
||||||
|
OnClearButtonClick="()=> OnSelected(null)" />
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
using CMSMicroservice.Protobuf.Protos.DiscountProduct;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace BackOffice.Pages.AutoComplete;
|
||||||
|
|
||||||
|
public partial class DiscountProductsAutoComplete
|
||||||
|
{
|
||||||
|
[Inject] public DiscountProductContract.DiscountProductContractClient DiscountProductService { get; set; } = default!;
|
||||||
|
|
||||||
|
[Parameter] public long? Value { get; set; }
|
||||||
|
[Parameter] public string? Label { get; set; } = "محصول تخفیفی";
|
||||||
|
[Parameter] public EventCallback<long?> ValueChanged { get; set; }
|
||||||
|
|
||||||
|
private List<DiscountProductDto> _items = new();
|
||||||
|
private DiscountProductDto? _item;
|
||||||
|
|
||||||
|
protected override async void OnParametersSet()
|
||||||
|
{
|
||||||
|
await base.OnParametersSetAsync();
|
||||||
|
|
||||||
|
if (Value.HasValue && Value.Value > 0 && (_item == null || _item.Id != Value.Value))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var getAll = await DiscountProductService.GetDiscountProductsAsync(new GetDiscountProductsRequest
|
||||||
|
{
|
||||||
|
PageNumber = 1,
|
||||||
|
PageSize = 50
|
||||||
|
});
|
||||||
|
|
||||||
|
if (getAll?.Models != null)
|
||||||
|
{
|
||||||
|
_item = getAll.Models.FirstOrDefault(x => x.Id == Value.Value);
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Silently handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnSelected(DiscountProductDto? model)
|
||||||
|
{
|
||||||
|
if (model == null)
|
||||||
|
{
|
||||||
|
_item = null;
|
||||||
|
await ValueChanged.InvokeAsync(null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_item = model;
|
||||||
|
await ValueChanged.InvokeAsync(model.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<DiscountProductDto>> Search(string value, CancellationToken token)
|
||||||
|
{
|
||||||
|
var request = new GetDiscountProductsRequest
|
||||||
|
{
|
||||||
|
PageNumber = 1,
|
||||||
|
PageSize = 9
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(value))
|
||||||
|
{
|
||||||
|
request.SearchQuery = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var getAll = await DiscountProductService.GetDiscountProductsAsync(request);
|
||||||
|
_items = getAll?.Models?.ToList() ?? new List<DiscountProductDto>();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
_items = new List<DiscountProductDto>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _items;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
@using CMSMicroservice.Protobuf.Protos.Inventory
|
@using CMSMicroservice.Protobuf.Protos.Inventory
|
||||||
@using Google.Protobuf.WellKnownTypes
|
@using Google.Protobuf.WellKnownTypes
|
||||||
@using InventoryProductType = CMSMicroservice.Protobuf.Protos.Inventory.ProductType
|
@using InventoryProductType = CMSMicroservice.Protobuf.Protos.Inventory.ProductType
|
||||||
|
@using BackOffice.Pages.AutoComplete
|
||||||
|
|
||||||
<MudDialog>
|
<MudDialog>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
@@ -19,12 +20,16 @@
|
|||||||
</MudSelect>
|
</MudSelect>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField T="long" @bind-Value="_productId"
|
@if (_productType == InventoryProductType.RegularProduct)
|
||||||
Label="شناسه محصول"
|
{
|
||||||
Variant="Variant.Outlined"
|
<ProductsAutoComplete @bind-Value="_productId"
|
||||||
Required="true"
|
Label="انتخاب محصول عادی" />
|
||||||
RequiredError="شناسه محصول الزامی است"
|
}
|
||||||
Min="1" />
|
else
|
||||||
|
{
|
||||||
|
<DiscountProductsAutoComplete @bind-Value="_discountProductId"
|
||||||
|
Label="انتخاب محصول تخفیفی" />
|
||||||
|
}
|
||||||
</MudItem>
|
</MudItem>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -103,7 +108,8 @@
|
|||||||
private bool _isSubmitting;
|
private bool _isSubmitting;
|
||||||
|
|
||||||
private InventoryProductType _productType = InventoryProductType.RegularProduct;
|
private InventoryProductType _productType = InventoryProductType.RegularProduct;
|
||||||
private long _productId;
|
private long? _productId;
|
||||||
|
private long? _discountProductId;
|
||||||
private long? _warehouseId;
|
private long? _warehouseId;
|
||||||
private int _quantity = 1;
|
private int _quantity = 1;
|
||||||
private string _referenceNumber = string.Empty;
|
private string _referenceNumber = string.Empty;
|
||||||
@@ -111,9 +117,12 @@
|
|||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
if (ProductIdParam.HasValue)
|
if (ProductIdParam.HasValue && ProductTypeParam.HasValue)
|
||||||
{
|
{
|
||||||
_productId = ProductIdParam.Value;
|
if (ProductTypeParam.Value == InventoryProductType.DiscountProduct)
|
||||||
|
_discountProductId = ProductIdParam.Value;
|
||||||
|
else
|
||||||
|
_productId = ProductIdParam.Value;
|
||||||
}
|
}
|
||||||
if (ProductTypeParam.HasValue)
|
if (ProductTypeParam.HasValue)
|
||||||
{
|
{
|
||||||
@@ -144,9 +153,19 @@
|
|||||||
_isSubmitting = true;
|
_isSubmitting = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var selectedProductId = ProductIdParam
|
||||||
|
?? (_productType == InventoryProductType.DiscountProduct ? _discountProductId : _productId);
|
||||||
|
|
||||||
|
if (!selectedProductId.HasValue || selectedProductId.Value <= 0)
|
||||||
|
{
|
||||||
|
Snackbar.Add("لطفاً یک محصول انتخاب کنید", Severity.Warning);
|
||||||
|
_isSubmitting = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var request = new AddStockRequest
|
var request = new AddStockRequest
|
||||||
{
|
{
|
||||||
ProductId = ProductIdParam ?? _productId,
|
ProductId = selectedProductId.Value,
|
||||||
ProductType = ProductTypeParam ?? _productType,
|
ProductType = ProductTypeParam ?? _productType,
|
||||||
Quantity = _quantity,
|
Quantity = _quantity,
|
||||||
ReferenceNumber = _referenceNumber ?? string.Empty,
|
ReferenceNumber = _referenceNumber ?? string.Empty,
|
||||||
|
|||||||
Reference in New Issue
Block a user