@maestro_io/maestro-web-sdk 2.1.3 → 2.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 (200) hide show
  1. package/dist/MaestroEventDelegate.d.ts +1 -0
  2. package/dist/components/atoms/SvgIcon/Icon.d.ts +0 -2
  3. package/dist/components/core/PanelManager/PanelManager.d.ts +3 -0
  4. package/dist/components/core/ScrollableContainer/ScrollableContainer.d.ts +3 -1
  5. package/dist/external/spatial-navigation/spatialNavigation.d.ts +1 -1
  6. package/dist/helpers/url.d.ts +1 -0
  7. package/dist/index.d.ts +3 -1
  8. package/dist/interfaces/IMaestroEvent.d.ts +27 -0
  9. package/dist/interfaces/IMaestroEventDelegate.d.ts +19 -6
  10. package/dist/interfaces/IMaestroManager.d.ts +8 -1
  11. package/dist/interfaces/IUserSettings.d.ts +36 -0
  12. package/dist/maestro-web-sdk.umd.js +3 -3
  13. package/dist/maestro-web-sdk.umd.js.map +1 -1
  14. package/dist/models/IPanel.d.ts +1 -2
  15. package/dist/modules/bets/view/BetsView.d.ts +4 -0
  16. package/dist/modules/bets/view/UserBets/BetsCard/BetsCard.d.ts +1 -0
  17. package/dist/modules/bets/view/UserBets/BetsCard/BetsCardEvent.d.ts +1 -0
  18. package/dist/modules/bets/view/UserBets/BetsCard/BetsCardFooter.d.ts +2 -1
  19. package/dist/modules/bets/view/UserBets/Boost/Boost.d.ts +2 -1
  20. package/dist/modules/bets/view/UserBets/Parlay/Parlay.d.ts +2 -1
  21. package/dist/modules/bets/view/UserBets/Straight/Straight.d.ts +2 -1
  22. package/dist/modules/bets/view/UserBets/Teaser/Teaser.d.ts +2 -1
  23. package/dist/modules/bets/view/components/Bet/Bet.d.ts +7 -0
  24. package/dist/modules/bets/view-model/BetsViewModel.d.ts +15 -0
  25. package/dist/modules/key-plays/interfaces/IKeyPlays.d.ts +1 -0
  26. package/dist/modules/key-plays/interfaces/IKeyPlaysResponse.d.ts +6 -6
  27. package/dist/modules/key-plays/view/KeyPlayCardView.d.ts +4 -1
  28. package/dist/modules/key-plays/view/KeyPlayErrorStateView.d.ts +2 -0
  29. package/dist/modules/key-plays/view-model/KeyPlaysViewModel.d.ts +5 -1
  30. package/dist/modules/stats/interfaces/IStats.d.ts +38 -12
  31. package/dist/modules/stats/mocks.d.ts +0 -80
  32. package/dist/modules/stats/utils/driveSummaryUtils.d.ts +18 -0
  33. package/dist/modules/stats/view/ActiveAthletes/ActiveAthletes.d.ts +6 -19
  34. package/dist/modules/stats/view/DriveSummary/DrivePlayCard.d.ts +26 -0
  35. package/dist/modules/stats/view/DriveSummary/DriveSummary.d.ts +24 -0
  36. package/dist/modules/stats/view/DriveSummary/index.d.ts +2 -0
  37. package/dist/modules/stats/view/GameLeaders/GameLeaders.d.ts +15 -4
  38. package/dist/modules/stats/view/MatchPredictor/MatchPredictorView.d.ts +13 -48
  39. package/dist/modules/stats/view/RecentGames/RecentGames.d.ts +10 -21
  40. package/dist/modules/stats/view/StatsItemView.d.ts +19 -0
  41. package/dist/modules/stats/view/StatsView.d.ts +3 -3
  42. package/dist/modules/stats/view/TeamStats/TeamStatsView.d.ts +2 -4
  43. package/dist/modules/stats/view/Teams/Teams.d.ts +10 -26
  44. package/dist/modules/stats/view/WinProbability/WinProbability.d.ts +10 -21
  45. package/dist/modules/stats/view-model/StatsViewModel.d.ts +149 -5
  46. package/dist/services/BetsService.d.ts +2 -2
  47. package/dist/services/NetworkManager/NetworkManager.d.ts +1 -3
  48. package/dist/services/NetworkManager/NetworkManagerFactory.d.ts +42 -0
  49. package/dist/services/NetworkManager/types.d.ts +77 -0
  50. package/dist/services/StatsService.d.ts +2 -2
  51. package/dist/services/UserSettingsManager.d.ts +63 -0
  52. package/dist/view-models/MaestroEventViewModel.d.ts +5 -0
  53. package/dist/view-models/PanelManagerViewModel.d.ts +24 -0
  54. package/dist/view-models/index.d.ts +4 -0
  55. package/package.json +1 -1
  56. package/dist/MaestroEventDelegate.js +0 -60
  57. package/dist/components/atoms/BaseButton/BaseButton.js +0 -11
  58. package/dist/components/atoms/BaseButton/index.js +0 -2
  59. package/dist/components/atoms/Image/index.js +0 -30
  60. package/dist/components/atoms/Rive/index.js +0 -53
  61. package/dist/components/atoms/SvgIcon/BetGeneralIcon.js +0 -9
  62. package/dist/components/atoms/SvgIcon/BetsIcon.js +0 -11
  63. package/dist/components/atoms/SvgIcon/BetsWarningIcon.js +0 -11
  64. package/dist/components/atoms/SvgIcon/CheckmarkIcon.js +0 -6
  65. package/dist/components/atoms/SvgIcon/CollapseIcon.js +0 -6
  66. package/dist/components/atoms/SvgIcon/ExpandIcon.js +0 -6
  67. package/dist/components/atoms/SvgIcon/FantasyIcon.d.ts +0 -6
  68. package/dist/components/atoms/SvgIcon/FantasyIcon.js +0 -8
  69. package/dist/components/atoms/SvgIcon/FlameIcon.js +0 -11
  70. package/dist/components/atoms/SvgIcon/Icon.js +0 -42
  71. package/dist/components/atoms/SvgIcon/KeyPlaysIcon.js +0 -10
  72. package/dist/components/atoms/SvgIcon/MobilePhoneIcon.js +0 -11
  73. package/dist/components/atoms/SvgIcon/PlayIcon.js +0 -8
  74. package/dist/components/atoms/SvgIcon/StatsIcon.js +0 -12
  75. package/dist/components/atoms/SvgIcon/TimesIcon.js +0 -6
  76. package/dist/components/atoms/SvgIcon/WarningIcon.js +0 -8
  77. package/dist/components/atoms/SvgIcon/index.js +0 -2
  78. package/dist/components/core/App/App.js +0 -41
  79. package/dist/components/core/App/index.js +0 -2
  80. package/dist/components/core/OverlayContainer.js +0 -58
  81. package/dist/components/core/PanelManager/PanelManager.js +0 -80
  82. package/dist/components/core/PanelManager/index.js +0 -2
  83. package/dist/components/core/ScrollableContainer/FocusableItem.js +0 -38
  84. package/dist/components/core/ScrollableContainer/ScrollableContainer.js +0 -166
  85. package/dist/components/core/ScrollableContainer/index.js +0 -2
  86. package/dist/components/molecules/ActionButton/ActionButton.js +0 -10
  87. package/dist/components/molecules/ActionButton/index.js +0 -2
  88. package/dist/components/molecules/Overlay/Overlay.js +0 -139
  89. package/dist/components/molecules/Overlay/index.js +0 -2
  90. package/dist/components/molecules/PanelNavButton/PanelNavButton.js +0 -40
  91. package/dist/components/molecules/PanelNavButton/index.js +0 -2
  92. package/dist/components/molecules/SegmentButton/SegmentButton.js +0 -10
  93. package/dist/components/molecules/SegmentButton/index.js +0 -2
  94. package/dist/components/molecules/WatchButton/WatchButton.js +0 -15
  95. package/dist/components/molecules/WatchButton/index.js +0 -2
  96. package/dist/components/organisms/PanelNavigation/PanelNavigation.js +0 -71
  97. package/dist/components/organisms/PanelNavigation/index.js +0 -2
  98. package/dist/components/organisms/SegmentController/SegmentController.js +0 -68
  99. package/dist/components/organisms/SegmentController/index.js +0 -2
  100. package/dist/external/AxiosNetworkClient.js +0 -83
  101. package/dist/external/LocalStorageCacheManager.js +0 -213
  102. package/dist/external/ReactRenderer.js +0 -86
  103. package/dist/external/mocks/MockExternalNetworkClient.js +0 -161
  104. package/dist/external/ports/cacheManager.js +0 -1
  105. package/dist/external/ports/networkClient.js +0 -1
  106. package/dist/external/ports/renderer.js +0 -1
  107. package/dist/external/spatial-navigation/index.js +0 -3
  108. package/dist/external/spatial-navigation/measureLayout.js +0 -30
  109. package/dist/external/spatial-navigation/spatialNavigation.js +0 -864
  110. package/dist/external/spatial-navigation/utils.js +0 -6
  111. package/dist/external/spatial-navigation/visualDebugger.js +0 -76
  112. package/dist/external/spatial-navigation/withFocusable.js +0 -245
  113. package/dist/helpers/Observable.js +0 -37
  114. package/dist/helpers/deliver-focus.d.ts +0 -5
  115. package/dist/helpers/deliver-focus.js +0 -12
  116. package/dist/index.js +0 -192
  117. package/dist/interfaces/IMaestroEvent.js +0 -6
  118. package/dist/interfaces/IMaestroEventDelegate.js +0 -1
  119. package/dist/interfaces/IMaestroManager.js +0 -1
  120. package/dist/models/IModel.js +0 -1
  121. package/dist/models/IPanel.js +0 -53
  122. package/dist/models/ITheme.js +0 -20
  123. package/dist/models/IWinningBet.js +0 -1
  124. package/dist/modules/bets/interfaces/IBets.js +0 -1
  125. package/dist/modules/bets/mocks.js +0 -572
  126. package/dist/modules/bets/view/BetsView.js +0 -116
  127. package/dist/modules/bets/view/HotProps/HotPropsView.js +0 -139
  128. package/dist/modules/bets/view/SixPack/SixPackView.js +0 -103
  129. package/dist/modules/bets/view/TabLoadFailureView.js +0 -12
  130. package/dist/modules/bets/view/UserBets/BetResult/BetResult.js +0 -6
  131. package/dist/modules/bets/view/UserBets/BetsCard/BetsCard.js +0 -122
  132. package/dist/modules/bets/view/UserBets/BetsCard/BetsCardEvent.js +0 -34
  133. package/dist/modules/bets/view/UserBets/BetsCard/BetsCardFooter.js +0 -22
  134. package/dist/modules/bets/view/UserBets/Boost/Boost.js +0 -6
  135. package/dist/modules/bets/view/UserBets/OutcomeBadge/OutcomeBadge.js +0 -9
  136. package/dist/modules/bets/view/UserBets/Parlay/Parlay.js +0 -13
  137. package/dist/modules/bets/view/UserBets/Straight/Straight.js +0 -6
  138. package/dist/modules/bets/view/UserBets/Teaser/Teaser.js +0 -13
  139. package/dist/modules/bets/view/UserBets/UserBetsView.js +0 -114
  140. package/dist/modules/bets/view/components/Bet/Bet.js +0 -32
  141. package/dist/modules/bets/view/components/BetPill/BetPill.js +0 -6
  142. package/dist/modules/bets/view/components/BetsCard/BetsCard.js +0 -15
  143. package/dist/modules/bets/view/components/BetsCard/BetsCardHeader.js +0 -20
  144. package/dist/modules/bets/view/components/GamblingDisclaimer/GamblingDisclaimer.js +0 -14
  145. package/dist/modules/bets/view/components/LocationWarning/LocationWarning.js +0 -16
  146. package/dist/modules/bets/view/components/PromoCodeBanner/PromoCodeBanner.js +0 -63
  147. package/dist/modules/bets/view/components/PromoCodeBanner/index.js +0 -1
  148. package/dist/modules/bets/view-model/BetsViewModel.js +0 -767
  149. package/dist/modules/key-plays/constants.js +0 -292
  150. package/dist/modules/key-plays/interfaces/IKeyPlays.js +0 -14
  151. package/dist/modules/key-plays/interfaces/IKeyPlaysResponse.js +0 -1
  152. package/dist/modules/key-plays/view/KeyPlayCardScoreTagView.js +0 -13
  153. package/dist/modules/key-plays/view/KeyPlayCardView.js +0 -120
  154. package/dist/modules/key-plays/view/KeyPlayErrorStateView.js +0 -58
  155. package/dist/modules/key-plays/view/KeyPlaysView.js +0 -166
  156. package/dist/modules/key-plays/view-model/KeyPlaysViewModel.js +0 -182
  157. package/dist/modules/stats/interfaces/IStats.js +0 -1
  158. package/dist/modules/stats/mocks.js +0 -686
  159. package/dist/modules/stats/utils/renderTeamStatistic.js +0 -16
  160. package/dist/modules/stats/utils.js +0 -62
  161. package/dist/modules/stats/view/ActiveAthletes/ActiveAthletes.js +0 -78
  162. package/dist/modules/stats/view/ActiveAthletes/CollapsedAthletes/CollapsedAthletes.js +0 -27
  163. package/dist/modules/stats/view/ActiveAthletes/ExpandedAthletes/ExpandedAthletes.js +0 -15
  164. package/dist/modules/stats/view/ActiveAthletes/index.js +0 -2
  165. package/dist/modules/stats/view/GameLeaders/GameLeaders.js +0 -9
  166. package/dist/modules/stats/view/GameLeaders/index.js +0 -2
  167. package/dist/modules/stats/view/MatchPredictor/DonutChart/DonutChart.js +0 -55
  168. package/dist/modules/stats/view/MatchPredictor/DonutChart/index.js +0 -1
  169. package/dist/modules/stats/view/MatchPredictor/MatchPredictorView.js +0 -66
  170. package/dist/modules/stats/view/MatchPredictor/index.js +0 -2
  171. package/dist/modules/stats/view/RecentGames/RecentGames.js +0 -22
  172. package/dist/modules/stats/view/RecentGames/index.js +0 -2
  173. package/dist/modules/stats/view/StatsQRCode/StatsQRCodeView.js +0 -38
  174. package/dist/modules/stats/view/StatsQRCode/index.js +0 -1
  175. package/dist/modules/stats/view/StatsView.js +0 -107
  176. package/dist/modules/stats/view/TeamStats/TeamStatsView.js +0 -69
  177. package/dist/modules/stats/view/TeamStats/index.js +0 -1
  178. package/dist/modules/stats/view/Teams/StatsCarousel.js +0 -14
  179. package/dist/modules/stats/view/Teams/StatsProgressBar.js +0 -18
  180. package/dist/modules/stats/view/Teams/Teams.js +0 -42
  181. package/dist/modules/stats/view/Teams/index.js +0 -2
  182. package/dist/modules/stats/view/WinProbability/WinProbability.js +0 -27
  183. package/dist/modules/stats/view/WinProbability/index.js +0 -2
  184. package/dist/modules/stats/view/components/AthletesStatistics/AthletesStatistics.js +0 -29
  185. package/dist/modules/stats/view/components/AthletesStatistics/StatisticTable.js +0 -12
  186. package/dist/modules/stats/view/components/AthletesStatistics/index.js +0 -2
  187. package/dist/modules/stats/view/index.js +0 -2
  188. package/dist/modules/stats/view-model/StatsViewModel.js +0 -90
  189. package/dist/services/BetsService.js +0 -102
  190. package/dist/services/NetworkManager/NetworkManager.js +0 -410
  191. package/dist/services/NetworkManager/errors.js +0 -45
  192. package/dist/services/StatsService.js +0 -68
  193. package/dist/services/ThemeManager/constants.js +0 -47
  194. package/dist/test-polyfills.js +0 -15
  195. package/dist/types/OverlayTypes.js +0 -4
  196. package/dist/view-models/MaestroEventViewModel.js +0 -168
  197. package/dist/view-models/OverlayViewModel.js +0 -222
  198. package/dist/view-models/PanelManagerViewModel.js +0 -80
  199. package/dist/view-models/ViewModel.js +0 -32
  200. package/dist/view-models/index.js +0 -59
