Wallet redux

This commit is contained in:
Brice Zele 2020-04-18 20:59:05 +01:00
parent 350b2e3b91
commit 94a094317a
18 changed files with 344 additions and 63 deletions

6
App.js
View File

@ -44,6 +44,8 @@ import WalletDetail from './screens/wallet/WalletDetail';
import WalletSelect from './screens/wallet/WalletSelect';
import { PersistGate } from 'redux-persist/integration/react';
import { store, persistor } from './redux/store';
import { Provider } from 'react-redux';
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
android:
@ -299,10 +301,12 @@ export const AppNavigator = createSwitchNavigator({
const AppContainer = createAppContainer(AppNavigator);
class App extends React.Component {
render() {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<PersistGate persistor={persistor}>
<AppContainer />
</PersistGate>
</Provider>

View File

@ -3,12 +3,35 @@
*/
import 'react-native-gesture-handler';
import { AppRegistry, YellowBox } from 'react-native';
import { AppRegistry, YellowBox, AsyncStorage } from 'react-native';
import App from './App';
import { name as appName } from './app.json';
import axios from "axios";
YellowBox.ignoredYellowBox = ['Warning: Each', 'Warning: Failed'];
console.disableYellowBox = true;
getAuthToken = () => {
return new Promise(async (resolve, reject) => {
try {
const data = await AsyncStorage.getItem('persist:root');
resolve(JSON.parse(data))
} catch (error) {
reject(error)
}
})
};
(async () => {
const authToken = await getAuthToken();
const auth = JSON.parse(authToken.authKeyReducer);
console.log("AUTHTOKEN", auth);
axios.defaults.headers.common['Authorization'] = `${auth.authKey.token_type} ${auth.authKey.access_token}`;
})();
AppRegistry.registerComponent(appName, () => App);

15
package-lock.json generated
View File

@ -2532,6 +2532,12 @@
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
},
"deep-diff": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz",
"integrity": "sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ=",
"dev": true
},
"deep-is": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@ -6404,6 +6410,15 @@
"resolved": "https://registry.npmjs.org/reanimated-bottom-sheet/-/reanimated-bottom-sheet-1.0.0-alpha.19.tgz",
"integrity": "sha512-Q0sGUHYdr5h2n/AY7pKQty35zcUAxxYM1nCl+luSQAyqiY6a5Kf8IBQRsOVvs60sDzqXxtbwxHgM5mkwaiQC4Q=="
},
"redux-logger": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/redux-logger/-/redux-logger-3.0.6.tgz",
"integrity": "sha1-91VZZvMJjzyIYExEnPC69XeCdL8=",
"dev": true,
"requires": {
"deep-diff": "^0.3.5"
}
},
"regenerate": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",

View File

