Kaynağa Gözat

add app/pages/my/EditAddress.js

wudebin 5 ay önce
ebeveyn
işleme
36657654a1

+ 187 - 0
Strides-SPAPP/app/pages/my/EditAddress.js

@@ -0,0 +1,187 @@
+import React, { Component } from 'react';
+import { View, Text, StyleSheet, TextInput, ScrollView } from 'react-native';
+import Button from '../../components/Button';
+import { CountryDropCode, GetCountryList } from '../../components/CountryIcon';
+import Dropdown from '../../components/Dropdown';
+
+export default class EditAddress extends Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      addressDto: {
+        countryCode: "",
+        city: "",
+        street: "",
+        zipCode: "",
+        houseNumber: ""
+      }
+    };
+  }
+
+  componentDidMount() {
+    const address = userInfo.address ?? {}
+    if (!address.countryCode) {
+      address.countryCode = "SG"
+    }
+    this.setState({
+      addressDto: address,
+      countryList: [],
+    })
+    userInfo.editAddress = false;
+    GetCountryList(list => {
+      this.setState({
+        countryList: list
+      })
+    })
+  }
+
+  changeCountry(value, index) {
+    this.state.addressDto.countryCode = value;
+    this.setState({
+      addressDto: this.state.addressDto
+    })
+  }
+
+  saveInfo() {
+    const dto = this.state.addressDto
+    if (!dto.city) {
+      toastShort($t('profile.plsInputCity'));
+      return;
+    }
+    if (!dto.street) {
+      toastShort($t('profile.plsInputStreet'));
+      return;
+    }
+    if (!dto.houseNumber) {
+      toastShort($t('profile.plsInputUnitNo'));
+      return;
+    }
+    if (!dto.zipCode) {
+      toastShort($t('profile.plsInputPostal'));
+      return;
+    }
+    userInfo.address = dto;
+    userInfo.addressLine = dto.houseNumber + ', ' + dto.street + ', ' + dto.zipCode
+    console.log(userInfo.addressLine);
+    userInfo.editAddress = true;
+    goBack();
+  }
+
+  render() {
+    return (
+      <View style={styles.container}>
+        <ScrollView style={ui.flex1}>
+          <View style={styles.formView}>
+            <Text style={styles.label}>{$t('sign.labelCountry')}</Text>
+            <Dropdown
+              style={styles.selectView}
+              title={$t('sign.labelCountry')}
+              list={this.state.countryList}
+              value={this.state.addressDto.countryCode}
+              nameKey='countryName'
+              valueKey='countryCode'
+              onChange={(value, index)=> this.changeCountry(value, index)}
+              customerItemView={
+                (item, index, onClick) => 
+                <CountryDropCode
+                  key={index} 
+                  country={item}
+                  value={this.state.addressDto.countryCode}
+                  onClick={onClick}/>
+              }/>
+          </View>
+          <View style={styles.formView}>
+            <Text style={styles.label}>{$t('profile.labelCity')}</Text>
+            <TextInput
+              style={styles.formInput}
+              placeholder={$t('profile.labelCity')}
+              maxLength={50}
+              placeholderTextColor={textPlacehoder}
+              defaultValue={this.state.addressDto?.city}
+              onChangeText={text => this.state.addressDto.city = text}
+            />
+          </View>
+          <View style={styles.formView}>
+            <Text style={styles.label}>{$t('profile.street')}</Text>
+            <TextInput
+              style={styles.formInput}
+              placeholder={$t('profile.hintStreet')}
+              maxLength={50}
+              placeholderTextColor={textPlacehoder}
+              defaultValue={this.state.addressDto?.street}
+              onChangeText={text => this.state.addressDto.street = text}
+            />
+          </View>
+          <View style={styles.formView}>
+            <Text style={styles.label}>{$t('profile.unitNumber')}</Text>
+            <TextInput
+              style={styles.formInput}
+              placeholder={$t('profile.hintUnitNo')}
+              maxLength={15}
+              placeholderTextColor={textPlacehoder}
+              defaultValue={this.state.addressDto?.houseNumber}
+              onChangeText={text => this.state.addressDto.houseNumber = text}
+            />
+          </View>
+          <View style={styles.formView}>
+            <Text style={styles.label}>{$t('profile.postalCode')}</Text>
+            <TextInput
+              style={styles.formInput}
+              placeholder={$t('profile.hintPostal')}
+              maxLength={10}
+              placeholderTextColor={textPlacehoder}
+              defaultValue={this.state.addressDto?.zipCode}
+              onChangeText={text => this.state.addressDto.zipCode = text}
+            />
+          </View>
+        </ScrollView>
+        <View style={styles.buttonView}>
+          <Button
+            text={$t('common.save')}
+            elevation={1.5}
+            onClick={() => {
+              this.saveInfo();
+            }}/>
+        </View>
+      </View>
+    );
+  }
+}
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    backgroundColor: pageBackground
+  },
+  formView: {
+    paddingTop: 16,
+    paddingLeft: 16,
+    paddingRight: 16,
+    paddingBottom: 4
+  },
+  selectView: {
+    marginTop: 4,
+    marginBottom: -8,
+    ...$padding(8, 0, 8, 4),
+    alignItems: 'center',
+    flexDirection: 'row',
+    borderBottomColor: '#EEE',
+    borderBottomWidth: 1
+  },
+  label: {
+    color: textPrimary,
+    fontSize: 14
+  },
+  formInput: {
+    color: textPrimary,
+    fontSize: 14,
+    height: 44,
+    paddingBottom: 2,
+    borderBottomColor: '#EEE',
+    borderBottomWidth: 1
+  },
+  buttonView: {
+    padding: 16,
+    marginBottom: 4
+  }
+})

