unioil-loyalty-rn-app/app/screens/login/index.js

295 lines
12 KiB
JavaScript

import * as React from 'react';
import {
StyleSheet,
TouchableOpacity,
View,
Text,
Image,
Alert,
Keyboard,
ImageBackground,
AppState,
Linking
} from 'react-native';
import { ContactOptions } from '../../components/contact.action';
import { connect } from "react-redux";
import DeviceInfo from "react-native-device-info";
import NetInfo from "../../components/netstatus";
import Assets from '../../components/assets.manager.js';
import Elements from '../../components/elements.js';
import Theme from '../../components/theme.style.js';
import Icon from '../../components/icons.js';
import REQUEST from '../../components/api/';
import DB from '../../components/storage/';
import CustomInput from '../../components/custominput';
import CustomSafeArea from '../../components/safeArea.component';
import { Actionsheet, StatusBar } from 'native-base';
import elements from '../../components/elements.js';
import { getOS } from '../../utils/device';
import { compareVersions } from '../route';
import { openModal } from '../../redux/actions/AlertActions';
import { getNavigationRef } from '../../utils/navigation';
class AddAccountCard extends React.PureComponent {
constructor(props) {
super(props)
}
state = {
loading: false,
focus: false,
activeInput: null,
cardnumber: "",
deviceUUID: "",
valid: false,
mobilenumber: "",
agree: false,
openOptions: false,
appState: AppState.currentState
}
componentDidMount() {
if(this.props.route.params?.reset){
this.reset()
}
AppState.addEventListener('change', this._handleAppStateChange)
this.init()
}
_handleAppStateChange = (nextAppState) => {
if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
this.validateAppVersion()
}
this.setState({ appState: nextAppState })
}
componentWillUnmount() {
}
init = async () => {
await DB.reset()
this.setState({ deviceUUID: await DB.get("deviceUUID") })
this.validateAppVersion();
}
validateAppVersion = async () => {
const navigationRef = getNavigationRef();
if(navigationRef.getCurrentRoute().name !== "Login") return;
await REQUEST(getOS() === 'ios' ? "getIOSAppVersion" : "getAndroidAppVersion", "get", {}, {}, {}, (res) => {
if(res.status == 1) {
let currentVersion = DeviceInfo.getReadableVersion()
let latestVersion = res.data.version
let is_force_update = parseInt(res.data.update_action)
let isNewVersion = compareVersions(currentVersion, "<", latestVersion)
if(isNewVersion) {
//Silent update
if(is_force_update == 2) return
const openModalData = {
open: true,
title: 'Update Information',
body: '\n' + res.data.update_message,
yesButtonOnly: true,
yesText: "Update Now",
yesCB: () => {
const link = getOS() === 'ios' ? 'itms-apps://apps.apple.com/ph/app/unioil/id1517293002?l=id' : 'market://details?id=com.project.yondu.unioilloyaltyapp';
Linking.openURL(link);
},
backdropCancellable: false
}
//Update
if(is_force_update === 0) {
openModalData.yesButtonOnly = false;
openModalData.noText = 'No';
openModalData.backdropCancellable = true
}
//For update
this.props.openModal(openModalData);
}
}
}, (err) => {
Alert.alert("Information", `\n${err.message}`);
}, "AppVersion", "Fetch")
}
reset = () => {
this.setState({
loading: false,
focus: false,
activeInput: null,
cardnumber: "",
deviceUUID: "",
valid: false,
mobilenumber: "",
agree: false
})
}
onErrorWarning = (success) => {
if(Platform.OS == 'ios'){
setTimeout(() => {
Alert.alert("Information", '\n' + success.message)
}, 700)
}else{
Alert.alert("Information", '\n' + success.message)
}
}
onSubmit = () => {
Keyboard.dismiss();
NetInfo.netstatus(isConnected => {
if(isConnected) {
this.setState({ loading: true })
this.validateMobileNumber(success => {
if(success.data.is_valid == 1 && success.status == 1){
this.setState({ loading: false })
this.props.navigation.navigate("LoginSendOTP", {
lcard_uuid: success.data.user_id,
mobile_number: Theme.formatter.MBNF(this.state.mobilenumber, 63),
card_number: success.data.card_number
})
} else {
this.setState({ loading: false })
this.onErrorWarning(success)
}
}, error => {
const message = error.message;
Alert.alert("Information", '\n' + message)
this.setState({ loading: false })
})
} else {
this.setState({ loading: false })
Elements.nointernet2(this.props)
}
})
}
onAgree = () => {
this.setState({ agree: this.state.agree == false ? true : false })
}
validateMobileNumber = async (successCallback, errorCallback) => {
let phoneNumber = Theme.formatter.MBNF(this.state.mobilenumber, "")
if(phoneNumber == null) {
setTimeout(() => {
Alert.alert("Information", '\n' + "Invalid mobile number")
}, 700)
this.setState({ loading: false })
return
}
await REQUEST("login_mobile", "post", {}, {}, {
deviceUUID: this.state.deviceUUID,
mobile_number: phoneNumber
}, function(data){
successCallback(data)
}, function(error){
errorCallback(error)
}, "Number", "Validate")
}
render() {
let version = `v${DeviceInfo.getReadableVersion()}`
return (
<CustomSafeArea customStatusBar={true}>
<ImageBackground
source={Assets.bg.login_bg}
style={{ flex: 1 }}>
<View style={{flex: 1}}>
<Elements.loaderView
title="Validating"
message="Please wait, validating your card number..."
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}}>
<View style={{width: '100%', height: 90, alignSelf: 'center', marginTop: 50 }}>
<Image source={Assets.logo.unioil} style={{width: '100%', height: '83%', resizeMode: 'contain'}} />
</View>
<View style={{flex: 1, alignItems: 'center'}}>
<Text style={{alignSelf: 'center', fontFamily: 'Arial', fontSize: 25, paddingLeft: 15, paddingRight: 15, paddingBottom: 15, color: Theme.colors.white, fontStyle: 'italic' }}>Make Life Rewarding</Text>
<Text style={{alignSelf: 'center', marginTop: 5, color: Theme.colors.white, fontFamily: 'Arial', fontSize: 16}}>
Enter your mobile number.
</Text>
<View>
<CustomInput
cantStartWithZero={true}
isMobileNumber={true}
textColor={Theme.colors.white}
onChangeText={(val) => {
let value = val.includes(".") ? val.replace(".", "") : val
this.setState({ mobilenumber: value, valid: value.length == 13 ? true : false, agree: false })
}}
/>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
<TouchableOpacity style={{flex: 0, padding: 8}} disabled={!this.state.valid} onPress={() => this.state.valid ? this.onAgree() : null}>
{!this.state.agree || !this.state.valid ? <Icon.Feather name="square" size={20} color={this.state.valid ? Theme.colors.black : this.props.app_theme?.theme.colors.border} /> : <Icon.AntDesign name="checksquare" color={Theme.colors.primary} size={20} />}
</TouchableOpacity>
<View style={{flexDirection: 'row', padding: 8}}>
<Text style={{ color: Theme.colors.white }}>I agree to Unioil's </Text>
<TouchableOpacity onPress={() => this.props.navigation.navigate("TermsConditions")}>
<Text style={{color: Theme.colors.white, textDecorationLine: 'underline'}}>Data Privacy Policy.</Text>
</TouchableOpacity>
</View>
</View>
</View>
<View style={{alignItems: 'center', justifyContent: 'flex-end', marginTop: Theme.screen.h * .02, marginBottom: Theme.screen.h * .01 }}>
<TouchableOpacity onPress={() => this.onSubmit()} disabled={(!this.state.agree || !this.state.valid)} style={{padding: Theme.screen.h * .02, width: Theme.screen.w * .73, borderRadius: 10, backgroundColor: (this.state.agree && this.state.valid) ? Theme.colors.primary : Theme.colors.darkGray + "40"}}>
<Text style={{fontSize: 16, fontFamily: 'Arial', textAlign: 'center', color: '#fff'}}>Log In</Text>
</TouchableOpacity>
</View>
<View style={{alignItems: 'center', marginBottom: Theme.screen.h * .01}}>
<Text style={{fontSize: 16, fontFamily: 'Arial', color: Theme.colors.textPrimary, color: '#fff'}}>or</Text>
</View>
<View style={{alignItems: 'center', justifyContent: 'flex-end'}}>
<TouchableOpacity onPress={() => this.props.navigation.navigate("EnrollActivate", {screen: "Login"}) } style={{padding: Theme.screen.h * .015, width: Theme.screen.w * .65, borderRadius: 10, borderWidth: 2, borderColor: Theme.colors.white}}>
<Text style={{fontSize: 16, fontFamily: 'Arial', textAlign: 'center', color: Theme.colors.white}}>Activate your Card</Text>
</TouchableOpacity>
</View>
<View style={{alignItems: 'center', justifyContent: 'flex-end', marginTop: Theme.screen.h * .01}}>
<TouchableOpacity onPress={() => this.props.navigation.navigate("ApplySelectCard") } style={{padding: Theme.screen.h * .015, width: Theme.screen.w * .65, borderRadius: 10, borderWidth: 2, borderColor: Theme.colors.white}}>
<Text style={{fontSize: 16, fontFamily: 'Arial', textAlign: 'center', color: Theme.colors.white}}>Apply for a Card</Text>
</TouchableOpacity>
</View>
<TouchableOpacity onPress={() => this.props.navigation.navigate("TermsConditions") } style={{marginTop: Theme.screen.h * .015, width: Theme.screen.w - 80}}>
<Text style={{fontSize: 16, fontFamily: 'Arial', textAlign: 'center', color: Theme.colors.white}}>Enter as Guest</Text>
</TouchableOpacity>
</View>
</View>
</View>
<View style={{flexDirection: 'row', marginBottom: 5}}>
<TouchableOpacity onPress={() => {this.setState({ openOptions: true })}} style={{padding: 15, alignItems: 'flex-start', flex: 1}}>
<Text style={{fontSize: 16, fontFamily: 'Arial', textAlign: 'left', color: Theme.colors.white}}>Contact Us</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {}} style={{padding: 15, justifyContent: 'flex-end', flex: 1}}>
<Text style={{fontSize: 16, fontFamily: 'Arial', textAlign: 'right', color: Theme.colors.white}}>{version}</Text>
</TouchableOpacity>
</View>
<ContactOptions isOpen={this.state.openOptions} onClose={() => this.setState({ openOptions: false })}/>
</ImageBackground>
</CustomSafeArea>
)
}
}
const mapStateToProps = (state) => {
return {
app_theme: state.appThemeReducer.theme
}
}
const mapDispatchToProps = {
openModal
}
export default connect(mapStateToProps, mapDispatchToProps)(AddAccountCard);