@umituz/react-native-subscription 2.14.99 → 2.14.101

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 (98) hide show
  1. package/README.md +211 -394
  2. package/package.json +3 -3
  3. package/src/application/README.md +46 -225
  4. package/src/application/ports/README.md +42 -97
  5. package/src/domain/README.md +36 -384
  6. package/src/domain/constants/README.md +0 -56
  7. package/src/domain/entities/README.md +43 -169
  8. package/src/domain/entities/SubscriptionStatus.ts +1 -1
  9. package/src/domain/errors/README.md +33 -287
  10. package/src/domain/value-objects/README.md +43 -179
  11. package/src/domains/README.md +50 -238
  12. package/src/domains/README.md.bak +274 -0
  13. package/src/domains/config/README.md +93 -383
  14. package/src/domains/config/domain/README.md +23 -376
  15. package/src/domains/config/domain/entities/README.md +34 -343
  16. package/src/domains/paywall/README.md +99 -369
  17. package/src/domains/paywall/components/README.md +34 -178
  18. package/src/domains/paywall/entities/README.md +34 -193
  19. package/src/domains/paywall/hooks/README.md +34 -122
  20. package/src/domains/wallet/README.md +34 -275
  21. package/src/domains/wallet/README.md.bak +209 -0
  22. package/src/domains/wallet/domain/README.md +34 -101
  23. package/src/domains/wallet/domain/entities/README.md +34 -115
  24. package/src/domains/wallet/domain/errors/README.md +34 -151
  25. package/src/domains/wallet/infrastructure/README.md +34 -89
  26. package/src/domains/wallet/presentation/components/README.md +34 -224
  27. package/src/domains/wallet/presentation/components/TransactionItem.tsx +1 -1
  28. package/src/domains/wallet/presentation/hooks/README.md +34 -248
  29. package/src/infrastructure/README.md +37 -496
  30. package/src/infrastructure/mappers/README.md +0 -13
  31. package/src/infrastructure/repositories/README.md +74 -360
  32. package/src/infrastructure/services/ActivationHandler.ts +1 -1
  33. package/src/infrastructure/services/README.md +95 -370
  34. package/src/infrastructure/services/SubscriptionService.ts +1 -1
  35. package/src/presentation/README.md +123 -408
  36. package/src/presentation/README.md.bak +172 -0
  37. package/src/presentation/components/README.md +151 -179
  38. package/src/presentation/components/README.md.bak +217 -0
  39. package/src/presentation/components/details/CreditRow.md +65 -310
  40. package/src/presentation/components/details/DetailRow.md +63 -255
  41. package/src/presentation/components/details/PremiumDetailsCard.md +65 -238
  42. package/src/presentation/components/details/PremiumStatusBadge.md +64 -239
  43. package/src/presentation/components/details/README.md +97 -447
  44. package/src/presentation/components/feedback/PaywallFeedbackModal.md +63 -287
  45. package/src/presentation/components/feedback/README.md +97 -445
  46. package/src/presentation/components/paywall/PaywallModal.md +66 -416
  47. package/src/presentation/components/paywall/README.md +50 -186
  48. package/src/presentation/components/sections/README.md +97 -466
  49. package/src/presentation/components/sections/SubscriptionSection.md +92 -244
  50. package/src/presentation/hooks/README.md +154 -741
  51. package/src/presentation/hooks/useAuthAwarePurchase.md +58 -325
  52. package/src/presentation/hooks/useAuthGate.md +61 -375
  53. package/src/presentation/hooks/useAuthSubscriptionSync.md +66 -370
  54. package/src/presentation/hooks/useCreditChecker.md +73 -378
  55. package/src/presentation/hooks/useCredits.md +74 -313
  56. package/src/presentation/hooks/useCredits.md.bak +231 -0
  57. package/src/presentation/hooks/useCreditsGate.md +66 -318
  58. package/src/presentation/hooks/useDeductCredit.md +0 -76
  59. package/src/presentation/hooks/useDeductCredit.ts +1 -1
  60. package/src/presentation/hooks/useDevTestCallbacks.md +63 -394
  61. package/src/presentation/hooks/useFeatureGate.md +105 -150
  62. package/src/presentation/hooks/useFeatureGate.md.bak +284 -0
  63. package/src/presentation/hooks/useInitializeCredits.md +64 -430
  64. package/src/presentation/hooks/usePaywall.md +61 -306
  65. package/src/presentation/hooks/usePaywallOperations.md +64 -458
  66. package/src/presentation/hooks/usePaywallVisibility.md +67 -316
  67. package/src/presentation/hooks/usePremium.md +84 -226
  68. package/src/presentation/hooks/usePremiumGate.md +60 -395
  69. package/src/presentation/hooks/usePremiumWithCredits.md +64 -401
  70. package/src/presentation/hooks/useSubscription.md +66 -422
  71. package/src/presentation/hooks/useSubscriptionDetails.md +65 -410
  72. package/src/presentation/hooks/useSubscriptionGate.md +80 -164
  73. package/src/presentation/hooks/useSubscriptionSettingsConfig.md +66 -346
  74. package/src/presentation/hooks/useSubscriptionStatus.md +66 -396
  75. package/src/presentation/hooks/useUserTier.md +63 -328
  76. package/src/presentation/hooks/useUserTierWithRepository.md +64 -424
  77. package/src/presentation/screens/README.md +48 -190
  78. package/src/presentation/types/README.md +0 -16
  79. package/src/presentation/utils/README.md +0 -21
  80. package/src/presentation/utils/subscriptionDateUtils.ts +1 -1
  81. package/src/revenuecat/README.md +99 -518
  82. package/src/revenuecat/application/README.md +35 -150
  83. package/src/revenuecat/application/ports/README.md +34 -162
  84. package/src/revenuecat/domain/README.md +42 -141
  85. package/src/revenuecat/domain/constants/README.md +34 -176
  86. package/src/revenuecat/domain/entities/README.md +34 -374
  87. package/src/revenuecat/domain/errors/README.md +47 -191
  88. package/src/revenuecat/domain/types/README.md +34 -366
  89. package/src/revenuecat/domain/value-objects/README.md +34 -434
  90. package/src/revenuecat/infrastructure/README.md +34 -43
  91. package/src/revenuecat/infrastructure/config/README.md +32 -23
  92. package/src/revenuecat/infrastructure/handlers/README.md +34 -211
  93. package/src/revenuecat/infrastructure/managers/README.md +34 -42
  94. package/src/revenuecat/infrastructure/services/README.md +35 -318
  95. package/src/revenuecat/infrastructure/utils/README.md +34 -375
  96. package/src/revenuecat/presentation/README.md +34 -176
  97. package/src/revenuecat/presentation/hooks/README.md +29 -35
  98. package/src/utils/README.md +38 -525
