Skip to content
Snippets Groups Projects
day-column.js 8.13 KiB
Newer Older
import React, { Component } from 'react'
  Text, View, TouchableOpacity
import {
  Surface,
  Group as G,
  Path,
  Shape
} from 'react-native/Libraries/ART/ReactNativeART'
import { connect } from 'react-redux'

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

tina's avatar
tina committed
import { LocalDate } from 'js-joda'
import moment from 'moment'
import styles from './styles'
Julia Friesel's avatar
Julia Friesel committed
import config from '../../config'
import cycleModule from '../../lib/cycle'
import { getCycleDay } from '../../db'
import DotAndLine from './dot-and-line'
import SymptomCell from './symptom-cell'

import { normalizeToScale } from '../helpers/chart'
const label = styles.column.label
class DayColumn extends Component {
    const { dateString, chartSymptoms, columnHeight } = props
    const cycleDayData = getCycleDay(dateString)
      this.data = chartSymptoms.reduce((symptomDataToDisplay, symptom, ) => {
        const symptomData = cycleDayData[symptom]

        if (symptomData && symptom === 'temperature') {
          symptomDataToDisplay[symptom] =
           this.getTemperatureProps(symptomData, columnHeight, dateString)
        } else {
          if (symptomData && ! symptomData.exclude) {
            // if symptomColorMethods entry doesn't exist for given symptom,
            // use 'default'
            const getSymptomColorIndex =
              this.symptomColorMethods[symptom] ||
              this.symptomColorMethods['default']

            symptomDataToDisplay[symptom] = getSymptomColorIndex(symptomData)

        return symptomDataToDisplay
      }, this.data)
    }

    this.fhmAndLtl = props.getFhmAndLtlInfo(
      props.dateString,
      this.data.temperature ? this.data.temperature.value : null,
  getTemperatureProps = (symptomData, columnHeight, dateString) => {
    const extractedData = {}
    const { value, exclude } = symptomData
    const neighborTemperatureGraphPoints =
      getInfoForNeighborColumns(dateString, columnHeight)

    for (const key in neighborTemperatureGraphPoints) {
      extractedData[key] = neighborTemperatureGraphPoints[key]
    }
    return Object.assign({
      value,
      y: normalizeToScale(value, columnHeight),
      temperatureExclude: exclude,
    }, extractedData)
  symptomColorMethods = {
    'mucus': (symptomData) => {
      const { feeling, texture } = symptomData
      const colorIndex = feeling + texture
      return colorIndex
    },
    'cervix': (symptomData) => {
      const { opening, firmness } = symptomData
      const isDataComplete = opening !== null && firmness !== null
      const isClosedAndHard =
        isDataComplete &&
        (opening === 0 && firmness === 0)
      const colorIndex = isClosedAndHard ? 0 : 2
      return colorIndex
    },
    'sex': (symptomData) => {
      const { solo, partner } = symptomData
      const colorIndex = (solo !== null && partner !== null) ?
        (solo + 2 * partner - 1) : 0
      return colorIndex
    },
    'bleeding': (symptomData) => {
      const { value } = symptomData
      const colorIndex = value
      return colorIndex
    },
    'default': () => { // desire, pain, mood, note
      const colorIndex = 0
      return colorIndex
    }
  }
  isSymptomDataComplete = (symptom) => {
    const { dateString } = this.props
    const cycleDayData = getCycleDay(dateString)
    const symptomData = cycleDayData[symptom]

    const dataCompletenessCheck = {
      'cervix': () => {
        const { opening, firmness } = symptomData
        return (opening !== null) && (firmness !== null)
      },
      'mucus': () => {
        const { feeling, texture } = symptomData
        return (feeling !== null) && (texture !== null)
      },
      'default': () => {
        return true
      }
    }
    return (dataCompletenessCheck[symptom] || dataCompletenessCheck['default'])()
  }
  onDaySelect = (date) => {
    this.props.setDate(date)
    this.props.navigate('CycleDay')
  }

  shouldComponentUpdate() {
    return false
    const columnElements = []
    const { dateString,
      symptomRowSymptoms,
      chartHeight,
      columnHeight,
      xAxisHeight } = this.props

      const ltlLine = (<Shape
Julia Friesel's avatar
Julia Friesel committed
        stroke={styles.nfpLine.stroke}
        strokeWidth={styles.nfpLine.strokeWidth}
        d={new Path()
          .moveTo(0, this.fhmAndLtl.drawLtlAt)
          .lineTo(config.columnWidth, this.fhmAndLtl.drawLtlAt)
        }
Julia Friesel's avatar
Julia Friesel committed
      />)
      columnElements.push(ltlLine)
    }
    if (this.fhmAndLtl.drawFhmLine) {
Julia Friesel's avatar
Julia Friesel committed
      const x = styles.nfpLine.strokeWidth / 2
      const fhmLine = (<Shape
        fill="red"
Julia Friesel's avatar
Julia Friesel committed
        stroke={styles.nfpLine.stroke}
        strokeWidth={styles.nfpLine.strokeWidth}
        d={new Path().moveTo(x, x).lineTo(x, columnHeight)}
Julia Friesel's avatar
Julia Friesel committed
      />)
      columnElements.push(fhmLine)
    }

    if (this.data && this.data.temperature && this.data.temperature.y) {
      const { temperatureExclude,
        y,
        rightY,
        leftY,
        rightTemperatureExclude,
        leftTemperatureExclude
      } = this.data.temperature

      columnElements.push(
        <DotAndLine
          y={y}
          exclude={temperatureExclude}
          rightY={rightY}
          rightTemperatureExclude={rightTemperatureExclude}
          leftY={leftY}
          leftTemperatureExclude={leftTemperatureExclude}
    const cycleDayNumber = cycleModule().getCycleDayNumber(dateString)
tina's avatar
tina committed
    const dayDate = LocalDate.parse(dateString)
    const shortDate = dayDate.dayOfMonth() === 1 ?
      moment(dateString, "YYYY-MM-DD").format('MMM')
      :
      moment(dateString, "YYYY-MM-DD").format('Do')
    const boldDateLabel = dayDate.dayOfMonth() === 1 ? {fontWeight: 'bold'} : {}
    const cycleDayLabel = (
      <Text style = {label.number}>
        {cycleDayNumber ? cycleDayNumber : ' '}
      </Text>)
    const dateLabel = (
tina's avatar
tina committed
      <Text style = {[label.date, boldDateLabel]}>
        {shortDate}
      </Text>
    )
    const column = (
        <Shape
          stroke={styles.column.stroke.color}
          strokeWidth={styles.column.stroke.width}
          d={new Path().lineTo(0, chartHeight)}
        />
        { columnElements }
      </G>
      <TouchableOpacity
        onPress={() => this.onDaySelect(dateString)}
        activeOpacity={1}
      >

        { symptomRowSymptoms.map(symptom => {
          const hasSymptomData = this.data.hasOwnProperty(symptom)
          return (
            <SymptomCell
              key={symptom}
              symptom={symptom}
              symptomValue={hasSymptomData && this.data[symptom]}
              isSymptomDataComplete={
                hasSymptomData && this.isSymptomDataComplete(symptom)
              }
              height={this.props.symptomHeight}
            />)
        }
        )}
        <Surface width={config.columnWidth} height={columnHeight}>
        </Surface>
        <View style={{height: xAxisHeight}}>
          {cycleDayLabel}
          {dateLabel}
        </View>
      </TouchableOpacity>
emelko's avatar
emelko committed
}
const mapDispatchToProps = (dispatch) => {
  return({
    setDate: (date) => dispatch(setDate(date)),
  })
}

export default connect(
  null,
  mapDispatchToProps,
)(DayColumn)


function getInfoForNeighborColumns(dateString, columnHeight) {
  const ret = {
    rightY: null,
    rightTemperatureExclude: null,
    leftY: null,
    leftTemperatureExclude: null
  }
  const target = LocalDate.parse(dateString)
  const dayBefore = target.minusDays(1).toString()
  const dayAfter = target.plusDays(1).toString()
  const cycleDayBefore = getCycleDay(dayBefore)
  const cycleDayAfter = getCycleDay(dayAfter)
  if (cycleDayAfter && cycleDayAfter.temperature) {
    ret.rightY = normalizeToScale(cycleDayAfter.temperature.value, columnHeight)
    ret.rightTemperatureExclude = cycleDayAfter.temperature.exclude
  }
  if (cycleDayBefore && cycleDayBefore.temperature) {
    ret.leftY = normalizeToScale(cycleDayBefore.temperature.value, columnHeight)
    ret.leftTemperatureExclude = cycleDayBefore.temperature.exclude
  }

  return ret
}