2
\$\begingroup\$

Just looking for advice/thoughts on the overall AccountModal and how its written. looking to achieve better written, more legible, less repetitive code, more concise, cleaner etc...

AccountScreen.js:

import React from 'react';
import { StyleSheet, ScrollView, View, Dimensions, Image } from 'react-native';
import * as Colors from '../assets/colors';
import * as Components from '../components';
import { onProfileChange } from '../actions/Profile';
import { TouchableOpacity } from 'react-native-gesture-handler';
import { connect } from 'react-redux';
const { width } = Dimensions.get('window');

class AccountScreen extends React.Component {
    constructor (props) {
        super(props);
        this.state = {
            visible: false,
            modalType: null,
            modalData: ''
        };
        this.listener = props.onProfileChange(this.props.email);
    }
    setModal = (type) => {
        this.setState({ visible: !this.state.visible, modalType: type, modalData: this.props[type] });
    };
    renderConditionalOptions = () => {
        if (this.props.role === 'a') {
            return (
                <View>
                    {this.props.activated !== true ? (
                        <TouchableOpacity
                            style={{
                                padding: width * 0.05,
                                borderBottomWidth: 1,
                                borderBottomColor: Colors.PRIMARY_OFF_WHITE
                            }}
                            onPress={() => this.setModal('activate')}
                        >
                            <Components.BodyText style={{ fontSize: 18 }} text={'Activate/De-Activate'} />
                        </TouchableOpacity>
                    ) : null}
                    <TouchableOpacity
                        style={{
                            padding: width * 0.05,
                            borderBottomWidth: 1,
                            borderBottomColor: Colors.PRIMARY_OFF_WHITE
                        }}
                        onPress={() => this.setModal('adultRated')}
                    >
                        <Components.BodyText style={{ fontSize: 18 }} text={'Change Content Rating'} />
                    </TouchableOpacity>

                    <TouchableOpacity
                        style={{
                            padding: width * 0.05,
                            borderBottomWidth: 1,
                            borderBottomColor: Colors.PRIMARY_OFF_WHITE
                        }}
                        onPress={() => this.setModal('categories')}
                    >
                        <Components.BodyText style={{ fontSize: 18 }} text={'Modify Categories'} />
                    </TouchableOpacity>

                    <TouchableOpacity
                        style={{
                            padding: width * 0.05,
                            borderBottomWidth: 1,
                            borderBottomColor: Colors.PRIMARY_OFF_WHITE
                        }}
                        onPress={() => this.verificationProcess}
                    >
                        <Components.BodyText style={{ fontSize: 18 }} text={'Get Verified'} />
                    </TouchableOpacity>
                </View>
            );
        }
    };

