diff --git a/.eslintrc b/.eslintrc index 24f9ab5..6ec6205 100644 --- a/.eslintrc +++ b/.eslintrc @@ -47,6 +47,7 @@ "no-var": "error", "prefer-const": "error", "no-trailing-spaces": "error", - "react/prop-types": 0 + "react/prop-types": 0, + "max-len": [1, {"ignoreStrings": true}] } } \ No newline at end of file diff --git a/components/chart/chart.js b/components/chart/chart.js index 32983c1..30ed5d7 100644 --- a/components/chart/chart.js +++ b/components/chart/chart.js @@ -11,11 +11,12 @@ import Svg,{ } from 'react-native-svg' import { LocalDate } from 'js-joda' import { getCycleDay, getOrCreateCycleDay, cycleDaysSortedByDate } from '../../db' -import getCycleDayNumberModule from '../../lib/get-cycle-day-number' +import cycleModule from '../../lib/cycle' import styles from './styles' import config from './config' +import { getCycleStatusForDay } from '../../lib/sympto-adapter' -const getCycleDayNumber = getCycleDayNumberModule() +const getCycleDayNumber = cycleModule().getCycleDayNumber const yAxis = makeYAxis(config) @@ -63,13 +64,29 @@ export default class CycleChart extends Component { const cycleDayNumber = getCycleDayNumber(dateString) const label = styles.column.label const dateLabel = dateString.split('-').slice(1).join('-') + const getFhmAndLtlInfo = setUpFertilityStatusFunc() + const nfpLineInfo = getFhmAndLtlInfo(dateString, cycleDay) return ( this.passDateToDayView(dateString)}> + {nfpLineInfo.drawFhmLine ? + : null} + {this.placeHorizontalGrid()} - {cycleDayNumber} - {dateLabel} + + + {cycleDayNumber} + + + {dateLabel} + {cycleDay && cycleDay.bleeding ? : null} + {nfpLineInfo.drawLtlAt ? + : null} + + {y ? + this.drawDotAndLines(y, cycleDay.temperature.exclude, index) + : null + } {cycleDay && cycleDay.mucus ? : null} {y ? this.drawDotAndLines(y, cycleDay.temperature.exclude, index) : null} @@ -181,15 +211,18 @@ function makeColumnInfo(n) { function getPreviousDays(n) { const today = new Date() - today.setHours(0); today.setMinutes(0); today.setSeconds(0); today.setMilliseconds(0) + today.setHours(0) + today.setMinutes(0) + today.setSeconds(0) + today.setMilliseconds(0) const earlierDate = new Date(today - (range.DAY * n)) return range(earlierDate, today).reverse() } function normalizeToScale(temp) { - const temperatureScale = config.temperatureScale - const valueRelativeToScale = (temperatureScale.high - temp) / (temperatureScale.high - temperatureScale.low) + const scale = config.temperatureScale + const valueRelativeToScale = (scale.high - temp) / (scale.high - scale.low) const scaleHeight = config.chartHeight return scaleHeight * valueRelativeToScale } @@ -202,7 +235,6 @@ function makeYAxis() { const tickPositions = [] const labels = [] - // for style reasons, we don't want the first and last tick for (let i = 1; i < numberOfTicks - 1; i++) { const y = tickDistance * i @@ -223,3 +255,79 @@ function makeYAxis() { return {labels, tickPositions} } + +function setUpFertilityStatusFunc() { + let cycleStatus + let cycleStartDate + let noMoreCycles = false + + function updateCurrentCycle(dateString) { + cycleStatus = getCycleStatusForDay(dateString) + if(!cycleStatus) { + noMoreCycles = true + return + } + if (cycleStatus.phases.preOvulatory) { + cycleStartDate = cycleStatus.phases.preOvulatory.start.date + } else { + cycleStartDate = cycleStatus.phases.periOvulatory.start.date + } + } + + function dateIsInPeriOrPostPhase(dateString) { + return ( + dateString >= cycleStatus.phases.periOvulatory.start.date + ) + } + + function precededByAnotherTempValue(dateString) { + return ( + // we are only interested in days that have a preceding + // temp + Object.keys(cycleStatus.phases).some(phaseName => { + return cycleStatus.phases[phaseName].cycleDays.some(day => { + return day.temperature && day.date < dateString + }) + }) + // and also a following temp, so we don't draw the line + // longer than necessary + && + cycleStatus.phases.postOvulatory.cycleDays.some(day => { + return day.temperature && day.date > dateString + }) + ) + } + + function isInTempMeasuringPhase(cycleDay, dateString) { + return ( + cycleDay && cycleDay.temperature + || precededByAnotherTempValue(dateString) + ) + } + + return function(dateString, cycleDay) { + const ret = {} + if (!cycleStatus && !noMoreCycles) updateCurrentCycle(dateString) + if (noMoreCycles) return ret + + if (dateString < cycleStartDate) updateCurrentCycle(dateString) + if (noMoreCycles) return ret + + const tempShift = cycleStatus.temperatureShift + + if (tempShift) { + if (tempShift.firstHighMeasurementDay.date === dateString) { + ret.drawFhmLine = true + } + + if ( + dateIsInPeriOrPostPhase(dateString) && + isInTempMeasuringPhase(cycleDay, dateString) + ) { + ret.drawLtlAt = normalizeToScale(tempShift.ltl) + } + } + + return ret + } +} \ No newline at end of file diff --git a/components/chart/styles.js b/components/chart/styles.js index 4e06b73..8c2ab2e 100644 --- a/components/chart/styles.js +++ b/components/chart/styles.js @@ -74,6 +74,10 @@ const styles = { horizontalGrid: { stroke: 'lightgrey', strokeWidth: 1 + }, + nfpLine: { + stroke: '#00b159', + strokeWidth: 3 } } diff --git a/components/cycle-day/cycle-day-overview.js b/components/cycle-day/cycle-day-overview.js index c2730d1..094bc65 100644 --- a/components/cycle-day/cycle-day-overview.js +++ b/components/cycle-day/cycle-day-overview.js @@ -14,10 +14,10 @@ import { cervixFirmness as firmnessLabels, cervixPosition as positionLabels } from './labels/labels' -import cycleDayModule from '../../lib/get-cycle-day-number' +import cycleDayModule from '../../lib/cycle' import { bleedingDaysSortedByDate } from '../../db' -const getCycleDayNumber = cycleDayModule() +const getCycleDayNumber = cycleDayModule().getCycleDayNumber export default class DayView extends Component { constructor(props) { @@ -72,7 +72,7 @@ export default class DayView extends Component { if (this.cycleDay.mucus) { const mucus = this.cycleDay.mucus if (typeof mucus.feeling === 'number' && typeof mucus.texture === 'number') { - mucusLabel = `${feelingLabels[mucus.feeling]} + ${textureLabels[mucus.texture]} ( ${computeSensiplanMucusLabels[mucus.computedNfp]} )` + mucusLabel = `${feelingLabels[mucus.feeling]} + ${textureLabels[mucus.texture]} ( ${computeSensiplanMucusLabels[mucus.value]} )` if (mucus.exclude) mucusLabel = "( " + mucusLabel + " )" } } else { diff --git a/components/cycle-day/index.js b/components/cycle-day/index.js index 3d2ffde..e0eb666 100644 --- a/components/cycle-day/index.js +++ b/components/cycle-day/index.js @@ -4,7 +4,8 @@ import { Text, ScrollView } from 'react-native' -import cycleDayModule from '../../lib/get-cycle-day-number' +import cycleModule from '../../lib/cycle' +import { getFertilityStatusStringForDay } from '../../lib/sympto-adapter' import DayView from './cycle-day-overview' import BleedingEditView from './symptoms/bleeding' import TemperatureEditView from './symptoms/temperature' @@ -14,7 +15,7 @@ import CervixEditView from './symptoms/cervix' import styles from '../../styles' import actionButtonModule from './action-buttons' -const getCycleDayNumber = cycleDayModule() +const getCycleDayNumber = cycleModule().getCycleDayNumber export default class Day extends Component { constructor(props) { @@ -34,6 +35,7 @@ export default class Day extends Component { render() { const cycleDayNumber = getCycleDayNumber(this.cycleDay.date) + const fertilityStatus = getFertilityStatusStringForDay(this.cycleDay.date) return ( @@ -42,7 +44,14 @@ export default class Day extends Component { - { cycleDayNumber && Cycle day {cycleDayNumber} } + { cycleDayNumber && + + Cycle day {cycleDayNumber} + } + + + {fertilityStatus} + { diff --git a/components/cycle-day/labels/labels.js b/components/cycle-day/labels/labels.js index 25909df..6e294ef 100644 --- a/components/cycle-day/labels/labels.js +++ b/components/cycle-day/labels/labels.js @@ -1,17 +1,14 @@ -const bleeding = ['spotting', 'light', 'medium', 'heavy'] -const mucusFeeling = ['dry', 'nothing', 'wet', 'slippery'] -const mucusTexture = ['nothing', 'creamy', 'egg white'] -const mucusNFP = ['t', 'Ø', 'f', 'S', '+S'] -const cervixOpening = ['closed', 'medium', 'open'] -const cervixFirmness = ['hard', 'soft'] -const cervixPosition = ['low', 'medium', 'high'] +export const bleeding = ['spotting', 'light', 'medium', 'heavy'] +export const mucusFeeling = ['dry', 'nothing', 'wet', 'slippery'] +export const mucusTexture = ['nothing', 'creamy', 'egg white'] +export const mucusNFP = ['t', 'Ø', 'f', 'S', '+S'] +export const cervixOpening = ['closed', 'medium', 'open'] +export const cervixFirmness = ['hard', 'soft'] +export const cervixPosition = ['low', 'medium', 'high'] -export { - bleeding, - mucusFeeling, - mucusTexture, - mucusNFP, - cervixOpening, - cervixFirmness, - cervixPosition -} +export const fertilityStatus = { + fertile: 'fertile', + infertile: 'infertile', + fertileUntilEvening: 'Fertile phase ends in the evening', + unknown: 'We cannot show any cycle information because no menses has been entered' +} \ No newline at end of file diff --git a/components/cycle-day/symptoms/mucus.js b/components/cycle-day/symptoms/mucus.js index 4a090d2..abafe56 100644 --- a/components/cycle-day/symptoms/mucus.js +++ b/components/cycle-day/symptoms/mucus.js @@ -94,7 +94,7 @@ export default class Mucus extends Component { saveSymptom('mucus', this.cycleDay, { feeling: this.state.feeling, texture: this.state.texture, - computedNfp: computeSensiplanValue(this.state.feeling, this.state.texture), + value: computeSensiplanValue(this.state.feeling, this.state.texture), exclude: this.state.exclude }) }, diff --git a/components/home.js b/components/home.js index fa62ad7..48af5f5 100644 --- a/components/home.js +++ b/components/home.js @@ -6,11 +6,11 @@ import { ScrollView } from 'react-native' import { LocalDate } from 'js-joda' -import styles from '../styles' -import cycleDayModule from '../lib/get-cycle-day-number' -import { getOrCreateCycleDay, bleedingDaysSortedByDate, deleteAll } from '../db' +import styles from '../styles/index' +import cycleModule from '../lib/cycle' +import { getOrCreateCycleDay, bleedingDaysSortedByDate, fillWithDummyData, deleteAll } from '../db' -const getCycleDayNumber = cycleDayModule() +const getCycleDayNumber = cycleModule().getCycleDayNumber export default class Home extends Component { constructor(props) { @@ -68,6 +68,12 @@ export default class Home extends Component { title="Go to chart"> + + +