Skip to content

Commit

Permalink
Merge branch 'main' into feature/ALFMOB-40-mock-add-to-bag-add-to-wis…
Browse files Browse the repository at this point in the history
…h-list
  • Loading branch information
timea-v committed Nov 13, 2024
2 parents 0d16b1e + 1912e9d commit fc7e580
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 30 deletions.
14 changes: 13 additions & 1 deletion Alfie/Alfie/Views/ProductDetails/ProductDetailsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,10 @@ extension ProductDetailsView {
VStack(alignment: .leading, spacing: Spacing.space100) {
titleHeader

Spacer()

price

colorSelector

if canShowSize {
Expand Down Expand Up @@ -344,11 +348,19 @@ extension ProductDetailsView {
.foregroundStyle(Colors.primary.black)
.frame(maxWidth: .infinity, minHeight: Constants.minTitleHeight, alignment: .leading)
.shimmering(while: shimmeringBinding(for: .titleHeader), animateOnStateTransition: false)
// TODO: Add a spacer and the price here in a future ticket
}
}
}

@ViewBuilder private var price: some View {
if let priceType = viewModel.priceType {
PriceComponentView(
type: priceType,
configuration: .init(preferredDistribution: .horizontal, size: .small, textAlignment: .leading)
)
}
}

private var colorSheet: some View {
ProductDetailsColorAndSizeSheet(
viewModel: viewModel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ final class ProductDetailsViewModel: ProductDetailsViewModelProtocol {
productImageUrls.count == 1
}

var priceType: PriceType? {
product?.priceType
}

init(productId: String, product: Product?, dependencies: ProductDetailsDependencyContainerProtocol) {
self.productId = productId
baseProduct = product
Expand Down
35 changes: 35 additions & 0 deletions Alfie/AlfieTests/Features/ProductDetailsViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,41 @@ final class ProductDetailsViewModelTests: XCTestCase {

XCTAssertEqual(sut.productDescription, product.longDescription)
}

func test_price_type_is_nil_when_no_product_is_missing() {
initViewModel()
XCTAssertNil(sut.priceType)
}

func test_price_type_is_not_nil_with_sale_product() {
initViewModel(product: Product.blazer)
guard case .sale(let fullPrice, let finalPrice) = sut.priceType else {
XCTFail("Unexpected price type")
return
}
XCTAssertEqual(fullPrice, "$495.00")
XCTAssertEqual(finalPrice, "$299.00")
}

func test_price_type_is_not_nil_with_range_price_product() {
initViewModel(product: Product.hat)
guard case .range(let lowerBound, let upperBound, let separator) = sut.priceType else {
XCTFail("Unexpected price type")
return
}
XCTAssertEqual(lowerBound, "$750.00")
XCTAssertEqual(upperBound, "$850.00")
XCTAssertEqual(separator, "-")
}

func test_price_type_is_not_nil_with_default_price_product() {
initViewModel(product: Product.necklace)
guard case .default(let price) = sut.priceType else {
XCTFail("Unexpected price type")
return
}
XCTAssertEqual(price, "$279.00")
}

// MARK: - Product fetch

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class MockProductDetailsViewModel: ProductDetailsViewModelProtocol {
public var shareConfiguration: ShareConfiguration?
public var shouldShowMediaPaginatedControl = true
public var hasSingleImage: Bool = false
public var priceType: PriceType? = nil

public init(state: ViewState<ProductDetailsViewStateModel, ProductDetailsViewErrorType> = .loading,
productId: String = "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ public enum ProductDetailsComplementaryInfoType {
case returns
}

// MARK: - PriceType

public enum PriceType {
case `default`(price: String)
case sale(fullPrice: String, finalPrice: String)
case range(lowerBound: String, upperBound: String, separator: String)
}

// MARK: - ProductDetailsViewModelProtocol

public protocol ProductDetailsViewModelProtocol: ObservableObject {
Expand All @@ -59,6 +67,7 @@ public protocol ProductDetailsViewModelProtocol: ObservableObject {
var shareConfiguration: ShareConfiguration? { get }
var shouldShowMediaPaginatedControl: Bool { get }
var hasSingleImage: Bool { get }
var priceType: PriceType? { get }

func viewDidAppear()
func shouldShow(section: ProductDetailsSection) -> Bool
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
public extension Product {
var priceType: PriceType {
if let range = priceRange {
guard let high = range.high else { return .default(price: range.low.amountFormatted) }
return .range(lowerBound: range.low.amountFormatted, upperBound: high.amountFormatted, separator: "-")
} else {
guard let salePreviousPrice = defaultVariant.price.was else {
return .default(price: defaultVariant.price.amount.amountFormatted)
}
return .sale(
fullPrice: salePreviousPrice.amountFormatted,
finalPrice: defaultVariant.price.amount.amountFormatted
)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,6 @@
import Models
import SwiftUI

public enum PriceType: Hashable {
case `default`(price: String)
case sale(fullPrice: String, finalPrice: String)
case range(lowerBound: String, upperBound: String, separator: String)
}

extension PriceType {
init(from product: Product) {
if let range = product.priceRange {
if let high = range.high {
self = .range(lowerBound: range.low.amountFormatted, upperBound: high.amountFormatted, separator: "-")
} else {
self = .default(price: range.low.amountFormatted)
}
} else {
if let salePreviousPrice = product.defaultVariant.price.was {
self = .sale(
fullPrice: salePreviousPrice.amountFormatted,
finalPrice: product.defaultVariant.price.amount.amountFormatted
)
} else {
self = .default(price: product.defaultVariant.price.amount.amountFormatted)
}
}
}
}

public extension PriceType {
static func formattedDefault(_ defaultPrice: Double, currencyCode: String) -> PriceType {
.default(price: defaultPrice.formatted(.currency(code: currencyCode)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public struct HorizontalProductCard: View {
} else {
""
}
self.priceType = PriceType(from: product)
self.priceType = product.priceType
self.colorTitle = colorTitle
self.sizeTitle = sizeTitle
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public struct VerticalProductCard: View {
self.image = product.defaultVariant.media.first?.asImage?.url
self.designer = product.brand.name
self.name = product.name
self.priceType = PriceType(from: product)
self.priceType = product.priceType
self.onUserAction = onUserAction
self._isSkeleton = isSkeleton
}
Expand Down

0 comments on commit fc7e580

Please sign in to comment.