@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,17 @@
|
|
|
1
|
+
# UI Guide — `getAchCategories`
|
|
2
|
+
|
|
3
|
+
## UI guidance
|
|
4
|
+
- Treat categories as relatively static. It is safe to fetch once on page load and
|
|
5
|
+
reuse for the lifetime of the view; the SDK's 30 s cache handles short-term re-calls.
|
|
6
|
+
- Sort by `order` ascending before rendering. Items with the same `order` should
|
|
7
|
+
fall back to `name` or `id` for stable ordering.
|
|
8
|
+
- For tab UIs, generate one tab per category; "All" / "Other" tabs are
|
|
9
|
+
caller-provided (not returned by the server).
|
|
10
|
+
- For section UIs (mission/badge listing grouped by category), iterate sorted
|
|
11
|
+
categories and render only those whose filtered item list is non-empty unless
|
|
12
|
+
you intentionally want empty sections.
|
|
13
|
+
- Loading indicator: skip on cache hit; show a brief shimmer on cold fetch
|
|
14
|
+
(typically 100–300 ms).
|
|
15
|
+
|
|
16
|
+
**Visitor mode**: supported. Use `_smartico.vapi(lang).getAchCategories()` to fetch
|
|
17
|
+
categories with `name` translated to the given language without an authenticated user.
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# UI Guide — `getBadges`
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
- Badges are completion-tracked achievements that **auto-unlock** when their
|
|
5
|
+
criteria are met. No opt-in step, no claim step, no recurring cycles.
|
|
6
|
+
- The same `TMissionOrBadge` shape is reused; treat the mission-only fields
|
|
7
|
+
on a badge object as not-applicable (see method TSDoc for the list).
|
|
8
|
+
- The default Smartico UI renders badges as a **category-grouped grid** —
|
|
9
|
+
not a flat list and not as status tabs. Each category section shows
|
|
10
|
+
`completed / total` in its header.
|
|
11
|
+
- No `onUpdate` subscription. Poll on the 30 s cache TTL or re-fetch on a
|
|
12
|
+
domain event your app already handles (e.g. after a game round, after a
|
|
13
|
+
bonus claim).
|
|
14
|
+
- Loading indicator: skip on cache hit; show a brief shimmer on cold fetch
|
|
15
|
+
(typically 100–500 ms).
|
|
16
|
+
|
|
17
|
+
## List view organization
|
|
18
|
+
|
|
19
|
+
Group by category (`category_ids`) and resolve display metadata via
|
|
20
|
+
[`getAchCategories`](../../api/classes/WSAPIMissions.md#getachcategories).
|
|
21
|
+
The category list serves both missions and badges — use it directly.
|
|
22
|
+
|
|
23
|
+
Recommended layout — sectioned grid:
|
|
24
|
+
|
|
25
|
+
1. Fetch badges + categories in parallel.
|
|
26
|
+
2. Sort categories by `order` ascending.
|
|
27
|
+
3. For each category, filter `badges.filter(b => b.category_ids.includes(cat.id))`.
|
|
28
|
+
4. Render one collapsible section per non-empty category, with a header
|
|
29
|
+
showing `<name> (<completed>/<total>)`.
|
|
30
|
+
5. Items inside a section render as a fixed-cell grid (typically 3–4
|
|
31
|
+
columns on desktop, 2 on mobile — see "Mobile vs desktop").
|
|
32
|
+
|
|
33
|
+
Items with `category_ids: []` (uncategorized): the SDK does NOT return a
|
|
34
|
+
synthetic "Other" category. If your UI surfaces uncategorized badges,
|
|
35
|
+
generate that bucket client-side. Many badge UIs simply hide uncategorized
|
|
36
|
+
badges.
|
|
37
|
+
|
|
38
|
+
A badge can appear in multiple categories — duplicate rendering across
|
|
39
|
+
sections is intentional. Do NOT dedupe; users navigate categories
|
|
40
|
+
independently.
|
|
41
|
+
|
|
42
|
+
**Sort within a category**: typical priority — `is_completed === true`
|
|
43
|
+
first (most recently completed by `complete_date_ts` DESC), then
|
|
44
|
+
in-progress (by `position` ASC), then not-yet-started (by `position` ASC),
|
|
45
|
+
then expired (by `position` ASC). `position` is the operator-configured
|
|
46
|
+
display order; lower = higher priority.
|
|
47
|
+
|
|
48
|
+
## Badge card / tile
|
|
49
|
+
|
|
50
|
+
Fields to render on the card:
|
|
51
|
+
|
|
52
|
+
- `image` — documented source size 256×256 px. Render at a 1:1 aspect
|
|
53
|
+
ratio. There is no built-in placeholder for missing images — provide a
|
|
54
|
+
neutral fallback (e.g. a generic locked-badge silhouette).
|
|
55
|
+
- `name` — the title. Translated server-side.
|
|
56
|
+
- Stage counter — show **`<completed_tasks> / <total_tasks>`** computed
|
|
57
|
+
from `tasks` (count `t.is_completed === true` over `tasks.length`), NOT
|
|
58
|
+
a percentage `progress` bar. The default Smartico UI deliberately keeps
|
|
59
|
+
task descriptions hidden ("surprise mechanics") and shows only the count
|
|
60
|
+
of stages cleared. The exception: a single-task badge can show just a
|
|
61
|
+
completion check-mark instead of `1/1`.
|
|
62
|
+
- Availability chip — drive from `badgeTimeLimitState`. See "Status-specific
|
|
63
|
+
visual treatments" for the per-state visual treatment.
|
|
64
|
+
- `ribbon` — optional tag rendered as a corner badge (`sale`, `hot`, `new`,
|
|
65
|
+
`vip` or a custom 250×300 px image URL). Render top-right on the card.
|
|
66
|
+
|
|
67
|
+
Fields NOT on the card (detail-view only): `description`, full task list
|
|
68
|
+
with names, `hint_text` (T&C), category memberships.
|
|
69
|
+
|
|
70
|
+
**Click target**: whole card opens the detail view. There is no action
|
|
71
|
+
button on the card itself — badges have no opt-in or claim flow.
|
|
72
|
+
|
|
73
|
+
## Detail view / popup
|
|
74
|
+
|
|
75
|
+
Top-to-bottom layout:
|
|
76
|
+
|
|
77
|
+
1. **Hero image** — `image` rendered at a larger size (typically
|
|
78
|
+
320×320 px or full-width up to a max). Apply the same status overlay
|
|
79
|
+
as the card (see "Status-specific visual treatments").
|
|
80
|
+
2. **Title & availability chip** — `name` + status chip.
|
|
81
|
+
3. **Description** — `description` HTML.
|
|
82
|
+
4. **Task list** — render `tasks[].name` as a vertical list, each with
|
|
83
|
+
a check-mark when `task.is_completed === true`. Do NOT render
|
|
84
|
+
`tasks[].progress` percentages; the badge UX convention is "stages
|
|
85
|
+
cleared", not "percent complete". Optionally show stage `points_reward`
|
|
86
|
+
beside each task name if the brand surfaces task rewards.
|
|
87
|
+
5. **Reward summary** — `reward` HTML if non-empty.
|
|
88
|
+
6. **Timing block** — formatted `active_from_ts` / `active_till_ts` or
|
|
89
|
+
completion date `complete_date_ts`. See "Countdown / timing format".
|
|
90
|
+
7. **T&C** — `hint_text` if present, in a smaller collapsible
|
|
91
|
+
"Terms" panel.
|
|
92
|
+
8. **Related games** — `related_games` array rendered as a horizontal
|
|
93
|
+
game-tile strip if non-empty. Each tile clicks through to the game
|
|
94
|
+
using `related_games[i].game_public_meta.link`.
|
|
95
|
+
|
|
96
|
+
No primary CTA button at the bottom — badges are passive. If the brand
|
|
97
|
+
wants to drive engagement from the popup, surface a `related_games` strip
|
|
98
|
+
or a deep-link CTA derived from the brand's own configuration; the SDK
|
|
99
|
+
itself does not return one for badges.
|
|
100
|
+
|
|
101
|
+
## Action button decision matrix
|
|
102
|
+
|
|
103
|
+
Badges have **no action buttons**. They auto-unlock when criteria are met.
|
|
104
|
+
Anything that looks like an action button in a badge view is either:
|
|
105
|
+
|
|
106
|
+
- A close / back affordance (popup chrome), or
|
|
107
|
+
- A "View related game" link derived from `related_games[i].game_public_meta.link`, or
|
|
108
|
+
- A custom brand-defined CTA the operator wires up externally — the SDK
|
|
109
|
+
does not return a `cta_action` payload for badges in practice.
|
|
110
|
+
|
|
111
|
+
Do NOT render opt-in buttons, claim buttons, or anything that mutates
|
|
112
|
+
state. Both surfaces would no-op against badge IDs (no server endpoint
|
|
113
|
+
accepts a badge for opt-in / claim).
|
|
114
|
+
|
|
115
|
+
## Image / asset specs
|
|
116
|
+
|
|
117
|
+
| Field | Documented source size | Aspect ratio | Fallback |
|
|
118
|
+
|---|---|---|---|
|
|
119
|
+
| `image` | 256×256 px | 1:1 | Neutral locked-badge silhouette |
|
|
120
|
+
| `ribbon` (custom URL) | 250×300 px | 5:6 portrait | Hide ribbon if URL fails to load |
|
|
121
|
+
| `related_games[i].game_public_meta.image` | per game-catalog spec (1:1) | 1:1 | Hide tile if image missing |
|
|
122
|
+
|
|
123
|
+
If `image` is missing or fails to load: render the fallback at the same
|
|
124
|
+
size. Do not show a broken-image icon — this UI surface is consumer-facing
|
|
125
|
+
gamification and a broken image undermines the reward fantasy.
|
|
126
|
+
|
|
127
|
+
## Status-specific visual treatments
|
|
128
|
+
|
|
129
|
+
Drive from `badgeTimeLimitState` first, then layer completion state on
|
|
130
|
+
top.
|
|
131
|
+
|
|
132
|
+
| `badgeTimeLimitState` | Card visual | Availability chip text |
|
|
133
|
+
|---|---|---|
|
|
134
|
+
| `BeforeStartDate` (0) — window hasn't started | Grayscale + subtle dim overlay. Lock-icon corner badge if `is_locked === true`. | `"Starts on <date>"` from `active_from_ts` |
|
|
135
|
+
| `AfterStartDateNoProgress` (1) — active, no progress yet, no end date | Full-color, no overlay | No chip (or a neutral `"Available"`) |
|
|
136
|
+
| `AfterStartDateNoProgressAndEndDate` (2) — active, no progress, has end date | Full-color | `"Until <date>"` from `active_till_ts` |
|
|
137
|
+
| `AfterStartDateWithProgressAndEndDate` (3) — active with progress, has end date | Full-color | `"<countdown>"` to `active_till_ts` (see "Countdown / timing format") |
|
|
138
|
+
| `AfterEndDateNotStarted` (4) — expired, never started | Grayscale + dim overlay + slash/X overlay | `"Expired"` |
|
|
139
|
+
| `AfterEndDateWithProgress` (5) — expired with some progress | Grayscale + dim overlay | `"Ended"` (or `"Expired"`) |
|
|
140
|
+
|
|
141
|
+
On top of the time-window treatment, layer the completion state:
|
|
142
|
+
|
|
143
|
+
- `is_completed === true` — color-restored card (override grayscale),
|
|
144
|
+
prominent check-mark corner badge, glow / shine accent. The default
|
|
145
|
+
Smartico UI shows the most-recently-completed badges first within a
|
|
146
|
+
category by `complete_date_ts` DESC.
|
|
147
|
+
- `is_completed === false` and at least one `task.is_completed === true` —
|
|
148
|
+
show the stage counter prominently (e.g. larger font, contrasting color)
|
|
149
|
+
to signal in-progress.
|
|
150
|
+
- All other cases — neutral card, stage counter at default emphasis.
|
|
151
|
+
|
|
152
|
+
## Countdown / timing format
|
|
153
|
+
|
|
154
|
+
Time displayed varies by badge state. Recommended format ("compact"):
|
|
155
|
+
|
|
156
|
+
- **Time-until-start** (`badgeTimeLimitState === BeforeStartDate`):
|
|
157
|
+
- More than 7 days away → `"Starts <date>"` (e.g. `"Starts 12 Jun"`)
|
|
158
|
+
- 1–7 days → `"Starts in <N> days"`
|
|
159
|
+
- < 24 h → `"Starts in <Hh Mm>"`
|
|
160
|
+
- **Time-until-end** (`AfterStartDateWithProgressAndEndDate`,
|
|
161
|
+
`AfterStartDateNoProgressAndEndDate`):
|
|
162
|
+
- > 7 days → `"Until <date>"`
|
|
163
|
+
- 1–7 days → `"<N> days left"`
|
|
164
|
+
- 1–24 h → `"<Hh Mm> left"`
|
|
165
|
+
- < 1 h → `"<Mm Ss> left"`, updated every second
|
|
166
|
+
- **Completed**: `"Completed <relative>"` (e.g. `"Completed 2 days ago"`)
|
|
167
|
+
from `complete_date_ts`. Tooltip shows full timestamp.
|
|
168
|
+
- **Expired / ended**: just the static label `"Expired"` or `"Ended"`.
|
|
169
|
+
|
|
170
|
+
Update cadence:
|
|
171
|
+
- > 1 hour away from boundary → refresh once a minute is enough.
|
|
172
|
+
- < 1 hour → refresh once a second.
|
|
173
|
+
- Avoid rendering ticking timers for badges that don't have an `active_till_ts`
|
|
174
|
+
(most badges) — most badges are open-ended.
|
|
175
|
+
|
|
176
|
+
## Empty / loading / error states
|
|
177
|
+
|
|
178
|
+
- **Loading (cold fetch)**: render a shimmer grid (skeleton cards) matching
|
|
179
|
+
the eventual grid layout. Show category-section headers if cached, else
|
|
180
|
+
shimmer the entire view.
|
|
181
|
+
- **Loading (cache hit)**: do not render a loading state. The promise
|
|
182
|
+
resolves within a microtask.
|
|
183
|
+
- **Empty result**: `[]` from the server means the brand has no badges
|
|
184
|
+
configured for the user (rare). Render a neutral empty-state illustration
|
|
185
|
+
with copy like `"No badges yet"`. Do NOT show this state during the
|
|
186
|
+
cold-fetch shimmer.
|
|
187
|
+
- **Error**: cache the prior result if any and keep rendering it; show a
|
|
188
|
+
small non-blocking error banner. Retry on the next poll tick. Do not
|
|
189
|
+
break the page on a single fetch failure.
|
|
190
|
+
|
|
191
|
+
## Animations / transitions
|
|
192
|
+
|
|
193
|
+
- **List entry**: cards fade-in on first render. Within a category section,
|
|
194
|
+
the default Smartico UI staggers the fade by ~30 ms per card.
|
|
195
|
+
- **Category section expand/collapse**: smooth height animation (~200 ms
|
|
196
|
+
ease-out).
|
|
197
|
+
- **Badge completion celebration**: when `is_completed` flips from `false`
|
|
198
|
+
to `true` between fetches (your consumer detects this by diffing the
|
|
199
|
+
prior list), play a celebration animation on the affected card —
|
|
200
|
+
shine sweep + check-mark scale-in. The default Smartico UI also opens
|
|
201
|
+
the detail popup automatically on a freshly-completed badge if the
|
|
202
|
+
user is currently viewing the badge surface; mirror this only if your
|
|
203
|
+
product surface justifies it.
|
|
204
|
+
- **Stage tick**: when `completed_tasks` increases between fetches without
|
|
205
|
+
full completion, briefly highlight the stage counter (color flash for
|
|
206
|
+
~500 ms) to acknowledge progress.
|
|
207
|
+
|
|
208
|
+
## Mobile vs desktop
|
|
209
|
+
|
|
210
|
+
- **Grid columns**: desktop typically 3–4 columns, tablet 2–3, mobile 2.
|
|
211
|
+
Cards are square (1:1 image aspect ratio drives the layout).
|
|
212
|
+
- **Card density**: mobile cards may hide the ribbon to reduce visual
|
|
213
|
+
noise; the stage counter remains.
|
|
214
|
+
- **Detail view**: mobile opens as a full-screen modal (slide-up); desktop
|
|
215
|
+
opens as a centered popup with backdrop dim.
|
|
216
|
+
- **Category sections**: mobile may default-collapse all sections except
|
|
217
|
+
the first one with non-zero progress; desktop typically renders all
|
|
218
|
+
sections expanded.
|
|
219
|
+
|
|
220
|
+
## Performance
|
|
221
|
+
|
|
222
|
+
- Diff the badge list between fetches to detect completion / stage events
|
|
223
|
+
for animations. Avoid full re-renders on every poll tick — keyed
|
|
224
|
+
per-card rendering matters because the celebration animations break
|
|
225
|
+
if the DOM nodes are recreated.
|
|
226
|
+
- The `image` URLs are CDN-hosted; let the browser cache them. Lazy-load
|
|
227
|
+
images below the fold; eager-load images in the first visible category.
|
|
228
|
+
- 30 s polling is fine for a small to medium badge catalog (< 200 badges).
|
|
229
|
+
For very large catalogs, consider polling only when the badges surface
|
|
230
|
+
is in the viewport (use `IntersectionObserver`) — the SDK doesn't
|
|
231
|
+
throttle for you.
|
|
232
|
+
|
|
233
|
+
**Visitor mode: not supported.** Use [`getMissions`](../../api/classes/WSAPIMissions.md#getmissions)
|
|
234
|
+
(visitor mode supported) or [`getAchCategories`](../../api/classes/WSAPIMissions.md#getachcategories)
|
|
235
|
+
(visitor mode supported) if you need achievement data for anonymous users.
|
|
236
|
+
Calling `_smartico.vapi(lang).getBadges()` returns no usable data — visitor
|
|
237
|
+
sessions have no badge-progress path on the server.
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# UI Guide — `getMissions`
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
- Register `onUpdate` on first render and treat each invocation as
|
|
5
|
+
"discard prior list, re-render from this array". Do not merge with
|
|
6
|
+
the previous list — fields like `progress` are absolute, not deltas.
|
|
7
|
+
- Loading indicator: the first `getMissions()` is a server round-trip
|
|
8
|
+
(typically 100–500 ms); subsequent calls within the cache window
|
|
9
|
+
resolve effectively synchronously.
|
|
10
|
+
- Don't poll `getMissions()` to detect opt-in / claim completion. The
|
|
11
|
+
`onUpdate` callback is the authoritative signal.
|
|
12
|
+
- The SDK returns a flat array; there is no pre-computed status bucket
|
|
13
|
+
field. Consumers apply the bucketing filter chain below themselves.
|
|
14
|
+
|
|
15
|
+
## Status bucketing
|
|
16
|
+
Partition the array using this **priority order — first match wins**:
|
|
17
|
+
|
|
18
|
+
1. **Missed** — time window passed before completion. Test:
|
|
19
|
+
`(!is_completed) && ((is_requires_optin && is_opted_in || !is_requires_optin)`
|
|
20
|
+
` && time_limit_ms && dt_start && (dt_start + time_limit_ms) < Date.now())`
|
|
21
|
+
`|| (active_till_ts && active_till_ts < Date.now())`.
|
|
22
|
+
Sort: `position` ASC.
|
|
23
|
+
2. **Completed** — `is_completed === true`, OR for missions of type
|
|
24
|
+
`AchievementStatus.RecurringUponCompletion`,
|
|
25
|
+
`max_completion_count === completion_count` (cap reached) OR
|
|
26
|
+
`completion_count > 0` (at least one cycle completed).
|
|
27
|
+
Sort: `complete_date_ts` DESC (most recent first).
|
|
28
|
+
3. **Locked** — `is_locked === true`, OR not yet available
|
|
29
|
+
(`active_from_ts > Date.now()`). Sort: `position` ASC.
|
|
30
|
+
4. **Available (in-progress)** — none of the above.
|
|
31
|
+
Sort: `position` ASC.
|
|
32
|
+
|
|
33
|
+
Each mission belongs to exactly ONE bucket. Many UIs render these as
|
|
34
|
+
status tabs / sections. The `availability_status` field
|
|
35
|
+
([AchievementAvailabilityStatus](../../api/enumerations/AchievementAvailabilityStatus.md)) is authoritative for **timer /
|
|
36
|
+
window state** (which countdown to show, whether the window has
|
|
37
|
+
elapsed) — but it is NOT a substitute for bucketing: distinguishing
|
|
38
|
+
"locked" from "opt-in required" requires reading `is_locked` and
|
|
39
|
+
`is_opted_in` directly. An "Overview" tab curating featured +
|
|
40
|
+
in-progress + a sample locked is a common pattern.
|
|
41
|
+
|
|
42
|
+
## Mission card / tile (list view)
|
|
43
|
+
|
|
44
|
+
Fields to render on the card:
|
|
45
|
+
- `image` — documented source size 256×256 px. Render at a 1:1 aspect
|
|
46
|
+
ratio; CSS `background-image` is conventional. There is no built-in
|
|
47
|
+
placeholder for missing images — provide a neutral fallback.
|
|
48
|
+
- `name` — the title. Translated server-side. Safe to render as HTML
|
|
49
|
+
if the consumer sanitizes first.
|
|
50
|
+
- Status chip — derived from the bucket the mission falls into;
|
|
51
|
+
includes a live countdown for time-limited entries (see "time
|
|
52
|
+
formatting" below).
|
|
53
|
+
- Description (fallback chain): `description` → `unlock_mission_description`
|
|
54
|
+
(when `is_locked`) → `tasks[0].name` (when no description and tasks
|
|
55
|
+
exist).
|
|
56
|
+
- Progress bar — render only when `progress > 0` (the 0–100 integer).
|
|
57
|
+
Hide for completed recurring missions (`AchievementStatus.RecurringUponCompletion`
|
|
58
|
+
on the Completed tab) to avoid showing residual percentage from a
|
|
59
|
+
prior cycle.
|
|
60
|
+
- Reward summary (`reward` HTML) — show only when `progress === 0`.
|
|
61
|
+
For in-progress missions, the progress percentage replaces the reward.
|
|
62
|
+
- Ribbon overlay (`ribbon` field) — presets `'sale'`, `'hot'`, `'new'`,
|
|
63
|
+
`'vip'` use built-in styling; a URL means a custom **250×300 px** image.
|
|
64
|
+
Position: top-left corner overlay.
|
|
65
|
+
- "Claim" button — replaces the progress bar when
|
|
66
|
+
`is_completed && requires_prize_claim && !prize_claimed_date_ts`.
|
|
67
|
+
- "Featured" marker — alternative to ribbon for operator-marked
|
|
68
|
+
featured missions.
|
|
69
|
+
|
|
70
|
+
Fields NOT shown on the card (detail popup only):
|
|
71
|
+
- Full `description` HTML beyond a single line
|
|
72
|
+
- `sub_header`
|
|
73
|
+
- `tasks[]` (except as description fallback)
|
|
74
|
+
- `hint_text` (T&C)
|
|
75
|
+
- `related_games`
|
|
76
|
+
- Opt-in / CTA action buttons (the status chip alone communicates
|
|
77
|
+
"opt-in required" on cards; the actual button lives in the popup)
|
|
78
|
+
|
|
79
|
+
Click target: the **whole card** opens the detail popup. The Claim
|
|
80
|
+
button (when present) is the only sub-element with its own handler;
|
|
81
|
+
it must `event.stopPropagation()` so the popup doesn't also open.
|
|
82
|
+
|
|
83
|
+
## Mission detail popup
|
|
84
|
+
|
|
85
|
+
Top-to-bottom structure (omit sections whose source field is empty):
|
|
86
|
+
1. Close button.
|
|
87
|
+
2. Ribbon overlay (same as card).
|
|
88
|
+
3. Title (`name`).
|
|
89
|
+
4. Sub-header (`sub_header`).
|
|
90
|
+
5. Status chip — typically without countdown (use the dedicated
|
|
91
|
+
time-remaining block below).
|
|
92
|
+
6. Image (`image`) — render larger than the card variant.
|
|
93
|
+
7. Lock icon overlay on the image when `is_locked === true`.
|
|
94
|
+
8. Time-remaining block — "Available again in" countdown for
|
|
95
|
+
recurring waiting; "Starts on" for `active_from_ts > now`;
|
|
96
|
+
"Expired on" for missed; countdown for in-window.
|
|
97
|
+
9. Full `description` (HTML).
|
|
98
|
+
10. Action button — see the decision matrix below.
|
|
99
|
+
11. Hint / T&C — `hint_text` surfaced as an info-icon tooltip
|
|
100
|
+
(tap to expand). Not inline.
|
|
101
|
+
12. Task list — only when `tasks.length > 1` (single-task missions
|
|
102
|
+
use the task name as description fallback on the card; the
|
|
103
|
+
list is redundant). Each task row: completion indicator
|
|
104
|
+
(checkbox/circle) + `task.name`. Append "N / M" using
|
|
105
|
+
`execution_count_actual / execution_count_expected` when the
|
|
106
|
+
operator has enabled count display. Show a points stamp for
|
|
107
|
+
tasks with `points_reward > 0`.
|
|
108
|
+
13. Progress bar (conditional, same rule as card).
|
|
109
|
+
14. Reward block (`reward`).
|
|
110
|
+
15. Related games — only games where `game_public_meta.enabled === true`.
|
|
111
|
+
Render as a horizontal carousel; show navigation arrows when
|
|
112
|
+
5+ games on desktop, 4+ on mobile. Thumbnails are 1:1 aspect
|
|
113
|
+
ratio; tap a thumbnail to launch the underlying game.
|
|
114
|
+
16. Unlock description (`unlock_mission_description`) at the
|
|
115
|
+
bottom when `is_locked`.
|
|
116
|
+
|
|
117
|
+
## Action button decision matrix
|
|
118
|
+
|
|
119
|
+
Apply in priority order; **first match wins**:
|
|
120
|
+
|
|
121
|
+
1. `is_locked === true` → **no action button**. Show the unlock
|
|
122
|
+
description and a lock-icon overlay on the image.
|
|
123
|
+
2. `is_completed && requires_prize_claim && !prize_claimed_date_ts`
|
|
124
|
+
AND `prize_claim_expiration_date >= Date.now()` (claimable) →
|
|
125
|
+
**"Claim" button**. Use `claim_button_title` as the label if set,
|
|
126
|
+
otherwise a localized default. On click: call
|
|
127
|
+
`requestMissionClaimReward(id, ach_completed_id)`. Optionally
|
|
128
|
+
animate a celebration overlay after success.
|
|
129
|
+
3. Same as (2) but claim window expired (`prize_claim_expiration_date < Date.now()`) →
|
|
130
|
+
render the Claim label as **disabled**; show the formatted expiration
|
|
131
|
+
date with a "claim expired on" prefix.
|
|
132
|
+
4. `is_completed` (no claim required, or already claimed) →
|
|
133
|
+
**no action button**. Show progress / completion state.
|
|
134
|
+
5. `is_requires_optin && !is_opted_in` (and not locked) →
|
|
135
|
+
**"Opt In" button**. Disable when:
|
|
136
|
+
- `active_from_ts > Date.now()` (not yet started),
|
|
137
|
+
- the mission falls in the Missed bucket,
|
|
138
|
+
- `active_till_ts && active_till_ts < Date.now()` (expired).
|
|
139
|
+
While the opt-in request is in flight, show a loading indicator
|
|
140
|
+
on the button. The SDK does NOT enforce a single in-flight call —
|
|
141
|
+
guard against double-clicks at the UI layer (set a local
|
|
142
|
+
`optInLoading` flag on click).
|
|
143
|
+
6. `cta_text && cta_action` (and none of the above) → **CTA button**
|
|
144
|
+
labeled with `cta_text`. On click: call
|
|
145
|
+
`_smartico.dp(cta_action)`. `cta_action` is a deep-link string
|
|
146
|
+
(e.g. `'dp:deposit'`, `'dp:gf_store'`) — not a URL.
|
|
147
|
+
Disable when the mission falls in the Missed bucket or is
|
|
148
|
+
otherwise out of window.
|
|
149
|
+
7. None of the above → no action button.
|
|
150
|
+
|
|
151
|
+
Recurring missions:
|
|
152
|
+
- Waiting for next cycle (`next_recurrence_date_ts > Date.now()`) →
|
|
153
|
+
**no button**; the status chip carries the "Available again in
|
|
154
|
+
DD:HH:MM:SS" countdown.
|
|
155
|
+
- Cap reached (`max_completion_count === completion_count`) → treated
|
|
156
|
+
as Completed; no button.
|
|
157
|
+
|
|
158
|
+
## `claim_button_action` companion action
|
|
159
|
+
|
|
160
|
+
*(important caveat)*
|
|
161
|
+
|
|
162
|
+
If `claim_button_action` is set, the consumer's claim handler is
|
|
163
|
+
expected to fire BOTH the claim API call AND the deep-link action
|
|
164
|
+
**at the same time** (concurrently). The deep-link runs synchronously
|
|
165
|
+
on click — it does NOT wait for the claim RPC to succeed. Consequences:
|
|
166
|
+
- If the deep-link navigates away (e.g. opens a casino game), the
|
|
167
|
+
user may miss the claim loading animation or any error toast.
|
|
168
|
+
- If the claim RPC fails after the navigation has already started,
|
|
169
|
+
there is no rollback.
|
|
170
|
+
- Treat `claim_button_action` as a *companion navigation*, not a
|
|
171
|
+
post-claim follow-up. Common pattern:
|
|
172
|
+
`dispatch claim → _smartico.dp(claim_button_action)` in the same
|
|
173
|
+
click handler, without `await`-ing the claim.
|
|
174
|
+
- `claim_button_action` accepts both `dp:...` deep-links and full
|
|
175
|
+
`http(s)://...` URLs (URLs open in a new tab).
|
|
176
|
+
|
|
177
|
+
## Image / asset specs
|
|
178
|
+
- Mission `image`: documented source size **256×256 px**, 1:1 aspect ratio.
|
|
179
|
+
- Custom ribbon URL: documented source size **250×300 px**.
|
|
180
|
+
- Related-game thumbnails: **1:1 aspect ratio** per `game_public_meta.image`.
|
|
181
|
+
- All assets are typically rendered as CSS `background-image` (no
|
|
182
|
+
`<img>` element) so dimensions are controlled by the consumer's CSS.
|
|
183
|
+
- No built-in fallback placeholders — consumers should provide one
|
|
184
|
+
when source fields are empty.
|
|
185
|
+
|
|
186
|
+
## Status-specific visual treatments
|
|
187
|
+
- **Locked**: lock-icon overlay on the image and a "locked" CSS
|
|
188
|
+
modifier on the image container. NOT grayscale (grayscale is the
|
|
189
|
+
convention for locked badges, not locked missions).
|
|
190
|
+
- **Completed**: no tint or strikethrough on the card itself; the
|
|
191
|
+
status chip carries the completion date.
|
|
192
|
+
- **Missed**: same chip styling as Locked, different label.
|
|
193
|
+
Missions stay visible in the Missed bucket unless an operator
|
|
194
|
+
config hides expired missions after N days.
|
|
195
|
+
- **In progress**: default styling.
|
|
196
|
+
- **Opt-in required**: same as in-progress; the status chip alone
|
|
197
|
+
signals "opt-in required".
|
|
198
|
+
- **Featured**: replace the ribbon (when no `ribbon` is set) with a
|
|
199
|
+
"featured" modifier; some brands use a gold border / glow.
|
|
200
|
+
- **Claimable** (claim button visible): add a "claimable" modifier
|
|
201
|
+
to the card root to apply a highlight border or glow drawing
|
|
202
|
+
attention to the action.
|
|
203
|
+
|
|
204
|
+
## Time-remaining countdown format
|
|
205
|
+
|
|
206
|
+
Convention used by the default Smartico UI (consumers should match for
|
|
207
|
+
a consistent feel across Smartico widgets):
|
|
208
|
+
- `≤ 0` → `00:00`
|
|
209
|
+
- `< 1 hour` → `MM:SS`
|
|
210
|
+
- `< 1 day` → `HH:MM:SS`
|
|
211
|
+
- `< 1 month` → `DD:HH:MM:SS`
|
|
212
|
+
- `< 1 year` → `MO:DD:HH:MM:SS`
|
|
213
|
+
- `≥ 1 year` → `YY:MO:DD:HH:MM:SS`
|
|
214
|
+
|
|
215
|
+
Update the displayed text every 1 second while the mission is in
|
|
216
|
+
progress.
|
|
217
|
+
|
|
218
|
+
## Empty states
|
|
219
|
+
|
|
220
|
+
Show a contextual empty-state message per bucket:
|
|
221
|
+
- Completed: "No completed missions yet"
|
|
222
|
+
- Locked: "No locked missions"
|
|
223
|
+
- Others (Available / Missed): "Nothing to show yet"
|
|
224
|
+
|
|
225
|
+
## Animations / transitions
|
|
226
|
+
- List entry: brief zoom-in or fade-in per card (stagger optional).
|
|
227
|
+
- Popup open: bounce + fade-in; stagger inner elements (title, image,
|
|
228
|
+
description, actions) for a layered reveal.
|
|
229
|
+
- Progress bar fill: animate the width over ~1 second when progress
|
|
230
|
+
advances (especially in the popup; cards often render the bar
|
|
231
|
+
statically).
|
|
232
|
+
- Claim success: hide the Claim button immediately on success and
|
|
233
|
+
(optionally) overlay a confetti or celebration animation.
|
|
234
|
+
- In-flight buttons (opt-in / claim): show a loading indicator
|
|
235
|
+
(animated dots, spinner) and disable the trigger element until the
|
|
236
|
+
response arrives.
|
|
237
|
+
|
|
238
|
+
## Mobile vs desktop
|
|
239
|
+
- Mobile: single-column vertical scroll.
|
|
240
|
+
- Desktop: multi-column grid. The default Smartico UI alternates a "big"
|
|
241
|
+
and "small" card variant in a masonry pattern (every 4th in even
|
|
242
|
+
rows / every 5th in odd rows is "big"). Consumers may use any grid
|
|
243
|
+
pattern that suits their design.
|
|
244
|
+
- The detail popup is structurally identical on mobile and desktop;
|
|
245
|
+
only sizing differs.
|
|
246
|
+
|
|
247
|
+
## Performance
|
|
248
|
+
|
|
249
|
+
The list is not paginated; the SDK returns the full visible mission
|
|
250
|
+
set in one response. For very large catalogs (50+ missions visible),
|
|
251
|
+
consider client-side virtualization in the consumer UI. The official
|
|
252
|
+
tracker does NOT virtualize.
|
|
253
|
+
|
|
254
|
+
**Cache TTL**: the SDK caches the response for 30 seconds. The cache
|
|
255
|
+
is invalidated and re-fetched automatically on each of the three
|
|
256
|
+
trigger events above; `onUpdate` fires after the re-fetch completes.
|
|
257
|
+
|
|
258
|
+
**Visitor mode**: supported, with caveats.
|
|
259
|
+
- The returned list reflects the brand's proxy "visitor" user, not
|
|
260
|
+
the actual anonymous viewer. Per-user fields (`is_opted_in`,
|
|
261
|
+
`progress`, `completed_count`) reflect the proxy user's state and
|
|
262
|
+
are not meaningful for display.
|
|
263
|
+
- `onUpdate` is accepted by the API but NEVER fires in visitor mode —
|
|
264
|
+
there is no live channel, so push events are not delivered.
|
|
265
|
+
Visitor-mode consumers should re-poll `getMissions()` periodically
|
|
266
|
+
if fresh data is needed.
|
|
267
|
+
- Additional server-side caching applies on top of the SDK cache,
|
|
268
|
+
so visitor-mode data may be a few minutes stale.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# UI Guide — `requestMissionClaimReward`
|
|
2
|
+
|
|
3
|
+
## UI guidance
|
|
4
|
+
- Show a loading indicator while the promise is pending; this is a
|
|
5
|
+
server round-trip with side effects (DB writes, CRM rules) and may
|
|
6
|
+
take 200–800ms depending on configured CRM automations.
|
|
7
|
+
- Disable the claim button for the duration of the call. The local
|
|
8
|
+
`prize_claimed_date_ts` flag won't flip until the auto-refresh fires
|
|
9
|
+
after the response.
|
|
10
|
+
- Treat `err_code === 0` and `err_code === 40017` identically in the
|
|
11
|
+
UI: hide the claim button. Don't surface 40017 as an error.
|
|
12
|
+
- For `err_code === 40015` (window expired), show a dedicated message
|
|
13
|
+
referencing the original `prize_claim_expiration_date`, not a generic
|
|
14
|
+
error.
|
|
15
|
+
- For `err_code === 40016` (not completed), this should not normally
|
|
16
|
+
happen if the UI gates on `is_completed === true`. If it does, the
|
|
17
|
+
local state is stale — auto-refresh will correct it.
|
|
18
|
+
- Do NOT optimistically mark the prize as claimed before the response.
|
|
19
|
+
Authoritative state comes from the SDK's auto-refresh.
|
|
20
|
+
|
|
21
|
+
**Visitor mode**: not supported.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# UI Guide — `requestMissionOptIn`
|
|
2
|
+
|
|
3
|
+
## UI guidance
|
|
4
|
+
- Show a loading indicator (spinner, dots, button-disable) while the
|
|
5
|
+
promise is pending; opt-in is a server round-trip and may take
|
|
6
|
+
100–500ms under normal conditions.
|
|
7
|
+
- Disable the trigger element for the duration of the call to prevent
|
|
8
|
+
double-clicks. The local `is_opted_in` flag won't flip until the
|
|
9
|
+
`onUpdate` callback fires post-response.
|
|
10
|
+
- Treat `err_code === 0` and `err_code === 40010` identically in the
|
|
11
|
+
UI: hide the opt-in button. Don't surface 40010 as an error.
|
|
12
|
+
- For `err_code === 40014` (locked), show the mission's
|
|
13
|
+
`unlock_mission_description` instead of a generic error.
|
|
14
|
+
- Do NOT optimistically set `is_opted_in = true` before the response.
|
|
15
|
+
Authoritative refresh comes from the SDK's `onUpdate` invocation,
|
|
16
|
+
not from local state.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# UI Guide — `claimRafflePrize`
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
- Action-focused mutation. The user has a winning row from a raffle
|
|
5
|
+
draw (visible via
|
|
6
|
+
[`getRaffleDrawRun`](../../api/classes/WSAPIRaffles.md#getraffledrawrun)
|
|
7
|
+
with `should_claim === true` or via
|
|
8
|
+
[`getRaffleDrawRunsHistory`](../../api/classes/WSAPIRaffles.md#getraffledrawrunshistory)
|
|
9
|
+
with `has_unclaimed_prize === true`), and they click Claim.
|
|
10
|
+
- Success (`errorCode === 0`) means the claim is recorded and prize
|
|
11
|
+
delivery is queued server-side. The actual delivery (wallet
|
|
12
|
+
credit, free spins, etc.) happens through the operator's
|
|
13
|
+
integration outside the SDK's response cycle.
|
|
14
|
+
- Latency: typically 200 ms – 1 s for a healthy WebSocket.
|
|
15
|
+
- Balance updates do NOT arrive in this response. Subscribe to
|
|
16
|
+
[`getUserProfile`](../../api/classes/WSAPIUser.md#getuserprofile)'s
|
|
17
|
+
`props_change` channel to observe credits.
|
|
18
|
+
|
|
19
|
+
## Result shape note
|
|
20
|
+
|
|
21
|
+
This method returns `{ errorCode, errorMessage? }` (camelCase
|
|
22
|
+
full-word) — **different** from most other SDK result types that
|
|
23
|
+
use `{ err_code, err_message }` (snake_case). Branch on the
|
|
24
|
+
camelCase keys.
|
|
25
|
+
|
|
26
|
+
## Loading state
|
|
27
|
+
|
|
28
|
+
- **Trigger**: set an in-flight flag (`claiming = true`)
|
|
29
|
+
immediately on click, BEFORE the call.
|
|
30
|
+
- **Visual**: replace the button label with animated dots /
|
|
31
|
+
spinner. Disable the button. Keep the detail / history view open.
|
|
32
|
+
- **Reset**: clear the flag on response — success or error.
|
|
33
|
+
|
|
34
|
+
## Idempotency UI guard
|
|
35
|
+
|
|
36
|
+
The SDK does NOT prevent double-clicks. A second call on the same
|
|
37
|
+
`won_id` returns `errorCode === 1` with `errorMessage` indicating
|
|
38
|
+
the prize has already been claimed. Guard the call site:
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
const [claiming, setClaiming] = useState(false);
|
|
42
|
+
|
|
43
|
+
const onClaim = async (won_id: number) => {
|
|
44
|
+
if (claiming) return; // in-flight guard
|
|
45
|
+
setClaiming(true);
|
|
46
|
+
const r = await window._smartico.api.claimRafflePrize({ won_id });
|
|
47
|
+
setClaiming(false);
|
|
48
|
+
handleResponse(r);
|
|
49
|
+
};
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Treat `errorCode === 1` with an "already claimed" message as
|
|
53
|
+
**idempotent success** in the UI — the underlying state is what
|
|
54
|
+
the consumer wants.
|
|
55
|
+
|
|
56
|
+
## Action button decision matrix
|
|
57
|
+
|
|
58
|
+
| Condition | Action |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `errorCode === 0` (success) | Show a success toast ("Prize claimed!"). The raffles list auto-refreshes via [`getRaffles`](../../api/classes/WSAPIRaffles.md#getraffles)'s `onUpdate`; the winner row's `claimed_date` populates on the next refresh. Don't manually re-fetch. |
|
|
61
|
+
| `errorCode === 1` + `errorMessage` mentions "already claimed" | Treat as success — same UI as above. Surface a brief "Already claimed" toast for clarity if you prefer. |
|
|
62
|
+
| `errorCode === 1` + any other `errorMessage` (control group, mismatch) | Show a generic error toast with the operator message. Allow retry only if the message suggests transient failure. |
|
|
63
|
+
| Other non-zero | Show a generic error toast. Allow retry. |
|
|
64
|
+
|
|
65
|
+
## Refresh after response
|
|
66
|
+
|
|
67
|
+
The SDK auto-refreshes the raffles cache on every claim response
|
|
68
|
+
(success OR failure) via the same push that delivers the result.
|
|
69
|
+
The `onUpdate` callback registered via `getRaffles({ onUpdate })`
|
|
70
|
+
fires with the refreshed list. **Don't manually call `getRaffles()`
|
|
71
|
+
after a claim** — the refresh is already happening.
|
|
72
|
+
|
|
73
|
+
The winner row in the active detail view (`getRaffleDrawRun`) is
|
|
74
|
+
NOT auto-refreshed — call that separately if the detail screen is
|
|
75
|
+
open and you want to see `claimed_date` immediately. The default
|
|
76
|
+
Smartico UI re-fetches the draw detail after a successful claim.
|
|
77
|
+
|
|
78
|
+
## No celebration animation
|
|
79
|
+
|
|
80
|
+
Unlike mission / SAW celebrations, the default Smartico UI does
|
|
81
|
+
NOT play a confetti or full-screen animation on raffle claim. The
|
|
82
|
+
winner row updates in-place with the claimed timestamp; a
|
|
83
|
+
success toast is the primary visual feedback. Add a celebration
|
|
84
|
+
in your own UI if your product surface calls for it.
|
|
85
|
+
|
|
86
|
+
## Mobile vs desktop
|
|
87
|
+
|
|
88
|
+
- **Error surfacing**: desktop snackbar / toast; mobile centered
|
|
89
|
+
modal.
|
|
90
|
+
- **Modal style**: desktop centered; mobile full-screen sheet.
|
|
91
|
+
- **Loading state**: identical (dots animation on the button).
|
|
92
|
+
|
|
93
|
+
## Performance
|
|
94
|
+
|
|
95
|
+
- Single round-trip per click.
|
|
96
|
+
- Prize delivery through the operator's integration is async
|
|
97
|
+
and out-of-band — the SDK consumer doesn't observe it directly.
|
|
98
|
+
- Don't poll for delivery confirmation — trust the success
|
|
99
|
+
response.
|