@propel-nsl/propel-react-native-sdk 1.0.0 → 1.0.2
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/CLIENT_INTEGRATION_GUIDE.md +499 -0
- package/README.md +36 -0
- package/RN_HOST_INTEGRATION.md +152 -0
- package/package.json +7 -3
- package/src/screens/Profile/index.tsx +0 -6
- package/src-app/services/index.ts +17 -13
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
# Propel SDK Integration Guide for Clients
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The Propel SDK is a comprehensive React Native library that enables seamless integration of reward and redemption functionality into your mobile application. This guide provides step-by-step instructions for integrating the SDK into your React Native project.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
- React Native version 0.72.0 or higher
|
|
10
|
+
- React version 18.0.0 or higher
|
|
11
|
+
- Node.js version 18 or higher
|
|
12
|
+
- iOS deployment target: iOS 12.0 or higher
|
|
13
|
+
- Android API Level: 21 or higher
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### 1. Installation
|
|
18
|
+
|
|
19
|
+
Install the Propel SDK package from npm:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @propel-nsl/propel-react-native-sdk
|
|
23
|
+
# or
|
|
24
|
+
yarn add @propel-nsl/propel-react-native-sdk
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 2. Required Dependencies
|
|
28
|
+
|
|
29
|
+
Install all required peer dependencies:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install @react-native-async-storage/async-storage \
|
|
33
|
+
@react-native-community/netinfo \
|
|
34
|
+
@react-navigation/native \
|
|
35
|
+
@react-navigation/stack \
|
|
36
|
+
@react-navigation/bottom-tabs \
|
|
37
|
+
@reduxjs/toolkit \
|
|
38
|
+
react-redux \
|
|
39
|
+
redux-saga \
|
|
40
|
+
react-native-gesture-handler \
|
|
41
|
+
react-native-reanimated \
|
|
42
|
+
react-native-safe-area-context \
|
|
43
|
+
react-native-screens \
|
|
44
|
+
react-native-device-info \
|
|
45
|
+
react-native-svg \
|
|
46
|
+
react-native-toast-message
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 3. Optional Dependencies
|
|
50
|
+
|
|
51
|
+
For enhanced functionality, install these optional dependencies:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npm install @react-native-clipboard/clipboard \
|
|
55
|
+
@react-native-community/masked-view \
|
|
56
|
+
react-native-fast-image \
|
|
57
|
+
react-native-image-picker \
|
|
58
|
+
react-native-permissions \
|
|
59
|
+
react-native-size-matters \
|
|
60
|
+
react-native-render-html \
|
|
61
|
+
react-native-otp-entry \
|
|
62
|
+
react-native-keyboard-aware-scroll-view \
|
|
63
|
+
react-native-country-picker-modal \
|
|
64
|
+
formik \
|
|
65
|
+
yup \
|
|
66
|
+
buffer
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 4. Metro Configuration
|
|
70
|
+
|
|
71
|
+
Update your `metro.config.js` file to properly resolve the SDK modules:
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
|
|
75
|
+
const path = require('path');
|
|
76
|
+
const exclusionList = require('metro-config/src/defaults/exclusionList');
|
|
77
|
+
|
|
78
|
+
// SDK installation path
|
|
79
|
+
const sdkRoot = path.resolve(
|
|
80
|
+
__dirname, 'node_modules/@propel-nsl/propel-react-native-sdk'
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// Axios ESM browser build path
|
|
84
|
+
const axiosEsm = path.resolve(__dirname, 'node_modules/axios/dist/esm/axios.js');
|
|
85
|
+
|
|
86
|
+
const config = {
|
|
87
|
+
projectRoot: __dirname,
|
|
88
|
+
watchFolders: [sdkRoot],
|
|
89
|
+
resolver: {
|
|
90
|
+
blockList: exclusionList([
|
|
91
|
+
/.*\/axios\/dist\/node\/.*/,
|
|
92
|
+
]),
|
|
93
|
+
resolveRequest: (context, moduleName, platform) => {
|
|
94
|
+
if (moduleName === 'axios' || moduleName === 'axios/lib/axios') {
|
|
95
|
+
return {
|
|
96
|
+
filePath: axiosEsm,
|
|
97
|
+
type: 'sourceFile',
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return context.resolveRequest(context, moduleName, platform);
|
|
101
|
+
},
|
|
102
|
+
extraNodeModules: {
|
|
103
|
+
'src-app': path.resolve(sdkRoot, 'src-app'),
|
|
104
|
+
react: path.resolve(__dirname, 'node_modules/react'),
|
|
105
|
+
'react-native': path.resolve(__dirname, 'node_modules/react-native'),
|
|
106
|
+
'react-redux': path.resolve(__dirname, 'node_modules/react-redux'),
|
|
107
|
+
'@reduxjs/toolkit': path.resolve(__dirname, 'node_modules/@reduxjs/toolkit'),
|
|
108
|
+
'@react-navigation/native': path.resolve(__dirname, 'node_modules/@react-navigation/native'),
|
|
109
|
+
'@react-navigation/stack': path.resolve(__dirname, 'node_modules/@react-navigation/stack'),
|
|
110
|
+
'@react-navigation/bottom-tabs': path.resolve(__dirname, 'node_modules/@react-navigation/bottom-tabs'),
|
|
111
|
+
'react-native-gesture-handler': path.resolve(__dirname, 'node_modules/react-native-gesture-handler'),
|
|
112
|
+
'react-native-reanimated': path.resolve(__dirname, 'node_modules/react-native-reanimated'),
|
|
113
|
+
'react-native-screens': path.resolve(__dirname, 'node_modules/react-native-screens'),
|
|
114
|
+
'react-native-safe-area-context': path.resolve(__dirname, 'node_modules/react-native-safe-area-context'),
|
|
115
|
+
'react-native-svg': path.resolve(__dirname, 'node_modules/react-native-svg'),
|
|
116
|
+
'react-native-fast-image': path.resolve(__dirname, 'node_modules/react-native-fast-image'),
|
|
117
|
+
'@react-native-async-storage/async-storage': path.resolve(__dirname, 'node_modules/@react-native-async-storage/async-storage'),
|
|
118
|
+
'@react-native-community/netinfo': path.resolve(__dirname, 'node_modules/@react-native-community/netinfo'),
|
|
119
|
+
'@react-native-clipboard/clipboard': path.resolve(__dirname, 'node_modules/@react-native-clipboard/clipboard'),
|
|
120
|
+
'@react-native-community/masked-view': path.resolve(__dirname, 'node_modules/@react-native-community/masked-view'),
|
|
121
|
+
'react-native-toast-message': path.resolve(__dirname, 'node_modules/react-native-toast-message'),
|
|
122
|
+
'react-native-device-info': path.resolve(__dirname, 'node_modules/react-native-device-info'),
|
|
123
|
+
'react-native-image-picker': path.resolve(__dirname, 'node_modules/react-native-image-picker'),
|
|
124
|
+
'react-native-permissions': path.resolve(__dirname, 'node_modules/react-native-permissions'),
|
|
125
|
+
'redux-saga': path.resolve(__dirname, 'node_modules/redux-saga'),
|
|
126
|
+
axios: axiosEsm,
|
|
127
|
+
buffer: path.resolve(__dirname, 'node_modules/buffer'),
|
|
128
|
+
formik: path.resolve(__dirname, 'node_modules/formik'),
|
|
129
|
+
yup: path.resolve(__dirname, 'node_modules/yup'),
|
|
130
|
+
'react-native-size-matters': path.resolve(__dirname, 'node_modules/react-native-size-matters'),
|
|
131
|
+
'react-native-render-html': path.resolve(__dirname, 'node_modules/react-native-render-html'),
|
|
132
|
+
'react-native-otp-entry': path.resolve(__dirname, 'node_modules/react-native-otp-entry'),
|
|
133
|
+
'react-native-keyboard-aware-scroll-view': path.resolve(__dirname, 'node_modules/react-native-keyboard-aware-scroll-view'),
|
|
134
|
+
'react-native-country-picker-modal': path.resolve(__dirname, 'node_modules/react-native-country-picker-modal'),
|
|
135
|
+
},
|
|
136
|
+
nodeModulesPaths: [
|
|
137
|
+
path.resolve(__dirname, 'node_modules'),
|
|
138
|
+
],
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
module.exports = mergeConfig(getDefaultConfig(__dirname), config);
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### 5. iOS Setup
|
|
146
|
+
|
|
147
|
+
After installing dependencies, run:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
cd ios && pod install && cd ..
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Integration Steps
|
|
154
|
+
|
|
155
|
+
### Step 1: Configure Navigation
|
|
156
|
+
|
|
157
|
+
Set up your app navigation to include the Propel SDK screen:
|
|
158
|
+
|
|
159
|
+
```tsx
|
|
160
|
+
import React from 'react';
|
|
161
|
+
import { NavigationContainer } from '@react-navigation/native';
|
|
162
|
+
import { createStackNavigator } from '@react-navigation/stack';
|
|
163
|
+
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
|
164
|
+
import { PropelSDKScreen } from '@propel-nsl/propel-react-native-sdk';
|
|
165
|
+
|
|
166
|
+
export type RootStackParamList = {
|
|
167
|
+
Home: undefined;
|
|
168
|
+
PropelSDK: {
|
|
169
|
+
screen: string;
|
|
170
|
+
authToken: string;
|
|
171
|
+
authId: string;
|
|
172
|
+
apiUrl?: string;
|
|
173
|
+
userId?: string;
|
|
174
|
+
userName?: string;
|
|
175
|
+
userMobile?: string;
|
|
176
|
+
userEmail?: string;
|
|
177
|
+
deviceId?: string;
|
|
178
|
+
clientName?: string;
|
|
179
|
+
clientVersion?: string;
|
|
180
|
+
environment?: 'development' | 'staging' | 'production';
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const Stack = createStackNavigator<RootStackParamList>();
|
|
185
|
+
|
|
186
|
+
function App() {
|
|
187
|
+
return (
|
|
188
|
+
<SafeAreaProvider>
|
|
189
|
+
<NavigationContainer>
|
|
190
|
+
<Stack.Navigator
|
|
191
|
+
screenOptions={{ headerShown: false, gestureEnabled: false }}
|
|
192
|
+
>
|
|
193
|
+
<Stack.Screen name="Home" component={HomeScreen} />
|
|
194
|
+
<Stack.Screen
|
|
195
|
+
name="PropelSDK"
|
|
196
|
+
component={PropelSDKScreen}
|
|
197
|
+
options={{
|
|
198
|
+
gestureEnabled: false,
|
|
199
|
+
animationEnabled: true,
|
|
200
|
+
}}
|
|
201
|
+
/>
|
|
202
|
+
</Stack.Navigator>
|
|
203
|
+
</NavigationContainer>
|
|
204
|
+
</SafeAreaProvider>
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Step 2: Create Navigation Function
|
|
210
|
+
|
|
211
|
+
Create a function to navigate to the SDK with proper parameters:
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
import { StackNavigationProp } from '@react-navigation/stack';
|
|
215
|
+
import type { RootStackParamList } from './App';
|
|
216
|
+
|
|
217
|
+
type NavigationProp = StackNavigationProp<RootStackParamList, 'Home'>;
|
|
218
|
+
|
|
219
|
+
interface SDKNavigationParams {
|
|
220
|
+
screen: 'dashboard' | 'redeem' | 'redemption-history';
|
|
221
|
+
authToken: string;
|
|
222
|
+
authId: string;
|
|
223
|
+
apiUrl?: string;
|
|
224
|
+
environment?: 'development' | 'staging' | 'production';
|
|
225
|
+
userId?: string;
|
|
226
|
+
userName?: string;
|
|
227
|
+
userMobile?: string;
|
|
228
|
+
userEmail?: string;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const openPropelSDK = (
|
|
232
|
+
navigation: NavigationProp,
|
|
233
|
+
params: SDKNavigationParams
|
|
234
|
+
) => {
|
|
235
|
+
navigation.navigate('PropelSDK', {
|
|
236
|
+
screen: params.screen,
|
|
237
|
+
authToken: params.authToken,
|
|
238
|
+
authId: params.authId,
|
|
239
|
+
apiUrl: params.apiUrl || 'https://api.propel.com',
|
|
240
|
+
environment: params.environment || 'production',
|
|
241
|
+
userId: params.userId,
|
|
242
|
+
userName: params.userName,
|
|
243
|
+
userMobile: params.userMobile,
|
|
244
|
+
userEmail: params.userEmail,
|
|
245
|
+
});
|
|
246
|
+
};
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Step 3: Implement SDK Launch
|
|
250
|
+
|
|
251
|
+
Add buttons or triggers to launch the SDK:
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
import React from 'react';
|
|
255
|
+
import { TouchableOpacity, Text, StyleSheet, View } from 'react-native';
|
|
256
|
+
|
|
257
|
+
const LaunchButtons: React.FC<{ navigation: NavigationProp }> = ({ navigation }) => {
|
|
258
|
+
const handleOpenDashboard = () => {
|
|
259
|
+
openPropelSDK(navigation, {
|
|
260
|
+
screen: 'dashboard',
|
|
261
|
+
authToken: 'YOUR_AUTH_TOKEN',
|
|
262
|
+
authId: 'YOUR_AUTH_ID',
|
|
263
|
+
environment: 'production',
|
|
264
|
+
});
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const handleOpenRedeem = () => {
|
|
268
|
+
openPropelSDK(navigation, {
|
|
269
|
+
screen: 'redeem',
|
|
270
|
+
authToken: 'YOUR_AUTH_TOKEN',
|
|
271
|
+
authId: 'YOUR_AUTH_ID',
|
|
272
|
+
environment: 'production',
|
|
273
|
+
});
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const handleOpenHistory = () => {
|
|
277
|
+
openPropelSDK(navigation, {
|
|
278
|
+
screen: 'redemption-history',
|
|
279
|
+
authToken: 'YOUR_AUTH_TOKEN',
|
|
280
|
+
authId: 'YOUR_AUTH_ID',
|
|
281
|
+
environment: 'production',
|
|
282
|
+
});
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
return (
|
|
286
|
+
<View style={styles.container}>
|
|
287
|
+
<TouchableOpacity style={styles.button} onPress={handleOpenDashboard}>
|
|
288
|
+
<Text style={styles.buttonText}>Open Dashboard</Text>
|
|
289
|
+
</TouchableOpacity>
|
|
290
|
+
|
|
291
|
+
<TouchableOpacity style={styles.button} onPress={handleOpenRedeem}>
|
|
292
|
+
<Text style={styles.buttonText}>Redeem Rewards</Text>
|
|
293
|
+
</TouchableOpacity>
|
|
294
|
+
|
|
295
|
+
<TouchableOpacity style={styles.button} onPress={handleOpenHistory}>
|
|
296
|
+
<Text style={styles.buttonText}>View History</Text>
|
|
297
|
+
</TouchableOpacity>
|
|
298
|
+
</View>
|
|
299
|
+
);
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
const styles = StyleSheet.create({
|
|
303
|
+
container: {
|
|
304
|
+
padding: 20,
|
|
305
|
+
gap: 10,
|
|
306
|
+
},
|
|
307
|
+
button: {
|
|
308
|
+
backgroundColor: '#007AFF',
|
|
309
|
+
padding: 15,
|
|
310
|
+
borderRadius: 8,
|
|
311
|
+
alignItems: 'center',
|
|
312
|
+
},
|
|
313
|
+
buttonText: {
|
|
314
|
+
color: 'white',
|
|
315
|
+
fontSize: 16,
|
|
316
|
+
fontWeight: '600',
|
|
317
|
+
},
|
|
318
|
+
});
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## Configuration Parameters
|
|
322
|
+
|
|
323
|
+
### Required Parameters
|
|
324
|
+
|
|
325
|
+
| Parameter | Type | Description |
|
|
326
|
+
|-----------|------|-------------|
|
|
327
|
+
| `screen` | string | Target screen: `dashboard`, `redeem`, or `redemption-history` |
|
|
328
|
+
| `authToken` | string | Authentication token provided by Propel |
|
|
329
|
+
| `authId` | string | Authentication ID provided by Propel |
|
|
330
|
+
|
|
331
|
+
### Optional Parameters
|
|
332
|
+
|
|
333
|
+
| Parameter | Type | Description |
|
|
334
|
+
|-----------|------|-------------|
|
|
335
|
+
| `apiUrl` | string | Custom API endpoint URL |
|
|
336
|
+
| `environment` | string | Environment: `development`, `staging`, or `production` |
|
|
337
|
+
| `userId` | string | Your application's user identifier |
|
|
338
|
+
| `userName` | string | User's display name |
|
|
339
|
+
| `userMobile` | string | User's mobile number |
|
|
340
|
+
| `userEmail` | string | User's email address |
|
|
341
|
+
| `deviceId` | string | Device identifier |
|
|
342
|
+
| `clientName` | string | Your application name |
|
|
343
|
+
| `clientVersion` | string | Your application version |
|
|
344
|
+
|
|
345
|
+
## Available Screens
|
|
346
|
+
|
|
347
|
+
### Dashboard
|
|
348
|
+
- **Purpose**: Main landing screen showing user rewards overview
|
|
349
|
+
- **Screen Value**: `dashboard`
|
|
350
|
+
|
|
351
|
+
### Redeem
|
|
352
|
+
- **Purpose**: Screen for redeeming available rewards
|
|
353
|
+
- **Screen Value**: `redeem`
|
|
354
|
+
|
|
355
|
+
### Redemption History
|
|
356
|
+
- **Purpose**: Screen showing transaction and redemption history
|
|
357
|
+
- **Screen Value**: `redemption-history`
|
|
358
|
+
|
|
359
|
+
## Authentication
|
|
360
|
+
|
|
361
|
+
The Propel SDK handles authentication internally using the provided `authToken` and `authId`. These credentials will be provided to you by Propel during the onboarding process.
|
|
362
|
+
|
|
363
|
+
### Authentication Flow
|
|
364
|
+
1. SDK receives authentication credentials
|
|
365
|
+
2. Validates credentials with Propel API
|
|
366
|
+
3. Establishes secure session
|
|
367
|
+
4. Provides access to requested functionality
|
|
368
|
+
|
|
369
|
+
## Environment Configuration
|
|
370
|
+
|
|
371
|
+
### Production
|
|
372
|
+
```tsx
|
|
373
|
+
openPropelSDK(navigation, {
|
|
374
|
+
screen: 'dashboard',
|
|
375
|
+
authToken: 'PRODUCTION_AUTH_TOKEN',
|
|
376
|
+
authId: 'PRODUCTION_AUTH_ID',
|
|
377
|
+
environment: 'production',
|
|
378
|
+
apiUrl: 'https://api.propel.com'
|
|
379
|
+
});
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Staging
|
|
383
|
+
```tsx
|
|
384
|
+
openPropelSDK(navigation, {
|
|
385
|
+
screen: 'dashboard',
|
|
386
|
+
authToken: 'STAGING_AUTH_TOKEN',
|
|
387
|
+
authId: 'STAGING_AUTH_ID',
|
|
388
|
+
environment: 'staging',
|
|
389
|
+
apiUrl: 'https://staging-api.propel.com'
|
|
390
|
+
});
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Development
|
|
394
|
+
```tsx
|
|
395
|
+
openPropelSDK(navigation, {
|
|
396
|
+
screen: 'dashboard',
|
|
397
|
+
authToken: 'DEV_AUTH_TOKEN',
|
|
398
|
+
authId: 'DEV_AUTH_ID',
|
|
399
|
+
environment: 'development',
|
|
400
|
+
apiUrl: 'https://dev-api.propel.com'
|
|
401
|
+
});
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Best Practices
|
|
405
|
+
|
|
406
|
+
### 1. Secure Credential Management
|
|
407
|
+
- Store authentication credentials securely
|
|
408
|
+
- Use environment variables for different environments
|
|
409
|
+
- Never hard-code credentials in your application
|
|
410
|
+
|
|
411
|
+
### 2. Error Handling
|
|
412
|
+
```tsx
|
|
413
|
+
const handleOpenSDK = async (screen: string) => {
|
|
414
|
+
try {
|
|
415
|
+
if (!authToken || !authId) {
|
|
416
|
+
Alert.alert('Error', 'Missing authentication credentials');
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
openPropelSDK(navigation, {
|
|
421
|
+
screen: screen as any,
|
|
422
|
+
authToken,
|
|
423
|
+
authId,
|
|
424
|
+
environment: 'production',
|
|
425
|
+
});
|
|
426
|
+
} catch (error) {
|
|
427
|
+
console.error('Failed to open Propel SDK:', error);
|
|
428
|
+
Alert.alert('Error', 'Unable to open rewards portal');
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### 3. User Experience
|
|
434
|
+
- Provide clear loading states during SDK initialization
|
|
435
|
+
- Handle network connectivity issues gracefully
|
|
436
|
+
- Offer retry mechanisms for failed operations
|
|
437
|
+
|
|
438
|
+
### 4. Performance Optimization
|
|
439
|
+
- Pre-load SDK data when possible
|
|
440
|
+
- Cache user information to reduce API calls
|
|
441
|
+
- Optimize images and assets for mobile devices
|
|
442
|
+
|
|
443
|
+
## Troubleshooting
|
|
444
|
+
|
|
445
|
+
### Common Issues
|
|
446
|
+
|
|
447
|
+
1. **Metro Bundler Errors**
|
|
448
|
+
- Ensure metro.config.js is properly configured
|
|
449
|
+
- Clear Metro cache: `npx react-native start --reset-cache`
|
|
450
|
+
|
|
451
|
+
2. **iOS Build Issues**
|
|
452
|
+
- Run `pod install` in iOS directory
|
|
453
|
+
- Clean build folder in Xcode
|
|
454
|
+
|
|
455
|
+
3. **Navigation Not Working**
|
|
456
|
+
- Verify screen names match exactly
|
|
457
|
+
- Check TypeScript types for parameter validation
|
|
458
|
+
|
|
459
|
+
4. **Authentication Failures**
|
|
460
|
+
- Validate authToken and authId are correct
|
|
461
|
+
- Check network connectivity to API endpoint
|
|
462
|
+
|
|
463
|
+
### Debug Mode
|
|
464
|
+
|
|
465
|
+
Enable debug logging for development:
|
|
466
|
+
|
|
467
|
+
```tsx
|
|
468
|
+
openPropelSDK(navigation, {
|
|
469
|
+
screen: 'dashboard',
|
|
470
|
+
authToken,
|
|
471
|
+
authId,
|
|
472
|
+
environment: 'development', // Enables debug logging
|
|
473
|
+
});
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
## Support
|
|
477
|
+
|
|
478
|
+
For technical support and integration assistance:
|
|
479
|
+
|
|
480
|
+
1. **Documentation**: Refer to this guide and inline code comments
|
|
481
|
+
2. **Debug Logs**: Enable debug mode and check console logs
|
|
482
|
+
3. **Contact**: Reach out to your Propel technical contact
|
|
483
|
+
|
|
484
|
+
## Version Information
|
|
485
|
+
|
|
486
|
+
- **Current SDK Version**: 1.0.0
|
|
487
|
+
- **React Native Compatibility**: >= 0.72.0
|
|
488
|
+
- **React Compatibility**: >= 18.0.0
|
|
489
|
+
- **iOS Compatibility**: >= 12.0
|
|
490
|
+
- **Android Compatibility**: API Level >= 21
|
|
491
|
+
|
|
492
|
+
## License
|
|
493
|
+
|
|
494
|
+
The Propel SDK is proprietary software. Usage is subject to Propel's terms of service and license agreement. Please ensure you have the appropriate licenses before integrating the SDK into your application.
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
**Last Updated**: February 2026
|
|
499
|
+
**Version**: 1.0.0
|
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Propel React Native SDK
|
|
2
|
+
|
|
3
|
+
A comprehensive React Native library for integrating Propel's reward and redemption functionality into your mobile application.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @propel-nsl/propel-react-native-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Documentation
|
|
12
|
+
|
|
13
|
+
For complete integration instructions, please see our [Client Integration Guide](./CLIENT_INTEGRATION_GUIDE.md).
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- 🚀 Easy integration with React Native navigation
|
|
18
|
+
- 🔐 Secure authentication handling
|
|
19
|
+
- 📱 Cross-platform support (iOS & Android)
|
|
20
|
+
- 🎨 Customizable UI components
|
|
21
|
+
- 📊 Comprehensive reward management
|
|
22
|
+
- 📱 Transaction history tracking
|
|
23
|
+
|
|
24
|
+
## Requirements
|
|
25
|
+
|
|
26
|
+
- React Native >= 0.72.0
|
|
27
|
+
- React >= 18.0.0
|
|
28
|
+
- Node.js >= 18
|
|
29
|
+
|
|
30
|
+
## License
|
|
31
|
+
|
|
32
|
+
Proprietary software. See license agreement for usage terms.
|
|
33
|
+
|
|
34
|
+
## Support
|
|
35
|
+
|
|
36
|
+
For technical support, please refer to the [Client Integration Guide](./CLIENT_INTEGRATION_GUIDE.md) or contact your Propel technical representative.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Propel SDK — React Native Host App Integration Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
When the host app is also a React Native app, the SDK is consumed as an **npm package** (`@propel-nsl/propel-react-native-sdk`). The host app imports `PropelSDKScreen` and adds it to its navigation tree. No native bridge modules are needed.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
### 1. Install the SDK package
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @propel-nsl/propel-react-native-sdk
|
|
13
|
+
# or
|
|
14
|
+
yarn add @propel-nsl/propel-react-native-sdk
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### 2. Install peer dependencies
|
|
18
|
+
|
|
19
|
+
The SDK declares its React Native dependencies as `peerDependencies`. Your host app must have these installed:
|
|
20
|
+
|
|
21
|
+
**Required:**
|
|
22
|
+
- `react` (>=18.0.0)
|
|
23
|
+
- `react-native` (>=0.72.0)
|
|
24
|
+
- `@react-native-async-storage/async-storage`
|
|
25
|
+
- `@react-native-community/netinfo`
|
|
26
|
+
- `@react-navigation/native`, `@react-navigation/stack`, `@react-navigation/bottom-tabs`
|
|
27
|
+
- `@reduxjs/toolkit`, `react-redux`, `redux-saga`
|
|
28
|
+
- `react-native-gesture-handler`, `react-native-reanimated`
|
|
29
|
+
- `react-native-safe-area-context`, `react-native-screens`
|
|
30
|
+
- `react-native-device-info`
|
|
31
|
+
- `react-native-svg`
|
|
32
|
+
- `react-native-toast-message`
|
|
33
|
+
|
|
34
|
+
**Optional:**
|
|
35
|
+
- `@react-native-clipboard/clipboard`
|
|
36
|
+
- `@react-native-community/masked-view`
|
|
37
|
+
- `react-native-fast-image`
|
|
38
|
+
- `react-native-image-picker`
|
|
39
|
+
- `react-native-permissions`
|
|
40
|
+
|
|
41
|
+
### 3. Configure Metro
|
|
42
|
+
|
|
43
|
+
The SDK ships raw TypeScript source that Metro transpiles. Add the SDK to your `metro.config.js` so Metro can resolve its internal `src-app` alias:
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
const path = require('path');
|
|
47
|
+
const sdkRoot = path.resolve(__dirname, 'node_modules/@propel-nsl/propel-react-native-sdk');
|
|
48
|
+
|
|
49
|
+
const config = {
|
|
50
|
+
watchFolders: [
|
|
51
|
+
sdkRoot,
|
|
52
|
+
],
|
|
53
|
+
resolver: {
|
|
54
|
+
extraNodeModules: {
|
|
55
|
+
'src-app': path.resolve(sdkRoot, 'src-app'),
|
|
56
|
+
},
|
|
57
|
+
nodeModulesPaths: [
|
|
58
|
+
path.resolve(__dirname, 'node_modules'),
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 4. iOS: pod install
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
cd ios && pod install
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Usage
|
|
71
|
+
|
|
72
|
+
### Add the SDK screen to your navigator
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
import { PropelSDKScreen } from '@propel-nsl/propel-react-native-sdk';
|
|
76
|
+
|
|
77
|
+
const Stack = createStackNavigator();
|
|
78
|
+
|
|
79
|
+
function App() {
|
|
80
|
+
return (
|
|
81
|
+
<NavigationContainer>
|
|
82
|
+
<Stack.Navigator>
|
|
83
|
+
<Stack.Screen name="Home" component={HomeScreen} />
|
|
84
|
+
<Stack.Screen
|
|
85
|
+
name="PropelSDK"
|
|
86
|
+
component={PropelSDKScreen}
|
|
87
|
+
options={{ headerShown: false, gestureEnabled: false }}
|
|
88
|
+
/>
|
|
89
|
+
</Stack.Navigator>
|
|
90
|
+
</NavigationContainer>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Navigate to the SDK
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
// Open Redeem screen
|
|
99
|
+
navigation.navigate('PropelSDK', {
|
|
100
|
+
screen: 'redeem',
|
|
101
|
+
authToken: '<your-auth-token>',
|
|
102
|
+
authId: '<your-auth-id>',
|
|
103
|
+
apiUrl: 'https://staging-admin.zaggle.in',
|
|
104
|
+
environment: 'staging',
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Open Redemption History screen
|
|
108
|
+
navigation.navigate('PropelSDK', {
|
|
109
|
+
screen: 'redemption-history',
|
|
110
|
+
authToken: '<your-auth-token>',
|
|
111
|
+
authId: '<your-auth-id>',
|
|
112
|
+
apiUrl: 'https://staging-admin.zaggle.in',
|
|
113
|
+
environment: 'staging',
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Available `screen` values
|
|
118
|
+
|
|
119
|
+
| Value | Destination |
|
|
120
|
+
|---|---|
|
|
121
|
+
| `dashboard` | Dashboard / Homepage |
|
|
122
|
+
| `redeem` | Redeem |
|
|
123
|
+
| `redemption-history` | Redemption History |
|
|
124
|
+
| `transaction-history` | Redemption History (alias) |
|
|
125
|
+
|
|
126
|
+
### Full list of params
|
|
127
|
+
|
|
128
|
+
| Param | Type | Required | Description |
|
|
129
|
+
|---|---|---|---|
|
|
130
|
+
| `screen` | string | Yes | Target screen (`dashboard`, `redeem`, or `redemption-history`) |
|
|
131
|
+
| `authToken` | string | Yes | Authentication token for SDK API calls |
|
|
132
|
+
| `authId` | string | Yes | Authentication ID |
|
|
133
|
+
| `apiUrl` | string | No | Override API base URL |
|
|
134
|
+
| `userId` | string | No | User identifier |
|
|
135
|
+
| `userName` | string | No | User display name |
|
|
136
|
+
| `userMobile` | string | No | User mobile number |
|
|
137
|
+
| `userEmail` | string | No | User email |
|
|
138
|
+
| `deviceId` | string | No | Device identifier |
|
|
139
|
+
| `clientName` | string | No | Client app name |
|
|
140
|
+
| `clientVersion` | string | No | Client app version |
|
|
141
|
+
| `environment` | string | No | `development`, `staging`, or `production` |
|
|
142
|
+
| `userToken` | string | No | Pre-existing access token (skips SDK auth) |
|
|
143
|
+
|
|
144
|
+
## Architecture
|
|
145
|
+
|
|
146
|
+
- The SDK runs its **own isolated Redux store** — it does not share state with the host app.
|
|
147
|
+
- When `__rnHostMode` is detected (set automatically by `PropelSDKScreen`), the SDK skips the native bridge and reads params directly from React props.
|
|
148
|
+
- The SDK authenticates itself using `authToken` + `authId` via its internal `sdkAuthApi`, then navigates to the requested screen.
|
|
149
|
+
|
|
150
|
+
## Sample Host App
|
|
151
|
+
|
|
152
|
+
See `propel-sample-host-app-rn/` for a complete working example.
|
package/package.json
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@propel-nsl/propel-react-native-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Propel Mobile SDK - React Native Core",
|
|
5
|
-
"files": ["src/", "src-app/", "lib/", "assets/", "index.ts"],
|
|
5
|
+
"files": ["src/", "src-app/", "lib/", "assets/", "index.ts", "CLIENT_INTEGRATION_GUIDE.md", "RN_HOST_INTEGRATION.md", "README.md"],
|
|
6
6
|
"main": "index.ts",
|
|
7
7
|
"react-native": "lib/index.ts",
|
|
8
8
|
"types": "lib/index.ts",
|
|
9
|
+
"README": "CLIENT_INTEGRATION_GUIDE.md",
|
|
9
10
|
"scripts": {
|
|
10
11
|
"bundle:android": "react-native bundle --platform android --dev false --entry-file index.ts --bundle-output ../android/propelsdk/src/main/assets/index.android.bundle --assets-dest ../android/propelsdk/src/main/res --minify",
|
|
11
12
|
"bundle:ios": "react-native bundle --platform ios --dev false --entry-file index.ts --bundle-output ../ios/PropelSDK/Assets/index.ios.jsbundle --assets-dest ../ios/PropelSDK/Assets --minify",
|
|
12
13
|
"bundle:android:dev": "react-native bundle --platform android --dev true --entry-file index.ts --bundle-output ../android/propelsdk/src/main/assets/index.android.bundle --assets-dest ../android/propelsdk/src/main/res",
|
|
13
|
-
"bundle:ios:dev": "react-native bundle --platform ios --dev true --entry-file index.ts --bundle-output ../ios/PropelSDK/Assets/index.ios.jsbundle --assets-dest ../ios/PropelSDK/Assets"
|
|
14
|
+
"bundle:ios:dev": "react-native bundle --platform ios --dev true --entry-file index.ts --bundle-output ../ios/PropelSDK/Assets/index.ios.jsbundle --assets-dest ../ios/PropelSDK/Assets",
|
|
15
|
+
"prepare": "npm run build",
|
|
16
|
+
"build": "echo 'Building SDK package...' && echo 'Documentation included in package'",
|
|
17
|
+
"prepublishOnly": "echo 'Preparing to publish SDK with documentation...' && npm run build"
|
|
14
18
|
},
|
|
15
19
|
"dependencies": {
|
|
16
20
|
"@babel/runtime": "^7.28.4",
|
|
@@ -272,12 +272,6 @@ const Profile: React.FC<ProfileProps> = ({ navigation }) => {
|
|
|
272
272
|
<Text style={styles.userName}>
|
|
273
273
|
{myProfileData?.client?.employee?.name}
|
|
274
274
|
</Text>
|
|
275
|
-
<Text style={styles.userEmail}>
|
|
276
|
-
{myProfileData?.client?.employee?.email}
|
|
277
|
-
</Text>
|
|
278
|
-
<Text style={styles.userPhone}>
|
|
279
|
-
{myProfileData?.client?.employee?.phone}
|
|
280
|
-
</Text>
|
|
281
275
|
</View>
|
|
282
276
|
|
|
283
277
|
{/* My Account Section */}
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
import api, { api1 } from "./api";
|
|
13
13
|
import ENDPOINTS from "./endpoints";
|
|
14
14
|
import DeviceInfo from "react-native-device-info";
|
|
15
|
-
import { getSDKCredentials } from "./sdkCredentials";
|
|
15
|
+
import { getSDKCredentials } from "./sdkCredentials";
|
|
16
16
|
|
|
17
17
|
let cachedDeviceId: string | null = null;
|
|
18
18
|
|
|
@@ -60,25 +60,29 @@ export const verifyMobileOtpApi = (payload: VerifyMobileOtpPayload) => {
|
|
|
60
60
|
};
|
|
61
61
|
|
|
62
62
|
export const sdkAuthApi = async () => {
|
|
63
|
+
const creds = getSDKCredentials();
|
|
64
|
+
if (!creds?.authToken || !creds?.authId) {
|
|
65
|
+
throw new Error("SDK credentials missing: authToken/authId not set");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const environment = creds.environment?.toUpperCase?.() || "PRODUCTION";
|
|
69
|
+
|
|
63
70
|
const payload = {
|
|
64
|
-
device_id: "device123",
|
|
65
|
-
client_name: "AndroidApp",
|
|
66
|
-
client_version: "1.0.0",
|
|
67
|
-
environment
|
|
71
|
+
device_id: creds.deviceId || "device123",
|
|
72
|
+
client_name: creds.clientName || "AndroidApp",
|
|
73
|
+
client_version: creds.clientVersion || "1.0.0",
|
|
74
|
+
environment,
|
|
68
75
|
user: {
|
|
69
|
-
user_id: "uuid",
|
|
70
|
-
name: "abc12345",
|
|
71
|
-
mobile: "9030992316",
|
|
72
|
-
email: "abc12345@yopmail.com",
|
|
76
|
+
user_id: creds.userId || "uuid",
|
|
73
77
|
},
|
|
74
78
|
};
|
|
75
|
-
|
|
79
|
+
|
|
76
80
|
const headers = {
|
|
77
|
-
"X-Auth-Token":
|
|
78
|
-
"X-Auth-Id":
|
|
81
|
+
"X-Auth-Token": creds.authToken,
|
|
82
|
+
"X-Auth-Id": creds.authId,
|
|
79
83
|
"Content-Type": "application/json",
|
|
80
84
|
};
|
|
81
|
-
|
|
85
|
+
|
|
82
86
|
return api1.post(ENDPOINTS.SDK_AUTH_INIT, payload, { headers });
|
|
83
87
|
};
|
|
84
88
|
export const myOrdersApi = async () => {
|