From a64bfbcd5054ccf8269979eb3d791e10bf670130 Mon Sep 17 00:00:00 2001 From: Bl00dyMarie Date: Mon, 13 Aug 2018 16:47:19 +0200 Subject: [PATCH 1/2] Implement Sex \o/: * Offers tracking sex activities and contraceptives as much as you want * "Other" contraceptive allows to specify with text input --- components/cycle-day/cycle-day-overview.js | 35 ++++- components/cycle-day/labels/labels.js | 13 ++ components/cycle-day/symptoms/index.js | 6 +- components/cycle-day/symptoms/sex.js | 153 +++++++++++++++++++++ db/index.js | 23 +++- 5 files changed, 223 insertions(+), 7 deletions(-) create mode 100644 components/cycle-day/symptoms/sex.js diff --git a/components/cycle-day/cycle-day-overview.js b/components/cycle-day/cycle-day-overview.js index f92934b..b127b74 100644 --- a/components/cycle-day/cycle-day-overview.js +++ b/components/cycle-day/cycle-day-overview.js @@ -98,11 +98,20 @@ export default class DayView extends Component { Desire + + Sex + + + + ) } @@ -132,15 +141,22 @@ function getLabel(symptomName, symptom) { typeof mucus.texture === 'number' && typeof mucus.value === 'number' ) { - let mucusLabel = `${feelingLabels[mucus.feeling]} + ${textureLabels[mucus.texture]} ( ${computeSensiplanMucusLabels[mucus.value]} )` + let mucusLabel = + `${feelingLabels[mucus.feeling]} + + ${textureLabels[mucus.texture]} + ( ${computeSensiplanMucusLabels[mucus.value]} )` if (mucus.exclude) mucusLabel = "( " + mucusLabel + " )" return mucusLabel } }, cervix: cervix => { if (cervix.opening > -1 && cervix.firmness > -1) { - let cervixLabel = `${openingLabels[cervix.opening]} + ${firmnessLabels[cervix.firmness]}` - if (cervix.position > -1) cervixLabel += `+ ${positionLabels[cervix.position]}` + let cervixLabel = + `${openingLabels[cervix.opening]} + + ${firmnessLabels[cervix.firmness]}` + if (cervix.position > -1) { + cervixLabel += `+ ${positionLabels[cervix.position]}` + } if (cervix.exclude) cervixLabel = "( " + cervixLabel + " )" return cervixLabel } @@ -153,6 +169,17 @@ function getLabel(symptomName, symptom) { const desireLabel = `${intensityLabels[desire.value]}` return desireLabel } + }, + sex: sex => { + let sexLabel = '' + if ( sex.solo || sex.partner ) { + sexLabel += 'Activity ' + } + if (sex.condom || sex.pill || sex.iud || + sex.patch || sex.ring || sex.implant || sex.other) { + sexLabel += 'Contraceptive' + } + return sexLabel ? sexLabel : 'edit' } } diff --git a/components/cycle-day/labels/labels.js b/components/cycle-day/labels/labels.js index 68735ee..ee88428 100644 --- a/components/cycle-day/labels/labels.js +++ b/components/cycle-day/labels/labels.js @@ -6,6 +6,19 @@ export const cervixOpening = ['closed', 'medium', 'open'] export const cervixFirmness = ['hard', 'soft'] export const cervixPosition = ['low', 'medium', 'high'] export const intensity = ['low', 'medium', 'high'] +export const sexActivity = { + solo: 'Solo', + partner: 'Partner' +} +export const contraceptives = { + condom: 'Condom', + pill: 'Pill', + iud: 'IUD', + patch: 'Patch', + ring: 'Ring', + implant: 'Implant', + other: 'Other' +} export const fertilityStatus = { fertile: 'fertile', diff --git a/components/cycle-day/symptoms/index.js b/components/cycle-day/symptoms/index.js index 617dbab..c3583df 100644 --- a/components/cycle-day/symptoms/index.js +++ b/components/cycle-day/symptoms/index.js @@ -4,6 +4,7 @@ import MucusEditView from './mucus' import CervixEditView from './cervix' import NoteEditView from './note' import DesireEditView from './desire' +import SexEditView from './sex' export default { BleedingEditView, @@ -11,5 +12,6 @@ export default { MucusEditView, CervixEditView, NoteEditView, - DesireEditView -} \ No newline at end of file + DesireEditView, + SexEditView +} diff --git a/components/cycle-day/symptoms/sex.js b/components/cycle-day/symptoms/sex.js new file mode 100644 index 0000000..5a90249 --- /dev/null +++ b/components/cycle-day/symptoms/sex.js @@ -0,0 +1,153 @@ +import React, { Component } from 'react' +import { + CheckBox, + Text, + TextInput, + View +} from 'react-native' +import styles from '../../../styles' +import { saveSymptom } from '../../../db' +import { + sexActivity as activityLabels, + contraceptives as contraceptiveLabels +} from '../labels/labels' + +export default class Sex extends Component { + constructor(props) { + super(props) + this.cycleDay = props.cycleDay + this.state = {} + if (this.cycleDay.sex !== null ) { + Object.assign(this.state, this.cycleDay.sex) + // We make sure other is always true when there is a note, + // e.g. when import is messed up. + if (this.cycleDay.sex && this.cycleDay.sex.note) { + this.state.other = true + } + } + } + + render() { + + return ( + + SEX + + {activityLabels.solo} + { + this.setState({solo: val}) + }} + /> + {activityLabels.partner} + { + this.setState({partner: val}) + }} + /> + + CONTRACEPTIVES + + + {contraceptiveLabels.condom} + + { + this.setState({condom: val}) + }} + /> + + {contraceptiveLabels.pill} + + { + this.setState({pill: val}) + }} + /> + + + + {contraceptiveLabels.iud} + + { + this.setState({iud: val}) + }} + /> + + {contraceptiveLabels.patch} + + { + this.setState({patch: val}) + }} + /> + + + + {contraceptiveLabels.ring} + + { + this.setState({ring: val}) + }} + /> + + {contraceptiveLabels.implant} + + { + this.setState({implant: val}) + }} + /> + + + + {contraceptiveLabels.other} + + { + this.setState({other: val}) + }} + /> + + { this.state.other && + { + this.setState({note: val}) + }} + /> + } + + {this.props.makeActionButtons( + { + symptom: 'sex', + cycleDay: this.cycleDay, + saveAction: () => { + const copyOfState = Object.assign({}, this.state) + if (!copyOfState.other) { + copyOfState.note = null + } + saveSymptom('sex', this.cycleDay, copyOfState) + }, + saveDisabled: Object.values(this.state).every(value => !value) + } + )} + + + ) + } +} diff --git a/db/index.js b/db/index.js index d3d49e8..f974795 100644 --- a/db/index.js +++ b/db/index.js @@ -60,6 +60,22 @@ const DesireSchema = { } } +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 }, + other: { type: 'bool', optional: true }, + note: { type: 'string', optional: true } + } +} + const CycleDaySchema = { name: 'CycleDay', primaryKey: 'date', @@ -88,6 +104,10 @@ const CycleDaySchema = { desire: { type: 'Desire', optional: true + }, + sex: { + type: 'Sex', + optional: true } } } @@ -100,7 +120,8 @@ const realmConfig = { MucusSchema, CervixSchema, NoteSchema, - DesireSchema + DesireSchema, + SexSchema ], // we only want this in dev mode deleteRealmIfMigrationNeeded: true From b3ace768a856fc5e26ea52ae74c972242826dc0b Mon Sep 17 00:00:00 2001 From: Bl00dyMarie Date: Wed, 15 Aug 2018 09:41:05 +0200 Subject: [PATCH 2/2] Text input is autofocussed only when someone just checked the "Other" checkbox :) --- components/cycle-day/symptoms/sex.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/components/cycle-day/symptoms/sex.js b/components/cycle-day/symptoms/sex.js index 5a90249..d9ec336 100644 --- a/components/cycle-day/symptoms/sex.js +++ b/components/cycle-day/symptoms/sex.js @@ -116,13 +116,16 @@ export default class Sex extends Component { { - this.setState({other: val}) + this.setState({ + other: val, + focusTextArea: true + }) }} /> { this.state.other &&