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