@playbasis-ai/qwikcard-sdk 2.3.16 → 2.3.19

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playbasis-ai/qwikcard-sdk",
3
- "version": "2.3.16",
3
+ "version": "2.3.19",
4
4
  "description": "Playbasis SDK for QwikCard College Rewards - React Native gamification integration",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -49,14 +49,16 @@ function AppContent({ leaderboardId }: { leaderboardId?: string }) {
49
49
  throw new Error('Missing playerId for widget bootstrap');
50
50
  }
51
51
 
52
- const [player, balances, quests, allBadges, playerBadges, rewards] = await Promise.all([
53
- client.getPlayer(playerId),
54
- client.getBalances(playerId),
55
- client.getPlayerQuests(playerId),
56
- client.getBadges(),
57
- client.getPlayerBadges(playerId),
58
- client.getRewards().catch(() => []), // Gracefully handle if rewards endpoint doesn't exist
59
- ]);
52
+ const [player, balances, playerQuests, questCatalog, allBadges, playerBadges, rewards] =
53
+ await Promise.all([
54
+ client.getPlayer(playerId),
55
+ client.getBalances(playerId),
56
+ client.getPlayerQuests(playerId),
57
+ client.getQuests(),
58
+ client.getBadges(),
59
+ client.getPlayerBadges(playerId),
60
+ client.getRewards().catch(() => []), // Gracefully handle if rewards endpoint doesn't exist
61
+ ]);
60
62
 
61
63
  const xp = balances.find((b) => b.currency === 'xp')?.balance ?? 0;
62
64
  const qwikCoins = balances.find((b) => b.currency === 'qwik-coins')?.balance ?? 0;
@@ -92,24 +94,35 @@ function AppContent({ leaderboardId }: { leaderboardId?: string }) {
92
94
  earnedDelta: 0,
93
95
  qwikCoins,
94
96
  },
