diff --git a/components/bleeding.js b/components/bleeding.js deleted file mode 100644 index 0472c3c73f7f4a4e2b21e236c5e93ea61fe55a1c..0000000000000000000000000000000000000000 --- a/components/bleeding.js +++ /dev/null @@ -1,102 +0,0 @@ -import React, { Component } from 'react' -import { - View, - Button, - Text, - Switch -} from 'react-native' -import RadioForm from 'react-native-simple-radio-button' -import styles from '../styles/index' -import { saveBleeding } from '../db' -import { bleeding as labels } from '../labels/labels' - -export default class Bleeding extends Component { - constructor(props) { - super(props) - this.cycleDay = props.cycleDay - this.showView = props.showView - let bleedingValue = this.cycleDay.bleeding && this.cycleDay.bleeding.value - if (! (typeof bleedingValue === 'number') ){ - bleedingValue = -1 - } - this.state = { - currentValue: bleedingValue, - exclude: this.cycleDay.bleeding ? this.cycleDay.bleeding.exclude : false - } - } - - render() { - const bleedingRadioProps = [ - {label: labels[0], value: 0 }, - {label: labels[1], value: 1 }, - {label: labels[2], value: 2 }, - {label: labels[3], value: 3 }, - ] - return ( - <View style={ styles.symptomEditView }> - <View style={ styles.symptomEditSplitSymptomsAndLastRowButtons }> - <View style={ styles.symptomEditListedSymptomView }> - <View style={{flex: 1}}> - <Text style={styles.symptomDayView}>Bleeding</Text> - </View> - <View style={{flex: 1}}> - <RadioForm - radio_props={bleedingRadioProps} - initial={this.state.currentValue} - formHorizontal={true} - labelHorizontal={false} - labelStyle={styles.radioButton} - onPress={(itemValue) => { - this.setState({currentValue: itemValue}) - }} - /> - </View> - </View> - <View style={ styles.itemsInRowSeparatedView }> - <View style={ styles.singleButtonView }> - <Text style={ styles.symptomDayView }>Exclude</Text> - </View> - <View style={ styles.singleButtonView }> - <Switch - onValueChange={(val) => { - this.setState({exclude: val}) - }} - value={this.state.exclude} - /> - </View> - </View> - </View> - <View style={ styles.itemsInRowSeparatedView }> - <View style={ styles.singleButtonView }> - <Button - onPress={() => this.showView('dayView')} - title="Cancel"> - </Button> - </View> - <View style={ styles.singleButtonView }> - <Button - onPress={() => { - saveBleeding(this.cycleDay) - this.showView('dayView') - }} - title="Delete"> - </Button> - </View> - <View style={ styles.singleButtonView }> - <Button - onPress={() => { - saveBleeding(this.cycleDay, { - value: this.state.currentValue, - exclude: this.state.exclude - }) - this.showView('dayView') - }} - disabled={ this.state.currentValue === -1 } - title="Save"> - </Button> - </View> - </View> - </View> - ) - } -} \ No newline at end of file diff --git a/components/cycle-day/action-buttons.js b/components/cycle-day/action-buttons.js new file mode 100644 index 0000000000000000000000000000000000000000..00085523344d66b1dd03fdd2a251529c4e65cd4c --- /dev/null +++ b/components/cycle-day/action-buttons.js @@ -0,0 +1,46 @@ +import React from 'react' +import { + View, + Button, +} from 'react-native' +import { saveSymptom } from '../../db' + +export default function (showView) { + return function ({ symptom, cycleDay, saveAction, saveDisabled}) { + const buttons = [ + { + title: 'Cancel', + action: () => showView('dayView') + }, + { + title: 'Delete', + action: () => { + saveSymptom(symptom, cycleDay) + showView('dayView') + } + }, { + title: 'Save', + action: () => { + saveAction() + showView('dayView') + }, + disabled: saveDisabled + } + ] + + return buttons.map(({ title, action, disabledCondition }, i) => { + const style = { flex: 1, marginHorizontal: 10 } + if (i === 0) style.marginLeft = 0 + if (i === buttons.length - 1) style.marginRight = 0 + return ( + <View style={style} key={i}> + <Button + onPress={action} + disabled={disabledCondition} + title={title}> + </Button> + </View > + ) + }) + } +} \ No newline at end of file diff --git a/components/cycle-day-overview.js b/components/cycle-day/cycle-day-overview.js similarity index 67% rename from components/cycle-day-overview.js rename to components/cycle-day/cycle-day-overview.js index cc780dae120d2f70332d08aa886448f87f18ba16..67415985c50ce1d969acf0aa5838ae639257d70c 100644 --- a/components/cycle-day-overview.js +++ b/components/cycle-day/cycle-day-overview.js @@ -4,10 +4,10 @@ import { Button, Text } from 'react-native' -import styles from '../styles/index' -import { bleeding as labels} from '../labels/labels' -import cycleDayModule from '../lib/get-cycle-day-number' -import { bleedingDaysSortedByDate } from '../db' +import styles from '../../styles' +import { bleeding as labels} from './labels/labels' +import cycleDayModule from '../../lib/get-cycle-day-number' +import { bleedingDaysSortedByDate } from '../../db' const getCycleDayNumber = cycleDayModule() @@ -47,30 +47,28 @@ export default class DayView extends Component { const temperatureValue = this.cycleDay.temperature && this.cycleDay.temperature.value let temperatureLabel if (typeof temperatureValue === 'number') { - temperatureLabel = `${temperatureValue} °C` - if (this.cycleDay.temperature.exclude) temperatureLabel = "( " + temperatureLabel + " )" + temperatureLabel = `${temperatureValue} °C - ${this.cycleDay.temperature.time}` + if (this.cycleDay.temperature.exclude) { + temperatureLabel = "( " + temperatureLabel + " )" + } } else { temperatureLabel = 'edit' } return ( - <View style={ styles.symptomEditListedSymptomView }> - <View style={ styles.itemsInRowSeparatedView }> - <View style={{flex: 1}}> - <Text style={styles.symptomDayView}>Bleeding</Text> - </View> - <View style={ styles.singleButtonView }> + <View style={styles.symptomEditView}> + <View style={styles.symptomViewRowInline}> + <Text style={styles.symptomDayView}>Bleeding</Text> + <View style={styles.symptomEditButton}> <Button onPress={() => this.showView('bleedingEditView')} title={bleedingLabel}> </Button> </View> </View> - <View style={ styles.itemsInRowSeparatedView}> - <View style={{flex: 1}}> - <Text style={styles.symptomDayView}>Temperature</Text> - </View> - <View style={ styles.singleButtonView }> + <View style={styles.symptomViewRowInline}> + <Text style={styles.symptomDayView}>Temperature</Text> + <View style={styles.symptomEditButton}> <Button onPress={() => this.showView('temperatureEditView')} title={temperatureLabel}> diff --git a/components/cycle-day.js b/components/cycle-day/index.js similarity index 70% rename from components/cycle-day.js rename to components/cycle-day/index.js index 7d46deaff6a993da2c09a21b1f6c68f1d9402b1a..bcd84651f05e14b725021fe983cb7bcaad78f33f 100644 --- a/components/cycle-day.js +++ b/components/cycle-day/index.js @@ -3,12 +3,13 @@ import { View, Text } from 'react-native' -import cycleDayModule from '../lib/get-cycle-day-number' +import cycleDayModule from '../../lib/get-cycle-day-number' import DayView from './cycle-day-overview' -import BleedingEditView from './bleeding' -import TemperatureEditView from './temperature' -import { formatDateForViewHeader } from '../labels/format' -import styles from '../styles/index' +import BleedingEditView from './symptoms/bleeding' +import TemperatureEditView from './symptoms/temperature' +import { formatDateForViewHeader } from './labels/format' +import styles from '../../styles' +import actionButtonModule from './action-buttons' const getCycleDayNumber = cycleDayModule() @@ -24,12 +25,14 @@ export default class Day extends Component { this.showView = view => { this.setState({visibleComponent: view}) } + + this.makeActionButtons = actionButtonModule(this.showView) } render() { const cycleDayNumber = getCycleDayNumber(this.cycleDay.date) return ( - <View style={ styles.cycleDayOuterView }> + <View> <View style={ styles.cycleDayDateView }> <Text style={styles.dateHeader}> {formatDateForViewHeader(this.cycleDay.date)} @@ -38,11 +41,11 @@ export default class Day extends Component { <View style={ styles.cycleDayNumberView }> { cycleDayNumber && <Text style={styles.cycleDayNumber} >Cycle day {cycleDayNumber}</Text> } </View > - <View style={ styles.cycleDaySymptomsView }> + <View> { { dayView: <DayView cycleDay={this.cycleDay} showView={this.showView} />, - bleedingEditView: <BleedingEditView cycleDay={this.cycleDay} showView={this.showView}/>, - temperatureEditView: <TemperatureEditView cycleDay={this.cycleDay} showView={this.showView}/> + bleedingEditView: <BleedingEditView cycleDay={this.cycleDay} makeActionButtons={this.makeActionButtons}/>, + temperatureEditView: <TemperatureEditView cycleDay={this.cycleDay} makeActionButtons={this.makeActionButtons}/> }[this.state.visibleComponent] } </View > diff --git a/labels/format.js b/components/cycle-day/labels/format.js similarity index 100% rename from labels/format.js rename to components/cycle-day/labels/format.js diff --git a/labels/labels.js b/components/cycle-day/labels/labels.js similarity index 100% rename from labels/labels.js rename to components/cycle-day/labels/labels.js diff --git a/components/cycle-day/symptoms/bleeding.js b/components/cycle-day/symptoms/bleeding.js new file mode 100644 index 0000000000000000000000000000000000000000..7ec0574b924c6556d82239af59d20efbab21966f --- /dev/null +++ b/components/cycle-day/symptoms/bleeding.js @@ -0,0 +1,76 @@ +import React, { Component } from 'react' +import { + View, + Text, + Switch +} from 'react-native' +import RadioForm from 'react-native-simple-radio-button' +import styles from '../../../styles' +import { saveSymptom } from '../../../db' +import { bleeding as labels } from '../labels/labels' + +export default class Bleeding extends Component { + constructor(props) { + super(props) + this.cycleDay = props.cycleDay + this.makeActionButtons = props.makeActionButtons + let bleedingValue = this.cycleDay.bleeding && this.cycleDay.bleeding.value + if (!(typeof bleedingValue === 'number')) { + bleedingValue = -1 + } + this.state = { + currentValue: bleedingValue, + exclude: this.cycleDay.bleeding ? this.cycleDay.bleeding.exclude : false + } + } + + render() { + const bleedingRadioProps = [ + { label: labels[0], value: 0 }, + { label: labels[1], value: 1 }, + { label: labels[2], value: 2 }, + { label: labels[3], value: 3 }, + ] + return ( + <View style={styles.symptomEditView}> + <Text style={styles.symptomDayView}>Bleeding</Text> + <View style={styles.radioButtonRow}> + <RadioForm + radio_props={bleedingRadioProps} + initial={this.state.currentValue} + formHorizontal={true} + labelHorizontal={false} + labelStyle={styles.radioButton} + onPress={(itemValue) => { + this.setState({ currentValue: itemValue }) + }} + /> + </View> + <View style={styles.symptomViewRowInline}> + <Text style={styles.symptomDayView}>Exclude</Text> + <Switch + onValueChange={(val) => { + this.setState({ exclude: val }) + }} + value={this.state.exclude} + /> + </View> + <View style={styles.actionButtonRow}> + {this.makeActionButtons( + { + symptom: 'bleeding', + cycleDay: this.cycleDay, + saveAction: () => { + saveSymptom('bleeding', this.cycleDay, { + value: this.state.currentValue, + exclude: this.state.exclude + }) + }, + saveDisabled: this.state.currentValue === -1 + } + )} + </View> + </View> + ) + } +} \ No newline at end of file diff --git a/components/cycle-day/symptoms/temperature.js b/components/cycle-day/symptoms/temperature.js new file mode 100644 index 0000000000000000000000000000000000000000..b9a3d5b1de1af5ebf9756465f40a3d0d57b0fc23 --- /dev/null +++ b/components/cycle-day/symptoms/temperature.js @@ -0,0 +1,80 @@ +import React, { Component } from 'react' +import { + View, + Text, + TextInput, + Switch +} from 'react-native' + +import { getPreviousTemperature, saveSymptom } from '../../../db' +import styles from '../../../styles' +import { LocalTime, ChronoUnit } from 'js-joda' + +export default class Temp extends Component { + constructor(props) { + super(props) + this.cycleDay = props.cycleDay + this.makeActionButtons = props.makeActionButtons + let initialValue + + if (this.cycleDay.temperature) { + initialValue = this.cycleDay.temperature.value.toString() + this.time = this.cycleDay.temperature.time + } else { + const prevTemp = getPreviousTemperature(this.cycleDay) + initialValue = prevTemp ? prevTemp.toString() : '' + } + + this.state = { + currentValue: initialValue, + exclude: this.cycleDay.temperature ? this.cycleDay.temperature.exclude : false + } + } + + render() { + const cycleDay = this.cycleDay + return ( + <View style={styles.symptomEditView}> + <View style={styles.symptomViewRowInline}> + <Text style={styles.symptomDayView}>Temperature (°C)</Text> + <TextInput + style={styles.temperatureTextInput} + placeholder="Enter" + onChangeText={(val) => { + this.setState({ currentValue: val }) + }} + keyboardType='numeric' + value={this.state.currentValue} + /> + </View> + <View style={styles.symptomViewRowInline}> + <Text style={styles.symptomDayView}>Exclude</Text> + <Switch + onValueChange={(val) => { + this.setState({ exclude: val }) + }} + value={this.state.exclude} + /> + </View> + <View style={styles.actionButtonRow}> + {this.makeActionButtons({ + symptom: 'temperature', + cycleDay: this.cycleDay, + saveAction: () => { + const dataToSave = { + value: Number(this.state.currentValue), + exclude: this.state.exclude + } + if (!cycleDay.temperature || cycleDay.temperature && !cycleDay.temperature.time) { + const now = LocalTime.now().truncatedTo(ChronoUnit.MINUTES).toString() + dataToSave.time = now + } + saveSymptom('temperature', cycleDay, dataToSave) + }, + saveDisabled: this.state.currentValue === '' + })} + </View> + </View> + ) + } +} diff --git a/components/home.js b/components/home.js index 60327e39712c80d7ac8f3999cd3def152538b850..0b005929168e47b34bd11b85b0ca0fc64903accb 100644 --- a/components/home.js +++ b/components/home.js @@ -5,7 +5,7 @@ import { Text } from 'react-native' import { LocalDate } from 'js-joda' -import styles from '../styles/index' +import styles from '../styles' import cycleDayModule from '../lib/get-cycle-day-number' import { getOrCreateCycleDay, bleedingDaysSortedByDate, deleteAll } from '../db' @@ -46,32 +46,28 @@ export default class Home extends Component { render() { const navigate = this.props.navigation.navigate return ( - <View style={ styles.homeContainerView }> - <View style={{flex: 2}}> - <View> - <Text style={styles.welcome}>{this.state.welcomeText}</Text> - </View> - </View> - <View style={ styles.homeButtonsView}> - <View> + <View> + <Text style={styles.welcome}>{this.state.welcomeText}</Text> + <View style={styles.homeButtons}> + <View style={styles.homeButton}> <Button onPress={() => this.passTodayToDayView()} title="Edit symptoms for today"> </Button> </View> - <View> + <View style={styles.homeButton}> <Button onPress={() => navigate('calendar')} title="Go to calendar"> </Button> </View> - <View> + <View style={styles.homeButton}> <Button onPress={() => navigate('chart')} title="Go to chart"> </Button> </View> - <View> + <View style={styles.homeButton}> <Button onPress={() => deleteAll()} title="delete everything"> diff --git a/components/temperature.js b/components/temperature.js deleted file mode 100644 index c6fccfcd8993a399ddf9db1fb61c8b99c8d01b52..0000000000000000000000000000000000000000 --- a/components/temperature.js +++ /dev/null @@ -1,102 +0,0 @@ -import React, { Component } from 'react' -import { - View, - Text, - Button, - TextInput, - Switch -} from 'react-native' - -import { saveTemperature, getPreviousTemperature } from '../db' -import styles from '../styles/index' - -export default class Temp extends Component { - constructor(props) { - super(props) - this.cycleDay = props.cycleDay - this.showView = props.showView - let initialValue - - if(this.cycleDay.temperature) { - initialValue = this.cycleDay.temperature.value.toString() - } else { - const prevTemp = getPreviousTemperature(this.cycleDay) - initialValue = prevTemp ? prevTemp.toString() : '' - } - - this.state = { - currentValue: initialValue, - exclude: this.cycleDay.temperature ? this.cycleDay.temperature.exclude : false - } - } - - render() { - const cycleDay = this.cycleDay - return ( - <View style={ styles.symptomEditView }> - <View style={ styles.symptomEditSplitSymptomsAndLastRowButtons }> - <View style={ styles.itemsInRowView }> - <View style={{flex: 3, margin: 5}}> - <Text style={styles.symptomDayView}>Temperature (°C)</Text> - </View> - <View style={{flex: 1, margin: 5}}> - <TextInput - placeholder="Enter" - onChangeText={(val) => { - this.setState({currentValue: val}) - }} - keyboardType='numeric' - value = {this.state.currentValue} - /> - </View> - </View> - <View style={ styles.itemsInRowSeparatedView }> - <View style={{flex: 1, margin: 5}}> - <Text style={styles.symptomDayView}>Exclude</Text> - </View> - <View style={{flex: 1, margin: 5}}> - <Switch - onValueChange = {(val) => { - this.setState({ exclude: val }) - }} - value = { this.state.exclude } - /> - </View> - </View> - </View> - <View style={ styles.itemsInRowSeparatedView }> - <View style={ styles.singleButtonView }> - <Button - onPress={() => { - this.showView('dayView') - }} - title="Cancel"> - </Button> - </View> - <View style={ styles.singleButtonView }> - <Button - onPress={() => { - saveTemperature(cycleDay) - this.showView('dayView') - }} - title="Delete"> - </Button> - </View> - <View style={ styles.singleButtonView }> - <Button - onPress={() => { - saveTemperature(cycleDay, { - value: Number(this.state.currentValue), - exclude: this.state.exclude - }) - this.showView('dayView') - }} - disabled={ this.state.currentValue === '' } - title="Save"> - </Button> - </View> - </View> - </View> - ) - } -} diff --git a/db.js b/db.js index 3fdd40159eecfb2b7e5aff7136588cdd65215c55..00e1d946d1ca1609cba97d29c75fe834870d18e6 100644 --- a/db.js +++ b/db.js @@ -47,20 +47,14 @@ const db = new Realm({ const bleedingDaysSortedByDate = db.objects('CycleDay').filtered('bleeding != null').sorted('date', true) const temperatureDaysSortedByDate = db.objects('CycleDay').filtered('temperature != null').sorted('date', true) -function saveTemperature(cycleDay, temperature) { +function saveSymptom(symptom, cycleDay, val) { db.write(() => { - cycleDay.temperature = temperature + cycleDay[symptom] = val }) } const cycleDaysSortedByDate = db.objects('CycleDay').sorted('date', true) -function saveBleeding(cycleDay, bleeding) { - db.write(() => { - cycleDay.bleeding = bleeding - }) -} - function getOrCreateCycleDay(localDate) { let result = db.objectForPrimaryKey('CycleDay', localDate) if (!result) { @@ -94,8 +88,7 @@ function getPreviousTemperature(cycleDay) { } export { - saveTemperature, - saveBleeding, + saveSymptom, getOrCreateCycleDay, bleedingDaysSortedByDate, temperatureDaysSortedByDate, diff --git a/styles/index.js b/styles/index.js index 5eb9cc18d02c1e9eee813bb20db5a791981b3f34..52fc65d4a18bbcb3a3584afa4ca6069365df00ec 100644 --- a/styles/index.js +++ b/styles/index.js @@ -14,91 +14,73 @@ export default StyleSheet.create({ dateHeader: { fontSize: 20, fontWeight: 'bold', - margin: 30, + margin: 15, color: 'white', textAlign: 'center', textAlignVertical: 'center' }, cycleDayNumber: { fontSize: 18, - margin: 20, + margin: 15, textAlign: 'center', textAlignVertical: 'center' }, symptomDayView: { fontSize: 20, - margin: 30, - textAlign: 'left', textAlignVertical: 'center' }, radioButton: { fontSize: 18, - margin: 5, + margin: 8, textAlign: 'center', textAlignVertical: 'center' }, - singleButtonView: { - flex: 1, - margin: 5 - }, - itemsInRowView: { - flex: 1, - flexDirection: 'row', - justifyContent: 'flex-start', - alignItems: 'center' - }, - itemsInRowSeparatedView: { - flex: 1, - flexDirection: 'row', - justifyContent: 'space-evenly', - alignItems: 'center' - }, symptomEditView: { - flex: 1, - flexDirection: 'column', justifyContent: 'space-between', - alignItems: 'flex-start' - }, - symptomEditSplitSymptomsAndLastRowButtons: { - flex: 4, - flexDirection: 'column', - justifyContent: 'flex-start', - alignItems: 'flex-start' + marginHorizontal: 15 }, - symptomEditListedSymptomView: { - flex: 1, - flexDirection: 'column', - justifyContent: 'flex-start', - alignItems: 'flex-start' + symptomEditRow: { + justifyContent: 'space-between', + marginBottom: 10, }, - cycleDayOuterView: { - flex: 1, - flexDirection: 'column', - justifyContent: 'space-around' + symptomViewRowInline: { + flexDirection: 'row', + justifyContent: 'space-between', + marginBottom: 10, + alignItems: 'center', + height: 50 }, cycleDayDateView: { - flex: 2, justifyContent: 'center', backgroundColor: 'steelblue' }, cycleDayNumberView: { - flex: 1, justifyContent: 'center', - backgroundColor: 'skyblue' - }, - cycleDaySymptomsView: { - flex: 8, - justifyContent: 'center' - }, - homeContainerView: { - flex: 0.5, - flexDirection: 'column', - justifyContent: 'space-around' - }, - homeButtonsView: { - flex: 3, - flexDirection: 'column', - justifyContent: 'space-around', - margin: 5 + backgroundColor: 'skyblue', + marginBottom: 15 + }, + homeButtons: { + marginHorizontal: 15 + }, + homeButton: { + marginBottom: 15 + }, + temperatureTextInput: { + width: 80, + textAlign: 'center', + fontSize: 20 + }, + actionButtonRow: { + flexDirection: 'row', + justifyContent: 'space-evenly', + marginTop: 50 + }, + symptomEditButton: { + width: 130 + }, + radioButtonRow: { + marginTop: 15, + marginLeft: 'auto', + marginRight: 'auto' } }) \ No newline at end of file