Merge branch 'home-split' into 'master'

Home split

See merge request bloodyhealth/drip!266
This commit is contained in:
Sofiya Tepikin
2020-03-02 20:51:04 +00:00
5 changed files with 186 additions and 130 deletions
+64
View File
@@ -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}`)
}
+40
View File
@@ -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 (
<View
onPress={ onPress }
style={ styles.homeElement }
>
<View style={styles.homeIconAndText}>
{children[0]}
{children[1]}
</View>
<View style={{paddingLeft: 15}}>
{children.slice(2)}
<Button
style={styles.homeButton}
onPress={ onPress }
backgroundColor={ buttonColor }>
{ buttonLabel }
</Button>
</View>
</View>
)
}
HomeElement.propTypes = {
buttonColor: PropTypes.string,
buttonLabel: PropTypes.string,
children: PropTypes.node,
onPress: PropTypes.func,
}
export default HomeElement
+56 -126
View File
@@ -1,74 +1,55 @@
import { ChronoUnit, LocalDate } from 'js-joda' import { LocalDate } from 'js-joda'
import React, { Component } from 'react' import React, { Component } from 'react'
import { ScrollView, View } from 'react-native' import { ScrollView, View } from 'react-native'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import { navigate } from '../slices/navigation' import { navigate } from '../slices/navigation'
import { setDate } from '../slices/date' import { getDate, setDate } from '../slices/date'
import DripHomeIcon from '../assets/drip-home-icons' import DripHomeIcon from '../assets/drip-home-icons'
import {
bleedingPrediction as predictLabels, import AppText from './app-text'
home as labels import IconText from './icon-text'
} from '../i18n/en/labels' import HomeElement from './home-element'
import { home as labels } from '../i18n/en/labels'
import links from '../i18n/en/links' import links from '../i18n/en/links'
import cycleModule from '../lib/cycle' import cycleModule from '../lib/cycle'
import { getFertilityStatusForDay } from '../lib/sympto-adapter' import { getFertilityStatusForDay } from '../lib/sympto-adapter'
import {
determinePredictionText,
getBleedingPredictionRange
} from './helpers/home'
import styles, { cycleDayColor, periodColor, secondaryColor } from '../styles' 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 (
<View style={[styles.homeIconTextWrapper, wrapperStyles]}>
<AppText style={styles.iconText}>
{ children }
</AppText>
</View>
)
}
const HomeElement = ({ children, onPress, buttonColor, buttonLabel }) => {
return (
<View
onPress={ onPress }
style={ styles.homeElement }
>
<View style={styles.homeIconAndText}>
{children[0]}
{children[1]}
</View>
<View style={{paddingLeft: 15}}>
{children.slice(2)}
<Button
style={styles.homeButton}
onPress={ onPress }
backgroundColor={ buttonColor }>
{ buttonLabel }
</Button>
</View>
</View>
)
}
class Home extends Component { 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 <App />
cycleDay: PropTypes.object,
date: PropTypes.string,
handleBackButtonPress: PropTypes.func,
}
constructor(props) { constructor(props) {
super(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 = { const { getCycleDayNumber, getPredictedMenses } = cycleModule()
cycleDayNumber: this.getCycleDayNumber(this.todayDateString),
predictionText: determinePredictionText(prediction), this.todayDateString = LocalDate.now().toString()
bleedingPredictionRange: getBleedingPredictionRange(prediction), this.cycleDayNumber = getCycleDayNumber(this.todayDateString)
...fertilityStatus
} const prediction = getPredictedMenses()
this.predictionText = determinePredictionText(prediction)
this.bleedingPredictionRange = getBleedingPredictionRange(prediction)
this.fertilityStatus = getFertilityStatusForDay(this.todayDateString)
} }
navigateToCycleDayView = () => { navigateToCycleDayView = () => {
@@ -86,18 +67,22 @@ class Home extends Component {
} }
render() { render() {
const { cycleDayNumber, phase, status } = this.state const {
cycleDayNumber,
predictionText,
bleedingPredictionRange,
} = this
const { phase, status, statusText } = this.fertilityStatus
const cycleDayMoreText = cycleDayNumber ? const cycleDayMoreText = cycleDayNumber ?
labels.cycleDayKnown(cycleDayNumber) : labels.cycleDayKnown(cycleDayNumber) :
labels.cycleDayNotEnoughInfo labels.cycleDayNotEnoughInfo
const { statusText } = this.state
return ( return (
<View flex={1}> <View flex={1}>
<ScrollView> <ScrollView>
<View style={styles.homeView}> <View style={styles.homeView}>
<HomeElement <HomeElement
onPress={this.navigateToCycleDayView} onPress={this.navigateToCycleDayView}
buttonColor={ cycleDayColor } buttonColor={ cycleDayColor }
@@ -106,9 +91,7 @@ class Home extends Component {
<View> <View>
<DripHomeIcon name="circle" size={80} color={cycleDayColor}/> <DripHomeIcon name="circle" size={80} color={cycleDayColor}/>
</View> </View>
<IconText wrapperStyles={styles.wrapperIcon}> <IconText>{cycleDayNumber || labels.unknown}</IconText>
{cycleDayNumber || labels.unknown}
</IconText>
<AppText style={styles.homeDescriptionText}> <AppText style={styles.homeDescriptionText}>
{cycleDayMoreText} {cycleDayMoreText}
@@ -122,12 +105,12 @@ class Home extends Component {
> >
<DripHomeIcon name="drop" size={100} color={periodColor} /> <DripHomeIcon name="drop" size={100} color={periodColor} />
<IconText wrapperStyles={{top: '45%', ...styles.wrapperIcon}}> <IconText wrapperStyles={{ top: '45%' }}>
{this.state.bleedingPredictionRange} {bleedingPredictionRange}
</IconText> </IconText>
<AppText style={styles.homeDescriptionText}> <AppText style={styles.homeDescriptionText}>
{this.state.predictionText} {predictionText}
</AppText> </AppText>
</HomeElement> </HomeElement>
@@ -138,9 +121,7 @@ class Home extends Component {
> >
<View style={styles.homeCircle}/> <View style={styles.homeCircle}/>
<IconText wrapperStyles={styles.wrapperIcon}> <IconText>{ phase ? phase.toString() : labels.unknown }</IconText>
{ phase ? phase.toString() : labels.unknown }
</IconText>
{ phase && { phase &&
<AppText style={styles.homeDescriptionText}> <AppText style={styles.homeDescriptionText}>
@@ -158,6 +139,12 @@ class Home extends Component {
} }
} }
const mapStateToProps = (state) => {
return({
date: getDate(state),
})
}
const mapDispatchToProps = (dispatch) => { const mapDispatchToProps = (dispatch) => {
return({ return({
navigate: (page) => dispatch(navigate(page)), navigate: (page) => dispatch(navigate(page)),
@@ -166,63 +153,6 @@ const mapDispatchToProps = (dispatch) => {
} }
export default connect( export default connect(
null, mapStateToProps,
mapDispatchToProps, mapDispatchToProps,
)(Home) )(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}`)
}
+24
View File
@@ -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 (
<View style={[ styles.homeIconTextWrapper, wrapperStyles ]}>
<AppText style={styles.iconText}>
{ children }
</AppText>
</View>
)
}
IconText.propTypes = {
children: PropTypes.node,
wrapperStyles: PropTypes.object,
}
export default IconText
+2 -4
View File
@@ -131,14 +131,12 @@ export default StyleSheet.create({
homeIconTextWrapper: { homeIconTextWrapper: {
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
width: 80,
position: 'absolute',
}, },
homeIconAndText: { homeIconAndText: {
justifyContent: 'center' justifyContent: 'center'
}, },
wrapperIcon: {
width: 80,
position: 'absolute'
},
homeCircle: { homeCircle: {
borderRadius: 100, borderRadius: 100,
borderWidth: 2.3, borderWidth: 2.3,