540 Refactor temperature to functional component

This commit is contained in:
Lisa Hillebrand
2022-04-15 18:04:20 +02:00
parent fe9d9b4fdc
commit 585017eadd
3 changed files with 145 additions and 184 deletions
+71 -102
View File
@@ -1,4 +1,4 @@
import React, { Component } from 'react'
import React, { useEffect, useState } from 'react'
import { Platform, StyleSheet, View } from 'react-native'
import PropTypes from 'prop-types'
import { Keyboard } from 'react-native'
@@ -12,129 +12,92 @@ import Segment from '../common/segment'
import { connect } from 'react-redux'
import { getDate } from '../../slices/date'
import {
isTemperatureOutOfRange,
getTemperatureOutOfRangeMessage,
getPreviousTemperature,
formatTemperature,
} from '../helpers/cycle-day'
import { temperature as labels } from '../../i18n/en/cycle-day'
import { Colors, Containers, Sizes, Spacing } from '../../styles'
const formatTemperature = (value) =>
value === null ? value : Number.parseFloat(value).toFixed(2)
const Temperature = ({ data, date, save }) => {
const [isTimePickerVisible, setIsTimePickerVisible] = useState(false)
const [temperature, setTemperature] = useState(
formatTemperature(data.value) || getPreviousTemperature(date)
)
class Temperature extends Component {
static propTypes = {
data: PropTypes.object,
date: PropTypes.string.isRequired,
save: PropTypes.func,
}
constructor(props) {
super(props)
const { data, date } = this.props
const { value } = data
const { shouldShowSuggestion, suggestedTemperature } =
getPreviousTemperature(date)
this.state = {
isTimePickerVisible: false,
shouldShowSuggestion,
suggestedTemperature: formatTemperature(suggestedTemperature),
value: formatTemperature(value),
// update state in parent component once to ensure
// that pre-filled values are saved on button click
useEffect(() => {
if (temperature) {
save(temperature, 'value')
}
}, [])
function onChangeTemperature(value) {
const formattedValue = value.replace(',', '.').trim()
if (!Number(formattedValue) && value !== '') return false
setTemperature(formattedValue)
}
onCancelTimePicker = () => {
this.setState({ isTimePickerVisible: false })
}
onChangeTemperature = (value) => {
if (!Number(value)) return false
this.setState({
value: value.trim(),
shouldShowSuggestion: false,
})
}
onShowTimePicker = () => {
function onShowTimePicker() {
Keyboard.dismiss()
this.setState({ isTimePickerVisible: true })
setIsTimePickerVisible(true)
}
setTemperature = () => {
const { value } = this.state
this.props.save(value, 'value')
}
setTime = (jsDate) => {
function setTime(jsDate) {
const time = moment(jsDate).format('HH:mm')
const isTimePickerVisible = false
this.props.save(time, 'time')
this.setState({ isTimePickerVisible })
save(time, 'time')
setIsTimePickerVisible(false)
}
render() {
const { shouldShowSuggestion, suggestedTemperature, value } = this.state
const { time } = this.props.data
const { time } = data
const inputStyle =
shouldShowSuggestion && value === null
? { color: Colors.grey }
: { color: Colors.greyDark }
const outOfRangeWarning = isTemperatureOutOfRange(value)
let temperatureToShow = null
const inputStyle = { color: Colors.greyDark }
const outOfRangeWarning = getTemperatureOutOfRangeMessage(temperature)
if (value) {
temperatureToShow = value
} else if (shouldShowSuggestion) {
temperatureToShow = suggestedTemperature
}
return (
<React.Fragment>
<Segment>
<AppText style={styles.title}>{labels.temperature.explainer}</AppText>
<View style={styles.container}>
<AppTextInput
value={temperatureToShow === null ? '' : temperatureToShow}
onChangeText={this.onChangeTemperature}
onEndEditing={this.setTemperature}
keyboardType="numeric"
maxLength={5}
style={inputStyle}
testID="temperatureInput"
underlineColorAndroid="transparent"
/>
<AppText>°C</AppText>
</View>
{outOfRangeWarning !== null && (
<View style={styles.hintContainer}>
<AppText style={styles.hint}>{outOfRangeWarning}</AppText>
</View>
)}
</Segment>
<Segment>
<AppText style={styles.title}>{labels.time}</AppText>
return (
<React.Fragment>
<Segment>
<AppText style={styles.title}>{labels.temperature.explainer}</AppText>
<View style={styles.container}>
<AppTextInput
onFocus={this.onShowTimePicker}
testID="timeInput"
value={time}
value={temperature}
onChangeText={onChangeTemperature}
onEndEditing={() => save(temperature, 'value')}
keyboardType="numeric"
maxLength={5}
style={inputStyle}
testID="temperatureInput"
underlineColorAndroid="transparent"
/>
<DateTimePicker
isVisible={this.state.isTimePickerVisible}
mode="time"
onConfirm={this.setTime}
onCancel={this.onCancelTimePicker}
display={Platform.OS === 'ios' ? 'spinner' : 'default'}
/>
</Segment>
</React.Fragment>
)
}
<AppText>°C</AppText>
</View>
{!!outOfRangeWarning && (
<View style={styles.hintContainer}>
<AppText style={styles.hint}>{outOfRangeWarning}</AppText>
</View>
)}
</Segment>
<Segment>
<AppText style={styles.title}>{labels.time}</AppText>
<AppTextInput
onFocus={onShowTimePicker}
testID="timeInput"
value={time}
/>
<DateTimePicker
isVisible={isTimePickerVisible}
mode="time"
onConfirm={setTime}
onCancel={() => setIsTimePickerVisible(false)}
display={Platform.OS === 'ios' ? 'spinner' : 'default'}
/>
</Segment>
</React.Fragment>
)
}
const styles = StyleSheet.create({
@@ -153,6 +116,12 @@ const styles = StyleSheet.create({
},
})
Temperature.propTypes = {
data: PropTypes.object.isRequired,
date: PropTypes.string.isRequired,
save: PropTypes.func.isRequired,
}
const mapStateToProps = (state) => {
return {
date: getDate(state),