@@ -1,767 +0,0 @@
1
- import { Observable } from '../../../helpers/Observable';
2
- import BetsService from '../../../services/BetsService';
3
- // Import ViewModel with correct path
4
- import { ViewModel } from '../../../view-models/ViewModel';
5
- import { MOCK_BETS_API_RESPONSE } from '../mocks';
6
- import SDK from '@/index';
7
- // The interval for polling bet data (in milliseconds)
8
- const DEFAULT_POLLING_INTERVAL = 30000; // 30 seconds
9
- const BET_ITEM_TYPE = {
10
- ODDS: 'odds',
11
- USER_BETS: 'userBets',
12
- PROMO: 'promo',
13
- HOT_PROPS: 'hotProps',
14
- LOCATION_DISCLAIMER: 'locationDisclaimer',
15
- GAMBLING_MESSAGE: 'gamblingMessage',
16
- };
17
- const BET_ERROR_STATE = {
18
- NONE: 'none',
19
- TAB_LOAD_FAILURE: 'tabLoadFailure',
20
- };
21
- const isPersonalizedBetsResponse = (data) => {
22
- return (typeof data === 'object' &&
23
- data !== null &&
24
- 'event' in data &&
25
- typeof data.event === 'object');
26
- };
27
- export class BetsViewModel extends ViewModel {
28
- constructor(eventId, delegate, options = {}) {
29
- super();
30
- // Observable properties
31
- Object.defineProperty(this, "betsItems", {
32
- enumerable: true,
33
- configurable: true,
34
- writable: true,
35
- value: new Observable([])
36
- });
37
- Object.defineProperty(this, "isDataLoading", {
38
- enumerable: true,
39
- configurable: true,
40
- writable: true,
41
- value: new Observable(true)
42
- });
43
- Object.defineProperty(this, "errorState", {
44
- enumerable: true,
45
- configurable: true,
46
- writable: true,
47
- value: new Observable('none')
48
- });
49
- Object.defineProperty(this, "hasEverSuccessfullyLoaded", {
50
- enumerable: true,
51
- configurable: true,
52
- writable: true,
53
- value: new Observable(false)
54
- });
55
- // Properties
56
- Object.defineProperty(this, "eventId", {
57
- enumerable: true,
58
- configurable: true,
59
- writable: true,
60
- value: void 0
61
- });
62
- Object.defineProperty(this, "delegate", {
63
- enumerable: true,
64
- configurable: true,
65
- writable: true,
66
- value: void 0
67
- });
68
- Object.defineProperty(this, "betsService", {
69
- enumerable: true,
70
- configurable: true,
71
- writable: true,
72
- value: void 0
73
- });
74
- Object.defineProperty(this, "pollingInterval", {
75
- enumerable: true,
76
- configurable: true,
77
- writable: true,
78
- value: void 0
79
- });
80
- Object.defineProperty(this, "pollingTask", {
81
- enumerable: true,
82
- configurable: true,
83
- writable: true,
84
- value: null
85
- });
86
- Object.defineProperty(this, "lastNonPersonalizedResponseHash", {
87
- enumerable: true,
88
- configurable: true,
89
- writable: true,
90
- value: null
91
- });
92
- Object.defineProperty(this, "lastPersonalizedResponseHash", {
93
- enumerable: true,
94
- configurable: true,
95
- writable: true,
96
- value: null
97
- });
98
- Object.defineProperty(this, "useMockData", {
99
- enumerable: true,
100
- configurable: true,
101
- writable: true,
102
- value: false
103
- });
104
- Object.defineProperty(this, "initialized", {
105
- enumerable: true,
106
- configurable: true,
107
- writable: true,
108
- value: false
109
- });
110
- this.eventId = eventId;
111
- this.delegate = delegate;
112
- this.betsService = new BetsService(delegate);
113
- this.pollingInterval = options.pollingInterval || DEFAULT_POLLING_INTERVAL;
114
- this.useMockData = options.useMockData || false;
115
- this.betsService = new BetsService(delegate);
116
- }
117
- /**
118
- * Initialize the ViewModel and start data fetching
119
- */
120
- async init() {
121
- await this.fetchNewData();
122
- this.refreshPolling();
123
- this.initialized = true;
124
- }
125
- /**
126
- * Clean up resources when the ViewModel is no longer needed
127
- */
128
- cleanup() {
129
- this.stopPolling();
130
- this.initialized = false;
131
- }
132
- /**
133
- * Refresh polling for bet data
134
- */
135
- refreshPolling() {
136
- // First stop any existing polling
137
- this.stopPolling();
138
- if (this.useMockData) {
139
- return;
140
- }
141
- // We'll determine whether to use authenticated polling in the polling task
142
- this.pollingTask = {
143
- stop: () => {
144
- // This will be replaced when actual polling starts
145
- },
146
- };
147
- // Start the poll loop
148
- this.pollWithInterval();
149
- }
150
- /**
151
- * Poll with the correct method based on authentication status
152
- */
153
- async pollWithInterval() {
154
- try {
155
- // Check if the user is authenticated
156
- const isAuthenticated = await this.delegate.userIsAuthenticated();
157
- if (isAuthenticated) {
158
- // Get user credentials
159
- const swid = (await this.delegate.getUserSWID()) || '';
160
- const jwt = (await this.delegate.getUserToken()) || '';
161
- // Start personalized polling
162
- this.pollingTask = this.betsService.pollPersonalizedBets(this.eventId, swid, jwt, this.pollingInterval, this.processPolledData.bind(this), this.handlePollingError.bind(this));
163
- }
164
- else {
165
- // Start non-personalized polling
166
- this.pollingTask = this.betsService.pollNonPersonalizedBets(this.eventId, this.pollingInterval, this.processPolledData.bind(this), this.handlePollingError.bind(this));
167
- }
168
- }
169
- catch (error) {
170
- console.error('Error setting up polling:', error);
171
- // If there's an error, fall back to non-personalized polling
172
- this.pollingTask = this.betsService.pollNonPersonalizedBets(this.eventId, this.pollingInterval, this.processPolledData.bind(this), this.handlePollingError.bind(this));
173
- }
174
- }
175
- /**
176
- * Process data received from polling
177
- */
178
- processPolledData(data) {
179
- // Calculate hash for the response to check if it's different from the last one
180
- const responseHash = JSON.stringify(data).hashCode();
181
- const isPersonalized = isPersonalizedBetsResponse(data);
182
- if (isPersonalized) {
183
- // Check if this is the same as the last successful response
184
- if (this.lastPersonalizedResponseHash === responseHash &&
185
- this.hasEverSuccessfullyLoaded.value) {
186
- console.log('Response hash is the same as last successful response - skipping update');
187
- return;
188
- }
189
- // Update tracking variables
190
- this.lastPersonalizedResponseHash = responseHash;
191
- // this.lastSuccessfulResponsePersonalized =
192
- // data as IPersonalizedBetsResponse;
193
- }
194
- else {
195
- // Check if this is the same as the last successful response
196
- if (this.lastNonPersonalizedResponseHash === responseHash &&
197
- this.hasEverSuccessfullyLoaded.value) {
198
- console.log('Response hash is the same as last successful response - skipping update');
199
- return;
200
- }
201
- // Update tracking variables
202
- this.lastNonPersonalizedResponseHash = responseHash;
203
- // this.lastSuccessfulResponseNonPersonalized = data as IBetsResponse;
204
- }
205
- // Update state
206
- this.hasEverSuccessfullyLoaded.value = true;
207
- this.errorState.value = 'none';
208
- // Process the response and update betsItems
209
- // This is a placeholder - you would need to implement the actual logic
210
- // for parsing different parts of the response (sixPacks, hot props, etc.)
211
- this.processBetsData(data);
212
- }
213
- /**
214
- * Process the bets data and update the betsItems
215
- */
216
- processBetsData(data) {
217
- // Clear current items
218
- const newItems = [];
219
- if (!Object.keys(data).length) {
220
- return;
221
- }
222
- // 1. Process regular odds (always available in both response types)
223
- const sixPack = this.processSixPackData(data);
224
- if (sixPack) {
225
- newItems.push(sixPack);
226
- }
227
- // 2. Process location disclaimer if this is a personalized response
228
- const locationDisclaimer = this.processLocationDisclaimer(data);
229
- if (locationDisclaimer) {
230
- newItems.push(locationDisclaimer);
231
- }
232
- // 3. Process user bets if this is a personalized response
233
- const userBets = this.processUserBetsData(data);
234
- if (userBets) {
235
- newItems.push(userBets);
236
- }
237
- // 4. Process featured(hot props) bets if available
238
- const hotProps = this.processHotProps(data);
239
- if (hotProps?.length) {
240
- newItems.push(...hotProps);
241
- }
242
- // 5. Process promo code
243
- const promoCode = this.processPromoCode(data);
244
- if (promoCode) {
245
- newItems.push(promoCode);
246
- }
247
- // 6. Process gambling message if available
248
- const gamblingMessage = this.processGamblingMessage(data);
249
- if (gamblingMessage) {
250
- newItems.push(gamblingMessage);
251
- }
252
- // Update the observable
253
- this.betsItems.value = newItems;
254
- }
255
- processLocationDisclaimer(data) {
256
- const isPersonalized = isPersonalizedBetsResponse(data);
257
- if (!isPersonalized || !data.disclaimers?.location) {
258
- return null;
259
- }
260
- return {
261
- type: 'locationDisclaimer',
262
- id: 'locationDisclaimer',
263
- data: {
264
- text: data.disclaimers.location,
265
- },
266
- };
267
- }
268
- processPromoCode(data) {
269
- const isPersonalized = isPersonalizedBetsResponse(data);
270
- if (!isPersonalized || !data.promos) {
271
- return null;
272
- }
273
- return {
274
- type: 'promo',
275
- data: {
276
- title: data.promos.title || '',
277
- description: data.promos.description || '',
278
- logo: data.promos.logo || '',
279
- qrCode: data.promos.qrCode || '',
280
- },
281
- id: `promo-${data.event?.id || data.id}`,
282
- };
283
- }
284
- processGamblingMessage(data) {
285
- const isPersonalized = isPersonalizedBetsResponse(data);
286
- if (!isPersonalized || !data.disclaimers?.gambling) {
287
- return null;
288
- }
289
- return {
290
- type: 'gamblingMessage',
291
- id: 'gamblingMessage',
292
- data: {
293
- text: data.disclaimers.gambling,
294
- },
295
- };
296
- }
297
- processSixPackData(response) {
298
- const isPersonalized = isPersonalizedBetsResponse(response);
299
- const teams = response.entities?.teams;
300
- const odds = !isPersonalized
301
- ? response.bets?.odds
302
- : response.event?.bets?.odds;
303
- const gameState = !isPersonalized
304
- ? response.gameState
305
- : response.event?.gameState;
306
- const sport = !isPersonalized ? response.sport : response.event?.sport;
307
- const eventId = !isPersonalized ? response.id : response.event?.id;
308
- if (!odds || !gameState || !sport || !eventId || !teams) {
309
- return null;
310
- }
311
- const teamArray = Object.values(teams);
312
- let awayTeam;
313
- let homeTeam;
314
- // Find home and away teams from odds
315
- for (const team of Object.values(teams)) {
316
- const spreadOdds = odds.find((odd) => odd.type === 'pointSpread');
317
- if (spreadOdds) {
318
- if (spreadOdds.values.some((v) => v.team === team.id && v.type === 'home')) {
319
- homeTeam = team;
320
- }
321
- else if (spreadOdds.values.some((v) => v.team === team.id && v.type === 'away')) {
322
- awayTeam = team;
323
- }
324
- }
325
- }
326
- // Fallback logic if we couldn't determine from odds
327
- if (!homeTeam || !awayTeam) {
328
- console.warn('Could not determine home/away teams from odds, using first two teams');
329
- switch (teamArray.length) {
330
- case 0:
331
- throw new Error('No teams found in response');
332
- case 1:
333
- // Only one team - unusual case, but handle gracefully
334
- homeTeam = teamArray[0];
335
- awayTeam = teamArray[0]; // Same team as both home and away (shouldn't happen)
336
- break;
337
- case 2:
338
- // Default to first team as home, second as away
339
- homeTeam = teamArray[0];
340
- awayTeam = teamArray[1];
341
- break;
342
- default:
343
- // More than 2 teams - take first two and log warning
344
- homeTeam = teamArray[0];
345
- awayTeam = teamArray[1];
346
- console.warn(`Warning: Unexpected team count (${teamArray.length}) in six pack response`);
347
- }
348
- }
349
- if (!awayTeam || !homeTeam) {
350
- throw new Error('Could not determine home or away team from response');
351
- }
352
- const isHomeFavoured = homeTeam.favored ?? true;
353
- const isInProgress = gameState === 'in';
354
- let awayTeamStartGameFirstLine = '';
355
- let awayTeamStartGameSecondLine = '';
356
- let homeTeamStartGameFirstLine = '';
357
- let homeTeamStartGameSecondLine = '';
358
- let awaySpreadFirstLine = '';
359
- let awaySpreadSecondLine = '';
360
- let homeSpreadFirstLine = '';
361
- let homeSpreadSecondLine = '';
362
- let awayTotalFirstLine = '';
363
- let awayTotalSecondLine = '';
364
- let homeTotalFirstLine = '';
365
- let homeTotalSecondLine = '';
366
- let awayMoneylineFirstLine = '';
367
- let homeMoneylineFirstLine = '';
368
- for (const oddsItem of odds) {
369
- switch (oddsItem.type) {
370
- case 'pointSpread':
371
- if (isInProgress) {
372
- // For in-progress games, use "close" for CO and "live" for current
373
- if (isHomeFavoured) {
374
- if (oddsItem.state === 'close') {
375
- for (const value of oddsItem.values) {
376
- if (value.type === 'home') {
377
- homeTeamStartGameFirstLine = value.line ?? '';
378
- homeTeamStartGameSecondLine = value.odds ?? '';
379
- }
380
- }
381
- }
382
- }
383
- else {
384
- if (oddsItem.state === 'close') {
385
- for (const value of oddsItem.values) {
386
- if (value.type === 'away') {
387
- awayTeamStartGameFirstLine = value.line ?? '';
388
- awayTeamStartGameSecondLine = value.odds ?? '';
389
- }
390
- }
391
- }
392
- }
393
- if (oddsItem.state === 'live') {
394
- for (const value of oddsItem.values) {
395
- if (value.type === 'home') {
396
- homeSpreadFirstLine = value.line ?? '';
397
- homeSpreadSecondLine = value.odds ?? '';
398
- }
399
- if (value.type === 'away') {
400
- awaySpreadFirstLine = value.line ?? '';
401
- awaySpreadSecondLine = value.odds ?? '';
402
- }
403
- }
404
- }
405
- }
406
- else {
407
- // For pre/post games, use "open" for CO and "close" for current
408
- if (isHomeFavoured) {
409
- if (oddsItem.state === 'open') {
410
- for (const value of oddsItem.values) {
411
- if (value.type === 'home') {
412
- homeTeamStartGameFirstLine = value.line ?? '';
413
- homeTeamStartGameSecondLine = value.odds ?? '';
414
- }
415
- }
416
- }
417
- }
418
- else {
419
- if (oddsItem.state === 'open') {
420
- for (const value of oddsItem.values) {
421
- if (value.type === 'away') {
422
- awayTeamStartGameFirstLine = value.line ?? '';
423
- awayTeamStartGameSecondLine = value.odds ?? '';
424
- }
425
- }
426
- }
427
- }
428
- if (oddsItem.state === 'close') {
429
- for (const value of oddsItem.values) {
430
- if (value.type === 'home') {
431
- homeSpreadFirstLine = value.line ?? '';
432
- homeSpreadSecondLine = value.odds ?? '';
433
- }
434
- if (value.type === 'away') {
435
- awaySpreadFirstLine = value.line ?? '';
436
- awaySpreadSecondLine = value.odds ?? '';
437
- }
438
- }
439
- }
440
- }
441
- break;
442
- case 'total':
443
- if (isInProgress) {
444
- if (isHomeFavoured) {
445
- if (oddsItem.state === 'close') {
446
- for (const value of oddsItem.values) {
447
- if (value.type === 'over') {
448
- awayTeamStartGameFirstLine = value.line ?? '';
449
- awayTeamStartGameSecondLine = value.odds ?? '';
450
- }
451
- }
452
- }
453
- }
454
- else {
455
- if (oddsItem.state === 'close') {
456
- for (const value of oddsItem.values) {
457
- if (value.type === 'under') {
458
- homeTeamStartGameFirstLine = value.line ?? '';
459
- homeTeamStartGameSecondLine = value.odds ?? '';
460
- }
461
- }
462
- }
463
- }
464
- if (oddsItem.state === 'live') {
465
- for (const value of oddsItem.values) {
466
- if (value.type === 'under') {
467
- homeTotalFirstLine = value.line ?? '';
468
- homeTotalSecondLine = value.odds ?? '';
469
- }
470
- if (value.type === 'over') {
471
- awayTotalFirstLine = value.line ?? '';
472
- awayTotalSecondLine = value.odds ?? '';
473
- }
474
- }
475
- }
476
- }
477
- else {
478
- if (isHomeFavoured) {
479
- if (oddsItem.state === 'open') {
480
- for (const value of oddsItem.values) {
481
- if (value.type === 'over') {
482
- awayTeamStartGameFirstLine = value.line ?? '';
483
- awayTeamStartGameSecondLine = value.odds ?? '';
484
- }
485
- }
486
- }
487
- }
488
- else {
489
- if (oddsItem.state === 'open') {
490
- for (const value of oddsItem.values) {
491
- if (value.type === 'under') {
492
- homeTeamStartGameFirstLine = value.line ?? '';
493
- homeTeamStartGameSecondLine = value.odds ?? '';
494
- }
495
- }
496
- }
497
- }
498
- if (oddsItem.state === 'close') {
499
- for (const value of oddsItem.values) {
500
- if (value.type === 'under') {
501
- homeTotalFirstLine = value.line ?? '';
502
- homeTotalSecondLine = value.odds ?? '';
503
- }
504
- if (value.type === 'over') {
505
- awayTotalFirstLine = value.line ?? '';
506
- awayTotalSecondLine = value.odds ?? '';
507
- }
508
- }
509
- }
510
- }
511
- break;
512
- case 'moneyline':
513
- if (isInProgress) {
514
- if (oddsItem.state === 'live') {
515
- for (const value of oddsItem.values) {
516
- if (value.type === 'home') {
517
- homeMoneylineFirstLine = value.odds ?? '';
518
- }
519
- if (value.type === 'away') {
520
- awayMoneylineFirstLine = value.odds ?? '';
521
- }
522
- }
523
- }
524
- }
525
- else {
526
- if (oddsItem.state === 'close') {
527
- for (const value of oddsItem.values) {
528
- if (value.type === 'home') {
529
- homeMoneylineFirstLine = value.odds ?? '';
530
- }
531
- if (value.type === 'away') {
532
- awayMoneylineFirstLine = value.odds ?? '';
533
- }
534
- }
535
- }
536
- }
537
- break;
538
- }
539
- }
540
- // Create the six pack data structure
541
- const awayTeamOdds = {
542
- teamAbbreviation: awayTeam.abbreviation ?? '',
543
- startOfGameFirstLine: awayTeamStartGameFirstLine,
544
- startOfGameSecondLine: awayTeamStartGameSecondLine,
545
- gameSpreadFirstLine: awaySpreadFirstLine,
546
- gameSpreadSecondLine: awaySpreadSecondLine,
547
- totalPointsFirstLine: awayTotalFirstLine,
548
- totalPointsSecondLine: awayTotalSecondLine,
549
- moneylineFirstLine: awayMoneylineFirstLine,
550
- };
551
- const homeTeamOdds = {
552
- teamAbbreviation: homeTeam.abbreviation ?? '',
553
- startOfGameFirstLine: homeTeamStartGameFirstLine,
554
- startOfGameSecondLine: homeTeamStartGameSecondLine,
555
- gameSpreadFirstLine: homeSpreadFirstLine,
556
- gameSpreadSecondLine: homeSpreadSecondLine,
557
- totalPointsFirstLine: homeTotalFirstLine,
558
- totalPointsSecondLine: homeTotalSecondLine,
559
- moneylineFirstLine: homeMoneylineFirstLine,
560
- };
561
- const sixPack = {
562
- awayTeamOdds,
563
- homeTeamOdds,
564
- gameState,
565
- sport: sport,
566
- };
567
- return {
568
- id: `sixpack-${eventId}`,
569
- type: 'sixPack',
570
- data: sixPack,
571
- teamInfo: {
572
- home: homeTeam,
573
- away: awayTeam,
574
- },
575
- };
576
- }
577
- processUserBetsData(data) {
578
- const isPersonalized = isPersonalizedBetsResponse(data);
579
- if (!isPersonalized || !data.event || !data.betsModule) {
580
- return null;
581
- }
582
- const betItems = {
583
- live: data.betsModule.live.filter((bet) => bet.type !== 'promo'),
584
- settled: data.betsModule.settled.filter((bet) => bet.type !== 'promo'),
585
- upcoming: data.betsModule.upcoming.filter((bet) => bet.type !== 'promo'),
586
- };
587
- return {
588
- data: {
589
- bets: betItems,
590
- defaultTab: data.betsModule.defaultTab,
591
- },
592
- id: `userBets-${data.event.id}`,
593
- type: 'userBets',
594
- };
595
- }
596
- processHotProps(response) {
597
- const isPersonalized = isPersonalizedBetsResponse(response);
598
- const hotProps = isPersonalized
599
- ? response.event?.featured
600
- : response.featured;
601
- if (!hotProps || !Array.isArray(hotProps)) {
602
- return null;
603
- }
604
- const hasData = hotProps.every((hotProp) => Boolean(hotProp && hotProp.id));
605
- if (!hasData) {
606
- return null;
607
- }
608
- return hotProps
609
- .filter((hotProp) => hotProp.selections && hotProp.selections.length > 0)
610
- .map((hotProp) => {
611
- const data = {
612
- items: hotProp.selections.map((item) => ({
613
- id: item.id,
614
- selectionText: hotProp.text,
615
- marketText: item.text,
616
- odds: item.odds.current || '',
617
- icon: item.icon,
618
- iconDark: item.iconDark,
619
- status: item.status,
620
- type: item.type,
621
- })),
622
- };
623
- return {
624
- data,
625
- type: 'hotProps',
626
- id: `hotProps-${hotProp.id}`,
627
- };
628
- });
629
- }
630
- /**
631
- * Handle errors that occur during polling
632
- */
633
- handlePollingError(error) {
634
- console.error('Polling error:', error);
635
- if (!this.hasEverSuccessfullyLoaded.value) {
636
- // If we've never had a successful load, show an error state
637
- this.errorState.value = 'tabLoadFailure';
638
- this.betsItems.value = [];
639
- }
640
- else {
641
- // If we had a previous successful load, keep showing the old data
642
- // No need to update errorState or betsItems
643
- }
644
- }
645
- /**
646
- * Stop polling for bet data
647
- */
648
- stopPolling() {
649
- if (this.pollingTask) {
650
- this.pollingTask.stop();
651
- this.pollingTask = null;
652
- }
653
- }
654
- /**
655
- * Fetch new bet data immediately (one-time)
656
- */
657
- async fetchNewData() {
658
- this.isDataLoading.value = true;
659
- try {
660
- // Handle mock data if enabled
661
- if (this.useMockData) {
662
- this.betsItems.value = [];
663
- await this.fetchMockData();
664
- return;
665
- }
666
- // Check if the user is authenticated
667
- const isAuthenticated = await this.delegate.userIsAuthenticated();
668
- if (isAuthenticated) {
669
- await this.fetchPersonalizedData();
670
- }
671
- else {
672
- await this.fetchNonPersonalizedData();
673
- }
674
- this.isDataLoading.value = false;
675
- }
676
- catch (error) {
677
- console.error('Error fetching bet data:', error);
678
- if (!this.hasEverSuccessfullyLoaded.value) {
679
- this.errorState.value = 'tabLoadFailure';
680
- this.betsItems.value = [];
681
- }
682
- this.isDataLoading.value = false;
683
- }
684
- }
685
- /**
686
- * Fetch personalized bet data
687
- */
688
- async fetchPersonalizedData() {
689
- try {
690
- const swid = await this.delegate.getUserSWID();
691
- const jwt = await this.delegate.getUserToken();
692
- if (!swid || !jwt) {
693
- throw new Error('Missing authentication data (SWID or JWT)');
694
- }
695
- const response = await this.betsService.getPersonalizedBets(this.eventId, swid, jwt);
696
- // Process the response
697
- this.processPolledData(response);
698
- }
699
- catch (error) {
700
- console.error('Error fetching personalized bets:', error);
701
- // Fall back to non-personalized data
702
- await this.fetchNonPersonalizedData();
703
- }
704
- }
705
- /**
706
- * Fetch non-personalized bet data
707
- */
708
- async fetchNonPersonalizedData() {
709
- const response = await this.betsService.getNonPersonalizedBets(this.eventId);
710
- // Process the response
711
- this.processPolledData(response);
712
- }
713
- /**
714
- * Fetch mock data for testing
715
- */
716
- async fetchMockData() {
717
- this.processBetsData(MOCK_BETS_API_RESPONSE);
718
- this.hasEverSuccessfullyLoaded.value = true;
719
- this.errorState.value = 'none';
720
- this.isDataLoading.value = false;
721
- }
722
- simulateUseCase(useCase, _) {
723
- switch (useCase) {
724
- case 'betsTabLoadFailure':
725
- this.errorState.value = 'tabLoadFailure';
726
- break;
727
- case 'betsMockData':
728
- this.stopPolling();
729
- this.useMockData = true;
730
- this.lastPersonalizedResponseHash = null;
731
- this.lastNonPersonalizedResponseHash = null;
732
- this.errorState.value = 'none';
733
- this.fetchNewData();
734
- break;
735
- case 'betsLiveData':
736
- this.useMockData = false;
737
- this.lastPersonalizedResponseHash = null;
738
- this.lastNonPersonalizedResponseHash = null;
739
- this.hasEverSuccessfullyLoaded.value = false;
740
- this.errorState.value = 'none';
741
- this.fetchNewData();
742
- this.refreshPolling();
743
- break;
744
- default:
745
- throw new Error(`Unsupported use case: ${useCase}`);
746
- }
747
- }
748
- clearTabLoadFailure() {
749
- this.errorState.value = 'none';
750
- SDK.getMaestroEventViewModel().navigation.setFocus('PANEL_NAV_BUTTON_1');
751
- setTimeout(async () => {
752
- await this.fetchNewData();
753
- }, 100);
754
- }
755
- }
756
- if (!String.prototype.hashCode) {
757
- String.prototype.hashCode = function () {
758
- let hash = 0;
759
- for (let i = 0; i < this.length; i++) {
760
- const char = this.charCodeAt(i);
761
- hash = (hash << 5) - hash + char;
762
- hash = hash & hash; // Convert to 32bit integer
763
- }
764
- return hash;
765
- };
766
- }
767
- export default BetsViewModel;