Skip to main content
Version: 5.7

RecipeDetail customization

RecipeDetails is one of the most customizable components, it has two customization states: success & loading:

Loading

Loading is of type LoaderConfig. You can create a custom template for RecipeDetails or otherwise the default template defined in defaultViews will be used.

LoaderParameters is an empty object for now, but tomorrow we'll be able to add properties to it, in order to avoid breaking changes in future versions.

object LoaderParameters

Success

Success state contains 12 customizable slots and one configuration field :

templating 1 templating 2 templating 3

Full customisation setting

If you want to fully customize this component we recommend copying the code into your Mealz template configuration. You can remove the code you do not overwrite.

recipeDetail{
success {
header {
view = MyCustomRecipeDetailHeader()
}
info {
view = MyCustomRecipeDetailInfo()
}
sponsorBanner {
view = MyCustomRecipeDetailSponsorBanner()
}
tag {
view = MyCustomRecipeDetailTags()
}
swapper{
view = MyCustomRecipeDetailSwapper()
}
footer {
view = MyCustomRecipeDetailSuccessFooter()
}
productListHeader {
view = MyCustomRecipeDetailProductListHeader()
}
products {
success {
view = MyCustomRecipeDetailProductSuccess()
}
loading {
view = MyCustomRecipeDetailProductLoading()
}
ignore {
view = MyCustomRecipeDetailProductIgnore()
}
}
oftenDeleted {
header {
view = MyCustomRecipeDetailOftenDeletedHeader()
}
product {
view = MyCustomRecipeDetailOftenDeletedProduct()
}
}
unavailable {
header {
view = MyCustomRecipeDetailUnavailableHeader()
}
product {
view = MyCustomRecipeDetailUnavailableProduct()
}
}
ingredients {
view = MyCustomRecipeDetailIngredients()
}
steps {
view = MyCustomRecipeDetailSteps()
}
gapBetweenProducts = 8 // default value
}
loading {
view = MyCustomRecipeLoading()
}
}
class MiamTemplateManager {
init {
MiamTheme.Template
{
// <---- copy above code here
}
}
}

The Header is the first customizable component on the RecipeDetail at the very top of the page; to create your own recipe detail header you create a class that implements RecipeDetailHeader

}

import ai.mealz.sdk.components.recipeDetail.success.header.RecipeDetailHeader
import ai.mealz.sdk.components.recipeDetail.success.header.RecipeDetailHeaderParameters


class MyCustomRecipeDetailHeader: RecipeDetailHeader {

@Composable
override fun Content(params: RecipeDetailHeaderParameters) {
// Your custom design here

}
}

Header params

data class RecipeDetailHeaderParameters(
val title: String,
val recipeId: String,
val scrollPosition: Int, // of the whole page below
val isLikeEnabled: Boolean,
val closeDialogue: () -> Unit
)

info

To create your own recipe detail info template you have to create class that implement RecipeDetailInfo

import ai.mealz.sdk.components.recipeDetail.success.info.RecipeDetailInfo
import ai.mealz.sdk.components.recipeDetail.success.info.RecipeDetailInfoParameters


class MyCustomRecipeDetailInfo: RecipeDetailInfo {

@Composable
override fun Content(params: RecipeDetailInfoParameters) {
// Your custom design here

}
}

Info params

data class RecipeDetailInfoParameters(
val recipe: Recipe, // full recipe
val guestCount: Int, // number of personne sharing the meal
val isUpdating: Boolean, // true is you should disable button
val isLikeEnable: Boolean, // if true you can show like button
val showGuestCounter: Boolean, // it true you should show guest counter
val updateGuest: (Int) -> Unit, // to call when changing the number of guest
val closeDetail: () -> Unit // close this view
)

SponsorBanner

To create your own recipe detail sponsor banner template you create a class that implements RecipeDetailSponsorBanner

import ai.mealz.sdk.components.recipeDetail.success.sponsorBanner.RecipeDetailSponsorBanner
import ai.mealz.sdk.components.recipeDetail.success.sponsorBanner.RecipeDetailSponsorBannerParameters


