codeforbtv/cvoeo-app

View on GitHub
screens/goal-details/index.js

Summary

Maintainability
F
4 days
Test Coverage
// @flow

import React, {Component} from 'react';
import {bindActionCreators} from 'redux';
import {Container} from 'native-base';
import {LinearGradient} from 'expo-linear-gradient';
import {
    Alert,
    Animated,
    Dimensions,
    Image,
    Platform,
    ScrollView,
    StatusBar,
    StyleSheet,
    Text,
    TouchableHighlight,
    View,
    YellowBox
} from 'react-native';
import {connect} from 'react-redux';
import Icon from 'react-native-vector-icons/FontAwesome5';
import DateTimePicker from 'react-native-modal-datetime-picker';
import * as actionCreators from './actions';
import commonStyles from '../../styles/common';
import MenuCircle from '../../components/menu-circle';
import styles from './styles';
import moment from 'moment';
import * as R from 'ramda';
import {isValidDate} from '../../libs/validators';

const myStyles = StyleSheet.create({...commonStyles, ...styles});

YellowBox.ignoreWarnings(['Setting a timer']);

type Props = {
    actions: Object,
    navigation: Object,
    uid: string
};

const addDaysToDate = R.curry((date, daysToAdd) => {
    const myDate = isValidDate(date) ? date : new Date();
    return moment(myDate).add(daysToAdd, 'day').toDate();
});

class GoalDetails extends Component<Props> {

    constructor(props) {
        super(props);
        this.ellipsisToggle = this.ellipsisToggle.bind(this);
        this.ellipsisLogoutAlert = this.ellipsisLogoutAlert.bind(this);
        this.state = {
            expanded2: false,
            expanded3: false,
            menuScale: new Animated.Value(0.01),
            isDatePickerVisible: false
        };
        this.icons = {
            dots: 'ellipsis-v',
            open: 'angle-down',
            close: 'angle-up'
        };
    }

    ellipsisToggle() {
        // Toggle circular menu open/close
        if (this.state.menuScale._value <= 0.01) {
            Animated.timing(
                this.state.menuScale,
                {
                    toValue: 1,
                    duration: 500
                }
            ).start();
        } else if (this.state.menuScale._value === 1.0) {
            Animated.timing(
                this.state.menuScale,
                {
                    toValue: 0,
                    duration: 500
                }
            ).start();
        }
    }

    ellipsisLogoutAlert() {
        const logoutCallback = this.props.actions.logout;

        Alert.alert(
            'Do you want to logout?',
            'This will return you to the login screen.',
            [
                {text: 'Logout', onPress: logoutCallback},
                {text: 'Cancel', onPress: this.ellipsisToggle, style: 'cancel'}
            ],
            {cancelable: false}
        );
    }

    showCustomDatePicker = () => {
        this.setState({isDatePickerVisible: true});
    };

    handleCustomDatePicked =  R.curry((update, date) => {
        this.hideCustomDatePicker();
        update({remind: date})();
    })

    hideCustomDatePicker = () => {
        this.setState({isDatePickerVisible: false});
    };

