@smartico/public-api 0.0.379 → 0.0.380

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/.nvmrc +1 -1
  2. package/README.md +31 -2
  3. package/dist/Store/BuyStoreItemErrorCode.d.ts +9 -1
  4. package/dist/Tournaments/TournamentRegistrationError.d.ts +3 -1
  5. package/dist/WSAPI/WSAPI.d.ts +13 -1235
  6. package/dist/WSAPI/WSAPIAvatars.d.ts +78 -0
  7. package/dist/WSAPI/WSAPIBase.d.ts +71 -0
  8. package/dist/WSAPI/WSAPIBonuses.d.ts +26 -0
  9. package/dist/WSAPI/WSAPIClans.d.ts +388 -0
  10. package/dist/WSAPI/WSAPIGamePick.d.ts +308 -0
  11. package/dist/WSAPI/WSAPIGeneral.d.ts +30 -0
  12. package/dist/WSAPI/WSAPIInbox.d.ts +126 -0
  13. package/dist/WSAPI/WSAPIJackpots.d.ts +109 -0
  14. package/dist/WSAPI/WSAPILeaderBoard.d.ts +25 -0
  15. package/dist/WSAPI/WSAPIMiniGames.d.ts +94 -0
  16. package/dist/WSAPI/WSAPIMissions.d.ts +517 -0
  17. package/dist/WSAPI/WSAPIRaffles.d.ts +119 -0
  18. package/dist/WSAPI/WSAPIStore.d.ts +656 -0
  19. package/dist/WSAPI/WSAPITournaments.d.ts +501 -0
  20. package/dist/WSAPI/WSAPITypes.d.ts +145 -85
  21. package/dist/WSAPI/WSAPIUser.d.ts +383 -0
  22. package/dist/index.js +3818 -1528
  23. package/dist/index.js.map +1 -1
  24. package/dist/index.modern.mjs +3180 -981
  25. package/dist/index.modern.mjs.map +1 -1
  26. package/docs/api/README.md +56 -2
  27. package/docs/api/classes/WSAPIAvatars.md +116 -0
  28. package/docs/api/classes/WSAPIBonuses.md +50 -0
  29. package/docs/api/classes/WSAPIClans.md +66 -0
  30. package/docs/api/classes/WSAPIGamePick.md +181 -0
  31. package/docs/api/classes/WSAPIGeneral.md +63 -0
  32. package/docs/api/classes/WSAPIInbox.md +277 -0
  33. package/docs/api/classes/WSAPIJackpots.md +185 -0
  34. package/docs/api/classes/WSAPILeaderBoard.md +39 -0
  35. package/docs/api/classes/WSAPIMiniGames.md +175 -0
  36. package/docs/api/classes/WSAPIMissions.md +611 -0
  37. package/docs/api/classes/WSAPIRaffles.md +195 -0
  38. package/docs/api/classes/WSAPIStore.md +744 -0
  39. package/docs/api/classes/WSAPITournaments.md +104 -0
  40. package/docs/api/classes/WSAPIUser.md +200 -0
  41. package/docs/api/enumerations/AchievementClaimPeriodTypeId.md +13 -0
  42. package/docs/api/enumerations/BuyStoreItemErrorCode.md +32 -0
  43. package/docs/api/interfaces/ClanPrizePublicMeta.md +41 -0
  44. package/docs/api/interfaces/ClanPrizeStructureEntry.md +7 -1
  45. package/docs/api/interfaces/ClanPublicMeta.md +4 -0
  46. package/docs/api/interfaces/SAWTemplateUI.md +10 -0
  47. package/docs/api/interfaces/TAchCategory.md +19 -4
  48. package/docs/api/interfaces/TBuyStoreItemResult.md +26 -8
  49. package/docs/api/interfaces/TMissionClaimRewardResult.md +14 -3
  50. package/docs/api/interfaces/TMissionOptInResult.md +10 -3
  51. package/docs/api/interfaces/TMissionOrBadge.md +6 -2
  52. package/docs/api/interfaces/TStoreItem.md +21 -1
  53. package/docs/api/interfaces/TTournamentDetailed.md +8 -0
  54. package/docs/api/interfaces/UserAchievement.md +1 -1
  55. package/docs/ui/clans/UIGuide_getClanInfo.md +153 -0
  56. package/docs/ui/clans/UIGuide_getClans.md +172 -0
  57. package/docs/ui/clans/UIGuide_joinClan.md +196 -0
  58. package/docs/ui/missions/UIGuide_getAchCategories.md +17 -0
  59. package/docs/ui/missions/UIGuide_getBadges.md +237 -0
  60. package/docs/ui/missions/UIGuide_getMissions.md +268 -0
  61. package/docs/ui/missions/UIGuide_requestMissionClaimReward.md +21 -0
  62. package/docs/ui/missions/UIGuide_requestMissionOptIn.md +16 -0
  63. package/docs/ui/store/UIGuide_buyStoreItem.md +133 -0
  64. package/docs/ui/store/UIGuide_getStoreCategories.md +19 -0
  65. package/docs/ui/store/UIGuide_getStoreItems.md +264 -0
  66. package/docs/ui/store/UIGuide_getStorePurchasedItems.md +122 -0
  67. package/docs/ui/tournaments/UIGuide_getClanTournamentPlayers.md +140 -0
  68. package/docs/ui/tournaments/UIGuide_getTournamentInstanceInfo.md +265 -0
  69. package/docs/ui/tournaments/UIGuide_getTournamentsList.md +236 -0
  70. package/docs/ui/tournaments/UIGuide_registerInTournament.md +156 -0
  71. package/docs/ui/user/UIGuide_getLevels.md +162 -0
  72. package/docs/ui/user/UIGuide_getUserProfile.md +213 -0
  73. package/package.json +3 -3
  74. package/scripts/postdoc-cleanup.js +195 -0
  75. package/src/Missions/MissionsUtils.ts +5 -2
  76. package/src/Store/BuyStoreItemErrorCode.ts +8 -0
  77. package/src/Store/StoreItem.ts +1 -0
  78. package/src/Store/StoreItemPurchased.ts +1 -0
  79. package/src/Store/StoreItemType.ts +1 -1
  80. package/src/Tournaments/TournamentRegistrationError.ts +4 -0
  81. package/src/WSAPI/WSAPI.ts +27 -2007
  82. package/src/WSAPI/WSAPIAvatars.ts +127 -0
  83. package/src/WSAPI/WSAPIBase.ts +93 -0
  84. package/src/WSAPI/WSAPIBonuses.ts +54 -0
  85. package/src/WSAPI/WSAPIClans.ts +417 -0
  86. package/src/WSAPI/WSAPIGamePick.ts +382 -0
  87. package/src/WSAPI/WSAPIGeneral.ts +57 -0
  88. package/src/WSAPI/WSAPIInbox.ts +222 -0
  89. package/src/WSAPI/WSAPIJackpots.ts +212 -0
  90. package/src/WSAPI/WSAPILeaderBoard.ts +40 -0
  91. package/src/WSAPI/WSAPIMiniGames.ts +181 -0
  92. package/src/WSAPI/WSAPIMissions.ts +572 -0
  93. package/src/WSAPI/WSAPIRaffles.ts +175 -0
  94. package/src/WSAPI/WSAPIStore.ts +732 -0
  95. package/src/WSAPI/WSAPITournaments.ts +541 -0
  96. package/src/WSAPI/WSAPITypes.ts +145 -87
  97. package/src/WSAPI/WSAPIUser.ts +456 -0
  98. package/tsconfig.json +17 -1
  99. package/docs/api/classes/WSAPI.md +0 -1927