@@ -1,342 +1,103 @@
1
1
  # useCredits Hook
2
2
 
3
- Hook for accessing and managing credits balance.
3
+ Hook for accessing and managing credits balance with real-time updates.
4
4
 
5
- ## Import
5
+ ## Location
6
6
 
7
- ```typescript
8
- import { useCredits } from '@umituz/react-native-subscription';
9
- ```
7
+ **Import Path**: `@umituz/react-native-subscription`
10
8
 
11
- ## Signature
9
+ **File**: `src/presentation/hooks/useCredits.ts`
12
10
 
13
- ```typescript
14
- function useCredits(): {
15
- credits: number;
16
- balance: number;
17
- transactions: Transaction[];
18
- isLoading: boolean;
19
- error: Error | null;
20
- refetch: () => Promise<void>;
21
- }
22
- ```
11
+ **Type**: Hook
23
12
 
24
- ## Returns
13
+ ## Strategy
25
14
 
26
- | Property | Type | Description |
27
- |----------|------|-------------|
28
- | `credits` | `number` | Current credit balance |
29
- | `balance` | `number` | Balance in currency (USD, etc.) |
30
- | `transactions` | `Transaction[]` | Transaction history |
31
- | `isLoading` | `boolean` | Loading state |
32
- | `error` | `Error \| null` | Error if any |
33
- | `refetch` | `() => Promise<void>` | Manually refetch data |
15
+ ### Data Fetching Flow
34
16
 
35
- ## Basic Usage
17
+ 1. **Initial Load**
18
+ - Fetch credits from repository on mount
19
+ - Cache results in TanStack Query
20
+ - Handle loading/error states
36
21
 
