{"version":3,"sources":["webpack:///./src/EbaySweden.TouchWeb/static/script/packages/debounce.js","webpack:///./src/EbaySweden.TouchWeb/static/script/packages/in-viewport.js","webpack:///./src/EbaySweden.TouchWeb/static/script/packages/format.js","webpack:///./src/EbaySweden.TouchWeb/static/script/packages/logger.js","webpack:///./src/frontend/lang/translate.jsx","webpack:///./src/frontend/constants/endpoints.js","webpack:///./src/frontend/lang/boot-languages.js","webpack:///./src/frontend/services/socket-io-channel.js","webpack:///./src/frontend/utils/http.js","webpack:///./src/frontend/constants/hosts.js","webpack:///./src/frontend/utils/url.js","webpack:///./src/frontend/utils/format.js","webpack:///./src/frontend/services/toast-queue.js","webpack:///./src/frontend/components/toasts/item-toast.module.scss","webpack:///./src/frontend/components/toasts/item-toast.jsx","webpack:///./src/frontend/services/toasts.js","webpack:///./src/frontend/services/boot-site-wide-notifications.js","webpack:///./src/EbaySweden.TouchWeb/static/script/app.js","webpack:///./src/EbaySweden.TouchWeb/static/script/packages/init-data.js","webpack:///./src/frontend/apps/syi/script/app_react/utils/language.js","webpack:///./src/EbaySweden.TouchWeb/static/script/utils/modules.js","webpack:///./src/frontend/state/environment/reducer.js","webpack:///./src/frontend/utils/api.js","webpack:///./src/frontend/state/environment/actions.js","webpack:///./src/frontend/components/alink/alink.jsx","webpack:///./src/EbaySweden.TouchWeb/static/script/packages/analytics.js","webpack:///./src/EbaySweden.TouchWeb/static/script/app/ui/google-tagmanager-service.js"],"names":["debounce","func","wait","immediate","timeout","context","this","args","arguments","later","apply","callNow","clearTimeout","isLocaleFormattingSupportedInBrowser","toLocaleString","e","name","toLocaleStringSupportsLocales","Intl","NumberFormat","formatNumber","number","format","formatMe","undefined","logger","error","scope","sentryException","Error","Sentry","useTranslator","useTranslation","t","ready","withTranslator","WrappedComponent","WithTranslator","props","displayName","withUrlLocalizer","WithUrlLocalizer","toLocalizedUrl","useUrlLocalizer","useCurrentLanguage","i18n","language","urlLocalizer","useRef","url","current","webApiUrl","initData","touchWebUrl","AVAILABLE_SHIPPING_COUNTRIES","BANK_ID_AUTHENTICATE","BANK_ID_PROGRESS","BRAND_LIST_PAGE","BRAND_PAGE","CAMPAIGN","campaignId","replace","CART_UPDATE_SUMMARY","CART_OVERVIEW_VIEW","CART_ADD_ITEM","CART_REMOVE_ITEMS","CART_SET_ITEM_QUANTITY","CHARITY_EARNINGS_TICKER","CMS_API","cmsApiUrl","COMBINED_SHIPPING_UPSELL","FAVORITE_SELLER_ADD","FAVORITE_SELLER_REMOVE","FAVOURITE_SELLERS","FAVOURITE_SELLERS_JSON","GEO_PUBLIC_API_URL","geoPublicApiUrl","GET_PROFILE_FEEDBACK_ITEMS","HYPERWALLET_PAYOUT_COMPLETE","HYPERWALLET_PAYOUT_TOKEN","HYPERWALLET_PAYOUT","INTERNATIONAL_SHIPPING_CALCULATOR","ITEM_DESCRIPTION","itemId","ITEM_DISCOUNT_QUOTA","LAST_CHANCE","LIVE_SHOPPING_PUBLIC_API","MEMBER_PAYOUT_SETTINGS_REMOVE","MEMBER_PAYOUT_SETTINGS","MEMBER_SYSTEM_MESSAGES","ORDER_CHECKOUT_AUTH_DATA","ORDER_CHECKOUT_BRAINTREE","ORDER_CHECKOUT_COMPLETE_PAYMENT","ORDER_CHECKOUT_CONFIRMATION","ORDER_CHECKOUT_INIT_PAYMENT","ORDER_CHECKOUT_PAYMENT_OPTIONS","ORDER_CHECKOUT_PAYMENT_STATUS","ORDER_CHECKOUT_PAYMENT","orderCheckoutPaymentUrl","ORDER_CHECKOUT_VIEW","ORDER_CHECKOUT_REQUEST_COMBINED_PRICE","ORDER_CHECKOUT_CANCEL_PAYMENT","ORDER_CHECKOUT_CREATE_UNCOMMITTED_PURCHASE_ORDER","ORDER_PURCHASE_BIN","ORDER_PURCHASE_SHOP_ITEMS","PAYMENT_SWISH_OPTOUT","PERSONALISED_SUGGESTIONS","SEARCH_SUGGESTIONS","SEARCH","SELLING_ATTRIBUTES","SELLING_CAMPAING_CODE","SELLING_CATEGORY_RESTRICTIONS","SELLING_DRAFT_LOAD_FROM_TEMPLATE","SELLING_DRAFT_SAVE","SELLING_DRAFT","draftId","SELLING_DRAFTS_DELETE","SELLING_DRAFTS","SELLING_ITEM_PUBLISH","SELLING_ITEM_STATUS","SELLING_ITEM_UPDATE","SELLING_PREVIEW","SELLING_SCRIBE_DURATION","SELLING_SCRIBE_INCREMENT","SELLING_SCRIBE_SESSION_DURATION","SELLING_SCRIBE_SESSION_START","SELLING_SCRIBE_VALIDATION_ERRORS","SELLING_SHIPPING_CALCULATOR","SELLING_SUGGEST_ATTRIBUTES","SELLING_TEMPLATE_SAVE","SELLING_TEMPLATE","templateId","SELLING_TEMPLATES_COUNT","SELLING_TEMPLATES_DELETE","SELLING_TEMPLATES","SETTINGS","SHIPPING_PROVIDERS","TOUCHWEB_URL","TRANSLATE_PROFILE_FEEDBACKITEMS","WEB_API","WISHLIST","WISHLIST_ADD","WISHLIST_REMOVE","START_OFF_PLATFORM_CHECKOUT","UPI","purchaseOrderId","INR","PURCHASE_ORDER","MARKETING_PUBLIC_API","i18nInitialized","bootLanguages","translations","window","touchwebTranslations","attributeTranslations","options","translationResources","key","value","namespace","attributeResources","resources","prev","s","use","initReactI18next","LanguageDetector","init","detection","order","htmlTag","document","html","defaultNS","ns","fallbackLng","debug","keySeparator","interpolation","escape","str","formatNumberWithSeparators","react","useSuspense","missingKeyLoggingConfig","err","saveMissing","saveMissingTo","missingKeyHandler","missingInterpolationHandler","text","whenInitialized","then","getCurrentLanguage","MissingSocketIoServerUrl","ReferenceError","MissingRoomId","SocketIoChannel","constructor","socketIoServerUrl","socket","io","autoConnect","events","rooms","on","room","join","payload","Type","callback","Event","contexts","socketIo","type","connect","isConnected","emit","has","add","leave","rejoinOnConnect","delete","addEventListener","event","removeEventListener","off","connected","disconnect","httpClient","baseUrl","shouldLocalizeUrl","axiosWrapper","httpClientConfig","axiosCaller","cancelTokenId","axiosConfig","version","utilizeCancelToken","cancel","cancelToken","safeUrl","substring","getSafeUrl","localizedUrl","getLanguage","axiosWithTokenRefresh","checkResponseVersion","response","finalizeResponse","catch","handleError","get","axiosConfigs","authenticated","axios","config","post","put","defaultClient","touchWebClient","webApiClient","ENDPOINTS","liveShoppingApiClient","marketingApiClient","SPA_PATH_REGEX","RegExp","SUPPORTED_LANGUAGES","formatQueryParams","queryParams","categoryId","formattedQueryParams","isSpaLink","urlOrPath","pathname","test","stripCategoryIdFromQueryParameters","stripHost","HOSTS","stripItmFromQueryParameters","itm_source","itm_medium","stripPaginationFromQueryParameters","spage","paging","page","fe","stripSavedQueryNameFromQueryParameters","savedQueryName","toAbsoluteUrl","relativeUrl","toAbsoluteUrlFromObject","search","languageCodeIso2","ignoredUrls","domain","isAbsolute","isAbsoluteUrl","urlObject","origin","localisedPathname","setLanguagePrefix","toQueryParameters","qs","parse","ignoreQueryPrefix","toRelativeTraderaUrl","toSearchString","addQueryPrefix","encode","skipNulls","arrayFormat","stringify","path","languagePrefix","matches","match","firstMatch","index","getLanguagePrefixFromUrl","getBackToHereRedirectUrl","location","forceRedirect","Math","round","random","protocol","host","formatDuration","durationInSeconds","minuteBreakpoint","floor","separator","toString","Number","formatPrice","price","locale","formattedPrice","opts","style","currency","currencyDisplay","useGrouping","minimumFractionDigits","maximumFractionDigits","formatDateWithDayOfWeek","dateString","weekday","year","month","day","DateTimeFormat","Date","items","inProgress","ItemToast","imageUrl","itemUrl","shortDescription","eventData","useLink","href","className","styles","src","title","alt","ToastMessage","message","newLeadingBidAmount","timeLeftMinutes","queuedToasts","item","ttlInMinutes","timeStamp","push","next","itemData","shift","notifyDone","isInProgress","getLength","length","openNextToast","a","nextItem","data","queueLength","toast","React","createElement","autoClose","max","onClose","handleNotification","visibilityState","showItemOutbiddedToast","showItemFirstBidToast","showItemSoldToast","showItemWonToast","showItemPaidToast","showItemWishListReminderToast","refreshLoginState","isLoggedIn","gtm","loadGtmScript","featureSwitches","socketUrl","joinMemberRoom","isRetry","success","ItemId","NewLeadingBidAmount","Price","TimeLeftMinutes","bootSiteWideNotifications","siteWideNotificationsEventPusherServerUrl","memberId","module","split","isSpaModule","loadSpaModule","initModule","default","loadModule","loadedModule","runModule","body","setAttribute","handleModuleError","initDataEL","getElementById","getAttribute","JSON","getInitData","toLocalizedRiotUrl","querySelector","discoverEnabled","isSinglePageApp","console","slice","createSlice","initialState","reducers","setEnvironmentHash","state","environmentHash","setIsSpaNavigationEnabled","isSpaNavigationEnabled","actions","reducer","API_ERRORS","IGNORE_ME","ABORTED","CANCELLED","NETWORK","TIMEOUT","VERSION_MISMATCH","LOGGED_OUT","defaultJsonRequestHeaders","Accept","withCredentials","headers","notAuthenticated","isUnauthorized","statusCode","submitOriginalRequest","antiCacheRegExp","getTime","handleMissingAuthToken","refreshAccessToken","handleErrorAfterRefresh","errorAfterRefreshToken","request","status","reject","handleUnauthorized","checkLoginState","errorResponseInterceptor","responseString","responseStatus","errorCode","isMissingAuthToken","axiosInstance","instance","create","interceptors","cancelTokens","tokenId","CancelToken","source","token","checkResponseLoggedOut","statusHandlers","isCancel","reloadOnUnauthorized","reload","logError","updateEnvironmentHash","dispatch","getState","environment","ALink","children","givenOnClick","onClick","otherProps","useDispatch","useSelector","to","evt","propTypes","defaultProps","pushToDataLayer","dataLayer","trackPageView","ga","isNonInteractive","analyticsData","userTriggered","trackTiming","category","variable","label","trackEvent","eventCategory","eventAction","action","eventLabel","eventValue","eventNonInteractive","hitCallback","level","Info","spaPageViewTrackingEnabled","_newPageFromServer","w","d","l","i","f","getElementsByTagName","j","async","parentNode","insertBefore","_getDatalayerObject","output","entry","_reset","newSpaPage","pageType","_pushInitialDataLayer","legacyDataLayer","_buildFromInitData","userLanguage","memberEmail","memberHashedEmail","memberEmailSha256","memberEmailMd5","memberFirstName","memberLastName","memberCountry","loginState","isNotInIframe","self","top","blueshiftEventApiKey","isNativeAppContext","isQuantcastConsentEnabled","isDigitalAudienceTrackingEnabled","quantcastSite","initialDataLayer","splitTestGroups","trackAction","nonInteractive","trackGtmEvent","eventName","trackLinkClickAndCallback","eventCallback","trackLinkClickAndGotoUrl"],"mappings":"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","file":"script/chunks/chunk.default~info.01a3f1da77.js","sourcesContent":["/**\n * Debounce function\n * Borrowed from underscore;\n */\nconst debounce = function(func, wait, immediate) {\n let timeout;\n return function() {\n let context = this,\n args = arguments;\n let later = function() {\n timeout = null;\n if (!immediate) {\n func.apply(context, args);\n }\n };\n let callNow = immediate && !timeout;\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n if (callNow) {\n func.apply(context, args);\n }\n };\n};\n\nexport default debounce;\n","const inViewport = (selector, callback, options, ...args) => {\n const El = Array.from(document.querySelectorAll(selector));\n\n if (El) {\n if ('IntersectionObserver' in window) {\n let defaultOptions = {\n root: null,\n rootMargin: '0px',\n threshold: 0\n };\n\n let observer = new IntersectionObserver(\n entries => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n callback(entry.target, args);\n observer.unobserve(entry.target);\n }\n });\n },\n { defaultOptions, ...options }\n );\n\n El.forEach(app => {\n observer.observe(app);\n });\n } else {\n callback(El[0], args);\n }\n }\n};\n\nexport default inViewport;\n","// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString\nfunction toLocaleStringSupportsLocales() {\n let number = 0;\n try {\n number.toLocaleString('i');\n } catch (e) {\n return e.name === 'RangeError';\n }\n return false;\n}\n\n// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString\nfunction toLocaleStringSupportsOptions() {\n return !!(\n typeof Intl === 'object' &&\n Intl &&\n typeof Intl.NumberFormat === 'function'\n );\n}\n\nconst isLocaleFormattingSupportedInBrowser =\n toLocaleStringSupportsLocales() && toLocaleStringSupportsOptions();\n\nexport const formatPrice = price => {\n if (!isLocaleFormattingSupportedInBrowser) {\n return typeof price !== 'number'\n ? `${parseInt(price)} kr`\n : `${price} kr`;\n }\n\n const format = formatMe =>\n formatMe.toLocaleString('sv-SE', {\n symbol: ' kr',\n symbolPosition: 'end',\n decimal: ',',\n comma: '.'\n });\n return typeof price !== 'number'\n ? `${format(parseInt(price))} kr`\n : `${format(price)} kr`;\n};\n\nexport const formatNumber = number => {\n if (!isLocaleFormattingSupportedInBrowser) {\n return typeof number !== 'number' ? `${parseInt(number)}` : `${number}`;\n }\n\n const format = formatMe => formatMe.toLocaleString('sv-SE');\n\n return number !== undefined\n ? typeof number !== 'number'\n ? format(parseInt(number))\n : format(number)\n : '';\n};\n\nexport const formatUserRating = rating => {\n if (!rating) return;\n const number = parseFloat(rating);\n if (number <= 0) return '0.0';\n if (number >= 5) return '5.0';\n return number.toFixed(1);\n};\n","import * as Sentry from '@sentry/browser';\n\n/**\n * @param {object} error - takes an exception and logs to Sentry or the console in development\n * @param {object} [scope] - Sentry CaptureContext created with new Sentry.Scope() or plain object\n * @desc logger is designed for logging errors. It will accept an argument of any type and create a stacktrace containing a reference to the callee.\n * @TODO Migrate this functionality to a logging module that handles different levels of logs\n */\nconst logger = (error, scope) => {\n let sentryException;\n if (error instanceof Error) {\n sentryException = error;\n } else if (typeof error === 'string') {\n sentryException = new Error(error);\n } else {\n sentryException = new Error(JSON.stringify(error));\n }\n if (scope) {\n Sentry.captureException(sentryException, scope);\n } else {\n Sentry.captureException(sentryException);\n }\n};\n\nexport default logger;\n","import React, { useRef } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { toLocalizedUrl } from 'tradera-utils/url';\n\n/**\n * i18next translation wrappers for translating static text in react components\n * When to use what?\n * -----\n * 1. For functional components use `useTranslator()` hook\n * 2. For class components use `withTranslator()` HOC\n */\n\n/**\n * Translation hook, wrapper for react-i18next\n * @return {{t: Function}}\n */\nexport const useTranslator = () => {\n const { t, ready } = useTranslation(['touchWeb', 'attributes'], {\n wait: true\n });\n return { t: ready ? t : () => '...' };\n};\n\n/**\n * Translation HOC, wrapper for react-i18next\n * @param {Component} WrappedComponent\n * @return {Component} The wrapped component.\n */\nexport function withTranslator(WrappedComponent) {\n function WithTranslator(props) {\n const { t } = useTranslator();\n return ;\n }\n\n WithTranslator.displayName = `withTranslator(${WrappedComponent.displayName ||\n WrappedComponent.name}`;\n return WithTranslator;\n}\n\n/**\n * Localization HOC, wrapper for URL-localizer\n * @param {Component} WrappedComponent\n */\nexport function withUrlLocalizer(WrappedComponent) {\n function WithUrlLocalizer(props) {\n const { toLocalizedUrl } = useUrlLocalizer();\n return ;\n }\n\n WithUrlLocalizer.displayName = `withUrlLocalizer(${WrappedComponent.displayName ||\n WrappedComponent.name}`;\n\n return WithUrlLocalizer;\n}\n\n/**\n * Current language hook, wrapper for react-i18next\n * @return {{language: string}}\n */\nexport const useCurrentLanguage = () => {\n const { i18n, ready } = useTranslation(undefined, { wait: true });\n return {\n language: ready ? i18n.language : null\n };\n};\n\n/**\n * Returns function to append language prefix to link\n * @return {{toLocalizedUrl: function}}\n */\nexport const useUrlLocalizer = () => {\n const { i18n, ready } = useTranslation(undefined, { wait: true });\n const urlLocalizer = useRef(url => toLocalizedUrl(url, i18n.language));\n return { toLocalizedUrl: ready ? urlLocalizer.current : url => url };\n};\n","import initData from 'init-data';\n\nconst { webApiUrl, touchWebUrl } = initData;\n\nexport default {\n AVAILABLE_SHIPPING_COUNTRIES:\n webApiUrl + '/member/getavailablecountriesforshipping',\n BANK_ID_AUTHENTICATE: touchWebUrl + 'bankid/authenticate',\n BANK_ID_PROGRESS: touchWebUrl + 'bankid/progress',\n BRAND_LIST_PAGE: touchWebUrl + 'brands/api',\n BRAND_PAGE: touchWebUrl + 'brand/api/',\n CAMPAIGN: campaignId =>\n touchWebUrl +\n 'campaign/api/{campaignId}'.replace('{campaignId}', campaignId),\n CART_UPDATE_SUMMARY: touchWebUrl + 'shopping/managecart/updatecartsummary',\n CART_OVERVIEW_VIEW: webApiUrl + '/shopping/checkout/cartoverview',\n CART_ADD_ITEM: webApiUrl + '/shopping/cart/item',\n CART_REMOVE_ITEMS: webApiUrl + '/shopping/cart/removeitems',\n CART_SET_ITEM_QUANTITY: webApiUrl + '/shopping/cart/setitemquantity',\n CHARITY_EARNINGS_TICKER:\n touchWebUrl + 'cache/kampanjer/earningsticker/earnings',\n CMS_API: initData.cmsApiUrl,\n COMBINED_SHIPPING_UPSELL: touchWebUrl + 'combined-shipping-upsell/items',\n FAVORITE_SELLER_ADD: touchWebUrl + 'my/favourite-sellers/add',\n FAVORITE_SELLER_REMOVE: touchWebUrl + 'my/favourite-sellers/remove',\n FAVOURITE_SELLERS: touchWebUrl + 'startpage/favourite-sellers',\n FAVOURITE_SELLERS_JSON: touchWebUrl + 'favourite-sellers.json',\n GEO_PUBLIC_API_URL: initData.geoPublicApiUrl,\n GET_PROFILE_FEEDBACK_ITEMS: touchWebUrl + 'profile/model',\n HYPERWALLET_PAYOUT_COMPLETE:\n webApiUrl + '/member/paymentprovider/completehyperwallettransfermethod',\n HYPERWALLET_PAYOUT_TOKEN:\n webApiUrl + '/member/paymentprovider/hyperwalletauthenticationtoken',\n HYPERWALLET_PAYOUT:\n webApiUrl +\n '/member/paymentprovider/hyperwallettransfermethodviewmodel',\n INTERNATIONAL_SHIPPING_CALCULATOR:\n webApiUrl + '/browse/internationalshippingcalculator',\n ITEM_DESCRIPTION: itemId =>\n `${webApiUrl}/browse/item/${itemId}/description`,\n ITEM_DISCOUNT_QUOTA: touchWebUrl + 'profile/shop-item-settings/quotas',\n LAST_CHANCE: touchWebUrl + 'StartPage/LastChance',\n LIVE_SHOPPING_PUBLIC_API: '/api/live',\n MEMBER_PAYOUT_SETTINGS_REMOVE:\n webApiUrl + '/member/profile/removetraderapaypayoutdestination',\n MEMBER_PAYOUT_SETTINGS:\n webApiUrl + '/member/paymentprovider/memberpayoutsettingsviewmodel',\n MEMBER_SYSTEM_MESSAGES: webApiUrl + '/member/system-messages',\n ORDER_CHECKOUT_AUTH_DATA:\n webApiUrl +\n '/shopping/ordercheckout/purchaseorderpaymentattemptauthenticationdata',\n ORDER_CHECKOUT_BRAINTREE:\n webApiUrl + '/shopping/ordercheckout/purchaseorderbraintreeclienttoken',\n ORDER_CHECKOUT_COMPLETE_PAYMENT:\n webApiUrl +\n '/shopping/ordercheckout/completepurchaseorderpaymentattempt',\n ORDER_CHECKOUT_CONFIRMATION:\n webApiUrl +\n '/shopping/ordercheckout/purchaseordercheckoutconfirmationviewmodel',\n ORDER_CHECKOUT_INIT_PAYMENT:\n webApiUrl +\n '/shopping/ordercheckout/initializepurchaseorderpaymentattempt',\n ORDER_CHECKOUT_PAYMENT_OPTIONS:\n webApiUrl + '/shopping/ordercheckout/purchaseorderpaymentoptions',\n ORDER_CHECKOUT_PAYMENT_STATUS:\n webApiUrl + '/shopping/ordercheckout/purchaseorderpaymentattemptstatus',\n ORDER_CHECKOUT_PAYMENT: initData.orderCheckoutPaymentUrl,\n ORDER_CHECKOUT_VIEW:\n webApiUrl + '/shopping/ordercheckout/purchaseordercheckoutviewmodel',\n ORDER_CHECKOUT_REQUEST_COMBINED_PRICE:\n webApiUrl + '/shopping/ordercheckout/requestcombinedshippingprice',\n ORDER_CHECKOUT_CANCEL_PAYMENT:\n webApiUrl + '/shopping/ordercheckout/cancelpurchaseorderpaymentattempt',\n ORDER_CHECKOUT_CREATE_UNCOMMITTED_PURCHASE_ORDER:\n webApiUrl + '/shopping/ordercheckout/createuncommittedpurchaseorder',\n ORDER_PURCHASE_BIN: webApiUrl + '/shopping/ordercheckout/purchasebin',\n ORDER_PURCHASE_SHOP_ITEMS:\n webApiUrl + '/shopping/ordercheckout/purchaseshopitems',\n PAYMENT_SWISH_OPTOUT: touchWebUrl + 'my/payments2/OptOut',\n PERSONALISED_SUGGESTIONS: '/api/personalised-suggestions',\n SEARCH_SUGGESTIONS: touchWebUrl + 'search/suggestions',\n SEARCH: touchWebUrl + 'search',\n SELLING_ATTRIBUTES: webApiUrl + '/selling/attributes',\n SELLING_CAMPAING_CODE: touchWebUrl + 'selling/api/campaign',\n SELLING_CATEGORY_RESTRICTIONS: webApiUrl + '/selling/category-restriction',\n SELLING_DRAFT_LOAD_FROM_TEMPLATE:\n touchWebUrl + 'selling/api/drafts/from-template',\n SELLING_DRAFT_SAVE: touchWebUrl + 'selling/api/drafts/',\n SELLING_DRAFT: draftId => touchWebUrl + `selling/api/drafts/${draftId}`,\n SELLING_DRAFTS_DELETE: touchWebUrl + 'selling/api/drafts/delete',\n SELLING_DRAFTS: touchWebUrl + 'selling/api/drafts/',\n SELLING_ITEM_PUBLISH: touchWebUrl + 'selling/api/items',\n SELLING_ITEM_STATUS: itemId =>\n touchWebUrl + `selling/api/items/${itemId}/status`,\n SELLING_ITEM_UPDATE: itemId =>\n touchWebUrl + `selling/api/items/${itemId}/update`,\n SELLING_PREVIEW: draftId =>\n touchWebUrl + `selling/api/drafts/preview/${draftId}`,\n SELLING_SCRIBE_DURATION: touchWebUrl + 'selling/api/scribe/duration',\n SELLING_SCRIBE_INCREMENT: touchWebUrl + 'selling/api/scribe/increment',\n SELLING_SCRIBE_SESSION_DURATION:\n touchWebUrl + 'selling/api/scribe/session-duration',\n SELLING_SCRIBE_SESSION_START:\n touchWebUrl + 'selling/api/scribe/session-start',\n SELLING_SCRIBE_VALIDATION_ERRORS:\n touchWebUrl + 'selling/api/scribe/form-validation-errors',\n SELLING_SHIPPING_CALCULATOR: touchWebUrl + 'selling/shippingcalculator',\n SELLING_SUGGEST_ATTRIBUTES: webApiUrl + '/selling/suggest/attributes',\n SELLING_TEMPLATE_SAVE: touchWebUrl + 'selling/api/templates',\n SELLING_TEMPLATE: templateId =>\n touchWebUrl + `selling/api/templates/${templateId}`,\n SELLING_TEMPLATES_COUNT: touchWebUrl + 'selling/api/templates-count',\n SELLING_TEMPLATES_DELETE: touchWebUrl + 'selling/api/templates/delete',\n SELLING_TEMPLATES: touchWebUrl + 'selling/api/templates',\n SETTINGS: touchWebUrl + 'profile/shop-item-settings/settings',\n SHIPPING_PROVIDERS: webApiUrl + '/selling/shippingproviderswithproducts',\n TOUCHWEB_URL: touchWebUrl,\n TRANSLATE_PROFILE_FEEDBACKITEMS: webApiUrl + '/member/feedback/translated',\n WEB_API: webApiUrl,\n WISHLIST: touchWebUrl + 'my/api/wish-list',\n WISHLIST_ADD: touchWebUrl + 'shopping/wishlist/add',\n WISHLIST_REMOVE: touchWebUrl + 'shopping/wishlist/remove',\n START_OFF_PLATFORM_CHECKOUT:\n touchWebUrl + 'shopping/cartoverview/StartCheckoutSession',\n UPI: purchaseOrderId =>\n webApiUrl + '/member/uppo-strike/?PurchaseOrderId=' + purchaseOrderId,\n INR: purchaseOrderId =>\n webApiUrl + '/member/ponr-strike/?PurchaseOrderId=' + purchaseOrderId,\n PURCHASE_ORDER: purchaseOrderId =>\n webApiUrl + '/member/purchaseorder/?PurchaseOrderId=' + purchaseOrderId,\n MARKETING_PUBLIC_API: '/api/marketing'\n};\n","import i18n from 'i18next';\nimport { logger } from 'packages';\nimport { initReactI18next } from 'react-i18next';\nimport LanguageDetector from 'i18next-browser-languagedetector';\nimport { toLocalizedUrl } from 'tradera-utils/url';\nimport { formatNumberWithSeparators } from 'tradera-utils/format';\nimport 'dayjs/locale/sv';\nimport 'dayjs/locale/da';\nimport 'dayjs/locale/de';\n\nlet i18nInitialized;\n\n/**\n * Initialize function for i18next\n * Must be run before doing any translations\n * @param {Array} [translations]\n * @param {Object} [options]\n * @returns {Promise} - a promise to the i18next t function\n */\nexport const bootLanguages = (\n translations = window.touchwebTranslations,\n attributeTranslations = window.attributeTranslations,\n options = {}\n) => {\n const translationResources = Object.entries(translations).map(\n ([key, value]) => ({\n key,\n value,\n namespace: 'touchWeb'\n })\n );\n const attributeResources = Object.entries(\n attributeTranslations\n ).map(([key, value]) => ({ key, value, namespace: 'attributes' }));\n\n const resources = translationResources\n .concat(attributeResources)\n .reduce((prev, { key, value, namespace }) => {\n const s = prev[key] || {};\n s[namespace] = value;\n return {\n ...prev,\n [key]: s\n };\n }, {});\n\n i18nInitialized = i18n\n .use(initReactI18next)\n .use(LanguageDetector)\n .init(\n {\n detection: {\n order: ['htmlTag'],\n htmlTag: document.html\n },\n defaultNS: ['touchWeb'],\n ns: ['attributes'],\n fallbackLng: 'sv',\n resources,\n debug: false,\n keySeparator: false,\n interpolation: {\n escape: str => str.replace(/{{/g, '').replace(/}}/g, ''),\n format: (value, format) => {\n if (format === 'formatNumber') {\n return formatNumberWithSeparators(value);\n }\n\n return value;\n }\n },\n react: {\n useSuspense: false // loading from file currently breaks if this is true\n },\n ...missingKeyLoggingConfig,\n ...options\n },\n err => {\n if (err) {\n logger('error when loading translations', err);\n }\n }\n );\n\n return i18nInitialized;\n};\n\nconst missingKeyLoggingConfig = {\n saveMissing: true,\n saveMissingTo: 'current',\n missingKeyHandler: (language, namespace, key) => {\n logger(\n `TranslationMissing (javascript) - Unable to find key ${key} (namespace ${namespace}) in language ${language}!`\n );\n },\n missingInterpolationHandler: (text, value) => {\n logger(\n `InterpolationFailure (javascript) - Unable to interpolate the text \"${text}\" fully. The following placeholder values were missing: ${JSON.stringify(\n value\n )}`\n );\n return undefined;\n }\n};\n\n/**\n * This function helps you make sure that i18next init has completed before continuing\n */\nexport const whenInitialized = () => {\n if (!i18nInitialized) {\n throw new Error(\n \"Can't call boot-languages whenInitialized before init!\"\n );\n }\n return i18nInitialized.then(t => ({\n t,\n toLocalizedUrl: url => toLocalizedUrl(url, i18n.language)\n }));\n};\n\n/**\n * Only required for Storybook, do not use.\n */\nexport const changeLanguage = language => i18n.changeLanguage(language);\n\nexport const getCurrentLanguage = () => i18n.language;\n","import io from 'socket.io-client';\nimport logger from 'packages/logger';\n\nexport class MissingSocketIoServerUrl extends ReferenceError {}\nexport class MissingRoomId extends ReferenceError {}\n\n/**\n * Connect to a socket.io channel & add callbacks for events it broadcasts\n * @param {string} socketIoServerUrl\n */\nexport class SocketIoChannel {\n constructor(socketIoServerUrl) {\n if (!socketIoServerUrl) {\n throw new MissingSocketIoServerUrl();\n }\n this.socket = io(socketIoServerUrl, {\n autoConnect: false\n });\n this.events = {};\n this.rooms = new Set();\n\n this.socket.on('connect', () => {\n // Rejoin room on reconnect if network connection is lost\n this.rooms.forEach(room => this.join(room));\n });\n\n this.socket.on('clientEvent', payload => {\n if (!payload.Type) {\n logger('socket.io missing clientEvent Type', {\n contexts: {\n socketIo: {\n payload\n }\n }\n });\n return;\n }\n const callback = this.events[payload.Type];\n if (callback) {\n callback(payload.Event, this);\n } else {\n logger(`socket.io unknown clientEvent type`, {\n contexts: {\n socketIo: {\n type: payload.Type\n }\n }\n });\n }\n });\n }\n\n connect() {\n if (!this.isConnected()) this.socket.connect();\n }\n\n join(room) {\n if (!room) {\n throw new MissingRoomId();\n }\n if (this.isConnected()) {\n this.socket.emit('join', room);\n }\n if (!this.rooms.has(room)) {\n // Queue join until connect\n this.rooms.add(room);\n }\n }\n\n leave(room, rejoinOnConnect = false) {\n if (!room) {\n throw new MissingRoomId();\n }\n if (this.isConnected() && this.rooms.has(room)) {\n this.socket.emit('leave', room);\n }\n if (!rejoinOnConnect) {\n this.rooms.delete(room);\n }\n }\n\n addEventListener(event, callback) {\n this.events[event] = callback;\n }\n\n removeEventListener(event) {\n delete this.events[event];\n }\n\n on(event, callback) {\n this.socket.on(event, callback);\n }\n\n off(event, callback) {\n this.socket.off(event, callback);\n }\n\n isConnected() {\n return this.socket?.connected;\n }\n\n disconnect() {\n if (!this || !this.isConnected()) return;\n this.rooms.forEach(room => this.leave(room, true));\n this.socket.disconnect();\n }\n}\n","import ENDPOINTS from 'tradera-constants/endpoints';\nimport {\n axiosWithTokenRefresh,\n checkResponseVersion,\n finalizeResponse,\n handleError,\n utilizeCancelToken,\n axiosConfigs\n} from 'tradera-utils/api';\nimport initData from 'init-data';\nimport { toLocalizedUrl } from 'tradera-utils/url';\nimport { getLanguage } from 'tradera-apps/syi/script/app_react/utils/language';\n\nexport const HTTP_STATUS_CODES = {\n NOT_FOUND: 404\n};\n\n// Prevents URL:s that begins with // when that was not intended.\nconst getSafeUrl = (baseUrl, url) => {\n if (baseUrl.endsWith('/') && url.startsWith('/')) {\n return baseUrl + url.substring(1);\n }\n return baseUrl + url;\n};\n\nconst httpClient = (baseUrl, shouldLocalizeUrl) => {\n const axiosWrapper = (url, httpClientConfig, axiosCaller) => {\n let { cancelTokenId, ...axiosConfig } = httpClientConfig;\n const version = initData.version;\n if (cancelTokenId) {\n const { cancel, cancelToken } = utilizeCancelToken(cancelTokenId);\n axiosConfig.cancelToken = cancelToken;\n if (cancel) {\n cancel();\n }\n }\n const safeUrl = getSafeUrl(baseUrl, url);\n const localizedUrl = shouldLocalizeUrl\n ? toLocalizedUrl(safeUrl, getLanguage())\n : safeUrl;\n return axiosCaller(axiosWithTokenRefresh(), localizedUrl, axiosConfig)\n .then(\n version ? checkResponseVersion(version) : response => response\n )\n .then(finalizeResponse())\n .catch(handleError());\n };\n\n return {\n get: (url, httpClientConfig = axiosConfigs.authenticated) => {\n return axiosWrapper(url, httpClientConfig, (axios, url, config) =>\n axios.get(url, config)\n );\n },\n post: (url, payload, httpClientConfig = axiosConfigs.authenticated) => {\n return axiosWrapper(url, httpClientConfig, (axios, url, config) =>\n axios.post(url, payload, config)\n );\n },\n put: (url, payload, httpClientConfig = axiosConfigs.authenticated) => {\n return axiosWrapper(url, httpClientConfig, (axios, url, config) =>\n axios.put(url, payload, config)\n );\n }\n };\n};\n\nexport const defaultClient = httpClient('');\nexport const touchWebClient = httpClient('/', true);\nexport const webApiClient = httpClient(ENDPOINTS.WEB_API);\nexport const cmsApiClient = httpClient(ENDPOINTS.CMS_API);\nexport const liveShoppingApiClient = httpClient(\n ENDPOINTS.LIVE_SHOPPING_PUBLIC_API\n);\nexport const marketingApiClient = httpClient(ENDPOINTS.MARKETING_PUBLIC_API);\n","export default {\n TRADERA: 'https://www.tradera.com'\n};\n","import qs from 'qs';\nimport HOSTS from 'tradera-constants/hosts';\nimport initData from 'init-data';\nimport logger from 'packages/logger';\n\n// List of SPA paths for the regex match, without initial slash\nconst SPA_REGEX_PATHS = [\n 'search',\n 'campaign',\n 'charity',\n 'kategorier',\n 'profile\\\\/items',\n 'brand\\\\/.+',\n // Category\n '[a-z]+[\\\\w\\\\-]+[\\\\-|_]\\\\d+'\n];\nconst SPA_PATH_REGEX = new RegExp(\n `^(\\\\/en|\\\\/da|\\\\/de)?/(${SPA_REGEX_PATHS.join('|')})`\n);\nconst SUPPORTED_LANGUAGES = ['en', 'de', 'da'];\n\n/**\n * Returns language parameter from url\n * @param {*} url\n */\nconst getLanguagePrefixFromUrl = url => {\n const matches = url.match(/\\/([a-z][a-z])((\\/.*$)|$)/);\n\n if (matches === null) {\n return null;\n }\n\n const firstMatch = matches.find((match, index) => index > 0 && match);\n\n if (SUPPORTED_LANGUAGES.indexOf(firstMatch) !== -1) {\n return firstMatch;\n }\n\n return null;\n};\n\n/**\n * Format query params parsed from query string\n *\n * @param {object} queryParams\n * @returns {object}\n */\nconst formatQueryParams = queryParams => {\n const { categoryId, ...rest } = queryParams;\n const formattedQueryParams = rest;\n if (categoryId !== undefined) {\n formattedQueryParams.categoryId = parseInt(categoryId, 10);\n }\n return formattedQueryParams;\n};\n\n/**\n * Check if url is absolute\n *\n * @param {string} url\n * @returns {boolean}\n */\nconst isAbsoluteUrl = url => new RegExp('^(?:[a-z]+:)?//', 'i').test(url);\n\n/**\n * Tests if a given url or path is an SPA link or not\n *\n * @param {string} urlOrPath\n * @returns {boolean}\n */\nfunction isSpaLink(urlOrPath) {\n let pathname;\n if (/(^http)s?:\\/\\//i.test(urlOrPath)) {\n try {\n ({ pathname } = new URL(urlOrPath));\n } catch {\n return false;\n }\n } else {\n pathname = urlOrPath;\n }\n return SPA_PATH_REGEX.test(pathname);\n}\n\n/**\n * Takes an object and returns a new object without attribute properties\n * @param {object} queryParams\n * @returns {object}\n */\nconst stripAttributesFromQueryParameters = queryParams => {\n // Using object spread to exclude listed variables from 'rest'\n // eslint-disable-next-line no-unused-vars\n const { attributes, ...rest } = queryParams;\n return rest;\n};\n\n/**\n * Takes an object and returns a new object without pagination properties\n * @param {object} queryParams\n * @returns {object}\n */\nconst stripCategoryIdFromQueryParameters = queryParams => {\n // Using object spread to exclude listed variables from 'rest'\n // eslint-disable-next-line no-unused-vars\n const { categoryId, ...rest } = queryParams;\n return rest;\n};\n\n/**\n * Removes tradera base from a url, leaving path and query\n *\n * @param {string} url\n * @returns {string}\n */\nconst stripHost = url =>\n url.startsWith('http') ? url.replace(HOSTS.TRADERA, '') : url;\n\n/**\n * Takes an object and returns a new object without itm properties\n * Itm tags should no longer be used, so this method will then be obsolete\n * @param {object} queryParams\n * @returns {object}\n */\nconst stripItmFromQueryParameters = queryParams => {\n // Using object spread to exclude listed variables from 'rest'\n // eslint-disable-next-line no-unused-vars\n const { itm_source, itm_medium, ...rest } = queryParams;\n return rest;\n};\n\n/**\n * Takes an object and returns a new object without pagination properties\n * @param {object} queryParams\n * @returns {object}\n */\nconst stripPaginationFromQueryParameters = queryParams => {\n // Using object spread to exclude listed variables from 'rest'\n // eslint-disable-next-line no-unused-vars\n const { spage, paging, page, fe, ...rest } = queryParams;\n return rest;\n};\n\n/**\n * Takes an object and returns a new object without savedQueryName properties\n * @param {object} queryParams\n * @returns {object}\n */\nconst stripSavedQueryNameFromQueryParameters = queryParams => {\n // Using object spread to exclude listed variables from 'rest'\n // eslint-disable-next-line no-unused-vars\n const { savedQueryName, ...rest } = queryParams;\n return rest;\n};\n\n/**\n * Takes an url and adds tradera base url if it is not already an absolute url\n *\n * @param {string} relativeUrl\n * @returns {string}\n */\nconst toAbsoluteUrl = relativeUrl =>\n relativeUrl.startsWith('http')\n ? relativeUrl\n : `${HOSTS.TRADERA}${\n relativeUrl.startsWith('/') ? relativeUrl : '/' + relativeUrl\n }`;\n\n/**\n * From react router location object to absolute url string\n * @param {{pathname: string, search: string}} url\n * @returns {string}\n */\nconst toAbsoluteUrlFromObject = url =>\n toAbsoluteUrl(\n `${url.pathname ? url.pathname : ''}${url.search ? url.search : ''}`\n );\n\n/**\n * From URL to URL with language prefix\n * @param {*} url\n * @param {*} languageCodeIso2\n */\nconst toLocalizedUrl = (url, languageCodeIso2) => {\n if (url === null || url === undefined || url === '' || url === false) {\n return url;\n }\n\n const ignoredUrls = [initData.webApiUrl, '/api/webapi/'];\n const isIgnoredUrl = ignoredUrls.find(domain => url.indexOf(domain) !== -1);\n if (isIgnoredUrl) {\n return url;\n }\n\n if (!languageCodeIso2) {\n logger(`Missing language code for URL ${url}`);\n return url;\n }\n\n const isAbsolute = isAbsoluteUrl(url);\n\n const urlObject = isAbsolute\n ? new URL(url)\n : new URL(url, 'http://dummy.com');\n const origin = isAbsolute ? urlObject.origin : '';\n const localisedPathname = setLanguagePrefix(\n urlObject.pathname,\n languageCodeIso2\n );\n\n return `${origin}${localisedPathname}${urlObject.search}`;\n};\n\n/**\n * Creates query parameters object from search string\n * @param {string} search\n */\nconst toQueryParameters = search =>\n qs.parse(search, { ignoreQueryPrefix: true });\n\n/**\n * Removes the Tradera host from a url, making it relative\n * @param {string} url\n * @returns {string}\n */\nconst toRelativeTraderaUrl = url => {\n if (url.startsWith(HOSTS.TRADERA)) {\n return url.replace(HOSTS.TRADERA, '');\n } else {\n return url;\n }\n};\n\n/**\n * Creates search string from all properties in object\n * @param {object} queryParams\n * @param {{[addQueryPrefix]: bool, [encode]: bool, [skipNulls]: bool }}\n * @returns {string}\n */\nconst toSearchString = (\n queryParams,\n {\n addQueryPrefix = true,\n encode = true,\n skipNulls = true,\n arrayFormat = 'repeat' //qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' }) ==> 'a=b&a=c'\n } = {}\n) =>\n qs.stringify(queryParams, {\n addQueryPrefix: addQueryPrefix,\n encode: encode,\n skipNulls: skipNulls,\n arrayFormat: arrayFormat\n });\n\nconst setLanguagePrefix = (path, languageCodeIso2) => {\n const languagePrefix = getLanguagePrefixFromUrl(path);\n const defaultLanguage = 'sv';\n\n if (languagePrefix) {\n if (languageCodeIso2 === defaultLanguage) {\n return path.replace(`/${languagePrefix}`, '');\n } else {\n return path.replace(languagePrefix, languageCodeIso2);\n }\n } else {\n if (languageCodeIso2 === defaultLanguage) {\n return path;\n } else {\n return `/${languageCodeIso2}${path}`;\n }\n }\n};\n\nconst getBackToHereRedirectUrl = () => {\n // Add random query parameter to force reload when redirecting to this url\n // and only the hash differs\n const queryParams = {\n ...qs.parse(location.search, { ignoreQueryPrefix: true }),\n forceRedirect: Math.round(Math.random() * 100000)\n };\n return (\n location.protocol +\n '//' +\n location.host +\n location.pathname +\n qs.stringify(queryParams, { addQueryPrefix: true })\n );\n};\n\nexport {\n SUPPORTED_LANGUAGES,\n getLanguagePrefixFromUrl,\n formatQueryParams,\n getBackToHereRedirectUrl,\n isAbsoluteUrl,\n isSpaLink,\n stripAttributesFromQueryParameters,\n stripCategoryIdFromQueryParameters,\n stripHost,\n stripItmFromQueryParameters,\n stripPaginationFromQueryParameters,\n stripSavedQueryNameFromQueryParameters,\n toAbsoluteUrl,\n toAbsoluteUrlFromObject,\n toLocalizedUrl,\n toQueryParameters,\n toRelativeTraderaUrl,\n toSearchString\n};\n","function formatDuration(durationInSeconds, minuteBreakpoint = 60) {\n if (Number.isInteger(durationInSeconds)) {\n if (durationInSeconds > 24 * 60 * 60) return ''; // Show format from server\n\n if (durationInSeconds > 60 * 60)\n return `${Math.floor(\n durationInSeconds / 60 / 60\n )} tim ${Math.floor((durationInSeconds / 60) % 60)} min`;\n\n if (durationInSeconds > minuteBreakpoint)\n return `${Math.floor(durationInSeconds / 60)} min`;\n\n return `${durationInSeconds} s`;\n } else {\n return '';\n }\n}\n\nfunction formatNumberWithSeparators(number, separator = '\\u2006') {\n return number\n .toString()\n .replace(/(\\d)(?=(\\d{3})+(?!\\d))/g, '$1' + separator);\n}\n\n// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString\nfunction toLocaleStringSupportsLocales() {\n try {\n Number(0).toLocaleString('i');\n } catch (e) {\n return e.name === 'RangeError';\n }\n return false;\n}\n\n// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString\nfunction toLocaleStringSupportsOptions() {\n return !!(\n typeof Intl === 'object' &&\n Intl &&\n typeof Intl.NumberFormat === 'function'\n );\n}\n\nconst isLocaleFormattingSupportedInBrowser =\n toLocaleStringSupportsLocales() && toLocaleStringSupportsOptions();\n\nfunction formatPrice(price, locale = 'sv-SE', options = {}) {\n if (!isLocaleFormattingSupportedInBrowser) {\n return `${typeof price === 'number' ? price : parseInt(price)} ${\n locale.startsWith('sv') ? 'kr' : 'SEK'\n }`;\n }\n let formattedPrice = typeof price !== 'number' ? parseInt(price) : price;\n const opts = {\n style: 'currency',\n currency: 'SEK',\n currencyDisplay: 'symbol',\n useGrouping: false,\n minimumFractionDigits: 0,\n maximumFractionDigits: 2,\n ...options\n };\n formattedPrice = formattedPrice.toLocaleString(locale, opts);\n formattedPrice = formatNumberWithSeparators(formattedPrice);\n return formattedPrice;\n}\n\nfunction formatDateWithDayOfWeek(dateString, locale) {\n if (!isLocaleFormattingSupportedInBrowser) {\n return dateString;\n }\n\n var options = {\n weekday: 'long',\n year: undefined,\n month: 'long',\n day: 'numeric'\n };\n return new Intl.DateTimeFormat(locale, options).format(\n Date.parse(dateString)\n );\n}\n\nexport {\n formatDuration,\n formatNumberWithSeparators,\n formatPrice,\n formatDateWithDayOfWeek\n};\n","/**\n * A queue with a that handled max age (ttl) for messages.\n * @returns\n */\nexport const createQueue = () => {\n const items = [];\n const dayInMinutes = 60 * 24;\n const add = (item, ttlInMinutes = dayInMinutes) => {\n const timeStamp = Date.now();\n items.push({ item, ttlInMinutes, timeStamp });\n };\n const isAlive = ({ ttlInMinutes, timeStamp }) => {\n return timeStamp + ttlInMinutes * 60 * 1000 >= Date.now();\n };\n let inProgress = null;\n return {\n add,\n next: () => {\n let itemData = items.shift();\n while (itemData && !isAlive(itemData)) {\n itemData = items.shift();\n }\n inProgress = itemData?.item || null;\n return inProgress;\n },\n notifyDone: () => {\n inProgress = null;\n },\n isInProgress: () => inProgress !== null,\n getLength: () => items.length\n };\n};\n","// extracted by mini-css-extract-plugin\nexport default {\"item-toast\":\"item-toast--QaLFk\",\"itemToast\":\"item-toast--QaLFk\",\"item-toast-image\":\"item-toast-image--i_l4w\",\"itemToastImage\":\"item-toast-image--i_l4w\"};","import React from 'react';\nimport { formatNumberWithSeparators } from 'tradera-utils/format';\nimport ALink from 'tradera-components/alink/alink';\nimport { useTranslator, useUrlLocalizer } from 'tradera-lang/translate';\nimport styles from './item-toast.module.scss';\n\nexport const ItemToast = ({\n imageUrl,\n itemUrl,\n shortDescription,\n type,\n eventData\n}) => {\n const { toLocalizedUrl } = useUrlLocalizer();\n\n return (\n \n \n

\n
\n
\n \n );\n};\n\nconst ToastMessage = ({ type, shortDescription, eventData }) => {\n const { t } = useTranslator();\n let message;\n switch (type) {\n case 'ItemOutbidded':\n message = t('siteWideNotifications_itemOutbidded', {\n newLeadingBidAmount: formatNumberWithSeparators(\n eventData.newLeadingBidAmount\n ),\n shortDescription\n });\n break;\n case 'ItemFirstBid':\n message = t('siteWideNotifications_itemFirstBid', {\n shortDescription\n });\n break;\n case 'ItemSold':\n message = t('siteWideNotifications_itemSold', {\n price: formatNumberWithSeparators(eventData.price),\n shortDescription\n });\n break;\n case 'ItemWon':\n message = t('siteWideNotifications_itemWon', {\n price: formatNumberWithSeparators(eventData.price),\n shortDescription\n });\n break;\n case 'ItemPaid':\n message = t('siteWideNotifications_itemPaid', {\n shortDescription\n });\n break;\n case 'ItemWishListReminder':\n message = t('siteWideNotifications_itemWishListReminder', {\n shortDescription,\n timeLeftMinutes: eventData.timeLeftMinutes\n });\n }\n return {message}
;\n};\n","import React from 'react';\nimport { toast } from 'react-toastify';\n\nimport { ItemToast } from 'tradera-components/toasts/item-toast';\nimport { webApiClient } from '../utils/http';\nimport { createQueue } from './toast-queue';\n\nconst queuedToasts = createQueue();\n\nexport const ToastTestButton = () => (\n \n);\n\nconst openNextToast = async () => {\n if (queuedToasts.isInProgress()) {\n return;\n }\n const nextItem = queuedToasts.next();\n if (nextItem) {\n try {\n const response = await webApiClient.get(\n `/browse/item-basic-info/${nextItem.eventData.itemId}`\n );\n const { imageUrl, itemUrl, shortDescription } = response.data.item;\n const queueLength = queuedToasts.getLength();\n toast(\n React.createElement(ItemToast, {\n imageUrl,\n itemUrl,\n shortDescription,\n type: nextItem.type,\n eventData: nextItem.eventData\n }),\n {\n autoClose: Math.max(2, 5 - queueLength) * 1000,\n onClose: () => {\n queuedToasts.notifyDone();\n openNextToast();\n }\n }\n );\n } catch (e) {\n queuedToasts.notifyDone();\n openNextToast();\n throw e;\n }\n }\n};\n\nconst handleNotification = async (type, eventData, ttlInMinutes = 10) => {\n if (document.visibilityState !== 'visible') {\n // We don't want to show messages if page is not visible. If we do they will queue up!\n return;\n }\n\n queuedToasts.add({ type, eventData }, ttlInMinutes);\n openNextToast();\n};\n\nexport const showItemOutbiddedToast = (itemId, newLeadingBidAmount) =>\n handleNotification('ItemOutbidded', {\n itemId,\n newLeadingBidAmount\n });\n\nexport const showItemFirstBidToast = itemId =>\n handleNotification('ItemFirstBid', { itemId });\n\nexport const showItemSoldToast = (itemId, price) =>\n handleNotification('ItemSold', { itemId, price });\n\nexport const showItemWonToast = (itemId, price) =>\n handleNotification('ItemWon', { itemId, price });\n\nexport const showItemPaidToast = itemId =>\n handleNotification('ItemPaid', { itemId });\n\nexport const showItemWishListReminderToast = (itemId, timeLeftMinutes) =>\n handleNotification(\n 'ItemWishListReminder',\n { itemId, timeLeftMinutes },\n timeLeftMinutes > 10 ? 10 : 2\n );\n","import { SocketIoChannel } from 'tradera-services/socket-io-channel';\nimport {\n showItemFirstBidToast,\n showItemOutbiddedToast,\n showItemPaidToast,\n showItemSoldToast,\n showItemWishListReminderToast,\n showItemWonToast\n} from './toasts';\nimport axios from 'axios';\nimport ENDPOINTS from 'tradera-constants/endpoints';\n\nconst refreshLoginState = async socket => {\n try {\n socket.disconnect();\n\n const response = await axios.get(\n ENDPOINTS.TOUCHWEB_URL + 'login/state'\n );\n\n if (!response.data?.isLoggedIn) {\n return;\n }\n\n socket.connect();\n } catch {\n // Could not get token.\n }\n};\n\nexport const bootSiteWideNotifications = ({ socketUrl, joinMemberRoom }) => {\n if (!joinMemberRoom) {\n return;\n }\n\n const socket = new SocketIoChannel(socketUrl);\n let isRetry = false;\n socket.on('JoinMemberRoom', async ({ success }) => {\n // To avoid infinite loop\n if (success || isRetry) {\n isRetry = false;\n return;\n }\n\n isRetry = true;\n await refreshLoginState(socket);\n });\n socket.join('member');\n socket.addEventListener('MemberItemOutbidded', data =>\n showItemOutbiddedToast(data.ItemId, data.NewLeadingBidAmount)\n );\n socket.addEventListener('MemberItemFirstBid', data =>\n showItemFirstBidToast(data.ItemId)\n );\n socket.addEventListener('MemberItemSold', data =>\n showItemSoldToast(data.ItemId, data.Price)\n );\n socket.addEventListener('MemberItemWon', data =>\n showItemWonToast(data.ItemId, data.Price)\n );\n socket.addEventListener('MemberItemPaid', data =>\n showItemPaidToast(data.ItemId)\n );\n socket.addEventListener('MemberItemWishListReminder', data =>\n showItemWishListReminderToast(data.ItemId, data.TimeLeftMinutes)\n );\n socket.connect();\n};\n","import 'core-js/modules/es.promise.finally';\nimport 'core-js/modules/es.array.iterator';\nimport 'intersection-observer';\nimport 'custom-event-polyfill';\nimport 'whatwg-fetch';\n\nimport initData from 'init-data';\nimport {\n handleModuleError,\n isSpaModule,\n loadModule,\n loadSpaModule,\n runModule\n} from 'utils/modules';\nimport { bootLanguages } from 'tradera-lang/boot-languages';\nimport gtm from 'static/script/app/ui/google-tagmanager-service';\nimport { bootSiteWideNotifications } from 'tradera-services/boot-site-wide-notifications';\n\nbootLanguages();\ngtm.loadGtmScript();\n\nif (initData) {\n if (initData.featureSwitches['site-wide-notifications']) {\n bootSiteWideNotifications({\n socketUrl: initData.siteWideNotificationsEventPusherServerUrl,\n joinMemberRoom: !!initData.memberId\n });\n }\n\n const module = initData.module.split('/')[4];\n let moduleLoader;\n if (isSpaModule(module, initData)) {\n moduleLoader = loadSpaModule(initData);\n } else {\n moduleLoader = import('./init-module')\n .then(initModule => initModule.default(initData))\n .then(() => loadModule(module, initData))\n .then(loadedModule => runModule(loadedModule, initData));\n }\n moduleLoader\n .then(() => {\n window.document.body.setAttribute('data-module-loaded', 'true');\n return;\n })\n .catch(handleModuleError);\n}\n","/**\n * @returns initData as JSON;\n * Default\n */\nconst initData = function() {\n if (!window.initData) {\n const initDataEL = document.getElementById('init-data');\n if (initDataEL) {\n const data = initDataEL.getAttribute('data-init-data');\n const parsed = JSON.parse(data);\n return parsed;\n } else {\n return null;\n }\n } else {\n return window.initData;\n }\n};\n\nexport const getInitData = initData;\nexport default new initData();\n","import { toLocalizedUrl } from 'tradera-utils/url';\n\nexport const toLocalizedRiotUrl = url => toLocalizedUrl(url, getLanguage());\n\nlet language;\nexport const getLanguage = () => {\n if (language === '' || language === null || language === undefined) {\n language = document.querySelector('html').getAttribute('lang');\n }\n\n return language;\n};\n","import logger from 'logger';\n\nfunction isSpaModule(module, initData) {\n const { discoverEnabled, isSinglePageApp } = initData;\n switch (module) {\n case 'start-page':\n case 'brand':\n case 'brand-list':\n case 'category-list':\n case 'endless-recommendation':\n case 'favourite-sellers':\n case 'landing':\n case 'live-shopping-event-list-page':\n case 'report-item':\n case 'profile':\n case 'verify-bankid':\n case 'tradera-shop':\n return true;\n\n case 'category':\n case 'custom-results':\n case 'search-results':\n return discoverEnabled;\n\n default:\n return isSinglePageApp;\n }\n}\n\nasync function loadSpaModule(initData) {\n const module = await import(\n /* webpackChunkName: \"tradera\" */ '../../../../frontend/apps/tradera/'\n );\n return module.default(initData);\n}\n\nasync function loadModule(module) {\n switch (module) {\n // Fallback modules for when SPA is toggled off\n // TODO: Remove when fully incorporated in SPA\n case 'start-page':\n case 'brand':\n case 'brand-list':\n case 'category-list':\n case 'landing':\n case 'live-shopping-event-list-page':\n case 'order-checkout':\n case 'verify-bankid':\n case 'profile':\n case 'cart':\n case 'upi':\n case 'inr':\n case 'cause':\n case 'causes':\n case 'causes-info':\n return await import(\n /* webpackChunkName: \"tradera\" */ '../../../../frontend/apps/tradera/'\n );\n\n // Non-SPA modules\n case 'basic':\n return await import(\n /* webpackChunkName: \"basic\" */ '../app/pages/basic'\n );\n case 'bidding':\n return await import(\n /* webpackChunkName: \"bidding\" */ '../app/pages/bidding'\n );\n case 'bin-form':\n return await import(\n /* webpackChunkName: \"bin-form\" */ '../app/pages/bin-form'\n );\n case 'cart-checkout':\n return await import(\n /* webpackChunkName: \"cart-checkout\" */ '../app/pages/cart-checkout'\n );\n case 'category':\n return await import(\n /* webpackChunkName: \"category-results\" */ '../app/pages/category'\n );\n case 'checkout-select-payment':\n return await import(\n /* webpackChunkName: \"checkout-select-payment\" */ '../app/pages/checkout-select-payment'\n );\n case 'checkout2':\n return await import(\n /* webpackChunkName: \"checkout2\" */ '../app/pages/checkout2'\n );\n case 'detailed-search':\n return await import(\n /* webpackChunkName: \"detailed-search\" */ '../app/pages/detailed-search'\n );\n case 'endless-recommendation':\n return await import(\n /* webpackChunkName: \"endless-recommendation\" */ '../app/pages/endless-recommendation'\n );\n case 'image-search':\n return await import(\n /* webpackChunkName: \"image-search\" */ 'tradera-apps/image-search'\n );\n case 'messages':\n return await import(\n /* webpackChunkName: \"messages\" */ '../app/pages/messages'\n );\n case 'messaging':\n return await import(\n /* webpackChunkName: \"messaging-iframe\" */ '../app/pages/messaging'\n );\n case 'search-results':\n return await import(\n /* webpackChunkName: \"search-results\" */ '../app/pages/search-results'\n );\n\n default:\n return await import(\n /* webpackChunkName: \"basic\" */ '../app/pages/basic'\n );\n }\n}\n\nfunction runModule(module, initData = {}) {\n if (!module.default) {\n //eslint-disable-next-line\n console.error(`Cannot run module \"${module}\" without exported default`);\n }\n return module.default(initData);\n}\n\nconst handleModuleError = error => logger(error);\n\nexport { isSpaModule, loadSpaModule, loadModule, runModule, handleModuleError };\n","import { createSlice } from '@reduxjs/toolkit';\n\nexport const initialState = {};\n\nconst slice = createSlice({\n name: 'environment',\n initialState,\n reducers: {\n setEnvironmentHash: (state, { payload }) => {\n state.environmentHash = payload;\n },\n setIsSpaNavigationEnabled: (state, { payload }) => {\n state.isSpaNavigationEnabled = payload;\n }\n }\n});\n\nexport const { setEnvironmentHash, setIsSpaNavigationEnabled } = slice.actions;\nexport const reducer = slice.reducer;\n","import axios from 'axios';\n\nimport { logger } from 'packages/index';\nimport ENDPOINTS from 'tradera-constants/endpoints';\n\n/**\n * Standardized api error codes\n */\nconst API_ERRORS = {\n IGNORE_ME: 'IGNORE_ME',\n ABORTED: 'ABORTED',\n CANCELLED: 'CANCELLED',\n NETWORK: 'NETWORK',\n TIMEOUT: 'TIMEOUT',\n VERSION_MISMATCH: 'VERSION_MISMATCH',\n LOGGED_OUT: 'LOGGED_OUT'\n};\n\nconst defaultJsonRequestHeaders = {\n // Force json response\n Accept: 'application/json',\n // For WebAPI and RequiresAuthorization to handle ajax request\n 'X-Requested-With': 'XMLHttpRequest'\n};\n\n/**\n * Standard Axios configs\n */\nconst axiosConfigs = {\n // Requests to endpoints with authentication\n authenticated: {\n // Send auth cookies\n withCredentials: true,\n headers: defaultJsonRequestHeaders\n },\n notAuthenticated: {\n // Dont send auth cookies\n withCredentials: false,\n headers: defaultJsonRequestHeaders\n }\n};\n\nconst isMissingAuthToken = responseString => {\n try {\n const responseObject = JSON.parse(responseString);\n const isMissing =\n responseObject.responseStatus.errorCode === 'MissingAuthToken';\n return isMissing;\n } catch {\n return false;\n }\n};\n\nconst isUnauthorized = statusCode => statusCode === 401;\n\nconst addAntiCacheParam = url => {\n const antiCacheRegExp = /([?&]_=)[^&]*/;\n return antiCacheRegExp.test(url)\n ? url.replace(antiCacheRegExp, '$1' + new Date().getTime())\n : url + (/\\?/.test(url) ? '&' : '?') + '_=' + new Date().getTime();\n};\n\nconst submitOriginalRequest = async error =>\n axios({\n ...error.config,\n url: addAntiCacheParam(error.config.url)\n });\n\nconst handleMissingAuthToken = async error => {\n const refreshAccessToken = async () =>\n axios.get(ENDPOINTS.TOUCHWEB_URL + 'login/state');\n const handleErrorAfterRefresh = async errorAfterRefreshToken => {\n if (isUnauthorized(errorAfterRefreshToken.request?.status)) {\n error.message = API_ERRORS.LOGGED_OUT;\n }\n return Promise.reject(error);\n };\n return refreshAccessToken()\n .then(() => submitOriginalRequest(error))\n .catch(handleErrorAfterRefresh);\n};\n\nconst handleUnauthorized = async error => {\n const checkLoginState = async () =>\n axios.get(ENDPOINTS.TOUCHWEB_URL + 'login/state');\n return checkLoginState().then(response => {\n const isLoggedIn = response.data?.isLoggedIn;\n if (isLoggedIn) {\n return submitOriginalRequest(error);\n }\n error.message = API_ERRORS.LOGGED_OUT;\n // eslint-disable-next-line promise/no-return-wrap\n return Promise.reject(error);\n });\n};\n\nconst errorResponseInterceptor = error => {\n if (isMissingAuthToken(error.request?.response)) {\n return handleMissingAuthToken(error);\n } else if (isUnauthorized(error.request?.status)) {\n return handleUnauthorized(error);\n }\n return Promise.reject(error);\n};\n\n/**\n * Create Axios instance or decorate existing instance with interceptor for expired token responses\n *\n * @param {AxiosInstance} [axiosInstance]\n * @returns {AxiosInstance}\n */\nfunction axiosWithTokenRefresh(axiosInstance) {\n let instance;\n if (axiosInstance === undefined) {\n instance = axios.create();\n } else {\n instance = axiosInstance;\n }\n instance.interceptors.response.use(\n response => response,\n errorResponseInterceptor\n );\n return instance;\n}\n\nconst cancelTokens = {};\n\n/**\n * Create new or return existing cancellation function\n *\n * Usage:\n * const { cancel, cancelToken } = utilizeCancelToken('tokenId')\n * if (cancel) cancel();\n * axios.get('http://api.com/...', { cancelToken });\n *\n * @param {string} tokenId - A string ID shared between requests that cancel together\n * @returns {{ cancel: function, cancelToken: function }}\n */\nfunction utilizeCancelToken(tokenId) {\n let cancel;\n if (tokenId in cancelTokens) {\n cancel = cancelTokens[tokenId].cancel;\n }\n cancelTokens[tokenId] = axios.CancelToken.source();\n return {\n cancel,\n cancelToken: cancelTokens[tokenId].token\n };\n}\n\n/**\n * Check response version and throw error if different from current\n *\n * @param {string} version\n * @return {function(*): object|void}\n */\nfunction checkResponseVersion(version = '12.0.0') {\n return response => {\n if (\n response.headers &&\n response.headers['X-Tradera-Version'] &&\n response.headers['X-Tradera-Version'] !== version\n ) {\n throw new Error(API_ERRORS.VERSION_MISMATCH);\n } else {\n return response;\n }\n };\n}\n\n/**\n * Checks redirect response for logged out user\n * This is an old solution. New solutions return a 401 response instead (see handleError).\n * Requires Axios config to include { withCredentials: true }\n *\n * @returns {Function}\n */\nfunction checkResponseLoggedOut() {\n return response => {\n if (\n response.data &&\n typeof response.data === 'string' &&\n response.data.includes('Logga in')\n ) {\n throw new Error(API_ERRORS.LOGGED_OUT);\n } else {\n return response;\n }\n };\n}\n\n/**\n * Final standardized formatting of an api response\n *\n * @returns { function(*): { data: *, status: integer }}\n */\nfunction finalizeResponse() {\n return response => {\n const { data, status } = response;\n return {\n data,\n status\n };\n };\n}\n\n/**\n * Common network request error handling\n *\n * @param {Object.} statusHandlers - { code: message }\n * @returns {function(*=): Promise}\n */\nfunction handleError(statusHandlers = {}) {\n return error => {\n let status = error.response && error.response.status;\n let message = error.message ? error.message : error.toString();\n if (axios.isCancel(error)) {\n error.message = API_ERRORS.CANCELLED;\n } else if (message.includes('timeout') || status === 408) {\n error.message = API_ERRORS.TIMEOUT;\n } else if (message.includes('Network')) {\n error.message = API_ERRORS.NETWORK;\n } else if (message.includes('Request aborted')) {\n error.message = API_ERRORS.ABORTED;\n } else if (status === 401) {\n error.message = API_ERRORS.LOGGED_OUT;\n } else if (status in statusHandlers) {\n error.message = statusHandlers[status];\n }\n throw error;\n };\n}\n\nfunction reloadOnUnauthorized(error) {\n switch (error.message) {\n case API_ERRORS.LOGGED_OUT:\n window.location.reload();\n break;\n default:\n throw error;\n }\n}\n\nfunction logError(error) {\n switch (error.message) {\n case API_ERRORS.IGNORE_ME:\n case API_ERRORS.CANCELLED:\n case API_ERRORS.NETWORK:\n case API_ERRORS.TIMEOUT:\n break;\n default:\n logger(error);\n break;\n }\n}\n\nexport {\n addAntiCacheParam,\n API_ERRORS,\n axiosConfigs,\n axiosWithTokenRefresh,\n checkResponseVersion,\n checkResponseLoggedOut,\n defaultJsonRequestHeaders,\n errorResponseInterceptor,\n finalizeResponse,\n handleError,\n logError,\n reloadOnUnauthorized,\n utilizeCancelToken\n};\n","import axios from 'axios';\nimport { getCurrentLanguage } from 'tradera-lang/boot-languages';\nimport { toLocalizedUrl } from 'tradera-utils/url';\nimport { setEnvironmentHash, setIsSpaNavigationEnabled } from './reducer';\n\nexport const updateEnvironmentHash = () => async (dispatch, getState) => {\n const url = toLocalizedUrl('/ping', getCurrentLanguage());\n const response = await axios.get(url);\n const environmentHash = response.headers['x-tradera-environment'];\n const current = getState().environment.environmentHash;\n if (environmentHash !== current) {\n dispatch(setEnvironmentHash(environmentHash));\n dispatch(setIsSpaNavigationEnabled(false));\n }\n};\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { useDispatch, useSelector } from 'react-redux';\nimport { Link } from 'react-router-dom';\nimport { updateEnvironmentHash } from 'tradera-state/environment/actions';\n\nconst ALink = ({\n useLink,\n href,\n children,\n onClick: givenOnClick,\n ...otherProps\n}) => {\n const dispatch = useDispatch();\n const isSpaNavigationEnabled = useSelector(\n state => state.environment.isSpaNavigationEnabled\n );\n if (isSpaNavigationEnabled && useLink) {\n // Strip away origin for local links\n let to = href;\n if (href?.startsWith(location.origin)) {\n const { pathname, search } = new URL(href);\n to = pathname + search;\n }\n return (\n {\n dispatch(updateEnvironmentHash());\n if (givenOnClick) givenOnClick(evt);\n }}>\n {children}\n \n );\n } else {\n return (\n \n {children}\n \n );\n }\n};\n\nALink.propTypes = {\n useLink: PropTypes.bool,\n href: PropTypes.string.isRequired,\n children: PropTypes.node.isRequired,\n onClick: PropTypes.func\n};\n\nALink.defaultProps = {\n useLink: false,\n onClick: null\n};\n\nexport default ALink;\n","/* eslint-disable */ /**\n OBSOLETE - use google tag manager service instead:\n src\\EbaySweden.TouchWeb\\static\\script\\app\\ui\\google-tagmanager-service.js\n\n\n * Ported from Applications/TouchWeb/src/EbaySweden.TouchWeb/static/script/app/ui/layout/google-tagmanager.js\n * Best way to import this module is `import * as Analytics from 'analytics'`\n */\n\nimport * as Sentry from '@sentry/browser';\n\nexport const pushToDataLayer = payload => {\n window.dataLayer = window.dataLayer || [];\n window.dataLayer.push(payload);\n};\nexport const trackPageView = () =>\n window.ga\n ? ga('send', 'pageview', location.pathname)\n : pushToDataLayer({ event: 'trackPageview' });\nexport const isNonInteractive = analyticsData =>\n analyticsData.userTriggered === undefined\n ? true\n : !analyticsData.userTriggered;\n/**\n * trackTiming\n * @param {*} category\n * @param {*} variable\n * @param {*} value\n * @param {*} label\n */\nexport const trackTiming = (category, variable, value, label = '') =>\n window.ga ? ga('send', 'timing', category, variable, value, label) : false;\n\n/**\n * Track Analytics Event\n */\nexport const trackEvent = analyticsData => {\n if (!analyticsData) {\n return;\n }\n pushToDataLayer({\n event: 'trackEvent',\n eventCategory: analyticsData.category || '',\n eventAction: analyticsData.action || '',\n eventLabel: analyticsData.label || '',\n eventValue: analyticsData.value || '0',\n eventNonInteractive: isNonInteractive(analyticsData),\n hitCallback: analyticsData.hitCallback || []\n });\n\n Sentry.addBreadcrumb({\n type: 'default',\n level: Sentry.Severity.Info,\n category: isNonInteractive(analyticsData) ? 'tracking' : 'ui-action',\n message: 'Analytics Event',\n data: analyticsData\n });\n};\n\n// Export object for Sinon stubbing\nexport default {\n pushToDataLayer,\n trackEvent,\n trackPageView,\n trackTiming\n};\n","/**\n *\n * # track events:\n * import GtmService from 'static/script/app/ui/google-tagmanager-service';\n * GtmService.trackGtmEvent(\"zorro\", { marvel: false, black: true })\n *\n *\n *\n */\n\nimport * as Sentry from '@sentry/browser';\nimport initData from '../../packages/init-data';\n\n/**\n * SPA page view tracking becomes enabled after first\n * page view tracking which happens after the first\n * page is loaded from server.\n * This prevents reset of data layer after a SPA route has\n * changed (happens late after full page load) and prevents\n * duplicated trackPageView events.\n */\nlet spaPageViewTrackingEnabled = false;\n\nclass GoogleTagManagerService {\n loadGtmScript() {\n this._newPageFromServer();\n\n const accountId = 'GTM-5TMB2D';\n (function(w, d, s, l, i) {\n w[l] = w[l] || [];\n w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });\n var f = d.getElementsByTagName(s)[0],\n j = d.createElement(s),\n dl = l != 'dataLayer' ? '&l=' + l : '';\n j.async = true;\n j.src = '//www.googletagmanager.com/gtm.js?id=' + i + dl;\n f.parentNode.insertBefore(j, f);\n })(window, document, 'script', 'dataLayer', accountId);\n }\n\n push(payload) {\n window.dataLayer = window.dataLayer || [];\n window.dataLayer.push(payload);\n }\n\n _getDatalayerObject() {\n let output = {};\n if (window.dataLayer) {\n for (let entry of window.dataLayer) {\n output = { ...output, ...entry };\n }\n }\n return output;\n }\n\n /**\n * destroy datalayer from previous loading. this is really only useful in spa pages, it's backwards compatible so it doesnt do any harm on old pages\n */\n _reset() {\n if (!window.dataLayer) {\n return;\n }\n\n let data = this._getDatalayerObject();\n for (let key of Object.keys(data)) {\n data[key] = undefined;\n }\n window.dataLayer.push({ ...data, event: 'reset' });\n }\n\n newSpaPage(pageType) {\n if (!spaPageViewTrackingEnabled) {\n return;\n }\n this._reset();\n this._pushInitialDataLayer();\n this.push({ event: 'pageType', 'page.pageType': pageType });\n }\n\n _newPageFromServer() {\n this._pushInitialDataLayer();\n // ------------------------------------------------\n // backwards compatibility\n // get old datalayer info and push it in\n if (window.legacyDataLayer) {\n for (let entry of window.legacyDataLayer) {\n window.dataLayer.push({\n event: 'legacyDataLayer',\n ...entry\n });\n }\n }\n }\n\n _buildFromInitData() {\n return {\n memberId: initData.memberId || 0,\n userLanguage: initData.languageCodeIso2,\n memberEmail: initData.isLoggedIn ? initData.memberEmail : '',\n memberHashedEmail: initData.isLoggedIn\n ? initData.memberEmailSha256\n : '',\n 'criteo.hashedEmail': initData.isLoggedIn\n ? initData.memberEmailMd5\n : '',\n memberFirstName: initData.isLoggedIn\n ? initData.memberFirstName\n : '',\n memberLastName: initData.isLoggedIn ? initData.memberLastName : '',\n memberCountry: initData.isLoggedIn ? initData.memberCountry : '',\n loginState: initData.isLoggedIn ? 'logged in' : 'not logged in',\n isNotInIframe: window.self === window.top,\n 'blueshift.event-api-key': initData.blueshiftEventApiKey,\n isSinglePageApp: initData.isSinglePageApp,\n isNativeAppContext: initData.isNativeAppContext,\n isQuantcastConsentEnabled:\n initData.featureSwitches['quantcast-consent'],\n isDigitalAudienceTrackingEnabled:\n initData.featureSwitches['digital-audience-tracking'],\n quantcastSite: initData.quantcastSite\n };\n }\n\n _pushInitialDataLayer() {\n // init datalayer\n let initialDataLayer = this._buildFromInitData();\n\n // add split tests to datalayer\n if (initData.splitTestGroups) {\n for (let [key, value] of Object.entries(initData.splitTestGroups)) {\n initialDataLayer[`splittest_${key}`] = value;\n }\n }\n window.dataLayer = window.dataLayer || [];\n window.dataLayer.push({\n ...initialDataLayer,\n event: 'initialDataLayer'\n });\n }\n\n /**\n * tracks a google analytics event\n * @param {string} category ga category\n * @param {string} action ga action what happens, ie: \"Filter box - open/close\"\n * @param {string} label ga label what the value of the action was, ie \"close\"\n * @param {integer} [value] ga interger value of the action.\n */\n trackAction(category, action, label, value = 0, nonInteractive = false) {\n this.push({\n event: 'trackEvent',\n eventCategory: category || '',\n eventAction: action || '',\n eventLabel: label || '',\n eventValue: value || '0',\n eventNonInteractive: nonInteractive\n });\n\n Sentry.addBreadcrumb({\n type: 'default',\n level: Sentry.Severity.Info,\n category: nonInteractive ? 'tracking' : 'ui-action',\n message: 'Analytics Event',\n data: {\n category,\n action,\n label,\n value\n }\n });\n }\n\n /**\n * google tag manager event. Note: if you want to send google analytics events use trackAction instead\n * @param {string} eventName\n * @param {object} [event] data\n */\n trackGtmEvent(eventName, data = {}) {\n this.push({\n event: eventName,\n ...data\n });\n }\n\n /**\n * Track a pageview. Use this script in SPA's to make sure that analytics gets pageview information.\n * This creates a virtual page view since google analytics by default doesn't track changes to url via\n * push state.\n */\n trackPageView() {\n this.trackGtmEvent('trackPageview');\n spaPageViewTrackingEnabled = true;\n }\n\n /**\n *\n * @param {string} category\n * @param {string} action\n * @param {string} label\n * @param {string} callback\n * @param {} value\n */\n trackLinkClickAndCallback(category, action, label, callback, value = 0) {\n this.push({\n event: 'trackEvent',\n eventCategory: category || '',\n eventAction: action || '',\n eventLabel: label || '',\n eventValue: value || '0',\n eventNonInteractive: false,\n eventCallback: callback // part of google tag manager api to execute code after all tags in datalayer have been executed\n });\n }\n\n trackLinkClickAndGotoUrl(category, action, label, url, value = 0) {\n const callback = () => {\n location.href = url;\n };\n this.trackLinkClickAndCallback(\n category,\n action,\n label,\n callback,\n value\n );\n }\n}\n\nexport default new GoogleTagManagerService();\n"],"sourceRoot":""}