@umituz/react-native-settings 4.20.62 → 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 (69) hide show
  1. package/package.json +6 -61
  2. package/src/domains/gamification/components/AchievementCard.tsx +142 -0
  3. package/src/domains/gamification/components/AchievementItem.tsx +182 -0
  4. package/src/domains/gamification/components/AchievementToast.tsx +122 -0
  5. package/src/domains/gamification/components/GamificationScreen/AchievementsList.tsx +84 -0
  6. package/src/domains/gamification/components/GamificationScreen/Header.tsx +29 -0
  7. package/src/domains/gamification/components/GamificationScreen/StatsGrid.tsx +51 -0
  8. package/src/domains/gamification/components/GamificationScreen/index.tsx +111 -0
  9. package/src/domains/gamification/components/GamificationScreen/styles.ts +43 -0
  10. package/src/domains/gamification/components/GamificationScreen/types.ts +77 -0
  11. package/src/domains/gamification/components/GamificationScreenWrapper.tsx +4 -4
  12. package/src/domains/gamification/components/GamificationSettingsItem.tsx +1 -1
  13. package/src/domains/gamification/components/LevelProgress.tsx +129 -0
  14. package/src/domains/gamification/components/PointsBadge.tsx +60 -0
  15. package/src/domains/gamification/components/StatsCard.tsx +89 -0
  16. package/src/domains/gamification/components/StreakDisplay.tsx +119 -0
  17. package/src/domains/gamification/components/index.ts +13 -0
  18. package/src/domains/gamification/examples/gamification.config.example.ts +1 -1
  19. package/src/domains/gamification/hooks/useGamification.ts +91 -0
  20. package/src/domains/gamification/index.ts +46 -19
  21. package/src/domains/gamification/store/gamificationStore.ts +162 -0
  22. package/src/domains/gamification/types/index.ts +95 -23
  23. package/src/domains/gamification/types/settings.ts +28 -0
  24. package/src/domains/gamification/utils/calculations.ts +85 -0
  25. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -51
  26. package/.github/ISSUE_TEMPLATE/documentation.md +0 -52
  27. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -63
  28. package/.github/PULL_REQUEST_TEMPLATE.md +0 -84
  29. package/AI_AGENT_GUIDELINES.md +0 -367
  30. package/ARCHITECTURE.md +0 -246
  31. package/CHANGELOG.md +0 -67
  32. package/CODE_OF_CONDUCT.md +0 -75
  33. package/CONTRIBUTING.md +0 -107
  34. package/DOCUMENTATION_MIGRATION.md +0 -319
  35. package/DOCUMENTATION_TEMPLATE.md +0 -155
  36. package/SECURITY.md +0 -98
  37. package/SETTINGS_SCREEN_GUIDE.md +0 -185
  38. package/TESTING.md +0 -358
  39. package/src/__tests__/integration.test.tsx +0 -371
  40. package/src/__tests__/performance.test.tsx +0 -369
  41. package/src/__tests__/setup.test.tsx +0 -20
  42. package/src/__tests__/setup.ts +0 -154
  43. package/src/domains/about/__tests__/integration.test.tsx +0 -328
  44. package/src/domains/about/__tests__/types.d.ts +0 -5
  45. package/src/domains/about/domain/entities/__tests__/AppInfo.test.ts +0 -93
  46. package/src/domains/about/infrastructure/repositories/__tests__/AboutRepository.test.ts +0 -153
  47. package/src/domains/about/presentation/components/__tests__/AboutContent.simple.test.tsx +0 -178
  48. package/src/domains/about/presentation/components/__tests__/AboutContent.test.tsx +0 -293
  49. package/src/domains/about/presentation/components/__tests__/AboutHeader.test.tsx +0 -201
  50. package/src/domains/about/presentation/components/__tests__/AboutSettingItem.test.tsx +0 -71
  51. package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.simple.test.tsx +0 -229
  52. package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.test.tsx +0 -240
  53. package/src/domains/about/presentation/screens/__tests__/AboutScreen.simple.test.tsx +0 -199
  54. package/src/domains/about/presentation/screens/__tests__/AboutScreen.test.tsx +0 -366
  55. package/src/domains/about/utils/__tests__/index.test.ts +0 -408
  56. package/src/domains/appearance/__tests__/components/AppearanceScreen.test.tsx +0 -195
  57. package/src/domains/appearance/__tests__/hooks/index.test.tsx +0 -232
  58. package/src/domains/appearance/__tests__/integration/index.test.tsx +0 -207
  59. package/src/domains/appearance/__tests__/services/appearanceService.test.ts +0 -299
  60. package/src/domains/appearance/__tests__/setup.ts +0 -88
  61. package/src/domains/appearance/__tests__/stores/appearanceStore.test.tsx +0 -175
  62. package/src/domains/cloud-sync/presentation/components/__tests__/CloudSyncSetting.test.tsx +0 -78
  63. package/src/domains/legal/__tests__/ContentValidationService.test.ts +0 -195
  64. package/src/domains/legal/__tests__/StyleCacheService.test.ts +0 -110
  65. package/src/domains/legal/__tests__/UrlHandlerService.test.ts +0 -71
  66. package/src/domains/legal/__tests__/setup.ts +0 -82
  67. package/src/presentation/components/__tests__/SettingsErrorBoundary.test.tsx +0 -186
  68. package/src/presentation/screens/__tests__/SettingsScreen.test.tsx +0 -322
  69. package/src/presentation/screens/hooks/__tests__/useFeatureDetection.test.tsx +0 -261
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Gamification Components
3
+ * All text via props - NO hardcoded strings
4
+ */
5
+
6
+ export { LevelProgress, type LevelProgressProps } from "./LevelProgress";
7
+ export { PointsBadge, type PointsBadgeProps } from "./PointsBadge";
8
+ export { AchievementCard, type AchievementCardProps } from "./AchievementCard";
9
+ export { AchievementToast, type AchievementToastProps } from "./AchievementToast";
10
+ export { StreakDisplay, type StreakDisplayProps } from "./StreakDisplay";
11
+ export { StatsCard, type StatsCardProps } from "./StatsCard";
12
+ export { AchievementItem, type AchievementItemProps } from "./AchievementItem";
13
+ export { GamificationScreen, type GamificationScreenProps } from "./GamificationScreen/index";
@@ -5,7 +5,7 @@
5
5
  * src/domains/settings/config/gamification.config.ts
