From d897c3b89f8c937abec549299ad65d70e8c5878c Mon Sep 17 00:00:00 2001
From: Julia Friesel <julia.friesel@gmail.com>
Date: Mon, 20 Aug 2018 13:35:40 +0200
Subject: [PATCH] On temperature view, replace menu with  action buttons

---
 app.js                                        | 63 +++++++++++--------
 components/cycle-day/action-buttons.js        | 47 --------------
 components/cycle-day/cycle-day-overview.js    |  5 +-
 .../symptoms/action-button-footer.js          | 42 +++++++------
 components/cycle-day/symptoms/index.js        | 58 +----------------
 components/cycle-day/symptoms/temperature.js  | 40 ++++++------
 components/menu.js                            | 31 ++++-----
 7 files changed, 102 insertions(+), 184 deletions(-)
 delete mode 100644 components/cycle-day/action-buttons.js

diff --git a/app.js b/app.js
index 2cfc07e7..b6e9ff58 100644
--- a/app.js
+++ b/app.js
@@ -1,11 +1,11 @@
 import React, { Component } from 'react'
-import { View, BackHandler } from 'react-native'
+import { View, BackHandler, ScrollView } from 'react-native'
 import Header from './components/header'
 import Menu from './components/menu'
 import Home from './components/home'
 import Calendar from './components/calendar'
 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 Settings from './components/settings'
 import Stats from './components/stats'
@@ -13,8 +13,11 @@ import Stats from './components/stats'
 // this is until react native fixes this bugg, see
 // https://github.com/facebook/react-native/issues/18868#issuecomment-382671739
 import { YellowBox } from 'react-native'
+import ActionButtonFooter from './components/cycle-day/symptoms/action-button-footer';
 YellowBox.ignoreWarnings(['Warning: isMounted(...) is deprecated'])
 