    render () {
        return (
            <ScrollView style={styles.container}>
                {/* HEADER CONTAINER CONTAINER */}
                <View style={styles.headerContainer}>
                    {/* IMG / NAME ROW */}
                    <View style={{ justifyContent: 'space-evenly', alignItems: 'center', flexDirection: 'row' }}>
                        <TouchableOpacity
                            onPress={() => this.setModal('profileImg')}
                            style={{
                                alignItems: 'center',
                                justifyContent: 'center',
                                borderColor: Colors.PRIMARY_GREEN,
                                borderWidth: 5,
                                borderRadius: width * 0.7,
                                backgroundColor: Colors.PRIMARY_OFF_WHITE,
                                width: width * 0.35,
                                height: width * 0.35
                            }}
                        >
                            <Image
                                style={{ borderRadius: width * 0.5, height: width * 0.33, width: width * 0.33 }}
                                source={
                                    this.props.profileImg != '' ? (
                                        { uri: this.props.profileImg }
                                    ) : (
                                        require('../assets/img/white-user.png')
                                    )
                                }
                                resizeMode={'contain'}
                            />
                        </TouchableOpacity>

                        <View style={{ alignItems: 'center' }}>
                            <Components.BodyText
                                text={this.props.legalName}
                                style={{
                                    fontSize: 22,
                                    fontWeight: 'bold',
                                    marginTop: width * 0.01
                                }}
                            />
                            {/* Edit Username  */}
                            <TouchableOpacity
                                onPress={() => this.setModal('username')}
                                style={{
                                    borderWidth: 1,
                                    borderColor: Colors.PRIMARY_OFF_WHITE,
                                    borderRadius: width,
                                    paddingHorizontal: width * 0.025,
                                    paddingVertical: width * 0.015,
                                    marginTop: width * 0.01
                                }}
                            >
                                <Components.BodyText
                                    text={'@' + this.props.username}
                                    style={{ textAlign: 'center', fontSize: 16 }}
                                />
                            </TouchableOpacity>
                        </View>
                    </View>
                </View>

                {/* LOWER CONTAINER */}
                <View
                    style={{
                        borderTopLeftRadius: 25,
                        borderTopRightRadius: 25,
                        borderBottomLeftRadius: 25,
                        borderBottomRightRadius: 25,
                        backgroundColor: 'white',
                        width: width,
                        marginBottom: width * 0.05
                    }}
                >
                    <TouchableOpacity
                        style={{
                            padding: width * 0.05,
                            borderBottomWidth: 1,
                            borderBottomColor: Colors.PRIMARY_OFF_WHITE
                        }}
                        onPress={() => this.setModal('email')}
                    >
                        <Components.BodyText text={'Update Email'} style={{ fontSize: 18 }} />
                    </TouchableOpacity>

                    <TouchableOpacity
                        style={{
                            padding: width * 0.05,
                            borderBottomWidth: 1,
                            borderBottomColor: Colors.PRIMARY_OFF_WHITE
                        }}
                        onPress={() => this.setModal('password')}
                    >
                        <Components.BodyText style={{ fontSize: 18 }} text={'Change Password'} />
                    </TouchableOpacity>

                    <TouchableOpacity
                        style={{
                            padding: width * 0.05,
                            borderBottomWidth: 1,
                            borderBottomColor: Colors.PRIMARY_OFF_WHITE
                        }}
                        onPress={() => this.setModal('phoneNumber')}
                    >
                        <Components.BodyText style={{ fontSize: 18 }} text={'Update Phone Number'} />
                    </TouchableOpacity>

                    {/* CONDITIONAL OPTIONS */}
                    {this.renderConditionalOptions()}
                </View>

                {this.state.visible === true ? (
                    <Components.AccountModal
                        visible={this.state.visible}
                        data={this.state.modalData}
                        type={this.state.modalType}
                        closeModal={this.setModal}
                        navigation={this.props.navigation}
                    />
                ) : null}
            </ScrollView>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        //justifyContent: 'space-between',
        backgroundColor: Colors.PRIMARY_OFF_WHITE
    },
    headerContainer: {
        borderBottomLeftRadius: 25,
        borderBottomRightRadius: 25,
        width: width,
        backgroundColor: 'white',
        shadowColor: '#333',
        shadowOffset: {
            width: 3,
            height: 3
        },
        shadowOpacity: 0.5,
        shadowRadius: 10,
        elevation: 15,
        paddingVertical: width * 0.05,
        marginBottom: 30
    }
});

const mapStateToProps = ({ profile }) => {
    const {
        role,
        activated,
        profileImg,
        legalName,
        username,
        email,
        phoneNumber,
        bio,
        adultRated,
        categories,
        verified
    } = profile;

    return {
        role,
        activated,
        profileImg,
        legalName,
        username,
        email,
        phoneNumber,
        bio,
        adultRated,
        categories,
        verified
    };
};

const mapDispatchToProps = { onProfileChange };

export default connect(mapStateToProps, mapDispatchToProps)(AccountScreen);

AccountModal.js:

//imports removed for brevity
const { height, width } = Dimensions.get('window');

