import * as React from 'react'; import { KeyboardAvoidingView, ScrollView, TouchableOpacity, View, Text } from 'react-native'; import { Avatar } from 'react-native-elements'; import { connect } from "react-redux"; import { openModal } from '../../../redux/actions/AlertActions'; import { checkPhoneNumberInput } from '../../../utils/number'; import { launchImageLibrary } from 'react-native-image-picker'; import { saveUserInfo, savePlainUserInfo } from "../../../redux/actions/AppUserInfoActions"; import { ContactOptions, ContactOptionsWithParams } from '../../../components/contact.action'; 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 moment from 'moment'; import DB from '../../../components/storage/'; import REQUEST from '../../../components/api/'; import RNFETCHBLOB from '../../../components/api/file.manager'; import Utils from './utils'; import CustomSafeArea from '../../../components/safeArea.component'; class EditProfile extends React.PureComponent { constructor(props) { super(props) } state = { openChangePhoto: false, loading: false, userProfile: null, focused: false, editprofileselect: false, customerserviceselect: false, currentFocus: null, opendialog: false, currentDialog: null, currentphoto: null, backModal: false, newphoto: null, newmobile: "", newemail: null, newaddress: null, newcity: null, vehicleType: null, fuelType: null, maritalStatus: null, gender: null, is_deleted: false, errors: {}, deleted: false, openOptions: false } componentDidMount() { this.setState({ loading: false, userProfile: this.props.route.params.data }) } 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, openChangePhoto: false }) } 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 } launchImageLibrary(options, (response) => { let filesize = this.formatBytes(response.fileSize) if(!filesize.stringFormat.includes('KB') && !filesize.stringFormat.includes('Bytes')) { this.props.openModal({ open: true, title: "Error", body: "Image size too large.", yesButtonOnly: true, yesText: "Okay", theme: this.props.app_theme }) return } if(!response.didCancel){ if(this.state.is_deleted){ this.setState({ is_deleted: false, currentphoto: null }) } this.setState({ newphoto: response, openChangePhoto: false }) } }) } 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 && (this.state.maritalStatus.value === "0" || !this.state.maritalStatus.value)) { res = Object.assign(this.state.errors, {maritalStatus : ["This field is required"]}) } if(this.state.gender && (this.state.gender.value === "0" || !this.state.gender.value)) { 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) }, this.props) } }, (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) }, this.props) } }, (error) => { errorCallback(error) }) } responseHandler = (res, responseCallback) => { if(res.status == 1){ setTimeout(() => { this.props.openModal({ open: true, title: "Success", body: "Your profile is successfully updated", yesCB: () => responseCallback(), yesButtonOnly: true, yesText: "Okay", theme: this.props.app_theme }) }, 700) } else { setTimeout(() => { this.props.openModal({ open: true, title: "Error", body: res?.email[0], yesButtonOnly: true, yesText: "Okay", theme: this.props.app_theme }) }, 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) { this.props.openModal({ open: true, title: "Error", body: "Failed to upload image", yesButtonOnly: true, yesText: "Okay", theme: this.props.app_theme }) } }, 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) { this.props.openModal({ open: true, title: "Error", body: "Failed to upload image", yesButtonOnly: true, yesText: "Okay", theme: this.props.app_theme }) } }, 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 }); if(this.hasChanges()){ if(this.state.newmobile != "" && this.state.newmobile.replace("+", "") != this.state.userProfile.mobile){ this.SaveWithOtp() }else{ this.SaveNoOtp() } }else{ this.props.navigation.goBack() } } disabledSaveChanges = () => { if(!this.state.userProfile) return false; const { email, address, vo_code, fueltype_code, civilstatus_code, gender_code } = this.state.userProfile; if(!email) { if(this.state.email === null || this.state.email === "") return true; } if(email && this.state.newemail === "") return true if(!address) { if(this.state.newaddress === null || this.state.newaddress === "") return true; } if(address && this.state.newaddress === "") return true if(vo_code === "0" && !this.state.vehicleType) return true if(fueltype_code === "0" && !this.state.fuelType) return true if(civilstatus_code === "0") { if(this.state.maritalStatus === null || this.state.maritalStatus.value === "0") return true; } if(civilstatus_code && this.state.maritalStatus === null) return false; else if(gender_code && this.state.maritalStatus.value === "0") return true; if(gender_code === "0") { if(this.state.gender === null || this.state.gender.value === "0") return true; } if(gender_code && this.state.gender === null) return false; else if(gender_code && this.state.gender.value === "0") return true; return false } hasChanges = () => { let values = Object.values(this.Body()) for(var x=0;x { this.setState({ openChangePhoto: true }) } 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({ openChangePhoto: false })} buttons={[ { name: 'Edit Photo', onPress: () => this.onEditPhoto() }, { name: 'Delete Photo', onPress: () => this.onDeletePhoto() } ]} /> 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()) { this.props.openModal({ open: true, title: "Warning", body: "You have an unsaved profile information, are you sure you want to navigate back?", yesCB: () => this.props.navigation.goBack(), theme: this.props.app_theme }) } else { this.props.navigation.goBack(); } }} 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 } this.setState({ openOptions: true })} error={"This field is required"} /> this.setState({ openOptions: true })} error={"This field is required"} /> this.setState({ openOptions: true })} error={"This field is required"} /> { const checker = checkPhoneNumberInput(value); if(!checker) return; this.setState({ newmobile: value }) }} onContact={() => this.setState({ openOptions: true })} disabled={true} bottomOption={true} 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.props.openModal({ open: true, title: "Update Profile", body: "Are you sure you want to save Changes to your profile?", yesCB: this.onSubmit, theme: this.props.app_theme })} style={{width: '92%', padding: 15, borderRadius: 10, backgroundColor: this.disabledSaveChanges() ? this.props.app_theme?.theme.dark ? this.props.app_theme?.theme.colors.border : Theme.colors.primary + "15" : Theme.colors.primary}}> Save Changes this.setState({ openOptions: false })} /> ) } } const mapStateToProps = (state) => { return { userinfo: state.appUserInfoReducer.userinfo, app_theme: state.appThemeReducer.theme } } const mapDispatchToProps = { saveUserInfo, openModal } export default connect(mapStateToProps, mapDispatchToProps)(EditProfile);