From d2d5d2f41f7bdf6c9bc222a9667022b1ffc88fe6 Mon Sep 17 00:00:00 2001
From: Sofiya Tepikin <sofiya.tepikin@gmail.com>
Date: Fri, 9 Aug 2019 21:33:26 +0200
Subject: [PATCH] Splits <CycleDayOverView /> to smaller components, to
 simplify it

---
 components/cycle-day/FillerBoxes.js        |  20 ++
 components/cycle-day/SymptomBox.js         | 170 +++++++++++
 components/cycle-day/cycle-day-overview.js | 319 +++------------------
 3 files changed, 234 insertions(+), 275 deletions(-)
 create mode 100644 components/cycle-day/FillerBoxes.js
 create mode 100644 components/cycle-day/SymptomBox.js

diff --git a/components/cycle-day/FillerBoxes.js b/components/cycle-day/FillerBoxes.js
new file mode 100644
index 00000000..f0e0c024
--- /dev/null
+++ b/components/cycle-day/FillerBoxes.js
@@ -0,0 +1,20 @@
+import React, { Component } from 'react'
+import { View, Dimensions } from 'react-native'
+import styles from '../../styles'
+
+export default class FillerBoxes extends Component {
+  render() {
+    const n = Dimensions.get('window').width / styles.symptomBox.width
+    const fillerBoxes = []
+    for (let i = 0; i < Math.ceil(n); i++) {
+      fillerBoxes.push(
+        <View
+          width={styles.symptomBox.width}
+          height={0}
+          key={i.toString()}
+        />
+      )
+    }
+    return fillerBoxes
+  }
+}
\ No newline at end of file
diff --git a/components/cycle-day/SymptomBox.js b/components/cycle-day/SymptomBox.js
new file mode 100644
index 00000000..b4af7c3e
--- /dev/null
+++ b/components/cycle-day/SymptomBox.js
@@ -0,0 +1,170 @@
+import React, { Component } from 'react'
+import { View, TouchableOpacity } from 'react-native'
+
+import AppText from '../app-text'
+import DripIcon from '../../assets/drip-icons'
+
+import styles from '../../styles'
+
+import { headerTitles as symptomTitles } from '../../i18n/en/labels'
+import * as labels from '../../i18n/en/cycle-day'
+const bleedingLabels = labels.bleeding.labels
+const intensityLabels = labels.intensity
+const sexLabels = labels.sex.categories
+const contraceptiveLabels = labels.contraceptives.categories
+const painLabels = labels.pain.categories
+const moodLabels = labels.mood.categories
+
+function isNumber(val) {
+  return typeof val === 'number'
+}
+
+const l = {
+  bleeding: ({ value, exclude }) => {
+    if (isNumber(value)) {
+      const bleedingLabel = bleedingLabels[value]
+      return exclude ? `(${bleedingLabel})` : bleedingLabel
+    }
+  },
+  temperature: ({ value, time, exclude }) => {
+    if (isNumber(value)) {
+      let temperatureLabel = `${value} °C`
+      if (time) {
+        temperatureLabel += ` - ${time}`
+      }
+      if (exclude) {
+        temperatureLabel = `(${temperatureLabel})`
+      }
+      return temperatureLabel
+    }
+  },
+  mucus: mucus => {
+    const filledCategories = ['feeling', 'texture'].filter(c => isNumber(mucus[c]))
+    let label = filledCategories.map(category => {
+      return labels.mucus.subcategories[category] + ': ' + labels.mucus[category].categories[mucus[category]]
+    }).join(', ')
+
+    if (isNumber(mucus.value)) label += `\n => ${labels.mucusNFP[mucus.value]}`
+    if (mucus.exclude) label = `(${label})`
+
+    return label
+  },
+  cervix: cervix => {
+    const filledCategories = ['opening', 'firmness', 'position'].filter(c => isNumber(cervix[c]))
+    let label = filledCategories.map(category => {
+      return labels.cervix.subcategories[category] + ': ' + labels.cervix[category].categories[cervix[category]]
+    }).join(', ')
+
+    if (cervix.exclude) label = `(${label})`
+
+    return label
+  },
+  note: note => note.value,
+  desire: ({ value }) => {
+    if (isNumber(value)) {
+      return intensityLabels[value]
+    }
+  },
+  sex: sex => {
+    const sexLabel = []
+    if (sex && Object.values({...sex}).some(val => val)){
+      Object.keys(sex).forEach(key => {
+        if(sex[key] && key !== 'other' && key !== 'note') {
+          sexLabel.push(
+            sexLabels[key] ||
+            contraceptiveLabels[key]
+          )
+        }
+        if(key === 'other' && sex.other) {
+          let label = contraceptiveLabels[key]
+          if(sex.note) {
+            label = `${label} (${sex.note})`
+          }
+          sexLabel.push(label)
+        }
+      })
+      return sexLabel.join(', ')
+    }
+  },
+  pain: pain => {
+    const painLabel = []
+    if (pain && Object.values({...pain}).some(val => val)){
+      Object.keys(pain).forEach(key => {
+        if(pain[key] && key !== 'other' && key !== 'note') {
+          painLabel.push(painLabels[key])
+        }
+        if(key === 'other' && pain.other) {
+          let label = painLabels[key]
+          if(pain.note) {
+            label = `${label} (${pain.note})`
+          }
+          painLabel.push(label)
+        }
+      })
+      return painLabel.join(', ')
+    }
+  },
+  mood: mood => {
+    const moodLabel = []
+    if (mood && Object.values({...mood}).some(val => val)){
+      Object.keys(mood).forEach(key => {
+        if(mood[key] && key !== 'other' && key !== 'note') {
+          moodLabel.push(moodLabels[key])
+        }
+        if(key === 'other' && mood.other) {
+          let label = moodLabels[key]
+          if(mood.note) {
+            label = `${label} (${mood.note})`
+          }
+          moodLabel.push(label)
+        }
+      })
+      return moodLabel.join(', ')
+    }
+  }
+}
+
+export default class SymptomBox extends Component {
+  getLabel = () => {
+    const { symptom, symptomData } = this.props
+    return symptomData && l[symptom](symptomData)
+  }
+
+  render() {
+    const { symptom, onPress, disabled } = this.props
+    const data = this.getLabel()
+    const iconName = `drip-icon-${symptom}`
+
+    const disabledStyle = disabled ? styles.symptomInFuture : null
+    const containerStyle = [
+      styles.symptomBox,
+      data && styles.symptomBoxActive,
+      disabledStyle
+    ]
+    const titleStyle = [
+      data && styles.symptomTextActive,
+      disabledStyle,
+      {fontSize: 15}
+    ]
+    const dataBoxStyle = [styles.symptomDataBox, disabledStyle]
+
+    return (
+      <TouchableOpacity onPress={onPress} disabled={disabled} testID={iconName}>
+        <View style={containerStyle}>
+          <Icon name={iconName} isActive={data} />
+          <AppText style={titleStyle} numberOfLines={1}>
+            {symptomTitles[symptom].toLowerCase()}
+          </AppText>
+        </View>
+        <View style={dataBoxStyle}>
+          <AppText style={styles.symptomDataText} numberOfLines={3}>
+            {data}
+          </AppText>
+        </View>
+      </TouchableOpacity>
+    )
+  }
+}
+
+const Icon = ({name, isActive}) =>
+  <DripIcon name={name} size={50} color={isActive ? 'white' : 'black'} />
\ 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 407aac2b..2961f815 100644
--- a/components/cycle-day/cycle-day-overview.js
+++ b/components/cycle-day/cycle-day-overview.js
@@ -1,33 +1,21 @@
 import React, { Component } from 'react'