@ -85,7 +85,8 @@
"jest": "^24.8.0",
"jetifier": "^1.6.5",
"metro-react-native-babel-preset": "^0.54.1",
"react-test-renderer": "16.8.3"
"react-test-renderer": "16.8.3",
"redux-logger": "^3.0.6"
},
"jest": {
"preset": "react-native"

View File

@ -0,0 +1,15 @@
import { AUTH_KEY_PENDING, AUTH_KEY_SUCCESS, AUTH_KEY_ERROR } from "../types/AuthKeyType";
export const fetchAuthKeyPending = () => ({
type: AUTH_KEY_PENDING
});
export const fetchAuthKeySuccess = (res) => ({
type: AUTH_KEY_SUCCESS,
result: res,
});
export const fetchAuthKeyError = (error) => ({
type: AUTH_KEY_ERROR,
result: error
});

View File

@ -0,0 +1,33 @@
import { AUTH_KEY_PENDING, AUTH_KEY_SUCCESS, AUTH_KEY_ERROR } from "../types/AuthKeyType";
import { REHYDRATE } from "redux-persist";
const initialState = {
loading: false,
authKey: null,
error: null,
};
export default (state = initialState, action) => {
switch (action.type) {
case AUTH_KEY_PENDING: return {
...state,
loading: true
}
case AUTH_KEY_SUCCESS: return {
...state,
loading: false,
authKey: action.result.data,
error: null
}
case AUTH_KEY_ERROR: return {
...state,
loading: false,
error: action.result
}
default: {
return state;
}
}
};

View File

@ -6,7 +6,7 @@ const initialState = {
error: null,
};
export const walletReducer = (state = initialState, action) => {
export default (state = initialState, action) => {
switch (action.type) {
case WALLET_LIST_PENDING: return {
...state,
@ -14,15 +14,19 @@ export const walletReducer = (state = initialState, action) => {
}
case WALLET_LIST_SUCCESS: return {
...state,
loading: true,
result: action.result,
loading: false,
result: action.result.data,
error: null
}
case WALLET_LIST_ERROR: return {
...state,
loading: false,
result: action.result,
error: action.result.statusText,
result: null,
error: action.result,
}
default: {
return state;
}
}

View File

@ -1,8 +1,19 @@
import { combineReducers } from "redux";
import { walletReducer } from "./WalletReducer";
import walletReducer from "./WalletReducer";
import authKeyReducer from "./AuthKeyReducer";
import { persistCombineReducers } from "redux-persist";
import { AsyncStorage } from "react-native";
const rootReducer = combineReducers({
walletReducer: walletReducer
const persistConfig = {
key: 'root',
storage: AsyncStorage,
whitelist: ['authKeyReducer'],
blacklist: []
};
const rootReducer = persistCombineReducers(persistConfig, {
wallet: walletReducer,
authKey: authKeyReducer
});
export default rootReducer;

View File

@ -1,21 +1,27 @@
import { AsyncStorage } from "react-native";
import { persistReducer, persistStore } from "redux-persist";
import { createStore, applyMiddleware } from "redux";
import { createStore, applyMiddleware, compose } from "redux";
import thunk from 'redux-thunk';
import { createLogger } from 'redux-logger';
import rootReducer from "./reducers";
const persistConfig = {
/* const persistConfig = {
key: 'root',
storage: AsyncStorage,
whitelist: [],
whitelist: ['authKeyReducer'],
blacklist: []
};
}; */
const middlewares = [];
middlewares.push(thunk);
const persistedReducer = persistReducer(persistConfig, rootReducer);
const middlewares = [thunk];
const store = createStore(persistedReducer, applyMiddleware(...middlewares));
const loggerMiddleware = createLogger({
predicate: () => process.env.NODE_ENV === 'development'
})
middlewares.push(loggerMiddleware);
const store = createStore(rootReducer, compose(applyMiddleware(...middlewares)));
let persistor = persistStore(store);
export { store, persistor };

View File

@ -0,0 +1,3 @@
export const AUTH_KEY_PENDING = 'AUTH_KEY_PENDING';
export const AUTH_KEY_SUCCESS = 'AUTH_KEY_SUCCESS';
export const AUTH_KEY_ERROR = 'AUTH_KEY_ERROR';

View File

@ -333,6 +333,7 @@ class MyHistory extends React.Component {
<View style={styles.emptyListe}>
<ProgressBarAndroid />
<Text>{I18n.t('LOADING_DOTS')}</Text>
</View>
)
}

View File

@ -45,6 +45,10 @@ import { FAB, Card, Surface } from 'react-native-paper'
import BottomSheet from 'reanimated-bottom-sheet'
const { width: viewportWidth, height: viewportHeight } = Dimensions.get('window');
import MarkerManager from './../../webservice/persistences/MarkerManager'
import { bindActionCreators } from 'redux';
import getAuthApiKey from '../../webservice/AuthKeyApi';
import { connect } from 'react-redux';
const slideHeight = responsiveHeight(30) > 270 ? 270 : responsiveHeight(30)
//var Fabric = require('react-native-fabric');
//var { Crashlytics } = Fabric
@ -154,10 +158,21 @@ class Home extends BaseScreen {
};
componentDidMount() {
AsyncStorage.getAllKeys((err, keys) => {
AsyncStorage.multiGet(keys, (err, stores) => {
stores.map((result, i, store) => {
let key = store[i][0];
let value = store[i][1];
console.log('STORAGE VALUE ', `key: ${key} | value: ${value}`);
});
});
});
this.mounted = true;
this.configuration = new Configuration()
const { navigation } = this.props;
this.markerManager = new MarkerManager()
this.props.getAuthApiKey();
this.configuration.getCurrentPubValue().then((value) => {
try {
const val = parseInt(value)
@ -1453,7 +1468,7 @@ class Home extends BaseScreen {
</View>)
}
render() {
console.log("PROPS", this.props);
if (false) {
return this.renderBottomHome()
} else
@ -2155,7 +2170,20 @@ class Home extends BaseScreen {
}
}
export default Home;
const mapStateToProps = state => ({
loading: state.loading,
authKey: state.authKey,
error: state.error
});
const mapDispatchToProps = dispatch => bindActionCreators({
getAuthApiKey
}, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(Home);
const markerDetails = StyleSheet.create({
solde: {
backgroundColor: theme.accent,

View File

@ -1,5 +1,5 @@
import React, { Component } from 'react';
import { StyleSheet, View, Image, StatusBar, ScrollView, TouchableOpacity } from 'react-native';
import { StyleSheet, View, Image, StatusBar, ScrollView, TouchableOpacity, ActivityIndicator, Platform } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
const route = require('./../../route.json');
let slugify = require('slugify');
@ -8,10 +8,13 @@ import * as Utils from '../../utils/DeviceUtils';
import { Images } from '../../config/Images';
import CustomText from '../../components/CustomText';
import { Color } from '../../config/Color';
import { SafeAreaView } from 'react-navigation';
import { baseUrl } from '../../webservice/IlinkConstants';
import { IlinkEmitter } from "../../utils/events";
import { Provider, Appbar } from 'react-native-paper';
import getWalletActivated from '../../webservice/WalletApi';
import { connect } from 'react-redux';
import { readUser } from '../../webservice/AuthApi';
import { bindActionCreators } from 'redux';
const card = [
{
@ -116,18 +119,14 @@ const card = [
}
];
export default class WalletSelect extends Component {
class WalletSelect extends Component {
constructor(props) {
super(props);
this.state = {
loading: true
}
slugify.extend({ '+': 'plus' });
IlinkEmitter.on("langueChange", this.updateLangue.bind(this));
}
static navigationOptions = ({ navigation }) => ({
header: null,
headerMode: 'none',
@ -144,12 +143,90 @@ export default class WalletSelect extends Component {
/>)
});
componentDidMount() {
readUser().then((user) => {
if (user) {
this.props.getWalletActivated(user.agentId);
}
});
}
updateLangue() {
this.props.navigation.setParams({ name: I18n.t('WALLET') })
this.forceUpdate()
}
renderLoader = () => {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
{Platform.OS === 'android'
?
(
<>
<ProgressBarAndroid />
<Text>{I18n.t('LOADING_DOTS')}</Text>
</>
) :
<>
<ActivityIndicator size="large" color={'#ccc'} />
<Text>{I18n.t('LOADING_DOTS')}</Text>
</>
}
</View>
)
}
renderWalletItem = (item) => {
let icon = `${baseUrl}/datas/img/network/${slugify(item.network, { lower: true })}-logo.png`;
return (
<TouchableOpacity
key={item.id}
style={[styles.paymentItem, { borderBottomColor: Color.borderColor }]}
onPress={() => this.props.navigation.push('walletDetail')}>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<View style={styles.iconContent}>
<Image style={{ width: 48, height: 48 }} source={{ uri: icon }} />
</View>
<View>
<CustomText body1>{item.network}</CustomText>
<CustomText footnote grayColor style={{ marginTop: 5 }}>
{I18n.t('COUNTRY')}: {item.country}
</CustomText>
</View>
</View>
</TouchableOpacity>
)
}
renderWalletList = () => {
const { result, error } = this.props;
if (error !== null) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<CustomText body1>{error}</CustomText>
</View>
)
}
if (result !== null)
return (
<ScrollView style={{ flex: 1, padding: 20 }}>
{
result != null && (
result.map((item, index) => {
this.renderWalletItem(item);
})
)
}
</ScrollView>
)
}
render() {
console.log("Wallet Props", this.props);
return (
<Provider>
<View style={{ flex: 1 }}>
@ -170,43 +247,32 @@ export default class WalletSelect extends Component {
/>
</Appbar.Header>
<ScrollView style={{ flex: 1, padding: 20 }}>
{
card.map((item, index) => {
let icon = `${baseUrl}/datas/img/network/${slugify(item.name, { lower: true })}-logo.png`;
console.log(icon);
return (
<TouchableOpacity
key={item.id}
style={[styles.paymentItem, { borderBottomColor: Color.borderColor }]}
onPress={() => this.props.navigation.push('walletDetail')}>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<View style={styles.iconContent}>
<Image style={{ width: 48, height: 48 }} source={{ uri: icon }} />
</View>
<View>
<CustomText body1>{item.name}</CustomText>
<CustomText footnote grayColor style={{ marginTop: 5 }}>
Pays: Gabon
</CustomText>
</View>
</View>
{item.primary ? (
<CustomText footnote primaryColor>
{I18n.t('PRINCIPAL')}
</CustomText>
) : null}
</TouchableOpacity>
)
})
this.props.loading ?
this.renderLoader() :
this.renderWalletList()
}
</ScrollView>
</View>
</Provider>
);
}
}
const mapStateToProps = state => ({
loading: state.loading,
result: state.result,
error: state.error
});
const mapDispatchToProps = dispatch => bindActionCreators({
getWalletActivated
}, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(WalletSelect);
const styles = StyleSheet.create({
container: {
flex: 1,

25
webservice/AuthKeyApi.js Normal file
View File

@ -0,0 +1,25 @@
import axios from "axios";
import { authKeyUrl, authKeyData } from "./IlinkConstants";
import { fetchAuthKeySuccess, fetchAuthKeyPending, fetchAuthKeyError } from "../redux/actions/AuthKeyActions";
const getAuthApiKey = (email) => {
return dispatch => {
dispatch(fetchAuthKeyPending());
axios.post(authKeyUrl, authKeyData)
.then(response => {
dispatch(fetchAuthKeySuccess(response));
})
.catch(error => {
dispatch(fetchAuthKeyError(error.message));
if (error.response)
dispatch(fetchAuthKeyError(error.response));
else if (error.request)
dispatch(fetchAuthKeyError(error.request))
else
dispatch(fetchAuthKeyError(error.message))
});
}
}
export default getAuthApiKey;

View File

@ -15,7 +15,14 @@ export const memberActionUrl = baseUrl + '/interacted/MembersAction.php';
export const networkActionUrl = baseUrl + '/interacted/NetworkAction.php';
export const locationActionUrl = baseUrl + '/interacted/LocationAction.php';
export const demandeActionUrl = baseUrl + '/interacted/DemandeAction.php';
export const configActionUrl = baseUrl + '/interacted/ConfigAction.php'
export const walletActionUrl = testBaseUrl + '/walletService/wallets/'
export const videoUrl = "https://www.youtube.com/watch?v=wwGPDPsSLWY"
export const MARKER_URL = baseUrl + "/interacted/LocationAction.php"
export const configActionUrl = baseUrl + '/interacted/ConfigAction.php';
export const walletActionUrl = testBaseUrl + '/walletService/wallets';
export const authKeyUrl = testBaseUrl + '/oauth/token';
export const videoUrl = "https://www.youtube.com/watch?v=wwGPDPsSLWY";
export const MARKER_URL = baseUrl + "/interacted/LocationAction.php";
export const authKeyData = {
"grant_type": "client_credentials",
"client_id": "3",
"client_secret": "E3jAPczLLGvQu87ulQqKB5yM7BXXQUwpL68CPBXe"
};

27
webservice/WalletApi.js Normal file
View File

@ -0,0 +1,27 @@
import axios from "axios";
import { walletActionUrl } from "./IlinkConstants";
import { fetchWalletListPending, fetchWalletListSuccess, fetchWalletListError } from "../redux/actions/WalletActions";
const getWalletActivated = (userID) => {
return dispatch => {
dispatch(fetchWalletListPending());
axios.post(`${walletActionUrl}/${userID}/activated`)
.then(response => {
console.log(response);
dispatch(fetchWalletListSuccess(response));
})
.catch(error => {
dispatch(fetchWalletListError(error.message));
if (error.response)
dispatch(fetchWalletListError(error.response));
else if (error.request)
dispatch(fetchWalletListError(error.request))
else
dispatch(fetchWalletListError(error.message))
});
}
}
export default getWalletActivated;

View File

@ -2805,6 +2805,11 @@ deep-assign@^3.0.0:
dependencies:
is-obj "^1.0.0"
deep-diff@^0.3.5:
version "0.3.8"
resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.8.tgz#c01de63efb0eec9798801d40c7e0dae25b582c84"
integrity sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ=
deep-extend@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
@ -6849,6 +6854,13 @@ reanimated-bottom-sheet@^1.0.0-alpha.10:
resolved "https://registry.yarnpkg.com/reanimated-bottom-sheet/-/reanimated-bottom-sheet-1.0.0-alpha.19.tgz#94ea79e7b2896b8f489547415d15d15c99ac44ba"
integrity sha512-Q0sGUHYdr5h2n/AY7pKQty35zcUAxxYM1nCl+luSQAyqiY6a5Kf8IBQRsOVvs60sDzqXxtbwxHgM5mkwaiQC4Q==
redux-logger@^3.0.6:
version "3.0.6"
resolved "https://registry.yarnpkg.com/redux-logger/-/redux-logger-3.0.6.tgz#f7555966f3098f3c88604c449cf0baf5778274bf"
integrity sha1-91VZZvMJjzyIYExEnPC69XeCdL8=
dependencies:
deep-diff "^0.3.5"
redux-persist@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-6.0.0.tgz#b4d2972f9859597c130d40d4b146fecdab51b3a8"