Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9f3d115aca | |||
| 2f187b1007 | |||
| d78fbf74e3 | |||
| c9430439c5 | |||
| 08712f460e | |||
| 3447a0ea1e | |||
| b4d92d0d7b | |||
| d5f0e3532a |
+6
-30
@@ -4,7 +4,9 @@ import PropTypes from 'prop-types'
|
|||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
|
||||||
import AppText from './common/app-text'
|
import AppText from './common/app-text'
|
||||||
|
import Asterisk from './common/Asterisk'
|
||||||
import Button from './common/button'
|
import Button from './common/button'
|
||||||
|
import Footnote from './common/Footnote'
|
||||||
|
|
||||||
import cycleModule from '../lib/cycle'
|
import cycleModule from '../lib/cycle'
|
||||||
import { getFertilityStatusForDay } from '../lib/sympto-adapter'
|
import { getFertilityStatusForDay } from '../lib/sympto-adapter'
|
||||||
@@ -16,9 +18,11 @@ import {
|
|||||||
import { Colors, Fonts, Sizes, Spacing } from '../styles'
|
import { Colors, Fonts, Sizes, Spacing } from '../styles'
|
||||||
import { LocalDate } from '@js-joda/core'
|
import { LocalDate } from '@js-joda/core'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { useDate } from '../hooks/useDate'
|
||||||
|
|
||||||
const Home = ({ navigate, setDate }) => {
|
const Home = ({ navigate }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const { setDate } = useDate()
|
||||||
|
|
||||||
function navigateToCycleDayView() {
|
function navigateToCycleDayView() {
|
||||||
setDate(todayDateString)
|
setDate(todayDateString)
|
||||||
@@ -69,26 +73,12 @@ const Home = ({ navigate, setDate }) => {
|
|||||||
<Button isCTA isSmall={false} onPress={navigateToCycleDayView}>
|
<Button isCTA isSmall={false} onPress={navigateToCycleDayView}>
|
||||||
{t('labels.home.addDataForToday')}
|
{t('labels.home.addDataForToday')}
|
||||||
</Button>
|
</Button>
|
||||||
{phase && (
|
{phase && <Footnote>{statusText}</Footnote>}
|
||||||
<View style={styles.asteriskLine}>
|
|
||||||
<Asterisk />
|
|
||||||
<AppText linkStyle={styles.whiteText} style={styles.greyText}>
|
|
||||||
{statusText}
|
|
||||||
</AppText>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const Asterisk = () => {
|
|
||||||
return <AppText style={styles.asterisk}>*</AppText>
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
asterisk: {
|
|
||||||
color: Colors.orange,
|
|
||||||
},
|
|
||||||
container: {
|
container: {
|
||||||
backgroundColor: Colors.purple,
|
backgroundColor: Colors.purple,
|
||||||
flex: 1,
|
flex: 1,
|
||||||
@@ -104,12 +94,6 @@ const styles = StyleSheet.create({
|
|||||||
marginBottom: Spacing.tiny,
|
marginBottom: Spacing.tiny,
|
||||||
marginTop: Spacing.small,
|
marginTop: Spacing.small,
|
||||||
},
|
},
|
||||||
asteriskLine: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignContent: 'flex-start',
|
|
||||||
marginBottom: Spacing.tiny,
|
|
||||||
marginTop: Spacing.small,
|
|
||||||
},
|
|
||||||
title: {
|
title: {
|
||||||
color: Colors.purpleLight,
|
color: Colors.purpleLight,
|
||||||
fontFamily: Fonts.bold,
|
fontFamily: Fonts.bold,
|
||||||
@@ -124,18 +108,10 @@ const styles = StyleSheet.create({
|
|||||||
color: 'white',
|
color: 'white',
|
||||||
fontSize: Sizes.subtitle,
|
fontSize: Sizes.subtitle,
|
||||||
},
|
},
|
||||||
whiteText: {
|
|
||||||
color: 'white',
|
|
||||||
},
|
|
||||||
greyText: {
|
|
||||||
color: Colors.greyLight,
|
|
||||||
paddingLeft: Spacing.base,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Home.propTypes = {
|
Home.propTypes = {
|
||||||
navigate: PropTypes.func,
|
navigate: PropTypes.func,
|
||||||
setDate: PropTypes.func,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Home
|
export default Home
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import AppStatusBar from './common/app-status-bar'
|
|||||||
import AcceptLicense from './AcceptLicense'
|
import AcceptLicense from './AcceptLicense'
|
||||||
import PasswordPrompt from './password-prompt'
|
import PasswordPrompt from './password-prompt'
|
||||||
|
|
||||||
|
import { DateProvider } from '../hooks/useDate'
|
||||||
|
|
||||||
export default function AppWrapper() {
|
export default function AppWrapper() {
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
const [isLicenseAccepted, setIsLicenseAccepted] = useState(false)
|
const [isLicenseAccepted, setIsLicenseAccepted] = useState(false)
|
||||||
@@ -47,7 +49,9 @@ export default function AppWrapper() {
|
|||||||
{isDbEncrypted ? (
|
{isDbEncrypted ? (
|
||||||
<PasswordPrompt enableShowApp={() => setIsDbEncrypted(false)} />
|
<PasswordPrompt enableShowApp={() => setIsDbEncrypted(false)} />
|
||||||
) : (
|
) : (
|
||||||
<App restartApp={() => checkIsDbEncrypted()} />
|
<DateProvider>
|
||||||
|
<App restartApp={() => checkIsDbEncrypted()} />
|
||||||
|
</DateProvider>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
+3
-4
@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'
|
|||||||
import { BackHandler, StyleSheet, View } from 'react-native'
|
import { BackHandler, StyleSheet, View } from 'react-native'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
import { LocalDate } from '@js-joda/core'
|
import { useDate } from '../hooks/useDate'
|
||||||
|
|
||||||
import Header from './header'
|
import Header from './header'
|
||||||
import Menu from './menu'
|
import Menu from './menu'
|
||||||
@@ -13,7 +13,8 @@ import setupNotifications from '../lib/notifications'
|
|||||||
import { closeDb } from '../db'
|
import { closeDb } from '../db'
|
||||||
|
|
||||||
const App = ({ restartApp }) => {
|
const App = ({ restartApp }) => {
|
||||||
const [date, setDate] = useState(LocalDate.now().toString())
|
const { setDate } = useDate()
|
||||||
|
|
||||||
const [currentPage, setCurrentPage] = useState('Home')
|
const [currentPage, setCurrentPage] = useState('Home')
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
if (currentPage === 'Home') {
|
if (currentPage === 'Home') {
|
||||||
@@ -43,8 +44,6 @@ const App = ({ restartApp }) => {
|
|||||||
const isTemperatureEditView = currentPage === 'TemperatureEditView'
|
const isTemperatureEditView = currentPage === 'TemperatureEditView'
|
||||||
const headerProps = { navigate: setCurrentPage }
|
const headerProps = { navigate: setCurrentPage }
|
||||||
const pageProps = {
|
const pageProps = {
|
||||||
date,
|
|
||||||
setDate,
|
|
||||||
isTemperatureEditView,
|
isTemperatureEditView,
|
||||||
navigate: setCurrentPage,
|
navigate: setCurrentPage,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import PropTypes from 'prop-types'
|
|||||||
import { StyleSheet, View } from 'react-native'
|
import { StyleSheet, View } from 'react-native'
|
||||||
import { CalendarList } from 'react-native-calendars'
|
import { CalendarList } from 'react-native-calendars'
|
||||||
|
|
||||||
|
import { useDate } from '../hooks/useDate'
|
||||||
|
|
||||||
import { getBleedingDaysSortedByDate } from '../db'
|
import { getBleedingDaysSortedByDate } from '../db'
|
||||||
import cycleModule from '../lib/cycle'
|
import cycleModule from '../lib/cycle'
|
||||||
import {
|
import {
|
||||||
@@ -12,7 +14,8 @@ import {
|
|||||||
todayToCalFormat,
|
todayToCalFormat,
|
||||||
} from './helpers/calendar'
|
} from './helpers/calendar'
|
||||||
|
|
||||||
const CalendarView = ({ setDate, navigate }) => {
|
const CalendarView = ({ navigate }) => {
|
||||||
|
const { setDate } = useDate()
|
||||||
const bleedingDays = getBleedingDaysSortedByDate()
|
const bleedingDays = getBleedingDaysSortedByDate()
|
||||||
const predictedMenses = cycleModule().getPredictedMenses()
|
const predictedMenses = cycleModule().getPredictedMenses()
|
||||||
|
|
||||||
@@ -49,7 +52,6 @@ const styles = StyleSheet.create({
|
|||||||
})
|
})
|
||||||
|
|
||||||
CalendarView.propTypes = {
|
CalendarView.propTypes = {
|
||||||
setDate: PropTypes.func.isRequired,
|
|
||||||
navigate: PropTypes.func.isRequired,
|
navigate: PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,12 +28,24 @@ import { Spacing } from '../../styles'
|
|||||||
const getSymptomsFromCycleDays = (cycleDays) =>
|
const getSymptomsFromCycleDays = (cycleDays) =>
|
||||||
SYMPTOMS.filter((symptom) => cycleDays.some((cycleDay) => cycleDay[symptom]))
|
SYMPTOMS.filter((symptom) => cycleDays.some((cycleDay) => cycleDay[symptom]))
|
||||||
|
|
||||||
const CycleChart = ({ navigate, setDate }) => {
|
const CycleChart = ({ navigate }) => {
|
||||||
const [shouldShowHint, setShouldShowHint] = useState(true)
|
const [shouldShowHint, setShouldShowHint] = useState(true)
|
||||||
|
|
||||||
useEffect(async () => {
|
useEffect(() => {
|
||||||
const flag = await getChartFlag()
|
let isMounted = true
|
||||||
setShouldShowHint(flag === 'true')
|
|
||||||
|
async function checkShouldShowHint() {
|
||||||
|
const flag = await getChartFlag()
|
||||||
|
if (isMounted) {
|
||||||
|
setShouldShowHint(flag === 'true')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkShouldShowHint()
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
isMounted = false
|
||||||
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const hideHint = () => {
|
const hideHint = () => {
|
||||||
@@ -72,7 +84,6 @@ const CycleChart = ({ navigate, setDate }) => {
|
|||||||
const renderColumn = ({ item }) => {
|
const renderColumn = ({ item }) => {
|
||||||
return (
|
return (
|
||||||
<DayColumn
|
<DayColumn
|
||||||
setDate={setDate}
|
|
||||||
dateString={item}
|
dateString={item}
|
||||||
navigate={navigate}
|
navigate={navigate}
|
||||||
symptomHeight={symptomHeight}
|
symptomHeight={symptomHeight}
|
||||||
@@ -124,7 +135,6 @@ const CycleChart = ({ navigate, setDate }) => {
|
|||||||
|
|
||||||
CycleChart.propTypes = {
|
CycleChart.propTypes = {
|
||||||
navigate: PropTypes.func,
|
navigate: PropTypes.func,
|
||||||
setDate: PropTypes.func,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import SymptomCell from './symptom-cell'
|
|||||||
import TemperatureColumn from './temperature-column'
|
import TemperatureColumn from './temperature-column'
|
||||||
import CycleDayLabel from './cycle-day-label'
|
import CycleDayLabel from './cycle-day-label'
|
||||||
|
|
||||||
|
import { useDate } from '../../hooks/useDate'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
symptomColorMethods,
|
symptomColorMethods,
|
||||||
getTemperatureProps,
|
getTemperatureProps,
|
||||||
@@ -19,13 +21,13 @@ const DayColumn = ({
|
|||||||
dateString,
|
dateString,
|
||||||
chartSymptoms,
|
chartSymptoms,
|
||||||
columnHeight,
|
columnHeight,
|
||||||
setDate,
|
|
||||||
navigate,
|
navigate,
|
||||||
shouldShowTemperatureColumn,
|
shouldShowTemperatureColumn,
|
||||||
symptomHeight,
|
symptomHeight,
|
||||||
symptomRowSymptoms,
|
symptomRowSymptoms,
|
||||||
xAxisHeight,
|
xAxisHeight,
|
||||||
}) => {
|
}) => {
|
||||||
|
const { setDate } = useDate()
|
||||||
const cycleDayData = getCycleDay(dateString)
|
const cycleDayData = getCycleDay(dateString)
|
||||||
let data = {}
|
let data = {}
|
||||||
|
|
||||||
@@ -105,7 +107,6 @@ DayColumn.propTypes = {
|
|||||||
chartSymptoms: PropTypes.array,
|
chartSymptoms: PropTypes.array,
|
||||||
columnHeight: PropTypes.number.isRequired,
|
columnHeight: PropTypes.number.isRequired,
|
||||||
navigate: PropTypes.func.isRequired,
|
navigate: PropTypes.func.isRequired,
|
||||||
setDate: PropTypes.func.isRequired,
|
|
||||||
shouldShowTemperatureColumn: PropTypes.bool,
|
shouldShowTemperatureColumn: PropTypes.bool,
|
||||||
symptomHeight: PropTypes.number.isRequired,
|
symptomHeight: PropTypes.number.isRequired,
|
||||||
symptomRowSymptoms: PropTypes.array,
|
symptomRowSymptoms: PropTypes.array,
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { StyleSheet } from 'react-native'
|
||||||
|
|
||||||
|
import AppText from './app-text'
|
||||||
|
|
||||||
|
import { Colors } from '../../styles'
|
||||||
|
|
||||||
|
const Asterisk = () => <AppText style={styles.asterisk}>*</AppText>
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
asterisk: {
|
||||||
|
color: Colors.orange,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default Asterisk
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { StyleSheet, View } from 'react-native'
|
||||||
|
|
||||||
|
import AppText from '../common/app-text'
|
||||||
|
import Asterisk from '../common/Asterisk'
|
||||||
|
|
||||||
|
import { Colors, Spacing } from '../../styles'
|
||||||
|
|
||||||
|
const Footnote = ({ children }) => {
|
||||||
|
if (!children) return false
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Asterisk />
|
||||||
|
<AppText linkStyle={styles.link} style={styles.text}>
|
||||||
|
{children}
|
||||||
|
</AppText>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Footnote.propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignContent: 'flex-start',
|
||||||
|
marginBottom: Spacing.tiny,
|
||||||
|
marginTop: Spacing.small,
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
color: 'white',
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
color: Colors.greyLight,
|
||||||
|
paddingLeft: Spacing.base,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default Footnote
|
||||||
@@ -9,10 +9,13 @@ import SymptomPageTitle from './symptom-page-title'
|
|||||||
import { getCycleDay } from '../../db'
|
import { getCycleDay } from '../../db'
|
||||||
import { getData, nextDate, prevDate } from '../helpers/cycle-day'
|
import { getData, nextDate, prevDate } from '../helpers/cycle-day'
|
||||||
|
|
||||||
|
import { useDate } from '../../hooks/useDate'
|
||||||
|
|
||||||
import { Spacing } from '../../styles'
|
import { Spacing } from '../../styles'
|
||||||
import { SYMPTOMS } from '../../config'
|
import { SYMPTOMS } from '../../config'
|
||||||
|
|
||||||
const CycleDayOverView = ({ date, setDate, isTemperatureEditView }) => {
|
const CycleDayOverView = ({ isTemperatureEditView }) => {
|
||||||
|
const { date, setDate } = useDate()
|
||||||
const cycleDay = getCycleDay(date)
|
const cycleDay = getCycleDay(date)
|
||||||
|
|
||||||
const [editedSymptom, setEditedSymptom] = useState(
|
const [editedSymptom, setEditedSymptom] = useState(
|
||||||
@@ -58,8 +61,6 @@ const CycleDayOverView = ({ date, setDate, isTemperatureEditView }) => {
|
|||||||
|
|
||||||
CycleDayOverView.propTypes = {
|
CycleDayOverView.propTypes = {
|
||||||
cycleDay: PropTypes.object,
|
cycleDay: PropTypes.object,
|
||||||
date: PropTypes.string,
|
|
||||||
setDate: PropTypes.func,
|
|
||||||
isTemperatureEditView: PropTypes.bool,
|
isTemperatureEditView: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react'
|
|||||||
import { StyleSheet, View } from 'react-native'
|
import { StyleSheet, View } from 'react-native'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
import AppText from './app-text'
|
import AppText from '../common/app-text'
|
||||||
|
|
||||||
import { Sizes, Spacing, Typography } from '../../styles'
|
import { Sizes, Spacing, Typography } from '../../styles'
|
||||||
|
|
||||||
@@ -3,7 +3,7 @@ import { FlatList, StyleSheet, View } from 'react-native'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import AppText from './app-text'
|
import AppText from '../common/app-text'
|
||||||
|
|
||||||
import cycleModule from '../../lib/cycle'
|
import cycleModule from '../../lib/cycle'
|
||||||
import { Spacing, Typography, Colors } from '../../styles'
|
import { Spacing, Typography, Colors } from '../../styles'
|
||||||
@@ -1,39 +1,45 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { ImageBackground, View } from 'react-native'
|
import { ImageBackground, View } from 'react-native'
|
||||||
import { ScaledSheet } from 'react-native-size-matters'
|
import { ScaledSheet } from 'react-native-size-matters'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import AppText from './common/app-text'
|
import AppText from '../common/app-text'
|
||||||
import StatsOverview from './common/StatsOverview'
|
import StatsOverview from './StatsOverview'
|
||||||
import StatsTable from './common/StatsTable'
|
import StatsTable from './StatsTable'
|
||||||
|
|
||||||
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 '../i18n/en/labels'
|
|
||||||
|
|
||||||
import { Containers, Sizes, Spacing, Typography } from '../styles'
|
import { Containers, Sizes, Spacing, Typography } from '../../styles'
|
||||||
|
|
||||||
const image = require('../assets/cycle-icon.png')
|
const image = require('../../assets/cycle-icon.png')
|
||||||
|
|
||||||
const Stats = () => {
|
const Stats = () => {
|
||||||
|
const { t } = useTranslation(null, { keyPrefix: 'stats' })
|
||||||
|
|
||||||
const cycleLengths = cycleModule().getAllCycleLengths()
|
const cycleLengths = cycleModule().getAllCycleLengths()
|
||||||
const numberOfCycles = cycleLengths.length
|
const numberOfCycles = cycleLengths.length
|
||||||
const hasAtLeastOneCycle = numberOfCycles >= 1
|
const cycleData =
|
||||||
const cycleData = hasAtLeastOneCycle
|
numberOfCycles > 0
|
||||||
? getCycleInfo(cycleLengths)
|
? getCycleInfo(cycleLengths)
|
||||||
: { minimum: '—', maximum: '—', stdDeviation: '—' }
|
: { minimum: '—', maximum: '—', stdDeviation: '—' }
|
||||||
|
const standardDeviation = cycleData.stdDeviation
|
||||||
|
? cycleData.stdDeviation
|
||||||
|
: '—'
|
||||||
const statsData = [
|
const statsData = [
|
||||||
[cycleData.minimum, labels.minLabel],
|
[cycleData.minimum, t('overview.min')],
|
||||||
[cycleData.maximum, labels.maxLabel],
|
[cycleData.maximum, t('overview.max')],
|
||||||
[cycleData.stdDeviation ? cycleData.stdDeviation : '—', labels.stdLabel],
|
[standardDeviation, t('overview.standardDeviation')],
|
||||||
[numberOfCycles, labels.basisOfStatsEnd],
|
[numberOfCycles, t('overview.completedCycles')],
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.pageContainer}>
|
<View style={styles.pageContainer}>
|
||||||
<View style={styles.overviewContainer}>
|
<View style={styles.overviewContainer}>
|
||||||
<AppText>{labels.cycleLengthExplainer}</AppText>
|
<AppText>{t('intro')}</AppText>
|
||||||
{!hasAtLeastOneCycle && <AppText>{labels.emptyStats}</AppText>}
|
{numberOfCycles === 0 ? (
|
||||||
{hasAtLeastOneCycle && (
|
<AppText>{t('noData')}</AppText>
|
||||||
|
) : (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<View style={styles.columnLeft}>
|
<View style={styles.columnLeft}>
|
||||||
<ImageBackground
|
<ImageBackground
|
||||||
@@ -49,11 +55,11 @@ const Stats = () => {
|
|||||||
{cycleData.mean}
|
{cycleData.mean}
|
||||||
</AppText>
|
</AppText>
|
||||||
<AppText style={styles.accentPurpleHuge}>
|
<AppText style={styles.accentPurpleHuge}>
|
||||||
{labels.daysLabel}
|
{t('overview.days')}
|
||||||
</AppText>
|
</AppText>
|
||||||
</ImageBackground>
|
</ImageBackground>
|
||||||
<AppText style={styles.accentOrange}>
|
<AppText style={styles.accentOrange}>
|
||||||
{labels.averageLabel}
|
{t('overview.average')}
|
||||||
</AppText>
|
</AppText>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.columnRight}>
|
<View style={styles.columnRight}>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import React, { createContext, useContext, useState } from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { LocalDate } from '@js-joda/core'
|
||||||
|
|
||||||
|
const DateContext = createContext()
|
||||||
|
|
||||||
|
export const DateProvider = ({ children }) => {
|
||||||
|
const [date, setDate] = useState(LocalDate.now().toString())
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DateContext.Provider value={{ date, setDate }}>
|
||||||
|
{children}
|
||||||
|
</DateContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
DateProvider.propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useDate = () => {
|
||||||
|
const { date, setDate } = useContext(DateContext)
|
||||||
|
return { date, setDate }
|
||||||
|
}
|
||||||
@@ -61,6 +61,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"stats": {
|
||||||
|
"noData": "At least one completed cycle is needed to display stats.",
|
||||||
|
"intro": "Basic statistics about the length of your cycles.",
|
||||||
|
"overview": {
|
||||||
|
"average": "Average cycle",
|
||||||
|
"days": "days",
|
||||||
|
"min": "Shortest",
|
||||||
|
"max": "Longest",
|
||||||
|
"standardDeviation": "Standard\ndeviation",
|
||||||
|
"completedCycles": "completed\ncycles"
|
||||||
|
},
|
||||||
|
"showStats": "Show period details",
|
||||||
|
"details": {
|
||||||
|
"cycleStart": "Cycle start",
|
||||||
|
"cycleLength": "Cycle length",
|
||||||
|
"bleedingDays": "Bleeding"
|
||||||
|
},
|
||||||
|
"footnote": "Based on the standard deviation of all your tracked periods drip. calculates a range for the starting day of the upcoming 3 periods. The range will be 3 days if your standard deviation is smaller than 1.5 and 5 days if the value is bigger.\n\nThe standard deviation tells you how much the length of your periods vary, 0 means all your periods are exactly the same length and the bigger the value the more the period length varies."
|
||||||
|
},
|
||||||
"plurals": {
|
"plurals": {
|
||||||
"day": "{{count}} day",
|
"day": "{{count}} day",
|
||||||
"day_plural": "{{count}} days"
|
"day_plural": "{{count}} days"
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { render } from '@testing-library/react-native'
|
||||||
|
|
||||||
|
import Footnote from '../../../components/common/Footnote'
|
||||||
|
|
||||||
|
describe('Footnote component', () => {
|
||||||
|
test('when children are present, renders them', () => {
|
||||||
|
const text = 'Some footnote text'
|
||||||
|
const { toJSON } = render(<Footnote>{text}</Footnote>)
|
||||||
|
|
||||||
|
expect(toJSON()).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('when no children, renders nothing', () => {
|
||||||
|
const { toJSON } = render(<Footnote></Footnote>)
|
||||||
|
|
||||||
|
expect(toJSON()).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Footnote component when children are present, renders them 1`] = `
|
||||||
|
<View
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"alignContent": "flex-start",
|
||||||
|
"flexDirection": "row",
|
||||||
|
"marginBottom": 8.571428571428571,
|
||||||
|
"marginTop": 21.428571428571427,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"color": "#555",
|
||||||
|
"fontFamily": "Jost-Book",
|
||||||
|
"fontSize": 34.285714285714285,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"color": "#F38337",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
>
|
||||||
|
*
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
linkStyle={
|
||||||
|
Object {
|
||||||
|
"color": "white",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
style={
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"color": "#555",
|
||||||
|
"fontFamily": "Jost-Book",
|
||||||
|
"fontSize": 34.285714285714285,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"color": "#CCC",
|
||||||
|
"paddingLeft": 34.285714285714285,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Some footnote text
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Footnote component when no children, renders nothing 1`] = `null`;
|
||||||
Reference in New Issue
Block a user