@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.
- package/.nvmrc +1 -1
- package/README.md +31 -2
- 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 +78 -0
- package/dist/WSAPI/WSAPIBase.d.ts +71 -0
- package/dist/WSAPI/WSAPIBonuses.d.ts +26 -0
- package/dist/WSAPI/WSAPIClans.d.ts +388 -0
- package/dist/WSAPI/WSAPIGamePick.d.ts +308 -0
- package/dist/WSAPI/WSAPIGeneral.d.ts +30 -0
- package/dist/WSAPI/WSAPIInbox.d.ts +126 -0
- package/dist/WSAPI/WSAPIJackpots.d.ts +109 -0
- package/dist/WSAPI/WSAPILeaderBoard.d.ts +25 -0
- package/dist/WSAPI/WSAPIMiniGames.d.ts +94 -0
- package/dist/WSAPI/WSAPIMissions.d.ts +517 -0
- package/dist/WSAPI/WSAPIRaffles.d.ts +119 -0
- package/dist/WSAPI/WSAPIStore.d.ts +656 -0
- package/dist/WSAPI/WSAPITournaments.d.ts +501 -0
- package/dist/WSAPI/WSAPITypes.d.ts +145 -85
- package/dist/WSAPI/WSAPIUser.d.ts +383 -0
- package/dist/index.js +3818 -1528
- package/dist/index.js.map +1 -1
- package/dist/index.modern.mjs +3180 -981
- package/dist/index.modern.mjs.map +1 -1
- package/docs/api/README.md +56 -2
- package/docs/api/classes/WSAPIAvatars.md +116 -0
- package/docs/api/classes/WSAPIBonuses.md +50 -0
- package/docs/api/classes/WSAPIClans.md +66 -0
- package/docs/api/classes/WSAPIGamePick.md +181 -0
- package/docs/api/classes/WSAPIGeneral.md +63 -0
- package/docs/api/classes/WSAPIInbox.md +277 -0
- package/docs/api/classes/WSAPIJackpots.md +185 -0
- package/docs/api/classes/WSAPILeaderBoard.md +39 -0
- package/docs/api/classes/WSAPIMiniGames.md +175 -0
- package/docs/api/classes/WSAPIMissions.md +611 -0
- package/docs/api/classes/WSAPIRaffles.md +195 -0
- package/docs/api/classes/WSAPIStore.md +744 -0
- package/docs/api/classes/WSAPITournaments.md +104 -0
- package/docs/api/classes/WSAPIUser.md +200 -0
- package/docs/api/enumerations/AchievementClaimPeriodTypeId.md +13 -0
- package/docs/api/enumerations/BuyStoreItemErrorCode.md +32 -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/SAWTemplateUI.md +10 -0
- package/docs/api/interfaces/TAchCategory.md +19 -4
- package/docs/api/interfaces/TBuyStoreItemResult.md +26 -8
- package/docs/api/interfaces/TMissionClaimRewardResult.md +14 -3
- package/docs/api/interfaces/TMissionOptInResult.md +10 -3
- package/docs/api/interfaces/TMissionOrBadge.md +6 -2
- package/docs/api/interfaces/TStoreItem.md +21 -1
- package/docs/api/interfaces/TTournamentDetailed.md +8 -0
- package/docs/api/interfaces/UserAchievement.md +1 -1
- 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/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/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_getLevels.md +162 -0
- package/docs/ui/user/UIGuide_getUserProfile.md +213 -0
- package/package.json +3 -3
- package/scripts/postdoc-cleanup.js +195 -0
- package/src/Missions/MissionsUtils.ts +5 -2
- 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 +127 -0
- package/src/WSAPI/WSAPIBase.ts +93 -0
- package/src/WSAPI/WSAPIBonuses.ts +54 -0
- package/src/WSAPI/WSAPIClans.ts +417 -0
- package/src/WSAPI/WSAPIGamePick.ts +382 -0
- package/src/WSAPI/WSAPIGeneral.ts +57 -0
- package/src/WSAPI/WSAPIInbox.ts +222 -0
- package/src/WSAPI/WSAPIJackpots.ts +212 -0
- package/src/WSAPI/WSAPILeaderBoard.ts +40 -0
- package/src/WSAPI/WSAPIMiniGames.ts +181 -0
- package/src/WSAPI/WSAPIMissions.ts +572 -0
- package/src/WSAPI/WSAPIRaffles.ts +175 -0
- package/src/WSAPI/WSAPIStore.ts +732 -0
- package/src/WSAPI/WSAPITournaments.ts +541 -0
- package/src/WSAPI/WSAPITypes.ts +145 -87
- package/src/WSAPI/WSAPIUser.ts +456 -0
- package/tsconfig.json +17 -1
- package/docs/api/classes/WSAPI.md +0 -1927
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# UI Guide — `getTournamentInstanceInfo`
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
- Powers the **tournament detail / lobby screen** — the surface a user
|
|
5
|
+
lands on after picking an item from
|
|
6
|
+
[`getTournamentsList`](../../api/classes/WSAPITournaments.md#gettournamentslist).
|
|
7
|
+
- One-shot fetch. There is no subscription and no client cache.
|
|
8
|
+
Re-call to refresh; the default Smartico UI polls every 3 s while
|
|
9
|
+
the detail view is open.
|
|
10
|
+
- For a clan tournament (`is_clan_based === true`), the response also
|
|
11
|
+
carries clan-level data (`clan_leaderboard[]`,
|
|
12
|
+
`clan_prize_structure[]`, `user_clan_id`).
|
|
13
|
+
|
|
14
|
+
## Detail view layout
|
|
15
|
+
|
|
16
|
+
Top-to-bottom layout (desktop):
|
|
17
|
+
|
|
18
|
+
1. **Header image** — `image2` (920×200 px) rendered as
|
|
19
|
+
`background-image` on the header block; falls back to `image1` if
|
|
20
|
+
missing.
|
|
21
|
+
2. **Tournament name + back affordance** — above the image (desktop)
|
|
22
|
+
or overlaid (mobile).
|
|
23
|
+
3. **Countdown ticker** — `DD:HH:MM:SS` live ticker. Counts to
|
|
24
|
+
`end_time` while `is_in_progress`; to `start_time` while
|
|
25
|
+
`is_upcoming`. Hidden when `is_finished` / `is_cancelled`.
|
|
26
|
+
Updates every 1 second.
|
|
27
|
+
4. **Info row** — date range, buy-in, registration count
|
|
28
|
+
(`registration_count / players_max_count`), duration. On desktop,
|
|
29
|
+
this lives inside the header image; on mobile it sits below.
|
|
30
|
+
5. **Registration CTA** — see "Registration CTA" below.
|
|
31
|
+
6. **Tab strip** — General · Players (or ClanBoard) · Prizes ·
|
|
32
|
+
RelatedGames (when non-empty).
|
|
33
|
+
7. **Active tab content** — see per-tab sections below.
|
|
34
|
+
8. **Sidebar (desktop only)** — if `related_games?.length > 0`,
|
|
35
|
+
render the related-games list; otherwise render a "Prizes
|
|
36
|
+
overview" panel.
|
|
37
|
+
|
|
38
|
+
Mobile layout collapses the sidebar into a tab (`RelatedGames`) and
|
|
39
|
+
moves the tournament name into the header overlay.
|
|
40
|
+
|
|
41
|
+
## Header image specs
|
|
42
|
+
|
|
43
|
+
| Field | Source size | Used where | Fallback |
|
|
44
|
+
|---|---|---|---|
|
|
45
|
+
| `image2` | 920×200 px | Desktop header background | Falls back to `image1` (544×216 px) |
|
|
46
|
+
| `image2_mobile` | 720×400 px | Mobile header background | Falls back to `image1` |
|
|
47
|
+
|
|
48
|
+
Render as CSS `background-image`, not `<img>`. No built-in placeholder
|
|
49
|
+
— provide a neutral fallback color/illustration if all three are
|
|
50
|
+
missing.
|
|
51
|
+
|
|
52
|
+
## Registration CTA
|
|
53
|
+
|
|
54
|
+
Same rules as the card-level CTA in
|
|
55
|
+
[`UIGuide_getTournamentsList`](./UIGuide_getTournamentsList.md), but
|
|
56
|
+
this time clicking it actually **invokes registration** via
|
|
57
|
+
[`registerInTournament`](../../api/classes/WSAPITournaments.md#registerintournament)
|
|
58
|
+
rather than opening the detail view (you're already in it).
|
|
59
|
+
|
|
60
|
+
| Condition | CTA label | Action |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `is_can_register === true` (no clan constraint) | "Join tournament" | Call `registerInTournament(instance_id)`; show loading state while the promise is pending |
|
|
63
|
+
| `is_can_register === true` AND `is_clan_based === true` AND `user_clan_id` is null | "Join tournament" | First prompt the user to pick a clan ([`joinClan`](../../api/classes/WSAPIClans.md#joinclan)), then call `registerInTournament` |
|
|
64
|
+
| `registration_status === 'REGISTERED'` (before start) | "You are registered" | Disabled / informational |
|
|
65
|
+
| `registration_status === 'REGISTERED'` AND `is_finished` | "You are registered" | Disabled / informational |
|
|
66
|
+
| `registration_status === 'PENDING'` | "Pending approval" | Disabled |
|
|
67
|
+
| `registration_status === 'REGISTERED_PENDING_QUALIFICATION'` | "Pending qualification" | Disabled |
|
|
68
|
+
| `registration_type === 'AUTO'` AND active | "Automatic registration" | Disabled / informational |
|
|
69
|
+
| Cancelled / expired / segment-blocked | "Registration closed" | Disabled |
|
|
70
|
+
|
|
71
|
+
For segment-blocked tournaments where the user fails entry conditions,
|
|
72
|
+
surface `segment_dont_match_message` (operator-supplied) below the
|
|
73
|
+
CTA or in a tooltip on hover.
|
|
74
|
+
|
|
75
|
+
## Tabs
|
|
76
|
+
|
|
77
|
+
| Tab | When shown | Content source |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| **General / Info** | Always | `description` HTML (sanitize before injecting) + optional `hint_text` (T&C) |
|
|
80
|
+
| **Players** | `is_clan_based === false` | `players[]` — individual leaderboard |
|
|
81
|
+
| **ClanBoard** | `is_clan_based === true` (replaces Players) | `clan_leaderboard[]` — clan leaderboard |
|
|
82
|
+
| **Prizes** | Always | `prizes[]` (non-clan) or `clan_prize_structure[]` (clan) |
|
|
83
|
+
| **Related games** | `related_games?.length > 0` AND mobile (desktop renders this in the sidebar) | `related_games[]` |
|
|
84
|
+
|
|
85
|
+
Default selected tab: General.
|
|
86
|
+
|
|
87
|
+
## Player leaderboard (non-clan)
|
|
88
|
+
|
|
89
|
+
Sourced from `players[]`. Columns:
|
|
90
|
+
|
|
91
|
+
| Column | Source | Notes |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| Position | `player.position`, zero-padded (`01`, `09`, `10`, …) | Show `'-'` when tournament status is REGISTER (no one has scored yet) OR `player.position === null` |
|
|
94
|
+
| Avatar | `player.avatar_url` (CDN-resized; 128×128 typical) | Operator setting `config.hide_avatars_leaderboards` may suppress |
|
|
95
|
+
| Username | `player.public_username` | |
|
|
96
|
+
| Score | `player.scores` | Hidden on rows where `is_me === false` if operator setting `show_other_users_score === false`. Always shown for `me`. |
|
|
97
|
+
|
|
98
|
+
**Top-3 styling**: rows where `position <= 3` get optional podium
|
|
99
|
+
treatment (gold / silver / bronze background or accent). CSS classes
|
|
100
|
+
in the default Smartico UI: `place-1`, `place-2`, `place-3`.
|
|
101
|
+
|
|
102
|
+
**"Me" row**: when `player.is_me === true`, highlight the row (e.g.
|
|
103
|
+
`place-my` class — background tint, slightly larger font). The user's
|
|
104
|
+
position is also surfaced separately in the dedicated "me" panel
|
|
105
|
+
below the leaderboard (see "`me` panel").
|
|
106
|
+
|
|
107
|
+
**Empty state**: when `players[]` is empty (e.g. tournament hasn't
|
|
108
|
+
started yet, no scores recorded), render an empty-state illustration
|
|
109
|
+
with copy like "No players yet" or "Be the first to register".
|
|
110
|
+
|
|
111
|
+
## Clan leaderboard (clan tournaments)
|
|
112
|
+
|
|
113
|
+
Sourced from `clan_leaderboard[]`, filtered to entries where
|
|
114
|
+
`contributing_members > 0`. Each row:
|
|
115
|
+
|
|
116
|
+
| Element | Source |
|
|
117
|
+
|---|---|
|
|
118
|
+
| Position badge | `clan.position` — podium styling for 1/2/3 |
|
|
119
|
+
| Clan image | `clan.public_meta.image_url`; fallback to first-letter avatar |
|
|
120
|
+
| Clan name | `clan.public_meta.name` |
|
|
121
|
+
| "Your clan" badge | If `clan.clan_id === user_clan_id`, add a "Your clan" pill |
|
|
122
|
+
| Contributing members | `clan.contributing_members` |
|
|
123
|
+
| Total score | `clan.total_score`, space-formatted (`1 234 567`) + "pts" suffix |
|
|
124
|
+
|
|
125
|
+
**User's clan highlight**: row gets a distinct background when
|
|
126
|
+
`clan.clan_id === user_clan_id`.
|
|
127
|
+
|
|
128
|
+
**Sticky "my clan" footer**: when `clan_leaderboard.length >= 5` and
|
|
129
|
+
`user_clan_id` is set, pin the user's clan row at the bottom of the
|
|
130
|
+
scrollable list as a sticky footer.
|
|
131
|
+
|
|
132
|
+
**Clan row click** opens a modal showing that clan's individual
|
|
133
|
+
player breakdown via
|
|
134
|
+
[`getClanTournamentPlayers`](../../api/classes/WSAPITournaments.md#getclantournamentplayers).
|
|
135
|
+
|
|
136
|
+
**Empty state**: render a Lottie animation (or static illustration) +
|
|
137
|
+
"No leaders" copy.
|
|
138
|
+
|
|
139
|
+
## `me` panel
|
|
140
|
+
|
|
141
|
+
When `detail.me` is populated, render a **sticky "me" panel** below
|
|
142
|
+
(or alongside) the leaderboard with:
|
|
143
|
+
|
|
144
|
+
- Rank badge — `me.position` (or `'-'` if not yet ranked)
|
|
145
|
+
- Avatar — `me.avatar_url`
|
|
146
|
+
- Username — `me.public_username`
|
|
147
|
+
- Score — `me.scores` (always shown, regardless of
|
|
148
|
+
`show_other_users_score`)
|
|
149
|
+
|
|
150
|
+
This panel is **not** rendered when `me` is undefined (visitor mode,
|
|
151
|
+
unregistered users, or registered users with no recorded score yet).
|
|
152
|
+
|
|
153
|
+
The `user_position_in_clan` and `user_score_in_clan` fields on the
|
|
154
|
+
response are not rendered by the default Smartico UI but are
|
|
155
|
+
available on `TTournamentDetailed` if your custom UI needs them.
|
|
156
|
+
|
|
157
|
+
## Prize structure
|
|
158
|
+
|
|
159
|
+
### Non-clan tournaments — `prizes[]`
|
|
160
|
+
|
|
161
|
+
Render as a ranked table. Each row:
|
|
162
|
+
|
|
163
|
+
- **Place range**: `place_from` – `place_to`; if equal, render the
|
|
164
|
+
single value (e.g. `1st place`); otherwise a range (e.g.
|
|
165
|
+
`2nd–5th place`).
|
|
166
|
+
- **Prize image**: `prizes[i].image_url` (1:1 aspect ratio).
|
|
167
|
+
- **Prize description**: derived from `type` + `points`:
|
|
168
|
+
- `'POINTS_ADD'` → "{points} pts"
|
|
169
|
+
- `'TANGIBLE'` / `'BONUS'` / `'MINI_GAME_ATTEMPT'` → `name`
|
|
170
|
+
- Other types → `name` fallback
|
|
171
|
+
|
|
172
|
+
### Clan tournaments — `clan_prize_structure[]`
|
|
173
|
+
|
|
174
|
+
More complex — render as accordions, one per `clan_place` entry:
|
|
175
|
+
|
|
176
|
+
- **Group header**: `<ordinal> Place` for clan placement (e.g.
|
|
177
|
+
`1st place`, `2nd place`). Overridable by
|
|
178
|
+
`clan_place_entry.public_meta.prize_name`.
|
|
179
|
+
- **Prize type label**:
|
|
180
|
+
- `prize_type_id === 1` (Fixed) → "Fixed prizes"
|
|
181
|
+
- `prize_type_id === 2` (Dynamic) → "Dynamic prizes" (uses
|
|
182
|
+
`prize_pool_amount`)
|
|
183
|
+
- **Per-tier rows** (from `tiers[]` inside each clan_place):
|
|
184
|
+
- Player place range (`player_place_from` – `player_place_to`)
|
|
185
|
+
- Tier image — `tier.public_meta.image_url` (optional)
|
|
186
|
+
- Prize amount derived from `prize_type_id` + `distribution_type`:
|
|
187
|
+
- Fixed → render `public_meta.name` (or points / gems / diamonds
|
|
188
|
+
from `details_json`)
|
|
189
|
+
- Dynamic + `distribution_type === 1` (ScoreWeighted) → render
|
|
190
|
+
`pool_amount` as "total pool" with "Score-weighted split"
|
|
191
|
+
secondary label
|
|
192
|
+
- Dynamic + `distribution_type === 2` (EqualSplit) → render
|
|
193
|
+
`pool_amount / range_size` as "avg per player" with "equal
|
|
194
|
+
split" secondary label
|
|
195
|
+
|
|
196
|
+
The default Smartico UI uses a `compact` variant for mobile that
|
|
197
|
+
collapses each clan_place group into a single line.
|
|
198
|
+
|
|
199
|
+
## Countdown ticker
|
|
200
|
+
|
|
201
|
+
`DD:HH:MM:SS` exact-digit format with 1-second tick. Each segment
|
|
202
|
+
in its own `<span>` for styling; RTL-aware (segment order reverses
|
|
203
|
+
in right-to-left locales).
|
|
204
|
+
|
|
205
|
+
Timing source:
|
|
206
|
+
- `is_upcoming` → counts down to `start_time`
|
|
207
|
+
- `is_in_progress` → counts down to `end_time`
|
|
208
|
+
- `is_finished` / `is_cancelled` → ticker hidden
|
|
209
|
+
|
|
210
|
+
When the countdown reaches zero, don't auto-flip the UI state — wait
|
|
211
|
+
for the next poll-driven refresh to pick up the lifecycle transition.
|
|
212
|
+
(The detail-info call doesn't push; lifecycle reads come from polling.)
|
|
213
|
+
|
|
214
|
+
## Empty / loading / error states
|
|
215
|
+
|
|
216
|
+
- **Loading (first fetch)**: render a skeleton layout — header
|
|
217
|
+
placeholder, blank tab strip, shimmer rows in the active tab area.
|
|
218
|
+
Don't render `null` (avoid a layout jump when data arrives).
|
|
219
|
+
- **Loading (poll refresh)**: keep the prior snapshot visible; do not
|
|
220
|
+
blank the UI. Stale state for ≤3 s is fine.
|
|
221
|
+
- **`players[]` empty**: empty-state illustration with copy like
|
|
222
|
+
"No players yet". Common when the tournament is upcoming and no
|
|
223
|
+
one has registered yet.
|
|
224
|
+
- **`clan_leaderboard[]` empty**: Lottie animation + "No leaders"
|
|
225
|
+
text.
|
|
226
|
+
- **Error**: keep last snapshot, show a small non-blocking error
|
|
227
|
+
banner, retry on next poll tick. If the first fetch fails, show a
|
|
228
|
+
full-screen "Failed to load — Try again" with a retry button.
|
|
229
|
+
|
|
230
|
+
## Animations / transitions
|
|
231
|
+
|
|
232
|
+
- **Tab switch**: cross-fade content (~150 ms).
|
|
233
|
+
- **Leaderboard position change**: when a player's `position` shifts
|
|
234
|
+
between polls (detect by diffing the prior snapshot), animate the
|
|
235
|
+
row to its new position (slide / FLIP animation). Helps users see
|
|
236
|
+
live movement.
|
|
237
|
+
- **Countdown final 10 s**: optional pulse / color change on the
|
|
238
|
+
countdown digits.
|
|
239
|
+
|
|
240
|
+
## Mobile vs desktop
|
|
241
|
+
|
|
242
|
+
- **Header**: desktop renders tournament name above the image and
|
|
243
|
+
info blocks (buy-in / registration / duration) inside the image;
|
|
244
|
+
mobile overlays name inside the image and moves info blocks below.
|
|
245
|
+
- **Image source**: desktop uses `image2`, mobile uses
|
|
246
|
+
`image2_mobile`; both fall back to `image1`.
|
|
247
|
+
- **Tab strip**: desktop shows all 3–4 tabs; mobile drops the
|
|
248
|
+
RelatedGames tab if there are no related games (and the sidebar
|
|
249
|
+
becomes an in-tab section on mobile).
|
|
250
|
+
- **Clan prize structure**: desktop uses the full accordion; mobile
|
|
251
|
+
uses a compact variant.
|
|
252
|
+
- **Leaderboard**: desktop shows full 4-column rows; mobile may
|
|
253
|
+
collapse avatar + username into a single column to save horizontal
|
|
254
|
+
space.
|
|
255
|
+
|
|
256
|
+
## Performance
|
|
257
|
+
|
|
258
|
+
- Diff snapshots between polls to detect position changes and animate
|
|
259
|
+
only the affected rows. Avoid full re-renders of the leaderboard
|
|
260
|
+
table on every poll tick.
|
|
261
|
+
- Virtualize the player list if `players.length > 100` (uncommon —
|
|
262
|
+
the server usually returns a top-N slice).
|
|
263
|
+
- Stop polling when the detail view is no longer visible
|
|
264
|
+
(`IntersectionObserver` or your router-driven unmount). Each poll
|
|
265
|
+
is a real network round-trip.
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# UI Guide — `getTournamentsList`
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
- The list is the lobby surface — designed for a tabbed grid where each
|
|
5
|
+
card opens a detail view (powered by
|
|
6
|
+
[`getTournamentInstanceInfo`](../../api/classes/WSAPITournaments.md#gettournamentinstanceinfo)).
|
|
7
|
+
- Register `onUpdate` on first render; treat each invocation as
|
|
8
|
+
"discard prior list, re-render from this array". `onUpdate` fires
|
|
9
|
+
only after `registerInTournament` resolves — lifecycle transitions
|
|
10
|
+
(start/finish/cancel) don't push.
|
|
11
|
+
- Loading indicator: the first call is a server round-trip
|
|
12
|
+
(typically 100–500 ms); subsequent calls within the 30 s cache window
|
|
13
|
+
resolve effectively synchronously.
|
|
14
|
+
|
|
15
|
+
## List view organization
|
|
16
|
+
|
|
17
|
+
The default Smartico UI groups tournaments into category tabs. A single
|
|
18
|
+
tournament can appear in multiple tabs simultaneously.
|
|
19
|
+
|
|
20
|
+
| Tab | Assignment rule | Sort |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| **Overview** (default) | `is_in_progress` OR `is_user_registered` OR `is_can_register` OR `is_upcoming` — i.e. anything not finished/cancelled | Featured pinned first; then by `start_time` ASC for upcoming, registered/registrable next |
|
|
23
|
+
| **MyTournaments** | `is_user_registered === true` | Insertion order |
|
|
24
|
+
| **InProgress** | `is_in_progress === true` | Insertion order |
|
|
25
|
+
| **Upcoming** | `is_upcoming === true` | `start_time` ASC |
|
|
26
|
+
| **Finished** | `is_finished === true` | Insertion order (server returns newest finished first) |
|
|
27
|
+
| **Top** | `is_can_register === true` | Featured pinned first |
|
|
28
|
+
|
|
29
|
+
**Featured pinning**: tournaments with `is_featured === true` AND
|
|
30
|
+
`is_cancelled === false` get moved to index 0 in the Overview and Top
|
|
31
|
+
tabs only. No visual difference on the card itself — just position.
|
|
32
|
+
|
|
33
|
+
**Default visible tabs**:
|
|
34
|
+
- Desktop: Overview · MyTournaments · InProgress · Finished
|
|
35
|
+
- Mobile: Overview · MyTournaments · InProgress
|
|
36
|
+
|
|
37
|
+
**Custom section filtering**: if your UI scopes the lobby to a
|
|
38
|
+
specific custom section (e.g. a deep-link `?custom_section_id=42`),
|
|
39
|
+
filter to tournaments whose `custom_section_id` matches; the SDK does
|
|
40
|
+
not filter for you.
|
|
41
|
+
|
|
42
|
+
**Bucketing helper** (raw-state to bucket — for reference):
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
function bucket(t: TTournament) {
|
|
46
|
+
if (t.is_in_progress) return 'live';
|
|
47
|
+
if (t.is_user_registered && !t.is_finished) return 'mine';
|
|
48
|
+
if (t.is_can_register) return 'available';
|
|
49
|
+
if (t.is_upcoming) return 'upcoming';
|
|
50
|
+
if (t.is_finished) return 'finished';
|
|
51
|
+
if (t.is_cancelled) return 'cancelled';
|
|
52
|
+
return 'other';
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Drive UI tabs from the boolean flags directly. Avoid recomputing
|
|
57
|
+
state from `start_time` / `end_time` / `registration_status` — the
|
|
58
|
+
SDK already encodes the canonical lifecycle.
|
|
59
|
+
|
|
60
|
+
## Tournament card / tile
|
|
61
|
+
|
|
62
|
+
Fields rendered on the card (top-to-bottom):
|
|
63
|
+
|
|
64
|
+
- **Background image** — `image1`, documented source 544×216 px.
|
|
65
|
+
Render at a 16:9-ish aspect ratio with `background-image`. No
|
|
66
|
+
built-in placeholder — provide a neutral fallback if missing.
|
|
67
|
+
- **Status badge** — top-left, color-coded by lifecycle state.
|
|
68
|
+
See "Status-specific visual treatments" below.
|
|
69
|
+
- **Clan badge** — appended to the status block when
|
|
70
|
+
`is_clan_based === true`.
|
|
71
|
+
- **Countdown line** — relative time string driven by `start_time`
|
|
72
|
+
(upcoming) or `end_time` (in-progress / finished). See "Countdown
|
|
73
|
+
/ timing format".
|
|
74
|
+
- **Tournament name** — `name`, prominent.
|
|
75
|
+
- **Ribbon** — `ribbon` field. Presets (`'sale'`, `'hot'`, `'new'`,
|
|
76
|
+
`'vip'`) are CSS classes; a custom URL (250×300 px) renders as an
|
|
77
|
+
image overlay top-right.
|
|
78
|
+
- **Footer row** (3 columns on desktop, may collapse on mobile):
|
|
79
|
+
- Registration count: `registration_count` / `players_max_count`
|
|
80
|
+
- Buy-in: derived from `registration_cost_points` /
|
|
81
|
+
`registration_cost_gems` / `registration_cost_diamonds` (only
|
|
82
|
+
one is set per tournament) — show "Free" if all are falsy.
|
|
83
|
+
`custom_price_text` (operator-supplied string) overrides if set.
|
|
84
|
+
- Prize pool: `prize_pool_short` if set, else a derived label
|
|
85
|
+
from `prizes[]` (or "Mixed" / "—" as fallback).
|
|
86
|
+
- **CTA button** — see "Action button decision matrix".
|
|
87
|
+
|
|
88
|
+
**Mobile card variant**: ribbon renders ABOVE the image (not as an
|
|
89
|
+
overlay); footer typically collapses to inline buy-in/prize line.
|
|
90
|
+
|
|
91
|
+
**Whole-card click** opens the detail view via
|
|
92
|
+
[`getTournamentInstanceInfo`](../../api/classes/WSAPITournaments.md#gettournamentinstanceinfo);
|
|
93
|
+
the CTA button click triggers the same detail-view open (it does NOT
|
|
94
|
+
invoke `registerInTournament` from the card — registration is always
|
|
95
|
+
performed from inside the detail view).
|
|
96
|
+
|
|
97
|
+
**Fields NOT on the card** (detail-view-only):
|
|
98
|
+
- `description` (HTML), full `prizes[]` table, `me` block, full player
|
|
99
|
+
leaderboard (via `getTournamentInstanceInfo`), clan leaderboard,
|
|
100
|
+
`related_games`, `min_scores_win`.
|
|
101
|
+
|
|
102
|
+
## Action button decision matrix
|
|
103
|
+
|
|
104
|
+
CTA label is driven by `is_can_register`, then by
|
|
105
|
+
`registration_status`. Resolve in priority order — first match wins.
|
|
106
|
+
|
|
107
|
+
| Condition | CTA label | Enabled? |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| `is_can_register === true` | "Join tournament" | Enabled — opens detail view |
|
|
110
|
+
| `registration_status === 'REGISTERED'` AND not yet started | "You are registered" | Disabled (informational) |
|
|
111
|
+
| `registration_status === 'REGISTERED'` AND `is_finished` | "You are registered" | Disabled (informational) |
|
|
112
|
+
| `registration_status === 'PENDING'` | "Pending approval" | Disabled |
|
|
113
|
+
| `registration_status === 'REGISTERED_PENDING_QUALIFICATION'` | "Pending qualification" | Disabled |
|
|
114
|
+
| `registration_type === 'AUTO'` AND tournament active | "Automatic registration" | Disabled (informational) |
|
|
115
|
+
| `is_clan_based` AND user has no clan | "Registration closed" | Disabled |
|
|
116
|
+
| Everything else (cancelled, expired, segment-blocked, max reached, etc.) | "Registration closed" | Disabled |
|
|
117
|
+
|
|
118
|
+
When CTA is "Registration closed" and the user fails segment
|
|
119
|
+
conditions, surface `segment_dont_match_message` (operator-supplied)
|
|
120
|
+
inside the detail view, not on the card.
|
|
121
|
+
|
|
122
|
+
The CTA button is also part of the card click target — clicking it
|
|
123
|
+
opens the detail view rather than invoking registration directly.
|
|
124
|
+
Registration only happens from the detail-view CTA.
|
|
125
|
+
|
|
126
|
+
## Image / asset specs
|
|
127
|
+
|
|
128
|
+
| Field | Documented source | Aspect ratio | Used where | Fallback |
|
|
129
|
+
|---|---|---|---|---|
|
|
130
|
+
| `image1` | 544×216 px | ~5:2 (landscape banner) | Card grid background | Neutral placeholder if missing |
|
|
131
|
+
| `image2` | 920×200 px | ~4.6:1 | Desktop lobby-detail header (rendered by detail view, not card) | Falls back to `image1` |
|
|
132
|
+
| `image2_mobile` | 720×400 px | 9:5 | Mobile lobby-detail header | Falls back to `image1` |
|
|
133
|
+
| `ribbon` (custom URL) | 250×300 px | 5:6 (portrait) | Card overlay | Hide ribbon if URL fails |
|
|
134
|
+
| `prizes[].image_url` | 1:1 square | 1:1 | Detail-view prize table only | Hide image if missing |
|
|
135
|
+
|
|
136
|
+
Do not render `image2` / `image2_mobile` on the card — they're sized
|
|
137
|
+
for the detail-view header.
|
|
138
|
+
|
|
139
|
+
## Status-specific visual treatments
|
|
140
|
+
|
|
141
|
+
Drive from the lifecycle booleans and `registration_status`. Recommended
|
|
142
|
+
treatments:
|
|
143
|
+
|
|
144
|
+
| State | Card visual | Badge text |
|
|
145
|
+
|---|---|---|
|
|
146
|
+
| `is_upcoming` (PUBLISHED) | Full-color card | "New" |
|
|
147
|
+
| `is_upcoming` (REGISTER — accepting registrations) | Full-color card, "live registration" pulse on the CTA | "Gathering" |
|
|
148
|
+
| `is_in_progress` | Full-color card, optional shimmer/glow accent | "Started" / "Live" |
|
|
149
|
+
| `is_finished` | Subtle desaturation (e.g. 80% opacity), no shimmer | "Finished" |
|
|
150
|
+
| `is_cancelled` | Status badge collapses / hidden; card itself may be hidden by the consumer's tab logic | (none — badge hidden) |
|
|
151
|
+
| `is_user_registered && !is_finished` | Color-restored card, add a "Registered" check-mark overlay | derived from `registration_status` |
|
|
152
|
+
|
|
153
|
+
The default Smartico UI collapses the cancelled card's status block to
|
|
154
|
+
`height: 10 px` to keep layout consistent without surfacing the
|
|
155
|
+
"Cancelled" label prominently — many consumers prefer to hide cancelled
|
|
156
|
+
items entirely.
|
|
157
|
+
|
|
158
|
+
**Clan tournaments**: append a "Clan" pill next to the status badge
|
|
159
|
+
when `is_clan_based === true`. No other structural change on the card.
|
|
160
|
+
|
|
161
|
+
## Countdown / timing format
|
|
162
|
+
|
|
163
|
+
The default Smartico UI uses moment.js-style relative formatting
|
|
164
|
+
(`"in 3 days"`, `"in 2 hours"`, `"a few seconds ago"`) with a status
|
|
165
|
+
prefix:
|
|
166
|
+
|
|
167
|
+
| State | Prefix | Time source |
|
|
168
|
+
|---|---|---|
|
|
169
|
+
| `is_upcoming` | "Starts in" | `start_time` |
|
|
170
|
+
| `is_in_progress` | "Ends in" | `end_time` |
|
|
171
|
+
| `is_finished` | "Finished" | (no relative time, or `end_time` past-tense) |
|
|
172
|
+
| `is_cancelled` | "Cancelled" | (no time) |
|
|
173
|
+
|
|
174
|
+
Suggested format tiers (compact):
|
|
175
|
+
- > 7 days → `"Starts <date>"` (e.g. `"Starts 12 Jun"`)
|
|
176
|
+
- 1–7 days → `"in N days"`
|
|
177
|
+
- 1–24 h → `"in Hh Mm"`
|
|
178
|
+
- < 1 h → `"in Mm Ss"`, update every second
|
|
179
|
+
- Within 60 s → exact seconds with 1-second tick
|
|
180
|
+
|
|
181
|
+
The detail view uses a more precise `DD:HH:MM:SS` ticker; the card
|
|
182
|
+
uses the compact relative form.
|
|
183
|
+
|
|
184
|
+
## Empty / loading / error states
|
|
185
|
+
|
|
186
|
+
- **Loading (cold fetch)**: render a shimmer grid (skeleton cards) at
|
|
187
|
+
the eventual grid layout. The first call is a network round-trip.
|
|
188
|
+
- **Loading (cache hit)**: do not render a loading state — the promise
|
|
189
|
+
resolves within a microtask.
|
|
190
|
+
- **Empty list**: `[]` means the user has no visible tournaments.
|
|
191
|
+
Show an empty-state illustration; copy varies by tab:
|
|
192
|
+
- Finished tab: "No tournaments finished yet"
|
|
193
|
+
- MyTournaments tab: "You haven't joined any tournaments yet"
|
|
194
|
+
- All other tabs: "No tournaments available"
|
|
195
|
+
- **Error**: keep the prior list visible if any, show a small
|
|
196
|
+
non-blocking error banner, retry on the next user-driven action.
|
|
197
|
+
|
|
198
|
+
## Animations / transitions
|
|
199
|
+
|
|
200
|
+
- **List entry**: cards fade-in with a ~30 ms stagger on first render.
|
|
201
|
+
- **Registration success celebration**: when `is_user_registered` flips
|
|
202
|
+
from `false` to `true` between fetches (detect by diffing prior list
|
|
203
|
+
in your `onUpdate` handler), play a check-mark scale-in on the
|
|
204
|
+
registered card. The default Smartico UI also briefly highlights the
|
|
205
|
+
whole card.
|
|
206
|
+
- **Countdown ticker**: update once per second when remaining time is
|
|
207
|
+
under 1 hour; once per minute otherwise.
|
|
208
|
+
- **Status badge transitions**: when a tournament moves from
|
|
209
|
+
`is_upcoming` to `is_in_progress` mid-render, animate the badge
|
|
210
|
+
recolor over ~300 ms. This transition happens only on cache miss /
|
|
211
|
+
refresh — not pushed live.
|
|
212
|
+
|
|
213
|
+
## Mobile vs desktop
|
|
214
|
+
|
|
215
|
+
- **Grid columns**: desktop 2–3, tablet 2, mobile 1 (full-width cards
|
|
216
|
+
due to the landscape image aspect ratio).
|
|
217
|
+
- **Tab strip**: desktop shows Overview · MyTournaments · InProgress ·
|
|
218
|
+
Finished; mobile drops Finished to reduce horizontal scroll.
|
|
219
|
+
- **Card footer**: desktop renders 3-column footer (registrations /
|
|
220
|
+
buy-in / prize pool); mobile collapses to a single-line summary.
|
|
221
|
+
- **Ribbon position**: desktop overlays on the image (top-right);
|
|
222
|
+
mobile renders above the image to avoid overlap on small cards.
|
|
223
|
+
|
|
224
|
+
## Performance
|
|
225
|
+
|
|
226
|
+
- The 30 s cache deduplicates rapid refetches; a poll loop hitting
|
|
227
|
+
`getTournamentsList` every 5 s effectively translates to one
|
|
228
|
+
network round-trip per 30 s.
|
|
229
|
+
- Diff lists between fetches to detect lifecycle transitions
|
|
230
|
+
(`is_upcoming → is_in_progress`, registration flips). Avoid full
|
|
231
|
+
re-renders on every poll tick if you animate the card transitions —
|
|
232
|
+
keyed per-card rendering matters because the celebration animations
|
|
233
|
+
break if the DOM nodes are recreated.
|
|
234
|
+
- The hardest perf hit is the countdown ticker. Consider rendering the
|
|
235
|
+
full countdown only on currently-visible cards (use
|
|
236
|
+
`IntersectionObserver` for off-screen virtualization on long lists).
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# UI Guide — `registerInTournament`
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
- Action-focused mutation. The user is on a tournament card or detail
|
|
5
|
+
view, the CTA is "Join tournament", and they click it.
|
|
6
|
+
- A successful response (`err_code === 0`) means: registration row
|
|
7
|
+
exists, buy-in already debited, lobby refresh fired. The SDK has
|
|
8
|
+
already updated the cache by the time you receive the response — the
|
|
9
|
+
`onUpdate` callback on `getTournamentsList` fires shortly after.
|
|
10
|
+
- Latency: typically 100–500 ms for a healthy WebSocket connection.
|
|
11
|
+
|
|
12
|
+
## Loading state
|
|
13
|
+
|
|
14
|
+
- **Trigger**: set an in-flight flag (`registering = true`) immediately
|
|
15
|
+
on click, BEFORE the call. This is the consumer's responsibility —
|
|
16
|
+
the SDK does NOT have an in-flight guard.
|
|
17
|
+
- **Visual**: replace the button label with animated dots (or a
|
|
18
|
+
spinner). Disable the button. Keep the modal / panel open.
|
|
19
|
+
- **Reset**: clear the in-flight flag on response — success or error.
|
|
20
|
+
|
|
21
|
+
## Idempotency UI guard
|
|
22
|
+
|
|
23
|
+
The SDK does NOT prevent double-clicks. Two simultaneous calls both
|
|
24
|
+
send to the server; both responses resolve. The first will succeed
|
|
25
|
+
(`err_code = 0`); the second usually returns `30004`
|
|
26
|
+
(already-registered) but may also succeed if the race is exactly tied.
|
|
27
|
+
|
|
28
|
+
**Two practical guards**:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
// 1. Component-local in-flight flag (simple)
|
|
32
|
+
const [registering, setRegistering] = useState(false);
|
|
33
|
+
|
|
34
|
+
const onJoin = async () => {
|
|
35
|
+
if (registering) return;
|
|
36
|
+
setRegistering(true);
|
|
37
|
+
const r = await window._smartico.api.registerInTournament(tournament.instance_id);
|
|
38
|
+
setRegistering(false);
|
|
39
|
+
handleResponse(r);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// 2. Disable the button while is_user_registered hasn't flipped yet
|
|
43
|
+
const disabled = registering || tournament.is_user_registered;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Treat `err_code = 30004` as **idempotent success** in the UI — hide
|
|
47
|
+
the Register button and show "Registered". Don't show an error.
|
|
48
|
+
|
|
49
|
+
## Action button decision matrix
|
|
50
|
+
|
|
51
|
+
| `err_code` | Action |
|
|
52
|
+
|---|---|
|
|
53
|
+
| `0` (success) | Close any registration modal · Show a success toast · Refresh the detail view if open (call `getTournamentInstanceInfo` again) · The lobby list auto-refreshes via `onUpdate` — DON'T manually re-fetch `getTournamentsList` |
|
|
54
|
+
| `30004` (already registered) | Same as success — treat as idempotent success |
|
|
55
|
+
| `1010` (no clan) | Open a clan-pick modal driven by [`getClans`](../../api/classes/WSAPIClans.md#getclans) and [`joinClan`](../../api/classes/WSAPIClans.md#joinclan); after the clan-join resolves, call `registerInTournament` again. Don't show an error |
|
|
56
|
+
| `30002` (insufficient points) | Show insufficient-points UI: `"You need X more points to join"`. Optional: deep-link to a points-earning surface. |
|
|
57
|
+
| `300010` (insufficient gems) | Show insufficient-gems UI (analogous to `30002` but for gems currency). NOT in the public enum — branch on the literal numeric value. |
|
|
58
|
+
| `300011` (insufficient diamonds) | Show insufficient-diamonds UI (analogous, for diamonds). NOT in the public enum — branch on the literal. |
|
|
59
|
+
| `30001` (instance not found) | Refresh the lobby; the tournament is gone. Show a brief "no longer available" toast. |
|
|
60
|
+
| `30003` (not in registerable state) | Refresh the lobby; the button should disappear. |
|
|
61
|
+
| `30005` (segment mismatch) | Show the operator-supplied `tournament.segment_dont_match_message` if set; fall back to `err_message`. Don't retry. |
|
|
62
|
+
| `30006` (anomalous "not registered") | Show generic error toast with `err_message`. Allow retry. |
|
|
63
|
+
| `30007` (status-change blocked) | Show generic error toast. Don't retry. |
|
|
64
|
+
| `30008` (tournament full) | Show "Tournament is full" message; the lobby auto-refresh will hide the button on the refreshed item. |
|
|
65
|
+
| Other non-zero / unknown | Show generic error toast with `err_message` if any. |
|
|
66
|
+
|
|
67
|
+
## Per-code error message strategy
|
|
68
|
+
|
|
69
|
+
| `err_code` | Use `err_message`? | Use operator copy? | Best UX text source |
|
|
70
|
+
|---|---|---|---|
|
|
71
|
+
| `0` (success) | — | — | `"You're registered in {tournament.name}"` (localized) |
|
|
72
|
+
| `30005` (segment mismatch) | Fallback only | **Preferred** | `tournament.segment_dont_match_message` → `err_message` → localized generic |
|
|
73
|
+
| `30002` / `300010` / `300011` (no balance) | Fallback | — | Localized `"Insufficient {currency}"` with deficit amount derived from `tournament.registration_cost_*` and the user's profile balance |
|
|
74
|
+
| `30008` (full) | Fallback | — | Localized `"Tournament is full"` |
|
|
75
|
+
| All other `3000x` | Fallback | — | Localized error string for the code → fall back to `err_message` |
|
|
76
|
+
|
|
77
|
+
`segment_dont_match_message` is a field on the root `TTournament`
|
|
78
|
+
object — read it directly as `tournament.segment_dont_match_message`.
|
|
79
|
+
|
|
80
|
+
## Clan tournament gating
|
|
81
|
+
|
|
82
|
+
When `tournament.is_clan_based === true`, the user must already be in
|
|
83
|
+
a clan before calling `registerInTournament`. Two paths:
|
|
84
|
+
|
|
85
|
+
1. **Pre-call check** (recommended): in the click handler, read the
|
|
86
|
+
user's clan membership (e.g. via {@link getUserProfile}). If they
|
|
87
|
+
have no clan, open a clan-pick modal (driven by
|
|
88
|
+
[`getClans`](../../api/classes/WSAPIClans.md#getclans) +
|
|
89
|
+
[`joinClan`](../../api/classes/WSAPIClans.md#joinclan)). After
|
|
90
|
+
`joinClan` resolves, call `registerInTournament` — typically
|
|
91
|
+
automatically, without requiring a second click.
|
|
92
|
+
2. **Server-side safety net**: if a race occurs (e.g. the user leaves
|
|
93
|
+
their clan between the pre-check and the server-side check), the
|
|
94
|
+
server returns `err_code = 1010`. Handle this the same way —
|
|
95
|
+
re-open the clan-pick flow, then retry.
|
|
96
|
+
|
|
97
|
+
The default Smartico UI uses approach 1 with 2 as a fallback.
|
|
98
|
+
|
|
99
|
+
## Optimistic update
|
|
100
|
+
|
|
101
|
+
**Do NOT optimistically flip `is_user_registered`** before the
|
|
102
|
+
response. The local tournament object should only update when the
|
|
103
|
+
auto-refreshed lobby array arrives via `getTournamentsList`'s
|
|
104
|
+
`onUpdate` callback. The `registering` in-flight flag provides
|
|
105
|
+
sufficient visual feedback during the wait.
|
|
106
|
+
|
|
107
|
+
If you DO use an optimistic state (for instant UI feedback), reconcile
|
|
108
|
+
on the response: if `err_code !== 0` AND `err_code !== 30004`, revert
|
|
109
|
+
the optimistic flip. Most consumers should skip optimistic UI for
|
|
110
|
+
this mutation — the latency is short enough that a loading spinner
|
|
111
|
+
suffices.
|
|
112
|
+
|
|
113
|
+
## Refresh after response
|
|
114
|
+
|
|
115
|
+
The SDK auto-refreshes `getTournamentsList` after every response
|
|
116
|
+
(success or error) via a server push. The `onUpdate` callback on
|
|
117
|
+
`getTournamentsList({ onUpdate })` fires with the refreshed array
|
|
118
|
+
shortly after `registerInTournament` resolves. **Don't manually call
|
|
119
|
+
`getTournamentsList()` after a register response — the cache is
|
|
120
|
+
already being refreshed.**
|
|
121
|
+
|
|
122
|
+
The detail view (`getTournamentInstanceInfo`) is NOT auto-refreshed.
|
|
123
|
+
If the detail screen is open, call it again to get the updated
|
|
124
|
+
leaderboard, registration count, and `me` block.
|
|
125
|
+
|
|
126
|
+
The user's balance (after a buy-in deduction) updates via the
|
|
127
|
+
SDK's user-properties channel — subscribe to user-property
|
|
128
|
+
changes separately if your UI shows the balance.
|
|
129
|
+
|
|
130
|
+
## Animations / transitions
|
|
131
|
+
|
|
132
|
+
- **Loading dots**: 3-dot bouncing animation on the button while the
|
|
133
|
+
call is in flight.
|
|
134
|
+
- **Success celebration**: when `is_user_registered` flips from
|
|
135
|
+
`false` to `true` on the refreshed lobby item, play a
|
|
136
|
+
check-mark scale-in on the registered card. The default Smartico UI
|
|
137
|
+
also fires a success toast with the tournament name.
|
|
138
|
+
- **Error modal**: dismissable; auto-close after ~5 s for
|
|
139
|
+
recoverable errors (`30002`, `300010`, `300011`); persistent for
|
|
140
|
+
`30005` (operator-supplied message is usually important).
|
|
141
|
+
|
|
142
|
+
## Mobile vs desktop
|
|
143
|
+
|
|
144
|
+
- **Loading state**: identical (dots animation on the button).
|
|
145
|
+
- **Error surfacing**: desktop typically uses a toast/snackbar;
|
|
146
|
+
mobile may use a centered modal with a clear "OK" affordance.
|
|
147
|
+
- **Clan-pick flow**: full-screen slide-up sheet on mobile;
|
|
148
|
+
centered modal on desktop.
|
|
149
|
+
|
|
150
|
+
## Performance
|
|
151
|
+
|
|
152
|
+
- Single round-trip per click. No batching needed.
|
|
153
|
+
- The lobby refresh (server push + SDK cache write + `onUpdate` fire)
|
|
154
|
+
adds ~50–100 ms after the response — fine for UI purposes.
|
|
155
|
+
- Don't poll `getTournamentsList` after a register response — the
|
|
156
|
+
refresh is already happening.
|