class MyCustomRecipeDetailSponsorBanner: RecipeDetailSponsorBanner {

@Composable
override fun Content(params: RecipeDetailSponsorBannerParameters) {
// Your custom design here

}
}

SponsorBanner params

data class RecipeDetailInfoParameters(
val sponsor: Sponsor, // all usefull info is inside attributes field
val openSponsorDetail: (sponsor: Sponsor) -> Unit // navigate to sponsor presentation page
)

SponsorBanner ressources

tip

you can replace and reuse string ressources if you want to take advantage of our internationalisation system

ex : Localisation.sponsorBanner.sponsorBannerSpeach.localised

Name Ressource IDValue FrValue Eng
sponsorBannerSpeachcom_miam_sponsor_banner_speachCette recette vous est proposée par notre partenaireThis recipe is brought to you by our partner
sponsorBannerMoreInfocom_miam_sponsor_banner_more_infoEn savoir plusRead more

Tags

To create your own recipe detail tags template you create a class that implements `RecipeDetailSuccessTag

import ai.mealz.sdk.components.recipeDetail.success.header.RecipeDetailSuccessTag
import ai.mealz.sdk.components.recipeDetail.success.header.RecipeDetailSuccessTagParameters


class MyCustomRecipeDetailTags: RecipeDetailSuccessTag {

@Composable
override fun Content(params: RecipeDetailSuccessTagParameters) {
// Your custom design here

}
}

Tags params

data class RecipeDetailSuccessTagParameters(
val title: String, // name of the recipe
val totalTime: String, // preparationTime + cookingTime + restingTime
val preparationTime: Duration?,
val cookingTime: Duration?,
val restingTime: Duration?,
val difficulty: RecipeDifficulty
)

public enum class RecipeDifficulty(public val value: Int) {
Easy(1),
Medium(2),
Hard(3)
}

Tags ressources

tip

you can replace and reuse string ressources if you want to take advantage of our internationalisation system

ex : Localisation.recipe.lowDifficulty.localised

Name Ressource IDValue FrValue Eng
lowDifficultycom_miam_recipe_difficulty_lowDébutantBeginner chef
mediumDifficultycom_miam_recipe_difficulty_mediumIntermédiaireIntermediate chef
highDifficultycom_miam_recipe_difficulty_highConfirméTop chef

Swapper

To create your own recipe detail swapper template you create a class that implements Swapper

import ai.mealz.sdk.components.baseComponent.swapper.Swapper
import ai.mealz.sdk.components.baseComponent.swapper.SwapperParameters


class MyCustomSwapper: Swapper {

@Composable
override fun Content(params: SwapperParameters) {
// Your custom design here

}
}

Swapper params

data class SwapperParameters(
val options: Map<String, SwapperOption>,
val state: SwapperImp.MultiSelectorState,
val selectedOption: String,
val onOptionSelect: (String) -> Unit
)

data class SwapperOption(val title: String, val icon: Int? = null)

Swapper resources

tip

you can replace and reuse string ressources if you want to take advantage of our internationalisation system

ex : Localisation.recipeDetails.shopping.localised

Name Ressource IDValue FrValue Eng
shoppingcom_miam_details_shoppingJe fais mes coursesI'm shopping
cookingcom_miam_details_cookingJe cuisineI'm cooking

To create your own recipe detail footer template you create a class that implements RecipeDetailSuccessFooter

import ai.mealz.sdk.components.recipeDetail.success.footer.RecipeDetailSuccessFooter
import ai.mealz.sdk.components.recipeDetail.success.footer.RecipeDetailSuccessFooterParameters

class MyCustomRecipeDetailSuccessFooter: RecipeDetailSuccessFooter {

@Composable
override fun Content(params: RecipeDetailSuccessFooterParameters) {
// Your custom design here

}
}
data class RecipeDetailSuccessFooterParameters(
val price: StateFlow<Double>, // Deprecated You now have access to the price of the items in basket & remaining items not in basket. What was now price is now `priceProductsInBasketPerGuest
val priceOfProductsInBasket: StateFlow<Double>, // price of products in basket
val priceOfRemainingProducts: StateFlow<Double>, // price of products that can be adde to basket (not taking in count ignored or unavailable product)
val priceProductsInBasketPerGuest: StateFlow<Double>, // priceOfProductsInBasket
val priceStatus: ComponentUiState,
val ingredientsStatus: IngredientStatus, // state for CTA
val isButtonLock: StateFlow<Boolean>, // true if main CTA should be disable
val onConfirm: () -> Unit // to call on main CTA click
)

