@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.
Files changed (78) hide show
  1. package/package.json +8 -60
  2. package/src/domains/gamification/README.md +343 -0
  3. package/src/domains/gamification/components/AchievementCard.tsx +142 -0
  4. package/src/domains/gamification/components/AchievementItem.tsx +182 -0
  5. package/src/domains/gamification/components/AchievementToast.tsx +122 -0
  6. package/src/domains/gamification/components/GamificationScreen/AchievementsList.tsx +84 -0
  7. package/src/domains/gamification/components/GamificationScreen/Header.tsx +29 -0
  8. package/src/domains/gamification/components/GamificationScreen/StatsGrid.tsx +51 -0
  9. package/src/domains/gamification/components/GamificationScreen/index.tsx +111 -0
  10. package/src/domains/gamification/components/GamificationScreen/styles.ts +43 -0
  11. package/src/domains/gamification/components/GamificationScreen/types.ts +77 -0
  12. package/src/domains/gamification/components/GamificationScreenWrapper.tsx +91 -0
  13. package/src/domains/gamification/components/GamificationSettingsItem.tsx +33 -0
  14. package/src/domains/gamification/components/LevelProgress.tsx +129 -0
  15. package/src/domains/gamification/components/PointsBadge.tsx +60 -0
  16. package/src/domains/gamification/components/StatsCard.tsx +89 -0
  17. package/src/domains/gamification/components/StreakDisplay.tsx +119 -0
  18. package/src/domains/gamification/components/index.ts +13 -0
  19. package/src/domains/gamification/examples/gamification.config.example.ts +70 -0
  20. package/src/domains/gamification/examples/localization.example.json +71 -0
  21. package/src/domains/gamification/hooks/useGamification.ts +91 -0
  22. package/src/domains/gamification/index.ts +65 -0
  23. package/src/domains/gamification/store/gamificationStore.ts +162 -0
  24. package/src/domains/gamification/types/index.ts +103 -0
  25. package/src/domains/gamification/types/settings.ts +28 -0
  26. package/src/domains/gamification/utils/calculations.ts +85 -0
  27. package/src/index.ts +18 -8
  28. package/src/presentation/navigation/SettingsStackNavigator.tsx +12 -0
  29. package/src/presentation/navigation/types.ts +2 -0
  30. package/src/presentation/navigation/utils/navigationScreenOptions.ts +7 -0
  31. package/src/presentation/screens/types/UserFeatureConfig.ts +2 -0
  32. package/src/presentation/utils/configCreators.ts +147 -0
  33. package/src/presentation/utils/index.ts +5 -0
  34. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -51
  35. package/.github/ISSUE_TEMPLATE/documentation.md +0 -52
  36. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -63
  37. package/.github/PULL_REQUEST_TEMPLATE.md +0 -84
  38. package/AI_AGENT_GUIDELINES.md +0 -367
  39. package/ARCHITECTURE.md +0 -246
  40. package/CHANGELOG.md +0 -67
  41. package/CODE_OF_CONDUCT.md +0 -75
  42. package/CONTRIBUTING.md +0 -107
  43. package/DOCUMENTATION_MIGRATION.md +0 -319
  44. package/DOCUMENTATION_TEMPLATE.md +0 -155
  45. package/SECURITY.md +0 -98
  46. package/SETTINGS_SCREEN_GUIDE.md +0 -185
  47. package/TESTING.md +0 -358
  48. package/src/__tests__/integration.test.tsx +0 -371
  49. package/src/__tests__/performance.test.tsx +0 -369
  50. package/src/__tests__/setup.test.tsx +0 -20
  51. package/src/__tests__/setup.ts +0 -154
  52. package/src/domains/about/__tests__/integration.test.tsx +0 -328
  53. package/src/domains/about/__tests__/types.d.ts +0 -5
  54. package/src/domains/about/domain/entities/__tests__/AppInfo.test.ts +0 -93
  55. package/src/domains/about/infrastructure/repositories/__tests__/AboutRepository.test.ts +0 -153
  56. package/src/domains/about/presentation/components/__tests__/AboutContent.simple.test.tsx +0 -178
  57. package/src/domains/about/presentation/components/__tests__/AboutContent.test.tsx +0 -293
  58. package/src/domains/about/presentation/components/__tests__/AboutHeader.test.tsx +0 -201
  59. package/src/domains/about/presentation/components/__tests__/AboutSettingItem.test.tsx +0 -71
  60. package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.simple.test.tsx +0 -229
  61. package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.test.tsx +0 -240
  62. package/src/domains/about/presentation/screens/__tests__/AboutScreen.simple.test.tsx +0 -199
  63. package/src/domains/about/presentation/screens/__tests__/AboutScreen.test.tsx +0 -366
  64. package/src/domains/about/utils/__tests__/index.test.ts +0 -408
  65. package/src/domains/appearance/__tests__/components/AppearanceScreen.test.tsx +0 -195
  66. package/src/domains/appearance/__tests__/hooks/index.test.tsx +0 -232
  67. package/src/domains/appearance/__tests__/integration/index.test.tsx +0 -207
  68. package/src/domains/appearance/__tests__/services/appearanceService.test.ts +0 -299
  69. package/src/domains/appearance/__tests__/setup.ts +0 -88
  70. package/src/domains/appearance/__tests__/stores/appearanceStore.test.tsx +0 -175
  71. package/src/domains/cloud-sync/presentation/components/__tests__/CloudSyncSetting.test.tsx +0 -78
  72. package/src/domains/legal/__tests__/ContentValidationService.test.ts +0 -195
  73. package/src/domains/legal/__tests__/StyleCacheService.test.ts +0 -110
  74. package/src/domains/legal/__tests__/UrlHandlerService.test.ts +0 -71
  75. package/src/domains/legal/__tests__/setup.ts +0 -82
  76. package/src/presentation/components/__tests__/SettingsErrorBoundary.test.tsx +0 -186
  77. package/src/presentation/screens/__tests__/SettingsScreen.test.tsx +0 -322
  78. package/src/presentation/screens/hooks/__tests__/useFeatureDetection.test.tsx +0 -261
