{"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/frontend/apps/tradera/configure-dayjs.js","webpack:///./src/frontend/utils/time-api.js","webpack:///./src/frontend/utils/server-date.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/services/global-socket.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","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","autoConnect","socket","io","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","formatStaticEndTime","endDateInput","dayjs","formatEndDate","nowDateInput","endDate","now","isSameOrAfter","hours","diff","minutes","timeParts","push","count","isAfter","separator","toString","Number","formatSellerDsrAverage","locale","minimumFractionDigits","maximumFractionDigits","formatPrice","price","formattedPrice","opts","style","currency","currencyDisplay","useGrouping","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","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","extend","isBetween","getServerDate","gtm","loadGtmScript","featureSwitches","socketUrl","joinMemberRoom","getGlobalSocket","isRetry","success","ItemId","NewLeadingBidAmount","Price","TimeLeftMinutes","bootSiteWideNotifications","webLiveUrl","memberId","module","split","isSpaModule","loadSpaModule","initModule","default","loadModule","loadedModule","runModule","body","setAttribute","handleModuleError","queryServerTime","retryCount","latencyLimit","maxRetries","requestStart","currentTime","start","latency","getServerTime","_minServerCheckInterval","_serverDiff","_didGetServerResponse","_lastCheckAtMs","updateServerDiff","serverTimeObject","timeNowOnServer","getTime","_initialPromise","promise","initDataEL","getElementById","getAttribute","JSON","getInitData","toLocalizedRiotUrl","querySelector","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","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","globalSocket","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.0fc52d5c47.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: webApiUrl + `/discover/favouritesellers-and-items2`,\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, autoConnect = false) {\n if (!socketIoServerUrl) {\n throw new MissingSocketIoServerUrl();\n }\n this.socket = io(socketIoServerUrl, {\n autoConnect\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","import dayjs from 'dayjs';\n\nfunction 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 formatStaticEndTime(endDateInput) {\n if (!endDateInput) return '';\n const endDate = dayjs(endDateInput);\n return endDate.format('D MMM HH:mm');\n}\n\nfunction formatEndDate(endDateInput, t, nowDateInput) {\n if (!endDateInput || !nowDateInput) return '';\n\n const endDate = dayjs(endDateInput);\n const now = dayjs(nowDateInput);\n if (endDate.isSameOrAfter(now.add(1, 'week'), 'day')) {\n return endDate.format('D MMM HH:mm');\n }\n if (endDate.isSameOrAfter(now.add(2, 'day'), 'day')) {\n return endDate.format('ddd HH:mm');\n }\n if (endDate.isSameOrAfter(now.add(1, 'day'))) {\n return `${t('vip_tomorrow')} ${endDate.format('HH:mm')}`;\n }\n if (endDate.isSameOrAfter(now.add(1, 'minute'))) {\n const hours = endDate.diff(now, 'hour');\n const minutes = endDate.diff(now, 'minute') % 60;\n const timeParts = [];\n if (hours > 0) {\n timeParts.push(t('vip_hours', { count: hours }));\n }\n if (minutes > 0) {\n timeParts.push(t('vip_minutes', { count: minutes }));\n }\n return timeParts.join(' ');\n }\n if (endDate.isAfter(now)) {\n return t('vip_less_than_1_min_left');\n }\n return t('vip_ended');\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 formatSellerDsrAverage(value, locale = 'sv-SE') {\n return value?.toLocaleString(locale, {\n minimumFractionDigits: 1,\n maximumFractionDigits: 1\n });\n}\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 formatStaticEndTime,\n formatEndDate,\n formatNumberWithSeparators,\n formatPrice,\n formatSellerDsrAverage,\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 {\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';\nimport { getGlobalSocket } from './global-socket';\n\nconst refreshLoginState = async socket => {\n try {\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.disconnect();\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 = getGlobalSocket(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.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.join('member');\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';\nimport { getServerDate } from 'tradera-utils/server-date';\nimport { configureDayjs } from 'tradera-apps/tradera/configure-dayjs';\n\nbootLanguages();\nconfigureDayjs();\ngetServerDate();\ngtm.loadGtmScript();\n\nif (initData) {\n if (initData.featureSwitches['site-wide-notifications']) {\n bootSiteWideNotifications({\n socketUrl: initData.webLiveUrl,\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","import dayjs from 'dayjs';\nimport isBetween from 'dayjs/plugin/isBetween';\nimport isSameOrAfter from 'dayjs/plugin/isSameOrAfter';\nimport { getCurrentLanguage } from 'tradera-lang/boot-languages';\n\nexport const configureDayjs = () => {\n dayjs.locale(getCurrentLanguage());\n dayjs.extend(isBetween);\n dayjs.extend(isSameOrAfter);\n};\n","import axios from 'axios';\nimport { getCurrentLanguage } from 'tradera-lang/boot-languages';\nimport { toLocalizedUrl } from 'tradera-utils/url';\n\nconst timeDiffInMs = start => {\n return Date.now() - start;\n};\n\nconst queryServerTime = async retryCount => {\n const latencyLimit = 2000;\n const maxRetries = 2;\n const requestStart = Date.now();\n const {\n data: { currentTime }\n } = await axios.get(\n toLocalizedUrl(\n '/api/webapi/discover/server-time.json',\n getCurrentLanguage()\n )\n );\n const latency = timeDiffInMs(requestStart);\n\n if (latency < latencyLimit) {\n return { currentTime: Date.parse(currentTime), latency };\n } else if (retryCount < maxRetries) {\n return queryServerTime(retryCount + 1);\n } else {\n return null;\n }\n};\n\n/**\n * Requests server time and returns\n * { currentTime, latency }\n */\nexport const getServerTime = async () => {\n return await queryServerTime(0);\n};\n","import { getServerTime } from 'tradera-utils/time-api';\n\nlet _minServerCheckInterval = 1000 * 60 * 5;\nlet _serverDiff = 0;\nlet _didGetServerResponse = false;\nlet _lastCheckAtMs = null;\n\nconst updateServerDiff = async () => {\n _lastCheckAtMs = Date.now();\n const serverTimeObject = await getServerTime();\n if (serverTimeObject) {\n _didGetServerResponse = true;\n // We add the whole latency even though it may give a later\n // time than in reality since a later time gives less time\n // left until auctions expire. This is better than showing\n // too much time left.\n const timeNowOnServer = new Date(\n serverTimeObject.currentTime + serverTimeObject.latency\n );\n _serverDiff = timeNowOnServer.getTime() - Date.now();\n }\n};\n\nconst shouldCheckServer = () =>\n _lastCheckAtMs === null ||\n Date.now() - _lastCheckAtMs >= _minServerCheckInterval;\n\nlet _initialPromise = null;\n\n/**\n * Gets the date on the server and shall be used for calculating auction time left.\n * @returns The date or null if server did not respond at least once.\n */\nexport const getServerDate = async () => {\n if (shouldCheckServer()) {\n let promise = updateServerDiff();\n if (!_didGetServerResponse) {\n _initialPromise = promise;\n }\n }\n\n if (_initialPromise) {\n try {\n await _initialPromise;\n } catch {\n // Don't throw any errors.\n }\n _initialPromise = null;\n }\n\n return _didGetServerResponse ? new Date(Date.now() + _serverDiff) : null;\n};\n\nexport const resetForTesting = () => {\n _minServerCheckInterval = 0;\n _didGetServerResponse = null;\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 { 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 case 'category':\n case 'custom-results':\n case 'search-results':\n return true;\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 '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 '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 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 { SocketIoChannel } from 'tradera-services/socket-io-channel';\n\nlet globalSocket = null;\n\nexport const getGlobalSocket = socketUrl => {\n if (!globalSocket) {\n globalSocket = new SocketIoChannel(socketUrl, true);\n }\n return globalSocket;\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":""}