Skip to content
Snippets Groups Projects
home.js 6.79 KiB
Newer Older
import { ChronoUnit, LocalDate } from 'js-joda'
Julia Friesel's avatar
Julia Friesel committed
import React, { Component } from 'react'
import { ScrollView, View } from 'react-native'
import { connect } from 'react-redux'

import { setDate } from '../slices/date'

import DripHomeIcon from '../assets/drip-home-icons'
import {
  bleedingPrediction as predictLabels,
} from '../i18n/en/labels'
import links from '../i18n/en/links'
import cycleModule from '../lib/cycle'
Julia Friesel's avatar
Julia Friesel committed
import { getFertilityStatusForDay } from '../lib/sympto-adapter'
import styles, { cycleDayColor, periodColor, secondaryColor } from '../styles'
Julia Friesel's avatar
Julia Friesel committed
import AppText from './app-text'
Julia Friesel's avatar
Julia Friesel committed
import Button from './button'
import { formatDateForShortText } from './helpers/format-date'
import { getCycleDay } from '../db'
const IconText = ({ children, wrapperStyles }) => {
  return (
    <View style={[styles.homeIconTextWrapper, wrapperStyles]}>
      <AppText style={styles.iconText}>
        { children }
    </View>
  )
}

const HomeElement = ({ children, onPress, buttonColor, buttonLabel  }) => {
  return (
      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>
class Home extends Component {
Julia Friesel's avatar
Julia Friesel committed
  constructor(props) {
    super(props)
    const { getCycleDayNumber, getPredictedMenses } = cycleModule()
    this.getCycleDayNumber = getCycleDayNumber
    this.getBleedingPrediction = getPredictedMenses
    this.todayDateString = LocalDate.now().toString()
Julia Friesel's avatar
Julia Friesel committed
    const prediction = this.getBleedingPrediction()
    const fertilityStatus = getFertilityStatusForDay(this.todayDateString)
Julia Friesel's avatar
Julia Friesel committed
      cycleDayNumber: this.getCycleDayNumber(this.todayDateString),
      predictionText: determinePredictionText(prediction),
      bleedingPredictionRange: getBleedingPredictionRange(prediction),
      ...fertilityStatus
Julia Friesel's avatar
Julia Friesel committed
  }

  setTodayDate = () => {
    this.props.setDate(this.todayDateString)
  }

  navigateToCycleDayView = () => {
    this.setTodayDate()
    this.props.navigate('CycleDay')
  }

  navigateToBleedingEditView = () => {
    this.setTodayDate()
    this.props.navigate(
      'BleedingEditView',
      getCycleDay(this.todayDateString)
    )
Julia Friesel's avatar
Julia Friesel committed
  render() {
    const { cycleDayNumber, phase, status } = this.state
    const { navigate } = this.props
    const cycleDayMoreText = cycleDayNumber ?
      labels.cycleDayKnown(cycleDayNumber) :
Julia Friesel's avatar
Julia Friesel committed
      labels.cycleDayNotEnoughInfo

    const { statusText } = this.state
Sofiya Tepikin's avatar
Sofiya Tepikin committed

Julia Friesel's avatar
Julia Friesel committed
    return (
Julia Friesel's avatar
Julia Friesel committed
      <View flex={1}>
        <ScrollView>
          <View style={styles.homeView}>

            <HomeElement
              onPress={this.navigateToCycleDayView}
              buttonColor={ cycleDayColor }
              buttonLabel={ labels.editToday }
Julia Friesel's avatar
Julia Friesel committed
            >
                <DripHomeIcon name="circle" size={80} color={cycleDayColor}/>
Julia Friesel's avatar
Julia Friesel committed
              </View>
              <IconText wrapperStyles={styles.wrapperIcon}>
                {cycleDayNumber || labels.unknown}
              </IconText>
              <AppText style={styles.homeDescriptionText}>
                {cycleDayMoreText}
              </AppText>
            </HomeElement>
            <HomeElement
              onPress={this.navigateToBleedingEditView}
              buttonColor={ periodColor }
              buttonLabel={ labels.trackPeriod }
Julia Friesel's avatar
Julia Friesel committed
            >
              <DripHomeIcon name="drop" size={100} color={periodColor} />
              <IconText wrapperStyles={{top: '45%', ...styles.wrapperIcon}}>
                {this.state.bleedingPredictionRange}
              </IconText>

              <AppText style={styles.homeDescriptionText}>
                {this.state.predictionText}
              </AppText>
            </HomeElement>
            <HomeElement
              onPress={ () => navigate('Chart') }
              buttonColor={ secondaryColor }
              buttonLabel={ labels.checkFertility }
Julia Friesel's avatar
Julia Friesel committed
            >
              <View style={styles.homeCircle}/>
              <IconText wrapperStyles={styles.wrapperIcon}>
                { phase ? phase.toString() : labels.unknown }
              </IconText>

              { phase &&
                <AppText style={styles.homeDescriptionText}>
                  {`${labels.phase(phase)} (${status})`}
                </AppText>
Julia Friesel's avatar
Julia Friesel committed
              }
              <AppText style={styles.homeDescriptionText}>
                { `${statusText} Visit ${links.wiki.url}.` }
              </AppText>
            </HomeElement>
Julia Friesel's avatar
Julia Friesel committed
        </ScrollView>
      </View>
Julia Friesel's avatar
Julia Friesel committed
    )
  }
const mapDispatchToProps = (dispatch) => {
  return({
    setDate: (date) => dispatch(setDate(date)),
  })
}

export default connect(
  null,
  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 }
}

Julia Friesel's avatar
Julia Friesel committed
function determinePredictionText(bleedingPrediction) {
  if (!bleedingPrediction.length) return predictLabels.noPrediction
  const {
    todayDate,
    predictedBleedingStart,
    predictedBleedingEnd,
    daysToEnd
  } = getTimes(bleedingPrediction)
emelko's avatar
emelko committed
  if (todayDate.isBefore(predictedBleedingStart)) {
Julia Friesel's avatar
Julia Friesel committed
    return predictLabels.predictionInFuture(
emelko's avatar
emelko committed
      todayDate.until(predictedBleedingStart, ChronoUnit.DAYS),
      todayDate.until(predictedBleedingEnd, ChronoUnit.DAYS)
emelko's avatar
emelko committed
  if (todayDate.isAfter(predictedBleedingEnd)) {
Julia Friesel's avatar
Julia Friesel committed
    return predictLabels.predictionInPast(
      formatDateForShortText(predictedBleedingStart),
      formatDateForShortText(predictedBleedingEnd)
Julia Friesel's avatar
Julia Friesel committed
    )
  }
  if (daysToEnd === 0) {
Julia Friesel's avatar
Julia Friesel committed
    return predictLabels.predictionStartedNoDaysLeft
  } else if (daysToEnd === 1) {
Julia Friesel's avatar
Julia Friesel committed
    return predictLabels.predictionStarted1DayLeft
Julia Friesel's avatar
Julia Friesel committed
    return predictLabels.predictionStartedXDaysLeft(daysToEnd)
emelko's avatar
emelko committed
}
Julia Friesel's avatar
Julia Friesel committed

function getBleedingPredictionRange(prediction) {
  if (!prediction.length) return labels.unknown
  const {
    todayDate,
    predictedBleedingStart,
    predictedBleedingEnd,
    daysToEnd
  } = getTimes(prediction)
emelko's avatar
emelko committed
  if (todayDate.isBefore(predictedBleedingStart)) {
    return `${todayDate.until(predictedBleedingStart, ChronoUnit.DAYS)}-${todayDate.until(predictedBleedingEnd, ChronoUnit.DAYS)}`
Julia Friesel's avatar
Julia Friesel committed
  }
emelko's avatar
emelko committed
  if (todayDate.isAfter(predictedBleedingEnd)) {
Julia Friesel's avatar
Julia Friesel committed
    return labels.unknown
  }
  return (daysToEnd === 0 ? '0' : `0 - ${daysToEnd}`)
Julia Friesel's avatar
Julia Friesel committed
}