class AccountModal extends React.Component {
    constructor (props) {
        super(props);
        this.state = {
            rating: null,
            visible: props.visible,
            text: '',
            text2: '',
            showInput: false,
            type: '',
            img: '',
            categories: props.categories != null ? props.categories : []
        };
    }
    componentDidMount () {
        let first = this.props.type[0];
        this.setState({ type: this.props.type.replace(/^./, first.toUpperCase()) });
    }
    format = (input) => {
        let trimmed = input;
        trimmed = trimmed.includes(' ') ? trimmed.replace(' ', '-') : trimmed;
        return (trimmed = trimmed[0].toUpperCase() + trimmed.substring(1));
    };
    openImgPicker = () => {
        ImagePicker.openPicker({
            width: 150,
            height: 150,
            cropping: true,
            cropperToolbarTitle: 'Pinch/Zoom to Crop Image',
            cropperCircleOverlay: true
        }).then((img) => {
            this.setState({ img: img.path });
        });
    };
    addCategory = () => {
        let trimmed = this.format(this.state.text);
        this.setState({ categories: [ ...this.state.categories, trimmed ] });
        this.refs.input.clear();
    };
    closeModal = () => {
        this.props.closeModal();
        this.refs.input.clear();
        this.props.resetInfo();
    };
    onSave = (type) => {
        switch (type) {
            case 'Bio':
                this.props.updateBio(this.props.docId, this.state.text);
                break;
            case 'Username':
                this.props.updateUsername(this.props.docId, this.state.text);
                break;
            case 'Email':
                this.props.updateEmail(this.props.docId, this.state.text);
                break;
            case 'Categories':
                this.props.updateCategories(this.props.docId, this.state.categories);
                break;
            case 'AdultRated':
                this.props.updateAdultRated(this.props.docId, this.state.rating);
                break;
            case 'ProfileImg':
                this.props.updateProfileImg({
                    uid: this.props.user.uid,
                    id: this.props.docId,
                    uri: this.state.img,
                    url: this.props.profileImg
                });
                break;
            case 'PhoneNumber':
                this.props.sendVerificationCode(this.state.text);
                this.refs.input.clear();
                break;
            case 'ConfirmCode':
                this.props.compareCode(
                    { id: this.props.verificationId, inputCode: this.state.text },
                    this.props.docId,
                    this.props.phoneNumber
                );
            case 'Verified':
            case 'Activate':
            case 'Deactivate':
        }
    };
    renderModal = () => {
        switch (this.state.type) {
            case 'Bio':
            case 'Username':
            case 'Email':
            case 'Verified':
                return (
                    <Modal
                        visible={this.state.visible}
                        transparent={true}
                        animationType={'slide'}
                        onRequestClose={() => this.closeModal}
                    >
                        <View style={styles.modalContainer}>
                            <Components.BodyText
                                text={this.state.type + ':'}
                                style={{
                                    color: 'white',
                                    fontSize: 20,
                                    fontWeight: 'bold',
                                    textAlign: 'center',
                                    marginBottom: 5
                                }}
                            />

                            <Components.BodyText
                                text={
                                    this.state.type === 'Selfie' ? (
                                        '$' + this.props.selfie + ' per selfie or screenshot'
                                    ) : this.state.type === 'Video' || this.state.type === 'Voice' ? (
                                        '$ ' + this.props[this.props.type] + ' per 5 minutes'
                                    ) : (
                                        this.props[this.props.type]
                                    )
                                }
                                style={{
                                    fontSize: 14,
                                    marginBottom: 20,
                                    color: 'white',
                                    textAlign: 'center'
                                }}
                            />

                            <Components.TransparentInput
                                placeholder={'Edit...'}
                                placeholderColor={'white'}
                                style={{
                                    borderRadius: 20,
                                    justifyContent: 'center',
                                    height: this.props.type === 'bio' ? width * 0.25 : width * 0.1,
                                    width: width * 0.6,
                                    marginBottom: 10,
                                    padding: 5
                                }}
                                ref={'input'}
                                multiline={this.props.type === 'bio' ? true : false}
                                onChangeText={(text) => {
                                    this.setState({ text: text.trim() });
                                }}
                            />

                            {this.props.info != '' ? (
                                <Components.BodyText text={this.props.info} fontSize={14} style={{ color: 'white' }} />
                            ) : null}

                            <ActivityIndicator
                                animating={this.props.loading}
                                color={Colors.PRIMARY_GREEN}
                                size={'small'}
                            />
                            // For specific firebase error forcing re-authentication
                            {this.props.info.includes('sensitive') ? (
                                <Components.Button
                                    text={'Re-Authenticate'}
                                    type={'alert'}
                                    onPress={() => this.props.navigation.navigate('Login')}
                                />
                            ) : null}

                            <View style={{ flexDirection: 'row', justifyContent: 'space-evenly', marginTop: 10 }}>
                                <Components.Button
                                    onPress={() => this.closeModal()}
                                    type={'secondary'}
                                    text={'Close'}
                                    fontSize={16}
                                    style={{ marginRight: 20 }}
                                />
                                <Components.Button
                                    onPress={() => this.onSave(this.state.type)}
                                    type={'primary'}
                                    text={'Save'}
                                    fontSize={16}
                                />
                            </View>
                        </View>
                    </Modal>
                );
            case 'ProfileImg':
                return (
                    <Modal
                        visible={this.state.visible}
                        transparent={true}
                        animationType={'slide'}
                        onRequestClose={() => this.closeModal}
                    >
                        <View style={styles.modalContainer}>
                            <TouchableOpacity
                                onPress={this.openImgPicker}
                                style={[ styles.transparentTouchable, { marginVertical: 20 } ]}
                            >
                                <Components.BodyText
                                    text={this.state.img != '' ? 'Image selected' : 'Tap to Select Image'}
                                    style={{ color: 'white', fontWeight: 'bold' }}
                                />
                            </TouchableOpacity>

                            {this.props.info != '' ? (
                                <Components.BodyText text={this.props.info} fontSize={14} style={{ color: 'white' }} />
                            ) : null}

                            <ActivityIndicator
                                animating={this.props.loading}
                                color={Colors.PRIMARY_GREEN}
                                size={'small'}
                            />

                            <View style={{ flexDirection: 'row', justifyContent: 'space-evenly', marginTop: 10 }}>
                                <Components.Button
                                    onPress={() => this.closeModal()}
                                    type={'secondary'}
                                    text={'Close'}
                                    fontSize={16}
                                    style={{ marginRight: 20 }}
                                />
                                <Components.Button
                                    onPress={() => this.onSave(this.state.type)}
                                    type={'primary'}
                                    text={'Save'}
                                    fontSize={16}
                                />
                            </View>
                        </View>
                    </Modal>
                );
            case 'AdultRated':
                return (
                    <Modal
                        visible={this.state.visible}
                        transparent={true}
                        animationType={'slide'}
                        onRequestClose={() => this.setState({ visible: false })}
                    >
                        <View style={styles.modalContainer}>
                            <Components.BodyText
                                text={
                                    this.state.rating == null ? (
                                        'Your current Adult Content rating: ' + '\n' + this.props.data
                                    ) : (
                                        "You're about to set Adult-Rated for: " + '\n' + this.state.rating
                                    )
                                }
                                style={{ color: 'white', textAlign: 'center', fontWeight: 'bold', fontSize: 16 }}
                            />

                            <Components.Button
                                onPress={() => this.setState({ rating: true })}
                                type={'alert'}
                                text={'Set for Adults'}
                                fontSize={16}
                                style={{ margin: 15 }}
                            />

                            <Components.Button
                                onPress={() => this.setState({ rating: false })}
                                type={'alert'}
                                text={'Set for Everyone'}
                                fontSize={16}
                                style={{ margin: 15 }}
                            />

                            {this.props.info != '' ? (
                                <Components.BodyText text={this.props.info} fontSize={14} style={{ color: 'white' }} />
                            ) : null}

                            <ActivityIndicator
                                animating={this.props.loading}
                                color={Colors.PRIMARY_GREEN}
                                size={'small'}
                            />

                            <View style={{ flexDirection: 'row', justifyContent: 'space-evenly', marginTop: 15 }}>
                                <Components.Button
                                    onPress={() => this.setState({ visible: false })}
                                    type={'secondary'}
                                    text={'Close'}
                                    fontSize={16}
                                    style={{ marginRight: 20 }}
                                />
                                <Components.Button
                                    onPress={() => this.onSave(this.state.type)}
                                    type={'primary'}
                                    text={'Save'}
                                    fontSize={16}
                                />
                            </View>
                        </View>
                    </Modal>
                );
            case 'Categories':
                return (
                    <Modal
                        visible={this.state.visible}
                        transparent={true}
                        animationType={'slide'}
                        onRequestClose={() => this.setState({ visible: false })}
                    >
                        <View style={styles.modalContainer}>
                            <Components.BodyText
                                text={this.state.type + ':'}
                                style={{ color: 'white', fontSize: 20, fontWeight: 'bold', textAlign: 'center' }}
                            />

                            <Components.BodyText
                                text={'Tap a category to delete'}
                                style={{ color: 'white', fontSize: 12, textAlign: 'center', marginBottom: 20 }}
                            />

                            <FlatList
                                data={this.state.categories}
                                style={{ marginVertical: 20 }}
                                horizontal={false}
                                numColumns={2}
                                keyExtractor={(item) => {
                                    return (
                                        item.toString() +
                                        new Date().getTime().toString() +
                                        Math.floor(Math.random() * Math.floor(new Date().getTime())).toString()
                                    );
                                }}
                                renderItem={({ item, index }) => (
                                    <TouchableOpacity
                                        onPress={() => {
                                            this.setState({
                                                categories: this.state.categories.filter((category) => {
                                                    if (item != category) {
                                                        return true;
                                                    } else {
                                                        return false;
                                                    }
                                                })
                                            });
                                        }}
                                        style={styles.transparentTouchable}
                                    >
                                        <Components.BodyText
                                            text={index + 1 + '. ' + item}
                                            style={{ fontSize: 16, color: 'white' }}
                                        />
                                    </TouchableOpacity>
                                )}
                            />

                            <View
                                style={{
                                    flexDirection: 'row',
                                    justifyContent: 'space-evenly',
                                    marginTop: 25,
                                    marginBottom: 15,
                                    alignItems: 'center'
                                }}
                            >
                                <Components.TransparentInput
                                    placeholder={'Add a category...'}
                                    placeholderColor={'white'}
                                    style={{ height: width * 0.1, width: width * 0.33, marginRight: 20 }}
                                    onChangeText={(text) => {
                                        this.setState({ text });
                                    }}
                                    returnKeyType={'done'}
                                    onSubmitEditing={() => this.addCategory()}
                                    ref={'input'}
                                />
                                <TouchableOpacity
                                    onPress={() => {
                                        this.addCategory();
                                    }}
                                >
                                    <Image
                                        source={require('../assets/img/white-plus.png')}
                                        resizeMode={'contain'}
                                        style={{ height: width * 0.09, width: width * 0.09 }}
                                    />
                                </TouchableOpacity>
                            </View>

                            {this.props.info != '' ? (
                                <Components.BodyText text={this.props.info} fontSize={14} style={{ color: 'white' }} />
                            ) : null}

                            <ActivityIndicator
                                animating={this.props.loading}
                                color={Colors.PRIMARY_GREEN}
                                size={'small'}
                            />

                            <View style={{ flexDirection: 'row', justifyContent: 'space-evenly', marginTop: 15 }}>
                                <Components.Button
                                    onPress={() => this.closeModal()}
                                    type={'secondary'}
                                    text={'Close'}
                                    fontSize={16}
                                    style={{ marginRight: 20 }}
                                />
                                <Components.Button
                                    onPress={() => this.onSave(this.state.type)}
                                    type={'primary'}
                                    text={'Save'}
                                    fontSize={16}
                                />
                            </View>
                        </View>
                    </Modal>
                );
            case 'Activate':
                return (
                    <Modal
                        visible={this.state.visible}
                        transparent={true}
                        animationType={'slide'}
                        onRequestClose={() => this.closeModal}
                    >
                        <View style={styles.modalContainer}>
                            <Components.BodyText
                                text={this.state.type + ' your account'}
                                style={{
                                    color: 'white',
                                    fontSize: 20,
                                    fontWeight: 'bold',
                                    textAlign: 'center',
                                    marginBottom: 5
                                }}
                            />

                            <Components.BodyText
                                text={
                                    'Profile must be complete to activate account. Activation status determines whether profile is accessbile in the Discover section'
                                }
                                style={{
                                    color: 'white',
                                    fontSize: 14,
                                    textAlign: 'center',
                                    marginBottom: 5
                                }}
                            />

                            {this.props.info != '' ? (
                                <Components.BodyText text={this.props.info} fontSize={14} style={{ color: 'white' }} />
                            ) : null}

                            <ActivityIndicator
                                animating={this.props.loading}
                                color={Colors.PRIMARY_GREEN}
                                size={'small'}
                            />

                            <View
                                style={{
                                    flexDirection: 'row',
                                    justifyContent: 'center',
                                    alignItems: 'center',
                                    marginBottom: 15
                                }}
                            >
                                <Components.Button
                                    onPress={() => this.onSave('Deactivate')}
                                    type={'action'}
                                    text={'De-Activate'}
                                    fontSize={16}
                                    style={{ marginRight: 20, height: width * 0.1 }}
                                />
                                <Components.Button
                                    onPress={() => this.onSave(this.state.type)}
                                    type={'primary'}
                                    text={'Activate'}
                                    fontSize={16}
                                    style={{ height: width * 0.1 }}
                                />
                            </View>

                            <Components.Button
                                onPress={() => this.closeModal()}
                                type={'secondary'}
                                text={'Close'}
                                fontSize={16}
                                style={{ height: width * 0.1 }}
                            />
                        </View>
                    </Modal>
                );
            case 'Password':
                return (
                    <Modal
                        visible={this.state.visible}
                        transparent={true}
                        animationType={'slide'}
                        onRequestClose={() => this.closeModal}
                    >
                        <View style={styles.modalContainer}>
                            <Components.BodyText
                                text={'Reset Password'}
                                style={{ color: 'white', fontWeight: 'bold', fontSize: 18, textAlign: 'center' }}
                            />
                            {this.props.info != '' ? (
                                <Components.BodyText
                                    text={this.props.info}
                                    fontSize={14}
                                    style={{ color: 'white', textAlign: 'center', marginVertical: 20 }}
                                />
                            ) : null}

                            <ActivityIndicator
                                animating={this.props.loading}
                                color={Colors.PRIMARY_GREEN}
                                size={'small'}
                            />

                            <View style={{ flexDirection: 'row', justifyContent: 'space-evenly', marginTop: 10 }}>
                                <Components.Button
                                    onPress={() => this.closeModal()}
                                    type={'secondary'}
                                    text={'Close'}
                                    fontSize={16}
                                    style={{ marginRight: 20 }}
                                />
                                <Components.Button
                                    onPress={() => this.props.sendPwdLink(this.props.email)}
                                    type={'primary'}
                                    text={'Reset'}
                                    fontSize={16}
                                />
                            </View>
                        </View>
                    </Modal>
                );
            case 'PhoneNumber':
                return (
                    <Modal
                        visible={this.state.visible}
                        transparent={true}
                        animationType={'slide'}
                        onRequestClose={() => this.closeModal}
                    >
                        <View style={styles.modalContainer}>
                            <Components.BodyText
                                text={'Update Phone Number'}
                                style={{ color: 'white', fontWeight: 'bold', fontSize: 20 }}
                            />
                            {this.props.verificationId == null ? (
                                <View style={{ alignItems: 'center' }}>
                                    <Components.TransparentInput
                                        placeholder={'Enter new phone number'}
                                        placeholderColor={'white'}
                                        style={{
                                            height: width * 0.1,
                                            width: width * 0.45,
                                            marginTop: 20,
                                            marginBottom: 5
                                        }}
                                        onChangeText={(text) => {
                                            this.setState({ text: text.trim() });
                                        }}
                                        returnKeyType={'done'}
                                        ref={'input'}
                                    />
                                    <Components.BodyText
                                        text={
                                            "Remember to include a '+', your country code, followed by your number. No spaces or hyphens."
                                        }
                                        style={{ color: 'white', textAlign: 'center', paddingHorizontal: 20 }}
                                    />
                                    {this.props.info != '' ? (
                                        <Components.BodyText
                                            text={this.props.info}
                                            fontSize={14}
                                            style={{ marginTop: 25, color: 'white' }}
                                        />
                                    ) : null}

                                    <ActivityIndicator
                                        animating={this.props.loading}
                                        color={Colors.PRIMARY_GREEN}
                                        size={'small'}
                                    />
                                    <View
                                        style={{ flexDirection: 'row', justifyContent: 'space-evenly', marginTop: 15 }}
                                    >
                                        <Components.Button
                                            onPress={() => this.closeModal()}
                                            type={'secondary'}
                                            text={'Close'}
                                            fontSize={16}
                                            style={{ marginRight: 20 }}
                                        />
                                        <Components.Button
                                            onPress={() => {
                                                this.onSave(this.state.type);
                                            }}
                                            type={'primary'}
                                            text={'Send Code'}
                                            fontSize={16}
                                        />
                                    </View>
                                </View>
                            ) : (
                                <View style={{ alignItems: 'center' }}>
                                    <Components.TransparentInput
                                        placeholder={'Enter confirmation code'}
                                        placeholderColor={'white'}
                                        style={{ height: width * 0.1, width: width * 0.45 }}
                                        onChangeText={(text) => {
                                            this.setState({ text: text.trim() });
                                        }}
                                        returnKeyType={'done'}
                                        ref={'input'}
                                    />

                                    {this.props.info != '' ? (
                                        <Components.BodyText
                                            text={this.props.info}
                                            fontSize={14}
                                            style={{ color: 'white' }}
                                        />
                                    ) : null}

                                    <ActivityIndicator
                                        animating={this.props.loading}
                                        color={Colors.PRIMARY_GREEN}
                                        size={'small'}
                                    />

                                    <View
                                        style={{ flexDirection: 'row', justifyContent: 'space-evenly', marginTop: 15 }}
                                    >
                                        <Components.Button
                                            onPress={() => this.closeModal()}
                                            type={'secondary'}
                                            text={'Close'}
                                            fontSize={16}
                                            style={{ marginRight: 20 }}
                                        />
                                        <Components.Button
                                            onPress={() => this.onSave('ConfirmCode')}
                                            type={'primary'}
                                            text={'Confirm Code'}
                                            fontSize={16}
                                        />
                                    </View>
                                </View>
                            )}
                        </View>
                    </Modal>
                );
        }
    };

