Latest
This commit is contained in:
@@ -4,11 +4,13 @@ using Prefab.Domain.Exceptions;
|
||||
using Prefab.Endpoints;
|
||||
using Prefab.Shared.Catalog;
|
||||
using Prefab.Shared.Catalog.Products;
|
||||
using Prefab.Shared;
|
||||
using Prefab.Web.Client.Models.Catalog;
|
||||
using Prefab.Web.Client.Models.Shared;
|
||||
using Prefab.Web.Client.ViewModels.Catalog;
|
||||
using Prefab.Web.Client.Services;
|
||||
using UrlBuilder = Prefab.Web.UrlPolicy.UrlPolicy;
|
||||
using CatalogNotFoundException = Prefab.Catalog.Domain.Exceptions.CatalogNotFoundException;
|
||||
|
||||
namespace Prefab.Web.Gateway;
|
||||
|
||||
@@ -29,6 +31,18 @@ public static class Products
|
||||
return Results.Json(result, statusCode: status);
|
||||
})
|
||||
.WithTags(nameof(Products));
|
||||
|
||||
endpoints.MapGet(
|
||||
"/bff/catalog/products/{slug}",
|
||||
async (DetailService service, string slug, CancellationToken cancellationToken) =>
|
||||
{
|
||||
var result = await service.Get(slug, cancellationToken);
|
||||
var status = result.Problem?.StatusCode ?? (result.IsSuccess
|
||||
? StatusCodes.Status200OK
|
||||
: StatusCodes.Status500InternalServerError);
|
||||
return Results.Json(result, statusCode: status);
|
||||
})
|
||||
.WithTags(nameof(Products));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,4 +131,77 @@ public static class Products
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class DetailService(IModuleClient moduleClient)
|
||||
{
|
||||
public async Task<Result<ProductDisplayModel>> Get(string slug, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(slug))
|
||||
{
|
||||
return Result<ProductDisplayModel>.Failure(new ResultProblem
|
||||
{
|
||||
Title = "Invalid product slug.",
|
||||
Detail = "Product slug is required.",
|
||||
StatusCode = StatusCodes.Status400BadRequest
|
||||
});
|
||||
}
|
||||
|
||||
var normalizedSlug = slug.Trim();
|
||||
|
||||
try
|
||||
{
|
||||
var response = await moduleClient.Product.GetProductConfig(normalizedSlug, cancellationToken);
|
||||
var product = response.Product ?? throw new InvalidOperationException("Product payload was empty.");
|
||||
var model = ProductDisplayModel.From(product);
|
||||
return Result<ProductDisplayModel>.Success(model);
|
||||
}
|
||||
catch (ValidationException validationException)
|
||||
{
|
||||
var problem = ResultProblem.FromValidation(validationException);
|
||||
return Result<ProductDisplayModel>.Failure(problem);
|
||||
}
|
||||
catch (CatalogNotFoundException)
|
||||
{
|
||||
return Result<ProductDisplayModel>.Failure(new ResultProblem
|
||||
{
|
||||
Title = "Product not found.",
|
||||
Detail = $"Product '{normalizedSlug}' was not found.",
|
||||
StatusCode = StatusCodes.Status404NotFound
|
||||
});
|
||||
}
|
||||
catch (RemoteProblemException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
return Result<ProductDisplayModel>.Failure(new ResultProblem
|
||||
{
|
||||
Title = "Product not found.",
|
||||
Detail = $"Product '{normalizedSlug}' was not found.",
|
||||
StatusCode = StatusCodes.Status404NotFound
|
||||
});
|
||||
}
|
||||
catch (DomainException domainException)
|
||||
{
|
||||
var problem = ResultProblem.Unexpected(domainException.Message, domainException, HttpStatusCode.UnprocessableEntity);
|
||||
return Result<ProductDisplayModel>.Failure(problem);
|
||||
}
|
||||
catch (RemoteProblemException ex)
|
||||
{
|
||||
var problem = ResultProblem.Unexpected("Failed to retrieve product.", ex, ex.StatusCode);
|
||||
return Result<ProductDisplayModel>.Failure(problem);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
var problem = ResultProblem.Unexpected("Failed to retrieve product.", exception);
|
||||
return Result<ProductDisplayModel>.Failure(problem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class ProductClientExtensions
|
||||
{
|
||||
public static Task<GetProductDetail.Response> GetProductConfig(
|
||||
this IProductClient productClient,
|
||||
string slug,
|
||||
CancellationToken cancellationToken) =>
|
||||
productClient.GetProductDetail(slug, cancellationToken);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user