import * as React from 'react'; import { KeyboardAvoidingView, ScrollView, TouchableOpacity, View, Text, Alert } from 'react-native'; import { Avatar } from 'react-native-elements'; import { connect } from "react-redux"; import { saveUserInfo, savePlainUserInfo } from "../../../redux/actions/AppUserInfoActions"; import CustomHeader from '../../../components/header.js'; import Assets from '../../../components/assets.manager.js'; import Theme from '../../../components/theme.style.js'; import Elements from '../../../components/elements.js'; import ImagePicker from 'react-native-image-picker'; import moment from 'moment'; import DB from '../../../components/storage/'; import REQUEST from '../../../components/api/'; import RNFETCHBLOB from '../../../components/api/file.manager'; import { ContactOptions, ContactOptionsWithParams } from '../../../components/contact.action'; import Utils from './utils'; import CustomSafeArea from '../../../components/safeArea.component'; class EditProfile extends React.PureComponent { constructor(props) { super(props) } state = { openModal: false, loading: false, userProfile: null, focused: false, editprofileselect: false, customerserviceselect: false, currentFocus: null, opendialog: false, currentDialog: null, currentphoto: null, newphoto: null, newmobile: "", newemail: null, newaddress: null, newcity: null, vehicleType: null, fuelType: null, maritalStatus: null, gender: null, is_deleted: false, errors: {}, deleted: false } componentDidMount() { this.setState({ loading: false, userProfile: this.props.route.params.data }) } componentWillUnmount() { } onInputFocus = (index) => { this.setState({ focused: true, currentFocus: index }) } onSelectPress = (index) => { this.setState({ opendialog: true, currentDialog: index }) } getFT = (type) => { let types = Assets.fueltypes for(var x=0;x { let types = Assets.vehicletypes for(var x=0;x { let types = Assets.civilstatus for(var x=0;x { let types = Assets.gender for(var x=0;x { } onDeletePhoto = () => { this.setState({ is_deleted: true, currentphoto: Assets.logo.profileHolder }) } formatBytes = (bytes, decimals = 2) => { if (bytes === 0) return '0 Bytes'; const k = 1024; const dm = decimals < 0 ? 0 : decimals; const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return { stringFormat: parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i], decimalFormat: parseFloat((bytes / Math.pow(k, i)).toFixed(dm)), sizeFormat: sizes[i] }; } onEditPhoto = () => { let options = { mediaType: 'photo', maxHeight: 1500, maxWidth: 1500, quality: 0.75 } ImagePicker.launchImageLibrary(options, (response) => { let filesize = this.formatBytes(response.fileSize) console.log(filesize.stringFormat.includes('KB')) if(!filesize.stringFormat.includes('KB') && !filesize.stringFormat.includes('Bytes')) { Alert.alert("Error", "Image size too large.") return } if(!response.didCancel){ if(this.state.is_deleted){ this.setState({ is_deleted: false, currentphoto: null }) } this.setState({ newphoto: response }) } }) } validateEmail = () => { let regEx = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/ return regEx.test(this.state.email) } FormValidate = async () => { let res = {} this.setState({ loading: true }) if(this.state.newemail == ""){ res = Object.assign(this.state.errors, {email: ["This field is required"]}) } if(this.state.newaddress == "" || this.state.newaddress == null && this.state.userProfile.address == ""){ res = Object.assign(this.state.errors, {address: ["This field is required"]}) } if(!this.state.vehicleType && this.state.userProfile.vo_code == "0"){ res = Object.assign(this.state.errors, {vehicleType: ["This field is required"]}) } if(!this.state.fuelType && this.state.userProfile.fueltype_code == "0"){ res = Object.assign(this.state.errors, {fuelType : ["This field is required"]}) } if(this.state.maritalStatus === null) { res = Object.assign(this.state.errors, {maritalStatus : ["This field is required"]}) } if(this.state.gender === null) { res = Object.assign(this.state.errors, {gender : ["This field is required"]}) } this.setState({ errors: res, loading: false }) return Object.keys(this.state.errors).length > 0 ? false : true } Body = function() { return { image: this.state.newphoto ? this.state.newphoto.uri : null, mobile: this.state.newmobile, email: this.state.newemail, address: this.state.newaddress, city: this.state.newcity, vo_code: this.state.vehicleType ? this.state.vehicleType.value : null, fueltype_code: this.state.fuelType ? this.state.fuelType.value : null, civilstatus_code: this.state.maritalStatus ? this.state.maritalStatus.value : null, gender_code: this.state.gender ? this.state.gender.value : null, is_deleted: this.state.is_deleted } } fetchProfileBlob = async (successCallback, errorCallback) => { let SESSION = await DB.session() let params = { newphoto: this.state.newphoto, userProfile: this.state.userProfile, newmobile: this.state.newmobile, newemail: this.state.newemail, newaddress: this.state.newaddress, newcity: this.state.newcity, vehicleType: this.state.vehicleType, fuelType: this.state.fuelType, maritalStatus: this.state.maritalStatus, gender: this.state.gender, is_deleted: this.state.is_deleted } RNFETCHBLOB("update_profile_no_otp", "POST", {Authorization: SESSION.token}, {}, Utils.blobBody(params), (res) => { if(res.status == 1) { this.updateProfileInBackground(onSuccess => successCallback(onSuccess), onError => errorCallback(onError)) } else { Utils.responseHandler(res, () => { successCallback(res) }, (errors) => { console.log(errors) errorCallback(errors) }) } }, (err) => { errorCallback(err) }) } updateProfileBlob = async (successCallback, errorCallback) => { let SESSION = await DB.session() let params = { userProfile: this.state.userProfile, newmobile: this.state.newmobile, newemail: this.state.newemail, newaddress: this.state.newaddress, newcity: this.state.newcity, vehicleType: this.state.vehicleType, fuelType: this.state.fuelType, maritalStatus: this.state.maritalStatus, gender: this.state.gender, is_deleted: this.state.is_deleted } await REQUEST("update_profile_no_otp", "post", { Authorization: SESSION.token, "Content-Type": "multipart/form-data", }, {}, Utils.formData(params), (res) => { if(res.status == 1) { this.updateProfileInBackground(onSuccess => successCallback(onSuccess), onError => errorCallback(onError)) } else { Utils.responseHandler(res, () => { successCallback(res) }, (errors) => { console.log(errors) errorCallback(errors) }) } }, (error) => { errorCallback(error) }) } responseHandler = (res, responseCallback) => { if(res.status == 1){ setTimeout(() => { Alert.alert( "Success", '\nYour profile is successfully updated\n', [{ text: 'OK', onPress: () => { responseCallback() } }] ); }, 700) } else { setTimeout(() => { Alert.alert("Error", res?.email[0]); }, 700) } } updateProfileInBackground = async (successCallback, errorCallback) => { const SESSION = await DB.session() try{ this.props.saveUserInfo({ token: SESSION.token, card_number: SESSION.user.card_number }).then(res => { DB.updateProfile(res, () => { successCallback(res) }, (error) => { errorCallback(error) }) }) .catch(error => this.setState({ loading: false })) } catch(error) { console.log(error) } } SaveNoOtp = async () => { this.setState({ loading: true }) if(this.state.newphoto) { this.fetchProfileBlob(success => { this.setState({ loading: false }) if(success.status == 0) { this.setState({ errors: success }) } else { this.responseHandler(success, handler => { this.props.route.params.onGoBack(success.data) this.props.navigation.goBack() }) } }, error => { this.setState({ loading: false }) setTimeout(() => { if(this.state.newphoto) Alert.alert("Error", "Failed to upload image") }, 300) }) } else { this.setState({ loading: true }) this.updateProfileBlob(success => { this.setState({ loading: false }) if(success.status == 0) { this.setState({ errors: success }) } else { this.responseHandler(success, handler => { this.props.route.params.onGoBack(success.data); this.props.navigation.pop(2); }) } }, error => { this.setState({ loading: false }) setTimeout(() => { if(this.state.newphoto) Alert.alert("Error", "Failed to upload image") }, 300) }) } } SaveWithOtp = () => { this.props.navigation.navigate("AccountSendOtp", { data: { lcard_uuid: this.state.userProfile.lcard_uuid, mobile_number: this.state.newmobile.replace("+", "") }, type: 'edit', callback: (res) => { if(res == "valid") this.SaveNoOtp() }, }) } onSubmit = async () => { this.setState({ focused: false, openModal: false }) if(this.hasChanges()){ let validation = await this.FormValidate(); if(!validation) return if(this.state.newmobile != "" && this.state.newmobile.replace("+", "") != this.state.userProfile.mobile){ this.SaveWithOtp() }else{ this.SaveNoOtp() } }else{ this.props.navigation.goBack() } } hasChanges = () => { let values = Object.values(this.Body()) for(var x=0;x { Elements.ActionOption({ options: ['Edit Photo', 'Delete Photo', 'Cancel'], functions: [{ execute: () => this.onEditPhoto() }, { execute: () => this.onDeletePhoto() }] }) } renderProfilePhoto = () => { if(this.state.currentphoto) return Assets.logo.profileHolder else if(!this.state.currentphoto && this.state.newphoto || this.state.newphoto) return {uri: this.state.newphoto.uri} else if(!this.state.currentphoto && !this.state.newphoto && this.state.userProfile && this.state.userProfile.photo) return {uri: this.state.userProfile.photo} else return Assets.logo.profileHolder } render() { return ( <> this.setState({ opendialog: !this.state.opendialog })} onSelect={(value, string) => { this.setState({ vehicleType: { value: value, string: string }, opendialog: !this.state.opendialog }) }} items={Assets.vehicletypes} /> this.setState({ opendialog: !this.state.opendialog })} onSelect={(value, string) => { this.setState({ fuelType: { value: value, string: string }, opendialog: !this.state.opendialog }) }} items={Assets.fueltypes} /> this.setState({ opendialog: !this.state.opendialog })} onSelect={(value, string) => { this.setState({ maritalStatus: { value: value, string: string }, opendialog: !this.state.opendialog }) }} items={Assets.civilstatus} /> this.setState({ opendialog: !this.state.opendialog })} onSelect={(value, string) => { this.setState({ gender: { value: value, string: string }, opendialog: !this.state.opendialog }) }} items={Assets.gender} /> { if(this.hasChanges()){ Alert.alert( null, 'You have an unsaved profile information, are you sure you want to navigate back?\n', [{ text: 'Cancel', style: 'cancel', }, { text: 'OK', onPress: () => this.props.navigation.navigate("MyProfile") }, ], {cancelable: true} ); }else{ this.props.navigation.navigate("MyProfile") } }} navigation={this.props.navigation} /> {this.state.userProfile && this.state.userProfile.photo && !this.state.is_deleted || this.state.userProfile && !this.state.userProfile.photo && this.state.newphoto && !this.state.is_deleted ? this.handleUpdatePhotoOptions()}> Edit Photo : this.onEditPhoto()}> Add Photo } ContactOptionsWithParams({ cardnumber: this.state?.userProfile?.data?.card_number })} error={"This field is required"} /> ContactOptionsWithParams({ cardnumber: this.state?.userProfile?.data?.card_number })} error={"This field is required"} /> ContactOptionsWithParams({ cardnumber: this.state?.userProfile?.data?.card_number })} error={"This field is required"} /> { this.setState({ newmobile: value }) }} focused={this.state.focused && this.state.currentFocus == 3 ? true : false} onFocus={() => this.onInputFocus(3)} error={"This field is required"} /> this.onInputFocus(4)} onChangeText={(value) => { this.setState({ newemail: value }) delete this.state.errors["email"] }} hasError={this.state.errors && this.state.errors.email ? true : false} errorMessage={this.state.errors && this.state.errors.email ? this.state.errors?.email[0] : "Invalid email"} /> this.onInputFocus(5)} onChangeText={(value) => { this.setState({ newaddress: value }) delete this.state.errors["address"] }} hasError={this.state.errors && this.state.errors.address ? true : false} errorMessage={this.state.errors && this.state.errors.address ? this.state.errors?.address[0] : "Invalid address"} /> { this.onInputFocus(7) this.onSelectPress(1) delete this.state.errors["vehicleType"] }} hasError={this.state.errors && this.state.errors.vehicleType ? true : false} errorMessage={this.state.errors && this.state.errors.vehicleType ? this.state.errors?.vehicleType[0] : "Invalid vehicle type"} /> { this.onInputFocus(8) this.onSelectPress(2) delete this.state.errors["fuelType"] }} hasError={this.state.errors && this.state.errors.fuelType ? true : false} errorMessage={this.state.errors && this.state.errors.fuelType ? this.state.errors?.fuelType[0] : "Invalid fuel type"} /> { this.onInputFocus(9) this.onSelectPress(3) delete this.state.errors["maritalStatus"] }} hasError={this.state.errors && this.state.errors.maritalStatus ? true : false} errorMessage={"This field is required"} /> { this.onInputFocus(10) this.onSelectPress(4) delete this.state.errors["gender"] }} hasError={this.state.errors && this.state.errors.gender ? true : false} errorMessage={"This field is required"} /> this.setState({ openModal: true })} style={{width: '92%', padding: 15, borderRadius: 10, backgroundColor: Theme.colors.primary}}> Save Changes this.setState({ openModal: false })} yesCB={this.onSubmit} /> ) } } const mapStateToProps = (state) => { return { userinfo: state.appUserInfoReducer.userinfo, app_theme: state.appThemeReducer.theme } } const mapDispatchToProps = { saveUserInfo } export default connect(mapStateToProps, mapDispatchToProps)(EditProfile);