On temperature view, replace menu with action buttons

This commit is contained in:
Julia Friesel
2018-08-20 13:35:40 +02:00
parent 87ac1d6b29
commit d897c3b89f
7 changed files with 102 additions and 184 deletions
+35 -24
View File
@@ -1,11 +1,11 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import { View, BackHandler } from 'react-native' import { View, BackHandler, ScrollView } from 'react-native'
import Header from './components/header' import Header from './components/header'
import Menu from './components/menu' import Menu from './components/menu'
import Home from './components/home' import Home from './components/home'
import Calendar from './components/calendar' import Calendar from './components/calendar'
import CycleDay from './components/cycle-day/cycle-day-overview' import CycleDay from './components/cycle-day/cycle-day-overview'
import SymptomView from './components/cycle-day/symptoms' import symptomViews from './components/cycle-day/symptoms'
import Chart from './components/chart/chart' import Chart from './components/chart/chart'
import Settings from './components/settings' import Settings from './components/settings'
import Stats from './components/stats' import Stats from './components/stats'
@@ -13,8 +13,11 @@ import Stats from './components/stats'
// this is until react native fixes this bugg, see // this is until react native fixes this bugg, see
// https://github.com/facebook/react-native/issues/18868#issuecomment-382671739 // https://github.com/facebook/react-native/issues/18868#issuecomment-382671739
import { YellowBox } from 'react-native' import { YellowBox } from 'react-native'
import ActionButtonFooter from './components/cycle-day/symptoms/action-button-footer';
YellowBox.ignoreWarnings(['Warning: isMounted(...) is deprecated']) YellowBox.ignoreWarnings(['Warning: isMounted(...) is deprecated'])
const isSymptomView = name => Object.keys(symptomViews).indexOf(name) > -1
export default class App extends Component { export default class App extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
@@ -24,9 +27,11 @@ export default class App extends Component {
const handleBackButtonPress = function() { const handleBackButtonPress = function() {
if (this.state.currentPage === 'Home') return false if (this.state.currentPage === 'Home') return false
// this is handled in the SymptomView if (isSymptomView(this.state.currentPage)) {
if (this.state.currentPage === 'SymptomView') return true this.navigate('CycleDay', {cycleDay: this.state.currentProps.cycleDay})
} else {
this.navigate('Home') this.navigate('Home')
}
return true return true
}.bind(this) }.bind(this)
@@ -41,34 +46,40 @@ export default class App extends Component {
this.setState({currentPage: pageName, currentProps: props}) this.setState({currentPage: pageName, currentProps: props})
} }
setActionButtonState(actionButtonInfo) {
this.setState({actionButtonInfo})
}
unsetActionButtonState() {
this.setState({actionButtonInfo: null})
}
render() { render() {
const page = {
Home, Calendar, CycleDay, Chart, Settings, Stats, ...symptomViews
}[this.state.currentPage]
return ( return (
<View style={{height: '100%', justifyContent: 'space-between' }}> <View style={{height: '100%', justifyContent: 'space-between' }}>
<View> <View>
{this.state.currentPage != 'CycleDay' && <Header title={this.state.currentPage}/>} {this.state.currentPage != 'CycleDay' && <Header title={this.state.currentPage}/>}
<View> <ScrollView>
<CurrentPage {React.createElement(page, {
page={this.state.currentPage} navigate: this.navigate.bind(this),
setActionButtonState: this.setActionButtonState.bind(this),
unsetActionButtonState: this.unsetActionButtonState.bind(this),
...this.state.currentProps
})}
</ScrollView>
</View>
{isSymptomView(this.state.currentPage) && this.state.actionButtonInfo ?
<ActionButtonFooter
{...this.state.actionButtonInfo}
navigate={this.navigate.bind(this)} navigate={this.navigate.bind(this)}
props={this.state.currentProps}
/> />
</View> :
</View> <Menu navigate={this.navigate.bind(this)}/>
<Menu navigate={this.navigate.bind(this)} /> }
</View> </View>
) )
} }
} }
class CurrentPage extends Component {
render () {
const page = {
Home, Calendar, CycleDay, SymptomView, Chart, Settings, Stats
}[this.props.page]
const props = this.props.props || {}
return React.createElement(page, {
navigate: this.props.navigate,
...props
})
}
}
-47
View File
@@ -1,47 +0,0 @@
import React from 'react'
import {
View,
Button,
} from 'react-native'
import { saveSymptom } from '../../db'
export default function (navigateToOverView) {
return function ({ symptom, cycleDay, saveAction, saveDisabled}) {
const buttons = [
{
title: 'Cancel',
action: () => navigateToOverView()
},
{
title: 'Delete',
action: () => {
saveSymptom(symptom, cycleDay)
navigateToOverView()
},
disabledCondition: !cycleDay[symptom]
}, {
title: 'Save',
action: () => {
saveAction()
navigateToOverView()
},
disabledCondition: saveDisabled
}
]
return buttons.map(({ title, action, disabledCondition }, i) => {
const style = { flex: 1, marginHorizontal: 10 }
if (i === 0) style.marginLeft = 0
if (i === buttons.length - 1) style.marginRight = 0
return (
<View style={style} key={i}>
<Button
onPress={action}
disabled={disabledCondition}
title={title}>
</Button>
</View >
)
})
}
}
+2 -3
View File
@@ -40,9 +40,8 @@ export default class CycleDayOverView extends Component {
} }
navigate(symptom) { navigate(symptom) {
this.props.navigate('SymptomView', { this.props.navigate(symptom, {
symptom, cycleDay: this.state.cycleDay,
cycleDay: this.state.cycleDay
}) })
} }
@@ -1,19 +1,20 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import { import {
View, View, TouchableOpacity, Text
Button,
} from 'react-native' } from 'react-native'
import Icon from 'react-native-vector-icons/MaterialCommunityIcons'
import { saveSymptom } from '../../../db' import { saveSymptom } from '../../../db'
import styles from '../../../styles' import styles, {iconStyles} from '../../../styles'
export default class ActionButtonFooter extends Component { export default class ActionButtonFooter extends Component {
render() { render() {
const { symptom, cycleDay, saveAction, saveDisabled, navigate} = this.props const { symptom, cycleDay, saveAction, saveDisabled, navigate} = this.props
const navigateToOverView = () => navigate('CycleDay', cycleDay) const navigateToOverView = () => navigate('CycleDay', {cycleDay})
const buttons = [ const buttons = [
{ {
title: 'Cancel', title: 'Cancel',
action: () => navigateToOverView() action: () => navigateToOverView(),
icon: 'cancel'
}, },
{ {
title: 'Delete', title: 'Delete',
@@ -21,31 +22,34 @@ export default class ActionButtonFooter extends Component {
saveSymptom(symptom, cycleDay) saveSymptom(symptom, cycleDay)
navigateToOverView() navigateToOverView()
}, },
disabledCondition: !cycleDay[symptom] disabledCondition: !cycleDay[symptom],
icon: 'delete-outline'
}, { }, {
title: 'Save', title: 'Save',
action: () => { action: () => {
saveAction() saveAction()
navigateToOverView() navigateToOverView()
}, },
disabledCondition: saveDisabled disabledCondition: saveDisabled,
icon: 'content-save-outline'
} }
] ]
return ( return (
<View style={styles.actionButtonRow}> <View style={styles.menu}>
{buttons.map(({ title, action, disabledCondition }, i) => { {buttons.map(({ title, action, disabledCondition, icon }, i) => {
const style = { flex: 1, marginHorizontal: 10 }
if (i === 0) style.marginLeft = 0
if (i === buttons.length - 1) style.marginRight = 0
return ( return (
<View style={style} key={i}> <TouchableOpacity
<Button
onPress={action} onPress={action}
style={styles.menuItem}
disabled={disabledCondition} disabled={disabledCondition}
title={title}> key={i.toString()}
</Button> >
</View > <Icon name={icon} {...iconStyles.menuIcon} />
<Text style={styles.menuText}>
{title}
</Text>
</TouchableOpacity>
) )
})} })}
</View> </View>
+1 -55
View File
@@ -1,7 +1,3 @@
import React, { Component } from 'react'
import { ScrollView, BackHandler } from 'react-native'
import Header from '../../header'
import actionButtonModule from '../action-buttons'
import BleedingEditView from './bleeding' import BleedingEditView from './bleeding'
import TemperatureEditView from './temperature' import TemperatureEditView from './temperature'
import MucusEditView from './mucus' import MucusEditView from './mucus'
@@ -10,7 +6,7 @@ import NoteEditView from './note'
import DesireEditView from './desire' import DesireEditView from './desire'
import SexEditView from './sex' import SexEditView from './sex'
const symptomViews = { export default {
BleedingEditView, BleedingEditView,
TemperatureEditView, TemperatureEditView,
MucusEditView, MucusEditView,
@@ -19,53 +15,3 @@ const symptomViews = {
DesireEditView, DesireEditView,
SexEditView SexEditView
} }
const titles = {
BleedingEditView: 'Bleeding',
TemperatureEditView: 'Temperature',
MucusEditView: 'Mucus',
CervixEditView: 'Cervix',
NoteEditView: 'Note',
DesireEditView: 'Desire',
SexEditView: 'Sex'
}
export default class SymptomView extends Component {
constructor(props) {
super(props)
this.state = {
visibleComponent: props.symptom,
cycleDay: props.cycleDay
}
this.makeActionButtons = actionButtonModule(() => {
this.props.navigate('CycleDay', {cycleDay: this.state.cycleDay})
})
const handleBackButtonPress = function() {
this.props.navigate('CycleDay', {cycleDay: this.state.cycleDay})
return true
}.bind(this)
this.backHandler = BackHandler.addEventListener('hardwareBackPress', handleBackButtonPress)
}
componentWillUnmount() {
this.backHandler.remove()
}
render() {
return (
<ScrollView>
<Header title={titles[this.state.visibleComponent]}/>
{React.createElement(
symptomViews[this.state.visibleComponent],
{
cycleDay: this.state.cycleDay,
makeActionButtons: this.makeActionButtons
}
)}
</ScrollView >
)
}
}
+21 -19
View File
@@ -4,7 +4,7 @@ import {
Text, Text,
TextInput, TextInput,
Switch, Switch,
Keyboard Keyboard,
} from 'react-native' } from 'react-native'
import DateTimePicker from 'react-native-modal-datetime-picker-nevo' import DateTimePicker from 'react-native-modal-datetime-picker-nevo'
@@ -37,10 +37,27 @@ export default class Temp extends Component {
time: this.time || LocalTime.now().truncatedTo(MINUTES).toString(), time: this.time || LocalTime.now().truncatedTo(MINUTES).toString(),
isTimePickerVisible: false isTimePickerVisible: false
} }
props.setActionButtonState({
symptom : 'temperature',
cycleDay: props.cycleDay,
saveAction: () => {
const dataToSave = {
value: Number(this.state.currentValue),
exclude: this.state.exclude,
time: this.state.time
}
saveSymptom('temperature', props.cycleDay, dataToSave)
},
saveDisabled: this.state.currentValue === '' || isInvalidTime(this.state.time)
})
}
componentWillUnmount() {
this.props.unsetActionButtonState()
} }
render() { render() {
const cycleDay = this.cycleDay
return ( return (
<View style={styles.symptomEditView}> <View style={styles.symptomEditView}>
<View style={styles.symptomViewRowInline}> <View style={styles.symptomViewRowInline}>
@@ -61,7 +78,7 @@ export default class Temp extends Component {
style={styles.temperatureTextInput} style={styles.temperatureTextInput}
onFocus={() => { onFocus={() => {
Keyboard.dismiss() Keyboard.dismiss()
this.setState({isTimePickerVisible: true}) this.setState({ isTimePickerVisible: true })
}} }}
value={this.state.time} value={this.state.time}
/> />
@@ -75,7 +92,7 @@ export default class Temp extends Component {
isTimePickerVisible: false isTimePickerVisible: false
}) })
}} }}
onCancel={() => this.setState({isTimePickerVisible: false})} onCancel={() => this.setState({ isTimePickerVisible: false })}
/> />
<View style={styles.symptomViewRowInline}> <View style={styles.symptomViewRowInline}>
<Text style={styles.symptomDayView}>Exclude</Text> <Text style={styles.symptomDayView}>Exclude</Text>
@@ -86,21 +103,6 @@ export default class Temp extends Component {
value={this.state.exclude} value={this.state.exclude}
/> />
</View> </View>
<View style={styles.actionButtonRow}>
{this.makeActionButtons({
symptom: 'temperature',
cycleDay: this.cycleDay,
saveAction: () => {
const dataToSave = {
value: Number(this.state.currentValue),
exclude: this.state.exclude,
time: this.state.time
}
saveSymptom('temperature', cycleDay, dataToSave)
},
saveDisabled: this.state.currentValue === '' || isInvalidTime(this.state.time)
})}
</View>
</View> </View>
) )
} }
+13 -10
View File
@@ -8,11 +8,12 @@ import styles, { iconStyles } from '../styles'
import Icon from 'react-native-vector-icons/MaterialCommunityIcons' import Icon from 'react-native-vector-icons/MaterialCommunityIcons'
export default class Menu extends Component { export default class Menu extends Component {
makeMenuItem({ title, icon, componentName }) { makeMenuItem({ title, icon, onPress}, i) {
return ( return (
<TouchableOpacity <TouchableOpacity
onPress={() => this.props.navigate(componentName)} onPress={onPress}
style={styles.menuItem} style={styles.menuItem}
key={i.toString()}
> >
<Icon name={icon} {...iconStyles.menuIcon} /> <Icon name={icon} {...iconStyles.menuIcon} />
<Text style={styles.menuText}> <Text style={styles.menuText}>
@@ -21,18 +22,20 @@ export default class Menu extends Component {
</TouchableOpacity> </TouchableOpacity>
) )
} }
goTo(componentName) {
this.props.navigate(componentName)
}
render() { render() {
return ( return (
this.props.symptomView ?
placeActionButtons()
:
<View style={styles.menu}> <View style={styles.menu}>
{[ {[
{title: 'Home', icon: 'home', componentName: 'Home'}, { title: 'Home', icon: 'home', onPress: () => this.goTo('Home') },
{title: 'Calendar', icon: 'calendar-range', componentName: 'Calendar'}, { title: 'Calendar', icon: 'calendar-range', onPress: () => this.goTo('Calendar') },
{title: 'Chart', icon: 'chart-line', componentName: 'Chart'}, { title: 'Chart', icon: 'chart-line', onPress: () => this.goTo('Chart') },
{title: 'Stats', icon: 'chart-pie', componentName: 'Stats'}, { title: 'Stats', icon: 'chart-pie', onPress: () => this.goTo('Stats') },
{title: 'Settings', icon: 'settings', componentName: 'Settings'}, { title: 'Settings', icon: 'settings', onPress: () => this.goTo('Settings') },
].map(this.makeMenuItem.bind(this))} ].map(this.makeMenuItem.bind(this))}
</View > </View >
) )