Add new home screen
This commit is contained in:
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="850.39px" height="850.39px" viewBox="0 0 850.39 850.39" enable-background="new 0 0 850.39 850.39" xml:space="preserve">
|
||||
<g>
|
||||
<defs>
|
||||
<rect id="SVGID_1_" x="350" y="336.467" width="144.262" height="181.533"/>
|
||||
</defs>
|
||||
<clipPath id="SVGID_2_">
|
||||
<use xlink:href="#SVGID_1_" overflow="visible"/>
|
||||
</clipPath>
|
||||
<path clip-path="url(#SVGID_2_)" fill="none" stroke="#89113E" stroke-width="2" stroke-miterlimit="10" d="M492.723,455.44
|
||||
c-5.531,39.136-41.74,66.377-80.876,60.847C372.712,510.757,351,483.64,351,444.115c0-37.555,79.739-114.673,80.391-105.969
|
||||
C434.248,376.247,499.843,405.058,492.723,455.44z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1004 B |
@@ -3,7 +3,7 @@ import Svg, { G, Path } from 'react-native-svg'
|
||||
|
||||
export default function HomeCycleIcon() {
|
||||
return (
|
||||
<Svg width={140} height={100} viewBox='200 200 350 350'>
|
||||
<Svg width={80} height={80} viewBox='340 345 170 170'>
|
||||
<G>
|
||||
<Path fill="none" stroke="#1E0B7A" strokeWidth="2" d="M379.708,350.568
|
||||
C356.431,365.455,341,391.529,341,421.21c0,46.275,37.515,83.79,83.791,83.79s83.79-37.515,83.79-83.79
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import React from 'react'
|
||||
import Svg, { G, Path } from 'react-native-svg'
|
||||
|
||||
export default function HomeDropIcon() {
|
||||
return (
|
||||
<Svg width={80} height={102.56} viewBox="350 275 145 144">
|
||||
<G>
|
||||
<Path fill="none" stroke="#89113E" stroke-width="2" stroke-miterlimit="10" d="M492.723,455.44
|
||||
c-5.531,39.136-41.74,66.377-80.876,60.847C372.712,510.757,351,483.64,351,444.115c0-37.555,79.739-114.673,80.391-105.969
|
||||
C434.248,376.247,499.843,405.058,492.723,455.44z"/>
|
||||
</G>
|
||||
</Svg>
|
||||
)
|
||||
}
|
||||
+11
-1
@@ -2,7 +2,7 @@ import React, { Component } from 'react'
|
||||
import { Text } from 'react-native'
|
||||
import styles from "../styles"
|
||||
|
||||
export class AppText extends Component {
|
||||
export default class AppText extends Component {
|
||||
render() {
|
||||
return (
|
||||
<Text style={[styles.appText, this.props.style]}>
|
||||
@@ -12,6 +12,16 @@ export class AppText extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
export class AppTextLight extends Component {
|
||||
render() {
|
||||
return (
|
||||
<Text style={[styles.appTextLight, this.props.style]}>
|
||||
{this.props.children}
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export class SymptomSectionHeader extends Component {
|
||||
render() {
|
||||
return (
|
||||
|
||||
+5
-11
@@ -40,20 +40,18 @@ export default class App extends Component {
|
||||
}
|
||||
|
||||
navigate = (pageName, props) => {
|
||||
const curr = this.state.currentPage
|
||||
if (navigatingToCycleDayFromMainMenuEntry(pageName, curr)) {
|
||||
this.cycleDayOrigin = curr
|
||||
}
|
||||
this.origin = this.state.currentPage
|
||||
this.setState({currentPage: pageName, currentProps: props})
|
||||
}
|
||||
|
||||
handleBackButtonPress = () => {
|
||||
if (this.state.currentPage === 'Home') return false
|
||||
if (isSymptomView(this.state.currentPage)) {
|
||||
this.navigate('CycleDay', { cycleDay: this.state.currentProps.cycleDay })
|
||||
this.navigate(
|
||||
this.origin, { cycleDay: this.state.currentProps.cycleDay }
|
||||
)
|
||||
} else if(this.state.currentPage === 'CycleDay') {
|
||||
this.navigate(this.cycleDayOrigin || 'Home')
|
||||
this.cycleDayOrigin = null
|
||||
this.navigate(this.origin)
|
||||
} else {
|
||||
this.navigate('Home')
|
||||
}
|
||||
@@ -93,7 +91,3 @@ export default class App extends Component {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function navigatingToCycleDayFromMainMenuEntry(target, curr) {
|
||||
return target === 'CycleDay' && ['Home', 'Calendar', 'Chart'].indexOf(curr) > -1
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import { getCycleDay, getCycleDaysSortedByDate, getAmountOfCycleDays } from '../
|
||||
import styles from './styles'
|
||||
import { scaleObservable } from '../../local-storage'
|
||||
import config from '../../config'
|
||||
import { AppText } from '../app-text'
|
||||
import AppText from '../app-text'
|
||||
import { shared as labels } from '../labels'
|
||||
import BleedingIcon from '../../assets/bleeding'
|
||||
import CervixIcon from '../../assets/cervix'
|
||||
|
||||
@@ -3,7 +3,7 @@ import { View } from 'react-native'
|
||||
import config from '../../config'
|
||||
import styles from './styles'
|
||||
import { scaleObservable, unitObservable } from '../../local-storage'
|
||||
import { AppText } from '../app-text'
|
||||
import AppText from '../app-text'
|
||||
|
||||
export function makeYAxisLabels(columnHeight) {
|
||||
const units = unitObservable.value
|
||||
|
||||
@@ -11,8 +11,8 @@ import Header from '../header'
|
||||
import { getOrCreateCycleDay } from '../../db'
|
||||
import cycleModule from '../../lib/cycle'
|
||||
import styles from '../../styles'
|
||||
import * as labels from './labels/labels'
|
||||
import { AppText } from '../app-text'
|
||||
import * as labels from './labels'
|
||||
import AppText from '../app-text'
|
||||
import BleedingIcon from '../../assets/bleeding'
|
||||
import CervixIcon from '../../assets/cervix'
|
||||
import DesireIcon from '../../assets/desire'
|
||||
|
||||
@@ -65,13 +65,6 @@ export const pain = {
|
||||
explainer: 'How did your body feel today?'
|
||||
}
|
||||
|
||||
export const fertilityStatus = {
|
||||
fertile: 'fertile',
|
||||
infertile: 'infertile',
|
||||
fertileUntilEvening: 'Fertile phase ends in the evening',
|
||||
unknown: 'We cannot show any cycle information because no menses has been entered'
|
||||
}
|
||||
|
||||
export const temperature = {
|
||||
outOfRangeWarning: 'This temperature value is out of the current range for the temperature chart. You can change the range in the settings.',
|
||||
outOfAbsoluteRangeWarning: 'This temperature value is too high or low to be shown on the temperature chart.',
|
||||
@@ -1,5 +0,0 @@
|
||||
import moment from "moment"
|
||||
|
||||
export function formatDateForViewHeader(date) {
|
||||
return moment(date).format('MMMM Do YYYY')
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
TouchableOpacity,
|
||||
} from 'react-native'
|
||||
import styles from '../../styles'
|
||||
import { AppText } from '../app-text'
|
||||
import AppText from '../app-text'
|
||||
|
||||
export default class SelectBoxGroup extends Component {
|
||||
render() {
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
TouchableOpacity,
|
||||
} from 'react-native'
|
||||
import styles from '../../styles'
|
||||
import { AppText } from '../app-text'
|
||||
import AppText from '../app-text'
|
||||
|
||||
export default class SelectTabGroup extends Component {
|
||||
render() {
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import { saveSymptom } from '../../../db'
|
||||
import styles, {iconStyles} from '../../../styles'
|
||||
import {sharedDialogs as labels} from '../labels/labels'
|
||||
import {sharedDialogs as labels} from '../labels'
|
||||
|
||||
export default class ActionButtonFooter extends Component {
|
||||
render() {
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
} from 'react-native'
|
||||
import styles from '../../../styles'
|
||||
import { saveSymptom } from '../../../db'
|
||||
import { bleeding as labels } from '../labels/labels'
|
||||
import { bleeding as labels } from '../labels'
|
||||
import ActionButtonFooter from './action-button-footer'
|
||||
import SelectTabGroup from '../select-tab-group'
|
||||
import SymptomSection from './symptom-section'
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
} from 'react-native'
|
||||
import styles from '../../../styles'
|
||||
import { saveSymptom } from '../../../db'
|
||||
import { cervix as labels } from '../labels/labels'
|
||||
import { cervix as labels } from '../labels'
|
||||
import ActionButtonFooter from './action-button-footer'
|
||||
import SelectTabGroup from '../select-tab-group'
|
||||
import SymptomSection from './symptom-section'
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
} from 'react-native'
|
||||
import styles from '../../../styles'
|
||||
import { saveSymptom } from '../../../db'
|
||||
import { intensity, desire } from '../labels/labels'
|
||||
import { intensity, desire } from '../labels'
|
||||
import ActionButtonFooter from './action-button-footer'
|
||||
import SelectTabGroup from '../select-tab-group'
|
||||
import SymptomSection from './symptom-section'
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
} from 'react-native'
|
||||
import styles from '../../../styles'
|
||||
import { saveSymptom } from '../../../db'
|
||||
import { mucus as labels } from '../labels/labels'
|
||||
import { mucus as labels } from '../labels'
|
||||
import computeSensiplanValue from '../../../lib/sensiplan-mucus'
|
||||
import ActionButtonFooter from './action-button-footer'
|
||||
import SelectTabGroup from '../select-tab-group'
|
||||
|
||||
@@ -9,7 +9,7 @@ import styles from '../../../styles'
|
||||
import { saveSymptom } from '../../../db'
|
||||
import ActionButtonFooter from './action-button-footer'
|
||||
import SymptomSection from './symptom-section'
|
||||
import { noteExplainer } from '../labels/labels'
|
||||
import { noteExplainer } from '../labels'
|
||||
|
||||
export default class Note extends Component {
|
||||
constructor(props) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
View
|
||||
} from 'react-native'
|
||||
import { saveSymptom } from '../../../db'
|
||||
import { pain as labels } from '../labels/labels'
|
||||
import { pain as labels } from '../labels'
|
||||
import ActionButtonFooter from './action-button-footer'
|
||||
import SelectBoxGroup from '../select-box-group'
|
||||
import SymptomSection from './symptom-section'
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
} from 'react-native'
|
||||
import styles from '../../../styles'
|
||||
import { saveSymptom } from '../../../db'
|
||||
import { sex as labels } from '../labels/labels'
|
||||
import { sex as labels } from '../labels'
|
||||
import ActionButtonFooter from './action-button-footer'
|
||||
import SelectBoxGroup from '../select-box-group'
|
||||
import SymptomSection from './symptom-section'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { Component } from 'react'
|
||||
import { View } from 'react-native'
|
||||
import { SymptomSectionHeader, AppText } from '../../app-text'
|
||||
import AppText, { SymptomSectionHeader } from '../../app-text'
|
||||
|
||||
export default class SymptomSection extends Component {
|
||||
render() {
|
||||
|
||||
@@ -12,7 +12,7 @@ import DateTimePicker from 'react-native-modal-datetime-picker-nevo'
|
||||
import { getPreviousTemperature, saveSymptom } from '../../../db'
|
||||
import styles from '../../../styles'
|
||||
import { LocalTime, ChronoUnit } from 'js-joda'
|
||||
import { temperature as labels } from '../labels/labels'
|
||||
import { temperature as labels } from '../labels'
|
||||
import { scaleObservable } from '../../../local-storage'
|
||||
import { shared } from '../../labels'
|
||||
import ActionButtonFooter from './action-button-footer'
|
||||
|
||||
@@ -4,11 +4,10 @@ import {
|
||||
Text,
|
||||
Dimensions
|
||||
} from 'react-native'
|
||||
import moment from 'moment'
|
||||
import styles, { iconStyles } from '../styles'
|
||||
import Icon from 'react-native-vector-icons/Entypo'
|
||||
import FeatherIcon from 'react-native-vector-icons/Feather'
|
||||
import { formatDateForViewHeader } from '../components/cycle-day/labels/format'
|
||||
|
||||
|
||||
export default class Header extends Component {
|
||||
render() {
|
||||
@@ -27,7 +26,7 @@ export default class Header extends Component {
|
||||
/>
|
||||
<View>
|
||||
<Text style={styles.dateHeader}>
|
||||
{formatDateForViewHeader(this.props.date)}
|
||||
{moment(this.props.date).format('MMMM Do YYYY')}
|
||||
</Text>
|
||||
{this.props.cycleDayNumber &&
|
||||
<Text style={styles.cycleDayNumber} >
|
||||
|
||||
+185
-59
@@ -1,108 +1,234 @@
|
||||
import React, { Component } from 'react'
|
||||
import {
|
||||
View,
|
||||
Button,
|
||||
Text,
|
||||
ScrollView
|
||||
} from 'react-native'
|
||||
import { ScrollView, View, TouchableOpacity, TouchableHighlight, Dimensions } from 'react-native'
|
||||
import { LocalDate, ChronoUnit } from 'js-joda'
|
||||
import styles from '../styles/index'
|
||||
import Icon from 'react-native-vector-icons/Entypo'
|
||||
import { secondaryColor, cycleDayColor, periodColor } from '../styles'
|
||||
import { home as labels, bleedingPrediction as predictLabels, shared } from './labels'
|
||||
import CycleCircle from '../assets/home-circle'
|
||||
import Drop from '../assets/home-drop'
|
||||
import cycleModule from '../lib/cycle'
|
||||
import { getOrCreateCycleDay, getBleedingDaysSortedByDate, fillWithMucusDummyData, fillWithCervixDummyData } from '../db'
|
||||
import {bleedingPrediction as labels} from './labels'
|
||||
import { getOrCreateCycleDay, getCycleDaysSortedByDate } from '../db'
|
||||
import { getFertilityStatusForDay } from '../lib/sympto-adapter'
|
||||
import styles from '../styles'
|
||||
import AppText, { AppTextLight } from './app-text'
|
||||
|
||||
export default class Home extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.getCycleDayNumber = cycleModule().getCycleDayNumber
|
||||
this.getBleedingPrediction = cycleModule().getPredictedMenses
|
||||
this.todayDateString = LocalDate.now().toString()
|
||||
const cycleDayNumber = this.getCycleDayNumber(this.todayDateString)
|
||||
const prediction = this.getBleedingPrediction()
|
||||
const fertilityStatus = getFertilityStatusForDay(this.todayDateString)
|
||||
|
||||
this.state = {
|
||||
welcomeText: determineWelcomeText(cycleDayNumber),
|
||||
predictionText: determinePredictionText()
|
||||
cycleDayNumber: this.getCycleDayNumber(this.todayDateString),
|
||||
predictionText: determinePredictionText(prediction),
|
||||
bleedingPredictionRange: getBleedingPredictionRange(prediction),
|
||||
...fertilityStatus
|
||||
}
|
||||
|
||||
this.bleedingDays = getBleedingDaysSortedByDate()
|
||||
this.bleedingDays.addListener(this.setStateWithCurrentText)
|
||||
this.cycleDays = getCycleDaysSortedByDate()
|
||||
this.cycleDays.addListener(this.updateState)
|
||||
}
|
||||
|
||||
setStateWithCurrentText = () => {
|
||||
const cycleDayNumber = this.getCycleDayNumber(this.todayDateString)
|
||||
updateState = () => {
|
||||
const prediction = this.getBleedingPrediction()
|
||||
const fertilityStatus = getFertilityStatusForDay(this.todayDateString)
|
||||
this.setState({
|
||||
welcomeText: determineWelcomeText(cycleDayNumber),
|
||||
predictionText: determinePredictionText()
|
||||
cycleDayNumber: this.getCycleDayNumber(this.todayDateString),
|
||||
predictionText: determinePredictionText(prediction),
|
||||
bleedingPredictionRange: getBleedingPredictionRange(prediction),
|
||||
...fertilityStatus
|
||||
})
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.bleedingDays.removeListener(this.setStateWithCurrentText)
|
||||
this.cycleDays.removeListener(this.updateState)
|
||||
}
|
||||
|
||||
passTodayToDayView() {
|
||||
passTodayTo(componentName) {
|
||||
const todayDateString = LocalDate.now().toString()
|
||||
const cycleDay = getOrCreateCycleDay(todayDateString)
|
||||
const navigate = this.props.navigate
|
||||
navigate('CycleDay', { cycleDay })
|
||||
navigate(componentName, { cycleDay })
|
||||
}
|
||||
|
||||
render() {
|
||||
const cycleDayMoreText = this.state.cycleDayNumber ?
|
||||
labels.cycleDayKnown(this.state.cycleDayNumber)
|
||||
:
|
||||
labels.cycleDayNotEnoughInfo
|
||||
|
||||
const {height, width} = Dimensions.get('window')
|
||||
return (
|
||||
<ScrollView>
|
||||
<Text style={styles.welcome}>{this.state.welcomeText}</Text>
|
||||
<Text style={styles.welcome}>{this.state.predictionText}</Text>
|
||||
<View style={styles.homeButtons}>
|
||||
<View style={styles.homeButton}>
|
||||
<Button
|
||||
onPress={() => this.passTodayToDayView()}
|
||||
title="Edit symptoms for today">
|
||||
</Button>
|
||||
<View flex={1}>
|
||||
<ScrollView>
|
||||
<View
|
||||
style={styles.homeView}
|
||||
>
|
||||
<TouchableOpacity
|
||||
onPress={() => this.passTodayTo('CycleDay')}
|
||||
style={styles.homeIconElement}
|
||||
>
|
||||
<View position='absolute'>
|
||||
<CycleCircle/>
|
||||
</View>
|
||||
<View style={[styles.homeIconTextWrapper, styles.wrapperCycle]}>
|
||||
<AppTextLight style={styles.iconText}>
|
||||
{this.state.cycleDayNumber || labels.unknown}
|
||||
</AppTextLight>
|
||||
</View>
|
||||
|
||||
{ this.state.showMore &&
|
||||
<AppText style={styles.paragraph}>{cycleDayMoreText}</AppText>
|
||||
}
|
||||
<View style={[
|
||||
styles.homeButton,
|
||||
{ backgroundColor: cycleDayColor }
|
||||
]}>
|
||||
<AppText style={styles.homeButtonText}>
|
||||
{labels.editToday}
|
||||
</AppText>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
onPress={() => this.passTodayTo('BleedingEditView')}
|
||||
style={styles.homeIconElement}
|
||||
>
|
||||
<View position='absolute'>
|
||||
<Drop/>
|
||||
</View>
|
||||
<View style={[styles.homeIconTextWrapper, styles.wrapperDrop]}>
|
||||
<AppTextLight style={styles.iconText}>
|
||||
{this.state.bleedingPredictionRange}
|
||||
</AppTextLight>
|
||||
</View>
|
||||
|
||||
{this.state.showMore &&
|
||||
<AppText style={styles.paragraph}>
|
||||
{this.state.predictionText}
|
||||
</AppText>
|
||||
}
|
||||
<View style={[
|
||||
styles.homeButton,
|
||||
{ backgroundColor: periodColor }
|
||||
]}>
|
||||
<AppText style={styles.homeButtonText}>
|
||||
{labels.trackPeriod}
|
||||
</AppText>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
onPress={() => this.props.navigate('Chart')}
|
||||
style={styles.homeIconElement}
|
||||
>
|
||||
<View style={styles.homeCircle}>
|
||||
<AppTextLight style={styles.iconText}>
|
||||
{this.state.phase ?
|
||||
this.state.phase.toString()
|
||||
:
|
||||
labels.unknown
|
||||
}
|
||||
</AppTextLight>
|
||||
</View>
|
||||
{this.state.phase &&
|
||||
<AppTextLight>
|
||||
{`${labels.phase(this.state.phase)} (${this.state.status})`}
|
||||
</AppTextLight>
|
||||
}
|
||||
{this.state.showMore &&
|
||||
<AppText styles={styles.paragraph}>
|
||||
{this.state.statusText}
|
||||
</AppText>
|
||||
}
|
||||
<View style={[
|
||||
styles.homeButton,
|
||||
{ backgroundColor: secondaryColor }
|
||||
]}>
|
||||
<AppText style={styles.homeButtonText}>
|
||||
{labels.checkFertility}
|
||||
</AppText>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.homeButton}>
|
||||
<Button
|
||||
onPress={() => fillWithMucusDummyData()}
|
||||
title="fill with example data for mucus&temp">
|
||||
</Button>
|
||||
</View>
|
||||
<View style={styles.homeButton}>
|
||||
<Button
|
||||
onPress={() => fillWithCervixDummyData()}
|
||||
title="fill with example data for cervix&temp">
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
{!this.state.showMore &&
|
||||
<TouchableHighlight
|
||||
onPress={() => this.setState({showMore: true})}
|
||||
style={[styles.showMore, {
|
||||
top: height / 2 - styles.header.height - 30,
|
||||
left: width - 40
|
||||
}]}
|
||||
>
|
||||
<View style={{alignItems: 'center'}}>
|
||||
<AppTextLight>{shared.more}</AppTextLight>
|
||||
<Icon name='chevron-thin-down' />
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
}
|
||||
|
||||
{this.state.showMore &&
|
||||
<TouchableHighlight
|
||||
onPress={() => this.setState({showMore: false})}
|
||||
style={[styles.showLess, {
|
||||
top: height / 2 - styles.header.height - 30,
|
||||
left: 10
|
||||
}]}
|
||||
>
|
||||
<View style={{alignItems: 'center'}}>
|
||||
<AppTextLight>{shared.less}</AppTextLight>
|
||||
<Icon name='chevron-thin-down' />
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function determineWelcomeText(cycleDayNumber) {
|
||||
const welcomeTextWithCycleDay = `Welcome! Today is day ${cycleDayNumber} of your current cycle`
|
||||
const welcomeText = `Welcome! We don't have enough information to know what your current cycle day is`
|
||||
return cycleDayNumber ? welcomeTextWithCycleDay : welcomeText
|
||||
}
|
||||
|
||||
function determinePredictionText() {
|
||||
const bleedingPrediction = cycleModule().getPredictedMenses()
|
||||
if (!bleedingPrediction.length) return labels.noPrediction
|
||||
function determinePredictionText(bleedingPrediction) {
|
||||
if (!bleedingPrediction.length) return predictLabels.noPrediction
|
||||
const todayDate = LocalDate.now()
|
||||
const bleedingStart = LocalDate.parse(bleedingPrediction[0][0])
|
||||
const bleedingEnd = LocalDate.parse(bleedingPrediction[0][ bleedingPrediction[0].length - 1 ])
|
||||
const bleedingEnd = LocalDate.parse(
|
||||
bleedingPrediction[0][ bleedingPrediction[0].length - 1 ]
|
||||
)
|
||||
if (todayDate.isBefore(bleedingStart)) {
|
||||
return labels.predictionInFuture(
|
||||
return predictLabels.predictionInFuture(
|
||||
todayDate.until(bleedingStart, ChronoUnit.DAYS),
|
||||
todayDate.until(bleedingEnd, ChronoUnit.DAYS)
|
||||
)
|
||||
}
|
||||
if (todayDate.isAfter(bleedingEnd)) {
|
||||
return labels.predictionInPast(bleedingStart.toString(), bleedingEnd.toString())
|
||||
return predictLabels.predictionInPast(
|
||||
bleedingStart.toString(), bleedingEnd.toString()
|
||||
)
|
||||
}
|
||||
const daysToEnd = todayDate.until(bleedingEnd, ChronoUnit.DAYS)
|
||||
if (daysToEnd === 0) {
|
||||
return labels.predictionStartedNoDaysLeft
|
||||
return predictLabels.predictionStartedNoDaysLeft
|
||||
} else if (daysToEnd === 1) {
|
||||
return labels.predictionStarted1DayLeft
|
||||
return predictLabels.predictionStarted1DayLeft
|
||||
} else {
|
||||
return labels.predictionStartedXDaysLeft(daysToEnd)
|
||||
return predictLabels.predictionStartedXDaysLeft(daysToEnd)
|
||||
}
|
||||
}
|
||||
|
||||
function getBleedingPredictionRange(prediction) {
|
||||
if (!prediction.length) return labels.unknown
|
||||
const todayDate = LocalDate.now()
|
||||
const bleedingStart = LocalDate.parse(prediction[0][0])
|
||||
const bleedingEnd = LocalDate.parse(prediction[0][ prediction[0].length - 1 ])
|
||||
if (todayDate.isBefore(bleedingStart)) {
|
||||
return `${todayDate.until(bleedingStart, ChronoUnit.DAYS)}-${todayDate.until(bleedingEnd, ChronoUnit.DAYS)}`
|
||||
}
|
||||
if (todayDate.isAfter(bleedingEnd)) {
|
||||
return labels.unknown
|
||||
}
|
||||
return '0'
|
||||
}
|
||||
+36
-2
@@ -11,7 +11,9 @@ export const shared = {
|
||||
unlock: 'Unlock',
|
||||
date: 'Date',
|
||||
cycleDayWithLinebreak: 'Cycle\nday',
|
||||
loading: 'Loading ...'
|
||||
loading: 'Loading ...',
|
||||
more: 'more',
|
||||
less: 'less'
|
||||
}
|
||||
|
||||
export const settings = {
|
||||
@@ -137,4 +139,36 @@ export const passwordPrompt = {
|
||||
areYouSureTitle: 'Are you sure?',
|
||||
areYouSure: 'Are you absolutely sure you want to permanently delete all your data?',
|
||||
reallyDeleteData: 'Yes, I am sure'
|
||||
}
|
||||
}
|
||||
|
||||
export const home = {
|
||||
editToday: 'add data for today',
|
||||
cycleDayNotEnoughInfo: "We don't have enough information to know what your current cycle day is.",
|
||||
unknown: '?',
|
||||
cycleDayKnown: d => `Your last period started ${getDaysDescriptor(d)}.`,
|
||||
trackPeriod: 'track your period',
|
||||
checkFertility: 'check your fertility',
|
||||
phase: n => `${['1st', '2nd', '3rd'][n - 1]} cycle phase`
|
||||
}
|
||||
|
||||
const getDaysDescriptor = cycleDayNumber => {
|
||||
if (cycleDayNumber === 1) return 'today'
|
||||
if (cycleDayNumber === 2) return 'yesterday'
|
||||
return `${cycleDayNumber - 1} days ago`
|
||||
}
|
||||
|
||||
export const fertilityStatus = {
|
||||
fertile: 'fertile',
|
||||
infertile: 'infertile',
|
||||
fertileUntilEvening: 'Fertile phase ends in the evening',
|
||||
unknown: 'We cannot show any cycle information because no period data has been added.',
|
||||
preOvuText: "With NFP rules, you may assume 5 days of infertility at the beginning of your cycle, provided you don't observe any fertile mucus or cervix values.",
|
||||
periOvuText: "We have not been able to detect both a temperature shift and mucus or cervix shift.",
|
||||
postOvuText: tempRule => {
|
||||
return (
|
||||
'We have detected a temperature shift (' + ['regular', '1st exception', '2nd exception'][tempRule] +
|
||||
' temperature rule), as well as a mucus shift according to NFP rules. You may assume infertility, but always remember to ' +
|
||||
'double-check for yourself. Make sure the data makes sense to you.'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { Component } from 'react'
|
||||
import { View, TextInput, TouchableOpacity, Alert, Image } from 'react-native'
|
||||
import nodejs from 'nodejs-mobile-react-native'
|
||||
import { saveEncryptionFlag } from '../local-storage'
|
||||
import { AppText } from './app-text'
|
||||
import AppText from './app-text'
|
||||
import styles from '../styles'
|
||||
import { passwordPrompt as labels, shared } from './labels'
|
||||
import { requestHash, deleteDbAndOpenNew, openDb } from '../db'
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
} from 'react-native'
|
||||
import styles from '../../styles/index'
|
||||
import { settings as labels } from '../labels'
|
||||
import { AppText } from '../app-text'
|
||||
import AppText from '../app-text'
|
||||
import TempReminderPicker from './temp-reminder-picker'
|
||||
import PeriodReminderPicker from './period-reminder'
|
||||
import TempSlider from './temp-slider'
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
TouchableOpacity,
|
||||
} from 'react-native'
|
||||
import nodejs from 'nodejs-mobile-react-native'
|
||||
import { AppText } from '../../app-text'
|
||||
import AppText from '../../app-text'
|
||||
import styles from '../../../styles'
|
||||
import { settings as labels } from '../../labels'
|
||||
import { requestHash, changeEncryptionAndRestartApp } from '../../../db'
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
TouchableOpacity
|
||||
} from 'react-native'
|
||||
import nodejs from 'nodejs-mobile-react-native'
|
||||
import { AppText } from '../../app-text'
|
||||
import AppText from '../../app-text'
|
||||
import styles from '../../../styles'
|
||||
import { settings as labels } from '../../labels'
|
||||
import { requestHash, changeEncryptionAndRestartApp } from '../../../db'
|
||||
|
||||
@@ -3,7 +3,7 @@ import { View } from 'react-native'
|
||||
import CreatePassword from './create'
|
||||
import ChangePassword from './update'
|
||||
import DeletePassword from './delete'
|
||||
import { AppText } from '../../app-text'
|
||||
import AppText from '../../app-text'
|
||||
import {
|
||||
hasEncryptionObservable
|
||||
} from '../../../local-storage'
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
View,
|
||||
TouchableOpacity} from 'react-native'
|
||||
import nodejs from 'nodejs-mobile-react-native'
|
||||
import { AppText } from '../../app-text'
|
||||
import AppText from '../../app-text'
|
||||
import styles from '../../../styles'
|
||||
import { settings as labels, shared } from '../../labels'
|
||||
import { requestHash, changeEncryptionAndRestartApp } from '../../../db'
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
View,
|
||||
Switch
|
||||
} from 'react-native'
|
||||
import { AppText } from '../app-text'
|
||||
import AppText from '../app-text'
|
||||
import {
|
||||
periodReminderObservable,
|
||||
savePeriodReminder
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
Switch
|
||||
} from 'react-native'
|
||||
import DateTimePicker from 'react-native-modal-datetime-picker-nevo'
|
||||
import { AppText } from '../app-text'
|
||||
import AppText from '../app-text'
|
||||
import {
|
||||
tempReminderObservable,
|
||||
saveTempReminder
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react'
|
||||
import { View } from 'react-native'
|
||||
import Slider from '@ptomasroos/react-native-multi-slider'
|
||||
import { AppText } from '../app-text'
|
||||
import AppText from '../app-text'
|
||||
import {
|
||||
scaleObservable,
|
||||
saveTempScale,
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ import styles from '../styles/index'
|
||||
import cycleModule from '../lib/cycle'
|
||||
import {getCycleLengthStats as getCycleInfo} from '../lib/cycle-length'
|
||||
import {stats as labels} from './labels'
|
||||
import { AppText } from './app-text'
|
||||
import AppText from './app-text'
|
||||
|
||||
export default class Stats extends Component {
|
||||
render() {
|
||||
|
||||
-152
@@ -1,152 +0,0 @@
|
||||
function convertToSymptoFormat(val) {
|
||||
const sympto = { date: val.date }
|
||||
if (val.bleeding) sympto.bleeding = {
|
||||
value: val.bleeding,
|
||||
exclude: false
|
||||
}
|
||||
if (val.temperature) sympto.temperature = {
|
||||
value: val.temperature,
|
||||
time: '08:00',
|
||||
exclude: false
|
||||
}
|
||||
if (val.mucus) sympto.mucus = {
|
||||
value: val.mucus,
|
||||
feeling: val.mucus,
|
||||
texture: val.mucus,
|
||||
exclude: false
|
||||
}
|
||||
if (val.cervix && typeof val.cervix.opening === 'number' && typeof val.cervix.firmness === 'number') sympto.cervix = {
|
||||
opening: val.cervix.opening,
|
||||
firmness: val.cervix.firmness,
|
||||
exclude: false
|
||||
}
|
||||
return sympto
|
||||
}
|
||||
|
||||
export const cycleWithFhmMucus = [
|
||||
{ date: '2018-07-01', bleeding: 2 },
|
||||
{ date: '2018-07-02', bleeding: 1 },
|
||||
{ date: '2018-07-06', temperature: 36.2},
|
||||
{ date: '2018-07-07', temperature: 36.35 },
|
||||
{ date: '2018-07-09', temperature: 36.6 },
|
||||
{ date: '2018-07-10', temperature: 36.45 },
|
||||
{ date: '2018-07-12', temperature: 36.7, mucus: 0 },
|
||||
{ date: '2018-07-13', temperature: 36.8, mucus: 4 },
|
||||
{ date: '2018-07-15', temperature: 36.9, mucus: 2 },
|
||||
{ date: '2018-07-16', temperature: 36.95, mucus: 2 },
|
||||
{ date: '2018-07-17', temperature: 36.9, mucus: 2 },
|
||||
{ date: '2018-07-18', temperature: 36.9, mucus: 2 }
|
||||
].map(convertToSymptoFormat).reverse()
|
||||
|
||||
export const longAndComplicatedCycleWithMucus = [
|
||||
{ date: '2018-06-01', temperature: 36.6, bleeding: 2 },
|
||||
{ date: '2018-06-02', temperature: 36.65 },
|
||||
{ date: '2018-06-04', temperature: 36.6 },
|
||||
{ date: '2018-06-05', temperature: 36.55 },
|
||||
{ date: '2018-06-06', temperature: 36.7, mucus: 0 },
|
||||
{ date: '2018-06-09', temperature: 36.5, mucus: 4 },
|
||||
{ date: '2018-06-10', temperature: 36.4, mucus: 2 },
|
||||
{ date: '2018-06-13', temperature: 36.45, mucus: 3 },
|
||||
{ date: '2018-06-14', temperature: 36.5, mucus: 4 },
|
||||
{ date: '2018-06-15', temperature: 36.55, mucus: 4 },
|
||||
{ date: '2018-06-16', temperature: 36.7, mucus: 3 },
|
||||
{ date: '2018-06-17', temperature: 36.65, mucus: 3 },
|
||||
{ date: '2018-06-18', temperature: 36.75, mucus: 4 },
|
||||
{ date: '2018-06-19', temperature: 36.8, mucus: 1 },
|
||||
{ date: '2018-06-20', temperature: 36.85, mucus: 2 },
|
||||
{ date: '2018-06-21', temperature: 36.8, mucus: 2 },
|
||||
{ date: '2018-06-22', temperature: 36.9, mucus: 2 },
|
||||
{ date: '2018-06-25', temperature: 36.9, mucus: 1 },
|
||||
{ date: '2018-06-26', temperature: 36.8, mucus: 1 },
|
||||
{ date: '2018-06-27', temperature: 36.9, mucus: 1 }
|
||||
].map(convertToSymptoFormat).reverse()
|
||||
|
||||
export const cycleWithTempAndNoMucusShift = [
|
||||
{ date: '2018-05-01', temperature: 36.6, bleeding: 2 },
|
||||
{ date: '2018-05-02', temperature: 36.65 },
|
||||
{ date: '2018-05-05', temperature: 36.55 },
|
||||
{ date: '2018-05-06', temperature: 36.7, mucus: 0 },
|
||||
{ date: '2018-05-08', temperature: 36.45, mucus: 1 },
|
||||
{ date: '2018-05-09', temperature: 36.5, mucus: 4 },
|
||||
{ date: '2018-05-10', temperature: 36.4, mucus: 2 },
|
||||
{ date: '2018-05-11', temperature: 36.5, mucus: 3 },
|
||||
{ date: '2018-05-13', temperature: 36.45, mucus: 3 },
|
||||
{ date: '2018-05-14', temperature: 36.5, mucus: 4 },
|
||||
{ date: '2018-05-15', temperature: 36.55, mucus: 4 },
|
||||
{ date: '2018-05-16', temperature: 36.7, mucus: 3 },
|
||||
{ date: '2018-05-17', temperature: 36.65, mucus: 3 },
|
||||
{ date: '2018-05-18', temperature: 36.75, mucus: 4 },
|
||||
{ date: '2018-05-19', temperature: 36.8, mucus: 4 },
|
||||
{ date: '2018-05-20', temperature: 36.85, mucus: 4 },
|
||||
{ date: '2018-05-23', temperature: 36.9, mucus: 3 },
|
||||
{ date: '2018-05-24', temperature: 36.85, mucus: 4 },
|
||||
{ date: '2018-05-26', temperature: 36.8, mucus: 4 },
|
||||
{ date: '2018-05-27', temperature: 36.9, mucus: 4 }
|
||||
].map(convertToSymptoFormat).reverse()
|
||||
|
||||
export const cervixShiftAndFhmOnSameDay = [
|
||||
{ date: '2018-08-01', bleeding: 2 },
|
||||
{ date: '2018-08-02', bleeding: 1 },
|
||||
{ date: '2018-08-03', bleeding: 0 },
|
||||
{ date: '2018-08-04', bleeding: 0 },
|
||||
{ date: '2018-08-05', temperature: 36.07 },
|
||||
{ date: '2018-08-06', temperature: 36.2 },
|
||||
{ date: '2018-08-07', temperature: 36.35 },
|
||||
{ date: '2018-08-08', temperature: 36.4 },
|
||||
{ date: '2018-08-09', temperature: 36.3 },
|
||||
{ date: '2018-08-10', temperature: 36.45 },
|
||||
{ date: '2018-08-11', temperature: 36.45 },
|
||||
{ date: '2018-08-12', temperature: 36.7, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-08-13', temperature: 36.8, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-08-14', temperature: 36.75, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-08-15', temperature: 36.9, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-08-16', temperature: 36.95, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-08-17', temperature: 36.9, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-08-18', temperature: 36.9, cervix: { opening: 1, firmness: 0 } }
|
||||
].map(convertToSymptoFormat).reverse()
|
||||
|
||||
export const longAndComplicatedCycleWithCervix = [
|
||||
{ date: '2018-06-01', temperature: 36.6, bleeding: 2 },
|
||||
{ date: '2018-06-02', temperature: 36.65 },
|
||||
{ date: '2018-06-04', temperature: 36.6 },
|
||||
{ date: '2018-06-05', temperature: 36.55 },
|
||||
{ date: '2018-06-06', temperature: 36.7, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-06-09', temperature: 36.5, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-06-10', temperature: 36.4, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-06-13', temperature: 36.45, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-06-14', temperature: 36.5, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-06-15', temperature: 36.55, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-06-16', temperature: 36.7, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-06-17', temperature: 36.65, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-06-18', temperature: 36.75, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-06-19', temperature: 36.8, cervix: { opening: 1, firmness: 0 } },
|
||||
{ date: '2018-06-20', temperature: 36.85, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-06-21', temperature: 36.8, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-06-22', temperature: 36.9, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-06-25', temperature: 36.9, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-06-26', temperature: 36.8, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-06-27', temperature: 36.9, cervix: { opening: 1, firmness: 1 } }
|
||||
].map(convertToSymptoFormat).reverse()
|
||||
|
||||
export const cycleWithTempAndNoCervixShift = [
|
||||
{ date: '2018-07-01', temperature: 36.6, bleeding: 2 },
|
||||
{ date: '2018-07-02', temperature: 36.65 },
|
||||
{ date: '2018-07-05', temperature: 36.55 },
|
||||
{ date: '2018-07-06', temperature: 36.7, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-07-08', temperature: 36.45, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-07-09', temperature: 36.5, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-07-10', temperature: 36.4, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-07-11', temperature: 36.5, cervix: { opening: 0, firmness: 1 } },
|
||||
{ date: '2018-07-13', temperature: 36.45, cervix: { opening: 0, firmness: 1 } },
|
||||
{ date: '2018-07-14', temperature: 36.5, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-07-15', temperature: 36.55, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-07-16', temperature: 36.7, cervix: { opening: 0, firmness: 1 } },
|
||||
{ date: '2018-07-17', temperature: 36.65, cervix: { opening: 0, firmness: 1 } },
|
||||
{ date: '2018-07-18', temperature: 36.75, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-07-19', temperature: 36.8, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-07-20', temperature: 36.85, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-07-23', temperature: 36.9, cervix: { opening: 0, firmness: 1 } },
|
||||
{ date: '2018-07-24', temperature: 36.85, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-07-26', temperature: 36.8, cervix: { opening: 1, firmness: 1 } },
|
||||
{ date: '2018-07-27', temperature: 36.9, cervix: { opening: 1, firmness: 1 } }
|
||||
].map(convertToSymptoFormat).reverse()
|
||||
-58
@@ -3,14 +3,6 @@ import { LocalDate, ChronoUnit } from 'js-joda'
|
||||
import nodejs from 'nodejs-mobile-react-native'
|
||||
import fs from 'react-native-fs'
|
||||
import restart from 'react-native-restart'
|
||||
import {
|
||||
cycleWithFhmMucus,
|
||||
longAndComplicatedCycleWithMucus,
|
||||
cycleWithTempAndNoMucusShift,
|
||||
cervixShiftAndFhmOnSameDay,
|
||||
longAndComplicatedCycleWithCervix,
|
||||
cycleWithTempAndNoCervixShift
|
||||
} from './fixtures'
|
||||
import schemas from './schemas'
|
||||
|
||||
let db
|
||||
@@ -75,56 +67,6 @@ export function getCycleDay(localDate) {
|
||||
return db.objectForPrimaryKey('CycleDay', localDate)
|
||||
}
|
||||
|
||||
export function fillWithMucusDummyData() {
|
||||
const dummyCycles = [
|
||||
cycleWithFhmMucus,
|
||||
longAndComplicatedCycleWithMucus,
|
||||
cycleWithTempAndNoMucusShift
|
||||
]
|
||||
|
||||
db.write(() => {
|
||||
db.deleteAll()
|
||||
dummyCycles.forEach(cycle => {
|
||||
cycle.forEach(day => {
|
||||
const existing = getCycleDay(day.date)
|
||||
if (existing) {
|
||||
Object.keys(day).forEach(key => {
|
||||
if (key === 'date') return
|
||||
existing[key] = day[key]
|
||||
})
|
||||
} else {
|
||||
db.create('CycleDay', day)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function fillWithCervixDummyData() {
|
||||
const dummyCycles = [
|
||||
cervixShiftAndFhmOnSameDay,
|
||||
longAndComplicatedCycleWithCervix,
|
||||
cycleWithTempAndNoCervixShift
|
||||
]
|
||||
|
||||
db.write(() => {
|
||||
db.deleteAll()
|
||||
dummyCycles.forEach(cycle => {
|
||||
cycle.forEach(day => {
|
||||
const existing = getCycleDay(day.date)
|
||||
if (existing) {
|
||||
Object.keys(day).forEach(key => {
|
||||
if (key === 'date') return
|
||||
existing[key] = day[key]
|
||||
})
|
||||
} else {
|
||||
db.create('CycleDay', day)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function getPreviousTemperature(cycleDay) {
|
||||
cycleDay.wrappedDate = LocalDate.parse(cycleDay.date)
|
||||
const winner = getTemperatureDaysSortedByDate().find(day => {
|
||||
|
||||
+27
-8
@@ -1,10 +1,13 @@
|
||||
import getFertilityStatus from './sympto'
|
||||
import cycleModule from './cycle'
|
||||
import { fertilityStatus } from '../components/cycle-day/labels/labels'
|
||||
import { fertilityStatus } from '../components/labels'
|
||||
|
||||
export function getFertilityStatusStringForDay(dateString) {
|
||||
export function getFertilityStatusForDay(dateString) {
|
||||
const status = getCycleStatusForDay(dateString)
|
||||
if (!status) return fertilityStatus.unknown
|
||||
if (!status) return {
|
||||
status: fertilityStatus.fertile,
|
||||
phase: null
|
||||
}
|
||||
|
||||
const phaseNameForDay = Object.keys(status.phases).find(phaseName => {
|
||||
const phase = status.phases[phaseName]
|
||||
@@ -18,7 +21,7 @@ export function getFertilityStatusStringForDay(dateString) {
|
||||
return dayIsAfterPhaseStart && dayIsBeforePhaseEnd
|
||||
})
|
||||
|
||||
return mapToString(phaseNameForDay, dateString, status)
|
||||
return formatStatus(phaseNameForDay, dateString, status)
|
||||
}
|
||||
|
||||
export function getCycleStatusForDay(dateString) {
|
||||
@@ -46,17 +49,33 @@ export function getCycleStatusForDay(dateString) {
|
||||
return getFertilityStatus(cycleInfo)
|
||||
}
|
||||
|
||||
function mapToString(phaseNameForDay, dateString, status) {
|
||||
function formatStatus(phaseNameForDay, dateString, status) {
|
||||
const mapping = {
|
||||
preOvulatory: () => fertilityStatus.infertile,
|
||||
preOvulatory: () => {
|
||||
return {
|
||||
status: fertilityStatus.infertile,
|
||||
phase: 1,
|
||||
statusText: fertilityStatus.preOvuText
|
||||
}
|
||||
},
|
||||
periOvulatory: (dateString, status) => {
|
||||
const phaseEnd = status.phases.periOvulatory.end
|
||||
if (phaseEnd && phaseEnd.date === dateString) {
|
||||
return fertilityStatus.fertileUntilEvening
|
||||
}
|
||||
return fertilityStatus.fertile
|
||||
return {
|
||||
status: fertilityStatus.fertile,
|
||||
phase: 2,
|
||||
statusText: fertilityStatus.periOvuText
|
||||
}
|
||||
},
|
||||
postOvulatory: () => fertilityStatus.infertile
|
||||
postOvulatory: (dateString, status) => {
|
||||
return {
|
||||
status: fertilityStatus.infertile,
|
||||
phase: 3,
|
||||
statusText: fertilityStatus.postOvuText(status.temperatureShift.rule)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mapping[phaseNameForDay](dateString, status)
|
||||
|
||||
@@ -35,6 +35,7 @@ export default function getSymptoThermalStatus(cycleInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO maybe add indicator if there was no preovuphase?
|
||||
status.phases.periOvulatory = {
|
||||
start: { date: null },
|
||||
cycleDays: []
|
||||
|
||||
+59
-6
@@ -10,6 +10,8 @@ export const shadesOfRed = [
|
||||
'#cf323d',
|
||||
'#c3000d'
|
||||
] // light to dark
|
||||
export const cycleDayColor = '#29287f'
|
||||
export const periodColor = '#802249'
|
||||
|
||||
const fontRegular = 'Prompt-Light'
|
||||
const fontLight = 'Prompt-Thin'
|
||||
@@ -27,6 +29,11 @@ export default StyleSheet.create({
|
||||
fontFamily: fontRegular,
|
||||
fontSize: regularSize
|
||||
},
|
||||
appTextLight: {
|
||||
color: 'black',
|
||||
fontFamily: fontLight,
|
||||
fontSize: regularSize
|
||||
},
|
||||
paragraph: {
|
||||
marginBottom: defaultBottomMargin
|
||||
},
|
||||
@@ -69,6 +76,58 @@ export default StyleSheet.create({
|
||||
borderRadius: 100,
|
||||
position: 'absolute'
|
||||
},
|
||||
homeView: {
|
||||
marginHorizontal: 50,
|
||||
marginTop: 20,
|
||||
},
|
||||
homeButton: {
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 20,
|
||||
borderRadius: 5,
|
||||
alignItems: 'center',
|
||||
width: 200,
|
||||
},
|
||||
homeButtonText: {
|
||||
color: fontOnPrimaryColor
|
||||
},
|
||||
homeIconElement: {
|
||||
alignItems: 'center',
|
||||
marginBottom: 10
|
||||
},
|
||||
homeIconTextWrapper: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginBottom: 10,
|
||||
},
|
||||
wrapperCycle: {
|
||||
width: 70,
|
||||
height: 75
|
||||
},
|
||||
wrapperDrop: {
|
||||
width: 80,
|
||||
height: 80,
|
||||
marginTop: 20
|
||||
},
|
||||
homeCircle: {
|
||||
borderRadius: 100,
|
||||
borderWidth: 0.5,
|
||||
width: 80,
|
||||
height: 80,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
borderColor: secondaryColor,
|
||||
},
|
||||
iconText: {
|
||||
fontSize: 25
|
||||
},
|
||||
showMore: {
|
||||
transform: [{rotate: '90deg'}],
|
||||
position: 'absolute',
|
||||
},
|
||||
showLess: {
|
||||
transform: [{rotate: '270deg'}],
|
||||
position: 'absolute'
|
||||
},
|
||||
cycleDayNumber: {
|
||||
fontSize: 15,
|
||||
color: fontOnPrimaryColor,
|
||||
@@ -168,12 +227,6 @@ export default StyleSheet.create({
|
||||
fontSize: 60,
|
||||
color: fontOnPrimaryColor
|
||||
},
|
||||
homeButtons: {
|
||||
marginHorizontal: 15
|
||||
},
|
||||
homeButton: {
|
||||
marginBottom: 15
|
||||
},
|
||||
temperatureTextInput: {
|
||||
fontSize: 20,
|
||||
color: 'black',
|
||||
|
||||
Reference in New Issue
Block a user