{"version":3,"file":"js/4419.92bcf742d57fff99.js","mappings":"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","sources":["webpack://@sazka/web/./js/app/tickets/components/tickets-filter/tickets-filter-state.ts","webpack://@sazka/web/./js/app/tickets/components/tickets-filter/tickets-sorting-options-enum.ts","webpack://@sazka/web/./js/app/tickets/api/favorite-tickets-api.ts","webpack://@sazka/web/./js/app/tickets/favorite-tickets-store.ts","webpack://@sazka/web/./js/app/tickets/utils/online-tickets-analytics-category-page.ts","webpack://@sazka/web/../../libs/utils/composables/use-breakpoints.ts","webpack://@sazka/web/../../libs/utils/debounce.ts","webpack://@sazka/web/../../libs/utils/string-utils.ts","webpack://@sazka/web/./js/app/tickets/components/ticket-promo-card.vue?3b6c","webpack://@sazka/web/./js/app/tickets/components/ticket-promo-card.vue","webpack://@sazka/web/./js/app/tickets/components/ticket-promo-card.vue?8d5d","webpack://@sazka/web/./js/app/tickets/widgets/random-recommendation/_promo-content.vue?bcb1","webpack://@sazka/web/./js/app/tickets/widgets/random-recommendation/_promo-content.vue","webpack://@sazka/web/./js/app/tickets/widgets/random-recommendation/_promo-content.vue?b4f1"],"sourcesContent":["import { computed, ref } from \"vue\";\r\nimport { TicketsSortingOptions } from \"@/tickets/components/tickets-filter/tickets-sorting-options-enum\";\r\n\r\nconst checkedFilters = ref<number[]>([]);\r\nconst selectedSorting = ref<TicketsSortingOptions>(TicketsSortingOptions.Default);\r\n\r\nconst sortedFiltersString = computed(() => {\r\n return [...checkedFilters.value].sort((a, b) => a - b).join(\",\");\r\n});\r\n\r\nexport function useTicketsFilterHelper() {\r\n const addFilter = (num: number) => {\r\n if (checkedFilters.value.includes(num)) return;\r\n\r\n checkedFilters.value.push(num);\r\n };\r\n\r\n const removeFilter = (num: number) => {\r\n checkedFilters.value = checkedFilters.value.filter((item) => item !== num);\r\n };\r\n\r\n return { addFilter, removeFilter };\r\n}\r\n\r\nexport { checkedFilters, selectedSorting, sortedFiltersString };\r\n","export enum TicketsSortingOptions {\r\n Default = \"recommended\",\r\n PriceAscending = \"price_ascending\",\r\n PriceDescending = \"price_descending\",\r\n WinAscending = \"win_ascending\",\r\n WinDescending = \"win_descending\",\r\n}\r\n","import { AxiosError } from \"axios\";\r\nimport { httpClient } from \"@sazka/utils/http-clients/http-client\";\r\nimport { showAlert } from \"@sazka/design-system/src/modal-alert/mount-alert\";\r\nimport { FavoriteTicket } from \"../models/favorite-ticket\";\r\n\r\nexport const fetchFavoriteTickets = async () => {\r\n const response = await httpClient.get<FavoriteTicket[]>(\"/api/favorite-tickets\");\r\n return response.data;\r\n};\r\n\r\nexport const createFavoriteTicket = async (externalSystemID: number) => {\r\n try {\r\n const ticketResponse = await httpClient.post<FavoriteTicket>(`/api/favorite-tickets/${externalSystemID}`);\r\n return ticketResponse.data;\r\n } catch (error) {\r\n const axiosError = error as AxiosError;\r\n if (axiosError.response?.status === 405) {\r\n showAlert({ title: \"MaximálnÄ› si mĹŻĹľete uloĹľit 5 online losĹŻ.\" });\r\n } else {\r\n throw error;\r\n }\r\n }\r\n};\r\n\r\nexport const deleteFavoriteTicket = async (externalSystemID: number) => {\r\n httpClient.delete(`/api/favorite-tickets/${externalSystemID}`);\r\n};\r\n\r\nexport default {\r\n fetchFavoriteTickets,\r\n createFavoriteTicket,\r\n deleteFavoriteTicket,\r\n};\r\n","import { defineStore } from \"pinia\";\r\nimport { FavoriteTicket } from \"./models/favorite-ticket\";\r\nimport api from \"./api/favorite-tickets-api\";\r\nimport { ref } from \"vue\";\r\n\r\nexport const useFavoriteTicketsStore = defineStore(\"favoriteTickets\", () => {\r\n const favoriteTickets = ref<FavoriteTicket[]>([]);\r\n const favoriteTicketsIds = ref<number[]>([]);\r\n\r\n const getFavoriteTicket = (externalSystemID: number) => {\r\n return favoriteTickets.value.find((ticket) => ticket.externalSystemID === externalSystemID);\r\n };\r\n\r\n const isFavoriteTicket = (externalSystemID: number) => favoriteTicketsIds.value.includes(externalSystemID);\r\n\r\n const loadFavoriteTickets = async () => {\r\n const favoriteTicketsResponse = await api.fetchFavoriteTickets();\r\n\r\n favoriteTickets.value = favoriteTicketsResponse;\r\n favoriteTicketsIds.value = favoriteTicketsResponse.map((ticket) => ticket.externalSystemID);\r\n };\r\n\r\n const createFavoriteTicket = async (externalSystemID: number) => {\r\n favoriteTicketsIds.value.push(externalSystemID);\r\n\r\n const ticket = await api.createFavoriteTicket(externalSystemID);\r\n if (!ticket) {\r\n favoriteTicketsIds.value = favoriteTicketsIds.value.filter((id) => id !== externalSystemID);\r\n return;\r\n }\r\n\r\n favoriteTickets.value = [...favoriteTickets.value, ticket];\r\n };\r\n\r\n const deleteFavoriteTicket = async (externalSystemID: number) => {\r\n favoriteTicketsIds.value = favoriteTicketsIds.value.filter((id) => id !== externalSystemID);\r\n favoriteTickets.value = favoriteTickets.value.filter((ticket) => ticket.externalSystemID !== externalSystemID);\r\n\r\n await api.deleteFavoriteTicket(externalSystemID);\r\n };\r\n\r\n const toggleFavoriteTicket = async (externalSystemID: number) => {\r\n if (isFavoriteTicket(externalSystemID)) {\r\n await deleteFavoriteTicket(externalSystemID);\r\n } else {\r\n await createFavoriteTicket(externalSystemID);\r\n }\r\n };\r\n return {\r\n favoriteTickets,\r\n favoriteTicketsIds,\r\n getFavoriteTicket,\r\n createFavoriteTicket,\r\n deleteFavoriteTicket,\r\n loadFavoriteTickets,\r\n isFavoriteTicket,\r\n toggleFavoriteTicket,\r\n };\r\n});\r\n","import { TicketsSortingOptions } from \"@/tickets/components/tickets-filter/tickets-sorting-options-enum\";\r\n\r\nexport namespace OnlineTicketsCategoryPageAnalytics {\r\n // V1.0\r\n\r\n // DL1.10\r\n export function pushLosyLobbyPage() {\r\n window.dataLayer.push({\r\n page: {\r\n type: \"lobby.escratches\",\r\n kind: \"lobby.escratches\",\r\n verticalCode: \"losy\",\r\n verticalCodeStrict: \"losy\",\r\n gameCode: \"no_game\",\r\n gameCodeStrict: \"no_game\",\r\n },\r\n });\r\n }\r\n\r\n // DL1.20\r\n export enum OnlineTicketsPlacement {\r\n AllScratches = \"allScratches\",\r\n FavoriteScratches = \"favoriteScratches\",\r\n NewScratches = \"newScratches\",\r\n MostPlayed = \"mostPlayed\",\r\n FamilyScratches = \"familyScratches\",\r\n Homepage = \"homepage\",\r\n }\r\n\r\n interface Product {\r\n id: string;\r\n gameCode: string;\r\n verticalCode: string;\r\n placement: OnlineTicketsPlacement;\r\n position: string;\r\n }\r\n\r\n interface DataLayerPayload {\r\n event: string;\r\n action: {\r\n show: {\r\n products: Product[];\r\n eventProperty1?: string;\r\n eventProperty2?: string;\r\n };\r\n };\r\n }\r\n\r\n export function pushTicketClick(\r\n gameCode: string,\r\n placement: OnlineTicketsPlacement,\r\n position: string,\r\n filterValues?: string,\r\n selectedSorting?: string\r\n ) {\r\n const product: Product = {\r\n id: gameCode,\r\n gameCode: gameCode,\r\n verticalCode: \"elosy\",\r\n placement: placement,\r\n position: position,\r\n };\r\n\r\n const dataLayerPayload: DataLayerPayload = {\r\n event: \"action.show.products\",\r\n action: {\r\n show: {\r\n products: [product],\r\n },\r\n },\r\n };\r\n\r\n if (placement === OnlineTicketsPlacement.AllScratches) {\r\n dataLayerPayload.action.show.eventProperty1 = filterValues;\r\n dataLayerPayload.action.show.eventProperty2 = selectedSorting;\r\n }\r\n\r\n window.dataLayer.push(dataLayerPayload);\r\n }\r\n\r\n // DL1.30\r\n export function pushRandomBetEvent() {\r\n window.dataLayer.push({\r\n event: \"action.click.randombet\",\r\n });\r\n }\r\n\r\n // DL1.31\r\n export function pushShowProductEvent(gameCode: string, buttonText: string) {\r\n window.dataLayer.push({\r\n event: \"action.show.products\",\r\n action: {\r\n show: {\r\n products: [\r\n {\r\n id: gameCode,\r\n gameCode: gameCode,\r\n verticalCode: \"elosy\",\r\n placement: \"randomBet\",\r\n button: buttonText,\r\n },\r\n ],\r\n },\r\n },\r\n });\r\n }\r\n\r\n // DL1.32\r\n export function pushRandomBetEventAgain() {\r\n window.dataLayer.push({\r\n event: \"action.clickNext.randombet\",\r\n });\r\n }\r\n\r\n // DL1.70 implemented in analytics-secondary-nav.ts (it's shared between lotteries and tickets)\r\n\r\n // DL1.80\r\n export function pushLobbyFilterGameList(filteredValues: string) {\r\n window.dataLayer.push({\r\n event: \"action.applyFilter.escratches\",\r\n action: {\r\n applyFilter: {\r\n label: filteredValues,\r\n },\r\n },\r\n });\r\n }\r\n\r\n // DL1.90\r\n export function pushLobbySortGameList(sortingType: TicketsSortingOptions) {\r\n window.dataLayer.push({\r\n event: \"action.sort.escratches\",\r\n action: {\r\n sort: {\r\n label: sortingType,\r\n },\r\n },\r\n });\r\n }\r\n\r\n // DL4.10, DL4.20, DL4.30 and DL4.40 implemented in app/shared/utils/analytics/analytics-cp-widget-banner.ts\r\n\r\n // DL4.25\r\n export function pushActionImpressProducts(\r\n gameCode: string,\r\n placement: \"mostPlayed\" | \"favoriteScratches\",\r\n position: number\r\n ) {\r\n window.dataLayer.push({\r\n event: \"action.impress.products\",\r\n action: {\r\n impress: {\r\n products: [\r\n {\r\n id: gameCode,\r\n gameCode: gameCode,\r\n verticalCode: \"elosy\",\r\n placement: placement,\r\n position: position,\r\n },\r\n ],\r\n },\r\n },\r\n });\r\n }\r\n\r\n // DL4.25 (second part)\r\n export function pushActionImpressProductsTicketFamily(gameCode: string, index: number, position: number) {\r\n window.dataLayer.push({\r\n event: \"action.impress.products\",\r\n action: {\r\n impress: {\r\n products: [\r\n {\r\n id: gameCode,\r\n gameCode: gameCode,\r\n verticalCode: \"elosy\",\r\n placement: \"familyScratches\",\r\n position: `escratches.${index}.${position}`,\r\n },\r\n ],\r\n },\r\n },\r\n });\r\n }\r\n}\r\n","import { Ref, ref } from \"vue\";\r\nimport { ResponsiveUtils } from \"../responsive-utils\";\r\n\r\ntype BreakpointType = keyof Omit<typeof ResponsiveUtils.breakpoints, \"xs\">;\r\ntype ReactiveBreakpoint = {\r\n key: BreakpointType;\r\n minSize: (typeof ResponsiveUtils.breakpoints)[BreakpointType];\r\n isInUse: boolean;\r\n value: Ref<boolean>;\r\n};\r\n\r\nlet initialized = false;\r\nlet reactiveBreakpoints: ReactiveBreakpoint[] = null;\r\n\r\n/**\r\n * Returns ref with boolean value, which means, current breakpoint is same or bigger\r\n * eg. media min-width: x\r\n * since its breakpoint up, it doesnt make sense for 'xs' which would be always true, so its omited\r\n * @param breakpoints breakpoint name eg. 'xs2' or 'xl'\r\n * @returns boolean\r\n */\r\nexport function useBreakpoints(breakpoints: BreakpointType): Ref<boolean>;\r\n\r\n/**\r\n * Returns object, with keys same as parameter value, their value is ref with boolean value, which means, current breakpoint is same or bigger\r\n * eg. media min-width: x\r\n * Example of return value: { sm: ref(true), md: ref(false) }\r\n * Returns only value passed in parametrs,\r\n * since its breakpoint up, it doesnt make sense for 'xs' which would be always true, so its omited\r\n * @param breakpoints all breakpoint names eg. 'xs2' or 'xl'\r\n */\r\nexport function useBreakpoints(...breakpoints: BreakpointType[]): { [key in BreakpointType]: Ref<boolean> };\r\n\r\nexport function useBreakpoints(...breakpoints: BreakpointType[]) {\r\n if (breakpoints?.length == 0) return;\r\n\r\n initialize();\r\n\r\n if (breakpoints.length > 1) {\r\n return breakpoints.reduce((acc, x) => {\r\n acc[x] = reactiveBreakpoint(x);\r\n return acc;\r\n }, {});\r\n } else {\r\n return reactiveBreakpoint(breakpoints[0]);\r\n }\r\n}\r\n\r\nfunction initialize() {\r\n if (initialized) return;\r\n reactiveBreakpoints = Object.keys(ResponsiveUtils.breakpoints)\r\n .filter((x) => x !== \"xs\")\r\n .map((x) => ({\r\n isInUse: false,\r\n key: x as BreakpointType,\r\n minSize: ResponsiveUtils.breakpoints[x] as (typeof ResponsiveUtils.breakpoints)[BreakpointType],\r\n value: ref(false),\r\n }));\r\n\r\n initialized = true;\r\n}\r\n\r\nfunction reactiveBreakpoint(breakpoint: BreakpointType) {\r\n const brkpnt = reactiveBreakpoints.find((x) => x.key === breakpoint);\r\n if (!brkpnt.isInUse) {\r\n brkpnt.isInUse = true;\r\n const media = window.matchMedia(`(min-width: ${brkpnt.minSize}px)`);\r\n brkpnt.value.value = media.matches;\r\n media.onchange = (e) => {\r\n brkpnt.value.value = e.matches;\r\n };\r\n }\r\n return brkpnt.value;\r\n}\r\n","/**\r\n * Debounce function - use like this:\r\n * var handler = debounce(function(){ do the work}, 100);\r\n * $(window).scroll(handler);\r\n * @param func callback function\r\n * @param wait time in milliseconds to wait\r\n * @param immediate\r\n */\r\n\r\ntype CallbackFunction = (...args: any[]) => any;\r\n\r\nexport function debounce<T extends CallbackFunction>(func: T, wait: number, immediate = false) {\r\n let timeout: number | null;\r\n\r\n return function (this: ThisParameterType<T>, ...args: Parameters<T>) {\r\n /* eslint-disable @typescript-eslint/no-this-alias */\r\n const context = this;\r\n const later = function () {\r\n timeout = null;\r\n if (!immediate) func.apply(context, args);\r\n };\r\n const callNow = immediate && !timeout;\r\n clearTimeout(timeout as number);\r\n timeout = window.setTimeout(later, wait);\r\n if (callNow) func.apply(context, args);\r\n };\r\n}\r\n","export namespace StringUtils {\r\n /**\r\n * Formats a number by adding commas for thousands separator and truncating decimal places.\r\n *\r\n * @param {number} value - The number to format.\r\n * @param {boolean} useNbsp - Optional flag to use non-breaking space as a separator. Defaults to true.\r\n * @return {string} The formatted number with commas and optional non-breaking space separator.\r\n */\r\n export const formatNumber = (value: number, useNbsp = true): string => {\r\n if (typeof value !== \"number\") {\r\n return \"---\";\r\n }\r\n const ref = value.toFixed(2).split(\".\");\r\n let preComma = ref[0] || \"\";\r\n const postComma = ref[1];\r\n preComma = stringReverse((stringReverse(preComma).match(/.{1,3}/g) || [\"\"]).join(useNbsp ? \";psbn&\" : \" \"));\r\n\r\n return postComma != \"00\" ? preComma + \",\" + postComma : preComma;\r\n };\r\n\r\n /**\r\n * Formats a currency value by calling formatNumber and appending the currency symbol.\r\n *\r\n * @param {number} value - The value to format as currency.\r\n * @param {boolean} useNbsp - Optional flag to use non-breaking space as a separator. Defaults to true.\r\n * @return {string} The formatted currency value with the currency symbol.\r\n */\r\n export const formatCurrency = (value: number, useNbsp = true): string => {\r\n // this is also case for 0\r\n if (!value || isNaN(value)) {\r\n value = 0;\r\n }\r\n return `${formatNumber(value, useNbsp)}${useNbsp ? \" \" : \" \"}KÄŤ`;\r\n };\r\n\r\n /**\r\n * Limits the length of the text if it exceeds the specified limit by truncating and adding ellipsis.\r\n *\r\n * @param {string} text - The input text to limit.\r\n * @param {number} limit - The maximum length of the text before truncation. Defaults to 50.\r\n * @return {string} The text with limited length, potentially truncated with ellipsis.\r\n */\r\n export const limitTextLength = (text: string, limit = 50) => {\r\n if (text && text.length > limit) {\r\n return text.substring(0, limit - 3) + \"...\";\r\n }\r\n return text;\r\n };\r\n\r\n /**\r\n * Reverses the given string.\r\n *\r\n * @param {string} str - The string to be reversed.\r\n * @return {string} The reversed string.\r\n */\r\n export function stringReverse(str: string): string {\r\n return str.split(\"\").reverse().join(\"\");\r\n }\r\n\r\n /**\r\n * Converts given HTML text to plain text.\r\n *\r\n * @param {string} htmlText - The HTML text to be converted to plain text.\r\n * @return {string} The plain text.\r\n */\r\n export function getPlainTextFromHtml(htmlText: string): string {\r\n const tempDiv = document.createElement(\"div\");\r\n tempDiv.innerHTML = htmlText;\r\n return tempDiv.textContent || tempDiv.innerText || \"\";\r\n }\r\n\r\n /**\r\n * Sanitizes a string by removing HTML tags and replacing multiple whitespaces/newlines with a single space.\r\n */\r\n export function sanitizeString(input: string): string {\r\n return input\r\n .replace(/<[^>]*>/g, \"\") // Remove HTML tags\r\n .replace(/\\s+/g, \" \") // Replace multiple whitespaces/newlines with a single space\r\n .trim(); // Remove leading and trailing spaces\r\n }\r\n}\r\n","import { defineComponent as _defineComponent } from 'vue'\nimport { unref as _unref, createElementVNode as _createElementVNode, createVNode as _createVNode, normalizeClass as _normalizeClass, openBlock as _openBlock, createElementBlock as _createElementBlock, createCommentVNode as _createCommentVNode, toDisplayString as _toDisplayString, createTextVNode as _createTextVNode } from \"vue\"\n\nconst _hoisted_1 = { class: \"ds-product-card__inner\" }\nconst _hoisted_2 = [\"innerHTML\"]\nconst _hoisted_3 = {\n key: 0,\n class: \"ds-product-card-tag ds-product-card-tag--add-favorites ds-product-card__left-placeholder authenticated\"\n}\nconst _hoisted_4 = { class: \"ds-product-card-tag ds-product-card-tag--scratch ds-product-card__right-placeholder\" }\nconst _hoisted_5 = { class: \"ds-product-card-tag__wrapper ds-product-card-tag__text\" }\nconst _hoisted_6 = { class: \"ds-product-card__text-wrap\" }\nconst _hoisted_7 = [\"innerHTML\"]\nconst _hoisted_8 = [\"innerHTML\"]\nconst _hoisted_9 = [\"innerHTML\"]\nconst _hoisted_10 = [\"href\", \"data-game-id\", \"data-game-code\", \"data-price\", \"data-prize\", \"data-transparent\"]\n\nimport { TicketPromoCard } from \"@/tickets/models/ticket-promo-card\";\r\nimport { WebpHelper } from \"@sazka/utils/webp-helper\";\r\nimport { StringUtils } from \"@sazka/utils/string-utils\";\r\nimport DsIcon from \"@sazka/design-system/src/icon/ds-icon.vue\";\r\nimport { computed } from \"vue\";\r\nimport { useFavoriteTicketsStore } from \"../favorite-tickets-store\";\r\n\r\n\nexport default /*@__PURE__*/_defineComponent({\n __name: 'ticket-promo-card',\n props: {\n card: {}\n },\n setup(__props: any) {\n\r\nconst props = __props;\r\n\r\nconst store = useFavoriteTicketsStore();\r\nconst isFavorite = computed(() => store.isFavoriteTicket(props.card.externalSystemID));\r\nconst toggleFavorite = () => store.toggleFavoriteTicket(props.card.externalSystemID);\r\n\r\nconst prizeText = computed(() =>\r\n props.card.teaserPriceText ? props.card.teaserPriceText : StringUtils.formatCurrency(props.card.prize)\r\n);\r\n\nreturn (_ctx: any,_cache: any) => {\n return (_openBlock(), _createElementBlock(\"div\", {\n class: _normalizeClass([\"ds-product-card ds-product-card--portrait\", [\r\n _ctx.card.isOnline ? 'ds-product-card--eticket' : 'ds-product-card--ticket',\r\n { authenticated: _ctx.card.hideForNotLoggedUsers },\r\n ]])\n }, [\n _createElementVNode(\"div\", _hoisted_1, [\n _createElementVNode(\"div\", {\n innerHTML: \r\n _unref(WebpHelper).createPictureTag(_ctx.card.teaserImageUrl, `${_ctx.card.name} - obrázek`, 'ds-product-card__img')\r\n \n }, null, 8, _hoisted_2),\n _cache[2] || (_cache[2] = _createElementVNode(\"em\", { class: \"ds-product-card__gradient\" }, null, -1)),\n (_ctx.card.isOnline)\n ? (_openBlock(), _createElementBlock(\"div\", _hoisted_3, [\n _createElementVNode(\"button\", {\n class: _normalizeClass([\"ds-product-card-tag__button ds-product-card-tag__button--add-favorites\", { 'ds-product-card-tag__button--active': isFavorite.value }]),\n \"data-js-hook\": \"ds-product-card-add-favorites\"\n }, [\n _createVNode(DsIcon, {\n onClick: toggleFavorite,\n name: \"favorite-star-active\",\n width: 16,\n height: 16\n })\n ], 2)\n ]))\n : _createCommentVNode(\"\", true),\n _createElementVNode(\"div\", _hoisted_4, [\n _cache[1] || (_cache[1] = _createElementVNode(\"img\", {\n class: \"ds-product-card-tag__img\",\n src: \"/frontend/web/img/scrappers/scratch.svg\",\n height: \"39\",\n width: \"60\",\n alt: \"\"\n }, null, -1)),\n _createElementVNode(\"span\", _hoisted_5, [\n _createTextVNode(_toDisplayString(_ctx.card.roundPrice) + \" \", 1),\n _cache[0] || (_cache[0] = _createElementVNode(\"span\", { class: \"ds-product-card-tag__currency\" }, \"KÄŤ\", -1))\n ])\n ]),\n _createElementVNode(\"div\", _hoisted_6, [\n _createElementVNode(\"h3\", {\n class: \"ds-product-card__title\",\n innerHTML: _ctx.card.name\n }, null, 8, _hoisted_7),\n _createElementVNode(\"span\", {\n class: \"ds-product-card__sub-text\",\n innerHTML: _ctx.card.teaserText\n }, null, 8, _hoisted_8),\n _createElementVNode(\"span\", {\n class: \"ds-product-card__price\",\n innerHTML: prizeText.value\n }, null, 8, _hoisted_9)\n ]),\n _createElementVNode(\"a\", {\n href: _ctx.card.pageUrl.relative,\n class: _normalizeClass([\"ds-product-card__link\", { 'game-launcher': _ctx.card.isOnline }]),\n \"data-game-id\": _ctx.card.externalSystemID,\n \"data-game-code\": _ctx.card.codeName,\n \"data-price\": _ctx.card.roundPrice,\n \"data-prize\": _ctx.card.prizeFilter ? _ctx.card.prizeFilter : _ctx.card.prize,\n \"data-transparent\": _ctx.card.isTransparent\n }, null, 10, _hoisted_10)\n ])\n ], 2))\n}\n}\n\n})","<template>\r\n <div\r\n class=\"ds-product-card ds-product-card--portrait\"\r\n :class=\"[\r\n card.isOnline ? 'ds-product-card--eticket' : 'ds-product-card--ticket',\r\n { authenticated: card.hideForNotLoggedUsers },\r\n ]\"\r\n >\r\n <div class=\"ds-product-card__inner\">\r\n <div\r\n v-html=\"\r\n WebpHelper.createPictureTag(card.teaserImageUrl, `${card.name} - obrázek`, 'ds-product-card__img')\r\n \"\r\n ></div>\r\n <em class=\"ds-product-card__gradient\"></em>\r\n <div\r\n v-if=\"card.isOnline\"\r\n class=\"ds-product-card-tag ds-product-card-tag--add-favorites ds-product-card__left-placeholder authenticated\"\r\n >\r\n <!-- Top left slot -->\r\n <button\r\n class=\"ds-product-card-tag__button ds-product-card-tag__button--add-favorites\"\r\n :class=\"{ 'ds-product-card-tag__button--active': isFavorite }\"\r\n data-js-hook=\"ds-product-card-add-favorites\"\r\n >\r\n <DsIcon @click=\"toggleFavorite\" name=\"favorite-star-active\" :width=\"16\" :height=\"16\" />\r\n </button>\r\n </div>\r\n\r\n <div class=\"ds-product-card-tag ds-product-card-tag--scratch ds-product-card__right-placeholder\">\r\n <!-- Top right slot -->\r\n <img\r\n class=\"ds-product-card-tag__img\"\r\n src=\"/frontend/web/img/scrappers/scratch.svg\"\r\n height=\"39\"\r\n width=\"60\"\r\n alt=\"\"\r\n />\r\n <span class=\"ds-product-card-tag__wrapper ds-product-card-tag__text\"\r\n >{{ card.roundPrice }} <span class=\"ds-product-card-tag__currency\">KÄŤ</span></span\r\n >\r\n </div>\r\n\r\n <div class=\"ds-product-card__text-wrap\">\r\n <h3 class=\"ds-product-card__title\" v-html=\"card.name\"></h3>\r\n <span class=\"ds-product-card__sub-text\" v-html=\"card.teaserText\"></span>\r\n <span class=\"ds-product-card__price\" v-html=\"prizeText\"></span>\r\n </div>\r\n\r\n <a\r\n :href=\"card.pageUrl.relative\"\r\n class=\"ds-product-card__link\"\r\n :class=\"{ 'game-launcher': card.isOnline }\"\r\n :data-game-id=\"card.externalSystemID\"\r\n :data-game-code=\"card.codeName\"\r\n :data-price=\"card.roundPrice\"\r\n :data-prize=\"card.prizeFilter ? card.prizeFilter : card.prize\"\r\n :data-transparent=\"card.isTransparent\"\r\n >\r\n </a>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { TicketPromoCard } from \"@/tickets/models/ticket-promo-card\";\r\nimport { WebpHelper } from \"@sazka/utils/webp-helper\";\r\nimport { StringUtils } from \"@sazka/utils/string-utils\";\r\nimport DsIcon from \"@sazka/design-system/src/icon/ds-icon.vue\";\r\nimport { computed } from \"vue\";\r\nimport { useFavoriteTicketsStore } from \"../favorite-tickets-store\";\r\n\r\nconst props = defineProps<{\r\n card: TicketPromoCard;\r\n}>();\r\n\r\nconst store = useFavoriteTicketsStore();\r\nconst isFavorite = computed(() => store.isFavoriteTicket(props.card.externalSystemID));\r\nconst toggleFavorite = () => store.toggleFavoriteTicket(props.card.externalSystemID);\r\n\r\nconst prizeText = computed(() =>\r\n props.card.teaserPriceText ? props.card.teaserPriceText : StringUtils.formatCurrency(props.card.prize)\r\n);\r\n</script>\r\n","import script from \"./ticket-promo-card.vue?vue&type=script&setup=true&lang=ts\"\nexport * from \"./ticket-promo-card.vue?vue&type=script&setup=true&lang=ts\"\n\nconst __exports__ = script;\n\nexport default __exports__","import { defineComponent as _defineComponent } from 'vue'\nimport { renderList as _renderList, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, createCommentVNode as _createCommentVNode, createVNode as _createVNode, normalizeClass as _normalizeClass, toDisplayString as _toDisplayString, createTextVNode as _createTextVNode, withCtx as _withCtx, createBlock as _createBlock, createElementVNode as _createElementVNode } from \"vue\"\n\nconst _hoisted_1 = [\"id\"]\nconst _hoisted_2 = {\n key: 0,\n class: \"promo-content__overlay\"\n}\nconst _hoisted_3 = {\n key: 0,\n class: \"promo-content__gradient--radial\"\n}\nconst _hoisted_4 = {\n key: 1,\n class: \"promo-content__card-shadow\"\n}\nconst _hoisted_5 = {\n key: 2,\n class: \"promo-content__gradient--left\"\n}\nconst _hoisted_6 = {\n key: 3,\n class: \"promo-content__gradient--right\"\n}\nconst _hoisted_7 = { class: \"promo-content__cta\" }\n\nimport { computed, nextTick, onMounted, onUnmounted, ref, watch } from \"vue\";\r\nimport { useGsap } from \"@sazka/utils/gsap-register\";\r\nimport DsButton from \"@sazka/design-system/src/button/ds-button.vue\";\r\nimport { TicketPromoCard as TicketPromoCardModel } from \"@/tickets/models/ticket-promo-card\";\r\nimport TicketPromoCard from \"@/tickets/components/ticket-promo-card.vue\";\r\nimport { useBreakpoints } from \"@sazka/utils/composables/use-breakpoints\";\r\nimport { debounce } from \"@sazka/utils/debounce\";\r\nimport { ResponsiveUtils } from \"@sazka/utils/responsive-utils\";\r\nimport { OnlineTicketsCategoryPageAnalytics } from \"@/tickets/utils/online-tickets-analytics-category-page\";\r\nimport { checkedFilters, selectedSorting } from \"@/tickets/components/tickets-filter/tickets-filter-state\";\r\nimport breakpoints = ResponsiveUtils.breakpoints;\r\n\r\n// CONSTANTS\r\nconst BUTTON_SHUFFLE_TEXT = \"ZKUSTE Ĺ TÄšSTĂŤ\";\r\nconst BUTTON_SCRATCH_TEXT = \"SETĹĂŤT ONLINE\";\r\nconst BUTTON_RESHUFFLE_TEXT = \"JINĂť LOS\";\r\n\r\nconst DEFAULT_ANIMATION_DURATION = 24;\r\nconst DEFAULT_ANIMATION_CARD_SCALE = 0.8;\r\nconst DEFAULT_ANIMATION_ROTATION = 40;\r\nconst DRAW_ANIMATION_DURATION = 4;\r\nconst DRAW_ANIMATION_ROTATION_ANGLE = 1080;\r\nconst DRAW_ANIMATION_MAX_CARDS = 10;\r\n\r\nconst WIDGET_TARGET_ROW_PLACEMENT_MOBILE = 7;\r\n\r\n// VARIABLES\r\n\nexport default /*@__PURE__*/_defineComponent({\n __name: '_promo-content',\n setup(__props) {\n\r\nconst { gsap } = useGsap();\r\nlet ctx: gsap.Context;\r\nlet animations: gsap.core.Timeline[] = [];\r\nlet allTicketCards: TicketPromoCardModel[];\r\nlet lastWindowWidth = window.innerWidth;\r\n\r\nconst widget: HTMLElement = document.getElementById(\"random-recommendation-card\");\r\nconst cardList: HTMLElement = document.getElementById(\"card-list\");\r\nconst widgetsGrid: HTMLElement = document.getElementById(\"cp-widgets-section\");\r\n\r\n// REFS\r\nconst wrapper = ref<HTMLElement>();\r\nconst buttonBuy = ref<HTMLElement>();\r\nconst currentAnimationState = ref<\"default\" | \"draw\" | \"drawResult\">(\"default\");\r\nconst ticketCards = ref<TicketPromoCardModel[]>([]);\r\nconst defaultAnimationCardsVisibleCount = ref(8);\r\nconst isDesktop = useBreakpoints(\"lg\");\r\n\r\nconst isMobile = computed(() => {\r\n return !useBreakpoints(\"xs2\").value;\r\n});\r\n\r\nconst isWidgetInMobileLayout = computed(() => {\r\n return widget && cardList && widgetsGrid && isMobile.value;\r\n});\r\n\r\nlet wasWidgetInMobileLayout: boolean;\r\n\r\n// FUNCTIONS\r\nfunction handleShuffle() {\r\n currentAnimationState.value = \"draw\";\r\n\r\n OnlineTicketsCategoryPageAnalytics.pushRandomBetEvent();\r\n}\r\n\r\nfunction handleScratchTicketOnline(name: string) {\r\n OnlineTicketsCategoryPageAnalytics.pushShowProductEvent(name, BUTTON_SCRATCH_TEXT);\r\n}\r\n\r\nfunction handleReshuffle() {\r\n currentAnimationState.value = \"draw\";\r\n\r\n OnlineTicketsCategoryPageAnalytics.pushRandomBetEventAgain();\r\n}\r\n\r\n// Calculates delay before repeating the animation based on the number of cards and a constant count.\r\nfunction repeatDelay() {\r\n if (ticketCards.value.length < defaultAnimationCardsVisibleCount.value) {\r\n return 0;\r\n } else {\r\n return (\r\n (DEFAULT_ANIMATION_DURATION / defaultAnimationCardsVisibleCount.value) *\r\n (ticketCards.value.length - defaultAnimationCardsVisibleCount.value)\r\n );\r\n }\r\n}\r\n\r\n// Determines the time each card animation should seek to start at, for staggering effect.\r\nfunction seekTime() {\r\n if (ticketCards.value.length < defaultAnimationCardsVisibleCount.value) {\r\n return DEFAULT_ANIMATION_DURATION / ticketCards.value.length;\r\n } else {\r\n return DEFAULT_ANIMATION_DURATION / defaultAnimationCardsVisibleCount.value;\r\n }\r\n}\r\n\r\n// Randomly selects and shuffles up to DRAW_ANIMATION_MAX_CARDS elements from allTicketCards\r\nfunction selectAndShuffleCards(cards: TicketPromoCardModel[]): TicketPromoCardModel[] {\r\n const shuffled = cards.slice();\r\n const count = Math.min(cards.length, DRAW_ANIMATION_MAX_CARDS);\r\n let temp: TicketPromoCardModel;\r\n let i: number;\r\n let j: number;\r\n\r\n // Shuffle the copied array\r\n for (i = shuffled.length - 1; i > 0; i--) {\r\n j = Math.floor(Math.random() * (i + 1));\r\n temp = shuffled[i];\r\n shuffled[i] = shuffled[j];\r\n shuffled[j] = temp;\r\n }\r\n\r\n // Select up to DRAW_ANIMATION_MAX_CARDS from the shuffled array\r\n return shuffled.slice(0, count);\r\n}\r\n\r\nfunction defaultAnimation() {\r\n const wrapperWidth = wrapper.value.clientWidth;\r\n\r\n // Adjust total count of visible cards based on widget width and screen width\r\n if (wrapperWidth < 255 || window.innerWidth > breakpoints.lg) {\r\n defaultAnimationCardsVisibleCount.value = 7;\r\n } else if (wrapperWidth < 300) {\r\n defaultAnimationCardsVisibleCount.value = 8;\r\n } else if (wrapperWidth < 350) {\r\n defaultAnimationCardsVisibleCount.value = 9;\r\n } else if (wrapperWidth < 390) {\r\n defaultAnimationCardsVisibleCount.value = 10;\r\n } else if (wrapperWidth < 440) {\r\n defaultAnimationCardsVisibleCount.value = 11;\r\n } else if (wrapperWidth < 483) {\r\n defaultAnimationCardsVisibleCount.value = 12;\r\n } else {\r\n defaultAnimationCardsVisibleCount.value = 13;\r\n }\r\n\r\n const cards = document.querySelectorAll<HTMLDivElement>(\".promo-content__card\");\r\n const cardWidth = cards[0]?.clientWidth || 0;\r\n\r\n cards.forEach((_, index) => {\r\n const currentCard = `#promo-content__card--index-${index}`;\r\n\r\n const CARD_TL = gsap\r\n .timeline({\r\n repeat: -1,\r\n repeatDelay: repeatDelay(),\r\n })\r\n .set(currentCard, {\r\n x: wrapperWidth / 2 + cardWidth / 2,\r\n rotateY: DEFAULT_ANIMATION_ROTATION,\r\n opacity: 0,\r\n scale: DEFAULT_ANIMATION_CARD_SCALE,\r\n display: \"block\",\r\n })\r\n .to(currentCard, { opacity: 1, duration: 0.1 * DEFAULT_ANIMATION_DURATION }, 0)\r\n .to(\r\n currentCard,\r\n { opacity: 0, duration: 0.1 * DEFAULT_ANIMATION_DURATION },\r\n 0.9 * DEFAULT_ANIMATION_DURATION\r\n )\r\n .fromTo(\r\n currentCard,\r\n { x: -wrapperWidth / 2 - cardWidth / 2 },\r\n {\r\n x: wrapperWidth / 2 + cardWidth / 2,\r\n duration: DEFAULT_ANIMATION_DURATION,\r\n immediateRender: false,\r\n ease: \"power1.inOut\",\r\n },\r\n 0\r\n )\r\n .fromTo(\r\n currentCard,\r\n { rotateY: DEFAULT_ANIMATION_ROTATION },\r\n {\r\n rotateY: -DEFAULT_ANIMATION_ROTATION,\r\n immediateRender: false,\r\n duration: DEFAULT_ANIMATION_DURATION,\r\n ease: \"power2.inOut\",\r\n },\r\n 0\r\n )\r\n .to(\r\n currentCard,\r\n { z: 100, scale: 0.9, duration: 0.1 * DEFAULT_ANIMATION_DURATION, repeat: 1, yoyo: true },\r\n 0.4 * DEFAULT_ANIMATION_DURATION\r\n )\r\n .fromTo(\r\n currentCard,\r\n { zIndex: 1 },\r\n {\r\n zIndex: cards.length,\r\n repeat: 1,\r\n yoyo: true,\r\n ease: \"none\",\r\n duration: 0.5 * DEFAULT_ANIMATION_DURATION,\r\n immediateRender: false,\r\n },\r\n 0\r\n )\r\n .set(currentCard, {\r\n display: \"none\",\r\n })\r\n .seek(index * seekTime());\r\n\r\n animations.push(CARD_TL);\r\n });\r\n\r\n const tl = gsap.timeline({\r\n repeat: -1,\r\n });\r\n\r\n tl.to(\".promo-content__button-shuffle\", {\r\n keyframes: {\r\n scale: [1, 1.1, 1],\r\n },\r\n duration: 2,\r\n });\r\n\r\n animations.push(tl);\r\n}\r\n\r\nfunction drawAnimation() {\r\n const offsetAngle = 360 / ticketCards.value.length;\r\n const cards = document.querySelectorAll<HTMLDivElement>(\".promo-content__card\");\r\n const cardWidth = cards[0]?.clientWidth || 0;\r\n const cardHeight = cards[0]?.clientHeight || 0;\r\n const rotationCenter = isDesktop ? 350 : 275;\r\n\r\n const wrapperWidth = wrapper.value.clientWidth;\r\n const centerX = cardWidth / 2;\r\n const centerY = cardHeight / 2 + rotationCenter;\r\n\r\n ticketCards.value.forEach((_, index) => {\r\n const cardClass = `#promo-content__card--index-${index}`;\r\n const initialRotation = index * offsetAngle;\r\n\r\n const tl = gsap.timeline({ defaults: { ease: \"expo.out\", duration: DRAW_ANIMATION_DURATION } });\r\n\r\n tl.set(cardClass, {\r\n transformOrigin: `${centerX}px ${centerY}px`,\r\n });\r\n tl.set(\".promo-content__gradient--left\", {\r\n width: wrapperWidth / 2 - cardWidth / 2,\r\n });\r\n tl.set(\".promo-content__gradient--right\", {\r\n width: wrapperWidth / 2 - cardWidth / 2,\r\n });\r\n\r\n tl.fromTo(\r\n cardClass,\r\n {\r\n rotation: initialRotation,\r\n zIndex: 1,\r\n },\r\n {\r\n rotation: initialRotation + DRAW_ANIMATION_ROTATION_ANGLE,\r\n zIndex: 1,\r\n onComplete: () => {\r\n if (index === ticketCards.value.length - 1) {\r\n currentAnimationState.value = \"drawResult\";\r\n }\r\n },\r\n }\r\n ).seek(0.05);\r\n\r\n animations.push(tl);\r\n });\r\n}\r\n\r\nfunction drawResult() {\r\n const tl = gsap.timeline({ defaults: { ease: \"power4.out\", duration: 0.5 } });\r\n const cards = document.querySelectorAll<HTMLDivElement>(\".promo-content__card\");\r\n const cardWidth = cards[0]?.clientWidth || 0;\r\n const CARD_OFFSET = isDesktop ? 1.6 : 1.3;\r\n\r\n tl.to(\r\n \".promo-content__card-shadow\",\r\n {\r\n x: `-=${cardWidth / CARD_OFFSET}`,\r\n zIndex: 9,\r\n duration: 0.2,\r\n },\r\n \"<\"\r\n );\r\n\r\n ticketCards.value.forEach((_, index) => {\r\n tl.to(\r\n `#promo-content__card--index-${index}`,\r\n {\r\n x: `-=${cardWidth / CARD_OFFSET}`,\r\n zIndex: index === 0 ? 10 : 1,\r\n duration: 0.2,\r\n },\r\n \"<\"\r\n );\r\n });\r\n\r\n tl.to(\r\n \".promo-content__gradient--left\",\r\n {\r\n width: `-=${cardWidth}`,\r\n opacity: 0,\r\n },\r\n \"<\"\r\n );\r\n tl.to(\r\n \".promo-content__gradient--right\",\r\n {\r\n width: `+=${cardWidth}`,\r\n opacity: 0,\r\n },\r\n \"<\"\r\n );\r\n tl.from(\r\n \".promo-content__gradient--radial\",\r\n {\r\n opacity: 0,\r\n },\r\n \"<\"\r\n );\r\n\r\n tl.set(\".promo-content__button-buy\", {\r\n x: `+=${cardWidth / CARD_OFFSET}`,\r\n });\r\n tl.set(\".promo-content__button-reshuffle\", {\r\n x: `+=${cardWidth / CARD_OFFSET}`,\r\n });\r\n\r\n tl.from(\".promo-content__button-buy\", {\r\n opacity: 0,\r\n });\r\n\r\n tl.from(\".promo-content__button-reshuffle\", {\r\n opacity: 0,\r\n });\r\n\r\n animations.push(tl);\r\n}\r\n\r\nfunction killAnimations() {\r\n animations.forEach((animation) => {\r\n animation.revert();\r\n });\r\n animations = [];\r\n\r\n ticketCards.value.forEach((_, index) => {\r\n // Reset position and scale\r\n gsap.set(`#promo-content__card--index-${index}`, { x: 0, zIndex: 0, scale: 1 });\r\n });\r\n}\r\n\r\nfunction animate() {\r\n killAnimations();\r\n\r\n switch (currentAnimationState.value) {\r\n case \"default\":\r\n ctx = gsap.context(() => {\r\n defaultAnimation();\r\n });\r\n break;\r\n case \"draw\":\r\n ticketCards.value = selectAndShuffleCards(allTicketCards);\r\n\r\n ctx = gsap.context(() => {\r\n nextTick(() => {\r\n drawAnimation();\r\n });\r\n });\r\n break;\r\n case \"drawResult\":\r\n ctx = gsap.context(() => {\r\n nextTick(() => {\r\n drawResult();\r\n });\r\n });\r\n break;\r\n }\r\n}\r\n\r\nwatch(currentAnimationState, () => {\r\n nextTick(() => {\r\n animate();\r\n });\r\n});\r\n\r\nconst resetWidget = () => {\r\n nextTick(() => {\r\n if (isWidgetInMobileLayout.value) {\r\n appendWidgetToPage(widget, cardList);\r\n } else {\r\n appendWidgetToPage(widget, widgetsGrid);\r\n }\r\n });\r\n};\r\n\r\nconst handleResizeAndPlacement = debounce(() => {\r\n const windowWidthChanged = window.innerWidth !== lastWindowWidth;\r\n const layoutChanged = wasWidgetInMobileLayout !== isWidgetInMobileLayout.value;\r\n\r\n lastWindowWidth = window.innerWidth;\r\n wasWidgetInMobileLayout = isWidgetInMobileLayout.value;\r\n\r\n if (windowWidthChanged && !layoutChanged) {\r\n animate();\r\n return;\r\n }\r\n\r\n currentAnimationState.value = \"default\";\r\n ticketCards.value = fillCardsArray(allTicketCards);\r\n resetWidget();\r\n}, 200);\r\n\r\nwatch(\r\n checkedFilters,\r\n () => {\r\n resetWidget();\r\n },\r\n { deep: true }\r\n);\r\n\r\nwatch(selectedSorting, () => {\r\n resetWidget();\r\n});\r\n\r\nfunction fillCardsArray(cards: TicketPromoCardModel[]): TicketPromoCardModel[] {\r\n const timesToDuplicate = Math.ceil(13 / cards.length);\r\n\r\n let duplicatedCards = [];\r\n for (let i = 0; i < timesToDuplicate; i++) {\r\n duplicatedCards = duplicatedCards.concat([...cards]);\r\n }\r\n\r\n return duplicatedCards;\r\n}\r\n\r\nfunction appendWidgetToPage(targetElement: HTMLElement, container: HTMLElement) {\r\n targetElement.remove();\r\n\r\n if (!isMobile.value) {\r\n targetElement.style.gridColumn = \"unset\";\r\n container.appendChild(targetElement);\r\n return;\r\n }\r\n\r\n targetElement.style.gridColumn = \"1 / -1\";\r\n\r\n if (checkedFilters.value.length > 0) {\r\n container.appendChild(targetElement);\r\n return;\r\n }\r\n\r\n const style = window.getComputedStyle(container);\r\n const gridTemplateColumns = style.getPropertyValue(\"grid-template-columns\").split(\" \").length;\r\n\r\n const targetIndex = (WIDGET_TARGET_ROW_PLACEMENT_MOBILE - 1) * gridTemplateColumns;\r\n\r\n const allChildren = Array.from(container.children).filter((card) => {\r\n // Filter out authenticated \"invisible\" cards\r\n return window.getComputedStyle(card).display !== \"none\";\r\n });\r\n\r\n if (allChildren.length > targetIndex) {\r\n // One is deducted to account for the two-column first element\r\n container.insertBefore(targetElement, allChildren[targetIndex - 1]);\r\n } else {\r\n container.appendChild(targetElement);\r\n }\r\n}\r\n\r\n// LIFECYCLE HOOKS\r\nonMounted(() => {\r\n if (isWidgetInMobileLayout.value) {\r\n appendWidgetToPage(widget, cardList);\r\n }\r\n widget.style.display = \"block\";\r\n\r\n allTicketCards = (\r\n window as unknown as Window & {\r\n ticketsForRecommendation: TicketPromoCardModel[];\r\n }\r\n ).ticketsForRecommendation;\r\n\r\n allTicketCards = allTicketCards.filter((ticket) => !ticket.hideForNotLoggedUsers);\r\n ticketCards.value = fillCardsArray(allTicketCards);\r\n\r\n nextTick(() => {\r\n animate();\r\n });\r\n\r\n window.addEventListener(\"resize\", handleResizeAndPlacement);\r\n\r\n wasWidgetInMobileLayout = isWidgetInMobileLayout.value;\r\n});\r\n\r\nonUnmounted(() => {\r\n // Cleans up the GSAP context to prevent memory leaks\r\n ctx.revert();\r\n\r\n window.removeEventListener(\"resize\", handleResizeAndPlacement);\r\n});\r\n\nreturn (_ctx: any,_cache: any) => {\n return (_openBlock(), _createElementBlock(_Fragment, null, [\n _createElementVNode(\"div\", {\n class: _normalizeClass(['promo-content', [currentAnimationState.value === 'default' ? '' : 'promo-content--center']]),\n ref_key: \"wrapper\",\n ref: wrapper\n }, [\n (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(ticketCards.value, (card, index) => {\n return (_openBlock(), _createElementBlock(\"div\", {\n key: index,\n id: `promo-content__card--index-${index}`,\n class: _normalizeClass([\r\n 'promo-content__card',\r\n [currentAnimationState.value === 'default' ? 'promo-content__card--left' : 'promo-content__card--center'],\r\n ])\n }, [\n (currentAnimationState.value === 'default')\n ? (_openBlock(), _createElementBlock(\"div\", _hoisted_2))\n : _createCommentVNode(\"\", true),\n _createVNode(TicketPromoCard, {\n card: card,\n class: \"promo-content__inner-card\"\n }, null, 8, [\"card\"])\n ], 10, _hoisted_1))\n }), 128)),\n (currentAnimationState.value === 'drawResult')\n ? (_openBlock(), _createElementBlock(\"div\", _hoisted_3))\n : _createCommentVNode(\"\", true),\n (currentAnimationState.value !== 'default')\n ? (_openBlock(), _createElementBlock(\"div\", _hoisted_4))\n : _createCommentVNode(\"\", true),\n (currentAnimationState.value !== 'default')\n ? (_openBlock(), _createElementBlock(\"div\", _hoisted_5))\n : _createCommentVNode(\"\", true),\n (currentAnimationState.value !== 'default')\n ? (_openBlock(), _createElementBlock(\"div\", _hoisted_6))\n : _createCommentVNode(\"\", true),\n _createElementVNode(\"div\", _hoisted_7, [\n (currentAnimationState.value === 'drawResult')\n ? (_openBlock(), _createBlock(DsButton, {\n key: 0,\n type: \"primary\",\n size: \"sm\",\n href: ticketCards.value[0].pageUrl.relative,\n class: _normalizeClass([\"promo-content__button-buy\", { 'game-launcher': ticketCards.value[0].isOnline }]),\n \"data-game-id\": ticketCards.value[0].externalSystemID,\n \"data-game-code\": ticketCards.value[0].codeName,\n ref_key: \"buttonBuy\",\n ref: buttonBuy,\n onClick: _cache[0] || (_cache[0] = ($event: any) => (handleScratchTicketOnline(ticketCards.value[0].codeName)))\n }, {\n default: _withCtx(() => [\n _createTextVNode(_toDisplayString(BUTTON_SCRATCH_TEXT))\n ]),\n _: 1\n }, 8, [\"href\", \"class\", \"data-game-id\", \"data-game-code\"]))\n : _createCommentVNode(\"\", true),\n (currentAnimationState.value === 'drawResult')\n ? (_openBlock(), _createBlock(DsButton, {\n key: 1,\n type: \"interaction\",\n size: \"sm\",\n \"icon-left\": \"rotate-thin\",\n onClick: handleReshuffle,\n class: \"promo-content__button-reshuffle\",\n ref: \"buttonShuffle\"\n }, {\n default: _withCtx(() => [\n _createTextVNode(_toDisplayString(BUTTON_RESHUFFLE_TEXT))\n ]),\n _: 1\n }, 512))\n : _createCommentVNode(\"\", true)\n ])\n ], 2),\n (currentAnimationState.value === 'default')\n ? (_openBlock(), _createBlock(DsButton, {\n key: 0,\n type: \"primary\",\n theme: \"dark\",\n size: \"sm\",\n \"icon-left\": \"heart-thin\",\n onClick: handleShuffle,\n class: \"promo-content__button-shuffle\"\n }, {\n default: _withCtx(() => [\n _createTextVNode(_toDisplayString(BUTTON_SHUFFLE_TEXT))\n ]),\n _: 1\n }))\n : _createCommentVNode(\"\", true)\n ], 64))\n}\n}\n\n})","<template>\r\n <div :class=\"['promo-content', [currentAnimationState === 'default' ? '' : 'promo-content--center']]\" ref=\"wrapper\">\r\n <div\r\n v-for=\"(card, index) in ticketCards\"\r\n :key=\"index\"\r\n :id=\"`promo-content__card--index-${index}`\"\r\n :class=\"[\r\n 'promo-content__card',\r\n [currentAnimationState === 'default' ? 'promo-content__card--left' : 'promo-content__card--center'],\r\n ]\"\r\n >\r\n <div v-if=\"currentAnimationState === 'default'\" class=\"promo-content__overlay\"></div>\r\n <TicketPromoCard :card=\"card\" class=\"promo-content__inner-card\" />\r\n </div>\r\n\r\n <div v-if=\"currentAnimationState === 'drawResult'\" class=\"promo-content__gradient--radial\"></div>\r\n <div v-if=\"currentAnimationState !== 'default'\" class=\"promo-content__card-shadow\"></div>\r\n <div v-if=\"currentAnimationState !== 'default'\" class=\"promo-content__gradient--left\"></div>\r\n <div v-if=\"currentAnimationState !== 'default'\" class=\"promo-content__gradient--right\"></div>\r\n\r\n <div class=\"promo-content__cta\">\r\n <DsButton\r\n v-if=\"currentAnimationState === 'drawResult'\"\r\n type=\"primary\"\r\n size=\"sm\"\r\n :href=\"ticketCards[0].pageUrl.relative\"\r\n class=\"promo-content__button-buy\"\r\n :class=\"{ 'game-launcher': ticketCards[0].isOnline }\"\r\n :data-game-id=\"ticketCards[0].externalSystemID\"\r\n :data-game-code=\"ticketCards[0].codeName\"\r\n ref=\"buttonBuy\"\r\n @click=\"handleScratchTicketOnline(ticketCards[0].codeName)\"\r\n >{{ BUTTON_SCRATCH_TEXT }}\r\n </DsButton>\r\n\r\n <DsButton\r\n v-if=\"currentAnimationState === 'drawResult'\"\r\n type=\"interaction\"\r\n size=\"sm\"\r\n icon-left=\"rotate-thin\"\r\n @click=\"handleReshuffle\"\r\n class=\"promo-content__button-reshuffle\"\r\n ref=\"buttonShuffle\"\r\n >{{ BUTTON_RESHUFFLE_TEXT }}\r\n </DsButton>\r\n </div>\r\n </div>\r\n\r\n <DsButton\r\n v-if=\"currentAnimationState === 'default'\"\r\n type=\"primary\"\r\n theme=\"dark\"\r\n size=\"sm\"\r\n icon-left=\"heart-thin\"\r\n @click=\"handleShuffle\"\r\n class=\"promo-content__button-shuffle\"\r\n >{{ BUTTON_SHUFFLE_TEXT }}\r\n </DsButton>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, nextTick, onMounted, onUnmounted, ref, watch } from \"vue\";\r\nimport { useGsap } from \"@sazka/utils/gsap-register\";\r\nimport DsButton from \"@sazka/design-system/src/button/ds-button.vue\";\r\nimport { TicketPromoCard as TicketPromoCardModel } from \"@/tickets/models/ticket-promo-card\";\r\nimport TicketPromoCard from \"@/tickets/components/ticket-promo-card.vue\";\r\nimport { useBreakpoints } from \"@sazka/utils/composables/use-breakpoints\";\r\nimport { debounce } from \"@sazka/utils/debounce\";\r\nimport { ResponsiveUtils } from \"@sazka/utils/responsive-utils\";\r\nimport { OnlineTicketsCategoryPageAnalytics } from \"@/tickets/utils/online-tickets-analytics-category-page\";\r\nimport { checkedFilters, selectedSorting } from \"@/tickets/components/tickets-filter/tickets-filter-state\";\r\nimport breakpoints = ResponsiveUtils.breakpoints;\r\n\r\n// CONSTANTS\r\nconst BUTTON_SHUFFLE_TEXT = \"ZKUSTE Ĺ TÄšSTĂŤ\";\r\nconst BUTTON_SCRATCH_TEXT = \"SETĹĂŤT ONLINE\";\r\nconst BUTTON_RESHUFFLE_TEXT = \"JINĂť LOS\";\r\n\r\nconst DEFAULT_ANIMATION_DURATION = 24;\r\nconst DEFAULT_ANIMATION_CARD_SCALE = 0.8;\r\nconst DEFAULT_ANIMATION_ROTATION = 40;\r\nconst DRAW_ANIMATION_DURATION = 4;\r\nconst DRAW_ANIMATION_ROTATION_ANGLE = 1080;\r\nconst DRAW_ANIMATION_MAX_CARDS = 10;\r\n\r\nconst WIDGET_TARGET_ROW_PLACEMENT_MOBILE = 7;\r\n\r\n// VARIABLES\r\nconst { gsap } = useGsap();\r\nlet ctx: gsap.Context;\r\nlet animations: gsap.core.Timeline[] = [];\r\nlet allTicketCards: TicketPromoCardModel[];\r\nlet lastWindowWidth = window.innerWidth;\r\n\r\nconst widget: HTMLElement = document.getElementById(\"random-recommendation-card\");\r\nconst cardList: HTMLElement = document.getElementById(\"card-list\");\r\nconst widgetsGrid: HTMLElement = document.getElementById(\"cp-widgets-section\");\r\n\r\n// REFS\r\nconst wrapper = ref<HTMLElement>();\r\nconst buttonBuy = ref<HTMLElement>();\r\nconst currentAnimationState = ref<\"default\" | \"draw\" | \"drawResult\">(\"default\");\r\nconst ticketCards = ref<TicketPromoCardModel[]>([]);\r\nconst defaultAnimationCardsVisibleCount = ref(8);\r\nconst isDesktop = useBreakpoints(\"lg\");\r\n\r\nconst isMobile = computed(() => {\r\n return !useBreakpoints(\"xs2\").value;\r\n});\r\n\r\nconst isWidgetInMobileLayout = computed(() => {\r\n return widget && cardList && widgetsGrid && isMobile.value;\r\n});\r\n\r\nlet wasWidgetInMobileLayout: boolean;\r\n\r\n// FUNCTIONS\r\nfunction handleShuffle() {\r\n currentAnimationState.value = \"draw\";\r\n\r\n OnlineTicketsCategoryPageAnalytics.pushRandomBetEvent();\r\n}\r\n\r\nfunction handleScratchTicketOnline(name: string) {\r\n OnlineTicketsCategoryPageAnalytics.pushShowProductEvent(name, BUTTON_SCRATCH_TEXT);\r\n}\r\n\r\nfunction handleReshuffle() {\r\n currentAnimationState.value = \"draw\";\r\n\r\n OnlineTicketsCategoryPageAnalytics.pushRandomBetEventAgain();\r\n}\r\n\r\n// Calculates delay before repeating the animation based on the number of cards and a constant count.\r\nfunction repeatDelay() {\r\n if (ticketCards.value.length < defaultAnimationCardsVisibleCount.value) {\r\n return 0;\r\n } else {\r\n return (\r\n (DEFAULT_ANIMATION_DURATION / defaultAnimationCardsVisibleCount.value) *\r\n (ticketCards.value.length - defaultAnimationCardsVisibleCount.value)\r\n );\r\n }\r\n}\r\n\r\n// Determines the time each card animation should seek to start at, for staggering effect.\r\nfunction seekTime() {\r\n if (ticketCards.value.length < defaultAnimationCardsVisibleCount.value) {\r\n return DEFAULT_ANIMATION_DURATION / ticketCards.value.length;\r\n } else {\r\n return DEFAULT_ANIMATION_DURATION / defaultAnimationCardsVisibleCount.value;\r\n }\r\n}\r\n\r\n// Randomly selects and shuffles up to DRAW_ANIMATION_MAX_CARDS elements from allTicketCards\r\nfunction selectAndShuffleCards(cards: TicketPromoCardModel[]): TicketPromoCardModel[] {\r\n const shuffled = cards.slice();\r\n const count = Math.min(cards.length, DRAW_ANIMATION_MAX_CARDS);\r\n let temp: TicketPromoCardModel;\r\n let i: number;\r\n let j: number;\r\n\r\n // Shuffle the copied array\r\n for (i = shuffled.length - 1; i > 0; i--) {\r\n j = Math.floor(Math.random() * (i + 1));\r\n temp = shuffled[i];\r\n shuffled[i] = shuffled[j];\r\n shuffled[j] = temp;\r\n }\r\n\r\n // Select up to DRAW_ANIMATION_MAX_CARDS from the shuffled array\r\n return shuffled.slice(0, count);\r\n}\r\n\r\nfunction defaultAnimation() {\r\n const wrapperWidth = wrapper.value.clientWidth;\r\n\r\n // Adjust total count of visible cards based on widget width and screen width\r\n if (wrapperWidth < 255 || window.innerWidth > breakpoints.lg) {\r\n defaultAnimationCardsVisibleCount.value = 7;\r\n } else if (wrapperWidth < 300) {\r\n defaultAnimationCardsVisibleCount.value = 8;\r\n } else if (wrapperWidth < 350) {\r\n defaultAnimationCardsVisibleCount.value = 9;\r\n } else if (wrapperWidth < 390) {\r\n defaultAnimationCardsVisibleCount.value = 10;\r\n } else if (wrapperWidth < 440) {\r\n defaultAnimationCardsVisibleCount.value = 11;\r\n } else if (wrapperWidth < 483) {\r\n defaultAnimationCardsVisibleCount.value = 12;\r\n } else {\r\n defaultAnimationCardsVisibleCount.value = 13;\r\n }\r\n\r\n const cards = document.querySelectorAll<HTMLDivElement>(\".promo-content__card\");\r\n const cardWidth = cards[0]?.clientWidth || 0;\r\n\r\n cards.forEach((_, index) => {\r\n const currentCard = `#promo-content__card--index-${index}`;\r\n\r\n const CARD_TL = gsap\r\n .timeline({\r\n repeat: -1,\r\n repeatDelay: repeatDelay(),\r\n })\r\n .set(currentCard, {\r\n x: wrapperWidth / 2 + cardWidth / 2,\r\n rotateY: DEFAULT_ANIMATION_ROTATION,\r\n opacity: 0,\r\n scale: DEFAULT_ANIMATION_CARD_SCALE,\r\n display: \"block\",\r\n })\r\n .to(currentCard, { opacity: 1, duration: 0.1 * DEFAULT_ANIMATION_DURATION }, 0)\r\n .to(\r\n currentCard,\r\n { opacity: 0, duration: 0.1 * DEFAULT_ANIMATION_DURATION },\r\n 0.9 * DEFAULT_ANIMATION_DURATION\r\n )\r\n .fromTo(\r\n currentCard,\r\n { x: -wrapperWidth / 2 - cardWidth / 2 },\r\n {\r\n x: wrapperWidth / 2 + cardWidth / 2,\r\n duration: DEFAULT_ANIMATION_DURATION,\r\n immediateRender: false,\r\n ease: \"power1.inOut\",\r\n },\r\n 0\r\n )\r\n .fromTo(\r\n currentCard,\r\n { rotateY: DEFAULT_ANIMATION_ROTATION },\r\n {\r\n rotateY: -DEFAULT_ANIMATION_ROTATION,\r\n immediateRender: false,\r\n duration: DEFAULT_ANIMATION_DURATION,\r\n ease: \"power2.inOut\",\r\n },\r\n 0\r\n )\r\n .to(\r\n currentCard,\r\n { z: 100, scale: 0.9, duration: 0.1 * DEFAULT_ANIMATION_DURATION, repeat: 1, yoyo: true },\r\n 0.4 * DEFAULT_ANIMATION_DURATION\r\n )\r\n .fromTo(\r\n currentCard,\r\n { zIndex: 1 },\r\n {\r\n zIndex: cards.length,\r\n repeat: 1,\r\n yoyo: true,\r\n ease: \"none\",\r\n duration: 0.5 * DEFAULT_ANIMATION_DURATION,\r\n immediateRender: false,\r\n },\r\n 0\r\n )\r\n .set(currentCard, {\r\n display: \"none\",\r\n })\r\n .seek(index * seekTime());\r\n\r\n animations.push(CARD_TL);\r\n });\r\n\r\n const tl = gsap.timeline({\r\n repeat: -1,\r\n });\r\n\r\n tl.to(\".promo-content__button-shuffle\", {\r\n keyframes: {\r\n scale: [1, 1.1, 1],\r\n },\r\n duration: 2,\r\n });\r\n\r\n animations.push(tl);\r\n}\r\n\r\nfunction drawAnimation() {\r\n const offsetAngle = 360 / ticketCards.value.length;\r\n const cards = document.querySelectorAll<HTMLDivElement>(\".promo-content__card\");\r\n const cardWidth = cards[0]?.clientWidth || 0;\r\n const cardHeight = cards[0]?.clientHeight || 0;\r\n const rotationCenter = isDesktop ? 350 : 275;\r\n\r\n const wrapperWidth = wrapper.value.clientWidth;\r\n const centerX = cardWidth / 2;\r\n const centerY = cardHeight / 2 + rotationCenter;\r\n\r\n ticketCards.value.forEach((_, index) => {\r\n const cardClass = `#promo-content__card--index-${index}`;\r\n const initialRotation = index * offsetAngle;\r\n\r\n const tl = gsap.timeline({ defaults: { ease: \"expo.out\", duration: DRAW_ANIMATION_DURATION } });\r\n\r\n tl.set(cardClass, {\r\n transformOrigin: `${centerX}px ${centerY}px`,\r\n });\r\n tl.set(\".promo-content__gradient--left\", {\r\n width: wrapperWidth / 2 - cardWidth / 2,\r\n });\r\n tl.set(\".promo-content__gradient--right\", {\r\n width: wrapperWidth / 2 - cardWidth / 2,\r\n });\r\n\r\n tl.fromTo(\r\n cardClass,\r\n {\r\n rotation: initialRotation,\r\n zIndex: 1,\r\n },\r\n {\r\n rotation: initialRotation + DRAW_ANIMATION_ROTATION_ANGLE,\r\n zIndex: 1,\r\n onComplete: () => {\r\n if (index === ticketCards.value.length - 1) {\r\n currentAnimationState.value = \"drawResult\";\r\n }\r\n },\r\n }\r\n ).seek(0.05);\r\n\r\n animations.push(tl);\r\n });\r\n}\r\n\r\nfunction drawResult() {\r\n const tl = gsap.timeline({ defaults: { ease: \"power4.out\", duration: 0.5 } });\r\n const cards = document.querySelectorAll<HTMLDivElement>(\".promo-content__card\");\r\n const cardWidth = cards[0]?.clientWidth || 0;\r\n const CARD_OFFSET = isDesktop ? 1.6 : 1.3;\r\n\r\n tl.to(\r\n \".promo-content__card-shadow\",\r\n {\r\n x: `-=${cardWidth / CARD_OFFSET}`,\r\n zIndex: 9,\r\n duration: 0.2,\r\n },\r\n \"<\"\r\n );\r\n\r\n ticketCards.value.forEach((_, index) => {\r\n tl.to(\r\n `#promo-content__card--index-${index}`,\r\n {\r\n x: `-=${cardWidth / CARD_OFFSET}`,\r\n zIndex: index === 0 ? 10 : 1,\r\n duration: 0.2,\r\n },\r\n \"<\"\r\n );\r\n });\r\n\r\n tl.to(\r\n \".promo-content__gradient--left\",\r\n {\r\n width: `-=${cardWidth}`,\r\n opacity: 0,\r\n },\r\n \"<\"\r\n );\r\n tl.to(\r\n \".promo-content__gradient--right\",\r\n {\r\n width: `+=${cardWidth}`,\r\n opacity: 0,\r\n },\r\n \"<\"\r\n );\r\n tl.from(\r\n \".promo-content__gradient--radial\",\r\n {\r\n opacity: 0,\r\n },\r\n \"<\"\r\n );\r\n\r\n tl.set(\".promo-content__button-buy\", {\r\n x: `+=${cardWidth / CARD_OFFSET}`,\r\n });\r\n tl.set(\".promo-content__button-reshuffle\", {\r\n x: `+=${cardWidth / CARD_OFFSET}`,\r\n });\r\n\r\n tl.from(\".promo-content__button-buy\", {\r\n opacity: 0,\r\n });\r\n\r\n tl.from(\".promo-content__button-reshuffle\", {\r\n opacity: 0,\r\n });\r\n\r\n animations.push(tl);\r\n}\r\n\r\nfunction killAnimations() {\r\n animations.forEach((animation) => {\r\n animation.revert();\r\n });\r\n animations = [];\r\n\r\n ticketCards.value.forEach((_, index) => {\r\n // Reset position and scale\r\n gsap.set(`#promo-content__card--index-${index}`, { x: 0, zIndex: 0, scale: 1 });\r\n });\r\n}\r\n\r\nfunction animate() {\r\n killAnimations();\r\n\r\n switch (currentAnimationState.value) {\r\n case \"default\":\r\n ctx = gsap.context(() => {\r\n defaultAnimation();\r\n });\r\n break;\r\n case \"draw\":\r\n ticketCards.value = selectAndShuffleCards(allTicketCards);\r\n\r\n ctx = gsap.context(() => {\r\n nextTick(() => {\r\n drawAnimation();\r\n });\r\n });\r\n break;\r\n case \"drawResult\":\r\n ctx = gsap.context(() => {\r\n nextTick(() => {\r\n drawResult();\r\n });\r\n });\r\n break;\r\n }\r\n}\r\n\r\nwatch(currentAnimationState, () => {\r\n nextTick(() => {\r\n animate();\r\n });\r\n});\r\n\r\nconst resetWidget = () => {\r\n nextTick(() => {\r\n if (isWidgetInMobileLayout.value) {\r\n appendWidgetToPage(widget, cardList);\r\n } else {\r\n appendWidgetToPage(widget, widgetsGrid);\r\n }\r\n });\r\n};\r\n\r\nconst handleResizeAndPlacement = debounce(() => {\r\n const windowWidthChanged = window.innerWidth !== lastWindowWidth;\r\n const layoutChanged = wasWidgetInMobileLayout !== isWidgetInMobileLayout.value;\r\n\r\n lastWindowWidth = window.innerWidth;\r\n wasWidgetInMobileLayout = isWidgetInMobileLayout.value;\r\n\r\n if (windowWidthChanged && !layoutChanged) {\r\n animate();\r\n return;\r\n }\r\n\r\n currentAnimationState.value = \"default\";\r\n ticketCards.value = fillCardsArray(allTicketCards);\r\n resetWidget();\r\n}, 200);\r\n\r\nwatch(\r\n checkedFilters,\r\n () => {\r\n resetWidget();\r\n },\r\n { deep: true }\r\n);\r\n\r\nwatch(selectedSorting, () => {\r\n resetWidget();\r\n});\r\n\r\nfunction fillCardsArray(cards: TicketPromoCardModel[]): TicketPromoCardModel[] {\r\n const timesToDuplicate = Math.ceil(13 / cards.length);\r\n\r\n let duplicatedCards = [];\r\n for (let i = 0; i < timesToDuplicate; i++) {\r\n duplicatedCards = duplicatedCards.concat([...cards]);\r\n }\r\n\r\n return duplicatedCards;\r\n}\r\n\r\nfunction appendWidgetToPage(targetElement: HTMLElement, container: HTMLElement) {\r\n targetElement.remove();\r\n\r\n if (!isMobile.value) {\r\n targetElement.style.gridColumn = \"unset\";\r\n container.appendChild(targetElement);\r\n return;\r\n }\r\n\r\n targetElement.style.gridColumn = \"1 / -1\";\r\n\r\n if (checkedFilters.value.length > 0) {\r\n container.appendChild(targetElement);\r\n return;\r\n }\r\n\r\n const style = window.getComputedStyle(container);\r\n const gridTemplateColumns = style.getPropertyValue(\"grid-template-columns\").split(\" \").length;\r\n\r\n const targetIndex = (WIDGET_TARGET_ROW_PLACEMENT_MOBILE - 1) * gridTemplateColumns;\r\n\r\n const allChildren = Array.from(container.children).filter((card) => {\r\n // Filter out authenticated \"invisible\" cards\r\n return window.getComputedStyle(card).display !== \"none\";\r\n });\r\n\r\n if (allChildren.length > targetIndex) {\r\n // One is deducted to account for the two-column first element\r\n container.insertBefore(targetElement, allChildren[targetIndex - 1]);\r\n } else {\r\n container.appendChild(targetElement);\r\n }\r\n}\r\n\r\n// LIFECYCLE HOOKS\r\nonMounted(() => {\r\n if (isWidgetInMobileLayout.value) {\r\n appendWidgetToPage(widget, cardList);\r\n }\r\n widget.style.display = \"block\";\r\n\r\n allTicketCards = (\r\n window as unknown as Window & {\r\n ticketsForRecommendation: TicketPromoCardModel[];\r\n }\r\n ).ticketsForRecommendation;\r\n\r\n allTicketCards = allTicketCards.filter((ticket) => !ticket.hideForNotLoggedUsers);\r\n ticketCards.value = fillCardsArray(allTicketCards);\r\n\r\n nextTick(() => {\r\n animate();\r\n });\r\n\r\n window.addEventListener(\"resize\", handleResizeAndPlacement);\r\n\r\n wasWidgetInMobileLayout = isWidgetInMobileLayout.value;\r\n});\r\n\r\nonUnmounted(() => {\r\n // Cleans up the GSAP context to prevent memory leaks\r\n ctx.revert();\r\n\r\n window.removeEventListener(\"resize\", handleResizeAndPlacement);\r\n});\r\n</script>\r\n","import script from \"./_promo-content.vue?vue&type=script&setup=true&lang=ts\"\nexport * from \"./_promo-content.vue?vue&type=script&setup=true&lang=ts\"\n\nconst __exports__ = script;\n\nexport default __exports__"],"names":["checkedFilters","ref","selectedSorting","TicketsSortingOptions","Default","sortedFiltersString","computed","value","sort","a","b","join","useTicketsFilterHelper","addFilter","num","includes","push","removeFilter","filter","item","fetchFavoriteTickets","async","response","httpClient","get","data","createFavoriteTicket","ticketResponse","post","externalSystemID","error","_axiosError$response","axiosError","status","showAlert","title","deleteFavoriteTicket","delete","useFavoriteTicketsStore","defineStore","favoriteTickets","favoriteTicketsIds","getFavoriteTicket","find","ticket","isFavoriteTicket","loadFavoriteTickets","favoriteTicketsResponse","api","map","id","toggleFavoriteTicket","OnlineTicketsCategoryPageAnalytics","pushLosyLobbyPage","window","dataLayer","page","type","kind","verticalCode","verticalCodeStrict","gameCode","gameCodeStrict","OnlineTicketsPlacement","pushTicketClick","placement","position","filterValues","product","dataLayerPayload","event","action","show","products","AllScratches","eventProperty1","eventProperty2","pushRandomBetEvent","pushShowProductEvent","buttonText","button","pushRandomBetEventAgain","pushLobbyFilterGameList","filteredValues","applyFilter","label","pushLobbySortGameList","sortingType","pushActionImpressProducts","impress","pushActionImpressProductsTicketFamily","index","initialized","reactiveBreakpoints","useBreakpoints","breakpoints","length","initialize","reduce","acc","x","reactiveBreakpoint","Object","keys","ResponsiveUtils","isInUse","key","minSize","breakpoint","brkpnt","media","matchMedia","matches","onchange","e","debounce","func","wait","immediate","timeout","args","context","this","later","apply","callNow","clearTimeout","setTimeout","StringUtils","stringReverse","str","split","reverse","getPlainTextFromHtml","htmlText","tempDiv","document","createElement","innerHTML","textContent","innerText","sanitizeString","input","replace","trim","formatNumber","useNbsp","toFixed","preComma","postComma","match","formatCurrency","isNaN","limitTextLength","text","limit","substring","_hoisted_1","class","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_defineComponent","__name","props","card","setup","__props","store","isFavorite","toggleFavorite","prizeText","teaserPriceText","prize","_ctx","_cache","_openBlock","_createElementBlock","_normalizeClass","isOnline","authenticated","hideForNotLoggedUsers","_createElementVNode","_unref","WebpHelper","createPictureTag","teaserImageUrl","name","_createVNode","DsIcon","onClick","width","height","_createCommentVNode","src","alt","_createTextVNode","_toDisplayString","roundPrice","teaserText","href","pageUrl","relative","codeName","prizeFilter","isTransparent","__exports__","BUTTON_SHUFFLE_TEXT","BUTTON_SCRATCH_TEXT","BUTTON_RESHUFFLE_TEXT","DEFAULT_ANIMATION_DURATION","DEFAULT_ANIMATION_CARD_SCALE","DEFAULT_ANIMATION_ROTATION","DRAW_ANIMATION_DURATION","DRAW_ANIMATION_ROTATION_ANGLE","DRAW_ANIMATION_MAX_CARDS","WIDGET_TARGET_ROW_PLACEMENT_MOBILE","gsap","useGsap","ctx","allTicketCards","animations","lastWindowWidth","innerWidth","widget","getElementById","cardList","widgetsGrid","wrapper","buttonBuy","currentAnimationState","ticketCards","defaultAnimationCardsVisibleCount","isDesktop","isMobile","isWidgetInMobileLayout","wasWidgetInMobileLayout","handleShuffle","handleScratchTicketOnline","handleReshuffle","repeatDelay","seekTime","selectAndShuffleCards","cards","shuffled","slice","count","Math","min","temp","i","j","floor","random","defaultAnimation","_cards$","wrapperWidth","clientWidth","lg","querySelectorAll","cardWidth","forEach","_","currentCard","CARD_TL","timeline","repeat","set","rotateY","opacity","scale","display","to","duration","fromTo","immediateRender","ease","z","yoyo","zIndex","seek","tl","keyframes","drawAnimation","_cards$2","_cards$3","offsetAngle","cardHeight","clientHeight","rotationCenter","centerX","centerY","cardClass","initialRotation","defaults","transformOrigin","rotation","onComplete","drawResult","_cards$4","CARD_OFFSET","from","killAnimations","animation","revert","animate","nextTick","watch","resetWidget","appendWidgetToPage","handleResizeAndPlacement","windowWidthChanged","layoutChanged","fillCardsArray","timesToDuplicate","ceil","duplicatedCards","concat","targetElement","container","remove","style","gridColumn","appendChild","getComputedStyle","gridTemplateColumns","getPropertyValue","targetIndex","allChildren","Array","children","insertBefore","deep","onMounted","ticketsForRecommendation","addEventListener","onUnmounted","removeEventListener","_Fragment","ref_key","_renderList","TicketPromoCard","_createBlock","DsButton","size","$event","default","_withCtx","theme"],"sourceRoot":""}