    render () {
        return <View>{this.renderModal()}</View>;
    }
}

const styles = StyleSheet.create({
    modalContainer: {
        width: width * 0.8,
        backgroundColor: Colors.PRIMARY_DARK,
        borderRadius: 20,
        borderWidth: 2,
        borderColor: Colors.PRIMARY_GREEN,
        alignItems: 'center',
        alignSelf: 'center',
        shadowColor: '#333',
        shadowOffset: {
            width: 30,
            height: 30
        },
        shadowOpacity: 0.9,
        shadowRadius: 30,
        elevation: 15,
        position: 'absolute',
        top: height * 0.25,
        paddingTop: 15,
        paddingBottom: 25
    },
    transparentTouchable: {
        margin: 5,
        borderWidth: 1,
        borderColor: Colors.PRIMARY_OFF_WHITE,
        borderRadius: width,
        paddingHorizontal: width * 0.025,
        paddingVertical: width * 0.015
    }
});

const mapDispatchToProps = {
    updateBio,
    resetInfo,
    updateUsername,
    updateEmail,
    updateCategories,
    updateAdultRated,
    updateProfileImg,
    updatePassword,
    sendPwdLink,
    sendVerificationCode,
    compareCode
};

const mapStateToProps = ({ profile, auth }) => {
    const {
        activated,
        profileImg,
        legalName,
        username,
        email,
        phoneNumber,
        bio,
        adultRated,
        categories,
        verified,
        info,
        loading,
        docId,
        selfie,
        video,
        voice,
        verificationId
    } = profile;
    const { user, error } = auth;
    return {
        activated,
        profileImg,
        legalName,
        username,
        email,
        phoneNumber,
        bio,
        adultRated,
        categories,
        verified,
        info,
        user,
        loading,
        docId,
        selfie,
        video,
        voice,
        error,
        verificationId
    };
};