@@ -0,0 +1,91 @@
1
+ /**
2
+ * useGamification Hook
3
+ * Main hook for gamification operations
4
+ */
5
+
6
+ import { useCallback, useEffect, useMemo } from "react";
7
+ import { useGamificationStore } from "../store/gamificationStore";
8
+ import { calculateLevel } from "../utils/calculations";
9
+ import type { GamificationConfig, LevelState, Achievement } from "../types";
10
+
11
+ export interface UseGamificationReturn {
12
+ // State
13
+ points: number;
14
+ totalTasksCompleted: number;
15
+ level: LevelState;
16
+ streak: { current: number; longest: number };
17
+ achievements: Achievement[];
18
+ isLoading: boolean;
19
+ isInitialized: boolean;
20
+
21
+ // Actions
22
+ initialize: (config: GamificationConfig) => Promise<void>;
23
+ completeTask: () => void;
24
+ addPoints: (amount: number) => void;
25
+ reset: () => Promise<void>;
26
+ }
27
+
28
+ export const useGamification = (
29
+ config?: GamificationConfig
30
+ ): UseGamificationReturn => {
31
+ const store = useGamificationStore();
32
+
33
+ // Auto-initialize if config provided
34
+ useEffect(() => {
35
+ if (config && !store.isInitialized) {
36
+ store.initialize(config);
37
+ }
38
+ }, [config, store.isInitialized]);
39
+
40
+ // Calculate level from config
41
+ const level = useMemo((): LevelState => {
42
+ if (!config?.levels.length) {
43
+ return {
44
+ currentLevel: 1,
45
+ currentPoints: store.points,
46
+ pointsToNext: 50,
47
+ progress: Math.min(100, (store.points / 50) * 100),
48
+ };
49
+ }
50
+ return calculateLevel(store.points, config.levels);
51
+ }, [store.points, config?.levels]);
52
+
53
+ const completeTask = useCallback(() => {
54
+ store.completeTask();
55
+ }, [store.completeTask]);
56
+
57
+ const addPoints = useCallback(
58
+ (amount: number) => {
59
+ store.addPoints(amount);
60
+ },
61
+ [store.addPoints]
62
+ );
63
+
64
+ const initialize = useCallback(
65
+ async (cfg: GamificationConfig) => {
66
+ await store.initialize(cfg);
67
+ },
68
+ [store.initialize]
69
+ );
70
+
71
+ const reset = useCallback(async () => {
72
+ await store.reset();
73
+ }, [store.reset]);
74
+
75
+ return {
76
+ points: store.points,
77
+ totalTasksCompleted: store.totalTasksCompleted,
78
+ level,
79
+ streak: {
80
+ current: store.streak.current,
81
+ longest: store.streak.longest,
82
+ },
83
+ achievements: store.achievements,
84
+ isLoading: store.isLoading,
85
+ isInitialized: store.isInitialized,
86
+ initialize,
87
+ completeTask,
88
+ addPoints,
89
+ reset,
90
+ };
91
+ };
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @umituz/react-native-gamification
3
+ *
4
+ * Generic gamification system for React Native apps
5
+ * All text via props - NO hardcoded strings
6
+ * Designed for 100+ apps
7
+ */
8
+
9
+ // Types
10
+ export type {
11
+ AchievementDefinition,
12
+ Achievement,
13
+ LevelDefinition,
14
+ LevelState,
15
+ StreakState,
16
+ GamificationConfig,
17
+ GamificationState,
18
+ GamificationActions,
19
+ GamificationStore,
20
+ } from "./types";
21
+
22
+ // Settings Integration Types
23
+ export type {
24
+ GamificationSettingsConfig,
25
+ GamificationMenuConfig,
26
+ } from "./types/settings";
27
+
28
+ // Store
29
+ export { useGamificationStore } from "./store/gamificationStore";
30
+
31
+ // Hooks
32
+ export { useGamification, type UseGamificationReturn } from "./hooks/useGamification";
33
+
34
+ // Utils
35
+ export {
36
+ calculateLevel,
37
+ checkAchievementUnlock,
38
+ updateAchievementProgress,
39
+ isStreakActive,
40
+ isSameDay,
41
+ } from "./utils/calculations";
42
+
43
+ // Components
44
+ export {
45
+ LevelProgress,
46
+ type LevelProgressProps,
47
+ PointsBadge,
48
+ type PointsBadgeProps,
49
+ AchievementCard,
50
+ type AchievementCardProps,
51
+ AchievementToast,
52
+ type AchievementToastProps,
53
+ StreakDisplay,
54
+ type StreakDisplayProps,
55
+ StatsCard,
56
+ type StatsCardProps,
57
+ AchievementItem,
58
+ type AchievementItemProps,
59
+ GamificationScreen,
60
+ type GamificationScreenProps,
61
+ } from "./components";
62
+
63
+ // Settings Integration Components
64
+ export { GamificationScreenWrapper } from "./components/GamificationScreenWrapper";
65
+ export { GamificationSettingsItem } from "./components/GamificationSettingsItem";
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Gamification Store
3
+ * Zustand store with persist middleware
4
+ */
5
+
6
+ import { createStore } from "@umituz/react-native-storage";
7
+ import type {
8
+ GamificationState,
9
+ GamificationActions,
10
+ GamificationConfig,
11
+ Achievement,
12
+ } from "../types";
13
+ import {
14
+ checkAchievementUnlock,
15
+ updateAchievementProgress,
16
+ isStreakActive,
17
+ isSameDay,
18
+ } from "../utils/calculations";
19
+
20
+ const DEFAULT_STATE: GamificationState = {
21
+ points: 0,
22
+ totalTasksCompleted: 0,
23
+ achievements: [],
24
+ streak: {
25
+ current: 0,
26
+ longest: 0,
27
+ lastActivityDate: null,
28
+ },
29
+ isLoading: false,
30
+ isInitialized: false,
31
+ };
32
+
33
+ let currentConfig: GamificationConfig | null = null;
34
+
35
+ export const useGamificationStore = createStore<GamificationState, GamificationActions>({
36
+ name: "gamification-storage",
37
+ initialState: DEFAULT_STATE,
38
+ persist: true,
39
+ version: 1,
40
+ partialize: (state) => ({
41
+ points: state.points,
42
+ totalTasksCompleted: state.totalTasksCompleted,
43
+ achievements: state.achievements,
44
+ streak: state.streak,
45
+ isLoading: false,
46
+ isInitialized: false,
47
+ }),
48
+ actions: (set, get) => ({
49
+ initialize: async (config: GamificationConfig) => {
50
+ currentConfig = config;
51
+ const state = get();
52
+
53
+ // Initialize achievements from config
54
+ const achievements: Achievement[] = config.achievements.map((def) => ({
55
+ ...def,
56
+ isUnlocked: false,
57
+ progress: 0,
58
+ }));
59
+
60
+ // Merge with existing unlocked achievements
61
+ const mergedAchievements = achievements.map((ach: Achievement) => {
62
+ const existing = state.achievements.find((a: Achievement) => a.id === ach.id);
63
+ if (existing) {
64
+ return { ...ach, isUnlocked: existing.isUnlocked, progress: existing.progress };
65
+ }
66
+ return ach;
67
+ });
68
+
69
+ set({ achievements: mergedAchievements, isInitialized: true });
70
+ },
71
+
72
+ addPoints: (amount: number) => {
73
+ const state = get();
74
+ set({ points: state.points + amount });
75
+ },
76
+
77
+ completeTask: () => {
78
+ const state = get();
79
+ const pointsToAdd = currentConfig?.pointsPerAction ?? 15;
80
+
81
+ set({
82
+ totalTasksCompleted: state.totalTasksCompleted + 1,
83
+ points: state.points + pointsToAdd,
84
+ });
85
+
86
+ // Update streak
87
+ get().updateStreak();
88
+
89
+ // Check achievements
90
+ get().checkAchievements();
91
+ },
92
+
93
+ updateStreak: () => {
94
+ const state = get();
95
+ const now = new Date();
96
+ const lastDate = state.streak.lastActivityDate
97
+ ? new Date(state.streak.lastActivityDate)
98
+ : null;
99
+
100
+ let newStreak = state.streak.current;
101
+
102
+ if (!lastDate || !isSameDay(lastDate, now)) {
103
+ if (isStreakActive(state.streak.lastActivityDate)) {
104
+ newStreak = state.streak.current + 1;
105
+ } else {
106
+ newStreak = 1;
107
+ }
108
+ }
109
+
110
+ set({
111
+ streak: {
112
+ current: newStreak,
113
+ longest: Math.max(state.streak.longest, newStreak),
114
+ lastActivityDate: now.toISOString(),
115
+ },
116
+ });
117
+ },
118
+
119
+ checkAchievements: () => {
120
+ if (!currentConfig) return [];
121
+
122
+ const state = get();
123
+ const newlyUnlocked: Achievement[] = [];
124
+
125
+ const updatedAchievements = state.achievements.map((ach: Achievement) => {
126
+ if (ach.isUnlocked) return ach;
127
+
128
+ const progress = updateAchievementProgress(
129
+ ach,
130
+ state.totalTasksCompleted,
131
+ state.streak.current
132
+ );
133
+
134
+ const shouldUnlock = checkAchievementUnlock(
135
+ ach,
136
+ state.totalTasksCompleted,
137
+ state.streak.current
138
+ );
139
+
140
+ if (shouldUnlock && !ach.isUnlocked) {
141
+ const unlocked = {
142
+ ...ach,
143
+ isUnlocked: true,
144
+ unlockedAt: new Date().toISOString(),
145
+ progress: 100,
146
+ };
147
+ newlyUnlocked.push(unlocked);
148
+ return unlocked;
149
+ }
150
+
151
+ return { ...ach, progress };
152
+ });
153
+
154
+ set({ achievements: updatedAchievements });
155
+ return newlyUnlocked;
156
+ },
157
+
158
+ reset: async () => {
159
+ set(DEFAULT_STATE);
160
+ },
161
+ }),
162
+ });
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Gamification Types
3
+ * Generic types for 100+ apps - NO app-specific code
4
+ */
5
+
6
+ // Achievement Definition (provided by app)
7
+ export interface AchievementDefinition {
8
+ id: string;
9
+ threshold: number;
10
+ type: "count" | "streak" | "milestone";
11
+ }
12
+
13
+ // Achievement State (internal)
14
+ export interface Achievement extends AchievementDefinition {
15
+ isUnlocked: boolean;
16
+ unlockedAt?: string;
17
+ progress: number;
18
+ }
19
+
20
+ // Level Definition (provided by app)
21
+ export interface LevelDefinition {
22
+ level: number;
23
+ minPoints: number;
24
+ maxPoints: number;
25
+ }
26
+
27
+ // Level State (internal)
28
+ export interface LevelState {
29
+ currentLevel: number;
30
+ currentPoints: number;
31
+ pointsToNext: number;
32
+ progress: number;
33
+ }
34
+
35
+ // Streak State
36
+ export interface StreakState {
37
+ current: number;
38
+ longest: number;
39
+ lastActivityDate: string | null;
40
+ }
41
+
42
+ // Gamification Config (provided by app via props)
43
+ export interface GamificationConfig {
44
+ storageKey: string;
45
+ achievements: AchievementDefinition[];
46
+ levels: LevelDefinition[];
47
+ pointsPerAction?: number;
48
+ streakBonusMultiplier?: number;
49
+ }
50
+
51
+ // Store State
52
+ export interface GamificationState {
53
+ points: number;
54
+ totalTasksCompleted: number;
55
+ achievements: Achievement[];
56
+ streak: StreakState;
57
+ isLoading: boolean;
58
+ isInitialized: boolean;
59
+ }
60
+
61
+ // Store Actions
62
+ export interface GamificationActions {
63
+ initialize: (config: GamificationConfig) => Promise<void>;
64
+ addPoints: (amount: number) => void;
65
+ completeTask: () => void;
66
+ updateStreak: () => void;
67
+ checkAchievements: () => Achievement[];
68
+ reset: () => Promise<void>;
69
+ }
70
+
71
+ // Combined Store
72
+ export type GamificationStore = GamificationState & GamificationActions;
73
+
74
+ // UI Component Props (all text via props - NO hardcoded strings)
75
+ export interface LevelProgressProps {
76
+ level: number;
77
+ points: number;
78
+ levelTitle: string;
79
+ pointsToNext: number;
80
+ progress: number;
81
+ showPoints?: boolean;
82
+ }
83
+
84
+ export interface AchievementCardProps {
85
+ title: string;
86
+ description: string;
87
+ icon: string;
88
+ isUnlocked: boolean;
89
+ progress: number;
90
+ threshold: number;
91
+ }
92
+
93
+ export interface StreakDisplayProps {
94
+ current: number;
95
+ longest: number;
96
+ streakLabel: string;
97
+ bestLabel: string;
98
+ }
99
+
100
+ export interface PointsBadgeProps {
101
+ points: number;
102
+ label?: string;
103
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Gamification Settings Integration Types
3
+ * Wrapper types for integrating gamification into settings
4
+ */
5
+
6
+ import type { GamificationConfig } from "./index";
7
+ import type { GamificationScreenProps } from "../components/GamificationScreen/types";
8
+
9
+ /**
10
+ * Configuration for gamification in settings
11
+ */
12
+ export interface GamificationSettingsConfig {
13
+ enabled: boolean;
14
+ config: GamificationConfig;
15
+ screenProps: Omit<GamificationScreenProps, "levelProps" | "stats" | "achievements">;
16
+ onNavigate?: () => void;
17
+ }
18
+
19
+ /**
20
+ * Configuration for gamification menu item
21
+ */
22
+ export interface GamificationMenuConfig {
23
+ enabled: boolean;
24
+ title: string;
25
+ subtitle?: string;
26
+ icon?: string;
27
+ onPress?: () => void;
28
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Gamification Calculations
3
+ * Pure utility functions - NO side effects
4
+ */
5
+
6
+ import type { LevelDefinition, LevelState, Achievement, AchievementDefinition } from "../types";
7
+
8
+ export const calculateLevel = (
9
+ points: number,
10
+ levels: LevelDefinition[]
11
+ ): LevelState => {
12
+ const sortedLevels = [...levels].sort((a, b) => a.minPoints - b.minPoints);
13
+
14
+ let currentLevelDef = sortedLevels[0];
15
+ let nextLevelDef: LevelDefinition | null = null;
16
+
17
+ for (let i = 0; i < sortedLevels.length; i++) {
18
+ if (points >= sortedLevels[i].minPoints) {
19
+ currentLevelDef = sortedLevels[i];
20
+ nextLevelDef = sortedLevels[i + 1] || null;
21
+ }
22
+ }
23
+
24
+ const pointsInLevel = points - currentLevelDef.minPoints;
25
+ const levelRange = nextLevelDef
26
+ ? nextLevelDef.minPoints - currentLevelDef.minPoints
27
+ : 100;
28
+ const progress = Math.min(100, (pointsInLevel / levelRange) * 100);
29
+ const pointsToNext = nextLevelDef
30
+ ? nextLevelDef.minPoints - points
31
+ : 0;
32
+
33
+ return {
34
+ currentLevel: currentLevelDef.level,
35
+ currentPoints: points,
36
+ pointsToNext,
37
+ progress,
38
+ };
39
+ };
40
+
41
+ export const checkAchievementUnlock = (
42
+ definition: AchievementDefinition,
43
+ tasksCompleted: number,
44
+ currentStreak: number
45
+ ): boolean => {
46
+ switch (definition.type) {
47
+ case "count":
48
+ return tasksCompleted >= definition.threshold;
49
+ case "streak":
50
+ return currentStreak >= definition.threshold;
51
+ case "milestone":
52
+ return tasksCompleted >= definition.threshold;
53
+ default:
54
+ return false;
55
+ }
56
+ };
57
+
58
+ export const updateAchievementProgress = (
59
+ definition: AchievementDefinition,
60
+ tasksCompleted: number,
61
+ currentStreak: number
62
+ ): number => {
63
+ const value = definition.type === "streak" ? currentStreak : tasksCompleted;
64
+ return Math.min(100, (value / definition.threshold) * 100);
65
+ };
66
+
67
+ export const isStreakActive = (lastActivityDate: string | null): boolean => {
68
+ if (!lastActivityDate) return false;
69
+
70
+ const last = new Date(lastActivityDate);
71
+ const now = new Date();
72
+ const diffDays = Math.floor(
73
+ (now.getTime() - last.getTime()) / (1000 * 60 * 60 * 24)
74
+ );
75
+
76
+ return diffDays <= 1;
77
+ };
78
+
79
+ export const isSameDay = (date1: Date, date2: Date): boolean => {
80
+ return (
81
+ date1.getFullYear() === date2.getFullYear() &&
82
+ date1.getMonth() === date2.getMonth() &&
83
+ date1.getDate() === date2.getDate()
84
+ );
85
+ };
package/src/index.ts CHANGED
@@ -120,14 +120,24 @@ export * from "./domains/cloud-sync";
120
120
  // Dev Domain - Development-only settings (DEV mode)
121
121
  export * from "./domains/dev";
122
122
 
123
+ // Gamification Domain - Achievements, levels, streaks
124
+ export * from "./domains/gamification";
125
+
126
+
123
127
  // =============================================================================
124
- // PRESENTATION LAYER - Re-exports from Dependencies
128
+ // PRESENTATION LAYER - Config Creator Utilities
125
129
  // =============================================================================
126
130
 
127
- // @ts-ignore - Re-exporting from peer dependency
128
- export { OnboardingResetSetting } from '@umituz/react-native-onboarding';
129
- // @ts-ignore - Re-exporting from peer dependency
130
- export type { OnboardingResetSettingProps } from '@umituz/react-native-onboarding';
131
-
132
- // @ts-ignore - Re-exporting from peer dependency
133
- // @ts-ignore - Re-exporting from peer dependency
131
+ export {
132
+ createAppearanceConfig,
133
+ createLanguageConfig,
134
+ createNotificationsConfig,
135
+ createAboutConfig,
136
+ createLegalConfig,
137
+ createFeedbackConfig,
138
+ createRatingConfig,
139
+ createFAQConfig,
140
+ createSubscriptionConfig,
141
+ type TranslationFunction,
142
+ type FeedbackFormData,
143
+ } from './presentation/utils';
@@ -29,8 +29,10 @@ import {
29
29
  createNotificationsScreenOptions,
30
30
  createFAQScreenOptions,
31
31
  createLanguageSelectionScreenOptions,
32
+ createGamificationScreenOptions,
32
33
  } from "./utils";
33
34
  import type { SettingsStackParamList, SettingsStackNavigatorProps } from "./types";
35
+ import { GamificationScreenWrapper } from "../../domains/gamification";
34
36
 
35
37
  const Stack = createStackNavigator<SettingsStackParamList>();
36
38
 
@@ -45,6 +47,7 @@ export const SettingsStackNavigator: React.FC<SettingsStackNavigatorProps> = ({
45
47
  devSettings,
46
48
  customSections = [],
47
49
  showHeader = true,
50
+ gamificationConfig,
48
51
  }) => {
49
52
  const tokens = useAppDesignTokens();
50
53
  const { t } = useLocalization();
@@ -143,6 +146,15 @@ export const SettingsStackNavigator: React.FC<SettingsStackNavigatorProps> = ({
143
146
  ) : null
144
147
  )}
145
148
 
149
+ {gamificationConfig?.enabled && (
150
+ <Stack.Screen
151
+ name="Gamification"
152
+ options={createGamificationScreenOptions(t)}
153
+ >
154
+ {() => <GamificationScreenWrapper config={gamificationConfig} />}
155
+ </Stack.Screen>
156
+ )}
157
+
146
158
  <Stack.Screen
147
159
  name="LanguageSelection"
148
160
  options={createLanguageSelectionScreenOptions(t)}
@@ -42,6 +42,7 @@ export type SettingsStackParamList = {
42
42
  Notifications: undefined;
43
43
  FAQ: undefined;
44
44
  LanguageSelection: undefined;
45
+ Gamification: undefined;
45
46
  };
46
47
 
47
48
  /**
@@ -89,4 +90,5 @@ export interface SettingsStackNavigatorProps {
89
90
  devSettings?: DevSettingsProps;
90
91
  customSections?: CustomSettingsSection[];
91
92
  showHeader?: boolean;
93
+ gamificationConfig?: import("../../domains/gamification").GamificationSettingsConfig;
92
94
  }
@@ -54,3 +54,10 @@ export const createLanguageSelectionScreenOptions = (t: any) => ({
54
54
  headerTitle: t("settings.language.title"),
55
55
  headerTitleAlign: "center" as const,
56
56
  });
57
+
58
+ export const createGamificationScreenOptions = (t: any) => ({
59
+ headerShown: true,
60
+ headerTitle: t("settings.gamification.title"),
61
+ headerTitleAlign: "center" as const,
62
+ });
63
+
@@ -12,6 +12,8 @@ import type { FeedbackType } from "../../../domains/feedback/domain/entities/Fee
12
12
  export interface UserProfileConfig {
13
13
  /** Show user profile header */
14
14
  enabled?: boolean;
15
+ /** Custom section title for grouping */
16
+ sectionTitle?: string;
15
17
  /** Custom display name for anonymous users */
16
18
  anonymousDisplayName?: string;
17
19
  /** Custom avatar service URL */