\r\n );\r\n};\r\n","import { useState } from 'react';\r\nimport { WineWidgetModel } from '../../../../models/WineWidgetModel';\r\n\r\ninterface UseCartQuantityProps {\r\n wine: WineWidgetModel;\r\n}\r\n\r\n/**\r\n * The `useCartQuantity` function is a custom hook that manages the quantity of items in a cart,\r\n * allowing for incrementing and decrementing the quantity within the given stock limit.\r\n * @param wine - The wine object.\r\n * @returns an object with three properties: `increment`, `decrement`, and `cartQuantity`.\r\n * The `increment` and `decrement` functions are used to increase and decrease the value of\r\n * `cartQuantity`, respectively. The `cartQuantity` property represents the quantity of items in the cart.\r\n */\r\n\r\nconst useCartQuantity = ({ wine }: UseCartQuantityProps) => {\r\n const [cartQuantity, setCartQuantity] = useState(wine.minimumCartQuantity ?? 1);\r\n\r\n /**\r\n * The function `decrement` decreases the value of `cartQuantity` by 1 if it is greater than 1.\r\n */\r\n const decrement = () => {\r\n if (cartQuantity > 1 && cartQuantity > wine.minimumCartQuantity) setCartQuantity((prevState) => prevState - 1);\r\n };\r\n\r\n /**\r\n * The function `increment` increases the value of `cartQuantity` by 1 if it is less than `stock`.\r\n */\r\n const increment = () => {\r\n if (cartQuantity < wine.availableQuantity && cartQuantity < wine.maximumCartQuantity) setCartQuantity((prevState) => prevState + 1);\r\n };\r\n\r\n return { increment, decrement, cartQuantity };\r\n};\r\n\r\nexport default useCartQuantity;\r\n","import { useTranslation } from 'react-i18next';\r\n\r\ninterface OrderableTextProps {\r\n backgroundColor: string;\r\n orderableText: string;\r\n showEurPrice?: boolean;\r\n isCartVisible?: boolean;\r\n}\r\n\r\n/**\r\n * The OrderableText component renders the orderable text.\r\n * @param backgroundColor - The background color of the orderable text.\r\n * @param orderableText - The orderable text.\r\n * @param showEurPrice - The boolean value to show the price in EUR.\r\n * @returns a JSX element. It is rendering the orderable text.\r\n */\r\n\r\nconst OrderableText = ({ backgroundColor, orderableText, showEurPrice }: OrderableTextProps) => {\r\n return (\r\n <>\r\n \r\n
{orderableText}
\r\n >\r\n );\r\n};\r\n\r\ninterface AvailableTextProps {\r\n showEurPrice?: boolean;\r\n isCartVisible?: boolean;\r\n}\r\n\r\n/**\r\n * The AvailableText component renders the available text.\r\n * @param showEurPrice - The boolean value to show the price in EUR.\r\n * @param isCartVisible - The boolean value to show the cart.\r\n * @returns a JSX element. It is rendering the available text.\r\n */\r\n\r\nexport const AvailableText = ({ showEurPrice, isCartVisible }: AvailableTextProps) => {\r\n const { t } = useTranslation();\r\n return ;\r\n};\r\n\r\n/**\r\n * The NotAvailableText component renders the not available text.\r\n * @param showEurPrice - The boolean value to show the price in EUR.\r\n * @param isCartVisible - The boolean value to show the cart.\r\n * @returns a JSX element. It is rendering the not available text.\r\n */\r\n\r\nexport const NotAvailableText = ({ showEurPrice, isCartVisible }: AvailableTextProps) => {\r\n const { t } = useTranslation();\r\n\r\n return ;\r\n};\r\n","import { useCalculatedDiscount } from 'shared-widget-components/src/hooks/useCalculatedDiscount';\r\nimport { WineWidgetModel } from '../../../models/WineWidgetModel';\r\nimport { formatEurPrice, formatHufPrice } from 'shared-widget-components/src/utils/FormatPrice';\r\n\r\n/**\r\n * The WineDiscount component renders the price of the wine based on the discount.\r\n * @returns a JSX fragment. It is rendering the price of the wine. The price is rendered inside a div element with a class name.\r\n */\r\nexport const WineDiscount = ({ wine }: { wine: WineWidgetModel }) => {\r\n const basePrice = wine.basePrice!;\r\n const currentPrice = wine.currentPrice!;\r\n\r\n const { calculatedDiscount } = useCalculatedDiscount({ basePrice, currentPrice });\r\n\r\n return (\r\n
\r\n {/** no discount, only eur and huf price */}\r\n {calculatedDiscount === 0 && wine.baseEurPrice && wine.showEurPrice && (\r\n
({formatEurPrice(wine.baseEurPrice)})
\r\n )}\r\n\r\n {/** discount, but no eur price */}\r\n {calculatedDiscount > 0 && wine.basePrice &&
{formatHufPrice(wine.basePrice)}
}\r\n
\r\n {wine.showEurPrice && (\r\n
\r\n {/** eur current price if there is a discount */}\r\n {calculatedDiscount > 0 && wine.currentEurPrice && wine.showEurPrice && (\r\n
({formatEurPrice(wine.currentEurPrice)}
\r\n )}\r\n {/** eur base price if there is a discount */}\r\n {calculatedDiscount > 0 && wine.baseEurPrice && wine.showEurPrice && (\r\n
{formatEurPrice(wine.baseEurPrice)})
\r\n )}\r\n
\r\n )}\r\n
\r\n );\r\n};\r\n","import { WineWidgetModel } from '../../models/WineWidgetModel';\r\nimport { AvailableText, NotAvailableText } from './components/OrderableText';\r\nimport { WineDiscount } from './components/WineDiscount';\r\n\r\ninterface WineContentProps {\r\n wine: WineWidgetModel;\r\n}\r\n\r\n/**\r\n * The WineInfo component renders the title, manufacturer name, price, discount, and\r\n * availability of the wine.\r\n * @param wine - The wine object.\r\n * @returns a JSX fragment. It is rendering the title, manufacturer name, price, discount, and\r\n */\r\nexport const WineInfo = ({ wine }: WineContentProps) => {\r\n return (\r\n <>\r\n
\r\n
\r\n
{wine.title}
\r\n {wine.productYear}\r\n
\r\n
\r\n
\r\n \r\n
{wine.availableQuantity > 0 ? : }
\r\n
\r\n >\r\n );\r\n};\r\n","import { WineWidgetModel } from '../../../models/WineWidgetModel';\r\n\r\n/* The `interface WineTagProps` is defining the type of props that the `WineTags` component expects. It\r\nspecifies that the `wine` prop should be of type `WineModel`. This allows the component to receive\r\nthe `wine` prop and access its properties and methods. */\r\ninterface WineTagProps {\r\n wine: WineWidgetModel;\r\n}\r\n\r\n/**\r\n * The WineTags component renders the first tags of a wine and displays the number of hidden tags.\r\n * @param {WineTagProps} - - `wine`: The wine object that contains information about the wine.\r\n * @returns The WineTags component is returning a div element with the class name 'absolute top-1\r\n * right-0 w-[25%] sm:w-[30%]'. Inside the div, it renders the FirstTags component and the\r\n * NumberOfHiddenTags component, passing the wine prop to both components.\r\n */\r\nexport const WineTags = ({ wine }: WineTagProps) => {\r\n const tagClasses = wine.isManufacturer ? 'absolute top-12 right-0 w-[40%]' : 'absolute top-4 right-0 w-[40%]';\r\n\r\n return (\r\n
\r\n \r\n \r\n
\r\n );\r\n};\r\n\r\n/**\r\n * The FirstTags component displays a count of tags.\r\n * @param {WineTagProps} - The `FirstTags` component takes a prop called `wine` which is an\r\n * object with the following structure:\r\n * @returns The component `FirstTags` returns tags based on the given number\r\n */\r\nconst FirstTags = ({ wine }: WineTagProps) => {\r\n return (\r\n <>\r\n {wine.tags &&\r\n wine.tags.slice(0, 3).map((tag, index) => (\r\n
\r\n
{tag.toUpperCase()}
\r\n
\r\n ))}\r\n >\r\n );\r\n};\r\n\r\n/**\r\n * The NumberOfHiddenTags component displays a count of hidden tags if the number of tags exceeds 3.\r\n * @param {WineTagProps} - The `NumberOfHiddenTags` component takes a prop called `wine` which is an\r\n * object with the following structure:\r\n * @returns The component `NumberOfHiddenTags` returns a `div` element with the text\r\n * `+{wine.tags.length - 3}` if the length of `wine.tags` is greater than 3.\r\n */\r\nconst NumberOfHiddenTags = ({ wine }: WineTagProps) => {\r\n return (\r\n <>\r\n {wine.tags && wine.tags.length > 3 && (\r\n
\r\n
+{wine.tags.length - 3}
\r\n
\r\n )}\r\n >\r\n );\r\n};\r\n","type DiscountTagProps = {\r\n discount: number;\r\n isManufacturer?: boolean;\r\n};\r\n\r\n/**\r\n * The DiscountTag component renders the discount tag.\r\n * @param discount - The discount value.\r\n * @param isManufacturer - The manufacturer name.\r\n * @returns a JSX element. It is rendering the discount tag.\r\n */\r\n\r\nexport const DiscountTag = ({ discount, isManufacturer }: DiscountTagProps) => {\r\n if (discount <= 0) return <>>;\r\n\r\n return
{-discount.toFixed(0)}%
;\r\n};\r\n","import { CartComponent } from './cart/CartComponent';\r\nimport { WineInfo } from './WineInfo';\r\nimport useMouse from './hooks/useMouse';\r\nimport { WineWidgetModel } from '../../models/WineWidgetModel';\r\nimport { WineTags } from './components/WineTags';\r\nimport { DiscountTag } from './components/DiscountTag';\r\nimport { CDNImage } from 'shared-widget-components/src/components/CDNImage/CDNImage';\r\nimport { useCalculatedDiscount } from 'shared-widget-components/src/hooks/useCalculatedDiscount';\r\nimport { useWineClasses } from './hooks/useWineClasses';\r\nimport { useOnWineClick } from './hooks/useOnWineClick';\r\n\r\ninterface WineProps {\r\n wine: WineWidgetModel;\r\n //drag and drop komponensben false, previewben true\r\n isShowCart: boolean;\r\n}\r\n\r\n/**\r\n * The Wine component renders a wine card with the wine image, title, manufacturer name, price, and discount.\r\n * @param wine - The wine object.\r\n * @param isShowCart - A boolean value that determines whether the cart component is visible or not\r\n * @returns a JSX fragment. It is rendering the wine card with the wine image, title, manufacturer name, price, and discount\r\n */\r\n\r\nexport const Wine = ({ wine, isShowCart }: WineProps) => {\r\n const { isCartVisible, handleMouseEnter, handleMouseLeave } = useMouse(isShowCart);\r\n\r\n const { onWineClick } = useOnWineClick(wine);\r\n\r\n const { slideUpDivClasses, classnameWithCart, classnameWithoutCart } = useWineClasses(wine.showEurPrice);\r\n\r\n const basePrice = wine.basePrice!;\r\n const currentPrice = wine.currentPrice!;\r\n\r\n const { calculatedDiscount } = useCalculatedDiscount({ basePrice, currentPrice });\r\n\r\n return (\r\n
\r\n \r\n \r\n {wine.isManufacturer && ( // if we are on a merchant site, we display the manufacturers name\r\n <>\r\n
{wine.manufacturerName}
\r\n \r\n >\r\n )}\r\n \r\n
\r\n \r\n \r\n
\r\n
\r\n );\r\n};\r\n","import { useState } from 'react';\r\n\r\n/**\r\n * The `useMouse` function returns an object with properties and functions related to handling mouse\r\n * events and showing/hiding a cart.\r\n * @param {boolean} isShowCart - A boolean value indicating whether the cart should be shown or not.\r\n * @returns The useMouse function returns an object with the following properties and functions:\r\n */\r\nconst useMouse = (isShowCart: boolean) => {\r\n // cart mutatása hoverre\r\n const [isCartVisible, setIsCartVisible] = useState(false);\r\n\r\n /**\r\n * The handleMouseEnter function shows the cart if it is currently visible.\r\n */\r\n const handleMouseEnter = () => {\r\n isShowCart && setIsCartVisible(true);\r\n };\r\n\r\n /**\r\n * The handleMouseLeave function hides the cart if it is currently visible.\r\n */\r\n const handleMouseLeave = () => {\r\n isShowCart && setIsCartVisible(false);\r\n };\r\n\r\n return { isCartVisible, handleMouseEnter, handleMouseLeave };\r\n};\r\n\r\nexport default useMouse;\r\n","import { WineWidgetModel } from 'shared-widget-components/src/services/FeaturedWinesService';\r\nimport useWineUrl from './useWineUrl';\r\n\r\nexport const useOnWineClick = (wine: WineWidgetModel) => {\r\n const { createUrl } = useWineUrl();\r\n\r\n const onWineClick = () => {\r\n // @ts-ignore\r\n const languageCode = window.currentLanguageCode;\r\n\r\n const url = createUrl(wine.id, wine.title, languageCode);\r\n\r\n // @ts-ignore\r\n if (window.isAdminPage) return;\r\n\r\n window.location.href = url;\r\n };\r\n\r\n return { onWineClick };\r\n};\r\n","import { convert as urlSlug } from 'url-slug';\r\n\r\nconst useWineUrl = () => {\r\n const createUrl = (wineId: number, wineName: string, languageCode: string) => {\r\n const domain = getWineDomain(languageCode);\r\n\r\n const slug = urlSlug(wineName);\r\n\r\n return `/${domain}/${wineId}/${slug}`;\r\n };\r\n\r\n const getWineDomain = (languageCode: string): string => {\r\n switch (languageCode) {\r\n case 'en':\r\n return 'wines';\r\n case 'de':\r\n return 'weine';\r\n case 'pl':\r\n return 'wina';\r\n case 'hu':\r\n default:\r\n return 'borok';\r\n }\r\n };\r\n\r\n return { createUrl };\r\n};\r\n\r\nexport default useWineUrl;\r\n","import { useEffect, useState } from 'react';\r\n\r\n/**\r\n * The useWineClasses hook provides classes for the wine cards.\r\n * @param showEurPrice - A boolean value that determines whether to show the price in EUR.\r\n * @returns an object with the following properties and methods:\r\n */\r\n\r\nexport const useWineClasses = (showEurPrice: boolean) => {\r\n // The slideUpDivClasses is the classname for the wine card the contains the cart animation.\r\n const slideUpDivClasses =\r\n 'w-full flex min-[350px]:transform-none lg:transform lg:absolute lg:bottom-20 lg:left-0 lg:px-3 lg:backdrop-blur-md flex flex-col bg-[#F6F5F2] bg-opacity-30 lg:transition-transform duration-300 ease-in-out';\r\n\r\n // The classnameWithCart and classnameWithoutCart are used to determine the position of the cart section on the wine card.\r\n const [classnameWithCart, setClassnameWithCart] = useState('');\r\n const [classnameWithoutCart, setClassnameWithoutCart] = useState('');\r\n\r\n useEffect(() => {\r\n const classnameWithCart = showEurPrice ? 'lg:translate-y-[75px]' : 'lg:translate-y-[60px]';\r\n const classnameWithoutCart = showEurPrice ? 'lg:translate-y-[160px]' : 'lg:translate-y-[140px]';\r\n setClassnameWithCart(classnameWithCart);\r\n setClassnameWithoutCart(classnameWithoutCart);\r\n }, [showEurPrice]);\r\n\r\n return { slideUpDivClasses, classnameWithCart, classnameWithoutCart };\r\n};\r\n","export const containerVariants = {\r\n hidden: { opacity: 0 },\r\n visible: {\r\n opacity: 1,\r\n transition: {\r\n staggerChildren: 0.3, // Adjust stagger timing here\r\n },\r\n },\r\n};\r\n\r\nexport const childVariants = {\r\n hidden: { opacity: 0 },\r\n visible: {\r\n opacity: 1,\r\n transition: {\r\n duration: 0.3, // Adjust duration here\r\n },\r\n },\r\n};\r\n","import { motion } from 'framer-motion';\r\nimport { useInView } from 'react-intersection-observer';\r\nimport { WineModel, WineWidgetModel } from '../../models/WineWidgetModel';\r\nimport { Wine } from './Wine';\r\nimport { containerVariants, childVariants } from './animation/animation';\r\n\r\ninterface WinesProps {\r\n item: WineModel;\r\n wineList: WineWidgetModel[];\r\n}\r\n\r\n/**\r\n * The FeaturedWines component renders the wine cards with the wine image, title, manufacturer name, price, and discount.\r\n * @param item - The wine object.\r\n * @param wineList - The list of wines.\r\n * @returns a JSX fragment. It is rendering the wine cards with the wine image, title, manufacturer name, price, and discount\r\n */\r\n\r\nexport const FeaturedWines = ({ item, wineList }: WinesProps) => {\r\n const [ref, inView] = useInView({ triggerOnce: true });\r\n\r\n return (\r\n \r\n {item.renderedWines > 0 && (\r\n <>\r\n {wineList?.slice(0, Number(item.renderedWines)).map((wine: WineWidgetModel, i: number) => {\r\n return (\r\n \r\n \r\n \r\n );\r\n })}\r\n >\r\n )}\r\n \r\n );\r\n};\r\n","import { motion } from 'framer-motion';\r\nimport { useInView } from 'react-intersection-observer';\r\nimport { WineModel, WineWidgetModel } from '../../models/WineWidgetModel';\r\nimport { Wine } from './Wine';\r\nimport { containerVariants, childVariants } from './animation/animation';\r\n\r\ninterface WinesProps {\r\n item: WineModel;\r\n wineList: WineWidgetModel[];\r\n}\r\n\r\n/**\r\n * The CustomWines component renders the wine cards with the wine image, title, manufacturer name, price, and discount.\r\n * @param item - The wine object.\r\n * @param wineList - The list of wines.\r\n * @returns a JSX fragment. It is rendering the wine cards with the wine image, title, manufacturer name, price, and discount\r\n */\r\n\r\nexport const CustomWines = ({ wineList }: WinesProps) => {\r\n const [ref, inView] = useInView({ triggerOnce: true });\r\n\r\n if (!wineList || wineList.length === 0) {\r\n return <>>;\r\n }\r\n\r\n const showEurPrice = wineList[0].showEurPrice;\r\n\r\n return (\r\n \r\n {wineList.map((wine: WineWidgetModel, index: number) => (\r\n \r\n \r\n \r\n ))}\r\n \r\n );\r\n};\r\n","import { WineTypes } from 'shared-widget-components/src/constants/Constants';\r\nimport { WineModel, WineWidgetModel } from '../../models/WineWidgetModel';\r\nimport { useFeaturedProductContext } from 'shared-widget-components/src/providers/FeaturedProductProvider';\r\nimport { FeaturedWines } from './FeaturedWines';\r\nimport { CustomWines } from './CustomWines';\r\n\r\ninterface WinesProps {\r\n item: WineModel;\r\n wineList: WineWidgetModel[];\r\n}\r\n\r\n/**\r\n * The Wines function renders either the RecommendedWines or CustomWines component\r\n * based on the type prop.\r\n * @returns either the component `` or the component `` based on the value of the `type` variable.\r\n */\r\nexport const Wines = ({ item, wineList }: WinesProps) => {\r\n const { featuredWines } = useFeaturedProductContext();\r\n\r\n if (item.type == WineTypes.FEATURED) {\r\n return ;\r\n }\r\n\r\n return ;\r\n};\r\n","const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);\nexport default {\n randomUUID\n};","// Unique ID creation requires a high quality random # generator. In the browser we therefore\n// require the crypto API and do not support built-in fallback to lower quality random number\n// generators (like Math.random()).\nlet getRandomValues;\nconst rnds8 = new Uint8Array(16);\nexport default function rng() {\n // lazy load so that environments that need to polyfill have a chance to do so\n if (!getRandomValues) {\n // getRandomValues needs to be invoked in a context where \"this\" is a Crypto implementation.\n getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);\n\n if (!getRandomValues) {\n throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');\n }\n }\n\n return getRandomValues(rnds8);\n}","import validate from './validate.js';\n/**\n * Convert array of 16 byte values to UUID string format of the form:\n * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n */\n\nconst byteToHex = [];\n\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).slice(1));\n}\n\nexport function unsafeStringify(arr, offset = 0) {\n // Note: Be careful editing this code! It's been tuned for performance\n // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434\n return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];\n}\n\nfunction stringify(arr, offset = 0) {\n const uuid = unsafeStringify(arr, offset); // Consistency check for valid UUID. If this throws, it's likely due to one\n // of the following:\n // - One or more input array values don't map to a hex octet (leading to\n // \"undefined\" in the uuid)\n // - Invalid input values for the RFC `version` or `variant` fields\n\n if (!validate(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n\n return uuid;\n}\n\nexport default stringify;","import native from './native.js';\nimport rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\n\nfunction v4(options, buf, offset) {\n if (native.randomUUID && !buf && !options) {\n return native.randomUUID();\n }\n\n options = options || {};\n const rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`\n\n rnds[6] = rnds[6] & 0x0f | 0x40;\n rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided\n\n if (buf) {\n offset = offset || 0;\n\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n\n return buf;\n }\n\n return unsafeStringify(rnds);\n}\n\nexport default v4;","import { Wines } from '../../Wines/Wines';\r\nimport { RefObject } from 'react';\r\nimport { WineModel, WineWidgetModel } from '../../../models/WineWidgetModel';\r\nimport { v4 as uuidv4 } from 'uuid';\r\n\r\ninterface WinesContentWithScrollbarProps {\r\n scrollbarRef: RefObject;\r\n isScrollbarVisible: boolean;\r\n scrollbarColor: string;\r\n item: WineModel;\r\n wineList: WineWidgetModel[];\r\n}\r\n\r\n/**\r\n * WinesContentWithScrollbar component\r\n * @param scrollbarRef - scrollbar reference\r\n * @param isScrollbarVisible - is scrollbar visible\r\n * @param scrollbarColor - scrollbar color\r\n * @param item - wine model\r\n * @param wineList - list of wines\r\n * @returns - WinesContentWithScrollbar component\r\n */\r\n\r\nconst WinesContentWithScrollbar = ({ scrollbarRef, isScrollbarVisible, scrollbarColor, item, wineList }: WinesContentWithScrollbarProps) => {\r\n // Generate a unique scrollbar class name\r\n const scrollbarId = uuidv4();\r\n const uniqueScrollbarClassName = `CustomScrollbar${scrollbarId}`;\r\n\r\n // Dynamic style for the scrollbar\r\n const dynamicStyle = `\r\n /* Chrome custom scrollbar */\r\n .${uniqueScrollbarClassName}::-webkit-scrollbar {\r\n width: 12px; !important;\r\n height: 12px !important;\r\n }\r\n .${uniqueScrollbarClassName}::-webkit-scrollbar-track {\r\n background: #f2f2f2; !important;\r\n border-radius: 8px; !important;\r\n }\r\n .${uniqueScrollbarClassName}::-webkit-scrollbar-thumb {\r\n background: ${scrollbarColor}; !important;\r\n border-radius: 8px; !important;\r\n }\r\n .${uniqueScrollbarClassName}::-webkit-scrollbar-thumb:hover {\r\n background: ${scrollbarColor}; !important;\r\n }\r\n\r\n /* Firefox custom scrollbar */\r\n @-moz-document url-prefix() {\r\n .${uniqueScrollbarClassName} {\r\n scrollbar-width: 16px !important;\r\n scrollbar-color: ${scrollbarColor} #f2f2f2 !important;\r\n }\r\n .${uniqueScrollbarClassName} {\r\n border-radius: 8px !important; \r\n }\r\n}\r\n`;\r\n\r\n return (\r\n
\r\n );\r\n};\r\n","import { WinesPreview } from './Widget/WinesPreview';\r\nimport { WinesPreviewWrapper } from './Widget/Scrollbar/WinesPreviewWrapper';\r\nimport { useWidgetBody } from './Widget/hooks/useWidgetBody';\r\nimport { WinesLoadingSkeleton } from './skeleton/WinesLoadingSkeleton';\r\n\r\ninterface RecommendedWinesWidgetWebshopProps {\r\n data: string;\r\n}\r\n\r\n/**\r\n * @description This component is displayed in the webshop as a fully functioning widget.\r\n * @param0 data string; The data / widgetState of the widget.\r\n * @returns {JSX.Element} The GalleryWidgetWebshop component\r\n */\r\n\r\nexport const WinesWidgetWebshop = ({ data }: RecommendedWinesWidgetWebshopProps) => {\r\n if (!data || data === '{}') return <>>;\r\n\r\n const InnerWineWidgetWebshop = () => {\r\n const RecommendedWineData = JSON.parse(data);\r\n const { languageCode, wineList, isLoading } = useWidgetBody(data, RecommendedWineData.wines, RecommendedWineData.type);\r\n\r\n if (isLoading) return ;\r\n\r\n return ;\r\n };\r\n\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n","import { useEffect, useState } from 'react';\r\nimport { useFormContext } from 'shared-widget-components/src/providers/FormContextProvider';\r\nimport { WineTypes } from 'shared-widget-components/src/constants/Constants';\r\nimport { WineModel, WineWidgetModel } from '../../../models/WineWidgetModel';\r\nimport useAsyncEffect from 'use-async-effect';\r\nimport { fetchWinesForPreview } from '../../../services/WinePreviewService';\r\nimport { isEqual } from 'lodash';\r\nexport const useWidgetBody = (data: string, wines: number[], type: string, buttonColor?: string, buttonTextColor?: string, primaryColor?: string, featuredWines?: WineWidgetModel[]) => {\r\n const [isValidationError, setIsValidationError] = useState(false);\r\n\r\n const showErrorMessage = () => {\r\n setIsValidationError(true);\r\n setTimeout(() => {\r\n setIsValidationError(false);\r\n }, 2000);\r\n };\r\n\r\n //@ts-ignore\r\n const languageCode = window.currentLanguageCode;\r\n\r\n const { reset } = useFormContext();\r\n\r\n useEffect(() => {\r\n if (data) return;\r\n reset({ type: 'FEATURED' } as WineModel);\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (data) {\r\n const parsedData: WineModel = JSON.parse(data);\r\n const productVariantIdList = featuredWines?.map((wine) => wine.productVariantId);\r\n reset({\r\n widgetTitle: parsedData.widgetTitle ?? { hu: { title: '' } },\r\n backgroundColor: parsedData.backgroundColor ?? primaryColor,\r\n textColor: parsedData.textColor ?? buttonTextColor,\r\n type: parsedData.type ?? WineTypes.FEATURED,\r\n renderedWines: parsedData.renderedWines ?? 5,\r\n wines: parsedData.wines ?? productVariantIdList,\r\n scrollbarColor: parsedData.scrollbarColor ?? buttonColor,\r\n });\r\n }\r\n }, [data, buttonColor, buttonTextColor, primaryColor, featuredWines]);\r\n\r\n const [wineList, setWineList] = useState([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n\r\n useAsyncEffect(async () => {\r\n if (!wines || wines?.length === 0) {\r\n setWineList([]);\r\n return;\r\n }\r\n const areArraysEqual = isEqual(\r\n wines,\r\n wineList.map((item) => item.productVariantId),\r\n );\r\n\r\n if (areArraysEqual || isLoading) return;\r\n setIsLoading(true);\r\n try {\r\n const wineDatas = await fetchWinesForPreview(wines);\r\n const reorderedWineDatas = wines.map((wineId: number) => wineDatas.find((wine: WineWidgetModel) => wine.productVariantId === wineId));\r\n setWineList(reorderedWineDatas);\r\n setIsLoading(false);\r\n } catch (error) {\r\n setIsLoading(false);\r\n throw new Error(error);\r\n }\r\n }, [wines, type]);\r\n\r\n return { languageCode, showErrorMessage, isValidationError, wineList, isLoading };\r\n};\r\n","/**\r\n * @module WinePreviewService\r\n * @description Service for fetching package preview data\r\n * @param productVariantIds - array of product variant IDs (list of long integers)\r\n * @returns Promise that resolves to the response\r\n */\r\nexport const fetchWinesForPreview = async (productVariantIds: number[]) => {\r\n try {\r\n const response = await fetch(`/Widget/WineProductVariantForCarousel`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(productVariantIds),\r\n });\r\n\r\n return await response.json();\r\n } catch (error) {\r\n throw new Error(error);\r\n }\r\n};\r\n","import * as yup from 'yup';\r\nimport { Language } from './slides/CustomSlide/LanguageSelector/hooks/useLanguageSelector';\r\n\r\nexport const validationSchema = yup.object().shape({\r\n backgroundColor: yup.string().required('Háttérszín megadása kötelező!'),\r\n textColor: yup.string().required('Szövegszín megadása kötelező!'),\r\n buttonColor: yup.string().required('Gomb színének megadása kötelező!'),\r\n buttonTextColor: yup.string().required('Gomb szövegének megadása kötelező!'),\r\n autoPlay: yup.boolean().required('Automatikus lejátszás megadása kötelező!'),\r\n // validáció a slideokra\r\n slides: yup\r\n .array()\r\n // legalább 1 slide szükséges, külöben error\r\n .min(1, 'Legalább 1 slide hozzáadása kötelező')\r\n .of(\r\n yup.object().shape({\r\n type: yup.string().required('Típus megadása kötelező!'),\r\n\r\n // event slide esetén egy event kiválasztása szükséges\r\n id: yup.number().when('type', {\r\n is: (slideType: string) => slideType === 'EVENT',\r\n then: (eventId) => eventId.required('Kérlek válassz a legördülő listából').min(1, 'Kérlek válassz a legördülő listából'),\r\n }),\r\n\r\n // product és package slide esetén egy id kiválasztása szükséges\r\n productVariantId: yup.number().when('type', {\r\n is: (slideType: string) => slideType === 'PACKAGE' || slideType === 'PRODUCT',\r\n then: (id) => id.required('Kérlek válassz a legördülő listából').min(1, 'Kérlek válassz a legördülő listából'),\r\n }),\r\n\r\n // custom slide esetén egy kép feltöltése szükséges\r\n image: yup.object().when('type', {\r\n is: (slideType: string) => slideType === 'CUSTOM',\r\n then: (image) =>\r\n image.shape({\r\n url: yup.string().required('Kép feltöltése kötelező').min(1, 'Kép megadása kötelező'),\r\n }),\r\n }),\r\n\r\n // custom slide esetén nyelvesített content ellenőrzése\r\n content: yup.object().when('type', {\r\n is: (slideType: string) => slideType === 'CUSTOM',\r\n then: () =>\r\n yup.lazy((content) => {\r\n // nyelvek listája\r\n const languages = Object.keys(content);\r\n\r\n // minden nyelvhez tartozó content validációja\r\n return yup.object().shape({\r\n ...languages.reduce((lang, value) => {\r\n lang[value] = yup.object().shape({\r\n title: yup.string().required(`${value.toUpperCase()} cím megadása kötelező`) as yup.StringSchema,\r\n description: yup.string().required(`${value.toUpperCase()} leírás megadása kötelező`) as yup.StringSchema,\r\n buttonText: yup.string().required(`${value.toUpperCase()} gomb szöveg megadása kötelező`) as yup.StringSchema,\r\n buttonLink: yup.string().required(`${value.toUpperCase()} gomb link megadása kötelező`) as yup.StringSchema,\r\n });\r\n\r\n return lang;\r\n }, {} as Record>),\r\n });\r\n }),\r\n }),\r\n }),\r\n ),\r\n});\r\n","import { FormContextProvider } from 'shared-widget-components/src/providers/FormContextProvider';\r\nimport { validationSchema } from './validationSchema';\r\n\r\ninterface CarouselPreviewWrapperProps {\r\n children: JSX.Element;\r\n}\r\n\r\n/**\r\n * CarouselPreviewWrapper component\r\n * this component is responsible for providing the context for the carousel\r\n * @param children - the children of the component\r\n * @returns CarouselPreviewWrapper component\r\n */\r\nexport const CarouselPreviewWrapper = ({ children }: CarouselPreviewWrapperProps) => {\r\n return {children};\r\n};\r\n","import { MouseEventHandler } from 'react';\r\nimport { LeftArrow, RightArrow } from 'shared-widget-components/src/components/Icons';\r\n\r\ninterface ArrowButtonsProps {\r\n prevSlide: MouseEventHandler;\r\n nextSlide: () => void;\r\n}\r\n\r\n/**\r\n * ArrowButtons component\r\n * this component is responsible for rendering the arrow buttons in the carousel\r\n * @param prevSlide - the previous slide function\r\n * @param nextSlide - the next slide function\r\n * @returns ArrowButtons component\r\n */\r\n\r\nexport const ArrowButtons = ({ prevSlide, nextSlide }: ArrowButtonsProps) => {\r\n return (\r\n
\r\n \r\n \r\n
\r\n );\r\n};\r\n","/**\r\n * AnimatedCircle component\r\n * this component is responsible for rendering the animated circle around the navigation buttons\r\n * @param radius - the radius of the circle\r\n * @param steps - the steps of the animation\r\n * @param duration - the duration of the animation\r\n * @param buttonColor - the color of the button\r\n * @returns AnimatedCircle component\r\n */\r\n\r\nimport { useState, useEffect } from 'react';\r\n\r\nexport const AnimatedCircle = ({ radius, steps, duration, buttonColor }: { radius: number; steps: number; duration: number; buttonColor: string }) => {\r\n // State to store the points of the circle\r\n const [points, setPoints] = useState<{ x: number; y: number }[]>([]);\r\n\r\n useEffect(() => {\r\n // Effect to calculate and update points for drawing the circle over time\r\n const interval = setInterval(() => {\r\n if (points.length >= steps) {\r\n clearInterval(interval);\r\n return;\r\n }\r\n\r\n const newPoints = [];\r\n const angleStep = (2 * Math.PI) / steps;\r\n\r\n for (let i = 0; i < points.length + 1; i++) {\r\n // Calculate the angle for each point, starting from the top\r\n const angle = i * angleStep - Math.PI / 2;\r\n\r\n // Calculate the coordinates (x, y) for each point on the circle\r\n const x = radius * Math.cos(angle);\r\n const y = radius * Math.sin(angle);\r\n\r\n newPoints.push({ x, y });\r\n }\r\n\r\n // Update the points state with the newly calculated points\r\n setPoints(newPoints);\r\n }, duration / steps); // Interval to add points continously, creating the effect of drawing the circle over time\r\n\r\n // Cleanup function\r\n return () => clearInterval(interval);\r\n }, [radius, steps, duration, points]);\r\n\r\n // Return the animated circle based on the calculated points\r\n return (\r\n
\r\n );\r\n};\r\n","import { BaseSlide } from '../../../models/slides/BaseSlide';\r\nimport { AnimatedCircle } from './AnimatedCircle';\r\n\r\ninterface NavigationButtonsProps {\r\n slides: BaseSlide[];\r\n handleDotClick: (index: number) => void;\r\n currentIndex: number;\r\n buttonColor: string;\r\n autoPlay: boolean;\r\n isHovered: boolean;\r\n}\r\n\r\n/**\r\n * NavigationButtons component\r\n * this component is responsible for rendering the navigation buttons of the carousel\r\n * @param images - the images of the carousel\r\n * @param handleDotClick - function to handle the dot click\r\n * @param currentIndex - the current index of the carousel\r\n * @param buttonColor - the color of the buttons\r\n * @param autoPlay - the autoplay state of the carousel\r\n * @param isHovered - the hover state of the carousel\r\n * @returns NavigationButtons component\r\n */\r\n\r\nexport const NavigationButtons = ({ slides, handleDotClick, currentIndex, buttonColor, autoPlay, isHovered }: NavigationButtonsProps) => {\r\n // Function to show the animation circle if needed\r\n const showAnimationCircle = (index: number) => {\r\n // If the index is not the current index, return false\r\n if (index !== currentIndex) return false;\r\n\r\n // If autoPlay is disabled, return false\r\n if (!autoPlay) return false;\r\n\r\n // If the carousel is hovered, return false\r\n if (isHovered) return false;\r\n\r\n return true;\r\n };\r\n\r\n return (\r\n
\r\n );\r\n};\r\n","import { MouseEventHandler } from 'react';\r\nimport { BaseSlide } from '../../../models/slides/BaseSlide';\r\nimport { ArrowButtons } from './ArrowButtons';\r\nimport { NavigationButtons } from './NavigationButtons';\r\n\r\ninterface CarouselButtonsProps {\r\n slides: BaseSlide[];\r\n currentIndex: number;\r\n prevSlide: MouseEventHandler;\r\n nextSlide: () => void;\r\n handleDotClick: (index: number) => void;\r\n buttonColor: string;\r\n autoPlay: boolean;\r\n isHovered: boolean;\r\n}\r\n\r\n/**\r\n * CarouselButtons component\r\n * this component is responsible for rendering the arrow and dot buttons in the carousel\r\n * @param slides - slides array\r\n * @param currentIndex - current index of the slide\r\n * @param prevSlide - function to go to the previous slide\r\n * @param nextSlide - function to go to the next slide\r\n * @param handleDotClick - function to handle the dot click\r\n * @param buttonColor - color of the buttons\r\n * @param autoPlay - auto play state\r\n * @param isHovered - is hovered state\r\n * @returns CarouselButtons component\r\n */\r\n\r\nexport const CarouselButtons = ({ slides, currentIndex, prevSlide, nextSlide, handleDotClick, buttonColor, autoPlay, isHovered }: CarouselButtonsProps) => {\r\n // If there is zero or one slide, return\r\n if (slides?.length <= 1) return <>>;\r\n\r\n return (\r\n
\r\n \r\n \r\n
\r\n );\r\n};\r\n","import { CDNImage } from 'shared-widget-components/src/components/CDNImage/CDNImage';\r\nimport { CarouselImages } from '../../../hooks/useCarouselImageRetriever';\r\n\r\n/**\r\n * SlideImage component\r\n * this component is responsible for rendering the slide image\r\n * @param image - the image of the slide\r\n * @returns SlideImage component\r\n */\r\n\r\nexport const SlideImage = ({ image }: { image: CarouselImages }) => {\r\n if (!image.backgroundImageUrl) {\r\n // if wine width is undefined, if package width is 500, else width is 1080\r\n const imageWidth = image.type === 'PRODUCT' ? undefined : image.type === 'PACKAGE' ? 500 : 1080;\r\n\r\n // if wine height is 370, if package height is undefined, else height is 607\r\n const imageHeight = image.type === 'PRODUCT' ? 370 : image.type === 'PACKAGE' ? undefined : 607;\r\n\r\n return ;\r\n }\r\n\r\n return (\r\n
\r\n \r\n
\r\n \r\n
\r\n
\r\n );\r\n};\r\n","import { CameraIcon } from 'shared-widget-components/src/components/Icons';\r\nimport { CarouselImages } from '../../../hooks/useCarouselImageRetriever';\r\n\r\n/**\r\n * SlideImagePlaceholder component\r\n * this component is responsible for rendering the placeholder of the carousel if there is no image\r\n * @param image - image url\r\n * @returns SlideImagePlaceholder component\r\n */\r\n\r\nexport const SlideImagePlaceholder = ({ image }: { image: CarouselImages }) => {\r\n return (\r\n
\r\n
\r\n \r\n
Ezen a sliden még nem található kép
\r\n
\r\n
\r\n );\r\n};\r\n","import { motion } from 'framer-motion';\r\nimport { CarouselImages } from '../../../hooks/useCarouselImageRetriever';\r\nimport { useState } from 'react';\r\nimport { useMobileSwipe } from './hooks/useMobileSwipe';\r\nimport { useDesktopSwipe } from './hooks/useDesktopSwipe';\r\nimport { SlideImage } from './CarouselSlideImage';\r\nimport { SlideImagePlaceholder } from './ImagePlaceholder';\r\n\r\ninterface CarouselSliderProps {\r\n images: CarouselImages[];\r\n currentIndex: number;\r\n prevSlide: () => void;\r\n nextSlide: () => void;\r\n}\r\n\r\n/**\r\n * CarouselSlideImages component\r\n * this component is responsible for rendering the images of the carousel\r\n * @param currentIndex - current index of the image\r\n * @param images - images array\r\n * @param prevSlide - function to go to the previous slide\r\n * @param nextSlide - function to go to the next slide\r\n * @returns CarouselSlider component\r\n */\r\nconst CarouselSlideImages = ({ currentIndex, images, prevSlide, nextSlide }: CarouselSliderProps) => {\r\n const [touchPosition, setTouchPosition] = useState(0);\r\n\r\n const { handleTouchStart, handleTouchMove, handleTouchEnd, isSwiping } = useMobileSwipe({ setTouchPosition, nextSlide, prevSlide });\r\n const { handleMouseDown, handleMouseMove, handleMouseUp, onMouseLeave, isDragging } = useDesktopSwipe({ setTouchPosition, touchPosition, nextSlide, prevSlide });\r\n\r\n // true if the user is swiping or dragging\r\n const isSwipingOrDragging = isSwiping || isDragging;\r\n\r\n return (\r\n
\r\n );\r\n};\r\n\r\nexport default CarouselSlideImages;\r\n","import { useState } from 'react';\r\nimport { MIN_SWIPE_DISTANCE } from '../../../../constants/Constants';\r\n\r\ninterface useMobileSwipeProps {\r\n setTouchPosition: (position: number) => void;\r\n nextSlide: () => void;\r\n prevSlide: () => void;\r\n}\r\n\r\nexport const useMobileSwipe = ({ setTouchPosition, nextSlide, prevSlide }: useMobileSwipeProps) => {\r\n // position of the touch start\r\n const [touchStart, setTouchStart] = useState(0);\r\n // position of the touch end\r\n const [touchEnd, setTouchEnd] = useState(0);\r\n // true if the user is swiping\r\n const [isSwiping, setIsSwiping] = useState(false);\r\n\r\n // function to handle touch start\r\n const handleTouchStart = (e: React.TouchEvent) => {\r\n setTouchStart(e.targetTouches[0].clientX);\r\n setIsSwiping(true);\r\n };\r\n\r\n // set the touch position and calculate the distance when the user is swiping\r\n const handleTouchMove = (e: React.TouchEvent) => {\r\n const currentPosition = e.targetTouches[0].clientX;\r\n\r\n setTouchEnd(e.targetTouches[0].clientX);\r\n setTouchPosition(currentPosition - touchStart);\r\n };\r\n\r\n // handle touch end\r\n const handleTouchEnd = () => {\r\n if (touchStart - touchEnd > MIN_SWIPE_DISTANCE) {\r\n // Swipe Left, show next\r\n nextSlide();\r\n }\r\n\r\n if (touchEnd - touchStart > MIN_SWIPE_DISTANCE) {\r\n // Swipe Right, show previous\r\n prevSlide();\r\n }\r\n setIsSwiping(false);\r\n setTouchPosition(0);\r\n };\r\n\r\n return {\r\n handleTouchStart,\r\n handleTouchMove,\r\n handleTouchEnd,\r\n isSwiping,\r\n };\r\n};\r\n","export const MIN_SWIPE_DISTANCE = 50;\r\n","import { useState } from 'react';\r\nimport { MIN_SWIPE_DISTANCE } from '../../../../constants/Constants';\r\n\r\ninterface useDesktopSwipeProps {\r\n setTouchPosition: (position: number) => void;\r\n touchPosition: number;\r\n nextSlide: () => void;\r\n prevSlide: () => void;\r\n}\r\n\r\nexport const useDesktopSwipe = ({ setTouchPosition, touchPosition, nextSlide, prevSlide }: useDesktopSwipeProps) => {\r\n // position of the touch start\r\n const [startPosition, setStartPosition] = useState(0);\r\n // true if the user is dragging\r\n const [isDragging, setIsDragging] = useState(false);\r\n\r\n // function to handle mouse down\r\n const handleMouseDown = (e: React.MouseEvent) => {\r\n e.preventDefault();\r\n setStartPosition(e.clientX);\r\n setIsDragging(true);\r\n };\r\n\r\n // set the touch position and calculate the distance when the user is dragging\r\n const handleMouseMove = (e: React.MouseEvent) => {\r\n if (!isDragging) return;\r\n e.preventDefault();\r\n setTouchPosition(e.clientX - startPosition);\r\n };\r\n\r\n // handle mouse up\r\n const handleMouseUp = () => {\r\n if (touchPosition > MIN_SWIPE_DISTANCE) {\r\n // Swipe Left, show next\r\n prevSlide();\r\n } else if (touchPosition < -MIN_SWIPE_DISTANCE) {\r\n // Swipe Right, show previous\r\n nextSlide();\r\n }\r\n setIsDragging(false);\r\n setTouchPosition(0);\r\n };\r\n\r\n // end the swipe action when the cursor leaves the element\r\n const onMouseLeave = () => {\r\n if (!isDragging) return;\r\n handleMouseUp();\r\n };\r\n\r\n return {\r\n handleMouseDown,\r\n handleMouseMove,\r\n handleMouseUp,\r\n onMouseLeave,\r\n isDragging,\r\n };\r\n};\r\n","export const fadeAnimationName = `@keyframes fadeIn: {\r\n from: { opacity: 0 },\r\n to: { opacity: 1 },\r\n}`;\r\n\r\nexport const fadeAnimation = 'fadeIn 1s linear forwards';\r\n","import sanitizeHtml from 'sanitize-html';\r\n\r\nexport const sanitizeUrl = (text: string) => {\r\n // Sanitize url\r\n const sanitizedUrl = sanitizeHtml(text, {\r\n allowedTags: [],\r\n allowedAttributes: {},\r\n });\r\n\r\n return sanitizedUrl;\r\n};\r\n","import { sanitizeUrl } from 'shared-widget-components/src/utils/sanitizeUrl';\r\nimport { truncateHtml } from 'shared-widget-components/src/utils/truncateHtml';\r\n\r\ninterface CustomSlideButtonProps {\r\n buttonColor: string;\r\n buttonTextColor: string;\r\n slideContent: any;\r\n}\r\n\r\n/**\r\n * CustomSlideButton component\r\n * this component is responsible for rendering the button of the custom slide\r\n * @param buttonColor - button color of the custom slide\r\n * @param buttonTextColor - button text color of the custom slide\r\n * @param slideContent - content of the custom slide\r\n * @returns CustomSlideButton component\r\n */\r\n\r\nexport const CustomSlideButton = ({ slideContent, buttonColor, buttonTextColor }: CustomSlideButtonProps) => {\r\n // ha nincs buttonText vagy buttonLink, akkor return\r\n if (!slideContent.buttonText || !slideContent.buttonLink) return <>>;\r\n\r\n // a button szöveg rövidítése megadott karakterszámra\r\n const truncatedButtonText = truncateHtml(slideContent.buttonText, 20);\r\n\r\n //@ts-ignore\r\n const isAdmin = window.isAdminPage;\r\n\r\n // a gombra kattintáskor történő esemény\r\n const handleNavigation = () => {\r\n if (isAdmin) return;\r\n const url = sanitizeUrl(slideContent.buttonLink);\r\n window.location.href = url;\r\n };\r\n\r\n return (\r\n \r\n );\r\n};\r\n","import { useEffect, useState } from 'react';\r\nimport { CustomSlide } from '../../../models/slides/CustomSlide';\r\nimport { fadeAnimation, fadeAnimationName } from '../../../utils/fadeAnimation';\r\nimport { sanitizeUrl } from 'shared-widget-components/src/utils/sanitizeUrl';\r\nimport { truncateHtml } from 'shared-widget-components/src/utils/truncateHtml';\r\nimport { CustomSlideButton } from './CustomSlideButton';\r\n\r\ninterface CustomSlideContentProps {\r\n slides: CustomSlide[];\r\n textColor: string;\r\n buttonColor: string;\r\n buttonTextColor: string;\r\n currentIndex: number;\r\n}\r\n\r\n/**\r\n * CustomSlideContent component\r\n * this component is responsible for rendering the content of the custom slide\r\n * @param slides - the list of the carousel slides\r\n * @param currentIndex - the index of the currently active slide\r\n * @param textColor - the color of the text\r\n * @param buttonColor - the color of the button\r\n * @param buttonTextColor - the color of the button text\r\n * @returns CustomSlideContent component\r\n */\r\n\r\nconst CustomSlideContent = ({ slides, buttonColor, buttonTextColor, textColor, currentIndex }: CustomSlideContentProps) => {\r\n //@ts-ignore\r\n const languageCode = window.currentLanguageCode;\r\n\r\n // the content of the slide on the current language || hu content if no content for the current language\r\n const defaultContent = slides[currentIndex].content[languageCode] || slides[currentIndex].content['hu'];\r\n\r\n const [slideContent, setSlideContent] = useState(defaultContent);\r\n\r\n useEffect(() => {\r\n // if there is no content for the current language, return\r\n if (!slides[currentIndex] || !slides[currentIndex].content[languageCode]) return;\r\n // set the content of the slide on the current language\r\n setSlideContent(slides[currentIndex].content[languageCode]);\r\n }, [slides, languageCode]);\r\n\r\n // a description rövidítése megadott karakterszámra\r\n const truncatedDescription = truncateHtml(slideContent.description, 120);\r\n\r\n return (\r\n
\r\n
\r\n
\r\n {slideContent.title}\r\n
\r\n
\r\n {truncatedDescription}\r\n
\r\n
\r\n\r\n
\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default CustomSlideContent;\r\n","import { PackageContentProps } from '../../../models/slides/PackageSlide';\r\n\r\n/**\r\n * PackageDiscount component\r\n * this component is responsible for rendering the package discount\r\n * @param calculatedDiscount - the calculated discount\r\n * @returns PackageDiscount component\r\n */\r\n\r\nexport const PackageDiscount = ({ calculatedDiscount }: PackageContentProps) => {\r\n if (!calculatedDiscount) return null;\r\n return (\r\n
\r\n
{-calculatedDiscount}%
\r\n
\r\n );\r\n};\r\n","import { truncateHtml } from 'shared-widget-components/src/utils/truncateHtml';\r\nimport { PackageContentProps } from '../../../models/slides/PackageSlide';\r\n\r\n/**\r\n * PackageTextContent component\r\n * this component is responsible for rendering the package text content\r\n * @param packageData - the data of the package\r\n * @param textColor - the color of the text\r\n * @param animationClass - the animation class\r\n * @returns PackageTextContent component\r\n */\r\n\r\nexport const PackageTextContent = ({ packageData, textColor, animationClass }: PackageContentProps) => {\r\n const truncatedDescription = truncateHtml(packageData.description, 120);\r\n\r\n return (\r\n <>\r\n
\r\n {packageData.title}\r\n
\r\n
\r\n {truncatedDescription}\r\n
\r\n >\r\n );\r\n};\r\n","import { PackageContentProps, PackageSlide } from '../../../models/slides/PackageSlide';\r\nimport { formatEurPrice, formatHufPrice } from 'shared-widget-components/src/utils/FormatPrice';\r\n\r\n/**\r\n * PackagePriceContent component\r\n * this component is responsible for rendering the package price content\r\n * @param packageData - the data of the package\r\n * @param calculatedDiscount - the calculated discount\r\n * @returns PackagePriceContent component\r\n */\r\n\r\nexport const PackagePriceContent = ({ packageData, calculatedDiscount }: PackageContentProps) => {\r\n if (!calculatedDiscount) {\r\n return (\r\n
\r\n );\r\n};\r\n","import { PackageSlide } from '../../../models/slides/PackageSlide';\r\nimport { fadeAnimation, fadeAnimationName } from '../../../utils/fadeAnimation';\r\nimport { usePackageContentClick } from './hooks/usePackageContentClick';\r\nimport { useInitPackageData } from './hooks/useInitPackageData';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useCalculatedDiscount } from 'shared-widget-components/src/hooks/useCalculatedDiscount';\r\nimport { PackageDiscount } from './PackageDiscount';\r\nimport { PackageTextContent } from './PackageTextContent';\r\nimport { PackagePriceContent } from './PackagePriceContent';\r\n\r\ninterface PackageSlideProps {\r\n // the list of the carousel slides\r\n slides: PackageSlide[];\r\n // the index of the currently active slide\r\n currentIndex: number;\r\n // the color of the text\r\n textColor: string;\r\n // the color of the button\r\n buttonColor: string;\r\n // the color of the button text\r\n buttonTextColor: string;\r\n}\r\n\r\n/**\r\n * PackageContent component\r\n * this component is responsible for rendering the package content\r\n * @param currentIndex - the index of the currently active slide\r\n * @param buttonColor - the color of the button\r\n * @param buttonTextColor - the color of the button text\r\n * @param textColor - the color of the text\r\n * @param slides - the list of the carousel slides\r\n * @returns PackageContent component\r\n */\r\n\r\nconst PackageContent = ({ currentIndex, textColor, buttonColor, buttonTextColor, slides }: PackageSlideProps) => {\r\n const { t } = useTranslation();\r\n const { packageData } = useInitPackageData({ slides, currentIndex });\r\n const { onPackageClick } = usePackageContentClick({ packageData });\r\n\r\n //@ts-ignore\r\n const isAdmin = window.isAdminPage;\r\n\r\n const basePrice = packageData.basePrice!;\r\n const currentPrice = packageData.currentPrice!;\r\n\r\n const { calculatedDiscount } = useCalculatedDiscount({ basePrice, currentPrice });\r\n\r\n if (!packageData.productVariantId) return <>>;\r\n\r\n return (\r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n {' '}\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default PackageContent;\r\n","import { useState, useEffect } from 'react';\r\nimport { PackageSlide } from '../../../../models/slides/PackageSlide';\r\n\r\ninterface UseInitPackageDataProps {\r\n slides: PackageSlide[];\r\n currentIndex: number;\r\n}\r\n\r\nexport const useInitPackageData = ({ slides, currentIndex }: UseInitPackageDataProps) => {\r\n const [packageData, setPackageData] = useState({} as PackageSlide);\r\n\r\n useEffect(() => {\r\n if (!slides || !slides[currentIndex]) return;\r\n setPackageData(slides[currentIndex]);\r\n }, [slides && slides[currentIndex]]);\r\n\r\n return { packageData };\r\n};\r\n","import { sanitizeUrl } from 'shared-widget-components/src/utils/sanitizeUrl';\r\nimport usePackageUrl from './usePackageUrl';\r\nimport { PackageSlide } from '../../../../models/slides/PackageSlide';\r\n\r\nexport const usePackageContentClick = ({ packageData }: { packageData: PackageSlide }) => {\r\n const { createUrl } = usePackageUrl();\r\n\r\n //@ts-ignore\r\n const isAdmin = window.isAdminPage;\r\n\r\n // @ts-ignore\r\n const languageCode = window.currentLanguageCode;\r\n\r\n // if not on admin page, navigate to the package page on click\r\n const onPackageClick = () => {\r\n if (isAdmin) return;\r\n\r\n const url = createUrl(packageData.productVariantId, packageData.title, languageCode);\r\n\r\n const sanitizedUrl = sanitizeUrl(url);\r\n\r\n window.location.href = sanitizedUrl;\r\n };\r\n return { onPackageClick };\r\n};\r\n","import { convert as urlSlug } from 'url-slug';\r\n\r\nconst usePackageUrl = () => {\r\n // megadott id, név és nyelv alapján generál egy url-t a borcsomagokhoz\r\n const createUrl = (winePackageId: number, packageName: string, languageCode: string) => {\r\n const domain = getPackageDomain(languageCode);\r\n\r\n const slug = urlSlug(packageName);\r\n\r\n return `/${domain}/${winePackageId}/${slug}`;\r\n };\r\n\r\n const getPackageDomain = (languageCode: string): string => {\r\n switch (languageCode) {\r\n case 'en':\r\n return 'winepackages';\r\n case 'de':\r\n return 'weinpaket';\r\n case 'pl':\r\n return 'pakiety-win';\r\n case 'hu':\r\n default:\r\n return 'borcsomagok';\r\n }\r\n };\r\n\r\n return { createUrl };\r\n};\r\n\r\nexport default usePackageUrl;\r\n","import { WineContentProps } from '../../../models/slides/ProductSlide';\r\n\r\n/**\r\n * WineDiscount component\r\n * this component is responsible for rendering the wine discount\r\n * @param calculatedDiscount - the calculated discount\r\n * @returns WineDiscount component\r\n */\r\n\r\nexport const WineDiscount = ({ calculatedDiscount }: WineContentProps) => {\r\n if (!calculatedDiscount) return null;\r\n return (\r\n
\r\n
-{calculatedDiscount}%
\r\n
\r\n );\r\n};\r\n","import { ProductSlide, WineContentProps } from '../../../models/slides/ProductSlide';\r\nimport { formatEurPrice, formatHufPrice } from 'shared-widget-components/src/utils/FormatPrice';\r\n\r\n/**\r\n * WinePriceContent component\r\n * this component is responsible for rendering the wine price content\r\n * @param wineData - the data of the wine\r\n * @param calculatedDiscount - the calculated discount\r\n * @returns WinePriceContent component\r\n */\r\n\r\nexport const WinePriceContent = ({ wineData, calculatedDiscount }: WineContentProps) => {\r\n if (!calculatedDiscount) {\r\n return (\r\n
\r\n );\r\n};\r\n","import { truncateHtml } from 'shared-widget-components/src/utils/truncateHtml';\r\nimport { WineContentProps } from '../../../models/slides/ProductSlide';\r\n\r\n/**\r\n * WineTextContent component\r\n * this component is responsible for rendering the wine text content\r\n * @param wineData - the data of the wine\r\n * @param textColor - the color of the text\r\n * @returns WineTextContent component\r\n */\r\n\r\nexport const WineTextContent = ({ wineData, textColor }: WineContentProps) => {\r\n const truncatedDescription = truncateHtml(wineData.description, 120);\r\n return (\r\n <>\r\n
\r\n {wineData.title}\r\n
\r\n
\r\n {truncatedDescription}\r\n
\r\n >\r\n );\r\n};\r\n","import { ProductSlide } from '../../../models/slides/ProductSlide';\r\nimport { fadeAnimation, fadeAnimationName } from '../../../utils/fadeAnimation';\r\nimport { useCalculatedDiscount } from 'shared-widget-components/src/hooks/useCalculatedDiscount';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { WineDiscount } from './WineDiscount';\r\nimport { WinePriceContent } from './WinePriceContent';\r\nimport { WineTextContent } from './WineTextContent';\r\nimport { useWineContent } from './hooks/useWineContent';\r\n\r\ninterface WineSlideProps {\r\n // the list of the carousel slides\r\n slides: ProductSlide[];\r\n // the index of the currently active slide\r\n currentIndex: number;\r\n // the color of the text\r\n textColor: string;\r\n // the color of the button\r\n buttonColor: string;\r\n // the color of the button text\r\n buttonTextColor: string;\r\n}\r\n\r\n/**\r\n * WineContent component\r\n * this component is responsible for rendering the wine content\r\n * @param currentIndex - the index of the currently active slide\r\n * @param buttonColor - the color of the button\r\n * @param buttonTextColor - the color of the button text\r\n * @param textColor - the color of the text\r\n * @param slides - the list of the carousel slides\r\n * @returns WineContent component\r\n */\r\n\r\nconst WineContent = ({ currentIndex, buttonColor, buttonTextColor, textColor, slides }: WineSlideProps) => {\r\n const { t } = useTranslation();\r\n\r\n const { wineData, onWineClick } = useWineContent({ slides, currentIndex });\r\n\r\n const basePrice = wineData.basePrice!;\r\n const currentPrice = wineData.currentPrice!;\r\n\r\n const { calculatedDiscount } = useCalculatedDiscount({ basePrice, currentPrice });\r\n\r\n // @ts-ignore\r\n const isAdmin = window.isAdminPage;\r\n\r\n if (!wineData.productVariantId) return <>>;\r\n\r\n return (\r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default WineContent;\r\n","import { sanitizeUrl } from 'shared-widget-components/src/utils/sanitizeUrl';\r\nimport useWineUrl from './useWineUrl';\r\nimport { useEffect, useState } from 'react';\r\nimport { ProductSlide } from '../../../../models/slides/ProductSlide';\r\n\r\ninterface useWineContentProps {\r\n slides: ProductSlide[];\r\n currentIndex: number;\r\n}\r\n\r\nexport const useWineContent = ({ slides, currentIndex }: useWineContentProps) => {\r\n const { createUrl } = useWineUrl();\r\n\r\n const [wineData, setWineData] = useState({} as ProductSlide);\r\n\r\n // @ts-ignore\r\n const isAdmin = window.isAdminPage;\r\n\r\n // @ts-ignore\r\n const languageCode = window.currentLanguageCode;\r\n\r\n // onclick the wine image, navigate to the wine page\r\n const onWineClick = () => {\r\n if (isAdmin) return;\r\n\r\n const url = createUrl(wineData.id, wineData.title, languageCode);\r\n\r\n const sanitizedUrl = sanitizeUrl(url);\r\n\r\n window.location.href = sanitizedUrl;\r\n };\r\n\r\n // set the wine data\r\n useEffect(() => {\r\n if (!slides || !slides[currentIndex]) return;\r\n setWineData(slides[currentIndex]);\r\n }, [slides && slides[currentIndex]]);\r\n\r\n return { wineData, onWineClick };\r\n};\r\n","import { convert as urlSlug } from 'url-slug';\r\n\r\nconst useWineUrl = () => {\r\n // megadott id, név és nyelv alapján generál egy url-t a borokhoz\r\n const createUrl = (wineId: number, wineName: string, languageCode: string) => {\r\n const domain = getWineDomain(languageCode);\r\n\r\n const slug = urlSlug(wineName);\r\n\r\n return `/${domain}/${wineId}/${slug}`;\r\n };\r\n\r\n const getWineDomain = (languageCode: string): string => {\r\n switch (languageCode) {\r\n case 'en':\r\n return 'wines';\r\n case 'de':\r\n return 'weine';\r\n case 'pl':\r\n return 'wina';\r\n case 'hu':\r\n default:\r\n return 'borok';\r\n }\r\n };\r\n\r\n return { createUrl };\r\n};\r\n\r\nexport default useWineUrl;\r\n","import { CalendarIcon } from 'shared-widget-components/src/components/Icons';\r\n\r\ninterface EventDateProps {\r\n dateFrom: Date | null;\r\n dateTo: Date | null;\r\n}\r\n\r\n/**\r\n * EventDate component\r\n * this component is responsible for rendering the date of the event\r\n * @param dateFrom - the start date of the event\r\n * @param dateTo - the end date of the event\r\n * @returns EventDate component\r\n */\r\n\r\nexport const EventDate = ({ dateFrom, dateTo }: EventDateProps) => {\r\n // Format the date using Moment.js\r\n const formatDate = (dateParam: string) => {\r\n const date = new Date(dateParam);\r\n // Helper function to add leading zeros\r\n const zeroPad = (num: number) => num.toString().padStart(2, '0');\r\n\r\n // Extract year, month, and day\r\n const year = date.getFullYear();\r\n const month = zeroPad(date.getMonth() + 1); // getMonth() is zero-indexed\r\n const day = zeroPad(date.getDate());\r\n\r\n // Extract hours and minutes\r\n const hours = zeroPad(date.getHours());\r\n const minutes = zeroPad(date.getMinutes());\r\n\r\n // Format the date as YYYY.MM.DD.\r\n const formattedDate = `${year}.${month}.${day}.`;\r\n\r\n // If the time is 00:00, return only the date\r\n if (hours === '00' && minutes === '00') {\r\n return formattedDate;\r\n }\r\n\r\n // Otherwise, return the date and time\r\n return `${formattedDate} ${hours}:${minutes}`;\r\n };\r\n\r\n if (!dateFrom) return <>>; // in case of no dates\r\n\r\n // in case of both dates are present\r\n return (\r\n
\r\n \r\n
\r\n
{formatDate('' + dateFrom)} -
\r\n
{dateTo ? formatDate('' + dateTo) : ''}
\r\n
\r\n
\r\n );\r\n};\r\n","import { truncateHtml } from 'shared-widget-components/src/utils/truncateHtml';\r\n\r\ninterface EventDescriptionProps {\r\n description: string;\r\n textColor: string;\r\n}\r\n\r\n/**\r\n * EventDescription component\r\n * this component is responsible for rendering the event description\r\n * @param description - the description of the event\r\n * @param textColor - the color of the text\r\n * @returns EventDescription component\r\n */\r\n\r\nexport const EventDescription = ({ description, textColor }: EventDescriptionProps) => {\r\n const truncatedDescription = truncateHtml(description, 120);\r\n\r\n return (\r\n
\r\n {truncatedDescription}\r\n
\r\n );\r\n};\r\n","interface EventOrganizerProps {\r\n organizer: string;\r\n textColor: string;\r\n}\r\n\r\n/**\r\n * EventOrganizer component\r\n * @param organizer - organizer of the event\r\n * @param textColor - text color of the organizer\r\n * @returns EventOrganizer component\r\n */\r\n\r\nexport const EventOrganizer = ({ organizer, textColor }: EventOrganizerProps) => {\r\n return (\r\n
\r\n {organizer}\r\n
\r\n );\r\n};\r\n","import { MobileIcon } from 'shared-widget-components/src/components/Icons';\r\nimport { formatHufPrice } from 'shared-widget-components/src/utils/FormatPrice';\r\n\r\n/**\r\n * Event price component\r\n * this component is responsible for rendering the event price\r\n * @param {number[]} price - price of the event\r\n * @returns EventPrice component\r\n */\r\n\r\nexport const EventPrice = ({ price }: { price: number[] }) => {\r\n if (!price || price.length === 0) return <>>;\r\n\r\n const minPrice = Math.min(...price);\r\n\r\n const formattedPrice = formatHufPrice(minPrice);\r\n\r\n return (\r\n
\r\n \r\n
{formattedPrice}-tól
\r\n
\r\n );\r\n};\r\n","interface EventTitleProps {\r\n title: string;\r\n textColor: string;\r\n}\r\n\r\n/**\r\n * EventTitle component\r\n * @param title - title of the event\r\n * @param textColor - text color of the title\r\n * @returns EventTitle component\r\n */\r\n\r\nexport const EventTitle = ({ title, textColor }: EventTitleProps) => {\r\n return (\r\n
\r\n {title}\r\n
\r\n );\r\n};\r\n","import { EventSlide } from '../../../models/slides/EventSlide';\r\nimport { fadeAnimation, fadeAnimationName } from '../../../utils/fadeAnimation';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { EventDate } from './EventDate';\r\nimport { EventDescription } from './EventDescription';\r\nimport { EventOrganizer } from './EventOrganizer';\r\nimport { EventPrice } from './EventPrice';\r\nimport { EventTitle } from './EventTitle';\r\nimport { useEvent } from './hooks/useEvent';\r\n\r\ninterface EventSlideProps {\r\n // the list of the carousel slides\r\n slides: EventSlide[];\r\n // the index of the currently active slide\r\n currentIndex: number;\r\n // the color of the text\r\n textColor: string;\r\n // the color of the button\r\n buttonColor: string;\r\n // the color of the button text\r\n buttonTextColor: string;\r\n}\r\n\r\n/**\r\n * EventContent component\r\n * this component is responsible for rendering the content of the event slide\r\n * @param currentIndex - the index of the currently active slide\r\n * @param textColor - the color of the text\r\n * @param buttonColor - the color of the button\r\n * @param buttonTextColor - the color of the button text\r\n * @param slides - the list of the carousel slides\r\n * @returns EventContent component\r\n */\r\n\r\nconst EventContent = ({ currentIndex, textColor, buttonColor, buttonTextColor, slides }: EventSlideProps) => {\r\n const { t } = useTranslation();\r\n\r\n const { eventData, onEventClick } = useEvent({ slides, currentIndex });\r\n\r\n //@ts-ignore\r\n const isAdmin = window.isAdminPage;\r\n\r\n if (!eventData.id) return <>>;\r\n\r\n return (\r\n
\r\n
\r\n \r\n
\r\n \r\n
\r\n \r\n \r\n {' '}\r\n
\r\n
\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default EventContent;\r\n","import { useState, useEffect } from 'react';\r\nimport { sanitizeUrl } from 'shared-widget-components/src/utils/sanitizeUrl';\r\nimport { EventSlide } from '../../../../models/slides/EventSlide';\r\nimport useEventUrl from './useEventUrl';\r\n\r\ninterface useEventProps {\r\n slides: EventSlide[];\r\n currentIndex: number;\r\n}\r\n\r\nexport const useEvent = ({ slides, currentIndex }: useEventProps) => {\r\n const { createUrl } = useEventUrl();\r\n\r\n const [eventData, setEventData] = useState({} as EventSlide);\r\n\r\n //@ts-ignore\r\n const isAdmin = window.isAdminPage;\r\n\r\n // @ts-ignore\r\n const languageCode = window.currentLanguageCode;\r\n\r\n // if not on admin page, navigate to the event page on click\r\n const onEventClick = () => {\r\n if (isAdmin) return;\r\n\r\n const url = createUrl(eventData.id, eventData.title, languageCode);\r\n\r\n const sanitizedUrl = sanitizeUrl(url);\r\n\r\n window.location.href = sanitizedUrl;\r\n };\r\n\r\n useEffect(() => {\r\n if (!slides || !slides[currentIndex]) return;\r\n setEventData(slides[currentIndex]);\r\n }, [slides && slides[currentIndex]]);\r\n\r\n return { eventData, onEventClick };\r\n};\r\n","import { convert as urlSlug } from 'url-slug';\r\n\r\nconst useEventUrl = () => {\r\n // megadott id, név és nyelv alapján generál egy url-t az eseményekhez\r\n const createUrl = (eventId: number, eventName: string, languageCode: string) => {\r\n const domain = getEventDomain(languageCode);\r\n\r\n const slug = urlSlug(eventName);\r\n\r\n return `/${domain}/${eventId}/${slug}`;\r\n };\r\n\r\n const getEventDomain = (languageCode: string): string => {\r\n switch (languageCode) {\r\n case 'en':\r\n return 'events';\r\n case 'de':\r\n return 'veranstaltungen';\r\n case 'pl':\r\n return 'wydarzenia';\r\n case 'hu':\r\n default:\r\n return 'esemenyek';\r\n }\r\n };\r\n\r\n return { createUrl };\r\n};\r\n\r\nexport default useEventUrl;\r\n","import { BaseSlide } from '../../models/slides/BaseSlide';\r\nimport CustomSlideContent from '../slides/CustomSlide/CustomSlideContent';\r\nimport PackageContent from '../slides/PackageSlide/PackageContent';\r\nimport WineContent from '../slides/WineSlide/WineContent';\r\nimport EventContent from '../slides/eventSlide/EventContent';\r\n\r\ninterface CarouselSlideContent {\r\n slides: any[];\r\n currentIndex: number;\r\n textColor: string;\r\n buttonColor: string;\r\n buttonTextColor: string;\r\n}\r\n\r\n/**\r\n * CarouselContent component\r\n * this component is responsible for rendering the content of the carousel by the type of the slide\r\n * @param currentIndex - the current index of the carousel\r\n * @param buttonColor - the color of the buttons\r\n * @param textColor - the color of the text\r\n * @param buttonTextColor - the color of the button text\r\n * @param slides - the slides of the carousel\r\n * @returns The content of the carousel\r\n */\r\n\r\nexport const CarouselContent = ({ currentIndex, buttonColor, textColor, buttonTextColor, slides }: CarouselSlideContent) => {\r\n return (\r\n
\r\n );\r\n};\r\n","import { useState } from 'react';\r\nimport { CarouselButtons } from './carouselButtons/CarouselButtons';\r\nimport CarouselSlideImages from './slideImages/CarouselSlideImages';\r\nimport useCarouselElement from './hooks/useCarouselElement';\r\nimport { useCarouselImageRetriever } from '../../hooks/useCarouselImageRetriever';\r\nimport { CarouselContent } from './CarouselContent';\r\n\r\ninterface CarouselElementProps {\r\n slides: any[];\r\n autoPlay: boolean;\r\n\r\n textColor: string;\r\n buttonColor: string;\r\n buttonTextColor: string;\r\n}\r\n\r\n/**\r\n * CarouselElement component\r\n * this component is responsible for rendering the carousel\r\n * @param autoPlay - the autoplay state of the carousel\r\n * @param buttonColor - the color of the buttons\r\n * @param textColor - the color of the text\r\n * @param buttonTextColor - the color of the button text\r\n * @param slides - the slides of the carousel\r\n * @returns The carousel element what will be displayed on the preview\r\n */\r\nexport const CarouselElement = ({ autoPlay, buttonColor, textColor, buttonTextColor, slides }: CarouselElementProps) => {\r\n const [isHovered, setIsHovered] = useState(false);\r\n\r\n const { currentIndex, handleDotClick, nextSlide, prevSlide } = useCarouselElement({ slides, isHovered, autoPlay });\r\n const { images } = useCarouselImageRetriever({ slides });\r\n\r\n return (\r\n
\r\n );\r\n};\r\n","import { useEffect, useState } from 'react';\r\n\r\ninterface UseCarouselComponent {\r\n slides: any[];\r\n isHovered: boolean;\r\n autoPlay: boolean;\r\n}\r\n\r\n/**\r\n * This custom hook is used to handle the navigation of the carousel\r\n * @param slides - slides\r\n */\r\nconst useCarouselElement = ({ slides, isHovered, autoPlay }: UseCarouselComponent) => {\r\n const [currentIndex, setCurrentIndex] = useState(0);\r\n\r\n // this function is used to navigate to the previous slide\r\n const prevSlide = () => {\r\n setCurrentIndex(currentIndex === 0 ? slides?.length - 1 : currentIndex - 1);\r\n };\r\n\r\n // this function is used to navigate to the next slide\r\n const nextSlide = () => {\r\n setCurrentIndex(currentIndex === slides?.length - 1 ? 0 : currentIndex + 1);\r\n };\r\n\r\n // this function is used to navigate to the selected slide\r\n const handleDotClick = (index: number) => {\r\n setCurrentIndex(index);\r\n };\r\n\r\n // this function is used to set the current index with a given timeout value\r\n useEffect(() => {\r\n if (!autoPlay) return;\r\n if (isHovered) return;\r\n const interval = setInterval(() => {\r\n nextSlide();\r\n }, 5000);\r\n\r\n return () => clearInterval(interval);\r\n }, [currentIndex, slides, isHovered, autoPlay]);\r\n\r\n // this function is used to reset the current index if the slides array's length changes\r\n useEffect(() => {\r\n setCurrentIndex(0);\r\n }, [slides.length]);\r\n\r\n return {\r\n currentIndex,\r\n prevSlide,\r\n nextSlide,\r\n handleDotClick,\r\n setCurrentIndex,\r\n };\r\n};\r\n\r\nexport default useCarouselElement;\r\n","import { useEffect, useState } from 'react';\r\nimport { CustomSlide } from '../models/slides/CustomSlide';\r\nimport { PackageSlide } from '../models/slides/PackageSlide';\r\nimport { ProductSlide } from '../models/slides/ProductSlide';\r\nimport { EventSlide } from '../models/slides/EventSlide';\r\nimport { BaseSlide } from '../models/slides/BaseSlide';\r\n\r\nexport interface CarouselImages {\r\n url: string;\r\n type: string;\r\n backgroundImageUrl?: string;\r\n\r\n alt: string;\r\n}\r\n\r\nexport const useCarouselImageRetriever = ({ slides }: { slides: BaseSlide[] }) => {\r\n const [images, setImages] = useState([]);\r\n\r\n useEffect(() => {\r\n if (!slides) return;\r\n const updatedImageUrls = slides.map((slider: BaseSlide, index) => {\r\n switch (slider.type) {\r\n case 'CUSTOM':\r\n const customSlide = slides[index] as CustomSlide;\r\n return { url: customSlide.image.url || '', alt: customSlide.image.alt || '', type: 'CUSTOM' };\r\n\r\n case 'PACKAGE':\r\n const packageSlide = slides[index] as PackageSlide;\r\n if (!packageSlide.showWineBottlesInFront) return { url: packageSlide.backgroundImage || '', alt: packageSlide.backgroundImage || '', type: 'PACKAGE' };\r\n return { url: packageSlide.foregroundImage || '', backgroundImageUrl: packageSlide.backgroundImage, alt: packageSlide.foregroundImage || '', type: 'PACKAGE' };\r\n\r\n case 'PRODUCT':\r\n const wineSlide = slides[index] as ProductSlide;\r\n return { url: wineSlide.imgUrl || '', alt: wineSlide.imgUrl || '', type: 'PRODUCT' };\r\n\r\n case 'EVENT':\r\n const eventSlide = slides[index] as EventSlide;\r\n return { url: eventSlide.image || '', alt: eventSlide.image || '', type: 'EVENT' };\r\n\r\n default:\r\n return { url: '', alt: '', type: '' };\r\n }\r\n });\r\n\r\n const filteredImages = updatedImageUrls.filter((obj) => obj !== null);\r\n setImages(filteredImages);\r\n }, [slides]);\r\n\r\n return { images };\r\n};\r\n","/**\r\n * @module PackagePreviewService\r\n * @description Service for fetching package preview data\r\n * @param productVariantIds - array of product variant IDs (list of long integers)\r\n * @returns Promise that resolves to the response\r\n */\r\nexport const fetchPackagesForPreview = async (productVariantIds: number[]) => {\r\n try {\r\n const response = await fetch(`/Widget/PackageProductVariantForCarousel`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(productVariantIds),\r\n });\r\n\r\n return await response.json();\r\n } catch (error) {\r\n throw new Error(error);\r\n }\r\n};\r\n","import { UseFormSetValue, FieldValues } from 'react-hook-form';\r\nimport { BaseSlide } from '../../../../../models/slides/BaseSlide';\r\nimport { PackageSlide } from '../../../../../models/slides/PackageSlide';\r\nimport { fetchPackagesForPreview } from '../../../../../services/packageServices/packagePreviewService';\r\nimport { getPackageSlide } from './getPackageSlide';\r\n\r\nexport const updatePackage = async ({ slide, setValue, index }: { slide: BaseSlide; setValue: UseFormSetValue; index: number }) => {\r\n const packageSlide = slide as PackageSlide;\r\n if (!packageSlide.productVariantId) setValue(`slideDatas[${index}]`, emptyPackage);\r\n\r\n try {\r\n const packageElement = (await fetchPackagesForPreview([packageSlide.productVariantId])) as PackageSlide[];\r\n\r\n const updatedPackage = getPackageSlide(packageElement);\r\n\r\n setValue(`slideDatas[${index}]`, updatedPackage);\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n};\r\n\r\nexport const emptyPackage = {\r\n imgUrl: '',\r\n type: 'PACKAGE',\r\n description: '',\r\n title: '',\r\n id: 0,\r\n productVariantId: 0,\r\n availableQuantity: 0,\r\n basePrice: 0,\r\n discount: 0,\r\n currentPrice: 0,\r\n currentEurPrice: 0,\r\n baseEurPrice: 0,\r\n showEurPrice: false,\r\n isManufacturer: false,\r\n};\r\n","import { PackageSlide } from '../../../../../models/slides/PackageSlide';\r\n\r\nexport const getPackageSlide = (packageElement: PackageSlide[]) => {\r\n const updatedPackage = {\r\n type: 'PACKAGE',\r\n title: packageElement[0]?.title || '',\r\n id: packageElement[0]?.id || 0,\r\n productVariantId: packageElement[0]?.productVariantId || 0,\r\n foregroundImage: packageElement[0]?.foregroundImage || '',\r\n backgroundImage: packageElement[0]?.backgroundImage || '',\r\n showWineBottlesInFront: packageElement[0]?.showWineBottlesInFront || false,\r\n availableQuantity: packageElement[0]?.availableQuantity || 0,\r\n description: packageElement[0]?.description || '',\r\n basePrice: packageElement[0]?.basePrice || 0,\r\n discount: packageElement[0]?.discount || 0,\r\n currentPrice: packageElement[0]?.currentPrice || 0,\r\n currentEurPrice: packageElement[0]?.currentEurPrice || 0,\r\n baseEurPrice: packageElement[0]?.baseEurPrice || 0,\r\n showEurPrice: packageElement[0]?.showEurPrice || false,\r\n isManufacturer: packageElement[0]?.isManufacturer || false,\r\n };\r\n\r\n return updatedPackage;\r\n};\r\n","/**\r\n * @module WinePreviewService\r\n * @description Service for fetching package preview data\r\n * @param productVariantIds - array of product variant IDs (list of long integers)\r\n * @returns Promise that resolves to the response\r\n */\r\nexport const fetchWinesForPreview = async (productVariantIds: number[]) => {\r\n try {\r\n const response = await fetch(`/Widget/WineProductVariantForCarousel`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(productVariantIds),\r\n });\r\n\r\n return await response.json();\r\n } catch (error) {\r\n throw new Error(error);\r\n }\r\n};\r\n","import { UseFormSetValue, FieldValues } from 'react-hook-form';\r\nimport { BaseSlide } from '../../../../../models/slides/BaseSlide';\r\nimport { ProductSlide } from '../../../../../models/slides/ProductSlide';\r\nimport { fetchWinesForPreview } from '../../../../../services/wineServices/WinePreviewService';\r\nimport { getProductSlide } from './getProductSlide';\r\n\r\nexport const updateProduct = async ({ slide, setValue, index }: { slide: BaseSlide; setValue: UseFormSetValue; index: number }) => {\r\n const wineSlide = slide as ProductSlide;\r\n if (!wineSlide.productVariantId) setValue(`slideDatas[${index}]`, emptyProduct);\r\n\r\n try {\r\n const wineElement = (await fetchWinesForPreview([wineSlide.productVariantId])) as ProductSlide[];\r\n const updatedWine = getProductSlide(wineElement);\r\n setValue(`slideDatas[${index}]`, updatedWine);\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n};\r\n\r\nexport const emptyProduct = {\r\n imgUrl: '',\r\n type: 'PRODUCT',\r\n description: '',\r\n title: '',\r\n id: 0,\r\n productVariantId: 0,\r\n availableQuantity: 0,\r\n basePrice: 0,\r\n discount: 0,\r\n currentPrice: 0,\r\n currentEurPrice: 0,\r\n baseEurPrice: 0,\r\n showEurPrice: false,\r\n isManufacturer: false,\r\n tags: [],\r\n productYear: 0,\r\n};\r\n","import { ProductSlide } from '../../../../../models/slides/ProductSlide';\r\n\r\nexport const getProductSlide = (wineElement: ProductSlide[]) => {\r\n const updatedWine = {\r\n imgUrl: wineElement[0]?.imgUrl || '',\r\n type: 'PRODUCT',\r\n title: wineElement[0]?.title || '',\r\n description: wineElement[0]?.description || '',\r\n id: wineElement[0]?.id || 0,\r\n productVariantId: wineElement[0]?.productVariantId || 0,\r\n availableQuantity: wineElement[0]?.availableQuantity || 0,\r\n basePrice: wineElement[0]?.basePrice || 0,\r\n discount: wineElement[0]?.discount || 0,\r\n currentPrice: wineElement[0]?.currentPrice || 0,\r\n currentEurPrice: wineElement[0]?.currentEurPrice || 0,\r\n baseEurPrice: wineElement[0]?.baseEurPrice || 0,\r\n showEurPrice: wineElement[0]?.showEurPrice || false,\r\n isManufacturer: wineElement[0]?.isManufacturer || false,\r\n tags: wineElement[0]?.tags || [],\r\n productYear: wineElement[0]?.productYear || 0,\r\n };\r\n\r\n return updatedWine;\r\n};\r\n","/**\r\n * @module EventPreviewService\r\n * @description Service for fetching event preview data\r\n * @param eventId - array of product variant IDs (list of long integers)\r\n * @returns Promise that resolves to the response\r\n */\r\nexport const fetchEventForPreview = async (eventId: number) => {\r\n try {\r\n const response = await fetch(`/Widget/event/${eventId}`, {\r\n method: 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n });\r\n\r\n return await response.json();\r\n } catch (error) {\r\n throw new Error(error);\r\n }\r\n};\r\n","import { FieldValues, UseFormSetValue } from 'react-hook-form';\r\nimport { BaseSlide } from '../../../../../models/slides/BaseSlide';\r\nimport { EventSlide } from '../../../../../models/slides/EventSlide';\r\nimport { fetchEventForPreview } from '../../../../../services/eventServices/EventPreviewService';\r\nimport { getEventSlide } from './getEventSlide';\r\n\r\nexport const updateEvent = async ({ slide, setValue, index }: { slide: BaseSlide; setValue: UseFormSetValue; index: number }) => {\r\n const eventSlide = slide as EventSlide;\r\n if (!eventSlide.id) setValue(`slideDatas[${index}]`, emptyEvent);\r\n\r\n try {\r\n const eventElement = (await fetchEventForPreview(eventSlide.id)) as EventSlide;\r\n const updatedEvent = getEventSlide(eventElement);\r\n setValue(`slideDatas[${index}]`, updatedEvent);\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n};\r\n\r\nexport const emptyEvent = { url: '', type: 'EVENT', description: '', title: '', id: 0, dateFrom: null, dateTo: null, organizer: '', location: [], ticketPrices: [], animalFriendly: null, disabledFriendly: null };\r\n","import { EventSlide } from '../../../../../models/slides/EventSlide';\r\n\r\nexport const getEventSlide = (eventElement: EventSlide) => {\r\n const updatedEvent = {\r\n image: eventElement?.image || '',\r\n type: 'EVENT',\r\n title: eventElement?.title || '',\r\n description: eventElement?.description || '',\r\n id: eventElement?.id || 0,\r\n dateFrom: eventElement?.dateFrom || null,\r\n dateTo: eventElement?.dateTo || null,\r\n organizer: eventElement?.organizer || '',\r\n location: eventElement?.location || [],\r\n ticketPrices: eventElement?.ticketPrices || [],\r\n animalFriendly: eventElement?.animalFriendly || null,\r\n disabledFriendly: eventElement?.disabledFriendly || null,\r\n };\r\n\r\n return updatedEvent;\r\n};\r\n","import { UseFormSetValue, FieldValues } from 'react-hook-form';\r\nimport { BaseSlide } from '../../../../../models/slides/BaseSlide';\r\nimport { getCustomSlide } from './getCustomSlide';\r\n\r\nexport const updateCustom = ({ slide, setValue, index }: { slide: BaseSlide; setValue: UseFormSetValue; index: number }) => {\r\n const customSlide = getCustomSlide(slide);\r\n setValue(`slideDatas[${index}]`, customSlide);\r\n return customSlide;\r\n};\r\n","import { BaseSlide } from '../../../../../models/slides/BaseSlide';\r\nimport { CustomSlide } from '../../../../../models/slides/CustomSlide';\r\n\r\nexport const getCustomSlide = (slide: BaseSlide) => {\r\n const customSlide = slide as CustomSlide;\r\n const updatedSlide = {\r\n image: customSlide.image || {\r\n alt: '',\r\n url: '',\r\n },\r\n type: 'CUSTOM',\r\n content: customSlide.content,\r\n };\r\n\r\n return updatedSlide as CustomSlide;\r\n};\r\n","import { ImageIcon } from 'shared-widget-components/src/components/Icons';\r\n\r\nexport const CarouselLoadingSkeleton = () => {\r\n return (\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n );\r\n};\r\n","import { useFormContext } from 'shared-widget-components/src/providers/FormContextProvider';\r\nimport { Carousel } from '../../models/CarouselModel';\r\nimport { CarouselElement } from './CarouselElement';\r\nimport { previewScrollbar } from 'shared-widget-components/src/components/preview/previewScrollbar';\r\nimport { useWatch } from 'react-hook-form';\r\nimport useInitCarouselSlides from '../widgetSettings/hooks/useInitCarouselSlides';\r\nimport { useEffect, useState } from 'react';\r\nimport { BaseSlide } from '../../models/slides/BaseSlide';\r\nimport { CarouselLoadingSkeleton } from '../skeleton/CarouselLoadingSkeleton';\r\n\r\ninterface CarouselPreviewProps {\r\n item: Carousel;\r\n}\r\n\r\n/**\r\n * CarouselPreview component\r\n * this component is responsible for rendering the preview of the carousel\r\n * @param item - the item of the carousel\r\n * @returns CarouselPreview component\r\n */\r\nconst CarouselPreview = ({ item }: CarouselPreviewProps) => {\r\n const { control } = useFormContext();\r\n const slideDatas: BaseSlide[] = useWatch({ control, name: 'slideDatas' });\r\n const [slides, setSlides] = useState([]);\r\n\r\n const { isLoading } = useInitCarouselSlides({ slides: item.slides });\r\n\r\n useEffect(() => {\r\n if (!slideDatas) return;\r\n setSlides(slideDatas);\r\n }, [slideDatas]);\r\n\r\n if (isLoading) return ;\r\n\r\n return (\r\n
\r\n \r\n
\r\n {slides?.length > 0 && (\r\n
\r\n \r\n
\r\n )}\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default CarouselPreview;\r\n","import { useEffect, useState } from 'react';\r\nimport { BaseSlide } from '../../../models/slides/BaseSlide';\r\nimport useAsyncEffect from 'use-async-effect';\r\nimport { useFormContext } from 'shared-widget-components/src/providers/FormContextProvider';\r\nimport { useWatch } from 'react-hook-form';\r\nimport { updatePackage } from './initHelper/package/packageHelper';\r\nimport { updateProduct } from './initHelper/product/productHelper';\r\nimport { updateEvent } from './initHelper/event/eventHelper';\r\nimport { updateCustom } from './initHelper/custom/customHelper';\r\nimport { slideDataUpdater } from './initHelper/slideDataUpdater';\r\nimport { CustomSlide } from '../../../models/slides/CustomSlide';\r\nimport { EventSlide } from '../../../models/slides/EventSlide';\r\nimport { ProductSlide } from '../../../models/slides/ProductSlide';\r\nimport { PackageSlide } from '../../../models/slides/PackageSlide';\r\n\r\ninterface useInitCarouselSlidesProps {\r\n slides: BaseSlide[];\r\n}\r\n\r\nexport type SlideType = CustomSlide | ProductSlide | EventSlide | PackageSlide;\r\n\r\nconst useInitCarouselSlides = ({ slides }: useInitCarouselSlidesProps) => {\r\n const { setValue, control } = useFormContext();\r\n const slideDatas: SlideType[] = useWatch({ control, name: 'slideDatas' });\r\n const [slideData, setSlideData] = useState([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n\r\n useAsyncEffect(async () => {\r\n setIsLoading(true);\r\n try {\r\n await slideDataUpdater({ slides, setValue });\r\n } catch (error) {\r\n throw new Error(error);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [slides.length]);\r\n\r\n useEffect(() => {\r\n if (!slideDatas) return;\r\n setSlideData(slideDatas);\r\n }, [slideDatas]);\r\n\r\n useAsyncEffect(async () => {\r\n for (let index = 0; index < slides.length; index++) {\r\n const slide = slides[index];\r\n const previousSlide = slideData[index];\r\n\r\n if (previousSlide && JSON.stringify(previousSlide) !== JSON.stringify(slide)) {\r\n switch (slide.type) {\r\n case 'CUSTOM':\r\n updateCustom({ slide, setValue, index });\r\n break;\r\n case 'PACKAGE':\r\n updatePackage({ slide, setValue, index });\r\n break;\r\n case 'PRODUCT':\r\n updateProduct({ slide, setValue, index });\r\n break;\r\n case 'EVENT':\r\n updateEvent({ slide, setValue, index });\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n }\r\n\r\n setSlideData(slides);\r\n }, [slides]);\r\n\r\n return { slideData, isLoading };\r\n};\r\n\r\nexport default useInitCarouselSlides;\r\n","import { FieldValues, UseFormSetValue } from 'react-hook-form';\r\nimport { BaseSlide } from '../../../../models/slides/BaseSlide';\r\nimport { CustomSlide } from '../../../../models/slides/CustomSlide';\r\nimport { EventSlide } from '../../../../models/slides/EventSlide';\r\nimport { PackageSlide } from '../../../../models/slides/PackageSlide';\r\nimport { ProductSlide } from '../../../../models/slides/ProductSlide';\r\nimport { fetchEventForPreview } from '../../../../services/eventServices/EventPreviewService';\r\nimport { fetchPackagesForPreview } from '../../../../services/packageServices/packagePreviewService';\r\nimport { fetchWinesForPreview } from '../../../../services/wineServices/WinePreviewService';\r\nimport { emptyEvent } from './event/eventHelper';\r\nimport { emptyPackage } from './package/packageHelper';\r\nimport { emptyProduct } from './product/productHelper';\r\n\r\nexport const slideDataUpdater = async ({ slides, setValue }: { slides: BaseSlide[]; setValue: UseFormSetValue }) => {\r\n if (!slides) return;\r\n const updatedSlidesPromise = slides.map(async (slider: BaseSlide, index) => {\r\n switch (slider.type) {\r\n case 'CUSTOM':\r\n const customSlide = slides[index] as CustomSlide;\r\n return { image: customSlide.image || { alt: '', url: '' }, type: 'CUSTOM', content: customSlide.content };\r\n\r\n case 'PACKAGE':\r\n const packageSlide = slides[index] as PackageSlide;\r\n if (!packageSlide.productVariantId) return emptyPackage;\r\n\r\n try {\r\n const packageElement = (await fetchPackagesForPreview([packageSlide.productVariantId])) as PackageSlide[];\r\n return {\r\n type: 'PACKAGE',\r\n title: packageElement[0]?.title || '',\r\n id: packageElement[0]?.id || 0,\r\n productVariantId: packageElement[0]?.productVariantId || 0,\r\n foregroundImage: packageElement[0]?.foregroundImage || '',\r\n backgroundImage: packageElement[0]?.backgroundImage || '',\r\n showWineBottlesInFront: packageElement[0]?.showWineBottlesInFront || false,\r\n availableQuantity: packageElement[0]?.availableQuantity || 0,\r\n description: packageElement[0]?.description || '',\r\n basePrice: packageElement[0]?.basePrice || 0,\r\n discount: packageElement[0]?.discount || 0,\r\n currentPrice: packageElement[0]?.currentPrice || 0,\r\n currentEurPrice: packageElement[0]?.currentEurPrice || 0,\r\n baseEurPrice: packageElement[0]?.baseEurPrice || 0,\r\n showEurPrice: packageElement[0]?.showEurPrice || false,\r\n isManufacturer: packageElement[0]?.isManufacturer || false,\r\n };\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n\r\n case 'PRODUCT':\r\n const wineSlide = slides[index] as ProductSlide;\r\n if (!wineSlide.productVariantId) return emptyProduct;\r\n\r\n try {\r\n const wineElement = (await fetchWinesForPreview([wineSlide.productVariantId])) as ProductSlide[];\r\n return {\r\n imgUrl: wineElement[0]?.imgUrl || '',\r\n type: 'PRODUCT',\r\n title: wineElement[0]?.title || '',\r\n description: wineElement[0]?.description || '',\r\n id: wineElement[0]?.id || 0,\r\n productVariantId: wineElement[0]?.productVariantId || 0,\r\n availableQuantity: wineElement[0]?.availableQuantity || 0,\r\n basePrice: wineElement[0]?.basePrice || 0,\r\n discount: wineElement[0]?.discount || 0,\r\n currentPrice: wineElement[0]?.currentPrice || 0,\r\n currentEurPrice: wineElement[0]?.currentEurPrice || 0,\r\n baseEurPrice: wineElement[0]?.baseEurPrice || 0,\r\n showEurPrice: wineElement[0]?.showEurPrice || false,\r\n isManufacturer: wineElement[0]?.isManufacturer || false,\r\n tags: wineElement[0]?.tags || [],\r\n productYear: wineElement[0]?.productYear || 0,\r\n };\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n\r\n case 'EVENT':\r\n const eventSlide = slides[index] as EventSlide;\r\n if (!eventSlide.id) return emptyEvent;\r\n\r\n try {\r\n const eventElement = (await fetchEventForPreview(eventSlide.id)) as EventSlide;\r\n return {\r\n image: eventElement?.image || '',\r\n type: 'EVENT',\r\n title: eventElement?.title || '',\r\n description: eventElement?.description || '',\r\n id: eventElement?.id || 0,\r\n dateFrom: eventElement?.dateFrom || null,\r\n dateTo: eventElement?.dateTo || null,\r\n organizer: eventElement?.organizer || '',\r\n location: eventElement?.location || [],\r\n ticketPrices: eventElement?.ticketPrices || [],\r\n animalFriendly: eventElement?.animalFriendly || null,\r\n disabledFriendly: eventElement?.disabledFriendly || null,\r\n };\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n\r\n default:\r\n return null;\r\n }\r\n });\r\n\r\n const updatedSlides = await Promise.all(updatedSlidesPromise);\r\n const filtered = updatedSlides.filter((obj) => obj !== null);\r\n\r\n if (!filtered) return;\r\n setValue('slideDatas', filtered);\r\n};\r\n","import { CarouselPreviewWrapper } from './CarouselPreviewWrapper';\r\nimport CarouselPreview from './widgetPreview/CarouselPreview';\r\nimport { useWidgetBody } from './widgetSettings/hooks/useWidgetBody';\r\n\r\ninterface CarouselWidgetWebshopProps {\r\n data: string;\r\n}\r\n\r\n/**\r\n * @description This component is displayed in the webshop as a fully functioning widget.\r\n * @param0 data string; The data / widgetState of the widget.\r\n * @returns {JSX.Element} The GalleryWidgetWebshop component\r\n */\r\n\r\nexport const CarouselWidgetWebshop = ({ data }: CarouselWidgetWebshopProps) => {\r\n // webshopon ha nincs adat, akkor ne jelenjen meg semmi\r\n if (!data || data === '{}') return <>>;\r\n\r\n const InnerCarouselWidgetWebshop = () => {\r\n useWidgetBody(data);\r\n const CarouselData = JSON.parse(data);\r\n\r\n return ;\r\n };\r\n\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n","import { useEffect, useState } from 'react';\r\nimport { useFormContext } from 'shared-widget-components/src/providers/FormContextProvider';\r\nimport { Carousel } from '../../../models/CarouselModel';\r\n\r\n/**\r\n * Custom hook to reset the form and update the widgetstate with data from backend\r\n * @param data - data from backend\r\n * @returns {object} - object containing the languageCode\r\n */\r\nexport const useWidgetBody = (data: string, buttonColor?: string, buttonTextColor?: string, primaryColor?: string) => {\r\n //@ts-ignore\r\n const languageCode = window.currentLanguageCode;\r\n const { reset, errors } = useFormContext();\r\n\r\n const [isValidationError, setIsValidationError] = useState(false);\r\n\r\n const showErrorMessage = () => {\r\n setIsValidationError(true);\r\n console.log('showErrorMessage -> errors', errors);\r\n setTimeout(() => {\r\n setIsValidationError(false);\r\n }, 2000);\r\n };\r\n\r\n // update widgetstate with data from backend\r\n useEffect(() => {\r\n try {\r\n const parsedData: Carousel = JSON.parse(data);\r\n reset({\r\n backgroundColor: parsedData.backgroundColor ?? primaryColor,\r\n textColor: parsedData.textColor ?? buttonTextColor,\r\n buttonColor: parsedData.buttonColor ?? buttonColor,\r\n slides: parsedData.slides ?? [],\r\n autoPlay: parsedData.autoPlay ?? true,\r\n buttonTextColor: parsedData.buttonTextColor ?? buttonTextColor,\r\n });\r\n } catch (error) {\r\n throw new Error('Hiba az adatok betöltése közben!');\r\n }\r\n }, [data, buttonColor, buttonTextColor, primaryColor]);\r\n\r\n return { languageCode, isValidationError, showErrorMessage };\r\n};\r\n","import * as yup from 'yup';\r\n\r\nexport const validationSchema = yup.object().shape({\r\n backgroundColor: yup.string().required('Háttérszín megadása kötelező!'),\r\n textColor: yup.string().required('Szövegszín megadása kötelező!'),\r\n buttonColor: yup.string().required('Gomb színének megadása kötelező!'),\r\n buttonTextColor: yup.string().required('Gomb szövegének megadása kötelező!'),\r\n});\r\n","import { FormContextProvider } from 'shared-widget-components/src/providers/FormContextProvider';\r\nimport { validationSchema } from './validationSchema';\r\n\r\ninterface SubscribePreviewWrapperProps {\r\n children: JSX.Element;\r\n}\r\n\r\n/**\r\n * SubscribePreviewWrapper component\r\n * this component is responsible for providing the context for the subscribe widget\r\n * @param children - the children of the component\r\n * @returns SubscribePreviewWrapper component\r\n */\r\nexport const SubscribePreviewWrapper = ({ children }: SubscribePreviewWrapperProps) => {\r\n return {children};\r\n};\r\n","import { useTranslation } from 'react-i18next';\r\n\r\ninterface SuccessScreenProps {\r\n textColor: string;\r\n}\r\n\r\nexport const SuccessScreen = ({ textColor }: SuccessScreenProps) => {\r\n const { t } = useTranslation();\r\n\r\n //@ts-ignore\r\n const isAdmin = window.isAdminPage;\r\n\r\n const subscribeImageUrl = isAdmin ? '/images/newsletter.png' : '/static_assets/newsletter.png';\r\n\r\n return (\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n {t('subscribeWidget.thanks')}\r\n
\r\n
\r\n {t('subscribeWidget.success')}\r\n
\r\n
\r\n
\r\n );\r\n};\r\n","import { useState } from 'react';\r\n\r\nimport { QuestionIcon, InfoSVG } from './Icons';\r\n\r\ninterface InfoIconProps {\r\n infoText: string;\r\n id?: string;\r\n className?: string;\r\n icon?: 'question' | 'info';\r\n variant?: 'primary' | 'secondary';\r\n}\r\n\r\n/**\r\n * @description This component is an infoicon that shows a tooltip when hovered over\r\n * @param infoText The text to show in the tooltip\r\n * @param id The id of the infoicon\r\n * @param className Addititonal classes to add to the infoicon\r\n * @param icon The icon to show in the infoicon. question or info. Defaults to question\r\n * @param variant The color of the infoicon. primary/blue or secondary/grey. Defaults to primary\r\n * @returns The InfoIcon component\r\n */\r\n\r\nconst InfoIcon = ({ infoText, id, className, icon, variant }: InfoIconProps) => {\r\n const [showTooltip, setShowTooltip] = useState(false);\r\n\r\n return (\r\n
\r\n );\r\n};\r\n\r\nconst CheckboxLabel = ({ label, link, inputKey, onClick, labelColor, linkColor }: CheckboxLabelProps) => {\r\n // case of no label or link\r\n if (!label && !link) return <>>;\r\n\r\n // case of label and no link\r\n if (label && !link) {\r\n return (\r\n \r\n );\r\n }\r\n\r\n // case of link and no label\r\n if (!label && link) {\r\n return (\r\n
\r\n {link}\r\n
\r\n );\r\n }\r\n\r\n // case of label and link\r\n if (label && link) {\r\n return (\r\n