diff --git a/components/helpers/home.js b/components/helpers/home.js
new file mode 100644
index 0000000..98e9f20
--- /dev/null
+++ b/components/helpers/home.js
@@ -0,0 +1,64 @@
+import { ChronoUnit, LocalDate } from 'js-joda'
+
+import { formatDateForShortText } from './format-date'
+
+import {
+ home as labels,
+ bleedingPrediction as predictLabels,
+} from '../../i18n/en/labels'
+
+function getTimes(prediction) {
+ const todayDate = LocalDate.now()
+ const predictedBleedingStart = LocalDate.parse(prediction[0][0])
+ /* the range of predicted bleeding days can be either 3 or 5 */
+ const predictedBleedingEnd =
+ LocalDate.parse(prediction[0][ prediction[0].length - 1 ])
+ const daysToEnd = todayDate.until(predictedBleedingEnd, ChronoUnit.DAYS)
+ return { todayDate, predictedBleedingStart, predictedBleedingEnd, daysToEnd }
+}
+
+export function determinePredictionText(bleedingPrediction) {
+ if (!bleedingPrediction.length) return predictLabels.noPrediction
+ const {
+ todayDate,
+ predictedBleedingStart,
+ predictedBleedingEnd,
+ daysToEnd
+ } = getTimes(bleedingPrediction)
+ if (todayDate.isBefore(predictedBleedingStart)) {
+ return predictLabels.predictionInFuture(
+ todayDate.until(predictedBleedingStart, ChronoUnit.DAYS),
+ todayDate.until(predictedBleedingEnd, ChronoUnit.DAYS)
+ )
+ }
+ if (todayDate.isAfter(predictedBleedingEnd)) {
+ return predictLabels.predictionInPast(
+ formatDateForShortText(predictedBleedingStart),
+ formatDateForShortText(predictedBleedingEnd)
+ )
+ }
+ if (daysToEnd === 0) {
+ return predictLabels.predictionStartedNoDaysLeft
+ } else if (daysToEnd === 1) {
+ return predictLabels.predictionStarted1DayLeft
+ } else {
+ return predictLabels.predictionStartedXDaysLeft(daysToEnd)
+ }
+}
+
+export function getBleedingPredictionRange(prediction) {
+ if (!prediction.length) return labels.unknown
+ const {
+ todayDate,
+ predictedBleedingStart,
+ predictedBleedingEnd,
+ daysToEnd
+ } = getTimes(prediction)
+ if (todayDate.isBefore(predictedBleedingStart)) {
+ return `${todayDate.until(predictedBleedingStart, ChronoUnit.DAYS)}-${todayDate.until(predictedBleedingEnd, ChronoUnit.DAYS)}`
+ }
+ if (todayDate.isAfter(predictedBleedingEnd)) {
+ return labels.unknown
+ }
+ return (daysToEnd === 0 ? '0' : `0 - ${daysToEnd}`)
+}
diff --git a/components/home-element.js b/components/home-element.js
new file mode 100644
index 0000000..5c2423b
--- /dev/null
+++ b/components/home-element.js
@@ -0,0 +1,40 @@
+import React from 'react'
+import { View } from 'react-native'
+import PropTypes from 'prop-types'
+
+import Button from './button'
+
+import styles from '../styles'
+
+const HomeElement = ({ children, onPress, buttonColor, buttonLabel }) => {
+ return (
+
+
+ {children[0]}
+ {children[1]}
+
+
+
+ {children.slice(2)}
+
+
+
+ )
+}
+
+HomeElement.propTypes = {
+ buttonColor: PropTypes.string,
+ buttonLabel: PropTypes.string,
+ children: PropTypes.node,
+ onPress: PropTypes.func,
+}
+
+export default HomeElement
diff --git a/components/home.js b/components/home.js
index 69604b0..0b300cb 100644
--- a/components/home.js
+++ b/components/home.js
@@ -1,74 +1,55 @@
-import { ChronoUnit, LocalDate } from 'js-joda'
+import { LocalDate } from 'js-joda'
import React, { Component } from 'react'
import { ScrollView, View } from 'react-native'
import { connect } from 'react-redux'
+import PropTypes from 'prop-types'
import { navigate } from '../slices/navigation'
-import { setDate } from '../slices/date'
+import { getDate, setDate } from '../slices/date'
import DripHomeIcon from '../assets/drip-home-icons'
-import {
- bleedingPrediction as predictLabels,
- home as labels
-} from '../i18n/en/labels'
+
+import AppText from './app-text'
+import IconText from './icon-text'
+import HomeElement from './home-element'
+
+import { home as labels } from '../i18n/en/labels'
import links from '../i18n/en/links'
+
import cycleModule from '../lib/cycle'
import { getFertilityStatusForDay } from '../lib/sympto-adapter'
+import {
+ determinePredictionText,
+ getBleedingPredictionRange
+} from './helpers/home'
+
import styles, { cycleDayColor, periodColor, secondaryColor } from '../styles'
-import AppText from './app-text'
-import Button from './button'
-import { formatDateForShortText } from './helpers/format-date'
-
-const IconText = ({ children, wrapperStyles }) => {
- return (
-
-
- { children }
-
-
- )
-}
-
-const HomeElement = ({ children, onPress, buttonColor, buttonLabel }) => {
- return (
-
-
- {children[0]}
- {children[1]}
-
-
-
- {children.slice(2)}
-
-
-
- )
-}
class Home extends Component {
+
+ static propTypes = {
+ navigate: PropTypes.func,
+ setDate: PropTypes.func,
+ // The following three is not being used,
+ // we could see if it's possible to not pass them from the
+ cycleDay: PropTypes.object,
+ date: PropTypes.string,
+ handleBackButtonPress: PropTypes.func,
+ }
+
constructor(props) {
super(props)
- const { getCycleDayNumber, getPredictedMenses } = cycleModule()
- this.getCycleDayNumber = getCycleDayNumber
- this.getBleedingPrediction = getPredictedMenses
- this.todayDateString = LocalDate.now().toString()
- const prediction = this.getBleedingPrediction()
- const fertilityStatus = getFertilityStatusForDay(this.todayDateString)
- this.state = {
- cycleDayNumber: this.getCycleDayNumber(this.todayDateString),
- predictionText: determinePredictionText(prediction),
- bleedingPredictionRange: getBleedingPredictionRange(prediction),
- ...fertilityStatus
- }
+ const { getCycleDayNumber, getPredictedMenses } = cycleModule()
+
+ this.todayDateString = LocalDate.now().toString()
+ this.cycleDayNumber = getCycleDayNumber(this.todayDateString)
+
+ const prediction = getPredictedMenses()
+ this.predictionText = determinePredictionText(prediction)
+ this.bleedingPredictionRange = getBleedingPredictionRange(prediction)
+
+ this.fertilityStatus = getFertilityStatusForDay(this.todayDateString)
}
navigateToCycleDayView = () => {
@@ -86,18 +67,22 @@ class Home extends Component {
}
render() {
- const { cycleDayNumber, phase, status } = this.state
+ const {
+ cycleDayNumber,
+ predictionText,
+ bleedingPredictionRange,
+ } = this
+
+ const { phase, status, statusText } = this.fertilityStatus
+
const cycleDayMoreText = cycleDayNumber ?
labels.cycleDayKnown(cycleDayNumber) :
labels.cycleDayNotEnoughInfo
- const { statusText } = this.state
-
return (
-
-
- {cycleDayNumber || labels.unknown}
-
+ {cycleDayNumber || labels.unknown}
{cycleDayMoreText}
@@ -122,12 +105,12 @@ class Home extends Component {
>
-
- {this.state.bleedingPredictionRange}
+
+ {bleedingPredictionRange}
- {this.state.predictionText}
+ {predictionText}
@@ -138,9 +121,7 @@ class Home extends Component {
>
-
- { phase ? phase.toString() : labels.unknown }
-
+ { phase ? phase.toString() : labels.unknown }
{ phase &&
@@ -158,6 +139,12 @@ class Home extends Component {
}
}
+const mapStateToProps = (state) => {
+ return({
+ date: getDate(state),
+ })
+}
+
const mapDispatchToProps = (dispatch) => {
return({
navigate: (page) => dispatch(navigate(page)),
@@ -166,63 +153,6 @@ const mapDispatchToProps = (dispatch) => {
}
export default connect(
- null,
+ mapStateToProps,
mapDispatchToProps,
)(Home)
-
-
-function getTimes(prediction) {
- const todayDate = LocalDate.now()
- const predictedBleedingStart = LocalDate.parse(prediction[0][0])
- /* the range of predicted bleeding days can be either 3 or 5 */
- const predictedBleedingEnd =
- LocalDate.parse(prediction[0][ prediction[0].length - 1 ])
- const daysToEnd = todayDate.until(predictedBleedingEnd, ChronoUnit.DAYS)
- return { todayDate, predictedBleedingStart, predictedBleedingEnd, daysToEnd }
-}
-
-function determinePredictionText(bleedingPrediction) {
- if (!bleedingPrediction.length) return predictLabels.noPrediction
- const {
- todayDate,
- predictedBleedingStart,
- predictedBleedingEnd,
- daysToEnd
- } = getTimes(bleedingPrediction)
- if (todayDate.isBefore(predictedBleedingStart)) {
- return predictLabels.predictionInFuture(
- todayDate.until(predictedBleedingStart, ChronoUnit.DAYS),
- todayDate.until(predictedBleedingEnd, ChronoUnit.DAYS)
- )
- }
- if (todayDate.isAfter(predictedBleedingEnd)) {
- return predictLabels.predictionInPast(
- formatDateForShortText(predictedBleedingStart),
- formatDateForShortText(predictedBleedingEnd)
- )
- }
- if (daysToEnd === 0) {
- return predictLabels.predictionStartedNoDaysLeft
- } else if (daysToEnd === 1) {
- return predictLabels.predictionStarted1DayLeft
- } else {
- return predictLabels.predictionStartedXDaysLeft(daysToEnd)
- }
-}
-
-function getBleedingPredictionRange(prediction) {
- if (!prediction.length) return labels.unknown
- const {
- todayDate,
- predictedBleedingStart,
- predictedBleedingEnd,
- daysToEnd
- } = getTimes(prediction)
- if (todayDate.isBefore(predictedBleedingStart)) {
- return `${todayDate.until(predictedBleedingStart, ChronoUnit.DAYS)}-${todayDate.until(predictedBleedingEnd, ChronoUnit.DAYS)}`
- }
- if (todayDate.isAfter(predictedBleedingEnd)) {
- return labels.unknown
- }
- return (daysToEnd === 0 ? '0' : `0 - ${daysToEnd}`)
-}
diff --git a/components/icon-text.js b/components/icon-text.js
new file mode 100644
index 0000000..be30d48
--- /dev/null
+++ b/components/icon-text.js
@@ -0,0 +1,24 @@
+import React from 'react'
+import { View } from 'react-native'
+import PropTypes from 'prop-types'
+
+import AppText from './app-text'
+
+import styles from '../styles'
+
+const IconText = ({ children, wrapperStyles }) => {
+ return (
+
+
+ { children }
+
+
+ )
+}
+
+IconText.propTypes = {
+ children: PropTypes.node,
+ wrapperStyles: PropTypes.object,
+}
+
+export default IconText
diff --git a/styles/index.js b/styles/index.js
index 7825d11..1b9bb4f 100644
--- a/styles/index.js
+++ b/styles/index.js
@@ -131,14 +131,12 @@ export default StyleSheet.create({
homeIconTextWrapper: {
alignItems: 'center',
justifyContent: 'center',
+ width: 80,
+ position: 'absolute',
},
homeIconAndText: {
justifyContent: 'center'
},
- wrapperIcon: {
- width: 80,
- position: 'absolute'
- },
homeCircle: {
borderRadius: 100,
borderWidth: 2.3,