    render() {
        const dots = this.icons.dots;
        const {navigation, uid, actions} = this.props;
        const goal = navigation.getParam('goal');
        const resetReminder = addDaysToDate(new Date());
        const update = _changes => () => {
            actions.updateGoal(uid, goal, _changes);
            navigation.navigate('Dashboard');
        };
        return (
            <Container>
                {Platform.OS === 'ios' && <StatusBar barStyle='default'/>}

                <View style={myStyles.dashRow}>
                    <View style={myStyles.titleRow}>
                        <Image
                            source={require('../../assets/images/FinancialFuturesLogo.jpg')}
                            style={
                                {
                                    position: 'absolute',
                                    left: -55,
                                    top: 18,
                                    width: '100%',
                                    height: 40,
                                    resizeMode: 'contain'
                                }
                            }
                        />
                        <Text style={[myStyles.title, {marginLeft: 100}]}>{' '}</Text>
                    </View>
                    <View style={myStyles.dots}>
                        <Animated.View
                            style={{
                                position: 'absolute',
                                transform: [
                                    {scale: this.state.menuScale}
                                ],
                                top: -125,
                                left: -133
                            }}
                        >
                            <TouchableHighlight
                                onPress={() => this.ellipsisLogoutAlert()}
                                underlayColor='transparent'
                                style={{
                                    width: 300,
                                    height: 300,
                                    zIndex: 1
                                }}
                            >
                                <View>
                                    <MenuCircle/>
                                    <Text style={myStyles.logoutText}>Log out</Text>
                                </View>
                            </TouchableHighlight>
                        </Animated.View>
                        <TouchableHighlight
                            onPress={this.ellipsisToggle}
                            underlayColor='transparent'
                        >
                            <Icon
                                name={dots}
                                style={myStyles.ellipsis}
                            />
                        </TouchableHighlight>
                    </View>
                </View>
                <LinearGradient
                    colors={['#fff', '#EFF0BE']}
                    style={
                        {
                            position: 'absolute',
                            left: 0,
                            right: 0,
                            top: 60,
                            height: (Dimensions.get('window').height - 60),
                            zIndex: -1
                        }
                    }
                />
                <TouchableHighlight
                    onPress={() => navigation.navigate('Dashboard')}
                    style={myStyles.backButton}
                >
                    <View style={myStyles.backButtonContentWrapper}>
                        <Icon name={'chevron-down'} style={myStyles.backButtonIcon}/>
                        <Text style={myStyles.backButtonText}>{'Close'}</Text>
                    </View>
                </TouchableHighlight>
                <ScrollView style={myStyles.scrollArea}>
                    <Text style={myStyles.subTitle}>{goal.title}</Text>
                    <Text style={myStyles.subText}>{goal.detail}</Text>
                    <View style={myStyles.buttonWrapper}>
                        <View style={myStyles.blockLabel}>
                            <Icon style={myStyles.blockLabelIcon} name={'user-clock'}/>
                            <Text style={myStyles.blockLabelText}>Remind me:</Text>
                        </View>
                        <TouchableHighlight
                            onPress={update({remind: resetReminder(1)})}
                            style={[myStyles.detailButton, {backgroundColor: '#F88E6D'}]}
                        >
                            <Text style={myStyles.detailButtonText}>tomorrow</Text>
                        </TouchableHighlight>
                        <TouchableHighlight
                            onPress={update({remind: resetReminder(3)})}
                            style={[myStyles.detailButton, {backgroundColor: '#FFD4C6'}]}
                        >
                            <Text style={myStyles.detailButtonText}>in 3 days</Text>
                        </TouchableHighlight>
                        <TouchableHighlight
                            onPress={update({remind: resetReminder(7)})}
                            style={[myStyles.detailButton, {backgroundColor: '#F6F4D6'}]}
                        >
                            <Text style={myStyles.detailButtonText}>in 1 week</Text>
                        </TouchableHighlight>
                        <TouchableHighlight
                            onPress={this.showCustomDatePicker}
                            style={[myStyles.detailButton, {backgroundColor: '#F6F4D6'}]}
                        >
                            <Text style={myStyles.detailButtonText}>Add date</Text>
                        </TouchableHighlight>
                        <TouchableHighlight
                            onPress={update({snoozed: !goal.snoozed})}
                            style={[myStyles.detailButton, {backgroundColor: '#F2F2CC'}]}>
                            <Text style={myStyles.detailButtonText}>{!goal.snoozed ? 'Pause' : 'Un-pause'}</Text>
                        </TouchableHighlight>
                        
                        <DateTimePicker
                            date={new Date()}
                            isVisible={this.state.isDatePickerVisible}
                            minimumDate={new Date()}
                            mode={'date'}
                            onCancel={this.hideCustomDatePicker}
                            onConfirm={this.handleCustomDatePicked(update)}
                        />
                    </View>
                </ScrollView>
            </Container>
        );
    }
}

const mapStateToProps = (state) => {
    const uid = (state.login.user || {}).uid;
    return {uid};
};

const mapDispatchToProps = (dispatch) => ({
    actions: bindActionCreators(actionCreators, dispatch)
});

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