diff --git a/locales/ar.json b/locales/ar.json index 7f7b2a3..c6cda76 100644 --- a/locales/ar.json +++ b/locales/ar.json @@ -96,6 +96,7 @@ }, "NFCScreen": { "ErrorMessage": "لمس بطاقة", + "BalanceCheckMessage": "تحقق من الرصيد", "NFCError": "خطأ NFC", "NFCCounterError": "خطأ في تطبيق المعاملة على البطاقة", "NFCErrorMessage": "لا يحتوي جهازك على قارئ NFC.", @@ -222,7 +223,8 @@ "PaymentModeSwitcher": { "SendHint": "انتقل إلى شاشة الإرسال", "ChargeHint": "انتقل لاستلام الشاشة", - "ScanHint": "انتقل إلى شاشة مسح الكاميرا" + "ScanHint": "انتقل إلى شاشة مسح الكاميرا", + "BalanceHint": "انتقل للتحقق من رصيد البطاقة" }, "SendPaymentCameraScreen": { "Send": "إرسال", diff --git a/locales/bi.json b/locales/bi.json index d6189ff..3d1786e 100644 --- a/locales/bi.json +++ b/locales/bi.json @@ -97,6 +97,7 @@ }, "NFCScreen": { "ErrorMessage": "Tajem Kad Lo Phon", + "BalanceCheckMessage": "Check Balance", "NFCError": "Problem", "NFCCounterError": "Error Applying Transaction To Card", "NFCErrorMessage": "Your device does not have an NFC reader.", @@ -223,7 +224,8 @@ "PaymentModeSwitcher": { "SendHint": "Navigate to send screen", "ChargeHint": "Navigate to receive screen", - "ScanHint": "Navigate to camera scan screen" + "ScanHint": "Navigate to camera scan screen", + "BalanceHint": "Navigate to check card balance" }, "SendPaymentCameraScreen": { "Send": "Sendem", diff --git a/locales/en.json b/locales/en.json index c0e8cde..0f9c113 100644 --- a/locales/en.json +++ b/locales/en.json @@ -96,6 +96,7 @@ }, "NFCScreen": { "ErrorMessage": "Hold Card To Back", + "BalanceCheckMessage": "Check Balance", "NFCError": "NFC Error", "NFCCounterError": "Error Applying Transaction To Card", "NFCErrorMessage": "Your device does not have an NFC reader.", @@ -222,7 +223,8 @@ "PaymentModeSwitcher": { "SendHint": "Navigate to send screen", "ChargeHint": "Navigate to receive screen", - "ScanHint": "Navigate to camera scan screen" + "ScanHint": "Navigate to camera scan screen", + "BalanceHint": "Navigate to check card balance" }, "SendPaymentCameraScreen": { "Send": "Send", diff --git a/locales/es.json b/locales/es.json index b145e8b..335b5af 100644 --- a/locales/es.json +++ b/locales/es.json @@ -97,6 +97,7 @@ }, "NFCScreen": { "ErrorMessage": "Toque la tarjeta", + "BalanceCheckMessage": "Consultar saldo", "NFCError": "Error de tarjeta", "NFCCounterError": "Error al aplicar la transacción a la tarjeta", "NFCErrorMessage": "Su dispositivo no tiene una lectora NFC.", @@ -223,7 +224,8 @@ "PaymentModeSwitcher": { "SendHint": "Navegar a la pantalla de envío", "ChargeHint": "Navegar a la pantalla de recepción", - "ScanHint": "Navegar a la pantalla de escaneo de la cámara" + "ScanHint": "Navegar a la pantalla de escaneo de la cámara", + "BalanceHint": "Navegar para consultar el saldo de la tarjeta" }, "SendPaymentCameraScreen": { "Send": "Enviar", diff --git a/locales/fr.json b/locales/fr.json index 0895661..42e00c8 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -96,6 +96,7 @@ }, "NFCScreen": { "ErrorMessage": "Carte Tap", + "BalanceCheckMessage": "Vérifier le solde", "NFCError": "Erreur NFC", "NFCCounterError": "Erreur lors de l'application de la transaction à la carte", "NFCErrorMessage": "Votre appareil ne possède pas de lecteur NFC.", @@ -222,7 +223,8 @@ "PaymentModeSwitcher": { "SendHint": "Accédez à l'écran d'envoi", "ChargeHint": "Naviguez pour recevoir l'écran", - "ScanHint": "Accédez à l'écran de numérisation de la caméra" + "ScanHint": "Accédez à l'écran de numérisation de la caméra", + "BalanceHint": "Naviguez pour vérifier le solde de la carte" }, "SendPaymentCameraScreen": { "Send": "Envoyer", diff --git a/package-lock.json b/package-lock.json index 33adafc..f146925 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "Sempo", - "version": "1.7.0", + "version": "1.7.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 99442fb..40eb9ef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Sempo", - "version": "1.7.4", + "version": "1.7.5", "private": true, "scripts": { "android": "react-native run-android", diff --git a/src/api/nfcAPI.js b/src/api/nfcAPI.js index 9698566..082d41f 100644 --- a/src/api/nfcAPI.js +++ b/src/api/nfcAPI.js @@ -2,10 +2,11 @@ import NfcManager, {NfcTech} from 'react-native-nfc-manager'; import {threeByteArrayToInt, byteArrayToHexString, intToThreeByteArray, getDisplayDecimals} from "../utils"; -export const OpenNFCRequest = async () => ( - NfcManager.registerTagEvent() - .then(() => NfcManager.requestTechnology(NfcTech.NfcA)) -); +export const OpenNFCRequest = async () => { + return NfcManager.registerTagEvent() + .then(() => NfcManager.requestTechnology(NfcTech.NfcA)) + +} export const closeNFCRequest = async () => NfcManager.cancelTechnologyRequest(); diff --git a/src/components/PaymentModeSwitcher.js b/src/components/PaymentModeSwitcher.js index 5f1411d..dbdef01 100644 --- a/src/components/PaymentModeSwitcher.js +++ b/src/components/PaymentModeSwitcher.js @@ -1,15 +1,9 @@ 'use strict'; import React, { Component } from 'react'; import { - Dimensions, StyleSheet, - Text, View, - Alert, TouchableNativeFeedback, - Vibration, - Clipboard, - Linking, } from 'react-native'; import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; @@ -41,6 +35,7 @@ class PaymentModeSwitcher extends Component { static defaultProps = { camera: false, send: false, + balance: false, charge: false, dark: false, }; @@ -49,13 +44,14 @@ class PaymentModeSwitcher extends Component { let paymentOptions = [ {mode: 'camera', name: 'qrcode-scan', active: this.props.camera, transform: [], label: strings('SendPaymentCameraScreen.CameraPrompt'), hint: strings('PaymentModeSwitcher.ScanHint')}, + {mode: 'balance', name: 'cellphone-nfc', active: this.props.balance, transform: [], label: strings('SendPaymentCameraScreen.CardBalance'), hint: strings('PaymentModeSwitcher.BalanceHint')}, {mode: 'send', name: 'send', active: this.props.send, transform: [{rotate: '-45deg'}], label: strings('SendPaymentCameraScreen.Send'), hint: strings('PaymentModeSwitcher.SendHint')}, ]; if (this.props.login.isVendor || this.props.login.isSupervendor) { paymentOptions.push({mode: 'charge', name: 'credit-card-multiple', active: this.props.charge, transform: [], label: strings('NavBar.chargeButtonText'), hint: strings('PaymentModeSwitcher.ChargeHint')}) } - + return ( {paymentOptions.map((option, index) => { diff --git a/src/components/PaymentSwitch.js b/src/components/PaymentSwitch.js index f4f5a8b..df2824e 100644 --- a/src/components/PaymentSwitch.js +++ b/src/components/PaymentSwitch.js @@ -9,6 +9,7 @@ import { import { connect } from "react-redux"; import SendPaymentCameraScreen from './SendPaymentFlow/SendPaymentCameraScreen'; +import CheckCardBalanceScreen from './SendPaymentFlow/CheckCardBalanceScreen'; import PaymentAmountScreen from "./SendPaymentFlow/PaymentAmountScreen.js" import PaymentsAmountScreen from "../components/ReceivePaymentFlow/PaymentsAmountScreen"; @@ -30,12 +31,13 @@ class PaymentSwitch extends Component { static defaultProps = { camera: false, send: false, - charge: false + charge: false, + balance: false }; render() { const { transferData } = this.props; - console.log('payment switch--',transferData.default_transfer_mode); + console.log('payment switch--', transferData.default_transfer_mode); if (transferData.default_transfer_mode === 'camera' && transferData.temp_transfer_mode === null) { return @@ -43,6 +45,8 @@ class PaymentSwitch extends Component { return } else if (transferData.default_transfer_mode === 'charge') { return + } else if (transferData.default_transfer_mode == 'balance') { + return } else if (this.props.login.isVendor) { return } else { diff --git a/src/components/SendPaymentFlow/CheckCardBalanceScreen.js b/src/components/SendPaymentFlow/CheckCardBalanceScreen.js new file mode 100644 index 0000000..c58b871 --- /dev/null +++ b/src/components/SendPaymentFlow/CheckCardBalanceScreen.js @@ -0,0 +1,419 @@ +'use strict'; +import React, { Component } from 'react'; +import { + StyleSheet, + Text, + View, + ActivityIndicator, + Image, + StatusBar +} from 'react-native'; +import { theme } from "../../Styles"; +import TransferCompleteNotifier from "./DisplayBalanceNotifier" +import AsyncButton from "../common/AsyncButton"; + +import { RESET_NEW_TRANSFER, RESET_TRANSFER_DATA } from '../../reducers/creditTransferReducer.js' +import { RESET_USER_BY_PUBLIC_SERIAL } from "../../reducers/userReducer"; +import { chargeNFCCard, closeNFCRead, resetNFCStatus } from "../../reducers/nfcReducer"; +import NfcManager from "react-native-nfc-manager"; + +import { connect } from "react-redux"; +import { strings } from '../../../locales/i18n'; + +import { tracker } from "../../analytics"; +import PaymentModeSwitcher from "../PaymentModeSwitcher"; +import ExitToHome from "../ExitToHome" +import { resetTransferData } from "../../reducers/creditTransferReducer"; + +const mapStateToProps = (state) => { + return { + newTransferStatus: state.creditTransfers.createStatus, + login: state.login, + transferData: state.creditTransfers.transferData, + NFCTransceiveStatus: state.NFC.TransceiveStatus, + }; +}; + +const mapDispatchToProps = (dispatch) => { + return { + resetTransferData: () => { + dispatch(resetTransferData()); + dispatch(resetNFCStatus()); + dispatch(closeNFCRead()); + }, + + resetNewTransfer: () => { + console.log("resetting new transfer") + dispatch({ type: RESET_NEW_TRANSFER }); + dispatch({ type: RESET_TRANSFER_DATA }); + dispatch({ type: RESET_USER_BY_PUBLIC_SERIAL }); + }, + chargeNFCCard: (chargeAmount) => dispatch(chargeNFCCard(chargeAmount, null)), + cancelNFCRead: () => dispatch(closeNFCRead()), + resetNFCStatus: () => dispatch(resetNFCStatus()) + }; +}; + +class CheckCardBalanceScreen extends Component { + constructor(props) { + super(props); + this.state = { + scanData: '', + transfer_account_name: '', + recipient_transfer_account_id: '', + transfer_amount: '', + transfer_use: '', + transfer_random_key: '', + question: '', + rating: null, + additional_information: '', + handleScan: true, + public_serial_number: '', + checkBalance: false, + vendorScan: false, + NFC_supported: false, + NFC_enabled: false, + detection_was_on_previously: false, + nfc_id: '', + amount: '', + checking_nfc: false, + invalid_nfc: false, + } + } + + componentDidMount() { + const { navigation } = this.props; + + // Component doesn't mount or unmount through standard nav so we need these event listeners. + this._unsubscribeFocus = navigation.addListener('focus', () => { + this.cleanUp(); + NfcManager.isSupported() + .then(NFC_supported => { + this.setState({ NFC_supported }); + if (NFC_supported) { + this._startNfc(); + } + }); + }); + + this._unsubscribeBlur = navigation.addListener('blur', () => { + this.cleanUp(); + this.closeNFC(); + }); + + this.cleanUp(); + + NfcManager.isSupported() + .then(NFC_supported => { + this.setState({ NFC_supported }); + if (NFC_supported) { + this._startNfc(); + } + }); + tracker.logEvent("CheckCardBalanceScreen"); + } + + cleanUp() { + this.props.resetNewTransfer(); + this.props.resetNFCStatus(); + } + + closeNFC() { + if (this.state.NFC_supported) { + this._stopDetection(); + this.props.cancelNFCRead(); + } + } + + componentWillUnmount() { + this._unsubscribeFocus(); + this._unsubscribeBlur(); + this.cleanUp(); + this.closeNFC(); + } + + componentDidUpdate(prevProps) { + if (this.props.NFCTransceiveStatus.success !== prevProps.NFCTransceiveStatus.success) { + this.setState({ + checkBalance: this.props.NFCTransceiveStatus.success + }); + + } + if (this.state.NFC_enabled && + !this.props.NFCTransceiveStatus.isOpen && + !NfcManager.isEnabled() && + !this.props.NFCTransceiveStatus.success) { + this.props.chargeNFCCard(0) + } + } + + _startNfc() { + NfcManager.start({}) + .then(result => { + console.log('start OK4', result); + }) + .catch(error => { + console.warn('start fail', error); + this.setState({ supported: false }); + }); + + NfcManager.isEnabled() + .then(NFC_enabled => { + this.setState({ NFC_enabled }); + if (NFC_enabled) { + this._startDetection() + } + }) + .catch(err => { + console.log(err); + }); + } + + _startDetection = () => { + this.setState({ detection_was_on_previously: true }); + this.props.chargeNFCCard(0); + }; + + _stopDetection = () => { + try { + NfcManager.cancelTechnologyRequest() + .then(result => { + console.log('stop OK', result) + }) + .catch(error => { + console.warn('nfc stop fail', error) + }) + } + catch (err) { + console.log('stop fail', err) + } + }; + + render() { + + let { login } = this.props; + if (this.props.NFCTransceiveStatus.success) { + return ( + + ) + } + + if (this.props.NFCTransceiveStatus.error) { + var error_message = String(this.props.NFCTransceiveStatus.error); + + if (error_message === 'transceive fail') { + error_message = strings('NFCScreen.NFCTransceiveFail') + } else if (error_message === 'fail to connect tag') { + error_message = strings('NFCScreen.NFCTagError') + } + } else { + error_message = `${strings('NFCScreen.ErrorMessage')}`; + } + + let cardOnly = ( + + ) + + let highCard = ( + + ) + + let midCard = ( + + ) + + let cardImage = cardOnly; + let middleStyle; + let bottomSection = null; + + let textDetails = ( + + + {strings('NFCScreen.BalanceCheckMessage')} + + + + {error_message} + + + + ); + + if (login.NFCPositions && login.NFCPositions[model]) { + let positionDetails = login.NFCPositions[model]; + + if (positionDetails.cardImage === 'HIGH') { + cardImage = highCard + } else if (positionDetails.cardImage === 'MID') { + cardImage = midCard + } + + middleStyle = { + alignItems: 'center', + justifyContent: 'center', + width: '100%', + height: positionDetails.middleHeight + }; + + topSection = ( + + + + + + ); + + bottomSection = ( + + + + + {textDetails} + + ) + + } else { + middleStyle = { + alignItems: 'center', + justifyContent: 'center', + width: '100%', + height: '50%' + }; + + bottomSection = ( + + {textDetails} + + ) + } + + if (this.props.NFCTransceiveStatus.isReading || this.props.newTransferStatus.isRequesting) { + let progressWidth; + try { + progressWidth = this.props.NFCTransceiveStatus.nfcStage / 4 * 200 + } catch (e) { + progressWidth = 200; + } + + return ( + + + + + + + + + + + + ) + } else if (this.props.NFCTransceiveStatus.error) { + return ( + + + + {error_message} + this.props.chargeNFCCard(this.props.transferData.transfer_amount)} + /> + + + ); + } else { + return ( + + + + + + + + + + {cardImage} + + {bottomSection} + + ); + } + } +} +export default connect(mapStateToProps, mapDispatchToProps)(CheckCardBalanceScreen); + +const styles = StyleSheet.create({ + rootContainer: { + flex: 1, + backgroundColor: '#FFF', + }, + retryText: { + color: theme.colors.error, + fontSize: 20, + padding: 10, + fontWeight: 'bold', + }, + inputValueText: { + color: '#3D454C', + fontSize: 38, + fontWeight: 'bold', + } +}); \ No newline at end of file diff --git a/src/components/SendPaymentFlow/DisplayBalanceNotifier.js b/src/components/SendPaymentFlow/DisplayBalanceNotifier.js new file mode 100644 index 0000000..8d923b1 --- /dev/null +++ b/src/components/SendPaymentFlow/DisplayBalanceNotifier.js @@ -0,0 +1,78 @@ +import React from 'react' +import { StyleSheet, Text, View } from 'react-native' +import { TouchableHighlight } from 'react-native-gesture-handler' + +import { strings } from '../../../locales/i18n'; + +import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; +import CurrencyAmount from "../CurrencyAmount"; + +export default function TransferCompleteNotifier(props) { + + const { navigation, balance, resetTransferData } = props; + + + if (balance !== undefined) { + var balanceDisplay = ( + + Balance: + + ) + } else { + balanceDisplay = null + } + + return ( + + + + + {balanceDisplay} + + + { + resetTransferData(); + navigation.navigate('Home') + }} + accessibilityLabel={strings('TransferCompleteScreen.Continue')}> + {strings('TransferCompleteScreen.Continue')} + + + + ) +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#FFF', + justifyContent: 'center', + alignItems: 'center', + }, + mainContainer: { + flex: 10, + backgroundColor: '#FFF', + justifyContent: 'center', + alignItems: 'center', + }, + chargeContainer: { + flex: 2, + margin: 20 + }, + chargeButton: { + padding: 10, + backgroundColor: '#2D9EA0', + justifyContent: 'center', + }, + chargeButtonText: { + color: '#FFF', + fontSize: 24, + textAlign: 'center' + }, + balance: { + color: '#3D454C', + fontSize: 38, + fontWeight: 'bold', + }, +}); \ No newline at end of file diff --git a/src/components/screens/CheckBalanceScreen.js b/src/components/screens/CheckBalanceScreen.js deleted file mode 100644 index c6c98c8..0000000 --- a/src/components/screens/CheckBalanceScreen.js +++ /dev/null @@ -1,228 +0,0 @@ -import React from 'react' -import { - StyleSheet, - Text, - View, - ActivityIndicator, - Modal, -} from 'react-native' - -import {connect} from "react-redux"; - -import Styles from '../../Styles'; - -import { getUserFromPublicSerialNumber, RESET_USER_BY_PUBLIC_SERIAL } from "../../reducers/userReducer"; - -import { RNCamera } from "react-native-camera"; -import { strings } from "../../../locales/i18n"; -import CurrencyAmount from '../CurrencyAmount' -import {chargeNFCCard, closeNFCRead} from "../../reducers/nfcReducer"; -import NfcManager from "react-native-nfc-manager"; - -const mapStateToProps = (state) => { - return { - locale: state.locale, - users: state.users, - NFCTransceiveStatus: state.NFC.TransceiveStatus - }; -}; - -const mapDispatchToProps = (dispatch) => { - return { - getUserFromPublicSerialNumber: (query) => dispatch(getUserFromPublicSerialNumber({query})), - resetCheckBalance: () => dispatch({type: RESET_USER_BY_PUBLIC_SERIAL}), - chargeNFCCard: (chargeAmount) => dispatch(chargeNFCCard(chargeAmount, null)), - cancelNFCRead: () => dispatch(closeNFCRead()) - }; -}; - -class CheckBalanceScreen extends React.Component { - constructor(props) { - super(props); - this.state = { - public_serial_number: '', - NFC_supported: true, - NFC_enabled: false, - detection_was_on_previously: false, - nfc_id: '', - amount: '', - checking_nfc: false, - invalid_nfc: false, - } - } - - static navigationOptions = ({ navigation }) => ({ - title: `${navigation.state.params.title}`, - }); - - componentDidMount() { - NfcManager.isSupported() - .then(NFC_supported => { - this.setState({ NFC_supported }); - if (NFC_supported) { - this._startNfc(); - } - }) - } - - componentWillUnmount() { - this.props.resetCheckBalance(); - this._stopDetection(); - this.props.cancelNFCRead(); - } - - _handleScan = (e) => { - try { - if (this.state.public_serial_number !== e.data) { - this.setState({ public_serial_number: e.data }); - this.props.getUserFromPublicSerialNumber({ - public_serial_number: e.data - }) - } - } - catch(err) { - console.log(err) - } - }; - - _startNfc() { - NfcManager.start({ - - }).then(result => { - console.log('start OK', result); - }) - .catch(error => { - console.warn('start fail', error); - this.setState({supported: false}); - }) - - - NfcManager.isEnabled() - .then(NFC_enabled => { - this.setState({ NFC_enabled }); - - if (NFC_enabled) { - this._startDetection() - } - - }) - .catch(err => { - console.log(err); - }) - - } - - _startDetection = () => { - this.setState({detection_was_on_previously: true}); - this.props.chargeNFCCard(0); - }; - - _stopDetection = () => { - NfcManager.cancelTechnologyRequest().then(result => { - console.log('stop OK', result) - }) - .catch(error => { - console.warn('stop fail', error) - }) - }; - - render() { - - if (this.props.users.getUserFromPublicSerialNumberStatus.success === true) { - var content = - - {this.props.users.getUserFromPublicSerialNumberStatus.load_result.message} - Balance: - - } else if (this.props.NFCTransceiveStatus.success === true) { - content = - - Balance: - - - } else if (this.props.users.getUserFromPublicSerialNumberStatus.error !== null) { - content = {this.props.users.getUserFromPublicSerialNumberStatus.error.message} - } else { - content = null - } - - return ( - - { - this.camera = ref; - }} - style={styles.preview} - type={RNCamera.Constants.Type.back} - flashMode={RNCamera.Constants.FlashMode.off} - onBarCodeRead={(e) => this._handleScan(e)} - barCodeTypes={[RNCamera.Constants.BarCodeType.qr]} - androidCameraPermissionOptions={{ - title: `${strings('CameraScreen.permissionDialog')}`, - message: `${strings('CameraScreen.permissionDialog')}`, - buttonPositive: 'Ok', - buttonNegative: 'Cancel', - }} - /> - {content} - {(this.props.users.getUserFromPublicSerialNumberStatus.isRequesting - || this.props.NFCTransceiveStatus.isReading)? - - - - - - - - : null } - - ) - } -} - -export default connect(mapStateToProps, mapDispatchToProps)(CheckBalanceScreen); - -const styles = StyleSheet.create({ - preview: { - flex: 11, - }, - modalBackground: { - flex: 1, - alignItems: 'center', - flexDirection: 'column', - justifyContent: 'space-around', - backgroundColor: '#00000040' - }, - activityIndicatorWrapper: { - backgroundColor: '#FFFFFF', - height: 100, - width: 100, - borderRadius: 10, - display: 'flex', - alignItems: 'center', - justifyContent: 'space-around' - }, - title: { - color: '#4A4A4A', - fontSize: 20, - fontWeight: 'bold', - textAlign: 'center', - marginTop: 20, - paddingLeft: 30, - paddingRight: 30, - paddingBottom: 5, - borderBottomWidth: 2, - borderColor: '#F7F7F7' - }, - balance: { - color: '#4A4A4A', - fontSize: 20, - fontWeight: 'bold', - textAlign: 'center', - } -}); \ No newline at end of file