@maestro_io/maestro-web-sdk 5.2.0 → 5.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/dist/10.maestro-web-sdk.esm.js +1 -1
  2. package/dist/10.maestro-web-sdk.esm.js.map +1 -1
  3. package/dist/11.maestro-web-sdk.esm.js +1 -1
  4. package/dist/11.maestro-web-sdk.esm.js.map +1 -1
  5. package/dist/12.maestro-web-sdk.esm.js +1 -1
  6. package/dist/12.maestro-web-sdk.esm.js.map +1 -1
  7. package/dist/13.maestro-web-sdk.esm.js +1 -1
  8. package/dist/13.maestro-web-sdk.esm.js.map +1 -1
  9. package/dist/14.maestro-web-sdk.esm.js +1 -1
  10. package/dist/14.maestro-web-sdk.esm.js.map +1 -1
  11. package/dist/15.maestro-web-sdk.esm.js +1 -1
  12. package/dist/15.maestro-web-sdk.esm.js.map +1 -1
  13. package/dist/16.maestro-web-sdk.esm.js +1 -1
  14. package/dist/16.maestro-web-sdk.esm.js.map +1 -1
  15. package/dist/17.maestro-web-sdk.esm.js +1 -1
  16. package/dist/17.maestro-web-sdk.esm.js.map +1 -1
  17. package/dist/18.maestro-web-sdk.esm.js +1 -1
  18. package/dist/18.maestro-web-sdk.esm.js.map +1 -1
  19. package/dist/19.maestro-web-sdk.esm.js +1 -1
  20. package/dist/19.maestro-web-sdk.esm.js.map +1 -1
  21. package/dist/20.maestro-web-sdk.esm.js +1 -1
  22. package/dist/20.maestro-web-sdk.esm.js.map +1 -1
  23. package/dist/21.maestro-web-sdk.esm.js +1 -1
  24. package/dist/21.maestro-web-sdk.esm.js.map +1 -1
  25. package/dist/22.maestro-web-sdk.esm.js +1 -1
  26. package/dist/22.maestro-web-sdk.esm.js.map +1 -1
  27. package/dist/23.maestro-web-sdk.esm.js +1 -1
  28. package/dist/23.maestro-web-sdk.esm.js.map +1 -1
  29. package/dist/24.maestro-web-sdk.esm.js +1 -1
  30. package/dist/24.maestro-web-sdk.esm.js.map +1 -1
  31. package/dist/25.maestro-web-sdk.esm.js +1 -1
  32. package/dist/25.maestro-web-sdk.esm.js.map +1 -1
  33. package/dist/26.maestro-web-sdk.esm.js +1 -1
  34. package/dist/26.maestro-web-sdk.esm.js.map +1 -1
  35. package/dist/27.maestro-web-sdk.esm.js +1 -1
  36. package/dist/27.maestro-web-sdk.esm.js.map +1 -1
  37. package/dist/28.maestro-web-sdk.esm.js +1 -1
  38. package/dist/28.maestro-web-sdk.esm.js.map +1 -1
  39. package/dist/29.maestro-web-sdk.esm.js +1 -1
  40. package/dist/29.maestro-web-sdk.esm.js.map +1 -1
  41. package/dist/3.maestro-web-sdk.esm.js +1 -1
  42. package/dist/3.maestro-web-sdk.esm.js.map +1 -1
  43. package/dist/30.maestro-web-sdk.esm.js +1 -1
  44. package/dist/30.maestro-web-sdk.esm.js.map +1 -1
  45. package/dist/31.maestro-web-sdk.esm.js +1 -1
  46. package/dist/31.maestro-web-sdk.esm.js.map +1 -1
  47. package/dist/32.maestro-web-sdk.esm.js +1 -1
  48. package/dist/32.maestro-web-sdk.esm.js.map +1 -1
  49. package/dist/33.maestro-web-sdk.esm.js +1 -1
  50. package/dist/33.maestro-web-sdk.esm.js.map +1 -1
  51. package/dist/34.maestro-web-sdk.esm.js +1 -1
  52. package/dist/34.maestro-web-sdk.esm.js.map +1 -1
  53. package/dist/35.maestro-web-sdk.esm.js +1 -1
  54. package/dist/35.maestro-web-sdk.esm.js.map +1 -1
  55. package/dist/36.maestro-web-sdk.esm.js +1 -1
  56. package/dist/36.maestro-web-sdk.esm.js.map +1 -1
  57. package/dist/37.maestro-web-sdk.esm.js +1 -1
  58. package/dist/37.maestro-web-sdk.esm.js.map +1 -1
  59. package/dist/38.maestro-web-sdk.esm.js +1 -1
  60. package/dist/38.maestro-web-sdk.esm.js.map +1 -1
  61. package/dist/39.maestro-web-sdk.esm.js +1 -1
  62. package/dist/39.maestro-web-sdk.esm.js.map +1 -1
  63. package/dist/6.maestro-web-sdk.esm.js +1 -1
  64. package/dist/7.maestro-web-sdk.esm.js +1 -1
  65. package/dist/8.maestro-web-sdk.esm.js +1 -1
  66. package/dist/8.maestro-web-sdk.esm.js.map +1 -1
  67. package/dist/9.maestro-web-sdk.esm.js +1 -1
  68. package/dist/maestro-web-sdk.esm.js +2 -2
  69. package/dist/maestro-web-sdk.umd.js +2 -2
  70. package/dist/maestro-web-sdk.umd.js.map +1 -1
  71. package/dist/package.json +1 -1
  72. package/dist/src/modules/espn/bets/services/BetsService.js +5 -5
  73. package/dist/src/modules/espn/fantasy/services/FantasyService.js +3 -0
  74. package/dist/src/modules/espn/fantasy/view/FantasyView.js +2 -1
  75. package/dist/src/modules/espn/fantasy/view-model/FantasyViewModel.FantasyPolling.d.ts +1 -1
  76. package/dist/src/modules/espn/fantasy/view-model/FantasyViewModel.FantasyPolling.js +10 -7
  77. package/dist/src/modules/espn/fantasy/view-model/FantasyViewModel.LeagueManagerPolling.d.ts +1 -1
  78. package/dist/src/modules/espn/fantasy/view-model/FantasyViewModel.LeagueManagerPolling.js +10 -7
  79. package/dist/src/modules/espn/fantasy/view-model/FantasyViewModel.TournamentPolling.d.ts +1 -1
  80. package/dist/src/modules/espn/fantasy/view-model/FantasyViewModel.TournamentPolling.js +10 -7
  81. package/dist/src/modules/espn/fantasy/view-model/FantasyViewModel.d.ts +1 -0
  82. package/dist/src/modules/espn/fantasy/view-model/FantasyViewModel.js +42 -32
  83. package/dist/src/modules/espn/shop/services/ShopService.js +1 -1
  84. package/dist/src/modules/espn/stats/services/StatsService.js +2 -2
  85. package/dist/src/modules/fox/multi-view/services/MultiViewService.d.ts +20 -15
  86. package/dist/src/modules/fox/multi-view/services/MultiViewService.js +6 -3
  87. package/dist/src/modules/fox/multi-view/types.d.ts +20 -0
  88. package/dist/src/modules/fox/multi-view/view/BuildYourOwn/BuildYourOwn.d.ts +7 -0
  89. package/dist/src/modules/fox/multi-view/view/BuildYourOwn/BuildYourOwn.js +99 -0
  90. package/dist/src/modules/fox/multi-view/view/BuildYourOwn/index.d.ts +2 -0
  91. package/dist/src/modules/fox/multi-view/view/BuildYourOwn/index.js +2 -0
  92. package/dist/src/modules/fox/multi-view/view/CuratedMultiview/CuratedMultiviews.js +2 -1
  93. package/dist/src/modules/fox/multi-view/view/FoxMultiView.js +3 -0
  94. package/dist/src/modules/fox/multi-view/view/components/BuildYourOwnTabs/BuildYourOwnTabs.d.ts +8 -0
  95. package/dist/src/modules/fox/multi-view/view/components/BuildYourOwnTabs/BuildYourOwnTabs.js +30 -0
  96. package/dist/src/modules/fox/multi-view/view/components/BuildYourOwnTabs/index.d.ts +2 -0
  97. package/dist/src/modules/fox/multi-view/view/components/BuildYourOwnTabs/index.js +2 -0
  98. package/dist/src/modules/fox/multi-view/view/components/CustomMultiviewStreamsCard/CustomMultiviewStreamsCard.d.ts +2 -6
  99. package/dist/src/modules/fox/multi-view/view/components/curated-multiview-card/CuratedMultiviewCard.js +27 -7
  100. package/dist/src/modules/fox/multi-view/view-model/MultiViewViewModel.d.ts +25 -4
  101. package/dist/src/modules/fox/multi-view/view-model/MultiViewViewModel.js +196 -15
  102. package/package.json +1 -1
