@maestro_io/maestro-web-sdk 2.1.1 → 2.1.3
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.
- package/dist/MaestroEventDelegate.js +60 -0
- package/dist/components/atoms/BaseButton/BaseButton.js +11 -0
- package/dist/components/atoms/BaseButton/index.js +2 -0
- package/dist/components/atoms/Image/index.js +30 -0
- package/dist/components/atoms/Rive/index.d.ts +1 -0
- package/dist/components/atoms/Rive/index.js +53 -0
- package/dist/components/atoms/SvgIcon/BetGeneralIcon.js +9 -0
- package/dist/components/atoms/SvgIcon/BetsIcon.js +11 -0
- package/dist/components/atoms/SvgIcon/BetsWarningIcon.js +11 -0
- package/dist/components/atoms/SvgIcon/CheckmarkIcon.js +6 -0
- package/dist/components/atoms/SvgIcon/CollapseIcon.js +6 -0
- package/dist/components/atoms/SvgIcon/ExpandIcon.js +6 -0
- package/dist/components/atoms/SvgIcon/FantasyIcon.js +8 -0
- package/dist/components/atoms/SvgIcon/FlameIcon.js +11 -0
- package/dist/components/atoms/SvgIcon/Icon.js +42 -0
- package/dist/components/atoms/SvgIcon/KeyPlaysIcon.js +10 -0
- package/dist/components/atoms/SvgIcon/MobilePhoneIcon.js +11 -0
- package/dist/components/atoms/SvgIcon/PlayIcon.js +8 -0
- package/dist/components/atoms/SvgIcon/StatsIcon.js +12 -0
- package/dist/components/atoms/SvgIcon/TimesIcon.js +6 -0
- package/dist/components/atoms/SvgIcon/WarningIcon.js +8 -0
- package/dist/components/atoms/SvgIcon/index.js +2 -0
- package/dist/components/core/App/App.js +41 -0
- package/dist/components/core/App/index.js +2 -0
- package/dist/components/core/OverlayContainer.js +58 -0
- package/dist/components/core/PanelManager/PanelManager.js +80 -0
- package/dist/components/core/PanelManager/index.js +2 -0
- package/dist/components/core/ScrollableContainer/FocusableItem.js +38 -0
- package/dist/components/core/ScrollableContainer/ScrollableContainer.js +166 -0
- package/dist/components/core/ScrollableContainer/index.js +2 -0
- package/dist/components/molecules/ActionButton/ActionButton.d.ts +1 -0
- package/dist/components/molecules/ActionButton/ActionButton.js +10 -0
- package/dist/components/molecules/ActionButton/index.js +2 -0
- package/dist/components/molecules/Overlay/Overlay.js +139 -0
- package/dist/components/molecules/Overlay/index.js +2 -0
- package/dist/components/molecules/PanelNavButton/PanelNavButton.d.ts +1 -0
- package/dist/components/molecules/PanelNavButton/PanelNavButton.js +40 -0
- package/dist/components/molecules/PanelNavButton/index.js +2 -0
- package/dist/components/molecules/SegmentButton/SegmentButton.js +10 -0
- package/dist/components/molecules/SegmentButton/index.js +2 -0
- package/dist/components/molecules/WatchButton/WatchButton.js +15 -0
- package/dist/components/molecules/WatchButton/index.js +2 -0
- package/dist/components/organisms/PanelNavigation/PanelNavigation.js +71 -0
- package/dist/components/organisms/PanelNavigation/index.js +2 -0
- package/dist/components/organisms/SegmentController/SegmentController.d.ts +2 -2
- package/dist/components/organisms/SegmentController/SegmentController.js +68 -0
- package/dist/components/organisms/SegmentController/index.d.ts +1 -1
- package/dist/components/organisms/SegmentController/index.js +2 -0
- package/dist/external/AxiosNetworkClient.js +83 -0
- package/dist/external/LocalStorageCacheManager.js +213 -0
- package/dist/external/ReactRenderer.d.ts +2 -2
- package/dist/external/ReactRenderer.js +86 -0
- package/dist/external/mocks/MockExternalNetworkClient.js +161 -0
- package/dist/external/ports/cacheManager.js +1 -0
- package/dist/external/ports/networkClient.js +1 -0
- package/dist/external/ports/renderer.js +1 -0
- package/dist/external/spatial-navigation/index.d.ts +3 -4
- package/dist/external/spatial-navigation/index.js +3 -0
- package/dist/external/spatial-navigation/measureLayout.js +30 -0
- package/dist/external/spatial-navigation/spatialNavigation.d.ts +2 -4
- package/dist/external/spatial-navigation/spatialNavigation.js +864 -0
- package/dist/external/spatial-navigation/utils.js +6 -0
- package/dist/external/spatial-navigation/visualDebugger.js +76 -0
- package/dist/external/spatial-navigation/withFocusable.d.ts +1 -0
- package/dist/external/spatial-navigation/withFocusable.js +245 -0
- package/dist/helpers/Observable.js +37 -0
- package/dist/helpers/deliver-focus.js +12 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +192 -0
- package/dist/interfaces/IMaestroEvent.js +6 -0
- package/dist/interfaces/IMaestroEventDelegate.js +1 -0
- package/dist/interfaces/IMaestroManager.js +1 -0
- package/dist/maestro-web-sdk.umd.js +3 -3
- package/dist/maestro-web-sdk.umd.js.map +1 -1
- package/dist/models/IModel.js +1 -0
- package/dist/models/IPanel.js +53 -0
- package/dist/models/ITheme.js +20 -0
- package/dist/models/IWinningBet.js +1 -0
- package/dist/modules/bets/interfaces/IBets.js +1 -0
- package/dist/modules/bets/mocks.js +572 -0
- package/dist/modules/bets/view/BetsView.js +116 -0
- package/dist/modules/bets/view/HotProps/HotPropsView.d.ts +7 -6
- package/dist/modules/bets/view/HotProps/HotPropsView.js +139 -0
- package/dist/modules/bets/view/SixPack/SixPackView.d.ts +2 -2
- package/dist/modules/bets/view/SixPack/SixPackView.js +103 -0
- package/dist/modules/bets/view/TabLoadFailureView.d.ts +1 -0
- package/dist/modules/bets/view/TabLoadFailureView.js +12 -0
- package/dist/modules/bets/view/UserBets/BetResult/BetResult.js +6 -0
- package/dist/modules/bets/view/UserBets/BetsCard/BetsCard.d.ts +7 -6
- package/dist/modules/bets/view/UserBets/BetsCard/BetsCard.js +122 -0
- package/dist/modules/bets/view/UserBets/BetsCard/BetsCardEvent.js +34 -0
- package/dist/modules/bets/view/UserBets/BetsCard/BetsCardFooter.js +22 -0
- package/dist/modules/bets/view/UserBets/Boost/Boost.js +6 -0
- package/dist/modules/bets/view/UserBets/OutcomeBadge/OutcomeBadge.js +9 -0
- package/dist/modules/bets/view/UserBets/Parlay/Parlay.js +13 -0
- package/dist/modules/bets/view/UserBets/Straight/Straight.js +6 -0
- package/dist/modules/bets/view/UserBets/Teaser/Teaser.js +13 -0
- package/dist/modules/bets/view/UserBets/UserBetsView.js +114 -0
- package/dist/modules/bets/view/components/Bet/Bet.d.ts +1 -0
- package/dist/modules/bets/view/components/Bet/Bet.js +32 -0
- package/dist/modules/bets/view/components/BetPill/BetPill.js +6 -0
- package/dist/modules/bets/view/components/BetsCard/BetsCard.js +15 -0
- package/dist/modules/bets/view/components/BetsCard/BetsCardHeader.js +20 -0
- package/dist/modules/bets/view/components/GamblingDisclaimer/GamblingDisclaimer.js +14 -0
- package/dist/modules/bets/view/components/LocationWarning/LocationWarning.js +16 -0
- package/dist/modules/bets/view/components/PromoCodeBanner/PromoCodeBanner.d.ts +2 -2
- package/dist/modules/bets/view/components/PromoCodeBanner/PromoCodeBanner.js +63 -0
- package/dist/modules/bets/view/components/PromoCodeBanner/index.d.ts +1 -1
- package/dist/modules/bets/view/components/PromoCodeBanner/index.js +1 -0
- package/dist/modules/bets/view-model/BetsViewModel.js +767 -0
- package/dist/modules/key-plays/constants.js +292 -0
- package/dist/modules/key-plays/interfaces/IKeyPlays.d.ts +4 -4
- package/dist/modules/key-plays/interfaces/IKeyPlays.js +14 -0
- package/dist/modules/key-plays/interfaces/IKeyPlaysResponse.js +1 -0
- package/dist/modules/key-plays/view/KeyPlayCardScoreTagView.js +13 -0
- package/dist/modules/key-plays/view/KeyPlayCardView.d.ts +0 -4
- package/dist/modules/key-plays/view/KeyPlayCardView.js +120 -0
- package/dist/modules/key-plays/view/KeyPlayErrorStateView.js +58 -0
- package/dist/modules/key-plays/view/KeyPlaysView.js +166 -0
- package/dist/modules/key-plays/view-model/KeyPlaysViewModel.js +182 -0
- package/dist/modules/stats/interfaces/IStats.d.ts +166 -0
- package/dist/modules/stats/interfaces/IStats.js +1 -0
- package/dist/modules/stats/mocks.d.ts +82 -0
- package/dist/modules/stats/mocks.js +686 -0
- package/dist/modules/stats/utils/renderTeamStatistic.d.ts +21 -0
- package/dist/modules/stats/utils/renderTeamStatistic.js +16 -0
- package/dist/modules/stats/utils.d.ts +39 -0
- package/dist/modules/stats/utils.js +62 -0
- package/dist/modules/stats/view/ActiveAthletes/ActiveAthletes.d.ts +34 -0
- package/dist/modules/stats/view/ActiveAthletes/ActiveAthletes.js +78 -0
- package/dist/modules/stats/view/ActiveAthletes/CollapsedAthletes/CollapsedAthletes.d.ts +5 -0
- package/dist/modules/stats/view/ActiveAthletes/CollapsedAthletes/CollapsedAthletes.js +27 -0
- package/dist/modules/stats/view/ActiveAthletes/ExpandedAthletes/ExpandedAthletes.d.ts +10 -0
- package/dist/modules/stats/view/ActiveAthletes/ExpandedAthletes/ExpandedAthletes.js +15 -0
- package/dist/modules/stats/view/ActiveAthletes/index.d.ts +2 -0
- package/dist/modules/stats/view/ActiveAthletes/index.js +2 -0
- package/dist/modules/stats/view/GameLeaders/GameLeaders.d.ts +8 -0
- package/dist/modules/stats/view/GameLeaders/GameLeaders.js +9 -0
- package/dist/modules/stats/view/GameLeaders/index.d.ts +2 -0
- package/dist/modules/stats/view/GameLeaders/index.js +2 -0
- package/dist/modules/stats/view/MatchPredictor/DonutChart/DonutChart.d.ts +17 -0
- package/dist/modules/stats/view/MatchPredictor/DonutChart/DonutChart.js +55 -0
- package/dist/modules/stats/view/MatchPredictor/DonutChart/index.d.ts +2 -0
- package/dist/modules/stats/view/MatchPredictor/DonutChart/index.js +1 -0
- package/dist/modules/stats/view/MatchPredictor/MatchPredictorView.d.ts +53 -0
- package/dist/modules/stats/view/MatchPredictor/MatchPredictorView.js +66 -0
- package/dist/modules/stats/view/MatchPredictor/index.d.ts +3 -0
- package/dist/modules/stats/view/MatchPredictor/index.js +2 -0
- package/dist/modules/stats/view/RecentGames/RecentGames.d.ts +63 -0
- package/dist/modules/stats/view/RecentGames/RecentGames.js +22 -0
- package/dist/modules/stats/view/RecentGames/index.d.ts +2 -0
- package/dist/modules/stats/view/RecentGames/index.js +2 -0
- package/dist/modules/stats/view/StatsQRCode/StatsQRCodeView.d.ts +52 -0
- package/dist/modules/stats/view/StatsQRCode/StatsQRCodeView.js +38 -0
- package/dist/modules/stats/view/StatsQRCode/index.d.ts +2 -0
- package/dist/modules/stats/view/StatsQRCode/index.js +1 -0
- package/dist/modules/stats/view/StatsView.d.ts +20 -0
- package/dist/modules/stats/view/StatsView.js +107 -0
- package/dist/modules/stats/view/TeamStats/TeamStatsView.d.ts +54 -0
- package/dist/modules/stats/view/TeamStats/TeamStatsView.js +69 -0
- package/dist/modules/stats/view/TeamStats/index.d.ts +2 -0
- package/dist/modules/stats/view/TeamStats/index.js +1 -0
- package/dist/modules/stats/view/Teams/StatsCarousel.d.ts +8 -0
- package/dist/modules/stats/view/Teams/StatsCarousel.js +14 -0
- package/dist/modules/stats/view/Teams/StatsProgressBar.d.ts +7 -0
- package/dist/modules/stats/view/Teams/StatsProgressBar.js +18 -0
- package/dist/modules/stats/view/Teams/Teams.d.ts +68 -0
- package/dist/modules/stats/view/Teams/Teams.js +42 -0
- package/dist/modules/stats/view/Teams/index.d.ts +2 -0
- package/dist/modules/stats/view/Teams/index.js +2 -0
- package/dist/modules/stats/view/WinProbability/WinProbability.d.ts +63 -0
- package/dist/modules/stats/view/WinProbability/WinProbability.js +27 -0
- package/dist/modules/stats/view/WinProbability/index.d.ts +2 -0
- package/dist/modules/stats/view/WinProbability/index.js +2 -0
- package/dist/modules/stats/view/components/AthletesStatistics/AthletesStatistics.d.ts +67 -0
- package/dist/modules/stats/view/components/AthletesStatistics/AthletesStatistics.js +29 -0
- package/dist/modules/stats/view/components/AthletesStatistics/StatisticTable.d.ts +4 -0
- package/dist/modules/stats/view/components/AthletesStatistics/StatisticTable.js +12 -0
- package/dist/modules/stats/view/components/AthletesStatistics/index.d.ts +2 -0
- package/dist/modules/stats/view/components/AthletesStatistics/index.js +2 -0
- package/dist/modules/stats/view/index.d.ts +2 -0
- package/dist/modules/stats/view/index.js +2 -0
- package/dist/modules/stats/view-model/StatsViewModel.d.ts +31 -0
- package/dist/modules/stats/view-model/StatsViewModel.js +90 -0
- package/dist/services/BetsService.js +102 -0
- package/dist/services/NetworkManager/NetworkManager.js +410 -0
- package/dist/services/NetworkManager/errors.js +45 -0
- package/dist/services/StatsService.d.ts +36 -0
- package/dist/services/StatsService.js +68 -0
- package/dist/services/ThemeManager/constants.js +47 -0
- package/dist/test-polyfills.d.ts +1 -0
- package/dist/test-polyfills.js +15 -0
- package/dist/types/OverlayTypes.js +4 -0
- package/dist/view-models/MaestroEventViewModel.d.ts +9 -0
- package/dist/view-models/MaestroEventViewModel.js +168 -0
- package/dist/view-models/OverlayViewModel.js +222 -0
- package/dist/view-models/PanelManagerViewModel.js +80 -0
- package/dist/view-models/ViewModel.js +32 -0
- package/dist/view-models/index.js +59 -0
- package/package.json +1 -1
|
@@ -0,0 +1,767 @@
|
|
|
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;
|