export default connect(mapStateToProps, mapDispatchToProps)(AccountModal);
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$
  • We can create a method to dynamically serve the redundant TouchableOpacity block as below:

    <TouchableOpacity
        style={{
            padding: width * 0.05,
            borderBottomWidth: 1,
            borderBottomColor: Colors.PRIMARY_OFF_WHITE
        }}
        onPress={() => this.setModal(setModal)}
    >
        <Components.BodyText style={{ fontSize: 18 }} text={textContent} />
    </TouchableOpacity>
    
  • Destructuring the state and props using ES6 destructuring.

    const {visible, modalData, modalType} = this.state;
    const {navigation} = this.props;
    
  • To keep main render clean we can further extract the IMG, ROW JSX into a method __renderImgNameRow

Applying all this yields:

import React from 'react';
import { StyleSheet, ScrollView, View, Dimensions, Image } from 'react-native';
import * as Colors from '../assets/colors';
import * as Components from '../components';
import { onProfileChange } from '../actions/Profile';
import { TouchableOpacity } from 'react-native-gesture-handler';
import { connect } from 'react-redux';
const { width } = Dimensions.get('window');

class AccountScreen extends React.Component {
    constructor (props) {
        super(props);
        this.state = {
            visible: false,
            modalType: null,
            modalData: ''
        };
        this.listener = props.onProfileChange(this.props.email);
    }
    setModal = (type) => {
        this.setState({ visible: !this.state.visible, modalType: type, modalData: this.props[type] });
    };
    renderConditionalOptions = () => {
        if (this.props.role === 'a') {
            return (
                <View>
                    {this.props.activated !== true ? (
                        this.__renderLowerTouchables('activate', 'Activate/De-Activate')
                    ) : null}
                    {this.__renderLowerTouchables('adultRated', 'Change Content Rating')}
                    {this.__renderLowerTouchables('categories', 'Modify Categories')}

                    <TouchableOpacity
                        style={{
                            padding: width * 0.05,
                            borderBottomWidth: 1,
                            borderBottomColor: Colors.PRIMARY_OFF_WHITE
                        }}
                        onPress={() => this.verificationProcess}
                    >
                        <Components.BodyText style={{ fontSize: 18 }} text={'Get Verified'} />
                    </TouchableOpacity>
                </View>
            );
        }
    };

