Merge branch '368-display-incomplete-mucus-and-cervix' into 'master'
make graph display for incomplete mucus and cervix values Closes #368 See merge request bloodyhealth/drip!245
This commit is contained in:
+153
-167
@@ -26,50 +26,110 @@ const label = styles.column.label
|
|||||||
class DayColumn extends Component {
|
class DayColumn extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super()
|
super()
|
||||||
const dateString = props.dateString
|
|
||||||
const columnHeight = props.columnHeight
|
const { dateString, chartSymptoms, columnHeight } = props
|
||||||
this.getCycleDayNumber = cycleModule().getCycleDayNumber
|
const cycleDayData = getCycleDay(dateString)
|
||||||
const cycleDay = getCycleDay(dateString)
|
|
||||||
this.data = {}
|
this.data = {}
|
||||||
if (cycleDay) {
|
|
||||||
this.data = props.chartSymptoms.reduce((acc, symptom) => {
|
if (cycleDayData) {
|
||||||
if (['bleeding', 'temperature', 'mucus', 'desire', 'note'].includes(symptom)) {
|
this.data = chartSymptoms.reduce((symptomDataToDisplay, symptom, ) => {
|
||||||
acc[symptom] = cycleDay[symptom] && cycleDay[symptom].value
|
const symptomData = cycleDayData[symptom]
|
||||||
if (symptom === 'temperature' && acc.temperature) {
|
|
||||||
acc.y = normalizeToScale(acc.temperature, columnHeight)
|
if (symptomData && symptom === 'temperature') {
|
||||||
const neighbor = getInfoForNeighborColumns(dateString, columnHeight)
|
symptomDataToDisplay[symptom] =
|
||||||
for (const key in neighbor) {
|
this.getTemperatureProps(symptomData, columnHeight, dateString)
|
||||||
acc[key] = neighbor[key]
|
} 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (symptom === 'cervix') {
|
|
||||||
acc.cervix = cycleDay.cervix &&
|
return symptomDataToDisplay
|
||||||
(cycleDay.cervix.opening + cycleDay.cervix.firmness)
|
|
||||||
} else if (symptom === 'sex') {
|
|
||||||
// solo = 1 + partner = 2
|
|
||||||
acc.sex = cycleDay.sex &&
|
|
||||||
(cycleDay.sex.solo + 2 * cycleDay.sex.partner)
|
|
||||||
} else if (symptom === 'pain') {
|
|
||||||
// is any pain documented?
|
|
||||||
acc.pain = cycleDay.pain &&
|
|
||||||
Object.values({...cycleDay.pain}).some(x => x === true)
|
|
||||||
} else if (symptom === 'mood') {
|
|
||||||
// is mood documented?
|
|
||||||
acc.mood = cycleDay.mood &&
|
|
||||||
Object.values({...cycleDay.mood}).some(x => x === true)
|
|
||||||
}
|
|
||||||
acc[`${symptom}Exclude`] = cycleDay[symptom] && cycleDay[symptom].exclude
|
|
||||||
return acc
|
|
||||||
}, this.data)
|
}, this.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fhmAndLtl = props.getFhmAndLtlInfo(
|
this.fhmAndLtl = props.getFhmAndLtlInfo(
|
||||||
props.dateString,
|
props.dateString,
|
||||||
this.data.temperature,
|
this.data.temperature ? this.data.temperature.value : null,
|
||||||
props.columnHeight
|
props.columnHeight
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) => {
|
onDaySelect = (date) => {
|
||||||
this.props.setDate(date)
|
this.props.setDate(date)
|
||||||
this.props.navigate('CycleDay')
|
this.props.navigate('CycleDay')
|
||||||
@@ -79,10 +139,48 @@ class DayColumn extends Component {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drawSymptom = (symptom) => {
|
||||||
|
|
||||||
|
const { symptomHeight } = this.props
|
||||||
|
const shouldDrawSymptom = this.data.hasOwnProperty(symptom)
|
||||||
|
const styleParent = [styles.symptomRow, {height: symptomHeight}]
|
||||||
|
|
||||||
|
if (shouldDrawSymptom) {
|
||||||
|
const styleSymptom = styles.iconShades[symptom]
|
||||||
|
const symptomData = this.data[symptom]
|
||||||
|
|
||||||
|
const dataIsComplete = this.isSymptomDataComplete(symptom)
|
||||||
|
const isMucusOrCervix = (symptom === 'mucus') || (symptom === 'cervix')
|
||||||
|
|
||||||
|
const backgroundColor = (isMucusOrCervix && !dataIsComplete) ?
|
||||||
|
'white' : styleSymptom[symptomData]
|
||||||
|
const borderWidth = (isMucusOrCervix && !dataIsComplete) ? 2 : 0
|
||||||
|
const borderColor = styleSymptom[0]
|
||||||
|
const styleChild = [styles.symptomIcon, {
|
||||||
|
backgroundColor,
|
||||||
|
borderColor,
|
||||||
|
borderWidth
|
||||||
|
}]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styleParent} key={symptom}>
|
||||||
|
<View style={styleChild} />
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<View style={styleParent} key={symptom} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const columnElements = []
|
const columnElements = []
|
||||||
const dateString = this.props.dateString
|
const { dateString,
|
||||||
const symptomHeight = this.props.symptomHeight
|
symptomRowSymptoms,
|
||||||
|
chartHeight,
|
||||||
|
columnHeight,
|
||||||
|
xAxisHeight } = this.props
|
||||||
|
|
||||||
if(this.fhmAndLtl.drawLtlAt) {
|
if(this.fhmAndLtl.drawLtlAt) {
|
||||||
const ltlLine = (<Shape
|
const ltlLine = (<Shape
|
||||||
@@ -103,37 +201,42 @@ class DayColumn extends Component {
|
|||||||
fill="red"
|
fill="red"
|
||||||
stroke={styles.nfpLine.stroke}
|
stroke={styles.nfpLine.stroke}
|
||||||
strokeWidth={styles.nfpLine.strokeWidth}
|
strokeWidth={styles.nfpLine.strokeWidth}
|
||||||
d={new Path()
|
d={new Path().moveTo(x, x).lineTo(x, columnHeight)}
|
||||||
.moveTo(x, x)
|
|
||||||
.lineTo(x, this.props.columnHeight)
|
|
||||||
}
|
|
||||||
key='fhm'
|
key='fhm'
|
||||||
/>)
|
/>)
|
||||||
columnElements.push(fhmLine)
|
columnElements.push(fhmLine)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.data && this.data.temperature && this.data.temperature.y) {
|
||||||
|
const { temperatureExclude,
|
||||||
|
y,
|
||||||
|
rightY,
|
||||||
|
leftY,
|
||||||
|
rightTemperatureExclude,
|
||||||
|
leftTemperatureExclude
|
||||||
|
} = this.data.temperature
|
||||||
|
|
||||||
if (this.data.y) {
|
|
||||||
columnElements.push(
|
columnElements.push(
|
||||||
<DotAndLine
|
<DotAndLine
|
||||||
y={this.data.y}
|
y={y}
|
||||||
exclude={this.data.temperatureExclude}
|
exclude={temperatureExclude}
|
||||||
rightY={this.data.rightY}
|
rightY={rightY}
|
||||||
rightTemperatureExclude={this.data.rightTemperatureExclude}
|
rightTemperatureExclude={rightTemperatureExclude}
|
||||||
leftY={this.data.leftY}
|
leftY={leftY}
|
||||||
leftTemperatureExclude={this.data.leftTemperatureExclude}
|
leftTemperatureExclude={leftTemperatureExclude}
|
||||||
key='dotandline'
|
key='dotandline'
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const cycleDayNumber = this.getCycleDayNumber(dateString)
|
const cycleDayNumber = cycleModule().getCycleDayNumber(dateString)
|
||||||
const dayDate = LocalDate.parse(dateString)
|
const dayDate = LocalDate.parse(dateString)
|
||||||
const shortDate = dayDate.dayOfMonth() === 1 ?
|
const shortDate = dayDate.dayOfMonth() === 1 ?
|
||||||
moment(dateString, "YYYY-MM-DD").format('MMM')
|
moment(dateString, "YYYY-MM-DD").format('MMM')
|
||||||
:
|
:
|
||||||
moment(dateString, "YYYY-MM-DD").format('Do')
|
moment(dateString, "YYYY-MM-DD").format('Do')
|
||||||
const boldDateLabel = dayDate.dayOfMonth() === 1 ? {fontWeight: 'bold'} : {}
|
const boldDateLabel = dayDate.dayOfMonth() === 1 ? {fontWeight: 'bold'} : {}
|
||||||
|
|
||||||
const cycleDayLabel = (
|
const cycleDayLabel = (
|
||||||
<Text style = {label.number}>
|
<Text style = {label.number}>
|
||||||
{cycleDayNumber ? cycleDayNumber : ' '}
|
{cycleDayNumber ? cycleDayNumber : ' '}
|
||||||
@@ -149,131 +252,26 @@ class DayColumn extends Component {
|
|||||||
<Shape
|
<Shape
|
||||||
stroke={styles.column.stroke.color}
|
stroke={styles.column.stroke.color}
|
||||||
strokeWidth={styles.column.stroke.width}
|
strokeWidth={styles.column.stroke.width}
|
||||||
d={new Path().lineTo(0, this.props.chartHeight)}
|
d={new Path().lineTo(0, chartHeight)}
|
||||||
/>
|
/>
|
||||||
{ columnElements }
|
{ columnElements }
|
||||||
</G>
|
</G>
|
||||||
)
|
)
|
||||||
|
|
||||||
const symptomIconViews = {
|
|
||||||
bleeding: (
|
|
||||||
<SymptomIconView
|
|
||||||
value={this.data.bleeding}
|
|
||||||
symptomHeight={symptomHeight}
|
|
||||||
key='bleeding'
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
{...styles.symptomIcon}
|
|
||||||
backgroundColor={styles.iconShades.bleeding[this.data.bleeding]}
|
|
||||||
/>
|
|
||||||
</SymptomIconView>
|
|
||||||
),
|
|
||||||
mucus: (
|
|
||||||
<SymptomIconView
|
|
||||||
value={this.data.mucus}
|
|
||||||
symptomHeight={symptomHeight}
|
|
||||||
key='mucus'
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
{...styles.symptomIcon}
|
|
||||||
backgroundColor={styles.iconShades.mucus[this.data.mucus]}
|
|
||||||
/>
|
|
||||||
</SymptomIconView>
|
|
||||||
),
|
|
||||||
cervix: (
|
|
||||||
<SymptomIconView
|
|
||||||
value={this.data.cervix}
|
|
||||||
symptomHeight={symptomHeight}
|
|
||||||
key='cervix'
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
{...styles.symptomIcon}
|
|
||||||
// cervix is sum of openess and firmness - fertile only when closed and hard (=0)
|
|
||||||
backgroundColor={this.data.cervix > 0 ?
|
|
||||||
styles.iconShades.cervix[2] :
|
|
||||||
styles.iconShades.cervix[0]
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</SymptomIconView>
|
|
||||||
),
|
|
||||||
sex: (
|
|
||||||
<SymptomIconView
|
|
||||||
value={this.data.sex}
|
|
||||||
symptomHeight={symptomHeight}
|
|
||||||
key='sex'
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
{...styles.symptomIcon}
|
|
||||||
backgroundColor={styles.iconShades.sex[this.data.sex - 1]}
|
|
||||||
/>
|
|
||||||
</SymptomIconView>
|
|
||||||
),
|
|
||||||
desire: (
|
|
||||||
<SymptomIconView
|
|
||||||
value={this.data.desire}
|
|
||||||
symptomHeight={symptomHeight}
|
|
||||||
key='desire'
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
{...styles.symptomIcon}
|
|
||||||
backgroundColor={styles.iconShades.desire[this.data.desire]}
|
|
||||||
/>
|
|
||||||
</SymptomIconView>
|
|
||||||
),
|
|
||||||
pain: (
|
|
||||||
<SymptomIconView
|
|
||||||
value={this.data.pain}
|
|
||||||
symptomHeight={symptomHeight}
|
|
||||||
key='pain'
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
{...styles.symptomIcon}
|
|
||||||
backgroundColor={styles.iconShades.pain}
|
|
||||||
/>
|
|
||||||
</SymptomIconView>
|
|
||||||
),
|
|
||||||
mood: (
|
|
||||||
<SymptomIconView
|
|
||||||
value={this.data.mood}
|
|
||||||
symptomHeight={symptomHeight}
|
|
||||||
key='mood'
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
{...styles.symptomIcon}
|
|
||||||
backgroundColor={styles.iconShades.mood}
|
|
||||||
/>
|
|
||||||
</SymptomIconView>
|
|
||||||
),
|
|
||||||
note: (
|
|
||||||
<SymptomIconView
|
|
||||||
value={this.data.note}
|
|
||||||
symptomHeight={symptomHeight}
|
|
||||||
key='note'
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
{...styles.symptomIcon}
|
|
||||||
backgroundColor={styles.iconShades.note}
|
|
||||||
/>
|
|
||||||
</SymptomIconView>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={() => this.onDaySelect(dateString)}
|
onPress={() => this.onDaySelect(dateString)}
|
||||||
activeOpacity={1}
|
activeOpacity={1}
|
||||||
>
|
>
|
||||||
<View>
|
<View>
|
||||||
{this.props.symptomRowSymptoms.map(symptomName => {
|
{symptomRowSymptoms.map(symptom => this.drawSymptom(symptom))}
|
||||||
return symptomIconViews[symptomName]
|
|
||||||
})}
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Surface width={config.columnWidth} height={this.props.columnHeight}>
|
<Surface width={config.columnWidth} height={columnHeight}>
|
||||||
{column}
|
{column}
|
||||||
</Surface>
|
</Surface>
|
||||||
|
|
||||||
<View style={{height: this.props.xAxisHeight}}>
|
<View style={{height: xAxisHeight}}>
|
||||||
{cycleDayLabel}
|
{cycleDayLabel}
|
||||||
{dateLabel}
|
{dateLabel}
|
||||||
</View>
|
</View>
|
||||||
@@ -294,18 +292,6 @@ export default connect(
|
|||||||
)(DayColumn)
|
)(DayColumn)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function SymptomIconView(props) {
|
|
||||||
const style = [styles.symptomRow, {height: props.symptomHeight}]
|
|
||||||
return (
|
|
||||||
<View style={style}>
|
|
||||||
{(typeof props.value === 'number' || props.value === true || typeof props.value === 'string') &&
|
|
||||||
props.children
|
|
||||||
}
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function getInfoForNeighborColumns(dateString, columnHeight) {
|
function getInfoForNeighborColumns(dateString, columnHeight) {
|
||||||
const ret = {
|
const ret = {
|
||||||
rightY: null,
|
rightY: null,
|
||||||
|
|||||||
Reference in New Issue
Block a user