diff --git a/components/chart/chart.js b/components/chart/chart.js
index 7a90b87..49ddaa1 100644
--- a/components/chart/chart.js
+++ b/components/chart/chart.js
@@ -1,24 +1,14 @@
import React, { Component } from 'react'
-import { Text as ReactNativeText, View, FlatList } from 'react-native'
+import { View, FlatList } from 'react-native'
import range from 'date-range'
-import Svg,{
- G,
- Rect,
- Text,
- Circle,
- Line,
- Path
-} from 'react-native-svg'
import { LocalDate } from 'js-joda'
-import { getCycleDay, getOrCreateCycleDay, cycleDaysSortedByDate } from '../../db'
-import cycleModule from '../../lib/cycle'
+import { yAxis, normalizeToScale } from './y-axis'
+import DayColumn from './day-column'
+import { getCycleDay, cycleDaysSortedByDate } from '../../db'
import styles from './styles'
import config from './config'
-import { getCycleStatusForDay } from '../../lib/sympto-adapter'
-const getCycleDayNumber = cycleModule().getCycleDayNumber
-
-const yAxis = makeYAxis(config)
+const yAxisView = {yAxis.labels}
export default class CycleChart extends Component {
constructor(props) {
@@ -40,15 +30,11 @@ export default class CycleChart extends Component {
cycleDaysSortedByDate.removeListener(this.reCalculateChartInfo)
}
- passDateToDayView(dateString) {
- const cycleDay = getOrCreateCycleDay(dateString)
- this.props.navigation.navigate('cycleDay', { cycleDay })
- }
render() {
return (
- {yAxis.labels}
+ { yAxisView }
0 ? cols[index - 1] : undefined }
leftNeighbor = {index < cols.length - 1 ? cols[index + 1] : undefined }
+ navigate={this.props.navigation.navigate}
/>
)
}}
keyExtractor={item => item.dateString}
- initialNumToRender={20}
+ initialNumToRender={15}
>
@@ -74,137 +61,6 @@ export default class CycleChart extends Component {
}
}
-class DayColumn extends Component {
- makeDayColumn({ dateString, cycleDay, y }, index) {
- 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}
-
-
- {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)
- : null}
-
- )
- }
-
- drawDotAndLines(currY, exclude) {
- let lineToRight
- let lineToLeft
-
- function makeLine(otherColY, x, excludeLine) {
- const middleY = ((otherColY - currY) / 2) + currY
- const target = [x, middleY]
- const lineStyle = excludeLine ? styles.curveExcluded : styles.curve
-
- return
- }
-
- const thereIsADotToTheRight = this.props.rightNeighbor && this.props.rightNeighbor.y
- const thereIsADotToTheLeft = this.props.leftNeighbor && this.props.leftNeighbor.y
-
- if (thereIsADotToTheRight) {
- const neighbor = this.props.rightNeighbor
- const excludedLine = neighbor.cycleDay.temperature.exclude || exclude
- lineToRight = makeLine(neighbor.y, config.columnWidth, excludedLine)
- }
- if (thereIsADotToTheLeft) {
- const neighbor = this.props.leftNeighbor
- const excludedLine = neighbor.cycleDay.temperature.exclude || exclude
- lineToLeft = makeLine(neighbor.y, 0, excludedLine)
- }
-
- const dotStyle = exclude ? styles.curveDotsExcluded : styles.curveDots
- return (
- {lineToRight}
- {lineToLeft}
-
- )
- }
-
- placeHorizontalGrid() {
- return yAxis.tickPositions.map(tick => {
- return (
-
- )
- })
- }
-
- render() {
- return (
-
- )
- }
-}
-
function makeColumnInfo(n) {
const xAxisDates = getPreviousDays(n).map(jsDate => {
return LocalDate.of(
@@ -234,116 +90,4 @@ function getPreviousDays(n) {
const earlierDate = new Date(today - (range.DAY * n))
return range(earlierDate, today).reverse()
-}
-
-function normalizeToScale(temp) {
- const scale = config.temperatureScale
- const valueRelativeToScale = (scale.high - temp) / (scale.high - scale.low)
- const scaleHeight = config.chartHeight
- return scaleHeight * valueRelativeToScale
-}
-
-function makeYAxis() {
- const scaleMin = config.temperatureScale.low
- const scaleMax = config.temperatureScale.high
- const numberOfTicks = (scaleMax - scaleMin) * 2
- const tickDistance = config.chartHeight / numberOfTicks
-
- 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
- const style = styles.yAxisLabel
- // this eyeballing is sadly necessary because RN does not
- // support percentage values for transforms, which we'd need
- // to reliably place the label vertically centered to the grid
- style.top = y - 8
- labels.push(
-
- {scaleMax - i * 0.5}
-
- )
- tickPositions.push(y)
- }
-
- 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/day-column.js b/components/chart/day-column.js
new file mode 100644
index 0000000..1b9b2f1
--- /dev/null
+++ b/components/chart/day-column.js
@@ -0,0 +1,145 @@
+import React, { Component } from 'react'
+import Svg,{
+ G,
+ Rect,
+ Text,
+ Circle,
+ Line,
+ Path
+} from 'react-native-svg'
+import styles from './styles'
+import config from './config'
+import { getOrCreateCycleDay } from '../../db'
+import cycleModule from '../../lib/cycle'
+import setUpFertilityStatusFunc from './nfp-lines'
+import { horizontalGrid } from './y-axis'
+
+const getCycleDayNumber = cycleModule().getCycleDayNumber
+
+export default class DayColumn extends Component {
+ makeDayColumn({ dateString, cycleDay, y }, index) {
+ 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)}>
+
+ {horizontalGrid}
+ {nfpLineInfo.drawFhmLine ?
+ : null}
+
+
+
+ {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)
+ : null}
+
+ )
+ }
+
+ drawDotAndLines(currY, exclude) {
+ let lineToRight
+ let lineToLeft
+
+ function makeLine(otherColY, x, excludeLine) {
+ const middleY = ((otherColY - currY) / 2) + currY
+ const target = [x, middleY]
+ const lineStyle = excludeLine ? styles.curveExcluded : styles.curve
+
+ return
+ }
+
+ const thereIsADotToTheRight = this.props.rightNeighbor && this.props.rightNeighbor.y
+ const thereIsADotToTheLeft = this.props.leftNeighbor && this.props.leftNeighbor.y
+
+ if (thereIsADotToTheRight) {
+ const neighbor = this.props.rightNeighbor
+ const excludedLine = neighbor.cycleDay.temperature.exclude || exclude
+ lineToRight = makeLine(neighbor.y, config.columnWidth, excludedLine)
+ }
+ if (thereIsADotToTheLeft) {
+ const neighbor = this.props.leftNeighbor
+ const excludedLine = neighbor.cycleDay.temperature.exclude || exclude
+ lineToLeft = makeLine(neighbor.y, 0, excludedLine)
+ }
+
+ const dotStyle = exclude ? styles.curveDotsExcluded : styles.curveDots
+ return (
+ {lineToRight}
+ {lineToLeft}
+
+ )
+ }
+
+
+ passDateToDayView(dateString) {
+ const cycleDay = getOrCreateCycleDay(dateString)
+ this.props.navigate('cycleDay', { cycleDay })
+ }
+
+ shouldComponentUpdate() {
+ // for now, until we've solved the mysterious re-rendering
+ return false
+ }
+
+ render() {
+ console.log(this.props.index)
+ return (
+
+ )
+ }
+}
\ No newline at end of file
diff --git a/components/chart/nfp-lines.js b/components/chart/nfp-lines.js
new file mode 100644
index 0000000..e091597
--- /dev/null
+++ b/components/chart/nfp-lines.js
@@ -0,0 +1,78 @@
+import { getCycleStatusForDay } from '../../lib/sympto-adapter'
+import { normalizeToScale } from './y-axis'
+
+export default function () {
+ 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/y-axis.js b/components/chart/y-axis.js
new file mode 100644
index 0000000..0e9179a
--- /dev/null
+++ b/components/chart/y-axis.js
@@ -0,0 +1,56 @@
+import React from 'react'
+import { Text as ReactNativeText } from 'react-native'
+import { Line } from 'react-native-svg'
+import config from './config'
+import styles from './styles'
+
+function makeYAxis() {
+ const scaleMin = config.temperatureScale.low
+ const scaleMax = config.temperatureScale.high
+ const numberOfTicks = (scaleMax - scaleMin) * 2
+ const tickDistance = config.chartHeight / numberOfTicks
+
+ 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
+ const style = styles.yAxisLabel
+ // this eyeballing is sadly necessary because RN does not
+ // support percentage values for transforms, which we'd need
+ // to reliably place the label vertically centered to the grid
+ style.top = y - 8
+ labels.push(
+
+ {scaleMax - i * 0.5}
+
+ )
+ tickPositions.push(y)
+ }
+
+ return {labels, tickPositions}
+}
+
+export const yAxis = makeYAxis()
+
+export const horizontalGrid = yAxis.tickPositions.map(tick => {
+ return (
+
+ )
+})
+
+export function normalizeToScale(temp) {
+ const scale = config.temperatureScale
+ const valueRelativeToScale = (scale.high - temp) / (scale.high - scale.low)
+ const scaleHeight = config.chartHeight
+ return scaleHeight * valueRelativeToScale
+}
\ No newline at end of file