Skip to content
Snippets Groups Projects
temperature.js 6.06 KiB
Newer Older
import React from 'react'
  Switch,
  Alert,
  ScrollView
import DateTimePicker from 'react-native-modal-datetime-picker-nevo'
import padWithZeros from '../../helpers/pad-time-with-zeros'
import { getPreviousTemperature } from '../../../db'
import styles from '../../../styles'
import { LocalTime, ChronoUnit } from 'js-joda'
import { temperature as labels } from '../../../i18n/en/cycle-day'
import { scaleObservable } from '../../../local-storage'
import { shared as sharedLabels } from '../../../i18n/en/labels'
import config from '../../../config'
import AppTextInput from '../../app-text-input'
import AppText from '../../app-text'
import SymptomSection from './symptom-section'
import SymptomView from './symptom-view'
const minutes = ChronoUnit.MINUTES
export default class Temp extends SymptomView {
  constructor(props) {
    super(props)
    const cycleDay = props.cycleDay
    this.temperature = cycleDay && cycleDay.temperature
    const temp = this.temperature
    this.state = {
      exclude: temp ? temp.exclude : false,
      time: temp ? temp.time : LocalTime.now().truncatedTo(minutes).toString(),
      isTimePickerVisible: false,
tina's avatar
tina committed
      outOfRange: null,
      note: temp ? temp.note : null
Julia Friesel's avatar
Julia Friesel committed
      this.state.temperature = temp.value.toString()
      if (temp.value === Math.floor(temp.value)) {
        this.state.temperature = `${this.state.temperature}.0`
      }
      const prevTemp = getPreviousTemperature(props.date)
        this.state.suggestedTemperature = prevTemp.toString()
        this.state.isSuggestion = true
  symptomName = 'temperature'

  isDeleteIconActive() {
    return ['temperature', 'note', 'exclude'].some(key => {
    // the time is always and the suggested temp sometimes prefilled, so they're not relevant for setting
    // the delete button active.
      return this.state[key] || this.state[key] === 0
    })
  }

  autoSave = () => {
    if (typeof this.state.temperature != 'string' || this.state.temperature === '') {
      this.deleteSymptomEntry()
      return
    }

    const dataToSave = {
      value: Number(this.state.temperature),
      exclude: this.state.exclude,
tina's avatar
tina committed
      time: this.state.time,
      note: this.state.note

    this.saveSymptomEntry(dataToSave)
  warnUserIfTempOutOfRange = async () => {
    const value = Number(this.state.temperature)
    const { min, max } = config.temperatureScale
    const range = { min, max }
    const scale = scaleObservable.value
    let warningMsg

    if (value < range.min || value > range.max) {
      warningMsg = labels.outOfAbsoluteRangeWarning
    } else if (value < scale.min || value > scale.max) {
      warningMsg = labels.outOfRangeWarning
    // RN alert runs asynchronously but doesn't provide a callback, so wrap
    // it in a promise
    return new Promise(resolve => {
      if (warningMsg) {
        // we set this so the time picker doesn't open at the same time
        this.warningAlertOpen = true
        Alert.alert(
          sharedLabels.warning,
          warningMsg,
          [
            { text: sharedLabels.ok, onPress: () => {
              this.warningAlertOpen = false
  }

  setTemperature = (temperature) => {
    if (isNaN(Number(temperature))) return
    this.setState({ temperature, isSuggestion: false })
  }
  setNote = (note) => {
    this.setState({ note })
  showTimePicker = () => {
    Keyboard.dismiss()
    this.setState({ isTimePickerVisible: true })
  }
    const inputStyle = [styles.temperatureTextInput]
    if (this.state.isSuggestion) {
      inputStyle.push(styles.temperatureTextInputSuggestion)
    }
Julia Friesel's avatar
Julia Friesel committed
      <ScrollView style={styles.page}>
        <SymptomSection
          header={labels.temperature.header}
          explainer={labels.temperature.explainer}
        >
          <View style={styles.framedSegmentInlineChildren}>
            <AppTextInput
Julia Friesel's avatar
Julia Friesel committed
              style={[inputStyle]}
              autoFocus={true}
              value={this.state.temperature || this.state.suggestedTemperature}
Julia Friesel's avatar
Julia Friesel committed
              onChangeText={this.setTemperature}
              keyboardType='numeric'
              maxLength={5}
              onBlur={this.warnUserIfTempOutOfRange}
Julia Friesel's avatar
Julia Friesel committed
            <AppText style={{ marginLeft: 5 }}>°C</AppText>
          </View>
        </SymptomSection>
        <SymptomSection
          header={labels.time}
        >
          <View style={styles.framedSegmentInlineChildren}>
            <AppTextInput
              style={[styles.temperatureTextInput]}
              onFocus={() => {
                if (this.warningAlertOpen) {
                  Keyboard.dismiss()
                } else {
                  this.showTimePicker()
                }
              }}
Julia Friesel's avatar
Julia Friesel committed
              value={this.state.time}
            />
            <DateTimePicker
              mode="time"
              isVisible={this.state.isTimePickerVisible}
              onConfirm={jsDate => {
                this.setState({
                  time: padWithZeros(jsDate),
                  isTimePickerVisible: false
                })
Julia Friesel's avatar
Julia Friesel committed
              onCancel={() => this.setState({ isTimePickerVisible: false })}
Julia Friesel's avatar
Julia Friesel committed
          </View>
        </SymptomSection>
        <SymptomSection
          header={labels.note.header}
          explainer={labels.note.explainer}
        >
          <AppTextInput
            multiline={true}
            autoFocus={this.state.focusTextArea}
            placeholder={sharedLabels.enter}
            value={this.state.note}
            onChangeText={this.setNote}
          />
        </SymptomSection>
        <SymptomSection
          header={labels.exclude.header}
          explainer={labels.exclude.explainer}
          inline={true}
        >
          <Switch
            onValueChange={(val) => {
              this.setState({ exclude: val })
            }}
            value={this.state.exclude}
          />
        </SymptomSection>
      </ScrollView>