-import {
-  ScrollView,
-  View,
-  TouchableOpacity,
-  Dimensions
-} from 'react-native'
+import { ScrollView, View } from 'react-native'
 import { LocalDate } from 'js-joda'
 import Header from '../header'
+import FillerBoxes from './FillerBoxes'
+import SymptomBox from './SymptomBox'
+
 import { getCycleDay } from '../../db'
 import cycleModule from '../../lib/cycle'
 import styles from '../../styles'
-import * as labels from '../../i18n/en/cycle-day'
-import { headerTitles as symptomTitles } from '../../i18n/en/labels'
-import AppText from '../app-text'
-import DripIcon from '../../assets/drip-icons'
-
-const bleedingLabels = labels.bleeding.labels
-const intensityLabels = labels.intensity
-const sexLabels = labels.sex.categories
-const contraceptiveLabels = labels.contraceptives.categories
-const painLabels = labels.pain.categories
-const moodLabels = labels.mood.categories
 
 export default class CycleDayOverView extends Component {
   constructor(props) {
     super(props)
+    const { date } = this.props
     this.state = {
-      date: this.props.date,
-      cycleDay: getCycleDay(this.props.date)
+      date,
+      cycleDay: getCycleDay(date)
     }
   }
 
@@ -46,216 +34,54 @@ export default class CycleDayOverView extends Component {
     this.props.navigate(symptom, this.state)
   }
 
-  getLabel(symptomName) {
-    const cycleDay = this.state.cycleDay
-    if (!cycleDay || !cycleDay[symptomName]) return
-
-    const l = {
-      bleeding: bleeding => {
-        if (isNumber(bleeding.value)) {
-          let bleedingLabel = bleedingLabels[bleeding.value]
-          if (bleeding.exclude) bleedingLabel = "( " + bleedingLabel + " )"
-          return bleedingLabel
-        }
-      },
-      temperature: temperature => {
-        if (isNumber(temperature.value)) {
-          let temperatureLabel = `${temperature.value} °C`
-          if (temperature.time) {
-            temperatureLabel = `${temperatureLabel} - ${temperature.time}`
-          }
-          if (temperature.exclude) {
-            temperatureLabel = "( " + temperatureLabel + " )"
-          }
-          return temperatureLabel
-        }
-      },
-      mucus: mucus => {
-        const filledCategories = ['feeling', 'texture'].filter(c => isNumber(mucus[c]))
-        let label = filledCategories.map(category => {
-          return labels.mucus.subcategories[category] + ': ' + labels.mucus[category].categories[mucus[category]]
-        }).join(', ')
-
-        if (isNumber(mucus.value)) label += `\n => ${labels.mucusNFP[mucus.value]}`
-        if (mucus.exclude) label = `(${label})`
-
-        return label
-      },
-      cervix: cervix => {
-        const filledCategories = ['opening', 'firmness', 'position'].filter(c => isNumber(cervix[c]))
-        let label = filledCategories.map(category => {
-          return labels.cervix.subcategories[category] + ': ' + labels.cervix[category].categories[cervix[category]]
-        }).join(', ')
-
-        if (cervix.exclude) label = `(${label})`
-
-        return label
-      },
-      note: note => {
-        return note.value
-      },
-      desire: desire => {
-        if (isNumber(desire.value)) {
-          const desireLabel = `${intensityLabels[desire.value]}`
-          return desireLabel
-        }
-      },
-      sex: sex => {
-        let sexLabel = []
-        if (sex && Object.values({...sex}).some(val => val)){
-          Object.keys(sex).forEach(key => {
-            if(sex[key] && key !== 'other' && key !== 'note') {
-              sexLabel.push(
-                sexLabels[key] ||
-                contraceptiveLabels[key]
-              )
-            }
-            if(key === 'other' && sex.other) {
-              let label = contraceptiveLabels[key]
-              if(sex.note) {
-                label = `${label} (${sex.note})`
-              }
-              sexLabel.push(label)
-            }
-          })
-          sexLabel = sexLabel.join(', ')
-          return sexLabel
-        }
-      },
-      pain: pain => {
-        let painLabel = []
-        if (pain && Object.values({...pain}).some(val => val)){
-          Object.keys(pain).forEach(key => {
-            if(pain[key] && key !== 'other' && key !== 'note') {
-              painLabel.push(painLabels[key])
-            }
-            if(key === 'other' && pain.other) {
-              let label = painLabels[key]
-              if(pain.note) {
-                label = `${label} (${pain.note})`
-              }
-              painLabel.push(label)
-            }
-          })
-          painLabel = painLabel.join(', ')
-          return painLabel
-        }
-      },
-      mood: mood => {
-        let moodLabel = []
-        if (mood && Object.values({...mood}).some(val => val)){
-          Object.keys(mood).forEach(key => {
-            if(mood[key] && key !== 'other' && key !== 'note') {
-              moodLabel.push(moodLabels[key])
-            }
-            if(key === 'other' && mood.other) {
-              let label = moodLabels[key]
-              if(mood.note) {
-                label = `${label} (${mood.note})`
-              }
-              moodLabel.push(label)
-            }
-          })
-          moodLabel = moodLabel.join(', ')
-          return moodLabel
-        }
-      }
-    }
-
-    const symptomValue = cycleDay[symptomName]
-    return l[symptomName](symptomValue)
-  }
-
   render() {
-    const getCycleDayNumber = cycleModule().getCycleDayNumber
-    const cycleDayNumber = getCycleDayNumber(this.state.date)
-    const dateInFuture = LocalDate
-      .now()
-      .isBefore(LocalDate.parse(this.state.date))
+    const { date, cycleDay } = this.state
+    const { getCycleDayNumber } = cycleModule()
+    const cycleDayNumber = getCycleDayNumber(date)
+    const dateInFuture = LocalDate.now().isBefore(LocalDate.parse(date))
+
+    const symptomBoxesList = [
+      'bleeding',
+      'temperature',
+      'mucus',
+      'cervix',
+      'desire',
+      'sex',
+      'pain',
+      'mood',
+      'note',
+    ]
 
     return (
       <View style={{ flex: 1 }}>
         <Header
           isCycleDayOverView={true}
           cycleDayNumber={cycleDayNumber}
-          date={this.state.date}
+          date={date}
           goToCycleDay={this.goToCycleDay}
         />
         <ScrollView>
           <View style={styles.symptomBoxesView}>
-            <SymptomBox
-              title={symptomTitles.bleeding}
-              onPress={() => this.navigate('BleedingEditView')}
-              data={this.getLabel('bleeding')}
-              disabled={dateInFuture}
-              iconName='drip-icon-bleeding'
-            >
-            </SymptomBox>
-            <SymptomBox
-              title={symptomTitles.temperature}
-              onPress={() => this.navigate('TemperatureEditView')}
-              data={this.getLabel('temperature')}
-              disabled={dateInFuture}
-              iconName='drip-icon-temperature'
-            >
-            </SymptomBox>
-            <SymptomBox
-              title={symptomTitles.mucus}
-              onPress={() => this.navigate('MucusEditView')}
-              data={this.getLabel('mucus')}
-              disabled={dateInFuture}
-              iconName='drip-icon-mucus'
-            >
-            </SymptomBox>
-            <SymptomBox
-              title={symptomTitles.cervix}
-              onPress={() => this.navigate('CervixEditView')}
-              data={this.getLabel('cervix')}
-              disabled={dateInFuture}
-              iconName='drip-icon-cervix'
-            >
-            </SymptomBox>
-            <SymptomBox
-              title={symptomTitles.desire}
-              onPress={() => this.navigate('DesireEditView')}
-              data={this.getLabel('desire')}
-              disabled={dateInFuture}
-              iconName='drip-icon-desire'
-            >
-            </SymptomBox>
-            <SymptomBox
-              title={symptomTitles.sex}
-              onPress={() => this.navigate('SexEditView')}
-              data={this.getLabel('sex')}
-              disabled={dateInFuture}
-              iconName='drip-icon-sex'
-            >
-            </SymptomBox>
-            <SymptomBox
-              title={symptomTitles.pain}
-              onPress={() => this.navigate('PainEditView')}
-              data={this.getLabel('pain')}
-              disabled={dateInFuture}
-              iconName='drip-icon-pain'
-            >
-            </SymptomBox>
-            <SymptomBox
-              title={symptomTitles.mood}
-              onPress={() => this.navigate('MoodEditView')}
-              data={this.getLabel('mood')}
-              disabled={dateInFuture}
-              iconName='drip-icon-mood'
-            >
-            </SymptomBox>
-            <SymptomBox
-              title={symptomTitles.note}
-              onPress={() => this.navigate('NoteEditView')}
-              data={this.getLabel('note')}
-              iconName='drip-icon-note'
-            >
-            </SymptomBox>
-            {/*  this is just to make the last row adhere to the grid
-        (and) because there are no pseudo properties in RN */}
+            {
+              symptomBoxesList.map(symptom => {
+                const symptomEditView =
+                  `${symptom[0].toUpperCase() + symptom.substring(1)}EditView`
+                const symptomData =
+                  cycleDay && cycleDay[symptom] ? cycleDay[symptom] : null
+                return(
+                  <SymptomBox
+                    key={symptom}
+                    symptom={symptom}
+                    symptomData={symptomData}
+                    onPress={() => this.navigate(symptomEditView)}
+                    disabled={dateInFuture}
+                  />)
+              })
+            }
+            {
+              // this is just to make the last row adhere to the grid
+              // (and) because there are no pseudo properties in RN
+            }
             <FillerBoxes />
           </View>
         </ScrollView>
@@ -263,60 +89,3 @@ export default class CycleDayOverView extends Component {
     )
   }
 }
-
-
-
-
-class SymptomBox extends Component {
-  render() {
-    const hasData = this.props.data
-    const boxActive = hasData ? styles.symptomBoxActive : {}
-    const textActive = hasData ? styles.symptomTextActive : {}
-    const disabledStyle = this.props.disabled ? styles.symptomInFuture : {}
-
-    return (
-      <TouchableOpacity
-        onPress={this.props.onPress}
-        disabled={this.props.disabled}
-        testID={this.props.iconName}
-      >
-        <View style={[styles.symptomBox, boxActive, disabledStyle]}>
-          <DripIcon name={this.props.iconName} size={50} color={hasData ? 'white' : 'black'}/>
-          <AppText
-            style={[textActive, disabledStyle, {fontSize: 15}]}
-            numberOfLines={1}
-          >
-            {this.props.title.toLowerCase()}
-          </AppText>
-        </View>
-        <View style={[styles.symptomDataBox, disabledStyle]}>
-          <AppText
-            style={styles.symptomDataText}
-            numberOfLines={3}
-          >{this.props.data}</AppText>
-        </View>
-      </TouchableOpacity>
-    )
-  }
-}
-
-class FillerBoxes extends Component {
-  render() {
-    const n = Dimensions.get('window').width / styles.symptomBox.width
-    const fillerBoxes = []
-    for (let i = 0; i < Math.ceil(n); i++) {
-      fillerBoxes.push(
-        <View
-          width={styles.symptomBox.width}
-          height={0}
-          key={i.toString()}
-        />
-      )
-    }
-    return fillerBoxes
-  }
-}
-
-function isNumber(val) {
-  return typeof val === 'number'
-}
-- 
GitLab