-
Notifications
You must be signed in to change notification settings - Fork 111
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Woo POS] [Variable Products] Add parent product to the POSItem enum,…
… and make UI (#14771)
- Loading branch information
Showing
10 changed files
with
224 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
WooCommerce/Classes/POS/Presentation/ParentProductCardView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import SwiftUI | ||
import struct Yosemite.POSParentProduct | ||
|
||
/// Displays a card for a parent product in POS. | ||
struct ParentProductCardView: View { | ||
private let parentProduct: POSParentProduct | ||
|
||
@ScaledMetric private var scale: CGFloat = 1.0 | ||
@Environment(\.dynamicTypeSize) var dynamicTypeSize | ||
|
||
init(parentProduct: POSParentProduct) { | ||
self.parentProduct = parentProduct | ||
} | ||
|
||
var body: some View { | ||
HStack(spacing: Constants.cardSpacing) { | ||
POSItemImageView(imageSource: parentProduct.productImageSource, | ||
imageSize: Constants.productCardSize * scale, | ||
scale: scale) | ||
.frame(width: min(Constants.productCardSize * scale, Constants.maximumProductCardSize), | ||
height: Constants.productCardSize * scale) | ||
.clipped() | ||
|
||
VStack(alignment: .leading, spacing: Constants.textSpacing) { | ||
Text(parentProduct.name) | ||
.lineLimit(2) | ||
.foregroundStyle(Color.posPrimaryText) | ||
.multilineTextAlignment(.leading) | ||
.font(Constants.itemNameFont) | ||
|
||
detailView() | ||
} | ||
.padding(.horizontal, Constants.horizontalTextPadding * (1 / scale)) | ||
.padding(.vertical, Constants.verticalTextPadding * (1 / scale)) | ||
Spacer() | ||
} | ||
.frame(maxWidth: .infinity, idealHeight: Constants.productCardSize * scale) | ||
.background(Color.posSecondaryBackground) | ||
.posItemCardBorderStyles() | ||
} | ||
} | ||
|
||
private extension ParentProductCardView { | ||
@ViewBuilder | ||
func detailView() -> some View { | ||
switch parentProduct.type { | ||
case .variable: | ||
Text(Localization.variationsAvailable) | ||
.foregroundStyle(Color.posSecondaryText) | ||
.font(.posBodyRegular) | ||
} | ||
} | ||
} | ||
|
||
private extension ParentProductCardView { | ||
enum Localization { | ||
static let variationsAvailable = NSLocalizedString( | ||
"pos.parentProductCard.optionsAvailable", | ||
value: "Options available", | ||
comment: "Text indicating that there are options available for a parent product" | ||
) | ||
} | ||
} | ||
|
||
private extension ParentProductCardView { | ||
enum Constants { | ||
static let productCardSize: CGFloat = 112 | ||
static let maximumProductCardSize: CGFloat = Constants.productCardSize * 2 | ||
static let cardSpacing: CGFloat = 0 | ||
static let textSpacing: CGFloat = 8 | ||
static let horizontalTextPadding: CGFloat = 32 | ||
static let verticalTextPadding: CGFloat = 8 | ||
static let itemNameFont: POSFontStyle = .posBodyEmphasized | ||
} | ||
} | ||
|
||
#if DEBUG | ||
#Preview { | ||
let parentProduct = POSParentProduct(id: UUID(), name: "Parent variable product", productImageSource: nil, productID: 42, type: .variable) | ||
ParentProductCardView(parentProduct: parentProduct) | ||
} | ||
#endif |
29 changes: 29 additions & 0 deletions
29
WooCommerce/Classes/POS/Presentation/Reusable Views/POSItemCardBorderStylesModifier.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import SwiftUI | ||
|
||
struct POSItemCardBorderStylesModifier: ViewModifier { | ||
func body(content: Content) -> some View { | ||
content | ||
.overlay { | ||
RoundedRectangle(cornerRadius: Constants.cardCornerRadius) | ||
.stroke(Color.black, lineWidth: Constants.nilOutline) | ||
} | ||
.clipShape(RoundedRectangle(cornerRadius: Constants.cardCornerRadius)) | ||
.shadow(color: Color.black.opacity(0.08), radius: 4, y: 2) | ||
} | ||
} | ||
|
||
private extension POSItemCardBorderStylesModifier { | ||
enum Constants { | ||
static let cardCornerRadius: CGFloat = 8.0 | ||
// The use of stroke means the shape is rendered as an outline (border) rather than a filled shape, | ||
// since we still have to give it a value, we use 0 so it renders no border but it's shaped as one. | ||
static let nilOutline: CGFloat = 0 | ||
} | ||
} | ||
|
||
extension View { | ||
/// Applies the POS item card border styles to the view. | ||
func posItemCardBorderStyles() -> some View { | ||
self.modifier(POSItemCardBorderStylesModifier()) | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
WooCommerce/Classes/POS/Presentation/Reusable Views/POSItemImageView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import SwiftUI | ||
|
||
/// A view that displays an image in a POS item view. | ||
struct POSItemImageView: View { | ||
let imageSource: String? | ||
let imageSize: CGFloat | ||
let scale: CGFloat | ||
|
||
var body: some View { | ||
if let imageSource = imageSource { | ||
ProductImageThumbnail(productImageURL: URL(string: imageSource), | ||
productImageSize: imageSize, | ||
scale: scale, | ||
foregroundColor: .clear, | ||
cachesOriginalImage: true) | ||
} else { | ||
Rectangle() | ||
.foregroundColor(Color(.secondarySystemFill)) | ||
} | ||
} | ||
} | ||
|
||
#Preview("Placeholder") { | ||
POSItemImageView(imageSource: nil, | ||
imageSize: 112, | ||
scale: 1) | ||
} | ||
|
||
#Preview("Image") { | ||
POSItemImageView(imageSource: "https://pd.w.org/2024/12/986762d0d4d4cf17.82435881-scaled.jpeg", | ||
imageSize: 112, | ||
scale: 1) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import Foundation | ||
|
||
public enum POSParentProductType { | ||
case variable | ||
} | ||
|
||
public struct POSParentProduct: Equatable, Hashable, Identifiable { | ||
public let id: UUID | ||
public let name: String | ||
public let productImageSource: String? | ||
public let productID: Int64 | ||
public let type: POSParentProductType | ||
|
||
public init(id: UUID, name: String, productImageSource: String?, productID: Int64, type: POSParentProductType) { | ||
self.id = id | ||
self.name = name | ||
self.productImageSource = productImageSource | ||
self.productID = productID | ||
self.type = type | ||
} | ||
} |
Oops, something went wrong.