Merge branch 'feature/add-stats-explainer-take2' into 'main'

Feature: add stats explainer take2

See merge request bloodyhealth/drip!546
This commit is contained in:
Maria Zadnepryanets
2022-09-26 17:19:23 +00:00
8 changed files with 224 additions and 181 deletions
+1 -1
View File
@@ -71,7 +71,7 @@ const Home = ({ navigate, setDate }) => {
<Button isCTA isSmall={false} onPress={navigateToCycleDayView}>
{t('labels.home.addDataForToday')}
</Button>
{phase && <Footnote>{statusText}</Footnote>}
{phase && <Footnote colorLabel="greyLight">{statusText}</Footnote>}
</ScrollView>
)
}
+12 -5
View File
@@ -7,13 +7,16 @@ import Asterisk from '../common/Asterisk'
import { Colors, Spacing } from '../../styles'
const Footnote = ({ children }) => {
const Footnote = ({ children, colorLabel }) => {
if (!children) return false
return (
<View style={styles.container}>
<Asterisk />
<AppText linkStyle={styles.link} style={styles.text}>
<AppText
linkStyle={styles.link}
style={{ ...styles.text, color: Colors[colorLabel] }}
>
{children}
</AppText>
</View>
@@ -22,6 +25,11 @@ const Footnote = ({ children }) => {
Footnote.propTypes = {
children: PropTypes.node,
colorLabel: PropTypes.string,
}
Footnote.defaultProps = {
colorLabel: 'greyDark',
}
const styles = StyleSheet.create({
@@ -29,14 +37,13 @@ const styles = StyleSheet.create({
flexDirection: 'row',
alignContent: 'flex-start',
marginBottom: Spacing.tiny,
marginTop: Spacing.small,
marginTop: Spacing.base,
},
link: {
color: 'white',
},
text: {
color: Colors.greyLight,
paddingLeft: Spacing.base,
paddingLeft: Spacing.small,
},
})
+39 -4
View File
@@ -1,9 +1,18 @@
import React from 'react'
import { Modal, StyleSheet, TouchableOpacity } from 'react-native'
import {
Dimensions,
Modal,
StyleSheet,
TouchableOpacity,
View,
} from 'react-native'
import PropTypes from 'prop-types'
const AppModal = ({ children, onClose }) => {
return (
import CloseIcon from './close-icon'
import { Sizes, Spacing } from '../../styles'
const AppModal = ({ children, onClose }) => (
<Modal
animationType="fade"
onRequestClose={onClose}
@@ -11,10 +20,14 @@ const AppModal = ({ children, onClose }) => {
visible={true}
>
<TouchableOpacity onPress={onClose} style={styles.blackBackground} />
<View style={styles.modalWindow}>
<View style={styles.headerContainer}>
<CloseIcon onClose={onClose} />
</View>
{children}
</View>
</Modal>
)
}
AppModal.propTypes = {
children: PropTypes.node,
@@ -27,6 +40,28 @@ const styles = StyleSheet.create({
flex: 1,
opacity: 0.5,
},
headerContainer: {
flexDirection: 'row',
justifyContent: 'flex-end',
paddingTop: Spacing.base,
paddingHorizontal: Spacing.base,
position: 'absolute',
width: '100%',
zIndex: 3, // works on ios
elevation: 3, // works on android
},
modalWindow: {
alignSelf: 'center',
backgroundColor: 'white',
borderRadius: 10,
marginTop: Sizes.huge * 2,
paddingVertical: Spacing.large * 2,
position: 'absolute',
maxHeight: Dimensions.get('window').height * 0.7,
zIndex: 2, // works on ios
elevation: 2, // works on android
minWidth: '80%',
},
})
export default AppModal
+1 -27
View File
@@ -1,13 +1,12 @@
import React, { useState } from 'react'
import PropTypes from 'prop-types'
import { Dimensions, ScrollView, StyleSheet, View } from 'react-native'
import { ScrollView, StyleSheet, View } from 'react-native'
import AppModal from '../common/app-modal'
import AppSwitch from '../common/app-switch'
import AppText from '../common/app-text'
import AppTextInput from '../common/app-text-input'
import Button from '../common/button'
import CloseIcon from '../common/close-icon'
import Segment from '../common/segment'
import SelectBoxGroup from './select-box-group'
import SelectTabGroup from './select-tab-group'
@@ -119,10 +118,6 @@ const SymptomEditView = ({ date, onClose, symptom, symptomData }) => {
return (
<AppModal onClose={onSave}>
<View style={styles.modalWindow}>
<View style={styles.headerContainer}>
<CloseIcon onClose={onSave} />
</View>
<ScrollView
contentContainerStyle={styles.modalContainer}
keyboardDismissMode="on-drag"
@@ -211,7 +206,6 @@ const SymptomEditView = ({ date, onClose, symptom, symptomData }) => {
</Segment>
)}
</ScrollView>
</View>
</AppModal>
)
}
@@ -229,32 +223,12 @@ const styles = StyleSheet.create({
paddingHorizontal: Spacing.base,
paddingBottom: Spacing.base,
},
headerContainer: {
flexDirection: 'row',
justifyContent: 'flex-end',
paddingTop: Spacing.base,
paddingHorizontal: Spacing.base,
position: 'absolute',
width: '100%',
zIndex: 3, // works on ios
elevation: 3, // works on android
},
input: {
height: Sizes.base * 5,
},
modalContainer: {
paddingHorizontal: Spacing.base,
},
modalWindow: {
alignSelf: 'center',
backgroundColor: 'white',
borderRadius: 10,
marginTop: Sizes.huge * 2,
paddingTop: Spacing.large * 2,
position: 'absolute',
minHeight: '40%',
maxHeight: Dimensions.get('window').height * 0.7,
},
segmentBorder: {
borderBottomColor: Colors.greyLight,
},
@@ -3,6 +3,7 @@ import { FlatList, StyleSheet, View } from 'react-native'
import PropTypes from 'prop-types'
import { useTranslation } from 'react-i18next'
import AppModal from '../common/app-modal'
import AppText from '../common/app-text'
import cycleModule from '../../lib/cycle'
@@ -35,13 +36,15 @@ Item.propTypes = {
data: PropTypes.object.isRequired,
}
const StatsTable = () => {
const PeriodDetailsModal = ({ onClose }) => {
const renderItem = ({ item }) => <Item data={item} />
const data = cycleModule().getStats()
if (!data || data.length === 0) return false
return (
<AppModal onClose={onClose}>
<View>
<FlatList
data={data}
renderItem={renderItem}
@@ -52,9 +55,15 @@ const StatsTable = () => {
stickyHeaderIndices={[0]}
contentContainerStyle={styles.container}
/>
</View>
</AppModal>
)
}
PeriodDetailsModal.propTypes = {
onClose: PropTypes.func,
}
const ItemDivider = () => <View style={styles.divider} />
const FlatListHeader = () => (
@@ -89,7 +98,7 @@ const styles = StyleSheet.create({
flexDirection: 'row',
justifyContent: 'space-between',
paddingVertical: Spacing.tiny,
backgroundColor: Colors.turquoiseLight,
backgroundColor: 'white',
},
cell: {
flex: 2,
@@ -100,8 +109,10 @@ const styles = StyleSheet.create({
justifyContent: 'center',
},
container: {
minHeight: '40%',
minWidth: '95%',
paddingHorizontal: Spacing.base,
},
})
export default StatsTable
export default PeriodDetailsModal
+6 -2
View File
@@ -15,10 +15,12 @@ StatsOverview.propTypes = {
}
const Row = ({ rowContent }) => {
const isStandardDeviation = rowContent[1].includes('deviation')
return (
<View style={styles.row}>
<Cell content={rowContent[0]} isLeft />
<Cell content={rowContent[1]} />
<Cell content={rowContent[1]} hasAsterisk={isStandardDeviation} />
</View>
)
}
@@ -27,7 +29,7 @@ Row.propTypes = {
rowContent: PropTypes.array.isRequired,
}
const Cell = ({ content, isLeft }) => {
const Cell = ({ content, isLeft, hasAsterisk }) => {
const styleContainer = isLeft ? styles.cellLeft : styles.cellRight
const styleText = isLeft ? styles.accentPurpleBig : styles.accentOrange
const numberOfLines = isLeft ? 1 : 2
@@ -41,6 +43,7 @@ const Cell = ({ content, isLeft }) => {
style={styleText}
>
{content}
{hasAsterisk && <AppText style={styles.accentOrange}>*</AppText>}
</AppText>
</View>
)
@@ -49,6 +52,7 @@ const Cell = ({ content, isLeft }) => {
Cell.propTypes = {
content: PropTypes.node.isRequired,
isLeft: PropTypes.bool,
hasAsterisk: PropTypes.bool,
}
const styles = StyleSheet.create({
+20 -8
View File
@@ -1,11 +1,13 @@
import React from 'react'
import { ImageBackground, View } from 'react-native'
import React, { useState } from 'react'
import { ImageBackground, SafeAreaView, ScrollView, View } from 'react-native'
import { ScaledSheet } from 'react-native-size-matters'
import { useTranslation } from 'react-i18next'
import AppText from '../common/app-text'
import Button from '../common/button'
import Footnote from '../common/Footnote'
import StatsOverview from './StatsOverview'
import StatsTable from './StatsTable'
import PeriodDetailsModal from './PeriodDetailsModal'
import cycleModule from '../../lib/cycle'
import { getCycleLengthStats as getCycleInfo } from '../../lib/cycle-length'
@@ -15,6 +17,8 @@ import { Containers, Sizes, Spacing, Typography } from '../../styles'
const image = require('../../assets/cycle-icon.png')
const Stats = () => {
const [isStatsVisible, setIsStatsVisible] = useState(false)
const { t } = useTranslation(null, { keyPrefix: 'stats' })
const cycleLengths = cycleModule().getAllCycleLengths()
@@ -34,12 +38,13 @@ const Stats = () => {
]
return (
<View style={styles.pageContainer}>
<View style={styles.overviewContainer}>
<SafeAreaView style={styles.pageContainer}>
<ScrollView contentContainerStyle={styles.overviewContainer}>
<AppText>{t('intro')}</AppText>
{numberOfCycles === 0 ? (
<AppText>{t('noData')}</AppText>
) : (
<>
<View style={styles.container}>
<View style={styles.columnLeft}>
<ImageBackground
@@ -66,10 +71,17 @@ const Stats = () => {
<StatsOverview data={statsData} />
</View>
</View>
<Button isCTA onPress={() => setIsStatsVisible(true)}>
{t('showStats')}
</Button>
{isStatsVisible && (
<PeriodDetailsModal onClose={() => setIsStatsVisible(false)} />
)}
</View>
<StatsTable />
</View>
<Footnote>{t('footnote')}</Footnote>
</>
)}
</ScrollView>
</SafeAreaView>
)
}
@@ -7,7 +7,7 @@ exports[`Footnote component when children are present, renders them 1`] = `
"alignContent": "flex-start",
"flexDirection": "row",
"marginBottom": 8.571428571428571,
"marginTop": 21.428571428571427,
"marginTop": 34.285714285714285,
}
}
>
@@ -41,8 +41,8 @@ exports[`Footnote component when children are present, renders them 1`] = `
"fontSize": 34.285714285714285,
},
Object {
"color": "#CCC",
"paddingLeft": 34.285714285714285,
"color": "#555",
"paddingLeft": 21.428571428571427,
},
]
}