Introduces NFP section redesign, upgrades slider version
This commit is contained in:
@@ -65,6 +65,7 @@ android/app/.project
|
||||
|
||||
ios/Podfile.lock
|
||||
android/app/src/main/res/drawable-*
|
||||
android/app/src/main/assets/*
|
||||
|
||||
# nodejs-mobile creates these with every npm install
|
||||
nodejs-assets/nodejs-project/sample-*
|
||||
|
||||
@@ -3,15 +3,21 @@ import PropTypes from 'prop-types'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
|
||||
import AppText from './app-text'
|
||||
import AppIcon from './app-icon'
|
||||
|
||||
import { Colors, Spacing, Typography } from '../../styles/redesign'
|
||||
import { Colors, Containers, Spacing, Typography } from '../../styles/redesign'
|
||||
|
||||
const Segment = ({ children, last, title }) => {
|
||||
const Segment = ({ children, icon, last, title }) => {
|
||||
const containerStyle = last ? styles.containerLast : styles.container
|
||||
|
||||
return (
|
||||
<View style={containerStyle}>
|
||||
{title && <AppText style={styles.title}>{title}</AppText>}
|
||||
{title &&
|
||||
<View style={styles.line}>
|
||||
{icon && <AppIcon name={icon} color={Colors.purple} />}
|
||||
<AppText style={styles.title}>{title}</AppText>
|
||||
</View>
|
||||
}
|
||||
{children}
|
||||
</View>
|
||||
)
|
||||
@@ -19,6 +25,7 @@ const Segment = ({ children, last, title }) => {
|
||||
|
||||
Segment.propTypes = {
|
||||
children: PropTypes.node,
|
||||
icon: PropTypes.string,
|
||||
last: PropTypes.bool,
|
||||
title: PropTypes.string
|
||||
}
|
||||
@@ -39,6 +46,10 @@ const styles = StyleSheet.create({
|
||||
containerLast: {
|
||||
...segmentContainer
|
||||
},
|
||||
line: {
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
title: {
|
||||
...Typography.subtitle
|
||||
}
|
||||
|
||||
@@ -1,39 +1,114 @@
|
||||
import React, { Component } from 'react'
|
||||
import {
|
||||
ScrollView, View
|
||||
} from 'react-native'
|
||||
import styles from '../../../styles'
|
||||
import labels from '../../../i18n/en/settings'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import Slider from '@ptomasroos/react-native-multi-slider'
|
||||
|
||||
import alertError from '../shared/alert-error'
|
||||
import AppPage from '../../common/app-page'
|
||||
import AppSwitch from '../../common/app-switch'
|
||||
import AppText from '../../common/app-text'
|
||||
import Label from './label'
|
||||
import Segment from '../../common/segment'
|
||||
import TempSlider from './temp-slider'
|
||||
import UseCervixSetting from './use-cervix'
|
||||
import Icon from 'react-native-vector-icons/Entypo'
|
||||
|
||||
import { useCervixObservable,
|
||||
saveUseCervix,
|
||||
scaleObservable,
|
||||
saveTempScale
|
||||
} from '../../../local-storage'
|
||||
import { Colors, Sizes } from '../../../styles/redesign'
|
||||
import labels from '../../../i18n/en/settings'
|
||||
import config from '../../../config'
|
||||
|
||||
export default class Settings extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {}
|
||||
|
||||
this.state = {
|
||||
useCervix: useCervixObservable.value,
|
||||
temperatureScale: { ...scaleObservable.value }
|
||||
}
|
||||
}
|
||||
|
||||
onCervixToggle = (value) => {
|
||||
this.setState({ useCervix: value })
|
||||
saveUseCervix(value)
|
||||
}
|
||||
|
||||
onSliderChange = (values) => {
|
||||
this.setState({ min: values[0], max: values[1] })
|
||||
}
|
||||
|
||||
onSliderChangeFinish = (values) => {
|
||||
this.setState({ min: values[0], max: values[1] })
|
||||
|
||||
try {
|
||||
saveTempScale({ min: values[0], max: values[1] })
|
||||
} catch(err) {
|
||||
alertError(labels.tempScale.saveError)
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { useCervix } = this.state
|
||||
const cervixText = useCervix ?
|
||||
labels.useCervix.cervixModeOn : labels.useCervix.cervixModeOff
|
||||
const { min, max } = this.state.temperatureScale
|
||||
return (
|
||||
<ScrollView>
|
||||
<AppPage>
|
||||
<Segment title={labels.useCervix.title}>
|
||||
<UseCervixSetting/>
|
||||
<AppSwitch
|
||||
onToggle={this.onCervixToggle}
|
||||
text={cervixText}
|
||||
value={useCervix}
|
||||
/>
|
||||
</Segment>
|
||||
<Segment title={labels.tempScale.segmentTitle}>
|
||||
<AppText>{labels.tempScale.segmentExplainer}</AppText>
|
||||
<TempSlider/>
|
||||
</Segment>
|
||||
<Segment style={styles.framedSegmentLast} >
|
||||
<View style={{flexDirection: 'row', alignItems: 'center'}}>
|
||||
<Icon name="info-with-circle"/>
|
||||
<AppText style={styles.framedSegmentTitle}>{` ${labels.preOvu.title} `}</AppText>
|
||||
<View style={styles.container}>
|
||||
<Slider
|
||||
customLabel={Label}
|
||||
enableLabel={true}
|
||||
markerStyle={styles.marker}
|
||||
markerOffsetY={Sizes.tiny}
|
||||
max={config.temperatureScale.max}
|
||||
min={config.temperatureScale.min}
|
||||
onValuesChange={this.onSliderChange}
|
||||
onValuesChangeFinish={this.onSliderChangeFinish}
|
||||
selectedStyle={styles.sliderAccentBackground}
|
||||
step={config.temperatureScale.step}
|
||||
trackStyle={styles.slider}
|
||||
unselectedStyle={styles.sliderBackground}
|
||||
values={[min, max]}
|
||||
/>
|
||||
</View>
|
||||
</Segment>
|
||||
<Segment icon="info-with-circle" last title={labels.preOvu.title}>
|
||||
<AppText>{labels.preOvu.note}</AppText>
|
||||
</Segment>
|
||||
</ScrollView>
|
||||
</AppPage>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
alignItems: 'center',
|
||||
paddingTop: Sizes.base
|
||||
},
|
||||
marker: {
|
||||
backgroundColor: Colors.tourquiseDark,
|
||||
borderRadius: 50,
|
||||
elevation: 4,
|
||||
height: Sizes.subtitle,
|
||||
width: Sizes.subtitle
|
||||
},
|
||||
slider: {
|
||||
borderRadius: 25,
|
||||
height: Sizes.small
|
||||
},
|
||||
sliderAccentBackground: {
|
||||
backgroundColor: Colors.tourquiseDark
|
||||
},
|
||||
sliderBackground: {
|
||||
backgroundColor: Colors.tourquise
|
||||
},
|
||||
})
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { StyleSheet } from 'react-native'
|
||||
|
||||
import AppText from '../../common/app-text'
|
||||
|
||||
import { Sizes } from '../../../styles/redesign'
|
||||
|
||||
const sliderRadius = 5
|
||||
const width = 50
|
||||
|
||||
export default class Label extends React.Component {
|
||||
static propTypes = {
|
||||
oneMarkerValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
twoMarkerValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
oneMarkerLeftPosition: PropTypes.number,
|
||||
twoMarkerLeftPosition: PropTypes.number,
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const {
|
||||
oneMarkerValue,
|
||||
twoMarkerValue,
|
||||
oneMarkerLeftPosition,
|
||||
twoMarkerLeftPosition,
|
||||
} = this.props
|
||||
|
||||
const minCoordinate = oneMarkerLeftPosition - width / 2 + sliderRadius
|
||||
const maxCoordinate = twoMarkerLeftPosition - width / 2 + sliderRadius
|
||||
const isMinNumber = Number.isFinite(oneMarkerLeftPosition) &&
|
||||
Number.isFinite(oneMarkerValue)
|
||||
const isMaxNumber = Number.isFinite(twoMarkerLeftPosition) &&
|
||||
Number.isFinite(twoMarkerValue)
|
||||
const minStyle = [styles.label, { left: minCoordinate }]
|
||||
const maxStyle = [styles.label, { left: maxCoordinate }]
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{isMinNumber && <AppText style={minStyle}>{oneMarkerValue}</AppText>}
|
||||
{isMaxNumber && <AppText style={maxStyle}>{twoMarkerValue}</AppText>}
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
label: {
|
||||
position: 'absolute',
|
||||
marginTop: (-1) * Sizes.base
|
||||
}
|
||||
})
|
||||
@@ -1,71 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import { View } from 'react-native'
|
||||
import Slider from '@ptomasroos/react-native-multi-slider'
|
||||
import AppText from '../../common/app-text'
|
||||
import {
|
||||
scaleObservable,
|
||||
saveTempScale,
|
||||
} from '../../../local-storage'
|
||||
import { secondaryColor } from '../../../styles/index'
|
||||
import labels from '../../../i18n/en/settings'
|
||||
import config from '../../../config'
|
||||
import alertError from '../shared/alert-error'
|
||||
|
||||
export default class TempSlider extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = Object.assign({}, scaleObservable.value)
|
||||
}
|
||||
|
||||
onValuesChange = (values) => {
|
||||
this.setState({
|
||||
min: values[0],
|
||||
max: values[1]
|
||||
})
|
||||
}
|
||||
|
||||
onValuesChangeFinish = (values) => {
|
||||
this.setState({
|
||||
min: values[0],
|
||||
max: values[1]
|
||||
})
|
||||
try {
|
||||
saveTempScale(this.state)
|
||||
} catch(err) {
|
||||
alertError(labels.tempScale.saveError)
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={{ alignItems: 'center' }}>
|
||||
<AppText>{`${labels.tempScale.min} ${this.state.min.toFixed(1)}`}</AppText>
|
||||
<AppText>{`${labels.tempScale.max} ${this.state.max.toFixed(1)}`}</AppText>
|
||||
<Slider
|
||||
values={[this.state.min, this.state.max]}
|
||||
min={config.temperatureScale.min}
|
||||
max={config.temperatureScale.max}
|
||||
step={0.5}
|
||||
onValuesChange={this.onValuesChange}
|
||||
onValuesChangeFinish={this.onValuesChangeFinish}
|
||||
selectedStyle={{
|
||||
backgroundColor: 'darkgrey',
|
||||
}}
|
||||
unselectedStyle={{
|
||||
backgroundColor: 'silver',
|
||||
}}
|
||||
trackStyle={{
|
||||
height: 10,
|
||||
}}
|
||||
markerStyle={{
|
||||
backgroundColor: secondaryColor,
|
||||
height: 20,
|
||||
width: 20,
|
||||
borderRadius: 100,
|
||||
marginTop: 10
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import {
|
||||
View,
|
||||
Switch
|
||||
} from 'react-native'
|
||||
import AppText from '../../common/app-text'
|
||||
import {
|
||||
useCervixObservable,
|
||||
saveUseCervix
|
||||
} from '../../../local-storage'
|
||||
import labels from '../../../i18n/en/settings'
|
||||
|
||||
export default class UseCervixSetting extends Component {
|
||||
constructor() {
|
||||
super()
|
||||
this.state = {useCervix: useCervixObservable.value}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||
<View style={{ flex: 1 }}>
|
||||
{this.state.useCervix ?
|
||||
<AppText>{labels.useCervix.cervixModeOn}</AppText>
|
||||
:
|
||||
<AppText>{labels.useCervix.cervixModeOff}</AppText>
|
||||
}
|
||||
</View>
|
||||
<Switch
|
||||
value={this.state.useCervix}
|
||||
onValueChange={bool => {
|
||||
this.setState({ useCervix: bool })
|
||||
saveUseCervix(bool)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ const config = {
|
||||
defaultHigh: 38,
|
||||
min: 34,
|
||||
max: 40,
|
||||
step: 0.5,
|
||||
units: 0.1,
|
||||
verticalPadding: 0.03
|
||||
},
|
||||
|
||||
Generated
+4112
-5530
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -27,7 +27,7 @@
|
||||
"postinstall": "npx jetify"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ptomasroos/react-native-multi-slider": "^1.0.0",
|
||||
"@ptomasroos/react-native-multi-slider": "^2.2.0",
|
||||
"ajv": "^5.5.2",
|
||||
"assert": "^1.4.1",
|
||||
"csvtojson": "^2.0.8",
|
||||
|
||||
@@ -7,6 +7,7 @@ export const fonts = {
|
||||
}
|
||||
|
||||
export const sizes = {
|
||||
tiny: 7,
|
||||
small: 14,
|
||||
base: 18,
|
||||
subtitle: 22,
|
||||
|
||||
Reference in New Issue
Block a user