413 lines
17 KiB
JavaScript
413 lines
17 KiB
JavaScript
import * as React from 'react';
|
|
import { connect } from "react-redux";
|
|
import {
|
|
SafeAreaView,
|
|
TouchableOpacity,
|
|
View,
|
|
Text,
|
|
FlatList,
|
|
Image,
|
|
StyleSheet,
|
|
Alert,
|
|
Modal
|
|
} from 'react-native';
|
|
import { returnIcon } from '../../utils/card';
|
|
import { AdjustableText } from '../../components/text';
|
|
import REQUEST from '../../components/api';
|
|
import Icon from '../../components/icons.js';
|
|
import CustomHeader from '../../components/header.js';
|
|
import Theme from '../../components/theme.style.js';
|
|
import Assets from '../../components/assets.manager.js';
|
|
import Elements from '../../components/elements.js';
|
|
import DB from '../../components/storage/';
|
|
import CustomSafeArea from '../../components/safeArea.component';
|
|
import Tokenization from '../../components/paymaya/tokenization';
|
|
import { ENV } from '../../components/environment';
|
|
|
|
class TopupPaymentList extends React.Component {
|
|
constructor(props) {
|
|
super(props)
|
|
}
|
|
|
|
state = {
|
|
cards: [],
|
|
defaultCardIndex: -1,
|
|
defaultSelectedCard: null,
|
|
showModal: false,
|
|
showCardAdded: false,
|
|
showCardDeleted: false,
|
|
deleteCard: null,
|
|
loading: false,
|
|
merchant: {},
|
|
newlyAddedCard: null,
|
|
isShowSelectionCard: this.props.route.params?.displaySelectionCard
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.getSelectedCard();
|
|
this.getFunding();
|
|
}
|
|
|
|
getFunding = async () => {
|
|
this.setState({ loading: true, cards: [] })
|
|
const USER_PROFILE = await DB.profile();
|
|
const SESSION = await DB.session();
|
|
|
|
await REQUEST("paymaya_tokens", "get", {'Authorization': SESSION.token}, {noID: true, value: USER_PROFILE.data.card_number}, {}, async (res) => {
|
|
if(res.data && res.data.cards && res.data.cards.length > 0) {
|
|
const getDefault = res.data.cards.find(card => card.default);
|
|
await DB.set(
|
|
"topupPaymentCards",
|
|
JSON.stringify(getDefault),
|
|
() => {},
|
|
() => {}
|
|
)
|
|
|
|
this.props.route?.params.onSelectedPaymentCard && this.props.route?.params.onSelectedPaymentCard(getDefault);
|
|
this.setState({cards: this.filterData(res.data.cards), merchant: res.data, defaultSelectedCard: getDefault})
|
|
} else if(res.data && !res.data.cards) {
|
|
await DB.set(
|
|
"topupPaymentCards",
|
|
JSON.stringify(null),
|
|
() => {},
|
|
() => {}
|
|
)
|
|
|
|
this.props.route?.params.onSelectedPaymentCard && this.props.route?.params.onSelectedPaymentCard(null);
|
|
this.setState({cards: [], merchant: {}, defaultSelectedCard: null})
|
|
}
|
|
|
|
this.setState({ loading: false })
|
|
}, (error) => {
|
|
this.onError(error);
|
|
}, "Funding", "Fetch")
|
|
}
|
|
|
|
onError = (err) => {
|
|
if(err.toJSON().message === 'Network Error') {
|
|
Elements.nointernet2()
|
|
} else {
|
|
Alert.alert("Information", `\n${err.message}`);
|
|
}
|
|
|
|
this.setState({ loading: false })
|
|
}
|
|
|
|
filterData = (data) => {
|
|
const defaultcard = data.find(card => card.default);
|
|
const cards = data.filter(card => !card.default);
|
|
cards.unshift(defaultcard);
|
|
return cards;
|
|
}
|
|
|
|
getSelectedCard = async () => {
|
|
const card = await DB.get("topupPaymentCards");
|
|
if(card) {
|
|
this.setState({ defaultSelectedCard: JSON.parse(card) });
|
|
}
|
|
}
|
|
|
|
deleteCard = async () => {
|
|
this.setState({ loading: true, showModal: false })
|
|
|
|
const SESSION = await DB.session()
|
|
const { uuid } = this.state.deleteCard;
|
|
|
|
await REQUEST("paymaya_tokens/" + uuid, "delete", {'Authorization': SESSION.token}, {}, {}, async (res) => {
|
|
if(res.status === 1){
|
|
this.setState({ loading: false, showCardDeleted: true, deleteCard: null })
|
|
}
|
|
else {
|
|
this.setState({ loading: false })
|
|
}
|
|
}, (err) => {
|
|
this.onError(err);
|
|
}, "Card", "Delete")
|
|
}
|
|
|
|
submitPaymentCard = async (defaultSelectedCard) => {
|
|
this.setState({ loading: true })
|
|
const SESSION = await DB.session()
|
|
await REQUEST("paymaya_tokens/" + defaultSelectedCard.uuid, "patch", {'Authorization': SESSION.token}, {}, {}, async (res) => {
|
|
if(res.status === 1) {
|
|
if(defaultSelectedCard == null) {
|
|
return
|
|
}
|
|
|
|
await DB.set(
|
|
"topupPaymentCards",
|
|
JSON.stringify(defaultSelectedCard),
|
|
() => {
|
|
this.props.route?.params.onSelectedPaymentCard && this.props.route?.params.onSelectedPaymentCard(defaultSelectedCard)
|
|
this.props.navigation.goBack();
|
|
},
|
|
() => {}
|
|
)
|
|
}
|
|
|
|
this.setState({ loading: false })
|
|
}, (err) => {
|
|
this.onError(err);
|
|
}, "Card", "Add")
|
|
}
|
|
|
|
returnCardName = (card) => {
|
|
let newCard = card.cardType;
|
|
if(newCard.includes("-")) {
|
|
newCard = newCard.split("-")[0];
|
|
}
|
|
|
|
return newCard.toUpperCase();
|
|
}
|
|
|
|
onAddNewCard = async (response) => {
|
|
const { paymaya_token_uuid } = response;
|
|
|
|
this.setState({showCardAdded: true, newlyAddedCard: paymaya_token_uuid});
|
|
this.getFunding()
|
|
}
|
|
|
|
renderDeleteErrorModal = () => {
|
|
return (
|
|
<Modal
|
|
animationType="none"
|
|
transparent={true}
|
|
visible={this.state.showModal}>
|
|
<TouchableOpacity activeOpacity={1} onPress={() => {}} style={styles.centeredView}>
|
|
<View style={[styles.modalView, { backgroundColor: this.props.app_theme?.theme.dark ? this.props.app_theme?.theme.colors.border : Theme.colors.white }]}>
|
|
<Text style={{fontSize: 20, color: this.props.app_theme?.theme.colors.text, marginBottom: 18}}>Confirmation</Text>
|
|
<Text style={{textAlign: 'center', fontSize: 18, color: this.props.app_theme?.theme.colors.text, marginBottom: 37}}>Are you sure you want to delete this card?</Text>
|
|
<View style={{flexDirection: 'row'}}>
|
|
<TouchableOpacity onPress={() => this.setState({ showModal: false })} style={{
|
|
flex: 1,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
paddingVertical: 7,
|
|
marginRight: 6,
|
|
borderWidth: 1,
|
|
borderColor: Theme.colors.primary,
|
|
borderRadius: 5
|
|
}}>
|
|
<Text style={{
|
|
fontSize: 17,
|
|
color: Theme.colors.primary
|
|
}}>No</Text>
|
|
</TouchableOpacity>
|
|
<TouchableOpacity onPress={() => this.deleteCard()} style={{
|
|
flex: 1,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
marginLeft: 6,
|
|
paddingVertical: 7,
|
|
borderWidth: 1,
|
|
borderColor: Theme.colors.primary,
|
|
backgroundColor: Theme.colors.primary,
|
|
borderRadius: 5
|
|
}}>
|
|
<Text style={{
|
|
fontSize: 17,
|
|
color: Theme.colors.white
|
|
}}>Yes</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
</TouchableOpacity>
|
|
</Modal>
|
|
)
|
|
}
|
|
|
|
renderCardAdded = () => {
|
|
if(!this.state.newlyAddedCard) return null
|
|
|
|
let card = this.state?.cards.find(item => item?.uuid === this.state.newlyAddedCard);
|
|
if(card && this.state.showCardAdded && !this.state.loading) {
|
|
return (
|
|
<View style={{
|
|
position: 'absolute',
|
|
top: 0,
|
|
right: 0,
|
|
left: 0,
|
|
bottom: 0,
|
|
backgroundColor: 'rgba(0,0,0,.4)',
|
|
justifyContent: 'center',
|
|
alignItems: 'center'
|
|
}}>
|
|
<View style={{
|
|
backgroundColor: 'white',
|
|
width: Theme.screen.w * .8,
|
|
padding: 20,
|
|
alignItems: 'center'
|
|
}}>
|
|
<Image style={{height: 90, width: 90, resizeMode: 'contain', alignSelf: 'center'}} source={require('../../assets/pump_addcard.png')}/>
|
|
<Text style={{fontWeight: 'bold', textAlign: 'center', fontSize: 14, marginVertical: 20}}>{this.returnCardName(card)} ending in {card?.last4} has been{'\n'}successfully added!</Text>
|
|
|
|
<TouchableOpacity onPress={() => {this.setState({ showCardAdded: false, newlyAddedCard: null })}} style={{paddingVertical: 10, borderRadius: 5, marginTop: 10, width: 120, backgroundColor: Theme.colors.primary, alignItems: 'center'}}>
|
|
<Text style={{fontSize: 17, color: Theme.colors.white}}>OK</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
)
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
renderCardDeleted = () => {
|
|
if(this.state.showCardDeleted) {
|
|
return (
|
|
<View style={{
|
|
position: 'absolute',
|
|
top: 0,
|
|
right: 0,
|
|
left: 0,
|
|
bottom: 0,
|
|
backgroundColor: 'rgba(0,0,0,.4)',
|
|
justifyContent: 'center',
|
|
alignItems: 'center'
|
|
}}>
|
|
<View style={{
|
|
backgroundColor: 'white',
|
|
width: Theme.screen.w * .8,
|
|
padding: 20,
|
|
alignItems: 'center'
|
|
}}>
|
|
<Text style={{fontWeight: 'bold', fontSize: 17, marginBottom: 20}}>Deleted Successfully</Text>
|
|
<Text style={{textAlign: 'center', fontSize: 15, marginBottom: 10}}>Your card has been successfully{'\n'}deleted!</Text>
|
|
<TouchableOpacity onPress={() => {
|
|
this.setState({ showCardDeleted: false })
|
|
this.getFunding();
|
|
}} style={{paddingVertical: 5, borderRadius: 5, marginTop: 10, width: 120, backgroundColor: Theme.colors.primary, alignItems: 'center'}}>
|
|
<Text style={{fontSize: 17, color: Theme.colors.white}}>OK</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
)
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
renderCardList = () => {
|
|
return (
|
|
<FlatList
|
|
keyExtractor={(item, index) => index.toString()}
|
|
data={this.state.cards}
|
|
scrollEnabled={true}
|
|
showsVerticalScrollIndicator={false}
|
|
style={this.state.cards.length === 0 && {flex: 1}}
|
|
contentContainerStyle={this.state.cards.length === 0 && {flex: 1}}
|
|
ListEmptyComponent={() => (
|
|
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
|
|
<Image source={Assets.icons.empty_card} style={{height: 80, marginBottom: 10, resizeMode: 'contain'}}/>
|
|
<AdjustableText style={{color: Theme.colors.gray, fontSize: 15}}>Empty</AdjustableText>
|
|
</View>
|
|
)}
|
|
renderItem={({item, index}) => {
|
|
if(!item) return null;
|
|
|
|
let primary = item.default;
|
|
|
|
return (
|
|
<View style={{ flex: 1, flexDirection: 'row', marginLeft: 15 }}>
|
|
<TouchableOpacity activeOpacity={0.5} onPress={() => {
|
|
this.submitPaymentCard(item);
|
|
}} key={index} style={{ flex: 1, alignItems: 'center', justifyContent: 'center', flexDirection: 'row', backgroundColor: this.props.app_theme?.theme.dark ? this.props.app_theme?.theme.colors.background : Theme.colors.white, padding: 12 }}>
|
|
<View style={{borderColor: primary ? Theme.colors.primary : "gray", borderWidth: 2, width: 15, height: 15, borderRadius: 7.5, marginRight: 10, paddingHorizontal: 2, paddingVertical: 2}}>
|
|
{primary && <View style={{flex:1, borderRadius: 10, backgroundColor: Theme.colors.primary}} /> }
|
|
</View>
|
|
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'center' }}>
|
|
<Image source={returnIcon(item.cardType)} style={{ width: 40, height: 40, resizeMode: 'contain', marginRight: 5 }} />
|
|
<View>
|
|
<Text style={{ fontSize: 15, color: this.props.app_theme?.theme.colors.text, textAlign: 'left' }}>{`**** **** **** ${item.last4}`}</Text>
|
|
{primary && <Text style={{fontStyle: 'italic', fontSize: 11, color: '#6887ed'}}>Primary</Text>}
|
|
</View>
|
|
</View>
|
|
<View style={{ borderRadius: 100, alignItems: 'center', backgroundColor: 'white', flexDirection: 'row', justifyContent: 'flex-end' }}>
|
|
<TouchableOpacity onPress={() => this.setState({ deleteCard: item, showModal: true })}
|
|
style={{ paddingVertical: 5 }}>
|
|
<Icon.EvilIcons name={"trash"} size={40} color={Theme.colors.primaryDark} />
|
|
</TouchableOpacity>
|
|
</View>
|
|
</TouchableOpacity>
|
|
</View>
|
|
)
|
|
}}
|
|
numColumns={1}
|
|
/>
|
|
)
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<CustomSafeArea>
|
|
<CustomHeader
|
|
title={'Card List'}
|
|
onBackPress={() => this.props.navigation.goBack()}
|
|
back={true}
|
|
menu={false}
|
|
navigation={this.props.navigation}
|
|
/>
|
|
<Elements.loaderView
|
|
title="Validating"
|
|
message="Please wait..."
|
|
isDarkMode={this.props.app_theme?.theme.dark}
|
|
backgroundColor={this.props.app_theme?.theme.colors.border}
|
|
color={this.props.app_theme?.theme.colors.text}
|
|
visible={this.state.loading} />
|
|
<View style={{ flex: 1 }}>
|
|
{this.renderCardList()}
|
|
|
|
<TouchableOpacity
|
|
onPress={() => this.props.navigation.navigate('TopupPaymentMethod', { onAddNewCard: (newcard) => this.onAddNewCard(newcard), merchant: this.state.merchant })}
|
|
style={{alignSelf: 'center'}}
|
|
>
|
|
<View style={{flexDirection: 'row', padding: 5}}>
|
|
<Icon.MaterialIcons
|
|
name="credit-card"
|
|
size={20}
|
|
color={Theme.colors.primary}
|
|
/>
|
|
<Text
|
|
style={{
|
|
fontFamily: 'Arial',
|
|
color: Theme.colors.primary,
|
|
marginLeft: 10,
|
|
marginBottom: 10,
|
|
fontSize: 16,
|
|
}}>
|
|
Add a Card
|
|
</Text>
|
|
</View>
|
|
</TouchableOpacity>
|
|
</View>
|
|
{this.renderCardAdded()}
|
|
{this.renderCardDeleted()}
|
|
{this.renderDeleteErrorModal()}
|
|
</CustomSafeArea>
|
|
)
|
|
}
|
|
}
|
|
|
|
const mapStateToProps = (state) => {
|
|
return {
|
|
app_theme: state.appThemeReducer.theme
|
|
}
|
|
}
|
|
|
|
export default connect(mapStateToProps, null)(TopupPaymentList)
|
|
|
|
|
|
const styles = StyleSheet.create({
|
|
centeredView: {
|
|
flex: 1,
|
|
justifyContent: "center",
|
|
backgroundColor: '#00000090',
|
|
},
|
|
modalView: {
|
|
margin: 25,
|
|
borderRadius: 10,
|
|
paddingHorizontal: 31,
|
|
paddingVertical: 20,
|
|
alignItems: "center",
|
|
},
|
|
}) |