@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.
- package/README.md +211 -394
- package/package.json +3 -3
- package/src/application/README.md +46 -225
- package/src/application/ports/README.md +42 -97
- package/src/domain/README.md +36 -384
- package/src/domain/constants/README.md +0 -56
- package/src/domain/entities/README.md +43 -169
- package/src/domain/entities/SubscriptionStatus.ts +1 -1
- package/src/domain/errors/README.md +33 -287
- package/src/domain/value-objects/README.md +43 -179
- package/src/domains/README.md +50 -238
- package/src/domains/README.md.bak +274 -0
- package/src/domains/config/README.md +93 -383
- package/src/domains/config/domain/README.md +23 -376
- package/src/domains/config/domain/entities/README.md +34 -343
- package/src/domains/paywall/README.md +99 -369
- package/src/domains/paywall/components/README.md +34 -178
- package/src/domains/paywall/entities/README.md +34 -193
- package/src/domains/paywall/hooks/README.md +34 -122
- package/src/domains/wallet/README.md +34 -275
- package/src/domains/wallet/README.md.bak +209 -0
- package/src/domains/wallet/domain/README.md +34 -101
- package/src/domains/wallet/domain/entities/README.md +34 -115
- package/src/domains/wallet/domain/errors/README.md +34 -151
- package/src/domains/wallet/infrastructure/README.md +34 -89
- package/src/domains/wallet/presentation/components/README.md +34 -224
- package/src/domains/wallet/presentation/components/TransactionItem.tsx +1 -1
- package/src/domains/wallet/presentation/hooks/README.md +34 -248
- package/src/infrastructure/README.md +37 -496
- package/src/infrastructure/mappers/README.md +0 -13
- package/src/infrastructure/repositories/README.md +74 -360
- package/src/infrastructure/services/ActivationHandler.ts +1 -1
- package/src/infrastructure/services/README.md +95 -370
- package/src/infrastructure/services/SubscriptionService.ts +1 -1
- package/src/presentation/README.md +123 -408
- package/src/presentation/README.md.bak +172 -0
- package/src/presentation/components/README.md +151 -179
- package/src/presentation/components/README.md.bak +217 -0
- package/src/presentation/components/details/CreditRow.md +65 -310
- package/src/presentation/components/details/DetailRow.md +63 -255
- package/src/presentation/components/details/PremiumDetailsCard.md +65 -238
- package/src/presentation/components/details/PremiumStatusBadge.md +64 -239
- package/src/presentation/components/details/README.md +97 -447
- package/src/presentation/components/feedback/PaywallFeedbackModal.md +63 -287
- package/src/presentation/components/feedback/README.md +97 -445
- package/src/presentation/components/paywall/PaywallModal.md +66 -416
- package/src/presentation/components/paywall/README.md +50 -186
- package/src/presentation/components/sections/README.md +97 -466
- package/src/presentation/components/sections/SubscriptionSection.md +92 -244
- package/src/presentation/hooks/README.md +154 -741
- package/src/presentation/hooks/useAuthAwarePurchase.md +58 -325
- package/src/presentation/hooks/useAuthGate.md +61 -375
- package/src/presentation/hooks/useAuthSubscriptionSync.md +66 -370
- package/src/presentation/hooks/useCreditChecker.md +73 -378
- package/src/presentation/hooks/useCredits.md +74 -313
- package/src/presentation/hooks/useCredits.md.bak +231 -0
- package/src/presentation/hooks/useCreditsGate.md +66 -318
- package/src/presentation/hooks/useDeductCredit.md +0 -76
- package/src/presentation/hooks/useDeductCredit.ts +1 -1
- package/src/presentation/hooks/useDevTestCallbacks.md +63 -394
- package/src/presentation/hooks/useFeatureGate.md +105 -150
- package/src/presentation/hooks/useFeatureGate.md.bak +284 -0
- package/src/presentation/hooks/useInitializeCredits.md +64 -430
- package/src/presentation/hooks/usePaywall.md +61 -306
- package/src/presentation/hooks/usePaywallOperations.md +64 -458
- package/src/presentation/hooks/usePaywallVisibility.md +67 -316
- package/src/presentation/hooks/usePremium.md +84 -226
- package/src/presentation/hooks/usePremiumGate.md +60 -395
- package/src/presentation/hooks/usePremiumWithCredits.md +64 -401
- package/src/presentation/hooks/useSubscription.md +66 -422
- package/src/presentation/hooks/useSubscriptionDetails.md +65 -410
- package/src/presentation/hooks/useSubscriptionGate.md +80 -164
- package/src/presentation/hooks/useSubscriptionSettingsConfig.md +66 -346
- package/src/presentation/hooks/useSubscriptionStatus.md +66 -396
- package/src/presentation/hooks/useUserTier.md +63 -328
- package/src/presentation/hooks/useUserTierWithRepository.md +64 -424
- package/src/presentation/screens/README.md +48 -190
- package/src/presentation/types/README.md +0 -16
- package/src/presentation/utils/README.md +0 -21
- package/src/presentation/utils/subscriptionDateUtils.ts +1 -1
- package/src/revenuecat/README.md +99 -518
- package/src/revenuecat/application/README.md +35 -150
- package/src/revenuecat/application/ports/README.md +34 -162
- package/src/revenuecat/domain/README.md +42 -141
- package/src/revenuecat/domain/constants/README.md +34 -176
- package/src/revenuecat/domain/entities/README.md +34 -374
- package/src/revenuecat/domain/errors/README.md +47 -191
- package/src/revenuecat/domain/types/README.md +34 -366
- package/src/revenuecat/domain/value-objects/README.md +34 -434
- package/src/revenuecat/infrastructure/README.md +34 -43
- package/src/revenuecat/infrastructure/config/README.md +32 -23
- package/src/revenuecat/infrastructure/handlers/README.md +34 -211
- package/src/revenuecat/infrastructure/managers/README.md +34 -42
- package/src/revenuecat/infrastructure/services/README.md +35 -318
- package/src/revenuecat/infrastructure/utils/README.md +34 -375
- package/src/revenuecat/presentation/README.md +34 -176
- package/src/revenuecat/presentation/hooks/README.md +29 -35
- package/src/utils/README.md +38 -525
|
@@ -1,231 +1,41 @@
|
|
|
1
1
|
# Wallet Presentation Components
|
|
2
2
|
|
|
3
|
+
## Location
|
|
3
4
|
UI components for wallet and credit display.
|
|
4
5
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
interface TransactionItemProps {
|
|
39
|
-
transaction: Transaction;
|
|
40
|
-
format?: 'full' | 'compact';
|
|
41
|
-
}
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
**Usage:**
|
|
45
|
-
```typescript
|
|
46
|
-
<TransactionItem
|
|
47
|
-
transaction={{
|
|
48
|
-
id: 'tx_123',
|
|
49
|
-
amount: -5,
|
|
50
|
-
reason: 'AI Generation',
|
|
51
|
-
timestamp: new Date(),
|
|
52
|
-
type: 'deduction',
|
|
53
|
-
}}
|
|
54
|
-
format="full"
|
|
55
|
-
/>
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### CreditProgressBar
|
|
59
|
-
Progress bar showing credit usage.
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
interface CreditProgressBarProps {
|
|
63
|
-
current: number;
|
|
64
|
-
total: number;
|
|
65
|
-
showLabel?: boolean;
|
|
66
|
-
showPercentage?: boolean;
|
|
67
|
-
height?: number;
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
**Usage:**
|
|
72
|
-
```typescript
|
|
73
|
-
<CreditProgressBar
|
|
74
|
-
current={50}
|
|
75
|
-
total={100}
|
|
76
|
-
showLabel={true}
|
|
77
|
-
showPercentage={true}
|
|
78
|
-
height={8}
|
|
79
|
-
/>
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### CreditPackageCard
|
|
83
|
-
Display card for purchasable credit packages.
|
|
84
|
-
|
|
85
|
-
```typescript
|
|
86
|
-
interface CreditPackageCardProps {
|
|
87
|
-
package: {
|
|
88
|
-
id: string;
|
|
89
|
-
amount: number;
|
|
90
|
-
price: number;
|
|
91
|
-
bonus?: number;
|
|
92
|
-
currency: string;
|
|
93
|
-
};
|
|
94
|
-
onPress: () => void;
|
|
95
|
-
highlight?: boolean;
|
|
96
|
-
}
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
**Usage:**
|
|
100
|
-
```typescript
|
|
101
|
-
<CreditPackageCard
|
|
102
|
-
package={{
|
|
103
|
-
id: 'premium_credits',
|
|
104
|
-
amount: 100,
|
|
105
|
-
price: 9.99,
|
|
106
|
-
bonus: 10,
|
|
107
|
-
currency: 'USD',
|
|
108
|
-
}}
|
|
109
|
-
onPress={() => purchaseCredits('premium_credits')}
|
|
110
|
-
highlight={true}
|
|
111
|
-
/>
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
## Usage Patterns
|
|
115
|
-
|
|
116
|
-
### Complete Credit Dashboard
|
|
117
|
-
|
|
118
|
-
```typescript
|
|
119
|
-
function CreditDashboard() {
|
|
120
|
-
const { credits, transactions, isLoading, refetch } = useCredits();
|
|
121
|
-
|
|
122
|
-
return (
|
|
123
|
-
<ScrollView>
|
|
124
|
-
<CreditBalanceCard
|
|
125
|
-
credits={credits}
|
|
126
|
-
balance={calculateBalance(credits)}
|
|
127
|
-
onRefresh={refetch}
|
|
128
|
-
/>
|
|
129
|
-
|
|
130
|
-
<View style={styles.section}>
|
|
131
|
-
<Text style={styles.title}>Recent Transactions</Text>
|
|
132
|
-
{transactions.slice(0, 10).map(tx => (
|
|
133
|
-
<TransactionItem key={tx.id} transaction={tx} />
|
|
134
|
-
))}
|
|
135
|
-
</View>
|
|
136
|
-
|
|
137
|
-
<Button onPress={() => navigation.navigate('CreditPackages')}>
|
|
138
|
-
Get More Credits
|
|
139
|
-
</Button>
|
|
140
|
-
</ScrollView>
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
### Credit Warning Banner
|
|
146
|
-
|
|
147
|
-
```typescript
|
|
148
|
-
function LowCreditWarning() {
|
|
149
|
-
const { credits } = useCredits();
|
|
150
|
-
const warningThreshold = 20;
|
|
151
|
-
|
|
152
|
-
if (credits > warningThreshold) return null;
|
|
153
|
-
|
|
154
|
-
return (
|
|
155
|
-
<Banner type={credits === 0 ? 'error' : 'warning'}>
|
|
156
|
-
<Text>
|
|
157
|
-
{credits === 0
|
|
158
|
-
? 'No credits remaining'
|
|
159
|
-
: `Only ${credits} credits left`
|
|
160
|
-
}
|
|
161
|
-
</Text>
|
|
162
|
-
<Button onPress={() => navigation.navigate('CreditPackages')}>
|
|
163
|
-
Get More
|
|
164
|
-
</Button>
|
|
165
|
-
</Banner>
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
### Credit History List
|
|
171
|
-
|
|
172
|
-
```typescript
|
|
173
|
-
function TransactionHistory() {
|
|
174
|
-
const { transactions } = useCredits();
|
|
175
|
-
|
|
176
|
-
return (
|
|
177
|
-
<FlatList
|
|
178
|
-
data={transactions}
|
|
179
|
-
keyExtractor={(item) => item.id}
|
|
180
|
-
renderItem={({ item }) => (
|
|
181
|
-
<TransactionItem transaction={item} format="compact" />
|
|
182
|
-
)}
|
|
183
|
-
ListHeaderComponent={() => (
|
|
184
|
-
<Text style={styles.title}>Transaction History</Text>
|
|
185
|
-
)}
|
|
186
|
-
ListEmptyComponent={() => (
|
|
187
|
-
<EmptyState
|
|
188
|
-
icon="receipt"
|
|
189
|
-
title="No transactions yet"
|
|
190
|
-
message="Your credit transaction history will appear here"
|
|
191
|
-
/>
|
|
192
|
-
)}
|
|
193
|
-
/>
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
## Styling
|
|
199
|
-
|
|
200
|
-
Components use design system:
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
import { useAppDesignTokens } from '@umituz/react-native-design-system';
|
|
204
|
-
|
|
205
|
-
const tokens = useAppDesignTokens();
|
|
206
|
-
|
|
207
|
-
const styles = StyleSheet.create({
|
|
208
|
-
card: {
|
|
209
|
-
backgroundColor: tokens.colors.surface,
|
|
210
|
-
borderRadius: tokens.radius.lg,
|
|
211
|
-
padding: tokens.spacing.lg,
|
|
212
|
-
marginBottom: tokens.spacing.md,
|
|
213
|
-
},
|
|
214
|
-
});
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
## Best Practices
|
|
218
|
-
|
|
219
|
-
1. **Visual Hierarchy**: Emphasize important information
|
|
220
|
-
2. **Color Coding**: Use colors to indicate status (low/warning/good)
|
|
221
|
-
3. **Loading States**: Show skeletons while loading
|
|
222
|
-
4. **Empty States**: Provide helpful empty state messages
|
|
223
|
-
5. **Refresh Capability**: Allow manual refresh
|
|
224
|
-
6. **Transactional History**: Show clear transaction history
|
|
225
|
-
7. **Purchase Links**: Easy access to purchase more credits
|
|
226
|
-
|
|
227
|
-
## Related
|
|
228
|
-
|
|
6
|
+
## Strategy
|
|
7
|
+
This directory contains React Native components for displaying credits, transactions, and wallet information with clear visual hierarchy and status indicators.
|
|
8
|
+
|
|
9
|
+
## Restrictions
|
|
10
|
+
|
|
11
|
+
### REQUIRED
|
|
12
|
+
- Must show loading states appropriately
|
|
13
|
+
- Must provide empty state messages
|
|
14
|
+
- Must allow manual refresh capability
|
|
15
|
+
- Must display transaction history clearly
|
|
16
|
+
|
|
17
|
+
### PROHIBITED
|
|
18
|
+
- DO NOT hide credit balance from users
|
|
19
|
+
- DO NOT show technical errors directly
|
|
20
|
+
- DO NOT skip loading indicators
|
|
21
|
+
- DO NOT obscure transaction details
|
|
22
|
+
|
|
23
|
+
### CRITICAL SAFETY
|
|
24
|
+
- Credit balance MUST always be visible
|
|
25
|
+
- Status indicators MUST be color-coded appropriately
|
|
26
|
+
- Transaction history MUST be complete and accurate
|
|
27
|
+
- Purchase links MUST be easily accessible
|
|
28
|
+
|
|
29
|
+
## AI Agent Guidelines
|
|
30
|
+
1. Emphasize important information with visual hierarchy
|
|
31
|
+
2. Use color coding to indicate status (low/warning/good)
|
|
32
|
+
3. Show skeleton screens while loading data
|
|
33
|
+
4. Provide helpful empty state messages
|
|
34
|
+
5. Allow users to manually refresh credit data
|
|
35
|
+
6. Display complete transaction history
|
|
36
|
+
7. Make credit purchases easily accessible
|
|
37
|
+
|
|
38
|
+
## Related Documentation
|
|
229
39
|
- [Credit Row](../../../presentation/components/details/CreditRow.md)
|
|
230
40
|
- [Credits Hook](../hooks/README.md)
|
|
231
41
|
- [Wallet Domain](../../domain/README.md)
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
AtomicText,
|
|
13
13
|
AtomicIcon,
|
|
14
14
|
} from "@umituz/react-native-design-system";
|
|
15
|
-
import { timezoneService } from "@umituz/react-native-
|
|
15
|
+
import { timezoneService } from "@umituz/react-native-design-system";
|
|
16
16
|
import type { CreditLog, TransactionReason } from "../../domain/types/transaction.types";
|
|
17
17
|
|
|
18
18
|
export interface TransactionItemTranslations {
|
|
@@ -1,255 +1,41 @@
|
|
|
1
1
|
# Wallet Presentation Hooks
|
|
2
2
|
|
|
3
|
+
## Location
|
|
3
4
|
React hooks for wallet and credit functionality.
|
|
4
5
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
</View>
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### useDeductCredit
|
|
44
|
-
Deduct credits with optimistic updates.
|
|
45
|
-
|
|
46
|
-
```typescript
|
|
47
|
-
function useDeductCredit(params: {
|
|
48
|
-
userId: string | undefined;
|
|
49
|
-
onCreditsExhausted?: () => void;
|
|
50
|
-
}): {
|
|
51
|
-
deductCredit: (cost?: number) => Promise<boolean>;
|
|
52
|
-
deductCredits: (cost: number) => Promise<boolean>;
|
|
53
|
-
isDeducting: boolean;
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
**Usage:**
|
|
58
|
-
```typescript
|
|
59
|
-
function AIGeneration() {
|
|
60
|
-
const { deductCredit } = useDeductCredit({
|
|
61
|
-
userId: user?.uid,
|
|
62
|
-
onCreditsExhausted: () => showPaywall(),
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
const handleGenerate = async () => {
|
|
66
|
-
const success = await deductCredit(5);
|
|
67
|
-
if (success) {
|
|
68
|
-
await callAIGenerationAPI();
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### useInitializeCredits
|
|
75
|
-
Initialize credits after purchase.
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
function useInitializeCredits(params: {
|
|
79
|
-
userId: string | undefined;
|
|
80
|
-
}): {
|
|
81
|
-
initializeCredits: (options?: {
|
|
82
|
-
purchaseId?: string;
|
|
83
|
-
productId?: string;
|
|
84
|
-
}) => Promise<boolean>;
|
|
85
|
-
isInitializing: boolean;
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
**Usage:**
|
|
90
|
-
```typescript
|
|
91
|
-
function PurchaseCompletion() {
|
|
92
|
-
const { initializeCredits } = useInitializeCredits({
|
|
93
|
-
userId: user?.uid,
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
const handlePurchaseComplete = async (transaction: Purchase) => {
|
|
97
|
-
const success = await initializeCredits({
|
|
98
|
-
purchaseId: transaction.transactionId,
|
|
99
|
-
productId: transaction.productId,
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
if (success) {
|
|
103
|
-
Alert.alert('Success', 'Credits added!');
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### useCreditChecker
|
|
110
|
-
Check credit availability before operations.
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
function useCreditChecker(params?: {
|
|
114
|
-
onCreditDeducted?: (userId: string, cost: number) => void;
|
|
115
|
-
}): {
|
|
116
|
-
checkCreditsAvailable: (
|
|
117
|
-
userId: string | undefined,
|
|
118
|
-
cost?: number
|
|
119
|
-
) => Promise<CreditCheckResult>;
|
|
120
|
-
deductCreditsAfterSuccess: (
|
|
121
|
-
userId: string | undefined,
|
|
122
|
-
cost?: number
|
|
123
|
-
) => Promise<void>;
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
**Usage:**
|
|
128
|
-
```typescript
|
|
129
|
-
function PreCheckFeature() {
|
|
130
|
-
const { checkCreditsAvailable } = useCreditChecker();
|
|
131
|
-
|
|
132
|
-
const handleCheck = async () => {
|
|
133
|
-
const result = await checkCreditsAvailable(user?.uid, 10);
|
|
134
|
-
|
|
135
|
-
if (!result.canProceed) {
|
|
136
|
-
Alert.alert(
|
|
137
|
-
'Insufficient Credits',
|
|
138
|
-
`You need ${result.required} credits but have ${result.currentBalance}`
|
|
139
|
-
);
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
await executeFeature();
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
## Usage Patterns
|
|
149
|
-
|
|
150
|
-
### Two-Step Credit Process
|
|
151
|
-
|
|
152
|
-
```typescript
|
|
153
|
-
function TwoStepCreditProcess() {
|
|
154
|
-
const { checkCreditsAvailable } = useCreditChecker();
|
|
155
|
-
const { deductCreditsAfterSuccess } = useCreditChecker();
|
|
156
|
-
|
|
157
|
-
const handleOperation = async () => {
|
|
158
|
-
// Step 1: Check credits
|
|
159
|
-
const check = await checkCreditsAvailable(user?.uid, 10);
|
|
160
|
-
|
|
161
|
-
if (!check.canProceed) {
|
|
162
|
-
showPaywall({ required: 10 });
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
try {
|
|
167
|
-
// Step 2: Perform operation
|
|
168
|
-
await performOperation();
|
|
169
|
-
|
|
170
|
-
// Step 3: Deduct credits after success
|
|
171
|
-
await deductCreditsAfterSuccess(user?.uid, 10);
|
|
172
|
-
|
|
173
|
-
Alert.alert('Success', 'Operation completed');
|
|
174
|
-
} catch (error) {
|
|
175
|
-
Alert.alert('Error', 'Operation failed');
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
### With Loading and Error States
|
|
182
|
-
|
|
183
|
-
```typescript
|
|
184
|
-
function CreditOperation() {
|
|
185
|
-
const { credits, isLoading, error } = useCredits({ userId: user?.uid });
|
|
186
|
-
const { deductCredit } = useDeductCredit({
|
|
187
|
-
userId: user?.uid,
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
const handleDeduct = async () => {
|
|
191
|
-
if (isLoading) return;
|
|
192
|
-
|
|
193
|
-
const success = await deductCredit(5);
|
|
194
|
-
|
|
195
|
-
if (success) {
|
|
196
|
-
await executeFeature();
|
|
197
|
-
} else {
|
|
198
|
-
Alert.alert('Failed', 'Could not deduct credits');
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
return (
|
|
203
|
-
<View>
|
|
204
|
-
{error && <ErrorBanner message={error.message} />}
|
|
205
|
-
{isLoading ? (
|
|
206
|
-
<LoadingSpinner />
|
|
207
|
-
) : (
|
|
208
|
-
<>
|
|
209
|
-
<Text>Credits: {credits}</Text>
|
|
210
|
-
<Button onPress={handleDeduct} disabled={isLoading}>
|
|
211
|
-
Use 5 Credits
|
|
212
|
-
</Button>
|
|
213
|
-
</>
|
|
214
|
-
)}
|
|
215
|
-
</View>
|
|
216
|
-
);
|
|
217
|
-
}
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
### With Auto-Initialization
|
|
221
|
-
|
|
222
|
-
```typescript
|
|
223
|
-
function AutoInitialize() {
|
|
224
|
-
const { isPremium } = usePremium();
|
|
225
|
-
const { credits } = useCredits({ userId: user?.uid });
|
|
226
|
-
const { initializeCredits, isInitializing } = useInitializeCredits({
|
|
227
|
-
userId: user?.uid,
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
useEffect(() => {
|
|
231
|
-
// Auto-initialize if premium but no credits
|
|
232
|
-
if (isPremium && !credits && !isInitializing) {
|
|
233
|
-
initializeCredits();
|
|
234
|
-
}
|
|
235
|
-
}, [isPremium, credits]);
|
|
236
|
-
|
|
237
|
-
return <YourComponent />;
|
|
238
|
-
}
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
## Best Practices
|
|
242
|
-
|
|
243
|
-
1. **Check Balance First**: Always check before deducting
|
|
244
|
-
2. **Handle Loading**: Show loading states appropriately
|
|
245
|
-
3. **Error Recovery**: Handle deduction failures gracefully
|
|
246
|
-
4. **Optimistic Updates**: Use optimistic updates for better UX
|
|
247
|
-
5. **Track Usage**: Log all credit operations
|
|
248
|
-
6. **Auto-Init**: Initialize credits after premium purchase
|
|
249
|
-
7. **Test Scenarios**: Test zero credits, max credits, failures
|
|
250
|
-
|
|
251
|
-
## Related
|
|
252
|
-
|
|
6
|
+
## Strategy
|
|
7
|
+
This directory contains React hooks specifically for credit management and wallet operations with optimistic updates and proper error handling.
|
|
8
|
+
|
|
9
|
+
## Restrictions
|
|
10
|
+
|
|
11
|
+
### REQUIRED
|
|
12
|
+
- Must check balance before deducting
|
|
13
|
+
- Must handle loading states appropriately
|
|
14
|
+
- Must handle deduction failures gracefully
|
|
15
|
+
- Must log all credit operations
|
|
16
|
+
|
|
17
|
+
### PROHIBITED
|
|
18
|
+
- DO NOT deduct credits without balance check
|
|
19
|
+
- DO NOT skip error handling
|
|
20
|
+
- DO NOT ignore loading states
|
|
21
|
+
- DO NOT perform operations without tracking
|
|
22
|
+
|
|
23
|
+
### CRITICAL SAFETY
|
|
24
|
+
- Balance checks MUST precede all deductions
|
|
25
|
+
- Deduction failures MUST be handled gracefully
|
|
26
|
+
- Optimistic updates MUST support rollback
|
|
27
|
+
- All operations MUST be logged
|
|
28
|
+
|
|
29
|
+
## AI Agent Guidelines
|
|
30
|
+
1. Always check credit balance before deducting
|
|
31
|
+
2. Show appropriate loading states during operations
|
|
32
|
+
3. Handle deduction failures with graceful recovery
|
|
33
|
+
4. Use optimistic updates for better user experience
|
|
34
|
+
5. Log all credit operations for debugging
|
|
35
|
+
6. Initialize credits automatically after premium purchase
|
|
36
|
+
7. Test edge cases: zero credits, max credits, failures
|
|
37
|
+
|
|
38
|
+
## Related Documentation
|
|
253
39
|
- [useCredits Hook Documentation](../../../presentation/hooks/useCredits.md)
|
|
254
40
|
- [useDeductCredit Hook Documentation](../../../presentation/hooks/useDeductCredit.md)
|
|
255
41
|
- [Credits Entity](../../domain/entities/README.md)
|