138 lines
4.2 KiB
C#
138 lines
4.2 KiB
C#
using System.Collections.Concurrent;
|
|
using FrontOffice.BFF.Products.Protobuf.Protos.Products;
|
|
|
|
namespace FrontOffice.Main.Utilities;
|
|
|
|
public record Product(
|
|
long Id,
|
|
string Title,
|
|
string Description,
|
|
string ImageUrl,
|
|
long Price,
|
|
int Discount = 0,
|
|
int Rate = 0,
|
|
int RemainingCount = 0)
|
|
{
|
|
public IReadOnlyList<ProductGalleryImage> Gallery { get; init; } = Array.Empty<ProductGalleryImage>();
|
|
}
|
|
|
|
public record ProductGalleryImage(
|
|
long ProductGalleryId,
|
|
long ProductImageId,
|
|
string Title,
|
|
string ImageUrl,
|
|
string ThumbnailUrl);
|
|
|
|
public class ProductService
|
|
{
|
|
|
|
private readonly ConcurrentDictionary<long, Product> _cache = new();
|
|
private readonly ProductsContract.ProductsContractClient _client;
|
|
|
|
public ProductService(ProductsContract.ProductsContractClient client)
|
|
{
|
|
_client = client;
|
|
|
|
}
|
|
|
|
public async Task<List<Product>> GetProductsAsync(string? query = null)
|
|
{
|
|
try
|
|
{
|
|
var resp = await _client.GetAllProductsByFilterAsync(new GetAllProductsByFilterRequest
|
|
{
|
|
Filter = new GetAllProductsByFilterFilter
|
|
{
|
|
Title = query ?? string.Empty,
|
|
Description = query ?? string.Empty,
|
|
ShortInfomation = query ?? string.Empty,
|
|
FullInformation = query ?? string.Empty
|
|
}
|
|
});
|
|
return MapAndCache(resp.Models);
|
|
}
|
|
catch
|
|
{
|
|
IEnumerable<Product> list = _cache.Values;
|
|
if (!string.IsNullOrWhiteSpace(query))
|
|
{
|
|
var q = query.Trim();
|
|
list = list.Where(p => p.Title.Contains(q, StringComparison.OrdinalIgnoreCase) || p.Description.Contains(q, StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
return list.OrderBy(p => p.Id).ToList();
|
|
}
|
|
}
|
|
|
|
public async Task<Product?> GetByIdAsync(long id)
|
|
{
|
|
if (_cache.TryGetValue(id, out var cached)) return cached;
|
|
|
|
try
|
|
{
|
|
var resp = await _client.GetProductsAsync(new GetProductsRequest { Id = id });
|
|
if (resp == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return MapAndCache(resp);
|
|
}
|
|
catch
|
|
{
|
|
_cache.TryGetValue(id, out var result);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
private List<Product> MapAndCache(Google.Protobuf.Collections.RepeatedField<GetAllProductsByFilterResponseModel> models)
|
|
{
|
|
var list = new List<Product>();
|
|
foreach (var m in models)
|
|
{
|
|
var p = new Product(
|
|
Id: m.Id,
|
|
Title: m.Title ?? string.Empty,
|
|
Description: m.Description ?? string.Empty,
|
|
ImageUrl: string.IsNullOrWhiteSpace(m.ImagePath) ? string.Empty : UrlUtility.DownloadUrl + m.ImagePath,
|
|
Price: m.Price,
|
|
Discount: m.Discount,
|
|
Rate: m.Rate,
|
|
RemainingCount: m.RemainingCount
|
|
);
|
|
_cache[p.Id] = p;
|
|
list.Add(p);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
private Product MapAndCache(GetProductsResponse model)
|
|
{
|
|
var gallery = model.Gallery
|
|
.Select(item => new ProductGalleryImage(
|
|
ProductGalleryId: item.ProductGalleryId,
|
|
ProductImageId: item.ProductImageId,
|
|
Title: item.Title ?? string.Empty,
|
|
ImageUrl: BuildUrl(item.ImagePath),
|
|
ThumbnailUrl: BuildUrl(item.ImageThumbnailPath)))
|
|
.ToList();
|
|
|
|
var product = new Product(
|
|
Id: model.Id,
|
|
Title: model.Title ?? string.Empty,
|
|
Description: model.Description ?? string.Empty,
|
|
ImageUrl: BuildUrl(model.ImagePath),
|
|
Price: model.Price,
|
|
Discount: model.Discount,
|
|
Rate: model.Rate,
|
|
RemainingCount: model.RemainingCount)
|
|
{
|
|
Gallery = gallery
|
|
};
|
|
|
|
_cache[product.Id] = product;
|
|
return product;
|
|
}
|
|
|
|
private static string BuildUrl(string? path) => string.IsNullOrWhiteSpace(path) ? string.Empty : UrlUtility.DownloadUrl + path;
|
|
}
|