Merge branch '671-feature-customisation-not-display-menstrual-bleeding-prediction' into 'main'

Feature: Customizable period prediction

Closes #671

See merge request bloodyhealth/drip!647
This commit is contained in:
bl00dymarie
2024-01-22 14:40:31 +00:00
9 changed files with 85 additions and 21 deletions
-1
View File
@@ -9,7 +9,6 @@ cache:
test_async:
script:
- npm install npm@7.0.1 -g
- npm install
- npm test
variables:
+4
View File
@@ -14,6 +14,7 @@ import {
determinePredictionText,
formatWithOrdinalSuffix,
} from './helpers/home'
import { periodPredictionObservable } from '../local-storage'
import { Colors, Fonts, Sizes, Spacing } from '../styles'
import { LocalDate } from '@js-joda/core'
@@ -32,6 +33,7 @@ const Home = ({ navigate, setDate }) => {
const cycleDayNumber = getCycleDayNumber(todayDateString)
const { status, phase, statusText } =
getFertilityStatusForDay(todayDateString)
const isPeriodPredictionEnabled = periodPredictionObservable.value
const prediction = determinePredictionText(getPredictedMenses(), t)
const cycleDayText = cycleDayNumber
@@ -65,9 +67,11 @@ const Home = ({ navigate, setDate }) => {
<Asterisk />
</View>
)}
{isPeriodPredictionEnabled && (
<View style={styles.line}>
<AppText style={styles.turquoiseText}>{prediction}</AppText>
</View>
)}
<Button isCTA isSmall={false} onPress={navigateToCycleDayView}>
{t('labels.home.addDataForToday')}
</Button>
+3 -1
View File
@@ -6,7 +6,7 @@ import AppText from './app-text'
import { Containers } from '../../styles'
const AppSwitch = ({ onToggle, text, value, trackColor }) => {
const AppSwitch = ({ onToggle, text, value, trackColor, disabled }) => {
return (
<View style={styles.container}>
<View style={styles.textContainer}>
@@ -17,6 +17,7 @@ const AppSwitch = ({ onToggle, text, value, trackColor }) => {
style={styles.switch}
value={value}
trackColor={trackColor}
disabled={disabled}
/>
</View>
)
@@ -27,6 +28,7 @@ AppSwitch.propTypes = {
text: PropTypes.string,
value: PropTypes.bool,
trackColor: PropTypes.string,
disabled: PropTypes.bool,
}
const styles = StyleSheet.create({
+2
View File
@@ -2,6 +2,7 @@ import { LocalDate } from '@js-joda/core'
import { verticalScale } from 'react-native-size-matters'
import { Colors, Fonts, Sizes } from '../../styles'
import { periodPredictionObservable } from '../../local-storage'
const { shades } = Colors.iconColors.bleeding
@@ -26,6 +27,7 @@ export const toCalFormat = (bleedingDaysSortedByDate) => {
}
export const predictionToCalFormat = (predictedDays) => {
if (!periodPredictionObservable.value) return {}
if (!predictedDays.length) return {}
const todayDateString = LocalDate.now().toString()
const middleIndex = (predictedDays[0].length - 1) / 2
+24 -8
View File
@@ -6,7 +6,12 @@ import AppText from '../../common/app-text'
import TemperatureSlider from './temperature-slider'
import Segment from '../../common/segment'
import { useCervixObservable, saveUseCervix } from '../../../local-storage'
import {
periodPredictionObservable,
savePeriodPrediction,
useCervixObservable,
saveUseCervix,
} from '../../../local-storage'
import { Colors } from '../../../styles'
import labels from '../../../i18n/en/settings'
@@ -15,9 +20,22 @@ const Settings = () => {
useCervixObservable.value
)
const [isEnabled, setIsEnabled] = useState(true)
const [isPeriodPredictionEnabled, setPeriodPrediction] = useState(
periodPredictionObservable.value
)
const [isEnabled, setIsEnabled] = useState(false)
const toggleSwitch = () => setIsEnabled((previousState) => !previousState)
const onPeriodPredictionToggle = (value) => {
setPeriodPrediction(value)
savePeriodPrediction(value)
}
const periodPredictionText = isPeriodPredictionEnabled
? labels.periodPrediction.on
: labels.periodPrediction.off
const onCervixToggle = (value) => {
setShouldUseCervix(value)
saveUseCervix(value)
@@ -103,13 +121,11 @@ const Settings = () => {
/>
</Segment>
<Segment title={'Period prediction'}>
<Segment title={labels.periodPrediction.title} last>
<AppSwitch
onToggle={toggleSwitch}
text={
'If turned on drip will predict your next menstrual bleeding, after you have tracked 3 complete menstrual cycles.'
}
value={isEnabled}
onToggle={onPeriodPredictionToggle}
text={periodPredictionText}
value={isPeriodPredictionEnabled}
trackColor={{ true: Colors.turquoiseDark }}
/>
</Segment>
@@ -8,11 +8,15 @@ import TemperatureReminder from './temperature-reminder'
import {
periodReminderObservable,
savePeriodReminder,
periodPredictionObservable,
} from '../../../local-storage'
import labels from '../../../i18n/en/settings'
import { Alert, Pressable } from 'react-native'
const Reminders = () => {
const isPeriodPredictionDisabled = !periodPredictionObservable.value
const [isPeriodReminderEnabled, setIsPeriodReminderEnabled] = useState(
periodReminderObservable.value.enabled
)
@@ -21,15 +25,27 @@ const Reminders = () => {
savePeriodReminder({ enabled: isEnabled })
}
const reminderDisabledPrompt = () => {
if (!periodPredictionObservable.value) {
Alert.alert(
labels.periodReminder.alertNoPeriodReminder.title,
labels.periodReminder.alertNoPeriodReminder.message
)
}
}
return (
<AppPage>
<Pressable onPress={reminderDisabledPrompt}>
<Segment title={labels.periodReminder.title}>
<AppSwitch
onToggle={periodReminderToggle}
text={labels.periodReminder.reminderText}
value={isPeriodReminderEnabled}
disabled={isPeriodPredictionDisabled}
/>
</Segment>
</Pressable>
<Segment title={labels.tempReminder.title} last>
<TemperatureReminder />
</Segment>
+10
View File
@@ -50,6 +50,11 @@ export default {
'Get a notification 3 days before your next period is likely to start.',
notification: (daysToEndOfPrediction) =>
`Your next period is likely to start in 3 to ${daysToEndOfPrediction} days.`,
alertNoPeriodReminder: {
title: 'Period predictions turned off',
message:
'To use the period reminder please first enable period predictions in the customization settings.',
},
},
useCervix: {
title: 'Secondary symptom',
@@ -58,6 +63,11 @@ export default {
cervixModeOff:
'By default, cervical mucus values are being used for symptothermal fertility detection. You can switch here to use cervix values for symptothermal fertility detection',
},
periodPrediction: {
title: 'Period predictions',
on: 'drip predicts your 3 next menstrual bleedings based on the statistics of your previously tracked cycles, min 3 complete cycles.',
off: 'There are no predictions for menstrual cycles displayed. If turned on the calendar and the home screen will display period predictions.',
},
passwordSettings: {
title: 'App password',
explainerDisabled:
+1 -1
View File
@@ -27,7 +27,7 @@ After tracking at least 3 menstrual cycles, drip. will give you an overview of
· whether the length of your cycles varied significantly (in "stats" and in bleeding predictions)
· and predict your next 3 cycles with a range of 3 or 5 days (on home screen and "calendar").
The app allows you to track different intensities of bleeding. On the chart and on the calendar, bleeding values are colored in different shades of red. The darker, the more intense your bleeding. Every bleeding value that is not excluded is taken into account for fertility calculation and prediction for the start of next cycles.
The app allows you to track different intensities of bleeding. On the chart and on the calendar, bleeding values are colored in different shades of red. The darker, the more intense your bleeding. Every bleeding value that is not excluded is taken into account for fertility calculation and period predictions.
Excluding bleeding values is for tracking bleeding when it's not marking the start of a new cycle or the continuation of menstrual bleeding the day(s) before, e.g. bleeding caused by ovulation or a miscarriage.
+15
View File
@@ -44,6 +44,21 @@ export async function savePeriodReminder(reminder) {
periodReminderObservable.set(reminder)
}
export const periodPredictionObservable = Observable()
setObvWithInitValue('periodPrediction', periodPredictionObservable, true)
export async function savePeriodPrediction(bool) {
await AsyncStorage.setItem('periodPrediction', JSON.stringify(bool))
periodPredictionObservable.set(bool)
if (!periodPredictionObservable.value) {
const result = await AsyncStorage.getItem('periodReminder')
if (JSON.parse(result).enabled) {
periodReminderObservable.set(false)
}
}
}
export const useCervixObservable = Observable()
setObvWithInitValue('useCervix', useCervixObservable, false)