Introduces Home component redesign

This commit is contained in:
mashazyu
2020-03-24 20:15:01 +01:00
committed by Sofiya Tepikin
parent b6c0fd0dce
commit 29d76d19b1
11 changed files with 150 additions and 180 deletions
+9 -2
View File
@@ -6,10 +6,16 @@ import Link from './link'
import { Colors, Typography } from '../../styles/redesign' import { Colors, Typography } from '../../styles/redesign'
export default function AppText({ children, onPress, numberOfLines, style}) { export default function AppText({
children,
linkStyle,
onPress,
numberOfLines,
style
}) {
// we parse for links in case the text contains any // we parse for links in case the text contains any
return ( return (
<Link> <Link style={linkStyle}>
<Text style={[styles.text, style]} <Text style={[styles.text, style]}
onPress={onPress} onPress={onPress}
numberOfLines={numberOfLines} numberOfLines={numberOfLines}
@@ -22,6 +28,7 @@ export default function AppText({ children, onPress, numberOfLines, style}) {
AppText.propTypes = { AppText.propTypes = {
children: PropTypes.node, children: PropTypes.node,
linkStyle: PropTypes.object,
onPress: PropTypes.func, onPress: PropTypes.func,
numberOfLines: PropTypes.number, numberOfLines: PropTypes.number,
style: PropTypes.oneOfType([PropTypes.array, PropTypes.object]), style: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
+21 -10
View File
@@ -7,7 +7,7 @@ import AppText from './app-text'
import { Colors, Fonts, Spacing } from '../../styles/redesign' import { Colors, Fonts, Spacing } from '../../styles/redesign'
const Button = ({ children, isCTA, onPress, testID }) => { const Button = ({ children, isCTA, onPress, testID }) => {
const buttonStyle = isCTA ? styles.orange : {} const buttonStyle = isCTA ? styles.cta : styles.regular
const textStyle = isCTA ? styles.buttonTextBold : styles.buttonTextRegular const textStyle = isCTA ? styles.buttonTextBold : styles.buttonTextRegular
return ( return (
<TouchableOpacity onPress={onPress} style={buttonStyle} testID={testID}> <TouchableOpacity onPress={onPress} style={buttonStyle} testID={testID}>
@@ -23,24 +23,35 @@ Button.propTypes = {
testID: PropTypes.string testID: PropTypes.string
} }
const button = { const text = {
paddingHorizontal: Spacing.large, padding: Spacing.base,
paddingVertical: Spacing.base,
textTransform: 'uppercase' textTransform: 'uppercase'
} }
const button = {
alignItems: 'center',
justifyContent: 'center',
margin: Spacing.base
}
const styles = StyleSheet.create({ const styles = StyleSheet.create({
orange: { regular: {
...button
},
cta: {
backgroundColor: Colors.orange, backgroundColor: Colors.orange,
borderRadius: 25 borderRadius: 25,
...button
}, },
buttonTextBold: { buttonTextBold: {
fontFamily: Fonts.main, color: 'white',
...button fontFamily: Fonts.bold,
...text
}, },
buttonTextRegular: { buttonTextRegular: {
fontFamily: Fonts.bold, color: Colors.greyDark,
...button fontFamily: Fonts.main,
...text
} }
}) })
+4 -3
View File
@@ -7,10 +7,10 @@ import { Colors, Typography } from '../../styles/redesign'
import links from '../../i18n/en/links' import links from '../../i18n/en/links'
const Link = ({ children }) => { const Link = ({ children, style }) => {
return ( return (
<Hyperlink <Hyperlink
linkStyle={styles.link} linkStyle={[styles.link, style]}
linkText={replaceUrlWithText} linkText={replaceUrlWithText}
linkDefault linkDefault
> >
@@ -20,7 +20,8 @@ const Link = ({ children }) => {
} }
Link.propTypes = { Link.propTypes = {
children: PropTypes.node children: PropTypes.node,
style: PropTypes.object
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
+1 -1
View File
@@ -10,7 +10,7 @@ const Icon = createIconSetFromIcoMoon(iconConfig, '', 'Menu')
const MenuIcon = ({ isActive, name }) => { const MenuIcon = ({ isActive, name }) => {
const color = isActive ? Colors.greyDark : Colors.grey const color = isActive ? Colors.greyDark : Colors.grey
return <Icon name={name} size={Sizes.icon} color={color} /> return <Icon name={name} size={Sizes.huge} color={color} />
} }
MenuIcon.propTypes = { MenuIcon.propTypes = {
+7
View File
@@ -62,3 +62,10 @@ export function getBleedingPredictionRange(prediction) {
} }
return (daysToEnd === 0 ? '0' : `0 - ${daysToEnd}`) return (daysToEnd === 0 ? '0' : `0 - ${daysToEnd}`)
} }
export const dateEnding = {
'1': 'st',
'2': 'nd',
'3': 'rd',
'default': 'th'
}
-40
View File
@@ -1,40 +0,0 @@
import React from 'react'
import { View } from 'react-native'
import PropTypes from 'prop-types'
import Button from './common/button'
import styles from '../styles'
const HomeElement = ({ children, onPress, buttonColor, buttonLabel }) => {
return (
<View
onPress={ onPress }
style={ styles.homeElement }
>
<View style={styles.homeIconAndText}>
{children[0]}
{children[1]}
</View>
<View style={{paddingLeft: 15}}>
{children.slice(2)}
<Button
style={styles.homeButton}
onPress={ onPress }
backgroundColor={ buttonColor }>
{ buttonLabel }
</Button>
</View>
</View>
)
}
HomeElement.propTypes = {
buttonColor: PropTypes.string,
buttonLabel: PropTypes.string,
children: PropTypes.node,
onPress: PropTypes.func,
}
export default HomeElement
+99 -98
View File
@@ -1,54 +1,51 @@
import { LocalDate } from 'js-joda'
import React, { Component } from 'react' import React, { Component } from 'react'
import { ScrollView, View } from 'react-native' import { ScrollView, StyleSheet, View } from 'react-native'
import { connect } from 'react-redux'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { LocalDate } from 'js-joda'
import { connect } from 'react-redux'
import { navigate } from '../slices/navigation' import { navigate } from '../slices/navigation'
import { getDate, setDate } from '../slices/date' import { getDate, setDate } from '../slices/date'
import DripHomeIcon from '../assets/drip-home-icons'
import AppText from './common/app-text' import AppText from './common/app-text'
import IconText from './icon-text' import Button from './common/button'
import HomeElement from './home-element'
import { home as labels } from '../i18n/en/labels'
import links from '../i18n/en/links'
import cycleModule from '../lib/cycle' import cycleModule from '../lib/cycle'
import { getFertilityStatusForDay } from '../lib/sympto-adapter' import { getFertilityStatusForDay } from '../lib/sympto-adapter'
import { import { determinePredictionText, dateEnding } from './helpers/home'
determinePredictionText,
getBleedingPredictionRange
} from './helpers/home'
import styles, { cycleDayColor, periodColor, secondaryColor } from '../styles' import { Colors, Fonts, Sizes, Spacing } from '../styles/redesign'
import { homeRedesign as labels, home as cycle } from '../i18n/en/labels'
class Home extends Component { class Home extends Component {
static propTypes = { static propTypes = {
navigate: PropTypes.func, navigate: PropTypes.func,
setDate: PropTypes.func, setDate: PropTypes.func
// The following are not being used,
// we could see if it's possible to not pass them from the <App />
cycleDay: PropTypes.object,
date: PropTypes.string,
} }
constructor(props) { constructor(props) {
super(props) super(props)
const today = LocalDate.now()
this.todayDateString = today.toString()
const { getCycleDayNumber, getPredictedMenses } = cycleModule() const { getCycleDayNumber, getPredictedMenses } = cycleModule()
this.todayDateString = LocalDate.now().toString()
this.cycleDayNumber = getCycleDayNumber(this.todayDateString) this.cycleDayNumber = getCycleDayNumber(this.todayDateString)
const {status, phase, statusText} =
getFertilityStatusForDay(this.todayDateString)
const prediction = getPredictedMenses() const prediction = getPredictedMenses()
this.predictionText = determinePredictionText(prediction)
this.bleedingPredictionRange = getBleedingPredictionRange(prediction)
this.fertilityStatus = getFertilityStatusForDay(this.todayDateString) this.cycleDayText = !this.cycleDayNumber ? cycle.cycleDayNotEnoughInfo
: `${this.cycleDayNumber}${dateEnding[this.cycleDayNumber] || dateEnding['default']}`
this.phase = phase
this.phaseText = !phase ? statusText
: `${phase}${dateEnding[phase] || dateEnding['default']}`
this.prediction = determinePredictionText(prediction)
this.status = status
this.statusText = statusText
this.title = `${today.dayOfMonth()} ${today.month()}`
} }
navigateToCycleDayView = () => { navigateToCycleDayView = () => {
@@ -56,88 +53,92 @@ class Home extends Component {
this.props.navigate('CycleDay') this.props.navigate('CycleDay')
} }
navigateToBleedingEditView = () => {
this.props.setDate(this.todayDateString)
this.props.navigate('BleedingEditView')
}
navigateToChart = () => {
this.props.navigate('Chart')
}
render() { render() {
const { const {
cycleDayNumber, cycleDayText,
predictionText, phase,
bleedingPredictionRange, phaseText,
prediction,
status,
statusText,
title
} = this } = this
const { phase, status, statusText } = this.fertilityStatus
const cycleDayMoreText = cycleDayNumber ?
labels.cycleDayKnown(cycleDayNumber) :
labels.cycleDayNotEnoughInfo
return ( return (
<View flex={1}> <ScrollView
<ScrollView> style={styles.container}
<View style={styles.homeView}> contentContainerStyle={styles.contentContainer}
<HomeElement >
onPress={this.navigateToCycleDayView} <AppText style={styles.title}>{title}</AppText>
buttonColor={ cycleDayColor } <View style={styles.line}>
buttonLabel={ labels.editToday } {this.cycleDayNumber && (
> <React.Fragment>
<View> <AppText style={styles.whiteText}>{cycleDayText}</AppText>
<DripHomeIcon name="circle" size={80} color={cycleDayColor}/> <AppText>{labels.cycleDay}</AppText>
</View> </React.Fragment>
<IconText>{cycleDayNumber || labels.unknown}</IconText> )}
{!this.cycleDayNumber && <AppText>{cycleDayText}</AppText>}
<AppText style={styles.homeDescriptionText}> </View>
{cycleDayMoreText} <View style={styles.line}>
</AppText> {!phase && <AppText>{phaseText}</AppText>}
</HomeElement> {phase && (
<React.Fragment>
<HomeElement <AppText style={styles.whiteText}>{phaseText}</AppText>
onPress={this.navigateToBleedingEditView} <AppText>{labels.cyclePhase}</AppText>
buttonColor={ periodColor } <AppText>{status}</AppText>
buttonLabel={ labels.trackPeriod } <Asterisk />
> </React.Fragment>
<DripHomeIcon name="drop" size={100} color={periodColor} /> )}
</View>
<IconText wrapperStyles={{ top: '45%' }}> <View style={styles.line}>
{bleedingPredictionRange} <AppText>{prediction}</AppText>
</IconText> </View>
<Button onPress={this.navigateToCycleDayView} isCTA>
<AppText style={styles.homeDescriptionText}> {labels.addData}
{predictionText} </Button>
</AppText> {phase && (
</HomeElement> <View style={styles.line}>
<Asterisk />
<HomeElement <AppText linkStyle={styles.whiteText}>{statusText}</AppText>
onPress={this.navigateToChart}
buttonColor={ secondaryColor }
buttonLabel={ labels.checkFertility }
>
<View style={styles.homeCircle}/>
<IconText>{ phase ? phase.toString() : labels.unknown }</IconText>
{ phase &&
<AppText style={styles.homeDescriptionText}>
{`${labels.phase(phase)} (${status})`}
</AppText>
}
<AppText style={styles.homeDescriptionText}>
{ `${statusText} Visit ${links.wiki.url}.` }
</AppText>
</HomeElement>
</View> </View>
</ScrollView> )}
</View> </ScrollView>
) )
} }
} }
const Asterisk = () => {
return <AppText style={styles.asterisk}>*</AppText>
}
const styles = StyleSheet.create({
asterisk: {
color: Colors.orange,
paddingRight: Spacing.base
},
container: {
backgroundColor: Colors.purple,
flex: 1
},
contentContainer: {
padding: Spacing.base
},
line: {
flexDirection: 'row',
justifyContent: 'flex-start',
marginBottom: Spacing.tiny
},
title: {
color: Colors.purpleLight,
fontFamily: Fonts.bold,
fontSize: Sizes.huge,
marginVertical: Spacing.base,
},
whiteText: {
color: 'white'
}
})
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
return({ return({
date: getDate(state), date: getDate(state),
-24
View File
@@ -1,24 +0,0 @@
import React from 'react'
import { View } from 'react-native'
import PropTypes from 'prop-types'
import AppText from './common/app-text'
import styles from '../styles'
const IconText = ({ children, wrapperStyles }) => {
return (
<View style={[ styles.homeIconTextWrapper, wrapperStyles ]}>
<AppText style={styles.iconText}>
{ children }
</AppText>
</View>
)
}
IconText.propTypes = {
children: PropTypes.node,
wrapperStyles: PropTypes.object,
}
export default IconText
+7 -1
View File
@@ -1,6 +1,12 @@
import labels from './settings' import labels from './settings'
const settingsTitles = labels.menuItems const settingsTitles = labels.menuItems
export const homeRedesign = {
cycleDay: ' day of your cycle',
cyclePhase: ' cycle phase - ',
addData: 'add data for today'
}
export const shared = { export const shared = {
cancel: 'Cancel', cancel: 'Cancel',
save: 'Save', save: 'Save',
@@ -113,7 +119,7 @@ export const fertilityStatus = {
fertileUntilEvening: 'Fertile phase ends in the evening', fertileUntilEvening: 'Fertile phase ends in the evening',
unknown: 'We cannot show any cycle information because no period data has been added.', unknown: 'We cannot show any cycle information because no period data has been added.',
preOvuText: "With NFP rules, you may assume 5 days of infertility at the beginning of your cycle, provided you don't observe any fertile cervical mucus or cervix values.", preOvuText: "With NFP rules, you may assume 5 days of infertility at the beginning of your cycle, provided you don't observe any fertile cervical mucus or cervix values.",
periOvuText: "We have not been able to detect both a temperature shift and cervical mucus or cervix shift. Please find more information on NFP rules here:", periOvuText: "We have not been able to detect both a temperature shift and cervical mucus or cervix shift. Please find more information on NFP rules here: https://gitlab.com/bloodyhealth/drip/wikis/home",
postOvuText: tempRule => { postOvuText: tempRule => {
return ( return (
'We have detected a temperature shift (' + ['regular', '1st exception', '2nd exception'][tempRule] + 'We have detected a temperature shift (' + ['regular', '1st exception', '2nd exception'][tempRule] +
+1
View File
@@ -1,4 +1,5 @@
export default { export default {
tiny: 4,
small: 10, small: 10,
base: 16, base: 16,
large: 20 large: 20
+1 -1
View File
@@ -11,7 +11,7 @@ export const sizes = {
base: 18, base: 18,
subtitle: 22, subtitle: 22,
title: 24, title: 24,
icon: 40 huge: 40
} }
const title = { const title = {