Compare commits

...

8 Commits

Author SHA1 Message Date
tina a4e0fa64e9 calculates cycle days for headaches 2024-10-15 17:52:38 +02:00
tina fd6f39fbc4 first exploration of place of feature and how to access data 2024-10-15 14:47:42 +02:00
wunderfisch d492a27797 Merge branch '723-feature-link-faq-in-app' into 'main'
adds a button leading to faq on website to about section in the app

Closes #723

See merge request bloodyhealth/drip!684
2024-10-03 16:35:28 +00:00
wunderfisch 22a451d4e6 Merge branch 'chore/add-condriputers' into 'main'
addding condriputers

See merge request bloodyhealth/drip!682
2024-10-03 16:35:10 +00:00
Lynn ae5f31015b Update README.md for M1 installations, fixed typo 2024-09-18 10:02:11 +00:00
Lynn c7104f7758 Update README.md for M1 installations 2024-09-18 10:00:33 +00:00
wunderfisch 86bdb8a1f8 adds a button leading to faq on website to about section in the app 2024-09-09 21:00:21 +02:00
wunderfisch 4212906917 addding condriputers 2024-02-29 17:54:25 +01:00
9 changed files with 219 additions and 4 deletions
+31 -1
View File
@@ -34,13 +34,31 @@ or clone it with HTTPS
git clone https://gitlab.com/bloodyhealth/drip.git
### 2. Node & yarn version
### 2. Node version
Make sure you are running Node 14 and classic yarn (v.1). It's easiest to switch Node versions using `nvm`, here's how to install NVM: https://github.com/nvm-sh/nvm#installing-and-updating. After installing nvm close the terminal and open it again to be able to use nvm.
Once you have nvm running you can install node 14:
nvm install v14.19.3
#### On Apple Silicon M1
NodeJS 14 does not compile on the M1 architecture, so it has to be installed through Rosetta: https://devzilla.io/using-nodejs-14-with-mac-silicon-m1 .
To activate Rosetta and switch to intel emulation run:
arch -x86_64 zsh
Run
arch
again to verify that it returns "i386".
Now install node 14:
nvm install v14.19.3
### 3. Yarn version
use npm to install yarn:
npm install --global yarn
@@ -127,6 +145,18 @@ iii. If you are building the app with XCode make sure you are running this as we
### Troubleshooting
#### [MacOS M1] Flipper problems
If a bug in the currently used Flipper version prevents building the project, comment out the respective line in the podfile, like so:
#use_flipper!()
Run
pod install
from the ios directory again to reload the dependencies.
#### [MacOS] Java problems
Make sure that you have Java 1.8 by running `java -version`.
+4
View File
@@ -18,6 +18,10 @@ const AboutSection = () => {
<AppPage title={t('title')}>
<Segment>
<AppText>{t('intro.text')}</AppText>
<Button isCTA isSmall onPress={() => Linking.openURL(links.faq.url)}>
{t('intro.faq')}
</Button>
<AppText>{t('intro.contact')}</AppText>
<ButtonRow>
{[links.email, links.gitlab, links.website].map((link) => (
<Button
+89
View File
@@ -0,0 +1,89 @@
import React from 'react'
import { FlatList, StyleSheet, View } from 'react-native'
import PropTypes from 'prop-types'
// import { useTranslation } from 'react-i18next'
import AppModal from '../common/app-modal'
import AppText from '../common/app-text'
import symOccModule from '../../lib/sympto-occurance'
import { Spacing, Typography, Colors } from '../../styles'
// const { t } = useTranslation(null, { keyPrefix: 'stats' })
const SymptomOccurance = ({ onClose }) => {
const cycleDays = symOccModule().getCycleStartsOfLastYear()
if (!cycleDays || cycleDays.length === 0) return false
console.log('cycle starts:', cycleDays)
const headacheDays = symOccModule().getPainDaysOfLastYear()
console.log('pain', headacheDays)
const cycleDaysOfPain = symOccModule().getCycleDayForPainDays(
cycleDays,
headacheDays
)
console.log('cycle days of pain', cycleDaysOfPain)
return (
<AppModal onClose={onClose}>
<View>
<FlatList
ListHeaderComponent={FlatListHeader}
contentContainerStyle={styles.container}
/>
</View>
</AppModal>
)
}
SymptomOccurance.propTypes = {
onClose: PropTypes.func,
}
const FlatListHeader = () => (
<View style={styles.row}>
<View style={styles.accentCell}>
<AppText style={styles.header}>
{'When did you experience headaches in the last year?'}
</AppText>
</View>
</View>
)
const styles = StyleSheet.create({
divider: {
height: 1,
width: '100%',
backgroundColor: Colors.grey,
},
header: {
...Typography.accentOrange,
paddingVertical: Spacing.small,
},
headerDivider: {
borderBottomColor: Colors.purple,
borderBottomWidth: 2,
},
row: {
flexDirection: 'row',
justifyContent: 'space-between',
paddingVertical: Spacing.tiny,
backgroundColor: 'white',
},
cell: {
flex: 2,
justifyContent: 'center',
},
accentCell: {
flex: 3,
justifyContent: 'center',
},
container: {
minHeight: '40%',
minWidth: '95%',
paddingHorizontal: Spacing.base,
},
})
export default SymptomOccurance
+11
View File
@@ -8,6 +8,7 @@ import Button from '../common/button'
import Footnote from '../common/Footnote'
import StatsOverview from './StatsOverview'
import PeriodDetailsModal from './PeriodDetailsModal'
import SymptomOccurance from './SymptomOccurance'
import cycleModule from '../../lib/cycle'
import { getCycleLengthStats as getCycleInfo } from '../../lib/cycle-length'
@@ -19,6 +20,8 @@ const image = require('../../assets/cycle-icon.png')
const Stats = () => {
const [isStatsVisible, setIsStatsVisible] = useState(false)
const [isSymptomOccuranceVisible, setIsSymptomOccuranceVisible] =
useState(false)
const { t } = useTranslation(null, { keyPrefix: 'stats' })
@@ -83,6 +86,14 @@ const Stats = () => {
{isStatsVisible && (
<PeriodDetailsModal onClose={() => setIsStatsVisible(false)} />
)}
<Button isCTA onPress={() => setIsSymptomOccuranceVisible(true)}>
{t('showSymptomOccurance')}
</Button>
{isSymptomOccuranceVisible && (
<SymptomOccurance
onClose={() => setIsSymptomOccuranceVisible(false)}
/>
)}
<Footnote>{t('footnote')}</Footnote>
</>
)}
+3
View File
@@ -73,6 +73,9 @@ export function getTemperatureDaysSortedByDate() {
.filtered('temperature != null')
.sorted('date', true)
}
export function getPainDaysSortedByDate() {
return db.objects('CycleDay').filtered('pain != null').sorted('date', true)
}
export function getCycleDaysSortedByDate() {
const cycleDays = db.objects('CycleDay').sorted('date', true)
+5 -2
View File
@@ -45,7 +45,9 @@
"text": "The drips are developing this app on a volunteer basis. We are always grateful for support. This could mean condriputing to the code, giving feedback, suggesting improvements or features, testing or donating. It helps and motivates us maintaining this app and developing new features. Thank you for your support!"
},
"intro": {
"text": "Please note that your data is stored locally on your phone and not on a server. This means your data cannot be read by anyone else unless they have access to your phone. We want to ensure that you stay in control of your own data. If you are planning to switch or reset your phone, please remember to export your data before doing so. You can reinstall the app afterwards and import your data.\n\nIf you encounter any technical issues, don't hesitate to contact us via email. You can also contribute to the code base on Gitlab and visit our website."
"text": "Please note that your data is stored locally on your phone and not on a server. This means your data cannot be read by anyone else unless they have access to your phone. We want to ensure that you stay in control of your own data. If you are planning to switch or reset your phone, please remember to export your data before doing so. You can reinstall the app afterwards and import your data.\n\nIf you encounter any issues, please take a look at our Frequently Asked Questions page.",
"faq": "FAQ",
"contact": "\nIf your issue is not listed, don't hesitate to contact us via email. You can also contribute to the code base on Gitlab and visit our website."
},
"philosophy": {
"title": "Remember to think for yourself",
@@ -154,7 +156,8 @@
"cycleLength": "Cycle length",
"bleedingDays": "Bleeding"
},
"footnote": "Based on the standard deviation of all your tracked periods drip. calculates a range for the starting day of the upcoming 3 periods. The range will be 3 days if your standard deviation is smaller than 1.5 and 5 days if the value is bigger.\n\nThe standard deviation tells you how much the length of your periods vary, 0 means all your periods are exactly the same length and the bigger the value the more the period length varies."
"footnote": "Based on the standard deviation of all your tracked periods drip. calculates a range for the starting day of the upcoming 3 periods. The range will be 3 days if your standard deviation is smaller than 1.5 and 5 days if the value is bigger.\n\nThe standard deviation tells you how much the length of your periods vary, 0 means all your periods are exactly the same length and the bigger the value the more the period length varies.",
"showSymptomOccurance": "Show details on headaches"
},
"plurals": {
"day": "{{count}} day",
+4
View File
@@ -39,4 +39,8 @@ export default {
url: 'https://www.flaticon.com',
text: 'Flaticon',
},
faq: {
url: 'https://dripapp.org/faq',
text: 'FAQ',
},
}
+70
View File
@@ -0,0 +1,70 @@
import * as joda from '@js-joda/core'
const LocalDate = joda.LocalDate
const DAYS = joda.ChronoUnit.DAYS
export default function config(opts) {
let cycleStartsSortedByDate
let painSortedByDate
if (!opts) {
// we only want to require (and run) the db module
// when not running the tests
cycleStartsSortedByDate = require('../db').getCycleStartsSortedByDate()
painSortedByDate = require('../db').getPainDaysSortedByDate()
// maxCycleLength = 45
} else {
cycleStartsSortedByDate = opts.cycleStartsSortedByDate || []
painSortedByDate = opts.painSortedByDate || []
// maxCycleLength = opts.maxCycleLength || 99
}
function getCycleStartsOfLastYear() {
const today = LocalDate.parse(new Date().toISOString().slice(0, 10))
const firstRelevantDay = today.minusYears(1)
const relevantCycles = cycleStartsSortedByDate.filter(({ date }) =>
LocalDate.parse(date).isAfter(firstRelevantDay)
)
return relevantCycles.map(({ date }) => date)
}
function getPainDaysOfLastYear() {
const today = LocalDate.parse(new Date().toISOString().slice(0, 10))
const firstRelevantDay = today.minusYears(1)
const relevantPainDays = painSortedByDate.filter(
({ date, pain }) =>
LocalDate.parse(date).isAfter(firstRelevantDay) && pain.headache
)
return relevantPainDays.map(({ date }) => date)
}
function getCycleDayForPainDays(cycleStarts, painDays) {
let i = 0
const cycleStartsAsc = cycleStarts.sort().reverse()
const painDaysAsc = painDays.sort().reverse()
const painCycleDays = painDaysAsc.map((pdate) => {
if (LocalDate.parse(pdate).isBefore(LocalDate.parse(cycleStartsAsc[i]))) {
// increase index i until cycleStart of this painDay is found
for (let j = i + 1; j < cycleStartsAsc.length; j++) {
i = j
if (
!LocalDate.parse(cycleStartsAsc[i]).isAfter(LocalDate.parse(pdate))
) {
// not(C > P) === C ≤ P
break
}
}
}
return LocalDate.parse(cycleStartsAsc[i]).until(
LocalDate.parse(pdate),
DAYS
)
})
return painCycleDays
}
return {
getCycleStartsOfLastYear,
getPainDaysOfLastYear,
getCycleDayForPainDays,
}
}
+2 -1
View File
@@ -7,7 +7,8 @@
"Tina Baumann",
"Sofiya Tepikin",
"Mariya Zadnepryanets",
"Lisa Hillebrand"
"Lisa Hillebrand",
"Martha Dörfler"
],
"scripts": {
"start": "react-native start",