diff --git a/components/chart/chart.js b/components/chart/chart.js index 4ee6dd6aa82d5fb98f6e04281abac4b592c67f67..201f0f866a29805107e8890f73ae1fcf37b31282 100644 --- a/components/chart/chart.js +++ b/components/chart/chart.js @@ -21,7 +21,10 @@ export default class CycleChart extends Component { {...item} index={index} navigate={this.props.navigate} + symptomHeight={this.symptomHeight} + columnHeight={this.columnHeight} chartHeight={this.state.chartHeight} + symptomRowSymptoms={this.symptomRowSymptoms} /> ) } @@ -33,7 +36,34 @@ export default class CycleChart extends Component { const height = nativeEvent.layout.height this.setState({ chartHeight: height }) this.reCalculateChartInfo = () => { - this.setState({ columns: this.makeColumnInfo(nfpLines()) }) + // how many symptoms need to be displayed on the chart's upper symptom row? + this.symptomRowSymptoms = [ + 'bleeding', + 'mucus', + 'cervix', + 'sex', + 'desire', + 'pain', + 'note' + ].filter((symptomName) => { + return this.cycleDaysSortedByDate.some(cycleDay => { + return cycleDay[symptomName] + }) + }) + + this.xAxisHeight = this.state.chartHeight * config.xAxisHeightPercentage + const remainingHeight = this.state.chartHeight - this.xAxisHeight + this.symptomHeight = config.symptomHeightPercentage * remainingHeight + this.symptomRowHeight = this.symptomRowSymptoms.length * this.symptomHeight + this.columnHeight = remainingHeight - this.symptomRowHeight + + const chartSymptoms = [...this.symptomRowSymptoms] + if (this.cycleDaysSortedByDate.some(day => day.temperature)) { + chartSymptoms.push('temperature') + } + + const columnData = this.makeColumnInfo(nfpLines(), chartSymptoms) + this.setState({ columns: columnData }) } this.cycleDaysSortedByDate.addListener(this.reCalculateChartInfo) @@ -45,7 +75,7 @@ export default class CycleChart extends Component { this.removeObvListener() } - makeColumnInfo(getFhmAndLtlInfo) { + makeColumnInfo(getFhmAndLtlInfo, chartSymptoms) { let amountOfCycleDays = getAmountOfCycleDays() // if there's not much data yet, we want to show at least 30 days on the chart if (amountOfCycleDays < 30) { @@ -63,21 +93,11 @@ export default class CycleChart extends Component { ).toString() }) - const chartSymptoms = [ - 'bleeding', - 'temperature', - 'mucus', - 'cervix', - 'sex', - 'desire', - 'pain', - 'note' - ].filter((symptomName) => { - return this.cycleDaysSortedByDate.some(cycleDay => cycleDay[symptomName]) - }) - const columns = xAxisDates.map(dateString => { + const column = { dateString } const cycleDay = getCycleDay(dateString) + if (!cycleDay) return column + const symptoms = chartSymptoms.reduce((acc, symptom) => { if (symptom === 'bleeding' || symptom === 'temperature' || @@ -85,28 +105,29 @@ export default class CycleChart extends Component { symptom === 'desire' || symptom === 'note' ) { - acc[symptom] = cycleDay && cycleDay[symptom] && cycleDay[symptom].value + acc[symptom] = cycleDay[symptom] && cycleDay[symptom].value } else if (symptom === 'cervix') { - acc[symptom] = cycleDay && cycleDay['cervix'] && (cycleDay['cervix'].opening + cycleDay['cervix'].firmness) + acc.cervix = cycleDay.cervix && + (cycleDay.cervix.opening + cycleDay.cervix.firmness) } else if (symptom === 'sex') { // solo = 1 + partner = 2 - acc[symptom] = cycleDay && cycleDay['sex'] && (cycleDay['sex'].solo + cycleDay['sex'].partner) + acc.sex = cycleDay.sex && (cycleDay.sex.solo + cycleDay.sex.partner) } else if (symptom === 'pain') { // is any pain documented? - acc[symptom] = cycleDay && cycleDay['pain'] && Object.values(cycleDay['pain']).some(x => x === true) + acc.pain = cycleDay.pain && + Object.values(cycleDay.pain).some(x => x === true) } - acc[`${symptom}Exclude`] = cycleDay && cycleDay[symptom] && cycleDay[symptom].exclude + acc[`${symptom}Exclude`] = cycleDay[symptom] && cycleDay[symptom].exclude return acc }, {}) const temp = symptoms.temperature - const columnHeight = this.state.chartHeight * config.columnHeightPercentage - return { - dateString, - y: temp ? normalizeToScale(temp, columnHeight) : null, - ...symptoms, - ...getFhmAndLtlInfo(dateString, temp, columnHeight) + if (temp) { + column.y = normalizeToScale(temp, this.columnHeight) } + + const fhmAndLtl = getFhmAndLtlInfo(dateString, temp, this.columnHeight) + return Object.assign(column, symptoms, fhmAndLtl) }) return columns.map((col, i) => { @@ -116,12 +137,6 @@ export default class CycleChart extends Component { } render() { - let columnHeight - let symptomRowHeight - if (this.state.chartHeight) { - columnHeight = this.state.chartHeight * config.columnHeightPercentage - symptomRowHeight = this.state.chartHeight * config.symptomRowHeightPercentage - } return ( <View onLayout={this.onLayout} @@ -136,14 +151,16 @@ export default class CycleChart extends Component { {this.state.chartHeight && this.state.chartLoaded && <View style={[styles.yAxis, { - height: columnHeight, - marginTop: symptomRowHeight + height: this.columnHeight, + marginTop: this.symptomRowHeight }]} > - {makeYAxisLabels(columnHeight)} + {makeYAxisLabels(this.columnHeight)} </View>} - {this.state.chartHeight && this.state.chartLoaded && makeHorizontalGrid(columnHeight, symptomRowHeight)} + {this.state.chartHeight && this.state.chartLoaded && + makeHorizontalGrid(this.columnHeight, this.symptomRowHeight) + } {this.state.chartHeight && <FlatList diff --git a/components/chart/day-column.js b/components/chart/day-column.js index 0e64d88e4d9e2c6d9ffae2b901cf8e472fc21c29..f2ed95b54bc2ff783e76b03fcd80ed55ad9ca0f9 100644 --- a/components/chart/day-column.js +++ b/components/chart/day-column.js @@ -37,12 +37,13 @@ export default class DayColumn extends Component { rightTemperatureExclude, leftY, leftTemperatureExclude, - chartHeight + columnHeight, + symptomHeight, + chartHeight, + symptomRowSymptoms, + xAxisHeight } = this.props - const columnHeight = chartHeight * config.columnHeightPercentage - const xAxisHeight = chartHeight * config.xAxisHeightPercentage - const symptomHeight = chartHeight * config.symptomRowHeightPercentage const columnElements = [] @@ -108,77 +109,102 @@ export default class DayColumn extends Component { </G> ) + const symptomIconViews = { + bleeding: ( + <SymptomIconView + value={this.props.bleeding} + symptomHeight={symptomHeight} + key='bleeding' + > + <Icon + name='drop' + size={12} + color={styles.bleedingIconShades[this.props.bleeding]} + /> + </SymptomIconView> + ), + mucus: ( + <SymptomIconView + value={this.props.mucus} + symptomHeight={symptomHeight} + key='mucus' + > + <View + {...styles.mucusIcon} + backgroundColor={styles.mucusIconShades[this.props.mucus]} + /> + </SymptomIconView> + ), + cervix: ( + <SymptomIconView + value={this.props.cervix} + symptomHeight={symptomHeight} + key='cervix' + > + <View + {...styles.mucusIcon} + // cervix is sum of openess and firmness - fertile only when closed and hard (=0) + backgroundColor={this.props.cervix > 0 ? 'blue' : 'green'} + /> + </SymptomIconView> + ), + sex: ( + <SymptomIconView + value={this.props.sex} + symptomHeight={symptomHeight} + key='sex' + > + <View + {...styles.mucusIcon} + backgroundColor='orange' + /> + </SymptomIconView> + ), + desire: ( + <SymptomIconView + value={this.props.desire} + symptomHeight={symptomHeight} + key='desire' + > + <View + {...styles.mucusIcon} + backgroundColor='red' + /> + </SymptomIconView> + ), + pain: ( + <SymptomIconView + value={this.props.pain} + symptomHeight={symptomHeight} + key='pain' + > + <View + {...styles.mucusIcon} + backgroundColor='blue' + /> + </SymptomIconView> + ), + note: ( + <SymptomIconView + value={this.props.note} + symptomHeight={symptomHeight} + key='note' + > + <View + {...styles.mucusIcon} + backgroundColor='green' + /> + </SymptomIconView> + ) + } + return ( <TouchableOpacity onPress={() => this.passDateToDayView(dateString)} activeOpacity={1} > - <View height={symptomHeight}> - <View style={styles.symptomRow}> - {typeof this.props.bleeding === 'number' && - <Icon - name='drop' - size={12} - color={styles.bleedingIconShades[this.props.bleeding]} - key='bleeding' - /> - } - </View> - <View style={styles.symptomRow}> - {typeof this.props.mucus === 'number' && - <View - {...styles.mucusIcon} - backgroundColor={styles.mucusIconShades[this.props.mucus]} - key='mucus' - /> - } - </View> - <View style={styles.symptomRow}> - {typeof this.props.cervix === 'number' && - <View - {...styles.mucusIcon} - // cervix is sum of openess and firmness - fertile only when closed and hard (=0) - backgroundColor={this.props.cervix > 0 ? 'blue' : 'green'} - key='cervix' - /> - } - </View> - <View style={styles.symptomRow}> - {typeof this.props.sex === 'number' && - <View - {...styles.mucusIcon} - backgroundColor='orange' - key='sex' - /> - } - </View> - <View style={styles.symptomRow}> - {typeof this.props.desire === 'number' && - <View - {...styles.mucusIcon} - backgroundColor='red' - key='desire' - /> - } - </View> - <View style={styles.symptomRow}> - {this.props.pain && - <View - {...styles.mucusIcon} - backgroundColor='blue' - key='pain' - /> - } - </View> - <View style={styles.symptomRow}> - {this.props.note && - <View - {...styles.mucusIcon} - backgroundColor='green' - key='note' - /> - } - </View> + <View> + {symptomRowSymptoms.map(symptomName => symptomIconViews[symptomName])} </View> <Svg width={config.columnWidth} height={columnHeight}> @@ -193,3 +219,16 @@ export default class DayColumn extends Component { ) } } + + +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> + ) +} + diff --git a/components/chart/styles.js b/components/chart/styles.js index 318fd54b4b577e1dc375a32ec32f4a175bd6e981..8441f9b2db7ea78de4d4a00cb9fc8164982cb8cb 100644 --- a/components/chart/styles.js +++ b/components/chart/styles.js @@ -95,8 +95,6 @@ const styles = { symptomRow: { alignItems: 'center', justifyContent: 'center', - width: '100%', - flex: 1 } } diff --git a/config.js b/config.js index 7cea4e1f1f616630c88582682c8c5dd82cd11ae8..d0c471ea618572d76c991926af5bc7b465267688 100644 --- a/config.js +++ b/config.js @@ -1,8 +1,7 @@ const config = { columnWidth: 25, - columnHeightPercentage: 0.62, xAxisHeightPercentage: 0.08, - symptomRowHeightPercentage: 0.30, + symptomHeightPercentage: 0.05, temperatureScale: { defaultLow: 35, defaultHigh: 38,