This commit is contained in:
2025-10-27 21:39:50 -04:00
parent 31f723bea4
commit 2fecd5b315
22 changed files with 1198 additions and 14 deletions

View File

@@ -0,0 +1,132 @@
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
};
}
}