Merge branch 'mood-category' into 'master'
Add mood component, add mood as tracking category to db schemas, add mood... See merge request bloodyhealth/drip!156
This commit is contained in:
@@ -23,6 +23,7 @@ const symptomIcons = {
|
||||
desire: <DripIcon size={16} name='drip-icon-desire' color={styles.iconShades.desire[2]}/>,
|
||||
sex: <DripIcon size={16} name='drip-icon-sex' color={styles.iconShades.sex[2]}/>,
|
||||
pain: <DripIcon size={16} name='drip-icon-pain' color={styles.iconShades.pain[0]}/>,
|
||||
mood: <DripIcon size={16} name='drip-icon-mood' color={styles.iconShades.mood[0]}/>,
|
||||
note: <DripIcon size={16} name='drip-icon-note' color={styles.iconShades.note[0]}/>
|
||||
}
|
||||
|
||||
@@ -62,6 +63,7 @@ export default class CycleChart extends Component {
|
||||
'sex',
|
||||
'desire',
|
||||
'pain',
|
||||
'mood',
|
||||
'note'
|
||||
].filter((symptomName) => {
|
||||
return this.cycleDaysSortedByDate.some(cycleDay => {
|
||||
|
||||
@@ -44,6 +44,10 @@ export default class DayColumn extends Component {
|
||||
// is any pain documented?
|
||||
acc.pain = cycleDay.pain &&
|
||||
Object.values(cycleDay.pain).some(x => x === true)
|
||||
} else if (symptom === 'mood') {
|
||||
// is mood documented?
|
||||
acc.mood = cycleDay.mood &&
|
||||
Object.values(cycleDay.mood).some(x => x === true)
|
||||
}
|
||||
acc[`${symptom}Exclude`] = cycleDay[symptom] && cycleDay[symptom].exclude
|
||||
return acc
|
||||
@@ -214,6 +218,18 @@ export default class DayColumn extends Component {
|
||||
/>
|
||||
</SymptomIconView>
|
||||
),
|
||||
mood: (
|
||||
<SymptomIconView
|
||||
value={this.data.mood}
|
||||
symptomHeight={symptomHeight}
|
||||
key='mood'
|
||||
>
|
||||
<View
|
||||
{...styles.symptomIcon}
|
||||
backgroundColor={styles.iconShades.mood}
|
||||
/>
|
||||
</SymptomIconView>
|
||||
),
|
||||
note: (
|
||||
<SymptomIconView
|
||||
value={this.data.note}
|
||||
|
||||
@@ -77,7 +77,8 @@ const styles = {
|
||||
'#9e346c',
|
||||
],
|
||||
'pain': ['#bccd67'],
|
||||
'note': ['#6CA299']
|
||||
'mood': ['#bc6642'],
|
||||
'note': ['#6ca299']
|
||||
},
|
||||
yAxis: {
|
||||
width: 27,
|
||||
|
||||
@@ -24,6 +24,7 @@ const intensityLabels = labels.intensity
|
||||
const sexLabels = labels.sex.categories
|
||||
const contraceptiveLabels = labels.contraceptives.categories
|
||||
const painLabels = labels.pain.categories
|
||||
const moodLabels = labels.mood.categories
|
||||
|
||||
export default class CycleDayOverView extends Component {
|
||||
constructor(props) {
|
||||
@@ -143,6 +144,25 @@ export default class CycleDayOverView extends Component {
|
||||
painLabel = painLabel.join(', ')
|
||||
return painLabel
|
||||
}
|
||||
},
|
||||
mood: mood => {
|
||||
let moodLabel = []
|
||||
if (mood && Object.values(mood).some(val => val)){
|
||||
Object.keys(mood).forEach(key => {
|
||||
if(mood[key] && key !== 'other' && key !== 'note') {
|
||||
moodLabel.push(moodLabels[key])
|
||||
}
|
||||
if(key === 'other' && mood.other) {
|
||||
let label = moodLabels[key]
|
||||
if(mood.note) {
|
||||
label = `${label} (${mood.note})`
|
||||
}
|
||||
moodLabel.push(label)
|
||||
}
|
||||
})
|
||||
moodLabel = moodLabel.join(', ')
|
||||
return moodLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,6 +246,14 @@ export default class CycleDayOverView extends Component {
|
||||
iconName='drip-icon-pain'
|
||||
>
|
||||
</SymptomBox>
|
||||
<SymptomBox
|
||||
title='Mood'
|
||||
onPress={() => this.navigate('MoodEditView')}
|
||||
data={this.getLabel('mood')}
|
||||
disabled={dateInFuture}
|
||||
iconName='drip-icon-mood'
|
||||
>
|
||||
</SymptomBox>
|
||||
<SymptomBox
|
||||
title='Note'
|
||||
onPress={() => this.navigate('NoteEditView')}
|
||||
@@ -236,9 +264,9 @@ export default class CycleDayOverView extends Component {
|
||||
{/* this is just to make the last row adhere to the grid
|
||||
(and) because there are no pseudo properties in RN */}
|
||||
<FillerBoxes />
|
||||
</View >
|
||||
</ScrollView >
|
||||
</View >
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -248,9 +276,9 @@ export default class CycleDayOverView extends Component {
|
||||
|
||||
class SymptomBox extends Component {
|
||||
render() {
|
||||
const d = this.props.data
|
||||
const boxActive = d ? styles.symptomBoxActive : {}
|
||||
const textActive = d ? styles.symptomTextActive : {}
|
||||
const hasData = this.props.data
|
||||
const boxActive = hasData ? styles.symptomBoxActive : {}
|
||||
const textActive = hasData ? styles.symptomTextActive : {}
|
||||
const disabledStyle = this.props.disabled ? styles.symptomInFuture : {}
|
||||
|
||||
return (
|
||||
@@ -259,7 +287,7 @@ class SymptomBox extends Component {
|
||||
disabled={this.props.disabled}
|
||||
>
|
||||
<View style={[styles.symptomBox, boxActive, disabledStyle]}>
|
||||
<DripIcon name={this.props.iconName} size={50} color={d ? 'white' : 'black'}/>
|
||||
<DripIcon name={this.props.iconName} size={50} color={hasData ? 'white' : 'black'}/>
|
||||
<AppText style={[textActive, disabledStyle]}>
|
||||
{this.props.title.toLowerCase()}
|
||||
</AppText>
|
||||
|
||||
@@ -6,6 +6,7 @@ import NoteEditView from './note'
|
||||
import DesireEditView from './desire'
|
||||
import SexEditView from './sex'
|
||||
import PainEditView from './pain'
|
||||
import MoodEditView from './mood'
|
||||
|
||||
export default {
|
||||
BleedingEditView,
|
||||
@@ -15,5 +16,6 @@ export default {
|
||||
NoteEditView,
|
||||
DesireEditView,
|
||||
SexEditView,
|
||||
PainEditView
|
||||
PainEditView,
|
||||
MoodEditView
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import React, { Component } from 'react'
|
||||
import {
|
||||
ScrollView,
|
||||
TextInput,
|
||||
View
|
||||
} from 'react-native'
|
||||
import { saveSymptom } from '../../../db'
|
||||
import { mood as labels } from '../../../i18n/en/cycle-day'
|
||||
import ActionButtonFooter from './action-button-footer'
|
||||
import SelectBoxGroup from '../select-box-group'
|
||||
import SymptomSection from './symptom-section'
|
||||
import styles from '../../../styles'
|
||||
|
||||
export default class Mood extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
const cycleDay = props.cycleDay
|
||||
if (cycleDay && cycleDay.mood) {
|
||||
this.state = Object.assign({}, cycleDay.mood)
|
||||
} else {
|
||||
this.state = {}
|
||||
}
|
||||
if (this.state.note) {
|
||||
this.state.other = true
|
||||
}
|
||||
}
|
||||
|
||||
toggleState = (key) => {
|
||||
const curr = this.state[key]
|
||||
this.setState({[key]: !curr})
|
||||
if (key === 'other' && !curr) {
|
||||
this.setState({focusTextArea: true})
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={{ flex: 1 }}>
|
||||
<ScrollView style={styles.page}>
|
||||
<SymptomSection
|
||||
explainer={labels.explainer}
|
||||
>
|
||||
<SelectBoxGroup
|
||||
labels={labels.categories}
|
||||
onSelect={this.toggleState}
|
||||
optionsState={this.state}
|
||||
/>
|
||||
{ this.state.other &&
|
||||
<TextInput
|
||||
autoFocus={this.state.focusTextArea}
|
||||
multiline={true}
|
||||
placeholder="Enter"
|
||||
value={this.state.note}
|
||||
onChangeText={(val) => {
|
||||
this.setState({note: val})
|
||||
}}
|
||||
/>
|
||||
}
|
||||
</SymptomSection>
|
||||
</ScrollView>
|
||||
<ActionButtonFooter
|
||||
symptom='mood'
|
||||
date={this.props.date}
|
||||
currentSymptomValue={this.state}
|
||||
saveAction={() => {
|
||||
const copyOfState = Object.assign({}, this.state)
|
||||
if (!copyOfState.other) {
|
||||
copyOfState.note = null
|
||||
}
|
||||
saveSymptom('mood', this.props.date, copyOfState)
|
||||
}}
|
||||
saveDisabled={Object.values(this.state).every(value => !value)}
|
||||
navigate={this.props.navigate}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
import cycleModule from '../../lib/cycle'
|
||||
|
||||
const TemperatureSchema = {
|
||||
name: 'Temperature',
|
||||
properties: {
|
||||
value: 'double',
|
||||
exclude: 'bool',
|
||||
time: {
|
||||
type: 'string',
|
||||
optional: true
|
||||
},
|
||||
note: {
|
||||
type: 'string',
|
||||
optional: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const BleedingSchema = {
|
||||
name: 'Bleeding',
|
||||
properties: {
|
||||
value: 'int',
|
||||
exclude: 'bool'
|
||||
}
|
||||
}
|
||||
|
||||
const MucusSchema = {
|
||||
name: 'Mucus',
|
||||
properties: {
|
||||
feeling: 'int',
|
||||
texture: 'int',
|
||||
value: 'int',
|
||||
exclude: 'bool'
|
||||
}
|
||||
}
|
||||
|
||||
const CervixSchema = {
|
||||
name: 'Cervix',
|
||||
properties: {
|
||||
opening: 'int',
|
||||
firmness: 'int',
|
||||
position: {type: 'int', optional: true },
|
||||
exclude: 'bool'
|
||||
}
|
||||
}
|
||||
|
||||
const NoteSchema = {
|
||||
name: 'Note',
|
||||
properties: {
|
||||
value: 'string'
|
||||
}
|
||||
}
|
||||
|
||||
const DesireSchema = {
|
||||
name: 'Desire',
|
||||
properties: {
|
||||
value: 'int'
|
||||
}
|
||||
}
|
||||
|
||||
const SexSchema = {
|
||||
name: 'Sex',
|
||||
properties: {
|
||||
solo: { type: 'bool', optional: true },
|
||||
partner: { type: 'bool', optional: true },
|
||||
condom: { type: 'bool', optional: true },
|
||||
pill: { type: 'bool', optional: true },
|
||||
iud: { type: 'bool', optional: true },
|
||||
patch: { type: 'bool', optional: true },
|
||||
ring: { type: 'bool', optional: true },
|
||||
implant: { type: 'bool', optional: true },
|
||||
diaphragm: { type: 'bool', optional: true },
|
||||
none: { type: 'bool', optional: true },
|
||||
other: { type: 'bool', optional: true },
|
||||
note: { type: 'string', optional: true }
|
||||
}
|
||||
}
|
||||
|
||||
const PainSchema = {
|
||||
name: 'Pain',
|
||||
properties: {
|
||||
cramps: { type: 'bool', optional: true },
|
||||
ovulationPain: { type: 'bool', optional: true },
|
||||
headache: { type: 'bool', optional: true },
|
||||
backache: { type: 'bool', optional: true },
|
||||
nausea: { type: 'bool', optional: true },
|
||||
tenderBreasts: { type: 'bool', optional: true },
|
||||
migraine: { type: 'bool', optional: true },
|
||||
other: { type: 'bool', optional: true },
|
||||
note: { type: 'string', optional: true }
|
||||
}
|
||||
}
|
||||
|
||||
const MoodSchema = {
|
||||
name: 'Mood',
|
||||
properties: {
|
||||
happy: { type: 'bool', optional: true },
|
||||
sad: { type: 'bool', optional: true },
|
||||
stressed: { type: 'bool', optional: true },
|
||||
balanced: { type: 'bool', optional: true },
|
||||
fine: { type: 'bool', optional: true },
|
||||
anxious: { type: 'bool', optional: true },
|
||||
energetic: { type: 'bool', optional: true },
|
||||
fatigue: { type: 'bool', optional: true },
|
||||
angry: { type: 'bool', optional: true },
|
||||
other: { type: 'bool', optional: true },
|
||||
note: { type: 'string', optional: true }
|
||||
}
|
||||
}
|
||||
|
||||
const CycleDaySchema = {
|
||||
name: 'CycleDay',
|
||||
primaryKey: 'date',
|
||||
properties: {
|
||||
date: 'string',
|
||||
temperature: {
|
||||
type: 'Temperature',
|
||||
optional: true
|
||||
},
|
||||
isCycleStart: 'bool',
|
||||
bleeding: {
|
||||
type: 'Bleeding',
|
||||
optional: true
|
||||
},
|
||||
mucus: {
|
||||
type: 'Mucus',
|
||||
optional: true
|
||||
},
|
||||
cervix: {
|
||||
type: 'Cervix',
|
||||
optional: true
|
||||
},
|
||||
note: {
|
||||
type: 'Note',
|
||||
optional: true
|
||||
},
|
||||
desire: {
|
||||
type: 'Desire',
|
||||
optional: true
|
||||
},
|
||||
sex: {
|
||||
type: 'Sex',
|
||||
optional: true
|
||||
},
|
||||
pain: {
|
||||
type: 'Pain',
|
||||
optional: true
|
||||
},
|
||||
mood: {
|
||||
type: 'Mood',
|
||||
optional: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
schema: [
|
||||
CycleDaySchema,
|
||||
TemperatureSchema,
|
||||
BleedingSchema,
|
||||
MucusSchema,
|
||||
CervixSchema,
|
||||
NoteSchema,
|
||||
DesireSchema,
|
||||
SexSchema,
|
||||
PainSchema,
|
||||
MoodSchema
|
||||
],
|
||||
schemaVersion: 3,
|
||||
migration: (oldRealm, newRealm) => {
|
||||
if (oldRealm.schemaVersion >= 3) return
|
||||
const oldBleedingDays = oldRealm.objects('CycleDay')
|
||||
.filtered('bleeding != null')
|
||||
.sorted('date', true)
|
||||
|
||||
const { isMensesStart } = cycleModule({
|
||||
bleedingDaysSortedByDate: oldBleedingDays
|
||||
})
|
||||
|
||||
const newBleedingDays = newRealm.objects('CycleDay')
|
||||
.filtered('bleeding != null')
|
||||
.sorted('date', true)
|
||||
|
||||
oldBleedingDays.forEach((day, i) => {
|
||||
newBleedingDays[i].isCycleStart = isMensesStart(day)
|
||||
})
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
import schema0 from './0.js'
|
||||
import schema1 from './1.js'
|
||||
import schema2 from './2.js'
|
||||
import schema3 from './3.js'
|
||||
|
||||
export default [schema0, schema1, schema2]
|
||||
export default [schema0, schema1, schema2, schema3]
|
||||
@@ -86,6 +86,22 @@ export const pain = {
|
||||
explainer: 'How did your body feel today?'
|
||||
}
|
||||
|
||||
export const mood = {
|
||||
categories: {
|
||||
happy: 'Happy',
|
||||
sad: 'Sad',
|
||||
stressed: 'Stressed',
|
||||
balanced: 'Balanced',
|
||||
fine: 'Fine',
|
||||
anxious: 'Anxious',
|
||||
energetic: 'Energetic',
|
||||
fatigue: 'Fatigue',
|
||||
angry: 'Angry',
|
||||
other: 'Other'
|
||||
},
|
||||
explainer: 'How did you feel today?'
|
||||
}
|
||||
|
||||
export const temperature = {
|
||||
outOfRangeWarning: 'This temperature value is out of the current range for the temperature chart. You can change the range in the settings.',
|
||||
outOfAbsoluteRangeWarning: 'This temperature value is too high or low to be shown on the temperature chart.',
|
||||
|
||||
@@ -40,6 +40,7 @@ export const headerTitles = {
|
||||
DesireEditView: 'Desire',
|
||||
SexEditView: 'Sex',
|
||||
PainEditView: 'Pain',
|
||||
MoodEditView: 'Mood',
|
||||
InfoSymptom: 'Info'
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user