+ 510 - 0
Strides-SPAPP/app/pages/my/EditProfile.js

@@ -0,0 +1,510 @@
+/**
+ * Edit Profile页面
+ * @邠心vbe on 2021/05/07
+ */
+import React, { Component, useEffect, useState } from 'react';
+import { View, Text, StyleSheet, Pressable, Image, TextInput } from 'react-native';
+import ImagePicker from 'react-native-image-crop-picker';
+import Modal from 'react-native-modal';
+import apiUpload from '../../api/apiUpload';
+import apiUser from '../../api/apiUser';
+import { ModalProps } from '../../components/BottomModal';
+import Button, { ViewHeight } from '../../components/Button';
+import { CountryDropCode, CountryDropNum, GetCountryList } from '../../components/CountryIcon';
+import Dropdown from '../../components/Dropdown';
+import TextView from '../../components/TextView';
+import { UploadThemes } from '../../components/ThemesConfig';
+import utils from '../../utils/utils';
+import { DialogMaxWidth } from '../charge/InfoDialog';
+import { PageList } from '../Router';
+
+//Image Picker参数
+const options = {
+  cropping: true,
+  multiple: false,
+  minFiles: 1,
+  maxFiles: 3,
+  mediaType: 'photo',
+  compressImageQuality: 0.8,
+  cropperCircleOverlay: true,
+  ...UploadThemes
+}
+
+//向右的箭头
+const ArrowRight = () => {
+  return (
+    <Entypo
+      size={16}
+      color='#999'
+      name='chevron-thin-right'
+      style={{
+        marginLeft: 16
+      }}
+    />
+  );
+}
+
+//分割线
+const Divide = () => {
+  return (
+    <View style={{
+      paddingLeft: 16,
+      paddingRight: 16
+    }}>
+      <Text style={{
+        height: 1,
+        backgroundColor: '#eee'
+      }}></Text>
+    </View>
+  );
+}
+
+//编辑弹窗
+const EditDialog = ({visible, title, value, keyType, countryList, areaNo="", showCalling=false, onChangedText}) => {
+  var changedText = value;
+  var [callingCode, setCalling] = useState();
+  useEffect(() => {
+    if (visible && areaNo) {
+      setCalling(areaNo)
+    }
+  }, [visible])
+  return (
+    <Modal
+      isVisible={visible}
+      {...ModalProps}
+      onBackdropPress={() => onChangedText('')}
+      onBackButtonPress={() => onChangedText('')}>
+      <View style={styles.dialog}>
+        <TextView style={styles.editNickname}>{title}</TextView>
+        <View style={ui.flexc}>
+          { showCalling &&
+            <Dropdown
+              prefixText="+"
+              list={countryList}
+              value={callingCode}   
+              nameKey='countryNum'
+              valueKey='countryNum'
+              autoSelect={false}
+              style={styles.countryView}
+              textStyle={styles.selectText}
+              onChange={(value, index)=> {
+                setCalling(value);
+              }}
+              customerItemView={
+                (item, index, onClick) => 
+                <CountryDropNum
+                  key={index} 
+                  country={item}
+                  value={callingCode}
+                  onClick={onClick}/>
+              }
+            />
+          }
+          <TextInput
+            style={styles.nickInput}
+            defaultValue={value}
+            keyboardType={keyType}
+            onChangeText={text => {
+              changedText = text;
+            }}/>
+        </View>
+        <View style={styles.modalButtons}>
+          <Button
+            style={styles.btnCancel}
+            viewStyle={ViewHeight(42)}
+            textColor={textCancel}
+            text={$t('common.cancel')}
+            onClick={() => {
+              onChangedText('');
+            }}/>
+          <Button
+            style={styles.btnOk}
+            viewStyle={ViewHeight(42)}
+            text={$t('common.save')}
+            onClick={() => {
+              onChangedText(changedText, callingCode);
+            }}/>
+        </View>
+        {/* <Ionicons
+          name='close'
+          size={28}
+          color={'#999'}
+          style={styles.closeIcon}
+          onPress={() => {
+            onChangedText('');
+          }} /> */}
+      </View>
+    </Modal>
+  );
+}
+
+//页面
+export default class EditProfile extends Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      editDialog: {
+        key: '',
+        value: '',
+        title: '',
+        visible: false
+      },
+      userInfo: {},
+      countryList: []
+    };
+    this.editAddress = false;
+  }
+
+  componentDidMount() {
+    /*this.props.navigation.addListener('beforeRemove', e => {
+      if (this.canUpdate) {
+        e.preventDefault();
+        //console.log('----update---', userInfo);
+      }
+    });*/
+    this.props.navigation.addListener('focus', e => {
+      if (this.editAddress && userInfo.editAddress) {
+        this.updateProfile(global.userInfo);
+      }
+      this.editAddress = false;
+    });
+    this.setState({
+      userInfo: userInfo
+    })
+    GetCountryList(list => {
+      this.setState({
+        countryList: list
+      })
+    })
+  }
+
+  updateProfile(_userInfo) {
+    apiUser.setProfile(_userInfo).then(res => {
+      toastShort($t('profile.updateSuccess'));
+      userInfo = _userInfo;
+      this.setState({
+        userInfo: _userInfo
+      });
+      //this.canUpdate = false;
+      //goBack();
+    }).catch(err => {
+      //this.canUpdate = false;
+      toastShort(err);
+    });
+  }
+
+  hideDialog() {
+    this.state.editDialog.visible = false;
+    this.setState({
+      editDialog: this.state.editDialog
+    });
+  }
+
+  pickAvatar() {
+    console.log("pickAvatar", $t('common.cropperTitle'));
+    ImagePicker.openPicker({
+      width: 200,
+      height: 200,
+      ...options,
+      cropperToolbarTitle: $t('common.cropperTitle')
+    }).then(image => {
+      if (image.path) {
+        this.uploadAvatar(image)
+      }
+    }).catch(errs => {
+      console.info("pickAvatarError", errs);
+    });
+  }
+
+  uploadAvatar(image) {
+    apiUpload.uploadImage(image.path, image.mime, 'USER_PROFILE').then(res => {
+      if (res.success && res.data.picturePath) {
+        //this.canUpdate = true;
+        this.state.userInfo.photoUrl = res.data.picturePath
+        /*this.setState({
+          userInfo: userInfo
+        });*/
+        this.updateProfile(this.state.userInfo);
+      } else {
+        toastShort($t('common.uploadFailed'));
+      }
+    }).catch(err => {
+      toastShort(err);
+    });
+  }
+
+  changeCountry(value, index) {
+    if (this.state.userInfo.countryCode !== value) {
+      var info = Object.assign({}, userInfo);
+      info.countryCode = value;
+      this.updateProfile(info)
+    }
+  }
+
+  render() {
+    return (
+      <View style={styles.container}>
+        <Pressable
+          style={styles.profileView}
+          android_ripple={ripple}
+          onPress={() => this.pickAvatar()}>
+          <TextView style={styles.label}>{$t('profile.avatar')}</TextView>
+          <Text style={ui.flex1}></Text>
+          { userInfo.photoUrl
+          ? <Image
+              style={styles.avatar}
+              source={{uri: utils.getImageUrl(userInfo.photoUrl)}}/>
+          : <Image
+              style={styles.avatar}
+              source={require('../../images/user/ic-avatar-default.png')}/>
+          }
+          <ArrowRight/>
+        </Pressable>
+        <Divide/>
+        <Pressable
+          style={styles.profileView}
+          android_ripple={ripple}
+          onPress={() => {
+            this.setState({
+              editDialog: {
+                key: 'nickName',
+                title: $t('profile.updateNickname'),
+                value: this.state.userInfo.nickName,
+                visible: true
+              }
+            });
+          }}>
+          <TextView style={styles.label}>{$t('profile.nickname')}</TextView>
+          <TextView style={styles.infoText}>{this.state.userInfo.nickName}</TextView>
+          <ArrowRight/>
+        </Pressable>
+        <Divide/>
+        <View style={styles.profileView}>
+          <TextView style={styles.label}>{$t('sign.labelCountry')}</TextView>
+          <TextView style={styles.infoText}></TextView>
+          <ArrowRight/>
+          <Dropdown
+            style={styles.selectView}
+            title={$t('sign.labelCountry')}
+            list={this.state.countryList}
+            value={this.state.userInfo.countryCode}
+            nameKey='countryName'
+            valueKey='countryCode'
+            showIcon={false}
+            textStyle={styles.rightText}
+            onChange={(value, index)=> this.changeCountry(value, index)}
+            customerItemView={
+              (item, index, onClick) => 
+              <CountryDropCode
+                key={index} 
+                country={item}
+                value={this.state.userInfo.countryCode}
+                onClick={onClick}/>
+            }/>
+        </View>
+        <Divide/>
+        <Pressable
+          style={styles.profileView}
+          android_ripple={ripple}
+          onPress={() => {
+            this.setState({
+              editDialog: {
+                key: 'phone',
+                visible: true,
+                showCalling: true,
+                title: $t('profile.updatePhoneNumber'),
+                value: this.state.userInfo.phone,
+                areaNo: this.state.userInfo.callingCode
+              }
+            });
+          }}>
+          <TextView style={styles.label}>{$t('profile.phoneNumber')}</TextView>
+          <TextView style={styles.infoText}>{(utils.isNotEmpty(this.state.userInfo.callingCode) && "+" + this.state.userInfo.callingCode)} {this.state.userInfo.phone}</TextView>
+          <ArrowRight/>
+        </Pressable>
+        <Divide/>
+        <Pressable
+          style={[styles.profileView, {
+            paddingRight: 48
+          }]}>
+          <TextView style={styles.label}>{$t('profile.email')}</TextView>
+          <TextView style={styles.infoText}>{userInfo.email}</TextView>
+          {/*<ArrowRight/>*/}
+        </Pressable>
+        <Divide/>
+        {/* <Pressable
+          style={styles.profileView}
+          android_ripple={ripple}
+          onPress={() => {
+            /*this.setState({
+              editDialog: {
+                key: 'addressLine',
+                title: 'Update Address',
+                value: userInfo.addressLine,
+                visible: true
+              }
+            });*
+            this.editAddress = true;
+            startPage(PageList.editAddress);
+          }}>
+          <TextView style={styles.label}>{$t('profile.address')}</TextView>
+          <TextView style={styles.infoText}>{userInfo.addressLine}</TextView>
+          <ArrowRight/>
+        </Pressable> */}
+        <Pressable
+          style={[styles.profileView, {
+            paddingRight: 48
+          }]}>
+          <TextView style={styles.label}>{$t('profile.userType')}</TextView>
+          <TextView style={styles.infoText}>{userInfo.userType}</TextView>
+          {/*<ArrowRight/>*/}
+        </Pressable>
+        <Divide/>
+        {/* <Pressable
+          style={[styles.profileView, {
+            paddingRight: 48
+          }]}>
+          <TextView style={styles.label}>{$t('profile.registerDate')}</TextView>
+          <TextView style={styles.infoText}>{"-"}</TextView>
+        </Pressable> */}
+        <EditDialog
+          title={this.state.editDialog.title}
+          visible={this.state.editDialog.visible}
+          value={this.state.editDialog.value}
+          areaNo={this.state.editDialog.areaNo}
+          countryList={this.state.countryList}
+          showCalling={this.state.editDialog.showCalling}
+          keyType={this.state.editDialog.key == 'phone' ? 'phone-pad' : 'default'}
+          onChangedText={(text, areaNo) => {
+            if (text) {
+              var info = Object.assign({}, userInfo);
+              if (this.state.editDialog.key == 'phone') {
+                if (!/^[0-9\+]\d{6,15}$/.test(text)) {
+                  toastShort($t('profile.errPhoneNumberFormat'));
+                  return;
+                }
+                info.callingCode = areaNo;
+              }
+              info[this.state.editDialog.key] = text;
+              /*this.setState({
+                userInfo: userInfo
+              });
+              this.canUpdate = true;*/
+              this.updateProfile(info);
+            }
+            this.hideDialog();
+          }}/>
+      </View>
+    );
+  }
+}
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    backgroundColor: pageBackground
+  },
+  profileView: {
+    padding: 16,
+    alignItems: 'center',
+    flexDirection: 'row'
+  },
+  label: {
+    color: '#666',
+    fontSize: 14
+  },
+  infoText: {
+    flex: 1,
+    color: textPrimary,
+    fontSize: 14,
+    paddingLeft: 16,
+    textAlign: 'right'
+  },
+  avatar: {
+    width: 62,
+    height: 62,
+    borderRadius: 80,
+  },
+  dialog: {
+    width: DialogMaxWidth,
+    paddingTop: 16,
+    paddingLeft: 20,
+    paddingRight: 20,
+    paddingBottom: 16,
+    marginLeft: 'auto',
+    marginRight: 'auto',
+    backgroundColor: colorLight,
+    borderRadius: isIOS ? 20 : 3
+  },
+  editNickname: {
+    color: '#000',
+    fontSize: 18,
+    textAlign: 'center'
+  },
+  nickInput: {
+    flex: 1,
+    color: textPrimary,
+    minHeight: 43,
+    fontSize: 14,
+    paddingTop: 8,
+    paddingLeft: 16,
+    paddingRight: 16,
+    paddingBottom: 8,
+    borderRadius: 4,
+    marginTop: 24,
+    backgroundColor: '#F6F6F6'
+  },
+  modalButtons: {
+    marginTop: 32,
+    paddingBottom: 12,
+    alignItems: 'center',
+    flexDirection: 'row'
+  },
+  btnCancel: {
+    flex: 1,
+    borderWidth: 1,
+    borderColor: colorCancel,
+    backgroundColor: pageBackground
+  },
+  btnOk: {
+    flex: 1,
+    marginLeft: 16,
+    borderWidth: 1,
+    borderColor: colorAccent,
+  },
+  closeIcon: {
+    top: 12,
+    right: 12,
+    position: "absolute"
+  },
+  countryView: {
+    width: 85,
+    marginTop: 24,
+    marginRight: 8,
+    minHeight: 43,
+    borderRadius: 4,
+    alignItems: 'center',
+    flexDirection: 'row',
+    ...$padding(0, 5, 0, 12),
+    backgroundColor: '#F6F6F6'
+  },
+  selectView: {
+    top: 0,
+    left: 0,
+    bottom: 0,
+    width: $vw(100),
+    alignItems: 'center',
+    flexDirection: 'row',
+    position: 'absolute',
+  },
+  selectText: {
+    color: textPrimary,
+    fontSize: 15
+  },
+  rightText: {
+    right: 48,
+    color: textPrimary,
+    fontSize: 14,
+    position: 'absolute'
+  },
+});