37
- ```typescript
38
- function CreditsDisplay() {
39
- const { credits, isLoading } = useCredits();
22
+ 2. **Real-time Updates**
23
+ - Subscribe to credit changes via repository listener
24
+ - Auto-update on balance changes
25
+ - Invalidate query on external modifications
40
26
 
41
- if (isLoading) return <ActivityIndicator />;
27
+ 3. **Cache Management**
28
+ - Use TanStack Query for caching
29
+ - Background refetch on window focus
30
+ - Manual refetch capability
42
31
 
43
- return (
44
- <View>
45
- <Text>Your Credits: {credits}</Text>
46
- <Text>Balance: ${balance.toFixed(2)}</Text>
47
- </View>
48
- );
49
- }
50
- ```
32
+ ### Integration Points
51
33
 
52
- ## Advanced Usage
34
+ - **Credits Repository**: `src/domains/wallet/infrastructure/repositories/CreditsRepository.ts`
35
+ - **Credits Entity**: `src/domains/wallet/domain/entities/UserCredits.ts`
36
+ - **TanStack Query**: For cache management and background updates
37
+ - **useFocusEffect**: For refresh on screen focus
53
38
 
54
- ### With Refresh Control
39
+ ## Restrictions
55
40
 
56
- ```typescript
57
- function CreditsWithRefresh() {
58
- const { credits, refetch, isLoading } = useCredits();
41
+ ### REQUIRED
59
42
 
60
- const [refreshing, setRefreshing] = useState(false);
43
+ - **User Authentication**: User MUST be authenticated to access credits
44
+ - **Error Handling**: MUST handle error state in UI
45
+ - **Loading State**: MUST show loading indicator while fetching
61
46
 
62
- const handleRefresh = async () => {
63
- setRefreshing(true);
64
- await refetch();
65
- setRefreshing(false);
66
- };
47
+ ### PROHIBITED
67
48
 
68
- return (
69
- <View>
70
- <Text>Credits: {credits}</Text>
49
+ - **NEVER** assume credits are available without checking loading state
50
+ - **NEVER** use this hook for unauthenticated users
51
+ - **DO NOT** mutate credits directly - use `useDeductCredit` instead
52
+ - **DO NOT** call refetch excessively (causes unnecessary network calls)
71
53
 
72
- <Button
73
- onPress={handleRefresh}
74
- disabled={refreshing || isLoading}
75
- title={refreshing ? 'Refreshing...' : 'Refresh'}
76
- />
77
- </View>
78
- );
79
- }
80
- ```
54
+ ### CRITICAL SAFETY
81
55
 
82
- ### With Auto-Refresh
56
+ - **ALWAYS** check `isLoading` before displaying credits
57
+ - **ALWAYS** handle `error` state to prevent crashes
58
+ - **NEVER** use `credits` value for security decisions (validate on backend)
59
+ - **MUST** implement error boundaries when displaying balance
83
60
 
84
- ```typescript
85
- function AutoRefreshCredits() {
86
- const { credits, refetch } = useCredits();
61
+ ## AI Agent Guidelines
87
62
 
88
- // Refresh every 30 seconds
89
- useEffect(() => {
90
- const interval = setInterval(() => {
91
- refetch();
92
- }, 30000);
63
+ ### When Implementing Credit Displays
93
64
 
94
- return () => clearInterval(interval);
95
- }, [refetch]);
65
+ 1. **Always** handle loading state explicitly
66
+ 2. **Always** handle error state gracefully
67
+ 3. **Always** provide manual refresh option
68
+ 4. **Always** format balance safely (handle undefined/null)
69
+ 5. **Never** use credits for security decisions (server-side validation required)
96
70
 
97
- // Refresh when app comes to foreground
98
- useFocusEffect(
99
- useCallback(() => {
100
- refetch();
101
- }, [refetch])
102
- );
71
+ ### Integration Checklist
103
72
 
104
- return <Text>Credits: {credits}</Text>;
105
- }
106
- ```
73
+ - [ ] Import from correct path: `@umituz/react-native-subscription`
74
+ - [ ] Handle loading state in UI
75
+ - [ ] Handle error state in UI
76
+ - [ ] Provide refresh mechanism
77
+ - [ ] Format balance safely with default values
78
+ - [ ] Implement error boundaries
79
+ - [ ] Test with no credits (zero balance)
80
+ - [ ] Test with loading states
81
+ - [ ] Test with error states
82
+ - [ ] Test refresh functionality
107
83
 
