unioil-loyalty-rn-app/app/screens/payatpump/fragments/stationdetailspanel.js

430 lines
18 KiB
JavaScript

import React from 'react';
import { useState, useEffect, useRef } from 'react';
import { connect } from 'react-redux';
import {
Text,
View,
TouchableOpacity,
Linking,
Platform,
Alert,
Modal,
FlatList,
Image,
ActivityIndicator,
} from 'react-native';
import {
NavigationApps,actions,
googleMapsTravelModes,
mapsTravelModes
} from "../../../components/navigationapps";
import { Divider } from 'native-base';
import { noInternetError } from '../../../utils/errorHandler';
import REQUEST_POST_PAY from '../../../components/api/postpayapi';
import Assets from '../../../components/assets.manager.js';
import Theme from '../../../components/theme.style.js';
import Icon from '../../../components/icons';
import DB from '../../../components/storage/';
const styles = {
container: {
flex: 1,
backgroundColor: '#f8f9fa',
alignItems: 'center',
justifyContent: 'center'
},
panel: {
flex: 1,
backgroundColor: 'white',
position: 'relative'
},
panelHeader: {
height: 60,
backgroundColor: Theme.colors.lightGray,
alignItems: 'center',
justifyContent: 'center'
},
centeredView: {
flex: 1,
justifyContent: "center",
backgroundColor: '#00000090',
},
modalView: {
margin: 25,
padding: 20,
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5
},
selectedPumpBorder: {
backgroundColor: '#ffbaa3',
borderRadius: 10,
borderWidth: 2,
borderColor: Theme.colors.primary,
padding: 5
},
unselectedPumpBorder: {
borderRadius: 10,
borderWidth: 2,
padding: 5
}
}
const PayatpumpStationDetails = (props) => {
const [panel, setpanel] = useState(null)
const [updateFavorite, setUpdateFavorite] = useState(0)
const [updateFavoriteVal, setUpdateFavoriteVal] = useState(false)
const [showModal, setShowModal] = useState(false)
const [error, setError] = useState(null)
const [selectedPump, setSelectedPump] = useState(null)
const [selectedPumpIndex, setSelectedPumpIndex] = useState(0)
const [initiateCancel, setInitiateCancel] = useState(false)
const [initiateProceed, setInitiateProceed] = useState(false)
const [confirmProceed, setConfirmProceed] = useState(false)
const pumpListRef = useRef(null);
useEffect(() => {
if(props.visible){
panel.show()
}
return setpanel(null)
}, [props.visible])
const renderStationDetails = (station, onPress) => {
// filter the value of key pair if it is empty
var filteredAddress = Object.entries(station.address).filter(([key, value]) => {
if(key === "stateCode") return `${value.replace(/\s/g, '')}`
return `${value}`
})
.map(([key, value]) => `${value}`)
return (
<TouchableOpacity activeOpacity={1} style={{backgroundColor: props.app_theme?.theme.dark ? props.app_theme?.theme.colors.border : Theme.colors.white, height: Platform.OS === 'android' ? 160 : 140 }}>
<View style={{flex: 0, padding: 15, flexDirection: 'row'}}>
<View style={{flex: 5}}>
<Text style={{fontFamily: 'arial',color: props.app_theme?.theme.dark ? props.app_theme?.theme.colors.text : Theme.colors.textPrimary, padding: 5, width: '90%', fontSize: 13}}>{filteredAddress.join(', ').toString()}</Text>
<View style={{padding: 5, width: '90%', flexDirection: 'row', alignItems: 'center'}}>
<Text style={{fontFamily: 'arial', color: '#6887ed', fontSize: 14}}>Contact: </Text>
<View style={{fontFamily: 'arial', color: Theme.colors.textPrimary, fontSize: 14}}>
<TouchableOpacity onPress={() => {
let url = Platform.OS == 'ios' ? 'telprompt:' : 'tel:'
Linking.canOpenURL(url).then(supported => {
if (!supported) {
alert("Call Not Supported")
} else {
Alert.alert("Call Customer Service", '\n' + "You will be redirected to the dialer to call Unioil Customer Service", [
{
text: 'Cancel',
style: 'cancel',
},{
text: 'OK', onPress: () => Linking.openURL(`${url}${num}`)
}
],
{cancelable: true})
return true
}
}).catch(err => {
console.error('An error occurred', err)
})
}}>
<Text style={{color: '#6887ed'}}>{station.phone}</Text>
</TouchableOpacity>
</View>
</View>
<Text style={{fontFamily: 'arial',color: props.app_theme?.theme.dark ? props.app_theme?.theme.colors.text : Theme.colors.textPrimary, padding: 0, width: '90%', fontSize: 13}}></Text>
<View style={{flexDirection: 'row', paddingBottom: 10, alignItems: 'center'}}>
<View style={{flex: 1, alignItems: 'flex-end'}}>
<TouchableOpacity
onPress={() => {
if(props.data.fuelService?.fuelingPoints == undefined) {
Alert.alert("Information", '\n' + "No pump available.")
} else {
setShowModal(true)
}
}}
style={{ backgroundColor: Theme.colors.primary, padding: 12, alignItems: 'center', justifyContent: 'center', borderRadius: 5 }}>
<Text style={{ color: Theme.colors.white, fontSize: 12 }}>PUMP AND GO</Text>
</TouchableOpacity>
</View>
</View>
</View>
</View>
{PumpSelectorModalView()}
</TouchableOpacity>
)
}
const resetFlags = () => {
setShowModal(false)
setSelectedPump(null)
setSelectedPumpIndex(null)
setInitiateCancel(false)
setInitiateProceed(false)
setConfirmProceed(false)
}
const initiateTransaction = async () => {
let store = props.data
let pump = selectedPump
let body = {
store_id: store.storeId,
pump: pump.pumpNumber
}
REQUEST_POST_PAY('postClaim', 'post', {}, {}, body, async (res) => {
if(res.status) {
resetFlags()
if(!res.data.saleItems) {
return Alert.alert('Information', '\n' + "No Transaction available");
}
props.onTransaction(res.data, store.storeId, selectedPump)
} else {
resetFlags()
setTimeout(() => {
Alert.alert('Information', res?.message?.key == 'buy_gas_pump_unavailable' ? '\n' + `Pump ${pump.pumpNumber} is not yet available. Try again.` : res?.message.key == 'pay_outside_petrozone_error' ? '\n' + res?.message.partnerApiMessage : '\n' + 'Failed transaction. Try again.')
}, 300)
}
}, (error) => {
resetFlags()
setTimeout(() => {
if(!noInternetError(error)) {
Alert.alert('Information', error?.message?.key == 'buy_gas_pump_unavailable' ? '\n' + `Pump ${pump.pumpNumber} is not yet available. Try again.` : error?.message?.key == 'pay_outside_petrozone_error' ? '\n' + error?.ermessageror?.partnerApiMessage : '\n' + 'Failed transaction. Try again.')
} else {
noInternetError(error);
}
}, 300)
})
}
const PumpSelectorModalView = () => {
return (
<Modal
animationType="none"
transparent={true}
visible={showModal}>
<View activeOpacity={1} style={styles.centeredView}>
<View style={[styles.modalView, { backgroundColor: props.app_theme?.theme.dark ? props.app_theme?.theme.colors.border : Theme.colors.white }, (!initiateCancel && !initiateProceed && !confirmProceed) && { width: Theme.screen.w * .8, borderRadius: 10, alignSelf: 'center', height: Theme.screen.h * .45}]}>
{!initiateCancel && !confirmProceed && (<TouchableOpacity style={{ width: 20, height: 20, alignSelf: 'flex-end', borderWidth: 1, borderColor: Theme.colors.primary, borderRadius: 30, alignItems: 'center', justifyContent: 'center' }}
onPress={() => {
setInitiateCancel(true)
if(initiateProceed) {
setInitiateProceed(false)
}
}}>
<Icon.Entypo name='cross' size={20} style={{color: Theme.colors.primary, bottom: 1, right: 0.5 }} />
</TouchableOpacity>)}
{(!initiateCancel && !initiateProceed && !confirmProceed) && PumpListView(selectedPump)}
{(initiateCancel && !initiateProceed && !confirmProceed) && CancelPumpSelectorView()}
{(initiateProceed && !initiateCancel && !confirmProceed) && ProceedPumpSelectorView()}
{confirmProceed && ConfirmPumpSelectorView()}
</View>
</View>
</Modal>
)
}
const CancelPumpSelectorView = () => {
return (
<>
<View style={{ marginTop: 10, marginBottom: 15 }}>
<Text style={{ color: props.app_theme?.theme.colors.text, fontSize: 18, textAlign: 'center' }}>Are you sure you want to{'\n'}cancel the transaction?</Text>
</View>
<View style={{ flexDirection: 'row', justifyContent: 'center' }}>
<TouchableOpacity onPress={() => {
setInitiateCancel(false)
selectedPump != null ? setInitiateProceed(true) : setInitiateProceed(false)
}} style={{ width: 100, paddingVertical: 5, margin: 12, backgroundColor: Theme.colors.white, borderColor: Theme.colors.primary, borderWidth: 0.5, alignItems: 'center', justifyContent: 'center', borderRadius: 5 }}>
<Text style={{ color: Theme.colors.primary, fontSize: 17, textAlign: 'center', fontWeight: 'bold' }}>No</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {
setShowModal(false)
setInitiateCancel(false)
setInitiateProceed(false)
setSelectedPump(null)
setSelectedPumpIndex(null)
}} style={{ width: 100, paddingVertical: 5, margin: 12, backgroundColor: Theme.colors.primary, justifyContent: 'center', alignItems: 'center', borderRadius: 5 }}>
<Text style={{ color: Theme.colors.white, fontSize: 17, textAlign: 'center', fontWeight: 'bold' }}>Yes</Text>
</TouchableOpacity>
</View>
</>
)
}
const ProceedPumpSelectorView = () => {
let message = selectedPump != null ? `This will process your transaction at` : "No selected pump."
return (
<View>
<View style={{ alignItems: 'center' }}>
<Image source={Assets.pumps.pump_logo} style={{padding: 40, width: 50, height: 50, resizeMode: 'contain'}} />
</View>
<View style={{ alignItems: 'center', padding: 5, marginBottom: 15 }}>
<Text style={{ fontSize: 19, textAlign: 'center', color: props.app_theme?.theme.colors.text }}>{message} {selectedPump != null && <Text style={{fontWeight: 'bold'}}>Pump {selectedPump.pumpNumber}.</Text>}</Text>
</View>
<View style={{ alignItems: 'center', padding: 5, marginBottom: 30 }}>
<Text style={{ fontSize: 19, textAlign: 'center', color: props.app_theme?.theme.colors.text }}>Please ensure that this is the correct pump and click OK below to proceed.</Text>
</View>
<View style={{ alignItems: 'center' }}>
<TouchableOpacity onPress={() => {
setInitiateCancel(false)
setInitiateProceed(false)
if(selectedPumpIndex > 3) {
setTimeout(() => {
pumpListRef.current?.scrollToIndex({ animated: true, index: Math.floor(selectedPumpIndex / 2) })
}, 500)
}
}}
style={{ paddingVertical: 5, width: 120, backgroundColor: Theme.colors.primary, justifyContent: 'center', alignItems: 'center', borderRadius: 5 }}>
<Text style={{ fontSize: 17, color: Theme.colors.white, textAlign: 'center' }}>OK</Text>
</TouchableOpacity>
</View>
</View>
)
}
const ConfirmPumpSelectorView = () => {
let message = selectedPump != null ? "Processing..." : "No selected pump."
return (
<>
<View style={{backgroundColor: 'transparent', alignItems: 'center', justifyContent: 'center' }}>
{
Platform.select({
ios: <Image source={Assets.icons.animated_loading} style={{width: 120, height: 120, backgroundColor: "orange"}} />,
android: <ActivityIndicator
size={140}
color={Theme.colors.primary}
/>
})
}
<View style={{ marginHorizontal: 40, marginTop: 10 }}>
<Text style={{ color: props.app_theme?.theme.colors.text, fontSize: 24, textAlign: 'center' }}>{message}</Text>
</View>
</View>
</>
)
}
const PumpListView = (currentSelectedPump) => {
return (
<>
<Text style={{ color: Theme.colors.primary, fontSize: 18, fontWeight: 'bold', textAlign: 'center', marginBottom: 20}}>Please {selectedPump ? "confirm" : "select"} your Pump no.{'\n'} to process the payment.</Text>
<FlatList
ref={pumpListRef}
keyExtractor={(item, index) => index.toString()}
contentContainerStyle={{ alignItems: 'center'}}
data={props.data.fuelService?.fuelingPoints}
scrollEnabled={true}
showsVerticalScrollIndicator={false}
renderItem={({item, index}) => {
let available = item.pumpStatus == "Available"
return (
<TouchableOpacity onPress={() => {
setInitiateProceed(true)
setSelectedPump(item)
setSelectedPumpIndex(index)
}}
style={{marginHorizontal: 15, marginBottom: 10, borderColor: (currentSelectedPump != null && currentSelectedPump.pumpNumber == item.pumpNumber) ? Theme.colors.primary : "transparent", borderWidth: 4, borderRadius: 15}}>
<Image source={available ? Assets.pumps.plain_pump : Assets.pumps.plain_pump_grey} style={{width: 80, height: 80, resizeMode: 'contain' }} />
<View style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
alignItems: 'center',
justifyContent: 'center'
}}>
<Text style={{
left: -9,
bottom: -10,
color: 'white',
fontWeight: 'bold',
fontSize: 19
}}>{index + 1}</Text>
</View>
</TouchableOpacity>
)
}}
numColumns={2}
/>
<Divider style={{backgroundColor: Theme.colors.primary, marginTop: 2}}/>
<TouchableOpacity
disabled={!selectedPump}
style={{ width: 120, paddingVertical: 5, marginTop: 15, backgroundColor: selectedPump != null ? Theme.colors.primary : Theme.colors.darkGray, alignItems: 'center', justifyContent: 'center', borderRadius: 5 }}
onPress={() => {
if(selectedPump != null) {
setConfirmProceed(true)
initiateTransaction()
}
}}>
<Text style={{ color: Theme.colors.white, fontSize: 17 }}>OK</Text>
</TouchableOpacity>
</>
)
}
if(props.data === null) {
return null
}
return (
<View style={{justifyContent: 'flex-end'}}>
<View style={[styles.panelHeader, {backgroundColor: props.app_theme?.theme.dark ? Theme.colors.darkGray : Theme.colors.lightGray}]}>
<View style={{flexDirection: 'row', padding: 15}}>
<Text numberOfLines={1} style={{flex: 1, paddingTop: 17, justifyContent: 'center', color: props.app_theme?.theme.dark ? props.app_theme?.theme.colors.text : Theme.colors.darkGray, fontSize: 16, fontWeight: 'bold'}}>
{props.data.storeName}
</Text>
<View style={{flex: 0, justifyContent: 'center'}}>
<TouchableOpacity onPress={() => {}} activeOpacity={1} style={{top: -25}}>
<View style={{width: 60, justifyContent: 'center', alignItems: 'center', height: 60, borderRadius: 30, backgroundColor: Theme.colors.primary, elevation: 10}}>
{(props.data && props.data.address != undefined && props.data.address != "") ?
<NavigationApps
iconSize={35}
row
modalVisible={true}
viewMode="sheet"
actionSheetBtnCloseTitle="Cancel"
actionSheetBtnOpenTitle={<Icon.FontAwesome name="location-arrow" color="#fff" size={25} />}
actionSheetTitle="Choose an application to view the route"
address={props.data.storeName} // address to navigate by for all apps
waze={{ address: props.data.address, lat: props.data.geoLocation.latitude, lon: props.data.geoLocation.longitude, action: actions.navigateByLatAndLon}} // specific settings for waze
googleMaps={{ address: props.data.address, lat: props.data.geoLocation.latitude, lon: props.data.geoLocation.longitude, action: actions.navigateByAddress, travelMode:googleMapsTravelModes.driving}} // specific settings for google maps
maps={{ address: props.data.address, lat: props.data.geoLocation.latitude, lon: props.data.geoLocation.longitude, action: actions.navigateByAddress, travelMode:mapsTravelModes.driving}} /> // specific settings for maps
: null}
</View>
<Text style={{color: Theme.colors.primary}}>Directions</Text>
</TouchableOpacity>
</View>
</View>
</View>
{renderStationDetails(props.data, props.onClick)}
</View>
);
}
const mapStateToProps = (state) => {
return {
app_theme: state.appThemeReducer.theme
}
}
export default connect(mapStateToProps, null)(PayatpumpStationDetails)