Merge branch 'settings-menu-footer' into 'master'

Fixes settings item menu in footer missing active state

Closes #282

See merge request bloodyhealth/drip!164
This commit is contained in:
Julia Friesel
2019-01-22 16:01:48 +00:00
2 changed files with 141 additions and 90 deletions
+69 -56
View File
@@ -20,20 +20,17 @@ const headerTitlesLowerCase = Object.keys(headerTitles).reduce((acc, curr) => {
acc[curr] = headerTitles[curr].toLowerCase() acc[curr] = headerTitles[curr].toLowerCase()
return acc return acc
}, {}) }, {})
const menuTitlesLowerCase = Object.keys(menuTitles).reduce((acc, curr) => {
acc[curr] = menuTitles[curr].toLowerCase()
return acc
}, {})
const isSymptomView = name => Object.keys(symptomViews).includes(name) const HOME_PAGE = 'Home'
const isSettingsView = name => Object.keys(settingsViews).includes(name) const INFO_SYMPTOM_PAGE = 'InfoSymptom'
const isMenuItem = name => Object.keys(menuTitles).includes(name) const CYCLE_DAY_PAGE = 'CycleDay'
const SETTINGS_MENU_PAGE = 'SettingsMenu'
export default class App extends Component { export default class App extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
currentPage: 'Home' currentPage: HOME_PAGE
} }
this.backHandler = BackHandler.addEventListener('hardwareBackPress', this.handleBackButtonPress) this.backHandler = BackHandler.addEventListener('hardwareBackPress', this.handleBackButtonPress)
setupNotifications(this.navigate) setupNotifications(this.navigate)
@@ -44,91 +41,107 @@ export default class App extends Component {
} }
navigate = (pageName, props) => { navigate = (pageName, props) => {
const { currentPage } = this.state
// for the back button to work properly, we want to // for the back button to work properly, we want to
// remember two origins: which menu item we came from // remember two origins: which menu item we came from
// and from where we navigated to the symptom view (day // and from where we navigated to the symptom view (day
// view or home page) // view or home page)
if (isMenuItem(this.state.currentPage)) { if (this.isMenuItem()) {
this.menuOrigin = this.state.currentPage this.menuOrigin = currentPage
} }
if (!isSymptomView(this.state.currentPage) && if (!this.isSymptomView() && !this.isInfoSymptomView()) {
this.state.currentPage !== 'InfoSymptom') { this.originForSymptomView = currentPage
this.originForSymptomView = this.state.currentPage
} }
this.setState({currentPage: pageName, currentProps: props}) this.setState({ currentPage: pageName, currentProps: props })
} }
handleBackButtonPress = () => { handleBackButtonPress = () => {
if (this.state.currentPage === 'Home') return false const { currentPage, currentProps } = this.state
if (isSymptomView(this.state.currentPage)) { if (currentPage === HOME_PAGE) return false
if (this.isSymptomView()) {
this.navigate( this.navigate(
this.originForSymptomView, { date: this.state.currentProps.date } this.originForSymptomView, { date: currentProps.date }
) )
} else if (isSettingsView(this.state.currentPage)) { } else if (this.isSettingsView()) {
this.navigate('SettingsMenu') this.navigate(SETTINGS_MENU_PAGE)
} else if (this.state.currentPage === 'CycleDay') { } else if (currentPage === CYCLE_DAY_PAGE) {
this.navigate(this.menuOrigin) this.navigate(this.menuOrigin)
} else if (this.state.currentPage === 'InfoSymptom') { } else if (this.isInfoSymptomView()) {
const { date, cycleDay, symptomView } = currentProps
this.navigate( this.navigate(
this.state.currentProps.symptomView, { symptomView, { date, cycleDay })
date: this.state.currentProps.date,
cycleDay: this.state.currentProps.cycleDay
})
} else { } else {
this.navigate('Home') this.navigate(HOME_PAGE)
} }
return true return true
} }
isMenuItem() {
return Object.keys(menuTitles).includes(this.state.currentPage)
}
isSymptomView() {
return Object.keys(symptomViews).includes(this.state.currentPage)
}
isInfoSymptomView() {
return this.state.currentPage === INFO_SYMPTOM_PAGE
}
isSettingsView() {
return Object.keys(settingsViews).includes(this.state.currentPage)
}
isDefaultView() { isDefaultView() {
return this.state.currentPage !== 'CycleDay' && const { currentPage } = this.state
!isSymptomView(this.state.currentPage) && return currentPage !== CYCLE_DAY_PAGE &&
this.state.currentPage !== 'InfoSymptom' !this.isSymptomView() &&
!this.isInfoSymptomView()
} }
render() { render() {
const page = { const { currentPage, currentProps } = this.state
Home, Calendar, CycleDay, Chart, InfoSymptom, const pages = {
SettingsMenu, ...settingsViews, Stats, ...symptomViews Home,
}[this.state.currentPage] Calendar,
CycleDay,
Chart,
InfoSymptom,
SettingsMenu,
...settingsViews,
Stats,
...symptomViews
}
const page = pages[currentPage]
const title = headerTitlesLowerCase[currentPage]
const isSymptomView = this.isSymptomView()
return ( return (
<View style={{flex: 1}}> <View style={{flex: 1}}>
{this.isDefaultView() && {this.isDefaultView() &&
<Header <Header title={title} />
title={headerTitlesLowerCase[this.state.currentPage]}
/>
} }
{this.state.currentPage === 'InfoSymptom' && {this.isInfoSymptomView() &&
<Header <Header title={title} goBack={this.handleBackButtonPress} />
title={headerTitlesLowerCase[this.state.currentPage]}
goBack={this.handleBackButtonPress}
/>
} }
{isSymptomView(this.state.currentPage) && {isSymptomView &&
<Header <Header
title={headerTitlesLowerCase[this.state.currentPage]} title={title}
isSymptomView={true} isSymptomView={true}
goBack={this.handleBackButtonPress} goBack={this.handleBackButtonPress}
date={this.state.currentProps.date} date={currentProps.date}
goToSymptomInfo={() => this.navigate('InfoSymptom', { goToSymptomInfo={() => this.navigate(INFO_SYMPTOM_PAGE, {
date: this.state.currentProps.date, symptomView: currentPage,
symptomView: this.state.currentPage, ...currentProps
cycleDay: this.state.currentProps.cycleDay
})} })}
/>} />}
{React.createElement(page, { {React.createElement(page, {
navigate: this.navigate, navigate: this.navigate,
...this.state.currentProps ...currentProps
})} })}
{!isSymptomView(this.state.currentPage) && {!isSymptomView &&
<Menu <Menu navigate={this.navigate} currentPage={currentPage} />
navigate={this.navigate}
titles={menuTitlesLowerCase}
currentPage={this.state.currentPage}
/>
} }
</View> </View>
) )
+61 -23
View File
@@ -1,46 +1,84 @@
import React, { Component } from 'react' import React from 'react'
import { import {
View, View,
Text, Text,
TouchableOpacity TouchableOpacity
} from 'react-native' } from 'react-native'
import settingsViews from './settings'
import { menuTitles } from '../i18n/en/labels'
import styles, { iconStyles, secondaryColor } from '../styles' import styles, { iconStyles, secondaryColor } from '../styles'
import Icon from 'react-native-vector-icons/MaterialCommunityIcons' import Icon from 'react-native-vector-icons/MaterialCommunityIcons'
export default class Menu extends Component { const menuTitlesLowerCase = Object.keys(menuTitles).reduce((acc, curr) => {
makeMenuItem = ({ title, icon, onPress}, i) => { acc[curr] = menuTitles[curr].toLowerCase()
const styleActive = (this.props.currentPage.toLowerCase() === title) ? return acc
{color: secondaryColor} : {} }, {})
const menuItems = [
{
labelKey: 'Home',
icon: 'home',
component: 'Home',
},
{
labelKey: 'Calendar',
icon: 'calendar-range',
component: 'Calendar',
},
{
labelKey: 'Chart',
icon: 'chart-line',
component: 'Chart',
},
{
labelKey: 'Stats',
icon: 'chart-pie',
component: 'Stats',
},
{
labelKey: 'Settings',
icon: 'settings',
component: 'SettingsMenu',
children: Object.keys(settingsViews),
}
]
const MenuItem = ({ icon, labelKey, active, onPress }) => {
const styleActive = active ? { color: secondaryColor } : null
return ( return (
<TouchableOpacity <TouchableOpacity
onPress={onPress}
style={styles.menuItem} style={styles.menuItem}
key={i.toString()} onPress={onPress}
> >
<Icon name={icon} {...iconStyles.menuIcon} {...styleActive} /> <Icon name={icon} {...iconStyles.menuIcon} {...styleActive} />
<Text style={[styles.menuText, styleActive]}> <Text style={[styles.menuText, styleActive]}>
{title} {menuTitlesLowerCase[labelKey]}
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
) )
} }
goTo(componentName) { const Menu = ({ currentPage, navigate }) => {
this.props.navigate(componentName)
}
render() {
const t = this.props.titles
return ( return (
<View style={styles.menu}> <View style={styles.menu}>
{[ { menuItems.map(({ icon, labelKey, component, children }) => {
{ title: t.Home, icon: 'home', onPress: () => this.goTo('Home') }, const isActive = (component === currentPage) ||
{ title: t.Calendar, icon: 'calendar-range', onPress: () => this.goTo('Calendar') }, (children && children.indexOf(currentPage) !== -1)
{ title: t.Chart, icon: 'chart-line', onPress: () => this.goTo('Chart') }, return (
{ title: t.Stats, icon: 'chart-pie', onPress: () => this.goTo('Stats') }, <MenuItem
{ title: t.Settings, icon: 'settings', onPress: () => this.goTo('SettingsMenu') }, key={labelKey}
].map(this.makeMenuItem)} labelKey={labelKey}
icon={icon}
active={isActive}
onPress={() => navigate(component)}
/>
)}
)}
</View > </View >
) )
}
} }
export default Menu