\n `,\n }}\n />\n );\n};\n","import{b as e,_ as o}from\"./_rollupPluginBabelHelpers-c70560be.js\";import*as n from\"react\";import{n as r}from\"./utils-c286d19e.js\";import{styled as t}from\"./styled.js\";import{theme as d}from\"./theme.js\";import\"styled-components\";var i,l,a,s=t.span(i||(i=e([\"\\n position: absolute;\\n top: \",\";\\n left: 0;\\n height: 16px;\\n width: 16px;\\n border-radius: 100%;\\n background-color: \",\";\\n border: 1px solid\\n \",\";\\n box-sizing: border-box;\\n\\n &:after {\\n content: '';\\n position: absolute;\\n display: none;\\n top: 2px;\\n left: 2px;\\n width: 10px;\\n height: 10px;\\n border-radius: 100%;\\n background-color: \",\";\\n }\\n\"])),(function(e){var o=e.position;return o>0?o+\"px\":0}),(function(e){return e.disabled?e.theme.color.background.disabled:e.theme.color.background.primary}),(function(e){return e.disabled?e.theme.color.border.divider:e.isHovered?e.theme.color.border.selected:e.theme.color.border.default}),(function(e){return e.disabled?e.theme.color.background.tertiary:e.theme.color.background.inverse})),c=t.label(l||(l=e([\"\\n display: block;\\n position: relative;\\n padding-left: 32px;\\n cursor: \",\";\\n color: \",\";\\n user-select: none;\\n font-size: 14px;\\n font-weight: \",\";\\n\\n &:hover input:not(:disabled):not(:checked) ~ \",\" {\\n border: 1px solid \",\";\\n }\\n\"])),(function(e){return e.disabled?\"inherit\":\"pointer\"}),(function(e){return e.disabled?d.color.text.disabled:d.color.text.primary}),(function(e){var o=e.bold;return void 0!==o&&o?800:300}),s,d.color.border.selected),b=t.input(a||(a=e([\"\\n position: absolute;\\n opacity: 0;\\n top: 0;\\n left: 0;\\n\\n &:checked {\\n ~ \",\" {\\n border-color: \",\";\\n\\n &:after {\\n display: block;\\n }\\n }\\n }\\n\"])),s,(function(e){return e.disabled?d.color.border.divider:d.color.border.selected})),p=function(e){var t=e.children,d=e.disabled,i=e.checked,l=e.isHovered,a=e.onChange,p=void 0===a?r:a,u=e.position,m=void 0===u?0:u,h=e.className,f=e.bold,x=e.name,v=e.labelDataTestId;return n.createElement(c,o({disabled:d,className:h,bold:f},v&&{\"data-testid\":v}),t,n.createElement(b,{disabled:d,type:\"radio\",checked:i,onChange:p,bold:f,name:x}),n.createElement(s,{disabled:d,position:m,isHovered:l}))};export{p as RadioButton};\n//# sourceMappingURL=RadioButton.js.map\n","import { defineMessages } from 'react-intl';\n\nexport const messages = defineMessages({\n chooseStore: {\n id: 'pd.clickandcollect.choose.store',\n defaultMessage: 'Vyberte pobočku',\n },\n pickHere: {\n id: 'pd.clickandcollect.pick.here',\n defaultMessage: 'Vyzvednout zde',\n },\n availableFrom: {\n id: 'pd.clickandcollect.available.from',\n defaultMessage: '{date} od {time}',\n },\n today: {\n id: 'pd.clickandcollect.today',\n defaultMessage: 'dnes',\n },\n tomorrow: {\n id: 'pd.clickandcollect.tomorrow',\n defaultMessage: 'zítra',\n },\n lessThan5: {\n id: 'pd.clickandcollect.lessThan5',\n defaultMessage: '{count} ks',\n },\n moreThan5: {\n id: 'pd.clickandcollect.moreThan5',\n defaultMessage: 'Více než 5 ks',\n },\n moreThan20: {\n id: 'pd.clickandcollect.moreThan20',\n defaultMessage: 'Více než 20 ks',\n },\n pickUpGiftInformation: {\n id: 'pd.clickandcollect.pickUp.gift.information',\n defaultMessage:\n 'Na objednávky prostřednictvím služby Vyzvednout ihned se nevztahují akce dárků zdarma.',\n },\n overloaded: {\n id: 'pd.clickandcollect.overloaded',\n defaultMessage: 'Pobočka je aktuálně pro vychystání zboží přezížena',\n },\n});\n","import { css } from 'styled-components';\n\nimport { styled, theme } from '@notino/react-styleguide';\n\nexport const StoreTitle = styled.p<{ isOverloaded: boolean }>`\n ${theme.typography.labelRegular400}\n margin-bottom: 0.25rem;\n\n ${({ isOverloaded }) =>\n isOverloaded &&\n css`\n color: '#aaa';\n `}\n`;\n\nexport const StoreDescription = styled.span`\n font-weight: 300;\n ${theme.typography.labelRegular400}\n color:${theme.color.text.tertiary};\n padding-bottom: 0.25rem;\n`;\n\nexport const StoreStockAvailabilityWrapper = styled.div`\n color: ${theme.color.text.positive};\n ${theme.typography.labelRegular400}\n`;\n\nexport const TextOverloaded = styled.p`\n color: rgb(204, 37, 37);\n font-weight: 500;\n`;\n","/**\n * @return [tomorrow, date after tomorrow]\n */\nconst getNextTwoDays = (): [Date, Date] => {\n const now = new Date();\n const tomorrowTime = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate() + 1,\n 0,\n 0,\n 0\n );\n const dayAfterTomorrowTime = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate() + 2,\n 0,\n 0,\n 0\n );\n return [tomorrowTime, dayAfterTomorrowTime];\n};\n\nexport const isTomorrow = (date: Date) => {\n const timeToCompare = new Date(date).getTime();\n const [tomorrow, dayAfterTomorrow] = getNextTwoDays();\n\n return (\n timeToCompare >= tomorrow.getTime() &&\n timeToCompare < dayAfterTomorrow.getTime()\n );\n};\n\nexport const isToday = (date: Date) => {\n const timeToCompare = new Date(date).getTime();\n const startOfToday = new Date();\n startOfToday.setHours(0, 0, 0, 0);\n const [tomorrow] = getNextTwoDays();\n\n return (\n timeToCompare >= startOfToday.getTime() &&\n timeToCompare < tomorrow.getTime()\n );\n};\n","import * as React from 'react';\n\nimport { IStore } from '../../model';\n\nimport { StoreStockAvailabilityWrapper } from './styled';\nimport { usePickUpTime } from './usePickupTime';\nimport { useStockCount } from './useStockCount';\n\nexport const StoreStockAvailability = ({\n stockCount,\n earliestPickup,\n}: IStore): JSX.Element => {\n const stockCountMessage = useStockCount(stockCount);\n const pickupTime = usePickUpTime(earliestPickup);\n return (\n
\n {stockCountMessage} |{' '}\n {pickupTime}\n \n );\n};\n","import { useIntl } from 'react-intl';\n\nimport { StockAvailability } from '@notino/shared/definitions/types';\n\nimport { messages } from '../../messages';\n\nexport const useStockCount = (stockCount: string): string => {\n const { formatMessage } = useIntl();\n switch (stockCount) {\n case StockAvailability.Last1:\n return formatMessage(messages.lessThan5, { count: 1 });\n case StockAvailability.Last2:\n return formatMessage(messages.lessThan5, { count: 2 });\n case StockAvailability.Last3:\n return formatMessage(messages.lessThan5, { count: 3 });\n case StockAvailability.Last4:\n return formatMessage(messages.lessThan5, { count: 4 });\n case StockAvailability.Last5:\n return formatMessage(messages.lessThan5, { count: 5 });\n case StockAvailability.MoreThan20:\n return formatMessage(messages.moreThan20, {});\n case StockAvailability.MoreThan5:\n return formatMessage(messages.moreThan5, {});\n }\n};\n","import { useIntl } from 'react-intl';\n\nimport { isToday, isTomorrow } from '../../../../utils/dateUtils';\nimport { messages } from '../../messages';\n\nimport { getEarliestPickupDate } from './utils';\n\nexport const usePickUpTime = (earliestPickup: string): string => {\n const { formatTime, formatDate, formatMessage } = useIntl();\n\n const earliestPickupDate = getEarliestPickupDate(new Date(earliestPickup));\n\n const time = formatTime(earliestPickupDate, {\n hour: 'numeric',\n minute: 'numeric',\n });\n\n let dateName: string;\n if (isToday(earliestPickupDate)) {\n dateName = formatMessage(messages.today);\n } else if (isTomorrow(earliestPickupDate)) {\n dateName = formatMessage(messages.tomorrow);\n } else {\n dateName = formatDate(earliestPickupDate, {\n weekday: 'long',\n });\n }\n\n return formatMessage(messages.availableFrom, {\n date: dateName,\n time,\n });\n};\n","/**\n * in case that API returns time in the past, change it to now\n * @param earliestPickup\n */\nexport const getEarliestPickupDate = (earliestPickup: Date) => {\n const now = new Date();\n return earliestPickup > now ? earliestPickup : now;\n};\n","import * as React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { messages } from '../../messages';\nimport { IStore } from '../../model';\n\nimport { StoreStockAvailability } from './StoreStockAvailability';\nimport { StoreDescription, StoreTitle, TextOverloaded } from './styled';\n\ninterface IStoreProps {\n data: IStore;\n}\n\nexport const Store: React.FC
= ({ data }) => {\n return (\n <>\n {data.name}\n \n {data.isOverloaded ? (\n \n \n \n ) : (\n \n )}\n >\n );\n};\n","import styled from 'styled-components';\n\nimport {\n ActionButtonWithConfirmation,\n breakpoints,\n theme,\n} from '@notino/react-styleguide';\n\nexport const StoreWrapper = styled.div`\n padding: 1.25rem 0;\n &:not(:last-child) {\n border-bottom: solid 1px ${theme.color.border.disabled};\n }\n &:first-child {\n padding-top: 0;\n }\n`;\nexport const ContentWrapper = styled.div<{\n shouldShowGiftInformationBox: boolean;\n}>`\n overflow-y: auto;\n padding: 1.5rem;\n margin-bottom: ${({ shouldShowGiftInformationBox }) =>\n shouldShowGiftInformationBox ? '8rem' : '4rem'};\n\n @media (min-width: ${breakpoints.md}) {\n max-height: 50vh;\n margin-bottom: 0;\n padding-bottom: 0;\n }\n`;\n\nexport const CenterWrapper = styled.div`\n padding-top: 2.8125rem;\n display: flex;\n justify-content: center;\n`;\n\nexport const ActionButtonWithConfirmationWrapper = styled.div`\n padding: 1rem;\n\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n\n background-color: white;\n\n box-shadow: 0px -2px 4px rgba(0, 0, 0, 0.1);\n\n @media (min-width: ${breakpoints.md}) {\n position: relative;\n padding: 1.5rem;\n }\n`;\n\nexport const StyledActionButtonWithConfirmation = styled(\n ActionButtonWithConfirmation\n)`\n @media (min-width: ${breakpoints.sm}) {\n margin: auto;\n display: block;\n }\n`;\n\nexport const GiftInformationBox = styled.div`\n padding: 0.75rem;\n background-color: ${theme.color.background.secondary};\n\n display: flex;\n gap: 0.5rem;\n\n margin-bottom: 1rem;\n\n svg {\n flex-shrink: 0;\n }\n`;\n","export const redirectToClickAndCollectCart = (\n cartId: string,\n isNewEndpoint: boolean\n) => {\n window.location.href = isNewEndpoint\n ? `/reservation/${cartId}`\n : `/reservation-1/${cartId}`;\n};\n","import * as React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { snakeCase } from 'lodash';\n\nimport {\n ButtonModel,\n IconSolidInfo,\n RadioButton,\n Spinner,\n Text,\n} from '@notino/react-styleguide';\nimport {\n GetCatalogProductViewQuery,\n StockAvailability,\n} from '@notino/shared/definitions/types';\nimport { CartType } from '@notino/web-tracking';\n\nimport { useModifaceVariants } from '@containers/ProductDetailContainer/ProductDetail/hooks/useModifaceVariants';\nimport { usePriceLogic } from '@containers/ProductDetailContainer/ProductDetail/hooks/usePriceLogic';\nimport {\n MIN_PRICE_PROMO_LABEL,\n RRP_PRICE_PROMO_LABEL,\n} from '@containers/ProductDetailContainer/ProductDetail/hooks/usePriceLogic/tracking';\nimport { useProductDetailContext } from '@containers/ProductDetailContainer/ProductDetail/ProductDetailContext';\nimport { useFeatureFlags } from '@context/featureFlags/FeatureFlagsProvider';\nimport { dispatchTrackingEvent } from '@context/tracking/utils';\nimport { ProductEventWither } from '@helpers/googleTagManager';\n\nimport { getRenderableDiscoBoxSampleId } from '../../DiscoveryBoxSelfChoice';\nimport { getGiftCampaigns } from '../../Gift';\n\nimport { Store } from './components/Store';\nimport { useTrackModalOrDrawerShow } from './hooks/useTrackModalShow';\nimport { messages } from './messages';\nimport {\n ContentWrapper,\n StoreWrapper,\n CenterWrapper,\n StyledActionButtonWithConfirmation,\n ActionButtonWithConfirmationWrapper,\n GiftInformationBox,\n} from './styled';\nimport { useClickAndCollect } from './useClickAndCollect';\n\ninterface IClickAndCollectContentProps {\n product: GetCatalogProductViewQuery['productDetailByCatalogMasterId'];\n selectedVariant: GetCatalogProductViewQuery['productDetailByCatalogMasterId']['variants'][number];\n}\n\nexport const ClickAndCollectContent = ({\n selectedVariant,\n product,\n}: IClickAndCollectContentProps) => {\n const [selectedStore, setSelectedStore] = React.useState('');\n const { rrpShown, minimalPriceShown } = usePriceLogic(selectedVariant);\n const flags = useFeatureFlags();\n\n const { giftCampaigns } = getGiftCampaigns({\n product,\n variant: selectedVariant,\n });\n\n const shouldShowGiftInformationBox = giftCampaigns?.length > 0;\n\n const {\n tryItFirstAvailable,\n engravingAvailable,\n product: { variants },\n } = useProductDetailContext();\n const modifaceVariants = useModifaceVariants(variants);\n\n const {\n stores,\n storesLoading,\n handleAddToClickAndCollect,\n addToClickAndCollectData: {\n loading: addToCnCLoading,\n error: addToCnCError,\n },\n } = useClickAndCollect(selectedVariant);\n\n useTrackModalOrDrawerShow();\n\n if (storesLoading) {\n return (\n \n \n \n );\n }\n\n const onRadioButtonClick = (storeId: string) => () => {\n setSelectedStore(storeId);\n };\n\n const handleSubmit = async () => {\n dispatchTrackingEvent({\n event: 'add_to_cart',\n product: ProductEventWither()\n .withProduct(product)\n .withVariant(selectedVariant)\n .withServices({\n modifaceVariants,\n tryItFirstAvailable,\n engravingAvailable,\n discoveryBoxAvailable: Boolean(\n getRenderableDiscoBoxSampleId(product, selectedVariant, flags)\n ),\n })\n .withAdditionalData({\n quantity: 1,\n cart_type: snakeCase(CartType.clickAndCollect),\n })\n .withAdditionalPromoLabels([\n rrpShown && RRP_PRICE_PROMO_LABEL,\n minimalPriceShown && MIN_PRICE_PROMO_LABEL,\n ])\n .build(),\n _clear: true,\n });\n\n await handleAddToClickAndCollect(selectedStore);\n };\n\n return (\n <>\n \n {stores?.collectStoresByCatalogId?.map((store) => {\n const outOfStock = store.stockCount === StockAvailability.OutOfStock;\n if (outOfStock) {\n return null;\n }\n\n return (\n \n \n \n \n \n );\n })}\n \n\n \n {shouldShowGiftInformationBox && (\n \n \n \n \n \n \n )}\n\n \n \n \n \n >\n );\n};\n","import * as React from 'react';\n\nimport { useMutation, useQuery } from '@apollo/client';\n\nimport {\n AddToClickAndCollectMutation,\n AddToClickAndCollectMutationVariables,\n GetCatalogProductViewQuery,\n GetStoresQuery,\n GetStoresQueryVariables,\n} from '@notino/shared/definitions/types';\n\nimport { useSettings } from '@containers/ProductDetailContainer/hooks/useSettings';\n\nimport addToClickAndCollectMutation from './mutations/addToClickAndCollect.graphql';\nimport getStoresQuery from './queries/stores.graphql';\nimport { redirectToClickAndCollectCart } from './utils';\n\nexport const useClickAndCollect = (\n variant: GetCatalogProductViewQuery['productDetailByCatalogMasterId']['variants'][number]\n) => {\n const { Settings: { isNewShoppingCartEndpointEnabled: isNewEndpoint } = {} } =\n useSettings();\n\n const { data: stores, loading: storesLoading } = useQuery<\n GetStoresQuery,\n GetStoresQueryVariables\n >(getStoresQuery, {\n variables: { catalogId: Number(variant.catalogId) },\n });\n\n const [addToClickAndCollectCart, addToClickAndCollectData] = useMutation<\n AddToClickAndCollectMutation,\n AddToClickAndCollectMutationVariables\n >(addToClickAndCollectMutation, {\n onCompleted: (response) => {\n redirectToClickAndCollectCart(\n response.addProductToClickAndCollect.cartId,\n isNewEndpoint\n );\n },\n });\n\n const handleAddToClickAndCollect = React.useCallback(\n async (warehouseCode: string) => {\n await addToClickAndCollectCart({\n variables: {\n productId: Number(variant.webId),\n warehouseCode: warehouseCode,\n },\n });\n },\n [addToClickAndCollectCart, variant.webId]\n );\n\n return React.useMemo(\n () => ({\n stores,\n storesLoading,\n handleAddToClickAndCollect,\n addToClickAndCollectData,\n }),\n [\n stores,\n storesLoading,\n handleAddToClickAndCollect,\n addToClickAndCollectData,\n ]\n );\n};\n","import * as React from 'react';\n\nimport { useTrackingContext } from '@context/tracking/TrackingContext';\nimport { dispatchTrackingEvent } from '@context/tracking/utils';\n\nexport const useTrackModalOrDrawerShow = () => {\n const { getTimeFromInit } = useTrackingContext();\n\n React.useEffect(() => {\n dispatchTrackingEvent({\n event: 'subpage_view',\n subpage: {\n name: 'click_and_collect_modal',\n interaction: 'automatic',\n timing: getTimeFromInit(),\n action: 'click_and_collect_opened',\n type: 'click_and_collect',\n },\n _clear: true,\n });\n }, [getTimeFromInit]);\n};\n","import { TrackingAttributes } from '@context/tracking/types';\nimport { dispatchTrackingEvent } from '@context/tracking/utils';\n\nexport const trackModalOrDrawerClose = ({\n timing,\n}: Omit) => {\n dispatchTrackingEvent({\n event: 'element_click',\n element: {\n name: 'click_and_collect',\n interaction: 'click',\n action: 'close_click_and_collect',\n timing,\n mode: 'off',\n type: 'product_detail',\n promo_labels: undefined,\n },\n _clear: true,\n });\n};\n\nexport const trackModalOrDrawerOpen = ({\n timing,\n}: Omit) => {\n dispatchTrackingEvent({\n event: 'element_click',\n element: {\n name: 'click_and_collect',\n interaction: 'click',\n action: 'open_click_and_collect',\n timing,\n mode: 'on',\n type: 'product_detail',\n promo_labels: undefined,\n },\n _clear: true,\n });\n};\n","import { defineMessages } from 'react-intl';\n\nexport const messages = defineMessages({\n pickupNow: {\n id: 'pd.clickandcollect.pickup.now',\n defaultMessage: 'Vyzvednout ihned',\n },\n});\n","import styled from 'styled-components';\n\nimport { breakpoints, Button, theme } from '@notino/react-styleguide';\n\nexport const PickUpButtonWrapper = styled.div`\n margin-top: 0.5rem;\n flex: 0 1 100%;\n @media (min-width: ${breakpoints.sm}) {\n margin-top: 0;\n flex: auto;\n }\n`;\n\nexport const PickUpButton = styled(Button)`\n width: 100%;\n height: 3.25rem;\n ${theme.typography.labelRegular}\n`;\n","import * as React from 'react';\nimport { FormattedMessage, useIntl } from 'react-intl';\n\nimport {\n ButtonModel,\n ModalContext,\n Text,\n useBreakpointValue,\n} from '@notino/react-styleguide';\nimport { GetCatalogProductViewQuery } from '@notino/shared/definitions/types';\n\nimport { useDrawer } from '@components/BottomSheet/DrawerProvider';\nimport { useTrackingContext } from '@context/tracking/TrackingContext';\n\nimport { ClickAndCollectContent } from './Content';\nimport { messages as modalMessages } from './Content/messages';\nimport {\n trackModalOrDrawerClose,\n trackModalOrDrawerOpen,\n} from './gtm/tracking';\nimport { messages } from './messages';\nimport { PickUpButton, PickUpButtonWrapper } from './styled';\n\ntype IClickAndCollectProps = {\n selectedVariant: GetCatalogProductViewQuery['productDetailByCatalogMasterId']['variants'][number];\n product: GetCatalogProductViewQuery['productDetailByCatalogMasterId'];\n onModalClosing: () => void;\n disabled?: boolean;\n};\n\nexport const ClickAndCollect: React.FC = ({\n selectedVariant,\n product,\n onModalClosing,\n disabled = false,\n}) => {\n const { formatMessage } = useIntl();\n const { getTimeFromInit } = useTrackingContext();\n const isDesktop = useBreakpointValue({ md: true });\n const { toggleModal, hideModal } = ModalContext.useModalContext();\n const { toggleDrawer } = useDrawer();\n const header = formatMessage(modalMessages.chooseStore);\n\n const onOpenClickAndCollectModalOrDrawer = React.useCallback(() => {\n trackModalOrDrawerOpen({ timing: getTimeFromInit() });\n\n if (!isDesktop) {\n toggleDrawer(\n ,\n {\n header,\n onDismiss: () =>\n trackModalOrDrawerClose({ timing: getTimeFromInit() }),\n }\n );\n return;\n }\n\n const handleCloseTracking = () => {\n hideModal();\n trackModalOrDrawerClose({ timing: getTimeFromInit() });\n onModalClosing();\n };\n\n toggleModal(\n ,\n {\n header: (\n \n {header}\n \n ),\n center: true,\n withFocusTrap: true,\n onClose: handleCloseTracking,\n noBorders: true,\n onlyTopBorder: true,\n modalDataTestId: 'clickAndCollectModal',\n }\n );\n }, [\n getTimeFromInit,\n isDesktop,\n toggleModal,\n selectedVariant,\n product,\n header,\n toggleDrawer,\n hideModal,\n onModalClosing,\n ]);\n\n return (\n \n \n \n \n \n );\n};\n","import { defineMessages } from 'react-intl';\n\nexport const messages = defineMessages({\n engravingMaxOrderQtyHeader: {\n id: 'engraving.max.order.quantity.header',\n defaultMessage: 'Lze objednat pouze {quantity} {unit}',\n },\n engravingMaxOrderQtyDesc: {\n id: 'engraving.max.order.quantity.description',\n defaultMessage:\n 'Aby se dostalo na co nejvíce zákazníku, z výrobních důvodů zatím neumožňujeme gravírování více kusů na jednu objednávku.',\n },\n addToCartQuantity: {\n id: 'pd.addToCart.quantity',\n defaultMessage: 'Množství',\n },\n});\n","import{a as e,_ as n}from\"./_rollupPluginBabelHelpers-c70560be.js\";import*as t from\"react\";import{T as o}from\"./index-f84fc463.js\";import\"./TextAlign.js\";import\"./index-2f916342.js\";import\"./utils-c286d19e.js\";import\"./StyledDropdown.js\";import\"./breakpoints.js\";import\"./theme.js\";import\"./styled.js\";import\"styled-components\";import\"./IconRegularCheckmark.js\";import\"./createSvgIcon-2fb674e7.js\";import\"./index-7252bb8c.js\";import\"./getSemanticColor.js\";import\"./HorizontalChevron.js\";import\"./IconRegularChevronDown.js\";import\"./IconRegularChevronUp.js\";var i=[\"options\",\"unit\",\"unitMulti\",\"handleOptionSelect\",\"currentOption\",\"disableSelectWhenSingleOption\",\"condensed\"],r=function(r){var l=r.options,p=r.unit,s=r.unitMulti,c=r.handleOptionSelect,u=void 0===c?function(){return null}:c,a=r.currentOption,m=void 0===a?0:a,d=r.disableSelectWhenSingleOption,j=r.condensed,f=e(r,i),b=t.useMemo((function(){var e=p?\" \"+p:\"\",n=p&&s?\" \"+s:e;return l.map((function(t){return{id:t,label:1===t?\"\"+t+e:\"\"+t+n}}))}),[l,p,s]),S=t.useCallback((function(e){var n=e.id;u(Number(n))}),[u]),h=t.useMemo((function(){return m&&b.find((function(e){return e.id===m}))||b[0]}),[m,b]);return t.createElement(o,n({},f,{options:b,disableSelectWhenSingleOption:d,currentOption:h,handleOptionSelect:S,condensed:j}))};export{r as QuantitySelector};\n//# sourceMappingURL=QuantitySelector.js.map\n","import styled, { css } from 'styled-components';\n\nimport { breakpoints, QuantitySelector } from '@notino/react-styleguide';\n\nconst getGridTemplateAreas = (isClickAndCollect: boolean) => {\n if (isClickAndCollect) {\n return css`\n grid-template-areas:\n 'addToCart'\n 'clickAndCollect';\n `;\n }\n return css`\n grid-template-areas: 'addToCart';\n `;\n};\n\nexport const BuyButtons = styled.div`\n display: grid;\n align-items: center;\n\n ${({ isClickAndCollect }) =>\n css`\n width: 100%;\n grid-gap: 0.5rem;\n padding: 1rem 0 1.5rem;\n ${getGridTemplateAreas(isClickAndCollect)}\n `}\n`;\n\nexport const ButtonWrapper = styled.div`\n & > button,\n form button {\n padding: 0 0.5625rem !important;\n height: 2.75rem;\n min-width: 7.5rem;\n text-transform: none !important;\n font-weight: normal !important;\n }\n flex: 1;\n min-width: 7.5rem;\n\n & > button,\n form button {\n height: 3.25rem;\n }\n`;\n\nexport const Label = styled.label`\n display: none;\n`;\n\nexport const DropdownButtonSeparator = styled.div`\n padding-right: 0.5rem;\n`;\n\nexport const QuantityWrapper = styled.div`\n width: 5.25rem;\n font-size: 0.875rem;\n & > div > div {\n min-height: 2.75rem;\n }\n`;\n\ninterface IWrapperProps {\n isClickAndCollect?: boolean;\n canBuy?: boolean;\n}\n\nexport const AddToCartWrapper = styled.div`\n grid-area: addToCart;\n\n display: flex;\n align-items: center;\n`;\n\nexport const ClickAndCollectWrapper = styled.div`\n grid-area: clickAndCollect;\n\n ${({ isClickAndCollect }) =>\n isClickAndCollect &&\n css`\n margin-top: -0.5rem;\n `}\n\n @media (min-width: ${breakpoints.sm}) {\n margin-top: 0;\n }\n`;\n\nexport const StyledQuantitySelector = styled(QuantitySelector)`\n [role='combobox'] {\n height: 3.25rem;\n }\n`;\n","import { snakeCase } from 'lodash';\n\nimport { GetCatalogProductViewQuery } from '@notino/shared/definitions/types';\nimport { CartType } from '@notino/web-tracking';\n\nimport { dispatchTrackingEvent } from '@context/tracking/utils';\nimport { ProductEventWither } from '@helpers/googleTagManager';\n\nexport const ENGRAVING_CODE = 'ENGXXXU_SENG01';\n\nexport const engravingPrefix = (text: string) => {\n return `Engraving - ${text}`;\n};\n\nexport const trackEngravingAddToCart = (\n productInfo: GetCatalogProductViewQuery['productDetailByCatalogMasterId'],\n variant: GetCatalogProductViewQuery['productDetailByCatalogMasterId']['variants'][number],\n quantity,\n additionalPromoLabels: string[]\n) => {\n dispatchTrackingEvent({\n event: 'add_to_cart',\n product: ProductEventWither()\n .withProduct(productInfo)\n .withVariant(variant)\n .withAdditionalData({\n // use engraving product code instead of product code\n // more info in comments: https://notino.tpondemand.com/entity/132907-nushopweb-pd-trackovani-pridavani-gravirovani-do\n product_code: ENGRAVING_CODE,\n price: variant.features.engraving.config.price,\n brand_name: engravingPrefix(productInfo.brand.name),\n ...(variant.name && {\n name: engravingPrefix(variant.name),\n }),\n cart_type: snakeCase(CartType.cart),\n quantity,\n })\n .withAdditionalPromoLabels(additionalPromoLabels)\n .build(),\n _clear: true,\n });\n};\n","export const prepareOptions = (maxQuantity: number): number[] => {\n const options = [];\n\n for (let option = 1; option <= maxQuantity; option++) {\n options.push(option);\n }\n\n return options;\n};\n","import * as React from 'react';\nimport { FormattedMessage, useIntl } from 'react-intl';\n\nimport { snakeCase } from 'lodash';\n\nimport { ModalModel, TextAlign, ModalContext } from '@notino/react-styleguide';\nimport {\n AvailabilityState,\n CartServiceType,\n GetCatalogProductViewQuery,\n} from '@notino/shared/definitions/types';\nimport { AdditionalServicesAvailability, CartType } from '@notino/web-tracking';\nimport { Ga4Events } from '@notino/web-tracking/dist/types/package/ga4/events';\n\nimport ErrorBoundary from '@components/ErrorBoundary';\nimport { useTrackingDisplayType } from '@containers/ProductDetailContainer/utils';\nimport { useFeatureFlags } from '@context/featureFlags/FeatureFlagsProvider';\nimport { useTrackingContext } from '@context/tracking/TrackingContext';\nimport { dispatchTrackingEvent } from '@context/tracking/utils';\nimport { ProductEventWither } from '@helpers/googleTagManager';\nimport { useAddToCardCloudTracking } from '@hooks/useAddToCardCloudTracking';\nimport { AddToCartButton } from '@sharedComponents/AddToCartButton/AddToCartButton';\n\nimport { ICurrency } from '../../../../App/model';\nimport { usePriceLogic } from '../../hooks/usePriceLogic';\nimport {\n MIN_PRICE_PROMO_LABEL,\n RRP_PRICE_PROMO_LABEL,\n} from '../../hooks/usePriceLogic/tracking';\nimport { IModifaceEffectVariants } from '../../ModiFaceModal/model';\nimport { trackPageReload } from '../../tracking';\nimport { ClickAndCollect } from '../ClickAndCollect';\nimport { useEngravingTryItFirstContext } from '../context/EngravingTryItFirst';\nimport { getRenderableDiscoBoxSampleId } from '../DiscoveryBoxSelfChoice';\nimport { useSkinAnalyzerVisibility } from '../SkinAnalyser/hooks/useAnalyzerVisibility';\n\nimport { messages } from './addToCartMessages';\nimport {\n ButtonWrapper,\n BuyButtons,\n Label,\n DropdownButtonSeparator,\n QuantityWrapper,\n AddToCartWrapper,\n ClickAndCollectWrapper,\n StyledQuantitySelector,\n} from './styled';\nimport { trackEngravingAddToCart } from './tracking';\nimport { prepareOptions } from './utils/prepareOptions';\n\ninterface IAddToCartProps {\n product: GetCatalogProductViewQuery['productDetailByCatalogMasterId'];\n variant: GetCatalogProductViewQuery['productDetailByCatalogMasterId']['variants'][number];\n orderUnit: string;\n productCode: string;\n currency: ICurrency;\n onProductAdded: () => void;\n modifaceVariants: IModifaceEffectVariants;\n engravingAvailable: AdditionalServicesAvailability;\n tryItFirstAvailable: AdditionalServicesAvailability;\n}\n\nconst QUANTITY_SELECTOR_KEYBOARD_CONFIG = {\n keyNavigation: true,\n};\n\nexport const AddToCart: React.FC = React.memo(\n ({\n variant,\n product,\n orderUnit,\n onProductAdded,\n modifaceVariants,\n engravingAvailable,\n tryItFirstAvailable,\n }) => {\n const {\n state: { engravingInitials, withEngraving, withTryItFirst },\n } = useEngravingTryItFirstContext();\n const { hideModal, toggleModal } = ModalContext.useModalContext();\n const { getTimeFromInit } = useTrackingContext();\n const { formatMessage } = useIntl();\n const [quantity, setQuantity] = React.useState(1);\n const { rrpShown, minimalPriceShown } = usePriceLogic(variant);\n const featureFlags = useFeatureFlags();\n\n const { shouldShowSkinAnalyzer } = useSkinAnalyzerVisibility();\n\n const addToCardCloudTracking = useAddToCardCloudTracking();\n\n const trackingDisplayType = useTrackingDisplayType(product);\n\n const onModalClose = React.useCallback(() => {\n setQuantity(1);\n hideModal();\n }, [hideModal]);\n\n const changeAmount = React.useCallback(\n (newQuantity: number): void => {\n if (withEngraving && newQuantity > 1) {\n const modalOptions = {\n header: (\n \n {formatMessage(messages.engravingMaxOrderQtyHeader, {\n quantity: 1,\n unit: orderUnit,\n })}\n
\n ),\n type: ModalModel.Types.default,\n onClose: onModalClose,\n };\n\n const modalContent = (\n \n );\n\n toggleModal(modalContent, modalOptions);\n }\n setQuantity(newQuantity);\n },\n [formatMessage, onModalClose, orderUnit, toggleModal, withEngraving]\n );\n\n const handleGtmPushProductDetail = React.useCallback(() => {\n trackPageReload({\n rrpShown,\n minimalPriceShown,\n variant,\n product,\n modifaceVariants,\n engravingAvailable,\n tryItFirstAvailable,\n trackingDisplayType,\n featureFlags,\n skinAnalyzer: shouldShowSkinAnalyzer,\n });\n }, [\n variant,\n product,\n modifaceVariants,\n engravingAvailable,\n tryItFirstAvailable,\n rrpShown,\n minimalPriceShown,\n trackingDisplayType,\n featureFlags,\n shouldShowSkinAnalyzer,\n ]);\n\n const handleQuantitySelectorClick = () => {\n dispatchTrackingEvent({\n event: 'element_click',\n element: {\n timing: getTimeFromInit(),\n interaction: 'click',\n mode: undefined,\n name: 'quantity_selector',\n type: 'product_detail',\n action: 'click_on_element',\n promo_labels: undefined,\n },\n _clear: true,\n });\n };\n\n const services = React.useMemo(\n () =>\n withEngraving && [\n {\n type: CartServiceType.Engraving,\n value: engravingInitials,\n count: quantity,\n productId: variant.webId,\n },\n ],\n [withEngraving, engravingInitials, quantity, variant.webId]\n );\n\n const trackingProduct: Extract<\n Ga4Events,\n { event: 'add_to_cart' }\n >['product'] = React.useMemo(\n () =>\n ProductEventWither()\n .withProduct(product)\n .withVariant(variant)\n .withServices({\n modifaceVariants,\n tryItFirstAvailable,\n engravingAvailable,\n skinAnalyzer: shouldShowSkinAnalyzer,\n discoveryBoxAvailable: Boolean(\n getRenderableDiscoBoxSampleId(product, variant, featureFlags)\n ),\n })\n .withAdditionalData({ quantity, cart_type: snakeCase(CartType.cart) })\n .withAdditionalPromoLabels([\n rrpShown && RRP_PRICE_PROMO_LABEL,\n minimalPriceShown && MIN_PRICE_PROMO_LABEL,\n ])\n .build(),\n [\n engravingAvailable,\n tryItFirstAvailable,\n product,\n minimalPriceShown,\n rrpShown,\n modifaceVariants,\n quantity,\n variant,\n featureFlags,\n shouldShowSkinAnalyzer,\n ]\n );\n\n const handleProductAdded = React.useCallback(() => {\n onProductAdded();\n\n const additionalPromoLabels = [\n rrpShown && RRP_PRICE_PROMO_LABEL,\n minimalPriceShown && MIN_PRICE_PROMO_LABEL,\n ];\n dispatchTrackingEvent({\n event: 'add_to_cart',\n product: trackingProduct,\n _clear: true,\n });\n\n addToCardCloudTracking({\n quantity,\n productCode: variant.productCode,\n });\n\n if (withEngraving) {\n trackEngravingAddToCart(\n product,\n variant,\n quantity,\n additionalPromoLabels\n );\n }\n }, [\n onProductAdded,\n rrpShown,\n minimalPriceShown,\n trackingProduct,\n addToCardCloudTracking,\n withEngraving,\n product,\n variant,\n quantity,\n ]);\n\n const trackAddFailed = React.useCallback(\n (message: string) => {\n dispatchTrackingEvent({\n event: 'add_to_cart_failed',\n add: {\n products: [trackingProduct],\n },\n error: {\n status: message || '',\n },\n _clear: true,\n });\n },\n [trackingProduct]\n );\n\n const canBuy = variant.availability.state === AvailabilityState.CanBeBought;\n const isClickAndCollect = variant.availability.availablePickUpStores > 0;\n\n return (\n \n \n {canBuy && (\n \n \n \n \n \n \n \n \n )}\n {isClickAndCollect && (\n \n 1}\n />\n \n )}\n \n \n );\n }\n);\n\nAddToCart.displayName = 'AddToCart';\n","import styled, { css } from 'styled-components';\n\nimport { breakpoints } from '@notino/react-styleguide';\n\nimport { IExpandableTextProps } from './model';\n\nconst useOnlyOnCss = ({\n useOnlyOn,\n}: Pick) => {\n if (useOnlyOn === 'mobile') {\n return css`\n @media (min-width: ${breakpoints.lg}) {\n display: none;\n }\n `;\n }\n if (useOnlyOn === 'desktop') {\n return css`\n display: none;\n @media (min-width: ${breakpoints.lg}) {\n display: block;\n }\n `;\n }\n return css``;\n};\n\nexport const ExpandableTextWrapper = styled.div<\n Pick\n>`\n height: ${({ isExpanded, height }) =>\n isExpanded ? 'auto' : height || '5.5rem'};\n overflow: ${({ isExpanded }) => (isExpanded ? 'auto' : 'hidden')};\n\n position: relative;\n\n ${({ useOnlyOn }) => {\n if (useOnlyOn === 'mobile') {\n return css`\n @media (min-width: ${breakpoints.lg}) {\n height: auto;\n overflow: auto;\n }\n `;\n }\n if (useOnlyOn === 'desktop') {\n return css`\n @media (max-width: ${breakpoints.lg}) {\n height: auto;\n overflow: auto;\n }\n `;\n }\n }}\n\n @media (min-width: ${breakpoints.lg}) {\n padding-right: 2rem;\n }\n`;\n\nexport const Gradient = styled.div>`\n position: absolute;\n bottom: 0;\n width: 100%;\n height: 100%;\n background: rgb(255, 255, 255);\n background: linear-gradient(\n 0deg,\n rgba(255, 255, 255, 1) 0%,\n rgba(0, 0, 0, 0) 100%\n );\n\n ${useOnlyOnCss}\n`;\n\nexport const DefaultExpandableTextButton = styled.button`\n background: none;\n border: none;\n text-decoration: underline;\n cursor: pointer;\n padding: 0.5rem 0;\n margin-top: 0.25rem;\n`;\n\nexport const ExpandableTextButtonWrapper = styled.div<\n Pick\n>`\n ${useOnlyOnCss}\n`;\n","import * as React from 'react';\n\nimport { ReactFCC } from '@notino/react-styleguide';\n\nimport { IExpandableTextProps } from './model';\nimport {\n Gradient,\n ExpandableTextWrapper,\n DefaultExpandableTextButton,\n ExpandableTextButtonWrapper,\n} from './styled';\n\nexport const ExpandableText: ReactFCC = ({\n isExpanded: isExpandedProp,\n buttonText,\n onClick,\n children,\n useOnlyOn,\n height,\n disabled,\n}) => {\n const [isExpanded, setIsExpanded] = React.useState(false);\n\n const isControlledComponent = isExpandedProp !== undefined;\n\n const resolvedIsExpanded = isControlledComponent\n ? isExpandedProp\n : isExpanded;\n\n const handleClick = () => {\n if (isControlledComponent) {\n onClick?.();\n return;\n }\n setIsExpanded(true);\n };\n\n if (disabled) {\n // eslint-disable-next-line react/jsx-no-useless-fragment\n return <>{children}>;\n }\n\n return (\n <>\n \n {children}\n\n {!resolvedIsExpanded && (\n \n )}\n \n\n {!resolvedIsExpanded &&\n getButtonComponent({ useOnlyOn, buttonText, handleClick })}\n >\n );\n};\n\nconst getButtonComponent = ({\n useOnlyOn,\n handleClick,\n buttonText,\n}: Pick & {\n handleClick: () => void;\n}) => {\n const btnCommonProps = {\n useOnlyOn,\n onClick: handleClick,\n ['data-testid']: 'expandable-text-button',\n };\n\n return typeof buttonText === 'string' ? (\n \n {buttonText}\n \n ) : (\n \n {buttonText}\n \n );\n};\n","import { defineMessages } from 'react-intl';\n\nexport const messages = defineMessages({\n taxIncludedDE: {\n id: 'pd.price.tax.included',\n defaultMessage: ', inkl. MwSt',\n },\n});\n","import styled from 'styled-components';\n\nimport { CurrencyStyled } from '@components/PriceLabel/components/styled';\n\nexport const PriceWrapper = styled.span`\n font-size: inherit;\n`;\n\nexport const CurrencyWrapper = styled(CurrencyStyled)`\n font-size: inherit;\n`;\n","import * as React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { useQuery } from '@apollo/client';\n\nimport { IStock } from '@notino/shared/definitions/custom-definitions';\nimport { GetShowUnitPricesQuery } from '@notino/shared/definitions/types';\n\nimport PriceLabel from '@components/PriceLabel';\nimport { ILocale } from '@containers/App/model';\nimport { IPrice } from '@containers/ProductListing/model';\nimport getShowUnitPricesQuery from '@queries/showUnitPrices.graphql';\nimport { UnitPriceDecimalPlaces } from '@utils/constants';\n\nimport { messages } from './messages';\nimport { CurrencyWrapper, PriceWrapper } from './styled';\n\nexport interface IPriceRatioProps {\n stockAvailability: string;\n unitAmount: number;\n locale: ILocale;\n unit: string;\n unitPrice?: IPrice;\n settingsQuery?: GetShowUnitPricesQuery;\n prepend?: JSX.Element;\n}\n\nexport const showPriceRatio = (\n queryResult: GetShowUnitPricesQuery,\n stockAvailability: string,\n unitPrice: IPrice,\n unitAmount: number\n): boolean =>\n queryResult.Settings &&\n queryResult.Settings.showUnitPrices &&\n stockAvailability !== IStock.outOfStock &&\n unitPrice &&\n !!unitAmount;\n\nexport const PriceRatio: React.FC = ({\n unitAmount,\n unit,\n stockAvailability,\n unitPrice,\n settingsQuery: settingsQueryResultProps,\n prepend,\n}) => {\n const { data: settingsQueryResult } = useQuery(\n getShowUnitPricesQuery,\n {\n ssr: true,\n skip: Boolean(settingsQueryResultProps),\n }\n );\n\n const queryResult = settingsQueryResultProps || settingsQueryResult;\n\n if (!showPriceRatio(queryResult, stockAvailability, unitPrice, unitAmount)) {\n return null;\n }\n\n return (\n <>\n {prepend}\n \n {' '}\n / {`${unitAmount}\\u00A0${unit}`}\n \n \n >\n );\n};\n","import * as React from 'react';\nimport { FormattedMessage, useIntl } from 'react-intl';\n\nimport { IStock } from '@notino/shared/definitions/custom-definitions';\nimport {\n AvailabilityState,\n CatalogVariantFragmentFragment,\n Roles,\n} from '@notino/shared/definitions/types';\n\nimport { PortalTooltip } from '@components/PortalTooltip';\nimport { useFormatPrice } from '@components/PriceLabel/useFormattedPrice';\nimport { ILocale } from '@containers/App/model';\nimport {\n IDamage,\n MaximumVolumeInPercent,\n} from '@containers/ProductListing/model';\nimport { useUser } from '@queries/useUser';\nimport { ExpandableText } from '@sharedComponents/ExpandableText';\n\nimport messages from '../../../messages';\nimport { usePriceLogic } from '../../hooks/usePriceLogic';\nimport { PriceRatio } from '../VariantsInSelectBox/PriceRatio';\n\nimport {\n Wrapper,\n CodeBlock,\n CodeName,\n Separator,\n Availability,\n AdditionalDescriptionStyled,\n AdditionalText,\n StyledInfoIcon,\n} from './styled';\nimport { useIsMinPriceDisplayedInVoucher } from './useIsMinPriceDisplayedInVoucher';\n\nconst Damage: React.FC<{ damage: IDamage }> = ({ damage }) => {\n const message =\n damage.volumeInPercent === MaximumVolumeInPercent\n ? messages.productDamaged\n : messages.productReturned;\n\n return (\n \n \n \n );\n};\n\ninterface IBelowTheLineProps {\n variant: CatalogVariantFragmentFragment;\n locale: ILocale;\n}\n\nexport const BellowTheLine: React.FC = React.memo(\n ({ variant, locale }) => {\n const {\n attributes,\n orderCode,\n productCode,\n webId,\n catalogId,\n annotation,\n additionalText,\n availability,\n stockAvailability,\n } = variant;\n\n const { user } = useUser();\n\n const { bottomRecentPrice } = usePriceLogic(variant);\n const formatPrice = useFormatPrice();\n const { formatMessage } = useIntl();\n\n const isMinPriceDisplayedInVoucher =\n useIsMinPriceDisplayedInVoucher(variant);\n\n const isImmediateCollection =\n availability.availablePickUpStores > 0 &&\n availability.state !== AvailabilityState.CanBeBought;\n\n const isMaster = attributes && attributes.Master;\n\n return (\n \n \n {isImmediateCollection ? (\n