RecipeDetailsUnaddedProduct
Unadded
To create your own recipe detail unadded product template you create a class that implements RecipeDetailsUnaddedProductProtocol
- Boilerplate
- Full Example
import SwiftUI
import MealziOSSDK
import mealzcore
public struct MyCustomRecipeDetailsUnaddedProductView: RecipeDetailsUnaddedProductProtocol {
public func content(params: RecipeDetailsUnaddedProductParameters) -> some View {
// Your custom design here
}
}
import SwiftUI
import MealziOSSDK
import mealzcore
@available(iOS 14, *)
public struct MealzRecipeDetailsUnaddedProductView: RecipeDetailsUnaddedProductProtocol {
public init() {}
let dim = Dimension.sharedInstance
public func content(params: RecipeDetailsUnaddedProductParameters) -> some View {
var lockButton: Bool {
return params.productStatus == ComponentUiState.locked
|| params.productStatus == ComponentUiState.loading
}
VStack {
HStack {
Text(params.data.ingredientName.capitalizingFirstLetter())
.padding(dim.mPadding)
.miamFontStyle(style: MiamFontStyleProvider.sharedInstance.bodyBigBoldStyle)
.foregroundColor(Color.mealzColor(.standardDarkText))
Spacer()
if let unit = params.data.ingredientUnit {
Text(QuantityFormatter.companion.readableFloatNumber(value: params.data.ingredientQuantity, unit: unit))
.padding(dim.mPadding)
.miamFontStyle(style: MiamFontStyleProvider.sharedInstance.bodyMediumStyle)
}
}
.foregroundColor(Color.mealzColor(.darkestGray))
.frame(height: 40)
.background(Color.mealzColor(.lightBackground))
.cornerRadius(dim.mCornerRadius, corners: .top)
HStack {
if let pictureURL = URL(string: params.data.pictureURL) {
AnyView(AsyncImage(url: pictureURL) { image in
image
.resizable()
.aspectRatio(contentMode: .fill)
}).frame(width: 72, height: 72)
.padding(dim.mPadding)
}
VStack(alignment: .leading) {
if let brand = params.data.brand {
Text(brand)
.miamFontStyle(style: MiamFontStyleProvider.sharedInstance.bodySmallBoldStyle)
}
Text(params.data.name)
.miamFontStyle(style: MiamFontStyleProvider.sharedInstance.bodySmallStyle)
HStack {
IngredientUnitBubble(capacity: params.data.capacity)
if params.data.isSponsored { MealzSponsoredTag() }
}
Button(action: params.onChooseProduct, label: {
Text(Localization.myBudget.replaceItem.localised)
.miamFontStyle(style: MiamFontStyleProvider.sharedInstance.bodyMediumBoldStyle)
.foregroundColor(Color.mealzColor(.primary))
})
}
.frame(maxWidth: .infinity,alignment: .leading)
.padding(.horizontal, dim.mlPadding)
.padding(.top, dim.mPadding)
}
HStack(spacing: Dimension.sharedInstance.lPadding) {
Text(params.data.formattedProductPrice)
.miamFontStyle(style: MiamFontStyleProvider.sharedInstance.titleBigStyle)
.foregroundColor(Color.mealzColor(.primaryText))
Spacer()
Button(action: params.onIgnoreProduct, label: {
Text(Localization.ingredient.ignoreProduct.localised)
.miamFontStyle(style: MiamFontStyleProvider.sharedInstance.bodyMediumBoldStyle)
.foregroundColor(Color.mealzColor(.grayText))
})
if lockButton {
Button(action: {}, label: {
ProgressLoader(color: .white, size: 24)
})
.padding(Dimension.sharedInstance.mlPadding)
.background(Color.mealzColor(.primary))
.cornerRadius(Dimension.sharedInstance.buttonCornerRadius)
}else{
Button(action: params.onAddProduct, label: {
Image.mealzIcon(icon: .basket)
.resizable()
.renderingMode(.template)
.foregroundColor(Color.mealzColor(.white))
.frame(width: 20, height: 20)
.padding(dim.mlPadding)
.background(Color.mealzColor(.primary)
.cornerRadius(dim.buttonCornerRadius))
.frame(width: 48, height: 48)
})
}
}
.padding(.horizontal, dim.mlPadding)
Spacer()
}
.frame(height: mealzProductHeight)
.overlay( /// apply a rounded border
RoundedRectangle(cornerRadius: dim.mCornerRadius)
.stroke(Color.mealzColor(.lightBackground), lineWidth: 1)
)
.padding(.horizontal, dim.mPadding)
}
}
with
public struct RecipeDetailsUnaddedProductParameters {
/// Contains all the info related to the product
public let data: RecipeProductData
/// Status of the product (ex: loading, success, etc)
public let productStatus: ComponentUiState
/// Closure to add the product
public let onAddProduct: () -> Void
/// Closure to ignore the product
public let onIgnoreProduct: () -> Void
/// Closure to open the Item Selector
public let onChooseProduct: () -> Void
where
public struct RecipeProductData {
/// The unit price of the product
public let unitPrice: Double
/// Name of the product
public let name: String
/// Brand of the product (if it has one)
public let brand: String?
/// How much the product contains (ex: 60 g)
public let capacity: String
/// The number of products
public let productQuantity: Int
/// The Unit of the product (ex: g, kg, etc)
public let productUnit: String
/// The formatted price (ex: $34.53 or €34.23)
public let formattedProductPrice: String
/// Checked imageURL of the product
public let pictureURL: String
/// The name of the specified ingredient (ex: banana)
public let ingredientName: String
/// The amount of products asked by the recipe
public let ingredientQuantity: Float
/// The unit used by the recipe for this ingredient (ex: g, kg, etc)
public let ingredientUnit: String?
/// If other recipes use this product as well, this variable tells how many recipes overall share
public let numberOfOtherRecipesSharingThisIngredient: Int
/// The number of guests for the recipe set by the user
public let guestsCount: Binding<Int>
/// The number of guests for the recipe set by the Recipe
public let defaultRecipeGuest: Int
/// If the product has been sponsored by one of Mealz's partners
public let isSponsored: Bool
/// The EAN (barcode number)
public let ean: String