diff --git a/.eslintrc b/.eslintrc index fb7b984..028ba73 100644 --- a/.eslintrc +++ b/.eslintrc @@ -49,6 +49,13 @@ "prefer-const": "error", "no-trailing-spaces": "error", "react/prop-types": 0, - "max-len": [1, {"ignoreStrings": true}] + "max-len": [ + 1, + { + "ignoreStrings": true, + "ignoreComments": true, + "ignoreTemplateLiterals": true + } + ] } } \ No newline at end of file diff --git a/components/chart/chart.js b/components/chart/chart.js index 09bcf44..d8a9713 100644 --- a/components/chart/chart.js +++ b/components/chart/chart.js @@ -1,9 +1,9 @@ import React, { Component } from 'react' -import { View, FlatList, ScrollView } from 'react-native' +import { View, FlatList, Text } from 'react-native' import range from 'date-range' import { LocalDate } from 'js-joda' import { makeYAxisLabels, normalizeToScale, makeHorizontalGrid } from './y-axis' -import setUpFertilityStatusFunc from './nfp-lines' +import nfpLines from './nfp-lines' import DayColumn from './day-column' import { getCycleDay, cycleDaysSortedByDate, getAmountOfCycleDays } from '../../db' import styles from './styles' @@ -12,24 +12,27 @@ import { scaleObservable } from '../../local-storage' export default class CycleChart extends Component { constructor(props) { super(props) - this.state = { - columns: makeColumnInfo(setUpFertilityStatusFunc()), - } + this.state = {} this.renderColumn = ({item, index}) => { return ( ) } + } - this.reCalculateChartInfo = (function(Chart) { - return function() { - Chart.setState({columns: makeColumnInfo(setUpFertilityStatusFunc())}) - } - })(this) + onLayout = ({ nativeEvent }) => { + if (this.state.chartHeight) return + + const height = nativeEvent.layout.height + this.setState({ chartHeight: height }) + this.reCalculateChartInfo = () => { + this.setState({ columns: this.makeColumnInfo(nfpLines(height)) }) + } cycleDaysSortedByDate.addListener(this.reCalculateChartInfo) this.removeObvListener = scaleObservable(this.reCalculateChartInfo, false) @@ -40,13 +43,65 @@ export default class CycleChart extends Component { this.removeObvListener() } + makeColumnInfo(getFhmAndLtlInfo) { + 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 jsDates = getTodayAndPreviousDays(amountOfCycleDays) + const xAxisDates = jsDates.map(jsDate => { + return LocalDate.of( + jsDate.getFullYear(), + jsDate.getMonth() + 1, + jsDate.getDate() + ).toString() + }) + + const columns = xAxisDates.map(dateString => { + const cycleDay = getCycleDay(dateString) + const symptoms = ['temperature', 'mucus', 'bleeding'].reduce((acc, symptom) => { + acc[symptom] = cycleDay && cycleDay[symptom] && cycleDay[symptom].value + acc[`${symptom}Exclude`] = cycleDay && cycleDay[symptom] && cycleDay[symptom].exclude + return acc + }, {}) + + const temp = symptoms.temperature + return { + dateString, + y: temp ? normalizeToScale(temp, this.state.chartHeight) : null, + ...symptoms, + ...getFhmAndLtlInfo(dateString, temp) + } + }) + + return columns.map((col, i) => { + const info = getInfoForNeighborColumns(i, columns) + return Object.assign(col, info) + }) + } + render() { return ( - - - {makeYAxisLabels()} - {makeHorizontalGrid()} - { + {!this.state.chartHeight && Loading...} + {this.state.chartHeight && + + {makeYAxisLabels(this.state.chartHeight)} + } + + {this.state.chartHeight && makeHorizontalGrid(this.state.chartHeight)} + + {this.state.chartHeight && + - } - - + + } + ) } } -function makeColumnInfo(getFhmAndLtlInfo) { - 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 xAxisDates = getTodayAndPreviousDays(amountOfCycleDays).map(jsDate => { - return LocalDate.of( - jsDate.getFullYear(), - jsDate.getMonth() + 1, - jsDate.getDate() - ).toString() - }) - - const columns = xAxisDates.map(dateString => { - const cycleDay = getCycleDay(dateString) - const symptoms = ['temperature', 'mucus', 'bleeding'].reduce((acc, symptom) => { - acc[symptom] = cycleDay && cycleDay[symptom] && cycleDay[symptom].value - acc[`${symptom}Exclude`] = cycleDay && cycleDay[symptom] && cycleDay[symptom].exclude - return acc - }, {}) - - return { - dateString, - y: symptoms.temperature ? normalizeToScale(symptoms.temperature) : null, - ...symptoms, - ...getFhmAndLtlInfo(dateString, symptoms.temperature) - } - }) - - return columns.map((col, i) => { - const info = getInfoForNeighborColumns(i, columns) - return Object.assign(col, info) - }) -} function getTodayAndPreviousDays(n) { const today = new Date() diff --git a/components/chart/day-column.js b/components/chart/day-column.js index 1b61a7a..b6bf2d5 100644 --- a/components/chart/day-column.js +++ b/components/chart/day-column.js @@ -105,25 +105,22 @@ export default class DayColumn extends Component { const cycleDayNumber = getCycleDayNumber(dateString) const shortDate = dateString.split('-').slice(1).join('-') const cycleDayLabel = ( - + {cycleDayNumber} ) const dateLabel = ( - + {shortDate} ) - columnElements.push( - - {cycleDayLabel} - {dateLabel} - - ) - return React.createElement( + const columnHeight = this.props.chartHeight * config.columnHeightPercentage + const xAxisHeight = this.props.chartHeight * config.xAxisHeightPercentage + + const column = React.createElement( TouchableOpacity, { - style: styles.column.rect, + style: [styles.column.rect, {height: columnHeight}], key: this.props.index.toString(), onPress: () => { this.passDateToDayView(dateString) @@ -132,5 +129,15 @@ export default class DayColumn extends Component { }, columnElements ) + + return ( + + {column} + + {cycleDayLabel} + {dateLabel} + + + ) } } \ No newline at end of file diff --git a/components/chart/nfp-lines.js b/components/chart/nfp-lines.js index d9f4507..ded95e8 100644 --- a/components/chart/nfp-lines.js +++ b/components/chart/nfp-lines.js @@ -1,7 +1,7 @@ import { getCycleStatusForDay } from '../../lib/sympto-adapter' import { normalizeToScale } from './y-axis' -export default function () { +export default function (chartHeight) { const cycle = { status: null } @@ -71,7 +71,7 @@ export default function () { dateIsInPeriOrPostPhase(dateString) && isInTempMeasuringPhase(temperature, dateString) ) { - ret.drawLtlAt = normalizeToScale(tempShift.ltl) + ret.drawLtlAt = normalizeToScale(tempShift.ltl, chartHeight) } } diff --git a/components/chart/styles.js b/components/chart/styles.js index 8ee5a30..d60e1a0 100644 --- a/components/chart/styles.js +++ b/components/chart/styles.js @@ -38,10 +38,10 @@ const styles = { }, rect: { width: config.columnWidth, - height: config.chartHeight, borderStyle: 'solid', borderColor: 'grey', - borderWidth: 0.5 + borderLeftWidth: 0.5, + borderRightWidth: 0.5, } }, bleedingIcon: { @@ -63,7 +63,6 @@ const styles = { '#993299' ], yAxis: { - height: config.chartHeight, width: config.columnWidth, borderRightWidth: 0.5, borderColor: 'lightgrey', diff --git a/components/chart/y-axis.js b/components/chart/y-axis.js index 5b78b36..e65449b 100644 --- a/components/chart/y-axis.js +++ b/components/chart/y-axis.js @@ -4,19 +4,18 @@ import config from '../../config' import styles from './styles' import { scaleObservable } from '../../local-storage' -export function makeYAxisLabels() { +export function makeYAxisLabels(chartHeight) { const units = config.temperatureScale.units const scaleMax = scaleObservable.value.max + const style = styles.yAxisLabel - return getTickPositions().map((y, i) => { - const style = styles.yAxisLabel + return getTickPositions(chartHeight).map((y, i) => { // 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 return ( {scaleMax - i * units} @@ -24,8 +23,8 @@ export function makeYAxisLabels() { }) } -export function makeHorizontalGrid() { - return getTickPositions().map(tick => { +export function makeHorizontalGrid(chartHeight) { + return getTickPositions(chartHeight).map(tick => { return ( { const value = Number(this.props.value) - console.log(value) if (isNaN(value)) return const scale = scaleObservable.value if (value < scale.min || value > scale.max) { diff --git a/config.js b/config.js index d44ba54..ffb8f60 100644 --- a/config.js +++ b/config.js @@ -1,6 +1,7 @@ const config = { - chartHeight: 350, columnWidth: 25, + columnHeightPercentage: 0.92, + xAxisHeightPercentage: 0.08, temperatureScale: { defaultLow: 35, defaultHigh: 38, @@ -10,9 +11,6 @@ const config = { } } -const margin = 3 -config.columnMiddle = config.columnWidth / 2, -config.dateRowY = config.chartHeight - 15 - margin -config.cycleDayNumberRowY = config.chartHeight - margin +config.columnMiddle = config.columnWidth / 2 export default config \ No newline at end of file diff --git a/styles/index.js b/styles/index.js index 43a5599..406de7a 100644 --- a/styles/index.js +++ b/styles/index.js @@ -92,16 +92,17 @@ export default StyleSheet.create({ }, header: { backgroundColor: primaryColor, - paddingVertical: 18, paddingHorizontal: 15, alignItems: 'center', - justifyContent: 'center' + justifyContent: 'center', + height: '10%' }, menu: { backgroundColor: primaryColor, alignItems: 'center', justifyContent: 'space-between', - flexDirection: 'row' + flexDirection: 'row', + height: '12%' }, menuItem: { alignItems: 'center', @@ -116,7 +117,8 @@ export default StyleSheet.create({ }, headerCycleDay: { flexDirection: 'row', - justifyContent: 'space-between' + justifyContent: 'space-between', + height: '15%' }, navigationArrow: { fontSize: 60,