{"version":3,"file":"coopse.script.8154.666d8993.chunk.js","mappings":"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","sources":["webpack:///./src/microApps/common/components/organisms/MissingItemBody/MissingItemBody.module.less","webpack:///./src/microApps/cart/components/molecules/RecipeProductListingItem/RecipeProductListingItem.tsx","webpack:///./src/microApps/cart/components/molecules/RecipeProductListingItem/RecipeProductListingItem.utils.ts","webpack:///./src/microApps/cart/components/molecules/RecipePortionCounter/RecipePortionCounter.tsx","webpack:///./src/microApps/common/components/molecules/RecipeModal/RecipeModalFooter.tsx","webpack:///./src/microApps/common/components/molecules/RecipeModal/RecipeModalHeader.tsx","webpack:///./src/microApps/common/components/molecules/RecipeModal/RecipeModalAccordion.module.less","webpack:///./src/microApps/common/components/molecules/RecipeModal/RecipeModalAccordion.tsx","webpack:///./src/microApps/common/components/molecules/RecipeModal/RecipeModalProductsFooter.tsx","webpack:///./src/microApps/common/components/molecules/RecipeModal/RecipeModalProducts.tsx","webpack:///./src/microApps/common/components/molecules/RecipeModal/RecipeModalRecept.tsx","webpack:///./src/microApps/common/components/molecules/RecipeModal/RecipeModalBody.tsx","webpack:///./src/microApps/common/components/molecules/RecipeModalTrigger/BuyableRecipeModalBody.tsx","webpack:///./src/microApps/common/components/organisms/MissingItemBody/MissingItemInfo.tsx","webpack:///./src/microApps/common/components/organisms/MissingItemBody/MissingItemBody.tsx","webpack:///./src/microApps/common/components/organisms/PurchasableItemBody/PurchasableItemBody.tsx","webpack:///./src/microApps/common/tracking/ga4/recipes/ga4Recipes.utils.ts","webpack:///./src/microApps/recipe/hooks/useRecipeCart.ts","webpack:///./src/microApps/recipe/hooks/useSubstitute.ts","webpack:///./src/microApps/recipe/models.ts","webpack:///./src/microApps/recipe/utils.ts"],"sourcesContent":["// extracted by mini-css-extract-plugin\nexport default {\"MissingItemInfo\":\"XyD819sD\",\"RecipeItemActions\":\"xGNPEbje\",\"RecipeItemActionsContainer\":\"t3_zjtbW\"};","import type { AnalyticsListOptions } from '../../../../../analytics/analyticsHandler';\nimport type { SwiperBreakpoints } from '../../../../../utility/coopSwiperBreakpoints';\nimport { Helpers } from '../../../../../utility/helpers';\nimport ProductPrice from '../../../../common/components/atoms/ProductPrice';\nimport EcomPromoSplash from '../../../../common/components/molecules/EcomPromoSplash';\nimport ProductSubstitutes from '../../../../common/components/molecules/ProductSubstitutes';\nimport type { PriceData } from '../../../../common/models/priceData/priceData';\nimport { PriceType } from '../../../../common/models/priceData/priceData';\nimport { mapProductToEcomPromotion } from '../../../../common/utils/productUtils';\nimport ProductListingItem from '../ProductListingItem';\n\ninterface RecipeItemProps {\n    priceData: PriceData;\n    totalPriceData: PriceData;\n    name: string;\n    packageSizeInformation: string;\n    image?: string;\n    manufacturer?: string;\n    selectedVarianceCode?: string;\n}\n\ninterface RecipeProductListingItemProps {\n    recipeProduct: RecipeItemProps;\n    product?: ApiProduct;\n    recipeProductSubstitutes: ApiProduct[];\n    isSubstituteActive: boolean;\n    buyable: boolean;\n    handleSubstituteChange: (product: ApiProduct) => void;\n    productSubstitutesBreakpoints: SwiperBreakpoints;\n    analyticsOptions?: AnalyticsListOptions;\n    additionalClassNames?: string;\n    isConstrained?: boolean;\n    priceType: PriceType;\n}\n\nconst RecipeProductListingItem = ({\n    recipeProduct: recipeProductItem,\n    product,\n    recipeProductSubstitutes,\n    isSubstituteActive,\n    buyable,\n    children,\n    handleSubstituteChange,\n    additionalClassNames,\n    analyticsOptions,\n    productSubstitutesBreakpoints,\n    isConstrained,\n    priceType,\n}: React.PropsWithChildren<RecipeProductListingItemProps>) => {\n    const getVariantName = () => {\n        if (recipeProductItem.selectedVarianceCode && product) {\n            const variant = product.variants?.find(\n                (_variant) => _variant.id === recipeProductItem.selectedVarianceCode,\n            );\n\n            return variant?.name;\n        }\n\n        return undefined;\n    };\n\n    const productPromotion = mapProductToEcomPromotion(product);\n\n    return (\n        <>\n            <ProductListingItem\n                slotPrice={\n                    buyable && (\n                        <div className=\"Cart-itemSummary\">\n                            <span className=\"Cart-itemPrice\">\n                                {/* Use price with tax for recipes and weekly menu */}\n                                <ProductPrice\n                                    totalPrice={recipeProductItem.totalPriceData}\n                                    priceType={priceType}\n                                    align=\"right\"\n                                    showExcludingTaxInfo={false}\n                                />\n                            </span>\n                            {priceType === PriceType.ExcludeTax && (\n                                <span className=\"u-flex u-textXXXSmall u-flexJustifyEnd u-textWeightNormal\">\n                                    {Helpers.getPriceTypeText(priceType)}\n                                </span>\n                            )}\n                        </div>\n                    )\n                }\n                slotSplash={\n                    productPromotion && (\n                        <EcomPromoSplash promotion={productPromotion} priceType={priceType} />\n                    )\n                }\n                isNicotineProduct={!!product?.details?.isNicotineProduct}\n                isPharmaceutical={!!product?.details?.pharmaceuticalData?.isPharmaceutical}\n                name={product?.name || recipeProductItem.name}\n                packageSizeInformation={recipeProductItem.packageSizeInformation}\n                variantName={getVariantName()}\n                image={recipeProductItem.image}\n                manufacturer={product?.manufacturer || recipeProductItem.manufacturer}\n                additionalClassNames={additionalClassNames}\n                analyticsOptions={null}\n            >\n                {children}\n            </ProductListingItem>\n            {isSubstituteActive && (\n                <div\n                    className=\"u-borderBottomGrayLight2 u-bgGrayLight\"\n                    style={{ position: 'relative', overflow: 'hidden' }}\n                >\n                    <ProductSubstitutes\n                        productSubstitutesBreakpoints={productSubstitutesBreakpoints}\n                        substitutes={recipeProductSubstitutes}\n                        handleProductSubstitution={handleSubstituteChange}\n                        analyticsOptions={analyticsOptions}\n                        isConstrained={isConstrained}\n                        priceType={priceType}\n                    />\n                </div>\n            )}\n        </>\n    );\n};\n\nexport default RecipeProductListingItem;\n","import { CoopSwiperBreakpointsUnique } from '../../../../../utility/coopSwiperBreakpointsUnique';\n\nexport const recipeModalProductSubstitutesBreakpoints =\n    CoopSwiperBreakpointsUnique.getUniqueBreakpointsFor(\n        CoopSwiperBreakpointsUnique.AREA_RECIPE_MODAL,\n    ).ProductList;\n","/* eslint-disable react/jsx-props-no-spreading */\n/* eslint-disable react/no-unstable-nested-components */\nimport { ChipIconButton } from '@coop/components';\nimport { MinusIcon, PlusIcon } from '@coop/icons';\n\nimport { useNumericStepperCalculation } from '../../../../common/components/atoms/NumericStepper';\n\ninterface RecipePortionCounterProps {\n    portions: number;\n    setPortions: (quantity: number) => void;\n    minValue: number;\n    maxValue: number;\n    incrementBy?: number;\n}\n\nconst RecipePortionCounter = (props: RecipePortionCounterProps) => {\n    const { calculateAdditionValue, calculateSubstractValue } = useNumericStepperCalculation({\n        incrementBy: props.incrementBy || 2,\n        minValue: props.minValue,\n        maxValue: props.maxValue,\n    });\n\n    return (\n        <div className=\"u-flex u-flexAlignCenter u-flexJustifyCenter\">\n            <span>{props.portions} portioner</span>\n            <div style={{ marginLeft: 24 }}>\n                <ChipIconButton\n                    icon={MinusIcon}\n                    label=\"Ta bort en portion\"\n                    theme=\"whiteGreen\"\n                    size={32}\n                    onClick={() => {\n                        const newValue = calculateSubstractValue(props.portions);\n                        props.setPortions(newValue);\n                    }}\n                />\n            </div>\n            <div style={{ marginLeft: 8 }}>\n                <ChipIconButton\n                    icon={PlusIcon}\n                    label=\"Lägg till en portion\"\n                    theme=\"whiteGreen\"\n                    size={32}\n                    onClick={() => {\n                        const newValue = calculateAdditionValue(props.portions);\n                        props.setPortions(newValue);\n                    }}\n                />\n            </div>\n        </div>\n    );\n};\n\nexport default RecipePortionCounter;\n","import { Button } from '@coop/components';\n\nimport { Helpers } from '../../../../../utility/helpers';\nimport { buildRecipeRedirectUrl } from '../../../../recipe/utils';\nimport { PriceType } from '../../../models/priceData/priceData';\n\ninterface RecipeModalFooterProps {\n    totalProducts?: number;\n    totalPrice: number;\n    externalId: number;\n    buyable: boolean;\n    handleBuy: () => void;\n    handleLinkClick: () => void;\n    priceType: PriceType;\n    isFoodBox: boolean;\n}\n\nconst RecipeModalFooter: React.FC<React.PropsWithChildren<RecipeModalFooterProps>> = ({\n    totalProducts,\n    totalPrice,\n    externalId,\n    buyable,\n    handleBuy,\n    handleLinkClick,\n    priceType,\n    isFoodBox,\n}) => {\n    return (\n        <div className=\"RecipeModal-footer u-md-flex\">\n            {buyable && (\n                <div>\n                    {totalProducts !== undefined && (\n                        <span className=\"u-block u-textXSmall\">\n                            Totalt{' '}\n                            <span className=\"u-textWeightNormal\">\n                                (<span>{totalProducts}</span> varor)\n                            </span>\n                        </span>\n                    )}\n                    <div>{Helpers.toEcommercePriceWithCurrency(totalPrice)}</div>\n                    {priceType === PriceType.ExcludeTax && (\n                        <div className=\"u-textWeightNormal u-textXSmall\">\n                            {Helpers.getPriceTypeText(priceType)}\n                        </div>\n                    )}\n                </div>\n            )}\n            <div className=\"u-flex\">\n                <Button asChild size={40} theme=\"primaryOutline\" className=\"u-marginRxsm\">\n                    <a\n                        href={buildRecipeRedirectUrl(externalId.toString())}\n                        onClick={handleLinkClick}\n                    >\n                        {isFoodBox ? 'Gå till produktsida' : 'Gå till receptsida'}\n                    </a>\n                </Button>\n                {buyable && (\n                    <Button size={40} theme=\"primary\" onClick={handleBuy}>\n                        K&ouml;p varor\n                    </Button>\n                )}\n            </div>\n        </div>\n    );\n};\n\nexport default RecipeModalFooter;\n","import { ChipIconButton, Icon } from '@coop/components';\nimport { ClockIcon, CloseIcon } from '@coop/icons';\n\nimport { Helpers } from '../../../../../utility/helpers';\nimport { getTransformedImageUrl } from '../../../utils/cloudinaryImageUtils';\nimport { RatingStars } from '../RatingStars';\n\ninterface RecipeModalHeaderProps {\n    recipeName: string;\n    imageUrl: string;\n    rating: number | null;\n    votes?: number;\n    time: string;\n    buyable: boolean;\n    pricePortion?: number;\n    close: () => void;\n}\n\nconst RecipeModalHeader: React.FC<React.PropsWithChildren<RecipeModalHeaderProps>> = ({\n    recipeName,\n    imageUrl,\n    rating,\n    votes,\n    time,\n    buyable,\n    pricePortion,\n    close,\n}) => {\n    const transformedImageUrl = getTransformedImageUrl(imageUrl, 'w_400,h_400');\n\n    return (\n        <div className=\"RecipeModal-header\">\n            {transformedImageUrl && (\n                <div\n                    className=\"RecipeModal-bgImage\"\n                    style={{\n                        backgroundImage: `url(${transformedImageUrl})`,\n                    }}\n                />\n            )}\n            <div className=\"RecipeModal-overlay\" />\n            <div className=\"RecipeModal-close\">\n                <ChipIconButton\n                    icon={CloseIcon}\n                    size={32}\n                    theme=\"whiteGreen\"\n                    label=\"Stäng\"\n                    onClick={close}\n                />\n            </div>\n            <h3 className=\"RecipeModal-heading\">{recipeName}</h3>\n            <div className=\"u-posRelative\">\n                <div className=\"Grid Grid--gutterHmd Grid--fit\">\n                    <div className=\"Grid-cell Grid-cell--fit\">\n                        {!!rating && !!votes && (\n                            <RatingStars rating={rating} votes={votes} color=\"white\" />\n                        )}\n                    </div>\n                    {time && (\n                        <div className=\"Grid-cell Grid-cell--fit u-flexAlignCenter\">\n                            <Icon icon={ClockIcon} className=\"u-marginRxxsm\" />\n                            <span className=\"u-textXSmall\">{time}</span>\n                        </div>\n                    )}\n                    {buyable && pricePortion && (\n                        <div className=\"Grid-cell Grid-cell--fit\">\n                            <span className=\"u-textXSmall\">{`Ca ${Helpers.toEcommercePriceWithCurrency(\n                                pricePortion,\n                            )}/port`}</span>\n                        </div>\n                    )}\n                </div>\n            </div>\n        </div>\n    );\n};\n\nexport default RecipeModalHeader;\n","// extracted by mini-css-extract-plugin\nexport default {\"RadioBox\":\"QpkilH1D\"};","import { Icon, RadioGroup } from '@coop/components';\nimport { MinusIcon, PlusIcon } from '@coop/icons';\nimport classnames from 'classnames';\nimport { useState } from 'react';\n\nimport type { RecipeCalculationType, RecipePrioritizationType } from '../../../../recipe/models';\nimport styles from './RecipeModalAccordion.module.less';\n\ninterface RecipeModalAccordionProps {\n    handleCalculationTypeChange: (\n        calculationType: RecipeCalculationType,\n        prioritization: RecipePrioritizationType | null,\n    ) => void;\n}\n\ntype RecipeModalAccordionRadioValues = RecipeCalculationType | RecipePrioritizationType;\ninterface RecipeModalAccordionRadioButtonData {\n    name: string;\n    description: string;\n    value: RecipeModalAccordionRadioValues;\n}\n\nconst RecipeModalAccordion = (props: RecipeModalAccordionProps) => {\n    const [isExpanded, setIsExpanded] = useState<boolean>(false);\n    const [inputSelected, setInputSelected] = useState<RecipeModalAccordionRadioButtonData>({\n        name: 'Bästa val',\n        description: 'Varorna kombineras och väljs för att du ska få så lite svinn som möjligt.',\n        value: 'waste',\n    });\n\n    const accordionExpandedToggle = () => setIsExpanded(!isExpanded);\n    const handleInputSelect = (selectedInput: RecipeModalAccordionRadioButtonData) => {\n        setInputSelected({ ...selectedInput });\n\n        let calculationType: RecipeCalculationType;\n        let recipeProritization: RecipePrioritizationType | null = null;\n\n        switch (selectedInput.value) {\n            case 'waste':\n                calculationType = 'waste';\n                break;\n            case 'price':\n                calculationType = 'price';\n                break;\n            case 'organic':\n                calculationType = 'waste';\n                recipeProritization = 'organic';\n                break;\n            default:\n                calculationType = 'waste';\n                break;\n        }\n\n        props.handleCalculationTypeChange?.(calculationType, recipeProritization);\n    };\n\n    const onValueChange = (value: string) => {\n        switch (value) {\n            case 'waste':\n                handleInputSelect({\n                    name: 'Bästa val',\n                    description:\n                        'Varorna kombineras och väljs för att du ska få så lite svinn som möjligt.',\n                    value: 'waste',\n                });\n                break;\n            case 'price':\n                handleInputSelect({\n                    name: 'Billigt',\n                    description:\n                        'Vi föreslår det billigaste alternativet. Självklart med så lite svinn som möjligt.',\n                    value: 'price',\n                });\n                break;\n            case 'organic':\n                handleInputSelect({\n                    name: 'Eko',\n                    description:\n                        'Vi föreslår en ekologisk vara om det finns. Alltid med så lite svinn som möjligt.',\n                    value: 'organic',\n                });\n                break;\n            default:\n                break;\n        }\n    };\n\n    // TODO A11Y: Redo accordion into Radix Accordion, remove Accordion.less\n    return (\n        <div className=\"Accordion Accordion--single\">\n            <ul className=\"Accordion-list\">\n                <li className={classnames('Accordion-item', isExpanded && 'is-expanded')}>\n                    <div\n                        className=\"Accordion-header u-textMedium u-paddingHmd\"\n                        onClick={accordionExpandedToggle}\n                    >\n                        <span className=\"u-inlineBlock u-textSmall u-md-textMedium u-marginRxxsm\">\n                            Önskade varor:{' '}\n                        </span>\n                        <span className=\"u-textWeightBold u-textSmall u-md-textMedium u-inlineBlock u-marginRxxsm\">\n                            {inputSelected.name}\n                        </span>\n                        <Icon\n                            icon={PlusIcon}\n                            className=\"Accordion-icon Accordion-icon--plus\"\n                            width={20}\n                            height={20}\n                        />\n                        <Icon\n                            icon={MinusIcon}\n                            className=\"Accordion-icon Accordion-icon--minus\"\n                            width={20}\n                            height={20}\n                        />\n                    </div>\n                    <div className=\"Accordion-panel\">\n                        <div className=\"u-paddingAmd\">\n                            <RadioGroup.Root onValueChange={onValueChange} defaultValue=\"waste\">\n                                <div className=\"Grid Grid--gutterAxsm\">\n                                    <div className=\"Grid-cell u-sm-size1of3\">\n                                        <RadioGroup.Item\n                                            value=\"price\"\n                                            id=\"calctype_price\"\n                                            label={\n                                                <>\n                                                    Billigt\n                                                    <i className=\"u-block u-sm-hidden u-md-hidden u-textXSmall u-marginTxxxsm\">\n                                                        Vi föreslår det billigaste alternativet.\n                                                        Självklart med så lite svinn som möjligt.\n                                                    </i>\n                                                </>\n                                            }\n                                            className={styles.RadioBox}\n                                        />\n                                    </div>\n                                    <div className=\"Grid-cell u-sm-size1of3\">\n                                        <RadioGroup.Item\n                                            value=\"waste\"\n                                            id=\"calctype_waste\"\n                                            label={\n                                                <>\n                                                    Bästa val\n                                                    <i className=\"u-block u-sm-hidden u-md-hidden u-textXSmall u-marginTxxxsm\">\n                                                        Varorna kombineras och väljs för att du ska\n                                                        få så lite svinn som möjligt.\n                                                    </i>\n                                                </>\n                                            }\n                                            className={styles.RadioBox}\n                                        />\n                                    </div>\n                                    <div className=\"Grid-cell u-sm-size1of3\">\n                                        <RadioGroup.Item\n                                            value=\"organic\"\n                                            id=\"calctype_eko\"\n                                            label={\n                                                <>\n                                                    Eko\n                                                    <i className=\"u-block u-sm-hidden u-md-hidden u-textXSmall u-marginTxxxsm\">\n                                                        Vi föreslår en ekologisk vara om det finns.\n                                                        Alltid med så lite svinn som möjligt.\n                                                    </i>\n                                                </>\n                                            }\n                                            className={styles.RadioBox}\n                                        />\n                                    </div>\n                                </div>\n                            </RadioGroup.Root>\n\n                            <div className=\"Grid-cell u-sm-block u-md-block u-sm-paddingTxsm u-md-paddingTsm\">\n                                <span className=\"u-textSmall\">{inputSelected.description}</span>\n                            </div>\n                        </div>\n                    </div>\n                </li>\n            </ul>\n        </div>\n    );\n};\n\nexport default RecipeModalAccordion;\n","import { Button } from '@coop/components';\n\nimport { Helpers } from '../../../../../utility/helpers';\n\ninterface RecipeModalProductsFooterProps {\n    totalProducts?: number;\n    totalPrice: number;\n    handleBuy: () => void;\n}\n\nconst RecipeModalProductsFooter: React.FC<\n    React.PropsWithChildren<RecipeModalProductsFooterProps>\n> = ({ totalProducts, totalPrice, handleBuy }) => {\n    return (\n        <div className=\"RecipeModal-footer u-md-hidden\">\n            <div className=\"u-marginBxsm\">\n                Totalt\n                {totalProducts !== undefined && (\n                    <>\n                        {' '}\n                        (<span>{totalProducts}</span> varor)\n                    </>\n                )}\n                :{' '}\n                <span className=\"u-textWeightBold\">\n                    {Helpers.toEcommercePriceWithCurrency(totalPrice)}\n                </span>\n            </div>\n            <Button size={40} theme=\"primary\" onClick={handleBuy} fullWidth>\n                K&ouml;p varor\n                <div />\n            </Button>\n        </div>\n    );\n};\n\nexport default RecipeModalProductsFooter;\n","import type { FC } from 'react';\n\nimport { Helpers } from '../../../../../utility/helpers';\nimport type { RecipeCartState, RecipeSection } from '../../../../recipe/hooks/useRecipeCart';\nimport type {\n    RecipeCalculationType,\n    RecipeItemState,\n    RecipePrioritizationType,\n} from '../../../../recipe/models';\nimport { PriceType } from '../../../models/priceData/priceData';\nimport RecipeModalAccordion from './RecipeModalAccordion';\nimport RecipeModalProductsFooter from './RecipeModalProductsFooter';\n\nexport interface RecipeProductItemsGroup {\n    cart: RecipeCartState | null;\n}\n\ninterface RecipeModalProductsProps extends RecipeProductItemsGroup {\n    renderCartItem: (item: RecipeItemState) => JSX.Element;\n    handleCalculationTypeChange: (\n        calculationType: RecipeCalculationType,\n        prioritization: RecipePrioritizationType | null,\n    ) => void;\n    buyable: boolean;\n    handleBuy: () => void;\n    totalProducts?: number;\n}\n\ninterface RecipeModalProductsListProps {\n    list: RecipeItemState[];\n    title: string | null;\n    renderCartItem: (item: RecipeItemState) => JSX.Element;\n}\n\ninterface RecipeModalSectionProps {\n    section: RecipeSection;\n    allItems: RecipeItemState[];\n    renderCartItem: (item: RecipeItemState) => JSX.Element;\n}\n\nconst RecipeModalSection: FC<React.PropsWithChildren<RecipeModalSectionProps>> = (props) => {\n    const sectionItems = props.allItems.filter((item) =>\n        props.section.substituteIdentifiers.includes(item.substituteIdentifier),\n    );\n\n    const getSectionTitle = () => {\n        switch (props.section.type) {\n            case 'shared':\n                return 'Varor som delas mellan recept';\n            case 'common':\n                return 'Bra att ha till receptet';\n            default:\n                return null;\n        }\n    };\n\n    return (\n        <RecipeModalProductsList\n            list={sectionItems}\n            title={getSectionTitle()}\n            renderCartItem={props.renderCartItem}\n        />\n    );\n};\n\nexport const RecipeModalProductsList: React.FC<\n    React.PropsWithChildren<RecipeModalProductsListProps>\n> = ({ list, title, renderCartItem }) => (\n    <div className=\"Cart-group\">\n        {title && (\n            <div className=\"Cart-groupHeader\">\n                <span className=\"Cart-groupHeading\">{title}</span>\n            </div>\n        )}\n        <ul className=\" Cart-itemList\">{list.map((item) => renderCartItem(item))}</ul>\n    </div>\n);\n\nconst RecipeModalProducts: React.FC<React.PropsWithChildren<RecipeModalProductsProps>> = ({\n    cart,\n    renderCartItem,\n    handleCalculationTypeChange,\n    buyable,\n    handleBuy,\n    totalProducts,\n}) => {\n    return (\n        <>\n            <RecipeModalAccordion handleCalculationTypeChange={handleCalculationTypeChange} />\n            <div className=\"Cart Cart--borderB\">\n                {cart?.sections.map((section) => (\n                    <RecipeModalSection\n                        key={section.id}\n                        section={section}\n                        allItems={cart?.items}\n                        renderCartItem={renderCartItem}\n                    />\n                ))}\n            </div>\n            {buyable && (\n                <RecipeModalProductsFooter\n                    totalProducts={totalProducts}\n                    // use price with tax for recipes\n                    totalPrice={\n                        (cart && Helpers.getPrice(cart.totalPriceData, PriceType.IncludeTax)) || 0\n                    }\n                    handleBuy={handleBuy}\n                />\n            )}\n        </>\n    );\n};\n\nexport default RecipeModalProducts;\n","/* eslint-disable react/no-array-index-key */\nimport { Button } from '@coop/components';\nimport * as React from 'react';\nimport { useMemo } from 'react';\n\nimport type { ApiRecipe } from '../../../../../models/recipe/recipeModel';\nimport { buildRecipeRedirectUrl } from '../../../../recipe/utils';\nimport { mapToIngredientProps, mapToRecipeCookingInstructions } from '../../../utils/recipeUtils';\nimport RawHtml from '../../atoms/RawHtml';\n\nconst RecipeModalRecept = ({ recipe, readonly }: { recipe: ApiRecipe; readonly?: boolean }) => {\n    const cookingInstructions = useMemo(\n        () => mapToRecipeCookingInstructions(recipe.cookingInstructions),\n        [recipe.cookingInstructions],\n    );\n\n    const recipePart = recipe.recipePart.map((part) => ({\n        part: part.name,\n        ingredients: mapToIngredientProps(part.ingredients),\n    }));\n\n    const ingredientLine = (formattedQuantity: string, unit: string, friendlyText: string) => {\n        if (formattedQuantity) {\n            return `${formattedQuantity} ${unit} ${friendlyText}`;\n        }\n\n        return friendlyText;\n    };\n\n    return (\n        <div\n            className=\"Tab-panel u-md-marginTz u-paddingA u-paddingTxlg is-active\"\n            data-panel=\"2\"\n            data-external-id={recipe.externalId}\n            data-recipe-name={recipe.name}\n        >\n            {recipe.preamble && (\n                <p className=\"u-marginTz u-md-marginTz u-marginBxlg u-textCenter\">\n                    <RawHtml html={recipe.preamble} />\n                </p>\n            )}\n            <div className=\"Grid Grid--gutterA\">\n                <div className=\"Grid-cell u-sm-size1of2\">\n                    <h5>\n                        Ingredienser{' '}\n                        {recipe.yieldValue > 0 && `(för ${recipe.yieldValue} portioner)`}\n                    </h5>\n                    <ul className=\"List List--noSpacing u-textSmall\">\n                        {recipePart.map(({ part, ingredients }, i) => (\n                            <div key={`${i}_${part}`}>\n                                {part && (\n                                    <li className=\"u-textWeightBold\">\n                                        <p>{part}</p>\n                                    </li>\n                                )}\n                                {ingredients.map(\n                                    ({ formattedQuantity, unit, friendlyText }, index) => (\n                                        <li\n                                            key={`${index}_${friendlyText}`}\n                                            className=\"u-colorBaseMid\"\n                                        >\n                                            <p>\n                                                {ingredientLine(\n                                                    formattedQuantity,\n                                                    unit,\n                                                    friendlyText,\n                                                )}\n                                            </p>\n                                        </li>\n                                    ),\n                                )}\n                            </div>\n                        ))}\n                    </ul>\n                </div>\n\n                {!recipe.isFoodBox && (\n                    <div className=\"Grid-cell u-sm-size1of2\">\n                        <h5>Gör så här</h5>\n                        <div className=\"List List--ordered-container\">\n                            {cookingInstructions.map(({ title, instructions }, i) => (\n                                <React.Fragment key={i}>\n                                    {title && <h5 className=\"u-textWeightBold\">{title}</h5>}\n                                    {!!instructions?.length && (\n                                        <ol className=\"List List--ordered u-textSmall\">\n                                            {instructions.map((el, e) => (\n                                                <li key={e} className=\"u-colorBaseMid\">\n                                                    {el}\n                                                </li>\n                                            ))}\n                                        </ol>\n                                    )}\n                                </React.Fragment>\n                            ))}\n                        </div>\n                    </div>\n                )}\n            </div>\n            {!readonly && (\n                <div className=\"Grid Grid--gutterA u-paddingH u-paddingTmd hideme\">\n                    <Button\n                        asChild\n                        size={40}\n                        theme=\"primaryOutline\"\n                        fullWidth\n                        className=\"u-md-hidden\"\n                    >\n                        <a href={buildRecipeRedirectUrl(recipe.externalId.toString())}>\n                            G&aring; till receptsidan\n                        </a>\n                    </Button>\n                </div>\n            )}\n        </div>\n    );\n};\n\nexport default RecipeModalRecept;\n","import { OverlayLoader } from '@coop/components';\nimport * as React from 'react';\n\nimport type { ApiRecipe } from '../../../../../models/recipe/recipeModel';\nimport { Helpers } from '../../../../../utility/helpers';\nimport RecipePortionCounter from '../../../../cart/components/molecules/RecipePortionCounter';\nimport type {\n    RecipeCalculationType,\n    RecipeItemState,\n    RecipeModalTab,\n    RecipePrioritizationType,\n} from '../../../../recipe/models';\nimport type { PriceType } from '../../../models/priceData/priceData';\nimport type { TabItem } from '../TabSwitcher';\nimport { TabSwitcher } from '../TabSwitcher';\nimport RecipeModalFooter from './RecipeModalFooter';\nimport RecipeModalHeader from './RecipeModalHeader';\nimport type { RecipeProductItemsGroup } from './RecipeModalProducts';\nimport RecipeModalProducts from './RecipeModalProducts';\nimport RecipeModalRecept from './RecipeModalRecept';\n\ninterface RecipeModalProps extends RecipeProductItemsGroup {\n    recipeData?: ApiRecipe;\n    modalTabToDisplay: RecipeModalTab;\n    renderCartItem: (item: RecipeItemState) => JSX.Element;\n    close: () => void;\n    isLoading: boolean;\n    handlePortionChange: (quantity: number) => void;\n    handleCalculationTypeChange: (\n        calculationType: RecipeCalculationType,\n        prioritization: RecipePrioritizationType | null,\n    ) => void;\n    handleBuy: () => void;\n    handleLinkClick: () => void;\n    readonly?: boolean;\n    priceType: PriceType;\n}\n\nconst RecipeModalBody: React.FC<React.PropsWithChildren<RecipeModalProps>> = ({\n    recipeData,\n    modalTabToDisplay = 1,\n    renderCartItem,\n    close,\n    isLoading,\n    handlePortionChange,\n    handleCalculationTypeChange,\n    handleBuy,\n    handleLinkClick,\n    readonly,\n    cart,\n    priceType,\n}) => {\n    let buyable = false;\n\n    if (cart) {\n        buyable = true;\n    }\n\n    buyable = readonly ? false : buyable;\n\n    const totalProducts = cart?.items\n        .filter((item) => item.purchasable)\n        .reduce((curr, next) => curr + (next.quantity || 0), 0);\n\n    return (\n        <div className=\"RecipeModal RecipeModal--fullHeight\">\n            <OverlayLoader isLoading={isLoading} />\n            {recipeData && (\n                <RecipeModalBodyWithData\n                    recipeData={recipeData}\n                    buyable={buyable}\n                    close={close}\n                    totalProducts={totalProducts}\n                    handlePortionChange={handlePortionChange}\n                    handleLinkClick={handleLinkClick}\n                    handleBuy={handleBuy}\n                    cart={cart}\n                    renderCartItem={renderCartItem}\n                    handleCalculationTypeChange={handleCalculationTypeChange}\n                    modalTabToDisplay={modalTabToDisplay}\n                    readonly={readonly}\n                    priceType={priceType}\n                />\n            )}\n        </div>\n    );\n};\n\nconst RecipeModalBodyWithData = ({\n    recipeData,\n    modalTabToDisplay = 1,\n    renderCartItem,\n    close,\n    handlePortionChange,\n    handleCalculationTypeChange,\n    handleBuy,\n    handleLinkClick,\n    readonly,\n    cart,\n    buyable,\n    totalProducts,\n    priceType,\n}: Omit<RecipeModalProps, 'recipeData' | 'isLoading'> &\n    Required<Pick<RecipeModalProps, 'recipeData'>> & {\n        buyable: boolean;\n        totalProducts?: number;\n    }) => {\n    const defaultPortions = recipeData.yieldValue || 4;\n    const rating = recipeData.avgRating || null;\n    const display = modalTabToDisplay === 2 && cart ? 2 : 1;\n\n    const [portions, setPortions] = React.useState(defaultPortions);\n\n    const createTabs = (): TabItem[] => {\n        return [\n            {\n                id: '1',\n                name: !recipeData?.isFoodBox ? 'Recept' : 'Beskrivning',\n                component: <RecipeModalRecept recipe={recipeData!} readonly={readonly} />,\n            },\n            ...(buyable\n                ? [\n                      {\n                          id: '2',\n                          name: 'Varor',\n                          component: (\n                              <RecipeModalProducts\n                                  renderCartItem={renderCartItem}\n                                  buyable={buyable}\n                                  cart={cart}\n                                  handleCalculationTypeChange={handleCalculationTypeChange}\n                                  handleBuy={handleBuy}\n                                  totalProducts={totalProducts}\n                              />\n                          ),\n                      },\n                  ]\n                : []),\n        ];\n    };\n\n    return (\n        <>\n            <RecipeModalHeader\n                recipeName={recipeData.name}\n                imageUrl={recipeData.imageUrl}\n                rating={rating}\n                time={recipeData.totalTime}\n                buyable={buyable}\n                close={close}\n            />\n            <TabSwitcher\n                items={createTabs()}\n                wrapperClasses=\"RecipeModal-body Tab--recipeModal\"\n                containerClasses=\"RecipeModal-contentTop\"\n                panelClasses=\"RecipeModal-content\"\n                listClasses=\"RecipeModal-tabs\"\n                itemClasses={() => 'RecipeModal-tabs'}\n                renderNextToTabs={() =>\n                    buyable && (\n                        <div className=\"RecipeModal-amountSelector\">\n                            <div className=\"u-sizeFull\">\n                                <RecipePortionCounter\n                                    minValue={1}\n                                    maxValue={20}\n                                    incrementBy={1}\n                                    portions={portions}\n                                    setPortions={(p) => {\n                                        setPortions(p);\n                                        handlePortionChange(p);\n                                    }}\n                                />\n                            </div>\n                        </div>\n                    )\n                }\n                initialActiveId={display.toString()}\n            />\n            {!readonly && (\n                <RecipeModalFooter\n                    priceType={priceType}\n                    totalProducts={totalProducts}\n                    // use price with tax for recipes\n                    totalPrice={(cart && Helpers.getPrice(cart.totalPriceData, priceType)) || 0}\n                    externalId={recipeData.externalId}\n                    buyable={buyable}\n                    handleBuy={handleBuy}\n                    handleLinkClick={handleLinkClick}\n                    isFoodBox={recipeData.isFoodBox}\n                />\n            )}\n        </>\n    );\n};\n\nexport default RecipeModalBody;\n","import { useCallback, useEffect, useRef } from 'react';\n\nimport type { ApiRecipe } from '../../../../../models/recipe/recipeModel';\nimport RecipeProductListingItem from '../../../../cart/components/molecules/RecipeProductListingItem/RecipeProductListingItem';\nimport { recipeModalProductSubstitutesBreakpoints } from '../../../../cart/components/molecules/RecipeProductListingItem/RecipeProductListingItem.utils';\nimport recipeFlow from '../../../../recipe/flow/recipeFlow';\nimport useRecipeCart from '../../../../recipe/hooks/useRecipeCart';\nimport useSubstitutes from '../../../../recipe/hooks/useSubstitute';\nimport type {\n    RecipeCalculationType,\n    RecipeItemState,\n    RecipePrioritizationType,\n} from '../../../../recipe/models';\nimport { RecipeModalTab } from '../../../../recipe/models';\nimport type { ApiAddMultipleRecipesRequest } from '../../../api/recipe/recipeModels';\nimport { useAsyncDispatcher } from '../../../hooks/useAsyncDispatcher';\nimport { useCurrentPriceType } from '../../../hooks/useCurrentPriceType';\nimport { useGroupError } from '../../../hooks/useGroupError';\nimport { useRequestEffects } from '../../../hooks/useRequestEffects';\nimport { useAppDispatch, useAppSelector } from '../../../hooks/useThunkDispatch';\nimport { storeSelectors } from '../../../selectors/storeSelectors';\nimport { ErrorGroup } from '../../../store/structureDefinitions/errorsState';\nimport { cartThunks } from '../../../thunks/cartThunks';\nimport { ga4CartTracking } from '../../../tracking/ga4/cart';\nimport type { ModifyCartAnalyticsOptions } from '../../../tracking/ga4/cart/ga4CartEvents';\nimport tracking from '../../../tracking/tracking';\nimport MissingItemBody from '../../organisms/MissingItemBody';\nimport PurchasableItemBody from '../../organisms/PurchasableItemBody/PurchasableItemBody';\nimport RecipeModalBody from '../RecipeModal/RecipeModalBody';\n\ninterface BuyableRecipeModalProps {\n    recipeId: string;\n    portions: number;\n    tabToDisplay: RecipeModalTab;\n    close: () => void;\n    readonly?: boolean;\n    analyticsListName: string;\n}\n\nconst useBuyableRecipeModalTracking = () => {\n    const modalPopupSent = useRef(false);\n\n    const trackModalPopup = useCallback((recipe: ApiRecipe, portions: number) => {\n        if (!modalPopupSent.current) {\n            tracking.ecommerce.recipes.modalPopup(recipe, RecipeModalTab.Products, portions);\n            modalPopupSent.current = true;\n        }\n    }, []);\n\n    const trackAddToCart = useCallback(\n        (\n            products: { quantity: number; productId: string; variantId?: string; index?: number }[],\n            storeId: string,\n            listOptions: ModifyCartAnalyticsOptions | null,\n        ) => {\n            ga4CartTracking.modifyCartItems(\n                products.map((item) => ({\n                    index: item.index,\n                    productId: item.productId,\n                    previousQuantity: 0,\n                    newQuantity: item.quantity,\n                    variantId: item.variantId,\n                })),\n                storeId,\n                listOptions,\n            );\n        },\n        [],\n    );\n\n    return {\n        trackModalPopup,\n        trackBuyRecipe: tracking.ecommerce.recipes.buyRecipe,\n        trackCalculationChange: tracking.ecommerce.recipes.calculationChange,\n        trackPortionChange: tracking.ecommerce.recipes.portionChange,\n        trackLinkClick: tracking.ecommerce.recipes.linkClick,\n        trackSubstituteProduct: tracking.ecommerce.recipes.substituteProduct,\n        trackAddToCart,\n    };\n};\n\nconst BuyableRecipeModalBody: React.FC<React.PropsWithChildren<BuyableRecipeModalProps>> = (\n    props,\n) => {\n    const recipeId = props.recipeId.toString();\n    const currentProductionUnit = useAppSelector(storeSelectors.currentProductionUnit);\n\n    const getRecipeDispatcher = useAsyncDispatcher(recipeFlow.getRecipeById, {\n        initialLoadingState: true,\n        keepPreviousResult: true,\n    });\n\n    const { currentPriceType } = useCurrentPriceType();\n\n    const { close, tabToDisplay } = props;\n\n    const { execute: getRecipe, result: getRecipeResult, isLoading, error } = getRecipeDispatcher;\n\n    useEffect(() => {\n        if (error) {\n            close();\n        }\n    }, [close, error]);\n\n    useGroupError(ErrorGroup.Global, error);\n\n    const {\n        trackModalPopup,\n        trackBuyRecipe,\n        trackCalculationChange,\n        trackPortionChange,\n        trackLinkClick,\n        trackSubstituteProduct,\n        trackAddToCart,\n    } = useBuyableRecipeModalTracking();\n\n    const {\n        updateItemQuantity,\n        updateSubstituteProduct,\n        updatePortions,\n        updateCalculation,\n        removeItem,\n        calculateCart,\n        recipeCart,\n        recipeCartProducts,\n        getProductExceptions,\n        isLoading: isLoadingRecipeCart,\n    } = useRecipeCart(!props.readonly);\n\n    const handleSubstituteChangeClick = (item: RecipeItemState, product: ApiProduct) => {\n        updateSubstituteProduct(item, product.identifier);\n        trackSubstituteProduct(item.name, recipeId, product.identifier, product.name);\n    };\n\n    const {\n        onSubsituteChangeClick,\n        onSubstituteTriggerClick,\n        expandedSubstituteIds,\n        isLoadingSubstitutes,\n        substitutes,\n    } = useSubstitutes(handleSubstituteChangeClick, recipeCart?.items);\n\n    const dispatch = useAppDispatch();\n\n    useEffect(() => {\n        getRecipe(recipeId);\n        if (!props.readonly) {\n            calculateCart({\n                calculation: 'waste',\n                prioritization: null,\n                recipes: [{ recipeId, portions: props.portions }],\n            });\n        }\n    }, [calculateCart, getRecipe, props.portions, props.readonly, recipeId]);\n\n    useEffect(() => {\n        if (getRecipeResult) {\n            trackModalPopup(getRecipeResult, getRecipeResult?.yieldValue);\n        }\n    }, [getRecipeResult, trackModalPopup]);\n\n    const buyRecipeDispatcher = useAsyncDispatcher((request: ApiAddMultipleRecipesRequest) =>\n        dispatch(cartThunks.buyMultipleRecipes(request)),\n    );\n\n    const {\n        execute: buyRecipe,\n        isLoading: buyRecipeLoading,\n        result: buyRecipeResult,\n    } = buyRecipeDispatcher;\n    useRequestEffects(\n        buyRecipeDispatcher,\n        {\n            onSuccess: () => {\n                const itemsToTrack = recipeCart?.items?.filter(\n                    (item) => !!item.quantity && item.quantity > 0 && item.purchasable,\n                );\n                if (itemsToTrack?.length) {\n                    trackAddToCart(\n                        itemsToTrack.map((item, index) => ({\n                            quantity: item.quantity!,\n                            productId: item.id,\n                            index,\n                        })),\n                        currentProductionUnit,\n                        {\n                            list: props.analyticsListName,\n                            listPosition: 0,\n                            recipe_list_id: recipeCart?.recipes\n                                ?.map((recipe) => recipe.code)\n                                .join('|'),\n                            recipe_list_name: recipeCart?.recipes\n                                ?.map((recipe) => recipe.title)\n                                .join('|'),\n                            recipe_origin: 'recipes',\n                        },\n                    );\n                }\n            },\n        },\n        ErrorGroup.Modal,\n    );\n\n    useEffect(() => {\n        if (buyRecipeResult) {\n            close();\n        }\n    }, [close, buyRecipeResult]);\n\n    const recipePortions = recipeCart?.recipes.find((recipe) => recipe.code === recipeId)?.portions;\n\n    const handlePortionChange = (portionQuantity: number) => {\n        if (getRecipeResult) {\n            trackPortionChange(getRecipeResult.name, recipeId, recipePortions, portionQuantity);\n        }\n        updatePortions(recipeId, portionQuantity);\n    };\n\n    const handleCalculationTypeChange = (\n        calculationType: RecipeCalculationType,\n        prioritization: RecipePrioritizationType | null,\n    ) => {\n        if (getRecipeResult) {\n            trackCalculationChange(\n                getRecipeResult.name,\n                recipeId,\n                calculationType,\n                prioritization,\n                recipePortions,\n            );\n        }\n\n        updateCalculation(calculationType, prioritization);\n    };\n\n    const handleRecipeLinkClick = () => {\n        if (getRecipeResult) {\n            trackLinkClick(getRecipeResult.name, recipeId, recipePortions);\n        }\n    };\n\n    const handleBuy = () => {\n        const productExceptions = getProductExceptions();\n        if (getRecipeResult) {\n            trackBuyRecipe(getRecipeResult.name, recipeId, recipePortions);\n        }\n\n        if (recipeCart) {\n            buyRecipe({\n                calculation: recipeCart.calculation,\n                prioritization: recipeCart.prioritization,\n                recipes: recipeCart.recipes.map((x) => ({\n                    recipeId: x.code,\n                    portions: x.portions,\n                    group: getRecipeResult?.isFoodBox ? 'foodbox' : 'recipe',\n                })),\n                products: productExceptions?.map((x) => ({\n                    productId: x.id,\n                    qty: x.quantity,\n                    substituteId: x.substituteIdentifier,\n                })),\n            });\n        }\n    };\n\n    return (\n        <RecipeModalBody\n            recipeData={getRecipeResult}\n            modalTabToDisplay={tabToDisplay}\n            handlePortionChange={handlePortionChange}\n            handleCalculationTypeChange={handleCalculationTypeChange}\n            handleBuy={handleBuy}\n            close={close}\n            priceType={currentPriceType}\n            isLoading={isLoading || isLoadingRecipeCart || isLoadingSubstitutes || buyRecipeLoading}\n            renderCartItem={(item) => {\n                return (\n                    <RecipeProductListingItem\n                        key={item.id}\n                        recipeProduct={item}\n                        priceType={currentPriceType}\n                        product={recipeCartProducts?.find(\n                            (product) => product.identifier === item.id,\n                        )}\n                        recipeProductSubstitutes={\n                            substitutes[item.substituteIdentifier]?.substituteProducts\n                        }\n                        buyable={item.purchasable}\n                        isSubstituteActive={expandedSubstituteIds.includes(\n                            item.substituteIdentifier,\n                        )}\n                        handleSubstituteChange={(product: ApiProduct) => {\n                            onSubsituteChangeClick(item, product);\n                        }}\n                        analyticsOptions={{ list: 'produktersättare - varukorg' }}\n                        productSubstitutesBreakpoints={recipeModalProductSubstitutesBreakpoints}\n                    >\n                        {item.purchasable ? (\n                            <PurchasableItemBody\n                                item={item}\n                                sectionType=\"recipe\"\n                                hasActiveSubstitutes={expandedSubstituteIds.includes(\n                                    item.substituteIdentifier,\n                                )}\n                                handleQuantityChange={updateItemQuantity}\n                                handleSubsituteTriggerClick={() =>\n                                    onSubstituteTriggerClick(item.substituteIdentifier)\n                                }\n                            />\n                        ) : (\n                            <MissingItemBody\n                                item={item}\n                                recipeSectionType=\"recipe\"\n                                hasActiveSubstitutes={expandedSubstituteIds.includes(\n                                    item.substituteIdentifier,\n                                )}\n                                handleSubsituteTriggerClick={() =>\n                                    onSubstituteTriggerClick(item.substituteIdentifier)\n                                }\n                                handleRemoveItem={removeItem}\n                            />\n                        )}\n                    </RecipeProductListingItem>\n                );\n            }}\n            cart={recipeCart}\n            handleLinkClick={handleRecipeLinkClick}\n            readonly={props.readonly}\n        />\n    );\n};\n\nexport default BuyableRecipeModalBody;\n","import { Icon } from '@coop/components';\nimport { Info1Icon } from '@coop/icons';\n\nimport styles from './MissingItemBody.module.less';\n\nconst MissingItemInfo = (props: { text: string }) => {\n    return (\n        <div className={styles.MissingItemInfo}>\n            <Icon icon={Info1Icon} width={16} height={16} color=\"red\" />\n            <span>{props.text}</span>\n        </div>\n    );\n};\n\nexport default MissingItemInfo;\n","import { ChipIconButton } from '@coop/components';\nimport { TrashIcon } from '@coop/icons';\nimport type { FC } from 'react';\n\nimport SharedBetweenRecipesTooltip from '../../../../recipe/components/SharedBetweenRecipesTooltip/SharedBetweenRecipesTooltip';\nimport type { RecipeItemState, RecipeSectionType } from '../../../../recipe/models';\nimport SubstituteTrigger from '../../atoms/SubstituteTrigger';\nimport styles from './MissingItemBody.module.less';\nimport MissingItemInfo from './MissingItemInfo';\n\ninterface MissingItemBodyProps {\n    item: RecipeItemState;\n    recipeSectionType: RecipeSectionType;\n    hasActiveSubstitutes: boolean;\n    handleSubsituteTriggerClick: (item: RecipeItemState) => void;\n    handleRemoveItem: (item: RecipeItemState) => void;\n}\n\nconst MissingItemBody: FC<React.PropsWithChildren<MissingItemBodyProps>> = (props) => {\n    return (\n        <div className={styles.RecipeItemActionsContainer}>\n            <MissingItemInfo text=\"Varan saknas i sortimentet.\" />\n            <div className={styles.RecipeItemActions}>\n                <div className={styles['RecipeItemActions-info']}>\n                    {props.item.belongsToRecipes && (\n                        <SharedBetweenRecipesTooltip\n                            sectionType={props.recipeSectionType}\n                            belongsToRecipes={props.item.belongsToRecipes}\n                        />\n                    )}\n                </div>\n                {props.item.substituteProductsAmount > 0 && (\n                    <SubstituteTrigger\n                        handleSubsituteTrigger={() => props.handleSubsituteTriggerClick(props.item)}\n                        theme=\"greenCta\"\n                        isActive={props.hasActiveSubstitutes}\n                    />\n                )}\n                {props.recipeSectionType !== 'common' && (\n                    <ChipIconButton\n                        icon={TrashIcon}\n                        label=\"Ta bort\"\n                        size={32}\n                        theme=\"green2\"\n                        onClick={() => props.handleRemoveItem(props.item)}\n                    />\n                )}\n            </div>\n        </div>\n    );\n};\n\nexport default MissingItemBody;\n","import type { FC } from 'react';\n\nimport SharedBetweenRecipesTooltip from '../../../../recipe/components/SharedBetweenRecipesTooltip/SharedBetweenRecipesTooltip';\nimport type { RecipeItemState, RecipeSectionType } from '../../../../recipe/models';\nimport SubstituteTrigger from '../../atoms/SubstituteTrigger';\nimport { QuantityStepper } from '../../QuantityStepper';\n\ninterface PurchasableItemBodyProps {\n    item: RecipeItemState;\n    sectionType: RecipeSectionType;\n    hasActiveSubstitutes: boolean;\n    handleQuantityChange: (item: RecipeItemState, newQuantity: number) => void;\n    handleSubsituteTriggerClick: (item: RecipeItemState) => void;\n}\n\nconst PurchasableItemBody: FC<React.PropsWithChildren<PurchasableItemBodyProps>> = (props) => {\n    return (\n        <>\n            {props.item.belongsToRecipes && (\n                <SharedBetweenRecipesTooltip\n                    sectionType={props.sectionType}\n                    belongsToRecipes={props.item.belongsToRecipes}\n                />\n            )}\n            {props.item.substituteProductsAmount > 0 && (\n                <SubstituteTrigger\n                    handleSubsituteTrigger={() => props.handleSubsituteTriggerClick(props.item)}\n                    theme=\"whiteGreen\"\n                    isActive={props.hasActiveSubstitutes}\n                />\n            )}\n            {(!!props.item.quantity || props.item.quantity === 0) && ( // 0 is allowed for good to have, !!0 = false, hence additional check for 0\n                <QuantityStepper\n                    quantity={props.item.quantity}\n                    setQuantity={(newQuantity) => {\n                        props.handleQuantityChange(props.item, newQuantity);\n                    }}\n                />\n            )}\n        </>\n    );\n};\n\nexport default PurchasableItemBody;\n","import type { RecipeItemState } from '../../../../recipe/models';\n\nexport const getRecipeSection = (item: RecipeItemState) => {\n    return {\n        recipeId: item.group === 'singleProducts' ? item.belongsToRecipes[0].code : 'shared',\n        recipeName: item.group === 'singleProducts' ? item.belongsToRecipes[0].name : 'shared',\n    };\n};\n","/* eslint-disable no-param-reassign */\nimport produce from 'immer';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport _ from 'underscore';\n\nimport type {\n    ApiHybrisRecipe,\n    ApiRecipeList,\n    ApiRecipeProductItem,\n} from '../../common/api/recipe/recipeModels';\nimport { SyncronQueue } from '../../common/api/SyncronQueue';\nimport { productFlow } from '../../common/flow/product/productFlow';\nimport { useAsyncDispatcher } from '../../common/hooks/useAsyncDispatcher';\nimport { useGroupErrorEffect } from '../../common/hooks/useGroupError';\nimport { useAppSelector } from '../../common/hooks/useThunkDispatch';\nimport { storeSelectors } from '../../common/selectors/storeSelectors';\nimport { ErrorGroup } from '../../common/store/structureDefinitions/errorsState';\nimport { ga4RecipesTracking } from '../../common/tracking/ga4/recipes';\nimport { getRecipeSection } from '../../common/tracking/ga4/recipes/ga4Recipes.utils';\nimport recipeFlow from '../flow/recipeFlow';\nimport type {\n    RecipeCalculationType,\n    RecipeItemState,\n    RecipePrioritizationType,\n    RecipeProductException,\n    RecipeProductGroupType,\n    RecipeSectionType,\n    ResolveRecipesRequest,\n} from '../models';\nimport { ItemState } from '../models';\n\nexport interface JoinedRecipe {\n    name: string;\n    id: string;\n}\n\nexport interface RecipeItemProductSubstitute extends RecipeItemState {\n    product: ApiProduct;\n}\n\nexport const mapItem = (\n    recipeProductItem: ApiRecipeProductItem,\n    group: RecipeProductGroupType,\n    isRemoved: boolean,\n): RecipeItemState => {\n    return {\n        id: recipeProductItem.id,\n        priceData: recipeProductItem.priceData,\n        purchasable: recipeProductItem.purchasable,\n        quantity: recipeProductItem.quantity,\n        substituteProductsAmount: recipeProductItem.substituteProductsAmount,\n        image: recipeProductItem.image,\n        manufacturer: recipeProductItem.manufacturer,\n        name: recipeProductItem.name,\n        substituteIdentifier: recipeProductItem.substituteIdentifier,\n        packageSizeInformation: recipeProductItem.packageSizeInformation,\n        belongsToRecipes:\n            recipeProductItem.belongsToRecipes?.map((item) => ({\n                name: item.name,\n                code: item.recipeId,\n            })) || [],\n        selectedVarianceCode: recipeProductItem.selectedVarianceCode,\n        totalPriceData: recipeProductItem.rowTotalPriceData,\n        group,\n        state: isRemoved ? ItemState.Removed : ItemState.Default,\n    };\n};\n\nexport type RecipeSection =\n    | ({\n          type: Extract<RecipeSectionType, 'common'>;\n      } & Omit<Section, 'portions'>)\n    | ({\n          type: Extract<RecipeSectionType, 'recipe'>;\n      } & Section)\n    | ({\n          type: Extract<RecipeSectionType, 'shared'>;\n      } & Omit<Section, 'portions'>);\n\nexport interface Section {\n    id: string; // could be shared or common\n    type: RecipeSectionType;\n    name: string;\n    imageUrl: string;\n    portions: number;\n    substituteIdentifiers: string[];\n    productIdentifiers: string[];\n    sharedSubstituteIdentifiers?: string[];\n}\n\nconst mapItems = (\n    hybrisRecipeList: ApiRecipeList,\n    removedSubsituteIdentifiers: string[],\n): RecipeItemState[] => {\n    const singleProducts = (hybrisRecipeList.singleProducts || []).map((item) =>\n        mapItem(\n            item,\n            'singleProducts',\n            removedSubsituteIdentifiers.includes(item.substituteIdentifier),\n        ),\n    );\n    const sharedProducts = (hybrisRecipeList.sharedProducts || []).map((item) =>\n        mapItem(\n            item,\n            'sharedProducts',\n            removedSubsituteIdentifiers.includes(item.substituteIdentifier),\n        ),\n    );\n    const goodToHaveProducts = (hybrisRecipeList.goodToHaveProducts || []).map((item) =>\n        mapItem(\n            item,\n            'commonProducts',\n            removedSubsituteIdentifiers.includes(item.substituteIdentifier),\n        ),\n    );\n\n    const allItems = [...singleProducts, ...sharedProducts, ...goodToHaveProducts];\n    return allItems;\n};\n\nconst mapSections = (\n    recipeList: ApiRecipeList,\n    removedSubsituteIdentifiers: string[],\n): RecipeSection[] => {\n    const singleProducts = (recipeList.singleProducts || []).filter(\n        (item) => !removedSubsituteIdentifiers.includes(item.substituteIdentifier),\n    );\n    const sharedProducts = recipeList.sharedProducts.filter(\n        (item) => !removedSubsituteIdentifiers.includes(item.substituteIdentifier),\n    );\n    const goodToHaveProducts = recipeList.goodToHaveProducts.filter(\n        (item) => !removedSubsituteIdentifiers.includes(item.substituteIdentifier),\n    );\n\n    const recipeSectionsMap = singleProducts.reduce<Record<string, RecipeSection>>(\n        (prev, next) => {\n            const sectionId = next.belongsToRecipes[0].recipeId;\n            const sectionName = next.belongsToRecipes[0].name;\n            const recipe = recipeList.recipes.find((_recipe) => _recipe.code === sectionId);\n\n            const final = { ...prev };\n\n            if (recipe) {\n                final[sectionId] = {\n                    id: sectionId,\n                    type: 'recipe',\n                    name: sectionName,\n                    imageUrl: recipe.imageUrl,\n                    portions: recipe.portions,\n                    substituteIdentifiers: prev[sectionId]?.substituteIdentifiers\n                        ? [...prev[sectionId].substituteIdentifiers, next.substituteIdentifier]\n                        : [next.substituteIdentifier],\n                    productIdentifiers: prev[sectionId]?.productIdentifiers\n                        ? [...prev[sectionId].productIdentifiers, next.id]\n                        : [next.id],\n                };\n            }\n\n            return final;\n        },\n        {} as Record<string, RecipeSection>,\n    );\n\n    // add info how many products are in shared section for each recipe\n    Object.keys(recipeSectionsMap).forEach((sectionId) => {\n        const sharedProductsBelongingToRecipe = sharedProducts\n            .filter((sharedProduct) =>\n                sharedProduct.belongsToRecipes\n                    .map((joinedRecipe) => joinedRecipe.recipeId)\n                    .includes(sectionId),\n            )\n            .map((product) => product.substituteIdentifier);\n\n        recipeSectionsMap[sectionId].sharedSubstituteIdentifiers = sharedProductsBelongingToRecipe;\n    });\n\n    const sharedRecipeProductIds = sharedProducts.map((x) => x.id);\n    const goodToHaveProductIds = goodToHaveProducts.map((x) => x.id);\n\n    const sharedRecipeSubstituteIds = sharedProducts.map((x) => x.substituteIdentifier);\n    const goodToHaveSubstituteIds = goodToHaveProducts.map((x) => x.substituteIdentifier);\n\n    const recipeSectionList = Object.values<RecipeSection>(recipeSectionsMap);\n\n    if (sharedRecipeSubstituteIds.length) {\n        recipeSectionList.push({\n            id: 'shared',\n            type: 'shared',\n            name: 'Delas mellan recepten',\n            substituteIdentifiers: sharedRecipeSubstituteIds,\n            productIdentifiers: sharedRecipeProductIds,\n            imageUrl: '/Assets/Images/recipe-shared.png',\n        });\n    }\n\n    if (goodToHaveProductIds.length) {\n        recipeSectionList.push({\n            id: 'common',\n            type: 'common',\n            name: 'Basvaror du behöver ha hemma',\n            substituteIdentifiers: goodToHaveSubstituteIds,\n            productIdentifiers: goodToHaveProductIds,\n            imageUrl: '/Assets/Images/recipe-good-to-have.png',\n        });\n    }\n\n    return recipeSectionList;\n};\n\nconst createCartState = (\n    recipeList: ApiRecipeList,\n    removedItems: RecipeItemState[],\n): RecipeCartState => {\n    const removedSubstituteIds = removedItems.map((item) => item.substituteIdentifier);\n    const sections = mapSections(recipeList, removedSubstituteIds);\n\n    return {\n        calculation: recipeList.calculation,\n        prioritization: recipeList.prioritization,\n        recipes: recipeList.recipes,\n        items: mapItems(recipeList, removedSubstituteIds),\n        sections,\n        totalPriceData: {\n            inclTaxPrice: recipeList.recipesTotalPrice.value,\n            exclTaxPrice: recipeList.recipesTotalPrice.valueWithoutTax,\n        },\n    };\n};\n\nconst recipeCartQueue = new SyncronQueue();\n\ninterface RecipeData {\n    recipeId: string;\n    portions: number;\n}\n\nexport interface RecipeCartState {\n    recipes: ApiHybrisRecipe[];\n    prioritization?: RecipePrioritizationType;\n    calculation: RecipeCalculationType;\n    items: RecipeItemState[];\n    sections: RecipeSection[];\n    totalPriceData: ApiPriceData;\n}\n\ninterface RecipeItemChangeState extends RecipeItemState {\n    removed?: boolean;\n}\n\ninterface RecipeCartChangesState {\n    recipes: RecipeData[];\n    prioritization: RecipePrioritizationType | null;\n    calculation: RecipeCalculationType;\n    productChanges: Record<string, RecipeItemChangeState>;\n}\n\nconst mapProductChangesToExceptions = (productChanges: Record<string, RecipeItemState>) => {\n    if (!productChanges) return [];\n\n    const changedProducts = Object.values(productChanges);\n    const productExceptions = changedProducts.map<RecipeProductException>((cp) => ({\n        productId: cp.id,\n        substituteId: cp.substituteIdentifier,\n        qty: cp.quantity,\n    }));\n\n    return productExceptions;\n};\n\nconst useRecipeCart = (initialLoading: boolean = true) => {\n    const [cartState, setCartState] = useState<RecipeCartState | null>(null);\n    const [cartChangesState, setCartChangesState] = useState<RecipeCartChangesState | null>(null);\n    const removedItems = useRef<RecipeItemState[]>([]);\n\n    const currentProductionUnit = useAppSelector(storeSelectors.currentProductionUnit);\n\n    const updateSubstituteProduct = useCallback((item: RecipeItemState, newProductId: string) => {\n        setCartChangesState((prevChanges) => {\n            return produce(prevChanges, (draft) => {\n                if (draft) {\n                    draft.productChanges[item.substituteIdentifier] = {\n                        ...item,\n                        id: newProductId,\n                        quantity: null,\n                    };\n                }\n\n                return draft;\n            });\n        });\n\n        const recipeSection = getRecipeSection(item);\n\n        ga4RecipesTracking.weeklyMenu.handleIngredient('change item')?.(\n            recipeSection.recipeId,\n            recipeSection.recipeName,\n            item.id,\n            item.name,\n        );\n    }, []);\n\n    const updateItemQuantity = useCallback((item: RecipeItemState, newQuantity: number) => {\n        setCartChangesState((prevChanges) => {\n            return produce(prevChanges, (draft) => {\n                if (draft) {\n                    draft.productChanges[item.substituteIdentifier] = {\n                        ...item,\n                        quantity: newQuantity,\n                    };\n                }\n                return draft;\n            });\n        });\n\n        const recipeSection = getRecipeSection(item);\n\n        if (item.quantity === null) {\n            return;\n        }\n\n        if (newQuantity > item.quantity) {\n            // add\n            ga4RecipesTracking.weeklyMenu.handleIngredient('add')?.(\n                recipeSection.recipeId,\n                recipeSection.recipeName,\n                item.id,\n                item.name,\n            );\n        }\n\n        if (newQuantity < item.quantity) {\n            // remove\n            ga4RecipesTracking.weeklyMenu.handleIngredient('remove')?.(\n                recipeSection.recipeId,\n                recipeSection.recipeName,\n                item.id,\n                item.name,\n            );\n        }\n    }, []);\n\n    const updatePortions = useCallback((recipeId: string, portions: number) => {\n        removedItems.current = [];\n        setCartChangesState((prevChanges) => {\n            return produce(prevChanges, (draft) => {\n                if (draft) {\n                    Object.values(draft.productChanges).forEach((pc) => {\n                        pc.quantity = null;\n                    });\n                    const recipeToChange = draft.recipes.find((cr) => cr.recipeId === recipeId);\n                    if (recipeToChange) {\n                        recipeToChange.portions = portions;\n                    }\n                }\n\n                return draft;\n            });\n        });\n    }, []);\n\n    const updateCalculation = useCallback(\n        (\n            calculationType: RecipeCalculationType,\n            prioritizationType: RecipePrioritizationType | null,\n        ) => {\n            removedItems.current = [];\n            setCartChangesState((prevChanges) => {\n                return produce(prevChanges, (draft) => {\n                    if (draft) {\n                        draft.productChanges = {}; // what to do here, keep substitues or always recalculate?\n                        draft.calculation = calculationType;\n                        draft.prioritization = prioritizationType;\n                    }\n\n                    return draft;\n                });\n            });\n        },\n        [],\n    );\n\n    const calculateCart = useCallback((request: ResolveRecipesRequest) => {\n        removedItems.current = [];\n        setCartChangesState((prevChanges) => {\n            return produce(prevChanges, (draft) => ({\n                ...draft,\n                calculation: request.calculation,\n                prioritization: request.prioritization,\n                recipes: request.recipes,\n                productChanges: {}, // what to do here, keep substitues or always recalculate?\n            }));\n        });\n    }, []);\n\n    const reCalculateCart = useCallback(() => {\n        removedItems.current = [];\n        setCartChangesState((prevChanges) => {\n            return produce(prevChanges, (draft) => {\n                if (draft) {\n                    draft.productChanges = {};\n                }\n\n                return draft; // what to do here, keep substitues or always recalculate?\n            });\n        });\n    }, []);\n\n    const removeItem = useCallback((item: RecipeItemState) => {\n        removedItems.current.push(item);\n\n        // fake cart recalculate\n        setCartChangesState((prevChanges) => {\n            return produce(prevChanges, (draft) => {\n                if (draft) {\n                    return { ...draft };\n                }\n\n                return draft;\n            });\n        });\n\n        const recipeSection = getRecipeSection(item);\n\n        ga4RecipesTracking.weeklyMenu.handleIngredient('empty')?.(\n            recipeSection.recipeId,\n            recipeSection.recipeName,\n            item.id,\n            item.name,\n        );\n    }, []);\n\n    const {\n        execute: resolve,\n        result: resolvedRecipes,\n        isLoading,\n        error: resolveError,\n    } = useAsyncDispatcher(\n        async (request: ResolveRecipesRequest, storeId: string) => {\n            // direct resolve to nortfork\n            // const normalResolve = await recipeFlow.resolveGastrofyRecipes({\n            //     options: {\n            //         calculation: request.calculation,\n            //         prioritization: request.prioritization || undefined,\n            //         productExceptions: request.products?.map((x) => ({\n            //             amount: x.qty || 0,\n            //             externalId: x.productId,\n            //             substituteIdentifier: x.substituteId,\n            //         })),\n            //     },\n            //     recipes: request.recipes.map((x) => ({\n            //         externalId: x.recipeId,\n            //         portions: x.portions,\n            //     })),\n            //     storeId,\n            // });\n\n            return recipeCartQueue.run(async () =>\n                recipeFlow.resolveRecipes(\n                    {\n                        calculation: request.calculation,\n                        prioritization: request.prioritization,\n                        recipes: request.recipes,\n                        products: request.products,\n                    },\n                    storeId,\n                ),\n            );\n        },\n        {\n            keepPreviousResult: true,\n            initialLoadingState: initialLoading,\n        },\n    );\n\n    useGroupErrorEffect(ErrorGroup.Global, !!resolveError, resolveError);\n\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n    const debouncedResolve = useCallback(_.debounce(resolve, 200), []);\n\n    useEffect(() => {\n        if (cartChangesState) {\n            debouncedResolve(\n                {\n                    calculation: cartChangesState.calculation,\n                    prioritization: cartChangesState.prioritization,\n                    recipes: cartChangesState.recipes,\n                    products: mapProductChangesToExceptions(cartChangesState.productChanges),\n                },\n                currentProductionUnit,\n            );\n        }\n    }, [cartChangesState, currentProductionUnit, debouncedResolve]);\n\n    const productChanges = useMemo(\n        () => (cartChangesState ? Object.values(cartChangesState.productChanges) : []),\n        [cartChangesState],\n    );\n\n    const isDirty = productChanges.length > 0 || removedItems.current.length;\n\n    useEffect(() => {\n        if (resolvedRecipes) {\n            // we need to fake removing items, thats why i keep them in ref\n            setCartState(createCartState(resolvedRecipes, removedItems.current));\n        }\n    }, [resolvedRecipes]);\n\n    const { execute, result: recipeCartProducts } = useAsyncDispatcher(\n        productFlow.getProductsByIds,\n        {\n            keepPreviousResult: true,\n            initialResultState: [],\n        },\n    );\n\n    useEffect(() => {\n        if (cartState?.items && cartState.items.length) {\n            execute(\n                cartState.items.map((x) => x.id),\n                currentProductionUnit,\n            );\n        }\n    }, [execute, cartState, currentProductionUnit]);\n\n    const getProductExceptions = () => {\n        const changedSubstituteIds =\n            cartChangesState && Object.keys(cartChangesState.productChanges);\n\n        const changedItems = cartState?.items.filter(\n            (item) =>\n                changedSubstituteIds && changedSubstituteIds.includes(item.substituteIdentifier),\n        );\n\n        return changedItems;\n    };\n\n    return {\n        updateItemQuantity,\n        updateSubstituteProduct,\n        updatePortions,\n        updateCalculation,\n        removeItem,\n        calculateCart,\n        reCalculateCart,\n        recipeCart: cartState,\n        recipeCartChanges: cartChangesState,\n        getProductExceptions,\n        recipeCartProducts,\n        isLoading,\n        isDirty,\n    };\n};\n\nexport default useRecipeCart;\n","import { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { productFlow } from '../../common/flow/product/productFlow';\nimport { useAsyncDispatcher } from '../../common/hooks/useAsyncDispatcher';\nimport { useRequestEffects } from '../../common/hooks/useRequestEffects';\nimport { useAppSelector } from '../../common/hooks/useThunkDispatch';\nimport { storeSelectors } from '../../common/selectors/storeSelectors';\nimport { ErrorGroup } from '../../common/store/structureDefinitions/errorsState';\nimport recipeFlow from '../flow/recipeFlow';\nimport type { RecipeItemState } from '../models';\n\nconst loadHybrisSubstitutes = async (storeId: string, substituteIdentifier: string) => {\n    const recipeProducts = await recipeFlow.getRecipeSubstitutes(storeId, substituteIdentifier);\n    const products =\n        (await productFlow.getProductsByIds(\n            recipeProducts\n                .filter((substitute) => substitute.purchasable)\n                .map((substitute) => substitute.id),\n            storeId,\n        )) || [];\n\n    return {\n        substituteIdentifier,\n        substitutes: products,\n    };\n};\n\nconst useSubstitutes = (\n    handleSubstituteChangeClick: (item: RecipeItemState, product: ApiProduct) => void,\n    allItems?: RecipeItemState[],\n) => {\n    const [expandedSubstituteIds, setExpandedSubstituteIds] = useState<string[]>([]);\n    const substituteSentForChange = useRef<{ substituteIdentifier: string; productId: string }>();\n\n    const onSubstituteToggle = useCallback((substituteIdentifier: string) => {\n        setExpandedSubstituteIds((prevIds) => {\n            const newIds = [...prevIds];\n            const index = newIds.findIndex((item) => item === substituteIdentifier);\n\n            if (index === -1) {\n                newIds.push(substituteIdentifier);\n            } else {\n                newIds.splice(index, 1);\n            }\n\n            return newIds;\n        });\n    }, []);\n\n    // since we dont have a substitute change endpoint like in cart, we need to wait for the resolve to return,\n    // this is not ideal, we then try to see if its in the returned items\n    useEffect(() => {\n        if (\n            !!substituteSentForChange.current &&\n            allItems?.find(\n                (item) =>\n                    item.id === substituteSentForChange.current?.productId &&\n                    item.substituteIdentifier ===\n                        substituteSentForChange.current.substituteIdentifier,\n            )\n        ) {\n            onSubstituteToggle(substituteSentForChange.current.substituteIdentifier);\n        }\n        substituteSentForChange.current = undefined;\n    }, [onSubstituteToggle, allItems]);\n\n    const onSubsituteChangeClick = useCallback(\n        (item: RecipeItemState, product: ApiProduct) => {\n            substituteSentForChange.current = {\n                substituteIdentifier: item.substituteIdentifier,\n                productId: product.identifier,\n            };\n            handleSubstituteChangeClick(item, product);\n        },\n        [handleSubstituteChangeClick],\n    );\n\n    const onSubstitutesLoaded = useCallback(\n        (substituteIdentifier: string, subsituteCount: number) => {\n            if (subsituteCount > 0) {\n                onSubstituteToggle(substituteIdentifier);\n            }\n        },\n        [onSubstituteToggle],\n    );\n\n    const [substitutes, setSubstitutes] = useState<\n        Record<string, { loadedCount: number; substituteProducts: ApiProduct[] }>\n    >({});\n    const currentProductionUnit = useAppSelector(storeSelectors.currentProductionUnit);\n\n    const substitutesDispatcher = useAsyncDispatcher(loadHybrisSubstitutes);\n    const {\n        execute: loadSubstitutes,\n        result: substitutesById,\n        isLoading: isLoadingSubstitutes,\n    } = substitutesDispatcher;\n    useRequestEffects(substitutesDispatcher, {}, ErrorGroup.Global);\n\n    useEffect(() => {\n        if (substitutesById) {\n            setSubstitutes((substituteMap) => ({\n                ...substituteMap,\n                [substitutesById.substituteIdentifier]: {\n                    substituteProducts: substitutesById.substitutes,\n                    loadedCount: substitutesById.substitutes.length,\n                },\n            }));\n            onSubstitutesLoaded(\n                substitutesById.substituteIdentifier,\n                substitutesById.substitutes.length,\n            );\n        }\n    }, [substitutesById, onSubstitutesLoaded]);\n\n    const onSubstituteTriggerClick = useCallback(\n        (substituteIdentifier: string) => {\n            if (substitutes[substituteIdentifier]?.substituteProducts.length) {\n                onSubstituteToggle(substituteIdentifier);\n            } else {\n                loadSubstitutes(currentProductionUnit, substituteIdentifier);\n            }\n        },\n        [onSubstituteToggle, loadSubstitutes, currentProductionUnit, substitutes],\n    );\n\n    return {\n        onSubsituteChangeClick,\n        onSubstituteTriggerClick,\n        substitutes,\n        isLoadingSubstitutes,\n        expandedSubstituteIds,\n    };\n};\n\nexport default useSubstitutes;\n","import type { PriceData } from '../common/models/priceData/priceData';\nimport type { EpiRecipeStartPageType } from '../episerver/components/pages/EpiRecipeStartPage/epiRecipeStartPageType';\n\ntype CategoryName = string;\ntype CategoryUrlSegment = string;\nexport type UrlSegmentToCategoryName = Record<CategoryUrlSegment, CategoryName>;\nexport type CategoryNameToUrlSegment = Record<CategoryName, CategoryUrlSegment>;\nexport type CategoryNameToContentReference = Record<CategoryName, string>;\nexport type CategoryNamesUnderLevel1 = Record<CategoryName, boolean>;\nexport type GetUrlForCategoriesSignature = (args: { categories: string[] }) => string;\nexport type RecipeQueryParam = 'page' | 'sort' | 'filter' | 'query';\nexport type SelectedEpiRecipeStartPageType = Pick<\n    EpiRecipeStartPageType,\n    | 'startpageModules'\n    | 'contentLink'\n    | 'contentType'\n    | 'name'\n    | 'startPublish'\n    | 'metaDescription'\n    | 'preamble'\n    | 'popularCategories'\n    | 'url'\n    | 'pageTypeNameForAnalytics'\n>;\nexport type RecipeCalculationType = 'waste' | 'price';\nexport type RecipePrioritizationType = 'organic' | 'sugar-free' | 'lactose-free' | 'gluten-free';\n\nexport const sectionTypes = {\n    recipe: 'recipe',\n    shared: 'shared',\n    common: 'common',\n};\n\n// export const sectionTypes = ['recipe', 'shared', 'common'] as const;\nexport type RecipeSectionType = keyof typeof sectionTypes;\n\nexport const productGroupTypes = ['singleProducts', 'sharedProducts', 'commonProducts'] as const;\nexport type RecipeProductGroupType = (typeof productGroupTypes)[number];\n\nexport enum ItemState {\n    Default = 'default',\n    Removed = 'removed',\n}\nexport interface RecipeProductException {\n    productId: string;\n    qty: number | null;\n    substituteId: string;\n    variantId?: string;\n}\n\nexport interface RecipeItemState {\n    id: string;\n    name: string;\n    image?: string;\n    manufacturer?: string;\n    substituteIdentifier: string;\n    substituteProductsAmount: number;\n    quantity: number | null;\n    purchasable: boolean;\n    priceData: PriceData;\n    totalPriceData: PriceData;\n    packageSizeInformation: string;\n    belongsToRecipes: SharedRecipe[];\n    selectedVarianceCode?: string;\n\n    // derived:\n    group: RecipeProductGroupType;\n    state: ItemState;\n}\n\nexport interface ResolveRecipesRequest {\n    recipes: { recipeId: string; portions: number }[];\n    products?: RecipeProductException[];\n    prioritization: RecipePrioritizationType | null;\n    calculation: RecipeCalculationType;\n}\n\nexport enum RecipeModalTab {\n    Overview = 1,\n    Products = 2,\n}\n\nexport const gastrofyAllergies = ['gluten', 'sugar', 'high-lactose', 'low-lactose', 'fodmap'];\n\nexport type GastrofyAllergiesType = (typeof gastrofyAllergies)[number];\n\nexport const gastrofyDiets = [\n    'paleo',\n    'vegan',\n    'vegetarian',\n    'pregnant',\n    'low-carb',\n    'inflammatory',\n    'anti-inflammatory',\n];\n\nexport type GastrofyDietsType = (typeof gastrofyDiets)[number];\n\nexport const gastrofyExcludes = [\n    'beef',\n    'pork',\n    'poultry',\n    'fish',\n    'shellfish',\n    'wild-meat',\n    'lamb',\n] as const;\n\nexport type GastrofyExcludeType = (typeof gastrofyExcludes)[number];\n\nexport interface RecipeDiscoveryRequest {\n    offset?: number;\n    limit: number;\n    storeId: string;\n    dataFields?: string[];\n    extraData?: string[];\n    tags?: string[];\n    exclude?: GastrofyExcludeType[];\n    allergies?: GastrofyAllergiesType[];\n    diets?: GastrofyDietsType[];\n    randomize?: boolean;\n    excludeRecipeIds?: string[];\n    externalRecipeIds?: string[];\n    mustHaveImage?: boolean;\n    isPublished?: boolean;\n    matchAllProducts?: boolean;\n    productIds?: string[];\n    orderBy?: string[];\n}\n\nexport interface RecipeResolveRequest {\n    storeId: string;\n    options: Options;\n    recipes: RecipeResolveData[];\n}\n\ninterface ProductException {\n    externalId: string;\n    substituteIdentifier: string;\n    amount: number;\n}\n\ninterface Options {\n    productExceptions?: ProductException[];\n    calculation: RecipeCalculationType;\n    prioritization?: RecipePrioritizationType;\n}\n\ninterface RecipeResolveData {\n    externalId: string;\n    portions: number;\n}\n\nexport interface SaveRecipeCommentRequest {\n    recipeExternalId: string;\n    authorName: string;\n    comment: string;\n}\n\nexport interface RecipeComment {\n    id: number;\n    recipeId: number;\n    name: string;\n    comment: string;\n    date: Date;\n    isAdmin: boolean;\n}\n\nexport interface ImageSticker {\n    imageUrl: string;\n    keyword: string;\n}\n\nexport interface RecipePart {\n    name?: string;\n    ingredients: Ingredient[];\n}\n\nexport interface Ingredient {\n    friendlyText: string;\n    formattedQuantity: string;\n    unit: string;\n    sequenceNumber: number;\n}\n\nexport interface CookingInstructions {\n    title: string;\n    instructions: string[];\n}\n\nexport interface RecipeCategory {\n    order: number;\n    categories: string[];\n}\n\nexport interface SharedRecipe {\n    code: string;\n    name: string;\n}\nexport interface RecipeProps {\n    id: number;\n    externalId: string;\n    name: string;\n    imageUrl: string;\n    stickerUrl?: string;\n    portions: number;\n    portionsUnit: string;\n    parts: RecipePart[];\n    averageRating: number;\n    ratingPercent: number;\n    ratingCount: number;\n    preamble: string;\n    climateImpactKg: number | null;\n    ovenTemperature: string;\n    cookingTime: string;\n    prepTime: string;\n    totalTime: string;\n    cookingInstructions: CookingInstructions[];\n    servingTips: string;\n    tips: string;\n    numberOfIngredients: number;\n    recipeCreator?: string;\n    categories: RecipeCategory[];\n    comments: RecipeComment[];\n    isFoodBox: boolean;\n}\n","import type { ApiCategoriesUrlOrder } from '../../models/recipe/recipeModel';\nimport type { RecipeCategoryFacet } from '../search/models/models';\nimport type {\n    CategoryNamesUnderLevel1,\n    CategoryNameToUrlSegment,\n    GetUrlForCategoriesSignature,\n} from './models';\n\n/**\n *\n * @param currStringArray current state of array\n * @param newString to be added or removed from currStringArray\n * @returns new array with or without newString\n */\nexport const createNewArrayByTogglingString = (currStringArray: string[], newString: string) => {\n    const shouldRemoveString = currStringArray.includes(newString);\n\n    if (shouldRemoveString) {\n        return currStringArray.filter((name) => name !== newString);\n    }\n\n    return [...currStringArray, newString];\n};\n\n/**\n * @returns a function that creates a path string where the categories are ordered correctly\n */\nexport const createGetUrlForCategories =\n    (\n        categoryNameToUrlSegment: CategoryNameToUrlSegment,\n        categoriesUrlOrder: ApiCategoriesUrlOrder,\n        recipeRootUrl: string,\n    ): GetUrlForCategoriesSignature =>\n    ({ categories }: { categories: string[] }) => {\n        const sortByCategoryUrlOrder = (a: string, b: string) =>\n            categoriesUrlOrder[a.toLowerCase()] - categoriesUrlOrder[b.toLowerCase()];\n\n        const mapCategoryNameToUrlSegment = (categoryName: string) =>\n            categoryName ? categoryNameToUrlSegment[categoryName.toLowerCase()] : null;\n\n        const removedPotentialLastSlashFromRoot =\n            recipeRootUrl.slice(-1) === '/'\n                ? recipeRootUrl.slice(0, recipeRootUrl.length - 1)\n                : recipeRootUrl;\n\n        const hasFilterQuery = categories.length > 2;\n\n        const builtPath = categories\n            .slice()\n            .sort(sortByCategoryUrlOrder)\n            .map(mapCategoryNameToUrlSegment)\n            .filter(Boolean)\n            .reduce((acc, currSegment, index) => {\n                if (index < 2) {\n                    return `${acc}/${currSegment}`;\n                }\n\n                if (index === 2) {\n                    return `${acc}?filter=${currSegment}`;\n                }\n\n                return `${acc},${currSegment}`;\n            }, removedPotentialLastSlashFromRoot);\n\n        return hasFilterQuery ? builtPath : `${builtPath}/`;\n    };\n\nexport const getCategoriesWhileRemovingCategoryFacetChildren = ({\n    currentCategories,\n    category,\n}: {\n    currentCategories: string[];\n    category: RecipeCategoryFacet;\n}) => {\n    if (Array.isArray(category.categories)) {\n        const childrenNames = category.categories.map((childCategory) =>\n            childCategory.item.toLowerCase(),\n        );\n\n        const categoriesWithoutChildren = currentCategories.filter(\n            (currCategory) => !childrenNames.includes(currCategory),\n        );\n\n        return createNewArrayByTogglingString(\n            categoriesWithoutChildren,\n            category.item.toLowerCase(),\n        );\n    }\n\n    return createNewArrayByTogglingString(currentCategories, category.item.toLowerCase());\n};\n\nexport const getCategoriesWhileRemovingCategoryFacetsParent = ({\n    currentCategories,\n    category,\n    parentCategory,\n}: {\n    currentCategories: string[];\n    category: RecipeCategoryFacet;\n    parentCategory: RecipeCategoryFacet;\n}) => {\n    const lowerCaseParentName = parentCategory.item.toLowerCase();\n\n    const categoriesWithoutParent = currentCategories.filter(\n        (categoryName) => categoryName !== lowerCaseParentName,\n    );\n\n    return createNewArrayByTogglingString(categoriesWithoutParent, category.item.toLowerCase());\n};\n\nexport const getAllCategoryNamesFromLevel2AndDown = (\n    categories: RecipeCategoryFacet[] | null,\n    collectedNames: string[] = [],\n    rootCall: boolean = true,\n): string[] => {\n    if (!categories) {\n        return collectedNames;\n    }\n\n    return categories.reduce((acc, facet) => {\n        const childCategories = getAllCategoryNamesFromLevel2AndDown(\n            facet.categories,\n            collectedNames,\n            false,\n        );\n\n        if (rootCall) {\n            return [...acc, ...childCategories];\n        }\n\n        return [...acc, ...childCategories, facet.item];\n    }, collectedNames);\n};\n\n/**\n * Removes categories on level 1\n * @returns the categories we can show\n */\nexport const getCategoryNamesUnderLevel1 = (\n    ssrCategoriesUrlOrder: ApiCategoriesUrlOrder,\n): CategoryNamesUnderLevel1 => {\n    const obj = ssrCategoriesUrlOrder ?? {};\n    return Object.entries(obj).reduce((acc, [key, val]) => {\n        if (val % 1000 !== 0) {\n            return {\n                ...acc,\n                [key]: true,\n            };\n        }\n\n        return acc;\n    }, {});\n};\n\nexport const buildRecipeRedirectUrl = (externalId: string) => `/redirect/recipe/${externalId}`;\n"],"names":["recipeProduct","recipeProductItem","product","recipeProductSubstitutes","isSubstituteActive","buyable","children","handleSubstituteChange","additionalClassNames","analyticsOptions","productSubstitutesBreakpoints","isConstrained","priceType","productPromotion","slotPrice","className","totalPrice","totalPriceData","align","showExcludingTaxInfo","ExcludeTax","getPriceTypeText","slotSplash","promotion","isNicotineProduct","details","isPharmaceutical","pharmaceuticalData","name","packageSizeInformation","variantName","selectedVarianceCode","variant","variants","find","_variant","id","getVariantName","image","manufacturer","style","position","overflow","substitutes","handleProductSubstitution","recipeModalProductSubstitutesBreakpoints","getUniqueBreakpointsFor","AREA_RECIPE_MODAL","ProductList","props","calculateAdditionValue","calculateSubstractValue","incrementBy","minValue","maxValue","portions","marginLeft","ChipIconButton","icon","label","theme","size","onClick","newValue","setPortions","totalProducts","externalId","handleBuy","handleLinkClick","isFoodBox","undefined","toEcommercePriceWithCurrency","Button","asChild","href","toString","recipeName","imageUrl","rating","votes","time","pricePortion","close","transformedImageUrl","backgroundImage","RatingStars","color","Icon","isExpanded","setIsExpanded","useState","inputSelected","setInputSelected","description","value","handleInputSelect","selectedInput","calculationType","recipeProritization","handleCalculationTypeChange","width","height","RadioGroup","Root","onValueChange","defaultValue","Item","fullWidth","RecipeModalSection","sectionItems","allItems","filter","item","section","substituteIdentifiers","includes","substituteIdentifier","RecipeModalProductsList","list","title","type","getSectionTitle","renderCartItem","map","cart","sections","items","getPrice","IncludeTax","recipe","readonly","cookingInstructions","useMemo","recipePart","part","ingredients","ingredientLine","formattedQuantity","unit","friendlyText","preamble","RawHtml","html","yieldValue","i","index","instructions","length","el","e","RecipeModalBodyWithData","recipeData","modalTabToDisplay","handlePortionChange","defaultPortions","avgRating","display","totalTime","TabSwitcher","component","wrapperClasses","containerClasses","panelClasses","listClasses","itemClasses","renderNextToTabs","p","initialActiveId","isLoading","purchasable","reduce","curr","next","quantity","OverlayLoader","recipeId","currentProductionUnit","storeSelectors","getRecipeDispatcher","useAsyncDispatcher","recipeFlow","getRecipeById","initialLoadingState","keepPreviousResult","currentPriceType","useCurrentPriceType","tabToDisplay","execute","getRecipe","result","getRecipeResult","error","useEffect","useGroupError","Global","trackModalPopup","trackBuyRecipe","trackCalculationChange","trackPortionChange","trackLinkClick","trackSubstituteProduct","trackAddToCart","modalPopupSent","useRef","useCallback","current","tracking","ecommerce","recipes","modalPopup","Products","products","storeId","listOptions","modifyCartItems","productId","previousQuantity","newQuantity","variantId","buyRecipe","calculationChange","portionChange","linkClick","substituteProduct","useBuyableRecipeModalTracking","updateItemQuantity","updateSubstituteProduct","updatePortions","updateCalculation","removeItem","calculateCart","recipeCart","recipeCartProducts","getProductExceptions","isLoadingRecipeCart","useRecipeCart","onSubsituteChangeClick","onSubstituteTriggerClick","expandedSubstituteIds","isLoadingSubstitutes","useSubstitute","identifier","dispatch","calculation","prioritization","buyRecipeDispatcher","request","cartThunks","buyMultipleRecipes","buyRecipeLoading","buyRecipeResult","useRequestEffects","onSuccess","itemsToTrack","analyticsListName","listPosition","recipe_list_id","code","join","recipe_list_name","recipe_origin","Modal","recipePortions","portionQuantity","productExceptions","x","group","qty","substituteId","RecipeProductListingItem","substituteProducts","PurchasableItemBody","sectionType","hasActiveSubstitutes","handleQuantityChange","handleSubsituteTriggerClick","MissingItemBody","recipeSectionType","handleRemoveItem","MissingItemInfo","text","RecipeItemActionsContainer","RecipeItemActions","belongsToRecipes","SharedBetweenRecipesTooltip","substituteProductsAmount","SubstituteTrigger","handleSubsituteTrigger","isActive","setQuantity","getRecipeSection","mapItem","isRemoved","priceData","rowTotalPriceData","state","Removed","Default","recipeCartQueue","SyncronQueue","initialLoading","cartState","setCartState","cartChangesState","setCartChangesState","removedItems","newProductId","prevChanges","draft","productChanges","recipeSection","weeklyMenu","handleIngredient","Object","values","forEach","pc","recipeToChange","cr","prioritizationType","reCalculateCart","push","resolve","resolvedRecipes","resolveError","run","resolveRecipes","debouncedResolve","cp","isDirty","recipeList","removedSubstituteIds","removedSubsituteIdentifiers","singleProducts","sharedProducts","goodToHaveProducts","recipeSectionsMap","prev","sectionId","sectionName","_recipe","final","productIdentifiers","keys","sharedProductsBelongingToRecipe","sharedProduct","joinedRecipe","sharedSubstituteIdentifiers","sharedRecipeProductIds","goodToHaveProductIds","sharedRecipeSubstituteIds","goodToHaveSubstituteIds","recipeSectionList","mapSections","hybrisRecipeList","inclTaxPrice","recipesTotalPrice","exclTaxPrice","valueWithoutTax","createCartState","productFlow","getProductsByIds","initialResultState","recipeCartChanges","changedSubstituteIds","loadHybrisSubstitutes","recipeProducts","getRecipeSubstitutes","substitute","handleSubstituteChangeClick","setExpandedSubstituteIds","substituteSentForChange","onSubstituteToggle","prevIds","newIds","findIndex","splice","onSubstitutesLoaded","subsituteCount","setSubstitutes","substitutesDispatcher","loadSubstitutes","substitutesById","substituteMap","loadedCount","ItemState","RecipeModalTab","createNewArrayByTogglingString","currStringArray","newString","createGetUrlForCategories","categoryNameToUrlSegment","categoriesUrlOrder","recipeRootUrl","categories","removedPotentialLastSlashFromRoot","slice","hasFilterQuery","builtPath","sort","a","b","toLowerCase","categoryName","Boolean","acc","currSegment","getCategoriesWhileRemovingCategoryFacetChildren","currentCategories","category","Array","isArray","childrenNames","childCategory","categoriesWithoutChildren","currCategory","getCategoriesWhileRemovingCategoryFacetsParent","parentCategory","lowerCaseParentName","categoriesWithoutParent","getAllCategoryNamesFromLevel2AndDown","collectedNames","rootCall","facet","childCategories","getCategoryNamesUnderLevel1","ssrCategoriesUrlOrder","obj","entries","key","val","buildRecipeRedirectUrl"],"sourceRoot":""}