@umituz/react-native-subscription 2.15.3 → 2.15.4
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/package.json +1 -1
- package/src/presentation/hooks/useSubscriptionSettingsConfig.ts +6 -2
- package/src/revenuecat/infrastructure/utils/ExpirationDateCalculator.ts +43 -12
- package/src/domains/README.md.bak +0 -274
- package/src/domains/wallet/README.md.bak +0 -209
- package/src/presentation/README.md.bak +0 -172
- package/src/presentation/components/README.md.bak +0 -217
- package/src/presentation/hooks/useCredits.md.bak +0 -231
- package/src/presentation/hooks/useFeatureGate.md.bak +0 -284
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
# Presentation Layer
|
|
2
|
-
|
|
3
|
-
UI/UX layer for the subscription system - React hooks, components, and screens.
|
|
4
|
-
|
|
5
|
-
## Location
|
|
6
|
-
|
|
7
|
-
**Directory**: `src/presentation/`
|
|
8
|
-
|
|
9
|
-
**Type**: Layer
|
|
10
|
-
|
|
11
|
-
## Strategy
|
|
12
|
-
|
|
13
|
-
### Layer Responsibilities
|
|
14
|
-
|
|
15
|
-
The Presentation Layer is responsible for:
|
|
16
|
-
|
|
17
|
-
1. **State Management**
|
|
18
|
-
- React hooks for data fetching and mutations
|
|
19
|
-
- TanStack Query for server state management
|
|
20
|
-
- Local state management for UI state
|
|
21
|
-
|
|
22
|
-
2. **UI Components**
|
|
23
|
-
- Reusable subscription components
|
|
24
|
-
- Feature gating UI elements
|
|
25
|
-
- Credit display components
|
|
26
|
-
- Paywall components
|
|
27
|
-
|
|
28
|
-
3. **User Interaction**
|
|
29
|
-
- Handle user actions
|
|
30
|
-
- Display appropriate feedback
|
|
31
|
-
- Guide users through purchase flows
|
|
32
|
-
- Show upgrade prompts at right time
|
|
33
|
-
|
|
34
|
-
### Architecture Pattern
|
|
35
|
-
|
|
36
|
-
The presentation layer follows a layered architecture where:
|
|
37
|
-
- Hooks manage state and data fetching at the top level
|
|
38
|
-
- Components consume hooks and render UI
|
|
39
|
-
- Screens compose multiple components together
|
|
40
|
-
- All layers communicate with the domain layer for business logic
|
|
41
|
-
|
|
42
|
-
### Integration Points
|
|
43
|
-
|
|
44
|
-
- **Domain Layer**: Business logic and data access
|
|
45
|
-
- **TanStack Query**: Server state management
|
|
46
|
-
- **RevenueCat**: Purchase operations
|
|
47
|
-
- **Navigation**: Screen routing
|
|
48
|
-
|
|
49
|
-
## Restrictions
|
|
50
|
-
|
|
51
|
-
### REQUIRED
|
|
52
|
-
|
|
53
|
-
- **Type Safety**: All components MUST be typed with TypeScript
|
|
54
|
-
- **Error Boundaries**: MUST implement error boundaries for all screens
|
|
55
|
-
- **Loading States**: MUST show loading indicators during async operations
|
|
56
|
-
- **User Feedback**: MUST provide feedback for all user actions
|
|
57
|
-
|
|
58
|
-
### PROHIBITED
|
|
59
|
-
|
|
60
|
-
- **NEVER** include business logic in components (use hooks instead)
|
|
61
|
-
- **NEVER** make direct API calls from components (use hooks)
|
|
62
|
-
- **DO NOT** store sensitive data in component state
|
|
63
|
-
- **NEVER** hardcode strings (use localization)
|
|
64
|
-
|
|
65
|
-
### CRITICAL SAFETY
|
|
66
|
-
|
|
67
|
-
- **ALWAYS** validate props before rendering
|
|
68
|
-
- **ALWAYS** handle loading and error states
|
|
69
|
-
- **NEVER** trust client-side state for security decisions
|
|
70
|
-
- **MUST** implement proper error boundaries
|
|
71
|
-
- **ALWAYS** sanitize user inputs before display
|
|
72
|
-
|
|
73
|
-
## Rules
|
|
74
|
-
|
|
75
|
-
### Component Structure
|
|
76
|
-
|
|
77
|
-
**CORRECT**: Proper component structure includes:
|
|
78
|
-
- Define TypeScript interface for props
|
|
79
|
-
- Import and use appropriate hooks for data fetching
|
|
80
|
-
- Return loading indicator when data is fetching
|
|
81
|
-
- Return error display when there's an error
|
|
82
|
-
- Render actual component only when data is available
|
|
83
|
-
|
|
84
|
-
**INCORRECT**: No loading/error handling
|
|
85
|
-
- Don't render component without checking if data is loading
|
|
86
|
-
- Don't display component without handling potential errors
|
|
87
|
-
- Never assume data is always available immediately
|
|
88
|
-
|
|
89
|
-
**INCORRECT**: Business logic in component
|
|
90
|
-
- Don't use useEffect to fetch data directly
|
|
91
|
-
- Don't manage complex state with useState for business logic
|
|
92
|
-
- Never include data transformation logic in components
|
|
93
|
-
|
|
94
|
-
### Hook Usage
|
|
95
|
-
|
|
96
|
-
**CORRECT**: Use hooks for data fetching
|
|
97
|
-
- Call useCredits to get credit balance with loading and error states
|
|
98
|
-
- Call usePremium to check premium status
|
|
99
|
-
- Always check if loading is true before rendering
|
|
100
|
-
- Always check if error exists before rendering
|
|
101
|
-
|
|
102
|
-
**INCORRECT**: Direct API calls in component
|
|
103
|
-
- Don't use useEffect with axios or fetch to call APIs
|
|
104
|
-
- Don't manage async operations manually in components
|
|
105
|
-
- Never handle API responses directly in UI components
|
|
106
|
-
|
|
107
|
-
### Error Boundaries
|
|
108
|
-
|
|
109
|
-
**CORRECT**: Wrap screens with error boundaries
|
|
110
|
-
- Import ErrorBoundary component
|
|
111
|
-
- Create fallback error screen component
|
|
112
|
-
- Wrap screen content with ErrorBoundary component
|
|
113
|
-
- Pass fallback component to ErrorBoundary
|
|
114
|
-
|
|
115
|
-
**INCORRECT**: No error boundary
|
|
116
|
-
- Don't export screens without error boundary wrapper
|
|
117
|
-
- Never let errors crash entire application
|
|
118
|
-
- Don't assume components will never throw errors
|
|
119
|
-
|
|
120
|
-
## AI Agent Guidelines
|
|
121
|
-
|
|
122
|
-
### When Building Presentation Layer
|
|
123
|
-
|
|
124
|
-
1. **Always** use hooks for data fetching and state management
|
|
125
|
-
2. **Always** handle loading and error states
|
|
126
|
-
3. **Always** provide user feedback for actions
|
|
127
|
-
4. **Always** implement error boundaries
|
|
128
|
-
5. **Never** include business logic in components
|
|
129
|
-
|
|
130
|
-
### Integration Checklist
|
|
131
|
-
|
|
132
|
-
- [ ] Use appropriate hooks for data access
|
|
133
|
-
- [ ] Handle loading states
|
|
134
|
-
- [ ] Handle error states
|
|
135
|
-
- [ ] Implement error boundaries
|
|
136
|
-
- [ ] Provide user feedback
|
|
137
|
-
- [ ] Test with various data states
|
|
138
|
-
- [ ] Test error scenarios
|
|
139
|
-
- [ ] Ensure type safety
|
|
140
|
-
- [ ] Use localization for all strings
|
|
141
|
-
- [ ] Test accessibility
|
|
142
|
-
|
|
143
|
-
### Common Patterns
|
|
144
|
-
|
|
145
|
-
1. **Compound Components**: Build complex UIs from simple components
|
|
146
|
-
2. **Render Props**: Share stateful logic between components
|
|
147
|
-
3. **Custom Hooks**: Extract reusable stateful logic
|
|
148
|
-
4. **Error Boundaries**: Prevent crashes from propagating
|
|
149
|
-
5. **Loading Skeletons**: Show placeholder during loading
|
|
150
|
-
6. **Optimistic Updates**: Update UI immediately, rollback on failure
|
|
151
|
-
7. **Graceful Degradation**: Show limited version on error
|
|
152
|
-
8. **Responsive Design**: Support different screen sizes
|
|
153
|
-
|
|
154
|
-
## Related Documentation
|
|
155
|
-
|
|
156
|
-
- **Hooks**: `hooks/README.md`
|
|
157
|
-
- **Components**: `components/README.md`
|
|
158
|
-
- **Screens**: `screens/README.md`
|
|
159
|
-
- **Wallet Domain**: `../../domains/wallet/README.md`
|
|
160
|
-
- **Paywall Domain**: `../../domains/paywall/README.md`
|
|
161
|
-
- **RevenueCat**: `../../revenuecat/README.md`
|
|
162
|
-
|
|
163
|
-
## Directory Structure
|
|
164
|
-
|
|
165
|
-
The presentation layer contains:
|
|
166
|
-
- **hooks/** - React hooks for state management (usePremium, useSubscription, useCredits, useDeductCredit, useFeatureGate)
|
|
167
|
-
- **components/** - UI components organized by functionality
|
|
168
|
-
- **details/** - Detail cards, badges
|
|
169
|
-
- **feedback/** - Modals, feedback components
|
|
170
|
-
- **sections/** - Section components
|
|
171
|
-
- **paywall/** - Paywall components
|
|
172
|
-
- **screens/** - Full-screen components (SubscriptionDetailScreen)
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
# Presentation Components
|
|
2
|
-
|
|
3
|
-
React Native UI components for subscription and paywall features.
|
|
4
|
-
|
|
5
|
-
## Location
|
|
6
|
-
|
|
7
|
-
**Directory**: `src/presentation/components/`
|
|
8
|
-
|
|
9
|
-
**Type**: Component Library
|
|
10
|
-
|
|
11
|
-
## Strategy
|
|
12
|
-
|
|
13
|
-
### Component Categories
|
|
14
|
-
|
|
15
|
-
Components are organized by functionality:
|
|
16
|
-
|
|
17
|
-
1. **Details Components**
|
|
18
|
-
- CreditRow: Display credit balance and info
|
|
19
|
-
- DetailRow: Generic detail display row
|
|
20
|
-
- PremiumStatusBadge: Visual premium indicator
|
|
21
|
-
- PremiumDetailsCard: Premium subscription details
|
|
22
|
-
|
|
23
|
-
2. **Feedback Components**
|
|
24
|
-
- PaywallFeedbackModal: User feedback collection
|
|
25
|
-
- Alert components: Warning and info displays
|
|
26
|
-
|
|
27
|
-
3. **Section Components**
|
|
28
|
-
- SubscriptionSection: Subscription info section
|
|
29
|
-
- CreditsSection: Credits balance section
|
|
30
|
-
|
|
31
|
-
4. **Paywall Components**
|
|
32
|
-
- PaywallModal: Upgrade/purchase modal
|
|
33
|
-
- Purchase options: Subscription and credit packages
|
|
34
|
-
|
|
35
|
-
### Design Principles
|
|
36
|
-
|
|
37
|
-
All components follow these principles:
|
|
38
|
-
- **Reusable**: Composable and configurable
|
|
39
|
-
- **Typed**: Full TypeScript support
|
|
40
|
-
- **Accessible**: WCAG compliant where possible
|
|
41
|
-
- **Testable**: Easy to test in isolation
|
|
42
|
-
- **Themeable**: Support custom styling
|
|
43
|
-
|
|
44
|
-
### Integration Points
|
|
45
|
-
|
|
46
|
-
- **React Native**: Core UI framework
|
|
47
|
-
- **Design System**: Shared UI components
|
|
48
|
-
- **Localization**: i18n string support
|
|
49
|
-
- **Theme**: Custom styling support
|
|
50
|
-
|
|
51
|
-
## Restrictions
|
|
52
|
-
|
|
53
|
-
### REQUIRED
|
|
54
|
-
|
|
55
|
-
- **Props Typing**: All components MUST have TypeScript interfaces
|
|
56
|
-
- **Default Props**: MUST provide sensible defaults
|
|
57
|
-
- **Accessibility**: MUST implement accessibility labels
|
|
58
|
-
- **Responsive**: MUST handle different screen sizes
|
|
59
|
-
|
|
60
|
-
### PROHIBITED
|
|
61
|
-
|
|
62
|
-
- **NEVER** hardcode colors or sizes (use theme)
|
|
63
|
-
- **NEVER** include business logic in components
|
|
64
|
-
- **DO NOT** make direct API calls
|
|
65
|
-
- **NEVER** hardcode strings (use localization)
|
|
66
|
-
|
|
67
|
-
### CRITICAL SAFETY
|
|
68
|
-
|
|
69
|
-
- **ALWAYS** validate props before rendering
|
|
70
|
-
- **ALWAYS** handle loading and error states
|
|
71
|
-
- **NEVER** trust user input for security decisions
|
|
72
|
-
- **MUST** implement proper error boundaries
|
|
73
|
-
- **ALWAYS** sanitize user-provided content
|
|
74
|
-
|
|
75
|
-
## Rules
|
|
76
|
-
|
|
77
|
-
### Component Structure
|
|
78
|
-
|
|
79
|
-
**CORRECT**: Proper component structure
|
|
80
|
-
- Define TypeScript interface for component props
|
|
81
|
-
- List all required props (amount, isLoading, onPress)
|
|
82
|
-
- List optional props with question marks
|
|
83
|
-
- Destructure props in function signature
|
|
84
|
-
- Check loading state and return SkeletonLoader
|
|
85
|
-
- Render TouchableOpacity with conditional disabled
|
|
86
|
-
- Display text content
|
|
87
|
-
|
|
88
|
-
**INCORRECT**: No props interface
|
|
89
|
-
- Don't create components without TypeScript interfaces
|
|
90
|
-
- Never omit type definitions for props
|
|
91
|
-
- Don't use any type or skip type checking
|
|
92
|
-
|
|
93
|
-
### Theme Usage
|
|
94
|
-
|
|
95
|
-
**CORRECT**: Use theme for styling
|
|
96
|
-
- Import and use useTheme hook
|
|
97
|
-
- Access colors from theme object
|
|
98
|
-
- Apply theme colors to styles
|
|
99
|
-
- Use semantic color names (primary, onPrimary)
|
|
100
|
-
|
|
101
|
-
**INCORRECT**: Hardcoded colors
|
|
102
|
-
- Don't use hex color codes directly in styles
|
|
103
|
-
- Never hardcode values like '#007AFF' or '#FFFFFF'
|
|
104
|
-
- Don't skip theme integration
|
|
105
|
-
- Avoid inline color values
|
|
106
|
-
|
|
107
|
-
### Accessibility
|
|
108
|
-
|
|
109
|
-
**CORRECT**: Accessibility support
|
|
110
|
-
- Define accessibilityLabel prop for Button
|
|
111
|
-
- Define accessibilityHint for additional context
|
|
112
|
-
- Set accessibilityState with disabled condition
|
|
113
|
-
- Provide clear, descriptive labels
|
|
114
|
-
- Include hints for complex interactions
|
|
115
|
-
|
|
116
|
-
**INCORRECT**: No accessibility
|
|
117
|
-
- Don't create components without a11y labels
|
|
118
|
-
- Never skip accessibilityHint for complex UI
|
|
119
|
-
- Don't omit accessibilityState for interactive elements
|
|
120
|
-
- Avoid non-descriptive labels
|
|
121
|
-
|
|
122
|
-
### Conditional Rendering
|
|
123
|
-
|
|
124
|
-
**CORRECT**: Handle all states
|
|
125
|
-
- Check if loading and return SkeletonLoader
|
|
126
|
-
- Check if error and return ErrorDisplay
|
|
127
|
-
- Check if credits is undefined and return Placeholder
|
|
128
|
-
- Render content only when all states are valid
|
|
129
|
-
- Handle all possible state combinations
|
|
130
|
-
|
|
131
|
-
**INCORRECT**: Incomplete state handling
|
|
132
|
-
- Don't render content without checking error state
|
|
133
|
-
- Never assume data is always defined
|
|
134
|
-
- Don't skip placeholder for undefined data
|
|
135
|
-
- Avoid incomplete conditional chains
|
|
136
|
-
|
|
137
|
-
## AI Agent Guidelines
|
|
138
|
-
|
|
139
|
-
### When Building Components
|
|
140
|
-
|
|
141
|
-
1. **Always** define TypeScript interfaces for props
|
|
142
|
-
2. **Always** use theme for styling (no hardcoded values)
|
|
143
|
-
3. **Always** implement accessibility labels
|
|
144
|
-
4. **Always** handle loading and error states
|
|
145
|
-
5. **Never** include business logic in components
|
|
146
|
-
|
|
147
|
-
### Integration Checklist
|
|
148
|
-
|
|
149
|
-
- [ ] Define TypeScript interface for props
|
|
150
|
-
- [ ] Use theme for all styling
|
|
151
|
-
- [ ] Implement accessibility labels
|
|
152
|
-
- [ ] Handle loading state
|
|
153
|
-
- [ ] Handle error state
|
|
154
|
-
- [ ] Provide sensible defaults
|
|
155
|
-
- [ ] Test with different screen sizes
|
|
156
|
-
- [ ] Test accessibility
|
|
157
|
-
- [ ] Test with various prop combinations
|
|
158
|
-
- [ ] Document component usage
|
|
159
|
-
|
|
160
|
-
### Common Patterns
|
|
161
|
-
|
|
162
|
-
1. **Compound Components**: Build complex UIs from simple parts
|
|
163
|
-
2. **Render Props**: Share stateful logic
|
|
164
|
-
3. **Slot Pattern**: Allow content injection
|
|
165
|
-
4. **Control Props**: Make components controlled or uncontrolled
|
|
166
|
-
5. **Asynchronous States**: Handle loading, error, success states
|
|
167
|
-
6. **Responsive Design**: Adapt to different screen sizes
|
|
168
|
-
7. **Theme Integration**: Use design system tokens
|
|
169
|
-
8. **Accessibility First**: Include a11y from the start
|
|
170
|
-
|
|
171
|
-
## Related Documentation
|
|
172
|
-
|
|
173
|
-
- **Details Components**: `details/README.md`
|
|
174
|
-
- **Feedback Components**: `feedback/README.md`
|
|
175
|
-
- **Section Components**: `sections/README.md`
|
|
176
|
-
- **Paywall Components**: `paywall/README.md`
|
|
177
|
-
- **Design System**: External design system documentation
|
|
178
|
-
- **Hooks**: `../hooks/README.md`
|
|
179
|
-
|
|
180
|
-
## Component Examples
|
|
181
|
-
|
|
182
|
-
### CreditRow
|
|
183
|
-
|
|
184
|
-
Display user's credit balance with optional actions.
|
|
185
|
-
|
|
186
|
-
Usage:
|
|
187
|
-
- Set amount prop to number of credits
|
|
188
|
-
- Set isLoading to true during data fetch
|
|
189
|
-
- Provide onPress callback for navigation
|
|
190
|
-
- Component displays credit count and handles tap
|
|
191
|
-
|
|
192
|
-
### PremiumStatusBadge
|
|
193
|
-
|
|
194
|
-
Visual indicator for premium subscription status.
|
|
195
|
-
|
|
196
|
-
Usage:
|
|
197
|
-
- Set isPremium to boolean status
|
|
198
|
-
- Set tier to subscription level (gold, silver, etc.)
|
|
199
|
-
- Component renders styled badge
|
|
200
|
-
|
|
201
|
-
### PaywallModal
|
|
202
|
-
|
|
203
|
-
Modal for subscription and credit purchase.
|
|
204
|
-
|
|
205
|
-
Usage:
|
|
206
|
-
- Set isVisible to boolean for show/hide
|
|
207
|
-
- Provide onClose callback
|
|
208
|
-
- Pass features array for premium features list
|
|
209
|
-
- Modal handles purchase flow
|
|
210
|
-
|
|
211
|
-
## Directory Structure
|
|
212
|
-
|
|
213
|
-
The components directory contains:
|
|
214
|
-
- **details/** - Detail display components (CreditRow, DetailRow, PremiumStatusBadge, PremiumDetailsCard)
|
|
215
|
-
- **feedback/** - Feedback and alert components (PaywallFeedbackModal)
|
|
216
|
-
- **sections/** - Section components (SubscriptionSection)
|
|
217
|
-
- **paywall/** - Paywall components (PaywallModal)
|
|
@@ -1,231 +0,0 @@
|
|
|
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`
|