public enum class ComponentUiState {
SUCCESS, ERROR, LOADING, EMPTY, IDLE, LOCKED;
}

public data class IngredientStatus(
public val type: IngredientStatusTypes = IngredientStatusTypes.INITIAL_STATE,
public val count: Int = 0
)

public enum class IngredientStatusTypes {
INITIAL_STATE,
NO_MORE_TO_ADD,
REMAINING_INGREDIENTS_TO_BE_ADDED;
}
tip

you can replace and reuse string resources if you want to take advantage of our internationalisation system ex : Localisation.recipeDetails.inMyBasket.localised

Name Resource IDValue FrValue Eng
inMyBasketcom_miam_details_in_my_basketdans mon panierIn my basket
continueShoppingcom_miam_details_continue_shoppingContinuer mes coursesContinue shopping

there are also plurials

Methods Resource IDValue FrValue Eng
addProduct(Int)com_miam_ingredient_add_productAjouter %d produit
Ajouter %d produits
Add %d product
Add %d products

ProductListHeader

To create your own recipe detail product list header template you create a class that implements RecipeDetailProductListHeader

import ai.mealz.sdk.components.recipeDetail.success.header.RecipeDetailProductListHeader
import ai.mealz.sdk.components.recipeDetail.success.header.RecipeDetailProductListHeaderParameters


class MyCustomRecipeDetailProductListHeader: RecipeDetailProductListHeader {

@Composable
override fun Content(params: RecipeDetailProductListHeaderParameters) {
// Your custom design here

}
}

ProductListHeader params

data class RecipeDetailProductListHeaderParameters(
val productCount: Int
)

ProductListHeader ressources

tip

you can replace and reuse string ressources if you want to take advantage of our internationalisation system

ex : Localisation.recipe.numberOfIngredients(Int).localised,

Name Ressource IDValue FrValue Eng
numberOfIngredients(Int)com_miam_recipe_number_of_ingredientsCalculé pour %d repas
Calculés pour %d repas
Calculated for %d meal
Calculated for %d meals

Product

Product has three sub-templates :

  • success : State when data is loaded from back end
  • loading : Still fetching data
  • ignored : Product will not be shown or added to basket (yet ingredient is still shown)
products {
success {
view = MyCustomRecipeDetailProductSuccess()
}
loading {
view = MyCustomRecipeDetailProductLoading()
}
ignore {
view = MyCustomRecipeDetailProductIgnore()
}
}

Product Success

To create your own recipe detail product success template you create a class that implements ProductSuccess

import ai.mealz.sdk.components.recipeDetail.success.product.success.ProductSuccess
import ai.mealz.sdk.components.recipeDetail.success.product.success.ProductSuccessParameters


class MyCustomRecipeDetailProductSuccess: ProductSuccess {

@Composable
override fun Content(params: ProductSuccessParameters) {
// Your custom design here

}
}

Product Success params

 data class ProductSuccessParameters(
val productName: String, // name of product in your referential
val productBrand: String,
val productQuantity: Int, // quantity of product
val productCapacityVolume: String, // packaging quantity (200g )
val productUnit: String, // example "g" for "grammes"
val unitPrice: Double, // example 12.058
val formattedUnitPrice: String, // example 12.05€
val productImage: String,
val ingredientName: String, // name of ingredient in our recipe
val ingredientQuantity: String, // required quantity in our recipe
val ingredientUnit: String, // unit in our recipe
val guestsCount: MutableStateFlow<Int>, // number of shares
val defaultRecipeGuest: Int, // if guestsCount is empty
val numberOfRecipeConcernsByProduct: Int,
val isLocked: Boolean, // if true you must disable any button on template
val isSponsored: Boolean, // if true product is a sponsored one
val isInBasket: Boolean, // if true product is in basket
val ean: String,
val replaceProduct: () -> Unit,
val ignoreProduct: () -> Unit,
val addProduct: () -> Unit,
val updateProductQuantity: (Int) -> Unit
)