6
6
  */
7
7
 
8
- import type { GamificationSettingsConfig } from "../types";
8
+ import type { GamificationSettingsConfig } from "../types/settings";
9
9
 
10
10
  /**
11
11
  * Creates gamification configuration for settings
@@ -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
+ };
@@ -1,38 +1,65 @@
1
1
  /**
2
- * Gamification Domain - Public API
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
3
7
  */
4
8
 
5
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
6
23
  export type {
7
24
  GamificationSettingsConfig,
8
25
  GamificationMenuConfig,
9
- } from "./types";
26
+ } from "./types/settings";
10
27
 
11
- // Components
12
- export { GamificationScreenWrapper } from "./components/GamificationScreenWrapper";
13
- export type { GamificationScreenWrapperProps } from "./components/GamificationScreenWrapper";
28
+ // Store
29
+ export { useGamificationStore } from "./store/gamificationStore";
14
30
 
15
- export { GamificationSettingsItem } from "./components/GamificationSettingsItem";
16
- export type { GamificationSettingsItemProps } from "./components/GamificationSettingsItem";
31
+ // Hooks
32
+ export { useGamification, type UseGamificationReturn } from "./hooks/useGamification";
17
33
 
18
- // Re-export from gamification package for convenience
34
+ // Utils
35
+ export {
36
+ calculateLevel,
37
+ checkAchievementUnlock,
38
+ updateAchievementProgress,
39
+ isStreakActive,
40
+ isSameDay,
41
+ } from "./utils/calculations";
42
+
43
+ // Components
19
44
  export {
20
- useGamification,
21
- useGamificationStore,
22
45
  LevelProgress,
46
+ type LevelProgressProps,
23
47
  PointsBadge,
48
+ type PointsBadgeProps,
24
49
  AchievementCard,
50
+ type AchievementCardProps,
25
51
  AchievementToast,
52
+ type AchievementToastProps,
26
53
  StreakDisplay,
54
+ type StreakDisplayProps,
27
55
  StatsCard,
56
+ type StatsCardProps,
28
57
  AchievementItem,
29
- } from "@umituz/react-native-gamification";
58
+ type AchievementItemProps,
59
+ GamificationScreen,
60
+ type GamificationScreenProps,
61
+ } from "./components";
30
62
 
