@umituz/react-native-settings 4.20.61 → 4.21.1
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 +8 -60
- package/src/domains/gamification/README.md +343 -0
- package/src/domains/gamification/components/AchievementCard.tsx +142 -0
- package/src/domains/gamification/components/AchievementItem.tsx +182 -0
- package/src/domains/gamification/components/AchievementToast.tsx +122 -0
- package/src/domains/gamification/components/GamificationScreen/AchievementsList.tsx +84 -0
- package/src/domains/gamification/components/GamificationScreen/Header.tsx +29 -0
- package/src/domains/gamification/components/GamificationScreen/StatsGrid.tsx +51 -0
- package/src/domains/gamification/components/GamificationScreen/index.tsx +111 -0
- package/src/domains/gamification/components/GamificationScreen/styles.ts +43 -0
- package/src/domains/gamification/components/GamificationScreen/types.ts +77 -0
- package/src/domains/gamification/components/GamificationScreenWrapper.tsx +91 -0
- package/src/domains/gamification/components/GamificationSettingsItem.tsx +33 -0
- package/src/domains/gamification/components/LevelProgress.tsx +129 -0
- package/src/domains/gamification/components/PointsBadge.tsx +60 -0
- package/src/domains/gamification/components/StatsCard.tsx +89 -0
- package/src/domains/gamification/components/StreakDisplay.tsx +119 -0
- package/src/domains/gamification/components/index.ts +13 -0
- package/src/domains/gamification/examples/gamification.config.example.ts +70 -0
- package/src/domains/gamification/examples/localization.example.json +71 -0
- package/src/domains/gamification/hooks/useGamification.ts +91 -0
- package/src/domains/gamification/index.ts +65 -0
- package/src/domains/gamification/store/gamificationStore.ts +162 -0
- package/src/domains/gamification/types/index.ts +103 -0
- package/src/domains/gamification/types/settings.ts +28 -0
- package/src/domains/gamification/utils/calculations.ts +85 -0
- package/src/index.ts +18 -8
- package/src/presentation/navigation/SettingsStackNavigator.tsx +12 -0
- package/src/presentation/navigation/types.ts +2 -0
- package/src/presentation/navigation/utils/navigationScreenOptions.ts +7 -0
- package/src/presentation/screens/types/UserFeatureConfig.ts +2 -0
- package/src/presentation/utils/configCreators.ts +147 -0
- package/src/presentation/utils/index.ts +5 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -51
- package/.github/ISSUE_TEMPLATE/documentation.md +0 -52
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -63
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -84
- package/AI_AGENT_GUIDELINES.md +0 -367
- package/ARCHITECTURE.md +0 -246
- package/CHANGELOG.md +0 -67
- package/CODE_OF_CONDUCT.md +0 -75
- package/CONTRIBUTING.md +0 -107
- package/DOCUMENTATION_MIGRATION.md +0 -319
- package/DOCUMENTATION_TEMPLATE.md +0 -155
- package/SECURITY.md +0 -98
- package/SETTINGS_SCREEN_GUIDE.md +0 -185
- package/TESTING.md +0 -358
- package/src/__tests__/integration.test.tsx +0 -371
- package/src/__tests__/performance.test.tsx +0 -369
- package/src/__tests__/setup.test.tsx +0 -20
- package/src/__tests__/setup.ts +0 -154
- package/src/domains/about/__tests__/integration.test.tsx +0 -328
- package/src/domains/about/__tests__/types.d.ts +0 -5
- package/src/domains/about/domain/entities/__tests__/AppInfo.test.ts +0 -93
- package/src/domains/about/infrastructure/repositories/__tests__/AboutRepository.test.ts +0 -153
- package/src/domains/about/presentation/components/__tests__/AboutContent.simple.test.tsx +0 -178
- package/src/domains/about/presentation/components/__tests__/AboutContent.test.tsx +0 -293
- package/src/domains/about/presentation/components/__tests__/AboutHeader.test.tsx +0 -201
- package/src/domains/about/presentation/components/__tests__/AboutSettingItem.test.tsx +0 -71
- package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.simple.test.tsx +0 -229
- package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.test.tsx +0 -240
- package/src/domains/about/presentation/screens/__tests__/AboutScreen.simple.test.tsx +0 -199
- package/src/domains/about/presentation/screens/__tests__/AboutScreen.test.tsx +0 -366
- package/src/domains/about/utils/__tests__/index.test.ts +0 -408
- package/src/domains/appearance/__tests__/components/AppearanceScreen.test.tsx +0 -195
- package/src/domains/appearance/__tests__/hooks/index.test.tsx +0 -232
- package/src/domains/appearance/__tests__/integration/index.test.tsx +0 -207
- package/src/domains/appearance/__tests__/services/appearanceService.test.ts +0 -299
- package/src/domains/appearance/__tests__/setup.ts +0 -88
- package/src/domains/appearance/__tests__/stores/appearanceStore.test.tsx +0 -175
- package/src/domains/cloud-sync/presentation/components/__tests__/CloudSyncSetting.test.tsx +0 -78
- package/src/domains/legal/__tests__/ContentValidationService.test.ts +0 -195
- package/src/domains/legal/__tests__/StyleCacheService.test.ts +0 -110
- package/src/domains/legal/__tests__/UrlHandlerService.test.ts +0 -71
- package/src/domains/legal/__tests__/setup.ts +0 -82
- package/src/presentation/components/__tests__/SettingsErrorBoundary.test.tsx +0 -186
- package/src/presentation/screens/__tests__/SettingsScreen.test.tsx +0 -322
- package/src/presentation/screens/hooks/__tests__/useFeatureDetection.test.tsx +0 -261
package/package.json
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "4.
|
|
4
|
-
"description": "Complete settings hub for React Native apps - consolidated package with settings, about, legal, appearance, feedback, FAQs, and
|
|
3
|
+
"version": "4.21.1",
|
|
4
|
+
"description": "Complete settings hub for React Native apps - consolidated package with settings, about, legal, appearance, feedback, FAQs, rating, and gamification",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"typecheck": "tsc --noEmit",
|
|
9
9
|
"lint": "eslint src",
|
|
10
10
|
"lint:fix": "eslint src --fix",
|
|
11
|
-
"
|
|
12
|
-
"version:minor": "npm version minor -m 'chore: release v%s'",
|
|
13
|
-
"version:major": "npm version major -m 'chore: release v%s'"
|
|
11
|
+
"vp": "npm version patch && npm publish && git push"
|
|
14
12
|
},
|
|
15
13
|
"keywords": [
|
|
16
14
|
"react-native",
|
|
@@ -26,6 +24,8 @@
|
|
|
26
24
|
"feedback",
|
|
27
25
|
"faqs",
|
|
28
26
|
"rating",
|
|
27
|
+
"gamification",
|
|
28
|
+
"achievements",
|
|
29
29
|
"consolidated"
|
|
30
30
|
],
|
|
31
31
|
"author": "Ümit UZ <umit@umituz.com>",
|
|
@@ -35,12 +35,10 @@
|
|
|
35
35
|
"url": "https://github.com/umituz/react-native-settings"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@react-native-async-storage/async-storage": "^2.2.0",
|
|
39
38
|
"@umituz/react-native-auth": "latest",
|
|
40
39
|
"@umituz/react-native-design-system": "latest",
|
|
41
40
|
"@umituz/react-native-localization": "latest",
|
|
42
41
|
"@umituz/react-native-notifications": "latest",
|
|
43
|
-
"@umituz/react-native-onboarding": "latest",
|
|
44
42
|
"@umituz/react-native-storage": "latest",
|
|
45
43
|
"@umituz/react-native-tanstack": "latest",
|
|
46
44
|
"firebase": "^12.7.0"
|
|
@@ -52,79 +50,29 @@
|
|
|
52
50
|
"@tanstack/react-query": ">=5.0.0",
|
|
53
51
|
"react": ">=19.0.0",
|
|
54
52
|
"react-native": ">=0.81.0",
|
|
55
|
-
"react-native-safe-area-context": ">=4.0.0"
|
|
56
|
-
"zustand": ">=5.0.0"
|
|
53
|
+
"react-native-safe-area-context": ">=4.0.0"
|
|
57
54
|
},
|
|
58
55
|
"devDependencies": {
|
|
59
|
-
"@babel/plugin-transform-runtime": "^7.28.5",
|
|
60
56
|
"@expo/vector-icons": "^15.0.0",
|
|
61
|
-
"@gorhom/bottom-sheet": "^5.2.8",
|
|
62
|
-
"@react-native-community/datetimepicker": "^8.5.1",
|
|
63
|
-
"@react-navigation/bottom-tabs": "^7.9.0",
|
|
64
57
|
"@react-navigation/native": "^7.1.26",
|
|
65
58
|
"@react-navigation/stack": "^7.6.13",
|
|
66
|
-
"@sentry/react-native": "^7.8.0",
|
|
67
|
-
"@sentry/types": "^10.32.1",
|
|
68
59
|
"@tanstack/react-query": "^5.0.0",
|
|
69
|
-
"@types/jest": "^29.5.14",
|
|
70
60
|
"@types/react": "~19.1.10",
|
|
71
61
|
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
|
72
62
|
"@typescript-eslint/parser": "^7.18.0",
|
|
73
|
-
"@umituz/react-native-auth": "latest",
|
|
74
|
-
"@umituz/react-native-design-system": "latest",
|
|
75
|
-
"@umituz/react-native-filesystem": "latest",
|
|
76
|
-
"@umituz/react-native-firebase": "latest",
|
|
77
|
-
"@umituz/react-native-haptics": "latest",
|
|
78
|
-
"@umituz/react-native-localization": "latest",
|
|
79
|
-
"@umituz/react-native-notifications": "latest",
|
|
80
|
-
"@umituz/react-native-onboarding": "latest",
|
|
81
|
-
"@umituz/react-native-sentry": "^1.4.3",
|
|
82
|
-
"@umituz/react-native-storage": "latest",
|
|
83
|
-
"@umituz/react-native-tanstack": "latest",
|
|
84
|
-
"@umituz/react-native-uuid": "latest",
|
|
85
63
|
"eslint": "^8.57.0",
|
|
86
64
|
"eslint-plugin-react": "^7.37.5",
|
|
87
65
|
"eslint-plugin-react-native": "^5.0.0",
|
|
88
|
-
"expo-apple-authentication": "^8.0.8",
|
|
89
|
-
"expo-application": "^7.0.8",
|
|
90
|
-
"expo-clipboard": "^8.0.8",
|
|
91
|
-
"expo-crypto": "^15.0.8",
|
|
92
|
-
"expo-device": "^8.0.10",
|
|
93
|
-
"expo-file-system": "^19.0.21",
|
|
94
|
-
"expo-haptics": "^15.0.8",
|
|
95
|
-
"expo-image": "^3.0.11",
|
|
96
|
-
"expo-localization": "^17.0.8",
|
|
97
|
-
"expo-notifications": "^0.32.15",
|
|
98
|
-
"expo-sharing": "^14.0.8",
|
|
99
|
-
"expo-video": "^3.0.15",
|
|
100
|
-
"i18next": "^25.7.3",
|
|
101
66
|
"react": "19.1.0",
|
|
102
|
-
"react-i18next": "^16.5.0",
|
|
103
67
|
"react-native": "0.81.5",
|
|
104
|
-
"react-native-gesture-handler": "^2.30.0",
|
|
105
|
-
"react-native-reanimated": "^4.2.1",
|
|
106
68
|
"react-native-safe-area-context": "^5.6.2",
|
|
107
|
-
"
|
|
108
|
-
"typescript": "^5.3.0",
|
|
109
|
-
"zustand": "^5.0.9"
|
|
69
|
+
"typescript": "^5.3.0"
|
|
110
70
|
},
|
|
111
71
|
"publishConfig": {
|
|
112
72
|
"access": "public"
|
|
113
73
|
},
|
|
114
74
|
"files": [
|
|
115
75
|
"src",
|
|
116
|
-
"README.md"
|
|
117
|
-
"LICENSE",
|
|
118
|
-
"CONTRIBUTING.md",
|
|
119
|
-
"CHANGELOG.md",
|
|
120
|
-
"CODE_OF_CONDUCT.md",
|
|
121
|
-
"SECURITY.md",
|
|
122
|
-
"ARCHITECTURE.md",
|
|
123
|
-
"TESTING.md",
|
|
124
|
-
"AI_AGENT_GUIDELINES.md",
|
|
125
|
-
"SETTINGS_SCREEN_GUIDE.md",
|
|
126
|
-
"DOCUMENTATION_TEMPLATE.md",
|
|
127
|
-
"DOCUMENTATION_MIGRATION.md",
|
|
128
|
-
".github"
|
|
76
|
+
"README.md"
|
|
129
77
|
]
|
|
130
78
|
}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
# Gamification Domain
|
|
2
|
+
|
|
3
|
+
Complete gamification integration for React Native Settings package.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The gamification domain provides a seamless integration of achievements, levels, streaks, and points into your settings screen. It wraps `@umituz/react-native-gamification` with settings-specific functionality.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- ✅ **Achievements System** - Track and display user achievements
|
|
12
|
+
- ✅ **Level Progression** - Visual level progress with points
|
|
13
|
+
- ✅ **Streak Tracking** - Daily streak monitoring
|
|
14
|
+
- ✅ **Statistics Display** - Comprehensive stats cards
|
|
15
|
+
- ✅ **Localized** - Full i18n support via `@umituz/react-native-localization`
|
|
16
|
+
- ✅ **Theme Support** - Automatic dark/light mode integration
|
|
17
|
+
- ✅ **Navigation Ready** - Pre-configured navigation integration
|
|
18
|
+
|
|
19
|
+
## Architecture
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
src/domains/gamification/
|
|
23
|
+
├── types/
|
|
24
|
+
│ └── index.ts # Type definitions
|
|
25
|
+
├── components/
|
|
26
|
+
│ ├── GamificationScreenWrapper.tsx # Main screen wrapper
|
|
27
|
+
│ └── GamificationSettingsItem.tsx # Menu item component
|
|
28
|
+
└── index.ts # Public API
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
The gamification domain is included in `@umituz/react-native-settings`. Ensure you have the peer dependency:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install @umituz/react-native-gamification
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
### 1. Configure Gamification in Settings
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
// src/domains/settings/config/gamification.config.ts
|
|
45
|
+
import type { GamificationSettingsConfig } from "@umituz/react-native-settings";
|
|
46
|
+
|
|
47
|
+
export const createGamificationConfig = ({ t }): GamificationSettingsConfig => ({
|
|
48
|
+
enabled: true,
|
|
49
|
+
config: {
|
|
50
|
+
storageKey: "app_gamification",
|
|
51
|
+
achievements: [
|
|
52
|
+
{ id: "first_task", threshold: 1, type: "count" },
|
|
53
|
+
{ id: "ten_tasks", threshold: 10, type: "count" },
|
|
54
|
+
{ id: "week_streak", threshold: 7, type: "streak" },
|
|
55
|
+
],
|
|
56
|
+
levels: [
|
|
57
|
+
{ level: 1, minPoints: 0, maxPoints: 50 },
|
|
58
|
+
{ level: 2, minPoints: 50, maxPoints: 150 },
|
|
59
|
+
{ level: 3, minPoints: 150, maxPoints: 300 },
|
|
60
|
+
],
|
|
61
|
+
pointsPerAction: 10,
|
|
62
|
+
streakBonusMultiplier: 1.5,
|
|
63
|
+
},
|
|
64
|
+
screenProps: {
|
|
65
|
+
title: t("gamification.title"),
|
|
66
|
+
statsTitle: t("gamification.stats.title"),
|
|
67
|
+
achievementsTitle: t("gamification.achievements.title"),
|
|
68
|
+
streakTitle: t("gamification.streak.title"),
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 2. Add to Settings Config
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// src/domains/settings/config/settings.config.ts
|
|
77
|
+
import { createGamificationConfig } from "./gamification.config";
|
|
78
|
+
|
|
79
|
+
export const createSettingsConfig = ({ t, user, isPremium }) => ({
|
|
80
|
+
// ... other configs
|
|
81
|
+
gamification: createGamificationConfig({ t }),
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 3. Pass to SettingsStackNavigator
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
// src/domains/settings/presentation/SettingsTab.tsx
|
|
89
|
+
import { SettingsStackNavigator } from "@umituz/react-native-settings";
|
|
90
|
+
|
|
91
|
+
export const SettingsTab = () => {
|
|
92
|
+
const { t } = useLocalization();
|
|
93
|
+
const config = useMemo(() => createSettingsConfig({ t }), [t]);
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<SettingsStackNavigator
|
|
97
|
+
appInfo={APP_INFO}
|
|
98
|
+
legalUrls={LEGAL_URLS}
|
|
99
|
+
gamificationConfig={config.gamification}
|
|
100
|
+
/>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 4. Add Menu Item (Optional)
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
// In your custom settings sections
|
|
109
|
+
import { GamificationSettingsItem } from "@umituz/react-native-settings";
|
|
110
|
+
|
|
111
|
+
const customSections = [
|
|
112
|
+
{
|
|
113
|
+
title: t("settings.sections.engagement"),
|
|
114
|
+
items: [
|
|
115
|
+
<GamificationSettingsItem
|
|
116
|
+
config={{
|
|
117
|
+
enabled: true,
|
|
118
|
+
title: t("settings.gamification.menuTitle"),
|
|
119
|
+
subtitle: t("settings.gamification.menuSubtitle"),
|
|
120
|
+
icon: "trophy",
|
|
121
|
+
onPress: () => navigation.navigate("Gamification"),
|
|
122
|
+
}}
|
|
123
|
+
/>,
|
|
124
|
+
],
|
|
125
|
+
},
|
|
126
|
+
];
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Localization
|
|
130
|
+
|
|
131
|
+
Add these keys to your localization files:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"settings": {
|
|
136
|
+
"gamification": {
|
|
137
|
+
"title": "Achievements",
|
|
138
|
+
"menuTitle": "Achievements & Progress",
|
|
139
|
+
"menuSubtitle": "View your achievements and stats"
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"gamification": {
|
|
143
|
+
"title": "Your Progress",
|
|
144
|
+
"level": {
|
|
145
|
+
"title": "Level {{level}}"
|
|
146
|
+
},
|
|
147
|
+
"stats": {
|
|
148
|
+
"title": "Statistics",
|
|
149
|
+
"totalPoints": "Total Points",
|
|
150
|
+
"tasksCompleted": "Tasks Completed",
|
|
151
|
+
"achievementsUnlocked": "Achievements"
|
|
152
|
+
},
|
|
153
|
+
"achievements": {
|
|
154
|
+
"title": "Achievements",
|
|
155
|
+
"empty": "No achievements yet. Keep going!",
|
|
156
|
+
"first_task": {
|
|
157
|
+
"title": "First Steps",
|
|
158
|
+
"description": "Complete your first task"
|
|
159
|
+
},
|
|
160
|
+
"ten_tasks": {
|
|
161
|
+
"title": "Getting Started",
|
|
162
|
+
"description": "Complete 10 tasks"
|
|
163
|
+
},
|
|
164
|
+
"week_streak": {
|
|
165
|
+
"title": "Week Warrior",
|
|
166
|
+
"description": "Maintain a 7-day streak"
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"streak": {
|
|
170
|
+
"title": "Streak",
|
|
171
|
+
"current": "Current Streak",
|
|
172
|
+
"best": "Best Streak"
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## API Reference
|
|
179
|
+
|
|
180
|
+
### Types
|
|
181
|
+
|
|
182
|
+
#### `GamificationSettingsConfig`
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
interface GamificationSettingsConfig {
|
|
186
|
+
enabled: boolean;
|
|
187
|
+
config: GamificationConfig;
|
|
188
|
+
screenProps: Omit<GamificationScreenProps, "levelProps" | "stats" | "achievements">;
|
|
189
|
+
onNavigate?: () => void;
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
#### `GamificationMenuConfig`
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
interface GamificationMenuConfig {
|
|
197
|
+
enabled: boolean;
|
|
198
|
+
title: string;
|
|
199
|
+
subtitle?: string;
|
|
200
|
+
icon?: string;
|
|
201
|
+
onPress?: () => void;
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Components
|
|
206
|
+
|
|
207
|
+
#### `GamificationScreenWrapper`
|
|
208
|
+
|
|
209
|
+
Main screen component that displays gamification data.
|
|
210
|
+
|
|
211
|
+
**Props:**
|
|
212
|
+
- `config: GamificationSettingsConfig` - Configuration object
|
|
213
|
+
|
|
214
|
+
#### `GamificationSettingsItem`
|
|
215
|
+
|
|
216
|
+
Menu item component for settings list.
|
|
217
|
+
|
|
218
|
+
**Props:**
|
|
219
|
+
- `config: GamificationMenuConfig` - Menu configuration
|
|
220
|
+
|
|
221
|
+
## Re-exported Components
|
|
222
|
+
|
|
223
|
+
All components from `@umituz/react-native-gamification` are re-exported for convenience:
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
import {
|
|
227
|
+
LevelProgress,
|
|
228
|
+
PointsBadge,
|
|
229
|
+
AchievementCard,
|
|
230
|
+
AchievementToast,
|
|
231
|
+
StreakDisplay,
|
|
232
|
+
StatsCard,
|
|
233
|
+
AchievementItem,
|
|
234
|
+
useGamification,
|
|
235
|
+
useGamificationStore,
|
|
236
|
+
} from "@umituz/react-native-settings";
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Example: Complete Integration
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
// 1. Create config
|
|
243
|
+
const gamificationConfig: GamificationSettingsConfig = {
|
|
244
|
+
enabled: true,
|
|
245
|
+
config: {
|
|
246
|
+
storageKey: "my_app_gamification",
|
|
247
|
+
achievements: [
|
|
248
|
+
{ id: "first_login", threshold: 1, type: "milestone" },
|
|
249
|
+
{ id: "power_user", threshold: 100, type: "count" },
|
|
250
|
+
],
|
|
251
|
+
levels: [
|
|
252
|
+
{ level: 1, minPoints: 0, maxPoints: 100 },
|
|
253
|
+
{ level: 2, minPoints: 100, maxPoints: 250 },
|
|
254
|
+
],
|
|
255
|
+
pointsPerAction: 5,
|
|
256
|
+
},
|
|
257
|
+
screenProps: {
|
|
258
|
+
title: "Your Achievements",
|
|
259
|
+
statsTitle: "Your Stats",
|
|
260
|
+
achievementsTitle: "Unlocked Achievements",
|
|
261
|
+
streakTitle: "Daily Streak",
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// 2. Use in navigator
|
|
266
|
+
<SettingsStackNavigator
|
|
267
|
+
appInfo={APP_INFO}
|
|
268
|
+
legalUrls={LEGAL_URLS}
|
|
269
|
+
gamificationConfig={gamificationConfig}
|
|
270
|
+
/>
|
|
271
|
+
|
|
272
|
+
// 3. Track actions in your app
|
|
273
|
+
import { useGamification } from "@umituz/react-native-settings";
|
|
274
|
+
|
|
275
|
+
const MyComponent = () => {
|
|
276
|
+
const { completeTask, addPoints } = useGamification();
|
|
277
|
+
|
|
278
|
+
const handleTaskComplete = () => {
|
|
279
|
+
completeTask(); // Adds points, updates streak, checks achievements
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
return <Button onPress={handleTaskComplete} title="Complete Task" />;
|
|
283
|
+
};
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Best Practices
|
|
287
|
+
|
|
288
|
+
1. **Config Files ≤ 80 lines** - Keep gamification config in separate file
|
|
289
|
+
2. **Use i18n** - Never hardcode strings, always use translation keys
|
|
290
|
+
3. **Initialize Early** - Initialize gamification in app startup
|
|
291
|
+
4. **Track Meaningfully** - Only track actions that matter to users
|
|
292
|
+
5. **Test Achievements** - Ensure thresholds are achievable and rewarding
|
|
293
|
+
|
|
294
|
+
## Testing
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
import { useGamification } from "@umituz/react-native-settings";
|
|
298
|
+
|
|
299
|
+
describe("Gamification", () => {
|
|
300
|
+
it("should track task completion", () => {
|
|
301
|
+
const { completeTask, totalTasksCompleted } = useGamification();
|
|
302
|
+
completeTask();
|
|
303
|
+
expect(totalTasksCompleted).toBe(1);
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## Troubleshooting
|
|
309
|
+
|
|
310
|
+
### Gamification screen not showing
|
|
311
|
+
- Ensure `gamificationConfig.enabled` is `true`
|
|
312
|
+
- Check that config is passed to `SettingsStackNavigator`
|
|
313
|
+
|
|
314
|
+
### Achievements not unlocking
|
|
315
|
+
- Verify achievement IDs match between config and localization
|
|
316
|
+
- Check threshold values are correct
|
|
317
|
+
- Ensure `completeTask()` or `addPoints()` is being called
|
|
318
|
+
|
|
319
|
+
### Localization missing
|
|
320
|
+
- Add all required translation keys
|
|
321
|
+
- Check language files are properly loaded
|
|
322
|
+
|
|
323
|
+
## Migration Guide
|
|
324
|
+
|
|
325
|
+
If migrating from standalone gamification package:
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
// Before
|
|
329
|
+
import { GamificationScreen } from "@umituz/react-native-gamification";
|
|
330
|
+
|
|
331
|
+
// After
|
|
332
|
+
import { GamificationScreenWrapper } from "@umituz/react-native-settings";
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Related Documentation
|
|
336
|
+
|
|
337
|
+
- [@umituz/react-native-gamification](../../../react-native-gamification/README.md)
|
|
338
|
+
- [Settings Architecture](../../ARCHITECTURE.md)
|
|
339
|
+
- [Settings Screen Guide](../../SETTINGS_SCREEN_GUIDE.md)
|
|
340
|
+
|
|
341
|
+
## License
|
|
342
|
+
|
|
343
|
+
MIT © Ümit UZ
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AchievementCard Component
|
|
3
|
+
* Displays achievement - all text via props
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { View, Text, StyleSheet, type ViewStyle, type TextStyle } from "react-native";
|
|
8
|
+
|
|
9
|
+
export interface AchievementCardProps {
|
|
10
|
+
title: string;
|
|
11
|
+
description: string;
|
|
12
|
+
icon: React.ReactNode;
|
|
13
|
+
isUnlocked: boolean;
|
|
14
|
+
progress: number;
|
|
15
|
+
// Customization
|
|
16
|
+
containerStyle?: ViewStyle;
|
|
17
|
+
titleStyle?: TextStyle;
|
|
18
|
+
descriptionStyle?: TextStyle;
|
|
19
|
+
progressBarStyle?: ViewStyle;
|
|
20
|
+
// Colors
|
|
21
|
+
unlockedColor?: string;
|
|
22
|
+
lockedColor?: string;
|
|
23
|
+
backgroundColor?: string;
|
|
24
|
+
textColor?: string;
|
|
25
|
+
subtextColor?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const AchievementCard: React.FC<AchievementCardProps> = ({
|
|
29
|
+
title,
|
|
30
|
+
description,
|
|
31
|
+
icon,
|
|
32
|
+
isUnlocked,
|
|
33
|
+
progress,
|
|
34
|
+
containerStyle,
|
|
35
|
+
titleStyle,
|
|
36
|
+
descriptionStyle,
|
|
37
|
+
progressBarStyle,
|
|
38
|
+
unlockedColor = "#4CAF50",
|
|
39
|
+
lockedColor = "#666666",
|
|
40
|
+
backgroundColor = "#1A1A1A",
|
|
41
|
+
textColor = "#FFFFFF",
|
|
42
|
+
subtextColor = "#888888",
|
|
43
|
+
}) => {
|
|
44
|
+
const accentColor = isUnlocked ? unlockedColor : lockedColor;
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<View
|
|
48
|
+
style={[
|
|
49
|
+
styles.container,
|
|
50
|
+
{ backgroundColor, borderColor: `${accentColor}40` },
|
|
51
|
+
containerStyle,
|
|
52
|
+
]}
|
|
53
|
+
>
|
|
54
|
+
<View style={[styles.iconContainer, { backgroundColor: `${accentColor}20` }]}>
|
|
55
|
+
{icon}
|
|
56
|
+
</View>
|
|
57
|
+
|
|
58
|
+
<View style={styles.content}>
|
|
59
|
+
<Text
|
|
60
|
+
style={[
|
|
61
|
+
styles.title,
|
|
62
|
+
{ color: isUnlocked ? textColor : subtextColor },
|
|
63
|
+
titleStyle,
|
|
64
|
+
]}
|
|
65
|
+
>
|
|
66
|
+
{title}
|
|
67
|
+
</Text>
|
|
68
|
+
<Text style={[styles.description, { color: subtextColor }, descriptionStyle]}>
|
|
69
|
+
{description}
|
|
70
|
+
</Text>
|
|
71
|
+
|
|
72
|
+
{!isUnlocked && (
|
|
73
|
+
<View style={[styles.progressBar, { backgroundColor: `${lockedColor}40` }, progressBarStyle]}>
|
|
74
|
+
<View
|
|
75
|
+
style={[
|
|
76
|
+
styles.progressFill,
|
|
77
|
+
{ width: `${progress}%`, backgroundColor: accentColor },
|
|
78
|
+
]}
|
|
79
|
+
/>
|
|
80
|
+
</View>
|
|
81
|
+
)}
|
|
82
|
+
</View>
|
|
83
|
+
|
|
84
|
+
{isUnlocked && (
|
|
85
|
+
<View style={[styles.checkmark, { backgroundColor: unlockedColor }]}>
|
|
86
|
+
<Text style={styles.checkmarkText}>✓</Text>
|
|
87
|
+
</View>
|
|
88
|
+
)}
|
|
89
|
+
</View>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const styles = StyleSheet.create({
|
|
94
|
+
container: {
|
|
95
|
+
flexDirection: "row",
|
|
96
|
+
alignItems: "center",
|
|
97
|
+
padding: 12,
|
|
98
|
+
borderRadius: 12,
|
|
99
|
+
borderWidth: 1,
|
|
100
|
+
gap: 12,
|
|
101
|
+
},
|
|
102
|
+
iconContainer: {
|
|
103
|
+
width: 48,
|
|
104
|
+
height: 48,
|
|
105
|
+
borderRadius: 24,
|
|
106
|
+
justifyContent: "center",
|
|
107
|
+
alignItems: "center",
|
|
108
|
+
},
|
|
109
|
+
content: {
|
|
110
|
+
flex: 1,
|
|
111
|
+
},
|
|
112
|
+
title: {
|
|
113
|
+
fontSize: 16,
|
|
114
|
+
fontWeight: "600",
|
|
115
|
+
},
|
|
116
|
+
description: {
|
|
117
|
+
fontSize: 13,
|
|
118
|
+
marginTop: 2,
|
|
119
|
+
},
|
|
120
|
+
progressBar: {
|
|
121
|
+
height: 4,
|
|
122
|
+
borderRadius: 2,
|
|
123
|
+
marginTop: 8,
|
|
124
|
+
overflow: "hidden",
|
|
125
|
+
},
|
|
126
|
+
progressFill: {
|
|
127
|
+
height: "100%",
|
|
128
|
+
borderRadius: 2,
|
|
129
|
+
},
|
|
130
|
+
checkmark: {
|
|
131
|
+
width: 24,
|
|
132
|
+
height: 24,
|
|
133
|
+
borderRadius: 12,
|
|
134
|
+
justifyContent: "center",
|
|
135
|
+
alignItems: "center",
|
|
136
|
+
},
|
|
137
|
+
checkmarkText: {
|
|
138
|
+
color: "#FFFFFF",
|
|
139
|
+
fontSize: 14,
|
|
140
|
+
fontWeight: "bold",
|
|
141
|
+
},
|
|
142
|
+
});
|