Product Success ressources

tip

you can replace and reuse string resources if you want to take advantage of our internationalisation system ex : Localisation.product.sponsored.localised

Name Ressource IDValue FrValue Eng
sponsoredcom_miam_basket_sponsoredSponsoriséSponsored
replaceItemcom_miam_budget_replace_itemRemplacerReplace
ignoreProductcom_miam_ingredient_ignore_productIgnorer ce produitIgnore this product

there are also plurials

Methods Ressource IDValue FrValue Eng
productsSharedRecipe(Int)com_miam_ingredient_shared_with_recipeCalculé pour %d repas
Calculés pour %d repas
Calculated for %d meal
Calculated for %d meals

Product Loading

To create your own recipe detail product loading template you create a class that implements ProductLoading

import ai.mealz.sdk.components.recipeDetail.success.product.loading.ProductLoading
import ai.mealz.sdk.components.recipeDetail.success.product.loading.ProductLoadingParameters


class MyCustomRecipeDetailProductLoading: ProductLoading {

@Composable
override fun Content(params: ProductLoadingParameters) {
// Your custom design here

}
}

Product Loading params

object ProductLoadingParameters

Product Ignored

To create your own recipe detail product ignore template you create a class that implements `ProductIgnore

import ai.mealz.sdk.components.recipeDetail.success.product.ignore.ProductIgnore
import ai.mealz.sdk.components.recipeDetail.success.product.ignore.ProductIgnoreParameters


class MyCustomRecipeDetailProductIgnore: ProductIgnore {

@Composable
override fun Content(params: ProductIgnoreParameters) {
// Your custom design here

}
}

Product Ignore params

data class ProductIgnoreParameters(
val ingredientName: String, // name of ingredient in recipe
val ingredientQuantity: String, // quantity required in recipe
val ingredientUnit: String, // ememple
val guestsCount: MutableStateFlow<Int>,// number of shares
val defaultRecipeGuest: Int, // initial number of shares
val chooseProduct: () -> Unit
)

Product Ignore resources

tip

you can replace and reuse string resources if you want to take advantage of our internationalisation system ex : `Localisation.ingredient.willNotBeAdded.localised`

Name Resource IDValue FrValue Eng
willNotBeAddedcom_miam_ingredient_will_not_be_addedCet ingrédient ne sera pas ajouté à votre panierThis ingredient will not be added to your basket
chooseProductcom_miam_ingredient_choose_productChoisir un produitChoose a product

Often deleted

Often deleted has two sub-templates :

  • header : The the toggle button that programmatically displays or hides the list of products
  • product : A single product in the list
oftenDeleted {
header {
view = MyCustomRecipeDetailOftenDeletedHeader()
}
product {
view = MyCustomRecipeDetailOftenDeletedProduct()
}
}

To create your own recipe detail product often deleted template you create a class that implements OftenDeletedProductsHeader

import ai.mealz.sdk.components.recipeDetail.success.product.ignore.ProductIgnore
import ai.mealz.sdk.components.recipeDetail.success.product.ignore.ProductIgnoreParameters


class MyCustomRecipeDetailOftenDeletedProductsHeader: OftenDeletedProductsHeader {

@Composable
override fun Content(params: ProductIgnoreParameters) {
// Your custom design here

}
}

Often deleted header params

data class OftenDeletedProductsHeaderParameters(
val title: String, // title of section
val isOpen: Boolean, // initial state if you want to colapse the section
val toggle: () -> Unit
)

Product

To create your own recipe detail often deleted product template you create a class that implements OftenDeletedProduct

import ai.mealz.sdk.components.recipeDetail.success.oftenDeleted.oftenDeletedProduct
import ai.mealz.sdk.components.recipeDetail.success.product.ignore.ProductIgnoreParameters


class MyCustomRecipeDetailOftenDeletedProduct: OftenDeletedProduct {

@Composable
override fun Content(params: OftenDeletedProductParameters) {
// Your custom design here

}
}

with

data class OftenDeletedProductParameters(
val ingredientName: String,
val ingredientQuantity: String,
val ingredientUnit: String,
val guestsCount: MutableStateFlow<Int>,
val defaultRecipeGuest: Int,
val chooseProduct: () -> Unit
)

Often deleted Product ressources

tip

you can replace and reuse string ressources if you want to take advantage of our internationalisation system

ex : Localisation.ingredient.willNotBeAdded.localised

Name Ressource IDValue FrValue Eng
willNotBeAddedcom_miam_ingredient_will_not_be_addedCet ingrédient ne sera pas ajouté à votre panierThis ingredient will not be added to your basket
chooseProductcom_miam_ingredient_choose_productChoisir un produitChoose a product

Unavailable

Unavailable has two sub-templates :

  • header : The toggle button that programmatically displays or hides the list of products
  • product : A single product in the list
unavailable {
header {
view = MyCustomRecipeDetailUnavailableHeader()
}
product {
view = MyCustomRecipeDetailUnavailableProduct()
}
}

To create your own recipe detail unavailable product template you create a class that implements UnavailableProductsHeader

import ai.mealz.sdk.components.recipeDetail.success.unavailable.header.UnavailableProductsHeader
import ai.mealz.sdk.components.recipeDetail.success.unavailable.header.UnavailableProductsHeaderParameters


class MyCustomRecipeDetailUnavailableProductsHeader: UnavailableProductsHeader {

@Composable
override fun Content(params: UnavailableProductsHeaderParameters) {
// Your custom design here

}
}

Unavailable Header params

data class UnavailableProductsHeaderParameters(
val title: String,
val isOpen: Boolean,
val toggle: () -> Unit
)

Unavailable Header ressources

warning

you can replace and reuse string ressources if you want to take advantage of our internationalisation system

ex : Localisation.recipeDetails.unavailable.localised

this on is pass throw params

Name Ressource IDValue FrValue Eng
unavailablecom_miam_detail_unavailableArticles indisponiblesUnavailable Products

Product

To create your own recipe detail unavailable product template you create a class that implements UnavailableProduct

import ai.mealz.sdk.components.recipeDetail.success.oftenDeleted.oftenDeletedProduct
import ai.mealz.sdk.components.recipeDetail.success.product.ignore.ProductIgnoreParameters


class MyCustomRecipeDetailUnavailableProduct: ProductUnavailableParameters {

@Composable
override fun Content(params: OftenDeletedProductParameters) {
// Your custom design here

}
}

with

data class UnavailableProductsHeaderParameters(
val title: String,
val isOpen: Boolean,
val toggle: () -> Unit
)

Ingredients

To create your own recipe detail ingredients template you create a class that implements Ingredients

import ai.mealz.sdk.components.recipeDetail.success.ingredients.Ingredients
import ai.mealz.sdk.components.recipeDetail.success.ingredients.IngredientsParameters


class MyCustomRecipeDetailIngredients: Ingredients {

@Composable
override fun Content(params: IngredientsParameters) {
// Your custom design here

}
}

Ingredients params

data class IngredientsParameters(
val ingredients: List<Ingredient>,
val guestsCount: Int,
val defaultRecipeGuest: Int
)

Ingredients resources

tip

you can replace and reuse string resources if you want to take advantage of our internationalisation system ex : `Localisation.recipe.numberOfIngredients(INT).localised`

Methods Resource IDValue FrValue Eng
numberOfIngredients(Int)com_miam_recipe_number_of_ingredients%d ingrédients%d ingredients

Steps

To create your own recipe detail Steps template you create a class that implements RecipeDetailSteps

import ai.mealz.sdk.components.recipeDetail.success.steps.RecipeDetailSteps
import ai.mealz.sdk.components.recipeDetail.success.steps.RecipeDetailStepsParamters


class MyCustomRecipeDetailSteps: RecipeDetailSteps {

@Composable
override fun Content(params: RecipeDetailStepsParamters) {
// Your custom design here

}
}

Steps params

data class RecipeDetailStepsParamters(
val steps: List<RecipeStep>
)

Steps ressources

tip

you can replace and reuse string ressources if you want to take advantage of our internationalisation system

ex : Localisation.recipe.steps.localised

Name Ressource IDValue FrValue Eng
stepscom_miam_recipe_stepsÉtapesSteps