@everymatrix/casino-games-category-section 0.0.363 → 0.0.367

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.
@@ -1,962 +1,953 @@
1
- <svelte:options tag={null} />
2
-
3
- <script lang="ts">
4
- import { onMount } from "svelte";
5
- import { platformFavorite, getDevice, isMobile } from 'rvhelper';
6
- import { _, addNewMessages } from './i18n';
7
- import type { CategoryData } from './CasinoGamesCategorySection.type';
8
- import { GamesCategorySectionTranslations } from './translations';
9
-
10
- import '@everymatrix/casino-winners';
11
- import '@everymatrix/casino-game-thumbnail';
12
-
13
- const MASONRY_CLASS_PREFIX = 'game-tile-';
14
-
15
- export let categoryindex:string = '';
16
- export let endpoint:string = '';
17
- export let datasource:string = '';
18
- export let lang:string = ''; // Language
19
- export let session:string = ''; // Value for sessionID
20
- export let userid:string = ''; // Value for UserID;
21
- export let favorites:string = '';
22
- export let clientstyling:string = '';
23
- export let clientstylingurl:string = '';
24
- export let currency:string = '';
25
-
26
- export let categoryid:string = '';
27
- export let categorygames:number = 0;
28
- export let livecasino:string = 'false';
29
- export let visiblegames:string = '';
30
- export let gamepagemodalurl:string = 'false';
31
- export let enablecasinowinners:string = 'true';
32
-
33
- export let tabsorder:string = '';
34
- export let enableautoscroll:string = '';
35
-
36
- export let once = true;
37
- export let top = 0;
38
- export let bottom = 0;
39
- export let left = 0;
40
- export let right = 0;
41
-
42
- //CasinoWinners Widget
43
- let periodrecent:string = 'Today';
44
- let periodtop:string = 'Last7Days';
45
- let numberusersrecent:string = '20';
46
- let numberuserstop:string = '20';
47
- let amountlimit:string = '1';
48
- let isrecentavailable:string = 'true';
49
- let istopavailable:string = 'true';
50
- let defaultcurrency:string = 'EUR';
51
- let winners: any[] = [];
52
- let winnersType:string;
53
- let isLoggedIn:boolean = false;
54
- let userCurrency:string;
55
-
56
- // CasinoPage loading state
57
- let isLoading:boolean = false;
58
- let hasErrors:boolean = false;
59
- let sessionID:string;
60
- let playerID:string;
61
-
62
- let lobbyView:boolean = true;
63
-
64
- let userAgent = window.navigator.userAgent;
65
-
66
- let operatorSpecifications:Object;
67
- let categoryData:CategoryData;
68
- let shownCategoryData = [];
69
- let showLoadCategory:boolean = true;
70
- let offset:number = 0;
71
- let limit:number = 40;
72
- let searched:boolean = false;
73
- let recentSearched:boolean = false;
74
- let scrollTop:boolean = false;
75
- let searchItem:boolean = false;
76
- let filteresPresent:boolean = false;
77
- let showItems:boolean = true;
78
-
79
- /* Start Lazy Loading */
80
- let nativeLoading:boolean = true;
81
- let intersecting:boolean = false;
82
- let container:any;
83
- let maxTotal:number;
84
- let categoryName:HTMLElement;
85
- let favoriteGames:Array<Object>;
86
- let showFavGamesCategory:boolean = false;
87
- let receivedFavoriteResults:Object;
88
- let sessionId:string = '';
89
- let userId:string = '';
90
- let mostPlayedScreen:Boolean = false;
91
- let customStylingContainer:HTMLElement;
92
- let validObservers:boolean = false;
93
-
94
- let thumbnailContainer:Array<HTMLElement> = new Array(10000);
95
- let intersectingIndexes:Object = {};
96
- let visibilityconnect:string = '';
97
- let hidden;
98
- let visibilityChange;
99
- let dataloaded;
100
- let categoriesCache:Object = {};
101
-
102
- let favoriteGamesData:any = {
103
- items: [],
104
- count: 0,
105
- name: ''
106
- };
107
- /* End Lazy Loading */
108
-
109
- Object.keys(GamesCategorySectionTranslations).forEach((item) => {
110
- addNewMessages(item, GamesCategorySectionTranslations[item]);
111
- });
112
-
113
- if (typeof document.hidden !== 'undefined') { // Opera 12.10 and Firefox 18 and later support
114
- hidden = 'hidden';
115
- visibilityChange = 'visibilitychange';
116
- } else if (typeof document.msHidden !== 'undefined') {
117
- hidden = 'msHidden';
118
- visibilityChange = 'msvisibilitychange';
119
- } else if (typeof document.webkitHidden !== 'undefined') {
120
- hidden = 'webkitHidden';
121
- visibilityChange = 'webkitvisibilitychange';
122
- }
123
-
124
- // IntersectionObserver used for loading more games
125
- let observer = new IntersectionObserver((entries) => {
126
- entries.forEach(async (entry) => {
127
- let gameid = entry.target.gameid; // eslint-disable-line
128
- let index = entry.target.elems_index; // eslint-disable-line
129
-
130
- if (entry.isIntersecting) {
131
- if (index * 1.2 > limit ) {
132
- loadMoreGames(categoryid);
133
- }
134
- intersectingIndexes[gameid] = 1;
135
- } else {
136
- intersectingIndexes[gameid] = 0;
137
- }
138
- });
139
- });
140
-
141
- // Start favored games section
142
- const getFavoredGames = (url:string, sessionId:string, userId:string) => {
143
- let options = {
144
- method: "GET",
145
- headers: {
146
- 'X-SessionID': sessionId,
147
- }
148
- };
149
-
150
- return new Promise((resolve, reject) => {
151
- fetch(url, options)
152
- .then((res:any) => res.json())
153
- .then((updatedArray:any) => {
154
- if (updatedArray) {
155
- favoriteGames = updatedArray.items;
156
- } else {
157
- favoriteGames = [];
158
- }
159
-
160
- shownCategoryData.forEach((item:any) => {
161
- item.isFavorite = checkFavorite(item.id);
162
- });
163
-
164
- let aux:any = shownCategoryData;
165
-
166
- shownCategoryData = undefined;
167
- shownCategoryData = aux;
168
-
169
- resolve(favoriteGames);
170
- }).catch((err:any) => {
171
- console.error(err);
172
-
173
- reject(err);
174
- });
175
- });
176
- }
177
-
178
- // @TODO categoryId type
179
- const getData = (categoryId:any, offset:number, limit:number, filterArray:Array<Object> = []) => {
180
- let url:any = new URL(`${endpoint}/casino/groups/${datasource}/${categoryid}`);
181
-
182
- let vendorFilters = JSON.parse(sessionStorage.getItem('vendorFiltersByCategory'));
183
-
184
- return new Promise((resolve, reject) => {
185
- url.searchParams.delete("pagination");
186
-
187
- url.searchParams.append("expand", "games(vendor)");
188
- url.searchParams.append("fields", "id,name,games");
189
- url.searchParams.append("platform", getDevice(userAgent));
190
- url.searchParams.append("pagination", `games(offset=${offset},limit=${limit})`);
191
- url.searchParams.append('language', lang);
192
-
193
- // if vendor filters are active, get filtered games
194
- window.postMessage({ type: 'CategoryVendors', categoryid }, window.location.href);
195
-
196
- if (vendorFilters) {
197
- if (vendorFilters[categoryid]) {
198
- if (vendorFilters[categoryid].length && lobbyView === false && showFavGamesCategory === false) {
199
- let queryParamVendorId:string = '';
200
-
201
- filteresPresent = true;
202
- vendorFilters[categoryid].forEach(vendorId => {
203
- queryParamVendorId = queryParamVendorId + (queryParamVendorId ? `, id=${vendorId}` : `id=${vendorId}`);
204
- });
205
-
206
- url.searchParams.append('filter', `games(vendor(${queryParamVendorId}))`);
207
- } else {
208
- filteresPresent = false;
209
- }
210
- }
211
- }
212
-
213
- if ( categoryId && Object.keys(categoriesCache).indexOf(categoryId) >= 0) {
214
-
215
- resolve(categoriesCache[categoryId]);
216
-
217
- } else {
218
- fetch(url)
219
- .then((res:any) => res.json())
220
- .then((categoryData:any) => {
221
- dataloaded = true
222
- hasErrors = false;
223
- maxTotal = categoryData.games.total;
224
-
225
- categoriesCache[categoryId] = categoryData;
226
-
227
- resolve(categoryData);
228
- }, (err:any) => {
229
- hasErrors = true;
230
-
231
- console.error(err);
232
-
233
- reject(err);
234
- });
235
- }
236
- });
237
- }
238
-
239
- const messageHandler = (e:any) => {
240
- if (e.data) {
241
- switch(e.data.type) {
242
- case 'MostPlayedData':
243
- searched = false;
244
- lobbyView = false;
245
- showLoadCategory = false;
246
- mostPlayedScreen = true;
247
- shownCategoryData = e.data.mostPlayedGames;
248
- categoryData = {
249
- id: 'MOSTPLAYED',
250
- name: 'Most Played Games',
251
- games: {
252
- count: e.data.mostPlayedGames.length,
253
- total: e.data.mostPlayedGames.length,
254
- items: e.data.mostPlayedGames
255
- }
256
- };
257
- break;
258
-
259
- case 'CustomOperatorData':
260
- operatorSpecifications = e.data.operatordetail;
261
- break;
262
-
263
- case "RecentSearchData":
264
- searched = true;
265
- mostPlayedScreen = false;
266
- recentSearched = true;
267
- if (e.data.searchData.length > 0) {
268
- shownCategoryData = e.data.searchData;
269
- showItems = true;
270
- if (shownCategoryData) {
271
- shownCategoryData.forEach((item:any) => {
272
- item.isFavorite = checkFavorite(item.id);
273
- });
274
- }
275
- } else {
276
- shownCategoryData = [];
277
- showItems = false;
278
- }
279
- break;
280
-
281
- case 'OutOfRecentSearches':
282
- searched = false;
283
- recentSearched = false;
284
- break;
285
-
286
- case "SearchData":
287
- searched = true;
288
- mostPlayedScreen = false;
289
- recentSearched = false;
290
- shownCategoryData = e.data.searchData.items || [];
291
- searchItem = true;
292
- if (e.data.receivedFavoriteResults) {
293
- favoriteGames = e.data.receivedFavoriteResults.items;
294
- }
295
- if (shownCategoryData) {
296
- shownCategoryData.forEach((item:any) => {
297
- item.isFavorite = checkFavorite(item.id);
298
- });
299
- }
300
- break;
301
-
302
- case `CategoryData_${categoryid}`:
303
- searched = false;
304
- lobbyView = true;
305
- showLoadCategory = true;
306
- searchItem = false;
307
- mostPlayedScreen = false;
308
- validObservers = false;
309
- if (e.data.receivedFavoriteResults) {
310
- favoriteGames = e.data.receivedFavoriteResults.items;
311
- }
312
-
313
- getData(e.data.categoryId, 0, e.data.visiblegames).then((res:any) => {
314
- categoryData = res;
315
- shownCategoryData = categoryData.games.items;
316
- if(shownCategoryData) {
317
- shownCategoryData.forEach((item:any) => {
318
- item.isFavorite = checkFavorite(item.id);
319
- });
320
- }
321
- });
322
- break;
323
-
324
- case 'CategoryChange':
325
- limit = 20;
326
- break;
327
-
328
-
329
- case 'CategoryUpdate':
330
- searched = false;
331
- lobbyView = false;
332
- searchItem = false;
333
- mostPlayedScreen = false;
334
- validObservers = true;
335
- categoryid = e.data.itemId;
336
- if (categoryid !== 'MOSTPLAYED') {
337
- showLoadCategory = false;
338
- }
339
-
340
- getData(categoryid, 0, limit).then((res:any) => {
341
- categoryData = res;
342
- categoryData.games.items.forEach((item:any) => {
343
- item.isFavorite = checkFavorite(item.id);
344
- });
345
- shownCategoryData = categoryData.games.items;
346
- showLoadCategory = false;
347
- // @TODO: replace this quick fix - when there are only a few category games, the view scrolls to the footer
348
- if(shownCategoryData.length < 10) {
349
- scrollTop = true;
350
- setTimeout(() => {
351
- window.postMessage({ type: 'WidgetTopReference', scrollTop }, window.location.href);
352
- }, 500);
353
- }
354
- });
355
- break;
356
-
357
- case 'FavoriteUpdate':
358
- mostPlayedScreen = false;
359
- lobbyView = true;
360
- shownCategoryData = categoryData.games.items;
361
- shownCategoryData.forEach((item:any) => {
362
- item.isFavorite = checkFavorite(item.id);
363
- });
364
-
365
- showLoadCategory = true;
366
- break;
367
-
368
- // Start favorite category section
369
- case 'UpdateCategoryFavoriteGames':
370
- if (e.data.receivedFavoriteResults) {
371
- favoriteGames = e.data.receivedFavoriteResults.items;
372
- if (!showFavGamesCategory) {
373
- window.postMessage({ type: 'FavoriteUpdate' }, window.location.href);
374
- } else if (!lobbyView && !mostPlayedScreen) {
375
- window.postMessage({ type: 'CategoryUpdate', itemId: categoryid }, window.location.href);
376
- }
377
- }
378
- break;
379
-
380
- case 'ShowFavoriteSection':
381
- let favGameArray;
382
-
383
- if (e.data) {
384
- favGameArray = e.data.receivedFavoriteResults.items;
385
- if (favGameArray.length) {
386
- favGameArray.forEach((item:any) => {
387
- if (item.gameModel) {
388
- item.gameModel.isFavorite = item.gameModel ? true : false;
389
- }
390
- });
391
- }
392
- favoriteGamesData.items = platformFavorite(favGameArray, favoriteGamesData.items);
393
- favoriteGamesData.name = "Favorites";
394
- showFavGamesCategory = true;
395
- }
396
- break;
397
- // End favorite category section
398
-
399
- case 'UserSessionID':
400
- sessionID = e.data.session;
401
- playerID = e.data.userID;
402
-
403
- if (favorites == 'true') {
404
- if (playerID && playerID.length && sessionID && sessionID.length > 0) {
405
- getFavoredGames(`${endpoint}/player/${playerID}/favorites/`, sessionID, playerID);
406
- }
407
- }
408
-
409
- break;
410
-
411
- default:
412
- // do nothing
413
- break;
414
- }
415
- }
416
- }
417
-
418
- // @TODO categoryId type fix
419
- const loadMoreGames = (categoryId:any) => {
420
- limit += 1;
421
-
422
- if (limit <= maxTotal) {
423
- getData(categoryId, offset, limit).then((res:any) => {
424
- categoryData = res;
425
- // @TODO categoryData type fix
426
- /**
427
- * This check is needed to prevent requests with less items
428
- * that started before but ended after the last request to add items to list
429
- * This could also use abort controller instead but refactoring is needed
430
- */
431
- if(categoryData.games.items.length > shownCategoryData.length){
432
- shownCategoryData = categoryData.games.items;
433
- shownCategoryData.forEach((item:any) => {
434
- item.isFavorite = checkFavorite(item.id);
435
- });
436
- }
437
- });
438
- }
439
- }
440
-
441
- const checkFavorite = (gameId:string) => {
442
- if (favoriteGames) {
443
- if (favoriteGames.findIndex(obj => obj.id == gameId) !== -1) {
444
- return true;
445
- } else {
446
- return false;
447
- }
448
- }
449
-
450
- return false;
451
- }
452
-
453
- // @TODO categoryId type fix
454
- const showCategory = (categoryId:any, categoryData:Object) => {
455
- window.postMessage({ type: "CategoryChange", itemId: categoryId }, window.location.href);
456
- window.postMessage({ type: "SetSliderIndex", categoryData}, window.location.href);
457
- }
458
-
459
- const initialSetup = () => {
460
- // Nothing to do here
461
- }
462
-
463
- const setClientStyling = () => {
464
- let sheet = document.createElement('style');
465
- sheet.innerHTML = clientstyling;
466
- setTimeout(() => { customStylingContainer.appendChild(sheet);});
467
- }
468
-
469
- const setClientStylingURL = () => {
470
- let cssFile:HTMLElement = document.createElement('style');
471
-
472
- fetch(new URL(clientstylingurl))
473
- .then((res:any) => res.text())
474
- .then((data:any) => {
475
- cssFile.innerHTML = data
476
-
477
- if (customStylingContainer) {
478
- setTimeout(() => { customStylingContainer.appendChild(cssFile); }, 1);
479
- }
480
- });
481
- }
482
-
483
- const handleVisibilityChange = () => {
484
- if (!document[hidden]) {
485
- visibilityconnect = 'connect';
486
- } else {
487
- visibilityconnect = 'disconnect';
488
- }
489
- }
490
-
491
- const setupObserver = () => {
492
- if (validObservers) {
493
- thumbnailContainer.forEach((item, index) => {
494
- if (item) {
495
- // Hack to make sure that I can identify the thumbnail index
496
- item.elems_index = index;
497
- observer.observe(item);
498
- }
499
- });
500
- }
501
- }
502
-
503
- onMount(() => {
504
- window.addEventListener('visibilitychange', (e) => handleVisibilityChange())
505
- window.addEventListener('message', messageHandler, false);
506
- window.postMessage({ type: 'GetFavoredGame' }, window.location.href);
507
-
508
- return () => {
509
- window.removeEventListener('message', messageHandler);
510
- window.removeEventListener('visibilitychange', messageHandler);
511
- }
512
- });
513
-
514
- $: dataloaded && thumbnailContainer && setupObserver();
515
- $: lang && initialSetup();
516
- $: clientstyling && setClientStyling();
517
- $: clientstylingurl && setClientStylingURL();
518
-
519
- </script>
520
- <div class="CasinoGamesCategorySectionContainer" part="CasinoGamesCategorySectionContainer" bind:this={customStylingContainer}>
521
- {#if hasErrors}
522
- <!-- @TODO diversify error handling -->
523
- {#if filteresPresent}
524
- <p class="SearchLoading" part="SearchLoading">404 Error - No result found.</p>
525
- {:else}
526
- <p class="SearchLoading" part="SearchLoading">500 Error - Internal Server Error.</p>
527
- {/if}
528
- {:else}
529
- {#if searched}
530
- <div class="CasinoGamesContainer" part="CasinoGamesContainer">
531
- <div class="CasinoGamesHeader Searched {isMobile(userAgent) ? 'CasinoGamesHeaderMobile' : ''}" part="CasinoGamesHeader Searched {isMobile(userAgent) ? 'CasinoGamesHeaderMobile' : ''}">
532
- {#if recentSearched}
533
- <h3 class="StatusText" part="StatusText">
534
- {$_('gamesCategorySection.recentSearchedItems')}
535
- </h3>
536
- {:else}
537
- {#if !shownCategoryData.length}
538
- <h3 class="StatusText" part="StatusText">
539
- {$_('gamesCategorySection.noResults')}
540
- </h3>
541
- {:else}
542
- <h3 class="StatusText" part="StatusText">
543
- {$_('gamesCategorySection.searchedItems')}
544
- </h3>
545
- {/if}
546
- {/if}
547
- </div>
548
- {#if shownCategoryData}
549
- {#if !showItems}
550
- <p class="NoSearchResults NoRecentSearches NoRecentSearchesCenter {isMobile(userAgent) ? 'NoRecentSearchesMobile' : ''}" part="NoSearchResults NoRecentSearches NoRecentSearchesCenter {isMobile(userAgent) ? 'NoRecentSearchesMobile' : ''}">{$_('gamesCategorySection.noRecentSearch')}</p>
551
- {/if}
552
- <ul class="CasinoGamesGrid SearchedGamesGrid GamesListIncreasedGap" part="CasinoGamesGrid SearchedGamesGrid GamesListIncreasedGap">
553
- {#each shownCategoryData as gameprops, index}
554
- <casino-game-thumbnail
555
- class="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
556
- part="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
557
- session={session}
558
- userid={userid}
559
- lang={lang}
560
- searchitem={searchItem}
561
- favorites={favorites}
562
- gamethumbnail={gameprops.thumbnail}
563
- gamename={gameprops.name}
564
- gamevendor={gameprops.vendor.name}
565
- gameisnew={gameprops.isNew}
566
- gamepopularity={gameprops.popularity}
567
- gamecellsize={gameprops.cellSize}
568
- gameid={gameprops.id}
569
- gamefunmode={gameprops.hasFunMode}
570
- gamefavorite={gameprops.isFavorite}
571
- {currency}
572
- livelobbyendpoint={gameprops.details ? gameprops.href : ''}
573
- {clientstyling}
574
- {clientstylingurl}
575
- {endpoint}
576
- {livecasino}
577
- {gamepagemodalurl}
578
- ></casino-game-thumbnail>
579
- {/each}
580
- </ul>
581
- {:else}
582
- <p class="SearchWaiting" part="SearchWaiting">Waiting</p>
583
- {/if}
584
- </div>
585
- {:else}
586
- <div>
587
- {#if categoryData}
588
- {#if (enablecasinowinners === 'true') && lobbyView && categoryindex == '1'}
589
- <div class="CasinoWinners">
590
- <casino-winners
591
- {session}
592
- {periodrecent}
593
- {periodtop}
594
- {numberusersrecent}
595
- {numberuserstop}
596
- {amountlimit}
597
- {lang}
598
- {isrecentavailable}
599
- {istopavailable}
600
- {defaultcurrency}
601
- {clientstyling}
602
- {clientstylingurl}
603
- {tabsorder}
604
- {enableautoscroll}
605
- {endpoint}
606
- ></casino-winners>
607
- </div>
608
- {/if}
609
- <div class="CasinoGamesContainer" part="CasinoGamesContainer">
610
- <div class="CasinoGamesHeader" part="CasinoGamesHeader">
611
- <h3 class="CategoryName" part="CategoryName" bind:this={categoryName}>
612
- {categoryData.name}
613
- </h3>
614
-
615
- {#if showLoadCategory}
616
- <!-- svelte-ignore a11y-missing-attribute -->
617
- <a class="CategoryNameLink" part="CategoryNameLink" on:click="{e => showCategory(categoryData.id, categoryData)}">
618
- <span class="CategoryLoadMore" part="CategoryLoadMore">
619
- {$_('gamesCategorySection.viewAll')} ({categoryData.games.total})
620
- </span>
621
- </a>
622
- {/if}
623
- </div>
624
- {#if shownCategoryData.length !== 0}
625
- <ul class="{(favoriteGamesData.items.length === 0 && showFavGamesCategory) ? '' : 'CasinoGamesGrid'} GamesListIncreasedGap" part="{(favoriteGamesData.items.length === 0 && showFavGamesCategory) ? '' : 'CasinoGamesGrid'} GamesListIncreasedGap" bind:this={container}>
626
- {#each shownCategoryData as gameprops, index}
627
- {#if intersecting || nativeLoading}
628
- <casino-game-thumbnail
629
- session={session}
630
- userid={userid}
631
- lang={lang}
632
- class="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
633
- part="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
634
- favorites={favorites}
635
- gamethumbnail={gameprops.thumbnail}
636
- gamename={gameprops.name}
637
- gamevendor={gameprops.vendor.name}
638
- gameisnew={gameprops.isNew}
639
- gamepopularity={gameprops.popularity}
640
- gamecellsize={gameprops.cellSize}
641
- gameid={gameprops.id}
642
- gamefunmode={gameprops.hasFunMode}
643
- gamefavorite={gameprops.isFavorite}
644
- bind:this={thumbnailContainer[index]}
645
- connectlive={intersectingIndexes[gameprops.id] == 1 ? 'connect' : 'disconnect'}
646
- visibilityconnect={visibilityconnect}
647
- {currency}
648
- livelobbyendpoint={gameprops.details ? gameprops.href : ''}
649
- {clientstyling}
650
- {clientstylingurl}
651
- {endpoint}
652
- {livecasino}
653
- {gamepagemodalurl}
654
- ></casino-game-thumbnail>
655
- {/if}
656
- {/each}
657
- </ul>
658
- {:else}
659
- <p class="NoSearchResults" part="NoSearchResults">You don't have any games in this category.</p>
660
- {/if}
661
- </div>
662
- {:else if showFavGamesCategory}
663
- <div class="CasinoGamesContainer" part="CasinoGamesContainer">
664
- <div class="CasinoGamesHeader" part="CasinoGamesHeader">
665
- <h3 class="CategoryName" part="CategoryName" bind:this={categoryName}>
666
- {$_('gamesCategorySection.favorites')}
667
- </h3>
668
- </div>
669
- <ul class="{(favoriteGamesData.items.length != 0) ? 'CasinoGamesGrid' : ''} 'GamesListIncreasedGap'}" part="{(favoriteGamesData.items.length != 0) ? 'CasinoGamesGrid' : ''} 'GamesListIncreasedGap'}" bind:this={container}>
670
- {#if favoriteGamesData}
671
- {#each favoriteGamesData.items as gameprops, index}
672
- {#if gameprops.gameModel}
673
- {#if gameprops.gameModel.isFavorite}
674
- {#if intersecting || nativeLoading}
675
- {#if isMobile(userAgent)}
676
- {#if (gameprops.gameModel.platform.includes("iPad") || gameprops.gameModel.platform.includes("iPhone") || gameprops.gameModel.platform.includes("Android"))}
677
- <casino-game-thumbnail
678
- class="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
679
- part="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
680
- session={session}
681
- userid={userid}
682
- lang={lang}
683
- favorites={favorites}
684
- gamethumbnail={gameprops.gameModel.thumbnail}
685
- gamename={gameprops.gameModel.name}
686
- gamevendor={gameprops.gameModel.vendor.name}
687
- gameisnew={gameprops.gameModel.isNew}
688
- gamepopularity={gameprops.gameModel.popularity}
689
- gamecellsize={gameprops.cellSize}
690
- gameid={gameprops.gameModel.id}
691
- gamefunmode={gameprops.gameModel.hasFunMode}
692
- gamefavorite={gameprops.gameModel.isFavorite}
693
- showfavoredcategory={showFavGamesCategory}
694
- connectlive={intersectingIndexes[gameprops.id] == 1 ? 'connect' : 'disconnect'}
695
- visibilityconnect={visibilityconnect}
696
- {currency}
697
- livelobbyendpoint={gameprops.gameModel.details ? gameprops.gameModel.launchUrl : ''}
698
- {clientstyling}
699
- {clientstylingurl}
700
- {endpoint}
701
- {livecasino}
702
- {gamepagemodalurl}
703
- ></casino-game-thumbnail>
704
- {/if}
705
- {:else if gameprops.gameModel.platform.includes("PC")}
706
- <casino-game-thumbnail
707
- class="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
708
- part="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
709
- session={session}
710
- userid={userid}
711
- lang={lang}
712
- favorites={favorites}
713
- gamethumbnail={gameprops.gameModel.thumbnail}
714
- gamename={gameprops.gameModel.name}
715
- gamevendor={gameprops.gameModel.vendor.name}
716
- gameisnew={gameprops.gameModel.isNew}
717
- gamepopularity={gameprops.gameModel.popularity}
718
- gamecellsize={gameprops.cellSize}
719
- gameid={gameprops.gameModel.id}
720
- gamefunmode={gameprops.gameModel.hasFunMode}
721
- gamefavorite={gameprops.gameModel.isFavorite}
722
- showfavoredcategory={showFavGamesCategory}
723
- connectlive={intersectingIndexes[gameprops.id] == 1 ? 'connect' : 'disconnect'}
724
- visibilityconnect={visibilityconnect}
725
- {currency}
726
- livelobbyendpoint={gameprops.gameModel.details ? gameprops.gameModel.launchUrl : ''}
727
- {clientstyling}
728
- {clientstylingurl}
729
- {endpoint}
730
- {livecasino}
731
- {gamepagemodalurl}
732
- ></casino-game-thumbnail>
733
- {/if}
734
- {/if}
735
- {/if}
736
- {/if}
737
- {:else}
738
- <p class="NoFavoriteGames {isMobile(userAgent) ? 'NoFavoriteGamesMobile' : ''}" part="NoFavoriteGames {isMobile(userAgent) ? 'NoFavoriteGamesMobile' : ''}">
739
- <svg version="1.1" class="UnfavoredIcon" part="UnfavoredIcon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="50px" y="50px"
740
- viewBox="0 0 512.001 512.001" style="enable-background:new 0 0 512.001 512.001;" xml:space="preserve"><path style="fill: white" d="M511.266,197.256c-1.764-5.431-6.458-9.388-12.108-10.209l-158.722-23.065L269.452,20.155
741
- c-2.527-5.12-7.741-8.361-13.451-8.361c-5.709,0-10.924,3.242-13.451,8.361l-70.988,143.828L12.843,187.047
742
- c-5.65,0.821-10.344,4.779-12.108,10.209c-1.765,5.43-0.293,11.391,3.795,15.376l114.848,111.955L92.27,482.67
743
- c-0.965,5.627,1.349,11.315,5.968,14.67c4.618,3.355,10.74,3.798,15.797,1.142L256,423.846l141.961,74.637
744
- c2.195,1.154,4.591,1.723,6.979,1.723c3.11,0,6.206-0.966,8.818-2.865c4.619-3.356,6.933-9.043,5.968-14.671L392.61,324.587
745
- l114.86-111.954C511.559,208.647,513.031,202.686,511.266,197.256z M366.023,308.608c-3.536,3.446-5.15,8.412-4.314,13.278
746
- l23.311,135.898l-122.038-64.162c-4.37-2.297-9.591-2.297-13.961,0l-122.045,64.163l23.304-135.9
747
- c0.834-4.866-0.779-9.83-4.313-13.276l-98.731-96.244l136.445-19.829c4.886-0.71,9.108-3.778,11.294-8.205L256,60.685
748
- l61.023,123.645c2.186,4.427,6.408,7.496,11.294,8.206l136.447,19.828L366.023,308.608z"/></svg>
749
- <span class="NoFavoriteText NoFavoriteTextHighlight" part="NoFavoriteText NoFavoriteTextHighlight">{$_('gamesCategorySection.noFavoritesTitle')}</span>
750
- {#if isMobile(userAgent)}
751
- <span class="NoFavoriteText" part="NoFavoriteText">{$_('gamesCategorySection.noFavoritesMobile')}</span>
752
- {:else}
753
- <span class="NoFavoriteText" part="NoFavoriteText">{$_('gamesCategorySection.noFavorites')}</span>
754
- {/if}
755
- </p>
756
- {/each}
757
- {:else}
758
- <p>{$_('gamesCategorySection.waiting')}</p>
759
- {/if}
760
- </ul>
761
- </div>
762
- {/if}
763
- </div>
764
- {/if}
765
- {/if}
766
- </div>
767
-
768
-
769
- <style lang="scss">
770
-
771
- :host {
772
- font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
773
- }
774
-
775
- *, *::before, *::after {
776
- margin: 0;
777
- padding: 0;
778
- box-sizing: border-box;
779
- }
780
-
781
- $grid-gap: 16px;
782
- $grid-cell-size: 192px;
783
- $grid-cell-size-small: 110px;
784
- $grid-cell-size-medium: 122px;
785
-
786
- .CasinoWinners {
787
- background: transparent;
788
- width: 100%;
789
- min-height: 200px;
790
- }
791
- .CategoryName,
792
- .StatusText {
793
- color: var(--emfe-w-color-white, #FFFFFF);
794
- font-size: 22px;
795
- font-weight: 500;
796
- }
797
-
798
- .CategoryLoadMore {
799
- font-size: 14px;
800
- color: var(--emfe-w-color-white, #FFFFFF);
801
- }
802
-
803
- .NoSearchResults {
804
- color: var(--emfe-w-color-white, #FFFFFF);
805
- text-align: center;
806
- width: 100%;
807
- padding-left: 5px;
808
- font-size: 16px;
809
- }
810
-
811
- .NoRecentSearches {
812
- padding-bottom: 30px;
813
- }
814
-
815
- .NoRecentSearchesCenter {
816
- text-align: center;
817
- }
818
-
819
- .NoFavoriteGames {
820
- color: var(--emfe-w-color-white, #FFFFFF);
821
- font-size: 16px;
822
- display: flex;
823
- flex-direction: column;
824
- align-items: center;
825
- justify-content: center;
826
- padding: 0 20px;
827
- height: 20vh;
828
- .UnfavoredIcon {
829
- width: 50px;
830
- height: 50px;
831
- }
832
- .NoFavoriteText {
833
- text-align: center;
834
- }
835
- .NoFavoriteTextHighlight {
836
- font-weight: 600;
837
- font-size: 18px;
838
- padding: 15px 0;
839
- }
840
- }
841
-
842
- .NoFavoriteGamesMobile {
843
- height: 50vh;
844
- }
845
-
846
- .SearchWaiting {
847
- grid-column: 1/-1;
848
- color: var(--emfe-w-color-white, #FFFFFF);
849
- font-size: 13px;
850
- text-align: center;
851
- }
852
-
853
- .CasinoGamesHeader {
854
- width: 100%;
855
- display: flex;
856
- align-items: center;
857
- justify-content: space-between;
858
- padding: 8px 5px 0;
859
- margin-bottom: 16px;
860
- .CategoryNameLink {
861
- display: block;
862
- cursor: pointer;
863
- }
864
-
865
- .CategoryLoadMore {
866
- font-weight: normal;
867
- }
868
-
869
- &.Searched {
870
- justify-content: center;
871
- }
872
- }
873
-
874
- .CasinoGamesContainer {
875
- width: 100%;
876
- margin-top: 24px;
877
- padding-bottom: 16px;
878
- }
879
-
880
- .CasinoGamesGrid {
881
- display: grid;
882
- gap: $grid-gap;
883
- grid-template-columns: repeat(auto-fill, minmax(Min($grid-cell-size, 46%), 1fr));
884
- grid-template-rows: repeat(auto-fill, $grid-cell-size);
885
- grid-auto-rows: $grid-cell-size;
886
- grid-auto-columns: $grid-cell-size;
887
- grid-auto-flow: row dense;
888
-
889
- .game-tile-2x1 {
890
- grid-row: span 2;
891
-
892
- @media screen and (max-width: 375px) {
893
- grid-row: span 1;
894
- }
895
- }
896
-
897
- .game-tile-2x2 {
898
- grid-row: span 2;
899
- grid-column: span 2;
900
-
901
- @media screen and (max-width: 375px) {
902
- grid-row: span 1;
903
- grid-column: span 1;
904
- }
905
- }
906
-
907
- .game-tile-1x2 {
908
- grid-column: span 2;
909
-
910
- @media screen and (max-width: 375px) {
911
- grid-column: span 1;
912
- }
913
- }
914
-
915
- &.GamesListIncreasedGap {
916
- gap: $grid-gap + 12;
917
- }
918
- }
919
-
920
- @media screen and (max-width: 385px) {
921
- .CasinoGamesGrid {
922
- display: grid;
923
- gap: $grid-gap;
924
- grid-template-columns: repeat(auto-fill, minmax(Min($grid-cell-size-small, 46%), 1fr));
925
- grid-template-rows: repeat(auto-fill, $grid-cell-size-small);
926
- grid-auto-rows: $grid-cell-size-small;
927
- grid-auto-columns: $grid-cell-size-small;
928
-
929
- &.GamesListIncreasedGap {
930
- gap: $grid-gap;
931
- }
932
- }
933
- }
934
-
935
- @media screen and (max-width: 480px) {
936
- .CasinoGamesGrid {
937
- display: grid;
938
- gap: $grid-gap;
939
- grid-template-columns: repeat(auto-fill, minmax(Min($grid-cell-size-medium, 46%), 1fr));
940
- grid-template-rows: repeat(auto-fill, $grid-cell-size-medium);
941
- grid-auto-rows: $grid-cell-size-medium;
942
- grid-auto-columns: $grid-cell-size-medium;
943
-
944
- &.GamesListIncreasedGap {
945
- gap: $grid-gap;
946
- }
947
- }
948
- }
949
-
950
- @media screen and (min-width: 1100px) {
951
- .CasinoGamesGrid {
952
- grid-template-rows: repeat(auto-fill, 142px);
953
- grid-auto-rows: 142px;
954
- }
955
- }
956
-
957
- .SearchLoading {
958
- display: block;
959
- padding: 50px;
960
- color: var(--emfe-w-color-white, #FFFFFF);
961
- }
962
- </style>
1
+ <svelte:options tag={null} />
2
+
3
+ <script lang="ts">
4
+ import { onMount } from "svelte";
5
+ import { platformFavorite, getDevice, isMobile } from 'rvhelper';
6
+ import { _, addNewMessages } from './i18n';
7
+ import type { CategoryData } from './CasinoGamesCategorySection.type';
8
+ import { GamesCategorySectionTranslations } from './translations';
9
+
10
+ import '@everymatrix/casino-winners';
11
+ import '@everymatrix/casino-game-thumbnail';
12
+
13
+ const MASONRY_CLASS_PREFIX = 'game-tile-';
14
+
15
+ export let categoryindex:string = '';
16
+ export let endpoint:string = '';
17
+ export let datasource:string = '';
18
+ export let lang:string = ''; // Language
19
+ export let session:string = ''; // Value for sessionID
20
+ export let userid:string = ''; // Value for UserID;
21
+ export let favorites:string = '';
22
+ export let clientstyling:string = '';
23
+ export let clientstylingurl:string = '';
24
+ export let currency:string = '';
25
+
26
+ export let categoryid:string = '';
27
+ export let categorygames:number = 0;
28
+ export let livecasino:string = 'false';
29
+ export let visiblegames:string = '';
30
+ export let gamepagemodalurl:string = 'false';
31
+ export let enablecasinowinners:string = 'true';
32
+
33
+ export let tabsorder:string = '';
34
+ export let enableautoscroll:string = '';
35
+
36
+ export let once = true;
37
+ export let top = 0;
38
+ export let bottom = 0;
39
+ export let left = 0;
40
+ export let right = 0;
41
+
42
+ //CasinoWinners Widget
43
+ let periodrecent:string = 'Today';
44
+ let periodtop:string = 'Last7Days';
45
+ let numberusersrecent:string = '20';
46
+ let numberuserstop:string = '20';
47
+ let amountlimit:string = '1';
48
+ let isrecentavailable:string = 'true';
49
+ let istopavailable:string = 'true';
50
+ let defaultcurrency:string = 'EUR';
51
+ let winners: any[] = [];
52
+ let winnersType:string;
53
+ let isLoggedIn:boolean = false;
54
+ let userCurrency:string;
55
+
56
+ // CasinoPage loading state
57
+ let isLoading:boolean = false;
58
+ let hasErrors:boolean = false;
59
+ let sessionID:string;
60
+ let playerID:string;
61
+
62
+ let lobbyView:boolean = true;
63
+
64
+ let userAgent = window.navigator.userAgent;
65
+
66
+ let operatorSpecifications:Object;
67
+ let categoryData:CategoryData;
68
+ let shownCategoryData = [];
69
+ let showLoadCategory:boolean = true;
70
+ let offset:number = 0;
71
+ let limit:number = 40;
72
+ let searched:boolean = false;
73
+ let recentSearched:boolean = false;
74
+ let scrollTop:boolean = false;
75
+ let searchItem:boolean = false;
76
+ let filteresPresent:boolean = false;
77
+ let showItems:boolean = true;
78
+
79
+ /* Start Lazy Loading */
80
+ let nativeLoading:boolean = true;
81
+ let intersecting:boolean = false;
82
+ let container:any;
83
+ let maxTotal:number;
84
+ let categoryName:HTMLElement;
85
+ let favoriteGames:Array<Object>;
86
+ let showFavGamesCategory:boolean = false;
87
+ let receivedFavoriteResults:Object;
88
+ let sessionId:string = '';
89
+ let userId:string = '';
90
+ let mostPlayedScreen:Boolean = false;
91
+ let customStylingContainer:HTMLElement;
92
+ let validObservers:boolean = false;
93
+
94
+ let thumbnailContainer:Array<HTMLElement> = new Array(10000);
95
+ let intersectingIndexes:Object = {};
96
+ let visibilityconnect:string = '';
97
+ let hidden;
98
+ let visibilityChange;
99
+ let dataloaded;
100
+
101
+ let favoriteGamesData:any = {
102
+ items: [],
103
+ count: 0,
104
+ name: ''
105
+ };
106
+ /* End Lazy Loading */
107
+
108
+ Object.keys(GamesCategorySectionTranslations).forEach((item) => {
109
+ addNewMessages(item, GamesCategorySectionTranslations[item]);
110
+ });
111
+
112
+ if (typeof document.hidden !== 'undefined') { // Opera 12.10 and Firefox 18 and later support
113
+ hidden = 'hidden';
114
+ visibilityChange = 'visibilitychange';
115
+ } else if (typeof document.msHidden !== 'undefined') {
116
+ hidden = 'msHidden';
117
+ visibilityChange = 'msvisibilitychange';
118
+ } else if (typeof document.webkitHidden !== 'undefined') {
119
+ hidden = 'webkitHidden';
120
+ visibilityChange = 'webkitvisibilitychange';
121
+ }
122
+
123
+ // IntersectionObserver used for loading more games
124
+ let observer = new IntersectionObserver((entries) => {
125
+ entries.forEach(async (entry) => {
126
+ let gameid = entry.target.gameid; // eslint-disable-line
127
+ let index = entry.target.elems_index; // eslint-disable-line
128
+
129
+ if (entry.isIntersecting) {
130
+ if (index * 1.2 > limit ) {
131
+ loadMoreGames(categoryid);
132
+ }
133
+ intersectingIndexes[gameid] = 1;
134
+ } else {
135
+ intersectingIndexes[gameid] = 0;
136
+ }
137
+ });
138
+ });
139
+
140
+ // Start favored games section
141
+ const getFavoredGames = (url:string, sessionId:string, userId:string) => {
142
+ let options = {
143
+ method: "GET",
144
+ headers: {
145
+ 'X-SessionID': sessionId,
146
+ }
147
+ };
148
+
149
+ return new Promise((resolve, reject) => {
150
+ fetch(url, options)
151
+ .then((res:any) => res.json())
152
+ .then((updatedArray:any) => {
153
+ if (updatedArray) {
154
+ favoriteGames = updatedArray.items;
155
+ } else {
156
+ favoriteGames = [];
157
+ }
158
+
159
+ shownCategoryData.forEach((item:any) => {
160
+ item.isFavorite = checkFavorite(item.id);
161
+ });
162
+
163
+ let aux:any = shownCategoryData;
164
+
165
+ shownCategoryData = undefined;
166
+ shownCategoryData = aux;
167
+
168
+ resolve(favoriteGames);
169
+ }).catch((err:any) => {
170
+ console.error(err);
171
+
172
+ reject(err);
173
+ });
174
+ });
175
+ }
176
+
177
+ // @TODO categoryId type
178
+ const getData = (categoryId:any, offset:number, limit:number, filterArray:Array<Object> = []) => {
179
+ let url:any = new URL(`${endpoint}/casino/groups/${datasource}/${categoryid}`);
180
+
181
+ let vendorFilters = JSON.parse(sessionStorage.getItem('vendorFiltersByCategory'));
182
+
183
+ return new Promise((resolve, reject) => {
184
+ url.searchParams.delete("pagination");
185
+
186
+ url.searchParams.append("expand", "games(vendor)");
187
+ url.searchParams.append("fields", "id,name,games");
188
+ url.searchParams.append("platform", getDevice(userAgent));
189
+ url.searchParams.append("pagination", `games(offset=${offset},limit=${limit})`);
190
+ url.searchParams.append('language', lang);
191
+
192
+ // if vendor filters are active, get filtered games
193
+ window.postMessage({ type: 'CategoryVendors', categoryid }, window.location.href);
194
+
195
+ if (vendorFilters) {
196
+ if (vendorFilters[categoryid]) {
197
+ if (vendorFilters[categoryid].length && lobbyView === false && showFavGamesCategory === false) {
198
+ let queryParamVendorId:string = '';
199
+
200
+ filteresPresent = true;
201
+ vendorFilters[categoryid].forEach(vendorId => {
202
+ queryParamVendorId = queryParamVendorId + (queryParamVendorId ? `, id=${vendorId}` : `id=${vendorId}`);
203
+ });
204
+
205
+ url.searchParams.append('filter', `games(vendor(${queryParamVendorId}))`);
206
+ } else {
207
+ filteresPresent = false;
208
+ }
209
+ }
210
+ }
211
+
212
+ fetch(url)
213
+ .then((res:any) => res.json())
214
+ .then((categoryData:any) => {
215
+ dataloaded = true
216
+ hasErrors = false;
217
+ maxTotal = categoryData.games.total;
218
+
219
+ resolve(categoryData);
220
+ }, (err:any) => {
221
+ hasErrors = true;
222
+
223
+ console.error(err);
224
+
225
+ reject(err);
226
+ });
227
+ });
228
+ }
229
+
230
+ const messageHandler = (e:any) => {
231
+ if (e.data) {
232
+ switch(e.data.type) {
233
+ case 'MostPlayedData':
234
+ searched = false;
235
+ lobbyView = false;
236
+ showLoadCategory = false;
237
+ mostPlayedScreen = true;
238
+ shownCategoryData = e.data.mostPlayedGames;
239
+ categoryData = {
240
+ id: 'MOSTPLAYED',
241
+ name: 'Most Played Games',
242
+ games: {
243
+ count: e.data.mostPlayedGames.length,
244
+ total: e.data.mostPlayedGames.length,
245
+ items: e.data.mostPlayedGames
246
+ }
247
+ };
248
+ break;
249
+
250
+ case 'CustomOperatorData':
251
+ operatorSpecifications = e.data.operatordetail;
252
+ break;
253
+
254
+ case "RecentSearchData":
255
+ searched = true;
256
+ mostPlayedScreen = false;
257
+ recentSearched = true;
258
+ if (e.data.searchData.length > 0) {
259
+ shownCategoryData = e.data.searchData;
260
+ showItems = true;
261
+ if (shownCategoryData) {
262
+ shownCategoryData.forEach((item:any) => {
263
+ item.isFavorite = checkFavorite(item.id);
264
+ });
265
+ }
266
+ } else {
267
+ shownCategoryData = [];
268
+ showItems = false;
269
+ }
270
+ break;
271
+
272
+ case 'OutOfRecentSearches':
273
+ searched = false;
274
+ recentSearched = false;
275
+ break;
276
+
277
+ case "SearchData":
278
+ searched = true;
279
+ mostPlayedScreen = false;
280
+ recentSearched = false;
281
+ shownCategoryData = e.data.searchData.items || [];
282
+ searchItem = true;
283
+ if (e.data.receivedFavoriteResults) {
284
+ favoriteGames = e.data.receivedFavoriteResults.items;
285
+ }
286
+ if (shownCategoryData) {
287
+ shownCategoryData.forEach((item:any) => {
288
+ item.isFavorite = checkFavorite(item.id);
289
+ });
290
+ }
291
+ break;
292
+
293
+ case `CategoryData_${categoryid}`:
294
+ searched = false;
295
+ lobbyView = true;
296
+ showLoadCategory = true;
297
+ searchItem = false;
298
+ mostPlayedScreen = false;
299
+ validObservers = false;
300
+ if (e.data.receivedFavoriteResults) {
301
+ favoriteGames = e.data.receivedFavoriteResults.items;
302
+ }
303
+
304
+ getData(e.data.categoryId, 0, e.data.visiblegames).then((res:any) => {
305
+ categoryData = res;
306
+ shownCategoryData = categoryData.games.items;
307
+ if(shownCategoryData) {
308
+ shownCategoryData.forEach((item:any) => {
309
+ item.isFavorite = checkFavorite(item.id);
310
+ });
311
+ }
312
+ });
313
+ break;
314
+
315
+ case 'CategoryChange':
316
+ limit = 20;
317
+ break;
318
+
319
+
320
+ case 'CategoryUpdate':
321
+ searched = false;
322
+ lobbyView = false;
323
+ searchItem = false;
324
+ mostPlayedScreen = false;
325
+ validObservers = true;
326
+ categoryid = e.data.itemId;
327
+ if (categoryid !== 'MOSTPLAYED') {
328
+ showLoadCategory = false;
329
+ }
330
+
331
+ getData(categoryid, 0, limit).then((res:any) => {
332
+ categoryData = res;
333
+ categoryData.games.items.forEach((item:any) => {
334
+ item.isFavorite = checkFavorite(item.id);
335
+ });
336
+ shownCategoryData = categoryData.games.items;
337
+ showLoadCategory = false;
338
+ // @TODO: replace this quick fix - when there are only a few category games, the view scrolls to the footer
339
+ if(shownCategoryData.length < 10) {
340
+ scrollTop = true;
341
+ setTimeout(() => {
342
+ window.postMessage({ type: 'WidgetTopReference', scrollTop }, window.location.href);
343
+ }, 500);
344
+ }
345
+ });
346
+ break;
347
+
348
+ case 'FavoriteUpdate':
349
+ mostPlayedScreen = false;
350
+ lobbyView = true;
351
+ shownCategoryData = categoryData.games.items;
352
+ shownCategoryData.forEach((item:any) => {
353
+ item.isFavorite = checkFavorite(item.id);
354
+ });
355
+
356
+ showLoadCategory = true;
357
+ break;
358
+
359
+ // Start favorite category section
360
+ case 'UpdateCategoryFavoriteGames':
361
+ if (e.data.receivedFavoriteResults) {
362
+ favoriteGames = e.data.receivedFavoriteResults.items;
363
+ if (!showFavGamesCategory) {
364
+ window.postMessage({ type: 'FavoriteUpdate' }, window.location.href);
365
+ } else if (!lobbyView && !mostPlayedScreen) {
366
+ window.postMessage({ type: 'CategoryUpdate', itemId: categoryid }, window.location.href);
367
+ }
368
+ }
369
+ break;
370
+
371
+ case 'ShowFavoriteSection':
372
+ let favGameArray;
373
+
374
+ if (e.data) {
375
+ favGameArray = e.data.receivedFavoriteResults.items;
376
+ if (favGameArray.length) {
377
+ favGameArray.forEach((item:any) => {
378
+ if (item.gameModel) {
379
+ item.gameModel.isFavorite = item.gameModel ? true : false;
380
+ }
381
+ });
382
+ }
383
+ favoriteGamesData.items = platformFavorite(favGameArray, favoriteGamesData.items);
384
+ favoriteGamesData.name = "Favorites";
385
+ showFavGamesCategory = true;
386
+ }
387
+ break;
388
+ // End favorite category section
389
+
390
+ case 'UserSessionID':
391
+ sessionID = e.data.session;
392
+ playerID = e.data.userID;
393
+
394
+ if (favorites == 'true') {
395
+ if (playerID && playerID.length && sessionID && sessionID.length > 0) {
396
+ getFavoredGames(`${endpoint}/player/${playerID}/favorites/`, sessionID, playerID);
397
+ }
398
+ }
399
+
400
+ break;
401
+
402
+ default:
403
+ // do nothing
404
+ break;
405
+ }
406
+ }
407
+ }
408
+
409
+ // @TODO categoryId type fix
410
+ const loadMoreGames = (categoryId:any) => {
411
+ limit += 1;
412
+
413
+ if (limit <= maxTotal) {
414
+ getData(categoryId, offset, limit).then((res:any) => {
415
+ categoryData = res;
416
+ // @TODO categoryData type fix
417
+ /**
418
+ * This check is needed to prevent requests with less items
419
+ * that started before but ended after the last request to add items to list
420
+ * This could also use abort controller instead but refactoring is needed
421
+ */
422
+ if(categoryData.games.items.length > shownCategoryData.length){
423
+ shownCategoryData = categoryData.games.items;
424
+ shownCategoryData.forEach((item:any) => {
425
+ item.isFavorite = checkFavorite(item.id);
426
+ });
427
+ }
428
+ });
429
+ }
430
+ }
431
+
432
+ const checkFavorite = (gameId:string) => {
433
+ if (favoriteGames) {
434
+ if (favoriteGames.findIndex(obj => obj.id == gameId) !== -1) {
435
+ return true;
436
+ } else {
437
+ return false;
438
+ }
439
+ }
440
+
441
+ return false;
442
+ }
443
+
444
+ // @TODO categoryId type fix
445
+ const showCategory = (categoryId:any, categoryData:Object) => {
446
+ window.postMessage({ type: "CategoryChange", itemId: categoryId }, window.location.href);
447
+ window.postMessage({ type: "SetSliderIndex", categoryData}, window.location.href);
448
+ }
449
+
450
+ const initialSetup = () => {
451
+ // Nothing to do here
452
+ }
453
+
454
+ const setClientStyling = () => {
455
+ let sheet = document.createElement('style');
456
+ sheet.innerHTML = clientstyling;
457
+ setTimeout(() => { customStylingContainer.appendChild(sheet);});
458
+ }
459
+
460
+ const setClientStylingURL = () => {
461
+ let cssFile:HTMLElement = document.createElement('style');
462
+
463
+ fetch(new URL(clientstylingurl))
464
+ .then((res:any) => res.text())
465
+ .then((data:any) => {
466
+ cssFile.innerHTML = data
467
+
468
+ if (customStylingContainer) {
469
+ setTimeout(() => { customStylingContainer.appendChild(cssFile); }, 1);
470
+ }
471
+ });
472
+ }
473
+
474
+ const handleVisibilityChange = () => {
475
+ if (!document[hidden]) {
476
+ visibilityconnect = 'connect';
477
+ } else {
478
+ visibilityconnect = 'disconnect';
479
+ }
480
+ }
481
+
482
+ const setupObserver = () => {
483
+ if (validObservers) {
484
+ thumbnailContainer.forEach((item, index) => {
485
+ if (item) {
486
+ // Hack to make sure that I can identify the thumbnail index
487
+ item.elems_index = index;
488
+ observer.observe(item);
489
+ }
490
+ });
491
+ }
492
+ }
493
+
494
+ onMount(() => {
495
+ window.addEventListener('visibilitychange', (e) => handleVisibilityChange())
496
+ window.addEventListener('message', messageHandler, false);
497
+ window.postMessage({ type: 'GetFavoredGame' }, window.location.href);
498
+
499
+ return () => {
500
+ window.removeEventListener('message', messageHandler);
501
+ window.removeEventListener('visibilitychange', messageHandler);
502
+ }
503
+ });
504
+
505
+ $: dataloaded && thumbnailContainer && setupObserver();
506
+ $: lang && initialSetup();
507
+ $: clientstyling && setClientStyling();
508
+ $: clientstylingurl && setClientStylingURL();
509
+
510
+ </script>
511
+ <div class="CasinoGamesCategorySectionContainer" part="CasinoGamesCategorySectionContainer" bind:this={customStylingContainer}>
512
+ {#if hasErrors}
513
+ <!-- @TODO diversify error handling -->
514
+ {#if filteresPresent}
515
+ <p class="SearchLoading" part="SearchLoading">404 Error - No result found.</p>
516
+ {:else}
517
+ <p class="SearchLoading" part="SearchLoading">500 Error - Internal Server Error.</p>
518
+ {/if}
519
+ {:else}
520
+ {#if searched}
521
+ <div class="CasinoGamesContainer" part="CasinoGamesContainer">
522
+ <div class="CasinoGamesHeader Searched {isMobile(userAgent) ? 'CasinoGamesHeaderMobile' : ''}" part="CasinoGamesHeader Searched {isMobile(userAgent) ? 'CasinoGamesHeaderMobile' : ''}">
523
+ {#if recentSearched}
524
+ <h3 class="StatusText" part="StatusText">
525
+ {$_('gamesCategorySection.recentSearchedItems')}
526
+ </h3>
527
+ {:else}
528
+ {#if !shownCategoryData.length}
529
+ <h3 class="StatusText" part="StatusText">
530
+ {$_('gamesCategorySection.noResults')}
531
+ </h3>
532
+ {:else}
533
+ <h3 class="StatusText" part="StatusText">
534
+ {$_('gamesCategorySection.searchedItems')}
535
+ </h3>
536
+ {/if}
537
+ {/if}
538
+ </div>
539
+ {#if shownCategoryData}
540
+ {#if !showItems}
541
+ <p class="NoSearchResults NoRecentSearches NoRecentSearchesCenter {isMobile(userAgent) ? 'NoRecentSearchesMobile' : ''}" part="NoSearchResults NoRecentSearches NoRecentSearchesCenter {isMobile(userAgent) ? 'NoRecentSearchesMobile' : ''}">{$_('gamesCategorySection.noRecentSearch')}</p>
542
+ {/if}
543
+ <ul class="CasinoGamesGrid SearchedGamesGrid GamesListIncreasedGap" part="CasinoGamesGrid SearchedGamesGrid GamesListIncreasedGap">
544
+ {#each shownCategoryData as gameprops, index}
545
+ <casino-game-thumbnail
546
+ class="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
547
+ part="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
548
+ session={session}
549
+ userid={userid}
550
+ lang={lang}
551
+ searchitem={searchItem}
552
+ favorites={favorites}
553
+ gamethumbnail={gameprops.thumbnail}
554
+ gamename={gameprops.name}
555
+ gamevendor={gameprops.vendor.name}
556
+ gameisnew={gameprops.isNew}
557
+ gamepopularity={gameprops.popularity}
558
+ gamecellsize={gameprops.cellSize}
559
+ gameid={gameprops.id}
560
+ gamefunmode={gameprops.hasFunMode}
561
+ gamefavorite={gameprops.isFavorite}
562
+ {currency}
563
+ livelobbyendpoint={gameprops.details ? gameprops.href : ''}
564
+ {clientstyling}
565
+ {clientstylingurl}
566
+ {endpoint}
567
+ {livecasino}
568
+ {gamepagemodalurl}
569
+ ></casino-game-thumbnail>
570
+ {/each}
571
+ </ul>
572
+ {:else}
573
+ <p class="SearchWaiting" part="SearchWaiting">Waiting</p>
574
+ {/if}
575
+ </div>
576
+ {:else}
577
+ <div>
578
+ {#if categoryData}
579
+ {#if (enablecasinowinners === 'true') && lobbyView && categoryindex == '1'}
580
+ <div class="CasinoWinners">
581
+ <casino-winners
582
+ {session}
583
+ {periodrecent}
584
+ {periodtop}
585
+ {numberusersrecent}
586
+ {numberuserstop}
587
+ {amountlimit}
588
+ {lang}
589
+ {isrecentavailable}
590
+ {istopavailable}
591
+ {defaultcurrency}
592
+ {clientstyling}
593
+ {clientstylingurl}
594
+ {tabsorder}
595
+ {enableautoscroll}
596
+ {endpoint}
597
+ ></casino-winners>
598
+ </div>
599
+ {/if}
600
+ <div class="CasinoGamesContainer" part="CasinoGamesContainer">
601
+ <div class="CasinoGamesHeader" part="CasinoGamesHeader">
602
+ <h3 class="CategoryName" part="CategoryName" bind:this={categoryName}>
603
+ {categoryData.name}
604
+ </h3>
605
+
606
+ {#if showLoadCategory}
607
+ <!-- svelte-ignore a11y-missing-attribute -->
608
+ <a class="CategoryNameLink" part="CategoryNameLink" on:click="{e => showCategory(categoryData.id, categoryData)}">
609
+ <span class="CategoryLoadMore" part="CategoryLoadMore">
610
+ {$_('gamesCategorySection.viewAll')} ({categoryData.games.total})
611
+ </span>
612
+ </a>
613
+ {/if}
614
+ </div>
615
+ {#if shownCategoryData.length !== 0}
616
+ <ul class="{(favoriteGamesData.items.length === 0 && showFavGamesCategory) ? '' : 'CasinoGamesGrid'} GamesListIncreasedGap" part="{(favoriteGamesData.items.length === 0 && showFavGamesCategory) ? '' : 'CasinoGamesGrid'} GamesListIncreasedGap" bind:this={container}>
617
+ {#each shownCategoryData as gameprops, index}
618
+ {#if intersecting || nativeLoading}
619
+ <casino-game-thumbnail
620
+ session={session}
621
+ userid={userid}
622
+ lang={lang}
623
+ class="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
624
+ part="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
625
+ favorites={favorites}
626
+ gamethumbnail={gameprops.thumbnail}
627
+ gamename={gameprops.name}
628
+ gamevendor={gameprops.vendor.name}
629
+ gameisnew={gameprops.isNew}
630
+ gamepopularity={gameprops.popularity}
631
+ gamecellsize={gameprops.cellSize}
632
+ gameid={gameprops.id}
633
+ gamefunmode={gameprops.hasFunMode}
634
+ gamefavorite={gameprops.isFavorite}
635
+ bind:this={thumbnailContainer[index]}
636
+ connectlive={intersectingIndexes[gameprops.id] == 1 ? 'connect' : 'disconnect'}
637
+ visibilityconnect={visibilityconnect}
638
+ {currency}
639
+ livelobbyendpoint={gameprops.details ? gameprops.href : ''}
640
+ {clientstyling}
641
+ {clientstylingurl}
642
+ {endpoint}
643
+ {livecasino}
644
+ {gamepagemodalurl}
645
+ ></casino-game-thumbnail>
646
+ {/if}
647
+ {/each}
648
+ </ul>
649
+ {:else}
650
+ <p class="NoSearchResults" part="NoSearchResults">You don't have any games in this category.</p>
651
+ {/if}
652
+ </div>
653
+ {:else if showFavGamesCategory}
654
+ <div class="CasinoGamesContainer" part="CasinoGamesContainer">
655
+ <div class="CasinoGamesHeader" part="CasinoGamesHeader">
656
+ <h3 class="CategoryName" part="CategoryName" bind:this={categoryName}>
657
+ {$_('gamesCategorySection.favorites')}
658
+ </h3>
659
+ </div>
660
+ <ul class="{(favoriteGamesData.items.length != 0) ? 'CasinoGamesGrid' : ''} 'GamesListIncreasedGap'}" part="{(favoriteGamesData.items.length != 0) ? 'CasinoGamesGrid' : ''} 'GamesListIncreasedGap'}" bind:this={container}>
661
+ {#if favoriteGamesData}
662
+ {#each favoriteGamesData.items as gameprops, index}
663
+ {#if gameprops.gameModel}
664
+ {#if gameprops.gameModel.isFavorite}
665
+ {#if intersecting || nativeLoading}
666
+ {#if isMobile(userAgent)}
667
+ {#if (gameprops.gameModel.platform.includes("iPad") || gameprops.gameModel.platform.includes("iPhone") || gameprops.gameModel.platform.includes("Android"))}
668
+ <casino-game-thumbnail
669
+ class="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
670
+ part="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
671
+ session={session}
672
+ userid={userid}
673
+ lang={lang}
674
+ favorites={favorites}
675
+ gamethumbnail={gameprops.gameModel.thumbnail}
676
+ gamename={gameprops.gameModel.name}
677
+ gamevendor={gameprops.gameModel.vendor.name}
678
+ gameisnew={gameprops.gameModel.isNew}
679
+ gamepopularity={gameprops.gameModel.popularity}
680
+ gamecellsize={gameprops.cellSize}
681
+ gameid={gameprops.gameModel.id}
682
+ gamefunmode={gameprops.gameModel.hasFunMode}
683
+ gamefavorite={gameprops.gameModel.isFavorite}
684
+ showfavoredcategory={showFavGamesCategory}
685
+ connectlive={intersectingIndexes[gameprops.id] == 1 ? 'connect' : 'disconnect'}
686
+ visibilityconnect={visibilityconnect}
687
+ {currency}
688
+ livelobbyendpoint={gameprops.gameModel.details ? gameprops.gameModel.launchUrl : ''}
689
+ {clientstyling}
690
+ {clientstylingurl}
691
+ {endpoint}
692
+ {livecasino}
693
+ {gamepagemodalurl}
694
+ ></casino-game-thumbnail>
695
+ {/if}
696
+ {:else if gameprops.gameModel.platform.includes("PC")}
697
+ <casino-game-thumbnail
698
+ class="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
699
+ part="{MASONRY_CLASS_PREFIX}{gameprops.cellSize ? gameprops.cellSize : '1x1'}"
700
+ session={session}
701
+ userid={userid}
702
+ lang={lang}
703
+ favorites={favorites}
704
+ gamethumbnail={gameprops.gameModel.thumbnail}
705
+ gamename={gameprops.gameModel.name}
706
+ gamevendor={gameprops.gameModel.vendor.name}
707
+ gameisnew={gameprops.gameModel.isNew}
708
+ gamepopularity={gameprops.gameModel.popularity}
709
+ gamecellsize={gameprops.cellSize}
710
+ gameid={gameprops.gameModel.id}
711
+ gamefunmode={gameprops.gameModel.hasFunMode}
712
+ gamefavorite={gameprops.gameModel.isFavorite}
713
+ showfavoredcategory={showFavGamesCategory}
714
+ connectlive={intersectingIndexes[gameprops.id] == 1 ? 'connect' : 'disconnect'}
715
+ visibilityconnect={visibilityconnect}
716
+ {currency}
717
+ livelobbyendpoint={gameprops.gameModel.details ? gameprops.gameModel.launchUrl : ''}
718
+ {clientstyling}
719
+ {clientstylingurl}
720
+ {endpoint}
721
+ {livecasino}
722
+ {gamepagemodalurl}
723
+ ></casino-game-thumbnail>
724
+ {/if}
725
+ {/if}
726
+ {/if}
727
+ {/if}
728
+ {:else}
729
+ <p class="NoFavoriteGames {isMobile(userAgent) ? 'NoFavoriteGamesMobile' : ''}" part="NoFavoriteGames {isMobile(userAgent) ? 'NoFavoriteGamesMobile' : ''}">
730
+ <svg version="1.1" class="UnfavoredIcon" part="UnfavoredIcon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="50px" y="50px"
731
+ viewBox="0 0 512.001 512.001" style="enable-background:new 0 0 512.001 512.001;" xml:space="preserve"><path style="fill: white" d="M511.266,197.256c-1.764-5.431-6.458-9.388-12.108-10.209l-158.722-23.065L269.452,20.155
732
+ c-2.527-5.12-7.741-8.361-13.451-8.361c-5.709,0-10.924,3.242-13.451,8.361l-70.988,143.828L12.843,187.047
733
+ c-5.65,0.821-10.344,4.779-12.108,10.209c-1.765,5.43-0.293,11.391,3.795,15.376l114.848,111.955L92.27,482.67
734
+ c-0.965,5.627,1.349,11.315,5.968,14.67c4.618,3.355,10.74,3.798,15.797,1.142L256,423.846l141.961,74.637
735
+ c2.195,1.154,4.591,1.723,6.979,1.723c3.11,0,6.206-0.966,8.818-2.865c4.619-3.356,6.933-9.043,5.968-14.671L392.61,324.587
736
+ l114.86-111.954C511.559,208.647,513.031,202.686,511.266,197.256z M366.023,308.608c-3.536,3.446-5.15,8.412-4.314,13.278
737
+ l23.311,135.898l-122.038-64.162c-4.37-2.297-9.591-2.297-13.961,0l-122.045,64.163l23.304-135.9
738
+ c0.834-4.866-0.779-9.83-4.313-13.276l-98.731-96.244l136.445-19.829c4.886-0.71,9.108-3.778,11.294-8.205L256,60.685
739
+ l61.023,123.645c2.186,4.427,6.408,7.496,11.294,8.206l136.447,19.828L366.023,308.608z"/></svg>
740
+ <span class="NoFavoriteText NoFavoriteTextHighlight" part="NoFavoriteText NoFavoriteTextHighlight">{$_('gamesCategorySection.noFavoritesTitle')}</span>
741
+ {#if isMobile(userAgent)}
742
+ <span class="NoFavoriteText" part="NoFavoriteText">{$_('gamesCategorySection.noFavoritesMobile')}</span>
743
+ {:else}
744
+ <span class="NoFavoriteText" part="NoFavoriteText">{$_('gamesCategorySection.noFavorites')}</span>
745
+ {/if}
746
+ </p>
747
+ {/each}
748
+ {:else}
749
+ <p>{$_('gamesCategorySection.waiting')}</p>
750
+ {/if}
751
+ </ul>
752
+ </div>
753
+ {/if}
754
+ </div>
755
+ {/if}
756
+ {/if}
757
+ </div>
758
+
759
+
760
+ <style lang="scss">
761
+
762
+ :host {
763
+ font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
764
+ }
765
+
766
+ *, *::before, *::after {
767
+ margin: 0;
768
+ padding: 0;
769
+ box-sizing: border-box;
770
+ }
771
+
772
+ $grid-gap: 16px;
773
+ $grid-cell-size: 192px;
774
+ $grid-cell-size-small: 110px;
775
+ $grid-cell-size-medium: 122px;
776
+
777
+ .CasinoWinners {
778
+ background: transparent;
779
+ width: 100%;
780
+ min-height: 200px;
781
+ }
782
+ .CategoryName,
783
+ .StatusText {
784
+ color: var(--emfe-w-color-white, #FFFFFF);
785
+ font-size: 22px;
786
+ font-weight: 500;
787
+ }
788
+
789
+ .CategoryLoadMore {
790
+ font-size: 14px;
791
+ color: var(--emfe-w-color-white, #FFFFFF);
792
+ }
793
+
794
+ .NoSearchResults {
795
+ color: var(--emfe-w-color-white, #FFFFFF);
796
+ text-align: center;
797
+ width: 100%;
798
+ padding-left: 5px;
799
+ font-size: 16px;
800
+ }
801
+
802
+ .NoRecentSearches {
803
+ padding-bottom: 30px;
804
+ }
805
+
806
+ .NoRecentSearchesCenter {
807
+ text-align: center;
808
+ }
809
+
810
+ .NoFavoriteGames {
811
+ color: var(--emfe-w-color-white, #FFFFFF);
812
+ font-size: 16px;
813
+ display: flex;
814
+ flex-direction: column;
815
+ align-items: center;
816
+ justify-content: center;
817
+ padding: 0 20px;
818
+ height: 20vh;
819
+ .UnfavoredIcon {
820
+ width: 50px;
821
+ height: 50px;
822
+ }
823
+ .NoFavoriteText {
824
+ text-align: center;
825
+ }
826
+ .NoFavoriteTextHighlight {
827
+ font-weight: 600;
828
+ font-size: 18px;
829
+ padding: 15px 0;
830
+ }
831
+ }
832
+
833
+ .NoFavoriteGamesMobile {
834
+ height: 50vh;
835
+ }
836
+
837
+ .SearchWaiting {
838
+ grid-column: 1/-1;
839
+ color: var(--emfe-w-color-white, #FFFFFF);
840
+ font-size: 13px;
841
+ text-align: center;
842
+ }
843
+
844
+ .CasinoGamesHeader {
845
+ width: 100%;
846
+ display: flex;
847
+ align-items: center;
848
+ justify-content: space-between;
849
+ padding: 8px 5px 0;
850
+ margin-bottom: 16px;
851
+ .CategoryNameLink {
852
+ display: block;
853
+ cursor: pointer;
854
+ }
855
+
856
+ .CategoryLoadMore {
857
+ font-weight: normal;
858
+ }
859
+
860
+ &.Searched {
861
+ justify-content: center;
862
+ }
863
+ }
864
+
865
+ .CasinoGamesContainer {
866
+ width: 100%;
867
+ margin-top: 24px;
868
+ padding-bottom: 16px;
869
+ }
870
+
871
+ .CasinoGamesGrid {
872
+ display: grid;
873
+ gap: $grid-gap;
874
+ grid-template-columns: repeat(auto-fill, minmax(Min($grid-cell-size, 46%), 1fr));
875
+ grid-template-rows: repeat(auto-fill, $grid-cell-size);
876
+ grid-auto-rows: $grid-cell-size;
877
+ grid-auto-columns: $grid-cell-size;
878
+ grid-auto-flow: row dense;
879
+
880
+ .game-tile-2x1 {
881
+ grid-row: span 2;
882
+
883
+ @media screen and (max-width: 375px) {
884
+ grid-row: span 1;
885
+ }
886
+ }
887
+
888
+ .game-tile-2x2 {
889
+ grid-row: span 2;
890
+ grid-column: span 2;
891
+
892
+ @media screen and (max-width: 375px) {
893
+ grid-row: span 1;
894
+ grid-column: span 1;
895
+ }
896
+ }
897
+
898
+ .game-tile-1x2 {
899
+ grid-column: span 2;
900
+
901
+ @media screen and (max-width: 375px) {
902
+ grid-column: span 1;
903
+ }
904
+ }
905
+
906
+ &.GamesListIncreasedGap {
907
+ gap: $grid-gap + 12;
908
+ }
909
+ }
910
+
911
+ @media screen and (max-width: 385px) {
912
+ .CasinoGamesGrid {
913
+ display: grid;
914
+ gap: $grid-gap;
915
+ grid-template-columns: repeat(auto-fill, minmax(Min($grid-cell-size-small, 46%), 1fr));
916
+ grid-template-rows: repeat(auto-fill, $grid-cell-size-small);
917
+ grid-auto-rows: $grid-cell-size-small;
918
+ grid-auto-columns: $grid-cell-size-small;
919
+
920
+ &.GamesListIncreasedGap {
921
+ gap: $grid-gap;
922
+ }
923
+ }
924
+ }
925
+
926
+ @media screen and (max-width: 480px) {
927
+ .CasinoGamesGrid {
928
+ display: grid;
929
+ gap: $grid-gap;
930
+ grid-template-columns: repeat(auto-fill, minmax(Min($grid-cell-size-medium, 46%), 1fr));
931
+ grid-template-rows: repeat(auto-fill, $grid-cell-size-medium);
932
+ grid-auto-rows: $grid-cell-size-medium;
933
+ grid-auto-columns: $grid-cell-size-medium;
934
+
935
+ &.GamesListIncreasedGap {
936
+ gap: $grid-gap;
937
+ }
938
+ }
939
+ }
940
+
941
+ @media screen and (min-width: 1100px) {
942
+ .CasinoGamesGrid {
943
+ grid-template-rows: repeat(auto-fill, 142px);
944
+ grid-auto-rows: 142px;
945
+ }
946
+ }
947
+
948
+ .SearchLoading {
949
+ display: block;
950
+ padding: 50px;
951
+ color: var(--emfe-w-color-white, #FFFFFF);
952
+ }
953
+ </style>