@umituz/react-native-subscription 2.14.96 → 2.14.98
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/LICENSE +21 -0
- package/README.md +462 -0
- package/package.json +3 -3
- package/src/application/README.md +229 -0
- package/src/application/ports/README.md +103 -0
- package/src/domain/README.md +402 -0
- package/src/domain/constants/README.md +80 -0
- package/src/domain/entities/README.md +176 -0
- package/src/domain/errors/README.md +307 -0
- package/src/domain/value-objects/README.md +186 -0
- package/src/domains/config/README.md +390 -0
- package/src/domains/paywall/README.md +371 -0
- package/src/domains/paywall/components/PaywallHeader.tsx +8 -11
- package/src/domains/paywall/components/README.md +185 -0
- package/src/domains/paywall/entities/README.md +199 -0
- package/src/domains/paywall/hooks/README.md +129 -0
- package/src/domains/wallet/README.md +292 -0
- package/src/domains/wallet/domain/README.md +108 -0
- package/src/domains/wallet/domain/entities/README.md +122 -0
- package/src/domains/wallet/domain/errors/README.md +157 -0
- package/src/domains/wallet/infrastructure/README.md +96 -0
- package/src/domains/wallet/presentation/components/BalanceCard.tsx +6 -12
- package/src/domains/wallet/presentation/components/README.md +231 -0
- package/src/domains/wallet/presentation/hooks/README.md +255 -0
- package/src/infrastructure/README.md +514 -0
- package/src/infrastructure/mappers/README.md +34 -0
- package/src/infrastructure/models/README.md +26 -0
- package/src/infrastructure/repositories/README.md +385 -0
- package/src/infrastructure/services/README.md +374 -0
- package/src/presentation/README.md +410 -0
- package/src/presentation/components/README.md +183 -0
- package/src/presentation/components/details/CreditRow.md +337 -0
- package/src/presentation/components/details/DetailRow.md +283 -0
- package/src/presentation/components/details/PremiumDetailsCard.md +266 -0
- package/src/presentation/components/details/PremiumStatusBadge.md +266 -0
- package/src/presentation/components/details/README.md +449 -0
- package/src/presentation/components/feedback/PaywallFeedbackModal.md +314 -0
- package/src/presentation/components/feedback/README.md +447 -0
- package/src/presentation/components/paywall/PaywallModal.md +444 -0
- package/src/presentation/components/paywall/README.md +190 -0
- package/src/presentation/components/sections/README.md +468 -0
- package/src/presentation/components/sections/SubscriptionSection.md +246 -0
- package/src/presentation/hooks/README.md +743 -0
- package/src/presentation/hooks/useAuthAwarePurchase.md +359 -0
- package/src/presentation/hooks/useAuthGate.md +403 -0
- package/src/presentation/hooks/useAuthSubscriptionSync.md +398 -0
- package/src/presentation/hooks/useCreditChecker.md +407 -0
- package/src/presentation/hooks/useCredits.md +342 -0
- package/src/presentation/hooks/useCreditsGate.md +346 -0
- package/src/presentation/hooks/useDeductCredit.md +160 -0
- package/src/presentation/hooks/useDevTestCallbacks.md +422 -0
- package/src/presentation/hooks/useFeatureGate.md +157 -0
- package/src/presentation/hooks/useInitializeCredits.md +458 -0
- package/src/presentation/hooks/usePaywall.md +334 -0
- package/src/presentation/hooks/usePaywallOperations.md +486 -0
- package/src/presentation/hooks/usePaywallVisibility.md +344 -0
- package/src/presentation/hooks/usePremium.md +230 -0
- package/src/presentation/hooks/usePremiumGate.md +423 -0
- package/src/presentation/hooks/usePremiumWithCredits.md +429 -0
- package/src/presentation/hooks/useSubscription.md +450 -0
- package/src/presentation/hooks/useSubscriptionDetails.md +438 -0
- package/src/presentation/hooks/useSubscriptionGate.md +168 -0
- package/src/presentation/hooks/useSubscriptionSettingsConfig.md +374 -0
- package/src/presentation/hooks/useSubscriptionStatus.md +424 -0
- package/src/presentation/hooks/useUserTier.md +356 -0
- package/src/presentation/hooks/useUserTierWithRepository.md +452 -0
- package/src/presentation/screens/README.md +194 -0
- package/src/presentation/types/README.md +38 -0
- package/src/presentation/utils/README.md +52 -0
- package/src/revenuecat/README.md +523 -0
- package/src/revenuecat/domain/README.md +147 -0
- package/src/revenuecat/domain/errors/README.md +197 -0
- package/src/revenuecat/infrastructure/config/README.md +40 -0
- package/src/revenuecat/infrastructure/managers/README.md +49 -0
- package/src/revenuecat/presentation/hooks/README.md +56 -0
- package/src/revenuecat/presentation/hooks/usePurchasePackage.ts +1 -1
- package/src/utils/README.md +529 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Paywall Entities
|
|
2
|
+
|
|
3
|
+
Domain entities for paywall configuration and state management.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This directory contains entities representing paywall configuration, triggers, and display logic.
|
|
8
|
+
|
|
9
|
+
## Entities
|
|
10
|
+
|
|
11
|
+
### PaywallTrigger
|
|
12
|
+
Represents an event that triggers paywall display.
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
interface PaywallTrigger {
|
|
16
|
+
type: PaywallTriggerType;
|
|
17
|
+
feature?: string;
|
|
18
|
+
packageName?: string;
|
|
19
|
+
context?: Record<string, any>;
|
|
20
|
+
timestamp: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type PaywallTriggerType =
|
|
24
|
+
| 'premium_feature' // Premium feature access attempt
|
|
25
|
+
| 'credit_gate' // Credit gate failure
|
|
26
|
+
| 'manual' // User manually opened
|
|
27
|
+
| 'onboarding_complete' // Post-onboarding
|
|
28
|
+
| 'usage_limit' // Free tier limit reached
|
|
29
|
+
| 'subscription_expired'; // Subscription expired
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Usage:**
|
|
33
|
+
```typescript
|
|
34
|
+
const trigger: PaywallTrigger = {
|
|
35
|
+
type: 'premium_feature',
|
|
36
|
+
feature: 'ai_generation',
|
|
37
|
+
context: { cost: 5 },
|
|
38
|
+
timestamp: Date.now(),
|
|
39
|
+
};
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### PaywallConfig
|
|
43
|
+
Configuration for paywall display.
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
interface PaywallConfig {
|
|
47
|
+
title: string;
|
|
48
|
+
subtitle: string;
|
|
49
|
+
description?: string;
|
|
50
|
+
features: string[];
|
|
51
|
+
highlightBenefit?: string; // Main value proposition
|
|
52
|
+
packages: PaywallPackage[];
|
|
53
|
+
defaultPackage?: string; // Pre-selected package
|
|
54
|
+
dismissible: boolean;
|
|
55
|
+
showCloseButton: boolean;
|
|
56
|
+
onUpgrade: (pkg: PaywallPackage) => void;
|
|
57
|
+
onDismiss: () => void;
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Usage:**
|
|
62
|
+
```typescript
|
|
63
|
+
const config: PaywallConfig = {
|
|
64
|
+
title: 'Upgrade to Premium',
|
|
65
|
+
subtitle: 'Unlock all features',
|
|
66
|
+
features: [
|
|
67
|
+
'Unlimited access',
|
|
68
|
+
'Priority support',
|
|
69
|
+
'Ad-free experience',
|
|
70
|
+
],
|
|
71
|
+
packages: availablePackages,
|
|
72
|
+
dismissible: true,
|
|
73
|
+
showCloseButton: true,
|
|
74
|
+
onUpgrade: (pkg) => purchasePackage(pkg),
|
|
75
|
+
onDismiss: () => navigation.goBack(),
|
|
76
|
+
};
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### PaywallPackage
|
|
80
|
+
Represents a subscription package displayed in paywall.
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
interface PaywallPackage {
|
|
84
|
+
identifier: string; // Unique package ID
|
|
85
|
+
productIdentifier: string; // RevenueCat product ID
|
|
86
|
+
title: string; // Display title
|
|
87
|
+
description: string; // Package description
|
|
88
|
+
price: number; // Price in local currency
|
|
89
|
+
pricePerMonth?: number; // Monthly equivalent (for annual)
|
|
90
|
+
currencyCode: string; // Currency code
|
|
91
|
+
period: PackagePeriod; // Billing period
|
|
92
|
+
features: string[]; // Package features
|
|
93
|
+
popular?: boolean; // Highlight as popular
|
|
94
|
+
savings?: number; // Savings amount (for annual)
|
|
95
|
+
badge?: string; // Custom badge text
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
type PackagePeriod = 'monthly' | 'annual' | 'lifetime';
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Usage:**
|
|
102
|
+
```typescript
|
|
103
|
+
const premiumPackage: PaywallPackage = {
|
|
104
|
+
identifier: 'premium_annual',
|
|
105
|
+
productIdentifier: 'com.app.premium.annual',
|
|
106
|
+
title: 'Premium Annual',
|
|
107
|
+
description: 'Best value - Save 50%',
|
|
108
|
+
price: 99.99,
|
|
109
|
+
pricePerMonth: 8.33,
|
|
110
|
+
currencyCode: 'USD',
|
|
111
|
+
period: 'annual',
|
|
112
|
+
features: [
|
|
113
|
+
'Unlimited access',
|
|
114
|
+
'Priority support',
|
|
115
|
+
'Ad-free',
|
|
116
|
+
'Advanced features',
|
|
117
|
+
],
|
|
118
|
+
popular: true,
|
|
119
|
+
savings: 20.00,
|
|
120
|
+
badge: 'BEST VALUE',
|
|
121
|
+
};
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### PaywallState
|
|
125
|
+
Manages current paywall state and context.
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
interface PaywallState {
|
|
129
|
+
visible: boolean;
|
|
130
|
+
trigger?: PaywallTrigger;
|
|
131
|
+
selectedPackage?: string;
|
|
132
|
+
pendingAction?: () => void; // Execute after upgrade
|
|
133
|
+
metadata?: {
|
|
134
|
+
userId?: string;
|
|
135
|
+
screen?: string; // Screen where paywall shown
|
|
136
|
+
previousScreen?: string; // Screen before paywall
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Usage:**
|
|
142
|
+
```typescript
|
|
143
|
+
const state: PaywallState = {
|
|
144
|
+
visible: true,
|
|
145
|
+
trigger: {
|
|
146
|
+
type: 'premium_feature',
|
|
147
|
+
feature: 'ai_generation',
|
|
148
|
+
timestamp: Date.now(),
|
|
149
|
+
},
|
|
150
|
+
selectedPackage: 'premium_annual',
|
|
151
|
+
pendingAction: () => executeAIGeneration(),
|
|
152
|
+
metadata: {
|
|
153
|
+
userId: 'user-123',
|
|
154
|
+
screen: 'AIGeneration',
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Key Operations
|
|
160
|
+
|
|
161
|
+
### Create Trigger
|
|
162
|
+
```typescript
|
|
163
|
+
function createTrigger(
|
|
164
|
+
type: PaywallTriggerType,
|
|
165
|
+
context?: Record<string, any>
|
|
166
|
+
): PaywallTrigger {
|
|
167
|
+
return {
|
|
168
|
+
type,
|
|
169
|
+
context,
|
|
170
|
+
timestamp: Date.now(),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Validate Config
|
|
176
|
+
```typescript
|
|
177
|
+
function validatePaywallConfig(config: PaywallConfig): void {
|
|
178
|
+
if (!config.title) throw new Error('Title is required');
|
|
179
|
+
if (!config.packages || config.packages.length === 0) {
|
|
180
|
+
throw new Error('At least one package is required');
|
|
181
|
+
}
|
|
182
|
+
if (config.defaultPackage && !config.packages.find(p => p.identifier === config.defaultPackage)) {
|
|
183
|
+
throw new Error('Default package must be in packages list');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Best Practices
|
|
189
|
+
|
|
190
|
+
1. **Rich Context**: Include context in triggers for analytics
|
|
191
|
+
2. **Validation**: Validate configurations before use
|
|
192
|
+
3. **Immutability**: Treat entities as immutable values
|
|
193
|
+
4. **Type Safety**: Use strict TypeScript types
|
|
194
|
+
5. **Analytics**: Track all paywall events and triggers
|
|
195
|
+
|
|
196
|
+
## Related
|
|
197
|
+
|
|
198
|
+
- [Paywall README](../README.md)
|
|
199
|
+
- [PaywallVisibility Hook](../../presentation/hooks/usePaywallVisibility.md)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Paywall Hooks
|
|
2
|
+
|
|
3
|
+
React hooks for paywall management and subscription upgrades.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This directory contains React hooks specifically for paywall functionality.
|
|
8
|
+
|
|
9
|
+
## Hooks
|
|
10
|
+
|
|
11
|
+
### usePaywallVisibility
|
|
12
|
+
Manages paywall visibility state.
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
function usePaywallVisibility(): {
|
|
16
|
+
showPaywall: boolean;
|
|
17
|
+
setShowPaywall: (visible: boolean) => void;
|
|
18
|
+
openPaywall: () => void;
|
|
19
|
+
closePaywall: () => void;
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Usage:**
|
|
24
|
+
```typescript
|
|
25
|
+
function PaywallWrapper() {
|
|
26
|
+
const { showPaywall, closePaywall } = usePaywallVisibility();
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<>
|
|
30
|
+
<YourApp />
|
|
31
|
+
<Modal visible={showPaywall} onRequestClose={closePaywall}>
|
|
32
|
+
<PaywallScreen onClose={closePaywall} />
|
|
33
|
+
</Modal>
|
|
34
|
+
</>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### usePaywallOperations
|
|
40
|
+
Handles paywall purchase operations.
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
function usePaywallOperations(config: {
|
|
44
|
+
userId: string | undefined;
|
|
45
|
+
isAnonymous: boolean;
|
|
46
|
+
onPaywallClose?: () => void;
|
|
47
|
+
onPurchaseSuccess?: () => void;
|
|
48
|
+
onAuthRequired?: () => void;
|
|
49
|
+
}): {
|
|
50
|
+
handlePurchase: (pkg: Package) => Promise<boolean>;
|
|
51
|
+
handleRestore: () => Promise<boolean>;
|
|
52
|
+
pendingPackage: Package | null;
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Usage:**
|
|
57
|
+
```typescript
|
|
58
|
+
function Paywall() {
|
|
59
|
+
const { handlePurchase, handleRestore } = usePaywallOperations({
|
|
60
|
+
userId: user?.uid,
|
|
61
|
+
isAnonymous: !user,
|
|
62
|
+
onPurchaseSuccess: () => navigation.goBack(),
|
|
63
|
+
onAuthRequired: () => showAuthModal(),
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<View>
|
|
68
|
+
<PackageList onSelectPackage={handlePurchase} />
|
|
69
|
+
<Button onPress={handleRestore}>Restore</Button>
|
|
70
|
+
</View>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Usage Patterns
|
|
76
|
+
|
|
77
|
+
### Feature Gating
|
|
78
|
+
```typescript
|
|
79
|
+
function useFeatureGate(feature: string) {
|
|
80
|
+
const { openPaywall } = usePaywallVisibility();
|
|
81
|
+
const { isPremium } = usePremium();
|
|
82
|
+
|
|
83
|
+
const gateFeature = useCallback(() => {
|
|
84
|
+
if (!isPremium) {
|
|
85
|
+
analytics.track('paywall_triggered', { feature });
|
|
86
|
+
openPaywall();
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
return true;
|
|
90
|
+
}, [isPremium, openPaywall]);
|
|
91
|
+
|
|
92
|
+
return gateFeature;
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Trigger-Based Paywall
|
|
97
|
+
```typescript
|
|
98
|
+
function useTriggeredPaywall() {
|
|
99
|
+
const { openPaywall } = usePaywallVisibility();
|
|
100
|
+
|
|
101
|
+
const showPaywallForFeature = (feature: string, context?: any) => {
|
|
102
|
+
openPaywall();
|
|
103
|
+
// Store trigger context for analytics
|
|
104
|
+
PaywallTracker.record({
|
|
105
|
+
type: 'premium_feature',
|
|
106
|
+
feature,
|
|
107
|
+
context,
|
|
108
|
+
timestamp: Date.now(),
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
return { showPaywallForFeature };
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Best Practices
|
|
117
|
+
|
|
118
|
+
1. **Centralized State**: Use global paywall visibility
|
|
119
|
+
2. **Auth Integration**: Handle authentication before purchase
|
|
120
|
+
3. **Pending Actions**: Store pending actions for post-purchase
|
|
121
|
+
4. **Analytics**: Track all paywall interactions
|
|
122
|
+
5. **Error Handling**: Handle purchase failures gracefully
|
|
123
|
+
6. **User Context**: Show relevant paywall based on context
|
|
124
|
+
|
|
125
|
+
## Related
|
|
126
|
+
|
|
127
|
+
- [usePaywallVisibility](../../presentation/hooks/usePaywallVisibility.md)
|
|
128
|
+
- [usePaywallOperations](../../presentation/hooks/usePaywallOperations.md)
|
|
129
|
+
- [PremiumGate Hook](../../presentation/hooks/usePremiumGate.md)
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# Wallet Domain
|
|
2
|
+
|
|
3
|
+
Kredi bakiyesi yönetimi, işlem geçmişi takibi ve ürün metadata yönetimi için kapsamlı çözüm.
|
|
4
|
+
|
|
5
|
+
## Özellikler
|
|
6
|
+
|
|
7
|
+
- **Kredi Bakiyesi Yönetimi**: Kullanıcıların kredi bakiyelerini takip edin ve yönetin
|
|
8
|
+
- **İşlem Geçmişi**: Tüm kredi işlemlerini geçmişte takip edin
|
|
9
|
+
- **Ürün Metadata**: Satın alınan ürünler için metadata yönetimi
|
|
10
|
+
- **Tür Desteği**: Farklı kredi türlerini (AI, premium, vb.) destekleyin
|
|
11
|
+
|
|
12
|
+
## Kurulum
|
|
13
|
+
|
|
14
|
+
### 1. Service Konfigürasyonu
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { configureProductMetadataService } from '@umituz/react-native-subscription';
|
|
18
|
+
|
|
19
|
+
// Service'i konfigüre edin
|
|
20
|
+
configureProductMetadataService({
|
|
21
|
+
firebase: firebaseInstance,
|
|
22
|
+
storage: storageInstance,
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. Repository Oluşturma
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { createTransactionRepository } from '@umituz/react-native-subscription';
|
|
30
|
+
|
|
31
|
+
const transactionRepository = createTransactionRepository({
|
|
32
|
+
firebase: firebaseInstance,
|
|
33
|
+
userId: 'user-123',
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Kullanım
|
|
38
|
+
|
|
39
|
+
### useWallet Hook
|
|
40
|
+
|
|
41
|
+
Kredi bakiyesi ve temel cüzdan işlemleri için:
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { useWallet } from '@umituz/react-native-subscription';
|
|
45
|
+
|
|
46
|
+
function MyComponent() {
|
|
47
|
+
const { balance, loading, error, refresh } = useWallet({
|
|
48
|
+
userId: 'user-123',
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
if (loading) return <ActivityIndicator />;
|
|
52
|
+
if (error) return <Text>Error: {error.message}</Text>;
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<View>
|
|
56
|
+
<Text>Balance: {balance.credits}</Text>
|
|
57
|
+
<Button onPress={refresh} title="Refresh" />
|
|
58
|
+
</View>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### useTransactionHistory Hook
|
|
64
|
+
|
|
65
|
+
İşlem geçmişini görüntülemek için:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { useTransactionHistory } from '@umituz/react-native-subscription';
|
|
69
|
+
|
|
70
|
+
function TransactionHistory() {
|
|
71
|
+
const { transactions, loading, hasMore, loadMore } = useTransactionHistory({
|
|
72
|
+
userId: 'user-123',
|
|
73
|
+
limit: 20,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<FlatList
|
|
78
|
+
data={transactions}
|
|
79
|
+
keyExtractor={(item) => item.id}
|
|
80
|
+
onEndReached={hasMore ? loadMore : undefined}
|
|
81
|
+
renderItem={({ item }) => (
|
|
82
|
+
<View>
|
|
83
|
+
<Text>{item.reason}</Text>
|
|
84
|
+
<Text>{item.amount} credits</Text>
|
|
85
|
+
<Text>{new Date(item.timestamp).toLocaleString()}</Text>
|
|
86
|
+
</View>
|
|
87
|
+
)}
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### useProductMetadata Hook
|
|
94
|
+
|
|
95
|
+
Ürün metadata yönetimi için:
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { useProductMetadata } from '@umituz/react-native-subscription';
|
|
99
|
+
|
|
100
|
+
function ProductInfo() {
|
|
101
|
+
const { metadata, loading, updateMetadata } = useProductMetadata({
|
|
102
|
+
userId: 'user-123',
|
|
103
|
+
productId: 'premium_monthly',
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const handleUpdate = async () => {
|
|
107
|
+
await updateMetadata({
|
|
108
|
+
lastUsed: new Date().toISOString(),
|
|
109
|
+
usageCount: (metadata?.usageCount || 0) + 1,
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<View>
|
|
115
|
+
<Text>Product: {metadata?.productId}</Text>
|
|
116
|
+
<Text>Usage: {metadata?.usageCount} times</Text>
|
|
117
|
+
<Button onPress={handleUpdate} title="Update Usage" />
|
|
118
|
+
</View>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Bileşenler
|
|
124
|
+
|
|
125
|
+
### BalanceCard
|
|
126
|
+
|
|
127
|
+
Kredi bakiyesini gösteren kart bileşeni:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import { BalanceCard } from '@umituz/react-native-subscription';
|
|
131
|
+
|
|
132
|
+
<BalanceCard
|
|
133
|
+
balance={150}
|
|
134
|
+
currency="USD"
|
|
135
|
+
translations={{
|
|
136
|
+
title: "Your Balance",
|
|
137
|
+
subtitle: "Credits available",
|
|
138
|
+
}}
|
|
139
|
+
/>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### TransactionItem
|
|
143
|
+
|
|
144
|
+
Tek işlem öğesi:
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
import { TransactionItem } from '@umituz/react-native-subscription';
|
|
148
|
+
|
|
149
|
+
<TransactionItem
|
|
150
|
+
transaction={{
|
|
151
|
+
id: 'tx-123',
|
|
152
|
+
amount: -50,
|
|
153
|
+
reason: 'purchase',
|
|
154
|
+
timestamp: '2024-01-01T00:00:00Z',
|
|
155
|
+
}}
|
|
156
|
+
translations={{
|
|
157
|
+
purchase: 'Purchase',
|
|
158
|
+
refund: 'Refund',
|
|
159
|
+
}}
|
|
160
|
+
/>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### TransactionList
|
|
164
|
+
|
|
165
|
+
İşlem listesi bileşeni:
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import { TransactionList } from '@umituz/react-native-subscription';
|
|
169
|
+
|
|
170
|
+
<TransactionList
|
|
171
|
+
transactions={transactions}
|
|
172
|
+
loading={loading}
|
|
173
|
+
onEndReached={loadMore}
|
|
174
|
+
translations={{
|
|
175
|
+
title: 'Transaction History',
|
|
176
|
+
empty: 'No transactions yet',
|
|
177
|
+
}}
|
|
178
|
+
/>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### WalletScreen
|
|
182
|
+
|
|
183
|
+
Tam cüzdan ekranı:
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import { WalletScreen } from '@umituz/react-native-subscription';
|
|
187
|
+
|
|
188
|
+
<WalletScreen
|
|
189
|
+
userId="user-123"
|
|
190
|
+
config={{
|
|
191
|
+
showBalance: true,
|
|
192
|
+
showHistory: true,
|
|
193
|
+
enableRefresh: true,
|
|
194
|
+
}}
|
|
195
|
+
translations={{
|
|
196
|
+
title: 'My Wallet',
|
|
197
|
+
balance: 'Balance',
|
|
198
|
+
history: 'History',
|
|
199
|
+
}}
|
|
200
|
+
/>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## API Referansı
|
|
204
|
+
|
|
205
|
+
### Tip Tanımlamaları
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
interface CreditBalance {
|
|
209
|
+
credits: number;
|
|
210
|
+
lastUpdated: string;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
interface TransactionLog {
|
|
214
|
+
id: string;
|
|
215
|
+
amount: number;
|
|
216
|
+
reason: TransactionReason;
|
|
217
|
+
timestamp: string;
|
|
218
|
+
metadata?: Record<string, any>;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
type TransactionReason =
|
|
222
|
+
| 'purchase'
|
|
223
|
+
| 'refund'
|
|
224
|
+
| 'usage'
|
|
225
|
+
| 'bonus'
|
|
226
|
+
| 'expiration';
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Yardımcı Fonksiyonlar
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
// Kredi maliyeti hesaplama
|
|
233
|
+
import { getCreditCost, creditsToDollars } from '@umituz/react-native-subscription';
|
|
234
|
+
|
|
235
|
+
const cost = getCreditCost('ai_generation'); // AI işlem maliyeti
|
|
236
|
+
const dollars = creditsToDollars(150, 0.01); // 150 kredi = $1.50
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Hata Yönetimi
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
import {
|
|
243
|
+
WalletError,
|
|
244
|
+
CreditLimitError,
|
|
245
|
+
handleWalletError,
|
|
246
|
+
} from '@umituz/react-native-subscription';
|
|
247
|
+
|
|
248
|
+
try {
|
|
249
|
+
// İşlem
|
|
250
|
+
} catch (error) {
|
|
251
|
+
if (error instanceof CreditLimitError) {
|
|
252
|
+
console.log('Yetersiz bakiye');
|
|
253
|
+
}
|
|
254
|
+
handleWalletError(error);
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Örnek Uygulama
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import React from 'react';
|
|
262
|
+
import { View, Text, Button } from 'react-native';
|
|
263
|
+
import {
|
|
264
|
+
useWallet,
|
|
265
|
+
useTransactionHistory,
|
|
266
|
+
BalanceCard,
|
|
267
|
+
TransactionList,
|
|
268
|
+
} from '@umituz/react-native-subscription';
|
|
269
|
+
|
|
270
|
+
export default function WalletExample() {
|
|
271
|
+
const { balance, refresh } = useWallet({ userId: 'user-123' });
|
|
272
|
+
const { transactions, loading } = useTransactionHistory({
|
|
273
|
+
userId: 'user-123',
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
return (
|
|
277
|
+
<View>
|
|
278
|
+
<BalanceCard balance={balance} />
|
|
279
|
+
<Button title="Refresh" onPress={refresh} />
|
|
280
|
+
<TransactionList transactions={transactions} loading={loading} />
|
|
281
|
+
</View>
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Best Practices
|
|
287
|
+
|
|
288
|
+
1. **Kredi Türleri**: Farklı kredi türleri için farklı cost config'leri kullanın
|
|
289
|
+
2. **Hata Yönetimi**: Tüm işlemleri try-catch blokları içinde sarın
|
|
290
|
+
3. **Loading State**: Yüklenme durumlarını her zaman gösterin
|
|
291
|
+
4. **Refresh**: Kullanıcıya manuel refresh imkanı verin
|
|
292
|
+
5. **Transaction Log**: Tüm işlemleri loglayın ve audit trail tutun
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Wallet Domain
|
|
2
|
+
|
|
3
|
+
Wallet domain containing credits and transaction management logic.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The wallet domain manages user credits, transactions, and credit allocation strategies. It handles credit initialization after purchase, credit deduction, and transaction history.
|
|
8
|
+
|
|
9
|
+
## Structure
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
wallet/
|
|
13
|
+
├── domain/
|
|
14
|
+
│ ├── entities/ # Credit and transaction entities
|
|
15
|
+
│ ├── errors/ # Wallet-specific errors
|
|
16
|
+
│ ├── types/ # Wallet type definitions
|
|
17
|
+
│ └── mappers/ # Data transformation mappers
|
|
18
|
+
├── infrastructure/
|
|
19
|
+
│ ├── repositories/ # Credits persistence
|
|
20
|
+
│ └── services/ # Credit operations
|
|
21
|
+
├── presentation/
|
|
22
|
+
│ ├── hooks/ # React hooks for credits
|
|
23
|
+
│ ├── components/ # Credit UI components
|
|
24
|
+
│ └── screens/ # Credit management screens
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Core Concepts
|
|
28
|
+
|
|
29
|
+
### Credits
|
|
30
|
+
User credits balance that can be consumed for premium features.
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
interface UserCredits {
|
|
34
|
+
credits: number;
|
|
35
|
+
purchasedAt: Date;
|
|
36
|
+
lastUpdatedAt: Date;
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Transactions
|
|
41
|
+
Record of credit transactions (additions and deductions).
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
interface Transaction {
|
|
45
|
+
id: string;
|
|
46
|
+
amount: number;
|
|
47
|
+
reason: string;
|
|
48
|
+
timestamp: Date;
|
|
49
|
+
type: 'purchase' | 'deduction' | 'bonus' | 'renewal';
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Allocation Modes
|
|
54
|
+
|
|
55
|
+
**ACCUMULATE**: Add credits to existing balance (renewals)
|
|
56
|
+
```typescript
|
|
57
|
+
// Renewal: 100 + 100 = 200 credits
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**REPLACE**: Replace existing credits (new purchase)
|
|
61
|
+
```typescript
|
|
62
|
+
// New purchase: Old balance replaced with new amount
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Key Features
|
|
66
|
+
|
|
67
|
+
- **Duplicate Protection**: Prevent duplicate credit allocations
|
|
68
|
+
- **Transactional Operations**: Atomic credit updates
|
|
69
|
+
- **Optimistic Updates**: Immediate UI with rollback
|
|
70
|
+
- **Transaction History**: Complete audit trail
|
|
71
|
+
- **Monthly Reset**: Credits reset on subscription renewal
|
|
72
|
+
|
|
73
|
+
## Usage
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// In hooks or components
|
|
77
|
+
import { useCredits } from './presentation/hooks/useCredits';
|
|
78
|
+
import { useDeductCredit } from './presentation/hooks/useDeductCredit';
|
|
79
|
+
|
|
80
|
+
function Feature() {
|
|
81
|
+
const { credits } = useCredits({ userId: user?.uid });
|
|
82
|
+
const { deductCredit } = useDeductCredit({
|
|
83
|
+
userId: user?.uid,
|
|
84
|
+
onCreditsExhausted: () => showPaywall(),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const handleUseFeature = async () => {
|
|
88
|
+
const success = await deductCredit(5);
|
|
89
|
+
if (success) {
|
|
90
|
+
await executeFeature();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Best Practices
|
|
97
|
+
|
|
98
|
+
1. **Check Balance First**: Verify credits before operations
|
|
99
|
+
2. **Handle Exhaustion**: Provide upgrade path when credits low
|
|
100
|
+
3. **Track Usage**: Log all credit transactions
|
|
101
|
+
4. **Reset Credits**: Clear credits on subscription renewal
|
|
102
|
+
5. **Test Edge Cases**: Zero credits, max credits, duplicates
|
|
103
|
+
|
|
104
|
+
## Related
|
|
105
|
+
|
|
106
|
+
- [Credits README](./README.md)
|
|
107
|
+
- [Credits Entity](./domain/entities/Credits.md)
|
|
108
|
+
- [useCredits Hook](../../presentation/hooks/useCredits.md)
|