From 94a094317a49b1157e6489882c8892742fcf7891 Mon Sep 17 00:00:00 2001 From: Brice Zele Date: Sat, 18 Apr 2020 20:59:05 +0100 Subject: [PATCH] Wallet redux --- App.js | 6 +- index.js | 25 ++++- package-lock.json | 15 +++ package.json | 3 +- redux/actions/AuthKeyActions.js | 15 +++ redux/reducers/AuthKeyReducer.js | 33 +++++++ redux/reducers/WalletReducer.js | 16 +-- redux/reducers/index.js | 17 +++- redux/store.js | 20 ++-- redux/types/AuthKeyType.js | 3 + screens/history-request/MyHistory.js | 1 + screens/home/Home.js | 32 +++++- screens/wallet/WalletSelect.js | 142 ++++++++++++++++++++------- webservice/AuthKeyApi.js | 25 +++++ webservice/IlinkConstants.js | 15 ++- webservice/WalletApi.js | 27 +++++ webservice/WalletService.js | 0 yarn.lock | 12 +++ 18 files changed, 344 insertions(+), 63 deletions(-) create mode 100644 redux/actions/AuthKeyActions.js create mode 100644 redux/reducers/AuthKeyReducer.js create mode 100644 redux/types/AuthKeyType.js create mode 100644 webservice/AuthKeyApi.js create mode 100644 webservice/WalletApi.js delete mode 100644 webservice/WalletService.js diff --git a/App.js b/App.js index 1674f079..b489f6fe 100644 --- a/App.js +++ b/App.js @@ -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 ( - + diff --git a/index.js b/index.js index b1687f5e..357824c7 100644 --- a/index.js +++ b/index.js @@ -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); diff --git a/package-lock.json b/package-lock.json index c38634f0..c6574093 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 790b99c3..780a62f8 100644 --- a/package.json +++ b/package.json @@ -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" diff --git a/redux/actions/AuthKeyActions.js b/redux/actions/AuthKeyActions.js new file mode 100644 index 00000000..bfd08ee2 --- /dev/null +++ b/redux/actions/AuthKeyActions.js @@ -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 +}); \ No newline at end of file diff --git a/redux/reducers/AuthKeyReducer.js b/redux/reducers/AuthKeyReducer.js new file mode 100644 index 00000000..386fc701 --- /dev/null +++ b/redux/reducers/AuthKeyReducer.js @@ -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; + } + + } +}; diff --git a/redux/reducers/WalletReducer.js b/redux/reducers/WalletReducer.js index 4f2baea5..534a20d4 100644 --- a/redux/reducers/WalletReducer.js +++ b/redux/reducers/WalletReducer.js @@ -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,16 +14,20 @@ 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; } } -}; \ No newline at end of file +}; diff --git a/redux/reducers/index.js b/redux/reducers/index.js index 42f025a7..ef764e91 100644 --- a/redux/reducers/index.js +++ b/redux/reducers/index.js @@ -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; \ No newline at end of file diff --git a/redux/store.js b/redux/store.js index fdd61193..bd16c477 100644 --- a/redux/store.js +++ b/redux/store.js @@ -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 }; \ No newline at end of file diff --git a/redux/types/AuthKeyType.js b/redux/types/AuthKeyType.js new file mode 100644 index 00000000..86cf9e46 --- /dev/null +++ b/redux/types/AuthKeyType.js @@ -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'; \ No newline at end of file diff --git a/screens/history-request/MyHistory.js b/screens/history-request/MyHistory.js index 7a1ea95d..401cba67 100644 --- a/screens/history-request/MyHistory.js +++ b/screens/history-request/MyHistory.js @@ -333,6 +333,7 @@ class MyHistory extends React.Component { {I18n.t('LOADING_DOTS')} + ) } diff --git a/screens/home/Home.js b/screens/home/Home.js index 51a6ad7b..e6f9a7bc 100644 --- a/screens/home/Home.js +++ b/screens/home/Home.js @@ -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 { ) } 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, diff --git a/screens/wallet/WalletSelect.js b/screens/wallet/WalletSelect.js index 000497f2..df0757f5 100644 --- a/screens/wallet/WalletSelect.js +++ b/screens/wallet/WalletSelect.js @@ -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 ( + + {Platform.OS === 'android' + ? + ( + <> + + {I18n.t('LOADING_DOTS')} + + + ) : + <> + + {I18n.t('LOADING_DOTS')} + + } + + ) + } + + renderWalletItem = (item) => { + let icon = `${baseUrl}/datas/img/network/${slugify(item.network, { lower: true })}-logo.png`; + return ( + this.props.navigation.push('walletDetail')}> + + + + + + {item.network} + + {I18n.t('COUNTRY')}: {item.country} + + + + + ) + } + + renderWalletList = () => { + + const { result, error } = this.props; + if (error !== null) { + return ( + + {error} + + ) + } + if (result !== null) + return ( + + { + result != null && ( + result.map((item, index) => { + this.renderWalletItem(item); + }) + ) + } + + ) + } + render() { + console.log("Wallet Props", this.props); return ( @@ -170,43 +247,32 @@ export default class WalletSelect extends Component { /> - - { - card.map((item, index) => { - let icon = `${baseUrl}/datas/img/network/${slugify(item.name, { lower: true })}-logo.png`; - console.log(icon); - return ( - this.props.navigation.push('walletDetail')}> - - - - - - {item.name} - - Pays: Gabon - - - - {item.primary ? ( - - {I18n.t('PRINCIPAL')} - - ) : null} - - ) - }) - } - + { + this.props.loading ? + this.renderLoader() : + this.renderWalletList() + } + + ); } } + +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, diff --git a/webservice/AuthKeyApi.js b/webservice/AuthKeyApi.js new file mode 100644 index 00000000..7ac06fd1 --- /dev/null +++ b/webservice/AuthKeyApi.js @@ -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; \ No newline at end of file diff --git a/webservice/IlinkConstants.js b/webservice/IlinkConstants.js index 70f21897..5b5abdf3 100644 --- a/webservice/IlinkConstants.js +++ b/webservice/IlinkConstants.js @@ -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" +}; diff --git a/webservice/WalletApi.js b/webservice/WalletApi.js new file mode 100644 index 00000000..8436ca9a --- /dev/null +++ b/webservice/WalletApi.js @@ -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; \ No newline at end of file diff --git a/webservice/WalletService.js b/webservice/WalletService.js deleted file mode 100644 index e69de29b..00000000 diff --git a/yarn.lock b/yarn.lock index dd4ff6e9..073786b7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"