@umituz/react-native-gamification 1.1.0
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/LICENSE +22 -0
- package/README.md +276 -0
- package/package.json +55 -0
- package/src/domain/entities/Achievement.ts +46 -0
- package/src/domain/entities/Leaderboard.ts +45 -0
- package/src/domain/entities/Level.ts +38 -0
- package/src/domain/entities/Point.ts +38 -0
- package/src/domain/entities/Progress.ts +41 -0
- package/src/domain/entities/Reward.ts +48 -0
- package/src/domain/entities/Streak.ts +38 -0
- package/src/domain/repositories/IGamificationRepository.ts +233 -0
- package/src/index.ts +89 -0
- package/src/infrastructure/repositories/StorageGamificationRepository.ts +732 -0
- package/src/infrastructure/storage/GamificationStore.ts +348 -0
- package/src/presentation/hooks/useAchievements.ts +35 -0
- package/src/presentation/hooks/useGamification.ts +91 -0
- package/src/presentation/hooks/useLevel.ts +37 -0
- package/src/presentation/hooks/usePoints.ts +34 -0
- package/src/presentation/hooks/useProgress.ts +31 -0
- package/src/presentation/hooks/useRewards.ts +41 -0
- package/src/presentation/hooks/useStreaks.ts +34 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Γmit UZ
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
# @umituz/react-native-gamification
|
|
2
|
+
|
|
3
|
+
Comprehensive gamification system for React Native apps with achievements, points, levels, streaks, leaderboards, rewards, and progress tracking.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- π **Achievements** - Track and unlock user achievements
|
|
8
|
+
- π° **Points System** - Award and manage user points
|
|
9
|
+
- π **Levels** - Experience-based leveling system
|
|
10
|
+
- π₯ **Streaks** - Track consecutive activities
|
|
11
|
+
- π
**Leaderboards** - Competitive rankings
|
|
12
|
+
- π **Rewards** - Unlockable rewards system
|
|
13
|
+
- π **Progress Tracking** - Monitor user progress across metrics
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @umituz/react-native-gamification
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Peer Dependencies
|
|
22
|
+
|
|
23
|
+
- `react` >= 18.2.0
|
|
24
|
+
- `react-native` >= 0.74.0
|
|
25
|
+
- `@umituz/react-native-storage` (latest)
|
|
26
|
+
- `zustand` >= 4.0.0
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { useGamification, useGamificationInitializer } from '@umituz/react-native-gamification';
|
|
32
|
+
|
|
33
|
+
function App() {
|
|
34
|
+
const userId = 'user-123';
|
|
35
|
+
useGamificationInitializer(userId);
|
|
36
|
+
|
|
37
|
+
const {
|
|
38
|
+
achievements,
|
|
39
|
+
pointBalance,
|
|
40
|
+
level,
|
|
41
|
+
addPoints,
|
|
42
|
+
addExperience
|
|
43
|
+
} = useGamification();
|
|
44
|
+
|
|
45
|
+
// Add points when user completes an action
|
|
46
|
+
const handleActionComplete = async () => {
|
|
47
|
+
await addPoints(10, 'action_completed', 'action-id', 'actions', 'Completed action');
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
// Your app UI
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Usage
|
|
57
|
+
|
|
58
|
+
### Initialization
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { useGamification, useGamificationInitializer } from '@umituz/react-native-gamification';
|
|
62
|
+
|
|
63
|
+
function MyComponent() {
|
|
64
|
+
const userId = 'user-123';
|
|
65
|
+
|
|
66
|
+
// Initialize gamification system
|
|
67
|
+
useGamificationInitializer(userId);
|
|
68
|
+
|
|
69
|
+
const gamification = useGamification();
|
|
70
|
+
|
|
71
|
+
// Check if initialized
|
|
72
|
+
if (!gamification.isInitialized) {
|
|
73
|
+
return <Loading />;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return <YourContent />;
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Achievements
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { useAchievements } from '@umituz/react-native-gamification';
|
|
84
|
+
|
|
85
|
+
function AchievementsScreen() {
|
|
86
|
+
const {
|
|
87
|
+
achievements,
|
|
88
|
+
unlockAchievement,
|
|
89
|
+
updateAchievementProgress
|
|
90
|
+
} = useAchievements();
|
|
91
|
+
|
|
92
|
+
// Update progress
|
|
93
|
+
await updateAchievementProgress('achievement-id', 50);
|
|
94
|
+
|
|
95
|
+
// Unlock achievement
|
|
96
|
+
await unlockAchievement('achievement-id');
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<View>
|
|
100
|
+
{achievements.map(achievement => (
|
|
101
|
+
<AchievementCard key={achievement.id} achievement={achievement} />
|
|
102
|
+
))}
|
|
103
|
+
</View>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Points
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
import { usePoints } from '@umituz/react-native-gamification';
|
|
112
|
+
|
|
113
|
+
function PointsDisplay() {
|
|
114
|
+
const {
|
|
115
|
+
pointBalance,
|
|
116
|
+
addPoints,
|
|
117
|
+
deductPoints
|
|
118
|
+
} = usePoints();
|
|
119
|
+
|
|
120
|
+
// Add points
|
|
121
|
+
await addPoints(100, 'purchase', 'purchase-id', 'purchases', 'Made a purchase');
|
|
122
|
+
|
|
123
|
+
// Deduct points
|
|
124
|
+
await deductPoints(50, 'reward_claim', 'reward-id', 'Claimed reward');
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<Text>Total Points: {pointBalance?.total || 0}</Text>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Levels
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { useLevel } from '@umituz/react-native-gamification';
|
|
136
|
+
|
|
137
|
+
function LevelDisplay() {
|
|
138
|
+
const {
|
|
139
|
+
level,
|
|
140
|
+
addExperience
|
|
141
|
+
} = useLevel();
|
|
142
|
+
|
|
143
|
+
// Add experience
|
|
144
|
+
await addExperience(50, 'action_completed');
|
|
145
|
+
|
|
146
|
+
return (
|
|
147
|
+
<View>
|
|
148
|
+
<Text>Level: {level?.currentLevel || 1}</Text>
|
|
149
|
+
<Text>XP: {level?.currentExperience || 0} / {level?.experienceToNextLevel || 100}</Text>
|
|
150
|
+
<ProgressBar progress={level?.levelProgress || 0} />
|
|
151
|
+
</View>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Streaks
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import { useStreaks } from '@umituz/react-native-gamification';
|
|
160
|
+
|
|
161
|
+
function StreakDisplay() {
|
|
162
|
+
const {
|
|
163
|
+
streaks,
|
|
164
|
+
updateStreakActivity
|
|
165
|
+
} = useStreaks();
|
|
166
|
+
|
|
167
|
+
// Update streak
|
|
168
|
+
await updateStreakActivity('daily_login', new Date().toISOString());
|
|
169
|
+
|
|
170
|
+
const loginStreak = streaks.find(s => s.type === 'daily_login');
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<Text>Login Streak: {loginStreak?.currentStreak || 0} days</Text>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Rewards
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
import { useRewards } from '@umituz/react-native-gamification';
|
|
182
|
+
|
|
183
|
+
function RewardsScreen() {
|
|
184
|
+
const {
|
|
185
|
+
rewards,
|
|
186
|
+
claimReward,
|
|
187
|
+
getAvailableRewards
|
|
188
|
+
} = useRewards();
|
|
189
|
+
|
|
190
|
+
const availableRewards = getAvailableRewards();
|
|
191
|
+
|
|
192
|
+
const handleClaim = async (rewardId: string) => {
|
|
193
|
+
const claim = await claimReward(rewardId);
|
|
194
|
+
if (claim) {
|
|
195
|
+
console.log('Reward claimed!');
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<View>
|
|
201
|
+
{availableRewards.map(reward => (
|
|
202
|
+
<RewardCard
|
|
203
|
+
key={reward.id}
|
|
204
|
+
reward={reward}
|
|
205
|
+
onClaim={() => handleClaim(reward.id)}
|
|
206
|
+
/>
|
|
207
|
+
))}
|
|
208
|
+
</View>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Progress Tracking
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
import { useProgress } from '@umituz/react-native-gamification';
|
|
217
|
+
|
|
218
|
+
function ProgressTracker() {
|
|
219
|
+
const {
|
|
220
|
+
progress,
|
|
221
|
+
updateProgress
|
|
222
|
+
} = useProgress();
|
|
223
|
+
|
|
224
|
+
// Update progress
|
|
225
|
+
await updateProgress({
|
|
226
|
+
userId: 'user-123',
|
|
227
|
+
metric: 'goals_completed',
|
|
228
|
+
increment: 1,
|
|
229
|
+
category: 'goals',
|
|
230
|
+
period: 'all-time'
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const goalsProgress = progress.find(p => p.metric === 'goals_completed');
|
|
234
|
+
|
|
235
|
+
return (
|
|
236
|
+
<View>
|
|
237
|
+
<Text>Goals Completed: {goalsProgress?.currentValue || 0}</Text>
|
|
238
|
+
<ProgressBar progress={goalsProgress?.progress || 0} />
|
|
239
|
+
</View>
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Custom Repository
|
|
245
|
+
|
|
246
|
+
You can provide a custom repository implementation for app-specific storage:
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
import { useGamificationRepository } from '@umituz/react-native-gamification';
|
|
250
|
+
import { MyCustomRepository } from './MyCustomRepository';
|
|
251
|
+
|
|
252
|
+
function App() {
|
|
253
|
+
const customRepository = new MyCustomRepository();
|
|
254
|
+
|
|
255
|
+
useGamificationRepository(customRepository);
|
|
256
|
+
|
|
257
|
+
// Rest of your app
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Architecture
|
|
262
|
+
|
|
263
|
+
This package follows Domain-Driven Design (DDD) principles:
|
|
264
|
+
|
|
265
|
+
- **Domain Layer** - Entities and repository interfaces
|
|
266
|
+
- **Infrastructure Layer** - Repository implementations and stores
|
|
267
|
+
- **Presentation Layer** - React hooks for easy integration
|
|
268
|
+
|
|
269
|
+
## License
|
|
270
|
+
|
|
271
|
+
MIT
|
|
272
|
+
|
|
273
|
+
## Author
|
|
274
|
+
|
|
275
|
+
Γmit UZ <umit@umituz.com>
|
|
276
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@umituz/react-native-gamification",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Comprehensive gamification system for React Native apps with achievements, points, levels, streaks, leaderboards, rewards, and progress tracking",
|
|
5
|
+
"main": "./src/index.ts",
|
|
6
|
+
"types": "./src/index.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"typecheck": "tsc --noEmit",
|
|
9
|
+
"lint": "tsc --noEmit",
|
|
10
|
+
"version:minor": "npm version minor -m 'chore: release v%s'",
|
|
11
|
+
"version:major": "npm version major -m 'chore: release v%s'"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"react-native",
|
|
15
|
+
"gamification",
|
|
16
|
+
"achievements",
|
|
17
|
+
"points",
|
|
18
|
+
"levels",
|
|
19
|
+
"streaks",
|
|
20
|
+
"leaderboards",
|
|
21
|
+
"rewards",
|
|
22
|
+
"progress",
|
|
23
|
+
"gameification"
|
|
24
|
+
],
|
|
25
|
+
"author": "Γmit UZ <umit@umituz.com>",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/umituz/react-native-gamification"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"react": ">=18.2.0",
|
|
33
|
+
"react-native": ">=0.74.0",
|
|
34
|
+
"@umituz/react-native-storage": "latest",
|
|
35
|
+
"zustand": ">=4.0.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/react": "^18.2.45",
|
|
39
|
+
"@types/react-native": "^0.73.0",
|
|
40
|
+
"react": "^18.2.0",
|
|
41
|
+
"react-native": "^0.74.0",
|
|
42
|
+
"typescript": "^5.3.3"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"zustand": "^4.5.0"
|
|
46
|
+
},
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"files": [
|
|
51
|
+
"src",
|
|
52
|
+
"README.md",
|
|
53
|
+
"LICENSE"
|
|
54
|
+
]
|
|
55
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Achievement Entity
|
|
3
|
+
*
|
|
4
|
+
* Represents a user achievement in the gamification system
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface Achievement {
|
|
8
|
+
id: string;
|
|
9
|
+
userId: string;
|
|
10
|
+
type: string; // Achievement type identifier (e.g., "first_goal", "streak_7_days")
|
|
11
|
+
title: string;
|
|
12
|
+
description: string;
|
|
13
|
+
icon?: string;
|
|
14
|
+
category?: string; // Category for grouping achievements
|
|
15
|
+
unlocked: boolean;
|
|
16
|
+
unlockedDate?: string;
|
|
17
|
+
progress: number; // Current progress (0-100 or 0-requirement)
|
|
18
|
+
requirement: number; // Required value to unlock
|
|
19
|
+
points?: number; // Points awarded when unlocked
|
|
20
|
+
rarity?: "common" | "rare" | "epic" | "legendary";
|
|
21
|
+
metadata?: Record<string, any>; // Additional metadata
|
|
22
|
+
createdDate: string;
|
|
23
|
+
updatedDate: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface AchievementDefinition {
|
|
27
|
+
type: string;
|
|
28
|
+
title: string;
|
|
29
|
+
description: string;
|
|
30
|
+
icon?: string;
|
|
31
|
+
category?: string;
|
|
32
|
+
requirement: number;
|
|
33
|
+
points?: number;
|
|
34
|
+
rarity?: "common" | "rare" | "epic" | "legendary";
|
|
35
|
+
metadata?: Record<string, any>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface AchievementProgress {
|
|
39
|
+
achievementId: string;
|
|
40
|
+
userId: string;
|
|
41
|
+
currentValue: number;
|
|
42
|
+
requirement: number;
|
|
43
|
+
progress: number; // Percentage (0-100)
|
|
44
|
+
unlocked: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Leaderboard Entity
|
|
3
|
+
*
|
|
4
|
+
* Represents leaderboard entries in the gamification system
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface LeaderboardEntry {
|
|
8
|
+
id: string;
|
|
9
|
+
userId: string;
|
|
10
|
+
leaderboardId: string; // Leaderboard identifier (e.g., "global", "weekly", "monthly")
|
|
11
|
+
rank: number; // Current rank (1-based)
|
|
12
|
+
score: number; // Score for ranking
|
|
13
|
+
metric: string; // Metric used for ranking (e.g., "points", "experience", "streak")
|
|
14
|
+
displayName?: string; // User's display name
|
|
15
|
+
avatar?: string; // User's avatar URL
|
|
16
|
+
metadata?: Record<string, any>;
|
|
17
|
+
period?: "daily" | "weekly" | "monthly" | "all-time"; // Time period for leaderboard
|
|
18
|
+
periodStart?: string; // Start date of the period
|
|
19
|
+
periodEnd?: string; // End date of the period
|
|
20
|
+
createdDate: string;
|
|
21
|
+
updatedDate: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface Leaderboard {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
metric: string; // Metric used for ranking
|
|
29
|
+
period?: "daily" | "weekly" | "monthly" | "all-time";
|
|
30
|
+
periodStart?: string;
|
|
31
|
+
periodEnd?: string;
|
|
32
|
+
entries: LeaderboardEntry[];
|
|
33
|
+
totalParticipants: number;
|
|
34
|
+
lastUpdated: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface LeaderboardRanking {
|
|
38
|
+
userId: string;
|
|
39
|
+
rank: number;
|
|
40
|
+
score: number;
|
|
41
|
+
percentile: number; // Percentile rank (0-100)
|
|
42
|
+
aboveUsers: number; // Number of users above
|
|
43
|
+
belowUsers: number; // Number of users below
|
|
44
|
+
}
|
|
45
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Level Entity
|
|
3
|
+
*
|
|
4
|
+
* Represents user levels in the gamification system
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface Level {
|
|
8
|
+
id: string;
|
|
9
|
+
userId: string;
|
|
10
|
+
currentLevel: number;
|
|
11
|
+
currentExperience: number; // Current XP in current level
|
|
12
|
+
totalExperience: number; // Total XP accumulated
|
|
13
|
+
experienceToNextLevel: number; // XP needed for next level
|
|
14
|
+
levelProgress: number; // Percentage progress in current level (0-100)
|
|
15
|
+
metadata?: Record<string, any>;
|
|
16
|
+
createdDate: string;
|
|
17
|
+
updatedDate: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface LevelDefinition {
|
|
21
|
+
level: number;
|
|
22
|
+
experienceRequired: number; // Total XP required to reach this level
|
|
23
|
+
title?: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
rewards?: string[]; // Reward IDs or types
|
|
26
|
+
metadata?: Record<string, any>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface LevelProgress {
|
|
30
|
+
userId: string;
|
|
31
|
+
currentLevel: number;
|
|
32
|
+
currentExperience: number;
|
|
33
|
+
totalExperience: number;
|
|
34
|
+
experienceToNextLevel: number;
|
|
35
|
+
levelProgress: number;
|
|
36
|
+
canLevelUp: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Point Entity
|
|
3
|
+
*
|
|
4
|
+
* Represents points in the gamification system
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface Point {
|
|
8
|
+
id: string;
|
|
9
|
+
userId: string;
|
|
10
|
+
amount: number;
|
|
11
|
+
source: string; // Source of points (e.g., "achievement", "action", "reward")
|
|
12
|
+
sourceId?: string; // ID of the source (e.g., achievement ID)
|
|
13
|
+
category?: string; // Category for grouping points
|
|
14
|
+
description?: string;
|
|
15
|
+
metadata?: Record<string, any>;
|
|
16
|
+
createdDate: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface PointBalance {
|
|
20
|
+
userId: string;
|
|
21
|
+
total: number;
|
|
22
|
+
byCategory: Record<string, number>; // Points grouped by category
|
|
23
|
+
lastUpdated: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface PointTransaction {
|
|
27
|
+
id: string;
|
|
28
|
+
userId: string;
|
|
29
|
+
amount: number; // Can be negative for deductions
|
|
30
|
+
source: string;
|
|
31
|
+
sourceId?: string;
|
|
32
|
+
category?: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
balance: number; // Balance after this transaction
|
|
35
|
+
metadata?: Record<string, any>;
|
|
36
|
+
createdDate: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Progress Entity
|
|
3
|
+
*
|
|
4
|
+
* Represents user progress tracking in the gamification system
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface Progress {
|
|
8
|
+
id: string;
|
|
9
|
+
userId: string;
|
|
10
|
+
metric: string; // Metric identifier (e.g., "goals_completed", "sessions_attended")
|
|
11
|
+
currentValue: number; // Current value
|
|
12
|
+
targetValue?: number; // Target value (optional)
|
|
13
|
+
progress: number; // Percentage progress (0-100)
|
|
14
|
+
unit?: string; // Unit of measurement (e.g., "times", "hours", "days")
|
|
15
|
+
category?: string; // Category for grouping
|
|
16
|
+
period?: "daily" | "weekly" | "monthly" | "all-time"; // Time period
|
|
17
|
+
periodStart?: string; // Start date of the period
|
|
18
|
+
periodEnd?: string; // End date of the period
|
|
19
|
+
metadata?: Record<string, any>;
|
|
20
|
+
createdDate: string;
|
|
21
|
+
updatedDate: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ProgressUpdate {
|
|
25
|
+
userId: string;
|
|
26
|
+
metric: string;
|
|
27
|
+
increment: number; // Amount to increment
|
|
28
|
+
category?: string;
|
|
29
|
+
period?: "daily" | "weekly" | "monthly" | "all-time";
|
|
30
|
+
metadata?: Record<string, any>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ProgressMilestone {
|
|
34
|
+
metric: string;
|
|
35
|
+
value: number;
|
|
36
|
+
title: string;
|
|
37
|
+
description?: string;
|
|
38
|
+
reward?: string; // Reward ID or type
|
|
39
|
+
metadata?: Record<string, any>;
|
|
40
|
+
}
|
|
41
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reward Entity
|
|
3
|
+
*
|
|
4
|
+
* Represents rewards in the gamification system
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface Reward {
|
|
8
|
+
id: string;
|
|
9
|
+
userId: string;
|
|
10
|
+
type: string; // Reward type (e.g., "badge", "unlock", "discount", "item")
|
|
11
|
+
title: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
icon?: string;
|
|
14
|
+
category?: string;
|
|
15
|
+
pointsCost?: number; // Points required to claim
|
|
16
|
+
levelRequired?: number; // Level required to claim
|
|
17
|
+
unlocked: boolean;
|
|
18
|
+
unlockedDate?: string;
|
|
19
|
+
claimed: boolean;
|
|
20
|
+
claimedDate?: string;
|
|
21
|
+
expiresAt?: string; // Expiration date for time-limited rewards
|
|
22
|
+
metadata?: Record<string, any>;
|
|
23
|
+
createdDate: string;
|
|
24
|
+
updatedDate: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface RewardDefinition {
|
|
28
|
+
type: string;
|
|
29
|
+
title: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
icon?: string;
|
|
32
|
+
category?: string;
|
|
33
|
+
pointsCost?: number;
|
|
34
|
+
levelRequired?: number;
|
|
35
|
+
rarity?: "common" | "rare" | "epic" | "legendary";
|
|
36
|
+
expiresAt?: string;
|
|
37
|
+
metadata?: Record<string, any>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface RewardClaim {
|
|
41
|
+
id: string;
|
|
42
|
+
userId: string;
|
|
43
|
+
rewardId: string;
|
|
44
|
+
pointsSpent?: number;
|
|
45
|
+
claimedDate: string;
|
|
46
|
+
metadata?: Record<string, any>;
|
|
47
|
+
}
|
|
48
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streak Entity
|
|
3
|
+
*
|
|
4
|
+
* Represents user streaks in the gamification system
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface Streak {
|
|
8
|
+
id: string;
|
|
9
|
+
userId: string;
|
|
10
|
+
type: string; // Streak type (e.g., "daily_login", "daily_goal", "weekly_workout")
|
|
11
|
+
currentStreak: number; // Current consecutive days/actions
|
|
12
|
+
longestStreak: number; // Longest streak ever achieved
|
|
13
|
+
lastActivityDate: string; // Last date when streak was maintained
|
|
14
|
+
isActive: boolean; // Whether streak is currently active
|
|
15
|
+
metadata?: Record<string, any>;
|
|
16
|
+
createdDate: string;
|
|
17
|
+
updatedDate: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface StreakDefinition {
|
|
21
|
+
type: string;
|
|
22
|
+
name: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
resetOnMiss: boolean; // Whether streak resets if missed
|
|
25
|
+
timezone?: string; // Timezone for daily streaks
|
|
26
|
+
metadata?: Record<string, any>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface StreakProgress {
|
|
30
|
+
userId: string;
|
|
31
|
+
type: string;
|
|
32
|
+
currentStreak: number;
|
|
33
|
+
longestStreak: number;
|
|
34
|
+
isActive: boolean;
|
|
35
|
+
daysUntilMilestone?: number; // Days until next milestone (7, 30, 100, etc.)
|
|
36
|
+
nextMilestone?: number; // Next milestone value
|
|
37
|
+
}
|
|
38
|
+
|