@smartico/public-api 0.0.379 → 0.0.381
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/.nvmrc +1 -1
- package/CLAUDE.md +103 -0
- package/README.md +53 -2
- package/dist/Base/ClassId.d.ts +2 -0
- package/dist/Jackpots/JackpotDetails.d.ts +14 -15
- package/dist/Jackpots/JackpotPot.d.ts +10 -6
- package/dist/Raffle/GetRaffleWonPrizesRequest.d.ts +9 -0
- package/dist/Raffle/GetRaffleWonPrizesResponse.d.ts +52 -0
- package/dist/Raffle/index.d.ts +2 -0
- package/dist/SmarticoAPI.d.ts +6 -1
- package/dist/SmarticoLib/index.d.ts +5 -1
- package/dist/Store/BuyStoreItemErrorCode.d.ts +9 -1
- package/dist/Tournaments/TournamentRegistrationError.d.ts +3 -1
- package/dist/WSAPI/WSAPI.d.ts +13 -1235
- package/dist/WSAPI/WSAPIAvatars.d.ts +296 -0
- package/dist/WSAPI/WSAPIBase.d.ts +71 -0
- package/dist/WSAPI/WSAPIBonuses.d.ts +240 -0
- package/dist/WSAPI/WSAPIClans.d.ts +388 -0
- package/dist/WSAPI/WSAPIGamePick.d.ts +593 -0
- package/dist/WSAPI/WSAPIGeneral.d.ts +172 -0
- package/dist/WSAPI/WSAPIInbox.d.ts +615 -0
- package/dist/WSAPI/WSAPIJackpots.d.ts +344 -0
- package/dist/WSAPI/WSAPILeaderBoard.d.ts +139 -0
- package/dist/WSAPI/WSAPIMiniGames.d.ts +510 -0
- package/dist/WSAPI/WSAPIMissions.d.ts +517 -0
- package/dist/WSAPI/WSAPIRaffles.d.ts +643 -0
- package/dist/WSAPI/WSAPIStore.d.ts +656 -0
- package/dist/WSAPI/WSAPITournaments.d.ts +501 -0
- package/dist/WSAPI/WSAPITypes.d.ts +376 -205
- package/dist/WSAPI/WSAPIUser.d.ts +533 -0
- package/dist/index.js +6745 -1661
- package/dist/index.js.map +1 -1
- package/dist/index.modern.mjs +6324 -1342
- package/dist/index.modern.mjs.map +1 -1
- package/docs/Callbacks.md +162 -0
- package/docs/SmarticoObject.md +445 -0
- package/docs/Transforms.md +99 -0
- package/docs/api/README.md +82 -2
- package/docs/api/classes/WSAPIAvatars.md +344 -0
- package/docs/api/classes/WSAPIBonuses.md +271 -0
- package/docs/api/classes/WSAPIClans.md +436 -0
- package/docs/api/classes/WSAPIGamePick.md +710 -0
- package/docs/api/classes/WSAPIGeneral.md +212 -0
- package/docs/api/classes/WSAPIInbox.md +801 -0
- package/docs/api/classes/WSAPIJackpots.md +439 -0
- package/docs/api/classes/WSAPILeaderBoard.md +157 -0
- package/docs/api/classes/WSAPIMiniGames.md +612 -0
- package/docs/api/classes/WSAPIMissions.md +590 -0
- package/docs/api/classes/WSAPIRaffles.md +773 -0
- package/docs/api/classes/WSAPIStore.md +719 -0
- package/docs/api/classes/WSAPITournaments.md +571 -0
- package/docs/api/classes/WSAPIUser.md +637 -0
- package/docs/api/documents/Callbacks.md +162 -0
- package/docs/api/documents/SmarticoObject.md +445 -0
- package/docs/api/documents/Transforms.md +99 -0
- package/docs/api/enumerations/AchievementClaimPeriodTypeId.md +13 -0
- package/docs/api/enumerations/BonusStatus-1.md +11 -6
- package/docs/api/enumerations/BuyStoreItemErrorCode.md +32 -0
- package/docs/api/enumerations/JoinClanErrorCode.md +81 -0
- package/docs/api/enumerations/TournamentRegistrationError.md +12 -0
- package/docs/api/functions/clanTournamentPlayersTransform.md +13 -0
- package/docs/api/interfaces/AvatarCustomized.md +25 -0
- package/docs/api/interfaces/AvatarDefinition.md +94 -0
- package/docs/api/interfaces/AvatarPrompt.md +45 -0
- package/docs/api/interfaces/BonusMetaMap-1.md +4 -1
- package/docs/api/interfaces/BonusTemplateMetaMap-1.md +9 -4
- package/docs/api/interfaces/Clan.md +4 -0
- package/docs/api/interfaces/ClanInfo.md +109 -0
- package/docs/api/interfaces/ClanMember.md +53 -0
- package/docs/api/interfaces/ClanPrizePublicMeta.md +41 -0
- package/docs/api/interfaces/ClanPrizeStructureEntry.md +7 -1
- package/docs/api/interfaces/ClanPublicMeta.md +4 -0
- package/docs/api/interfaces/ClanTournamentPlayerRaw.md +67 -0
- package/docs/api/interfaces/GemsDiamondsLog.md +43 -0
- package/docs/api/interfaces/GetClanInfoResponse.md +61 -0
- package/docs/api/interfaces/GetClanTournamentPlayersResponse.md +81 -0
- package/docs/api/interfaces/GetRaffleWonPrizesRequest.md +59 -0
- package/docs/api/interfaces/GetRaffleWonPrizesResponse.md +95 -0
- package/docs/api/interfaces/InboxMarkMessageAction.md +10 -2
- package/docs/api/interfaces/JackpotDetails.md +14 -15
- package/docs/api/interfaces/JackpotPot.md +9 -6
- package/docs/api/interfaces/LeaderBoardDetailsT.md +14 -8
- package/docs/api/interfaces/LeaderBoardUserT.md +8 -5
- package/docs/api/interfaces/LeaderBoardsRewardsT.md +7 -0
- package/docs/api/interfaces/PointsLog.md +43 -0
- package/docs/api/interfaces/RaffleWonPrize.md +59 -0
- package/docs/api/interfaces/RaffleWonPrizePublicMeta.md +27 -0
- package/docs/api/interfaces/RaffleWonPrizeUser.md +43 -0
- package/docs/api/interfaces/SAWTemplateUI.md +10 -0
- package/docs/api/interfaces/TAchCategory.md +14 -4
- package/docs/api/interfaces/TAvatarCustomized.md +4 -4
- package/docs/api/interfaces/TAvatarDefinition.md +13 -14
- package/docs/api/interfaces/TAvatarPrompt.md +6 -6
- package/docs/api/interfaces/TBonus.md +16 -8
- package/docs/api/interfaces/TBuyStoreItemResult.md +4 -11
- package/docs/api/interfaces/TClaimBonusResult.md +5 -5
- package/docs/api/interfaces/TClan.md +8 -4
- package/docs/api/interfaces/TClanInfo.md +47 -0
- package/docs/api/interfaces/TClanJoinResult.md +11 -1
- package/docs/api/interfaces/TClanTournamentPlayer.md +55 -0
- package/docs/api/interfaces/TClanTournamentPlayersResult.md +27 -0
- package/docs/api/interfaces/TClans.md +3 -1
- package/docs/api/interfaces/TGetTranslations.md +4 -0
- package/docs/api/interfaces/TInboxMessage.md +14 -6
- package/docs/api/interfaces/TInboxMessageBody.md +18 -12
- package/docs/api/interfaces/TLevel.md +17 -20
- package/docs/api/interfaces/TLevelCurrent.md +19 -18
- package/docs/api/interfaces/TMiniGamePlayBatchResult.md +14 -6
- package/docs/api/interfaces/TMiniGamePlayResult.md +9 -4
- package/docs/api/interfaces/TMissionClaimRewardResult.md +6 -3
- package/docs/api/interfaces/TMissionOptInResult.md +6 -3
- package/docs/api/interfaces/TMissionOrBadge.md +5 -4
- package/docs/api/interfaces/TRaffleOptinResponse.md +4 -2
- package/docs/api/interfaces/TSegmentCheckResult.md +10 -0
- package/docs/api/interfaces/TSetAvatarResult.md +3 -3
- package/docs/api/interfaces/TStoreItem.md +11 -1
- package/docs/api/interfaces/TTournament.md +1 -1
- package/docs/api/interfaces/TTournamentDetailed.md +9 -1
- package/docs/api/interfaces/TTournamentRegistrationResult.md +4 -2
- package/docs/api/interfaces/TUICustomSection.md +23 -19
- package/docs/api/interfaces/TUserProfile.md +18 -16
- package/docs/api/interfaces/TransformedRaffleClaimPrizeResponse.md +6 -2
- package/docs/api/interfaces/UserAchievement.md +1 -1
- package/docs/api/interfaces/UserLevelExtraCountersT.md +9 -2
- package/docs/api/type-aliases/ActivityLogEntry.md +3 -0
- package/docs/native/ADDING_METHODS.md +7 -2
- package/docs/native/PROTOCOL.md +337 -0
- package/docs/ui/avatars/UIGuide_getAvatarPrompts.md +100 -0
- package/docs/ui/avatars/UIGuide_getAvatarsCustomized.md +90 -0
- package/docs/ui/avatars/UIGuide_getAvatarsList.md +105 -0
- package/docs/ui/avatars/UIGuide_setAvatar.md +118 -0
- package/docs/ui/bonuses/UIGuide_claimBonus.md +144 -0
- package/docs/ui/bonuses/UIGuide_getBonuses.md +176 -0
- package/docs/ui/clans/UIGuide_getClanInfo.md +153 -0
- package/docs/ui/clans/UIGuide_getClans.md +172 -0
- package/docs/ui/clans/UIGuide_joinClan.md +196 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetActiveRound.md +99 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetActiveRounds.md +76 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetBoard.md +81 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetGameInfo.md +78 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetHistory.md +55 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetRoundInfoForUser.md +71 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetUserInfo.md +64 -0
- package/docs/ui/gamepick/UIGuide_gamePickSubmitSelection.md +103 -0
- package/docs/ui/gamepick/UIGuide_gamePickSubmitSelectionQuiz.md +67 -0
- package/docs/ui/general/UIGuide_getCustomSections.md +137 -0
- package/docs/ui/general/UIGuide_getRelatedItemsForGame.md +140 -0
- package/docs/ui/inbox/UIGuide_deleteInboxMessage.md +135 -0
- package/docs/ui/inbox/UIGuide_getInboxMessageBody.md +133 -0
- package/docs/ui/inbox/UIGuide_getInboxMessages.md +186 -0
- package/docs/ui/inbox/UIGuide_markInboxMessageAsRead.md +122 -0
- package/docs/ui/inbox/UIGuide_markUnmarkInboxMessageAsFavorite.md +84 -0
- package/docs/ui/jackpots/UIGuide_getJackpotEligibleGames.md +73 -0
- package/docs/ui/jackpots/UIGuide_getJackpotWinners.md +83 -0
- package/docs/ui/jackpots/UIGuide_jackpotGet.md +138 -0
- package/docs/ui/jackpots/UIGuide_jackpotOptIn.md +85 -0
- package/docs/ui/jackpots/UIGuide_jackpotOptOut.md +65 -0
- package/docs/ui/leaderboard/UIGuide_getLeaderBoard.md +166 -0
- package/docs/ui/minigames/UIGuide_getMiniGames.md +153 -0
- package/docs/ui/minigames/UIGuide_getMiniGamesHistory.md +90 -0
- package/docs/ui/minigames/UIGuide_playMiniGame.md +150 -0
- package/docs/ui/minigames/UIGuide_playMiniGameBatch.md +128 -0
- package/docs/ui/missions/UIGuide_getAchCategories.md +17 -0
- package/docs/ui/missions/UIGuide_getBadges.md +237 -0
- package/docs/ui/missions/UIGuide_getMissions.md +268 -0
- package/docs/ui/missions/UIGuide_requestMissionClaimReward.md +21 -0
- package/docs/ui/missions/UIGuide_requestMissionOptIn.md +16 -0
- package/docs/ui/raffles/UIGuide_claimRafflePrize.md +99 -0
- package/docs/ui/raffles/UIGuide_getRaffleDrawRun.md +117 -0
- package/docs/ui/raffles/UIGuide_getRaffleDrawRunsHistory.md +92 -0
- package/docs/ui/raffles/UIGuide_getRaffleWonPrizes.md +120 -0
- package/docs/ui/raffles/UIGuide_getRaffles.md +175 -0
- package/docs/ui/raffles/UIGuide_requestRaffleOptin.md +114 -0
- package/docs/ui/store/UIGuide_buyStoreItem.md +133 -0
- package/docs/ui/store/UIGuide_getStoreCategories.md +19 -0
- package/docs/ui/store/UIGuide_getStoreItems.md +264 -0
- package/docs/ui/store/UIGuide_getStorePurchasedItems.md +122 -0
- package/docs/ui/tournaments/UIGuide_getClanTournamentPlayers.md +140 -0
- package/docs/ui/tournaments/UIGuide_getTournamentInstanceInfo.md +265 -0
- package/docs/ui/tournaments/UIGuide_getTournamentsList.md +236 -0
- package/docs/ui/tournaments/UIGuide_registerInTournament.md +156 -0
- package/docs/ui/user/UIGuide_getActivityLog.md +130 -0
- package/docs/ui/user/UIGuide_getLevels.md +167 -0
- package/docs/ui/user/UIGuide_getUserProfile.md +213 -0
- package/package.json +3 -3
- package/scripts/postdoc-cleanup.js +195 -0
- package/src/Base/ClassId.ts +2 -0
- package/src/Jackpots/JackpotDetails.ts +14 -15
- package/src/Jackpots/JackpotPot.ts +10 -6
- package/src/Missions/MissionsUtils.ts +5 -2
- package/src/Raffle/GetRaffleWonPrizesRequest.ts +12 -0
- package/src/Raffle/GetRaffleWonPrizesResponse.ts +56 -0
- package/src/Raffle/index.ts +3 -1
- package/src/SmarticoAPI.ts +14 -1
- package/src/SmarticoLib/index.ts +4 -0
- package/src/Store/BuyStoreItemErrorCode.ts +8 -0
- package/src/Store/StoreItem.ts +1 -0
- package/src/Store/StoreItemPurchased.ts +1 -0
- package/src/Store/StoreItemType.ts +1 -1
- package/src/Tournaments/TournamentRegistrationError.ts +4 -0
- package/src/WSAPI/WSAPI.ts +27 -2007
- package/src/WSAPI/WSAPIAvatars.ts +345 -0
- package/src/WSAPI/WSAPIBase.ts +93 -0
- package/src/WSAPI/WSAPIBonuses.ts +268 -0
- package/src/WSAPI/WSAPIClans.ts +417 -0
- package/src/WSAPI/WSAPIGamePick.ts +667 -0
- package/src/WSAPI/WSAPIGeneral.ts +199 -0
- package/src/WSAPI/WSAPIInbox.ts +711 -0
- package/src/WSAPI/WSAPIJackpots.ts +448 -0
- package/src/WSAPI/WSAPILeaderBoard.ts +154 -0
- package/src/WSAPI/WSAPIMiniGames.ts +597 -0
- package/src/WSAPI/WSAPIMissions.ts +572 -0
- package/src/WSAPI/WSAPIRaffles.ts +703 -0
- package/src/WSAPI/WSAPIStore.ts +732 -0
- package/src/WSAPI/WSAPITournaments.ts +541 -0
- package/src/WSAPI/WSAPITypes.ts +376 -207
- package/src/WSAPI/WSAPIUser.ts +606 -0
- package/tsconfig.json +26 -2
- package/docs/api/classes/WSAPI.md +0 -1927
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# UI Guide — `getLeaderBoard`
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
- Returns the top-20 ranked entries for one period, the current user's
|
|
5
|
+
own rank, and the configured prize table.
|
|
6
|
+
- One call per (period type, current-or-previous) — the SDK caches
|
|
7
|
+
under a single key, so switching periods or current/previous within
|
|
8
|
+
30 s returns stale cached data unless `clearCaches()` is invoked.
|
|
9
|
+
- No subscription, no push refresh. Poll manually if the consumer
|
|
10
|
+
needs live updates during an in-progress period.
|
|
11
|
+
|
|
12
|
+
## List view organization
|
|
13
|
+
|
|
14
|
+
The default Smartico UI renders the leaderboard with three top-level
|
|
15
|
+
tabs inside the page:
|
|
16
|
+
|
|
17
|
+
| Tab | Content |
|
|
18
|
+
|---|---|
|
|
19
|
+
| **Leaders** | The ranked `users[]` list + sticky "me" row |
|
|
20
|
+
| **Prizes** | The `rewards[]` table — one row per paid place |
|
|
21
|
+
| **Rules** | The `rules` HTML (operator-defined terms) |
|
|
22
|
+
|
|
23
|
+
A separate **period selector** sits above the tabs — one tab per
|
|
24
|
+
configured board (DAILY / WEEKLY / MONTHLY). Switching periods
|
|
25
|
+
dispatches a new `getLeaderBoard()` call.
|
|
26
|
+
|
|
27
|
+
A **current ↔ previous** toggle button sits below the Leaders list.
|
|
28
|
+
Label depends on the active period: "Yesterday's winners" /
|
|
29
|
+
"Last week's winners" / "Previous month's winners" / "Today's
|
|
30
|
+
leaders" / "Current standings".
|
|
31
|
+
|
|
32
|
+
## Rank table layout
|
|
33
|
+
|
|
34
|
+
Columns per row (in the Leaders tab):
|
|
35
|
+
|
|
36
|
+
| Column | Source | Notes |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| Position | `user.position` | Server-computed DENSE_RANK. Show as `01`, `02`, … `20`. |
|
|
39
|
+
| Avatar | `user.avatar_url` | Hide via operator config `hide_avatars_leaderboards` if applicable. |
|
|
40
|
+
| Username | `user.public_username` | |
|
|
41
|
+
| Points | `user.points` | Operator config `leaderboard_hide_other_points` may suppress points for everyone except the current user. |
|
|
42
|
+
| Level badge | (Drives from separate `getCurrentLevel` lookup, not on this type) | Operator config `leaderboard_hide_levels` may suppress. |
|
|
43
|
+
|
|
44
|
+
**Top-3 podium styling**: apply distinct CSS classes (`place-1`,
|
|
45
|
+
`place-2`, `place-3`) to rows with `position <= 3` (and
|
|
46
|
+
`position !== -1`). The default Smartico UI uses CSS-only treatment
|
|
47
|
+
— no podium banner or 1st/2nd/3rd icons.
|
|
48
|
+
|
|
49
|
+
**Desktop padding**: when `users.length < 8`, the default UI pads the
|
|
50
|
+
list height with a vertical spacer so the card height stays stable
|
|
51
|
+
across periods. Skip this on mobile.
|
|
52
|
+
|
|
53
|
+
## "Me" sticky row
|
|
54
|
+
|
|
55
|
+
`board.me` is the current authenticated user's entry. Render rules:
|
|
56
|
+
|
|
57
|
+
- **Visitor mode**: `me` is `undefined` — skip the sticky row.
|
|
58
|
+
- **`me.position === -1`**: the user has not yet accumulated points
|
|
59
|
+
this period (or is otherwise unranked). Show a friendly state:
|
|
60
|
+
`"You're unranked — earn points to climb the board"`.
|
|
61
|
+
- **`me.position > 0` AND visible in `users[]` (top 20)**: highlight
|
|
62
|
+
the matching row in the main list (CSS class). The default
|
|
63
|
+
Smartico UI also keeps a sticky bottom row for consistency.
|
|
64
|
+
- **`me.position > 20`**: pin the sticky bottom row with the user's
|
|
65
|
+
rank, avatar, username, and points. The default Smartico UI shows
|
|
66
|
+
this on desktop only (mobile uses a stub spacer to keep layout
|
|
67
|
+
height stable but does not render the sticky row).
|
|
68
|
+
|
|
69
|
+
## Prize table (Prizes tab)
|
|
70
|
+
|
|
71
|
+
Render `rewards[]` as a two-column table:
|
|
72
|
+
|
|
73
|
+
| Column | Source |
|
|
74
|
+
|---|---|
|
|
75
|
+
| Place | `reward.place` (e.g. `1`, `2`, `3`) formatted as "1st place", "2nd place", etc. — use the locale's plural-ordinal helper for proper rendering. |
|
|
76
|
+
| Prize | `reward.points` formatted with locale separators + the brand's points unit (e.g. `"100 points"`, `"1,000 pts"`). |
|
|
77
|
+
|
|
78
|
+
Show in order — the first array element is place 1.
|
|
79
|
+
|
|
80
|
+
The default Smartico UI does NOT inline rewards on the main leaders
|
|
81
|
+
list (only in the dedicated Prizes tab). Custom UIs may want to
|
|
82
|
+
inline a hint on the top-3 rows.
|
|
83
|
+
|
|
84
|
+
## Rules tab
|
|
85
|
+
|
|
86
|
+
Render `board.rules` as sanitized HTML. The default Smartico UI uses
|
|
87
|
+
`dangerouslySetInnerHTML` — **sanitize before injecting** to
|
|
88
|
+
prevent XSS if your product surface is exposed to untrusted operator
|
|
89
|
+
content.
|
|
90
|
+
|
|
91
|
+
## Period selector (current ↔ previous)
|
|
92
|
+
|
|
93
|
+
When the user switches between current and previous period:
|
|
94
|
+
|
|
95
|
+
1. Call `clearCaches()` to bust the shared OCache key
|
|
96
|
+
(otherwise the second call returns stale data within 30 s).
|
|
97
|
+
2. Call `getLeaderBoard(periodType, getPreviousPeriod)` with the new
|
|
98
|
+
`getPreviousPeriod` value.
|
|
99
|
+
3. Replace the rendered data.
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
const onTogglePrevious = async (showPrevious: boolean) => {
|
|
103
|
+
await window._smartico.api.clearCaches();
|
|
104
|
+
const board = await window._smartico.api.getLeaderBoard(
|
|
105
|
+
activePeriodType,
|
|
106
|
+
showPrevious,
|
|
107
|
+
);
|
|
108
|
+
console.log('[smartico] switched to', showPrevious ? 'previous' : 'current', 'period — re-render with this board:', board);
|
|
109
|
+
};
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Same pattern applies when switching between period types
|
|
113
|
+
(`DAILY` → `WEEKLY` → `MONTHLY`).
|
|
114
|
+
|
|
115
|
+
## Status-specific visual treatments
|
|
116
|
+
|
|
117
|
+
- **Current period**: full-color rendering; live point counts.
|
|
118
|
+
- **Previous period** (`getPreviousPeriod: true`): identical
|
|
119
|
+
rendering — the default Smartico UI does not visually
|
|
120
|
+
differentiate. Custom UIs may want to apply subtle desaturation
|
|
121
|
+
or an "ENDED" pill to signal that the rankings are final.
|
|
122
|
+
- **Unranked `me`** (`position === -1`): friendly "earn points to
|
|
123
|
+
enter the board" copy in the sticky panel.
|
|
124
|
+
|
|
125
|
+
## Empty / loading / error states
|
|
126
|
+
|
|
127
|
+
- **Loading (cold fetch)**: render a skeleton table (8 placeholder
|
|
128
|
+
rows) sized to the eventual layout. The default Smartico UI uses
|
|
129
|
+
a `Loader` spinner.
|
|
130
|
+
- **Empty `users[]`**: render a Lottie / static illustration with
|
|
131
|
+
copy like "No Leaders Yet". Common early in a fresh period.
|
|
132
|
+
- **`board === undefined`** (no board configured for this period):
|
|
133
|
+
hide the leaderboard surface entirely or surface a neutral
|
|
134
|
+
"Leaderboard not available" message.
|
|
135
|
+
- **Error**: keep the prior list if any; show a non-blocking error
|
|
136
|
+
banner; retry on the next user-driven action.
|
|
137
|
+
|
|
138
|
+
## Animations / transitions
|
|
139
|
+
|
|
140
|
+
- **Initial fade-in**: rows fade in on first paint.
|
|
141
|
+
- **Rank change between fetches**: the default Smartico UI does NOT
|
|
142
|
+
animate rank changes — rows re-render in-place. Custom UIs that
|
|
143
|
+
poll may want to diff snapshots and apply a FLIP animation to
|
|
144
|
+
highlight position movement.
|
|
145
|
+
- **Period switch**: cross-fade table contents (~150 ms ease-out).
|
|
146
|
+
|
|
147
|
+
## Mobile vs desktop
|
|
148
|
+
|
|
149
|
+
- **Period tab strip**: desktop uses a standard tab component;
|
|
150
|
+
mobile uses a scrollable custom-styled strip.
|
|
151
|
+
- **Sticky "me" row**: desktop renders it; mobile renders only a
|
|
152
|
+
stub spacer (no sticky row, to save vertical space).
|
|
153
|
+
- **Desktop padding**: list height padded to ≥ 8 rows; mobile does
|
|
154
|
+
not pad.
|
|
155
|
+
|
|
156
|
+
## Performance
|
|
157
|
+
|
|
158
|
+
- The 30 s cache deduplicates rapid refetches, but the single-key
|
|
159
|
+
design means switching periods within the window returns stale
|
|
160
|
+
data. `clearCaches()` is the only way to force a fresh fetch
|
|
161
|
+
before the TTL expires.
|
|
162
|
+
- For live polling during an in-progress period, ~30 s cadence is
|
|
163
|
+
appropriate (matching the cache TTL — additional polls within
|
|
164
|
+
the window are free).
|
|
165
|
+
- The leaderboard list is small (max 20 rows + 1 me row); no
|
|
166
|
+
virtualization needed.
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# UI Guide — `getMiniGames`
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
- Returns the operator-configured mini-game templates ("SAW" =
|
|
5
|
+
Spin And Win — covers wheel, scratch card, lootbox, gift box,
|
|
6
|
+
treasure hunt, plinko, coin flip, quiz, and several other formats).
|
|
7
|
+
- Templates carry per-user state (`spin_count`,
|
|
8
|
+
`next_available_spin_ts`, `jackpot_current`) — these update via
|
|
9
|
+
`onUpdate` after any spin / acknowledge / server-pushed grant.
|
|
10
|
+
- The list is NOT filtered by spin availability — apply
|
|
11
|
+
`visibile_when_can_spin` client-side to hide templates the user
|
|
12
|
+
can't currently play.
|
|
13
|
+
- Visitor mode supported.
|
|
14
|
+
|
|
15
|
+
## List view organization
|
|
16
|
+
|
|
17
|
+
The default Smartico UI presents mini-game templates as a **flat
|
|
18
|
+
list** (no per-game-type tabs). Templates of different
|
|
19
|
+
`saw_game_type` values appear together, sorted by the operator's
|
|
20
|
+
configured priority.
|
|
21
|
+
|
|
22
|
+
Client-side visibility filter:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
const visible = games.filter(g =>
|
|
26
|
+
!g.visibile_when_can_spin || (g.spin_count && g.spin_count > 0)
|
|
27
|
+
);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`visibile_when_can_spin` is operator-configured per template. When
|
|
31
|
+
`true`, the template should be hidden from the lobby until the user
|
|
32
|
+
has spins (or balance for paid templates).
|
|
33
|
+
|
|
34
|
+
## Item card
|
|
35
|
+
|
|
36
|
+
Fields rendered per game card:
|
|
37
|
+
|
|
38
|
+
| Field | Source | Notes |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| Thumbnail | `thumbnail` (256×256 px source from template UI definition) | Render at 1:1 aspect ratio. |
|
|
41
|
+
| Name | `name` | Server-side `{{jackpot}}` substitution inlines the live jackpot value. |
|
|
42
|
+
| Description | `description` | Short marketing tagline. |
|
|
43
|
+
| Game-type pill | `saw_game_type` | E.g. "Spin", "Scratch", "Lootbox" — translate the enum value to a display label. |
|
|
44
|
+
| Spin-count badge | `spin_count` (only when `saw_buyin_type === 'spins'`) | Show as a chip on the card. |
|
|
45
|
+
| Buy-in indicator | `saw_buyin_type` + `buyin_cost_points` / `_gems` / `_diamonds` | "Free", "100 pts", "5 gems", etc. |
|
|
46
|
+
| Jackpot display | `jackpot_current` + `jackpot_symbol` | Only when `jackpot_add_on_attempt > 0`. Animate the value count-up when it changes via push. |
|
|
47
|
+
| Promo image | `promo_image` (500×240 px) | Optional larger artwork for featured / hero rendering. |
|
|
48
|
+
| Countdown | `next_available_spin_ts` (epoch ms) | Show "Available in HH:MM:SS" when set and in the future. |
|
|
49
|
+
| Play CTA | (derived) | See "Action button decision matrix". |
|
|
50
|
+
|
|
51
|
+
**Whole-card click target**: opens the detail / play view for that
|
|
52
|
+
template.
|
|
53
|
+
|
|
54
|
+
## Detail / play view per game type
|
|
55
|
+
|
|
56
|
+
The `saw_game_type` value drives the renderer:
|
|
57
|
+
|
|
58
|
+
| `SAWGameType` | Renderer | Behavior |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| `SpinAWheel` (1) | Canvas wheel; spin to a stop position on a 360° track | ~15 s animation; bezier ease-out |
|
|
61
|
+
| `ScratchCard` (2) | Canvas scratch-off reveal | User drags / taps to scratch; prize revealed underneath |
|
|
62
|
+
| `MatchX` (3) | Score-prediction UI (separate games server) | DON'T call `playMiniGame` — the games server fires the spin internally |
|
|
63
|
+
| `GiftBox` (4) | Tap-to-reveal gift boxes | Bubbles layout; tap chooses a box |
|
|
64
|
+
| `PrizeDrop` (5) | None (push-only) | Don't call `playMiniGame`; prizes arrive via push |
|
|
65
|
+
| `Quiz` (6) | Q&A UI (separate games server) | DON'T call `playMiniGame` |
|
|
66
|
+
| `LootboxWeekdays` (7) | Pick-N-from-grid | Grid layout or vertical-map (`game_layout` determines) |
|
|
67
|
+
| `LootboxCalendarDays` (8) | Pick-N-from-grid | Same; pool filtered to current calendar date |
|
|
68
|
+
| `TreasureHunt` (9) | Map exploration | `steps_to_finish_game` cells |
|
|
69
|
+
| `Voyager` (10) | Journey UI | `min_steps_to_finish_game` floor |
|
|
70
|
+
| `Plinko` (11) | Physics ball-drop | Animated drop through pegs |
|
|
71
|
+
| `CoinFlip` (12) | Binary coin flip | Heads-or-tails reveal |
|
|
72
|
+
|
|
73
|
+
The default Smartico UI uses a lazy-loaded component dispatcher
|
|
74
|
+
keyed on `saw_game_type`. For custom UIs, render the matching
|
|
75
|
+
component per game type — they share the same `playMiniGame`
|
|
76
|
+
trigger (except `PrizeDrop`, `MatchX`, `Quiz` as noted).
|
|
77
|
+
|
|
78
|
+
## Action button decision matrix
|
|
79
|
+
|
|
80
|
+
CTA on the card / detail view (evaluate in priority order):
|
|
81
|
+
|
|
82
|
+
| Condition | CTA | Notes |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| `next_available_spin_ts > now` | "Available in HH:MM:SS" (countdown, disabled) | Countdown to next allowed spin |
|
|
85
|
+
| `saw_buyin_type === 'spins'` AND `spin_count === 0` | "No spins" (disabled) | Show `no_attempts_message` from the template |
|
|
86
|
+
| Insufficient balance (paid templates) | "Not enough {currency}" (disabled) | Compare `buyin_cost_*` against `getUserProfile` balance |
|
|
87
|
+
| User not in segment / template expired | (hidden — server filtered) | Template typically excluded by server visibility |
|
|
88
|
+
| Default (playable) | "Play" / "Spin" | Enabled — invokes `playMiniGame` |
|
|
89
|
+
|
|
90
|
+
`over_limit_message` and `no_attempts_message` are operator-supplied
|
|
91
|
+
messages; surface them under the disabled CTA rather than a generic
|
|
92
|
+
error.
|
|
93
|
+
|
|
94
|
+
## Image / asset specs
|
|
95
|
+
|
|
96
|
+
| Field | Aspect | Notes |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| `thumbnail` | 1:1 (square), 256×256 px | Card icon |
|
|
99
|
+
| `promo_image` | ~2:1 wide, 500×240 px | Featured / hero artwork |
|
|
100
|
+
| `prizes[].icon` | 1:1 (square) | Per-prize icon |
|
|
101
|
+
|
|
102
|
+
## Status-specific visual treatments
|
|
103
|
+
|
|
104
|
+
- **Playable**: full-color card; Play CTA enabled.
|
|
105
|
+
- **No spins / insufficient balance**: card desaturated or dimmed;
|
|
106
|
+
CTA disabled with operator message.
|
|
107
|
+
- **Countdown**: card normal; CTA replaced with countdown timer
|
|
108
|
+
(update every second).
|
|
109
|
+
- **`visibile_when_can_spin` filter**: card hidden entirely.
|
|
110
|
+
- **Jackpot increasing live**: pulse / glow the jackpot value when
|
|
111
|
+
it ticks up via push (detect by diffing previous snapshot in
|
|
112
|
+
`onUpdate`).
|
|
113
|
+
|
|
114
|
+
## Countdown / timing format
|
|
115
|
+
|
|
116
|
+
`next_available_spin_ts` — epoch ms — drives the countdown. Use:
|
|
117
|
+
|
|
118
|
+
- `> 1 hour` → `"HH:MM"` ("01:23")
|
|
119
|
+
- `1 minute – 1 hour` → `"MM:SS"`
|
|
120
|
+
- `< 1 minute` → `"0:SS"`, ticking down per second
|
|
121
|
+
|
|
122
|
+
Update once per second while visible. Hide the countdown and show
|
|
123
|
+
the Play CTA when the timestamp passes.
|
|
124
|
+
|
|
125
|
+
## Empty / loading / error states
|
|
126
|
+
|
|
127
|
+
- **Loading**: skeleton grid (3–6 placeholder cards).
|
|
128
|
+
- **Empty**: `[]` means no templates configured. Render a neutral
|
|
129
|
+
empty-state.
|
|
130
|
+
- **Error**: keep prior list if any; show non-blocking error banner.
|
|
131
|
+
|
|
132
|
+
## Animations / transitions
|
|
133
|
+
|
|
134
|
+
- **Card entry**: fade-in stagger.
|
|
135
|
+
- **Jackpot tick**: count-up animation when value increases via
|
|
136
|
+
push (detected by diffing prior snapshot in `onUpdate`).
|
|
137
|
+
- **Spin-count flash**: highlight the spin-count badge when it
|
|
138
|
+
changes (campaign grant, prize win that grants spins).
|
|
139
|
+
|
|
140
|
+
## Mobile vs desktop
|
|
141
|
+
|
|
142
|
+
- **Card density**: desktop 3–4 columns; mobile 2 columns
|
|
143
|
+
(sometimes 1 for large promo cards).
|
|
144
|
+
- **Detail view**: desktop centered modal; mobile full-screen.
|
|
145
|
+
- **Game canvas**: scales with viewport.
|
|
146
|
+
|
|
147
|
+
## Performance
|
|
148
|
+
|
|
149
|
+
- 30 s cache deduplicates rapid refetches.
|
|
150
|
+
- Diff snapshots in `onUpdate` to detect jackpot / spin-count
|
|
151
|
+
changes for animations.
|
|
152
|
+
- Lazy-load game-type renderers (each game type is a substantial
|
|
153
|
+
component bundle).
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# UI Guide — `getMiniGamesHistory`
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
- Paginated, newest-first list of past spins. Each row carries the
|
|
5
|
+
won prize ID, the spin's `client_request_id`, an `is_claimed`
|
|
6
|
+
flag, and the template that produced it.
|
|
7
|
+
- Use to power a "My prizes" / win-history surface, and to surface
|
|
8
|
+
Claim CTAs on unacknowledged spins (`is_claimed === false`).
|
|
9
|
+
- 30 s cache. No subscription / push refresh.
|
|
10
|
+
|
|
11
|
+
## List view organization
|
|
12
|
+
|
|
13
|
+
Single flat list, server-sorted newest-first by spin creation
|
|
14
|
+
timestamp. No client-side re-sort required. No tabs in the default
|
|
15
|
+
Smartico UI — but a custom UI might tab by:
|
|
16
|
+
|
|
17
|
+
- "Claimed" vs "Unclaimed" (filter by `is_claimed`)
|
|
18
|
+
- Per-template (use `saw_template_id` filter argument)
|
|
19
|
+
|
|
20
|
+
## Item card / row
|
|
21
|
+
|
|
22
|
+
Fields rendered per row:
|
|
23
|
+
|
|
24
|
+
| Field | Source | Notes |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| Template icon | `template.thumbnail` (or similar) | 1:1 |
|
|
27
|
+
| Prize name | Look up `template.prizes[i]` by `saw_prize_id` | Display the prize's `name`. |
|
|
28
|
+
| Prize amount | `template.prizes[i].prize_value` or `prize_amount` | E.g. "100 points" |
|
|
29
|
+
| Spin date | `create_date_ts` | Format as user-local relative time ("2h ago") or short date |
|
|
30
|
+
| Claim status | `is_claimed` | Show check-mark when true; "Pending claim" CTA when false |
|
|
31
|
+
| Acknowledge date | `acknowledge_date_ts` | Only when `is_claimed === true` |
|
|
32
|
+
|
|
33
|
+
**Click target**: typically opens the template detail / play view
|
|
34
|
+
(to "play again" or read prize terms). Optional.
|
|
35
|
+
|
|
36
|
+
## Action button — Claim CTA on unacknowledged rows
|
|
37
|
+
|
|
38
|
+
When `is_claimed === false`, render a "Claim" button:
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
const onClaimHistoryRow = async (row: TSawHistory) => {
|
|
42
|
+
await window._smartico.api.miniGameWinAcknowledgeRequest(row.client_request_id);
|
|
43
|
+
console.log('[smartico] re-acknowledged spin — refresh history list to flip is_claimed');
|
|
44
|
+
const refreshed = await window._smartico.api.getMiniGamesHistory({ limit: 20 });
|
|
45
|
+
// ...
|
|
46
|
+
};
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Note: a server-side fallback job auto-acknowledges stale spins
|
|
50
|
+
every ~60 seconds, so unclaimed rows usually self-resolve without
|
|
51
|
+
explicit user action. The manual Claim CTA is for instant recovery
|
|
52
|
+
when the user is actively viewing the history surface.
|
|
53
|
+
|
|
54
|
+
## Pagination
|
|
55
|
+
|
|
56
|
+
`limit` defaults to 20; `offset` defaults to 0. For load-more
|
|
57
|
+
pagination, advance `offset` by the prior page size. Detect end of
|
|
58
|
+
list when the returned array length is less than `limit`.
|
|
59
|
+
|
|
60
|
+
`saw_template_id` filter scopes to a single template's history —
|
|
61
|
+
useful for a per-game "previous wins" panel.
|
|
62
|
+
|
|
63
|
+
## Empty / loading / error states
|
|
64
|
+
|
|
65
|
+
- **Loading (cold fetch)**: skeleton list (3–5 placeholder rows).
|
|
66
|
+
- **Empty**: "No mini-game history yet" with optional illustration.
|
|
67
|
+
- **Empty (filtered)**: "No history for this game".
|
|
68
|
+
- **Error**: keep prior list if any; non-blocking error banner.
|
|
69
|
+
|
|
70
|
+
## Refresh
|
|
71
|
+
|
|
72
|
+
No subscription / push refresh. Re-call after:
|
|
73
|
+
|
|
74
|
+
- A successful `playMiniGame` / `playMiniGameBatch` to surface the
|
|
75
|
+
new row at the top.
|
|
76
|
+
- A successful `miniGameWinAcknowledgeRequest` to flip `is_claimed`.
|
|
77
|
+
|
|
78
|
+
The 30 s cache deduplicates rapid refetches.
|
|
79
|
+
|
|
80
|
+
## Mobile vs desktop
|
|
81
|
+
|
|
82
|
+
- **Row density**: identical on both.
|
|
83
|
+
- **Claim CTA**: inline button on each row (both platforms).
|
|
84
|
+
|
|
85
|
+
## Performance
|
|
86
|
+
|
|
87
|
+
- The 30 s cache helps when the user navigates between tabs and
|
|
88
|
+
re-renders the history.
|
|
89
|
+
- Don't over-fetch — limit to 20–50 rows per page.
|
|
90
|
+
- Filter by `saw_template_id` when the surface is per-template.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# UI Guide — `playMiniGame`
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
- Action-focused mutation. User clicks "Play" / "Spin" on a mini-
|
|
5
|
+
game card; the server runs the prize selection and returns the
|
|
6
|
+
won prize.
|
|
7
|
+
- Auto-acknowledges on success (fire-and-forget) — most consumers
|
|
8
|
+
don't need to handle acknowledge manually.
|
|
9
|
+
- The SDK does NOT prevent double-clicks at the public API level;
|
|
10
|
+
guard the call site.
|
|
11
|
+
|
|
12
|
+
## Loading state — the game animation IS the loading state
|
|
13
|
+
|
|
14
|
+
For most mini-game types, the **game animation itself serves as the
|
|
15
|
+
loading state**. Start the animation immediately on click (before
|
|
16
|
+
the response arrives); the server response arrives during the
|
|
17
|
+
animation; sync the final reveal to land at the animation's end
|
|
18
|
+
position.
|
|
19
|
+
|
|
20
|
+
Typical animation durations by game type:
|
|
21
|
+
|
|
22
|
+
- Wheel: ~15 s (long enough to mask any reasonable latency)
|
|
23
|
+
- Scratch card: user-driven (no time pressure)
|
|
24
|
+
- Lootbox: ~3 s (open animation)
|
|
25
|
+
- Gift box: ~2 s (reveal)
|
|
26
|
+
- Treasure hunt / Voyager / Plinko / Coin flip: ~2–5 s
|
|
27
|
+
- Match X / Quiz: not applicable (separate game server)
|
|
28
|
+
|
|
29
|
+
If the server response arrives late (network slow), pause the
|
|
30
|
+
animation or hold at a "still spinning" loop until the result
|
|
31
|
+
lands.
|
|
32
|
+
|
|
33
|
+
## Idempotency guard
|
|
34
|
+
|
|
35
|
+
The SDK does NOT prevent double-clicks. Guard the call site:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
const [playing, setPlaying] = useState(false);
|
|
39
|
+
|
|
40
|
+
const onPlay = async () => {
|
|
41
|
+
if (playing) return;
|
|
42
|
+
setPlaying(true);
|
|
43
|
+
startAnimation();
|
|
44
|
+
const r = await window._smartico.api.playMiniGame(template_id);
|
|
45
|
+
syncAnimationToResult(r);
|
|
46
|
+
setPlaying(false);
|
|
47
|
+
handleResult(r);
|
|
48
|
+
};
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Don't skip this guard** — a double-tap deducts the buy-in twice.
|
|
52
|
+
The server has its own per-user-per-template lock that serialises
|
|
53
|
+
concurrent requests, but it still processes both sequentially.
|
|
54
|
+
|
|
55
|
+
## Action button decision matrix
|
|
56
|
+
|
|
57
|
+
UI behavior per `err_code`:
|
|
58
|
+
|
|
59
|
+
| `err_code` | Action |
|
|
60
|
+
|---|---|
|
|
61
|
+
| `0` (success) | Animate the result; show acknowledge modal per `template.acknowledge_type` (see below); refresh balance widgets. |
|
|
62
|
+
| `40001` (no spins) | Disable Play; show `no_attempts_message` from the template. |
|
|
63
|
+
| `40002` (prize pool empty) | Disable Play; show "All prizes claimed for now". |
|
|
64
|
+
| `40003` (insufficient points) | Disable Play; show insufficient-balance UI naming the deficit. |
|
|
65
|
+
| `40004` (max spins reached) | Show countdown to next available spin. `first_spin_in_period` is on the batch result type; for the single-play path, derive next-available from `template.next_available_spin_ts`. |
|
|
66
|
+
| `40007` (template not active) | Disable / hide the template. |
|
|
67
|
+
| `40009` (segment mismatch / lootbox empty for today) | Hide the template OR show "Not available today" for lootboxes. |
|
|
68
|
+
| `40011` / `40012` (insufficient gems / diamonds) | Same as `40003` for the matching currency. |
|
|
69
|
+
| `-40001` (visitor stopped) | Silently end the game; no prize modal. Default Smartico UI doesn't surface this as an error. |
|
|
70
|
+
| Other non-zero | Show generic error toast. Allow retry. |
|
|
71
|
+
|
|
72
|
+
## Prize reveal modals
|
|
73
|
+
|
|
74
|
+
`template.acknowledge_type` controls the post-animation modal:
|
|
75
|
+
|
|
76
|
+
| Value | Behavior |
|
|
77
|
+
|---|---|
|
|
78
|
+
| `Silent` (1) | No modal; auto-acknowledge fires silently. |
|
|
79
|
+
| `QuickMessage` (2) | Toast popup; auto-closes after ~5 s; auto-acknowledge fires. |
|
|
80
|
+
| `FullMessage` (3) | Full-screen modal; user dismisses; auto-acknowledge fires. |
|
|
81
|
+
| `ExplicitAcknowledge` (4) | Modal with explicit "Claim" CTA; acknowledge sends only on tap. Use this for high-value or lootbox-style rewards. |
|
|
82
|
+
|
|
83
|
+
For `ExplicitAcknowledge`, suppress the SDK's auto-acknowledge by
|
|
84
|
+
NOT using this method's `playMiniGame` directly — call the
|
|
85
|
+
acknowledge via [`miniGameWinAcknowledgeRequest`](../../api/classes/WSAPIMiniGames.md#minigamewinacknowledgerequest)
|
|
86
|
+
when the user taps Claim. (The SDK still auto-fires the
|
|
87
|
+
acknowledge from `playMiniGame`, but the visual gate is still
|
|
88
|
+
meaningful.)
|
|
89
|
+
|
|
90
|
+
Modal contents per prize:
|
|
91
|
+
|
|
92
|
+
- Icon: `prize.icon` (1:1)
|
|
93
|
+
- Title: `prize.name`
|
|
94
|
+
- Message: `prize.aknowledge_message` (note the typo in the field
|
|
95
|
+
name — `aknowledge` not `acknowledge`)
|
|
96
|
+
- CTA: `prize.acknowledge_action_title` with action
|
|
97
|
+
`prize.acknowledge_dp` (pass through `_smartico.dp()` for safe
|
|
98
|
+
execution)
|
|
99
|
+
- Optional additional CTA: `prize.acknowledge_action_title_additional`
|
|
100
|
+
+ `prize.acknowledge_dp_additional`
|
|
101
|
+
|
|
102
|
+
## "No prize" handling
|
|
103
|
+
|
|
104
|
+
When the won prize has `prize_type === 'no-prize'`, the user has
|
|
105
|
+
"lost" — the buy-in was still deducted. Show a friendly "Better
|
|
106
|
+
luck next time" treatment rather than a celebration. The operator
|
|
107
|
+
configures these slots intentionally — they're not errors.
|
|
108
|
+
|
|
109
|
+
## Refresh after success
|
|
110
|
+
|
|
111
|
+
The SDK auto-refreshes the templates cache after every spin. The
|
|
112
|
+
`onUpdate` callback registered via `getMiniGames` fires with the
|
|
113
|
+
updated array — observe the new `spin_count`, `jackpot_current`,
|
|
114
|
+
and `next_available_spin_ts`.
|
|
115
|
+
|
|
116
|
+
The user's balance updates (points / gems / diamonds credited from
|
|
117
|
+
prize wins) flow via
|
|
118
|
+
[`getUserProfile`](../../api/classes/WSAPIUser.md#getuserprofile)'s
|
|
119
|
+
`props_change` channel.
|
|
120
|
+
|
|
121
|
+
## Per-game-type animation nuances
|
|
122
|
+
|
|
123
|
+
| Game type | Animation pattern |
|
|
124
|
+
|---|---|
|
|
125
|
+
| Spin a Wheel | Start spinning on click; sync the final position to land on the won prize sector at ~15 s. Cubic-bezier deceleration. |
|
|
126
|
+
| Scratch Card | User-driven; the won prize is hidden under the scratch layer. Reveal at scratch completion threshold (~60% scratched). |
|
|
127
|
+
| Gift Box | All boxes shake on play; user taps to "open" their chosen box; the won prize appears in the tapped box. |
|
|
128
|
+
| Lootbox (Weekdays / CalendarDays) | Grid layout; user picks N from grid; pre-determined positions reveal the won prize. |
|
|
129
|
+
| Treasure Hunt | Multi-step map; each play advances one step; final step reveals the prize. |
|
|
130
|
+
| Voyager | Journey-style multi-step. |
|
|
131
|
+
| Plinko | Ball drops through pegs; landing position determines the won prize. Physics-driven path or pre-computed to match server result. |
|
|
132
|
+
| Coin Flip | Binary heads/tails reveal. |
|
|
133
|
+
|
|
134
|
+
The default Smartico UI ships components for all these — for
|
|
135
|
+
custom UIs, the consumer is responsible for the animation per type.
|
|
136
|
+
|
|
137
|
+
## Mobile vs desktop
|
|
138
|
+
|
|
139
|
+
- **Game canvas**: scales with viewport.
|
|
140
|
+
- **Modal**: desktop centered with backdrop; mobile full-screen.
|
|
141
|
+
- **Touch targets**: mobile needs 44×44 px minimum for game
|
|
142
|
+
interactions.
|
|
143
|
+
|
|
144
|
+
## Performance
|
|
145
|
+
|
|
146
|
+
- Single round-trip per spin.
|
|
147
|
+
- Pre-load game animation assets at template card render time so
|
|
148
|
+
the animation starts immediately on click.
|
|
149
|
+
- The `onUpdate` callback fires after each spin — use it to refresh
|
|
150
|
+
the card's spin_count badge.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# UI Guide — `playMiniGameBatch`
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
- Plays the same template `spin_count` times in a single
|
|
5
|
+
round-trip. Returns an array of per-spin results.
|
|
6
|
+
- Each result is independent — the server does NOT roll back on
|
|
7
|
+
partial failures.
|
|
8
|
+
- Use for "Spin N times" / "Open N lootboxes" affordances.
|
|
9
|
+
|
|
10
|
+
## Result shape note
|
|
11
|
+
|
|
12
|
+
`TMiniGamePlayBatchResult` uses **camelCase** `errCode` /
|
|
13
|
+
`errMessage` (differs from `TMiniGamePlayResult` which uses
|
|
14
|
+
`err_code` / `err_message`). Branch on the camelCase keys.
|
|
15
|
+
|
|
16
|
+
## Loading state
|
|
17
|
+
|
|
18
|
+
For multi-spin batches, the UI needs to choose between:
|
|
19
|
+
|
|
20
|
+
1. **Sequential animation** — animate each spin one at a time using
|
|
21
|
+
the response array as the "script". The default Smartico UI
|
|
22
|
+
uses this pattern for multi-spin lootboxes. ~2-3 s per spin.
|
|
23
|
+
2. **Bulk reveal** — animate all spins in parallel (faster but
|
|
24
|
+
visually busy). Suitable for "open 10 lootboxes" power-user
|
|
25
|
+
affordances.
|
|
26
|
+
3. **Skip animation** — show a results table immediately.
|
|
27
|
+
Suitable for "auto-spin N" power affordances.
|
|
28
|
+
|
|
29
|
+
Set an in-flight flag on click; clear it when the response lands
|
|
30
|
+
AND any animation completes.
|
|
31
|
+
|
|
32
|
+
## Idempotency guard
|
|
33
|
+
|
|
34
|
+
Same as `playMiniGame` — guard against double-clicks. A
|
|
35
|
+
double-tap sends two batches, each deducting `spin_count` worth of
|
|
36
|
+
buy-in.
|
|
37
|
+
|
|
38
|
+
## Per-spin result handling
|
|
39
|
+
|
|
40
|
+
Iterate `results[]` and handle each result independently:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
for (const [i, r] of results.entries()) {
|
|
44
|
+
if (r.errCode === 0) {
|
|
45
|
+
const prize = template.prizes.find(p => p.id === r.saw_prize_id);
|
|
46
|
+
if (prize?.prize_type === 'no-prize') {
|
|
47
|
+
console.log('[smartico] spin', i, 'lost');
|
|
48
|
+
} else {
|
|
49
|
+
console.log('[smartico] spin', i, 'won:', prize?.name);
|
|
50
|
+
}
|
|
51
|
+
} else if (r.errCode === 40001) {
|
|
52
|
+
console.log('[smartico] spin', i, '— no spins left; abort the rest of the animation early');
|
|
53
|
+
break;
|
|
54
|
+
} else if (r.errCode === 40004) {
|
|
55
|
+
const msTillNext = template.max_spins_period_ms! - (Date.now() - (r.first_spin_in_period ?? 0));
|
|
56
|
+
console.log('[smartico] spin', i, 'capped — ' + Math.ceil(msTillNext / 1000) + 's until next');
|
|
57
|
+
} else {
|
|
58
|
+
console.error('[smartico] spin', i, 'failed:', r.errMessage);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Partial-success handling
|
|
64
|
+
|
|
65
|
+
Common scenario: user requests 5 spins but only has 3 spin
|
|
66
|
+
tickets. Results[0–2] succeed; results[3–4] fail with
|
|
67
|
+
`SAW_NO_SPINS`.
|
|
68
|
+
|
|
69
|
+
UI options:
|
|
70
|
+
|
|
71
|
+
- Show all 3 successful prizes; then surface a "You ran out of
|
|
72
|
+
spins" message for the remaining 2 attempts.
|
|
73
|
+
- Or skip the failed animations entirely and only render the
|
|
74
|
+
successful results.
|
|
75
|
+
|
|
76
|
+
The default Smartico UI shows successful results then a brief
|
|
77
|
+
"No more spins" toast.
|
|
78
|
+
|
|
79
|
+
## `first_spin_in_period` for cooldown UX
|
|
80
|
+
|
|
81
|
+
When any result has `errCode === SAW_FAILED_MAX_SPINS_REACHED`
|
|
82
|
+
(40004), the result's `first_spin_in_period` field carries the
|
|
83
|
+
epoch ms of the user's first spin in the current cooldown
|
|
84
|
+
period. Compute the countdown:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
const msTillNext = template.max_spins_period_ms! - (Date.now() - r.first_spin_in_period!);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Show "Available in HH:MM:SS" countdown on the disabled Play CTA.
|
|
91
|
+
|
|
92
|
+
## Jackpot wins in batches
|
|
93
|
+
|
|
94
|
+
When a result has `jackpot_amount` set, the user won a jackpot on
|
|
95
|
+
that specific spin. Drain the template's `jackpot_current` in the
|
|
96
|
+
UI (the next `getMiniGames` push will confirm the reset).
|
|
97
|
+
|
|
98
|
+
For multi-jackpot wins in a single batch (rare but possible), sum
|
|
99
|
+
the amounts visually.
|
|
100
|
+
|
|
101
|
+
## Animations / transitions
|
|
102
|
+
|
|
103
|
+
Sequential animation pattern (most common):
|
|
104
|
+
|
|
105
|
+
1. Disable the Play CTA, show loading state.
|
|
106
|
+
2. For each result in order:
|
|
107
|
+
- Trigger the game-type animation (wheel spin, scratch
|
|
108
|
+
reveal, lootbox open, etc.).
|
|
109
|
+
- Sync the final position / reveal to the result's prize.
|
|
110
|
+
- Show a brief prize callout (~500 ms) between spins.
|
|
111
|
+
3. After the last spin, show a summary modal with total wins.
|
|
112
|
+
|
|
113
|
+
The default Smartico UI uses this pattern for lootboxes; wheel /
|
|
114
|
+
plinko / coin flip typically animate one at a time.
|
|
115
|
+
|
|
116
|
+
## Mobile vs desktop
|
|
117
|
+
|
|
118
|
+
- **Sequential animation**: identical on both, just smaller canvas
|
|
119
|
+
on mobile.
|
|
120
|
+
- **Summary modal**: desktop centered; mobile full-screen sheet.
|
|
121
|
+
|
|
122
|
+
## Performance
|
|
123
|
+
|
|
124
|
+
- Single round-trip per batch — much cheaper than N sequential
|
|
125
|
+
`playMiniGame` calls (one WS roundtrip vs N).
|
|
126
|
+
- Pre-determine the animation sequence from the result array
|
|
127
|
+
before starting — don't await each spin's animation completion
|
|
128
|
+
before deciding the next.
|