diff --git a/components/chart/chart.js b/components/chart/chart.js
index 9d16920..6b07629 100644
--- a/components/chart/chart.js
+++ b/components/chart/chart.js
@@ -1,32 +1,20 @@
-import React, { Component } from 'react'
+import React, { useEffect, useState } from 'react'
import PropTypes from 'prop-types'
-import {
- ActivityIndicator,
- Dimensions,
- FlatList,
- PixelRatio,
- StyleSheet,
- View,
-} from 'react-native'
+import { Dimensions, PixelRatio, StyleSheet, View } from 'react-native'
-import AppLoadingView from '../common/app-loading'
import AppPage from '../common/app-page'
-import AppText from '../common/app-text'
import DayColumn from './day-column'
import HorizontalGrid from './horizontal-grid'
+import MainGrid from './main-grid'
import NoData from './no-data'
+import NoTemperature from './no-temperature'
import Tutorial from './tutorial'
import YAxis from './y-axis'
import { getCycleDaysSortedByDate } from '../../db'
-import nothingChanged from '../../db/db-unchanged'
-import {
- getChartFlag,
- scaleObservable,
- setChartFlag,
-} from '../../local-storage'
-import { makeColumnInfo, nfpLines } from '../helpers/chart'
+import { getChartFlag, setChartFlag } from '../../local-storage'
+import { makeColumnInfo } from '../helpers/chart'
import {
CHART_COLUMN_WIDTH,
@@ -35,204 +23,108 @@ import {
CHART_XAXIS_HEIGHT_RATIO,
SYMPTOMS,
} from '../../config'
-import { shared } from '../../i18n/en/labels'
-import { Colors, Spacing } from '../../styles'
+import { Spacing } from '../../styles'
-class CycleChart extends Component {
- static propTypes = {
- navigate: PropTypes.func,
- end: PropTypes.bool,
- setDate: PropTypes.func,
- }
+const getSymptomsFromCycleDays = (cycleDays) =>
+ SYMPTOMS.filter((symptom) => cycleDays.some((cycleDay) => cycleDay[symptom]))
- constructor(props) {
- super(props)
+const CycleChart = ({ navigate, setDate }) => {
+ const [shouldShowHint, setShouldShowHint] = useState(true)
- this.state = {}
- this.cycleDaysSortedByDate = getCycleDaysSortedByDate()
- this.getFhmAndLtlInfo = nfpLines()
- this.shouldShowTemperatureColumn = false
-
- this.checkShouldShowHint()
- this.prepareSymptomData()
- }
-
- componentWillUnmount() {
- this.cycleDaysSortedByDate.removeListener(this.handleDbChange)
- this.removeObvListener()
- }
-
- checkShouldShowHint = async () => {
+ useEffect(async () => {
const flag = await getChartFlag()
- const shouldShowHint = flag === 'true' ? true : false
- this.setState({ shouldShowHint })
+ setShouldShowHint(flag === 'true')
+ }, [])
+
+ const hideHint = () => {
+ setShouldShowHint(false)
+ setChartFlag()
}
- setShouldShowHint = async () => {
- await setChartFlag()
- this.setState({ shouldShowHint: false })
- }
+ const cycleDaysSortedByDate = getCycleDaysSortedByDate()
- onLayout = () => {
- if (this.state.chartHeight) return false
+ const chartSymptoms = getSymptomsFromCycleDays(cycleDaysSortedByDate)
+ const symptomRowSymptoms = chartSymptoms.filter(
+ (symptom) => symptom !== 'temperature'
+ )
- this.reCalculateChartInfo()
- this.updateListeners(this.reCalculateChartInfo)
- }
+ const shouldShowTemperatureColumn = chartSymptoms.indexOf('temperature') > -1
- prepareSymptomData = () => {
- this.symptomRowSymptoms = SYMPTOMS.filter((symptomName) => {
- return this.cycleDaysSortedByDate.some((cycleDay) => {
- return symptomName !== 'temperature' && cycleDay[symptomName]
- })
- })
- this.chartSymptoms = [...this.symptomRowSymptoms]
- if (this.cycleDaysSortedByDate.some((day) => day.temperature)) {
- this.chartSymptoms.push('temperature')
- this.shouldShowTemperatureColumn = true
- }
- }
+ const { width, height } = Dimensions.get('window')
+ const numberOfColumnsToRender = Math.round(width / CHART_COLUMN_WIDTH)
- renderColumn = ({ item, index }) => {
+ const xAxisHeight = height * 0.7 * CHART_XAXIS_HEIGHT_RATIO
+ const remainingHeight = height * 0.7 - xAxisHeight
+ const symptomHeight = PixelRatio.roundToNearestPixel(
+ remainingHeight * CHART_SYMPTOM_HEIGHT_RATIO
+ )
+ const symptomRowHeight =
+ PixelRatio.roundToNearestPixel(symptomRowSymptoms.length * symptomHeight) +
+ CHART_GRID_LINE_HORIZONTAL_WIDTH
+ const columnHeight = remainingHeight - symptomRowHeight
+
+ const chartHeight = shouldShowTemperatureColumn
+ ? height * 0.7
+ : symptomRowHeight + xAxisHeight
+
+ const columns = makeColumnInfo()
+
+ const renderColumn = ({ item }) => {
return (
)
}
- reCalculateChartInfo = () => {
- const { width, height } = Dimensions.get('window')
+ const hasDataToDisplay = chartSymptoms.length > 0
- this.xAxisHeight = height * 0.7 * CHART_XAXIS_HEIGHT_RATIO
- const remainingHeight = height * 0.7 - this.xAxisHeight
- this.symptomHeight = PixelRatio.roundToNearestPixel(
- remainingHeight * CHART_SYMPTOM_HEIGHT_RATIO
- )
- this.symptomRowHeight =
- PixelRatio.roundToNearestPixel(
- this.symptomRowSymptoms.length * this.symptomHeight
- ) + CHART_GRID_LINE_HORIZONTAL_WIDTH
- this.columnHeight = remainingHeight - this.symptomRowHeight
- const chartHeight = this.shouldShowTemperatureColumn
- ? height * 0.7
- : this.symptomRowHeight + this.xAxisHeight
- const numberOfColumnsToRender = Math.round(width / CHART_COLUMN_WIDTH)
- const columns = makeColumnInfo()
-
- this.setState({ columns, chartHeight, numberOfColumnsToRender })
+ if (!hasDataToDisplay) {
+ return
}
- updateListeners(dataUpdateHandler) {
- // remove existing listeners
- if (this.handleDbChange) {
- this.cycleDaysSortedByDate.removeListener(this.handleDbChange)
- }
- if (this.removeObvListener) this.removeObvListener()
-
- this.handleDbChange = (_, changes) => {
- if (nothingChanged(changes)) return
- dataUpdateHandler()
- }
-
- this.cycleDaysSortedByDate.addListener(this.handleDbChange)
- this.removeObvListener = scaleObservable(dataUpdateHandler, false)
- }
-
- render() {
- const {
- chartHeight,
- chartLoaded,
- shouldShowHint,
- numberOfColumnsToRender,
- } = this.state
- const hasDataToDisplay = this.chartSymptoms.length > 0
-
- return (
-
- {!hasDataToDisplay && }
- {hasDataToDisplay && !chartHeight && !chartLoaded && }
-
- {shouldShowHint && chartLoaded && (
-
- )}
- {hasDataToDisplay &&
- chartLoaded &&
- !this.shouldShowTemperatureColumn && (
-
-
- {shared.noTemperatureWarning}
-
-
- )}
- {hasDataToDisplay && (
-
- {chartHeight && chartLoaded && (
-
- )}
-
- {chartHeight && (
- item}
- initialNumToRender={numberOfColumnsToRender}
- windowSize={30}
- onLayout={() => this.setState({ chartLoaded: true })}
- onEndReached={() => this.setState({ end: true })}
- ListFooterComponent={}
- updateCellsBatchingPeriod={800}
- contentContainerStyle={{ height: chartHeight }}
- />
- )}
- {chartHeight && chartLoaded && (
-
- {this.shouldShowTemperatureColumn && (
-
- )}
-
- )}
-
+ return (
+
+
+ {shouldShowHint && }
+ {!shouldShowTemperatureColumn && }
+
+
+
+ {shouldShowTemperatureColumn && (
+
)}
-
- )
- }
-}
-
-function LoadingMoreView({ end }) {
- return (
-
- {!end && }
-
+
+
)
}
-LoadingMoreView.propTypes = {
- end: PropTypes.bool,
+CycleChart.propTypes = {
+ navigate: PropTypes.func,
+ setDate: PropTypes.func,
}
const styles = StyleSheet.create({
@@ -242,20 +134,12 @@ const styles = StyleSheet.create({
chartContainer: {
flexDirection: 'column',
},
- loadingContainer: {
- height: '100%',
- backgroundColor: Colors.turquoiseLight,
- justifyContent: 'center',
- },
page: {
marginVertical: Spacing.small,
},
pageContainer: {
paddingHorizontal: Spacing.base,
},
- warning: {
- padding: Spacing.large,
- },
})
export default CycleChart
diff --git a/components/chart/day-column.js b/components/chart/day-column.js
index ac4ac55..7d9e0a0 100644
--- a/components/chart/day-column.js
+++ b/components/chart/day-column.js
@@ -12,13 +12,13 @@ import {
symptomColorMethods,
getTemperatureProps,
isSymptomDataComplete,
+ nfpLines,
} from '../helpers/chart'
const DayColumn = ({
dateString,
chartSymptoms,
columnHeight,
- getFhmAndLtlInfo,
setDate,
navigate,
shouldShowTemperatureColumn,
@@ -54,7 +54,7 @@ const DayColumn = ({
}, data)
}
- const fhmAndLtl = getFhmAndLtlInfo(
+ const fhmAndLtl = nfpLines()(
dateString,
data.temperature ? data.temperature.value : null,
columnHeight
@@ -104,7 +104,6 @@ DayColumn.propTypes = {
dateString: PropTypes.string.isRequired,
chartSymptoms: PropTypes.array,
columnHeight: PropTypes.number.isRequired,
- getFhmAndLtlInfo: PropTypes.func.isRequired,
navigate: PropTypes.func.isRequired,
setDate: PropTypes.func.isRequired,
shouldShowTemperatureColumn: PropTypes.bool,
diff --git a/components/chart/loading-more.js b/components/chart/loading-more.js
new file mode 100644
index 0000000..97df4db
--- /dev/null
+++ b/components/chart/loading-more.js
@@ -0,0 +1,27 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { ActivityIndicator, StyleSheet, View } from 'react-native'
+
+import { Colors } from '../../styles'
+
+function LoadingMoreView({ end }) {
+ return (
+
+ {!end && }
+
+ )
+}
+
+LoadingMoreView.propTypes = {
+ end: PropTypes.bool,
+}
+
+const styles = StyleSheet.create({
+ loadingContainer: {
+ height: '100%',
+ backgroundColor: Colors.turquoiseLight,
+ justifyContent: 'center',
+ },
+})
+
+export default LoadingMoreView
diff --git a/components/chart/main-grid.js b/components/chart/main-grid.js
new file mode 100644
index 0000000..bd65b1f
--- /dev/null
+++ b/components/chart/main-grid.js
@@ -0,0 +1,32 @@
+import React, { useState } from 'react'
+import PropTypes from 'prop-types'
+import { FlatList } from 'react-native'
+
+import LoadingMoreView from './loading-more'
+
+const MainGrid = (props) => {
+ const [endReached, setEndReached] = useState(false)
+ return (
+ item}
+ windowSize={30}
+ onEndReached={() => setEndReached(true)}
+ ListFooterComponent={}
+ updateCellsBatchingPeriod={800}
+ {...props}
+ />
+ )
+}
+
+MainGrid.propTypes = {
+ height: PropTypes.number,
+ data: PropTypes.array,
+ renderItem: PropTypes.func,
+ initialNumToRender: PropTypes.number,
+ contentContainerStyle: PropTypes.object,
+}
+
+export default MainGrid
diff --git a/components/chart/no-temperature.js b/components/chart/no-temperature.js
new file mode 100644
index 0000000..931b035
--- /dev/null
+++ b/components/chart/no-temperature.js
@@ -0,0 +1,19 @@
+import React from 'react'
+import { StyleSheet } from 'react-native'
+import AppText from '../common/app-text'
+
+import { shared } from '../../i18n/en/labels'
+
+import { Spacing } from '../../styles'
+
+function NoTemperature() {
+ return {shared.noTemperatureWarning}
+}
+
+const styles = StyleSheet.create({
+ warning: {
+ padding: Spacing.large,
+ },
+})
+
+export default NoTemperature