Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c56b6fe62e |
@@ -33,7 +33,7 @@
|
|||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:windowSoftInputMode="adjustPan"
|
android:windowSoftInputMode="adjustResize"
|
||||||
android:screenOrientation="sensorPortrait">
|
android:screenOrientation="sensorPortrait">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import { StyleSheet, View } from 'react-native'
|
|
||||||
|
|
||||||
import AppText from '../common/app-text'
|
|
||||||
|
|
||||||
import { Containers, Spacing, Typography } from '../../styles'
|
|
||||||
|
|
||||||
const AppHelp = ({ text }) => (
|
|
||||||
<View style={styles.container}>
|
|
||||||
<AppText style={styles.accentPurple}>*</AppText>
|
|
||||||
<AppText>{text}</AppText>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
|
|
||||||
AppHelp.propTypes = {
|
|
||||||
text: PropTypes.string.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
accentPurple: {
|
|
||||||
...Typography.accentPurple,
|
|
||||||
alignSelf: 'flex-start',
|
|
||||||
paddingRight: Spacing.base,
|
|
||||||
},
|
|
||||||
container: {
|
|
||||||
...Containers.rowContainer,
|
|
||||||
padding: Spacing.base,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
export default AppHelp
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import { StyleSheet, Text, Linking } from 'react-native'
|
|
||||||
|
|
||||||
import { Colors, Typography } from '../../styles'
|
|
||||||
|
|
||||||
const AppLink = ({ children, url, ...props }) => {
|
|
||||||
return (
|
|
||||||
<Text style={styles.link} {...props} onPress={() => Linking.openURL(url)}>
|
|
||||||
{children}
|
|
||||||
</Text>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
AppLink.propTypes = {
|
|
||||||
children: PropTypes.node,
|
|
||||||
url: PropTypes.string,
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
link: {
|
|
||||||
...Typography.mainText,
|
|
||||||
color: Colors.purple,
|
|
||||||
textDecorationLine: 'underline',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
export default AppLink
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { Dimensions, FlatList, StyleSheet, View } from 'react-native'
|
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
|
|
||||||
import AppText from './app-text'
|
|
||||||
import CloseIcon from './close-icon'
|
|
||||||
|
|
||||||
import cycleModule from '../../lib/cycle'
|
|
||||||
import { Sizes, Spacing, Typography, Colors } from '../../styles'
|
|
||||||
import { humanizeDate } from '../helpers/format-date'
|
|
||||||
|
|
||||||
const Item = ({ data }) => {
|
|
||||||
const { t } = useTranslation(null, { keyPrefix: 'plurals' })
|
|
||||||
|
|
||||||
if (!data) return false
|
|
||||||
|
|
||||||
const { date, cycleLength, bleedingLength } = data
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={styles.row}>
|
|
||||||
<View style={styles.accentCell}>
|
|
||||||
<AppText>{humanizeDate(date)}</AppText>
|
|
||||||
</View>
|
|
||||||
<View style={styles.cell}>
|
|
||||||
<AppText>{t('day', { count: cycleLength })}</AppText>
|
|
||||||
</View>
|
|
||||||
<View style={styles.cell}>
|
|
||||||
<AppText>{t('day', { count: bleedingLength })}</AppText>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Item.propTypes = {
|
|
||||||
data: PropTypes.object.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
const StatsTable = ({ onClose }) => {
|
|
||||||
const renderItem = ({ item }) => <Item data={item} />
|
|
||||||
const data = cycleModule().getStats()
|
|
||||||
|
|
||||||
if (!data || data.length === 0) return false
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={styles.modalContainer}>
|
|
||||||
<View style={styles.headerContainer}>
|
|
||||||
<CloseIcon onClose={onClose} />
|
|
||||||
</View>
|
|
||||||
<FlatList
|
|
||||||
data={data}
|
|
||||||
renderItem={renderItem}
|
|
||||||
keyExtractor={(item) => item.date}
|
|
||||||
ItemSeparatorComponent={ItemDivider}
|
|
||||||
ListHeaderComponent={FlatListHeader}
|
|
||||||
ListHeaderComponentStyle={styles.headerDivider}
|
|
||||||
stickyHeaderIndices={[0]}
|
|
||||||
contentContainerStyle={styles.container}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
StatsTable.propTypes = {
|
|
||||||
onClose: PropTypes.func,
|
|
||||||
}
|
|
||||||
|
|
||||||
const ItemDivider = () => <View style={styles.divider} />
|
|
||||||
|
|
||||||
const FlatListHeader = () => {
|
|
||||||
const { t } = useTranslation(null, { keyPrefix: 'stats' })
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={styles.row}>
|
|
||||||
<View style={styles.accentCell}>
|
|
||||||
<AppText style={styles.header}>{t('cycle_start')}</AppText>
|
|
||||||
</View>
|
|
||||||
<View style={styles.cell}>
|
|
||||||
<AppText style={styles.header}>{t('cycle_length')}</AppText>
|
|
||||||
</View>
|
|
||||||
<View style={styles.cell}>
|
|
||||||
<AppText style={styles.header}>{t('bleeding')}</AppText>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
accentCell: {
|
|
||||||
flex: 3,
|
|
||||||
justifyContent: 'center',
|
|
||||||
},
|
|
||||||
cell: {
|
|
||||||
flex: 2,
|
|
||||||
justifyContent: 'center',
|
|
||||||
},
|
|
||||||
container: {
|
|
||||||
paddingHorizontal: Spacing.base,
|
|
||||||
},
|
|
||||||
divider: {
|
|
||||||
height: 1,
|
|
||||||
width: '100%',
|
|
||||||
backgroundColor: Colors.grey,
|
|
||||||
},
|
|
||||||
header: {
|
|
||||||
...Typography.accentOrange,
|
|
||||||
paddingVertical: Spacing.small,
|
|
||||||
},
|
|
||||||
headerContainer: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'flex-end',
|
|
||||||
paddingTop: Spacing.base,
|
|
||||||
paddingRight: Spacing.base,
|
|
||||||
},
|
|
||||||
headerDivider: {
|
|
||||||
borderBottomColor: Colors.purple,
|
|
||||||
borderBottomWidth: 2,
|
|
||||||
},
|
|
||||||
modalContainer: {
|
|
||||||
alignSelf: 'center',
|
|
||||||
backgroundColor: Colors.turquoiseLight,
|
|
||||||
marginTop: Sizes.huge * 2,
|
|
||||||
maxHeight: Dimensions.get('window').height * 0.7,
|
|
||||||
minHeight: '40%',
|
|
||||||
position: 'absolute',
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
row: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
paddingVertical: Spacing.tiny,
|
|
||||||
backgroundColor: Colors.turquoiseLight,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
export default StatsTable
|
|
||||||
@@ -4,7 +4,7 @@ import { ScrollView, StyleSheet, View } from 'react-native'
|
|||||||
|
|
||||||
import AppText from '../common/app-text'
|
import AppText from '../common/app-text'
|
||||||
|
|
||||||
import { Colors, Containers, Typography } from '../../styles'
|
import { Colors, Typography } from '../../styles'
|
||||||
|
|
||||||
const AppPage = ({
|
const AppPage = ({
|
||||||
children,
|
children,
|
||||||
@@ -35,7 +35,10 @@ AppPage.propTypes = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: { ...Containers.pageContainer },
|
container: {
|
||||||
|
backgroundColor: Colors.turquoiseLight,
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
scrollView: {
|
scrollView: {
|
||||||
backgroundColor: Colors.turquoiseLight,
|
backgroundColor: Colors.turquoiseLight,
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
|
|||||||
@@ -1,15 +1,30 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { StyleSheet, TextInput } from 'react-native'
|
import { KeyboardAvoidingView, StyleSheet, TextInput } from 'react-native'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
import { Colors, Spacing, Typography } from '../../styles'
|
import { Colors, Spacing, Typography } from '../../styles'
|
||||||
|
|
||||||
const AppTextInput = ({ style, ...props }) => (
|
const AppTextInput = ({ style, isKeyboardOffset, ...props }) => {
|
||||||
|
const behavior = isKeyboardOffset ? 'padding' : 'height'
|
||||||
|
const keyboardVerticalOffset = isKeyboardOffset ? 300 : 0
|
||||||
|
|
||||||
|
return (
|
||||||
|
<KeyboardAvoidingView
|
||||||
|
behavior={behavior}
|
||||||
|
keyboardVerticalOffset={keyboardVerticalOffset}
|
||||||
|
>
|
||||||
<TextInput style={[styles.input, style]} {...props} />
|
<TextInput style={[styles.input, style]} {...props} />
|
||||||
|
</KeyboardAvoidingView>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
AppTextInput.propTypes = {
|
AppTextInput.propTypes = {
|
||||||
style: PropTypes.object,
|
style: PropTypes.object,
|
||||||
|
isKeyboardOffset: PropTypes.bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
AppTextInput.defultProps = {
|
||||||
|
isKeyboardOffset: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
|||||||
@@ -2,18 +2,24 @@ import React from 'react'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { StyleSheet, Text } from 'react-native'
|
import { StyleSheet, Text } from 'react-native'
|
||||||
|
|
||||||
|
import Link from './link'
|
||||||
|
|
||||||
import { Colors, Typography } from '../../styles'
|
import { Colors, Typography } from '../../styles'
|
||||||
|
|
||||||
const AppText = ({ children, style, ...props }) => {
|
const AppText = ({ children, linkStyle, style, ...props }) => {
|
||||||
|
// we parse for links in case the text contains any
|
||||||
return (
|
return (
|
||||||
|
<Link style={linkStyle}>
|
||||||
<Text style={[styles.text, style]} {...props}>
|
<Text style={[styles.text, style]} {...props}>
|
||||||
{children}
|
{children}
|
||||||
</Text>
|
</Text>
|
||||||
|
</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
AppText.propTypes = {
|
AppText.propTypes = {
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
|
linkStyle: PropTypes.object,
|
||||||
style: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
|
style: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import Hyperlink from 'react-native-hyperlink'
|
||||||
|
import { StyleSheet } from 'react-native'
|
||||||
|
|
||||||
|
import { Colors, Typography } from '../../styles'
|
||||||
|
|
||||||
|
import links from '../../i18n/en/links'
|
||||||
|
|
||||||
|
const Link = ({ children, style }) => {
|
||||||
|
return (
|
||||||
|
<Hyperlink
|
||||||
|
linkStyle={[styles.link, style]}
|
||||||
|
linkText={replaceUrlWithText}
|
||||||
|
linkDefault
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Hyperlink>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Link.propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
|
style: PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
link: {
|
||||||
|
color: Colors.purple,
|
||||||
|
textDecorationLine: 'underline',
|
||||||
|
...Typography.mainText,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
function replaceUrlWithText(url) {
|
||||||
|
const link = Object.values(links).find((l) => l.url === url)
|
||||||
|
return (link && link.text) || url
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Link
|
||||||
@@ -4,7 +4,7 @@ import { StyleSheet, View } from 'react-native'
|
|||||||
|
|
||||||
import AppText from './app-text'
|
import AppText from './app-text'
|
||||||
|
|
||||||
import { Colors, Containers, Spacing, Typography } from '../../styles'
|
import { Colors, Spacing, Typography } from '../../styles'
|
||||||
|
|
||||||
const Segment = ({ children, last, title }) => {
|
const Segment = ({ children, last, title }) => {
|
||||||
const containerStyle = last ? styles.containerLast : styles.container
|
const containerStyle = last ? styles.containerLast : styles.container
|
||||||
@@ -25,16 +25,21 @@ Segment.propTypes = {
|
|||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const segmentContainer = {
|
||||||
|
marginHorizontal: Spacing.base,
|
||||||
|
marginBottom: Spacing.base,
|
||||||
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
borderStyle: 'solid',
|
borderStyle: 'solid',
|
||||||
borderBottomWidth: 1,
|
borderBottomWidth: 1,
|
||||||
borderBottomColor: Colors.greyLight,
|
borderBottomColor: Colors.greyLight,
|
||||||
paddingBottom: Spacing.base,
|
paddingBottom: Spacing.base,
|
||||||
...Containers.segmentContainer,
|
...segmentContainer,
|
||||||
},
|
},
|
||||||
containerLast: {
|
containerLast: {
|
||||||
...Containers.segmentContainer,
|
...segmentContainer,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
...Typography.subtitle,
|
...Typography.subtitle,
|
||||||
|
|||||||
@@ -6,21 +6,21 @@ import AppText from './app-text'
|
|||||||
|
|
||||||
import { Sizes, Spacing, Typography } from '../../styles'
|
import { Sizes, Spacing, Typography } from '../../styles'
|
||||||
|
|
||||||
const StatsOverview = ({ data }) => {
|
const Table = ({ tableContent }) => {
|
||||||
return data.map((rowContent, i) => <Row key={i} rowContent={rowContent} />)
|
return tableContent.map((rowContent, i) => (
|
||||||
|
<Row key={i} rowContent={rowContent} />
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
StatsOverview.propTypes = {
|
Table.propTypes = {
|
||||||
data: PropTypes.array.isRequired,
|
tableContent: PropTypes.array.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
const Row = ({ rowContent }) => {
|
const Row = ({ rowContent }) => {
|
||||||
const showHelp = rowContent[1].includes('deviation') ? true : false
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.row}>
|
<View style={styles.row}>
|
||||||
<Cell content={rowContent[0]} isLeft />
|
<Cell content={rowContent[0]} isLeft />
|
||||||
<Cell content={rowContent[1]} showHelp={showHelp} />
|
<Cell content={rowContent[1]} />
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ Row.propTypes = {
|
|||||||
rowContent: PropTypes.array.isRequired,
|
rowContent: PropTypes.array.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
const Cell = ({ content, isLeft, showHelp }) => {
|
const Cell = ({ content, isLeft }) => {
|
||||||
const styleContainer = isLeft ? styles.cellLeft : styles.cellRight
|
const styleContainer = isLeft ? styles.cellLeft : styles.cellRight
|
||||||
const styleText = isLeft ? styles.accentPurpleBig : styles.accentOrange
|
const styleText = isLeft ? styles.accentPurpleBig : styles.accentOrange
|
||||||
const numberOfLines = isLeft ? 1 : 2
|
const numberOfLines = isLeft ? 1 : 2
|
||||||
@@ -44,7 +44,6 @@ const Cell = ({ content, isLeft, showHelp }) => {
|
|||||||
>
|
>
|
||||||
{content}
|
{content}
|
||||||
</AppText>
|
</AppText>
|
||||||
{showHelp && <AppText style={styles.accentPurpleBig}>*</AppText>}
|
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -52,7 +51,6 @@ const Cell = ({ content, isLeft, showHelp }) => {
|
|||||||
Cell.propTypes = {
|
Cell.propTypes = {
|
||||||
content: PropTypes.node.isRequired,
|
content: PropTypes.node.isRequired,
|
||||||
isLeft: PropTypes.bool,
|
isLeft: PropTypes.bool,
|
||||||
showHelp: PropTypes.bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
@@ -67,14 +65,18 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
cellLeft: {
|
cellLeft: {
|
||||||
alignItems: 'flex-end',
|
alignItems: 'flex-end',
|
||||||
flex: 3,
|
flex: 5,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
cellRight: {
|
cellRight: {
|
||||||
flex: 5,
|
flex: 5,
|
||||||
flexDirection: 'row',
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
row: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
marginBottom: Spacing.tiny,
|
||||||
|
marginLeft: Spacing.tiny,
|
||||||
},
|
},
|
||||||
row: { flexDirection: 'row' },
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export default StatsOverview
|
export default Table
|
||||||
@@ -109,13 +109,6 @@ const SymptomEditView = ({ date, onClose, symptom, symptomData }) => {
|
|||||||
}
|
}
|
||||||
const iconName = shouldShowInfo ? 'chevron-up' : 'chevron-down'
|
const iconName = shouldShowInfo ? 'chevron-up' : 'chevron-down'
|
||||||
const noteText = symptom === 'note' ? data.value : data.note
|
const noteText = symptom === 'note' ? data.value : data.note
|
||||||
const inputProps = {
|
|
||||||
multiline: true,
|
|
||||||
numberOfLines: 3,
|
|
||||||
scrollEnabled: false,
|
|
||||||
style: styles.input,
|
|
||||||
textAlignVertical: 'top',
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppModal onClose={onSave}>
|
<AppModal onClose={onSave}>
|
||||||
@@ -164,7 +157,7 @@ const SymptomEditView = ({ date, onClose, symptom, symptomData }) => {
|
|||||||
/>
|
/>
|
||||||
{isOtherSelected && (
|
{isOtherSelected && (
|
||||||
<AppTextInput
|
<AppTextInput
|
||||||
{...inputProps}
|
multiline={true}
|
||||||
placeholder={sharedLabels.enter}
|
placeholder={sharedLabels.enter}
|
||||||
value={data.note}
|
value={data.note}
|
||||||
onChangeText={(value) => onSelectBoxNote(value)}
|
onChangeText={(value) => onSelectBoxNote(value)}
|
||||||
@@ -186,7 +179,8 @@ const SymptomEditView = ({ date, onClose, symptom, symptomData }) => {
|
|||||||
<Segment style={styles.segmentBorder}>
|
<Segment style={styles.segmentBorder}>
|
||||||
<AppText>{symtomPage[symptom].note}</AppText>
|
<AppText>{symtomPage[symptom].note}</AppText>
|
||||||
<AppTextInput
|
<AppTextInput
|
||||||
{...inputProps}
|
multiline={true}
|
||||||
|
numberOfLines={3}
|
||||||
onChangeText={onEditNote}
|
onChangeText={onEditNote}
|
||||||
placeholder={sharedLabels.enter}
|
placeholder={sharedLabels.enter}
|
||||||
testID="noteInput"
|
testID="noteInput"
|
||||||
@@ -239,9 +233,6 @@ const styles = StyleSheet.create({
|
|||||||
zIndex: 3, // works on ios
|
zIndex: 3, // works on ios
|
||||||
elevation: 3, // works on android
|
elevation: 3, // works on android
|
||||||
},
|
},
|
||||||
input: {
|
|
||||||
height: Sizes.base * 5,
|
|
||||||
},
|
|
||||||
modalContainer: {
|
modalContainer: {
|
||||||
paddingHorizontal: Spacing.base,
|
paddingHorizontal: Spacing.base,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -22,18 +22,3 @@ export function dateToTitle(dateString) {
|
|||||||
? labels.today
|
? labels.today
|
||||||
: moment(dateString).format('ddd DD. MMM YY')
|
: moment(dateString).format('ddd DD. MMM YY')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function humanizeDate(dateString) {
|
|
||||||
if (!dateString) return ''
|
|
||||||
|
|
||||||
const today = LocalDate.now()
|
|
||||||
|
|
||||||
try {
|
|
||||||
const dateToDisplay = LocalDate.parse(dateString)
|
|
||||||
return today.equals(dateToDisplay)
|
|
||||||
? labels.today
|
|
||||||
: moment(dateString).format('DD. MMM YY')
|
|
||||||
} catch (e) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Alert, KeyboardAvoidingView, StyleSheet, View } from 'react-native'
|
import { Alert, StyleSheet, View } from 'react-native'
|
||||||
import nodejs from 'nodejs-mobile-react-native'
|
import nodejs from 'nodejs-mobile-react-native'
|
||||||
|
|
||||||
import AppPage from './common/app-page'
|
import AppPage from './common/app-page'
|
||||||
@@ -68,8 +68,8 @@ const PasswordPrompt = ({ enableShowApp }) => {
|
|||||||
<>
|
<>
|
||||||
<Header isStatic />
|
<Header isStatic />
|
||||||
<AppPage contentContainerStyle={styles.contentContainer}>
|
<AppPage contentContainerStyle={styles.contentContainer}>
|
||||||
<KeyboardAvoidingView behavior="padding" keyboardVerticalOffset={150}>
|
|
||||||
<AppTextInput
|
<AppTextInput
|
||||||
|
isKeyboardOffset={false}
|
||||||
onChangeText={setPassword}
|
onChangeText={setPassword}
|
||||||
secureTextEntry={true}
|
secureTextEntry={true}
|
||||||
placeholder={labels.enterPassword}
|
placeholder={labels.enterPassword}
|
||||||
@@ -84,7 +84,6 @@ const PasswordPrompt = ({ enableShowApp }) => {
|
|||||||
{labels.title}
|
{labels.title}
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
</KeyboardAvoidingView>
|
|
||||||
</AppPage>
|
</AppPage>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,18 +4,16 @@ import { useTranslation } from 'react-i18next'
|
|||||||
|
|
||||||
import AppPage from '../common/app-page'
|
import AppPage from '../common/app-page'
|
||||||
import AppText from '../common/app-text'
|
import AppText from '../common/app-text'
|
||||||
import AppLink from '../common/AppLink'
|
|
||||||
import Segment from '../common/segment'
|
import Segment from '../common/segment'
|
||||||
|
|
||||||
const License = ({ children }) => {
|
const License = ({ children }) => {
|
||||||
const { t } = useTranslation(null, { keyPrefix: 'settings.license' })
|
const { t } = useTranslation()
|
||||||
const currentYear = new Date().getFullYear()
|
const currentYear = new Date().getFullYear()
|
||||||
const link = 'https://www.gnu.org/licenses/gpl-3.0.html'
|
|
||||||
return (
|
return (
|
||||||
<AppPage title={t('title')}>
|
<AppPage title={t('settings.license.title')}>
|
||||||
<Segment last>
|
<Segment last>
|
||||||
<AppText>{t('text', { currentYear })}</AppText>
|
<AppText>{t('settings.license.text', { currentYear })}</AppText>
|
||||||
<AppLink url={link}>{link}</AppLink>
|
|
||||||
{children}
|
{children}
|
||||||
</Segment>
|
</Segment>
|
||||||
</AppPage>
|
</AppPage>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { Platform, Linking } from 'react-native'
|
|||||||
|
|
||||||
import AppPage from '../common/app-page'
|
import AppPage from '../common/app-page'
|
||||||
import AppText from '../common/app-text'
|
import AppText from '../common/app-text'
|
||||||
import AppLink from '../common/AppLink'
|
|
||||||
import Segment from '../common/segment'
|
import Segment from '../common/segment'
|
||||||
import Button from '../common/button'
|
import Button from '../common/button'
|
||||||
import ButtonRow from '../common/button-row'
|
import ButtonRow from '../common/button-row'
|
||||||
@@ -36,15 +35,13 @@ const AboutSection = () => {
|
|||||||
</Segment>
|
</Segment>
|
||||||
<Segment title={t('credits.title')}>
|
<Segment title={t('credits.title')}>
|
||||||
<AppText>
|
<AppText>
|
||||||
{t('credits.text')}{' '}
|
{t('credits.text', {
|
||||||
<AppLink url={links.flaticon.url}>flaticon</AppLink>.{' '}
|
smashicons: links.smashicons.url,
|
||||||
</AppText>
|
pause08: links.pause08.url,
|
||||||
<AppText>
|
kazachek: links.kazachek.url,
|
||||||
{t('credits.madeBy')}{' '}
|
freepik: links.freepik.url,
|
||||||
<AppLink url={links.smashicons.url}>smashicons</AppLink>,{' '}
|
flaticon: links.flaticon.url,
|
||||||
<AppLink url={links.pause08.url}>pause08</AppLink>,{' '}
|
})}
|
||||||
<AppLink url={links.kazachek.url}>kazachek</AppLink>,{' '}
|
|
||||||
<AppLink url={links.freepik.url}>freepik</AppLink>.
|
|
||||||
</AppText>
|
</AppText>
|
||||||
</Segment>
|
</Segment>
|
||||||
<Segment title={t('donate.title')}>
|
<Segment title={t('donate.title')}>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Alert, KeyboardAvoidingView, StyleSheet, View } from 'react-native'
|
import { Alert, StyleSheet, View } from 'react-native'
|
||||||
import nodejs from 'nodejs-mobile-react-native'
|
import nodejs from 'nodejs-mobile-react-native'
|
||||||
|
|
||||||
import AppTextInput from '../../common/app-text-input'
|
import AppTextInput from '../../common/app-text-input'
|
||||||
@@ -53,7 +53,7 @@ const ConfirmWithPassword = ({ onSuccess, onCancel }) => {
|
|||||||
const isPassword = password !== null
|
const isPassword = password !== null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KeyboardAvoidingView behavior="padding" keyboardVerticalOffset={150}>
|
<>
|
||||||
<AppTextInput
|
<AppTextInput
|
||||||
onChangeText={setPassword}
|
onChangeText={setPassword}
|
||||||
placeholder={labels.enterCurrent}
|
placeholder={labels.enterCurrent}
|
||||||
@@ -70,7 +70,7 @@ const ConfirmWithPassword = ({ onSuccess, onCancel }) => {
|
|||||||
{shared.confirmToProceed}
|
{shared.confirmToProceed}
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
</KeyboardAvoidingView>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import Reminders from './reminders/reminders'
|
|||||||
import NfpSettings from './nfp-settings'
|
import NfpSettings from './nfp-settings'
|
||||||
import DataManagement from './data-management'
|
import DataManagement from './data-management'
|
||||||
import Password from './password'
|
import Password from './password'
|
||||||
import About from './About'
|
import About from './about'
|
||||||
import License from './License'
|
import License from './License'
|
||||||
import PrivacyPolicy from './privacy-policy'
|
import PrivacyPolicy from './privacy-policy'
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
import AppPage from '../common/app-page'
|
||||||
|
import AppText from '../common/app-text'
|
||||||
|
import Segment from '../common/segment'
|
||||||
|
|
||||||
|
const License = ({ children }) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const currentYear = new Date().getFullYear()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppPage title={t('settings.license.title')}>
|
||||||
|
<Segment last>
|
||||||
|
<AppText>{t('settings.license.text', { currentYear })}</AppText>
|
||||||
|
{children}
|
||||||
|
</Segment>
|
||||||
|
</AppPage>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
License.propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default License
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import { KeyboardAvoidingView, StyleSheet } from 'react-native'
|
import { StyleSheet } from 'react-native'
|
||||||
import nodejs from 'nodejs-mobile-react-native'
|
import nodejs from 'nodejs-mobile-react-native'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
@@ -41,8 +41,9 @@ const EnterNewPassword = ({ changeEncryptionAndRestart }) => {
|
|||||||
const isButtonActive = password.length > 0 && passwordConfirmation.length > 0
|
const isButtonActive = password.length > 0 && passwordConfirmation.length > 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KeyboardAvoidingView behavior="padding" keyboardVerticalOffset={150}>
|
<>
|
||||||
<AppTextInput
|
<AppTextInput
|
||||||
|
isKeyboardOffset={false}
|
||||||
onChangeText={setPassword}
|
onChangeText={setPassword}
|
||||||
placeholder={labels.enterNew}
|
placeholder={labels.enterNew}
|
||||||
textContentType="password"
|
textContentType="password"
|
||||||
@@ -50,6 +51,7 @@ const EnterNewPassword = ({ changeEncryptionAndRestart }) => {
|
|||||||
secureTextEntry={true}
|
secureTextEntry={true}
|
||||||
/>
|
/>
|
||||||
<AppTextInput
|
<AppTextInput
|
||||||
|
isKeyboardOffset={false}
|
||||||
onChangeText={setPasswordConfirmation}
|
onChangeText={setPasswordConfirmation}
|
||||||
placeholder={labels.confirmPassword}
|
placeholder={labels.confirmPassword}
|
||||||
textContentType="password"
|
textContentType="password"
|
||||||
@@ -66,7 +68,7 @@ const EnterNewPassword = ({ changeEncryptionAndRestart }) => {
|
|||||||
>
|
>
|
||||||
{labels.savePassword}
|
{labels.savePassword}
|
||||||
</Button>
|
</Button>
|
||||||
</KeyboardAvoidingView>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+35
-59
@@ -1,50 +1,39 @@
|
|||||||
import React, { useState } from 'react'
|
import React from 'react'
|
||||||
import { ImageBackground, SafeAreaView, ScrollView, 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 Button from './common/button'
|
import AppPage from './common/app-page'
|
||||||
import AppHelp from './common/AppHelp'
|
|
||||||
import AppModal from './common/app-modal'
|
|
||||||
import AppText from './common/app-text'
|
import AppText from './common/app-text'
|
||||||
import StatsOverview from './common/StatsOverview'
|
import Segment from './common/segment'
|
||||||
import StatsTable from './common/StatsTable'
|
import Table from './common/table'
|
||||||
|
|
||||||
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 { Sizes, Spacing, Typography } from '../styles'
|
||||||
|
|
||||||
const image = require('../assets/cycle-icon.png')
|
const image = require('../assets/cycle-icon.png')
|
||||||
|
|
||||||
const Stats = () => {
|
const Stats = () => {
|
||||||
const [isStatsVisible, setIsStatsVisible] = useState(false)
|
|
||||||
|
|
||||||
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 hasAtLeastOneCycle = numberOfCycles >= 1
|
||||||
const cycleData = hasAtLeastOneCycle
|
const cycleData = hasAtLeastOneCycle ? getCycleInfo(cycleLengths)
|
||||||
? getCycleInfo(cycleLengths)
|
|
||||||
: { minimum: '—', maximum: '—', stdDeviation: '—' }
|
: { minimum: '—', maximum: '—', stdDeviation: '—' }
|
||||||
const statsData = [
|
const statsData = [
|
||||||
[cycleData.minimum, t('min')],
|
[cycleData.minimum, labels.minLabel],
|
||||||
[cycleData.maximum, t('max')],
|
[cycleData.maximum, labels.maxLabel],
|
||||||
[
|
[cycleData.stdDeviation ? cycleData.stdDeviation : '—', labels.stdLabel],
|
||||||
cycleData.stdDeviation ? cycleData.stdDeviation : '—',
|
[numberOfCycles, labels.basisOfStatsEnd]
|
||||||
t('standard_deviation'),
|
|
||||||
],
|
|
||||||
[numberOfCycles, t('completed_cycles')],
|
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.pageContainer}>
|
<AppPage contentContainerStyle={styles.pageContainer}>
|
||||||
<ScrollView contentContainerStyle={styles.overviewContainer}>
|
<Segment last style={styles.pageContainer}>
|
||||||
<AppText>{t('cycle_length_explainer')}</AppText>
|
<AppText>{labels.cycleLengthExplainer}</AppText>
|
||||||
{!hasAtLeastOneCycle && <AppText>{t('no_data')}</AppText>}
|
{!hasAtLeastOneCycle && <AppText>{labels.emptyStats}</AppText>}
|
||||||
{hasAtLeastOneCycle && (
|
{hasAtLeastOneCycle &&
|
||||||
<>
|
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<View style={styles.columnLeft}>
|
<View style={styles.columnLeft}>
|
||||||
<ImageBackground
|
<ImageBackground
|
||||||
@@ -59,31 +48,21 @@ const Stats = () => {
|
|||||||
>
|
>
|
||||||
{cycleData.mean}
|
{cycleData.mean}
|
||||||
</AppText>
|
</AppText>
|
||||||
<AppText style={styles.accentPurpleHuge}>{t('days')}</AppText>
|
<AppText style={styles.accentPurpleHuge}>
|
||||||
|
{labels.daysLabel}
|
||||||
|
</AppText>
|
||||||
</ImageBackground>
|
</ImageBackground>
|
||||||
<AppText style={styles.accentOrange}>{t('average')}</AppText>
|
<AppText style={styles.accentOrange}>
|
||||||
|
{labels.averageLabel}
|
||||||
|
</AppText>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.columnRight}>
|
<View style={styles.columnRight}>
|
||||||
<StatsOverview data={statsData} />
|
<Table tableContent={statsData} />
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<Button isCTA onPress={() => setIsStatsVisible(true)}>
|
}
|
||||||
{t('show_stats')}
|
</Segment>
|
||||||
</Button>
|
</AppPage>
|
||||||
<AppHelp text={t('standard_deviation_help')} />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</ScrollView>
|
|
||||||
|
|
||||||
{isStatsVisible && (
|
|
||||||
<AppModal onClose={() => setIsStatsVisible(false)}>
|
|
||||||
<StatsTable
|
|
||||||
onClose={() => setIsStatsVisible(false)}
|
|
||||||
testID="statsTable"
|
|
||||||
/>
|
|
||||||
</AppModal>
|
|
||||||
)}
|
|
||||||
</SafeAreaView>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,24 +77,25 @@ const styles = ScaledSheet.create({
|
|||||||
},
|
},
|
||||||
accentPurpleGiant: {
|
accentPurpleGiant: {
|
||||||
...Typography.accentPurpleGiant,
|
...Typography.accentPurpleGiant,
|
||||||
marginTop: Spacing.base * -2,
|
marginTop: Spacing.base * (-2),
|
||||||
},
|
},
|
||||||
accentPurpleHuge: {
|
accentPurpleHuge: {
|
||||||
...Typography.accentPurpleHuge,
|
...Typography.accentPurpleHuge,
|
||||||
marginTop: Spacing.base * -1,
|
marginTop: Spacing.base * (-1),
|
||||||
},
|
},
|
||||||
container: {
|
container: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
|
paddingTop: Spacing.base
|
||||||
},
|
},
|
||||||
columnLeft: {
|
columnLeft: {
|
||||||
...column,
|
...column,
|
||||||
flex: 3,
|
flex: 2,
|
||||||
},
|
},
|
||||||
columnRight: {
|
columnRight: {
|
||||||
...column,
|
...column,
|
||||||
flex: 5,
|
flex: 3,
|
||||||
paddingTop: Spacing.small,
|
paddingTop: Spacing.small,
|
||||||
},
|
},
|
||||||
image: {
|
image: {
|
||||||
@@ -125,13 +105,9 @@ const styles = ScaledSheet.create({
|
|||||||
paddingTop: Spacing.large * 2.5,
|
paddingTop: Spacing.large * 2.5,
|
||||||
marginBottom: Spacing.large,
|
marginBottom: Spacing.large,
|
||||||
},
|
},
|
||||||
overviewContainer: {
|
|
||||||
paddingHorizontal: Spacing.base,
|
|
||||||
paddingTop: Spacing.base,
|
|
||||||
},
|
|
||||||
pageContainer: {
|
pageContainer: {
|
||||||
...Containers.pageContainer,
|
marginTop: Spacing.base * 2,
|
||||||
},
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export default Stats
|
export default Stats
|
||||||
|
|||||||
+2
-22
@@ -17,8 +17,7 @@
|
|||||||
"about": {
|
"about": {
|
||||||
"credits": {
|
"credits": {
|
||||||
"title": "Credits",
|
"title": "Credits",
|
||||||
"text": "We love the drip. team. Thanks and lots of <3 to all of our condriputors. Thanks to Paula Härtel for the symptom tracking icons. All the other icons from:",
|
"text": "We love the drip. team. Thanks and lots of <3 to all of our condriputors. Thanks to Paula Härtel for the symptom tracking icons. All the other icons are made by {{smashicons}}, {{pause08}}, {{kazachek}} & {{freepik}} from {{flaticon}}."
|
||||||
"madeBy": "Made by:"
|
|
||||||
},
|
},
|
||||||
"donate": {
|
"donate": {
|
||||||
"button": "Donate here",
|
"button": "Donate here",
|
||||||
@@ -39,7 +38,7 @@
|
|||||||
},
|
},
|
||||||
"license": {
|
"license": {
|
||||||
"title": "drip. an open-source cycle tracking app",
|
"title": "drip. an open-source cycle tracking app",
|
||||||
"text": "Copyright (C) {{currentYear}} Heart of Code e.V.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details:"
|
"text": "Copyright (C) {{currentYear}} Heart of Code e.V.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: https://www.gnu.org/licenses/gpl-3.0.html."
|
||||||
},
|
},
|
||||||
"privacyPolicy": {
|
"privacyPolicy": {
|
||||||
"title": "Privacy Policy",
|
"title": "Privacy Policy",
|
||||||
@@ -60,24 +59,5 @@
|
|||||||
"text": "You can read through the source code of drip. to ensure the given information is correct. The source code is like a recipe: It tells you how much and what kind of ingredients you need and how you prepare them to cook a tasty meal or program a funky app.\n\nBuon appetito!"
|
"text": "You can read through the source code of drip. to ensure the given information is correct. The source code is like a recipe: It tells you how much and what kind of ingredients you need and how you prepare them to cook a tasty meal or program a funky app.\n\nBuon appetito!"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"plurals": {
|
|
||||||
"day": "{{count}} day",
|
|
||||||
"day_plural": "{{count}} days"
|
|
||||||
},
|
|
||||||
"stats": {
|
|
||||||
"show_stats": "Show period details",
|
|
||||||
"cycle_start": "Cycle start",
|
|
||||||
"cycle_length": "Cycle length",
|
|
||||||
"bleeding": "Bleeding",
|
|
||||||
"cycle_length_explainer": "Basic statistics about the length of your cycles.",
|
|
||||||
"no_data": "At least one completed cycle is needed to display stats.",
|
|
||||||
"days": "days",
|
|
||||||
"completed_cycles": "completed\ncycles",
|
|
||||||
"average": "Average cycle",
|
|
||||||
"min": "Shortest",
|
|
||||||
"max": "Longest",
|
|
||||||
"standard_deviation": "Standard\ndeviation",
|
|
||||||
"standard_deviation_help": "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."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// Import Jest Native matchers
|
||||||
|
import '@testing-library/jest-native/extend-expect'
|
||||||
+1
-4
@@ -1,10 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
preset: '@testing-library/react-native',
|
preset: '@testing-library/react-native',
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
|
||||||
moduleNameMapper: {
|
setupFilesAfterEnv: ['./jest-setup.js'],
|
||||||
'\\.(png)$': require.resolve('./test/file-mock.js'),
|
|
||||||
},
|
|
||||||
setupFilesAfterEnv: ['./test/jest-setup.js'],
|
|
||||||
transformIgnorePatterns: [
|
transformIgnorePatterns: [
|
||||||
'node_modules/(?!((jest-)?react-native(-.*)?|@react-native(-community)?)/)',
|
'node_modules/(?!((jest-)?react-native(-.*)?|@react-native(-community)?)/)',
|
||||||
],
|
],
|
||||||
|
|||||||
+3
-23
@@ -3,8 +3,6 @@ import { getCycleLengthStats } from './cycle-length'
|
|||||||
const LocalDate = joda.LocalDate
|
const LocalDate = joda.LocalDate
|
||||||
const DAYS = joda.ChronoUnit.DAYS
|
const DAYS = joda.ChronoUnit.DAYS
|
||||||
|
|
||||||
const toJSON = (realmObj) => JSON.parse(JSON.stringify(realmObj))
|
|
||||||
|
|
||||||
export default function config(opts) {
|
export default function config(opts) {
|
||||||
let bleedingDaysSortedByDate
|
let bleedingDaysSortedByDate
|
||||||
let cycleStartsSortedByDate
|
let cycleStartsSortedByDate
|
||||||
@@ -16,13 +14,9 @@ export default function config(opts) {
|
|||||||
if (!opts) {
|
if (!opts) {
|
||||||
// we only want to require (and run) the db module
|
// we only want to require (and run) the db module
|
||||||
// when not running the tests
|
// when not running the tests
|
||||||
bleedingDaysSortedByDate = toJSON(
|
bleedingDaysSortedByDate = require('../db').getBleedingDaysSortedByDate()
|
||||||
require('../db').getBleedingDaysSortedByDate()
|
cycleStartsSortedByDate = require('../db').getCycleStartsSortedByDate()
|
||||||
)
|
cycleDaysSortedByDate = require('../db').getCycleDaysSortedByDate()
|
||||||
cycleStartsSortedByDate = toJSON(
|
|
||||||
require('../db').getCycleStartsSortedByDate()
|
|
||||||
)
|
|
||||||
cycleDaysSortedByDate = toJSON(require('../db').getCycleDaysSortedByDate())
|
|
||||||
maxBreakInBleeding = 1
|
maxBreakInBleeding = 1
|
||||||
maxCycleLength = 99
|
maxCycleLength = 99
|
||||||
minCyclesForPrediction = 3
|
minCyclesForPrediction = 3
|
||||||
@@ -228,19 +222,6 @@ export default function config(opts) {
|
|||||||
return predictedMenses
|
return predictedMenses
|
||||||
}
|
}
|
||||||
|
|
||||||
const getStats = () =>
|
|
||||||
cycleStartsSortedByDate.map((day, i) => {
|
|
||||||
const today = getTodayDate()
|
|
||||||
const cycleLength =
|
|
||||||
i === 0 ? getCycleDayNumber(today) : getAllCycleLengths()[i - 1]
|
|
||||||
|
|
||||||
return {
|
|
||||||
date: day.date,
|
|
||||||
cycleLength,
|
|
||||||
bleedingLength: ++getMensesDaysRightAfter(day).length,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getCycleDayNumber,
|
getCycleDayNumber,
|
||||||
getCycleForDay,
|
getCycleForDay,
|
||||||
@@ -251,6 +232,5 @@ export default function config(opts) {
|
|||||||
isMensesStart,
|
isMensesStart,
|
||||||
getMensesDaysRightAfter,
|
getMensesDaysRightAfter,
|
||||||
getCycleByStartDay,
|
getCycleByStartDay,
|
||||||
getStats,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -48,6 +48,7 @@
|
|||||||
"react-native-calendars": "^1.1287.0",
|
"react-native-calendars": "^1.1287.0",
|
||||||
"react-native-document-picker": "^8.1.1",
|
"react-native-document-picker": "^8.1.1",
|
||||||
"react-native-fs": "^2.20.0",
|
"react-native-fs": "^2.20.0",
|
||||||
|
"react-native-hyperlink": "0.0.19",
|
||||||
"react-native-modal-datetime-picker": "14.0.0",
|
"react-native-modal-datetime-picker": "14.0.0",
|
||||||
"react-native-push-notification": "3.2.1",
|
"react-native-push-notification": "3.2.1",
|
||||||
"react-native-share": "^7.9.0",
|
"react-native-share": "^7.9.0",
|
||||||
@@ -59,7 +60,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.12.9",
|
"@babel/core": "^7.12.9",
|
||||||
"@babel/eslint-parser": "^7.19.1",
|
"@babel/eslint-parser": "^7.16.3",
|
||||||
"@babel/preset-react": "^7.16.0",
|
"@babel/preset-react": "^7.16.0",
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
"@testing-library/jest-native": "^4.0.12",
|
"@testing-library/jest-native": "^4.0.12",
|
||||||
|
|||||||
+5
-13
@@ -9,7 +9,7 @@ export default {
|
|||||||
marginTop: Spacing.small,
|
marginTop: Spacing.small,
|
||||||
marginRight: Spacing.small,
|
marginRight: Spacing.small,
|
||||||
paddingHorizontal: Spacing.small,
|
paddingHorizontal: Spacing.small,
|
||||||
paddingVertical: Spacing.tiny,
|
paddingVertical: Spacing.tiny
|
||||||
},
|
},
|
||||||
boxActive: {
|
boxActive: {
|
||||||
backgroundColor: Colors.orange,
|
backgroundColor: Colors.orange,
|
||||||
@@ -17,25 +17,17 @@ export default {
|
|||||||
centerItems: {
|
centerItems: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center'
|
||||||
},
|
|
||||||
pageContainer: {
|
|
||||||
backgroundColor: Colors.turquoiseLight,
|
|
||||||
flex: 1,
|
|
||||||
},
|
},
|
||||||
rowContainer: {
|
rowContainer: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between'
|
||||||
},
|
},
|
||||||
selectGroupContainer: {
|
selectGroupContainer: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
flexWrap: 'wrap',
|
flexWrap: 'wrap',
|
||||||
marginVertical: Spacing.small,
|
marginVertical: Spacing.small
|
||||||
},
|
}
|
||||||
segmentContainer: {
|
|
||||||
marginHorizontal: Spacing.base,
|
|
||||||
marginBottom: Spacing.base,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
+14
-18
@@ -23,7 +23,7 @@ export const sizes = {
|
|||||||
const accentText = {
|
const accentText = {
|
||||||
fontFamily: fonts.bold,
|
fontFamily: fonts.bold,
|
||||||
textAlignVertical: 'center',
|
textAlignVertical: 'center',
|
||||||
textTransform: 'uppercase',
|
textTransform: 'uppercase'
|
||||||
}
|
}
|
||||||
|
|
||||||
const accentTextBig = {
|
const accentTextBig = {
|
||||||
@@ -43,51 +43,47 @@ const accentTextHuge = {
|
|||||||
|
|
||||||
const accentTextSmall = {
|
const accentTextSmall = {
|
||||||
...accentText,
|
...accentText,
|
||||||
fontSize: sizes.small,
|
fontSize: sizes.small
|
||||||
}
|
}
|
||||||
|
|
||||||
const title = {
|
const title = {
|
||||||
color: Colors.purple,
|
color: Colors.purple,
|
||||||
marginVertical: Spacing.large,
|
marginVertical: Spacing.large
|
||||||
}
|
}
|
||||||
|
|
||||||
const label = {
|
const label = {
|
||||||
fontSize: sizes.small,
|
fontSize: sizes.small,
|
||||||
textTransform: 'uppercase',
|
textTransform: 'uppercase'
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
accentOrange: {
|
accentOrange: {
|
||||||
...accentTextSmall,
|
...accentTextSmall,
|
||||||
color: Colors.orange,
|
color: Colors.orange
|
||||||
},
|
|
||||||
accentPurple: {
|
|
||||||
...accentTextSmall,
|
|
||||||
color: Colors.purple,
|
|
||||||
},
|
},
|
||||||
accentPurpleBig: {
|
accentPurpleBig: {
|
||||||
...accentTextBig,
|
...accentTextBig,
|
||||||
color: Colors.purple,
|
color: Colors.purple
|
||||||
},
|
},
|
||||||
accentPurpleGiant: {
|
accentPurpleGiant: {
|
||||||
...accentTextGiant,
|
...accentTextGiant,
|
||||||
color: Colors.purple,
|
color: Colors.purple
|
||||||
},
|
},
|
||||||
accentPurpleHuge: {
|
accentPurpleHuge: {
|
||||||
...accentTextHuge,
|
...accentTextHuge,
|
||||||
color: Colors.purple,
|
color: Colors.purple
|
||||||
},
|
},
|
||||||
mainText: {
|
mainText: {
|
||||||
fontFamily: fonts.main,
|
fontFamily: fonts.main,
|
||||||
fontSize: sizes.base,
|
fontSize: sizes.base
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
...label,
|
...label
|
||||||
},
|
},
|
||||||
labelBold: {
|
labelBold: {
|
||||||
color: Colors.greyDark,
|
color: Colors.greyDark,
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
...label,
|
...label
|
||||||
},
|
},
|
||||||
labelLight: {
|
labelLight: {
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
@@ -95,7 +91,7 @@ export default {
|
|||||||
},
|
},
|
||||||
subtitle: {
|
subtitle: {
|
||||||
fontSize: sizes.subtitle,
|
fontSize: sizes.subtitle,
|
||||||
...title,
|
...title
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
@@ -103,7 +99,7 @@ export default {
|
|||||||
fontWeight: '700',
|
fontWeight: '700',
|
||||||
fontSize: sizes.title,
|
fontSize: sizes.title,
|
||||||
marginHorizontal: Spacing.base,
|
marginHorizontal: Spacing.base,
|
||||||
...title,
|
...title
|
||||||
},
|
},
|
||||||
titleWithoutMargin: {
|
titleWithoutMargin: {
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
@@ -111,5 +107,5 @@ export default {
|
|||||||
fontFamily: fonts.bold,
|
fontFamily: fonts.bold,
|
||||||
fontWeight: '700',
|
fontWeight: '700',
|
||||||
fontSize: sizes.title,
|
fontSize: sizes.title,
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { render, screen } from '@testing-library/react-native'
|
import { render, screen } from '@testing-library/react-native'
|
||||||
|
import License from '../components/settings/License'
|
||||||
|
|
||||||
import License from '../../../components/settings/License'
|
jest.mock('react-i18next', () => ({
|
||||||
|
useTranslation: () => ({
|
||||||
|
t: (str, options) => {
|
||||||
|
return str + (options ? JSON.stringify(options) : '')
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}))
|
||||||
|
|
||||||
describe('License screen', () => {
|
describe('License screen', () => {
|
||||||
test('It should have a correct year', async () => {
|
test('It should have a correct year', async () => {
|
||||||
render(<License />)
|
render(<License setLicense={() => {}} />)
|
||||||
const year = new Date().getFullYear().toString()
|
const year = new Date().getFullYear().toString()
|
||||||
|
|
||||||
screen.getByText(year, { exact: false })
|
screen.getByText(year, { exact: false })
|
||||||
})
|
})
|
||||||
|
|
||||||
test('It should match the snapshot', async () => {
|
|
||||||
const licenseScreen = render(<License />)
|
|
||||||
|
|
||||||
expect(licenseScreen).toMatchSnapshot()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { render, screen, fireEvent } from '@testing-library/react-native'
|
|
||||||
|
|
||||||
import AcceptLicense from '../../components/AcceptLicense'
|
|
||||||
|
|
||||||
import { saveLicenseFlag } from '../../local-storage'
|
|
||||||
|
|
||||||
jest.mock('../../local-storage', () => ({
|
|
||||||
saveLicenseFlag: jest.fn(() => Promise.resolve()),
|
|
||||||
}))
|
|
||||||
|
|
||||||
describe('AcceptLicense', () => {
|
|
||||||
test('On clicking OK button, the license is accepted', async () => {
|
|
||||||
const mockedSetLicense = jest.fn()
|
|
||||||
render(<AcceptLicense setLicense={mockedSetLicense} />)
|
|
||||||
|
|
||||||
const okButton = screen.getByText('ok', { exact: false })
|
|
||||||
|
|
||||||
fireEvent(okButton, 'click')
|
|
||||||
|
|
||||||
await expect(saveLicenseFlag).toHaveBeenCalled()
|
|
||||||
expect(mockedSetLicense).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('There is a Cancel button', async () => {
|
|
||||||
render(<AcceptLicense setLicense={jest.fn()} />)
|
|
||||||
|
|
||||||
screen.getByText('cancel', { exact: false })
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,395 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`Stats screen when provided data, renders stats 1`] = `
|
|
||||||
<RCTSafeAreaView
|
|
||||||
emulateUnlessSupported={true}
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"backgroundColor": "#E9F2ED",
|
|
||||||
"flex": 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<RCTScrollView
|
|
||||||
contentContainerStyle={
|
|
||||||
Object {
|
|
||||||
"paddingHorizontal": 34.285714285714285,
|
|
||||||
"paddingTop": 34.285714285714285,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
cycle_length_explainer
|
|
||||||
</Text>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"alignItems": "center",
|
|
||||||
"flexDirection": "row",
|
|
||||||
"justifyContent": "space-between",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flex": 3,
|
|
||||||
"flexDirection": "column",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
accessibilityIgnoresInvertColors={true}
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"marginBottom": 42.857142857142854,
|
|
||||||
"paddingTop": 107.14285714285714,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
source={123}
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"bottom": 0,
|
|
||||||
"left": 0,
|
|
||||||
"position": "absolute",
|
|
||||||
"right": 0,
|
|
||||||
"top": 0,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"height": undefined,
|
|
||||||
"width": undefined,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"resizeMode": "contain",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Text
|
|
||||||
ellipsizeMode="clip"
|
|
||||||
numberOfLines={1}
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"color": "#3A2671",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 85.71428571428571,
|
|
||||||
"marginTop": -68.57142857142857,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
30.33
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"color": "#3A2671",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 68.57142857142857,
|
|
||||||
"marginTop": -34.285714285714285,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
days
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"color": "#F38337",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 27.857142857142858,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
average
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flex": 5,
|
|
||||||
"flexDirection": "column",
|
|
||||||
"paddingTop": 21.428571428571427,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<StatsOverview
|
|
||||||
data={
|
|
||||||
Array [
|
|
||||||
Array [
|
|
||||||
30,
|
|
||||||
"min",
|
|
||||||
],
|
|
||||||
Array [
|
|
||||||
31,
|
|
||||||
"max",
|
|
||||||
],
|
|
||||||
Array [
|
|
||||||
0.58,
|
|
||||||
"standard_deviation",
|
|
||||||
],
|
|
||||||
Array [
|
|
||||||
3,
|
|
||||||
"completed_cycles",
|
|
||||||
],
|
|
||||||
]
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
accessible={true}
|
|
||||||
collapsable={false}
|
|
||||||
focusable={true}
|
|
||||||
onClick={[Function]}
|
|
||||||
onResponderGrant={[Function]}
|
|
||||||
onResponderMove={[Function]}
|
|
||||||
onResponderRelease={[Function]}
|
|
||||||
onResponderTerminate={[Function]}
|
|
||||||
onResponderTerminationRequest={[Function]}
|
|
||||||
onStartShouldSetResponder={[Function]}
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"alignItems": "center",
|
|
||||||
"alignSelf": "center",
|
|
||||||
"backgroundColor": "#F38337",
|
|
||||||
"borderRadius": 25,
|
|
||||||
"flexDirection": "row",
|
|
||||||
"justifyContent": "center",
|
|
||||||
"marginTop": 34.285714285714285,
|
|
||||||
"minWidth": "15%",
|
|
||||||
"opacity": 1,
|
|
||||||
"paddingHorizontal": 8.571428571428571,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "white",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"fontSize": 27.857142857142858,
|
|
||||||
"padding": 21.428571428571427,
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
show_stats
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<AppHelp
|
|
||||||
text="standard_deviation_help"
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</RCTScrollView>
|
|
||||||
</RCTSafeAreaView>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`Stats screen when provided no data, renders no_data text 1`] = `
|
|
||||||
<RCTSafeAreaView
|
|
||||||
emulateUnlessSupported={true}
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"backgroundColor": "#E9F2ED",
|
|
||||||
"flex": 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<RCTScrollView
|
|
||||||
contentContainerStyle={
|
|
||||||
Object {
|
|
||||||
"paddingHorizontal": 34.285714285714285,
|
|
||||||
"paddingTop": 34.285714285714285,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
cycle_length_explainer
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
no_data
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</RCTScrollView>
|
|
||||||
</RCTSafeAreaView>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`Stats screen when provided null, renders no_data text 1`] = `
|
|
||||||
<RCTSafeAreaView
|
|
||||||
emulateUnlessSupported={true}
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"backgroundColor": "#E9F2ED",
|
|
||||||
"flex": 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<RCTScrollView
|
|
||||||
contentContainerStyle={
|
|
||||||
Object {
|
|
||||||
"paddingHorizontal": 34.285714285714285,
|
|
||||||
"paddingTop": 34.285714285714285,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
cycle_length_explainer
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
no_data
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</RCTScrollView>
|
|
||||||
</RCTSafeAreaView>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`Stats screen when provided undefined, renders no_data text 1`] = `
|
|
||||||
<RCTSafeAreaView
|
|
||||||
emulateUnlessSupported={true}
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"backgroundColor": "#E9F2ED",
|
|
||||||
"flex": 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<RCTScrollView
|
|
||||||
contentContainerStyle={
|
|
||||||
Object {
|
|
||||||
"paddingHorizontal": 34.285714285714285,
|
|
||||||
"paddingTop": 34.285714285714285,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
cycle_length_explainer
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
no_data
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</RCTScrollView>
|
|
||||||
</RCTSafeAreaView>
|
|
||||||
`;
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { render } from '@testing-library/react-native'
|
|
||||||
|
|
||||||
import AppHelp from '../../../components/common/AppHelp'
|
|
||||||
|
|
||||||
describe('AppHelp screen', () => {
|
|
||||||
test('when provided text, should render it', async () => {
|
|
||||||
const text = 'Some help test'
|
|
||||||
const { toJSON } = render(<AppHelp text={text} />)
|
|
||||||
|
|
||||||
expect(toJSON()).toMatchSnapshot()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { render } from '@testing-library/react-native'
|
|
||||||
|
|
||||||
import StatsOverview from '../../../components/common/StatsOverview'
|
|
||||||
|
|
||||||
describe('StatsOverview screen', () => {
|
|
||||||
test('when provided correct, renders it', async () => {
|
|
||||||
const data = [
|
|
||||||
[21, 'shortest'],
|
|
||||||
[21, 'longest'],
|
|
||||||
[0, 'standard deviation'],
|
|
||||||
[2, 'completed cycles'],
|
|
||||||
]
|
|
||||||
const { toJSON } = render(<StatsOverview data={data} />)
|
|
||||||
|
|
||||||
expect(toJSON()).toMatchSnapshot()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('when provided empty data, renders nothing (does not break)', async () => {
|
|
||||||
const data = []
|
|
||||||
const { toJSON } = render(<StatsOverview data={data} />)
|
|
||||||
|
|
||||||
expect(toJSON()).toMatchSnapshot()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { render } from '@testing-library/react-native'
|
|
||||||
|
|
||||||
import StatsTable from '../../../components/common/StatsTable'
|
|
||||||
|
|
||||||
const mockGetStats = jest
|
|
||||||
.fn()
|
|
||||||
.mockImplementationOnce(() => [
|
|
||||||
{ date: '2022-07-01', cycleLength: 31, bleedingLength: 5 },
|
|
||||||
{ date: '2022-06-01', cycleLength: 31, bleedingLength: 5 },
|
|
||||||
])
|
|
||||||
.mockImplementationOnce(() => [])
|
|
||||||
.mockImplementationOnce(() => null)
|
|
||||||
.mockImplementationOnce(() => undefined)
|
|
||||||
|
|
||||||
jest.mock('../../../lib/cycle', () => ({
|
|
||||||
__esModule: true,
|
|
||||||
default: () => ({
|
|
||||||
getStats: mockGetStats,
|
|
||||||
}),
|
|
||||||
}))
|
|
||||||
|
|
||||||
describe('StatsTable screen', () => {
|
|
||||||
test('when provided correct data set, renders it', async () => {
|
|
||||||
const { toJSON } = render(<StatsTable onClose={jest.fn()} />)
|
|
||||||
|
|
||||||
expect(toJSON()).toMatchSnapshot()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('when provided no data, renders nothing', async () => {
|
|
||||||
const { toJSON } = render(<StatsTable onClose={jest.fn()} />)
|
|
||||||
|
|
||||||
expect(toJSON()).toMatchSnapshot()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('when provided null, renders nothing', async () => {
|
|
||||||
const { toJSON } = render(<StatsTable onClose={jest.fn()} />)
|
|
||||||
|
|
||||||
expect(toJSON()).toMatchSnapshot()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('when provided undefined, renders nothing', async () => {
|
|
||||||
const { toJSON } = render(<StatsTable onClose={jest.fn()} />)
|
|
||||||
|
|
||||||
expect(toJSON()).toMatchSnapshot()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`AppHelp screen when provided text, should render it 1`] = `
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"alignItems": "center",
|
|
||||||
"flexDirection": "row",
|
|
||||||
"justifyContent": "space-between",
|
|
||||||
"padding": 34.285714285714285,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"alignSelf": "flex-start",
|
|
||||||
"color": "#3A2671",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 27.857142857142858,
|
|
||||||
"paddingRight": 34.285714285714285,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
*
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Some help test
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
`;
|
|
||||||
@@ -1,321 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`StatsOverview screen when provided correct, renders it 1`] = `
|
|
||||||
Array [
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flexDirection": "row",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"alignItems": "flex-end",
|
|
||||||
"flex": 3,
|
|
||||||
"justifyContent": "center",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
ellipsizeMode="clip"
|
|
||||||
numberOfLines={1}
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"color": "#3A2671",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 64.28571428571428,
|
|
||||||
"marginRight": 8.571428571428571,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
21
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flex": 5,
|
|
||||||
"flexDirection": "row",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
ellipsizeMode="tail"
|
|
||||||
numberOfLines={2}
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"color": "#F38337",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 27.857142857142858,
|
|
||||||
"margin": 15,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
shortest
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>,
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flexDirection": "row",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"alignItems": "flex-end",
|
|
||||||
"flex": 3,
|
|
||||||
"justifyContent": "center",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
ellipsizeMode="clip"
|
|
||||||
numberOfLines={1}
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"color": "#3A2671",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 64.28571428571428,
|
|
||||||
"marginRight": 8.571428571428571,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
21
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flex": 5,
|
|
||||||
"flexDirection": "row",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
ellipsizeMode="tail"
|
|
||||||
numberOfLines={2}
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"color": "#F38337",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 27.857142857142858,
|
|
||||||
"margin": 15,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
longest
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>,
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flexDirection": "row",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"alignItems": "flex-end",
|
|
||||||
"flex": 3,
|
|
||||||
"justifyContent": "center",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
ellipsizeMode="clip"
|
|
||||||
numberOfLines={1}
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"color": "#3A2671",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 64.28571428571428,
|
|
||||||
"marginRight": 8.571428571428571,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
0
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flex": 5,
|
|
||||||
"flexDirection": "row",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
ellipsizeMode="tail"
|
|
||||||
numberOfLines={2}
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"color": "#F38337",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 27.857142857142858,
|
|
||||||
"margin": 15,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
standard deviation
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"color": "#3A2671",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 64.28571428571428,
|
|
||||||
"marginRight": 8.571428571428571,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
*
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>,
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flexDirection": "row",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"alignItems": "flex-end",
|
|
||||||
"flex": 3,
|
|
||||||
"justifyContent": "center",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
ellipsizeMode="clip"
|
|
||||||
numberOfLines={1}
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"color": "#3A2671",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 64.28571428571428,
|
|
||||||
"marginRight": 8.571428571428571,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
2
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flex": 5,
|
|
||||||
"flexDirection": "row",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
ellipsizeMode="tail"
|
|
||||||
numberOfLines={2}
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"color": "#F38337",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 27.857142857142858,
|
|
||||||
"margin": 15,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
completed cycles
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>,
|
|
||||||
]
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`StatsOverview screen when provided empty data, renders nothing (does not break) 1`] = `null`;
|
|
||||||
@@ -1,433 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`StatsTable screen when provided correct data set, renders it 1`] = `
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"alignSelf": "center",
|
|
||||||
"backgroundColor": "#E9F2ED",
|
|
||||||
"marginTop": 137.14285714285714,
|
|
||||||
"maxHeight": 933.8,
|
|
||||||
"minHeight": "40%",
|
|
||||||
"position": "absolute",
|
|
||||||
"width": "100%",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flexDirection": "row",
|
|
||||||
"justifyContent": "flex-end",
|
|
||||||
"paddingRight": 34.285714285714285,
|
|
||||||
"paddingTop": 34.285714285714285,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
accessible={true}
|
|
||||||
collapsable={false}
|
|
||||||
focusable={true}
|
|
||||||
hitSlop={
|
|
||||||
Object {
|
|
||||||
"bottom": 39.23529411764706,
|
|
||||||
"left": 42.857142857142854,
|
|
||||||
"right": 42.857142857142854,
|
|
||||||
"top": 39.23529411764706,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onClick={[Function]}
|
|
||||||
onResponderGrant={[Function]}
|
|
||||||
onResponderMove={[Function]}
|
|
||||||
onResponderRelease={[Function]}
|
|
||||||
onResponderTerminate={[Function]}
|
|
||||||
onResponderTerminationRequest={[Function]}
|
|
||||||
onStartShouldSetResponder={[Function]}
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"alignSelf": "flex-start",
|
|
||||||
"marginBottom": 34.285714285714285,
|
|
||||||
"opacity": 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
allowFontScaling={false}
|
|
||||||
selectable={false}
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": undefined,
|
|
||||||
"fontSize": 12,
|
|
||||||
},
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"fontSize": 47.14285714285714,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
Object {
|
|
||||||
"color": "#F38337",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
Object {
|
|
||||||
"fontFamily": "Entypo",
|
|
||||||
"fontStyle": "normal",
|
|
||||||
"fontWeight": "normal",
|
|
||||||
},
|
|
||||||
Object {},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
<RCTScrollView
|
|
||||||
ItemSeparatorComponent={[Function]}
|
|
||||||
ListHeaderComponent={[Function]}
|
|
||||||
ListHeaderComponentStyle={
|
|
||||||
Object {
|
|
||||||
"borderBottomColor": "#3A2671",
|
|
||||||
"borderBottomWidth": 2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
contentContainerStyle={
|
|
||||||
Object {
|
|
||||||
"paddingHorizontal": 34.285714285714285,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"bleedingLength": 5,
|
|
||||||
"cycleLength": 31,
|
|
||||||
"date": "2022-07-01",
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"bleedingLength": 5,
|
|
||||||
"cycleLength": 31,
|
|
||||||
"date": "2022-06-01",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
getItem={[Function]}
|
|
||||||
getItemCount={[Function]}
|
|
||||||
keyExtractor={[Function]}
|
|
||||||
onContentSizeChange={[Function]}
|
|
||||||
onLayout={[Function]}
|
|
||||||
onMomentumScrollBegin={[Function]}
|
|
||||||
onMomentumScrollEnd={[Function]}
|
|
||||||
onScroll={[Function]}
|
|
||||||
onScrollBeginDrag={[Function]}
|
|
||||||
onScrollEndDrag={[Function]}
|
|
||||||
removeClippedSubviews={false}
|
|
||||||
renderItem={[Function]}
|
|
||||||
scrollEventThrottle={50}
|
|
||||||
stickyHeaderIndices={
|
|
||||||
Array [
|
|
||||||
0,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
viewabilityConfigCallbackPairs={Array []}
|
|
||||||
>
|
|
||||||
<View>
|
|
||||||
<View
|
|
||||||
onLayout={[Function]}
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"borderBottomColor": "#3A2671",
|
|
||||||
"borderBottomWidth": 2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"backgroundColor": "#E9F2ED",
|
|
||||||
"flexDirection": "row",
|
|
||||||
"justifyContent": "space-between",
|
|
||||||
"paddingVertical": 8.571428571428571,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flex": 3,
|
|
||||||
"justifyContent": "center",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"color": "#F38337",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 27.857142857142858,
|
|
||||||
"paddingVertical": 21.428571428571427,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
cycle_start
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flex": 2,
|
|
||||||
"justifyContent": "center",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"color": "#F38337",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 27.857142857142858,
|
|
||||||
"paddingVertical": 21.428571428571427,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
cycle_length
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flex": 2,
|
|
||||||
"justifyContent": "center",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"color": "#F38337",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 27.857142857142858,
|
|
||||||
"paddingVertical": 21.428571428571427,
|
|
||||||
"textAlignVertical": "center",
|
|
||||||
"textTransform": "uppercase",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
bleeding
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
onLayout={[Function]}
|
|
||||||
style={null}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"backgroundColor": "#E9F2ED",
|
|
||||||
"flexDirection": "row",
|
|
||||||
"justifyContent": "space-between",
|
|
||||||
"paddingVertical": 8.571428571428571,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flex": 3,
|
|
||||||
"justifyContent": "center",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
01. Jul 22
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flex": 2,
|
|
||||||
"justifyContent": "center",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
day{"count":31}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flex": 2,
|
|
||||||
"justifyContent": "center",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
day{"count":5}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"backgroundColor": "#888",
|
|
||||||
"height": 1,
|
|
||||||
"width": "100%",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
onLayout={[Function]}
|
|
||||||
style={null}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"backgroundColor": "#E9F2ED",
|
|
||||||
"flexDirection": "row",
|
|
||||||
"justifyContent": "space-between",
|
|
||||||
"paddingVertical": 8.571428571428571,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flex": 3,
|
|
||||||
"justifyContent": "center",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
01. Jun 22
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flex": 2,
|
|
||||||
"justifyContent": "center",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
day{"count":31}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"flex": 2,
|
|
||||||
"justifyContent": "center",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
day{"count":5}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</RCTScrollView>
|
|
||||||
</View>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`StatsTable screen when provided no data, renders nothing 1`] = `null`;
|
|
||||||
|
|
||||||
exports[`StatsTable screen when provided null, renders nothing 1`] = `null`;
|
|
||||||
|
|
||||||
exports[`StatsTable screen when provided undefined, renders nothing 1`] = `null`;
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`License screen It should match the snapshot 1`] = `
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"backgroundColor": "#E9F2ED",
|
|
||||||
"flex": 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<RCTScrollView
|
|
||||||
contentContainerStyle={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"backgroundColor": "#E9F2ED",
|
|
||||||
"flexGrow": 1,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<View>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"alignSelf": "center",
|
|
||||||
"color": "#3A2671",
|
|
||||||
"fontFamily": "Jost-Bold",
|
|
||||||
"fontSize": 51.42857142857143,
|
|
||||||
"fontWeight": "700",
|
|
||||||
"marginHorizontal": 34.285714285714285,
|
|
||||||
"marginVertical": 42.857142857142854,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
title
|
|
||||||
</Text>
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"marginBottom": 34.285714285714285,
|
|
||||||
"marginHorizontal": 34.285714285714285,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"color": "#555",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
text{"currentYear":2022}
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
onPress={[Function]}
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"color": "#3A2671",
|
|
||||||
"fontFamily": "Jost-Book",
|
|
||||||
"fontSize": 34.285714285714285,
|
|
||||||
"textDecorationLine": "underline",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
https://www.gnu.org/licenses/gpl-3.0.html
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</RCTScrollView>
|
|
||||||
</View>
|
|
||||||
`;
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { fireEvent, render } from '@testing-library/react-native'
|
|
||||||
|
|
||||||
import Stats from '../../components/stats'
|
|
||||||
|
|
||||||
jest.mock('../../components/common/AppHelp', () => 'AppHelp')
|
|
||||||
jest.mock('../../components/common/StatsOverview', () => 'StatsOverview')
|
|
||||||
jest.mock('../../components/common/StatsTable', () => 'StatsTable')
|
|
||||||
|
|
||||||
const mockGetAllCycleLengths = jest
|
|
||||||
.fn()
|
|
||||||
.mockImplementationOnce(() => [])
|
|
||||||
.mockImplementationOnce(() => [30, 31, 30])
|
|
||||||
.mockImplementationOnce(() => null)
|
|
||||||
.mockImplementationOnce(() => undefined)
|
|
||||||
.mockImplementationOnce(() => [30, 31, 30])
|
|
||||||
|
|
||||||
jest.mock('../../lib/cycle', () => ({
|
|
||||||
__esModule: true,
|
|
||||||
default: () => ({
|
|
||||||
getAllCycleLengths: mockGetAllCycleLengths,
|
|
||||||
}),
|
|
||||||
}))
|
|
||||||
|
|
||||||
describe('Stats screen', () => {
|
|
||||||
test('when provided no data, renders no_data text', async () => {
|
|
||||||
const { toJSON } = render(<Stats />)
|
|
||||||
|
|
||||||
expect(toJSON()).toMatchSnapshot()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('when provided data, renders stats', async () => {
|
|
||||||
const { toJSON } = render(<Stats />)
|
|
||||||
|
|
||||||
expect(toJSON()).toMatchSnapshot()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('when provided null, renders no_data text', async () => {
|
|
||||||
const { toJSON } = render(<Stats />)
|
|
||||||
|
|
||||||
expect(toJSON()).toMatchSnapshot()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('when provided undefined, renders no_data text', async () => {
|
|
||||||
const { toJSON } = render(<Stats />)
|
|
||||||
|
|
||||||
expect(toJSON()).toMatchSnapshot()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('when button is clicked, StatsTable is rendered', async () => {
|
|
||||||
const { getByText, findByTestId } = render(<Stats />)
|
|
||||||
const button = getByText('show_stats')
|
|
||||||
|
|
||||||
fireEvent(button, 'click')
|
|
||||||
|
|
||||||
await expect(findByTestId('statsTable')).toBeTruthy()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
module.exports = 123
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import { humanizeDate } from '../../components/helpers/format-date'
|
|
||||||
|
|
||||||
describe('humanizeDate', () => {
|
|
||||||
test('if receives null, returns empty string', () => {
|
|
||||||
const result = humanizeDate(null)
|
|
||||||
|
|
||||||
expect(result).toEqual('')
|
|
||||||
})
|
|
||||||
|
|
||||||
test('if receives undefined, returns empty string', () => {
|
|
||||||
const result = humanizeDate(undefined)
|
|
||||||
|
|
||||||
expect(result).toEqual('')
|
|
||||||
})
|
|
||||||
|
|
||||||
test('if receives incorrectly formatted date, returns empty string', () => {
|
|
||||||
const result = humanizeDate('abc')
|
|
||||||
|
|
||||||
expect(result).toEqual('')
|
|
||||||
})
|
|
||||||
|
|
||||||
test('if receives correct date string, returns date in humanized format', () => {
|
|
||||||
const result = humanizeDate('2022-01-07')
|
|
||||||
|
|
||||||
expect(result).toEqual('07. Jan 22')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
// Import Jest Native matchers
|
|
||||||
import '@testing-library/jest-native/extend-expect'
|
|
||||||
|
|
||||||
jest.mock('react-i18next', () => ({
|
|
||||||
useTranslation: () => ({
|
|
||||||
t: (str, options) => str + (options ? JSON.stringify(options) : ''),
|
|
||||||
}),
|
|
||||||
}))
|
|
||||||
@@ -102,12 +102,12 @@
|
|||||||
json5 "^2.2.1"
|
json5 "^2.2.1"
|
||||||
semver "^6.3.0"
|
semver "^6.3.0"
|
||||||
|
|
||||||
"@babel/eslint-parser@^7.19.1":
|
"@babel/eslint-parser@^7.16.3":
|
||||||
version "7.19.1"
|
version "7.16.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz#4f68f6b0825489e00a24b41b6a1ae35414ecd2f4"
|
resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.16.3.tgz#2a6b1702f3f5aea48e00cea5a5bcc241c437e459"
|
||||||
integrity sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==
|
integrity sha512-iB4ElZT0jAt7PKVaeVulOECdGe6UnmA/O0P9jlF5g5GBOwDVbna8AXhHRu4s27xQf6OkveyA8iTDv1jHdDejgQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1"
|
eslint-scope "^5.1.1"
|
||||||
eslint-visitor-keys "^2.1.0"
|
eslint-visitor-keys "^2.1.0"
|
||||||
semver "^6.3.0"
|
semver "^6.3.0"
|
||||||
|
|
||||||
@@ -1515,13 +1515,6 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-5.3.0.tgz#b6f01fa510c9d360134a77f7a2820bdca3a396bf"
|
resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-5.3.0.tgz#b6f01fa510c9d360134a77f7a2820bdca3a396bf"
|
||||||
integrity sha512-3uObVJ08i0vSbtsTWQ8omy8XUlVDnoest5MOLp6delLUZev8bu++S+3Aua7xWPPWzQt9pcuwDqjEOKslQVDj8g==
|
integrity sha512-3uObVJ08i0vSbtsTWQ8omy8XUlVDnoest5MOLp6delLUZev8bu++S+3Aua7xWPPWzQt9pcuwDqjEOKslQVDj8g==
|
||||||
|
|
||||||
"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1":
|
|
||||||
version "5.1.1-v1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129"
|
|
||||||
integrity sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==
|
|
||||||
dependencies:
|
|
||||||
eslint-scope "5.1.1"
|
|
||||||
|
|
||||||
"@ptomasroos/react-native-multi-slider@^2.2.0":
|
"@ptomasroos/react-native-multi-slider@^2.2.0":
|
||||||
version "2.2.2"
|
version "2.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/@ptomasroos/react-native-multi-slider/-/react-native-multi-slider-2.2.2.tgz#35a97fb8c355627c6a2ded010b360ac5728b44ad"
|
resolved "https://registry.yarnpkg.com/@ptomasroos/react-native-multi-slider/-/react-native-multi-slider-2.2.2.tgz#35a97fb8c355627c6a2ded010b360ac5728b44ad"
|
||||||
@@ -3411,7 +3404,7 @@ eslint-plugin-react@^7.8.2:
|
|||||||
resolve "^2.0.0-next.3"
|
resolve "^2.0.0-next.3"
|
||||||
string.prototype.matchall "^4.0.5"
|
string.prototype.matchall "^4.0.5"
|
||||||
|
|
||||||
eslint-scope@5.1.1, eslint-scope@^5.1.1:
|
eslint-scope@^5.1.1:
|
||||||
version "5.1.1"
|
version "5.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
|
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
|
||||||
integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
|
integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
|
||||||
@@ -5436,6 +5429,13 @@ lines-and-columns@^1.1.6:
|
|||||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
||||||
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
|
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
|
||||||
|
|
||||||
|
linkify-it@^2.2.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf"
|
||||||
|
integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==
|
||||||
|
dependencies:
|
||||||
|
uc.micro "^1.0.1"
|
||||||
|
|
||||||
locate-path@^3.0.0:
|
locate-path@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
|
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
|
||||||
@@ -5580,6 +5580,11 @@ mdast-util-compact@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
unist-util-visit "^1.1.0"
|
unist-util-visit "^1.1.0"
|
||||||
|
|
||||||
|
mdurl@^1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
|
||||||
|
integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==
|
||||||
|
|
||||||
memoize-one@^5.2.1:
|
memoize-one@^5.2.1:
|
||||||
version "5.2.1"
|
version "5.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
|
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
|
||||||
@@ -6898,6 +6903,14 @@ react-native-fs@^2.20.0:
|
|||||||
base-64 "^0.1.0"
|
base-64 "^0.1.0"
|
||||||
utf8 "^3.0.0"
|
utf8 "^3.0.0"
|
||||||
|
|
||||||
|
react-native-hyperlink@0.0.19:
|
||||||
|
version "0.0.19"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-native-hyperlink/-/react-native-hyperlink-0.0.19.tgz#ca375cde1d244bb94c551736852ee0d688c8bb1f"
|
||||||
|
integrity sha512-x4wuRGDMnnpWcRr5MCK1D2UcEuzD9IHK8lfjEhO/+QqXNaX31HdeD3ss3BXXZgHxpRYtLbTB0TuFcl1HHANp3w==
|
||||||
|
dependencies:
|
||||||
|
linkify-it "^2.2.0"
|
||||||
|
mdurl "^1.0.0"
|
||||||
|
|
||||||
react-native-modal-datetime-picker@14.0.0:
|
react-native-modal-datetime-picker@14.0.0:
|
||||||
version "14.0.0"
|
version "14.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-native-modal-datetime-picker/-/react-native-modal-datetime-picker-14.0.0.tgz#ca2c81a275ee3a23d9ad02113e76ed243c90781e"
|
resolved "https://registry.yarnpkg.com/react-native-modal-datetime-picker/-/react-native-modal-datetime-picker-14.0.0.tgz#ca2c81a275ee3a23d9ad02113e76ed243c90781e"
|
||||||
@@ -8267,6 +8280,11 @@ ua-parser-js@^0.7.30:
|
|||||||
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6"
|
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6"
|
||||||
integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==
|
integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==
|
||||||
|
|
||||||
|
uc.micro@^1.0.1:
|
||||||
|
version "1.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
|
||||||
|
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
|
||||||
|
|
||||||
uglify-es@^3.1.9:
|
uglify-es@^3.1.9:
|
||||||
version "3.3.9"
|
version "3.3.9"
|
||||||
resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677"
|
resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677"
|
||||||
|
|||||||
Reference in New Issue
Block a user