diff --git a/ios/Invest/Info.plist b/ios/Invest/Info.plist index 9cdea26..3e80920 100644 --- a/ios/Invest/Info.plist +++ b/ios/Invest/Info.plist @@ -6,6 +6,8 @@ <array> <string>dcv.investcustomer.vn</string> </array> + + <key>CFBundleDevelopmentRegion</key> <string>en</string> <key>CFBundleDisplayName</key> @@ -42,6 +44,8 @@ <key>LSApplicationQueriesSchemes</key> <array> <string>itms-apps</string> + <string>tel</string> + <string>telprompt</string> </array> <key>LSRequiresIPhoneOS</key> <true/> diff --git a/src/Config/Functions.js b/src/Config/Functions.js index 9675e39..2f3e038 100644 --- a/src/Config/Functions.js +++ b/src/Config/Functions.js @@ -5,15 +5,43 @@ import { Alert, Text, PermissionsAndroid, + Linking, } from 'react-native'; import moment from 'moment'; import _ from 'lodash'; import I18n from '../helper/i18/i18n'; import AppText from '../components/AppText'; - -import {DETAILNEW, TABNAVIGATOR} from '../routers/ScreenNames'; +import AsyncStorage from '@react-native-community/async-storage'; +import {DETAILNEW, TABNAVIGATOR, AUTHEN} from '../routers/ScreenNames'; import R from '../assets/R'; +export const logout = (navigation) => { + AsyncStorage.clear(); + navigation.reset({ + index: 1, + routes: [{name: AUTHEN}], + }); +}; + +export const callNumber = (phone) => { + console.log('callNumber ----> ', phone); + let phoneNumber = phone; + if (Platform.OS !== 'android') { + phoneNumber = `telprompt:${phone}`; + } else { + phoneNumber = `tel:${phone}`; + } + Linking.canOpenURL(phoneNumber) + .then((supported) => { + if (!supported) { + Alert.alert('Phone number is not available'); + } else { + return Linking.openURL(phoneNumber); + } + }) + .catch((err) => console.log(err)); +}; + export const convertScreen = (name) => { switch (name) { case 'CUSTOMER_NEWS': diff --git a/src/Screens/Account/PacrtCQG/FeePro.js b/src/Screens/Account/PacrtCQG/FeePro.js index 02aa438..35c45bd 100644 --- a/src/Screens/Account/PacrtCQG/FeePro.js +++ b/src/Screens/Account/PacrtCQG/FeePro.js @@ -26,6 +26,19 @@ const FeePro = (props) => { setListItem(newList); }, [props.data]); + useEffect(() => { + const newList = data.map((e) => { + console.log(props.listRegister); + if (props.listRegister.includes(e.id)) { + return {...e, selected: true}; + } else { + return {...e, selected: false}; + } + }); + + setListItem(newList); + }, [props.listRegister]); + const onSelected = (selected) => { if (selected.id == 10) { const newList = listItem.map((e) => { diff --git a/src/Screens/Account/PacrtCQG/Footer.js b/src/Screens/Account/PacrtCQG/Footer.js index 6195b4c..53aa035 100644 --- a/src/Screens/Account/PacrtCQG/Footer.js +++ b/src/Screens/Account/PacrtCQG/Footer.js @@ -9,6 +9,9 @@ const Footer = (props) => { return ( <View style={{flex: 1, paddingHorizontal: 10, marginTop: 10}}> <View style={{flexDirection: 'row', marginVertical: 5}}> + <Text style={styles.txtTitle}> + {I18n.t('Provisional')}:{toPriceVnd(props.price)} + </Text> <AppText i18nKey={'Open_account_demo'} style={styles.txtTitle} /> <TouchableOpacity onPress={() => @@ -17,9 +20,6 @@ const Footer = (props) => { <AppText i18nKey={'Here'} style={styles.txtLink} /> </TouchableOpacity> </View> - <Text style={styles.txtTitle}> - {I18n.t('Provisional')}:{toPriceVnd(props.price)} - </Text> <View style={{ justifyContent: 'center', diff --git a/src/Screens/Account/PacrtCQG/PacketCQG.js b/src/Screens/Account/PacrtCQG/PacketCQG.js index 5548568..1a382fe 100644 --- a/src/Screens/Account/PacrtCQG/PacketCQG.js +++ b/src/Screens/Account/PacrtCQG/PacketCQG.js @@ -8,7 +8,11 @@ import ContainerTop from './ContainerTop'; import WrapNomarl from './WrapNomarl'; import Footer from './Footer'; import FeePro from './FeePro'; -import {getListPacketCQG, openCQG} from '../../../apis/Functions/packetCQG'; +import { + getListPacketCQG, + openCQG, + updateCQG, +} from '../../../apis/Functions/packetCQG'; import {connect} from 'react-redux'; import {showLoading, hideLoading} from '../../../actions/loadingAction'; import {useNavigation} from '@react-navigation/native'; @@ -24,6 +28,8 @@ const PacketCQG = (props) => { const [feePro, setFeePro] = useState({data: [], title: ''}); const [totalMD, setTotalMD] = useState(0); const [totalTB, setTotalTB] = useState(0); + const [isUpdate, setIsUpdate] = useState(false); + const [listRegister, setListRegister] = useState([]); const navigate = useNavigation(); @@ -50,9 +56,14 @@ const PacketCQG = (props) => { const onClick = async () => { const newList = listData.map((e) => e.id); - + let res; props.showLoading(); - const res = await openCQG({packages: newList}); + if (isUpdate) { + res = await updateCQG({packages: newList}); + } else { + res = await openCQG({packages: newList}); + } + props.hideLoading(); if (res.data.code == 200) { props.saveUserToRedux(res.data.data); @@ -117,14 +128,23 @@ const PacketCQG = (props) => { }; const getData = async () => { const res = await getListPacketCQG({}); - console.log(res.data.data.fee.data); if ((res.data.code = 200 && res.data.data)) { - setListData(res.data.data.fee.data); - setFee(res.data.data.fee); setFeeConnect(res.data.data.fee_connect); setFeeNonPro(res.data.data.fee_pro); setFeePro(res.data.data.fee_non_pro); + + if (res.data.package_register.length > 0) { + setListData(res.data.package_register); + const temp = res.data.package_register.filter( + (e) => e.id != 1 && e.id != 2, + ); + const listId = temp.map((e) => e.id); + setListRegister(listId); + setIsUpdate(true); + } else { + setListData(res.data.data.fee.data); + } } else { showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message); } @@ -142,11 +162,13 @@ const PacketCQG = (props) => { onRemovePacket={onRemovePacket} onChoosePacket={onChoosePacket} data={feeConnect} + listRegister={listRegister} /> <WrapNomarl onRemovePacket={onRemovePacket} onChoosePacket={onChoosePacket} data={feeNonPro} + listRegister={listRegister} /> <FeePro @@ -157,6 +179,7 @@ const PacketCQG = (props) => { onRemoveAllMD={onRemoveAllMD} onRemoveAllTB={onRemoveAllTB} data={feePro} + listRegister={listRegister} /> <Footer onClick={onClick} price={price} /> diff --git a/src/Screens/Account/PacrtCQG/WrapNomarl.js b/src/Screens/Account/PacrtCQG/WrapNomarl.js index c2a08a9..1e52e92 100644 --- a/src/Screens/Account/PacrtCQG/WrapNomarl.js +++ b/src/Screens/Account/PacrtCQG/WrapNomarl.js @@ -19,6 +19,21 @@ const ContainerTop = (props) => { setListItem(newList); }, [props.data]); + useEffect(() => { + const newList = data.map((e) => { + console.log(props.listRegister); + if (props.listRegister.includes(e.id)) { + console.log('Chay vao day', e.id); + return {...e, selected: true}; + } else { + console.log('Chay xuong duoi', e.id); + return {...e, selected: false}; + } + }); + + setListItem(newList); + }, [props.listRegister]); + const onSelected = (selected) => { const newList = listItem.map((e) => { if (e.id != selected.id) return e; diff --git a/src/Screens/Authen/Login.js b/src/Screens/Authen/Login.js index 4aea22b..e1fc1d9 100644 --- a/src/Screens/Authen/Login.js +++ b/src/Screens/Authen/Login.js @@ -81,17 +81,25 @@ const Login = (props) => { }); props.hideLoading(); - if (res.data.code == 200 && res.data.data) { - const jsonValue = JSON.stringify({email, pass}); - AsyncStorage.setItem(KEY.TOKEN, res.data.data.token); - AsyncStorage.setItem(KEY.ACCOUNT, jsonValue); - props.saveUserToRedux(res.data.data); - navigate.reset({ - index: 1, - routes: [{name: TABNAVIGATOR}], - }); + if (res.data) { + if (res.data.code == 200 && res.data.data) { + const jsonValue = JSON.stringify({email, pass}); + AsyncStorage.setItem(KEY.TOKEN, res.data.data.token); + AsyncStorage.setItem(KEY.ACCOUNT, jsonValue); + props.saveUserToRedux(res.data.data); + navigate.reset({ + index: 1, + routes: [{name: TABNAVIGATOR}], + }); + } else { + showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message); + } } else { - showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message); + showAlert( + TYPE.ERROR, + I18n.t('Notification'), + I18n.t('Systemmaintenance'), + ); } } else { showAlert( diff --git a/src/Screens/Home/Home.js b/src/Screens/Home/Home.js index 2cf4d67..8195aa0 100644 --- a/src/Screens/Home/Home.js +++ b/src/Screens/Home/Home.js @@ -23,6 +23,8 @@ const Home = (props) => { const [isSortPercent, setIsSortPercent] = useState(null); const [isSortPriceOpenClose, setIsSortPriceOpenClose] = useState(null); const [isSortPriceHighLow, setIsSortPriceHighLow] = useState(null); + + console.log(props.user); const SORT_TYPE = { DESC: 'DESC', ASC: 'ASC', diff --git a/src/Screens/Menu/Profile/Tab/CQG.js b/src/Screens/Menu/Profile/Tab/CQG.js index 22118cb..dddc713 100644 --- a/src/Screens/Menu/Profile/Tab/CQG.js +++ b/src/Screens/Menu/Profile/Tab/CQG.js @@ -1,18 +1,38 @@ import React from 'react'; import {View, Text, TouchableOpacity, Image, StyleSheet} from 'react-native'; import R from '../../../../assets/R'; -import {getFontXD, HEIGHTXD, WIDTHXD} from '../../../../Config/Functions'; +import { + getFontXD, + HEIGHTXD, + WIDTHXD, + logout, +} from '../../../../Config/Functions'; import {connect} from 'react-redux'; import AppText from '../../../../components/AppText'; import I18n from '../../../../helper/i18/i18n'; import {useNavigation} from '@react-navigation/native'; import {PACKETCQG} from '../../../../routers/ScreenNames'; +import {closeCQG} from '../../../../apis/Functions/packetCQG'; +import {showLoading, hideLoading} from '../../../../actions/loadingAction'; +import {showAlert, TYPE} from '../../../../components/DropdownAlert'; const Profile = (props) => { - const onClickCLose = () => { - console.log('Close click'); - }; const navigation = useNavigation(); + + const onClickCLose = async () => { + props.showLoading(); + const res = await closeCQG(); + props.hideLoading(); + if (res.data.code == 200) { + showAlert(TYPE.SUCCESS, I18n.t('Notification'), res.data.message); + } else if (res.data.code == 401) { + logout(navigation); + showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message); + } else { + showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message); + } + }; + return ( <View style={styles.container}> {props.user.status == 6 ? ( @@ -145,4 +165,4 @@ const mapStateToProps = (state) => { user: state.userReducer, }; }; -export default connect(mapStateToProps, {})(Profile); +export default connect(mapStateToProps, {showLoading, hideLoading})(Profile); diff --git a/src/Screens/ServiceCustomer/ServiceCustomerView.js b/src/Screens/ServiceCustomer/ServiceCustomerView.js index bfb4276..aa150f0 100644 --- a/src/Screens/ServiceCustomer/ServiceCustomerView.js +++ b/src/Screens/ServiceCustomer/ServiceCustomerView.js @@ -1,13 +1,19 @@ import React, {useState, useEffect} from 'react'; -import {View, Text, StyleSheet, Platform} from 'react-native'; +import { + View, + Text, + StyleSheet, + Platform, + Linking, + TouchableOpacity, +} from 'react-native'; import R from '../../assets/R'; import AppText from '../../components/AppText'; import TextMulti from '../../components/Input/TextMulti'; import I18n from '../../helper/i18/i18n'; import {connect} from 'react-redux'; import HeaderBack from '../../components/Header/HeaderBack'; -import {getFontXD, HEIGHTXD, WIDTHXD} from '../../Config/Functions'; -import {TouchableOpacity} from 'react-native-gesture-handler'; +import {getFontXD, HEIGHTXD, WIDTHXD, callNumber} from '../../Config/Functions'; import {showLoading, hideLoading} from '../../actions/loadingAction'; import {showAlert, TYPE} from '../../components/DropdownAlert'; import {sendRequest} from '../../apis/Functions/General'; @@ -28,6 +34,7 @@ const ServiceCustomerView = (props) => { showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message); } }; + console.log(props.user.company_info); const { name, @@ -39,6 +46,7 @@ const ServiceCustomerView = (props) => { office_sat_time, office_sun_time, address, + hotline_call, } = props.user.company_info; return ( @@ -60,13 +68,21 @@ const ServiceCustomerView = (props) => { <Text style={styles.title}>Email:</Text> <Text style={styles.txtContent}> {email}</Text> </View> - <View style={styles.row}> - <Text style={styles.title}>Website: </Text> - <Text style={styles.txtContent}>{website}</Text> - </View> + <TouchableOpacity + onPress={async () => { + const supported = await Linking.canOpenURL(website); + if (supported) Linking.openURL(website); + }}> + <View style={styles.row}> + <Text style={styles.title}>Website: </Text> + <Text style={styles.txtLink}>{website}</Text> + </View> + </TouchableOpacity> <AppText i18nKey={'HotLine'} style={styles.title} /> - <Text style={styles.txtContent}>{hotline}</Text> + <TouchableOpacity onPress={() => callNumber(hotline_call)}> + <Text style={styles.txtContent}>{hotline}</Text> + </TouchableOpacity> <AppText i18nKey={'WorkingTime'} style={styles.title} /> <View style={{flexDirection: 'row'}}> @@ -122,6 +138,12 @@ const styles = StyleSheet.create({ fontSize: getFontXD(42), marginTop: 5, }, + txtLink: { + fontSize: getFontXD(42), + marginTop: 5, + textDecorationLine: 'underline', + color: R.colors.main, + }, row: { flexDirection: 'row', }, diff --git a/src/apis/Functions/packetCQG.js b/src/apis/Functions/packetCQG.js index 2fe2f36..ca738a5 100644 --- a/src/apis/Functions/packetCQG.js +++ b/src/apis/Functions/packetCQG.js @@ -11,3 +11,13 @@ export const openCQG = async (body) => PostData(url.urlOpenCQG, body) .then((res) => res) .catch((err) => err); + +export const closeCQG = async (body) => + PostData(url.urlCloseCQG, body) + .then((res) => res) + .catch((err) => err); + +export const updateCQG = async (body) => + PostData(url.urlUpdateCQG, body) + .then((res) => res) + .catch((err) => err); diff --git a/src/apis/url.js b/src/apis/url.js index 5429aa7..4257a41 100644 --- a/src/apis/url.js +++ b/src/apis/url.js @@ -1,4 +1,4 @@ -export const root = 'http://api.dcvinvest.com/'; +export const root = 'http://services.dcvinvest.com/'; export default { urllogin: root + 'api/auth/customer-login', urlRegistor: root + 'api/auth/customer-register', @@ -57,4 +57,6 @@ export default { urlProfitLost: root + 'api/v1/customers/calculate-profit', urlGetListExchangeRate: root + 'api/v1/customers/get-list-exchange-rate', + urlCloseCQG: root + 'api/v1/customers/cancel-open-cqg', + urlUpdateCQG: root + 'api/v1/customers/update-open-cqg', }; diff --git a/src/components/Header/Drawer.js b/src/components/Header/Drawer.js index 883e70c..a903148 100644 --- a/src/components/Header/Drawer.js +++ b/src/components/Header/Drawer.js @@ -8,7 +8,7 @@ import { ScrollView, } from 'react-native'; import R from '../../assets/R'; -import {HEIGHTXD, getFontXD, WIDTHXD} from '../../Config/Functions'; +import {HEIGHTXD, getFontXD, WIDTHXD, logout} from '../../Config/Functions'; import Icon from 'react-native-vector-icons/MaterialIcons'; import AsyncStorage from '@react-native-community/async-storage'; import DeviceInfo from 'react-native-device-info'; @@ -298,12 +298,8 @@ const Drawer = (props) => { <TouchableOpacity onPress={() => { - AsyncStorage.clear(); + logout(navigate); props.toggleModal(); - navigate.reset({ - index: 1, - routes: [{name: AUTHEN}], - }); }} style={styles.footer}> <Icon name={'logout'} size={25} color={'#F81515'} /> diff --git a/src/components/Header/HeaderHome.js b/src/components/Header/HeaderHome.js index 90de6be..c454ac4 100644 --- a/src/components/Header/HeaderHome.js +++ b/src/components/Header/HeaderHome.js @@ -61,7 +61,7 @@ const renderWallet = (status, current_money, current_cqg_money, contract) => { </TouchableOpacity> </View> ); - if (status == 6) + if (status == 6 || status == 7) return ( <View style={{flex: 1, flexDirection: 'row'}}> <View style={styles.containerWallet}> @@ -100,12 +100,12 @@ const renderWallet = (status, current_money, current_cqg_money, contract) => { <View style={{width: 1, backgroundColor: '#EDEDF1', height: '100%'}} /> <View style={styles.containerWallet}> <AppText - i18nKey={'WaitOpenCQG'} + i18nKey={status == 5 ? 'WaitOpenCQG' : 'WaitUpdateCQG'} style={[styles.txtWhite, {color: '#FFB721'}]}></AppText> </View> </View> ); - if (status == 3) + if (status == 3 || status == 8) return ( <View style={{flex: 1, flexDirection: 'row'}}> <View style={styles.containerWallet}> diff --git a/src/helper/i18/locales/en.js b/src/helper/i18/locales/en.js index 870870e..c9120eb 100644 --- a/src/helper/i18/locales/en.js +++ b/src/helper/i18/locales/en.js @@ -277,4 +277,6 @@ export default { CloseAccount: 'Close account', UpdatePacket: 'Update packet', Count: 'Count', + Systemmaintenance: 'The system is maintenance', + WaitUpdateCQG: 'Waiting Update CQG', }; diff --git a/src/helper/i18/locales/vn.js b/src/helper/i18/locales/vn.js index 862192a..7d02d89 100644 --- a/src/helper/i18/locales/vn.js +++ b/src/helper/i18/locales/vn.js @@ -102,7 +102,7 @@ export default { Open_account: 'Mở tài khoản', Provisional: 'Tạm tính', Here: 'Tại đây', - Open_account_demo: 'Bạn có thể mở tài khoản thử', + Open_account_demo: 'Hoặc bạn có thể mở tài khoản thử', Features_develop: 'Không có dữ liệu!', Email: 'Email', Password: 'Mật khẩu', @@ -272,4 +272,6 @@ export default { CloseAccount: 'Đóng tài khoản', UpdatePacket: 'Cập nhật gói cước', Count: 'Số lượng', + Systemmaintenance: 'Hệ thống đang bảo trì', + WaitUpdateCQG: 'Chờ cập nhật CQG', };