@umituz/react-native-subscription 2.14.98 → 2.14.100
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 -395
- package/package.json +1 -1
- 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/errors/README.md +33 -287
- package/src/domain/value-objects/README.md +43 -179
- package/src/domains/README.md +52 -0
- package/src/domains/README.md.bak +274 -0
- package/src/domains/config/README.md +93 -383
- package/src/domains/config/domain/README.md +37 -0
- package/src/domains/config/domain/entities/README.md +41 -0
- 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/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/README.md +95 -370
- 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 +96 -156
- 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/revenuecat/README.md +99 -518
- package/src/revenuecat/application/README.md +43 -0
- package/src/revenuecat/application/ports/README.md +41 -0
- package/src/revenuecat/domain/README.md +42 -141
- package/src/revenuecat/domain/constants/README.md +41 -0
- package/src/revenuecat/domain/entities/README.md +42 -0
- package/src/revenuecat/domain/errors/README.md +47 -191
- package/src/revenuecat/domain/types/README.md +41 -0
- package/src/revenuecat/domain/value-objects/README.md +41 -0
- package/src/revenuecat/infrastructure/README.md +41 -0
- package/src/revenuecat/infrastructure/config/README.md +32 -23
- package/src/revenuecat/infrastructure/handlers/README.md +41 -0
- package/src/revenuecat/infrastructure/managers/README.md +34 -42
- package/src/revenuecat/infrastructure/services/README.md +42 -0
- package/src/revenuecat/infrastructure/utils/README.md +41 -0
- package/src/revenuecat/presentation/README.md +42 -0
- package/src/revenuecat/presentation/hooks/README.md +29 -35
- package/src/utils/README.md +38 -525
|
@@ -2,423 +2,93 @@
|
|
|
2
2
|
|
|
3
3
|
Hook for accessing detailed subscription status information.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Location
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
import { useSubscriptionStatus } from '@umituz/react-native-subscription';
|
|
9
|
-
```
|
|
7
|
+
**Import Path**: `@umituz/react-native-subscription`
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
**File**: `src/presentation/hooks/useSubscriptionStatus.ts`
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
function useSubscriptionStatus(): {
|
|
15
|
-
status: SubscriptionStatus | null;
|
|
16
|
-
tier: UserTier;
|
|
17
|
-
isActive: boolean;
|
|
18
|
-
isExpired: boolean;
|
|
19
|
-
willRenew: boolean;
|
|
20
|
-
expirationDate: Date | null;
|
|
21
|
-
daysUntilExpiration: number | null;
|
|
22
|
-
isLoading: boolean;
|
|
23
|
-
error: Error | null;
|
|
24
|
-
refetch: () => Promise<void>;
|
|
25
|
-
}
|
|
26
|
-
```
|
|
11
|
+
**Type**: Hook
|
|
27
12
|
|
|
28
|
-
##
|
|
13
|
+
## Strategy
|
|
29
14
|
|
|
30
|
-
|
|
31
|
-
|----------|------|-------------|
|
|
32
|
-
| `status` | `SubscriptionStatus \| null` | Full status object |
|
|
33
|
-
| `tier` | `UserTier` | User tier (guest/free/premium) |
|
|
34
|
-
| `isActive` | `boolean` | Subscription is currently active |
|
|
35
|
-
| `isExpired` | `boolean` | Subscription has expired |
|
|
36
|
-
| `willRenew` | `boolean` | Subscription will auto-renew |
|
|
37
|
-
| `expirationDate` | `Date \| null` | When subscription expires |
|
|
38
|
-
| `daysUntilExpiration` | `number \| null` | Days until expiration |
|
|
39
|
-
| `isLoading` | `boolean` | Loading state |
|
|
40
|
-
| `error` | `Error \| null` | Error if any |
|
|
15
|
+
### Subscription Status Flow
|
|
41
16
|
|
|
42
|
-
|
|
17
|
+
1. **Status Fetch**: Retrieve current subscription status from repository
|
|
18
|
+
2. **Status Parsing**: Extract tier, active state, expiration info
|
|
19
|
+
3. **Real-time Updates**: Update when subscription changes
|
|
20
|
+
4. **Expiration Tracking**: Calculate days until expiration
|
|
21
|
+
5. **Renewal Status**: Determine if subscription will auto-renew
|
|
22
|
+
6. **Caching**: Cache status for performance (5 min default)
|
|
43
23
|
|
|
44
|
-
|
|
45
|
-
function SubscriptionStatusDisplay() {
|
|
46
|
-
const {
|
|
47
|
-
status,
|
|
48
|
-
tier,
|
|
49
|
-
isActive,
|
|
50
|
-
expirationDate,
|
|
51
|
-
daysUntilExpiration,
|
|
52
|
-
isLoading,
|
|
53
|
-
} = useSubscriptionStatus();
|
|
24
|
+
### Integration Points
|
|
54
25
|
|
|
55
|
-
|
|
26
|
+
- **Subscription Repository**: `src/infrastructure/repositories/SubscriptionRepository.ts`
|
|
27
|
+
- **SubscriptionStatus Entity**: `src/domain/entities/README.md`
|
|
28
|
+
- **TanStack Query**: For caching and real-time updates
|
|
29
|
+
- **RevenueCat**: For subscription data source
|
|
56
30
|
|
|
57
|
-
|
|
58
|
-
<View>
|
|
59
|
-
<Text>Tier: {tier}</Text>
|
|
60
|
-
<Text>Status: {isActive ? 'Active' : 'Inactive'}</Text>
|
|
31
|
+
## Restrictions
|
|
61
32
|
|
|
62
|
-
|
|
63
|
-
<Text>
|
|
64
|
-
Expires: {expirationDate.toLocaleDateString()}
|
|
65
|
-
({daysUntilExpiration} days)
|
|
66
|
-
</Text>
|
|
67
|
-
)}
|
|
68
|
-
</View>
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
```
|
|
33
|
+
### REQUIRED
|
|
72
34
|
|
|
73
|
-
|
|
35
|
+
- **Loading State**: MUST handle loading state
|
|
36
|
+
- **Error Handling**: MUST handle error state
|
|
37
|
+
- **Null Check**: MUST handle null status (guest users)
|
|
38
|
+
- **Expiration**: SHOULD warn users before expiration
|
|
74
39
|
|
|
75
|
-
###
|
|
40
|
+
### PROHIBITED
|
|
76
41
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
42
|
+
- **NEVER** assume status exists (check for null)
|
|
43
|
+
- **NEVER** use for security decisions without server validation
|
|
44
|
+
- **DO NOT** show expiration for lifetime subscriptions
|
|
45
|
+
- **DO NOT** cache beyond configured time
|
|
80
46
|
|
|
81
|
-
|
|
82
|
-
return <Text>Auto-renewal is on</Text>;
|
|
83
|
-
}
|
|
47
|
+
### CRITICAL SAFETY
|
|
84
48
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
49
|
+
- **ALWAYS** check if status is null before accessing properties
|
|
50
|
+
- **NEVER** trust client-side status for security
|
|
51
|
+
- **MUST** implement error boundaries
|
|
52
|
+
- **ALWAYS** refresh status when app comes to foreground
|
|
88
53
|
|
|
89
|
-
|
|
90
|
-
return (
|
|
91
|
-
<WarningCard
|
|
92
|
-
type={daysUntilExpiration <= 1 ? 'critical' : 'warning'}
|
|
93
|
-
message={`Your subscription expires in ${daysUntilExpiration} day${daysUntilExpiration > 1 ? 's' : ''}`}
|
|
94
|
-
/>
|
|
95
|
-
);
|
|
96
|
-
}
|
|
54
|
+
## AI Agent Guidelines
|
|
97
55
|
|
|
98
|
-
|
|
99
|
-
return <InfoCard message={`Subscription expires in ${daysUntilExpiration} days`} />;
|
|
100
|
-
}
|
|
56
|
+
### When Displaying Subscription Info
|
|
101
57
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
58
|
+
1. **Always** check for null status (guest users)
|
|
59
|
+
2. **Always** handle loading and error states
|
|
60
|
+
3. **Always** show expiration warnings
|
|
61
|
+
4. **Always** display auto-renewal status
|
|
62
|
+
5. **Never** show technical details to end users
|
|
105
63
|
|
|
106
|
-
###
|
|
64
|
+
### Integration Checklist
|
|
107
65
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
66
|
+
- [ ] Import from correct path: `@umituz/react-native-subscription`
|
|
67
|
+
- [ ] Handle loading state
|
|
68
|
+
- [ ] Handle error state
|
|
69
|
+
- [ ] Check for null status (guest users)
|
|
70
|
+
- [ ] Display subscription tier
|
|
71
|
+
- [ ] Show expiration date
|
|
72
|
+
- [ ] Show days until expiration
|
|
73
|
+
- [ ] Show auto-renewal status
|
|
74
|
+
- [ ] Implement expiration warnings
|
|
75
|
+
- [ ] Test with active subscription
|
|
76
|
+
- [ ] Test with expired subscription
|
|
77
|
+
- [ ] Test with guest user (null status)
|
|
111
78
|
|
|
112
|
-
|
|
113
|
-
if (isExpired) {
|
|
114
|
-
return { color: 'red', icon: '⚠️', text: 'Expired' };
|
|
115
|
-
}
|
|
116
|
-
if (isActive) {
|
|
117
|
-
return { color: 'green', icon: '✅', text: 'Active' };
|
|
118
|
-
}
|
|
119
|
-
return { color: 'gray', icon: '⏸️', text: 'Inactive' };
|
|
120
|
-
};
|
|
79
|
+
### Common Patterns
|
|
121
80
|
|
|
122
|
-
|
|
81
|
+
1. **Status Badge**: Visual indicator of subscription status
|
|
82
|
+
2. **Expiration Countdown**: Days remaining until expiration
|
|
83
|
+
3. **Warning System**: Notify users before expiration
|
|
84
|
+
4. **Detail Card**: Comprehensive subscription information
|
|
85
|
+
5. **Lifecycle Management**: Handle subscription events
|
|
123
86
|
|
|
124
|
-
|
|
125
|
-
<View style={[styles.badge, { backgroundColor: config.color }]}>
|
|
126
|
-
<Text>{config.icon}</Text>
|
|
127
|
-
<Text>{config.text}</Text>
|
|
128
|
-
</View>
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
```
|
|
87
|
+
## Related Documentation
|
|
132
88
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
// Refetch every 5 minutes
|
|
140
|
-
useEffect(() => {
|
|
141
|
-
const interval = setInterval(() => {
|
|
142
|
-
refetch();
|
|
143
|
-
}, 5 * 60 * 1000);
|
|
144
|
-
|
|
145
|
-
return () => clearInterval(interval);
|
|
146
|
-
}, [refetch]);
|
|
147
|
-
|
|
148
|
-
// Refetch when app comes to foreground
|
|
149
|
-
useFocusEffect(
|
|
150
|
-
useCallback(() => {
|
|
151
|
-
refetch();
|
|
152
|
-
}, [refetch])
|
|
153
|
-
);
|
|
154
|
-
|
|
155
|
-
return (
|
|
156
|
-
<View>
|
|
157
|
-
<Text>Status: {status?.type}</Text>
|
|
158
|
-
<Button
|
|
159
|
-
onPress={refetch}
|
|
160
|
-
disabled={isLoading}
|
|
161
|
-
title="Refresh"
|
|
162
|
-
/>
|
|
163
|
-
</View>
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
### With Detailed Info Card
|
|
169
|
-
|
|
170
|
-
```typescript
|
|
171
|
-
function DetailedSubscriptionCard() {
|
|
172
|
-
const {
|
|
173
|
-
status,
|
|
174
|
-
tier,
|
|
175
|
-
isActive,
|
|
176
|
-
willRenew,
|
|
177
|
-
expirationDate,
|
|
178
|
-
daysUntilExpiration,
|
|
179
|
-
} = useSubscriptionStatus();
|
|
180
|
-
|
|
181
|
-
if (!status) return null;
|
|
182
|
-
|
|
183
|
-
return (
|
|
184
|
-
<Card style={styles.card}>
|
|
185
|
-
<View style={styles.header}>
|
|
186
|
-
<Badge tier={tier} />
|
|
187
|
-
<Badge
|
|
188
|
-
variant={isActive ? 'success' : 'default'}
|
|
189
|
-
text={isActive ? 'Active' : 'Inactive'}
|
|
190
|
-
/>
|
|
191
|
-
</View>
|
|
192
|
-
|
|
193
|
-
<Divider />
|
|
194
|
-
|
|
195
|
-
<View style={styles.section}>
|
|
196
|
-
<DetailRow
|
|
197
|
-
label="Plan"
|
|
198
|
-
value={status.productId?.replace('_', ' ').toUpperCase()}
|
|
199
|
-
/>
|
|
200
|
-
<DetailRow
|
|
201
|
-
label="Auto-renew"
|
|
202
|
-
value={willRenew ? 'Enabled' : 'Disabled'}
|
|
203
|
-
/>
|
|
204
|
-
</View>
|
|
205
|
-
|
|
206
|
-
{expirationDate && (
|
|
207
|
-
<>
|
|
208
|
-
<Divider />
|
|
209
|
-
<View style={styles.section}>
|
|
210
|
-
<DetailRow
|
|
211
|
-
label="Expires"
|
|
212
|
-
value={expirationDate.toLocaleDateString()}
|
|
213
|
-
/>
|
|
214
|
-
{daysUntilExpiration !== null && (
|
|
215
|
-
<DetailRow
|
|
216
|
-
label="Days remaining"
|
|
217
|
-
value={daysUntilExpiration.toString()}
|
|
218
|
-
/>
|
|
219
|
-
)}
|
|
220
|
-
</View>
|
|
221
|
-
</>
|
|
222
|
-
)}
|
|
223
|
-
|
|
224
|
-
{daysUntilExpiration !== null &&
|
|
225
|
-
daysUntilExpiration <= 7 && (
|
|
226
|
-
<Alert
|
|
227
|
-
severity={daysUntilExpiration <= 3 ? 'warning' : 'info'}
|
|
228
|
-
message={`Subscription expires in ${daysUntilExpiration} days`}
|
|
229
|
-
/>
|
|
230
|
-
)}
|
|
231
|
-
</Card>
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
## Examples
|
|
237
|
-
|
|
238
|
-
### Subscription Countdown
|
|
239
|
-
|
|
240
|
-
```typescript
|
|
241
|
-
function SubscriptionCountdown() {
|
|
242
|
-
const { expirationDate, daysUntilExpiration, isActive } =
|
|
243
|
-
useSubscriptionStatus();
|
|
244
|
-
|
|
245
|
-
if (!isActive || !expirationDate) {
|
|
246
|
-
return null;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
const [timeLeft, setTimeLeft] = useState('');
|
|
250
|
-
|
|
251
|
-
useEffect(() => {
|
|
252
|
-
const updateCountdown = () => {
|
|
253
|
-
const now = new Date();
|
|
254
|
-
const diff = expirationDate.getTime() - now.getTime();
|
|
255
|
-
|
|
256
|
-
if (diff <= 0) {
|
|
257
|
-
setTimeLeft('Expired');
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
|
|
262
|
-
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
|
263
|
-
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
|
|
264
|
-
|
|
265
|
-
setTimeLeft(`${days}d ${hours}h ${minutes}m`);
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
updateCountdown();
|
|
269
|
-
const interval = setInterval(updateCountdown, 60000); // Every minute
|
|
270
|
-
|
|
271
|
-
return () => clearInterval(interval);
|
|
272
|
-
}, [expirationDate]);
|
|
273
|
-
|
|
274
|
-
return (
|
|
275
|
-
<View style={styles.countdown}>
|
|
276
|
-
<Text>Expires in:</Text>
|
|
277
|
-
<Text style={styles.timeLeft}>{timeLeft}</Text>
|
|
278
|
-
</View>
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
### Status History Tracker
|
|
284
|
-
|
|
285
|
-
```typescript
|
|
286
|
-
function StatusHistoryTracker() {
|
|
287
|
-
const { status } = useSubscriptionStatus();
|
|
288
|
-
const previousStatus = useRef(status);
|
|
289
|
-
|
|
290
|
-
useEffect(() => {
|
|
291
|
-
if (previousStatus.current?.type !== status?.type) {
|
|
292
|
-
analytics.track('subscription_status_changed', {
|
|
293
|
-
from: previousStatus.current?.type,
|
|
294
|
-
to: status?.type,
|
|
295
|
-
timestamp: Date.now(),
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
// Log to database for audit trail
|
|
299
|
-
logStatusChange(previousStatus.current, status);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
previousStatus.current = status;
|
|
303
|
-
}, [status]);
|
|
304
|
-
|
|
305
|
-
return null;
|
|
306
|
-
}
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
### Lifecycle Management
|
|
310
|
-
|
|
311
|
-
```typescript
|
|
312
|
-
function SubscriptionLifecycleManager() {
|
|
313
|
-
const { status, isActive, daysUntilExpiration, willRenew } =
|
|
314
|
-
useSubscriptionStatus();
|
|
315
|
-
|
|
316
|
-
useEffect(() => {
|
|
317
|
-
if (!isActive) {
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// Expiration warning
|
|
322
|
-
if (daysUntilExpiration === 3) {
|
|
323
|
-
notifications.send({
|
|
324
|
-
title: 'Subscription Expiring Soon',
|
|
325
|
-
body: 'Your subscription expires in 3 days',
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// Renewal reminder
|
|
330
|
-
if (daysUntilExpiration === 1 && !willRenew) {
|
|
331
|
-
notifications.send({
|
|
332
|
-
title: 'Last Chance!',
|
|
333
|
-
body: 'Your subscription expires tomorrow. Renew now to maintain access.',
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
}, [daysUntilExpiration, willRenew, isActive]);
|
|
337
|
-
|
|
338
|
-
return null;
|
|
339
|
-
}
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
## State Machine
|
|
343
|
-
|
|
344
|
-
```typescript
|
|
345
|
-
function SubscriptionStateMachine() {
|
|
346
|
-
const { status, isActive, isExpired } = useSubscriptionStatus();
|
|
347
|
-
|
|
348
|
-
const getState = () => {
|
|
349
|
-
if (!status) return 'unknown';
|
|
350
|
-
if (!isActive) return 'inactive';
|
|
351
|
-
if (isExpired) return 'expired';
|
|
352
|
-
return 'active';
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
const state = getState();
|
|
356
|
-
|
|
357
|
-
switch (state) {
|
|
358
|
-
case 'unknown':
|
|
359
|
-
return <LoadingState />;
|
|
360
|
-
case 'inactive':
|
|
361
|
-
return <UpgradePrompt />;
|
|
362
|
-
case 'expired':
|
|
363
|
-
return <RenewPrompt />;
|
|
364
|
-
case 'active':
|
|
365
|
-
return <PremiumContent />;
|
|
366
|
-
default:
|
|
367
|
-
return null;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
## Visual Status Indicator
|
|
373
|
-
|
|
374
|
-
```typescript
|
|
375
|
-
function StatusIndicator() {
|
|
376
|
-
const { isActive, isExpired, willRenew } = useSubscriptionStatus();
|
|
377
|
-
|
|
378
|
-
const getStatusColor = () => {
|
|
379
|
-
if (isExpired) return '#F44336'; // red
|
|
380
|
-
if (isActive) return '#4CAF50'; // green
|
|
381
|
-
return '#9E9E9E'; // gray
|
|
382
|
-
};
|
|
383
|
-
|
|
384
|
-
const getStatusIcon = () => {
|
|
385
|
-
if (isExpired) return '⚠️';
|
|
386
|
-
if (isActive && willRenew) return '♻️';
|
|
387
|
-
if (isActive && !willRenew) return '⏳';
|
|
388
|
-
return '⏸️';
|
|
389
|
-
};
|
|
390
|
-
|
|
391
|
-
return (
|
|
392
|
-
<View style={[styles.indicator, { borderColor: getStatusColor() }]}>
|
|
393
|
-
<Text>{getStatusIcon()}</Text>
|
|
394
|
-
<ActivityIndicator
|
|
395
|
-
size={8}
|
|
396
|
-
color={getStatusColor()}
|
|
397
|
-
animating={isActive}
|
|
398
|
-
/>
|
|
399
|
-
</View>
|
|
400
|
-
);
|
|
401
|
-
}
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
## Best Practices
|
|
405
|
-
|
|
406
|
-
1. **Handle null status** - Check if status exists
|
|
407
|
-
2. **Show expiration warnings** - Remind users before expiry
|
|
408
|
-
3. **Display renewal status** - Show if auto-renew is on/off
|
|
409
|
-
4. **Track changes** - Monitor status transitions
|
|
410
|
-
5. **Refresh regularly** - Keep status up to date
|
|
411
|
-
6. **Handle errors** - Show user-friendly error messages
|
|
412
|
-
|
|
413
|
-
## Related Hooks
|
|
414
|
-
|
|
415
|
-
- **usePremium** - Simple premium check
|
|
416
|
-
- **useSubscription** - Subscription details
|
|
417
|
-
- **useSubscriptionDetails** - Package and plan info
|
|
418
|
-
- **useUserTier** - Tier information
|
|
419
|
-
|
|
420
|
-
## See Also
|
|
421
|
-
|
|
422
|
-
- [SubscriptionStatus Entity](../../domain/entities/README.md)
|
|
423
|
-
- [usePremium](./usePremium.md)
|
|
424
|
-
- [useUserTier](./useUserTier.md)
|
|
89
|
+
- **usePremium**: Simple premium status check
|
|
90
|
+
- **useSubscription**: Detailed subscription information
|
|
91
|
+
- **useSubscriptionDetails**: Package and feature details
|
|
92
|
+
- **useUserTier**: Tier information
|
|
93
|
+
- **SubscriptionStatus Entity**: `src/domain/entities/README.md`
|
|
94
|
+
- **Subscription Repository**: `src/infrastructure/repositories/README.md`
|