133 lines
3.9 KiB
C#
133 lines
3.9 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Prefab.Shared.Catalog.Products;
|
|
|
|
namespace Prefab.Web.Client.Models.Catalog;
|
|
|
|
/// <summary>
|
|
/// UI-facing projection of the catalog product detail configuration payload.
|
|
/// </summary>
|
|
public sealed class ProductDisplayModel
|
|
{
|
|
public Guid Id { get; init; }
|
|
|
|
public string Slug { get; init; } = string.Empty;
|
|
|
|
public string Name { get; init; } = string.Empty;
|
|
|
|
public string? Description { get; init; }
|
|
|
|
public decimal? BasePrice { get; init; }
|
|
|
|
public string? Sku { get; init; }
|
|
|
|
public IReadOnlyList<CategoryRef> Categories { get; init; } = Array.Empty<CategoryRef>();
|
|
|
|
public IReadOnlyList<OptionDefinition> Options { get; init; } = Array.Empty<OptionDefinition>();
|
|
|
|
public IReadOnlyList<Spec> Specs { get; init; } = Array.Empty<Spec>();
|
|
|
|
public IReadOnlyDictionary<string, string>? GenericAttributes { get; init; }
|
|
|
|
public sealed record OptionDefinition(
|
|
Guid Id,
|
|
string Code,
|
|
string Name,
|
|
int DataType,
|
|
bool IsVariantAxis,
|
|
string? Unit,
|
|
decimal? Min,
|
|
decimal? Max,
|
|
decimal? Step,
|
|
decimal? PricePerUnit,
|
|
IReadOnlyList<Tier> Tiers,
|
|
IReadOnlyList<OptionValue> Values);
|
|
|
|
public sealed record OptionValue(
|
|
Guid Id,
|
|
string Code,
|
|
string Label,
|
|
decimal? PriceDelta,
|
|
int PriceDeltaKind);
|
|
|
|
public sealed record Tier(
|
|
decimal FromInclusive,
|
|
decimal? ToInclusive,
|
|
decimal UnitRate,
|
|
decimal? FlatDelta);
|
|
|
|
public sealed record Spec(
|
|
string Name,
|
|
string? Value,
|
|
decimal? NumericValue,
|
|
string? UnitCode);
|
|
|
|
public sealed record CategoryRef(
|
|
Guid Id,
|
|
string Name,
|
|
string Slug);
|
|
|
|
public static ProductDisplayModel From(GetProductDetail.ProductDetailDto product)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(product);
|
|
|
|
var options = product.Options?
|
|
.Select(option => new OptionDefinition(
|
|
option.Id,
|
|
option.Code,
|
|
option.Name,
|
|
option.DataType,
|
|
option.IsVariantAxis,
|
|
option.Unit,
|
|
option.Min,
|
|
option.Max,
|
|
option.Step,
|
|
option.PricePerUnit,
|
|
option.Tiers?
|
|
.Select(tier => new Tier(
|
|
tier.FromInclusive,
|
|
tier.ToInclusive,
|
|
tier.UnitRate,
|
|
tier.FlatDelta))
|
|
.ToList() ?? new List<Tier>(),
|
|
option.Values?
|
|
.Select(value => new OptionValue(
|
|
value.Id,
|
|
value.Code,
|
|
value.Label,
|
|
value.PriceDelta,
|
|
value.PriceDeltaKind))
|
|
.ToList() ?? new List<OptionValue>()))
|
|
.ToList() ?? new List<OptionDefinition>();
|
|
|
|
var specs = product.Specs?
|
|
.Select(spec => new Spec(
|
|
spec.Name,
|
|
spec.Value,
|
|
spec.NumericValue,
|
|
spec.UnitCode))
|
|
.ToList() ?? new List<Spec>();
|
|
|
|
var categories = product.Categories?
|
|
.Select(category => new CategoryRef(
|
|
category.Id,
|
|
category.Name,
|
|
category.Slug))
|
|
.ToList() ?? new List<CategoryRef>();
|
|
|
|
return new ProductDisplayModel
|
|
{
|
|
Id = product.Id,
|
|
Slug = product.Slug,
|
|
Name = product.Name,
|
|
Description = product.Description,
|
|
BasePrice = product.Price,
|
|
Sku = product.Sku,
|
|
Categories = categories,
|
|
Options = options,
|
|
Specs = specs,
|
|
GenericAttributes = product.GenericAttributes
|
|
};
|
|
}
|
|
}
|