diff --git a/components/cycle-day/cycle-day-overview.js b/components/cycle-day/cycle-day-overview.js index 3fcfe64..932531b 100644 --- a/components/cycle-day/cycle-day-overview.js +++ b/components/cycle-day/cycle-day-overview.js @@ -1,87 +1,61 @@ -import React, { Component } from 'react' +import React, { useState } from 'react' import { StyleSheet, View } from 'react-native' import PropTypes from 'prop-types' -import { LocalDate } from 'js-joda' import AppPage from '../common/app-page' import SymptomBox from './symptom-box' import SymptomPageTitle from './symptom-page-title' import { connect } from 'react-redux' -import { getDate, setDate } from '../../slices/date' -import { navigate } from '../../slices/navigation' +import { getDate } from '../../slices/date' import cycleModule from '../../lib/cycle' import { dateToTitle } from '../helpers/format-date' import { getCycleDay } from '../../db' import { getData } from '../helpers/cycle-day' -import { general as labels} from '../../i18n/en/cycle-day' +import { general as labels } from '../../i18n/en/cycle-day' import { Spacing } from '../../styles' import { SYMPTOMS } from '../../config' -class CycleDayOverView extends Component { +const CycleDayOverView = ({ date, isTemperatureEditView }) => { + const cycleDay = getCycleDay(date) - static propTypes = { - navigate: PropTypes.func, - setDate: PropTypes.func, - cycleDay: PropTypes.object, - date: PropTypes.string, - isTemperatureEditView: PropTypes.bool, - } + const { getCycleDayNumber } = cycleModule() + const cycleDayNumber = getCycleDayNumber(date) + const subtitle = cycleDayNumber && `${labels.cycleDayNumber}${cycleDayNumber}` + const [editedSymptom, setEditedSymptom] = useState( + isTemperatureEditView ? 'temperature' : '' + ) - constructor(props) { - super(props) + return ( + + + + {SYMPTOMS.map((symptom) => { + const symptomData = + cycleDay && cycleDay[symptom] ? cycleDay[symptom] : null - this.state = { cycleDay: getCycleDay(props.date), data: null } - if (props.isTemperatureEditView) { - const todayDateString = LocalDate.now().toString() - props.setDate(todayDateString) - } - } + return ( + + ) + })} + + + ) +} - updateCycleDay = (date) => { - this.props.setDate(date) - this.setState({ cycleDay: getCycleDay(date) }) - } - - render() { - const { cycleDay } = this.state - const { date, isTemperatureEditView } = this.props - - const { getCycleDayNumber } = cycleModule() - const cycleDayNumber = getCycleDayNumber(date) - const subtitle = cycleDayNumber && `${labels.cycleDayNumber}${cycleDayNumber}` - - return ( - - - - {SYMPTOMS.map(symptom => { - const symptomData = cycleDay && cycleDay[symptom] - ? cycleDay[symptom] : null - - const isSymptomEdited = isTemperatureEditView && symptom === 'temperature' - - return( - - ) - })} - - - ) - } +CycleDayOverView.propTypes = { + cycleDay: PropTypes.object, + date: PropTypes.string, + isTemperatureEditView: PropTypes.bool, } const styles = StyleSheet.create({ @@ -89,24 +63,14 @@ const styles = StyleSheet.create({ flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'space-between', - padding: Spacing.base - } + padding: Spacing.base, + }, }) const mapStateToProps = (state) => { - return({ + return { date: getDate(state), - }) + } } -const mapDispatchToProps = (dispatch) => { - return({ - setDate: (date) => dispatch(setDate(date)), - navigate: (page) => dispatch(navigate(page)), - }) -} - -export default connect( - mapStateToProps, - mapDispatchToProps, -)(CycleDayOverView) +export default connect(mapStateToProps, null)(CycleDayOverView) diff --git a/components/cycle-day/symptom-box.js b/components/cycle-day/symptom-box.js index 294a176..837c89b 100644 --- a/components/cycle-day/symptom-box.js +++ b/components/cycle-day/symptom-box.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react' +import React from 'react' import PropTypes from 'prop-types' import { StyleSheet, View, TouchableOpacity } from 'react-native' import { scale } from 'react-native-size-matters' @@ -14,94 +14,75 @@ import { isDateInFuture } from '../helpers/cycle-day' import { Colors, Sizes, Spacing } from '../../styles' import { headerTitles as symptomTitles } from '../../i18n/en/labels' -class SymptomBox extends Component { - static propTypes = { - date: PropTypes.string.isRequired, - isSymptomEdited: PropTypes.bool, - symptom: PropTypes.string.isRequired, - symptomData: PropTypes.object, - symptomDataToDisplay: PropTypes.string, - updateCycleDayData: PropTypes.func.isRequired, - } +const SymptomBox = ({ + date, + symptom, + symptomData, + symptomDataToDisplay, + editedSymptom, + setEditedSymptom, +}) => { + const isSymptomEdited = editedSymptom === symptom + const isSymptomDisabled = isDateInFuture(date) && symptom !== 'note' + const isExcluded = symptomData !== null ? symptomData.exclude : false - static defaultProps = { - isSymptomEdited: false, - } + const iconColor = isSymptomDisabled ? Colors.greyLight : Colors.grey + const iconName = `drip-icon-${symptom}` + const symptomNameStyle = [ + styles.symptomName, + isSymptomDisabled && styles.symptomNameDisabled, + isExcluded && styles.symptomNameExcluded, + ] + const textStyle = [ + styles.text, + isSymptomDisabled && styles.textDisabled, + isExcluded && styles.textExcluded, + ] - constructor(props) { - super(props) + return ( + <> + {isSymptomEdited && ( + setEditedSymptom('')} + /> + )} - this.state = { - isSymptomEdited: props.isSymptomEdited, - } - } - - onFinishEditing = () => { - const { date, updateCycleDayData } = this.props - - updateCycleDayData(date) - this.setState({ isSymptomEdited: false }) - } - - onEditSymptom = () => { - this.setState({ isSymptomEdited: true }) - } - - render() { - const { date, symptom, symptomData, symptomDataToDisplay } = this.props - const { isSymptomEdited } = this.state - const isSymptomDisabled = isDateInFuture(date) && symptom !== 'note' - const isExcluded = symptomData !== null ? symptomData.exclude : false - - const iconColor = isSymptomDisabled ? Colors.greyLight : Colors.grey - const iconName = `drip-icon-${symptom}` - const symptomNameStyle = [ - styles.symptomName, - isSymptomDisabled && styles.symptomNameDisabled, - isExcluded && styles.symptomNameExcluded, - ] - const textStyle = [ - styles.text, - isSymptomDisabled && styles.textDisabled, - isExcluded && styles.textExcluded, - ] - - return ( - - {isSymptomEdited && ( - - )} - - - - - - {symptomTitles[symptom].toLowerCase()} + setEditedSymptom(symptom)} + style={styles.container} + testID={iconName} + > + + + + {symptomTitles[symptom].toLowerCase()} + + {symptomDataToDisplay && ( + + {symptomDataToDisplay} - {symptomDataToDisplay && ( - - {symptomDataToDisplay} - - )} - - - - ) - } + )} + + + + ) +} + +SymptomBox.propTypes = { + date: PropTypes.string.isRequired, + symptom: PropTypes.string.isRequired, + symptomData: PropTypes.object, + symptomDataToDisplay: PropTypes.string, + editedSymptom: PropTypes.string.isRequired, + setEditedSymptom: PropTypes.func.isRequired, } const styles = StyleSheet.create({ diff --git a/components/cycle-day/symptom-page-title.js b/components/cycle-day/symptom-page-title.js index 41885ee..62dbc46 100644 --- a/components/cycle-day/symptom-page-title.js +++ b/components/cycle-day/symptom-page-title.js @@ -12,33 +12,25 @@ import { nextDate, prevDate } from '../helpers/cycle-day' import { Colors, Containers, Spacing, Typography } from '../../styles' import { HIT_SLOP } from '../../config' -const SymptomPageTitle = ({ - date, - reloadSymptomData, - setDate, - subtitle, - title, -}) => { +const SymptomPageTitle = ({ date, setDate, subtitle, title }) => { const navigate = (isForward) => { - const nextDay = isForward ? nextDate(date) : prevDate(date) - reloadSymptomData(nextDay) - setDate(nextDay) + const newDate = isForward ? nextDate(date) : prevDate(date) + setDate(newDate) } - const formattedTitle = title.length > 21 - ? title.substring(0, 18) + '...' - : title + const formattedTitle = + title.length > 21 ? title.substring(0, 18) + '...' : title return ( navigate(false)} hitSlop={HIT_SLOP}> - + {formattedTitle} {subtitle && {subtitle}} navigate(true)} hitSlop={HIT_SLOP}> - + ) @@ -46,7 +38,6 @@ const SymptomPageTitle = ({ SymptomPageTitle.propTypes = { date: PropTypes.string.isRequired, - reloadSymptomData: PropTypes.func.isRequired, setDate: PropTypes.func.isRequired, subtitle: PropTypes.string, title: PropTypes.string, diff --git a/lib/notifications.js b/lib/notifications.js index af762dc..b0334ea 100644 --- a/lib/notifications.js +++ b/lib/notifications.js @@ -1,25 +1,34 @@ -import {tempReminderObservable, periodReminderObservable} from '../local-storage' +import { + tempReminderObservable, + periodReminderObservable, +} from '../local-storage' import Notification from 'react-native-push-notification' import Moment from 'moment' +import { LocalDate } from 'js-joda' + import labels from '../i18n/en/settings' import { getBleedingDaysSortedByDate } from '../db' import cycleModule from './cycle' import nothingChanged from '../db/db-unchanged' +import store from '../store' +import { setDate } from '../slices/date' export default function setupNotifications(navigate) { Notification.configure({ onNotification: (notification) => { // https://github.com/zo0r/react-native-push-notification/issues/966#issuecomment-479069106 if (notification.data?.id === '1' || notification.id === '1') { + const todayDate = LocalDate.now().toString() + store.dispatch(setDate(todayDate)) navigate('TemperatureEditView') } else { navigate('Home') } - } + }, }) - tempReminderObservable(reminder => { - Notification.cancelLocalNotifications({id: '1'}) + tempReminderObservable((reminder) => { + Notification.cancelLocalNotifications({ id: '1' }) if (reminder.enabled) { const [hours, minutes] = reminder.time.split(':') let target = new Moment() @@ -27,7 +36,7 @@ export default function setupNotifications(navigate) { .minutes(parseInt(minutes)) .seconds(0) - if(target.isBefore(new Moment())) { + if (target.isBefore(new Moment())) { target = target.add(1, 'd') } @@ -37,29 +46,31 @@ export default function setupNotifications(navigate) { message: labels.tempReminder.notification, date: target.toDate(), vibrate: false, - repeatType: 'day' + repeatType: 'day', }) } }, false) - periodReminderObservable(reminder => { - Notification.cancelLocalNotifications({id: '2'}) + periodReminderObservable((reminder) => { + Notification.cancelLocalNotifications({ id: '2' }) if (reminder.enabled) setupPeriodReminder() }, false) getBleedingDaysSortedByDate().addListener((_, changes) => { // the listener fires on setup, so we check if there were actually any changes if (nothingChanged(changes)) return - Notification.cancelLocalNotifications({id: '2'}) + Notification.cancelLocalNotifications({ id: '2' }) if (periodReminderObservable.value.enabled) setupPeriodReminder() }) - } function setupPeriodReminder() { const bleedingPrediction = cycleModule().getPredictedMenses() if (bleedingPrediction.length > 0) { - const predictedBleedingStart = Moment(bleedingPrediction[0][0], "YYYY-MM-DD") + const predictedBleedingStart = Moment( + bleedingPrediction[0][0], + 'YYYY-MM-DD' + ) // 3 days before and at 6 am const reminderDate = predictedBleedingStart .subtract(3, 'days') @@ -68,7 +79,7 @@ function setupPeriodReminder() { .seconds(0) if (reminderDate.isAfter()) { - // period is likely to start in 3 to 3 + (length of prediction - 1) days + // period is likely to start in 3 to 3 + (length of prediction - 1) days const daysToEndOfPrediction = bleedingPrediction[0].length + 2 Notification.localNotificationSchedule({ @@ -76,7 +87,7 @@ function setupPeriodReminder() { userInfo: { id: '2' }, message: labels.periodReminder.notification(daysToEndOfPrediction), date: reminderDate.toDate(), - vibrate: false + vibrate: false, }) } }