@@ -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,133 @@
1
+ # UI Guide — `buyStoreItem`
2
+
3
+ ## Overview
4
+ Buy is a server round-trip with side effects (DB writes, balance
5
+ deduction, reward issuance, optional CRM rules). Expected latency
6
+ 200–800ms depending on reward type. Always show an in-flight
7
+ indicator on the Buy button and disable it for the duration of the
8
+ call; never optimistically update the local balance / pool — wait
9
+ for the auto-refresh.
10
+
11
+ ## Confirm modal (recommended)
12
+ The typical UX shows a confirm modal between the item list and the
13
+ Buy click: tapping a card opens the item detail modal which displays
14
+ the item image, name, full description, price, the user's current
15
+ balance, and the Buy button. The Buy button on the **card itself**
16
+ is optional; many implementations only show it inside the detail
17
+ modal. This serves both as a confirmation step and as the natural
18
+ place to render insufficient-balance / locked / sold-out messages
19
+ next to the action.
20
+
21
+ ## Buy button decision matrix
22
+
23
+ Apply in priority order; **first match wins**. The state checks all
24
+ derive from a single `TStoreItem` (from `getStoreItems()`) plus the
25
+ user's current balance (from user properties).
26
+
27
+ 1. `pool != null && pool <= 0` → **disabled "Sold Out" button** (or
28
+ hide the Buy button and show an out-of-stock badge). Auto-refresh
29
+ will update the state if stock is restored.
30
+ 2. `active_till_date && Date.now() >= active_till_date` →
31
+ **disabled "Expired" button**. Show the formatted expiry date.
32
+ 3. `can_buy === false` → **disabled Buy button**. Surface
33
+ `cant_buy_message` (operator-defined) if set; otherwise a
34
+ generic "Not available" caption. This catches segment locks
35
+ and operator-set restrictions.
36
+ 4. User balance for the item's `purchase_type` is less than the
37
+ effective price (`discounted_price ?? price`) →
38
+ **disabled "Insufficient balance" button**. Show how many
39
+ units of the currency are missing (e.g. "120 points needed").
40
+ The button label can stay "Buy" but with a disabled visual.
41
+ 5. A purchase is currently in flight for this item (local flag) →
42
+ **Buy button with loading indicator**; ignore additional clicks.
43
+ 6. None of the above → **enabled Buy button** labelled e.g. "Buy"
44
+ with the price + currency icon (points / gems / diamonds) as a
45
+ stamp. On click: call `buyStoreItem(item.id)`; set the local
46
+ in-flight flag.
47
+
48
+ Variants by `purchase_type`:
49
+ - `'points'` — show the points icon next to the price.
50
+ - `'gems'` — show the gems icon.
51
+ - `'diamonds'` — show the diamonds icon.
52
+
53
+ If `discounted_price` is set, render both prices: the original
54
+ `price` with a strikethrough and the `discounted_price` highlighted.
55
+
56
+ ## In-flight UX
57
+ - Replace the Buy button label with a loading dots / spinner
58
+ animation while the promise is pending. Keep the button visually
59
+ "pressed" / disabled.
60
+ - Do NOT close the detail modal during the call — closing risks the
61
+ user double-clicking after re-opening.
62
+
63
+ ## Success UX
64
+ On `err_code === 0`:
65
+ - Close the detail modal.
66
+ - Show a success toast (e.g. "Item purchased successfully"). The
67
+ toast is the primary feedback — there is no dedicated success
68
+ modal for the generic case.
69
+ - Do NOT manually re-fetch `getStoreItems()` — the auto-refresh
70
+ fires.
71
+ - Reward-type-specific celebrations (e.g. opening a mini-game spin
72
+ immediately after a `'minigamespin'` purchase, navigating to the
73
+ bonus screen after a bonus purchase) are application choices and
74
+ not enforced by the SDK.
75
+
76
+ ## Error UX per code
77
+ - For `11006` (cap reached): prefer the item's `limit_message`
78
+ operator copy over `err_message`.
79
+ - For `11014` (time-window): prefer the item's `purchase_limit_message`
80
+ operator copy over `err_message`. Both are localized, operator-tuned
81
+ strings meant for the user.
82
+ - For `11009` (sold out): show a dedicated "sold out" message.
83
+ - For `11004`: show a localized "try again later" / "not eligible"
84
+ message; the raw `err_message` is rarely user-friendly.
85
+ - For all other non-zero codes: fall back to `err_message`, or to
86
+ a generic "Something went wrong. Try again later." if `err_message`
87
+ is empty.
88
+ - Render the error in a dedicated error modal (closing the item
89
+ detail modal first) or as an inline message inside the detail
90
+ modal — both patterns are valid; the dedicated modal is the
91
+ reference implementation.
92
+
93
+ ## Status-specific visual treatments on the item card
94
+ - `pool != null && pool <= 0` → grey-out overlay + "Out of Stock"
95
+ caption. When operator-enabled, unavailable items can be visually
96
+ greyed out entirely.
97
+ - `can_buy === false` → optional "cant_buy" visual treatment
98
+ (border / icon) + tooltip showing `cant_buy_message`.
99
+ - `active_till_date` set → live-updating countdown overlay,
100
+ format `DD:HH:MM:SS` (see below). Hide once expired and replace
101
+ with an "Expired" badge.
102
+ - `discounted_price` set → discount ribbon (corner overlay) showing
103
+ the percent or a custom ribbon image.
104
+ - `purchased_today` / `purchased_this_week` / `purchased_this_month`
105
+ true → optional "purchased recently" badge; useful for items
106
+ with a per-period cap, hints at why the Buy button might be
107
+ disabled.
108
+
109
+ ## Countdown format
110
+ For items with `active_till_date`:
111
+ - Format `DD:HH:MM:SS`, each segment zero-padded to 2 digits.
112
+ - Update cadence: 1 second.
113
+ - Once `Date.now() >= active_till_date`, hide the countdown and
114
+ mark the item as expired (disabled Buy button, "Expired" badge).
115
+
116
+ ## Animations
117
+ - In-flight: dots / spinner animation on the Buy button.
118
+ - Success: a celebratory animation (confetti, coin shower) for
119
+ high-value items is a common pattern but not enforced by the SDK.
120
+ The default minimal UX is the success toast.
121
+
122
+ ## Mobile vs desktop
123
+ The buy flow is identical on mobile and desktop; the layout
124
+ differences live in the parent list view (see `getStoreItems` for
125
+ grid / row variants). The detail modal and Buy button behaviour
126
+ are the same on both.
127
+
128
+ ## Empty states
129
+ Not applicable to this method (returns a single result). For the
130
+ list-level empty / loading / error states, see the `getStoreItems`
131
+ documentation.
132
+
133
+ **Visitor mode**: not supported.