Profile.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /**
  2. * Profile Settings页面
  3. * @邠心vbe on 2021/04/27
  4. */
  5. import React, { Component } from 'react';
  6. import { View, Text, StyleSheet, Image, ScrollView, Switch, Pressable } from 'react-native';
  7. import apiUser from '../../api/apiUser';
  8. import { setAccessToken } from '../../api/http';
  9. import Button, { ElevationObject } from '../../components/Button';
  10. import Dialog from '../../components/Dialog';
  11. import { StationBack } from '../../components/Toolbar';
  12. import ProfileBackground from '../../icons/ProfileBackground';
  13. import TopChargeBackground from '../../icons/TopChargeBackground';
  14. import { getStorageJsonSync, setStorage, setStorageJson } from '../../utils/storage';
  15. import utils from '../../utils/utils';
  16. import { PageList } from '../Router';
  17. import VehicleList from './VehicleList';
  18. export default class Profile extends Component {
  19. constructor(props) {
  20. super(props);
  21. this.state = {
  22. userInfo: {
  23. notifyLowBalance: true,
  24. notifyChargingComplete: true,
  25. notifyPromotionsOffers: true
  26. },
  27. refreshId: 0,
  28. totalVehicle: 0
  29. };
  30. this.changed = false;
  31. }
  32. componentDidMount() {
  33. this.props.navigation.addListener('focus', () => {
  34. getUserInfo(info => {
  35. this.setState({
  36. userInfo: info,
  37. refreshId: this.state.refreshId + 1
  38. });
  39. }, true);
  40. });
  41. }
  42. componentWillUnmount() {
  43. if (this.changed) {
  44. this.setChangedSwitch();
  45. }
  46. }
  47. removeVehicle(id) {
  48. Dialog.showDialog({
  49. title: 'Remove Vehicle',
  50. message: 'Are you sure you want to remove this vehicle?',
  51. callback: btn => {
  52. if (btn == 'ok') {
  53. Dialog.dismissLoading();
  54. this.deleteVehicle(id);
  55. }
  56. }
  57. })
  58. }
  59. deleteVehicle(id) {
  60. Dialog.showProgressDialog();
  61. apiUser.deleteVehicle({
  62. vehiclePk: id
  63. }).then(res => {
  64. Dialog.dismissLoading();
  65. toastShort('Delete successfully');
  66. this.setState({
  67. refreshId: this.state.refreshId + 1
  68. })
  69. }).catch(err => {
  70. Dialog.dismissLoading();
  71. toastShort(err);
  72. });
  73. }
  74. changeSwitch(key, value) {
  75. userInfo[key] = value;
  76. this.setState({
  77. userInfo: userInfo
  78. });
  79. this.changed = true;
  80. }
  81. setChangedSwitch() {
  82. apiUser.setNotifySwitch(userInfo);
  83. }
  84. deleteAccount() {
  85. Dialog.showDialog({
  86. title: $t('profile.deleteAccount'),
  87. message: $t('profile.confirmDeleteAccount'),
  88. ok: $t('nav.confirm'),
  89. callback: button => {
  90. if (button == Dialog.BUTTON_OK) {
  91. this.deleteMyAccount();
  92. }
  93. }
  94. })
  95. }
  96. deleteMyAccount() {
  97. Dialog.showProgressDialog();
  98. apiUser.deleteAccount().then(res => {
  99. toastShort($t('profile.deleteAccountSuccess'))
  100. Dialog.dismissLoading();
  101. setTimeout(() => {
  102. startPage(PageList.login);
  103. }, 500);
  104. }).catch(err => {
  105. Dialog.dismissLoading();
  106. toastShort(err)
  107. })
  108. }
  109. logout() {
  110. Dialog.showDialog({
  111. title: $t('profile.signOut'),
  112. message: $t('profile.tipSignOut'),
  113. callback: btn => {
  114. if (btn == 'ok') {
  115. Dialog.showProgressDialog();
  116. setTimeout(() => {
  117. this.requestLogout();
  118. }, 500);
  119. }
  120. }
  121. })
  122. }
  123. async requestLogout() {
  124. const data = await getStorageJsonSync('loginData');
  125. if (data && data.email) {
  126. delete data.password
  127. setStorageJson('loginData', data);
  128. setStorage('RegisterTokenDate', "");
  129. }
  130. global.userInfo = {}
  131. /*this.setState({
  132. isLogin: false,
  133. userInfo: {}
  134. });*/
  135. setAccessToken('');
  136. goBack();
  137. Dialog.dismissLoading();
  138. }
  139. render() {
  140. return (
  141. <ScrollView style={styles.container}>
  142. {/* Profile Info */}
  143. <View style={styles.headerView}>
  144. <View style={styles.background}>
  145. {/* <ProfileBackground/> */}
  146. </View>
  147. {/* <Image
  148. style={styles.background}
  149. source={require('../../images/user/bg-profile.svg')}/> */}
  150. <Pressable
  151. style={styles.profileView}
  152. onPress={() => {
  153. startPage(PageList.editProfile);
  154. }}>
  155. { userInfo.photoUrl
  156. ? <Image
  157. style={styles.avatar}
  158. source={{uri: utils.getImageUrl(userInfo.photoUrl)}}/>
  159. : <Image
  160. style={styles.avatar}
  161. source={require('../../images/user/ic-avatar-default.png')}/>
  162. }
  163. <View style={styles.infoContent}>
  164. <Text
  165. style={styles.nickname}
  166. ellipsizeMode='tail'
  167. numberOfLines={1}>{userInfo.nickName}</Text>
  168. <Text style={styles.userText}>{userInfo.email}</Text>
  169. <Text style={styles.userText}>{(utils.isNotEmpty(userInfo.callingCode) && "+" + userInfo.callingCode) + userInfo.phone}</Text>
  170. </View>
  171. <FontAwesome
  172. size={34}
  173. color={colorDark}
  174. name='angle-right'/>
  175. </Pressable>
  176. <StationBack bottom={52} scale={0.8}/>
  177. </View>
  178. {/* Summary Info */}
  179. <View style={styles.cardView}>
  180. <View style={styles.cardItem}>
  181. <Image
  182. style={styles.cardIcon}
  183. source={require('../../images/user/card-vehicle.png')}/>
  184. <View style={styles.cardInfo}>
  185. <Text style={styles.cardPrimary}>{this.state.totalVehicle}</Text>
  186. <Text style={styles.cardLabel}>My Vehicles</Text>
  187. </View>
  188. </View>
  189. <View style={[styles.cardItem, styles.cardDivide]}>
  190. <Image
  191. style={styles.cardIcon}
  192. source={require('../../images/user/card-wallet.png')}/>
  193. <Pressable
  194. style={styles.cardInfo}
  195. onPress={() => {
  196. startPage(PageList.wallet);
  197. }}>
  198. <Text style={styles.cardPrimary}>{currency}{userInfo.credit}</Text>
  199. <Text style={styles.cardLabel}>Credit Wallet</Text>
  200. </Pressable>
  201. </View>
  202. </View>
  203. {/* Vehicle List */}
  204. <View style={styles.titleView}>
  205. <Text style={styles.title}>My Vehicles</Text>
  206. <Button
  207. style={{backgroundColor: colorLight}}
  208. borderRadius={3}
  209. viewStyle={styles.titleAdd}
  210. onClick={() => {
  211. startPage(PageList.addVehicle)
  212. }}>
  213. <Entypo name='plus' size={14} color={colorDark}/>
  214. <Text style={{fontSize: 12, paddingLeft: 1, color: textPrimary}}>Add Vehicle</Text>
  215. </Button>
  216. </View>
  217. <View style={styles.verhicleList}>
  218. <VehicleList
  219. refreshId={this.state.refreshId}
  220. onResult={count => {
  221. this.setState({
  222. totalVehicle: count
  223. })
  224. }}
  225. onDelete={id => this.removeVehicle(id)}
  226. />
  227. </View>
  228. {/* Account List */}
  229. {/* <View style={styles.titleView}>
  230. <Text style={styles.title}>My Cards</Text>
  231. <Button
  232. textColor={textPrimary}
  233. style={styles.titleAdd}
  234. onClick={() => {
  235. startPage(PageList.addCard)
  236. }}>
  237. <Entypo name='plus' size={14} color={colorDark}/>
  238. <Text style={{fontSize: 12, paddingLeft: 1}}>Add Card</Text>
  239. </Button>
  240. </View>
  241. <View style={styles.accountList}>
  242. <CardList refreshId={this.state.refreshId}/>
  243. </View> */}
  244. {/* Notifications */}
  245. <View style={styles.titleView}>
  246. <Text style={styles.title}>Notifications</Text>
  247. </View>
  248. <View style={styles.notificationView}>
  249. <Pressable
  250. style={styles.notificationItem}
  251. android_ripple={ripple}
  252. onPress={() => {
  253. this.changeSwitch("notifyChargingComplete", !userInfo.notifyChargingComplete);
  254. }}>
  255. <Text style={styles.notiLabel}>Notify me when charging complete</Text>
  256. <Switch
  257. value={this.state.userInfo.notifyChargingComplete}
  258. trackColor={isIOS ? { false: "#B2B2B2", true: colorAccent } : null}
  259. onValueChange={v => {
  260. this.changeSwitch("notifyChargingComplete", v);
  261. }}/>
  262. </Pressable>
  263. <Pressable
  264. style={[styles.notificationItem, styles.divide]}
  265. android_ripple={ripple}
  266. onPress={() => {
  267. this.changeSwitch("notifyLowBalance", !userInfo.notifyLowBalance);
  268. }}>
  269. <Text style={styles.notiLabel}>Notify me when wallet is low balance</Text>
  270. <Switch
  271. value={this.state.userInfo.notifyLowBalance}
  272. trackColor={isIOS ? { false: "#B2B2B2", true: colorAccent } : null}
  273. onValueChange={v => {
  274. this.changeSwitch("notifyLowBalance", v);
  275. }}/>
  276. </Pressable>
  277. <Pressable
  278. style={[styles.notificationItem, styles.divide]}
  279. android_ripple={ripple}
  280. onPress={() => {
  281. this.changeSwitch("notifyPromotionsOffers", !userInfo.notifyPromotionsOffers);
  282. }}>
  283. <Text style={styles.notiLabel}>Notify me for promotions and offers</Text>
  284. <Switch
  285. value={this.state.userInfo.notifyPromotionsOffers}
  286. trackColor={isIOS ? { false: "#B2B2B2", true: colorAccent } : null}
  287. onValueChange={v => {
  288. this.changeSwitch("notifyPromotionsOffers", v);
  289. }}/>
  290. </Pressable>
  291. </View>
  292. <Button
  293. style={styles.deleteButton}
  294. text="DELETE MY ACCOUNT"
  295. textColor={textButton}
  296. onClick={() => this.deleteAccount()}
  297. />
  298. <Button
  299. style={styles.deleteButton}
  300. text="Logout"
  301. textColor={textButton}
  302. onClick={() => this.logout()}
  303. />
  304. </ScrollView>
  305. );
  306. }
  307. }
  308. const styles = StyleSheet.create({
  309. container: {
  310. flex: 1,
  311. backgroundColor: pageBackground
  312. },
  313. headerView: {
  314. paddingBottom: 72
  315. },
  316. background: {
  317. left: 0,
  318. right: 0,
  319. bottom: 0,
  320. height: $vw(62.4),
  321. alignItems: 'center',
  322. position: 'absolute'
  323. },
  324. profileView: {
  325. padding: 16,
  326. zIndex: 10,
  327. alignItems: 'center',
  328. flexDirection: 'row'
  329. },
  330. avatar: {
  331. width: 66,
  332. height: 66,
  333. borderWidth: 2,
  334. borderRadius: 80,
  335. borderColor: colorLight
  336. },
  337. infoContent: {
  338. flex: 1,
  339. paddingLeft: 16,
  340. },
  341. nickname: {
  342. color: '#000',
  343. fontSize: 16,
  344. paddingTop: 1,
  345. paddingBottom: 1.5,
  346. },
  347. userText: {
  348. color: textPrimary,
  349. fontSize: 13,
  350. paddingTop: 1.5
  351. },
  352. cardView: {
  353. padding: 16,
  354. marginTop: -56,
  355. marginLeft: 16,
  356. marginRight: 16,
  357. borderRadius: 10,
  358. ...ElevationObject(2),
  359. alignItems: 'center',
  360. flexDirection: 'row',
  361. backgroundColor: colorLight,
  362. },
  363. cardItem: {
  364. flex: 1,
  365. alignItems: 'center',
  366. flexDirection: 'row',
  367. justifyContent: 'center'
  368. },
  369. cardDivide: {
  370. borderLeftWidth: 1,
  371. borderLeftColor: '#EEE'
  372. },
  373. cardIcon: {
  374. width: 32,
  375. height: 32
  376. },
  377. cardInfo: {
  378. paddingLeft: 16,
  379. alignItems: 'center'
  380. },
  381. cardPrimary: {
  382. color: textPrimary,
  383. fontSize: 18,
  384. paddingBottom: 2
  385. },
  386. cardLabel: {
  387. color: textPrimary,
  388. fontSize: 13,
  389. },
  390. titleView: {
  391. padding: 12,
  392. alignItems: 'center',
  393. flexDirection: 'row'
  394. },
  395. title: {
  396. flex: 1,
  397. padding: 8,
  398. color: '#000',
  399. fontSize: 16,
  400. },
  401. titleAdd: {
  402. padding: 8,
  403. color: textPrimary,
  404. alignItems: 'center',
  405. flexDirection: 'row'
  406. },
  407. verhicleList: {
  408. paddingLeft: 16,
  409. paddingRight: 16,
  410. marginBottom: -16
  411. },
  412. accountList: {
  413. paddingLeft: 16,
  414. paddingRight: 16,
  415. marginBottom: -16
  416. },
  417. notificationView: {
  418. marginLeft: 16,
  419. marginRight: 16,
  420. marginBottom: 20,
  421. borderRadius: 10,
  422. overflow: 'hidden',
  423. paddingLeft: 16,
  424. paddingRight: 16,
  425. borderColor: '#f5f5f5',
  426. borderWidth: 1,
  427. backgroundColor: colorLight,
  428. ...ElevationObject(1.5)
  429. },
  430. notificationItem: {
  431. paddingTop: 16,
  432. paddingBottom: 16,
  433. alignItems: 'center',
  434. flexDirection: 'row'
  435. },
  436. notiLabel: {
  437. flex: 1,
  438. color: textPrimary,
  439. fontSize: 14
  440. },
  441. divide: {
  442. borderTopWidth: 1,
  443. borderTopColor: '#eee'
  444. },
  445. deleteButton: {
  446. ...$margin(32, 16, 16),
  447. backgroundColor: '#EA0A2A'
  448. }
  449. })