95
- goals: quests.map((q) => ({
96
- goalId: q.id,
97
- type: 'financial',
98
- target: q.target,
99
- current: q.progress,
100
- progressPct: q.target > 0 ? Math.round((q.progress / q.target) * 100) : 0,
101
- startDate: new Date().toISOString().slice(0, 10),
102
- endDate: q.expiresAt ?? new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
103
- status:
104
- q.status === 'completed' ? 'completed' : q.status === 'expired' ? 'at_risk' : 'on_track',
105
- rewards: {
106
- xp: q.rewards?.find((r) => r.type === 'points')?.amount || 100,
107
- badges: (q.rewards
108
- ?.filter((r) => r.type === 'badge')
109
- .map((r) => r.badgeId)
110
- .filter(Boolean) || []) as string[],
111
- },
112
- })),
97
+ goals: (() => {
98
+ const quests = playerQuests.length > 0 ? playerQuests : questCatalog;
99
+ const nowIso = new Date().toISOString().slice(0, 10);
100
+ return quests.map((q) => ({
101
+ goalId: q.id,
102
+ type: 'financial',
103
+ target: q.target ?? 1,
104
+ current: q.progress ?? 0,
105
+ progressPct:
106
+ q.target && q.target > 0
107
+ ? Math.round(((q.progress ?? 0) / q.target) * 100)
108
+ : 0,
109
+ startDate: nowIso,
110
+ endDate: q.expiresAt ?? new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
111
+ status:
112
+ q.status === 'completed'
113
+ ? 'completed'
114
+ : q.status === 'expired'
115
+ ? 'at_risk'
116
+ : 'on_track',
117
+ rewards: {
118
+ xp: q.rewards?.find((r) => r.type === 'points')?.amount || 100,
119
+ badges: (q.rewards
120
+ ?.filter((r) => r.type === 'badge')
121
+ .map((r) => r.badgeId)
122
+ .filter(Boolean) || []) as string[],
123
+ },
124
+ }));
125
+ })(),
113
126
  badges: allBadges.map((b) => ({
114
127
  id: b.id,
115
128
  name: b.name,
package/src/api/client.ts CHANGED
@@ -247,10 +247,11 @@ export class PlaybasisClient {
247
247
  }
248
248
 
249
249
  async getPlayerQuests(playerId: string): Promise<Quest[]> {
250
- const data = await this.request<{ quests?: Quest[]; items?: Quest[] }>(
250
+ const data = await this.request<Quest[] | { quests?: Quest[]; items?: Quest[] }>(
251
251
  'GET',
252
252
  `/players/${encodeURIComponent(playerId)}/quests`,
253
253
  );
254
+ if (Array.isArray(data)) return data;
254
255
  return data.quests || data.items || [];
255
256
  }
256
257
 
@@ -272,10 +273,11 @@ export class PlaybasisClient {
272
273
  }
273
274
 
274
275
  async getPlayerBadges(playerId: string): Promise<Badge[]> {
275
- const data = await this.request<{ badges?: Badge[]; items?: Badge[] }>(
276
+ const data = await this.request<Badge[] | { badges?: Badge[]; items?: Badge[] }>(
276
277
  'GET',
277
278
  `/players/${encodeURIComponent(playerId)}/badges`,
278
279
  );
280
+ if (Array.isArray(data)) return data;
279
281
  return data.badges || data.items || [];
280
282
  }
281
283
 
@@ -309,12 +311,56 @@ export class PlaybasisClient {
309
311
  if (options?.limit) params.set('limit', String(options.limit));
310
312
  if (options?.cursor) params.set('cursor', options.cursor);
311
313
 
312
- const data = await this.request<{
313
- leaderboard?: { entries?: LeaderboardEntry[]; total?: number };
314
- }>('GET', `/leaderboards/${encodeURIComponent(leaderboardId)}?${params}`);
314
+ const data = await this.request<
315
+ | { entries?: LeaderboardEntry[]; total?: number }
316
+ | { items?: LeaderboardEntry[]; total?: number }
317
+ | { leaderboard?: { entries?: LeaderboardEntry[]; total?: number } }
318
+ >('GET', `/leaderboards/${encodeURIComponent(leaderboardId)}?${params}`);
319
+ const leaderboardData = data as { leaderboard?: { entries?: LeaderboardEntry[]; total?: number } };
320
+ const entries =
321
+ 'entries' in data
322
+ ? data.entries
323
+ : 'items' in data
324
+ ? data.items
325
+ : leaderboardData.leaderboard?.entries;
326
+ const total =
327
+ 'total' in data && typeof data.total === 'number'
328
+ ? data.total
329
+ : leaderboardData.leaderboard?.total ?? entries?.length ?? 0;
330
+
331
+ const normalizedEntries = (entries || []).map((entry, index) => {
332
+ const raw = entry as LeaderboardEntry & {
333
+ balance?: number;
334
+ points?: number;
335
+ value?: number;
336
+ name?: string;
337
+ id?: string;
338
+ };
339
+ const score =
340
+ typeof raw.score === 'number'
341
+ ? raw.score
342
+ : typeof raw.balance === 'number'
343
+ ? raw.balance
344
+ : typeof raw.points === 'number'
345
+ ? raw.points
346
+ : typeof raw.value === 'number'
347
+ ? raw.value
348
+ : 0;
349
+ const rank = typeof raw.rank === 'number' ? raw.rank : index + 1;
350
+ const displayName = raw.displayName || raw.name || raw.playerId || 'Player';
351
+ const playerId = raw.playerId || raw.id || displayName;
352
+
353
+ return {
354
+ playerId,
355
+ displayName,
356
+ rank,
357
+ score,
358
+ metadata: raw.metadata,
359
+ };
360
+ });
315
361
  return {
316
- entries: data.leaderboard?.entries || [],
317
- total: data.leaderboard?.total || 0,
362
+ entries: normalizedEntries,
363
+ total,
318
364
  };
319
365
  }
320
366