    __renderLowerTouchables = (setModal, textContent) => {
        return (
            <TouchableOpacity
                        style={{
                            padding: width * 0.05,
                            borderBottomWidth: 1,
                            borderBottomColor: Colors.PRIMARY_OFF_WHITE
                        }}
                        onPress={() => this.setModal(setModal)}
                    >
                        <Components.BodyText style={{ fontSize: 18 }} text={textContent} />
                    </TouchableOpacity>
        )
    }

    __renderImgNameRow = () => {
        return (
            <View style={{ justifyContent: 'space-evenly', alignItems: 'center', flexDirection: 'row' }}>
                        <TouchableOpacity
                            onPress={() => this.setModal('profileImg')}
                            style={{
                                alignItems: 'center',
                                justifyContent: 'center',
                                borderColor: Colors.PRIMARY_GREEN,
                                borderWidth: 5,
                                borderRadius: width * 0.7,
                                backgroundColor: Colors.PRIMARY_OFF_WHITE,
                                width: width * 0.35,
                                height: width * 0.35
                            }}
                        >
                            <Image
                                style={{ borderRadius: width * 0.5, height: width * 0.33, width: width * 0.33 }}
                                source={
                                    this.props.profileImg != '' ? (
                                        { uri: this.props.profileImg }
                                    ) : (
                                        require('../assets/img/white-user.png')
                                    )
                                }
                                resizeMode={'contain'}
                            />
                        </TouchableOpacity>

                        <View style={{ alignItems: 'center' }}>
                            <Components.BodyText
                                text={this.props.legalName}
                                style={{
                                    fontSize: 22,
                                    fontWeight: 'bold',
                                    marginTop: width * 0.01
                                }}
                            />
                            {/* Edit Username  */}
                            <TouchableOpacity
                                onPress={() => this.setModal('username')}
                                style={{
                                    borderWidth: 1,
                                    borderColor: Colors.PRIMARY_OFF_WHITE,
                                    borderRadius: width,
                                    paddingHorizontal: width * 0.025,
                                    paddingVertical: width * 0.015,
                                    marginTop: width * 0.01
                                }}
                            >
                                <Components.BodyText
                                    text={'@' + this.props.username}
                                    style={{ textAlign: 'center', fontSize: 16 }}
                                />
                            </TouchableOpacity>
                        </View>
                    </View>
        )
    }