@@ -1,2 +1,2 @@
1
- (window.webpackJsonp=window.webpackJsonp||[]).push([[11],{104:function(e,t,a){"use strict";a.d(t,"a",(function(){return s})),a.d(t,"b",(function(){return i}));const s=e=>e.toLowerCase().trim().replace(/[\s\W-]+/g,"-").replace(/^-+|-+$/g,"");function i(e){let t=0;for(let a=0;a<e.length;a++){t=(t<<5)-t+e.charCodeAt(a),t&=t}return t}},122:function(e,t,a){"use strict";a.d(t,"a",(function(){return s}));const s=e=>"product"===e.type},244:function(e,t,a){"use strict";a.r(t),a.d(t,"ShopViewModel",(function(){return k}));var s=a(3),i=a(35);function r(e,t,a){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var a=e[Symbol.toPrimitive];if(void 0!==a){var s=a.call(e,t||"default");if("object"!=typeof s)return s;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}var o=class{constructor(e){r(this,"networkManager",void 0),r(this,"eventId",void 0),this.eventId=e,this.networkManager=new i.b({externalBaseURL:"https://site.api.espn.com"})}pollShopData(e,t,a){return this.networkManager.pollExternalApiRequestWithHeaders({endpoint:`/apis/site/v2/events/${this.eventId}/shop`,interval:e,method:i.a.GET,params:{},headers:{},onData:t,onError:a})}},n=a(34),l=a(122);const c={shop:[{sections:[{title:"Chiefs Shop",items:[{type:"product",name:"Men's Kansas City Chiefs Patrick Mahomes Nike Red Game Player Jersey",image:{href:"https://fanatics.frgimages.com/kansas-city-chiefs/mens-kansas-city-chiefs-patrick-mahomes-nike-red-game-player-jersey_pi3453000_ff_3453170-8a4fb50f27b4aacd8c3b_full.jpg"},price:{displayRetail:"$119.99"},detail:{title:"Chiefs Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/chiefs-mahomes-jersey",link:{href:"https://fanatics.com/chiefs-mahomes-jersey",text:"Scan to shop"}}},{type:"product",name:"Kansas City Chiefs New Era 2024 AFC Conference Champions Locker Room 9FORTY Adjustable Hat - Red",image:{href:"https://fanatics.frgimages.com/kansas-city-chiefs/kansas-city-chiefs-new-era-2024-afc-conference-champions-locker-room-9forty-adjustable-hat-red_pi5595000_ff_5595784_full.jpg"},price:{displayRetail:"$34.99",displaySale:"$24.99"},detail:{title:"Chiefs Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/chiefs-hat",link:{href:"https://fanatics.com/chiefs-hat",text:"Scan to shop"}}},{type:"browse",name:"Want More?",caption:"Browse all Chiefs merch",image:{href:"https://a.espncdn.com/i/teamlogos/nfl/500/kc.png"},detail:{title:"Chiefs Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/chiefs",link:{href:"https://fanatics.com/chiefs",text:"Scan to browse all"}}}]},{title:"49ers Shop",items:[{type:"product",name:"Men's San Francisco 49ers Brock Purdy Nike Scarlet Game Player Jersey",image:{href:"https://fanatics.frgimages.com/san-francisco-49ers/mens-san-francisco-49ers-brock-purdy-nike-scarlet-game-player-jersey_pi5068000_ff_5068449_full.jpg"},price:{displayRetail:"$119.99"},detail:{title:"49ers Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/49ers-purdy-jersey",link:{href:"https://fanatics.com/49ers-purdy-jersey",text:"Scan to shop"}}},{type:"product",name:"Men's San Francisco 49ers George Kittle Nike Scarlet Game Player Jersey",image:{href:"https://fanatics.frgimages.com/san-francisco-49ers/mens-san-francisco-49ers-george-kittle-nike-scarlet-game-player-jersey_pi4234000_ff_4234524_full.jpg"},price:{displayRetail:"$119.99",displayClearance:"$79.99"},detail:{title:"49ers Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/49ers-kittle-jersey",link:{href:"https://fanatics.com/49ers-kittle-jersey",text:"Scan to shop"}}},{type:"browse",name:"Want More?",caption:"Browse all 49ers merch",image:{href:"https://a.espncdn.com/i/teamlogos/nfl/500/sf.png"},detail:{title:"49ers Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/49ers",link:{href:"https://fanatics.com/49ers",text:"Scan to browse all"}}}]},{title:"NFL Shop",items:[{type:"product",name:"NFL Nike Official Authentic Game Football",image:{href:"https://fanatics.frgimages.com/nfl/nfl-nike-official-authentic-game-football_pi4759000_ff_4759291_full.jpg"},price:{displayRetail:"$99.99"},detail:{title:"NFL Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/nfl-football",link:{href:"https://fanatics.com/nfl-football",text:"Scan to shop"}}},{type:"browse",name:"Want More?",caption:"Browse all NFL merch",image:{href:"https://a.espncdn.com/i/teamlogos/leagues/500/nfl.png"},detail:{title:"NFL Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/nfl",link:{href:"https://fanatics.com/nfl",text:"Scan to browse all"}}}]}]}]},p={shop:[{sections:[{title:"Lakers Shop",items:[{type:"product",name:"Men's Los Angeles Lakers LeBron James Nike Purple Swingman Jersey - Icon Edition",image:{href:"https://fanatics.frgimages.com/los-angeles-lakers/mens-los-angeles-lakers-lebron-james-nike-purple-swingman-jersey-icon-edition_pi4548000_ff_4548764_full.jpg"},price:{displayRetail:"$129.99"},detail:{title:"Lakers Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/lakers-lebron-jersey",link:{href:"https://fanatics.com/lakers-lebron-jersey",text:"Scan to shop"}}},{type:"product",name:"Men's Los Angeles Lakers Anthony Davis Nike Gold Swingman Jersey - City Edition",image:{href:"https://fanatics.frgimages.com/los-angeles-lakers/mens-los-angeles-lakers-anthony-davis-nike-gold-swingman-jersey-city-edition_pi5129000_ff_5129446_full.jpg"},price:{displayRetail:"$129.99"},detail:{title:"Lakers Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/lakers-davis-jersey",link:{href:"https://fanatics.com/lakers-davis-jersey",text:"Scan to shop"}}},{type:"browse",name:"Want More?",caption:"Browse all Lakers merch",image:{href:"https://a.espncdn.com/i/teamlogos/nba/500/lal.png"},detail:{title:"Lakers Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/lakers",link:{href:"https://fanatics.com/lakers",text:"Scan to browse all"}}}]}]}]},h={shop:[{sections:[{title:"Texas Football Shop",items:[{type:"product",name:"Texas Longhorns Champion University Tee - Burnt Orange",image:{href:"https://fanatics.frgimages.com/texas-longhorns/texas-longhorns-champion-university-tee-burnt-orange_pi4892000_ff_4892615_full.jpg"},price:{displayRetail:"$34.99"},detail:{title:"Texas Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas-tee",link:{href:"https://fanatics.com/texas-tee",text:"Scan to shop"}}},{type:"browse",name:"Want More?",caption:"Browse all Texas merch",image:{href:"https://a.espncdn.com/i/teamlogos/ncaa/500/251.png"},detail:{title:"Texas Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas",link:{href:"https://fanatics.com/texas",text:"Scan to browse all"}}}]},{title:"Texas A&M Shop",items:[{type:"product",name:"Texas A&M Aggies New Era Maroon 9FORTY Adjustable Hat",image:{href:"https://fanatics.frgimages.com/texas-am-aggies/texas-am-aggies-new-era-maroon-9forty-adjustable-hat_pi4156000_ff_4156429_full.jpg"},price:{displayRetail:"$29.99"},detail:{title:"Texas A&M Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas-am-hat",link:{href:"https://fanatics.com/texas-am-hat",text:"Scan to shop"}}},{type:"browse",name:"Want More?",caption:"Browse all Texas A&M merch",image:{href:"https://a.espncdn.com/i/teamlogos/ncaa/500/245.png"},detail:{title:"Texas A&M Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas-am",link:{href:"https://fanatics.com/texas-am",text:"Scan to browse all"}}}]}]}]},f={shop:[{sections:[],defaultItem:{detail:{disclaimer:"Visit shop.espn.com to explore more products and exclusive offers.",title:"Shop the ESPN Store",backgroundImage:"https://placedog.net/568x704"}}}]},d={shop:[{sections:[{title:"Team Shop",items:[{type:"product",name:"Premium Team Jersey - Official Merchandise",image:{href:"https://via.placeholder.com/400x400/0066cc/ffffff?text=Team+Jersey"},price:{displayRetail:"$89.99"},detail:{title:"Team Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/team-jersey",link:{href:"https://fanatics.com/team-jersey",text:"Scan to shop"}}},{type:"browse",name:"Want More?",caption:"Browse all team merch",image:{href:"https://via.placeholder.com/400x400/0066cc/ffffff?text=Team+Logo"},detail:{title:"Team Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/team",link:{href:"https://fanatics.com/team",text:"Scan to browse all"}}}]}]}]};var m=a(4),u=a(104);function v(e,t,a){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var a=e[Symbol.toPrimitive];if(void 0!==a){var s=a.call(e,t||"default");if("object"!=typeof s)return s;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}class g{constructor(e){v(this,"polling",{interval:3e4,task:null,lastResponseHash:null}),v(this,"shopService",void 0),this.shopService=e}refresh(e){this.stop(),this.start(e)}stop(){this.polling.task&&(this.polling.task.stop(),this.polling.task=null)}removeLastResponseHash(){this.polling.lastResponseHash=null}start(e){try{this.polling.task=this.shopService.pollShopData(this.polling.interval,t=>{this.updateInterval(t.headers,e),this.processPolledData(t.data,e)},e=>this.handlePollingError(e))}catch(e){Object(m.a)(e,{context:"ShopViewModel.pollShop"}),console.error("[SHOP] Error setting up shop polling:",e)}}updateInterval(e,t){const a=this.getResponseHeaderPollingIntervalValue(e);a&&a!==this.polling.interval&&(console.log(`[SHOP] Updating shop polling interval from ${this.polling.interval}ms to ${a}ms`),this.polling.interval=a,this.refresh(t))}getResponseHeaderPollingIntervalValue(e){const t=e["polling-interval"];if(!t)return null;const a=parseInt(t,10);return isNaN(a)||a<=0?(console.warn(`[SHOP] Invalid polling interval header received: ${t}.`),null):1e3*a}processPolledData(e,t){const a=Object(u.b)(JSON.stringify(e));this.polling.lastResponseHash!==a?(this.polling.lastResponseHash=a,t(e)):console.log("[SHOP] Shop Response hash is the same as last successful response - skipping update")}handlePollingError(e){console.error("[SHOP] Shop polling error:",e),Object(m.a)(e,{context:"ShopViewModel.pollShop",extra:{pollingInterval:this.polling.interval}})}}var y=a(8);function S(e,t,a){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var a=e[Symbol.toPrimitive];if(void 0!==a){var s=a.call(e,t||"default");if("object"!=typeof s)return s;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}class k extends n.a{constructor(e,t,a={}){super(),S(this,"sections",new s.a([])),S(this,"isDataLoading",new s.a(!0)),S(this,"errorState",new s.a("none")),S(this,"hasEverSuccessfullyLoaded",new s.a(!1)),S(this,"promoData",new s.a(null)),S(this,"shopService",void 0),S(this,"analyticsService",void 0),S(this,"shopPolling",void 0),S(this,"useMockData",!1),S(this,"mockDataType","nfl"),S(this,"initialized",!1),this.shopService=new o(e),this.analyticsService=t,this.shopPolling=new g(this.shopService),this.useMockData=a.useMockData||!1,this.mockDataType=a.mockDataType||"nfl"}init(){this.trackPanelView(),this.fetchNewData(),this.initialized=!0}cleanup(){this.shopPolling.stop(),this.initialized=!1}async trackPanelView(){try{var e;const t=(null===(e=y.default.getMaestroEventViewModel().statsViewModel)||void 0===e?void 0:e.currentGameState.value)||"unknown";await this.analyticsService.panelView("espnShop",{game_state:[t]})}catch(e){Object(m.a)(e,{context:"ShopViewModel.trackPanelView"}),console.error("[SHOP] Error tracking panel view:",e)}}parsePriceToNumber(e){const t=e.replace(/[^0-9.,]/g,""),a=t.lastIndexOf(","),s=t.lastIndexOf(".");let i;return i=a>s?t.replace(/\./g,"").replace(",","."):s>a?t.replace(/,/g,""):-1!==a?t.replace(",","."):t,Number(i)||0}async trackItemClick(e,t,a){try{var s,i,r,o;let f=0,d=null;const m=(null===(s=y.default.getMaestroEventViewModel().statsViewModel)||void 0===s?void 0:s.currentGameState.value)||"unknown";if(t&&Object(l.a)(t)){var n,c,p,h;const e=null===(n=t.price)||void 0===n?void 0:n.displayRetail,a=(null===(c=t.price)||void 0===c?void 0:c.displayClearance)||(null===(p=t.price)||void 0===p?void 0:p.displaySale)||(null===(h=t.price)||void 0===h?void 0:h.displayRetail);if(a&&e){const t=this.parsePriceToNumber(e),s=this.parsePriceToNumber(a);f=t>0?Math.round(100*(1-s/t)):0,d=a}}await this.analyticsService.panelClick({type:"espnShop",name:"shop_item_clicked",metadata:{card:[e],game_state:[m],product:(null==a||null===(i=a.product)||void 0===i?void 0:i.id)||null,entity_type:[(null==a||null===(r=a.product)||void 0===r?void 0:r.type)||"unknown"],entity_name:[(null==a||null===(o=a.product)||void 0===o?void 0:o.shortDisplayName)||"unknown"],price:d,sale:[f+"%"]}})}catch(e){Object(m.a)(e,{context:"ShopViewModel.trackItemClick",item:t,section:a}),console.error("[SHOP] Error tracking shop item click:",e)}}refreshPolling(){try{if(this.useMockData)return;this.shopPolling.refresh(this.processShopData.bind(this))}catch(e){this.setTabLoadFailure()}}processShopData(e){try{var t;const a=null===(t=e.shop)||void 0===t?void 0:t[0],s=(null==a?void 0:a.sections)||[];if((null==s||!s.length)&&null!=a&&a.defaultItem)return this.errorState.value="emptyShop",this.sections.value=[],void(this.promoData.value=a.defaultItem);this.sections.value=s,this.errorState.value="none",this.hasEverSuccessfullyLoaded.value=!0,this.isDataLoading.value&&(this.isDataLoading.value=!1)}catch(e){Object(m.a)(e,{context:"ShopViewModel.processShopData"}),console.error("[SHOP] Error processing shop data:",e),this.setTabLoadFailure()}}setTabLoadFailure(){this.hasEverSuccessfullyLoaded.value||(this.errorState.value="tabLoadFailure",this.sections.value=[]),this.isDataLoading.value&&(this.isDataLoading.value=!1)}fetchNewData(){this.isDataLoading.value=!0;try{if(this.useMockData)return this.sections.value=[],void this.fetchMockData();this.refreshPolling()}catch(e){Object(m.a)(e,{context:"ShopViewModel.fetchNewData"}),console.error("[SHOP] Error fetching shop data:",e),this.setTabLoadFailure()}}fetchMockData(){let e;switch(this.mockDataType){case"nba":e=p;break;case"ncf":e=h;break;case"empty":e=f;break;case"single":e=d;break;case"nfl":default:e=c}this.processShopData(e),this.hasEverSuccessfullyLoaded.value=!0,this.isDataLoading.value=!1}clearTabLoadFailure(){this.errorState.value="none",this.shopPolling.removeLastResponseHash(),setTimeout(()=>{this.refreshPolling()},100)}}t.default=k}}]);
1
+ (window.webpackJsonp=window.webpackJsonp||[]).push([[11],{104:function(e,t,a){"use strict";a.d(t,"a",(function(){return s})),a.d(t,"b",(function(){return i}));const s=e=>e.toLowerCase().trim().replace(/[\s\W-]+/g,"-").replace(/^-+|-+$/g,"");function i(e){let t=0;for(let a=0;a<e.length;a++){t=(t<<5)-t+e.charCodeAt(a),t&=t}return t}},122:function(e,t,a){"use strict";a.d(t,"a",(function(){return s}));const s=e=>"product"===e.type},245:function(e,t,a){"use strict";a.r(t),a.d(t,"ShopViewModel",(function(){return k}));var s=a(3),i=a(35);function r(e,t,a){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var a=e[Symbol.toPrimitive];if(void 0!==a){var s=a.call(e,t||"default");if("object"!=typeof s)return s;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}var o=class{constructor(e){r(this,"networkManager",void 0),r(this,"eventId",void 0),this.eventId=e,this.networkManager=new i.b({externalBaseURL:"https://site.api.espn.com"})}pollShopData(e,t,a){return this.networkManager.pollExternalApiRequestWithHeaders({endpoint:`/apis/site/v2/events/${this.eventId}/shop`,interval:e,method:i.a.GET,params:{deviceType:"ictv"},headers:{},onData:t,onError:a})}},n=a(34),l=a(122);const c={shop:[{sections:[{title:"Chiefs Shop",items:[{type:"product",name:"Men's Kansas City Chiefs Patrick Mahomes Nike Red Game Player Jersey",image:{href:"https://fanatics.frgimages.com/kansas-city-chiefs/mens-kansas-city-chiefs-patrick-mahomes-nike-red-game-player-jersey_pi3453000_ff_3453170-8a4fb50f27b4aacd8c3b_full.jpg"},price:{displayRetail:"$119.99"},detail:{title:"Chiefs Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/chiefs-mahomes-jersey",link:{href:"https://fanatics.com/chiefs-mahomes-jersey",text:"Scan to shop"}}},{type:"product",name:"Kansas City Chiefs New Era 2024 AFC Conference Champions Locker Room 9FORTY Adjustable Hat - Red",image:{href:"https://fanatics.frgimages.com/kansas-city-chiefs/kansas-city-chiefs-new-era-2024-afc-conference-champions-locker-room-9forty-adjustable-hat-red_pi5595000_ff_5595784_full.jpg"},price:{displayRetail:"$34.99",displaySale:"$24.99"},detail:{title:"Chiefs Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/chiefs-hat",link:{href:"https://fanatics.com/chiefs-hat",text:"Scan to shop"}}},{type:"browse",name:"Want More?",caption:"Browse all Chiefs merch",image:{href:"https://a.espncdn.com/i/teamlogos/nfl/500/kc.png"},detail:{title:"Chiefs Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/chiefs",link:{href:"https://fanatics.com/chiefs",text:"Scan to browse all"}}}]},{title:"49ers Shop",items:[{type:"product",name:"Men's San Francisco 49ers Brock Purdy Nike Scarlet Game Player Jersey",image:{href:"https://fanatics.frgimages.com/san-francisco-49ers/mens-san-francisco-49ers-brock-purdy-nike-scarlet-game-player-jersey_pi5068000_ff_5068449_full.jpg"},price:{displayRetail:"$119.99"},detail:{title:"49ers Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/49ers-purdy-jersey",link:{href:"https://fanatics.com/49ers-purdy-jersey",text:"Scan to shop"}}},{type:"product",name:"Men's San Francisco 49ers George Kittle Nike Scarlet Game Player Jersey",image:{href:"https://fanatics.frgimages.com/san-francisco-49ers/mens-san-francisco-49ers-george-kittle-nike-scarlet-game-player-jersey_pi4234000_ff_4234524_full.jpg"},price:{displayRetail:"$119.99",displayClearance:"$79.99"},detail:{title:"49ers Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/49ers-kittle-jersey",link:{href:"https://fanatics.com/49ers-kittle-jersey",text:"Scan to shop"}}},{type:"browse",name:"Want More?",caption:"Browse all 49ers merch",image:{href:"https://a.espncdn.com/i/teamlogos/nfl/500/sf.png"},detail:{title:"49ers Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/49ers",link:{href:"https://fanatics.com/49ers",text:"Scan to browse all"}}}]},{title:"NFL Shop",items:[{type:"product",name:"NFL Nike Official Authentic Game Football",image:{href:"https://fanatics.frgimages.com/nfl/nfl-nike-official-authentic-game-football_pi4759000_ff_4759291_full.jpg"},price:{displayRetail:"$99.99"},detail:{title:"NFL Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/nfl-football",link:{href:"https://fanatics.com/nfl-football",text:"Scan to shop"}}},{type:"browse",name:"Want More?",caption:"Browse all NFL merch",image:{href:"https://a.espncdn.com/i/teamlogos/leagues/500/nfl.png"},detail:{title:"NFL Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/nfl",link:{href:"https://fanatics.com/nfl",text:"Scan to browse all"}}}]}]}]},p={shop:[{sections:[{title:"Lakers Shop",items:[{type:"product",name:"Men's Los Angeles Lakers LeBron James Nike Purple Swingman Jersey - Icon Edition",image:{href:"https://fanatics.frgimages.com/los-angeles-lakers/mens-los-angeles-lakers-lebron-james-nike-purple-swingman-jersey-icon-edition_pi4548000_ff_4548764_full.jpg"},price:{displayRetail:"$129.99"},detail:{title:"Lakers Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/lakers-lebron-jersey",link:{href:"https://fanatics.com/lakers-lebron-jersey",text:"Scan to shop"}}},{type:"product",name:"Men's Los Angeles Lakers Anthony Davis Nike Gold Swingman Jersey - City Edition",image:{href:"https://fanatics.frgimages.com/los-angeles-lakers/mens-los-angeles-lakers-anthony-davis-nike-gold-swingman-jersey-city-edition_pi5129000_ff_5129446_full.jpg"},price:{displayRetail:"$129.99"},detail:{title:"Lakers Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/lakers-davis-jersey",link:{href:"https://fanatics.com/lakers-davis-jersey",text:"Scan to shop"}}},{type:"browse",name:"Want More?",caption:"Browse all Lakers merch",image:{href:"https://a.espncdn.com/i/teamlogos/nba/500/lal.png"},detail:{title:"Lakers Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/lakers",link:{href:"https://fanatics.com/lakers",text:"Scan to browse all"}}}]}]}]},h={shop:[{sections:[{title:"Texas Football Shop",items:[{type:"product",name:"Texas Longhorns Champion University Tee - Burnt Orange",image:{href:"https://fanatics.frgimages.com/texas-longhorns/texas-longhorns-champion-university-tee-burnt-orange_pi4892000_ff_4892615_full.jpg"},price:{displayRetail:"$34.99"},detail:{title:"Texas Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas-tee",link:{href:"https://fanatics.com/texas-tee",text:"Scan to shop"}}},{type:"browse",name:"Want More?",caption:"Browse all Texas merch",image:{href:"https://a.espncdn.com/i/teamlogos/ncaa/500/251.png"},detail:{title:"Texas Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas",link:{href:"https://fanatics.com/texas",text:"Scan to browse all"}}}]},{title:"Texas A&M Shop",items:[{type:"product",name:"Texas A&M Aggies New Era Maroon 9FORTY Adjustable Hat",image:{href:"https://fanatics.frgimages.com/texas-am-aggies/texas-am-aggies-new-era-maroon-9forty-adjustable-hat_pi4156000_ff_4156429_full.jpg"},price:{displayRetail:"$29.99"},detail:{title:"Texas A&M Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas-am-hat",link:{href:"https://fanatics.com/texas-am-hat",text:"Scan to shop"}}},{type:"browse",name:"Want More?",caption:"Browse all Texas A&M merch",image:{href:"https://a.espncdn.com/i/teamlogos/ncaa/500/245.png"},detail:{title:"Texas A&M Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas-am",link:{href:"https://fanatics.com/texas-am",text:"Scan to browse all"}}}]}]}]},d={shop:[{sections:[],defaultItem:{detail:{disclaimer:"Visit shop.espn.com to explore more products and exclusive offers.",title:"Shop the ESPN Store",backgroundImage:"https://placedog.net/568x704"}}}]},f={shop:[{sections:[{title:"Team Shop",items:[{type:"product",name:"Premium Team Jersey - Official Merchandise",image:{href:"https://via.placeholder.com/400x400/0066cc/ffffff?text=Team+Jersey"},price:{displayRetail:"$89.99"},detail:{title:"Team Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/team-jersey",link:{href:"https://fanatics.com/team-jersey",text:"Scan to shop"}}},{type:"browse",name:"Want More?",caption:"Browse all team merch",image:{href:"https://via.placeholder.com/400x400/0066cc/ffffff?text=Team+Logo"},detail:{title:"Team Shop",qrCode:"https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/team",link:{href:"https://fanatics.com/team",text:"Scan to browse all"}}}]}]}]};var m=a(4),u=a(104);function v(e,t,a){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var a=e[Symbol.toPrimitive];if(void 0!==a){var s=a.call(e,t||"default");if("object"!=typeof s)return s;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}class g{constructor(e){v(this,"polling",{interval:3e4,task:null,lastResponseHash:null}),v(this,"shopService",void 0),this.shopService=e}refresh(e){this.stop(),this.start(e)}stop(){this.polling.task&&(this.polling.task.stop(),this.polling.task=null)}removeLastResponseHash(){this.polling.lastResponseHash=null}start(e){try{this.polling.task=this.shopService.pollShopData(this.polling.interval,t=>{this.updateInterval(t.headers,e),this.processPolledData(t.data,e)},e=>this.handlePollingError(e))}catch(e){Object(m.a)(e,{context:"ShopViewModel.pollShop"}),console.error("[SHOP] Error setting up shop polling:",e)}}updateInterval(e,t){const a=this.getResponseHeaderPollingIntervalValue(e);a&&a!==this.polling.interval&&(console.log(`[SHOP] Updating shop polling interval from ${this.polling.interval}ms to ${a}ms`),this.polling.interval=a,this.refresh(t))}getResponseHeaderPollingIntervalValue(e){const t=e["polling-interval"];if(!t)return null;const a=parseInt(t,10);return isNaN(a)||a<=0?(console.warn(`[SHOP] Invalid polling interval header received: ${t}.`),null):1e3*a}processPolledData(e,t){const a=Object(u.b)(JSON.stringify(e));this.polling.lastResponseHash!==a?(this.polling.lastResponseHash=a,t(e)):console.log("[SHOP] Shop Response hash is the same as last successful response - skipping update")}handlePollingError(e){console.error("[SHOP] Shop polling error:",e),Object(m.a)(e,{context:"ShopViewModel.pollShop",extra:{pollingInterval:this.polling.interval}})}}var y=a(8);function S(e,t,a){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var a=e[Symbol.toPrimitive];if(void 0!==a){var s=a.call(e,t||"default");if("object"!=typeof s)return s;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}class k extends n.a{constructor(e,t,a={}){super(),S(this,"sections",new s.a([])),S(this,"isDataLoading",new s.a(!0)),S(this,"errorState",new s.a("none")),S(this,"hasEverSuccessfullyLoaded",new s.a(!1)),S(this,"promoData",new s.a(null)),S(this,"shopService",void 0),S(this,"analyticsService",void 0),S(this,"shopPolling",void 0),S(this,"useMockData",!1),S(this,"mockDataType","nfl"),S(this,"initialized",!1),this.shopService=new o(e),this.analyticsService=t,this.shopPolling=new g(this.shopService),this.useMockData=a.useMockData||!1,this.mockDataType=a.mockDataType||"nfl"}init(){this.trackPanelView(),this.fetchNewData(),this.initialized=!0}cleanup(){this.shopPolling.stop(),this.initialized=!1}async trackPanelView(){try{var e;const t=(null===(e=y.default.getMaestroEventViewModel().statsViewModel)||void 0===e?void 0:e.currentGameState.value)||"unknown";await this.analyticsService.panelView("espnShop",{game_state:[t]})}catch(e){Object(m.a)(e,{context:"ShopViewModel.trackPanelView"}),console.error("[SHOP] Error tracking panel view:",e)}}parsePriceToNumber(e){const t=e.replace(/[^0-9.,]/g,""),a=t.lastIndexOf(","),s=t.lastIndexOf(".");let i;return i=a>s?t.replace(/\./g,"").replace(",","."):s>a?t.replace(/,/g,""):-1!==a?t.replace(",","."):t,Number(i)||0}async trackItemClick(e,t,a){try{var s,i,r,o;let d=0,f=null;const m=(null===(s=y.default.getMaestroEventViewModel().statsViewModel)||void 0===s?void 0:s.currentGameState.value)||"unknown";if(t&&Object(l.a)(t)){var n,c,p,h;const e=null===(n=t.price)||void 0===n?void 0:n.displayRetail,a=(null===(c=t.price)||void 0===c?void 0:c.displayClearance)||(null===(p=t.price)||void 0===p?void 0:p.displaySale)||(null===(h=t.price)||void 0===h?void 0:h.displayRetail);if(a&&e){const t=this.parsePriceToNumber(e),s=this.parsePriceToNumber(a);d=t>0?Math.round(100*(1-s/t)):0,f=a}}await this.analyticsService.panelClick({type:"espnShop",name:"shop_item_clicked",metadata:{card:[e],game_state:[m],product:(null==a||null===(i=a.product)||void 0===i?void 0:i.id)||null,entity_type:[(null==a||null===(r=a.product)||void 0===r?void 0:r.type)||"unknown"],entity_name:[(null==a||null===(o=a.product)||void 0===o?void 0:o.shortDisplayName)||"unknown"],price:f,sale:[d+"%"]}})}catch(e){Object(m.a)(e,{context:"ShopViewModel.trackItemClick",item:t,section:a}),console.error("[SHOP] Error tracking shop item click:",e)}}refreshPolling(){try{if(this.useMockData)return;this.shopPolling.refresh(this.processShopData.bind(this))}catch(e){this.setTabLoadFailure()}}processShopData(e){try{var t;const a=null===(t=e.shop)||void 0===t?void 0:t[0],s=(null==a?void 0:a.sections)||[];if((null==s||!s.length)&&null!=a&&a.defaultItem)return this.errorState.value="emptyShop",this.sections.value=[],void(this.promoData.value=a.defaultItem);this.sections.value=s,this.errorState.value="none",this.hasEverSuccessfullyLoaded.value=!0,this.isDataLoading.value&&(this.isDataLoading.value=!1)}catch(e){Object(m.a)(e,{context:"ShopViewModel.processShopData"}),console.error("[SHOP] Error processing shop data:",e),this.setTabLoadFailure()}}setTabLoadFailure(){this.hasEverSuccessfullyLoaded.value||(this.errorState.value="tabLoadFailure",this.sections.value=[]),this.isDataLoading.value&&(this.isDataLoading.value=!1)}fetchNewData(){this.isDataLoading.value=!0;try{if(this.useMockData)return this.sections.value=[],void this.fetchMockData();this.refreshPolling()}catch(e){Object(m.a)(e,{context:"ShopViewModel.fetchNewData"}),console.error("[SHOP] Error fetching shop data:",e),this.setTabLoadFailure()}}fetchMockData(){let e;switch(this.mockDataType){case"nba":e=p;break;case"ncf":e=h;break;case"empty":e=d;break;case"single":e=f;break;case"nfl":default:e=c}this.processShopData(e),this.hasEverSuccessfullyLoaded.value=!0,this.isDataLoading.value=!1}clearTabLoadFailure(){this.errorState.value="none",this.shopPolling.removeLastResponseHash(),setTimeout(()=>{this.refreshPolling()},100)}}t.default=k}}]);
2
2
  //# sourceMappingURL=11.maestro-web-sdk.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["webpack:///./src/helpers/strings.ts","webpack:///./src/modules/espn/shop/types.ts","webpack:///./src/modules/espn/shop/services/ShopService.ts","webpack:///./src/modules/espn/shop/mocks.ts","webpack:///./src/modules/espn/shop/view-model/ShopViewModel.ShopPolling.ts","webpack:///./src/modules/espn/shop/view-model/ShopViewModel.ts"],"names":["slugify","str","toLowerCase","trim","replace","stringHashCode","hash","i","length","charCodeAt","isShopProduct","item","type","ShopService","constructor","eventId","_defineProperty","this","networkManager","NetworkManager","externalBaseURL","pollShopData","interval","onData","onError","pollExternalApiRequestWithHeaders","endpoint","method","HttpMethod","GET","params","headers","MOCK_SHOP_NFL_RESPONSE","shop","sections","title","items","name","image","href","price","displayRetail","detail","qrCode","link","text","displaySale","caption","displayClearance","MOCK_SHOP_NBA_RESPONSE","MOCK_SHOP_NCF_RESPONSE","MOCK_SHOP_EMPTY_RESPONSE","defaultItem","disclaimer","backgroundImage","MOCK_SHOP_SINGLE_SECTION_RESPONSE","ShopPolling","service","task","lastResponseHash","shopService","refresh","callback","stop","start","polling","removeLastResponseHash","response","updateInterval","processPolledData","data","error","handlePollingError","captureException","context","console","headerInterval","getResponseHeaderPollingIntervalValue","log","newInterval","parsedInterval","parseInt","isNaN","warn","responseHash","JSON","stringify","extra","pollingInterval","ShopViewModel","ViewModel","analyticsService","options","super","Observable","shopPolling","useMockData","mockDataType","init","trackPanelView","fetchNewData","initialized","cleanup","_SDK$getMaestroEventV","gameState","SDK","getMaestroEventViewModel","statsViewModel","currentGameState","value","panelView","game_state","parsePriceToNumber","priceString","cleaned","lastComma","lastIndexOf","lastDot","normalized","Number","card","section","_SDK$getMaestroEventV2","_section$product","_section$product2","_section$product3","sale","_item$price","_item$price2","_item$price3","_item$price4","basePrice","currentPrice","basePriceNumber","salePriceNumber","Math","round","panelClick","metadata","product","id","entity_type","entity_name","shortDisplayName","refreshPolling","processShopData","bind","err","setTabLoadFailure","_data$shop","errorState","promoData","hasEverSuccessfullyLoaded","isDataLoading","fetchMockData","mockData","clearTabLoadFailure","setTimeout"],"mappings":"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","file":"11.maestro-web-sdk.esm.js","sourcesContent":["export const slugify = (str: string) =>\n str\n .toLowerCase()\n .trim()\n .replace(/[\\s\\W-]+/g, '-')\n .replace(/^-+|-+$/g, '');\n\nexport function stringHashCode(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return hash;\n}\n","/**\n * Shop module type definitions\n * Based on ESPN Shop API structure\n */\n\n/**\n * Image reference\n */\nexport interface IShopImage {\n /** Image URL */\n href?: string;\n /** Image width */\n width?: number;\n /** Image height */\n height?: number;\n}\n\n/**\n * Logo reference (same structure as image)\n */\nexport interface IShopLogo {\n /** Logo URL */\n href?: string;\n /** Logo width */\n width?: number;\n /** Logo height */\n height?: number;\n}\n\n/**\n * Link reference\n */\nexport interface IShopLink {\n /** Link URL */\n href?: string;\n /** Link text */\n text?: string;\n /** Link relations (e.g., [\"ictv\", \"fanatics\", \"index\", \"team\"]) */\n rel?: string[];\n}\n\n/**\n * Price information for a product\n */\nexport interface IShopPrice {\n /** Retail price display string (e.g., \"$29.99\") */\n displayRetail?: string;\n /** Sale price display string (e.g., \"$19.99\") - optional */\n displaySale?: string;\n /** Clearance price display string (e.g., \"$14.99\") - optional */\n displayClearance?: string;\n}\n\n/**\n * Product detail information shown in detail view\n */\nexport interface IShopDetail {\n /** Title for the detail view */\n title?: string;\n /** Description (optional, used for browse cards) */\n description?: string;\n /** Link information */\n link?: IShopLink;\n /** Background image URL */\n backgroundImage?: string;\n /** QR code image URL */\n qrCode?: string;\n /** Disclaimer text */\n disclaimer?: string;\n}\n\n/**\n * Product item in a shop section\n */\nexport interface IShopProduct {\n /** Item type discriminator */\n type?: 'product';\n /** Product name */\n name?: string;\n /** Product image */\n image?: IShopImage;\n /** Price information */\n price?: IShopPrice;\n /** Detail view information */\n detail?: IShopDetail;\n}\n\n/**\n * Browse card item (Want More?) in a shop section\n */\nexport interface IShopBrowseCard {\n /** Item type discriminator */\n type?: 'browse';\n /** Browse card name */\n name?: string;\n /** Caption text (e.g., \"Browse all Canadiens merch\") */\n caption?: string;\n /** Team/League/Event logo */\n image?: IShopImage;\n /** Detail view information */\n detail?: IShopDetail;\n}\n\n/**\n * Union type for all shop items\n */\nexport type IShopItem = IShopProduct | IShopBrowseCard;\n\n/**\n * Section product information (team/league info)\n */\nexport interface IShopSectionProduct {\n /** Product/Team ID */\n id?: string;\n /** Short display name (e.g., \"Canadiens\") */\n shortDisplayName?: string;\n /** Logo reference */\n logo?: IShopLogo;\n /** Type (e.g., \"team\") */\n type?: string;\n /** Link information */\n link?: IShopLink;\n /** Background image URL */\n backgroundImage?: string;\n}\n\n/**\n * Shop section containing a title and list of items\n */\nexport interface IShopSection {\n /** Section title (e.g., \"Shop Canadiens Merch\") */\n title?: string;\n /** Section product/team information */\n product?: IShopSectionProduct;\n /** Array of products or browse cards */\n items?: IShopItem[];\n}\n\nexport type IShopDefaultItem = {\n image?: {\n href?: string;\n width?: number;\n height?: number;\n };\n type?: string;\n detail?: {\n title?: string;\n link?: {\n href?: string;\n text?: string;\n };\n backgroundImage?: string;\n qrCode?: string;\n disclaimer?: string;\n };\n};\n\n/**\n * Shop container with sections\n */\nexport interface IShopContainer {\n /** Array of shop sections */\n sections?: IShopSection[];\n defaultItem?: IShopDefaultItem;\n}\n\n/**\n * Main shop API response\n */\nexport interface IShopResponse {\n /** Array of shop containers (typically one) */\n shop?: IShopContainer[];\n}\n\nexport const isShopProduct = (item: IShopItem): item is IShopProduct => {\n return item.type === 'product';\n};\n\nexport interface IShopViewModel {\n cleanup(): void;\n}\n","import NetworkManager, {\n HttpMethod,\n} from '../../../../services/NetworkManager/NetworkManager';\nimport { IShopResponse } from '../types';\nimport { ResponseWithHeaders } from '../../../../services/NetworkManager/types';\n\n/**\n * Service for handling shop-related API calls\n */\nclass ShopService {\n public networkManager: NetworkManager;\n private eventId: string;\n\n constructor(eventId: string) {\n this.eventId = eventId;\n this.networkManager = new NetworkManager({\n externalBaseURL: 'https://site.api.espn.com',\n });\n }\n\n /**\n * Start polling shop data\n *\n * @param interval - The polling interval in milliseconds\n * @param onData - Callback for successful data fetch with headers\n * @param onError - Callback for errors\n * @returns Object with a stop function to stop polling\n */\n pollShopData(\n interval: number,\n onData: (data: ResponseWithHeaders<IShopResponse>) => void,\n onError?: (error: Error) => void\n ): { stop: () => void } {\n return this.networkManager.pollExternalApiRequestWithHeaders({\n endpoint: `/apis/site/v2/events/${this.eventId}/shop`,\n interval,\n method: HttpMethod.GET,\n params: {},\n headers: {},\n onData,\n onError,\n });\n }\n}\n\nexport default ShopService;\n","import { IShopResponse } from './types';\n\n/**\n * Mock shop data for NFL game with multiple sections\n * Covers: regular products, sale products, and browse card\n */\nexport const MOCK_SHOP_NFL_RESPONSE: IShopResponse = {\n shop: [\n {\n sections: [\n {\n title: 'Chiefs Shop',\n items: [\n {\n type: 'product',\n name:\n \"Men's Kansas City Chiefs Patrick Mahomes Nike Red Game Player Jersey\",\n image: {\n href:\n 'https://fanatics.frgimages.com/kansas-city-chiefs/mens-kansas-city-chiefs-patrick-mahomes-nike-red-game-player-jersey_pi3453000_ff_3453170-8a4fb50f27b4aacd8c3b_full.jpg',\n },\n price: {\n displayRetail: '$119.99',\n },\n detail: {\n title: 'Chiefs Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/chiefs-mahomes-jersey',\n link: {\n href: 'https://fanatics.com/chiefs-mahomes-jersey',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'product',\n name:\n 'Kansas City Chiefs New Era 2024 AFC Conference Champions Locker Room 9FORTY Adjustable Hat - Red',\n image: {\n href:\n 'https://fanatics.frgimages.com/kansas-city-chiefs/kansas-city-chiefs-new-era-2024-afc-conference-champions-locker-room-9forty-adjustable-hat-red_pi5595000_ff_5595784_full.jpg',\n },\n price: {\n displayRetail: '$34.99',\n displaySale: '$24.99',\n },\n detail: {\n title: 'Chiefs Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/chiefs-hat',\n link: {\n href: 'https://fanatics.com/chiefs-hat',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'browse',\n name: 'Want More?',\n caption: 'Browse all Chiefs merch',\n image: {\n href: 'https://a.espncdn.com/i/teamlogos/nfl/500/kc.png',\n },\n detail: {\n title: 'Chiefs Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/chiefs',\n link: {\n href: 'https://fanatics.com/chiefs',\n text: 'Scan to browse all',\n },\n },\n },\n ],\n },\n {\n title: '49ers Shop',\n items: [\n {\n type: 'product',\n name:\n \"Men's San Francisco 49ers Brock Purdy Nike Scarlet Game Player Jersey\",\n image: {\n href:\n 'https://fanatics.frgimages.com/san-francisco-49ers/mens-san-francisco-49ers-brock-purdy-nike-scarlet-game-player-jersey_pi5068000_ff_5068449_full.jpg',\n },\n price: {\n displayRetail: '$119.99',\n },\n detail: {\n title: '49ers Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/49ers-purdy-jersey',\n link: {\n href: 'https://fanatics.com/49ers-purdy-jersey',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'product',\n name:\n \"Men's San Francisco 49ers George Kittle Nike Scarlet Game Player Jersey\",\n image: {\n href:\n 'https://fanatics.frgimages.com/san-francisco-49ers/mens-san-francisco-49ers-george-kittle-nike-scarlet-game-player-jersey_pi4234000_ff_4234524_full.jpg',\n },\n price: {\n displayRetail: '$119.99',\n displayClearance: '$79.99',\n },\n detail: {\n title: '49ers Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/49ers-kittle-jersey',\n link: {\n href: 'https://fanatics.com/49ers-kittle-jersey',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'browse',\n name: 'Want More?',\n caption: 'Browse all 49ers merch',\n image: {\n href: 'https://a.espncdn.com/i/teamlogos/nfl/500/sf.png',\n },\n detail: {\n title: '49ers Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/49ers',\n link: {\n href: 'https://fanatics.com/49ers',\n text: 'Scan to browse all',\n },\n },\n },\n ],\n },\n {\n title: 'NFL Shop',\n items: [\n {\n type: 'product',\n name: 'NFL Nike Official Authentic Game Football',\n image: {\n href:\n 'https://fanatics.frgimages.com/nfl/nfl-nike-official-authentic-game-football_pi4759000_ff_4759291_full.jpg',\n },\n price: {\n displayRetail: '$99.99',\n },\n detail: {\n title: 'NFL Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/nfl-football',\n link: {\n href: 'https://fanatics.com/nfl-football',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'browse',\n name: 'Want More?',\n caption: 'Browse all NFL merch',\n image: {\n href: 'https://a.espncdn.com/i/teamlogos/leagues/500/nfl.png',\n },\n detail: {\n title: 'NFL Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/nfl',\n link: {\n href: 'https://fanatics.com/nfl',\n text: 'Scan to browse all',\n },\n },\n },\n ],\n },\n ],\n },\n ],\n};\n\n/**\n * Mock shop data for NBA game\n */\nexport const MOCK_SHOP_NBA_RESPONSE: IShopResponse = {\n shop: [\n {\n sections: [\n {\n title: 'Lakers Shop',\n items: [\n {\n type: 'product',\n name:\n \"Men's Los Angeles Lakers LeBron James Nike Purple Swingman Jersey - Icon Edition\",\n image: {\n href:\n 'https://fanatics.frgimages.com/los-angeles-lakers/mens-los-angeles-lakers-lebron-james-nike-purple-swingman-jersey-icon-edition_pi4548000_ff_4548764_full.jpg',\n },\n price: {\n displayRetail: '$129.99',\n },\n detail: {\n title: 'Lakers Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/lakers-lebron-jersey',\n link: {\n href: 'https://fanatics.com/lakers-lebron-jersey',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'product',\n name:\n \"Men's Los Angeles Lakers Anthony Davis Nike Gold Swingman Jersey - City Edition\",\n image: {\n href:\n 'https://fanatics.frgimages.com/los-angeles-lakers/mens-los-angeles-lakers-anthony-davis-nike-gold-swingman-jersey-city-edition_pi5129000_ff_5129446_full.jpg',\n },\n price: {\n displayRetail: '$129.99',\n },\n detail: {\n title: 'Lakers Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/lakers-davis-jersey',\n link: {\n href: 'https://fanatics.com/lakers-davis-jersey',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'browse',\n name: 'Want More?',\n caption: 'Browse all Lakers merch',\n image: {\n href: 'https://a.espncdn.com/i/teamlogos/nba/500/lal.png',\n },\n detail: {\n title: 'Lakers Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/lakers',\n link: {\n href: 'https://fanatics.com/lakers',\n text: 'Scan to browse all',\n },\n },\n },\n ],\n },\n ],\n },\n ],\n};\n\n/**\n * Mock shop data for NCAA Football\n */\nexport const MOCK_SHOP_NCF_RESPONSE: IShopResponse = {\n shop: [\n {\n sections: [\n {\n title: 'Texas Football Shop',\n items: [\n {\n type: 'product',\n name: 'Texas Longhorns Champion University Tee - Burnt Orange',\n image: {\n href:\n 'https://fanatics.frgimages.com/texas-longhorns/texas-longhorns-champion-university-tee-burnt-orange_pi4892000_ff_4892615_full.jpg',\n },\n price: {\n displayRetail: '$34.99',\n },\n detail: {\n title: 'Texas Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas-tee',\n link: {\n href: 'https://fanatics.com/texas-tee',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'browse',\n name: 'Want More?',\n caption: 'Browse all Texas merch',\n image: {\n href: 'https://a.espncdn.com/i/teamlogos/ncaa/500/251.png',\n },\n detail: {\n title: 'Texas Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas',\n link: {\n href: 'https://fanatics.com/texas',\n text: 'Scan to browse all',\n },\n },\n },\n ],\n },\n {\n title: 'Texas A&M Shop',\n items: [\n {\n type: 'product',\n name: 'Texas A&M Aggies New Era Maroon 9FORTY Adjustable Hat',\n image: {\n href:\n 'https://fanatics.frgimages.com/texas-am-aggies/texas-am-aggies-new-era-maroon-9forty-adjustable-hat_pi4156000_ff_4156429_full.jpg',\n },\n price: {\n displayRetail: '$29.99',\n },\n detail: {\n title: 'Texas A&M Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas-am-hat',\n link: {\n href: 'https://fanatics.com/texas-am-hat',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'browse',\n name: 'Want More?',\n caption: 'Browse all Texas A&M merch',\n image: {\n href: 'https://a.espncdn.com/i/teamlogos/ncaa/500/245.png',\n },\n detail: {\n title: 'Texas A&M Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas-am',\n link: {\n href: 'https://fanatics.com/texas-am',\n text: 'Scan to browse all',\n },\n },\n },\n ],\n },\n ],\n },\n ],\n};\n\n/**\n * Mock shop data with empty sections\n */\nexport const MOCK_SHOP_EMPTY_RESPONSE: IShopResponse = {\n shop: [\n {\n sections: [],\n defaultItem: {\n detail: {\n disclaimer:\n 'Visit shop.espn.com to explore more products and exclusive offers.',\n title: 'Shop the ESPN Store',\n backgroundImage: 'https://placedog.net/568x704',\n },\n },\n },\n ],\n};\n\n/**\n * Mock shop data with single section\n */\nexport const MOCK_SHOP_SINGLE_SECTION_RESPONSE: IShopResponse = {\n shop: [\n {\n sections: [\n {\n title: 'Team Shop',\n items: [\n {\n type: 'product',\n name: 'Premium Team Jersey - Official Merchandise',\n image: {\n href:\n 'https://via.placeholder.com/400x400/0066cc/ffffff?text=Team+Jersey',\n },\n price: {\n displayRetail: '$89.99',\n },\n detail: {\n title: 'Team Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/team-jersey',\n link: {\n href: 'https://fanatics.com/team-jersey',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'browse',\n name: 'Want More?',\n caption: 'Browse all team merch',\n image: {\n href:\n 'https://via.placeholder.com/400x400/0066cc/ffffff?text=Team+Logo',\n },\n detail: {\n title: 'Team Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/team',\n link: {\n href: 'https://fanatics.com/team',\n text: 'Scan to browse all',\n },\n },\n },\n ],\n },\n ],\n },\n ],\n};\n","import { captureException } from '@/sentry';\nimport ShopService from '@/modules/espn/shop/services/ShopService';\nimport { IShopResponse } from '../types';\nimport { stringHashCode } from '@/helpers/strings';\n\ntype Polling = {\n interval: number;\n task: { stop: () => void } | null;\n lastResponseHash: number | null;\n};\n\nconst DEFAULT_SHOP_POLLING_INTERVAL = 30000; // 30 seconds\n\nexport default class ShopPolling {\n private polling: Polling = {\n interval: DEFAULT_SHOP_POLLING_INTERVAL,\n task: null,\n lastResponseHash: null,\n };\n private shopService: ShopService;\n\n constructor(service: ShopService) {\n this.shopService = service;\n }\n\n /**\n * Refresh polling for shop data\n */\n refresh(callback: (data: IShopResponse) => void): void {\n // First stop any existing polling\n this.stop();\n\n // Start the poll loop\n this.start(callback);\n }\n\n /**\n * Stop polling for shop data\n */\n stop(): void {\n if (this.polling.task) {\n this.polling.task.stop();\n this.polling.task = null;\n }\n }\n\n removeLastResponseHash(): void {\n this.polling.lastResponseHash = null;\n }\n\n private start(callback: (data: IShopResponse) => void): void {\n try {\n this.polling.task = this.shopService.pollShopData(\n this.polling.interval,\n (response) => {\n this.updateInterval(response.headers, callback);\n this.processPolledData(response.data, callback);\n },\n (error) => this.handlePollingError(error)\n );\n } catch (error) {\n captureException(error, {\n context: 'ShopViewModel.pollShop',\n });\n console.error('[SHOP] Error setting up shop polling:', error);\n }\n }\n\n /**\n * @description Update polling interval checking either response header or panel config.\n * Refresh polling if necessary.\n */\n private updateInterval(\n headers: Record<string, string>,\n callback: (data: IShopResponse) => void\n ): void {\n const headerInterval = this.getResponseHeaderPollingIntervalValue(headers);\n\n // Only update if we have a valid new interval and it's different from current\n if (headerInterval && headerInterval !== this.polling.interval) {\n console.log(\n `[SHOP] Updating shop polling interval from ${this.polling.interval}ms to ${headerInterval}ms`\n );\n this.polling.interval = headerInterval;\n // Restart polling with the new interval\n this.refresh(callback);\n }\n }\n\n private getResponseHeaderPollingIntervalValue(\n headers: Record<string, string>\n ): number | null {\n const newInterval = headers['polling-interval'];\n if (!newInterval) {\n return null;\n }\n\n const parsedInterval = parseInt(newInterval, 10);\n if (isNaN(parsedInterval) || parsedInterval <= 0) {\n console.warn(\n `[SHOP] Invalid polling interval header received: ${newInterval}.`\n );\n return null;\n }\n\n return parsedInterval * 1000; // Convert seconds to milliseconds\n }\n\n /**\n * Process data received from polling\n */\n private processPolledData(\n data: IShopResponse,\n callback: (data: IShopResponse) => void\n ): void {\n // Calculate hash for the response to check if it's different from the last one\n const responseHash = stringHashCode(JSON.stringify(data));\n\n // Check if this is the same as the last successful response\n if (this.polling.lastResponseHash === responseHash) {\n console.log(\n '[SHOP] Shop Response hash is the same as last successful response - skipping update'\n );\n return;\n }\n\n this.polling.lastResponseHash = responseHash;\n callback(data);\n }\n\n /**\n * Handle errors that occur during shop polling\n */\n private handlePollingError(error: Error): void {\n console.error('[SHOP] Shop polling error:', error);\n\n captureException(error, {\n context: 'ShopViewModel.pollShop',\n extra: {\n pollingInterval: this.polling.interval,\n },\n });\n }\n}\n","import { Observable } from '../../../../helpers/Observable';\nimport ShopService from '../services/ShopService';\nimport AnalyticsService from '@/services/AnalyticsService/AnalyticsService';\nimport { ViewModel } from '../../../../view-models/ViewModel';\nimport {\n IShopResponse,\n IShopSection,\n IShopProduct,\n IShopBrowseCard,\n isShopProduct,\n IShopDefaultItem,\n} from '../types';\nimport {\n MOCK_SHOP_NFL_RESPONSE,\n MOCK_SHOP_NBA_RESPONSE,\n MOCK_SHOP_NCF_RESPONSE,\n MOCK_SHOP_EMPTY_RESPONSE,\n MOCK_SHOP_SINGLE_SECTION_RESPONSE,\n} from '../mocks';\n\nimport { captureException } from '@/sentry';\nimport ShopPolling from './ShopViewModel.ShopPolling';\nimport SDK from '@/index';\n\nconst SHOP_ERROR_STATE = {\n NONE: 'none',\n TAB_LOAD_FAILURE: 'tabLoadFailure',\n EMPTY_SHOP: 'emptyShop',\n} as const;\n\nexport type ShopErrorState = typeof SHOP_ERROR_STATE[keyof typeof SHOP_ERROR_STATE];\n\n/**\n * ViewModel for Shop panel\n * Manages shop data fetching, polling, and state\n */\nexport class ShopViewModel extends ViewModel {\n // Observable properties\n public sections = new Observable<IShopSection[]>([]);\n public isDataLoading = new Observable<boolean>(true);\n public errorState = new Observable<ShopErrorState>('none');\n public hasEverSuccessfullyLoaded = new Observable<boolean>(false);\n public promoData = new Observable<IShopDefaultItem | null>(null);\n\n // Properties\n private shopService: ShopService;\n private analyticsService: AnalyticsService;\n private shopPolling: ShopPolling;\n private useMockData: boolean = false;\n private mockDataType: string = 'nfl';\n initialized = false;\n\n constructor(\n eventId: string,\n analyticsService: AnalyticsService,\n options: {\n useMockData?: boolean;\n mockDataType?: 'nfl' | 'nba' | 'ncf' | 'empty' | 'single';\n } = {}\n ) {\n super();\n this.shopService = new ShopService(eventId);\n this.analyticsService = analyticsService;\n this.shopPolling = new ShopPolling(this.shopService);\n this.useMockData = options.useMockData || false;\n this.mockDataType = options.mockDataType || 'nfl';\n }\n\n /**\n * Initialize the ViewModel and start data fetching\n */\n init() {\n // Track panel view on initialization\n this.trackPanelView();\n\n this.fetchNewData();\n this.initialized = true;\n }\n\n /**\n * Clean up resources when the ViewModel is no longer needed\n */\n cleanup(): void {\n this.shopPolling.stop();\n this.initialized = false;\n }\n\n /**\n * Track panel view event\n */\n private async trackPanelView(): Promise<void> {\n try {\n const gameState =\n SDK.getMaestroEventViewModel().statsViewModel?.currentGameState.value ||\n 'unknown';\n\n await this.analyticsService.panelView('espnShop', {\n game_state: [gameState],\n });\n } catch (error) {\n captureException(error, {\n context: 'ShopViewModel.trackPanelView',\n });\n console.error('[SHOP] Error tracking panel view:', error);\n }\n }\n\n /**\n * Parse price string to number, handling currency formats\n */\n private parsePriceToNumber(priceString: string): number {\n // Remove currency symbols and spaces\n const cleaned = priceString.replace(/[^0-9.,]/g, '');\n\n // Find the last occurrence of comma or dot (decimal separator)\n const lastComma = cleaned.lastIndexOf(',');\n const lastDot = cleaned.lastIndexOf('.');\n\n let normalized: string;\n\n if (lastComma > lastDot) {\n // EU format: €1.234,56 -> comma is decimal separator\n normalized = cleaned.replace(/\\./g, '').replace(',', '.');\n } else if (lastDot > lastComma) {\n // US format: $1,234.56 -> dot is decimal separator\n normalized = cleaned.replace(/,/g, '');\n } else if (lastComma !== -1) {\n // Only comma present, assume decimal: €25,00\n normalized = cleaned.replace(',', '.');\n } else if (lastDot !== -1) {\n // Only dot present, assume decimal: $25.00\n normalized = cleaned;\n } else {\n // No separators: 25\n normalized = cleaned;\n }\n\n return Number(normalized) || 0;\n }\n\n /**\n * Track shop item card click event\n */\n async trackItemClick(\n card: 'product_summary' | 'want more' | 'product_detail' | 'fallback',\n item: IShopProduct | IShopBrowseCard | null,\n section: IShopSection | null\n ): Promise<void> {\n try {\n let sale = 0;\n let price: string | null = null;\n\n const gameState =\n SDK.getMaestroEventViewModel().statsViewModel?.currentGameState.value ||\n 'unknown';\n\n if (item && isShopProduct(item)) {\n const basePrice = item.price?.displayRetail;\n const currentPrice =\n item.price?.displayClearance ||\n item.price?.displaySale ||\n item.price?.displayRetail;\n\n if (currentPrice && basePrice) {\n const basePriceNumber = this.parsePriceToNumber(basePrice);\n const salePriceNumber = this.parsePriceToNumber(currentPrice);\n\n if (basePriceNumber > 0) {\n sale = Math.round((1 - salePriceNumber / basePriceNumber) * 100);\n } else {\n sale = 0;\n }\n price = currentPrice;\n }\n }\n\n await this.analyticsService.panelClick({\n type: 'espnShop',\n name: 'shop_item_clicked',\n metadata: {\n card: [card],\n game_state: [gameState],\n product: section?.product?.id || null,\n entity_type: [section?.product?.type || 'unknown'],\n entity_name: [section?.product?.shortDisplayName || 'unknown'],\n price,\n sale: [`${sale}%`],\n },\n });\n } catch (error) {\n captureException(error, {\n context: 'ShopViewModel.trackItemClick',\n item,\n section,\n });\n console.error('[SHOP] Error tracking shop item click:', error);\n }\n }\n\n /**\n * Refresh polling for shop data\n */\n refreshPolling(): void {\n try {\n if (this.useMockData) {\n return;\n }\n\n this.shopPolling.refresh(this.processShopData.bind(this));\n } catch (err) {\n this.setTabLoadFailure();\n }\n }\n\n /**\n * Process the shop data and update the sections\n */\n private processShopData(data: IShopResponse) {\n try {\n const shop = data.shop?.[0];\n const sections = shop?.sections || [];\n\n // Check if there are any sections\n if (!sections?.length && shop?.defaultItem) {\n this.errorState.value = 'emptyShop';\n this.sections.value = [];\n\n this.promoData.value = shop.defaultItem;\n return;\n }\n\n // Update sections and clear error state\n this.sections.value = sections;\n this.errorState.value = 'none';\n this.hasEverSuccessfullyLoaded.value = true;\n\n if (this.isDataLoading.value) {\n this.isDataLoading.value = false;\n }\n } catch (err) {\n captureException(err, {\n context: 'ShopViewModel.processShopData',\n });\n console.error('[SHOP] Error processing shop data:', err);\n this.setTabLoadFailure();\n }\n }\n\n setTabLoadFailure() {\n if (!this.hasEverSuccessfullyLoaded.value) {\n this.errorState.value = 'tabLoadFailure';\n this.sections.value = [];\n }\n\n if (this.isDataLoading.value) {\n this.isDataLoading.value = false;\n }\n }\n\n /**\n * Fetch new shop data immediately (one-time)\n */\n fetchNewData() {\n this.isDataLoading.value = true;\n\n try {\n // Handle mock data if enabled\n if (this.useMockData) {\n this.sections.value = [];\n this.fetchMockData();\n return;\n }\n\n this.refreshPolling();\n } catch (error) {\n captureException(error, {\n context: 'ShopViewModel.fetchNewData',\n });\n console.error('[SHOP] Error fetching shop data:', error);\n\n this.setTabLoadFailure();\n }\n }\n\n /**\n * Fetch mock data for testing\n */\n private fetchMockData() {\n let mockData: IShopResponse;\n\n switch (this.mockDataType) {\n case 'nba':\n mockData = MOCK_SHOP_NBA_RESPONSE;\n break;\n case 'ncf':\n mockData = MOCK_SHOP_NCF_RESPONSE;\n break;\n case 'empty':\n mockData = MOCK_SHOP_EMPTY_RESPONSE;\n break;\n case 'single':\n mockData = MOCK_SHOP_SINGLE_SECTION_RESPONSE;\n break;\n case 'nfl':\n default:\n mockData = MOCK_SHOP_NFL_RESPONSE;\n break;\n }\n\n this.processShopData(mockData);\n this.hasEverSuccessfullyLoaded.value = true;\n this.isDataLoading.value = false;\n }\n\n /**\n * Clear tab load failure and retry\n */\n clearTabLoadFailure() {\n this.errorState.value = 'none';\n this.shopPolling.removeLastResponseHash();\n setTimeout(() => {\n this.refreshPolling();\n }, 100);\n }\n}\n\nexport default ShopViewModel;\n"],"sourceRoot":""}
1
+ {"version":3,"sources":["webpack:///./src/helpers/strings.ts","webpack:///./src/modules/espn/shop/types.ts","webpack:///./src/modules/espn/shop/services/ShopService.ts","webpack:///./src/modules/espn/shop/mocks.ts","webpack:///./src/modules/espn/shop/view-model/ShopViewModel.ShopPolling.ts","webpack:///./src/modules/espn/shop/view-model/ShopViewModel.ts"],"names":["slugify","str","toLowerCase","trim","replace","stringHashCode","hash","i","length","charCodeAt","isShopProduct","item","type","ShopService","constructor","eventId","_defineProperty","this","networkManager","NetworkManager","externalBaseURL","pollShopData","interval","onData","onError","pollExternalApiRequestWithHeaders","endpoint","method","HttpMethod","GET","params","deviceType","headers","MOCK_SHOP_NFL_RESPONSE","shop","sections","title","items","name","image","href","price","displayRetail","detail","qrCode","link","text","displaySale","caption","displayClearance","MOCK_SHOP_NBA_RESPONSE","MOCK_SHOP_NCF_RESPONSE","MOCK_SHOP_EMPTY_RESPONSE","defaultItem","disclaimer","backgroundImage","MOCK_SHOP_SINGLE_SECTION_RESPONSE","ShopPolling","service","task","lastResponseHash","shopService","refresh","callback","stop","start","polling","removeLastResponseHash","response","updateInterval","processPolledData","data","error","handlePollingError","captureException","context","console","headerInterval","getResponseHeaderPollingIntervalValue","log","newInterval","parsedInterval","parseInt","isNaN","warn","responseHash","JSON","stringify","extra","pollingInterval","ShopViewModel","ViewModel","analyticsService","options","super","Observable","shopPolling","useMockData","mockDataType","init","trackPanelView","fetchNewData","initialized","cleanup","_SDK$getMaestroEventV","gameState","SDK","getMaestroEventViewModel","statsViewModel","currentGameState","value","panelView","game_state","parsePriceToNumber","priceString","cleaned","lastComma","lastIndexOf","lastDot","normalized","Number","card","section","_SDK$getMaestroEventV2","_section$product","_section$product2","_section$product3","sale","_item$price","_item$price2","_item$price3","_item$price4","basePrice","currentPrice","basePriceNumber","salePriceNumber","Math","round","panelClick","metadata","product","id","entity_type","entity_name","shortDisplayName","refreshPolling","processShopData","bind","err","setTabLoadFailure","_data$shop","errorState","promoData","hasEverSuccessfullyLoaded","isDataLoading","fetchMockData","mockData","clearTabLoadFailure","setTimeout"],"mappings":"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","file":"11.maestro-web-sdk.esm.js","sourcesContent":["export const slugify = (str: string) =>\n str\n .toLowerCase()\n .trim()\n .replace(/[\\s\\W-]+/g, '-')\n .replace(/^-+|-+$/g, '');\n\nexport function stringHashCode(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return hash;\n}\n","/**\n * Shop module type definitions\n * Based on ESPN Shop API structure\n */\n\n/**\n * Image reference\n */\nexport interface IShopImage {\n /** Image URL */\n href?: string;\n /** Image width */\n width?: number;\n /** Image height */\n height?: number;\n}\n\n/**\n * Logo reference (same structure as image)\n */\nexport interface IShopLogo {\n /** Logo URL */\n href?: string;\n /** Logo width */\n width?: number;\n /** Logo height */\n height?: number;\n}\n\n/**\n * Link reference\n */\nexport interface IShopLink {\n /** Link URL */\n href?: string;\n /** Link text */\n text?: string;\n /** Link relations (e.g., [\"ictv\", \"fanatics\", \"index\", \"team\"]) */\n rel?: string[];\n}\n\n/**\n * Price information for a product\n */\nexport interface IShopPrice {\n /** Retail price display string (e.g., \"$29.99\") */\n displayRetail?: string;\n /** Sale price display string (e.g., \"$19.99\") - optional */\n displaySale?: string;\n /** Clearance price display string (e.g., \"$14.99\") - optional */\n displayClearance?: string;\n}\n\n/**\n * Product detail information shown in detail view\n */\nexport interface IShopDetail {\n /** Title for the detail view */\n title?: string;\n /** Description (optional, used for browse cards) */\n description?: string;\n /** Link information */\n link?: IShopLink;\n /** Background image URL */\n backgroundImage?: string;\n /** QR code image URL */\n qrCode?: string;\n /** Disclaimer text */\n disclaimer?: string;\n}\n\n/**\n * Product item in a shop section\n */\nexport interface IShopProduct {\n /** Item type discriminator */\n type?: 'product';\n /** Product name */\n name?: string;\n /** Product image */\n image?: IShopImage;\n /** Price information */\n price?: IShopPrice;\n /** Detail view information */\n detail?: IShopDetail;\n}\n\n/**\n * Browse card item (Want More?) in a shop section\n */\nexport interface IShopBrowseCard {\n /** Item type discriminator */\n type?: 'browse';\n /** Browse card name */\n name?: string;\n /** Caption text (e.g., \"Browse all Canadiens merch\") */\n caption?: string;\n /** Team/League/Event logo */\n image?: IShopImage;\n /** Detail view information */\n detail?: IShopDetail;\n}\n\n/**\n * Union type for all shop items\n */\nexport type IShopItem = IShopProduct | IShopBrowseCard;\n\n/**\n * Section product information (team/league info)\n */\nexport interface IShopSectionProduct {\n /** Product/Team ID */\n id?: string;\n /** Short display name (e.g., \"Canadiens\") */\n shortDisplayName?: string;\n /** Logo reference */\n logo?: IShopLogo;\n /** Type (e.g., \"team\") */\n type?: string;\n /** Link information */\n link?: IShopLink;\n /** Background image URL */\n backgroundImage?: string;\n}\n\n/**\n * Shop section containing a title and list of items\n */\nexport interface IShopSection {\n /** Section title (e.g., \"Shop Canadiens Merch\") */\n title?: string;\n /** Section product/team information */\n product?: IShopSectionProduct;\n /** Array of products or browse cards */\n items?: IShopItem[];\n}\n\nexport type IShopDefaultItem = {\n image?: {\n href?: string;\n width?: number;\n height?: number;\n };\n type?: string;\n detail?: {\n title?: string;\n link?: {\n href?: string;\n text?: string;\n };\n backgroundImage?: string;\n qrCode?: string;\n disclaimer?: string;\n };\n};\n\n/**\n * Shop container with sections\n */\nexport interface IShopContainer {\n /** Array of shop sections */\n sections?: IShopSection[];\n defaultItem?: IShopDefaultItem;\n}\n\n/**\n * Main shop API response\n */\nexport interface IShopResponse {\n /** Array of shop containers (typically one) */\n shop?: IShopContainer[];\n}\n\nexport const isShopProduct = (item: IShopItem): item is IShopProduct => {\n return item.type === 'product';\n};\n\nexport interface IShopViewModel {\n cleanup(): void;\n}\n","import NetworkManager, {\n HttpMethod,\n} from '../../../../services/NetworkManager/NetworkManager';\nimport { IShopResponse } from '../types';\nimport { ResponseWithHeaders } from '../../../../services/NetworkManager/types';\n\n/**\n * Service for handling shop-related API calls\n */\nclass ShopService {\n public networkManager: NetworkManager;\n private eventId: string;\n\n constructor(eventId: string) {\n this.eventId = eventId;\n this.networkManager = new NetworkManager({\n externalBaseURL: 'https://site.api.espn.com',\n });\n }\n\n /**\n * Start polling shop data\n *\n * @param interval - The polling interval in milliseconds\n * @param onData - Callback for successful data fetch with headers\n * @param onError - Callback for errors\n * @returns Object with a stop function to stop polling\n */\n pollShopData(\n interval: number,\n onData: (data: ResponseWithHeaders<IShopResponse>) => void,\n onError?: (error: Error) => void\n ): { stop: () => void } {\n return this.networkManager.pollExternalApiRequestWithHeaders({\n endpoint: `/apis/site/v2/events/${this.eventId}/shop`,\n interval,\n method: HttpMethod.GET,\n params: { deviceType: 'ictv' },\n headers: {},\n onData,\n onError,\n });\n }\n}\n\nexport default ShopService;\n","import { IShopResponse } from './types';\n\n/**\n * Mock shop data for NFL game with multiple sections\n * Covers: regular products, sale products, and browse card\n */\nexport const MOCK_SHOP_NFL_RESPONSE: IShopResponse = {\n shop: [\n {\n sections: [\n {\n title: 'Chiefs Shop',\n items: [\n {\n type: 'product',\n name:\n \"Men's Kansas City Chiefs Patrick Mahomes Nike Red Game Player Jersey\",\n image: {\n href:\n 'https://fanatics.frgimages.com/kansas-city-chiefs/mens-kansas-city-chiefs-patrick-mahomes-nike-red-game-player-jersey_pi3453000_ff_3453170-8a4fb50f27b4aacd8c3b_full.jpg',\n },\n price: {\n displayRetail: '$119.99',\n },\n detail: {\n title: 'Chiefs Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/chiefs-mahomes-jersey',\n link: {\n href: 'https://fanatics.com/chiefs-mahomes-jersey',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'product',\n name:\n 'Kansas City Chiefs New Era 2024 AFC Conference Champions Locker Room 9FORTY Adjustable Hat - Red',\n image: {\n href:\n 'https://fanatics.frgimages.com/kansas-city-chiefs/kansas-city-chiefs-new-era-2024-afc-conference-champions-locker-room-9forty-adjustable-hat-red_pi5595000_ff_5595784_full.jpg',\n },\n price: {\n displayRetail: '$34.99',\n displaySale: '$24.99',\n },\n detail: {\n title: 'Chiefs Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/chiefs-hat',\n link: {\n href: 'https://fanatics.com/chiefs-hat',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'browse',\n name: 'Want More?',\n caption: 'Browse all Chiefs merch',\n image: {\n href: 'https://a.espncdn.com/i/teamlogos/nfl/500/kc.png',\n },\n detail: {\n title: 'Chiefs Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/chiefs',\n link: {\n href: 'https://fanatics.com/chiefs',\n text: 'Scan to browse all',\n },\n },\n },\n ],\n },\n {\n title: '49ers Shop',\n items: [\n {\n type: 'product',\n name:\n \"Men's San Francisco 49ers Brock Purdy Nike Scarlet Game Player Jersey\",\n image: {\n href:\n 'https://fanatics.frgimages.com/san-francisco-49ers/mens-san-francisco-49ers-brock-purdy-nike-scarlet-game-player-jersey_pi5068000_ff_5068449_full.jpg',\n },\n price: {\n displayRetail: '$119.99',\n },\n detail: {\n title: '49ers Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/49ers-purdy-jersey',\n link: {\n href: 'https://fanatics.com/49ers-purdy-jersey',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'product',\n name:\n \"Men's San Francisco 49ers George Kittle Nike Scarlet Game Player Jersey\",\n image: {\n href:\n 'https://fanatics.frgimages.com/san-francisco-49ers/mens-san-francisco-49ers-george-kittle-nike-scarlet-game-player-jersey_pi4234000_ff_4234524_full.jpg',\n },\n price: {\n displayRetail: '$119.99',\n displayClearance: '$79.99',\n },\n detail: {\n title: '49ers Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/49ers-kittle-jersey',\n link: {\n href: 'https://fanatics.com/49ers-kittle-jersey',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'browse',\n name: 'Want More?',\n caption: 'Browse all 49ers merch',\n image: {\n href: 'https://a.espncdn.com/i/teamlogos/nfl/500/sf.png',\n },\n detail: {\n title: '49ers Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/49ers',\n link: {\n href: 'https://fanatics.com/49ers',\n text: 'Scan to browse all',\n },\n },\n },\n ],\n },\n {\n title: 'NFL Shop',\n items: [\n {\n type: 'product',\n name: 'NFL Nike Official Authentic Game Football',\n image: {\n href:\n 'https://fanatics.frgimages.com/nfl/nfl-nike-official-authentic-game-football_pi4759000_ff_4759291_full.jpg',\n },\n price: {\n displayRetail: '$99.99',\n },\n detail: {\n title: 'NFL Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/nfl-football',\n link: {\n href: 'https://fanatics.com/nfl-football',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'browse',\n name: 'Want More?',\n caption: 'Browse all NFL merch',\n image: {\n href: 'https://a.espncdn.com/i/teamlogos/leagues/500/nfl.png',\n },\n detail: {\n title: 'NFL Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/nfl',\n link: {\n href: 'https://fanatics.com/nfl',\n text: 'Scan to browse all',\n },\n },\n },\n ],\n },\n ],\n },\n ],\n};\n\n/**\n * Mock shop data for NBA game\n */\nexport const MOCK_SHOP_NBA_RESPONSE: IShopResponse = {\n shop: [\n {\n sections: [\n {\n title: 'Lakers Shop',\n items: [\n {\n type: 'product',\n name:\n \"Men's Los Angeles Lakers LeBron James Nike Purple Swingman Jersey - Icon Edition\",\n image: {\n href:\n 'https://fanatics.frgimages.com/los-angeles-lakers/mens-los-angeles-lakers-lebron-james-nike-purple-swingman-jersey-icon-edition_pi4548000_ff_4548764_full.jpg',\n },\n price: {\n displayRetail: '$129.99',\n },\n detail: {\n title: 'Lakers Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/lakers-lebron-jersey',\n link: {\n href: 'https://fanatics.com/lakers-lebron-jersey',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'product',\n name:\n \"Men's Los Angeles Lakers Anthony Davis Nike Gold Swingman Jersey - City Edition\",\n image: {\n href:\n 'https://fanatics.frgimages.com/los-angeles-lakers/mens-los-angeles-lakers-anthony-davis-nike-gold-swingman-jersey-city-edition_pi5129000_ff_5129446_full.jpg',\n },\n price: {\n displayRetail: '$129.99',\n },\n detail: {\n title: 'Lakers Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/lakers-davis-jersey',\n link: {\n href: 'https://fanatics.com/lakers-davis-jersey',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'browse',\n name: 'Want More?',\n caption: 'Browse all Lakers merch',\n image: {\n href: 'https://a.espncdn.com/i/teamlogos/nba/500/lal.png',\n },\n detail: {\n title: 'Lakers Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/lakers',\n link: {\n href: 'https://fanatics.com/lakers',\n text: 'Scan to browse all',\n },\n },\n },\n ],\n },\n ],\n },\n ],\n};\n\n/**\n * Mock shop data for NCAA Football\n */\nexport const MOCK_SHOP_NCF_RESPONSE: IShopResponse = {\n shop: [\n {\n sections: [\n {\n title: 'Texas Football Shop',\n items: [\n {\n type: 'product',\n name: 'Texas Longhorns Champion University Tee - Burnt Orange',\n image: {\n href:\n 'https://fanatics.frgimages.com/texas-longhorns/texas-longhorns-champion-university-tee-burnt-orange_pi4892000_ff_4892615_full.jpg',\n },\n price: {\n displayRetail: '$34.99',\n },\n detail: {\n title: 'Texas Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas-tee',\n link: {\n href: 'https://fanatics.com/texas-tee',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'browse',\n name: 'Want More?',\n caption: 'Browse all Texas merch',\n image: {\n href: 'https://a.espncdn.com/i/teamlogos/ncaa/500/251.png',\n },\n detail: {\n title: 'Texas Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas',\n link: {\n href: 'https://fanatics.com/texas',\n text: 'Scan to browse all',\n },\n },\n },\n ],\n },\n {\n title: 'Texas A&M Shop',\n items: [\n {\n type: 'product',\n name: 'Texas A&M Aggies New Era Maroon 9FORTY Adjustable Hat',\n image: {\n href:\n 'https://fanatics.frgimages.com/texas-am-aggies/texas-am-aggies-new-era-maroon-9forty-adjustable-hat_pi4156000_ff_4156429_full.jpg',\n },\n price: {\n displayRetail: '$29.99',\n },\n detail: {\n title: 'Texas A&M Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas-am-hat',\n link: {\n href: 'https://fanatics.com/texas-am-hat',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'browse',\n name: 'Want More?',\n caption: 'Browse all Texas A&M merch',\n image: {\n href: 'https://a.espncdn.com/i/teamlogos/ncaa/500/245.png',\n },\n detail: {\n title: 'Texas A&M Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/texas-am',\n link: {\n href: 'https://fanatics.com/texas-am',\n text: 'Scan to browse all',\n },\n },\n },\n ],\n },\n ],\n },\n ],\n};\n\n/**\n * Mock shop data with empty sections\n */\nexport const MOCK_SHOP_EMPTY_RESPONSE: IShopResponse = {\n shop: [\n {\n sections: [],\n defaultItem: {\n detail: {\n disclaimer:\n 'Visit shop.espn.com to explore more products and exclusive offers.',\n title: 'Shop the ESPN Store',\n backgroundImage: 'https://placedog.net/568x704',\n },\n },\n },\n ],\n};\n\n/**\n * Mock shop data with single section\n */\nexport const MOCK_SHOP_SINGLE_SECTION_RESPONSE: IShopResponse = {\n shop: [\n {\n sections: [\n {\n title: 'Team Shop',\n items: [\n {\n type: 'product',\n name: 'Premium Team Jersey - Official Merchandise',\n image: {\n href:\n 'https://via.placeholder.com/400x400/0066cc/ffffff?text=Team+Jersey',\n },\n price: {\n displayRetail: '$89.99',\n },\n detail: {\n title: 'Team Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/team-jersey',\n link: {\n href: 'https://fanatics.com/team-jersey',\n text: 'Scan to shop',\n },\n },\n },\n {\n type: 'browse',\n name: 'Want More?',\n caption: 'Browse all team merch',\n image: {\n href:\n 'https://via.placeholder.com/400x400/0066cc/ffffff?text=Team+Logo',\n },\n detail: {\n title: 'Team Shop',\n qrCode:\n 'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=https://fanatics.com/team',\n link: {\n href: 'https://fanatics.com/team',\n text: 'Scan to browse all',\n },\n },\n },\n ],\n },\n ],\n },\n ],\n};\n","import { captureException } from '@/sentry';\nimport ShopService from '@/modules/espn/shop/services/ShopService';\nimport { IShopResponse } from '../types';\nimport { stringHashCode } from '@/helpers/strings';\n\ntype Polling = {\n interval: number;\n task: { stop: () => void } | null;\n lastResponseHash: number | null;\n};\n\nconst DEFAULT_SHOP_POLLING_INTERVAL = 30000; // 30 seconds\n\nexport default class ShopPolling {\n private polling: Polling = {\n interval: DEFAULT_SHOP_POLLING_INTERVAL,\n task: null,\n lastResponseHash: null,\n };\n private shopService: ShopService;\n\n constructor(service: ShopService) {\n this.shopService = service;\n }\n\n /**\n * Refresh polling for shop data\n */\n refresh(callback: (data: IShopResponse) => void): void {\n // First stop any existing polling\n this.stop();\n\n // Start the poll loop\n this.start(callback);\n }\n\n /**\n * Stop polling for shop data\n */\n stop(): void {\n if (this.polling.task) {\n this.polling.task.stop();\n this.polling.task = null;\n }\n }\n\n removeLastResponseHash(): void {\n this.polling.lastResponseHash = null;\n }\n\n private start(callback: (data: IShopResponse) => void): void {\n try {\n this.polling.task = this.shopService.pollShopData(\n this.polling.interval,\n (response) => {\n this.updateInterval(response.headers, callback);\n this.processPolledData(response.data, callback);\n },\n (error) => this.handlePollingError(error)\n );\n } catch (error) {\n captureException(error, {\n context: 'ShopViewModel.pollShop',\n });\n console.error('[SHOP] Error setting up shop polling:', error);\n }\n }\n\n /**\n * @description Update polling interval checking either response header or panel config.\n * Refresh polling if necessary.\n */\n private updateInterval(\n headers: Record<string, string>,\n callback: (data: IShopResponse) => void\n ): void {\n const headerInterval = this.getResponseHeaderPollingIntervalValue(headers);\n\n // Only update if we have a valid new interval and it's different from current\n if (headerInterval && headerInterval !== this.polling.interval) {\n console.log(\n `[SHOP] Updating shop polling interval from ${this.polling.interval}ms to ${headerInterval}ms`\n );\n this.polling.interval = headerInterval;\n // Restart polling with the new interval\n this.refresh(callback);\n }\n }\n\n private getResponseHeaderPollingIntervalValue(\n headers: Record<string, string>\n ): number | null {\n const newInterval = headers['polling-interval'];\n if (!newInterval) {\n return null;\n }\n\n const parsedInterval = parseInt(newInterval, 10);\n if (isNaN(parsedInterval) || parsedInterval <= 0) {\n console.warn(\n `[SHOP] Invalid polling interval header received: ${newInterval}.`\n );\n return null;\n }\n\n return parsedInterval * 1000; // Convert seconds to milliseconds\n }\n\n /**\n * Process data received from polling\n */\n private processPolledData(\n data: IShopResponse,\n callback: (data: IShopResponse) => void\n ): void {\n // Calculate hash for the response to check if it's different from the last one\n const responseHash = stringHashCode(JSON.stringify(data));\n\n // Check if this is the same as the last successful response\n if (this.polling.lastResponseHash === responseHash) {\n console.log(\n '[SHOP] Shop Response hash is the same as last successful response - skipping update'\n );\n return;\n }\n\n this.polling.lastResponseHash = responseHash;\n callback(data);\n }\n\n /**\n * Handle errors that occur during shop polling\n */\n private handlePollingError(error: Error): void {\n console.error('[SHOP] Shop polling error:', error);\n\n captureException(error, {\n context: 'ShopViewModel.pollShop',\n extra: {\n pollingInterval: this.polling.interval,\n },\n });\n }\n}\n","import { Observable } from '../../../../helpers/Observable';\nimport ShopService from '../services/ShopService';\nimport AnalyticsService from '@/services/AnalyticsService/AnalyticsService';\nimport { ViewModel } from '../../../../view-models/ViewModel';\nimport {\n IShopResponse,\n IShopSection,\n IShopProduct,\n IShopBrowseCard,\n isShopProduct,\n IShopDefaultItem,\n} from '../types';\nimport {\n MOCK_SHOP_NFL_RESPONSE,\n MOCK_SHOP_NBA_RESPONSE,\n MOCK_SHOP_NCF_RESPONSE,\n MOCK_SHOP_EMPTY_RESPONSE,\n MOCK_SHOP_SINGLE_SECTION_RESPONSE,\n} from '../mocks';\n\nimport { captureException } from '@/sentry';\nimport ShopPolling from './ShopViewModel.ShopPolling';\nimport SDK from '@/index';\n\nconst SHOP_ERROR_STATE = {\n NONE: 'none',\n TAB_LOAD_FAILURE: 'tabLoadFailure',\n EMPTY_SHOP: 'emptyShop',\n} as const;\n\nexport type ShopErrorState = typeof SHOP_ERROR_STATE[keyof typeof SHOP_ERROR_STATE];\n\n/**\n * ViewModel for Shop panel\n * Manages shop data fetching, polling, and state\n */\nexport class ShopViewModel extends ViewModel {\n // Observable properties\n public sections = new Observable<IShopSection[]>([]);\n public isDataLoading = new Observable<boolean>(true);\n public errorState = new Observable<ShopErrorState>('none');\n public hasEverSuccessfullyLoaded = new Observable<boolean>(false);\n public promoData = new Observable<IShopDefaultItem | null>(null);\n\n // Properties\n private shopService: ShopService;\n private analyticsService: AnalyticsService;\n private shopPolling: ShopPolling;\n private useMockData: boolean = false;\n private mockDataType: string = 'nfl';\n initialized = false;\n\n constructor(\n eventId: string,\n analyticsService: AnalyticsService,\n options: {\n useMockData?: boolean;\n mockDataType?: 'nfl' | 'nba' | 'ncf' | 'empty' | 'single';\n } = {}\n ) {\n super();\n this.shopService = new ShopService(eventId);\n this.analyticsService = analyticsService;\n this.shopPolling = new ShopPolling(this.shopService);\n this.useMockData = options.useMockData || false;\n this.mockDataType = options.mockDataType || 'nfl';\n }\n\n /**\n * Initialize the ViewModel and start data fetching\n */\n init() {\n // Track panel view on initialization\n this.trackPanelView();\n\n this.fetchNewData();\n this.initialized = true;\n }\n\n /**\n * Clean up resources when the ViewModel is no longer needed\n */\n cleanup(): void {\n this.shopPolling.stop();\n this.initialized = false;\n }\n\n /**\n * Track panel view event\n */\n private async trackPanelView(): Promise<void> {\n try {\n const gameState =\n SDK.getMaestroEventViewModel().statsViewModel?.currentGameState.value ||\n 'unknown';\n\n await this.analyticsService.panelView('espnShop', {\n game_state: [gameState],\n });\n } catch (error) {\n captureException(error, {\n context: 'ShopViewModel.trackPanelView',\n });\n console.error('[SHOP] Error tracking panel view:', error);\n }\n }\n\n /**\n * Parse price string to number, handling currency formats\n */\n private parsePriceToNumber(priceString: string): number {\n // Remove currency symbols and spaces\n const cleaned = priceString.replace(/[^0-9.,]/g, '');\n\n // Find the last occurrence of comma or dot (decimal separator)\n const lastComma = cleaned.lastIndexOf(',');\n const lastDot = cleaned.lastIndexOf('.');\n\n let normalized: string;\n\n if (lastComma > lastDot) {\n // EU format: €1.234,56 -> comma is decimal separator\n normalized = cleaned.replace(/\\./g, '').replace(',', '.');\n } else if (lastDot > lastComma) {\n // US format: $1,234.56 -> dot is decimal separator\n normalized = cleaned.replace(/,/g, '');\n } else if (lastComma !== -1) {\n // Only comma present, assume decimal: €25,00\n normalized = cleaned.replace(',', '.');\n } else if (lastDot !== -1) {\n // Only dot present, assume decimal: $25.00\n normalized = cleaned;\n } else {\n // No separators: 25\n normalized = cleaned;\n }\n\n return Number(normalized) || 0;\n }\n\n /**\n * Track shop item card click event\n */\n async trackItemClick(\n card: 'product_summary' | 'want more' | 'product_detail' | 'fallback',\n item: IShopProduct | IShopBrowseCard | null,\n section: IShopSection | null\n ): Promise<void> {\n try {\n let sale = 0;\n let price: string | null = null;\n\n const gameState =\n SDK.getMaestroEventViewModel().statsViewModel?.currentGameState.value ||\n 'unknown';\n\n if (item && isShopProduct(item)) {\n const basePrice = item.price?.displayRetail;\n const currentPrice =\n item.price?.displayClearance ||\n item.price?.displaySale ||\n item.price?.displayRetail;\n\n if (currentPrice && basePrice) {\n const basePriceNumber = this.parsePriceToNumber(basePrice);\n const salePriceNumber = this.parsePriceToNumber(currentPrice);\n\n if (basePriceNumber > 0) {\n sale = Math.round((1 - salePriceNumber / basePriceNumber) * 100);\n } else {\n sale = 0;\n }\n price = currentPrice;\n }\n }\n\n await this.analyticsService.panelClick({\n type: 'espnShop',\n name: 'shop_item_clicked',\n metadata: {\n card: [card],\n game_state: [gameState],\n product: section?.product?.id || null,\n entity_type: [section?.product?.type || 'unknown'],\n entity_name: [section?.product?.shortDisplayName || 'unknown'],\n price,\n sale: [`${sale}%`],\n },\n });\n } catch (error) {\n captureException(error, {\n context: 'ShopViewModel.trackItemClick',\n item,\n section,\n });\n console.error('[SHOP] Error tracking shop item click:', error);\n }\n }\n\n /**\n * Refresh polling for shop data\n */\n refreshPolling(): void {\n try {\n if (this.useMockData) {\n return;\n }\n\n this.shopPolling.refresh(this.processShopData.bind(this));\n } catch (err) {\n this.setTabLoadFailure();\n }\n }\n\n /**\n * Process the shop data and update the sections\n */\n private processShopData(data: IShopResponse) {\n try {\n const shop = data.shop?.[0];\n const sections = shop?.sections || [];\n\n // Check if there are any sections\n if (!sections?.length && shop?.defaultItem) {\n this.errorState.value = 'emptyShop';\n this.sections.value = [];\n\n this.promoData.value = shop.defaultItem;\n return;\n }\n\n // Update sections and clear error state\n this.sections.value = sections;\n this.errorState.value = 'none';\n this.hasEverSuccessfullyLoaded.value = true;\n\n if (this.isDataLoading.value) {\n this.isDataLoading.value = false;\n }\n } catch (err) {\n captureException(err, {\n context: 'ShopViewModel.processShopData',\n });\n console.error('[SHOP] Error processing shop data:', err);\n this.setTabLoadFailure();\n }\n }\n\n setTabLoadFailure() {\n if (!this.hasEverSuccessfullyLoaded.value) {\n this.errorState.value = 'tabLoadFailure';\n this.sections.value = [];\n }\n\n if (this.isDataLoading.value) {\n this.isDataLoading.value = false;\n }\n }\n\n /**\n * Fetch new shop data immediately (one-time)\n */\n fetchNewData() {\n this.isDataLoading.value = true;\n\n try {\n // Handle mock data if enabled\n if (this.useMockData) {\n this.sections.value = [];\n this.fetchMockData();\n return;\n }\n\n this.refreshPolling();\n } catch (error) {\n captureException(error, {\n context: 'ShopViewModel.fetchNewData',\n });\n console.error('[SHOP] Error fetching shop data:', error);\n\n this.setTabLoadFailure();\n }\n }\n\n /**\n * Fetch mock data for testing\n */\n private fetchMockData() {\n let mockData: IShopResponse;\n\n switch (this.mockDataType) {\n case 'nba':\n mockData = MOCK_SHOP_NBA_RESPONSE;\n break;\n case 'ncf':\n mockData = MOCK_SHOP_NCF_RESPONSE;\n break;\n case 'empty':\n mockData = MOCK_SHOP_EMPTY_RESPONSE;\n break;\n case 'single':\n mockData = MOCK_SHOP_SINGLE_SECTION_RESPONSE;\n break;\n case 'nfl':\n default:\n mockData = MOCK_SHOP_NFL_RESPONSE;\n break;\n }\n\n this.processShopData(mockData);\n this.hasEverSuccessfullyLoaded.value = true;\n this.isDataLoading.value = false;\n }\n\n /**\n * Clear tab load failure and retry\n */\n clearTabLoadFailure() {\n this.errorState.value = 'none';\n this.shopPolling.removeLastResponseHash();\n setTimeout(() => {\n this.refreshPolling();\n }, 100);\n }\n}\n\nexport default ShopViewModel;\n"],"sourceRoot":""}
@@ -1,2 +1,2 @@
1
- (window.webpackJsonp=window.webpackJsonp||[]).push([[12],{104:function(e,t,s){"use strict";s.d(t,"a",(function(){return a})),s.d(t,"b",(function(){return n}));const a=e=>e.toLowerCase().trim().replace(/[\s\W-]+/g,"-").replace(/^-+|-+$/g,"");function n(e){let t=0;for(let s=0;s<e.length;s++){t=(t<<5)-t+e.charCodeAt(s),t&=t}return t}},246:function(e,t,s){"use strict";s.r(t),s.d(t,"BetsViewModel",(function(){return h}));var a=s(3),n=s(35);function o(e,t,s){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var s=e[Symbol.toPrimitive];if(void 0!==s){var a=s.call(e,t||"default");if("object"!=typeof a)return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:s,enumerable:!0,configurable:!0,writable:!0}):e[t]=s,e}var i=class{constructor(e){o(this,"networkManager",void 0),this.networkManager=new n.b({externalBaseURL:e.getBettingAPIBaseURL()})}async getNonPersonalizedBets(e){return this.networkManager.externalApiRequest({endpoint:this.nonPersonalizedBetsEndpoint(e),method:n.a.GET,params:{},headers:{}})}async getPersonalizedBets(e,t,s){return this.networkManager.externalApiRequest({endpoint:this.personalizedBetsEndpoint(e),method:n.a.GET,params:{swid:t},headers:{"x-p13n-auth":s}})}async getPersonalizedBetsWithHeaders(e,t,s){return this.networkManager.externalApiRequestWithHeaders({endpoint:this.personalizedBetsEndpoint(e),method:n.a.GET,params:{swid:t},headers:{"x-p13n-auth":s}})}pollPersonalizedBets(e,t,s,a,o,i){return this.networkManager.pollExternalApiRequest({endpoint:this.personalizedBetsEndpoint(e),interval:a,method:n.a.GET,params:{swid:t},headers:{"x-p13n-auth":s},onData:o,onError:i})}pollPersonalizedBetsWithHeaders(e,t,s,a,o,i){return this.networkManager.pollExternalApiRequestWithHeaders({endpoint:this.personalizedBetsEndpoint(e),interval:a,method:n.a.GET,params:{swid:t},headers:{"x-p13n-auth":s},onData:o,onError:i})}nonPersonalizedBetsEndpoint(e){return`/site/v2/events/${e}/odds`}personalizedBetsEndpoint(e){return`/personalized/site/v2/events/${e}/odds`}},r=s(10),d=s(34);const l={id:"401721458",sport:"basketball",date:"2025-02-28T02:00Z",gameState:"post",featured:[{date:"2024-06-09T17:35Z",id:"00015c79-3454-4356-bab6-af050554b761",selections:[{icon:"https://a.espncdn.com/i/espnbet/mybets_under_caret_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_under_caret_icon.png",id:"f54ad0791-304e-43fe-a45a-96bd237c9c78",odds:{},outcome:"PENDING",status:"upcoming",text:"Under 5.5",type:"under"},{icon:"https://a.espncdn.com/i/espnbet/mybets_under_caret_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_under_caret_icon.png",id:"f54ad079-3604e-43fe-a45a-96bd237c9c78",odds:{},outcome:"PENDING",status:"upcoming",text:"Under 5.5",type:"under"},{icon:"https://a.espncdn.com/i/espnbet/mybets_under_caret_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_under_caret_icon.png",id:"f54ad079-5304e-43fe-a45a-96bd237c9c78",odds:{},outcome:"PENDING",status:"upcoming",text:"Under 5.5",type:"under"},{icon:"https://a.espncdn.com/i/espnbet/mybets_under_caret_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_under_caret_icon.png",id:"f54ad079-3044e-43fe-a45a-96bd237c9c78",odds:{},outcome:"PENDING",status:"upcoming",text:"Under 5.5",type:"under"},{icon:"https://a.espncdn.com/i/espnbet/mybets_under_caret_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_under_caret_icon.png",id:"f54ad079-304e-43fe-a45a-96bd237c9c278",odds:{},outcome:"PENDING",status:"upcoming",text:"Under 5.5",type:"under"},{icon:"https://a.espncdn.com/i/espnbet/mybets_under_caret_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_under_caret_icon.png",id:"f54ad079-304e-43fe-a45a-96bd1237c9c78",odds:{},outcome:"PENDING",status:"upcoming",text:"Under 5.5",type:"under"}],text:"Carlos Santana Total Hits + Runs + RBIs"}],bets:{odds:[{displayName:"Moneyline",abbreviation:"ML",type:"moneyline",state:"close",values:[{odds:"-500",outcome:"WIN",team:"130",type:"home"},{odds:"+360",outcome:"LOSS",team:"164",type:"away"}]},{displayName:"Moneyline",abbreviation:"ML",type:"moneyline",state:"open",values:[{odds:"-700",team:"130",type:"home"},{odds:"+450",team:"164",type:"away"}]},{displayName:"Total Points",abbreviation:"Total",type:"total",state:"close",values:[{line:"o154.5",odds:"-115",outcome:"WIN",type:"over"},{line:"u154.5",odds:"-105",outcome:"LOSS",type:"under"}]},{displayName:"Total Points",abbreviation:"Total",type:"total",state:"open",values:[{line:"o154.5",odds:"-105",type:"over"},{line:"u154.5",odds:"-115",type:"under"}]},{displayName:"Spread",abbreviation:"Spread",type:"pointSpread",state:"close",values:[{line:"-9.5",odds:"-105",outcome:"LOSS",team:"130",type:"home"},{line:"+9.5",odds:"-115",outcome:"WIN",team:"164",type:"away"}]},{displayName:"Spread",abbreviation:"Spread",type:"pointSpread",state:"open",values:[{line:"-11.5",odds:"-105",team:"130",type:"home"},{line:"+11.5",odds:"-115",team:"164",type:"away"}]}]}},c={entities:{teams:{130:{id:"130",uid:"s:40~l:41~t:130",guid:"c00151c6-cdd4-5aab-0130-37416052eb2a",slug:"michigan-wolverines",abbreviation:"MICH",displayName:"Michigan Wolverines",shortDisplayName:"Michigan",name:"Wolverines",nickname:"Michigan",location:"Michigan",color:"00274c",alternateColor:"ffcb05",favored:!0},164:{id:"164",uid:"s:40~l:41~t:164",guid:"425c8e51-59d0-75a1-0815-dc3556c5cfda",slug:"rutgers-scarlet-knights",abbreviation:"RUTG",displayName:"Rutgers Scarlet Knights",shortDisplayName:"Rutgers",name:"Scarlet Knights",nickname:"Rutgers",location:"Rutgers",color:"d21034",alternateColor:"ffffff",favored:!1}}},event:l,betsModule:{defaultTab:"live",upcoming:[],live:[{id:"emnPo+hN/Q7CzX/obYcJZCYGql4=",type:"PARLAY",betStatus:"OPEN",outcome:"PENDING",overrideOutcome:"NOT_SET",betAmount:"10",payoutAmount:"171.55",odds:"+1616",startTime:"2022-11-29T17:54Z",events:[{displayName:"Investec South African Open Championship Future",legs:[{id:"71acdfe8-611e-47ae-b7ee-ba6684c6fefa",marketId:"fc47f9f9-2852-4f63-9a70-4adf5b4addd2",marketSelectionId:"92803c34-a8b7-476e-9136-b88729c7e51e",marketType:"list",status:"PENDING",odds:"+370",boostType:"NONE",selectionText:"Aaron Baddeley",type:"list",marketText:"Tournament Winner",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/golf/organization/dp-world-tour/competition/investec-south-african-open-championship/event/56773312-5fdb-4cb5-b387-df8c18a2c857&market_selection_id[0]=92803c34-a8b7-476e-9136-b88729c7e51e&odds_numerator[0]=11&odds_denominator[0]=2",marketStatus:"LIVE"}]},{displayName:"Lorem Ipsum Dolor Sit Amet",legs:[{id:"472f176b-7575-4d1d-ac63-bcb2d4ec6da9",marketId:"2e5fdfdf-7021-464f-939d-5497030fe765",marketSelectionId:"3727a3f5-5143-4616-ab4f-713bcf40aa21",marketType:"list",status:"PENDING",odds:"+265",boostType:"NONE",selectionText:"Aaron Pike",type:"list",marketText:"Tournament Winner",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/golf/organization/dp-world-tour/competition/isps-handa-australian-open/event/df8ba72f-4be8-4569-840e-954dbd9a7806&market_selection_id[0]=3727a3f5-5143-4616-ab4f-713bcf40aa21&odds_numerator[0]=73&odds_denominator[0]=20",marketStatus:"LIVE"}]},{displayName:"Australian Open Future",legs:[{id:"472f176b-7575-4d1d-ac63-bcb2d4ec6da9",marketId:"2e5fdfdf-7021-464f-939d-5497030fe765",marketSelectionId:"3727a3f5-5143-4616-ab4f-713bcf40aa21",marketType:"list",status:"PENDING",odds:"+265",boostType:"NONE",selectionText:"Aaron Pike",type:"list",marketText:"Tournament Winner",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/golf/organization/dp-world-tour/competition/isps-handa-australian-open/event/df8ba72f-4be8-4569-840e-954dbd9a7806&market_selection_id[0]=3727a3f5-5143-4616-ab4f-713bcf40aa21&odds_numerator[0]=73&odds_denominator[0]=20",marketStatus:"LIVE"}]},{displayName:"USA vs. Australia Future",legs:[{id:"472f176b-7575-4d1d-ac63-bcb2d4ec6da9",marketId:"2e5fdfdf-7021-464f-939d-5497030fe765",marketSelectionId:"3727a3f5-5143-4616-ab4f-713bcf40aa21",marketType:"list",status:"PENDING",odds:"+265",boostType:"NONE",selectionText:"Aaron Pike",type:"list",marketText:"Tournament Winner",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/golf/organization/dp-world-tour/competition/isps-handa-australian-open/event/df8ba72f-4be8-4569-840e-954dbd9a7806&market_selection_id[0]=3727a3f5-5143-4616-ab4f-713bcf40aa21&odds_numerator[0]=73&odds_denominator[0]=20",marketStatus:"LIVE"}]},{displayName:"Championship Future",legs:[{id:"472f176b-7575-4d1d-ac63-bcb2d4ec6da9",marketId:"2e5fdfdf-7021-464f-939d-5497030fe765",marketSelectionId:"3727a3f5-5143-4616-ab4f-713bcf40aa21",marketType:"list",status:"PENDING",odds:"+265",boostType:"NONE",selectionText:"Aaron Pike",type:"list",marketText:"Tournament Winner",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/golf/organization/dp-world-tour/competition/isps-handa-australian-open/event/df8ba72f-4be8-4569-840e-954dbd9a7806&market_selection_id[0]=3727a3f5-5143-4616-ab4f-713bcf40aa21&odds_numerator[0]=73&odds_denominator[0]=20",marketStatus:"LIVE"}]}],rewardInfo:{type:"NONE"},legCount:5,isNoAction:!1,betDisplayStatement:"to win"},{id:"9m1bBxUYPyPPjkpzT6buDlcuQng=",type:"STRAIGHT",betStatus:"OPEN",outcome:"PENDING",overrideOutcome:"NOT_SET",betAmount:"2",payoutAmount:"10.80",odds:"+440",startTime:"2025-04-30T15:12Z",events:[{displayName:"SBG/SBE Odds Boost Test",legs:[{id:"8061671d-6d38-4193-a5a6-beab37855840",marketId:"567d2a44-ba70-4881-86d7-d25fca94b592",marketSelectionId:"59b2b7ee-46c1-4cbc-9286-77fd8670cf9d",marketType:"list",status:"PENDING",odds:"+440",boostType:"ODDS_BOOST",selectionText:"Lauri Markkanen and Anfernee Simons to Each Record 20+ Points",type:"list",marketText:"SBG/SBE Odds Boost (Was +100)",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/odds-boost/organization/odds-boosts/competition/odds-boosts/event/218e1dca-f68d-4d61-9d79-394e7d752cae&market_selection_id[0]=59b2b7ee-46c1-4cbc-9286-77fd8670cf9d&odds_numerator[0]=27&odds_denominator[0]=5",marketStatus:"LIVE"}]}],rewardInfo:{type:"ODDS_BOOST",icon:{light:"https://a.espncdn.com/i/espnbet/boost.png",dark:"https://a.espncdn.com/i/espnbet/boost.png"}},legCount:1,isNoAction:!1,betDisplayStatement:"to win"},{id:"MCH06SyVYvu1UZkhj4KutmL9qKY=",type:"STRAIGHT",betStatus:"OPEN",outcome:"PENDING",overrideOutcome:"NOT_SET",betAmount:"3",payoutAmount:"16.20",odds:"+440",startTime:"2025-04-30T15:12Z",events:[{displayName:"SBG/SBE Odds Boost Test",legs:[{id:"020d7a12-3aa8-459e-8aa2-34eaced4ad7d",marketId:"567d2a44-ba70-4881-86d7-d25fca94b592",marketSelectionId:"59b2b7ee-46c1-4cbc-9286-77fd8670cf9d",marketType:"list",status:"PENDING",odds:"+440",boostType:"ODDS_BOOST",selectionText:"Lauri Markkanen and Anfernee Simons to Each Record 20+ Points",type:"list",marketText:"SBG/SBE Odds Boost (Was +100)",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/odds-boost/organization/odds-boosts/competition/odds-boosts/event/218e1dca-f68d-4d61-9d79-394e7d752cae&market_selection_id[0]=59b2b7ee-46c1-4cbc-9286-77fd8670cf9d&odds_numerator[0]=27&odds_denominator[0]=5",marketStatus:"LIVE"}]}],rewardInfo:{type:"ODDS_BOOST",icon:{light:"https://a.espncdn.com/i/espnbet/boost.png",dark:"https://a.espncdn.com/i/espnbet/boost.png"}},legCount:1,isNoAction:!1,betDisplayStatement:"to win"},{id:"xfFjqsLCjaFx93eH6c8bOQ9mEkI=",type:"STRAIGHT",betStatus:"OPEN",outcome:"PENDING",overrideOutcome:"NOT_SET",betAmount:"2",payoutAmount:"12.00",odds:"+500",startTime:"2025-04-30T17:11Z",events:[{displayName:"SBG NHL In The News Test",legs:[{id:"910a1ebf-592d-4ae6-9471-6f648786b7e6",marketId:"c5252e65-0999-40af-b366-11967f009871",marketSelectionId:"c9b1446c-26af-43c4-9705-3a2275dc0ee5",marketType:"list",status:"PENDING",odds:"+500",boostType:"NONE",selectionText:"Long Desc Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus non gravida mi. Aliquam volutpat felis ut tempor dictum.",type:"list",marketText:"SBG In The News NHL",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/odds-boost/organization/in-the-news/competition/in-the-news/event/4cd8e64d-472c-412f-b786-dd91c98ab74e&market_selection_id[0]=c9b1446c-26af-43c4-9705-3a2275dc0ee5&odds_numerator[0]=6&odds_denominator[0]=1",marketStatus:"LIVE"}]}],rewardInfo:{type:"NONE"},legCount:1,isNoAction:!1,betDisplayStatement:"to win"},{id:"A0RLmTR8mjEFSwaa21JeOhyVdXc=",type:"STRAIGHT",betStatus:"OPEN",outcome:"PENDING",overrideOutcome:"NOT_SET",betAmount:"1",payoutAmount:"3.00",odds:"+200",startTime:"2025-04-30T17:13Z",events:[{displayName:"SBG NBA Special Test",legs:[{id:"1aa22098-57b7-4a77-bbf2-ca7ebf812083",marketId:"bc783144-0a2c-465b-9e8f-2ef55a17705c",marketSelectionId:"7a91fb3d-1291-4163-b5e0-07fe63e8e706",marketType:"list",status:"PENDING",odds:"+200",boostType:"NONE",selectionText:"Tyrese Haliburton to Record 12+ Assists",type:"list",marketText:"SBG NBA Special Test",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/odds-boost/organization/specials/competition/specials/event/d53171e2-f821-4da8-9b1c-ce1a4b735914&market_selection_id[0]=7a91fb3d-1291-4163-b5e0-07fe63e8e706&odds_numerator[0]=33&odds_denominator[0]=10",marketStatus:"LIVE"}]}],rewardInfo:{type:"NONE"},legCount:1,isNoAction:!1,betDisplayStatement:"to win"},{id:"Qhelx5np79zhAchzXXTL1HdDb80=",type:"STRAIGHT",betStatus:"OPEN",outcome:"PENDING",overrideOutcome:"NOT_SET",betAmount:"2",payoutAmount:"10.00",odds:"+400",startTime:"2025-04-30T17:13Z",events:[{displayName:"SBG NBA Special Test",legs:[{id:"73f3af25-5e1a-47eb-bcec-5b23e911c14e",marketId:"bc783144-0a2c-465b-9e8f-2ef55a17705c",marketSelectionId:"0a898e16-2a0a-44dd-a580-3ae3bade3684",marketType:"list",status:"PENDING",odds:"+400",boostType:"NONE",selectionText:"Long Desc Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus non gravida mi. Aliquam volutpat felis ut tempor dictum.",type:"list",marketText:"SBG NBA Special Test",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/odds-boost/organization/specials/competition/specials/event/d53171e2-f821-4da8-9b1c-ce1a4b735914&market_selection_id[0]=0a898e16-2a0a-44dd-a580-3ae3bade3684&odds_numerator[0]=37&odds_denominator[0]=10",marketStatus:"LIVE"}]}],rewardInfo:{type:"NONE"},legCount:1,isNoAction:!1,betDisplayStatement:"to win"}],settled:[{id:"z/WEFT7NDVjgb0d/+Elr45MfuRg=",type:"STRAIGHT",betStatus:"SETTLED",outcome:"WIN",overrideOutcome:"NOT_SET",closedAtTime:"2025-03-08T05:33Z",betAmount:"1",payoutAmount:"1.91",odds:"-110",startTime:"2025-03-08T03:00Z",events:[{displayName:"San Antonio Spurs @ Sacramento Kings",legs:[{id:"05011199-c88f-4c0d-be31-1b1c7549e273",marketId:"728792c6-d2da-435b-920a-eb86bdc45e8c",marketSelectionId:"60f8aef9-4c98-4ce2-b861-34e72c2ad13b",marketType:"total",status:"WIN",odds:"-110",boostType:"NONE",selectionText:"Over 235",type:"over",points:"235.0",marketText:"Total Points",icon:"https://a.espncdn.com/i/espnbet/mybets_green_check_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_green_check_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/basketball/organization/united-states/competition/nba/event/e1163795-ddfa-4bfc-9d52-018e8259e4b5&market_selection_id[0]=60f8aef9-4c98-4ce2-b861-34e72c2ad13b&odds_numerator[0]=2&odds_denominator[0]=1",marketStatus:"SETTLED",accrued:{goal:235}}]}],rewardInfo:{type:"NONE"},legCount:1,isNoAction:!1,betDisplayStatement:"you won"}]},promotion:{title:"The official sportsbook of ESPN",description:"Open the ESPN BET app on a mobile device and start betting!",logo:"https://a.espncdn.com/i/espnbet/ESPN_Bet_Sportsbook_Light.svg",qrCode:"https://assets.geo.hosted.espnsb.com/api/ext_mocks/qr.png",backgroundImage:"https://www.espn.com/redesign/assets/img/ictv/bkg_qr_bet.png"},disclaimers:{location:"Use a translation with a key based on location here",gambling:"Use a translation with some key based on gambling here"},...l};var p=s(8),u=s(4),m=s(104);function b(e,t,s){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var s=e[Symbol.toPrimitive];if(void 0!==s){var a=s.call(e,t||"default");if("object"!=typeof a)return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:s,enumerable:!0,configurable:!0,writable:!0}):e[t]=s,e}const g=e=>"object"==typeof e&&null!==e&&"event"in e&&"object"==typeof e.event;class h extends d.a{constructor(e,t,s,n={}){super(),b(this,"betsItems",new a.a([])),b(this,"isDataLoading",new a.a(!0)),b(this,"errorState",new a.a("none")),b(this,"hasEverSuccessfullyLoaded",new a.a(!1)),b(this,"hideWagers",new a.a(!1)),b(this,"eventId",void 0),b(this,"delegate",void 0),b(this,"betsService",void 0),b(this,"analyticsService",void 0),b(this,"pollingInterval",void 0),b(this,"pollingTask",null),b(this,"lastNonPersonalizedResponseHash",null),b(this,"lastPersonalizedResponseHash",null),b(this,"useMockData",!1),b(this,"userSettingsManager",void 0),b(this,"settingsSubscription",null),b(this,"initialized",!1),this.eventId=e,this.delegate=t,this.betsService=new i(t),this.analyticsService=s,this.pollingInterval=3e4,this.useMockData=n.useMockData||!1,this.userSettingsManager=r.a.getInstance(),this.hideWagers.value=this.userSettingsManager.shouldHideWagers(),this.settingsSubscription=this.userSettingsManager.settings.subscribe(()=>{this.updateHideWagersFromSettings()}),this.betsService=new i(t)}async init(){this.trackPanelView(),await this.fetchNewData(),this.refreshPolling(),this.initialized=!0}cleanup(){this.stopPolling(),this.settingsSubscription&&(this.settingsSubscription(),this.settingsSubscription=null),this.initialized=!1}async trackPanelView(){try{const e=this.getUserBetCounts();await this.analyticsService.panelView("espnBet",e)}catch(e){Object(u.a)(e,{context:"BetsViewModel.trackPanelView"}),console.error("[BET] Error tracking panel view:",e)}}async trackCardClick(e,t){try{const s={...this.getUserBetCounts(),card:e,bet_type:t||null};await this.analyticsService.panelClick({type:"espnBet",name:"bets_item_clicked",metadata:s})}catch(s){Object(u.a)(s,{context:"BetsViewModel.trackCardClick",cardType:e,betType:t}),console.error("[BET] Error tracking card click:",s)}}getUserBetCounts(){try{let e=0,t=0;for(const s of this.betsItems.value)if("userBets"===s.type){const a=s;t=[...a.data.bets.live,...a.data.bets.settled,...a.data.bets.upcoming].length,e=a.data.bets.live.length;break}return{in_game_bets:e,total_bets:t}}catch(e){return Object(u.a)(e,{context:"BetsViewModel.getUserBetCounts"}),console.error("[BET] Error getting user bet counts:",e),{in_game_bets:0,total_bets:0}}}refreshPolling(){this.stopPolling(),this.useMockData||(this.pollingTask={stop:()=>{}},this.pollWithInterval())}async getUserCredentials(){return{swid:await this.delegate.getUserSWID()||"",jwt:await this.delegate.getUserToken()||""}}updatePollingInterval(e){const t=this.getResponseHeaderPollingIntervalValue(e),s=this.getPanelConfigInterval(),a=t||s;a&&a!==this.pollingInterval&&(this.pollingInterval=a,console.log(`[BET] Updating polling interval to ${this.pollingInterval} milliseconds`),this.refreshPolling())}getPanelConfigInterval(){var e,t,s;const a=p.default.getPageConfig(),n=null==a||null===(e=a.panels)||void 0===e?void 0:e.find(e=>"espnBet"===e.panel_type);if(!n)return null;const o=null===(t=n.renderer)||void 0===t||null===(s=t.block_data)||void 0===s?void 0:s.odds_polling_interval;if(!o)return null;const i=parseInt(o,10);return isNaN(i)||i<=0?(console.warn(`[BET] Invalid polling interval from panel config: ${o}.`),null):1e3*i}getResponseHeaderPollingIntervalValue(e){const t=e["polling-interval"];if(!t)return null;const s=parseInt(t,10);return isNaN(s)||s<=0?(console.warn(`[BET] Invalid polling interval header received: ${t}.`),null):1e3*s}async pollWithInterval(){try{const{swid:e,jwt:t}=await this.getUserCredentials();this.pollingTask=this.betsService.pollPersonalizedBetsWithHeaders(this.eventId,e,t,this.pollingInterval,e=>{this.updatePollingInterval(e.headers),this.processPolledData(e.data)},this.handlePollingError.bind(this))}catch(e){Object(u.a)(e,{context:"BetsViewModel.pollWithInterval"}),console.error("[BET] Error setting up polling:",e)}}processPolledData(e){const t=Object(m.b)(JSON.stringify(e));if(g(e)){if(this.lastPersonalizedResponseHash===t&&this.hasEverSuccessfullyLoaded.value)return void console.log("[BET] Response hash is the same as last successful response - skipping update");this.lastPersonalizedResponseHash=t}else{if(this.lastNonPersonalizedResponseHash===t&&this.hasEverSuccessfullyLoaded.value)return void console.log("[BET] Response hash is the same as last successful response - skipping update");this.lastNonPersonalizedResponseHash=t}this.hasEverSuccessfullyLoaded.value=!0,this.errorState.value="none",this.processBetsData(e)}processBetsData(e){const t=[];if(!Object.keys(e).length)return;const s=this.processSixPackData(e);s&&t.push(s);const a=this.processLocationDisclaimer(e);a&&t.push(a);const n=this.processUserBetsData(e);n&&t.push(n);const o=this.processHotProps(e);o&&t.push(o);const i=this.processPromoCode(e);i&&t.push(i);const r=this.processGamblingMessage(e);r&&t.push(r),this.betsItems.value=t}processLocationDisclaimer(e){var t;return g(e)&&null!==(t=e.disclaimers)&&void 0!==t&&t.location?{type:"locationDisclaimer",id:"locationDisclaimer",data:{text:e.disclaimers.location}}:null}processPromoCode(e){var t;return g(e)&&e.promotion?{type:"promo",data:{title:e.promotion.title||"",description:e.promotion.description||"",logo:e.promotion.logo||"",qrCode:e.promotion.qrCode||"",backgroundImage:e.promotion.backgroundImage||""},id:"promo-"+((null===(t=e.event)||void 0===t?void 0:t.id)||e.id)}:null}processGamblingMessage(e){var t;return g(e)&&null!==(t=e.disclaimers)&&void 0!==t&&t.gambling?{type:"gamblingMessage",id:"gamblingMessage",data:{text:e.disclaimers.gambling}}:null}processSixPackData(e){var t,s,a,n,o,i,r,d,l,c;const p=g(e),u=null===(t=e.entities)||void 0===t?void 0:t.teams,m=p?null===(a=e.event)||void 0===a||null===(n=a.bets)||void 0===n?void 0:n.odds:null===(s=e.bets)||void 0===s?void 0:s.odds,b=p?null===(o=e.event)||void 0===o?void 0:o.gameState:e.gameState,h=p?null===(i=e.event)||void 0===i?void 0:i.sport:e.sport,f=p?null===(r=e.event)||void 0===r?void 0:r.id:e.id,v=p?"soccer"===(null===(d=e.event)||void 0===d?void 0:d.sport):"soccer"===e.sport;if(!(m&&b&&h&&f&&u))return null;const y=Object.values(u);let _,k;for(const e of Object.values(u)){const t=m.find(e=>"pointSpread"===e.type);t&&(t.values.some(t=>t.team===e.id&&"home"===t.type)?k=e:t.values.some(t=>t.team===e.id&&"away"===t.type)&&(_=e))}if(!k||!_)switch(console.warn("Could not determine home/away teams from odds, using first two teams"),y.length){case 0:throw new Error("No teams found in response");case 1:k=y[0],_=y[0];break;case 2:k=y[0],_=y[1];break;default:k=y[0],_=y[1],console.warn(`Warning: Unexpected team count (${y.length}) in six pack response`)}if(!_||!k)throw new Error("Could not determine home or away team from response");const S="in"===b,T=v&&!S?null===(E=k.favoredAtOpen)||void 0===E||E:null===(N=k.favored)||void 0===N||N;var N,E;const w=v&&!S?null!==(P=_.favoredAtOpen)&&void 0!==P&&P:null!==(I=_.favored)&&void 0!==I&&I;var I,P;let D="",B="",O="",L="",A="",x="",G="",M="",W="",z="",C="",R="",H="",V="",j="",U="",q="";const F=new Set,$=[];for(const e of m){F.has(e.type)||($.push({type:e.type,abbreviation:e.abbreviation}),F.add(e.type));const t="live"===e.state,s="close"===e.state,a="open"===e.state;switch(e.type){case"pointSpread":if(S?t:s)for(const t of e.values){var Z,Y,J,K;if("home"===t.type)G=null!==(Z=t.line)&&void 0!==Z?Z:"",M=null!==(Y=t.odds)&&void 0!==Y?Y:"";if("away"===t.type)A=null!==(J=t.line)&&void 0!==J?J:"",x=null!==(K=t.odds)&&void 0!==K?K:""}if((S?s:a)&&!v){if(T)for(const t of e.values){var Q,X;if("home"===t.type)O=null!==(Q=t.line)&&void 0!==Q?Q:"",L=null!==(X=t.odds)&&void 0!==X?X:""}if(w)for(const t of e.values){var ee,te;if("away"===t.type)D=null!==(ee=t.line)&&void 0!==ee?ee:"",B=null!==(te=t.odds)&&void 0!==te?te:""}}break;case"total":if(S?t:s)for(const t of e.values){var se,ae,ne,oe,ie,re,de,le;if("over"===t.type)if(v)C=null!==(se=t.line)&&void 0!==se?se:"",R=null!==(ae=t.odds)&&void 0!==ae?ae:"";else W=null!==(ne=t.line)&&void 0!==ne?ne:"",z=null!==(oe=t.odds)&&void 0!==oe?oe:"";if("under"===t.type)if(v)W=null!==(ie=t.line)&&void 0!==ie?ie:"",z=null!==(re=t.odds)&&void 0!==re?re:"";else C=null!==(de=t.line)&&void 0!==de?de:"",R=null!==(le=t.odds)&&void 0!==le?le:""}if(S?s:a){if(!T)for(const t of e.values){var ce,pe;if(v&&"over"===t.type||!v&&"under"===t.type)O=null!==(ce=t.line)&&void 0!==ce?ce:"",L=null!==(pe=t.odds)&&void 0!==pe?pe:""}if(!w)for(const t of e.values){var ue,me;if(v&&"under"===t.type||!v&&"over"===t.type)D=null!==(ue=t.line)&&void 0!==ue?ue:"",B=null!==(me=t.odds)&&void 0!==me?me:""}}break;case"moneyline":{const n=S?t:s;if(n)for(const t of e.values){var be,ge;if("home"===t.type)V=null!==(be=t.odds)&&void 0!==be?be:"";if("away"===t.type)H=null!==(ge=t.odds)&&void 0!==ge?ge:""}if(v){const t=S?s:a;for(const s of e.values)if("draw"===s.type){var he,fe;if(t)j=null!==(he=s.odds)&&void 0!==he?he:"",U="DRAW";if(n)q=null!==(fe=s.odds)&&void 0!==fe?fe:""}if(t){if(T)for(const t of e.values){var ve,ye;if("home"===t.type)O=null!==(ve=t.odds)&&void 0!==ve?ve:"",L=null!==(ye=e.abbreviation)&&void 0!==ye?ye:""}if(w)for(const t of e.values){var _e,ke;if("away"===t.type)D=null!==(_e=t.odds)&&void 0!==_e?_e:"",B=null!==(ke=e.abbreviation)&&void 0!==ke?ke:""}}}break}}}const Se={teamAbbreviation:null!==(l=_.abbreviation)&&void 0!==l?l:"",startOfGameFirstLine:D,startOfGameSecondLine:B,gameSpreadFirstLine:A,gameSpreadSecondLine:x,totalPointsFirstLine:W,totalPointsSecondLine:z,moneylineFirstLine:H},Te={teamAbbreviation:null!==(c=k.abbreviation)&&void 0!==c?c:"",startOfGameFirstLine:O,startOfGameSecondLine:L,gameSpreadFirstLine:G,gameSpreadSecondLine:M,totalPointsFirstLine:C,totalPointsSecondLine:R,moneylineFirstLine:V};return{id:"sixpack-"+f,type:"sixPack",data:{topTeamOdds:v?Te:Se,bottomTeamOdds:v?Se:Te,drawOdds:j&&U&&q?{teamAbbreviation:"DRAW",startOfGameFirstLine:j,startOfGameSecondLine:U,gameSpreadFirstLine:"",gameSpreadSecondLine:"",totalPointsFirstLine:"",totalPointsSecondLine:"",moneylineFirstLine:q}:void 0,orderedColumns:$,gameState:b},teamInfo:{home:k,away:_},hideWagers:this.hideWagers.value}}processUserBetsData(e){if(!g(e)||!e.event||!e.betsModule)return null;return{data:{bets:{live:e.betsModule.live.filter(e=>"promo"!==e.type),settled:e.betsModule.settled.filter(e=>"promo"!==e.type),upcoming:e.betsModule.upcoming.filter(e=>"promo"!==e.type)},defaultTab:e.betsModule.defaultTab},id:"userBets-"+e.event.id,type:"userBets",hideWagers:this.hideWagers.value}}processHotProps(e){var t;const s=g(e)?null===(t=e.event)||void 0===t?void 0:t.featured:e.featured;if(!s||!Array.isArray(s))return null;if(!s.every(e=>Boolean(e&&e.id)))return null;const a=s.filter(e=>e.selections.length>0);return{type:"hotProps",hideWagers:this.hideWagers.value,id:"hotProps",data:{items:a.map(e=>{const t=e.selections[0];return{id:t.id,odds:t.odds.current||"",marketText:t.text,selectionText:e.text,status:t.status,type:t.type,icon:t.icon,iconDark:t.iconDark,outcome:t.outcome}})}}}handlePollingError(e){console.error("Polling error:",e),this.hasEverSuccessfullyLoaded.value||(this.errorState.value="tabLoadFailure",this.betsItems.value=[])}stopPolling(){this.pollingTask&&(this.pollingTask.stop(),this.pollingTask=null),this.isDataLoading.value&&(this.isDataLoading.value=!1)}async fetchNewData(){this.isDataLoading.value=!0;try{if(this.useMockData)return this.betsItems.value=[],void await this.fetchMockData();await this.fetchPersonalizedData(),this.isDataLoading.value=!1}catch(e){Object(u.a)(e,{context:"BetsViewModel.fetchNewData"}),console.error("[BET] Error fetching bet data:",e),this.hasEverSuccessfullyLoaded.value||(this.errorState.value="tabLoadFailure",this.betsItems.value=[]),this.isDataLoading.value=!1}}async fetchPersonalizedData(){try{const{swid:e,jwt:t}=await this.getUserCredentials(),s=await this.betsService.getPersonalizedBets(this.eventId,e,t);this.processPolledData(s)}catch(e){throw Object(u.a)(e,{context:"BetsViewModel.fetchPersonalizedData"}),console.error("[BET] Error fetching personalized bets:",e),e}}async fetchMockData(){this.processBetsData(c),this.hasEverSuccessfullyLoaded.value=!0,this.errorState.value="none",this.isDataLoading.value=!1}clearTabLoadFailure(){this.errorState.value="none",setTimeout(()=>{this.refreshPolling()},100)}shouldHideWagers(){return this.hideWagers.value}updateHideWagersFromSettings(){this.hideWagers.value=this.userSettingsManager.shouldHideWagers(),this.refreshBetItemsWithNewSettings()}refreshBetItemsWithNewSettings(){this.betsItems.value=this.betsItems.value.map(e=>"sixPack"===e.type||"userBets"===e.type||"hotProps"===e.type?{...e,hideWagers:this.hideWagers.value}:e)}}t.default=h}}]);
1
+ (window.webpackJsonp=window.webpackJsonp||[]).push([[12],{104:function(e,t,s){"use strict";s.d(t,"a",(function(){return a})),s.d(t,"b",(function(){return n}));const a=e=>e.toLowerCase().trim().replace(/[\s\W-]+/g,"-").replace(/^-+|-+$/g,"");function n(e){let t=0;for(let s=0;s<e.length;s++){t=(t<<5)-t+e.charCodeAt(s),t&=t}return t}},247:function(e,t,s){"use strict";s.r(t),s.d(t,"BetsViewModel",(function(){return h}));var a=s(3),n=s(35);function o(e,t,s){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var s=e[Symbol.toPrimitive];if(void 0!==s){var a=s.call(e,t||"default");if("object"!=typeof a)return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:s,enumerable:!0,configurable:!0,writable:!0}):e[t]=s,e}var i=class{constructor(e){o(this,"networkManager",void 0),this.networkManager=new n.b({externalBaseURL:e.getBettingAPIBaseURL()})}async getNonPersonalizedBets(e){return this.networkManager.externalApiRequest({endpoint:this.nonPersonalizedBetsEndpoint(e),method:n.a.GET,params:{deviceType:"ictv"},headers:{}})}async getPersonalizedBets(e,t,s){return this.networkManager.externalApiRequest({endpoint:this.personalizedBetsEndpoint(e),method:n.a.GET,params:{swid:t,deviceType:"ictv"},headers:{"x-p13n-auth":s}})}async getPersonalizedBetsWithHeaders(e,t,s){return this.networkManager.externalApiRequestWithHeaders({endpoint:this.personalizedBetsEndpoint(e),method:n.a.GET,params:{swid:t,deviceType:"ictv"},headers:{"x-p13n-auth":s}})}pollPersonalizedBets(e,t,s,a,o,i){return this.networkManager.pollExternalApiRequest({endpoint:this.personalizedBetsEndpoint(e),interval:a,method:n.a.GET,params:{swid:t,deviceType:"ictv"},headers:{"x-p13n-auth":s},onData:o,onError:i})}pollPersonalizedBetsWithHeaders(e,t,s,a,o,i){return this.networkManager.pollExternalApiRequestWithHeaders({endpoint:this.personalizedBetsEndpoint(e),interval:a,method:n.a.GET,params:{swid:t,deviceType:"ictv"},headers:{"x-p13n-auth":s},onData:o,onError:i})}nonPersonalizedBetsEndpoint(e){return`/site/v2/events/${e}/odds`}personalizedBetsEndpoint(e){return`/personalized/site/v2/events/${e}/odds`}},r=s(10),d=s(34);const l={id:"401721458",sport:"basketball",date:"2025-02-28T02:00Z",gameState:"post",featured:[{date:"2024-06-09T17:35Z",id:"00015c79-3454-4356-bab6-af050554b761",selections:[{icon:"https://a.espncdn.com/i/espnbet/mybets_under_caret_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_under_caret_icon.png",id:"f54ad0791-304e-43fe-a45a-96bd237c9c78",odds:{},outcome:"PENDING",status:"upcoming",text:"Under 5.5",type:"under"},{icon:"https://a.espncdn.com/i/espnbet/mybets_under_caret_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_under_caret_icon.png",id:"f54ad079-3604e-43fe-a45a-96bd237c9c78",odds:{},outcome:"PENDING",status:"upcoming",text:"Under 5.5",type:"under"},{icon:"https://a.espncdn.com/i/espnbet/mybets_under_caret_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_under_caret_icon.png",id:"f54ad079-5304e-43fe-a45a-96bd237c9c78",odds:{},outcome:"PENDING",status:"upcoming",text:"Under 5.5",type:"under"},{icon:"https://a.espncdn.com/i/espnbet/mybets_under_caret_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_under_caret_icon.png",id:"f54ad079-3044e-43fe-a45a-96bd237c9c78",odds:{},outcome:"PENDING",status:"upcoming",text:"Under 5.5",type:"under"},{icon:"https://a.espncdn.com/i/espnbet/mybets_under_caret_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_under_caret_icon.png",id:"f54ad079-304e-43fe-a45a-96bd237c9c278",odds:{},outcome:"PENDING",status:"upcoming",text:"Under 5.5",type:"under"},{icon:"https://a.espncdn.com/i/espnbet/mybets_under_caret_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_under_caret_icon.png",id:"f54ad079-304e-43fe-a45a-96bd1237c9c78",odds:{},outcome:"PENDING",status:"upcoming",text:"Under 5.5",type:"under"}],text:"Carlos Santana Total Hits + Runs + RBIs"}],bets:{odds:[{displayName:"Moneyline",abbreviation:"ML",type:"moneyline",state:"close",values:[{odds:"-500",outcome:"WIN",team:"130",type:"home"},{odds:"+360",outcome:"LOSS",team:"164",type:"away"}]},{displayName:"Moneyline",abbreviation:"ML",type:"moneyline",state:"open",values:[{odds:"-700",team:"130",type:"home"},{odds:"+450",team:"164",type:"away"}]},{displayName:"Total Points",abbreviation:"Total",type:"total",state:"close",values:[{line:"o154.5",odds:"-115",outcome:"WIN",type:"over"},{line:"u154.5",odds:"-105",outcome:"LOSS",type:"under"}]},{displayName:"Total Points",abbreviation:"Total",type:"total",state:"open",values:[{line:"o154.5",odds:"-105",type:"over"},{line:"u154.5",odds:"-115",type:"under"}]},{displayName:"Spread",abbreviation:"Spread",type:"pointSpread",state:"close",values:[{line:"-9.5",odds:"-105",outcome:"LOSS",team:"130",type:"home"},{line:"+9.5",odds:"-115",outcome:"WIN",team:"164",type:"away"}]},{displayName:"Spread",abbreviation:"Spread",type:"pointSpread",state:"open",values:[{line:"-11.5",odds:"-105",team:"130",type:"home"},{line:"+11.5",odds:"-115",team:"164",type:"away"}]}]}},c={entities:{teams:{130:{id:"130",uid:"s:40~l:41~t:130",guid:"c00151c6-cdd4-5aab-0130-37416052eb2a",slug:"michigan-wolverines",abbreviation:"MICH",displayName:"Michigan Wolverines",shortDisplayName:"Michigan",name:"Wolverines",nickname:"Michigan",location:"Michigan",color:"00274c",alternateColor:"ffcb05",favored:!0},164:{id:"164",uid:"s:40~l:41~t:164",guid:"425c8e51-59d0-75a1-0815-dc3556c5cfda",slug:"rutgers-scarlet-knights",abbreviation:"RUTG",displayName:"Rutgers Scarlet Knights",shortDisplayName:"Rutgers",name:"Scarlet Knights",nickname:"Rutgers",location:"Rutgers",color:"d21034",alternateColor:"ffffff",favored:!1}}},event:l,betsModule:{defaultTab:"live",upcoming:[],live:[{id:"emnPo+hN/Q7CzX/obYcJZCYGql4=",type:"PARLAY",betStatus:"OPEN",outcome:"PENDING",overrideOutcome:"NOT_SET",betAmount:"10",payoutAmount:"171.55",odds:"+1616",startTime:"2022-11-29T17:54Z",events:[{displayName:"Investec South African Open Championship Future",legs:[{id:"71acdfe8-611e-47ae-b7ee-ba6684c6fefa",marketId:"fc47f9f9-2852-4f63-9a70-4adf5b4addd2",marketSelectionId:"92803c34-a8b7-476e-9136-b88729c7e51e",marketType:"list",status:"PENDING",odds:"+370",boostType:"NONE",selectionText:"Aaron Baddeley",type:"list",marketText:"Tournament Winner",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/golf/organization/dp-world-tour/competition/investec-south-african-open-championship/event/56773312-5fdb-4cb5-b387-df8c18a2c857&market_selection_id[0]=92803c34-a8b7-476e-9136-b88729c7e51e&odds_numerator[0]=11&odds_denominator[0]=2",marketStatus:"LIVE"}]},{displayName:"Lorem Ipsum Dolor Sit Amet",legs:[{id:"472f176b-7575-4d1d-ac63-bcb2d4ec6da9",marketId:"2e5fdfdf-7021-464f-939d-5497030fe765",marketSelectionId:"3727a3f5-5143-4616-ab4f-713bcf40aa21",marketType:"list",status:"PENDING",odds:"+265",boostType:"NONE",selectionText:"Aaron Pike",type:"list",marketText:"Tournament Winner",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/golf/organization/dp-world-tour/competition/isps-handa-australian-open/event/df8ba72f-4be8-4569-840e-954dbd9a7806&market_selection_id[0]=3727a3f5-5143-4616-ab4f-713bcf40aa21&odds_numerator[0]=73&odds_denominator[0]=20",marketStatus:"LIVE"}]},{displayName:"Australian Open Future",legs:[{id:"472f176b-7575-4d1d-ac63-bcb2d4ec6da9",marketId:"2e5fdfdf-7021-464f-939d-5497030fe765",marketSelectionId:"3727a3f5-5143-4616-ab4f-713bcf40aa21",marketType:"list",status:"PENDING",odds:"+265",boostType:"NONE",selectionText:"Aaron Pike",type:"list",marketText:"Tournament Winner",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/golf/organization/dp-world-tour/competition/isps-handa-australian-open/event/df8ba72f-4be8-4569-840e-954dbd9a7806&market_selection_id[0]=3727a3f5-5143-4616-ab4f-713bcf40aa21&odds_numerator[0]=73&odds_denominator[0]=20",marketStatus:"LIVE"}]},{displayName:"USA vs. Australia Future",legs:[{id:"472f176b-7575-4d1d-ac63-bcb2d4ec6da9",marketId:"2e5fdfdf-7021-464f-939d-5497030fe765",marketSelectionId:"3727a3f5-5143-4616-ab4f-713bcf40aa21",marketType:"list",status:"PENDING",odds:"+265",boostType:"NONE",selectionText:"Aaron Pike",type:"list",marketText:"Tournament Winner",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/golf/organization/dp-world-tour/competition/isps-handa-australian-open/event/df8ba72f-4be8-4569-840e-954dbd9a7806&market_selection_id[0]=3727a3f5-5143-4616-ab4f-713bcf40aa21&odds_numerator[0]=73&odds_denominator[0]=20",marketStatus:"LIVE"}]},{displayName:"Championship Future",legs:[{id:"472f176b-7575-4d1d-ac63-bcb2d4ec6da9",marketId:"2e5fdfdf-7021-464f-939d-5497030fe765",marketSelectionId:"3727a3f5-5143-4616-ab4f-713bcf40aa21",marketType:"list",status:"PENDING",odds:"+265",boostType:"NONE",selectionText:"Aaron Pike",type:"list",marketText:"Tournament Winner",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/golf/organization/dp-world-tour/competition/isps-handa-australian-open/event/df8ba72f-4be8-4569-840e-954dbd9a7806&market_selection_id[0]=3727a3f5-5143-4616-ab4f-713bcf40aa21&odds_numerator[0]=73&odds_denominator[0]=20",marketStatus:"LIVE"}]}],rewardInfo:{type:"NONE"},legCount:5,isNoAction:!1,betDisplayStatement:"to win"},{id:"9m1bBxUYPyPPjkpzT6buDlcuQng=",type:"STRAIGHT",betStatus:"OPEN",outcome:"PENDING",overrideOutcome:"NOT_SET",betAmount:"2",payoutAmount:"10.80",odds:"+440",startTime:"2025-04-30T15:12Z",events:[{displayName:"SBG/SBE Odds Boost Test",legs:[{id:"8061671d-6d38-4193-a5a6-beab37855840",marketId:"567d2a44-ba70-4881-86d7-d25fca94b592",marketSelectionId:"59b2b7ee-46c1-4cbc-9286-77fd8670cf9d",marketType:"list",status:"PENDING",odds:"+440",boostType:"ODDS_BOOST",selectionText:"Lauri Markkanen and Anfernee Simons to Each Record 20+ Points",type:"list",marketText:"SBG/SBE Odds Boost (Was +100)",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/odds-boost/organization/odds-boosts/competition/odds-boosts/event/218e1dca-f68d-4d61-9d79-394e7d752cae&market_selection_id[0]=59b2b7ee-46c1-4cbc-9286-77fd8670cf9d&odds_numerator[0]=27&odds_denominator[0]=5",marketStatus:"LIVE"}]}],rewardInfo:{type:"ODDS_BOOST",icon:{light:"https://a.espncdn.com/i/espnbet/boost.png",dark:"https://a.espncdn.com/i/espnbet/boost.png"}},legCount:1,isNoAction:!1,betDisplayStatement:"to win"},{id:"MCH06SyVYvu1UZkhj4KutmL9qKY=",type:"STRAIGHT",betStatus:"OPEN",outcome:"PENDING",overrideOutcome:"NOT_SET",betAmount:"3",payoutAmount:"16.20",odds:"+440",startTime:"2025-04-30T15:12Z",events:[{displayName:"SBG/SBE Odds Boost Test",legs:[{id:"020d7a12-3aa8-459e-8aa2-34eaced4ad7d",marketId:"567d2a44-ba70-4881-86d7-d25fca94b592",marketSelectionId:"59b2b7ee-46c1-4cbc-9286-77fd8670cf9d",marketType:"list",status:"PENDING",odds:"+440",boostType:"ODDS_BOOST",selectionText:"Lauri Markkanen and Anfernee Simons to Each Record 20+ Points",type:"list",marketText:"SBG/SBE Odds Boost (Was +100)",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/odds-boost/organization/odds-boosts/competition/odds-boosts/event/218e1dca-f68d-4d61-9d79-394e7d752cae&market_selection_id[0]=59b2b7ee-46c1-4cbc-9286-77fd8670cf9d&odds_numerator[0]=27&odds_denominator[0]=5",marketStatus:"LIVE"}]}],rewardInfo:{type:"ODDS_BOOST",icon:{light:"https://a.espncdn.com/i/espnbet/boost.png",dark:"https://a.espncdn.com/i/espnbet/boost.png"}},legCount:1,isNoAction:!1,betDisplayStatement:"to win"},{id:"xfFjqsLCjaFx93eH6c8bOQ9mEkI=",type:"STRAIGHT",betStatus:"OPEN",outcome:"PENDING",overrideOutcome:"NOT_SET",betAmount:"2",payoutAmount:"12.00",odds:"+500",startTime:"2025-04-30T17:11Z",events:[{displayName:"SBG NHL In The News Test",legs:[{id:"910a1ebf-592d-4ae6-9471-6f648786b7e6",marketId:"c5252e65-0999-40af-b366-11967f009871",marketSelectionId:"c9b1446c-26af-43c4-9705-3a2275dc0ee5",marketType:"list",status:"PENDING",odds:"+500",boostType:"NONE",selectionText:"Long Desc Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus non gravida mi. Aliquam volutpat felis ut tempor dictum.",type:"list",marketText:"SBG In The News NHL",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/odds-boost/organization/in-the-news/competition/in-the-news/event/4cd8e64d-472c-412f-b786-dd91c98ab74e&market_selection_id[0]=c9b1446c-26af-43c4-9705-3a2275dc0ee5&odds_numerator[0]=6&odds_denominator[0]=1",marketStatus:"LIVE"}]}],rewardInfo:{type:"NONE"},legCount:1,isNoAction:!1,betDisplayStatement:"to win"},{id:"A0RLmTR8mjEFSwaa21JeOhyVdXc=",type:"STRAIGHT",betStatus:"OPEN",outcome:"PENDING",overrideOutcome:"NOT_SET",betAmount:"1",payoutAmount:"3.00",odds:"+200",startTime:"2025-04-30T17:13Z",events:[{displayName:"SBG NBA Special Test",legs:[{id:"1aa22098-57b7-4a77-bbf2-ca7ebf812083",marketId:"bc783144-0a2c-465b-9e8f-2ef55a17705c",marketSelectionId:"7a91fb3d-1291-4163-b5e0-07fe63e8e706",marketType:"list",status:"PENDING",odds:"+200",boostType:"NONE",selectionText:"Tyrese Haliburton to Record 12+ Assists",type:"list",marketText:"SBG NBA Special Test",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/odds-boost/organization/specials/competition/specials/event/d53171e2-f821-4da8-9b1c-ce1a4b735914&market_selection_id[0]=7a91fb3d-1291-4163-b5e0-07fe63e8e706&odds_numerator[0]=33&odds_denominator[0]=10",marketStatus:"LIVE"}]}],rewardInfo:{type:"NONE"},legCount:1,isNoAction:!1,betDisplayStatement:"to win"},{id:"Qhelx5np79zhAchzXXTL1HdDb80=",type:"STRAIGHT",betStatus:"OPEN",outcome:"PENDING",overrideOutcome:"NOT_SET",betAmount:"2",payoutAmount:"10.00",odds:"+400",startTime:"2025-04-30T17:13Z",events:[{displayName:"SBG NBA Special Test",legs:[{id:"73f3af25-5e1a-47eb-bcec-5b23e911c14e",marketId:"bc783144-0a2c-465b-9e8f-2ef55a17705c",marketSelectionId:"0a898e16-2a0a-44dd-a580-3ae3bade3684",marketType:"list",status:"PENDING",odds:"+400",boostType:"NONE",selectionText:"Long Desc Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus non gravida mi. Aliquam volutpat felis ut tempor dictum.",type:"list",marketText:"SBG NBA Special Test",icon:"https://a.espncdn.com/i/espnbet/mybets_allsports_green_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_allsports_green_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/odds-boost/organization/specials/competition/specials/event/d53171e2-f821-4da8-9b1c-ce1a4b735914&market_selection_id[0]=0a898e16-2a0a-44dd-a580-3ae3bade3684&odds_numerator[0]=37&odds_denominator[0]=10",marketStatus:"LIVE"}]}],rewardInfo:{type:"NONE"},legCount:1,isNoAction:!1,betDisplayStatement:"to win"}],settled:[{id:"z/WEFT7NDVjgb0d/+Elr45MfuRg=",type:"STRAIGHT",betStatus:"SETTLED",outcome:"WIN",overrideOutcome:"NOT_SET",closedAtTime:"2025-03-08T05:33Z",betAmount:"1",payoutAmount:"1.91",odds:"-110",startTime:"2025-03-08T03:00Z",events:[{displayName:"San Antonio Spurs @ Sacramento Kings",legs:[{id:"05011199-c88f-4c0d-be31-1b1c7549e273",marketId:"728792c6-d2da-435b-920a-eb86bdc45e8c",marketSelectionId:"60f8aef9-4c98-4ce2-b861-34e72c2ad13b",marketType:"total",status:"WIN",odds:"-110",boostType:"NONE",selectionText:"Over 235",type:"over",points:"235.0",marketText:"Total Points",icon:"https://a.espncdn.com/i/espnbet/mybets_green_check_icon.png",iconDark:"https://a.espncdn.com/i/espnbet/dark/mybets_green_check_icon.png",url:"https://espnbet.test-app.link/qa_integrations?%243p=a_espn&clr=espnbettingintegration&$canonical_url=/sport/basketball/organization/united-states/competition/nba/event/e1163795-ddfa-4bfc-9d52-018e8259e4b5&market_selection_id[0]=60f8aef9-4c98-4ce2-b861-34e72c2ad13b&odds_numerator[0]=2&odds_denominator[0]=1",marketStatus:"SETTLED",accrued:{goal:235}}]}],rewardInfo:{type:"NONE"},legCount:1,isNoAction:!1,betDisplayStatement:"you won"}]},promotion:{title:"The official sportsbook of ESPN",description:"Open the ESPN BET app on a mobile device and start betting!",logo:"https://a.espncdn.com/i/espnbet/ESPN_Bet_Sportsbook_Light.svg",qrCode:"https://assets.geo.hosted.espnsb.com/api/ext_mocks/qr.png",backgroundImage:"https://www.espn.com/redesign/assets/img/ictv/bkg_qr_bet.png"},disclaimers:{location:"Use a translation with a key based on location here",gambling:"Use a translation with some key based on gambling here"},...l};var p=s(8),u=s(4),m=s(104);function b(e,t,s){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var s=e[Symbol.toPrimitive];if(void 0!==s){var a=s.call(e,t||"default");if("object"!=typeof a)return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:s,enumerable:!0,configurable:!0,writable:!0}):e[t]=s,e}const g=e=>"object"==typeof e&&null!==e&&"event"in e&&"object"==typeof e.event;class h extends d.a{constructor(e,t,s,n={}){super(),b(this,"betsItems",new a.a([])),b(this,"isDataLoading",new a.a(!0)),b(this,"errorState",new a.a("none")),b(this,"hasEverSuccessfullyLoaded",new a.a(!1)),b(this,"hideWagers",new a.a(!1)),b(this,"eventId",void 0),b(this,"delegate",void 0),b(this,"betsService",void 0),b(this,"analyticsService",void 0),b(this,"pollingInterval",void 0),b(this,"pollingTask",null),b(this,"lastNonPersonalizedResponseHash",null),b(this,"lastPersonalizedResponseHash",null),b(this,"useMockData",!1),b(this,"userSettingsManager",void 0),b(this,"settingsSubscription",null),b(this,"initialized",!1),this.eventId=e,this.delegate=t,this.betsService=new i(t),this.analyticsService=s,this.pollingInterval=3e4,this.useMockData=n.useMockData||!1,this.userSettingsManager=r.a.getInstance(),this.hideWagers.value=this.userSettingsManager.shouldHideWagers(),this.settingsSubscription=this.userSettingsManager.settings.subscribe(()=>{this.updateHideWagersFromSettings()}),this.betsService=new i(t)}async init(){this.trackPanelView(),await this.fetchNewData(),this.refreshPolling(),this.initialized=!0}cleanup(){this.stopPolling(),this.settingsSubscription&&(this.settingsSubscription(),this.settingsSubscription=null),this.initialized=!1}async trackPanelView(){try{const e=this.getUserBetCounts();await this.analyticsService.panelView("espnBet",e)}catch(e){Object(u.a)(e,{context:"BetsViewModel.trackPanelView"}),console.error("[BET] Error tracking panel view:",e)}}async trackCardClick(e,t){try{const s={...this.getUserBetCounts(),card:e,bet_type:t||null};await this.analyticsService.panelClick({type:"espnBet",name:"bets_item_clicked",metadata:s})}catch(s){Object(u.a)(s,{context:"BetsViewModel.trackCardClick",cardType:e,betType:t}),console.error("[BET] Error tracking card click:",s)}}getUserBetCounts(){try{let e=0,t=0;for(const s of this.betsItems.value)if("userBets"===s.type){const a=s;t=[...a.data.bets.live,...a.data.bets.settled,...a.data.bets.upcoming].length,e=a.data.bets.live.length;break}return{in_game_bets:e,total_bets:t}}catch(e){return Object(u.a)(e,{context:"BetsViewModel.getUserBetCounts"}),console.error("[BET] Error getting user bet counts:",e),{in_game_bets:0,total_bets:0}}}refreshPolling(){this.stopPolling(),this.useMockData||(this.pollingTask={stop:()=>{}},this.pollWithInterval())}async getUserCredentials(){return{swid:await this.delegate.getUserSWID()||"",jwt:await this.delegate.getUserToken()||""}}updatePollingInterval(e){const t=this.getResponseHeaderPollingIntervalValue(e),s=this.getPanelConfigInterval(),a=t||s;a&&a!==this.pollingInterval&&(this.pollingInterval=a,console.log(`[BET] Updating polling interval to ${this.pollingInterval} milliseconds`),this.refreshPolling())}getPanelConfigInterval(){var e,t,s;const a=p.default.getPageConfig(),n=null==a||null===(e=a.panels)||void 0===e?void 0:e.find(e=>"espnBet"===e.panel_type);if(!n)return null;const o=null===(t=n.renderer)||void 0===t||null===(s=t.block_data)||void 0===s?void 0:s.odds_polling_interval;if(!o)return null;const i=parseInt(o,10);return isNaN(i)||i<=0?(console.warn(`[BET] Invalid polling interval from panel config: ${o}.`),null):1e3*i}getResponseHeaderPollingIntervalValue(e){const t=e["polling-interval"];if(!t)return null;const s=parseInt(t,10);return isNaN(s)||s<=0?(console.warn(`[BET] Invalid polling interval header received: ${t}.`),null):1e3*s}async pollWithInterval(){try{const{swid:e,jwt:t}=await this.getUserCredentials();this.pollingTask=this.betsService.pollPersonalizedBetsWithHeaders(this.eventId,e,t,this.pollingInterval,e=>{this.updatePollingInterval(e.headers),this.processPolledData(e.data)},this.handlePollingError.bind(this))}catch(e){Object(u.a)(e,{context:"BetsViewModel.pollWithInterval"}),console.error("[BET] Error setting up polling:",e)}}processPolledData(e){const t=Object(m.b)(JSON.stringify(e));if(g(e)){if(this.lastPersonalizedResponseHash===t&&this.hasEverSuccessfullyLoaded.value)return void console.log("[BET] Response hash is the same as last successful response - skipping update");this.lastPersonalizedResponseHash=t}else{if(this.lastNonPersonalizedResponseHash===t&&this.hasEverSuccessfullyLoaded.value)return void console.log("[BET] Response hash is the same as last successful response - skipping update");this.lastNonPersonalizedResponseHash=t}this.hasEverSuccessfullyLoaded.value=!0,this.errorState.value="none",this.processBetsData(e)}processBetsData(e){const t=[];if(!Object.keys(e).length)return;const s=this.processSixPackData(e);s&&t.push(s);const a=this.processLocationDisclaimer(e);a&&t.push(a);const n=this.processUserBetsData(e);n&&t.push(n);const o=this.processHotProps(e);o&&t.push(o);const i=this.processPromoCode(e);i&&t.push(i);const r=this.processGamblingMessage(e);r&&t.push(r),this.betsItems.value=t}processLocationDisclaimer(e){var t;return g(e)&&null!==(t=e.disclaimers)&&void 0!==t&&t.location?{type:"locationDisclaimer",id:"locationDisclaimer",data:{text:e.disclaimers.location}}:null}processPromoCode(e){var t;return g(e)&&e.promotion?{type:"promo",data:{title:e.promotion.title||"",description:e.promotion.description||"",logo:e.promotion.logo||"",qrCode:e.promotion.qrCode||"",backgroundImage:e.promotion.backgroundImage||""},id:"promo-"+((null===(t=e.event)||void 0===t?void 0:t.id)||e.id)}:null}processGamblingMessage(e){var t;return g(e)&&null!==(t=e.disclaimers)&&void 0!==t&&t.gambling?{type:"gamblingMessage",id:"gamblingMessage",data:{text:e.disclaimers.gambling}}:null}processSixPackData(e){var t,s,a,n,o,i,r,d,l,c;const p=g(e),u=null===(t=e.entities)||void 0===t?void 0:t.teams,m=p?null===(a=e.event)||void 0===a||null===(n=a.bets)||void 0===n?void 0:n.odds:null===(s=e.bets)||void 0===s?void 0:s.odds,b=p?null===(o=e.event)||void 0===o?void 0:o.gameState:e.gameState,h=p?null===(i=e.event)||void 0===i?void 0:i.sport:e.sport,f=p?null===(r=e.event)||void 0===r?void 0:r.id:e.id,v=p?"soccer"===(null===(d=e.event)||void 0===d?void 0:d.sport):"soccer"===e.sport;if(!(m&&b&&h&&f&&u))return null;const y=Object.values(u);let _,k;for(const e of Object.values(u)){const t=m.find(e=>"pointSpread"===e.type);t&&(t.values.some(t=>t.team===e.id&&"home"===t.type)?k=e:t.values.some(t=>t.team===e.id&&"away"===t.type)&&(_=e))}if(!k||!_)switch(console.warn("Could not determine home/away teams from odds, using first two teams"),y.length){case 0:throw new Error("No teams found in response");case 1:k=y[0],_=y[0];break;case 2:k=y[0],_=y[1];break;default:k=y[0],_=y[1],console.warn(`Warning: Unexpected team count (${y.length}) in six pack response`)}if(!_||!k)throw new Error("Could not determine home or away team from response");const S="in"===b,T=v&&!S?null===(E=k.favoredAtOpen)||void 0===E||E:null===(N=k.favored)||void 0===N||N;var N,E;const w=v&&!S?null!==(P=_.favoredAtOpen)&&void 0!==P&&P:null!==(I=_.favored)&&void 0!==I&&I;var I,P;let D="",B="",O="",L="",A="",x="",G="",M="",W="",z="",C="",R="",H="",V="",j="",U="",q="";const F=new Set,$=[];for(const e of m){F.has(e.type)||($.push({type:e.type,abbreviation:e.abbreviation}),F.add(e.type));const t="live"===e.state,s="close"===e.state,a="open"===e.state;switch(e.type){case"pointSpread":if(S?t:s)for(const t of e.values){var Z,Y,J,K;if("home"===t.type)G=null!==(Z=t.line)&&void 0!==Z?Z:"",M=null!==(Y=t.odds)&&void 0!==Y?Y:"";if("away"===t.type)A=null!==(J=t.line)&&void 0!==J?J:"",x=null!==(K=t.odds)&&void 0!==K?K:""}if((S?s:a)&&!v){if(T)for(const t of e.values){var Q,X;if("home"===t.type)O=null!==(Q=t.line)&&void 0!==Q?Q:"",L=null!==(X=t.odds)&&void 0!==X?X:""}if(w)for(const t of e.values){var ee,te;if("away"===t.type)D=null!==(ee=t.line)&&void 0!==ee?ee:"",B=null!==(te=t.odds)&&void 0!==te?te:""}}break;case"total":if(S?t:s)for(const t of e.values){var se,ae,ne,oe,ie,re,de,le;if("over"===t.type)if(v)C=null!==(se=t.line)&&void 0!==se?se:"",R=null!==(ae=t.odds)&&void 0!==ae?ae:"";else W=null!==(ne=t.line)&&void 0!==ne?ne:"",z=null!==(oe=t.odds)&&void 0!==oe?oe:"";if("under"===t.type)if(v)W=null!==(ie=t.line)&&void 0!==ie?ie:"",z=null!==(re=t.odds)&&void 0!==re?re:"";else C=null!==(de=t.line)&&void 0!==de?de:"",R=null!==(le=t.odds)&&void 0!==le?le:""}if(S?s:a){if(!T)for(const t of e.values){var ce,pe;if(v&&"over"===t.type||!v&&"under"===t.type)O=null!==(ce=t.line)&&void 0!==ce?ce:"",L=null!==(pe=t.odds)&&void 0!==pe?pe:""}if(!w)for(const t of e.values){var ue,me;if(v&&"under"===t.type||!v&&"over"===t.type)D=null!==(ue=t.line)&&void 0!==ue?ue:"",B=null!==(me=t.odds)&&void 0!==me?me:""}}break;case"moneyline":{const n=S?t:s;if(n)for(const t of e.values){var be,ge;if("home"===t.type)V=null!==(be=t.odds)&&void 0!==be?be:"";if("away"===t.type)H=null!==(ge=t.odds)&&void 0!==ge?ge:""}if(v){const t=S?s:a;for(const s of e.values)if("draw"===s.type){var he,fe;if(t)j=null!==(he=s.odds)&&void 0!==he?he:"",U="DRAW";if(n)q=null!==(fe=s.odds)&&void 0!==fe?fe:""}if(t){if(T)for(const t of e.values){var ve,ye;if("home"===t.type)O=null!==(ve=t.odds)&&void 0!==ve?ve:"",L=null!==(ye=e.abbreviation)&&void 0!==ye?ye:""}if(w)for(const t of e.values){var _e,ke;if("away"===t.type)D=null!==(_e=t.odds)&&void 0!==_e?_e:"",B=null!==(ke=e.abbreviation)&&void 0!==ke?ke:""}}}break}}}const Se={teamAbbreviation:null!==(l=_.abbreviation)&&void 0!==l?l:"",startOfGameFirstLine:D,startOfGameSecondLine:B,gameSpreadFirstLine:A,gameSpreadSecondLine:x,totalPointsFirstLine:W,totalPointsSecondLine:z,moneylineFirstLine:H},Te={teamAbbreviation:null!==(c=k.abbreviation)&&void 0!==c?c:"",startOfGameFirstLine:O,startOfGameSecondLine:L,gameSpreadFirstLine:G,gameSpreadSecondLine:M,totalPointsFirstLine:C,totalPointsSecondLine:R,moneylineFirstLine:V};return{id:"sixpack-"+f,type:"sixPack",data:{topTeamOdds:v?Te:Se,bottomTeamOdds:v?Se:Te,drawOdds:j&&U&&q?{teamAbbreviation:"DRAW",startOfGameFirstLine:j,startOfGameSecondLine:U,gameSpreadFirstLine:"",gameSpreadSecondLine:"",totalPointsFirstLine:"",totalPointsSecondLine:"",moneylineFirstLine:q}:void 0,orderedColumns:$,gameState:b},teamInfo:{home:k,away:_},hideWagers:this.hideWagers.value}}processUserBetsData(e){if(!g(e)||!e.event||!e.betsModule)return null;return{data:{bets:{live:e.betsModule.live.filter(e=>"promo"!==e.type),settled:e.betsModule.settled.filter(e=>"promo"!==e.type),upcoming:e.betsModule.upcoming.filter(e=>"promo"!==e.type)},defaultTab:e.betsModule.defaultTab},id:"userBets-"+e.event.id,type:"userBets",hideWagers:this.hideWagers.value}}processHotProps(e){var t;const s=g(e)?null===(t=e.event)||void 0===t?void 0:t.featured:e.featured;if(!s||!Array.isArray(s))return null;if(!s.every(e=>Boolean(e&&e.id)))return null;const a=s.filter(e=>e.selections.length>0);return{type:"hotProps",hideWagers:this.hideWagers.value,id:"hotProps",data:{items:a.map(e=>{const t=e.selections[0];return{id:t.id,odds:t.odds.current||"",marketText:t.text,selectionText:e.text,status:t.status,type:t.type,icon:t.icon,iconDark:t.iconDark,outcome:t.outcome}})}}}handlePollingError(e){console.error("Polling error:",e),this.hasEverSuccessfullyLoaded.value||(this.errorState.value="tabLoadFailure",this.betsItems.value=[])}stopPolling(){this.pollingTask&&(this.pollingTask.stop(),this.pollingTask=null),this.isDataLoading.value&&(this.isDataLoading.value=!1)}async fetchNewData(){this.isDataLoading.value=!0;try{if(this.useMockData)return this.betsItems.value=[],void await this.fetchMockData();await this.fetchPersonalizedData(),this.isDataLoading.value=!1}catch(e){Object(u.a)(e,{context:"BetsViewModel.fetchNewData"}),console.error("[BET] Error fetching bet data:",e),this.hasEverSuccessfullyLoaded.value||(this.errorState.value="tabLoadFailure",this.betsItems.value=[]),this.isDataLoading.value=!1}}async fetchPersonalizedData(){try{const{swid:e,jwt:t}=await this.getUserCredentials(),s=await this.betsService.getPersonalizedBets(this.eventId,e,t);this.processPolledData(s)}catch(e){throw Object(u.a)(e,{context:"BetsViewModel.fetchPersonalizedData"}),console.error("[BET] Error fetching personalized bets:",e),e}}async fetchMockData(){this.processBetsData(c),this.hasEverSuccessfullyLoaded.value=!0,this.errorState.value="none",this.isDataLoading.value=!1}clearTabLoadFailure(){this.errorState.value="none",setTimeout(()=>{this.refreshPolling()},100)}shouldHideWagers(){return this.hideWagers.value}updateHideWagersFromSettings(){this.hideWagers.value=this.userSettingsManager.shouldHideWagers(),this.refreshBetItemsWithNewSettings()}refreshBetItemsWithNewSettings(){this.betsItems.value=this.betsItems.value.map(e=>"sixPack"===e.type||"userBets"===e.type||"hotProps"===e.type?{...e,hideWagers:this.hideWagers.value}:e)}}t.default=h}}]);
2
2
  //# sourceMappingURL=12.maestro-web-sdk.esm.js.map