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() {
|
export default function HomeCycleIcon() {
|
||||||
return (
|
return (
|
||||||
<Svg width={140} height={100} viewBox='200 200 350 350'>
|
<Svg width={80} height={80} viewBox='340 345 170 170'>
|
||||||
<G>
|
<G>
|
||||||
<Path fill="none" stroke="#1E0B7A" strokeWidth="2" d="M379.708,350.568
|
<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
|
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 { Text } from 'react-native'
|
||||||
import styles from "../styles"
|
import styles from "../styles"
|
||||||
|
|
||||||
export class AppText extends Component {
|
export default class AppText extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Text style={[styles.appText, this.props.style]}>
|
<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 {
|
export class SymptomSectionHeader extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
+5
-11
@@ -40,20 +40,18 @@ export default class App extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
navigate = (pageName, props) => {
|
navigate = (pageName, props) => {
|
||||||
const curr = this.state.currentPage
|
this.origin = this.state.currentPage
|
||||||
if (navigatingToCycleDayFromMainMenuEntry(pageName, curr)) {
|
|
||||||
this.cycleDayOrigin = curr
|
|
||||||
}
|
|
||||||
this.setState({currentPage: pageName, currentProps: props})
|
this.setState({currentPage: pageName, currentProps: props})
|
||||||
}
|
}
|
||||||
|
|
||||||
handleBackButtonPress = () => {
|
handleBackButtonPress = () => {
|
||||||
if (this.state.currentPage === 'Home') return false
|
if (this.state.currentPage === 'Home') return false
|
||||||
if (isSymptomView(this.state.currentPage)) {
|
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') {
|
} else if(this.state.currentPage === 'CycleDay') {
|
||||||
this.navigate(this.cycleDayOrigin || 'Home')
|
this.navigate(this.origin)
|
||||||
this.cycleDayOrigin = null
|
|
||||||
} else {
|
} else {
|
||||||
this.navigate('Home')
|
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 styles from './styles'
|
||||||
import { scaleObservable } from '../../local-storage'
|
import { scaleObservable } from '../../local-storage'
|
||||||
import config from '../../config'
|
import config from '../../config'
|
||||||
import { AppText } from '../app-text'
|
import AppText from '../app-text'
|
||||||
import { shared as labels } from '../labels'
|
import { shared as labels } from '../labels'
|
||||||
import BleedingIcon from '../../assets/bleeding'
|
import BleedingIcon from '../../assets/bleeding'
|
||||||
import CervixIcon from '../../assets/cervix'
|
import CervixIcon from '../../assets/cervix'
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { View } from 'react-native'
|
|||||||
import config from '../../config'
|
import config from '../../config'
|
||||||
import styles from './styles'
|
import styles from './styles'
|
||||||
import { scaleObservable, unitObservable } from '../../local-storage'
|
import { scaleObservable, unitObservable } from '../../local-storage'
|
||||||
import { AppText } from '../app-text'
|
import AppText from '../app-text'
|
||||||
|
|
||||||
export function makeYAxisLabels(columnHeight) {
|
export function makeYAxisLabels(columnHeight) {
|
||||||
const units = unitObservable.value
|
const units = unitObservable.value
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import Header from '../header'
|
|||||||
import { getOrCreateCycleDay } from '../../db'
|
import { getOrCreateCycleDay } from '../../db'
|
||||||
import cycleModule from '../../lib/cycle'
|
import cycleModule from '../../lib/cycle'
|
||||||
import styles from '../../styles'
|
import styles from '../../styles'
|
||||||
import * as labels from './labels/labels'
|
import * as labels from './labels'
|
||||||
import { AppText } from '../app-text'
|
import AppText from '../app-text'
|
||||||
import BleedingIcon from '../../assets/bleeding'
|
import BleedingIcon from '../../assets/bleeding'
|
||||||
import CervixIcon from '../../assets/cervix'
|
import CervixIcon from '../../assets/cervix'
|
||||||
import DesireIcon from '../../assets/desire'
|
import DesireIcon from '../../assets/desire'
|
||||||
|
|||||||
@@ -65,13 +65,6 @@ export const pain = {
|
|||||||
explainer: 'How did your body feel today?'
|
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 = {
|
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.',
|
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.',
|
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,
|
TouchableOpacity,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import styles from '../../styles'
|
import styles from '../../styles'
|
||||||
import { AppText } from '../app-text'
|
import AppText from '../app-text'
|
||||||
|
|
||||||
export default class SelectBoxGroup extends Component {
|
export default class SelectBoxGroup extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import styles from '../../styles'
|
import styles from '../../styles'
|
||||||
import { AppText } from '../app-text'
|
import AppText from '../app-text'
|
||||||
|
|
||||||
export default class SelectTabGroup extends Component {
|
export default class SelectTabGroup extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons'
|
import Icon from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||||
import { saveSymptom } from '../../../db'
|
import { saveSymptom } from '../../../db'
|
||||||
import styles, {iconStyles} from '../../../styles'
|
import styles, {iconStyles} from '../../../styles'
|
||||||
import {sharedDialogs as labels} from '../labels/labels'
|
import {sharedDialogs as labels} from '../labels'
|
||||||
|
|
||||||
export default class ActionButtonFooter extends Component {
|
export default class ActionButtonFooter extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import styles from '../../../styles'
|
import styles from '../../../styles'
|
||||||
import { saveSymptom } from '../../../db'
|
import { saveSymptom } from '../../../db'
|
||||||
import { bleeding as labels } from '../labels/labels'
|
import { bleeding as labels } from '../labels'
|
||||||
import ActionButtonFooter from './action-button-footer'
|
import ActionButtonFooter from './action-button-footer'
|
||||||
import SelectTabGroup from '../select-tab-group'
|
import SelectTabGroup from '../select-tab-group'
|
||||||
import SymptomSection from './symptom-section'
|
import SymptomSection from './symptom-section'
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import styles from '../../../styles'
|
import styles from '../../../styles'
|
||||||
import { saveSymptom } from '../../../db'
|
import { saveSymptom } from '../../../db'
|
||||||
import { cervix as labels } from '../labels/labels'
|
import { cervix as labels } from '../labels'
|
||||||
import ActionButtonFooter from './action-button-footer'
|
import ActionButtonFooter from './action-button-footer'
|
||||||
import SelectTabGroup from '../select-tab-group'
|
import SelectTabGroup from '../select-tab-group'
|
||||||
import SymptomSection from './symptom-section'
|
import SymptomSection from './symptom-section'
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import styles from '../../../styles'
|
import styles from '../../../styles'
|
||||||
import { saveSymptom } from '../../../db'
|
import { saveSymptom } from '../../../db'
|
||||||
import { intensity, desire } from '../labels/labels'
|
import { intensity, desire } from '../labels'
|
||||||
import ActionButtonFooter from './action-button-footer'
|
import ActionButtonFooter from './action-button-footer'
|
||||||
import SelectTabGroup from '../select-tab-group'
|
import SelectTabGroup from '../select-tab-group'
|
||||||
import SymptomSection from './symptom-section'
|
import SymptomSection from './symptom-section'
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import styles from '../../../styles'
|
import styles from '../../../styles'
|
||||||
import { saveSymptom } from '../../../db'
|
import { saveSymptom } from '../../../db'
|
||||||
import { mucus as labels } from '../labels/labels'
|
import { mucus as labels } from '../labels'
|
||||||
import computeSensiplanValue from '../../../lib/sensiplan-mucus'
|
import computeSensiplanValue from '../../../lib/sensiplan-mucus'
|
||||||
import ActionButtonFooter from './action-button-footer'
|
import ActionButtonFooter from './action-button-footer'
|
||||||
import SelectTabGroup from '../select-tab-group'
|
import SelectTabGroup from '../select-tab-group'
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import styles from '../../../styles'
|
|||||||
import { saveSymptom } from '../../../db'
|
import { saveSymptom } from '../../../db'
|
||||||
import ActionButtonFooter from './action-button-footer'
|
import ActionButtonFooter from './action-button-footer'
|
||||||
import SymptomSection from './symptom-section'
|
import SymptomSection from './symptom-section'
|
||||||
import { noteExplainer } from '../labels/labels'
|
import { noteExplainer } from '../labels'
|
||||||
|
|
||||||
export default class Note extends Component {
|
export default class Note extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
View
|
View
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import { saveSymptom } from '../../../db'
|
import { saveSymptom } from '../../../db'
|
||||||
import { pain as labels } from '../labels/labels'
|
import { pain as labels } from '../labels'
|
||||||
import ActionButtonFooter from './action-button-footer'
|
import ActionButtonFooter from './action-button-footer'
|
||||||
import SelectBoxGroup from '../select-box-group'
|
import SelectBoxGroup from '../select-box-group'
|
||||||
import SymptomSection from './symptom-section'
|
import SymptomSection from './symptom-section'
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import styles from '../../../styles'
|
import styles from '../../../styles'
|
||||||
import { saveSymptom } from '../../../db'
|
import { saveSymptom } from '../../../db'
|
||||||
import { sex as labels } from '../labels/labels'
|
import { sex as labels } from '../labels'
|
||||||
import ActionButtonFooter from './action-button-footer'
|
import ActionButtonFooter from './action-button-footer'
|
||||||
import SelectBoxGroup from '../select-box-group'
|
import SelectBoxGroup from '../select-box-group'
|
||||||
import SymptomSection from './symptom-section'
|
import SymptomSection from './symptom-section'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import { View } from 'react-native'
|
import { View } from 'react-native'
|
||||||
import { SymptomSectionHeader, AppText } from '../../app-text'
|
import AppText, { SymptomSectionHeader } from '../../app-text'
|
||||||
|
|
||||||
export default class SymptomSection extends Component {
|
export default class SymptomSection extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import DateTimePicker from 'react-native-modal-datetime-picker-nevo'
|
|||||||
import { getPreviousTemperature, saveSymptom } from '../../../db'
|
import { getPreviousTemperature, saveSymptom } from '../../../db'
|
||||||
import styles from '../../../styles'
|
import styles from '../../../styles'
|
||||||
import { LocalTime, ChronoUnit } from 'js-joda'
|
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 { scaleObservable } from '../../../local-storage'
|
||||||
import { shared } from '../../labels'
|
import { shared } from '../../labels'
|
||||||
import ActionButtonFooter from './action-button-footer'
|
import ActionButtonFooter from './action-button-footer'
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
Dimensions
|
Dimensions
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
|
import moment from 'moment'
|
||||||
import styles, { iconStyles } from '../styles'
|
import styles, { iconStyles } from '../styles'
|
||||||
import Icon from 'react-native-vector-icons/Entypo'
|
import Icon from 'react-native-vector-icons/Entypo'
|
||||||
import FeatherIcon from 'react-native-vector-icons/Feather'
|
import FeatherIcon from 'react-native-vector-icons/Feather'
|
||||||
import { formatDateForViewHeader } from '../components/cycle-day/labels/format'
|
|
||||||
|
|
||||||
|
|
||||||
export default class Header extends Component {
|
export default class Header extends Component {
|
||||||
render() {
|
render() {
|
||||||
@@ -27,7 +26,7 @@ export default class Header extends Component {
|
|||||||
/>
|
/>
|
||||||
<View>
|
<View>
|
||||||
<Text style={styles.dateHeader}>
|
<Text style={styles.dateHeader}>
|
||||||
{formatDateForViewHeader(this.props.date)}
|
{moment(this.props.date).format('MMMM Do YYYY')}
|
||||||
</Text>
|
</Text>
|
||||||
{this.props.cycleDayNumber &&
|
{this.props.cycleDayNumber &&
|
||||||
<Text style={styles.cycleDayNumber} >
|
<Text style={styles.cycleDayNumber} >
|
||||||
|
|||||||
+185
-59
@@ -1,108 +1,234 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import {
|
import { ScrollView, View, TouchableOpacity, TouchableHighlight, Dimensions } from 'react-native'
|
||||||
View,
|
|
||||||
Button,
|
|
||||||
Text,
|
|
||||||
ScrollView
|
|
||||||
} from 'react-native'
|
|
||||||
import { LocalDate, ChronoUnit } from 'js-joda'
|
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 cycleModule from '../lib/cycle'
|
||||||
import { getOrCreateCycleDay, getBleedingDaysSortedByDate, fillWithMucusDummyData, fillWithCervixDummyData } from '../db'
|
import { getOrCreateCycleDay, getCycleDaysSortedByDate } from '../db'
|
||||||
import {bleedingPrediction as labels} from './labels'
|
import { getFertilityStatusForDay } from '../lib/sympto-adapter'
|
||||||
|
import styles from '../styles'
|
||||||
|
import AppText, { AppTextLight } from './app-text'
|
||||||
|
|
||||||
export default class Home extends Component {
|
export default class Home extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.getCycleDayNumber = cycleModule().getCycleDayNumber
|
this.getCycleDayNumber = cycleModule().getCycleDayNumber
|
||||||
|
this.getBleedingPrediction = cycleModule().getPredictedMenses
|
||||||
this.todayDateString = LocalDate.now().toString()
|
this.todayDateString = LocalDate.now().toString()
|
||||||
const cycleDayNumber = this.getCycleDayNumber(this.todayDateString)
|
const prediction = this.getBleedingPrediction()
|
||||||
|
const fertilityStatus = getFertilityStatusForDay(this.todayDateString)
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
welcomeText: determineWelcomeText(cycleDayNumber),
|
cycleDayNumber: this.getCycleDayNumber(this.todayDateString),
|
||||||
predictionText: determinePredictionText()
|
predictionText: determinePredictionText(prediction),
|
||||||
|
bleedingPredictionRange: getBleedingPredictionRange(prediction),
|
||||||
|
...fertilityStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bleedingDays = getBleedingDaysSortedByDate()
|
this.cycleDays = getCycleDaysSortedByDate()
|
||||||
this.bleedingDays.addListener(this.setStateWithCurrentText)
|
this.cycleDays.addListener(this.updateState)
|
||||||
}
|
}
|
||||||
|
|
||||||
setStateWithCurrentText = () => {
|
updateState = () => {
|
||||||
const cycleDayNumber = this.getCycleDayNumber(this.todayDateString)
|
const prediction = this.getBleedingPrediction()
|
||||||
|
const fertilityStatus = getFertilityStatusForDay(this.todayDateString)
|
||||||
this.setState({
|
this.setState({
|
||||||
welcomeText: determineWelcomeText(cycleDayNumber),
|
cycleDayNumber: this.getCycleDayNumber(this.todayDateString),
|
||||||
predictionText: determinePredictionText()
|
predictionText: determinePredictionText(prediction),
|
||||||
|
bleedingPredictionRange: getBleedingPredictionRange(prediction),
|
||||||
|
...fertilityStatus
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.bleedingDays.removeListener(this.setStateWithCurrentText)
|
this.cycleDays.removeListener(this.updateState)
|
||||||
}
|
}
|
||||||
|
|
||||||
passTodayToDayView() {
|
passTodayTo(componentName) {
|
||||||
const todayDateString = LocalDate.now().toString()
|
const todayDateString = LocalDate.now().toString()
|
||||||
const cycleDay = getOrCreateCycleDay(todayDateString)
|
const cycleDay = getOrCreateCycleDay(todayDateString)
|
||||||
const navigate = this.props.navigate
|
const navigate = this.props.navigate
|
||||||
navigate('CycleDay', { cycleDay })
|
navigate(componentName, { cycleDay })
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const cycleDayMoreText = this.state.cycleDayNumber ?
|
||||||
|
labels.cycleDayKnown(this.state.cycleDayNumber)
|
||||||
|
:
|
||||||
|
labels.cycleDayNotEnoughInfo
|
||||||
|
|
||||||
|
const {height, width} = Dimensions.get('window')
|
||||||
return (
|
return (
|
||||||
<ScrollView>
|
<View flex={1}>
|
||||||
<Text style={styles.welcome}>{this.state.welcomeText}</Text>
|
<ScrollView>
|
||||||
<Text style={styles.welcome}>{this.state.predictionText}</Text>
|
<View
|
||||||
<View style={styles.homeButtons}>
|
style={styles.homeView}
|
||||||
<View style={styles.homeButton}>
|
>
|
||||||
<Button
|
<TouchableOpacity
|
||||||
onPress={() => this.passTodayToDayView()}
|
onPress={() => this.passTodayTo('CycleDay')}
|
||||||
title="Edit symptoms for today">
|
style={styles.homeIconElement}
|
||||||
</Button>
|
>
|
||||||
|
<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>
|
||||||
<View style={styles.homeButton}>
|
|
||||||
<Button
|
</ScrollView>
|
||||||
onPress={() => fillWithMucusDummyData()}
|
|
||||||
title="fill with example data for mucus&temp">
|
{!this.state.showMore &&
|
||||||
</Button>
|
<TouchableHighlight
|
||||||
</View>
|
onPress={() => this.setState({showMore: true})}
|
||||||
<View style={styles.homeButton}>
|
style={[styles.showMore, {
|
||||||
<Button
|
top: height / 2 - styles.header.height - 30,
|
||||||
onPress={() => fillWithCervixDummyData()}
|
left: width - 40
|
||||||
title="fill with example data for cervix&temp">
|
}]}
|
||||||
</Button>
|
>
|
||||||
</View>
|
<View style={{alignItems: 'center'}}>
|
||||||
</View>
|
<AppTextLight>{shared.more}</AppTextLight>
|
||||||
</ScrollView>
|
<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) {
|
function determinePredictionText(bleedingPrediction) {
|
||||||
const welcomeTextWithCycleDay = `Welcome! Today is day ${cycleDayNumber} of your current cycle`
|
if (!bleedingPrediction.length) return predictLabels.noPrediction
|
||||||
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
|
|
||||||
const todayDate = LocalDate.now()
|
const todayDate = LocalDate.now()
|
||||||
const bleedingStart = LocalDate.parse(bleedingPrediction[0][0])
|
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)) {
|
if (todayDate.isBefore(bleedingStart)) {
|
||||||
return labels.predictionInFuture(
|
return predictLabels.predictionInFuture(
|
||||||
todayDate.until(bleedingStart, ChronoUnit.DAYS),
|
todayDate.until(bleedingStart, ChronoUnit.DAYS),
|
||||||
todayDate.until(bleedingEnd, ChronoUnit.DAYS)
|
todayDate.until(bleedingEnd, ChronoUnit.DAYS)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (todayDate.isAfter(bleedingEnd)) {
|
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)
|
const daysToEnd = todayDate.until(bleedingEnd, ChronoUnit.DAYS)
|
||||||
if (daysToEnd === 0) {
|
if (daysToEnd === 0) {
|
||||||
return labels.predictionStartedNoDaysLeft
|
return predictLabels.predictionStartedNoDaysLeft
|
||||||
} else if (daysToEnd === 1) {
|
} else if (daysToEnd === 1) {
|
||||||
return labels.predictionStarted1DayLeft
|
return predictLabels.predictionStarted1DayLeft
|
||||||
} else {
|
} 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',
|
unlock: 'Unlock',
|
||||||
date: 'Date',
|
date: 'Date',
|
||||||
cycleDayWithLinebreak: 'Cycle\nday',
|
cycleDayWithLinebreak: 'Cycle\nday',
|
||||||
loading: 'Loading ...'
|
loading: 'Loading ...',
|
||||||
|
more: 'more',
|
||||||
|
less: 'less'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const settings = {
|
export const settings = {
|
||||||
@@ -137,4 +139,36 @@ export const passwordPrompt = {
|
|||||||
areYouSureTitle: 'Are you sure?',
|
areYouSureTitle: 'Are you sure?',
|
||||||
areYouSure: 'Are you absolutely sure you want to permanently delete all your data?',
|
areYouSure: 'Are you absolutely sure you want to permanently delete all your data?',
|
||||||
reallyDeleteData: 'Yes, I am sure'
|
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 { View, TextInput, TouchableOpacity, Alert, Image } from 'react-native'
|
||||||
import nodejs from 'nodejs-mobile-react-native'
|
import nodejs from 'nodejs-mobile-react-native'
|
||||||
import { saveEncryptionFlag } from '../local-storage'
|
import { saveEncryptionFlag } from '../local-storage'
|
||||||
import { AppText } from './app-text'
|
import AppText from './app-text'
|
||||||
import styles from '../styles'
|
import styles from '../styles'
|
||||||
import { passwordPrompt as labels, shared } from './labels'
|
import { passwordPrompt as labels, shared } from './labels'
|
||||||
import { requestHash, deleteDbAndOpenNew, openDb } from '../db'
|
import { requestHash, deleteDbAndOpenNew, openDb } from '../db'
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import styles from '../../styles/index'
|
import styles from '../../styles/index'
|
||||||
import { settings as labels } from '../labels'
|
import { settings as labels } from '../labels'
|
||||||
import { AppText } from '../app-text'
|
import AppText from '../app-text'
|
||||||
import TempReminderPicker from './temp-reminder-picker'
|
import TempReminderPicker from './temp-reminder-picker'
|
||||||
import PeriodReminderPicker from './period-reminder'
|
import PeriodReminderPicker from './period-reminder'
|
||||||
import TempSlider from './temp-slider'
|
import TempSlider from './temp-slider'
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import nodejs from 'nodejs-mobile-react-native'
|
import nodejs from 'nodejs-mobile-react-native'
|
||||||
import { AppText } from '../../app-text'
|
import AppText from '../../app-text'
|
||||||
import styles from '../../../styles'
|
import styles from '../../../styles'
|
||||||
import { settings as labels } from '../../labels'
|
import { settings as labels } from '../../labels'
|
||||||
import { requestHash, changeEncryptionAndRestartApp } from '../../../db'
|
import { requestHash, changeEncryptionAndRestartApp } from '../../../db'
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
TouchableOpacity
|
TouchableOpacity
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import nodejs from 'nodejs-mobile-react-native'
|
import nodejs from 'nodejs-mobile-react-native'
|
||||||
import { AppText } from '../../app-text'
|
import AppText from '../../app-text'
|
||||||
import styles from '../../../styles'
|
import styles from '../../../styles'
|
||||||
import { settings as labels } from '../../labels'
|
import { settings as labels } from '../../labels'
|
||||||
import { requestHash, changeEncryptionAndRestartApp } from '../../../db'
|
import { requestHash, changeEncryptionAndRestartApp } from '../../../db'
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { View } from 'react-native'
|
|||||||
import CreatePassword from './create'
|
import CreatePassword from './create'
|
||||||
import ChangePassword from './update'
|
import ChangePassword from './update'
|
||||||
import DeletePassword from './delete'
|
import DeletePassword from './delete'
|
||||||
import { AppText } from '../../app-text'
|
import AppText from '../../app-text'
|
||||||
import {
|
import {
|
||||||
hasEncryptionObservable
|
hasEncryptionObservable
|
||||||
} from '../../../local-storage'
|
} from '../../../local-storage'
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
View,
|
View,
|
||||||
TouchableOpacity} from 'react-native'
|
TouchableOpacity} from 'react-native'
|
||||||
import nodejs from 'nodejs-mobile-react-native'
|
import nodejs from 'nodejs-mobile-react-native'
|
||||||
import { AppText } from '../../app-text'
|
import AppText from '../../app-text'
|
||||||
import styles from '../../../styles'
|
import styles from '../../../styles'
|
||||||
import { settings as labels, shared } from '../../labels'
|
import { settings as labels, shared } from '../../labels'
|
||||||
import { requestHash, changeEncryptionAndRestartApp } from '../../../db'
|
import { requestHash, changeEncryptionAndRestartApp } from '../../../db'
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
View,
|
View,
|
||||||
Switch
|
Switch
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import { AppText } from '../app-text'
|
import AppText from '../app-text'
|
||||||
import {
|
import {
|
||||||
periodReminderObservable,
|
periodReminderObservable,
|
||||||
savePeriodReminder
|
savePeriodReminder
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
Switch
|
Switch
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import DateTimePicker from 'react-native-modal-datetime-picker-nevo'
|
import DateTimePicker from 'react-native-modal-datetime-picker-nevo'
|
||||||
import { AppText } from '../app-text'
|
import AppText from '../app-text'
|
||||||
import {
|
import {
|
||||||
tempReminderObservable,
|
tempReminderObservable,
|
||||||
saveTempReminder
|
saveTempReminder
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import { View } from 'react-native'
|
import { View } from 'react-native'
|
||||||
import Slider from '@ptomasroos/react-native-multi-slider'
|
import Slider from '@ptomasroos/react-native-multi-slider'
|
||||||
import { AppText } from '../app-text'
|
import AppText from '../app-text'
|
||||||
import {
|
import {
|
||||||
scaleObservable,
|
scaleObservable,
|
||||||
saveTempScale,
|
saveTempScale,
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ import styles from '../styles/index'
|
|||||||
import cycleModule from '../lib/cycle'
|
import cycleModule from '../lib/cycle'
|
||||||
import {getCycleLengthStats as getCycleInfo} from '../lib/cycle-length'
|
import {getCycleLengthStats as getCycleInfo} from '../lib/cycle-length'
|
||||||
import {stats as labels} from './labels'
|
import {stats as labels} from './labels'
|
||||||
import { AppText } from './app-text'
|
import AppText from './app-text'
|
||||||
|
|
||||||
export default class Stats extends Component {
|
export default class Stats extends Component {
|
||||||
render() {
|
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 nodejs from 'nodejs-mobile-react-native'
|
||||||
import fs from 'react-native-fs'
|
import fs from 'react-native-fs'
|
||||||
import restart from 'react-native-restart'
|
import restart from 'react-native-restart'
|
||||||
import {
|
|
||||||
cycleWithFhmMucus,
|
|
||||||
longAndComplicatedCycleWithMucus,
|
|
||||||
cycleWithTempAndNoMucusShift,
|
|
||||||
cervixShiftAndFhmOnSameDay,
|
|
||||||
longAndComplicatedCycleWithCervix,
|
|
||||||
cycleWithTempAndNoCervixShift
|
|
||||||
} from './fixtures'
|
|
||||||
import schemas from './schemas'
|
import schemas from './schemas'
|
||||||
|
|
||||||
let db
|
let db
|
||||||
@@ -75,56 +67,6 @@ export function getCycleDay(localDate) {
|
|||||||
return db.objectForPrimaryKey('CycleDay', 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) {
|
export function getPreviousTemperature(cycleDay) {
|
||||||
cycleDay.wrappedDate = LocalDate.parse(cycleDay.date)
|
cycleDay.wrappedDate = LocalDate.parse(cycleDay.date)
|
||||||
const winner = getTemperatureDaysSortedByDate().find(day => {
|
const winner = getTemperatureDaysSortedByDate().find(day => {
|
||||||
|
|||||||
+27
-8
@@ -1,10 +1,13 @@
|
|||||||
import getFertilityStatus from './sympto'
|
import getFertilityStatus from './sympto'
|
||||||
import cycleModule from './cycle'
|
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)
|
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 phaseNameForDay = Object.keys(status.phases).find(phaseName => {
|
||||||
const phase = status.phases[phaseName]
|
const phase = status.phases[phaseName]
|
||||||
@@ -18,7 +21,7 @@ export function getFertilityStatusStringForDay(dateString) {
|
|||||||
return dayIsAfterPhaseStart && dayIsBeforePhaseEnd
|
return dayIsAfterPhaseStart && dayIsBeforePhaseEnd
|
||||||
})
|
})
|
||||||
|
|
||||||
return mapToString(phaseNameForDay, dateString, status)
|
return formatStatus(phaseNameForDay, dateString, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCycleStatusForDay(dateString) {
|
export function getCycleStatusForDay(dateString) {
|
||||||
@@ -46,17 +49,33 @@ export function getCycleStatusForDay(dateString) {
|
|||||||
return getFertilityStatus(cycleInfo)
|
return getFertilityStatus(cycleInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapToString(phaseNameForDay, dateString, status) {
|
function formatStatus(phaseNameForDay, dateString, status) {
|
||||||
const mapping = {
|
const mapping = {
|
||||||
preOvulatory: () => fertilityStatus.infertile,
|
preOvulatory: () => {
|
||||||
|
return {
|
||||||
|
status: fertilityStatus.infertile,
|
||||||
|
phase: 1,
|
||||||
|
statusText: fertilityStatus.preOvuText
|
||||||
|
}
|
||||||
|
},
|
||||||
periOvulatory: (dateString, status) => {
|
periOvulatory: (dateString, status) => {
|
||||||
const phaseEnd = status.phases.periOvulatory.end
|
const phaseEnd = status.phases.periOvulatory.end
|
||||||
if (phaseEnd && phaseEnd.date === dateString) {
|
if (phaseEnd && phaseEnd.date === dateString) {
|
||||||
return fertilityStatus.fertileUntilEvening
|
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)
|
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 = {
|
status.phases.periOvulatory = {
|
||||||
start: { date: null },
|
start: { date: null },
|
||||||
cycleDays: []
|
cycleDays: []
|
||||||
|
|||||||
+59
-6
@@ -10,6 +10,8 @@ export const shadesOfRed = [
|
|||||||
'#cf323d',
|
'#cf323d',
|
||||||
'#c3000d'
|
'#c3000d'
|
||||||
] // light to dark
|
] // light to dark
|
||||||
|
export const cycleDayColor = '#29287f'
|
||||||
|
export const periodColor = '#802249'
|
||||||
|
|
||||||
const fontRegular = 'Prompt-Light'
|
const fontRegular = 'Prompt-Light'
|
||||||
const fontLight = 'Prompt-Thin'
|
const fontLight = 'Prompt-Thin'
|
||||||
@@ -27,6 +29,11 @@ export default StyleSheet.create({
|
|||||||
fontFamily: fontRegular,
|
fontFamily: fontRegular,
|
||||||
fontSize: regularSize
|
fontSize: regularSize
|
||||||
},
|
},
|
||||||
|
appTextLight: {
|
||||||
|
color: 'black',
|
||||||
|
fontFamily: fontLight,
|
||||||
|
fontSize: regularSize
|
||||||
|
},
|
||||||
paragraph: {
|
paragraph: {
|
||||||
marginBottom: defaultBottomMargin
|
marginBottom: defaultBottomMargin
|
||||||
},
|
},
|
||||||
@@ -69,6 +76,58 @@ export default StyleSheet.create({
|
|||||||
borderRadius: 100,
|
borderRadius: 100,
|
||||||
position: 'absolute'
|
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: {
|
cycleDayNumber: {
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
color: fontOnPrimaryColor,
|
color: fontOnPrimaryColor,
|
||||||
@@ -168,12 +227,6 @@ export default StyleSheet.create({
|
|||||||
fontSize: 60,
|
fontSize: 60,
|
||||||
color: fontOnPrimaryColor
|
color: fontOnPrimaryColor
|
||||||
},
|
},
|
||||||
homeButtons: {
|
|
||||||
marginHorizontal: 15
|
|
||||||
},
|
|
||||||
homeButton: {
|
|
||||||
marginBottom: 15
|
|
||||||
},
|
|
||||||
temperatureTextInput: {
|
temperatureTextInput: {
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
color: 'black',
|
color: 'black',
|
||||||
|
|||||||
Reference in New Issue
Block a user