31
- export type {
32
- GamificationConfig,
33
- GamificationState,
34
- Achievement,
35
- LevelState,
36
- StreakState,
37
- UseGamificationReturn,
38
- } from "@umituz/react-native-gamification";
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
+ });
@@ -1,31 +1,103 @@
1
1
  /**
2
- * Gamification Domain - Types
3
- * Settings package integration for gamification
2
+ * Gamification Types
3
+ * Generic types for 100+ apps - NO app-specific code
4
4
  */
5
5
 
6
- import type {
7
- GamificationConfig,
8
- GamificationScreenProps,
9
- } from "@umituz/react-native-gamification";
6
+ // Achievement Definition (provided by app)
7
+ export interface AchievementDefinition {
8
+ id: string;
9
+ threshold: number;
10
+ type: "count" | "streak" | "milestone";
11
+ }
10
12
 
11
- /**
12
- * Gamification settings configuration
13
- * Passed from app to settings package
14
- */
15
- export interface GamificationSettingsConfig {
16
- enabled: boolean;
17
- config: GamificationConfig;
18
- screenProps: Omit<GamificationScreenProps, "levelProps" | "stats" | "achievements">;
19
- onNavigate?: () => void;
13
+ // Achievement State (internal)
14
+ export interface Achievement extends AchievementDefinition {
15
+ isUnlocked: boolean;
16
+ unlockedAt?: string;
17
+ progress: number;
20
18
  }
21
19
 
22
- /**
23
- * Gamification menu item configuration
24
- */
25
- export interface GamificationMenuConfig {
26
- enabled: boolean;
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 {
27
85
  title: string;
28
- subtitle?: string;
29
- icon?: string;
30
- onPress?: () => void;
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;
31
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
+ };
@@ -1,51 +0,0 @@
1
- ---
2
- name: Bug report
3
- about: Create a report to help us improve
4
- title: '[BUG] '
5
- labels: bug
6
- assignees: ''
7
- ---
8
-
9
- ## Bug Description
10
-
11
- A clear and concise description of what the bug is.
12
-
13
- ## Reproduction Steps
14
-
15
- 1. Go to '...'
16
- 2. Click on '....'
17
- 3. Scroll down to '....'
18
- 4. See error
19
-
20
- ## Expected Behavior
21
-
22
- A clear and concise description of what you expected to happen.
23
-
24
- ## Actual Behavior
25
-
26
- A clear and concise description of what actually happened.
27
-
28
- ## Screenshots
29
-
30
- If applicable, add screenshots to help explain your problem.
31
-
32
- ## Environment
33
-
34
- | Software | Version |
35
- |----------|---------|
36
- | React Native | |
37
- | iOS | |
38
- | Android | |
39
- | @umituz/react-native-settings | |
40
- | Node | |
41
- | npm/yarn | |
42
-
43
- ## Additional Context
44
-
45
- Add any other context about the problem here.
46
-
47
- ## Console Logs
48
-
49
- ```
50
- Paste your console logs here
51
- ```
@@ -1,52 +0,0 @@
1
- ---
2
- name: Documentation
3
- about: Report documentation issues or suggest improvements
4
- title: '[DOCS] '
5
- labels: documentation
6
- assignees: ''
7
- ---
8
-
9
- ## Documentation Issue
10
-
11
- Please describe the documentation issue:
12
-
13
- - [ ] Inaccurate information
14
- - [ ] Missing information
15
- - [ ] Unclear or confusing
16
- - [ ] Outdated content
17
- - [ ] Typo or grammatical error
18
- - [ ] Suggestion for improvement
19
-
20
- ## Affected Documentation
21
-
22
- Which documentation file(s) are affected?
23
- - [ ] README.md
24
- - [ ] ARCHITECTURE.md
25
- - [ ] TESTING.md
26
- - [ ] AI_AGENT_GUIDELINES.md
27
- - [ ] SETTINGS_SCREEN_GUIDE.md
28
- - [ ] Specific component README
29
- - [ ] Other (please specify)
30
-
31
- ## Current Documentation
32
-
33
- Paste or describe the current documentation content that needs improvement:
34
-
35
- ```
36
- Paste current documentation here
37
- ```
38
-
39
- ## Suggested Change
40
-
41
- Please describe what should be changed or added:
42
-
43
- ## Additional Context
44
-
45
- Add any other context, screenshots, or examples about the documentation issue.
46
-
47
- ## AI Agent Guidelines
48
-
49
- If this is about AI agent guidelines, please specify:
50
- - Which file needs updating
51
- - What guidelines are missing or unclear
52
- - How the guidelines could be improved