src/components/views/helpers/sidedrawer.js
import React, { Component } from 'react';
import { Platform, TouchableHighlight, Text, View, StyleSheet, FlatList } from 'react-native';
import Drawer from 'react-native-drawer';
import Icon from 'react-native-vector-icons/FontAwesome';
import PropTypes from 'prop-types';
import DrawerHelp from '../../../util/drawerhelper';
import SafeArea from './safearea';
import DrawerHeader from './drawerheader';
import NavigatorService from '../../../config/navigationservice';
/**
* Class for the side drawer component.
* @extends Component
*/
class SideDrawer extends Component {
/**
* Helper prop types.
*/
static propTypes = {
renderMainContent: PropTypes.func.isRequired
}
/**
* Creates an instance of the SideDrawer component.
*
* @constructor
* @param {Object} props - The component's properties
*/
constructor (props) {
super(props);
this.state = { drawerOpen: false, numNotifications: 0, profileData: {} };
// console.log(this.state.drawerOpen);
DrawerHelp.setDrawer(this);
};
/**
* Component has mounted.
*/
componentDidMount = () => {
this.setState({
profileData: {profilePicture: DrawerHelp.getDefaultProfile()}
})
}
/**
* Toggles the side drawer open and closed.
*/
toggleDrawer = () => {
// console.log(this.state.drawerOpen);
this.setState({
drawerOpen: !this.state.drawerOpen
});
}
/**
* Render a text input item.
*
* @param {Object} item - A list item
*/
_renderItem = ({item}) => (
<View style={styles.icon}>
<Icon.Button
name={item.icon_name}
type={item.icon_type}
backgroundColor="#F5FCFF"
color="#000"
size={30}
onPress={() => this.onItemPressed(item)}>
<Text style={styles.itemText}>{item.text}</Text>
{
this.state.numNotifications > 0 &&
item.text === 'Alerts' &&
<View style={styles.notifications}>
<Text style={styles.notificationsText}>{this.state.numNotifications}</Text>
</View>
}
</Icon.Button>
</View>
);
/**
* Function is called when a drawer item is pressed.
*
* @param {Object} item - The drawer item that is pressed, see drawerData for possible items.
*/
onItemPressed = (item) => {
let routeParams = {};
if (item.hasOwnProperty('params')) { // If there's parameters, flatten them
routeParams = this.getParams(item.params);
}
this.navigateToScreen(item.screen, routeParams);
}
/**
* Flattens a list of objects into an object with properties.
* Example:
* Original: [{key: k1, value: v1}, {key: k2, value: v2}]
* After: {k1: v1, k2: v2}
*
* @param {List} params - A list of key, value pair objects
* @return {Object} An object with properties
*/
getParams = (params) => {
let paramsAsObject = {};
for (let i=0; i < params.length; i++) {
// Property value 'key' becomes the property in final object
paramsAsObject[params[i].key] = params[i].value;
}
return paramsAsObject;
}
/**
* Navigate to a specified screen. Screen must be a possible navigation
*
* @param {string} screen - The name of the screen to navigate to.
* @param {Object} params - The params to add to the navigation call. Key, value pairs
*/
navigateToScreen = (screen, params) => {
// console.log(screen);
this.closeDrawer();
// Need to use navigator service because we are navigating from above the root navigator
NavigatorService.navigate(screen, params);
}
/**
* Closes the drawer.
*/
closeDrawer = () => {
this._drawer.close();
this.setState({drawerOpen: false});
};
/**
* Opens the drawer.
*
* @param {Number} numNotifications - The number of notifications
*/
openDrawer = (numNotifications) => {
this._drawer.open();
this.setState({drawerOpen: true, numNotifications});
};
/**
* Extract the key from the item and index
*/
_keyExtractor = (item, index) => item.text;
/**
* Render the contents of the drawer.
*/
renderSideMenuContent = () => (
return (
<View style={{height: '100%'}}>
<SafeArea/>
<DrawerHeader
image={this.state.profileData.profilePicture}
name={this.state.profileData.full_name ? this.state.profileData.full_name : ''}/>
<FlatList
style={styles.flatList}
data={drawerData}
extraData={this.state}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}/>
<SafeArea />
</View>
);
/**
* Render the side drawer.
*/
render() {
return (
<Drawer
ref={(ref) => this._drawer = ref}
open={this.state.drawerOpen}
content={this.renderSideMenuContent()}
type="overlay"
tapToClose={true}
styles={drawerStyles}
openDrawerOffset={0.2}
panCloseMask={0.2}
closedDrawerOffset={-3}
onClose={() => {
this.setState({drawerOpen: false});
}}
panOpenMask={0.80}
captureGestures="open"
acceptPan={false}>
{/* Main Content goes here (e.g. Tab Views) */}
{this.props.renderMainContent()}
</Drawer>
);
}
}
export default SideDrawer;
/*
* 'text' property is the drawer name
* 'icon_name' property is the icon name from the icon type
* 'icon_type' property is the type of icon (see react-native-vector-icons)
* 'screen' property must be the stack navigator defined in navigation.js
* 'params' property is a list of key, value pair objects. The 'key' property will appear as a param in the navigated to screen, with value 'value'
*/
const drawerData = [
{
text: 'Profile',
icon_name: 'user',
icon_type: 'font-awesome',
screen: 'ProfileStack',
},
{
text: 'Alerts',
icon_name: 'bell',
icon_type: 'font-awesome',
screen: 'AlertStack'
},
{
text: 'Settings',
icon_name: 'cog',
icon_type: 'font-awesome',
screen: 'SettingsStack'
},
{
text: 'Help Center',
icon_name: 'info-circle',
icon_type: 'font-awesome',
screen: 'HelpStack'
},
{
text: 'Logout',
icon_name: 'sign-out',
icon_type: 'font-awesome',
screen: 'AuthLoading',
params: [{ key: 'logout', value: true }]
}
]
const drawerStyles = StyleSheet.create({
drawer: {
shadowColor: '#000000',
shadowOpacity: 0.8,
shadowRadius: 3,
// backgroundColor: 'rgba(0, 0, 0, 0.5)',
backgroundColor: '#F5FCFF',
},
main: {
paddingLeft: 3
},
});
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
icon: {
marginTop: 5,
marginLeft: 5,
marginRight: 5,
// padding: 10
},
flatlist: {
flex: 1,
marginTop: 5
},
itemText: {
flex: 1,
fontSize: 20,
paddingRight: 40,
marginLeft: 20,
marginTop: 3
},
notifications: {
width: 30,
height: 30,
borderRadius: 15,
marginLeft: 5,
backgroundColor: '#696969',
alignItems: 'center',
justifyContent: 'center'
},
notificationsText: {
fontSize: 20,
color: 'white',
}
});