Add product categories and full information display
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FrontOffice.BFF.Products.Protobuf.Protos.Products;
|
||||
|
||||
namespace FrontOffice.Main.Utilities;
|
||||
@@ -7,13 +9,18 @@ public record Product(
|
||||
long Id,
|
||||
string Title,
|
||||
string Description,
|
||||
string FullInformation,
|
||||
string ImageUrl,
|
||||
long Price,
|
||||
int Discount = 0,
|
||||
int Discount = 1,
|
||||
int Rate = 0,
|
||||
int RemainingCount = 0)
|
||||
{
|
||||
public IReadOnlyList<ProductGalleryImage> Gallery { get; init; } = Array.Empty<ProductGalleryImage>();
|
||||
public IReadOnlyList<ProductGalleryImage> Gallery { get; init; }
|
||||
= [];
|
||||
|
||||
public IReadOnlyList<ProductCategoryPathInfo> Categories { get; init; }
|
||||
= [];
|
||||
}
|
||||
|
||||
public record ProductGalleryImage(
|
||||
@@ -23,16 +30,28 @@ public record ProductGalleryImage(
|
||||
string ImageUrl,
|
||||
string ThumbnailUrl);
|
||||
|
||||
public record ProductCategoryNodeInfo(
|
||||
long Id,
|
||||
string Title,
|
||||
long? ParentId);
|
||||
|
||||
public record ProductCategoryPathInfo(
|
||||
long CategoryId,
|
||||
string Title,
|
||||
IReadOnlyList<ProductCategoryNodeInfo> Nodes)
|
||||
{
|
||||
public string DisplayLabel => string.Join(" › ", Nodes.Select(node => node.Title));
|
||||
public ProductCategoryNodeInfo Leaf => Nodes.Last();
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -57,8 +76,11 @@ public class ProductService
|
||||
if (!string.IsNullOrWhiteSpace(query))
|
||||
{
|
||||
var q = query.Trim();
|
||||
list = list.Where(p => p.Title.Contains(q, StringComparison.OrdinalIgnoreCase) || p.Description.Contains(q, StringComparison.OrdinalIgnoreCase));
|
||||
list = list.Where(p =>
|
||||
p.Title.Contains(q, StringComparison.OrdinalIgnoreCase) ||
|
||||
p.Description.Contains(q, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
return list.OrderBy(p => p.Id).ToList();
|
||||
}
|
||||
}
|
||||
@@ -84,7 +106,8 @@ public class ProductService
|
||||
}
|
||||
}
|
||||
|
||||
private List<Product> MapAndCache(Google.Protobuf.Collections.RepeatedField<GetAllProductsByFilterResponseModel> models)
|
||||
private List<Product> MapAndCache(
|
||||
Google.Protobuf.Collections.RepeatedField<GetAllProductsByFilterResponseModel> models)
|
||||
{
|
||||
var list = new List<Product>();
|
||||
foreach (var m in models)
|
||||
@@ -93,15 +116,20 @@ public class ProductService
|
||||
Id: m.Id,
|
||||
Title: m.Title ?? string.Empty,
|
||||
Description: m.Description ?? string.Empty,
|
||||
FullInformation: m.FullInformation ?? 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;
|
||||
if (_cache.All(a => a.Key != p.Id))
|
||||
_cache[p.Id] = p;
|
||||
|
||||
|
||||
list.Add(p);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -120,18 +148,53 @@ public class ProductService
|
||||
Id: model.Id,
|
||||
Title: model.Title ?? string.Empty,
|
||||
Description: model.Description ?? string.Empty,
|
||||
FullInformation: model.FullInformation ?? string.Empty,
|
||||
ImageUrl: BuildUrl(model.ImagePath),
|
||||
Price: model.Price,
|
||||
Discount: model.Discount,
|
||||
Rate: model.Rate,
|
||||
RemainingCount: model.RemainingCount)
|
||||
{
|
||||
Gallery = gallery
|
||||
Gallery = gallery,
|
||||
Categories = MapCategoryPaths(model.Categories)
|
||||
};
|
||||
|
||||
_cache[product.Id] = product;
|
||||
return product;
|
||||
}
|
||||
|
||||
private static string BuildUrl(string? path) => string.IsNullOrWhiteSpace(path) ? string.Empty : UrlUtility.DownloadUrl + path;
|
||||
}
|
||||
private static string BuildUrl(string? path) =>
|
||||
string.IsNullOrWhiteSpace(path) ? string.Empty : UrlUtility.DownloadUrl + path;
|
||||
|
||||
private static IReadOnlyList<ProductCategoryPathInfo> MapCategoryPaths(IEnumerable<ProductCategoryPath>? categories)
|
||||
{
|
||||
if (categories is null)
|
||||
{
|
||||
return Array.Empty<ProductCategoryPathInfo>();
|
||||
}
|
||||
|
||||
var result = new List<ProductCategoryPathInfo>();
|
||||
foreach (var category in categories)
|
||||
{
|
||||
var nodes = category.Path
|
||||
.Select(node => new ProductCategoryNodeInfo(
|
||||
Id: node.Id,
|
||||
Title: node.Title ?? string.Empty,
|
||||
ParentId: node.ParentId
|
||||
))
|
||||
.ToList();
|
||||
|
||||
if (nodes.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result.Add(new ProductCategoryPathInfo(
|
||||
CategoryId: category.CategoryId,
|
||||
Title: category.Title ?? string.Empty,
|
||||
Nodes: nodes));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user