@smartico/public-api 0.0.380 → 0.0.382
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/CLAUDE.md +103 -0
- package/README.md +32 -10
- 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/MiniGames/SAWGameType.d.ts +3 -1
- package/dist/MiniGames/SAWTemplateUI.d.ts +7 -0
- 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/WSAPI/WSAPIAvatars.d.ts +267 -49
- package/dist/WSAPI/WSAPIBonuses.d.ts +224 -10
- package/dist/WSAPI/WSAPIGamePick.d.ts +538 -253
- package/dist/WSAPI/WSAPIGeneral.d.ts +156 -14
- package/dist/WSAPI/WSAPIInbox.d.ts +547 -58
- package/dist/WSAPI/WSAPIJackpots.d.ts +292 -57
- package/dist/WSAPI/WSAPILeaderBoard.d.ts +127 -13
- package/dist/WSAPI/WSAPIMiniGames.d.ts +465 -49
- package/dist/WSAPI/WSAPIRaffles.d.ts +576 -52
- package/dist/WSAPI/WSAPITournaments.d.ts +3 -3
- package/dist/WSAPI/WSAPITypes.d.ts +243 -132
- package/dist/WSAPI/WSAPIUser.d.ts +193 -43
- package/dist/index.js +3412 -616
- package/dist/index.js.map +1 -1
- package/dist/index.modern.mjs +3395 -609
- 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 +26 -0
- package/docs/api/classes/WSAPIAvatars.md +282 -54
- package/docs/api/classes/WSAPIBonuses.md +233 -12
- package/docs/api/classes/WSAPIClans.md +380 -10
- package/docs/api/classes/WSAPIGamePick.md +555 -26
- package/docs/api/classes/WSAPIGeneral.md +165 -16
- package/docs/api/classes/WSAPIInbox.md +588 -64
- package/docs/api/classes/WSAPIJackpots.md +320 -66
- package/docs/api/classes/WSAPILeaderBoard.md +133 -15
- package/docs/api/classes/WSAPIMiniGames.md +501 -64
- package/docs/api/classes/WSAPIMissions.md +58 -79
- package/docs/api/classes/WSAPIRaffles.md +647 -69
- package/docs/api/classes/WSAPIStore.md +83 -108
- package/docs/api/classes/WSAPITournaments.md +495 -28
- package/docs/api/classes/WSAPIUser.md +520 -83
- 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/BonusStatus-1.md +11 -6
- 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/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/TAchCategory.md +2 -7
- 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 -29
- 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 +1 -9
- package/docs/api/interfaces/TMissionOptInResult.md +1 -5
- package/docs/api/interfaces/TMissionOrBadge.md +4 -7
- 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 +3 -13
- package/docs/api/interfaces/TTournament.md +1 -1
- package/docs/api/interfaces/TTournamentDetailed.md +1 -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/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/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/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/user/UIGuide_getActivityLog.md +130 -0
- package/docs/ui/user/UIGuide_getLevels.md +47 -42
- package/package.json +1 -1
- package/src/Base/ClassId.ts +2 -0
- package/src/Jackpots/JackpotDetails.ts +14 -15
- package/src/Jackpots/JackpotPot.ts +10 -6
- package/src/MiniGames/SAWGameType.ts +3 -0
- package/src/MiniGames/SAWTemplateUI.ts +10 -0
- 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/WSAPI/WSAPIAvatars.ts +267 -49
- package/src/WSAPI/WSAPIBonuses.ts +224 -10
- package/src/WSAPI/WSAPIGamePick.ts +538 -253
- package/src/WSAPI/WSAPIGeneral.ts +156 -14
- package/src/WSAPI/WSAPIInbox.ts +545 -56
- package/src/WSAPI/WSAPIJackpots.ts +297 -61
- package/src/WSAPI/WSAPILeaderBoard.ts +127 -13
- package/src/WSAPI/WSAPIMiniGames.ts +465 -49
- package/src/WSAPI/WSAPIRaffles.ts +592 -64
- package/src/WSAPI/WSAPITournaments.ts +3 -3
- package/src/WSAPI/WSAPITypes.ts +243 -132
- package/src/WSAPI/WSAPIUser.ts +193 -43
- package/tsconfig.json +9 -1
|
@@ -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.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# UI Guide — `getRaffleDrawRun`
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
- Powers the **draw detail / winners screen** for a single raffle
|
|
5
|
+
draw run. Adds paginated `prizes[].winners[]` rows (usernames +
|
|
6
|
+
avatars) to the same `TRaffleDraw` shape already embedded in
|
|
7
|
+
[`getRaffles`](../../api/classes/WSAPIRaffles.md#getraffles).
|
|
8
|
+
- One-shot fetch. No cache, no subscription. Re-call to refresh —
|
|
9
|
+
the default Smartico UI polls on a variable cadence depending on
|
|
10
|
+
the draw's `current_state`.
|
|
11
|
+
|
|
12
|
+
## Detail view layout
|
|
13
|
+
|
|
14
|
+
Top-to-bottom layout:
|
|
15
|
+
|
|
16
|
+
1. **Header** — `image_url` / `image_url_mobile` as background.
|
|
17
|
+
2. **Title + state chip** — `name` + a chip driven by
|
|
18
|
+
`current_state` (Open / Drawing / Finished).
|
|
19
|
+
3. **Countdown ticker** — `DD : HH : MM : SS` to `execution_ts`
|
|
20
|
+
while Open; not rendered during WinnerSelection or after
|
|
21
|
+
Executed (replaced by drawing animation / winner list).
|
|
22
|
+
4. **Prize cards** — one per `prizes[]` entry. Each shows
|
|
23
|
+
`name`, `description`, `image_url`, `prizes_per_run_actual`,
|
|
24
|
+
and (if `current_state === Executed`) the paginated
|
|
25
|
+
`winners[]` rows.
|
|
26
|
+
5. **My tickets** — `my_tickets_count` / `my_last_tickets` for
|
|
27
|
+
Open draws.
|
|
28
|
+
6. **Opt-in / claim CTAs** — see the
|
|
29
|
+
[`requestRaffleOptin`](../../api/classes/WSAPIRaffles.md#requestraffleoptin)
|
|
30
|
+
and [`claimRafflePrize`](../../api/classes/WSAPIRaffles.md#claimraffleprize)
|
|
31
|
+
UI guides.
|
|
32
|
+
|
|
33
|
+
## Winners list (paginated)
|
|
34
|
+
|
|
35
|
+
When `current_state === Executed`, each prize card carries a
|
|
36
|
+
`winners[]` array (type `TRafflePrizeWinner`). Render as a table:
|
|
37
|
+
|
|
38
|
+
| Column | Source |
|
|
39
|
+
|---|---|
|
|
40
|
+
| Position | Computed from list order (the server-sorted result places the current user's wins at the top). |
|
|
41
|
+
| Avatar | `winner.avatar_url`. Fallback to a letter avatar when missing. |
|
|
42
|
+
| Username | `winner.username`. Fallback to "Anonymous" if empty. |
|
|
43
|
+
| Ticket | `winner.ticket.ticket_id_string` (use the string form for display). |
|
|
44
|
+
| Claimed | If `winner.claimed_date` is set, show "Claimed"; otherwise show "Pending" (or a Claim CTA if `should_claim === true` and the row matches the current user). |
|
|
45
|
+
|
|
46
|
+
**Pagination** via `winners_from` / `winners_to`:
|
|
47
|
+
|
|
48
|
+
- Default window per call: `0 – 20`.
|
|
49
|
+
- Server cap per call: 50 rows. Passing a larger window silently
|
|
50
|
+
truncates.
|
|
51
|
+
- Total count: `winners_total` on the returned `TRaffleDraw`.
|
|
52
|
+
- The default Smartico UI uses page size 7 internally with a
|
|
53
|
+
custom pagination component — your UI can choose any size up to
|
|
54
|
+
50.
|
|
55
|
+
|
|
56
|
+
For load-more pagination: advance `winners_from` by the prior page
|
|
57
|
+
size on each subsequent call; reuse the same response transform.
|
|
58
|
+
|
|
59
|
+
## Refresh / polling
|
|
60
|
+
|
|
61
|
+
`getRaffleDrawRun` has no cache and no push refresh. Poll manually
|
|
62
|
+
when the consumer is viewing a live draw. Recommended cadence
|
|
63
|
+
keyed to `current_state` + remaining time:
|
|
64
|
+
|
|
65
|
+
| State / Time | Poll interval |
|
|
66
|
+
|---|---|
|
|
67
|
+
| `WinnerSelection` (drawing) | 3 s |
|
|
68
|
+
| `Open`, `< 5 minutes` to execution | 10 s |
|
|
69
|
+
| `Open`, `> 5 minutes` to execution | 30 s |
|
|
70
|
+
| `Executed` | No polling needed (state is terminal) |
|
|
71
|
+
|
|
72
|
+
Stop polling when the detail view unmounts.
|
|
73
|
+
|
|
74
|
+
## Image / asset specs
|
|
75
|
+
|
|
76
|
+
Inherits from [`getRaffles`](./UIGuide_getRaffles.md#image--asset-specs):
|
|
77
|
+
|
|
78
|
+
- Draw promo: 365×175 px (desktop), 300×145 px (mobile)
|
|
79
|
+
- Background image: 900×85 px (desktop), 1328×240 px (mobile)
|
|
80
|
+
- Prize image: 256×256 px (1:1 square)
|
|
81
|
+
- Avatar: serve via CDN; letter-avatar fallback when empty
|
|
82
|
+
|
|
83
|
+
## Empty / loading / error states
|
|
84
|
+
|
|
85
|
+
- **Loading**: render the modal frame + countdown immediately
|
|
86
|
+
(driven by the caller-side `TRaffleDraw` from `getRaffles`);
|
|
87
|
+
show a winners-list skeleton while the call is in flight.
|
|
88
|
+
- **`winners[]` empty** (Executed draw with no winners): render
|
|
89
|
+
"No winners yet" placeholder. Rare — the server should have
|
|
90
|
+
selected at least one winner per `prizes_per_run_actual`.
|
|
91
|
+
- **Error**: keep the prior snapshot if any; show a non-blocking
|
|
92
|
+
error banner; retry on next poll tick.
|
|
93
|
+
|
|
94
|
+
## Animations / transitions
|
|
95
|
+
|
|
96
|
+
- **WinnerSelection**: full-screen Lottie drawing animation; the
|
|
97
|
+
winners list area is hidden until state transitions to Executed.
|
|
98
|
+
- **Winners-list page change**: cross-fade rows on pagination.
|
|
99
|
+
- **No confetti / celebration animation** on the user's win row —
|
|
100
|
+
surface a "You won!" pill on rows where `should_claim` is true
|
|
101
|
+
for the current user.
|
|
102
|
+
|
|
103
|
+
## Mobile vs desktop
|
|
104
|
+
|
|
105
|
+
- **Modal style**: desktop centered with backdrop dim; mobile
|
|
106
|
+
full-screen slide-up sheet.
|
|
107
|
+
- **Image source**: desktop fields vs `*_mobile` fields.
|
|
108
|
+
- **Winners-list layout**: desktop 4 columns; mobile may collapse
|
|
109
|
+
the position column or compact the row.
|
|
110
|
+
|
|
111
|
+
## Performance
|
|
112
|
+
|
|
113
|
+
- Each call is a fresh network round-trip. During live drawing
|
|
114
|
+
(3 s polling), this is the active surface; `getRaffles` is not
|
|
115
|
+
polled in parallel.
|
|
116
|
+
- Pagination is server-side — don't over-fetch by passing a large
|
|
117
|
+
window; reuse smaller windows.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# UI Guide — `getRaffleDrawRunsHistory`
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
- Powers a **draw-history modal / page** showing past-executed runs
|
|
5
|
+
for a raffle (optionally scoped to a single recurring draw
|
|
6
|
+
schedule).
|
|
7
|
+
- Use to surface unclaimed-prize CTAs across the user's history,
|
|
8
|
+
let the user revisit completed draws, or build a "my wins"
|
|
9
|
+
surface.
|
|
10
|
+
- One-shot fetch, no cache. Re-call to refresh — typically only
|
|
11
|
+
needed after a new execution lands or after a
|
|
12
|
+
[`claimRafflePrize`](../../api/classes/WSAPIRaffles.md#claimraffleprize)
|
|
13
|
+
call resolves.
|
|
14
|
+
|
|
15
|
+
## List view organization
|
|
16
|
+
|
|
17
|
+
Server-sorted by `execution_ts` DESC (newest first). No client-side
|
|
18
|
+
sort required.
|
|
19
|
+
|
|
20
|
+
If `props.draw_id` is omitted, the list interleaves history across
|
|
21
|
+
all draws of the raffle. The default Smartico UI shows them in
|
|
22
|
+
their server order — no per-draw grouping. To group by draw, key on
|
|
23
|
+
`row.id` (the schedule_id) client-side.
|
|
24
|
+
|
|
25
|
+
If `props.draw_id` is set, the list scopes to one draw's recurring
|
|
26
|
+
history.
|
|
27
|
+
|
|
28
|
+
## Item row
|
|
29
|
+
|
|
30
|
+
Fields rendered per row:
|
|
31
|
+
|
|
32
|
+
| Field | Source | Notes |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| Image | `image_url` (or `image_url_mobile` on mobile); fallback to `icon_url` | Same specs as in `getRaffles` UI guide. |
|
|
35
|
+
| Name | `name` | |
|
|
36
|
+
| Description | `description` | Optional; the default UI may omit it on dense lists. |
|
|
37
|
+
| Grand badge | If `is_grand === true`, render a "Grand" pill | |
|
|
38
|
+
| Scheduled date | `execution_ts` formatted as user-local date/time | |
|
|
39
|
+
| Actual date | `actual_execution_ts` — typically same as scheduled, but may differ slightly on recovery paths | |
|
|
40
|
+
| User won? | If `is_winner === true`, surface a "You won!" pill | |
|
|
41
|
+
| Claim CTA | If `has_unclaimed_prize === true`, show a "Claim" button that opens the prize detail via [`getRaffleDrawRun`](../../api/classes/WSAPIRaffles.md#getraffledrawrun) | |
|
|
42
|
+
|
|
43
|
+
Row click target: opens the executed draw's detail view (winner
|
|
44
|
+
list) by calling `getRaffleDrawRun({ raffle_id, run_id })`.
|
|
45
|
+
|
|
46
|
+
## Claim CTA on history rows
|
|
47
|
+
|
|
48
|
+
When `row.has_unclaimed_prize === true`, surface a Claim button.
|
|
49
|
+
Clicking it should:
|
|
50
|
+
|
|
51
|
+
1. Fetch the run detail via
|
|
52
|
+
[`getRaffleDrawRun`](../../api/classes/WSAPIRaffles.md#getraffledrawrun)
|
|
53
|
+
to locate the user's winning row(s).
|
|
54
|
+
2. Pass each winner row's `raf_won_id` to
|
|
55
|
+
[`claimRafflePrize`](../../api/classes/WSAPIRaffles.md#claimraffleprize).
|
|
56
|
+
|
|
57
|
+
The default Smartico UI renders the Claim button inline on the
|
|
58
|
+
history row and opens a confirmation flow when clicked.
|
|
59
|
+
|
|
60
|
+
## Empty / loading / error states
|
|
61
|
+
|
|
62
|
+
- **Loading (cold fetch)**: render a skeleton list (3–5
|
|
63
|
+
placeholder rows) sized to the eventual layout.
|
|
64
|
+
- **Empty result**: `[]` means no executed runs yet. Render a
|
|
65
|
+
neutral empty-state ("No history yet").
|
|
66
|
+
- **Error**: keep prior state if any; show a non-blocking error
|
|
67
|
+
banner; retry on next user-driven action.
|
|
68
|
+
|
|
69
|
+
## Refresh
|
|
70
|
+
|
|
71
|
+
No subscription, no cache, no push. Call manually:
|
|
72
|
+
|
|
73
|
+
- After a `claimRafflePrize` resolves (to refresh
|
|
74
|
+
`has_unclaimed_prize`).
|
|
75
|
+
- After a new run executes on the server side (the user observes
|
|
76
|
+
the new history row).
|
|
77
|
+
- On a periodic poll if your UI wants to show new executions
|
|
78
|
+
promptly — typically not necessary for history surfaces.
|
|
79
|
+
|
|
80
|
+
## Mobile vs desktop
|
|
81
|
+
|
|
82
|
+
- **Image source**: `image_url_mobile` / `background_image_url_mobile`
|
|
83
|
+
on mobile.
|
|
84
|
+
- **Row density**: mobile may collapse description and date columns
|
|
85
|
+
to save horizontal space.
|
|
86
|
+
|
|
87
|
+
## Performance
|
|
88
|
+
|
|
89
|
+
- Each call is a fresh network round-trip. Scope with `draw_id` when
|
|
90
|
+
possible to keep response size manageable.
|
|
91
|
+
- Don't poll the history surface in real time — re-fetch
|
|
92
|
+
on user-initiated actions only.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# UI Guide — `getRaffleWonPrizes`
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
- Powers a **"my prizes" screen** for a single raffle — the flat list of
|
|
5
|
+
every prize the current user has won across all of that raffle's draws,
|
|
6
|
+
newest-won first.
|
|
7
|
+
- One-shot, paginated fetch. No cache, no subscription. Re-call to refresh
|
|
8
|
+
(e.g. after a [`claimRafflePrize`](../../api/classes/WSAPIRaffles.md#claimraffleprize)).
|
|
9
|
+
- Each row already carries `public_meta.name` + `public_meta.image_url`, so
|
|
10
|
+
you can render full prize cards without a follow-up
|
|
11
|
+
[`getRaffleDrawRun`](../../api/classes/WSAPIRaffles.md#getraffledrawrun) call.
|
|
12
|
+
|
|
13
|
+
## List view organization
|
|
14
|
+
|
|
15
|
+
- Single flat list (no per-draw grouping), ordered newest-win first.
|
|
16
|
+
- There is **no** server-side "unclaimed first" ordering. If your design
|
|
17
|
+
surfaces actionable prizes at the top, sort client-side by
|
|
18
|
+
`requires_claim && !claimed_date`, then keep the server order within each
|
|
19
|
+
group.
|
|
20
|
+
- Drive "load more" off `total` (the full win count across all draws), not
|
|
21
|
+
off the page length:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
const hasMore = page.offset + page.won_prizes.length < page.total;
|
|
25
|
+
console.log('[smartico] more pages?', hasMore);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Item card / tile
|
|
29
|
+
|
|
30
|
+
One card per `won_prizes[]` row:
|
|
31
|
+
|
|
32
|
+
| Element | Source | Notes |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| Prize image | `public_meta.name` → `public_meta.image_url` | Square artwork; the default Smartico UI renders it as a circular icon. |
|
|
35
|
+
| Prize name | `public_meta.name` | Localised. Truncate long names (~30 chars) with an ellipsis. |
|
|
36
|
+
| Claimed / Claim CTA | `requires_claim` + `claimed_date` | See the action matrix below. |
|
|
37
|
+
| Won-by attribution | `user.public_username` / `user.avatar_id` | The list belongs to one user; usually shown once in the header, not per card. |
|
|
38
|
+
|
|
39
|
+
## Action button decision matrix
|
|
40
|
+
|
|
41
|
+
Per row:
|
|
42
|
+
|
|
43
|
+
| `requires_claim` | `claimed_date` | Render |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `false` | (any) | No CTA — prize was auto-delivered. Optionally show a "Delivered" tag. |
|
|
46
|
+
| `true` | `null` | **Claim** button. On click call `claimRafflePrize({ won_id: prize.raf_won_id })` — `raf_won_id` IS the `won_id`. |
|
|
47
|
+
| `true` | epoch ms | No CTA — show a "Claimed" tag (optionally with the claimed date). |
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
const canClaim = prize.requires_claim && !prize.claimed_date;
|
|
51
|
+
if (canClaim) {
|
|
52
|
+
console.log('[smartico] show Claim — on click: claimRafflePrize({ won_id:', prize.raf_won_id, '})');
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Guard the Claim button against double-clicks (set an in-flight flag on click).
|
|
57
|
+
A second claim of an already-claimed prize is rejected server-side. After a
|
|
58
|
+
successful claim, re-call `getRaffleWonPrizes` to pick up the new
|
|
59
|
+
`claimed_date` (this method has no `onUpdate`).
|
|
60
|
+
|
|
61
|
+
## User attribution (avatar + username)
|
|
62
|
+
|
|
63
|
+
The `user` object describes whose prizes these are.
|
|
64
|
+
|
|
65
|
+
- **Null-check `user` first** — it is `null` when `won_prizes` is empty.
|
|
66
|
+
- **Avatar**: use `user.avatar_id`. If it already starts with `http`, use it
|
|
67
|
+
directly as the `<img src>`. Otherwise it is an avatar token — prepend the
|
|
68
|
+
widget's configured avatar domain (`{avatarDomain}/avatar/{avatar_id}`).
|
|
69
|
+
`user.avatar_url` is always `null`; ignore it. `user.avatar_real_id`
|
|
70
|
+
identifies the avatar definition internally and is not used for rendering.
|
|
71
|
+
- **Username**: `user.public_username` is server-masked for privacy (e.g.
|
|
72
|
+
`"32:r*****"`). Render it verbatim. For the current user, show a localised
|
|
73
|
+
"You" label instead of the masked string.
|
|
74
|
+
|
|
75
|
+
## Image / asset specs
|
|
76
|
+
|
|
77
|
+
- Prize image (`public_meta.image_url`): square (1:1) CDN artwork. The default
|
|
78
|
+
Smartico UI renders it at 40×40 px with `border-radius: 50%`.
|
|
79
|
+
- Provide a letter/placeholder fallback when `image_url` is empty.
|
|
80
|
+
|
|
81
|
+
## Empty / loading / error states
|
|
82
|
+
|
|
83
|
+
- **Loading**: show a card skeleton grid while the call is in flight.
|
|
84
|
+
- **Empty** (`errCode === 0` and `won_prizes.length === 0`): render an empty
|
|
85
|
+
state ("No prizes won yet"). Note this is *also* the response when the user
|
|
86
|
+
is not eligible to see the raffle — the two are indistinguishable, so keep
|
|
87
|
+
the copy neutral.
|
|
88
|
+
- **Error** (`errCode !== 0`): keep any prior snapshot; show a non-blocking
|
|
89
|
+
error banner with a retry. `errCode` is `1` for all server errors —
|
|
90
|
+
surface `errMsg` if present.
|
|
91
|
+
|
|
92
|
+
## Refresh / polling
|
|
93
|
+
|
|
94
|
+
- One-shot promise; no client cache; no push refresh.
|
|
95
|
+
- Re-call on screen open, on explicit "load more", and after a successful
|
|
96
|
+
`claimRafflePrize`.
|
|
97
|
+
- **Do not poll on a timer** — the server rate-limits this call (~30/min, with
|
|
98
|
+
a ~5 s minimum gap between calls). Tight polling will start failing.
|
|
99
|
+
|
|
100
|
+
## Pagination
|
|
101
|
+
|
|
102
|
+
- `offset` / `limit` page the rows; the SDK defaults to `0` / `20`.
|
|
103
|
+
- The server does **not** clamp `limit` — pass an explicit, sane page size.
|
|
104
|
+
- An `offset` past the end returns an empty page with the real `total` and
|
|
105
|
+
`errCode 0` (not an error).
|
|
106
|
+
- For "load more": advance `offset` by your page size each call.
|
|
107
|
+
|
|
108
|
+
## Mobile vs desktop
|
|
109
|
+
|
|
110
|
+
- Desktop: multi-column card grid. Mobile: single-column list or compact
|
|
111
|
+
2-column grid.
|
|
112
|
+
- The response shape is identical across viewports; only layout density
|
|
113
|
+
differs.
|
|
114
|
+
|
|
115
|
+
## Performance
|
|
116
|
+
|
|
117
|
+
- Each call is a fresh network round-trip. Fetch one page at a time and append
|
|
118
|
+
on "load more" rather than pre-fetching all pages.
|
|
119
|
+
- The server caches responses briefly, so a quick re-open is cheap — but the
|
|
120
|
+
rate limit still applies; debounce rapid re-fetches.
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# UI Guide — `getRaffles`
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
- Returns the user's visible raffles, each carrying an embedded
|
|
5
|
+
`draws[]` array with full per-draw state. Use as the source-of-truth
|
|
6
|
+
for the raffles lobby + draw cards.
|
|
7
|
+
- The list refreshes automatically after
|
|
8
|
+
[`claimRafflePrize`](../../api/classes/WSAPIRaffles.md#claimraffleprize)
|
|
9
|
+
or
|
|
10
|
+
[`requestRaffleOptin`](../../api/classes/WSAPIRaffles.md#requestraffleoptin)
|
|
11
|
+
resolves. Server-side draw executions invalidate the SDK cache too.
|
|
12
|
+
- Winner detail (usernames, avatars) requires a follow-up call to
|
|
13
|
+
[`getRaffleDrawRun`](../../api/classes/WSAPIRaffles.md#getraffledrawrun)
|
|
14
|
+
— the embedded `draws[]` carry only pagination metadata.
|
|
15
|
+
|
|
16
|
+
## List view organization
|
|
17
|
+
|
|
18
|
+
The default Smartico UI renders raffles as a vertical list with each
|
|
19
|
+
raffle expanding to show its draws. There are no top-level tabs.
|
|
20
|
+
|
|
21
|
+
Per-raffle, draws are bucketed within the detail panel:
|
|
22
|
+
|
|
23
|
+
1. **Active / Upcoming** — `draws.filter(d => d.current_state !== 3)`
|
|
24
|
+
(1 = Open, 2 = WinnerSelection); sort by `execution_ts` ASC.
|
|
25
|
+
2. **Executed** — `draws.filter(d => d.current_state === 3)`;
|
|
26
|
+
rendered after the active draws.
|
|
27
|
+
|
|
28
|
+
## Ticket-cap banner
|
|
29
|
+
|
|
30
|
+
Drive from `TRaffle.ticket_cap_visualization` (enum):
|
|
31
|
+
|
|
32
|
+
| Value | Banner |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `Empty` (0) | No banner. |
|
|
35
|
+
| `Counter` (1) | "X tickets remaining" where X = `max_tickets_count - current_tickets_count`. Format large numbers with locale separators. |
|
|
36
|
+
| `Message` (2) | "All tickets have been distributed" (when 0 remaining). |
|
|
37
|
+
|
|
38
|
+
## Raffle card (top-level)
|
|
39
|
+
|
|
40
|
+
Fields rendered on each raffle row:
|
|
41
|
+
|
|
42
|
+
- `image_url` (890×193 px desktop) / `image_url_mobile` (300×142 px).
|
|
43
|
+
- `name`, `description`.
|
|
44
|
+
- `start_date` / `end_date` — formatted as user-local dates.
|
|
45
|
+
- Total tickets banner (see above).
|
|
46
|
+
- Draw count or active-draw summary.
|
|
47
|
+
|
|
48
|
+
`custom_section_id` lets the consumer place the raffle into an
|
|
49
|
+
operator-defined custom section. `custom_data` is operator-defined
|
|
50
|
+
JSON / string for custom UI extensions.
|
|
51
|
+
|
|
52
|
+
## Draw card (per-raffle children)
|
|
53
|
+
|
|
54
|
+
Fields rendered on each `draws[i]`:
|
|
55
|
+
|
|
56
|
+
| Field | Notes |
|
|
57
|
+
|---|---|
|
|
58
|
+
| Card image | `background_image_url` (900×85 px desktop) / `background_image_url_mobile` (1328×240 px). Falls back to `icon_url` (256×256). |
|
|
59
|
+
| Title | `name`. |
|
|
60
|
+
| Description | `description`. |
|
|
61
|
+
| Grand badge | If `is_grand === true`, render a "Grand draw" pill. |
|
|
62
|
+
| Countdown | To `execution_ts`. See "Countdown / timing format". |
|
|
63
|
+
| State chip | Drive from `current_state` ({@link RaffleDrawInstanceState}): Open / Drawing / Finished. |
|
|
64
|
+
| My-tickets | `my_tickets_count` if > 0. |
|
|
65
|
+
| Last tickets preview | `my_last_tickets[]` (capped at ~5; newest first). Note the SDK field is spelled `ticekt_id` (typo). |
|
|
66
|
+
| Total tickets | `total_tickets_count`. |
|
|
67
|
+
| Prize summary | Top-priority prize from `prizes[]`. |
|
|
68
|
+
| Opt-in / Opted-in chip | See "Action button decision matrix". |
|
|
69
|
+
|
|
70
|
+
The draw card click target opens the draw detail (which fetches
|
|
71
|
+
winners via `getRaffleDrawRun`).
|
|
72
|
+
|
|
73
|
+
## Action button decision matrix
|
|
74
|
+
|
|
75
|
+
Per-draw CTA (evaluate in priority order):
|
|
76
|
+
|
|
77
|
+
| Condition | CTA |
|
|
78
|
+
|---|---|
|
|
79
|
+
| `current_state === WinnerSelection` (2) | "Drawing now…" (informational) — show the Lottie drawing animation |
|
|
80
|
+
| `current_state === Executed` (3) | "View winners" — opens detail via `getRaffleDrawRun` |
|
|
81
|
+
| `requires_optin && user_opted_in && current_state !== Executed` | "Fully opted in" (informational pill, no click) |
|
|
82
|
+
| `requires_optin && !user_opted_in && is_active && current_state !== Executed` | "Opt in" — invokes `requestRaffleOptin` |
|
|
83
|
+
| `!requires_optin && is_active && current_state === Open` | "View prizes" (or no CTA — the user is automatically participating) |
|
|
84
|
+
| `!is_active` and other terminal states | No CTA |
|
|
85
|
+
|
|
86
|
+
Opt-in is per-run — when a recurring draw advances to a new run,
|
|
87
|
+
`user_opted_in` resets to `false` on the new run. The Opt-in CTA
|
|
88
|
+
returns even for users who opted in to the previous run.
|
|
89
|
+
|
|
90
|
+
## Image / asset specs
|
|
91
|
+
|
|
92
|
+
| Field | Documented source | Aspect | Used where |
|
|
93
|
+
|---|---|---|---|
|
|
94
|
+
| `TRaffle.image_url` | 890×193 px | ~4.6:1 | Raffle row header (desktop) |
|
|
95
|
+
| `TRaffle.image_url_mobile` | 300×142 px | ~2.1:1 | Raffle row header (mobile) |
|
|
96
|
+
| `TRaffleDraw.image_url` | 365×175 px | ~2:1 | Draw promo |
|
|
97
|
+
| `TRaffleDraw.image_url_mobile` | 300×145 px | ~2:1 | Draw promo (mobile) |
|
|
98
|
+
| `TRaffleDraw.icon_url` | 256×256 px | 1:1 | Draw icon (compact contexts) |
|
|
99
|
+
| `TRaffleDraw.background_image_url` | 900×85 px | ~10.6:1 | Draw row background (desktop) |
|
|
100
|
+
| `TRaffleDraw.background_image_url_mobile` | 1328×240 px | ~5.5:1 | Draw row background (mobile) |
|
|
101
|
+
| `TRafflePrize.image_url` | 256×256 px | 1:1 | Prize card |
|
|
102
|
+
|
|
103
|
+
Fallback chain (per element): brand-supplied placeholder if the
|
|
104
|
+
field is empty. The SDK doesn't ship default images.
|
|
105
|
+
|
|
106
|
+
## Status-specific visual treatments
|
|
107
|
+
|
|
108
|
+
- **Open** (`current_state === 1`): full-color card with active
|
|
109
|
+
countdown. Show My-tickets / prizes prominently.
|
|
110
|
+
- **WinnerSelection** (`current_state === 2`): show Lottie drawing
|
|
111
|
+
animation (full-screen overlay in the default Smartico UI). The
|
|
112
|
+
default UI polls every 3 s during this state.
|
|
113
|
+
- **Executed** (`current_state === 3`): subtle desaturation; show
|
|
114
|
+
"View winners" CTA; surface "You won!" badge if any prize matches
|
|
115
|
+
the user.
|
|
116
|
+
- **Grand** draws (`is_grand: true`): larger card, distinct accent
|
|
117
|
+
color, grand badge. Otherwise identical fields.
|
|
118
|
+
- **Sold out** (ticket cap reached): banner + no opt-in CTA.
|
|
119
|
+
|
|
120
|
+
## Countdown / timing format
|
|
121
|
+
|
|
122
|
+
The default Smartico UI uses a hard-stamped `DD : HH : MM : SS`
|
|
123
|
+
ticker counting down to `execution_ts`. CSS state classes:
|
|
124
|
+
|
|
125
|
+
- Normal — default styling
|
|
126
|
+
- `alert` — applied when < 5 minutes remain (yellow/amber accent)
|
|
127
|
+
- `alarm` — applied when < 1 minute remains (red accent)
|
|
128
|
+
|
|
129
|
+
**Polling escalation**: the widget polls
|
|
130
|
+
[`getRaffleDrawRun`](../../api/classes/WSAPIRaffles.md#getraffledrawrun)
|
|
131
|
+
at a variable rate keyed to remaining time:
|
|
132
|
+
|
|
133
|
+
- 30 s default
|
|
134
|
+
- 10 s when < 5 minutes remain
|
|
135
|
+
- 3 s when in `WinnerSelection` state
|
|
136
|
+
|
|
137
|
+
For non-default UIs, mirror this pattern or use a constant 30 s
|
|
138
|
+
poll — the cost is one network round-trip per poll tick.
|
|
139
|
+
|
|
140
|
+
## Empty / loading / error states
|
|
141
|
+
|
|
142
|
+
- **Loading (cold fetch)**: render a skeleton grid sized to the
|
|
143
|
+
eventual layout.
|
|
144
|
+
- **Loading (cache hit)**: do not render a loading state — the
|
|
145
|
+
promise resolves within a microtask.
|
|
146
|
+
- **Empty result**: `[]` means no visible raffles. Render a neutral
|
|
147
|
+
empty-state illustration.
|
|
148
|
+
- **Error**: keep the prior list if any; show a non-blocking error
|
|
149
|
+
banner; retry on next user-driven action.
|
|
150
|
+
|
|
151
|
+
## Animations / transitions
|
|
152
|
+
|
|
153
|
+
- **List entry**: cards fade-in on first render.
|
|
154
|
+
- **WinnerSelection state**: full-screen Lottie animation while the
|
|
155
|
+
server selects winners.
|
|
156
|
+
- **No celebration animation on claim** — the winner row updates
|
|
157
|
+
in-place. See `claimRafflePrize` UI guide.
|
|
158
|
+
- **Opt-in success**: ~500 ms delay then UI state flip via
|
|
159
|
+
`onUpdate` refresh.
|
|
160
|
+
|
|
161
|
+
## Mobile vs desktop
|
|
162
|
+
|
|
163
|
+
- **Image source**: `*_url` for desktop, `*_url_mobile` for mobile.
|
|
164
|
+
- **Draw row background**: desktop 900×85 px (wide strip); mobile
|
|
165
|
+
1328×240 px (taller hero treatment).
|
|
166
|
+
- **Detail modal**: desktop centered modal with backdrop dim; mobile
|
|
167
|
+
full-screen slide-up sheet.
|
|
168
|
+
|
|
169
|
+
## Performance
|
|
170
|
+
|
|
171
|
+
- The 30 s cache deduplicates rapid refetches.
|
|
172
|
+
- During an in-flight draw (WinnerSelection), polling
|
|
173
|
+
`getRaffleDrawRun` instead of `getRaffles` is cheaper — the latter
|
|
174
|
+
is a larger payload.
|
|
175
|
+
- Image assets are CDN-served; lazy-load images below the fold.
|