    render () {
        const {visible, modalData, modalType} = this.state;
        const {navigation} = this.props;
        return (
            <ScrollView style={styles.container}>
                {/* HEADER CONTAINER CONTAINER */}
                <View style={styles.headerContainer}>
                    {/* IMG / NAME ROW */}
                    {__renderImgNameRow()}
                </View>
                {/* LOWER CONTAINER */}
                <View
                    style={style.lowerContainer}
                >
                    {this.__renderLowerTouchables('email', 'Update Email')}
                    {this.__renderLowerTouchables('password', 'Change Password')}
                    {this.__renderLowerTouchables('phoneNumber', 'Update Phone Number')}
                    {/* CONDITIONAL OPTIONS */}
                    {this.renderConditionalOptions()}
                </View>

                {visible && (
                    <Components.AccountModal
                        visible={visible}
                        data={modalData}
                        type={modalType}
                        closeModal={this.setModal}
                        navigation={navigation}
                    />
                )}
            </ScrollView>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        //justifyContent: 'space-between',
        backgroundColor: Colors.PRIMARY_OFF_WHITE
    },
    headerContainer: {
        borderBottomLeftRadius: 25,
        borderBottomRightRadius: 25,
        width: width,
        backgroundColor: 'white',
        shadowColor: '#333',
        shadowOffset: {
            width: 3,
            height: 3
        },
        shadowOpacity: 0.5,
        shadowRadius: 10,
        elevation: 15,
        paddingVertical: width * 0.05,
        marginBottom: 30
    },
    lowerContainer: {
                        borderTopLeftRadius: 25,
                        borderTopRightRadius: 25,
                        borderBottomLeftRadius: 25,
                        borderBottomRightRadius: 25,
                        backgroundColor: 'white',
                        width: width,
                        marginBottom: width * 0.05
                    }
});

const mapStateToProps = ({ profile }) => {
    const {
        role,
        activated,
        profileImg,
        legalName,
        username,
        email,
        phoneNumber,
        bio,
        adultRated,
        categories,
        verified
    } = profile;

    return {
        role,
        activated,
        profileImg,
        legalName,
        username,
        email,
        phoneNumber,
        bio,
        adultRated,
        categories,
        verified
    };
};

const mapDispatchToProps = { onProfileChange };

export default connect(mapStateToProps, mapDispatchToProps)(AccountScreen);
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.