108
- ### With Credit History
84
+ ### Common Patterns to Implement
109
85
 
110
- ```typescript
111
- function CreditsWithHistory() {
112
- const { credits, transactions, isLoading } = useCredits();
86
+ 1. **Balance Card**: Display credits with currency conversion
87
+ 2. **Transaction List**: Show recent credit activity
88
+ 3. **Low Credits Warning**: Alert when balance is low
89
+ 4. **Refresh Control**: Pull-to-refresh or button
90
+ 5. **Real-time Updates**: Use focus effect for auto-refresh
91
+ 6. **Purchase Prompt**: Link to credit packages when low
92
+ 7. **Skeletal Loading**: Show skeleton during initial load
93
+ 8. **Error Recovery**: Retry mechanism for failed fetches
113
94
 
114
- return (
115
- <View>
116
- <BalanceDisplay credits={credits} />
95
+ ## Related Documentation
117
96
 
118
- <Text style={styles.historyTitle}>Recent Transactions</Text>
119
-
120
- {isLoading ? (
121
- <ActivityIndicator />
122
- ) : (
123
- <FlatList
124
- data={transactions}
125
- keyExtractor={(item) => item.id}
126
- renderItem={({ item }) => (
127
- <TransactionItem
128
- amount={item.amount}
129
- reason={item.reason}
130
- timestamp={item.timestamp}
131
- />
132
- )}
133
- />
134
- )}
135
- </View>
136
- );
137
- }
138
- ```
139
-
140
- ### With Balance Conversion
141
-
142
- ```typescript
143
- function CreditsWithConversion() {
144
- const { credits, balance } = useCredits();
145
-
146
- const creditValue = 0.01; // 1 credit = $0.01
147
-
148
- return (
149
- <View>
150
- <Text style={styles.credits}>{credits} Credits</Text>
151
- <Text style={styles.balance}>
152
- Worth approximately ${(balance || 0).toFixed(2)}
153
- </Text>
154
- <Text style={styles.info}>
155
- (1 credit = ${(creditValue).toFixed(2)})
156
- </Text>
157
- </View>
158
- );
159
- }
160
- ```
161
-
162
- ## Examples
163
-
164
- ### Credits Balance Card
165
-
166
- ```typescript
167
- function CreditsBalanceCard() {
168
- const { credits, balance, isLoading } = useCredits();
169
-
170
- if (isLoading) {
171
- return <SkeletonLoader />;
172
- }
173
-
174
- return (
175
- <Card style={styles.card}>
176
- <Card.Header>
177
- <Card.Title>Your Balance</Card.Title>
178
- </Card.Header>
179
-
180
- <Card.Body>
181
- <View style={styles.balanceContainer}>
182
- <Text style={styles.credits}>{credits}</Text>
183
- <Text style={styles.label}>Credits</Text>
184
- </View>
185
-
186
- <View style={styles.balanceContainer}>
187
- <Text style={styles.balance}>
188
- ${(balance || 0).toFixed(2)}
189
- </Text>
190
- <Text style={styles.label}>Value</Text>
191
- </View>
192
- </Card.Body>
193
-
194
- <Card.Footer>
195
- <Button
196
- onPress={() => navigation.navigate('CreditPackages')}
197
- title="Get More Credits"
198
- size="sm"
199
- />
200
- </Card.Footer>
201
- </Card>
202
- );
203
- }
204
- ```
205
-
206
- ### Credits Indicator
207
-
208
- ```typescript
209
- function CreditsIndicator() {
210
- const { credits } = useCredits();
211
-
212
- return (
213
- <TouchableOpacity
214
- onPress={() => navigation.navigate('Wallet')}
215
- style={styles.indicator}
216
- >
217
- <Icon name="coins" size={20} color="#FFD700" />
218
- <Text style={styles.credits}>{credits}</Text>
219
- </TouchableOpacity>
220
- );
221
- }
222
- ```
223
-
224
- ### Low Credits Warning
225
-
226
- ```typescript
227
- function LowCreditsWarning() {
228
- const { credits } = useCredits();
229
- const lowCreditThreshold = 10;
230
-
231
- useEffect(() => {
232
- if (credits <= lowCreditThreshold && credits > 0) {
233
- notifications.show({
234
- title: 'Low Credits',
235
- body: `You have ${credits} credits remaining. Purchase more to continue using features.`,
236
- });
237
- }
238
- }, [credits]);
239
-
240
- if (credits <= lowCreditThreshold) {
241
- return (
242
- <Alert
243
- severity={credits === 0 ? 'error' : 'warning'}
244
- message={
245
- credits === 0
246
- ? 'No credits remaining. Purchase more to continue.'
247
- : `Low credits: ${credits} remaining`
248
- }
249
- action={
250
- <Button onPress={() => navigation.navigate('CreditPackages')}>
251
- Get More
252
- </Button>
253
- }
254
- />
255
- );
256
- }
257
-
258
- return null;
259
- }
260
- ```
261
-
262
- ### Credits Usage Chart
263
-
264
- ```typescript
265
- function CreditsUsageChart() {
266
- const { transactions } = useCredits();
267
-
268
- // Group transactions by date
269
- const usageByDate = useMemo(() => {
270
- const grouped = transactions.reduce((acc, tx) => {
271
- const date = new Date(tx.timestamp).toDateString();
272
- acc[date] = (acc[date] || 0) + Math.abs(tx.amount);
273
- return acc;
274
- }, {});
275
-
276
- return Object.entries(grouped)
277
- .map(([date, amount]) => ({ date, amount }))
278
- .sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime())
279
- .slice(-7); // Last 7 days
280
- }, [transactions]);
281
-
282
- return (
283
- <View>
284
- <Text>Credits Usage (Last 7 Days)</Text>
285
-
286
- <LineChart
287
- data={usageByDate}
288
- xKey="date"
289
- yKey="amount"
290
- height={200}
291
- />
292
- </View>
293
- );
294
- }
295
- ```
296
-
297
- ### Real-Time Balance Updates
298
-
299
- ```typescript
300
- function RealtimeCreditsBalance() {
301
- const { credits, refetch } = useCredits();
302
-
303
- // Listen to credit updates
304
- useEffect(() => {
305
- const unsubscribe = creditsListener.on((newBalance) => {
306
- console.log('Credits updated:', newBalance);
307
- refetch();
308
- });
309
-
310
- return () => unsubscribe?.();
311
- }, []);
312
-
313
- return (
314
- <View>
315
- <Text>Credits: {credits}</Text>
316
- </View>
317
- );
318
- }
319
- ```
320
-
321
- ## Best Practices
322
-
323
- 1. **Handle loading** - Show skeleton or spinner
324
- 2. **Display balance** - Show both credits and value
325
- 3. **Provide purchase option** - Link to credit packages
326
- 4. **Show warnings** - Alert when credits are low
327
- 5. **Track usage** - Display transaction history
328
- 6. **Auto-refresh** - Keep balance up to date
329
- 7. **Handle errors** - Show user-friendly messages
330
-
331
- ## Related Hooks
332
-
333
- - **useCreditsGate** - For gating features with credits
334
- - **useDeductCredit** - For deducting credits
335
- - **useTransactionHistory** - For transaction list
336
- - **useWallet** - Wallet domain hook
337
-
338
- ## See Also
339
-
340
- - [CreditsGate](./useCreditsGate.md)
341
- - [DeductCredit](./useDeductCredit.md)
342
- - [Wallet Domain](../../../domains/wallet/README.md)
97
+ - **useDeductCredit**: Deduct credits from balance
98
+ - **useCreditChecker**: Check credit availability before operations
99
+ - **useInitializeCredits**: Initialize credits after purchase
100
+ - **useCreditsGate**: Gate features behind credit requirements
101
+ - **useFeatureGate**: Unified feature gating with credits
102
+ - **Credits Repository**: `src/domains/wallet/infrastructure/repositories/README.md`
103
+ - **Wallet Domain**: `src/domains/wallet/README.md`
@@ -0,0 +1,231 @@
1
+ # useCredits Hook
2
+
3
+ Hook for accessing and managing credits balance with real-time updates.
4
+
5
+ ## Location
6
+
7
+ **Import Path**: `@umituz/react-native-subscription`
8
+
9
+ **File**: `src/presentation/hooks/useCredits.ts`
10
+
11
+ **Type**: Hook
12
+
13
+ ## Strategy
14
+
15
+ ### Data Fetching Flow
16
+
17
+ 1. **Initial Load**
18
+ - Fetch credits from repository on mount
19
+ - Cache results in TanStack Query
20
+ - Handle loading/error states
21
+
22
+ 2. **Real-time Updates**
23
+ - Subscribe to credit changes via repository listener
24
+ - Auto-update on balance changes
25
+ - Invalidate query on external modifications
26
+
27
+ 3. **Cache Management**
28
+ - Use TanStack Query for caching
29
+ - Background refetch on window focus
30
+ - Manual refetch capability
31
+
32
+ ### Integration Points
33
+
34
+ - **Credits Repository**: `src/domains/wallet/infrastructure/repositories/CreditsRepository.ts`
35
+ - **Credits Entity**: `src/domains/wallet/domain/entities/UserCredits.ts`
36
+ - **TanStack Query**: For cache management and background updates
37
+ - **useFocusEffect**: For refresh on screen focus
38
+
39
+ ## Restrictions
40
+
41
+ ### REQUIRED
42
+
43
+ - **User Authentication**: User MUST be authenticated to access credits
44
+ - **Error Handling**: MUST handle error state in UI
45
+ - **Loading State**: MUST show loading indicator while fetching
46
+
47
+ ### PROHIBITED
48
+
49
+ - **NEVER** assume credits are available without checking loading state
50
+ - **NEVER** use this hook for unauthenticated users
51
+ - **DO NOT** mutate credits directly - use `useDeductCredit` instead
52
+ - **DO NOT** call refetch excessively (causes unnecessary network calls)
53
+
54
+ ### CRITICAL SAFETY
55
+
56
+ - **ALWAYS** check `isLoading` before displaying credits
57
+ - **ALWAYS** handle `error` state to prevent crashes
58
+ - **NEVER** use `credits` value for security decisions (validate on backend)
59
+ - **MUST** implement error boundaries when displaying balance
60
+
61
+ ## Rules
62
+
63
+ ### Basic Usage
64
+
65
+ ```typescript
66
+ // CORRECT - Handle all states
67
+ function CreditsDisplay() {
68
+ const { credits, isLoading, error } = useCredits();
69
+
70
+ if (isLoading) return <ActivityIndicator />;
71
+ if (error) return <ErrorDisplay error={error} />;
72
+
73
+ return <Text>Credits: {credits}</Text>;
74
+ }
75
+
76
+ // INCORRECT - No loading check
77
+ function CreditsDisplay() {
78
+ const { credits } = useCredits();
79
+ return <Text>Credits: {credits}</Text>; // May show undefined
80
+ }
81
+
82
+ // INCORRECT - No error handling
83
+ function CreditsDisplay() {
84
+ const { credits, isLoading, error } = useCredits();
85
+
86
+ if (isLoading) return <ActivityIndicator />;
87
+ return <Text>Credits: {credits}</Text>; // Crashes if error
88
+ }
89
+ ```
90
+
91
+ ### Manual Refresh
92
+
93
+ ```typescript
94
+ // CORRECT - Manual refetch with loading state
95
+ function CreditsWithRefresh() {
96
+ const { credits, refetch, isLoading } = useCredits();
97
+
98
+ const handleRefresh = async () => {
99
+ await refetch();
100
+ };
101
+
102
+ return (
103
+ <Button onPress={handleRefresh} disabled={isLoading}>
104
+ Refresh
105
+ </Button>
106
+ );
107
+ }
108
+
109
+ // INCORRECT - Ignore loading state during refresh
110
+ const handleRefresh = () => {
111
+ refetch(); // No loading indication
112
+ };
113
+ ```
114
+
115
+ ### Transaction History
116
+
117
+ ```typescript
118
+ // CORRECT - Display transactions with safety checks
119
+ function CreditsWithHistory() {
120
+ const { credits, transactions, isLoading } = useCredits();
121
+
122
+ if (isLoading) return <ActivityIndicator />;
123
+
124
+ return (
125
+ <View>
126
+ <Text>Credits: {credits}</Text>
127
+ <FlatList
128
+ data={transactions || []}
129
+ keyExtractor={(item) => item.id}
130
+ renderItem={({ item }) => <TransactionItem {...item} />}
131
+ />
132
+ </View>
133
+ );
134
+ }
135
+
136
+ // INCORRECT - Assume transactions exist
137
+ <FlatList
138
+ data={transactions} // Crashes if undefined
139
+ keyExtractor={(item) => item.id}
140
+ renderItem={({ item }) => <TransactionItem {...item} />}
141
+ />
142
+ ```
143
+
144
+ ### Auto-Refresh Patterns
145
+
146
+ ```typescript
147
+ // CORRECT - Refresh on focus with effect cleanup
148
+ function AutoRefreshCredits() {
149
+ const { credits, refetch } = useCredits();
150
+
151
+ useFocusEffect(
152
+ useCallback(() => {
153
+ refetch();
154
+ }, [refetch])
155
+ );
156
+
157
+ return <Text>Credits: {credits}</Text>;
158
+ }
159
+
160
+ // INCORRECT - Missing dependency
161
+ useFocusEffect(
162
+ useCallback(() => {
163
+ refetch();
164
+ }, []) // Missing refetch dependency
165
+ );
166
+ ```
167
+
168
+ ### Balance Display
169
+
170
+ ```typescript
171
+ // CORRECT - Safe balance display with formatting
172
+ function BalanceDisplay() {
173
+ const { credits, balance, isLoading } = useCredits();
174
+
175
+ if (isLoading) return <Skeleton />;
176
+
177
+ return (
178
+ <View>
179
+ <Text>{credits} Credits</Text>
180
+ <Text>Value: ${(balance || 0).toFixed(2)}</Text>
181
+ </View>
182
+ );
183
+ }
184
+
185
+ // INCORRECT - Unsafe balance access
186
+ <Text>Value: ${balance.toFixed(2)}</Text> // Crashes if undefined
187
+ ```
188
+
189
+ ## AI Agent Guidelines
190
+
191
+ ### When Implementing Credit Displays
192
+
193
+ 1. **Always** handle loading state explicitly
194
+ 2. **Always** handle error state gracefully
195
+ 3. **Always** provide manual refresh option
196
+ 4. **Always** format balance safely (handle undefined/null)
197
+ 5. **Never** use credits for security decisions (server-side validation required)
198
+
199
+ ### Integration Checklist
200
+
201
+ - [ ] Import from correct path: `@umituz/react-native-subscription`
202
+ - [ ] Handle loading state in UI
203
+ - [ ] Handle error state in UI
204
+ - [ ] Provide refresh mechanism
205
+ - [ ] Format balance safely with default values
206
+ - [ ] Implement error boundaries
207
+ - [ ] Test with no credits (zero balance)
208
+ - [ ] Test with loading states
209
+ - [ ] Test with error states
210
+ - [ ] Test refresh functionality
211
+
212
+ ### Common Patterns to Implement
213
+
214
+ 1. **Balance Card**: Display credits with currency conversion
215
+ 2. **Transaction List**: Show recent credit activity
216
+ 3. **Low Credits Warning**: Alert when balance is low
217
+ 4. **Refresh Control**: Pull-to-refresh or button
218
+ 5. **Real-time Updates**: Use focus effect for auto-refresh
219
+ 6. **Purchase Prompt**: Link to credit packages when low
220
+ 7. **Skeletal Loading**: Show skeleton during initial load
221
+ 8. **Error Recovery**: Retry mechanism for failed fetches
222
+
223
+ ## Related Documentation
224
+
225
+ - **useDeductCredit**: Deduct credits from balance
226
+ - **useCreditChecker**: Check credit availability before operations
227
+ - **useInitializeCredits**: Initialize credits after purchase
228
+ - **useCreditsGate**: Gate features behind credit requirements
229
+ - **useFeatureGate**: Unified feature gating with credits
230
+ - **Credits Repository**: `src/domains/wallet/infrastructure/repositories/README.md`
231
+ - **Wallet Domain**: `src/domains/wallet/README.md`