Merge branch 'chore/refactor-customization' into '676-feature-customisation-not-display-mucus-cervix'
Chore/refactor customization See merge request bloodyhealth/drip!672
This commit is contained in:
@@ -1,18 +1,34 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { StyleSheet, TouchableOpacity, View } from 'react-native'
|
import { Alert, StyleSheet, TouchableOpacity, View } from 'react-native'
|
||||||
|
|
||||||
import AppText from '../common/app-text'
|
import AppText from '../common/app-text'
|
||||||
|
|
||||||
import { Colors, Containers } from '../../styles'
|
import { Colors, Containers } from '../../styles'
|
||||||
import labels from '../../i18n/en/settings'
|
import labels from '../../i18n/en/settings'
|
||||||
|
|
||||||
export default function SelectTabGroup({ activeButton, buttons, onSelect }) {
|
export default function SelectTabGroup({
|
||||||
// TODO https://gitlab.com/bloodyhealth/drip/-/issues/707
|
activeButton,
|
||||||
|
buttons,
|
||||||
|
onSelect,
|
||||||
|
disabled,
|
||||||
|
}) {
|
||||||
|
// TODO https://gitlab.com/bloodyhealth/drip/-/issues/707
|
||||||
const oneTimeTransformIntoNumber =
|
const oneTimeTransformIntoNumber =
|
||||||
typeof activeButton === 'boolean' && Number(activeButton)
|
typeof activeButton === 'boolean' && Number(activeButton)
|
||||||
const isSecondarySymptomSwitch =
|
const isSecondarySymptomSwitch =
|
||||||
buttons[0]['label'] === labels.secondarySymptom.mucus
|
buttons[0]['label'] === labels.secondarySymptom.mucus
|
||||||
|
|
||||||
|
// Disable is only used for secondarySymptom in customization, if more come up maybe consider more tidy solution
|
||||||
|
const showDisabledAlert = (label) => {
|
||||||
|
if (label === 'cervix' || label === 'mucus') {
|
||||||
|
Alert.alert(
|
||||||
|
labels.secondarySymptom.disabled.title,
|
||||||
|
labels.secondarySymptom.disabled.message
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
{buttons.map(({ label, value }, i) => {
|
{buttons.map(({ label, value }, i) => {
|
||||||
@@ -23,16 +39,20 @@ export default function SelectTabGroup({ activeButton, buttons, onSelect }) {
|
|||||||
isActive && styles.boxActive,
|
isActive && styles.boxActive,
|
||||||
isSecondarySymptomSwitch && styles.purpleBox,
|
isSecondarySymptomSwitch && styles.purpleBox,
|
||||||
isSecondarySymptomSwitch && isActive && styles.activePurpleBox,
|
isSecondarySymptomSwitch && isActive && styles.activePurpleBox,
|
||||||
|
disabled && styles.disabledBox,
|
||||||
]
|
]
|
||||||
const textStyle = [
|
const textStyle = [
|
||||||
styles.text,
|
styles.text,
|
||||||
isSecondarySymptomSwitch && styles.purpleText,
|
isSecondarySymptomSwitch && styles.purpleText,
|
||||||
isActive && styles.textActive,
|
isActive && styles.textActive,
|
||||||
|
disabled && styles.greyText,
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={() => onSelect(value)}
|
onPress={() =>
|
||||||
|
!disabled ? onSelect(value) : showDisabledAlert(label)
|
||||||
|
}
|
||||||
key={i}
|
key={i}
|
||||||
style={boxStyle}
|
style={boxStyle}
|
||||||
>
|
>
|
||||||
@@ -48,6 +68,7 @@ SelectTabGroup.propTypes = {
|
|||||||
activeButton: PropTypes.number,
|
activeButton: PropTypes.number,
|
||||||
buttons: PropTypes.array.isRequired,
|
buttons: PropTypes.array.isRequired,
|
||||||
onSelect: PropTypes.func.isRequired,
|
onSelect: PropTypes.func.isRequired,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
@@ -75,4 +96,11 @@ const styles = StyleSheet.create({
|
|||||||
purpleText: {
|
purpleText: {
|
||||||
color: Colors.purple,
|
color: Colors.purple,
|
||||||
},
|
},
|
||||||
|
greyText: {
|
||||||
|
color: Colors.grey,
|
||||||
|
},
|
||||||
|
disabledBox: {
|
||||||
|
borderColor: Colors.grey,
|
||||||
|
backgroundColor: Colors.turquoiseLight,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import {
|
|||||||
temperatureTrackingCategoryObservable,
|
temperatureTrackingCategoryObservable,
|
||||||
mucusTrackingCategoryObservable,
|
mucusTrackingCategoryObservable,
|
||||||
cervixTrackingCategoryObservable,
|
cervixTrackingCategoryObservable,
|
||||||
|
periodPredictionObservable,
|
||||||
|
useCervixAsSecondarySymptomObservable,
|
||||||
saveDesireTrackingCategory,
|
saveDesireTrackingCategory,
|
||||||
saveFertilityTrackingEnabled,
|
saveFertilityTrackingEnabled,
|
||||||
saveMoodTrackingCategory,
|
saveMoodTrackingCategory,
|
||||||
@@ -31,8 +33,6 @@ import {
|
|||||||
saveSexTrackingCategory,
|
saveSexTrackingCategory,
|
||||||
saveTemperatureTrackingCategory,
|
saveTemperatureTrackingCategory,
|
||||||
saveUseCervixAsSecondarySymptom,
|
saveUseCervixAsSecondarySymptom,
|
||||||
periodPredictionObservable,
|
|
||||||
useCervixAsSecondarySymptomObservable,
|
|
||||||
} from '../../../local-storage'
|
} from '../../../local-storage'
|
||||||
import labels from '../../../i18n/en/settings'
|
import labels from '../../../i18n/en/settings'
|
||||||
import { SYMPTOMS } from '../../../config'
|
import { SYMPTOMS } from '../../../config'
|
||||||
@@ -81,6 +81,7 @@ const Settings = () => {
|
|||||||
const [isFertilityTrackingEnabled, setFertilityTrackingEnabled] = useState(
|
const [isFertilityTrackingEnabled, setFertilityTrackingEnabled] = useState(
|
||||||
fertilityTrackingObservable.value
|
fertilityTrackingObservable.value
|
||||||
)
|
)
|
||||||
|
|
||||||
const fertilityTrackingToggle = (value) => {
|
const fertilityTrackingToggle = (value) => {
|
||||||
setFertilityTrackingEnabled(value)
|
setFertilityTrackingEnabled(value)
|
||||||
saveFertilityTrackingEnabled(value)
|
saveFertilityTrackingEnabled(value)
|
||||||
@@ -179,7 +180,14 @@ const Settings = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const secondarySymptomDisabledPrompt = () => {
|
const secondarySymptomDisabledPrompt = () => {
|
||||||
if (!isMucusTrackingCategoryEnabled == isCervixTrackingCategoryEnabled) {
|
if (!isFertilityTrackingEnabled) {
|
||||||
|
Alert.alert(
|
||||||
|
labels.secondarySymptom.disabled.title,
|
||||||
|
labels.secondarySymptom.disabled.message
|
||||||
|
)
|
||||||
|
} else if (
|
||||||
|
!isMucusTrackingCategoryEnabled == isCervixTrackingCategoryEnabled
|
||||||
|
) {
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
labels.secondarySymptom.disabled.title,
|
labels.secondarySymptom.disabled.title,
|
||||||
labels.secondarySymptom.disabled.noSecondaryEnabled
|
labels.secondarySymptom.disabled.noSecondaryEnabled
|
||||||
@@ -187,13 +195,26 @@ const Settings = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const manageFertilityFeature =
|
||||||
|
isTemperatureTrackingCategoryEnabled &&
|
||||||
|
(isMucusTrackingCategoryEnabled || isCervixTrackingCategoryEnabled)
|
||||||
|
|
||||||
const cervixText = useCervixAsSecondarySymptom
|
const cervixText = useCervixAsSecondarySymptom
|
||||||
? labels.secondarySymptom.cervixModeOn
|
? labels.secondarySymptom.cervixModeOn
|
||||||
: labels.secondarySymptom.cervixModeOff
|
: labels.secondarySymptom.cervixModeOff
|
||||||
|
|
||||||
const sliderDisabledPrompt = () => {
|
const sliderDisabledPrompt = () => {
|
||||||
if (!isTemperatureTrackingCategoryEnabled) {
|
if (!isTemperatureTrackingCategoryEnabled) {
|
||||||
Alert.alert(labels.disabled.title, labels.disabled.message)
|
Alert.alert(labels.tempScale.disabled, labels.tempScale.disabledMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fertilityDisabledPrompt = () => {
|
||||||
|
if (!manageFertilityFeature) {
|
||||||
|
Alert.alert(
|
||||||
|
labels.fertilityTracking.disabledTitle,
|
||||||
|
labels.fertilityTracking.disabled
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,53 +274,34 @@ const Settings = () => {
|
|||||||
symptom={SYMPTOMS[8]}
|
symptom={SYMPTOMS[8]}
|
||||||
/>
|
/>
|
||||||
</Segment>
|
</Segment>
|
||||||
<Pressable onPress={sliderDisabledPrompt}>
|
<Pressable onPress={fertilityDisabledPrompt}>
|
||||||
<Segment title={labels.fertilityTracking.title}>
|
<Segment title={labels.fertilityTracking.title}>
|
||||||
{isTemperatureTrackingCategoryEnabled &&
|
<AppText>{labels.fertilityTracking.message}</AppText>
|
||||||
(isMucusTrackingCategoryEnabled ||
|
<AppSwitch
|
||||||
isCervixTrackingCategoryEnabled) ? (
|
onToggle={fertilityTrackingToggle}
|
||||||
<>
|
text={fertilityTrackingText}
|
||||||
<AppText>{labels.fertilityTracking.message}</AppText>
|
value={isFertilityTrackingEnabled}
|
||||||
<AppSwitch
|
disabled={!manageFertilityFeature}
|
||||||
onToggle={fertilityTrackingToggle}
|
/>
|
||||||
text={fertilityTrackingText}
|
|
||||||
value={isFertilityTrackingEnabled}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<AppText>{labels.disabled.message}</AppText>
|
|
||||||
)}
|
|
||||||
</Segment>
|
</Segment>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
|
||||||
<Pressable onPress={sliderDisabledPrompt}>
|
<Pressable onPress={sliderDisabledPrompt}>
|
||||||
<Segment title={labels.tempScale.segmentTitle}>
|
<Segment title={labels.tempScale.segmentTitle}>
|
||||||
{isTemperatureTrackingCategoryEnabled && (
|
<AppText>{labels.tempScale.segmentExplainer}</AppText>
|
||||||
<>
|
<TemperatureSlider disabled={!isTemperatureTrackingCategoryEnabled} />
|
||||||
<AppText>{labels.tempScale.segmentExplainer}</AppText>
|
|
||||||
<TemperatureSlider />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{!isTemperatureTrackingCategoryEnabled && (
|
|
||||||
<AppText>{labels.disabled.message}</AppText>
|
|
||||||
)}
|
|
||||||
</Segment>
|
</Segment>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
|
||||||
<Pressable onPress={secondarySymptomDisabledPrompt}>
|
<Pressable onPress={secondarySymptomDisabledPrompt}>
|
||||||
<Segment title={labels.secondarySymptom.title}>
|
<Segment title={labels.secondarySymptom.title}>
|
||||||
{!isFertilityTrackingEnabled ? (
|
<AppText>{cervixText}</AppText>
|
||||||
<AppText>{labels.secondarySymptom.disabled.message}</AppText>
|
<SelectTabGroup
|
||||||
) : (
|
activeButton={useCervixAsSecondarySymptom}
|
||||||
<>
|
buttons={secondarySymptomButtons}
|
||||||
<AppText>{cervixText}</AppText>
|
onSelect={(value) => onSelectTab(value)}
|
||||||
<SelectTabGroup
|
disabled={!isFertilityTrackingEnabled}
|
||||||
activeButton={useCervixAsSecondarySymptom}
|
/>
|
||||||
buttons={secondarySymptomButtons}
|
|
||||||
onSelect={(value) => onSelectTab(value)}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Segment>
|
</Segment>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { StyleSheet, View } from 'react-native'
|
import { StyleSheet, View } from 'react-native'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
import Slider from '@ptomasroos/react-native-multi-slider'
|
import Slider from '@ptomasroos/react-native-multi-slider'
|
||||||
|
|
||||||
import alertError from '../common/alert-error'
|
import alertError from '../common/alert-error'
|
||||||
@@ -10,7 +11,7 @@ import { Colors, Sizes } from '../../../styles'
|
|||||||
import labels from '../../../i18n/en/settings'
|
import labels from '../../../i18n/en/settings'
|
||||||
import { TEMP_MIN, TEMP_MAX, TEMP_SLIDER_STEP } from '../../../config'
|
import { TEMP_MIN, TEMP_MAX, TEMP_SLIDER_STEP } from '../../../config'
|
||||||
|
|
||||||
const TemperatureSlider = () => {
|
const TemperatureSlider = ({ disabled }) => {
|
||||||
const savedValue = scaleObservable.value
|
const savedValue = scaleObservable.value
|
||||||
const [minTemperature, setMinTemperature] = useState(savedValue.min)
|
const [minTemperature, setMinTemperature] = useState(savedValue.min)
|
||||||
const [maxTemperature, setMaxTemperature] = useState(savedValue.max)
|
const [maxTemperature, setMaxTemperature] = useState(savedValue.max)
|
||||||
@@ -25,6 +26,14 @@ const TemperatureSlider = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sliderAccentBackground = disabled
|
||||||
|
? styles.disabledSliderAccentBackground
|
||||||
|
: styles.sliderAccentBackground
|
||||||
|
|
||||||
|
const sliderBackground = disabled
|
||||||
|
? styles.disabledSliderBackground
|
||||||
|
: styles.sliderBackground
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Slider
|
<Slider
|
||||||
@@ -35,11 +44,13 @@ const TemperatureSlider = () => {
|
|||||||
max={TEMP_MAX}
|
max={TEMP_MAX}
|
||||||
min={TEMP_MIN}
|
min={TEMP_MIN}
|
||||||
onValuesChange={onTemperatureSliderChange}
|
onValuesChange={onTemperatureSliderChange}
|
||||||
selectedStyle={styles.sliderAccentBackground}
|
|
||||||
step={TEMP_SLIDER_STEP}
|
step={TEMP_SLIDER_STEP}
|
||||||
trackStyle={styles.slider}
|
trackStyle={styles.slider}
|
||||||
unselectedStyle={styles.sliderBackground}
|
|
||||||
values={[minTemperature, maxTemperature]}
|
values={[minTemperature, maxTemperature]}
|
||||||
|
enabledOne={!disabled}
|
||||||
|
enabledTwo={!disabled}
|
||||||
|
selectedStyle={sliderAccentBackground}
|
||||||
|
unselectedStyle={sliderBackground}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
@@ -47,6 +58,10 @@ const TemperatureSlider = () => {
|
|||||||
|
|
||||||
export default TemperatureSlider
|
export default TemperatureSlider
|
||||||
|
|
||||||
|
TemperatureSlider.propTypes = {
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
@@ -54,6 +69,7 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
marker: {
|
marker: {
|
||||||
backgroundColor: Colors.turquoiseDark,
|
backgroundColor: Colors.turquoiseDark,
|
||||||
|
|
||||||
borderRadius: 50,
|
borderRadius: 50,
|
||||||
elevation: 4,
|
elevation: 4,
|
||||||
height: Sizes.subtitle,
|
height: Sizes.subtitle,
|
||||||
@@ -66,7 +82,13 @@ const styles = StyleSheet.create({
|
|||||||
sliderAccentBackground: {
|
sliderAccentBackground: {
|
||||||
backgroundColor: Colors.turquoiseDark,
|
backgroundColor: Colors.turquoiseDark,
|
||||||
},
|
},
|
||||||
|
disabledSliderAccentBackground: {
|
||||||
|
backgroundColor: Colors.grey,
|
||||||
|
},
|
||||||
sliderBackground: {
|
sliderBackground: {
|
||||||
backgroundColor: Colors.turquoise,
|
backgroundColor: Colors.turquoise,
|
||||||
},
|
},
|
||||||
|
disabledSliderBackground: {
|
||||||
|
backgroundColor: Colors.greyLight,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
+12
-10
@@ -36,17 +36,16 @@ export default {
|
|||||||
tempScale: {
|
tempScale: {
|
||||||
segmentTitle: 'Temperature scale',
|
segmentTitle: 'Temperature scale',
|
||||||
segmentExplainer:
|
segmentExplainer:
|
||||||
'Change the minimum and maximum value for the temperature chart',
|
'Change the minimum and maximum value for the temperature chart.',
|
||||||
min: 'Min',
|
min: 'Min',
|
||||||
max: 'Max',
|
max: 'Max',
|
||||||
loadError: 'Could not load saved temperature scale settings',
|
loadError: 'Could not load saved temperature scale settings',
|
||||||
saveError: 'Could not save temperature scale settings',
|
saveError: 'Could not save temperature scale settings',
|
||||||
|
disabled: 'Disabled',
|
||||||
|
disabledMessage:
|
||||||
|
'To use the temperature scale please first enable temperature tracking above.',
|
||||||
},
|
},
|
||||||
disabled: {
|
|
||||||
title: 'This feature is turned off',
|
|
||||||
message:
|
|
||||||
'To use the temperature scale please first enable the temperature tracking category above.',
|
|
||||||
},
|
|
||||||
tempReminder: {
|
tempReminder: {
|
||||||
title: 'Temperature reminder',
|
title: 'Temperature reminder',
|
||||||
noTimeSet: 'Set a time for a daily reminder to take your temperature',
|
noTimeSet: 'Set a time for a daily reminder to take your temperature',
|
||||||
@@ -72,21 +71,24 @@ export default {
|
|||||||
},
|
},
|
||||||
fertilityTracking: {
|
fertilityTracking: {
|
||||||
title: 'Fertility phases calculation',
|
title: 'Fertility phases calculation',
|
||||||
|
disabledTitle: 'Disabled',
|
||||||
|
disabled:
|
||||||
|
'To use fertility phases calculation please enable temperature tracking and cervical mucus or cervix tracking above.',
|
||||||
message:
|
message:
|
||||||
'If you enter menstrual bleeding, temperature and cervical mucus or cervix data according to the sympto-thermal rules, drip will calculate cycle phases with the provided data.',
|
'If you enter menstrual bleeding, temperature and cervical mucus or cervix data according to the sympto-thermal method, drip will calculate cycle phases with the provided data.',
|
||||||
on: 'If you switch this off, drip will not show fertility related information.',
|
on: 'If you switch this off, drip will not show fertility related information.',
|
||||||
off: 'If you switch this on, drip will show fertility related information.',
|
off: 'If you switch this on, drip will show fertility related information.',
|
||||||
},
|
},
|
||||||
secondarySymptom: {
|
secondarySymptom: {
|
||||||
title: 'Secondary symptom',
|
title: 'Secondary symptom',
|
||||||
cervixModeOn:
|
cervixModeOn:
|
||||||
'Cervix values are being used for sympto-thermal fertility detection. You can switch here to use cervical mucus values for sympto-thermal fertility detection',
|
'Cervix values are being used for fertility detection according to the sympto-thermal method.',
|
||||||
cervixModeOff:
|
cervixModeOff:
|
||||||
'By default, cervical mucus values are being used for sympto-thermal fertility detection. You can switch here to use cervix values for sympto-thermal fertility detection',
|
'Cervical mucus values are being used for fertility detection according to the sympto-thermal method.',
|
||||||
disabled: {
|
disabled: {
|
||||||
title: 'Disabled',
|
title: 'Disabled',
|
||||||
message:
|
message:
|
||||||
'To set a secondary symptom please first enable the temperature, cervical mucus or cervix tracking category as well as the fertility feature above.',
|
'To set a secondary symptom please first enable the cervical mucus or cervix tracking category as well as temperature and fertility phases calculation above.',
|
||||||
noSecondaryEnabled:
|
noSecondaryEnabled:
|
||||||
'To switch the secondary symptom both cervical mucus and cervix need to be enabled above.',
|
'To switch the secondary symptom both cervical mucus and cervix need to be enabled above.',
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user