Merge branch 'chart-refactoring-part-2' into 'master'
Chart refactoring part 2 See merge request bloodyhealth/drip!255
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { Shape } from 'react-native/Libraries/ART/ReactNativeART'
|
||||
|
||||
import styles from './styles'
|
||||
|
||||
const ChartLine = ({ path, isNfpLine = false }) => {
|
||||
const strokeStyle =
|
||||
isNfpLine ? styles.nfpLine.stroke : styles.column.stroke.color
|
||||
const strokeWidth =
|
||||
isNfpLine ? styles.nfpLine.strokeWidth : styles.column.stroke.width
|
||||
|
||||
return (
|
||||
<Shape
|
||||
stroke={strokeStyle}
|
||||
strokeWidth={strokeWidth}
|
||||
d={path}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
ChartLine.propTypes = {
|
||||
path: PropTypes.object,
|
||||
isNfpLine: PropTypes.bool,
|
||||
}
|
||||
|
||||
export default ChartLine
|
||||
+19
-51
@@ -1,20 +1,20 @@
|
||||
import React, { Component } from 'react'
|
||||
import { View, FlatList, ActivityIndicator } from 'react-native'
|
||||
import { LocalDate } from 'js-joda'
|
||||
|
||||
import AppLoadingView from '../app-loading'
|
||||
import YAxis from './y-axis'
|
||||
import nfpLines from './nfp-lines'
|
||||
import DayColumn from './day-column'
|
||||
import HorizontalGrid from './horizontal-grid'
|
||||
|
||||
import { getCycleDaysSortedByDate, getAmountOfCycleDays } from '../../db'
|
||||
import styles from './styles'
|
||||
import { getCycleDaysSortedByDate } from '../../db'
|
||||
import nothingChanged from '../../db/db-unchanged'
|
||||
import { scaleObservable } from '../../local-storage'
|
||||
import { makeColumnInfo } from '../helpers/chart'
|
||||
|
||||
import config from '../../config'
|
||||
|
||||
import AppLoadingView from '../app-loading'
|
||||
|
||||
import nothingChanged from '../../db/db-unchanged'
|
||||
import styles from './styles'
|
||||
|
||||
export default class CycleChart extends Component {
|
||||
constructor(props) {
|
||||
@@ -32,7 +32,6 @@ export default class CycleChart extends Component {
|
||||
navigate={this.props.navigate}
|
||||
symptomHeight={this.symptomHeight}
|
||||
columnHeight={this.columnHeight}
|
||||
chartHeight={this.state.chartHeight}
|
||||
symptomRowSymptoms={this.symptomRowSymptoms}
|
||||
chartSymptoms={this.chartSymptoms}
|
||||
getFhmAndLtlInfo={this.getFhmAndLtlInfo}
|
||||
@@ -72,7 +71,7 @@ export default class CycleChart extends Component {
|
||||
this.chartSymptoms.push('temperature')
|
||||
}
|
||||
|
||||
const columnData = this.makeColumnInfo()
|
||||
const columnData = makeColumnInfo()
|
||||
this.setState({
|
||||
columns: columnData,
|
||||
chartHeight: height
|
||||
@@ -104,43 +103,29 @@ export default class CycleChart extends Component {
|
||||
this.removeObvListener()
|
||||
}
|
||||
|
||||
makeColumnInfo() {
|
||||
let amountOfCycleDays = getAmountOfCycleDays()
|
||||
// if there's not much data yet, we want to show at least 30 days on the chart
|
||||
if (amountOfCycleDays < 30) {
|
||||
amountOfCycleDays = 30
|
||||
} else {
|
||||
// we don't want the chart to end abruptly before the first data day
|
||||
amountOfCycleDays += 5
|
||||
}
|
||||
const localDates = getTodayAndPreviousDays(amountOfCycleDays)
|
||||
return localDates.map(localDate => localDate.toString())
|
||||
}
|
||||
|
||||
render() {
|
||||
const { chartHeight, chartLoaded } = this.state
|
||||
return (
|
||||
<View
|
||||
onLayout={this.onLayout}
|
||||
style={{ flexDirection: 'row', flex: 1 }}
|
||||
style={styles.container}
|
||||
>
|
||||
{!chartLoaded && <AppLoadingView />}
|
||||
|
||||
{chartHeight && chartLoaded && (
|
||||
<YAxis
|
||||
height={this.columnHeight}
|
||||
symptomsToDisplay={this.symptomRowSymptoms}
|
||||
symptomsSectionHeight={this.symptomRowHeight}
|
||||
/>
|
||||
<React.Fragment>
|
||||
<YAxis
|
||||
height={this.columnHeight}
|
||||
symptomsToDisplay={this.symptomRowSymptoms}
|
||||
symptomsSectionHeight={this.symptomRowHeight}
|
||||
/>
|
||||
<HorizontalGrid
|
||||
height={this.columnHeight}
|
||||
startPosition={this.symptomRowHeight}
|
||||
/>
|
||||
</React.Fragment>
|
||||
)}
|
||||
|
||||
{chartHeight && chartLoaded && (
|
||||
<HorizontalGrid
|
||||
height={this.columnHeight}
|
||||
startPosition={this.symptomRowHeight}
|
||||
/>)
|
||||
}
|
||||
|
||||
{chartHeight &&
|
||||
<FlatList
|
||||
horizontal={true}
|
||||
@@ -171,20 +156,3 @@ function LoadingMoreView(props) {
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
function getTodayAndPreviousDays(n) {
|
||||
const today = LocalDate.now()
|
||||
const targetDate = today.minusDays(n)
|
||||
|
||||
function getDaysInRange(currDate, range) {
|
||||
if (currDate.isBefore(targetDate)) {
|
||||
return range
|
||||
} else {
|
||||
range.push(currDate)
|
||||
const next = currDate.minusDays(1)
|
||||
return getDaysInRange(next, range)
|
||||
}
|
||||
}
|
||||
|
||||
return getDaysInRange(today, [])
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { Text, View } from 'react-native'
|
||||
|
||||
import moment from 'moment'
|
||||
import { LocalDate } from 'js-joda'
|
||||
|
||||
import styles from './styles'
|
||||
import cycleModule from '../../lib/cycle'
|
||||
|
||||
const CycleDayLabel = ({ height, date }) => {
|
||||
const { label } = styles.column
|
||||
const dayDate = LocalDate.parse(date)
|
||||
const cycleDayNumber = cycleModule().getCycleDayNumber(date)
|
||||
|
||||
const isFirstDayOfMonth = dayDate.dayOfMonth() === 1
|
||||
const dateFormatting = isFirstDayOfMonth ? 'MMM' : 'Do'
|
||||
const shortDate = moment(date, "YYYY-MM-DD").format(dateFormatting)
|
||||
const boldDateLabel = isFirstDayOfMonth ? {fontWeight: 'bold'} : {}
|
||||
|
||||
return (
|
||||
<View style={{ height }}>
|
||||
<Text style={label.number}>
|
||||
{cycleDayNumber ? cycleDayNumber : ' '}
|
||||
</Text>
|
||||
<Text style={[label.date, boldDateLabel]}>
|
||||
{shortDate}
|
||||
</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
CycleDayLabel.propTypes = {
|
||||
height: PropTypes.number,
|
||||
date: PropTypes.string,
|
||||
}
|
||||
|
||||
export default CycleDayLabel
|
||||
+22
-201
@@ -1,30 +1,20 @@
|
||||
import React, { Component } from 'react'
|
||||
import {
|
||||
Text, View, TouchableOpacity
|
||||
} from 'react-native'
|
||||
import {
|
||||
Surface,
|
||||
Group as G,
|
||||
Path,
|
||||
Shape
|
||||
} from 'react-native/Libraries/ART/ReactNativeART'
|
||||
import { TouchableOpacity } from 'react-native'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
import { setDate } from '../../slices/date'
|
||||
|
||||
import { LocalDate } from 'js-joda'
|
||||
import moment from 'moment'
|
||||
import styles from './styles'
|
||||
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 TemperatureColumn from './temperature-column'
|
||||
import CycleDayLabel from './cycle-day-label'
|
||||
|
||||
import { normalizeToScale } from '../helpers/chart'
|
||||
|
||||
const label = styles.column.label
|
||||
import {
|
||||
symptomColorMethods,
|
||||
getTemperatureProps,
|
||||
isSymptomDataComplete
|
||||
} from '../helpers/chart'
|
||||
|
||||
class DayColumn extends Component {
|
||||
constructor(props) {
|
||||
@@ -40,14 +30,13 @@ class DayColumn extends Component {
|
||||
|
||||
if (symptomData && symptom === 'temperature') {
|
||||
symptomDataToDisplay[symptom] =
|
||||
this.getTemperatureProps(symptomData, columnHeight, dateString)
|
||||
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']
|
||||
symptomColorMethods[symptom] || symptomColorMethods['default']
|
||||
|
||||
symptomDataToDisplay[symptom] = getSymptomColorIndex(symptomData)
|
||||
}
|
||||
@@ -64,75 +53,6 @@ class DayColumn extends Component {
|
||||
)
|
||||
}
|
||||
|
||||
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')
|
||||
@@ -143,89 +63,11 @@ class DayColumn extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const columnElements = []
|
||||
const { dateString,
|
||||
symptomRowSymptoms,
|
||||
chartHeight,
|
||||
columnHeight,
|
||||
xAxisHeight } = this.props
|
||||
|
||||
if(this.fhmAndLtl.drawLtlAt) {
|
||||
const ltlLine = (<Shape
|
||||
stroke={styles.nfpLine.stroke}
|
||||
strokeWidth={styles.nfpLine.strokeWidth}
|
||||
d={new Path()
|
||||
.moveTo(0, this.fhmAndLtl.drawLtlAt)
|
||||
.lineTo(config.columnWidth, this.fhmAndLtl.drawLtlAt)
|
||||
}
|
||||
key='ltl'
|
||||
/>)
|
||||
columnElements.push(ltlLine)
|
||||
}
|
||||
|
||||
if (this.fhmAndLtl.drawFhmLine) {
|
||||
const x = styles.nfpLine.strokeWidth / 2
|
||||
const fhmLine = (<Shape
|
||||
fill="red"
|
||||
stroke={styles.nfpLine.stroke}
|
||||
strokeWidth={styles.nfpLine.strokeWidth}
|
||||
d={new Path().moveTo(x, x).lineTo(x, columnHeight)}
|
||||
key='fhm'
|
||||
/>)
|
||||
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}
|
||||
key='dotandline'
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const cycleDayNumber = cycleModule().getCycleDayNumber(dateString)
|
||||
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 = (
|
||||
<Text style = {[label.date, boldDateLabel]}>
|
||||
{shortDate}
|
||||
</Text>
|
||||
)
|
||||
|
||||
const column = (
|
||||
<G>
|
||||
<Shape
|
||||
stroke={styles.column.stroke.color}
|
||||
strokeWidth={styles.column.stroke.width}
|
||||
d={new Path().lineTo(0, chartHeight)}
|
||||
/>
|
||||
{ columnElements }
|
||||
</G>
|
||||
)
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={() => this.onDaySelect(dateString)}
|
||||
@@ -240,21 +82,25 @@ class DayColumn extends Component {
|
||||
symptom={symptom}
|
||||
symptomValue={hasSymptomData && this.data[symptom]}
|
||||
isSymptomDataComplete={
|
||||
hasSymptomData && this.isSymptomDataComplete(symptom)
|
||||
hasSymptomData && isSymptomDataComplete(symptom, dateString)
|
||||
}
|
||||
height={this.props.symptomHeight}
|
||||
/>)
|
||||
}
|
||||
)}
|
||||
|
||||
<Surface width={config.columnWidth} height={columnHeight}>
|
||||
{column}
|
||||
</Surface>
|
||||
<TemperatureColumn
|
||||
horizontalLinePosition={this.fhmAndLtl.drawLtlAt}
|
||||
isVerticalLine={this.fhmAndLtl.drawFhmLine}
|
||||
data={this.data && this.data.temperature}
|
||||
columnHeight={columnHeight}
|
||||
/>
|
||||
|
||||
<CycleDayLabel
|
||||
height={xAxisHeight}
|
||||
date={dateString}
|
||||
/>
|
||||
|
||||
<View style={{height: xAxisHeight}}>
|
||||
{cycleDayLabel}
|
||||
{dateLabel}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}
|
||||
@@ -270,28 +116,3 @@ 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
|
||||
}
|
||||
|
||||
@@ -25,6 +25,10 @@ const orangeColor = '#bc6642'
|
||||
const mintColor = '#6ca299'
|
||||
|
||||
const styles = {
|
||||
container: {
|
||||
flexDirection: 'row',
|
||||
flex: 1,
|
||||
},
|
||||
curve: {
|
||||
stroke: colorTemperature,
|
||||
strokeWidth: lineWidth,
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { Surface , Path } from 'react-native/Libraries/ART/ReactNativeART'
|
||||
|
||||
import ChartLine from './chart-line'
|
||||
import DotAndLine from './dot-and-line'
|
||||
|
||||
import styles from './styles'
|
||||
import config from '../../config'
|
||||
|
||||
const TemperatureColumn = ({
|
||||
horizontalLinePosition,
|
||||
isVerticalLine,
|
||||
data,
|
||||
columnHeight
|
||||
}) => {
|
||||
|
||||
const x = styles.nfpLine.strokeWidth / 2
|
||||
|
||||
return (
|
||||
<Surface width={config.columnWidth} height={columnHeight}>
|
||||
|
||||
<ChartLine
|
||||
path={new Path().lineTo(0, columnHeight)}
|
||||
/>
|
||||
|
||||
{horizontalLinePosition && <ChartLine
|
||||
path={new Path()
|
||||
.moveTo(0, horizontalLinePosition)
|
||||
.lineTo(config.columnWidth, horizontalLinePosition)
|
||||
}
|
||||
isNfpLine={true}
|
||||
key='ltl'
|
||||
/>}
|
||||
|
||||
{isVerticalLine && <ChartLine
|
||||
path={new Path().moveTo(x, x).lineTo(x, columnHeight)}
|
||||
isNfpLine={true}
|
||||
key='fhm'
|
||||
/>}
|
||||
|
||||
{data && data.y && <DotAndLine
|
||||
y={data.y}
|
||||
exclude={data.temperatureExclude}
|
||||
rightY={data.rightY}
|
||||
rightTemperatureExclude={data.rightTemperatureExclude}
|
||||
leftY={data.leftY}
|
||||
leftTemperatureExclude={data.leftTemperatureExclude}
|
||||
key='dotandline'
|
||||
/>}
|
||||
|
||||
</Surface>
|
||||
)
|
||||
}
|
||||
|
||||
TemperatureColumn.propTypes = {
|
||||
horizontalLinePosition: PropTypes.number,
|
||||
isVerticalLine: PropTypes.bool,
|
||||
data: PropTypes.object,
|
||||
columnHeight: PropTypes.number,
|
||||
}
|
||||
|
||||
export default TemperatureColumn
|
||||
@@ -1,6 +1,12 @@
|
||||
import { LocalDate } from 'js-joda'
|
||||
|
||||
import { scaleObservable, unitObservable } from '../../local-storage'
|
||||
import { getCycleDay, getAmountOfCycleDays } from '../../db'
|
||||
|
||||
import config from '../../config'
|
||||
|
||||
//YAxis helpers
|
||||
|
||||
export function normalizeToScale(temp, columnHeight) {
|
||||
const scale = scaleObservable.value
|
||||
const valueRelativeToScale = (scale.max - temp) / (scale.max - scale.min)
|
||||
@@ -65,3 +71,130 @@ export function getTickList(columnHeight) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//DayColumn helpers
|
||||
|
||||
export function isSymptomDataComplete(symptom, dateString) {
|
||||
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'])()
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
export function 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)
|
||||
}
|
||||
|
||||
export const 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
|
||||
}
|
||||
}
|
||||
|
||||
// Chart helpers
|
||||
|
||||
export function makeColumnInfo() {
|
||||
let amountOfCycleDays = getAmountOfCycleDays()
|
||||
// if there's not much data yet, we want to show at least 30 days on the chart
|
||||
if (amountOfCycleDays < 30) {
|
||||
amountOfCycleDays = 30
|
||||
} else {
|
||||
// we don't want the chart to end abruptly before the first data day
|
||||
amountOfCycleDays += 5
|
||||
}
|
||||
const localDates = getTodayAndPreviousDays(amountOfCycleDays)
|
||||
return localDates.map(localDate => localDate.toString())
|
||||
}
|
||||
|
||||
function getTodayAndPreviousDays(n) {
|
||||
const today = LocalDate.now()
|
||||
const targetDate = today.minusDays(n)
|
||||
|
||||
function getDaysInRange(currDate, range) {
|
||||
if (currDate.isBefore(targetDate)) {
|
||||
return range
|
||||
} else {
|
||||
range.push(currDate)
|
||||
const next = currDate.minusDays(1)
|
||||
return getDaysInRange(next, range)
|
||||
}
|
||||
}
|
||||
|
||||
return getDaysInRange(today, [])
|
||||
}
|
||||
Reference in New Issue
Block a user