+const isSymptomView = name => Object.keys(symptomViews).indexOf(name) > -1
+
 export default class App extends Component {
   constructor(props) {
     super(props)
@@ -24,9 +27,11 @@ export default class App extends Component {
 
     const handleBackButtonPress = function() {
       if (this.state.currentPage === 'Home') return false
-      // this is handled in the SymptomView
-      if (this.state.currentPage === 'SymptomView') return true
-      this.navigate('Home')
+      if (isSymptomView(this.state.currentPage)) {
+        this.navigate('CycleDay', {cycleDay: this.state.currentProps.cycleDay})
+      } else {
+        this.navigate('Home')
+      }
       return true
     }.bind(this)
 
@@ -41,34 +46,40 @@ export default class App extends Component {
     this.setState({currentPage: pageName, currentProps: props})
   }
 
+  setActionButtonState(actionButtonInfo) {
+    this.setState({actionButtonInfo})
+  }
+
+  unsetActionButtonState() {
+    this.setState({actionButtonInfo: null})
+  }
+
   render() {
+    const page = {
+      Home, Calendar, CycleDay, Chart, Settings, Stats, ...symptomViews
+    }[this.state.currentPage]
     return (
       <View style={{height: '100%', justifyContent: 'space-between' }}>
         <View>
           {this.state.currentPage != 'CycleDay' && <Header title={this.state.currentPage}/>}
-          <View>
-            <CurrentPage
-              page={this.state.currentPage}
-              navigate={this.navigate.bind(this)}
-              props={this.state.currentProps}
-            />
-          </View>
+          <ScrollView>
+            {React.createElement(page, {
+              navigate: this.navigate.bind(this),
+              setActionButtonState: this.setActionButtonState.bind(this),
+              unsetActionButtonState: this.unsetActionButtonState.bind(this),
+              ...this.state.currentProps
+            })}
+          </ScrollView>
         </View>
-        <Menu navigate={this.navigate.bind(this)} />
+        {isSymptomView(this.state.currentPage) && this.state.actionButtonInfo ?
+          <ActionButtonFooter
+            {...this.state.actionButtonInfo}
+            navigate={this.navigate.bind(this)}
+          />
+          :
+          <Menu navigate={this.navigate.bind(this)}/>
+        }
       </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
-    })
-  }
 }
\ No newline at end of file
diff --git a/components/cycle-day/action-buttons.js b/components/cycle-day/action-buttons.js
deleted file mode 100644
index 0a6b0a07..00000000
--- a/components/cycle-day/action-buttons.js
+++ /dev/null
@@ -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 >
-      )
-    })
-  }
-}
\ No newline at end of file
diff --git a/components/cycle-day/cycle-day-overview.js b/components/cycle-day/cycle-day-overview.js
index 0076aa20..9ab32254 100644
--- a/components/cycle-day/cycle-day-overview.js
+++ b/components/cycle-day/cycle-day-overview.js
@@ -40,9 +40,8 @@ export default class CycleDayOverView extends Component {
   }
 
   navigate(symptom) {
-    this.props.navigate('SymptomView', {
-      symptom,
-      cycleDay: this.state.cycleDay
+    this.props.navigate(symptom, {
+      cycleDay: this.state.cycleDay,
     })
   }
 
diff --git a/components/cycle-day/symptoms/action-button-footer.js b/components/cycle-day/symptoms/action-button-footer.js
index 0f05a7bc..be0cd6ae 100644
--- a/components/cycle-day/symptoms/action-button-footer.js
+++ b/components/cycle-day/symptoms/action-button-footer.js
@@ -1,19 +1,20 @@
 import React, { Component } from 'react'
 import {
-  View,
-  Button,
+  View, TouchableOpacity, Text
 } from 'react-native'
+import Icon from 'react-native-vector-icons/MaterialCommunityIcons'
 import { saveSymptom } from '../../../db'
-import styles from '../../../styles'
+import styles, {iconStyles} from '../../../styles'
 
 export default class ActionButtonFooter extends Component {
   render() {
     const { symptom, cycleDay, saveAction, saveDisabled, navigate} = this.props
-    const navigateToOverView = () => navigate('CycleDay', cycleDay)
+    const navigateToOverView = () => navigate('CycleDay', {cycleDay})
     const buttons = [
       {
         title: 'Cancel',
-        action: () => navigateToOverView()
+        action: () => navigateToOverView(),
+        icon: 'cancel'
       },
       {
         title: 'Delete',
@@ -21,31 +22,34 @@ export default class ActionButtonFooter extends Component {
           saveSymptom(symptom, cycleDay)
           navigateToOverView()
         },
-        disabledCondition: !cycleDay[symptom]
+        disabledCondition: !cycleDay[symptom],
+        icon: 'delete-outline'
       }, {
         title: 'Save',
         action: () => {
           saveAction()
           navigateToOverView()
         },
-        disabledCondition: saveDisabled
+        disabledCondition: saveDisabled,
+        icon: 'content-save-outline'
       }
     ]
 
     return (
-      <View style={styles.actionButtonRow}>
-        {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
+      <View style={styles.menu}>
+        {buttons.map(({ title, action, disabledCondition, icon }, i) => {
           return (
-            <View style={style} key={i}>
-              <Button
-                onPress={action}
-                disabled={disabledCondition}
-                title={title}>
-              </Button>
-            </View >
+            <TouchableOpacity
+              onPress={action}
+              style={styles.menuItem}
+              disabled={disabledCondition}
+              key={i.toString()}
+            >
+              <Icon name={icon} {...iconStyles.menuIcon} />
+              <Text style={styles.menuText}>
+                {title}
+              </Text>
+            </TouchableOpacity>
           )
         })}
       </View>
diff --git a/components/cycle-day/symptoms/index.js b/components/cycle-day/symptoms/index.js
index 4ce40106..12622b73 100644
--- a/components/cycle-day/symptoms/index.js
+++ b/components/cycle-day/symptoms/index.js
@@ -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 TemperatureEditView from './temperature'
 import MucusEditView from './mucus'
@@ -10,7 +6,7 @@ import NoteEditView from './note'
 import DesireEditView from './desire'
 import SexEditView from './sex'
 
-const symptomViews = {
+export default {
   BleedingEditView,
   TemperatureEditView,
   MucusEditView,
@@ -18,54 +14,4 @@ const symptomViews = {
   NoteEditView,
   DesireEditView,
   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 >
-    )
-  }
-}
+}
\ No newline at end of file
diff --git a/components/cycle-day/symptoms/temperature.js b/components/cycle-day/symptoms/temperature.js
index 72968832..a7bd55e7 100644
--- a/components/cycle-day/symptoms/temperature.js
+++ b/components/cycle-day/symptoms/temperature.js
@@ -4,7 +4,7 @@ import {
   Text,
   TextInput,
   Switch,
-  Keyboard
+  Keyboard,
 } from 'react-native'
 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(),
       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() {
-    const cycleDay = this.cycleDay
     return (
       <View style={styles.symptomEditView}>
         <View style={styles.symptomViewRowInline}>
@@ -61,7 +78,7 @@ export default class Temp extends Component {
             style={styles.temperatureTextInput}
             onFocus={() => {
               Keyboard.dismiss()
-              this.setState({isTimePickerVisible: true})
+              this.setState({ isTimePickerVisible: true })
             }}
             value={this.state.time}
           />
@@ -75,7 +92,7 @@ export default class Temp extends Component {
               isTimePickerVisible: false
             })
           }}
-          onCancel={() => this.setState({isTimePickerVisible: false})}
+          onCancel={() => this.setState({ isTimePickerVisible: false })}
         />
         <View style={styles.symptomViewRowInline}>
           <Text style={styles.symptomDayView}>Exclude</Text>
@@ -86,21 +103,6 @@ export default class Temp extends Component {
             value={this.state.exclude}
           />
         </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>
     )
   }
diff --git a/components/menu.js b/components/menu.js
index 1a8bed76..8a551877 100644
--- a/components/menu.js
+++ b/components/menu.js
@@ -8,11 +8,12 @@ import styles, { iconStyles } from '../styles'
 import Icon from 'react-native-vector-icons/MaterialCommunityIcons'
 
 export default class Menu extends Component {
-  makeMenuItem({ title, icon, componentName }) {
+  makeMenuItem({ title, icon, onPress}, i) {
     return (
       <TouchableOpacity
-        onPress={() => this.props.navigate(componentName)}
+        onPress={onPress}
         style={styles.menuItem}
+        key={i.toString()}
       >
         <Icon name={icon} {...iconStyles.menuIcon} />
         <Text style={styles.menuText}>
@@ -21,20 +22,22 @@ export default class Menu extends Component {
       </TouchableOpacity>
     )
   }
+
+  goTo(componentName) {
+    this.props.navigate(componentName)
+  }
+
   render() {
     return (
-      this.props.symptomView ?
-        placeActionButtons()
-        :
-        <View style={styles.menu}>
-          {[
-            {title: 'Home', icon: 'home', componentName: 'Home'},
-            {title: 'Calendar', icon: 'calendar-range', componentName: 'Calendar'},
-            {title: 'Chart', icon: 'chart-line', componentName: 'Chart'},
-            {title: 'Stats', icon: 'chart-pie', componentName: 'Stats'},
-            {title: 'Settings', icon: 'settings', componentName: 'Settings'},
-          ].map(this.makeMenuItem.bind(this))}
-        </View >
+      <View style={styles.menu}>
+        {[
+          { title: 'Home', icon: 'home', onPress: () => this.goTo('Home') },
+          { title: 'Calendar', icon: 'calendar-range', onPress: () => this.goTo('Calendar') },
+          { title: 'Chart', icon: 'chart-line', onPress: () => this.goTo('Chart') },
+          { title: 'Stats', icon: 'chart-pie', onPress: () => this.goTo('Stats') },
+          { title: 'Settings', icon: 'settings', onPress: () => this.goTo('Settings') },
+        ].map(this.makeMenuItem.bind(this))}
+      </View >
     )
   }
 }
-- 
GitLab