diff --git a/app/src/main/kotlin/edu/stanford/bdh/engagehf/bluetooth/component/AppScreenEvents.kt b/app/src/main/kotlin/edu/stanford/bdh/engagehf/bluetooth/component/AppScreenEvents.kt
index 57a866a2e..06aabf5dd 100644
--- a/app/src/main/kotlin/edu/stanford/bdh/engagehf/bluetooth/component/AppScreenEvents.kt
+++ b/app/src/main/kotlin/edu/stanford/bdh/engagehf/bluetooth/component/AppScreenEvents.kt
@@ -33,5 +33,6 @@ class AppScreenEvents @Inject constructor(
data object AddBloodPressureRecord : Event
data object AddHeartRateRecord : Event
data class NavigateToTab(val bottomBarItem: BottomBarItem) : Event
+ data object SymptomsDescriptionBottomSheet : Event
}
}
diff --git a/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsDescriptionBottomSheet.kt b/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsDescriptionBottomSheet.kt
new file mode 100644
index 000000000..5bd11285c
--- /dev/null
+++ b/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsDescriptionBottomSheet.kt
@@ -0,0 +1,89 @@
+package edu.stanford.bdh.engagehf.health.symptoms
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import edu.stanford.bdh.engagehf.R
+import edu.stanford.spezi.core.design.component.VerticalSpacer
+import edu.stanford.spezi.core.design.theme.Spacings
+import edu.stanford.spezi.core.design.theme.SpeziTheme
+import edu.stanford.spezi.core.design.theme.TextStyles
+import edu.stanford.spezi.core.design.theme.ThemePreviews
+
+@Composable
+fun SymptomsDescriptionBottomSheet() {
+ LazyColumn(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(Spacings.medium),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ item {
+ Text(
+ text = stringResource(R.string.symptoms_description_title),
+ style = TextStyles.titleLarge
+ )
+ VerticalSpacer()
+ TitleDescriptionItem(
+ title = stringResource(R.string.overall_score_title),
+ description = stringResource(R.string.overall_score_description)
+ )
+ TitleDescriptionItem(
+ title = stringResource(R.string.physical_limits_score_title),
+ description = stringResource(R.string.physical_limits_score_description)
+ )
+ TitleDescriptionItem(
+ title = stringResource(R.string.social_limits_score_title),
+ description = stringResource(R.string.social_limits_score_description)
+ )
+ TitleDescriptionItem(
+ title = stringResource(R.string.quality_of_life_score_title),
+ description = stringResource(R.string.quality_of_life_score_description)
+ )
+ TitleDescriptionItem(
+ title = stringResource(R.string.symptoms_frequency_score_title),
+ description = stringResource(R.string.specific_symptoms_score_description)
+ )
+ TitleDescriptionItem(
+ title = stringResource(R.string.dizziness_score_title),
+ description = stringResource(R.string.dizziness_score_description)
+ )
+ VerticalSpacer()
+ }
+ }
+}
+
+@Composable
+fun TitleDescriptionItem(title: String, description: String) {
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(vertical = Spacings.small),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Text(
+ text = title,
+ style = TextStyles.titleMedium
+ )
+ Text(
+ text = description,
+ style = TextStyles.bodyMedium,
+ textAlign = TextAlign.Center
+ )
+ }
+}
+
+@ThemePreviews
+@Composable
+fun SymptomsDescriptionBottomSheetPreview() {
+ SpeziTheme(isPreview = true) {
+ SymptomsDescriptionBottomSheet()
+ }
+}
diff --git a/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsScreen.kt b/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsScreen.kt
index 69d3afb72..07764413e 100644
--- a/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsScreen.kt
+++ b/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsScreen.kt
@@ -1,6 +1,5 @@
package edu.stanford.bdh.engagehf.health.symptoms
-import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -12,9 +11,9 @@ import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.itemsIndexed
-import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowDropDown
+import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.outlined.Check
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.DropdownMenu
@@ -31,9 +30,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
@@ -71,7 +68,6 @@ import edu.stanford.bdh.engagehf.R
import edu.stanford.bdh.engagehf.health.HealthTableItem
import edu.stanford.spezi.core.design.component.CenteredBoxContent
import edu.stanford.spezi.core.design.component.VerticalSpacer
-import edu.stanford.spezi.core.design.theme.Colors.onPrimary
import edu.stanford.spezi.core.design.theme.Colors.primary
import edu.stanford.spezi.core.design.theme.Colors.secondary
import edu.stanford.spezi.core.design.theme.Sizes
@@ -163,14 +159,9 @@ private fun LazyListScope.listHeader(
onClick = { onAction(SymptomsViewModel.Action.Info) }
) {
Icon(
- painter = painterResource(id = edu.stanford.spezi.core.design.R.drawable.ic_info),
+ imageVector = Icons.Filled.Info,
contentDescription = stringResource(R.string.info_icon_content_description),
- modifier = Modifier
- .size(Sizes.Icon.medium)
- .background(primary, shape = CircleShape)
- .shadow(Spacings.small, CircleShape)
- .padding(Spacings.small),
- tint = onPrimary
+ tint = primary
)
}
}
@@ -280,12 +271,12 @@ fun SymptomsChart(
}
@Composable
-fun SymptomsDropdown(headerData: HeaderData, onAction: (SymptomsViewModel.Action) -> Unit) {
+private fun SymptomsDropdown(headerData: HeaderData, onAction: (SymptomsViewModel.Action) -> Unit) {
Box(modifier = Modifier.wrapContentSize(Alignment.TopStart)) {
TextButton(onClick = {
onAction(SymptomsViewModel.Action.ToggleSymptomTypeDropdown(true))
}) {
- SymptomTypeText(headerData.selectedSymptomType)
+ SymptomTypeTitleText(headerData.selectedSymptomType)
Icon(Icons.Default.ArrowDropDown, contentDescription = "ArrowDropDown")
}
DropdownMenu(
@@ -297,7 +288,7 @@ fun SymptomsDropdown(headerData: HeaderData, onAction: (SymptomsViewModel.Action
val isSelected = headerData.selectedSymptomType == symptomType
DropdownMenuItem(
text = {
- SymptomTypeText(symptomType)
+ headerData.selectedSymptomTypeText
},
onClick = {
onAction(SymptomsViewModel.Action.ToggleSymptomTypeDropdown(false))
@@ -317,16 +308,16 @@ fun SymptomsDropdown(headerData: HeaderData, onAction: (SymptomsViewModel.Action
}
@Composable
-fun SymptomTypeText(symptomType: SymptomType) {
+private fun SymptomTypeTitleText(symptomType: SymptomType) {
Text(
text =
when (symptomType) {
- SymptomType.OVERALL -> stringResource(R.string.symptom_type_overall)
- SymptomType.PHYSICAL_LIMITS -> stringResource(R.string.symptom_type_physical)
- SymptomType.SOCIAL_LIMITS -> stringResource(R.string.symptom_type_social)
- SymptomType.QUALITY_OF_LIFE -> stringResource(R.string.symptom_type_quality)
- SymptomType.SYMPTOMS_FREQUENCY -> stringResource(R.string.symptom_type_specific)
- SymptomType.DIZZINESS -> stringResource(R.string.symptom_type_dizziness)
+ SymptomType.OVERALL -> stringResource(R.string.overall_score_title)
+ SymptomType.PHYSICAL_LIMITS -> stringResource(R.string.physical_limits_score_title)
+ SymptomType.SOCIAL_LIMITS -> stringResource(R.string.social_limits_score_title)
+ SymptomType.QUALITY_OF_LIFE -> stringResource(R.string.quality_of_life_score_title)
+ SymptomType.SYMPTOMS_FREQUENCY -> stringResource(R.string.symptoms_frequency_score_title)
+ SymptomType.DIZZINESS -> stringResource(R.string.dizziness_score_title)
}
)
}
diff --git a/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsUiStateMapper.kt b/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsUiStateMapper.kt
index dc00def18..0b9763957 100644
--- a/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsUiStateMapper.kt
+++ b/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsUiStateMapper.kt
@@ -1,8 +1,10 @@
package edu.stanford.bdh.engagehf.health.symptoms
+import edu.stanford.bdh.engagehf.R
import edu.stanford.bdh.engagehf.health.AggregatedHealthData
import edu.stanford.bdh.engagehf.health.NewestHealthData
import edu.stanford.bdh.engagehf.health.TableEntryData
+import edu.stanford.spezi.core.design.component.StringResource
import edu.stanford.spezi.core.utils.LocaleProvider
import edu.stanford.spezi.core.utils.extensions.roundToDecimalPlaces
import java.time.ZoneId
@@ -40,13 +42,25 @@ class SymptomsUiStateMapper @Inject constructor(
formattedValue = newestHealthData.formattedValue,
formattedDate = newestHealthData.formattedDate,
selectedSymptomType = selectedSymptomType,
- isSelectedSymptomTypeDropdownExpanded = false
+ isSelectedSymptomTypeDropdownExpanded = false,
+ selectedSymptomTypeText = getSelectedSymptomTypeText(selectedSymptomType),
),
valueFormatter = ::valueFormatter
)
)
}
+ private fun getSelectedSymptomTypeText(selectedSymptomType: SymptomType): StringResource {
+ return when (selectedSymptomType) {
+ SymptomType.OVERALL -> StringResource(R.string.symptom_type_overall)
+ SymptomType.PHYSICAL_LIMITS -> StringResource(R.string.symptom_type_physical)
+ SymptomType.SOCIAL_LIMITS -> StringResource(R.string.symptom_type_social)
+ SymptomType.QUALITY_OF_LIFE -> StringResource(R.string.symptom_type_quality)
+ SymptomType.SYMPTOMS_FREQUENCY -> StringResource(R.string.symptom_type_specific)
+ SymptomType.DIZZINESS -> StringResource(R.string.symptom_type_dizziness)
+ }
+ }
+
private fun valueFormatter(value: Double): String {
val year = value.toInt()
val dayOfYearFraction = value - year
diff --git a/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsViewModel.kt b/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsViewModel.kt
index ce0bc2f25..6447adb00 100644
--- a/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsViewModel.kt
+++ b/app/src/main/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsViewModel.kt
@@ -5,9 +5,11 @@ package edu.stanford.bdh.engagehf.health.symptoms
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
+import edu.stanford.bdh.engagehf.bluetooth.component.AppScreenEvents
import edu.stanford.bdh.engagehf.health.AggregatedHealthData
import edu.stanford.bdh.engagehf.health.HealthRepository
import edu.stanford.bdh.engagehf.health.TableEntryData
+import edu.stanford.spezi.core.design.component.StringResource
import edu.stanford.spezi.core.logging.speziLogger
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -23,6 +25,7 @@ import javax.inject.Inject
class SymptomsViewModel @Inject internal constructor(
private val symptomsUiStateMapper: SymptomsUiStateMapper,
private val healthRepository: HealthRepository,
+ private val appScreenEvents: AppScreenEvents,
) : ViewModel() {
private val logger by speziLogger()
@@ -56,7 +59,12 @@ class SymptomsViewModel @Inject internal constructor(
fun onAction(action: Action) {
when (action) {
- Action.Info -> {}
+ is Action.Info -> {
+ appScreenEvents.emit(
+ AppScreenEvents.Event.SymptomsDescriptionBottomSheet
+ )
+ }
+
is Action.SelectSymptomType -> {
_uiState.update {
(it as? SymptomsUiState.Success)?.let { success ->
@@ -110,6 +118,7 @@ data class SymptomsUiData(
)
data class HeaderData(
+ val selectedSymptomTypeText: StringResource,
val formattedValue: String,
val formattedDate: String,
val selectedSymptomType: SymptomType,
diff --git a/app/src/main/kotlin/edu/stanford/bdh/engagehf/navigation/screens/AppScreen.kt b/app/src/main/kotlin/edu/stanford/bdh/engagehf/navigation/screens/AppScreen.kt
index cb0bb3d0a..f83ad84cb 100644
--- a/app/src/main/kotlin/edu/stanford/bdh/engagehf/navigation/screens/AppScreen.kt
+++ b/app/src/main/kotlin/edu/stanford/bdh/engagehf/navigation/screens/AppScreen.kt
@@ -39,6 +39,7 @@ import edu.stanford.bdh.engagehf.health.bloodpressure.bottomsheet.AddBloodPressu
import edu.stanford.bdh.engagehf.health.bloodpressure.bottomsheet.BloodPressureDescriptionBottomSheet
import edu.stanford.bdh.engagehf.health.heartrate.bottomsheet.AddHeartRateBottomSheet
import edu.stanford.bdh.engagehf.health.heartrate.bottomsheet.HeartRateDescriptionBottomSheet
+import edu.stanford.bdh.engagehf.health.symptoms.SymptomsDescriptionBottomSheet
import edu.stanford.bdh.engagehf.health.weight.bottomsheet.AddWeightBottomSheet
import edu.stanford.bdh.engagehf.health.weight.bottomsheet.WeightDescriptionBottomSheet
import edu.stanford.bdh.engagehf.medication.ui.MedicationScreen
@@ -209,6 +210,7 @@ private fun BottomSheetContent(
BottomSheetContent.BLOOD_PRESSURE_DESCRIPTION_INFO -> BloodPressureDescriptionBottomSheet()
BottomSheetContent.HEART_RATE_DESCRIPTION_INFO -> HeartRateDescriptionBottomSheet()
BottomSheetContent.BLUETOOTH_DEVICE_PAIRING -> BLEDevicePairingBottomSheet()
+ BottomSheetContent.SYMPTOMS_DESCRIPTION_INFO -> SymptomsDescriptionBottomSheet()
}
}
diff --git a/app/src/main/kotlin/edu/stanford/bdh/engagehf/navigation/screens/AppScreenViewModel.kt b/app/src/main/kotlin/edu/stanford/bdh/engagehf/navigation/screens/AppScreenViewModel.kt
index 159bb2001..72c17ae4e 100644
--- a/app/src/main/kotlin/edu/stanford/bdh/engagehf/navigation/screens/AppScreenViewModel.kt
+++ b/app/src/main/kotlin/edu/stanford/bdh/engagehf/navigation/screens/AppScreenViewModel.kt
@@ -89,6 +89,8 @@ class AppScreenViewModel @Inject constructor(
BottomSheetContent.BLOOD_PRESSURE_DESCRIPTION_INFO
}
+ AppScreenEvents.Event.SymptomsDescriptionBottomSheet -> BottomSheetContent.SYMPTOMS_DESCRIPTION_INFO
+
AppScreenEvents.Event.CloseBottomSheet -> {
null
}
@@ -187,6 +189,7 @@ enum class BottomSheetContent {
ADD_WEIGHT_RECORD,
ADD_BLOOD_PRESSURE_RECORD,
ADD_HEART_RATE_RECORD,
+ SYMPTOMS_DESCRIPTION_INFO,
BLUETOOTH_DEVICE_PAIRING,
}
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 95666d167..f41a0ca6c 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -91,5 +91,20 @@
Deine Geräte
Zuletzt gesehen am %1$s
Abmeldung fehlgeschlagen.
+ Einladungscode
+ Onboarding
Kontakt
+ Ihre Symptome verstehen
+ Gesamt Score
+ Dieser Wert zeigt, wie sich Ihre Herzinsuffizienz insgesamt auf Sie auswirkt. Sie können einen Wert zwischen 0 und 100 erreichen. Ein höherer Wert bedeutet, dass es Ihnen besser geht. Ein Wert über 80 wird oft als gut angesehen. Ein Ziel der Herzmedikamente ist es, diesen Wert im Laufe der Zeit zu verbessern oder zu verhindern, dass er sich verringert.
+ Physikalische Grenzen Score
+ Dieser Wert gibt an, wie sehr Ihr Herz Ihre Fähigkeit, sich zu betätigen, beeinträchtigt. Höhere Werte bedeuten, dass Sie weniger eingeschränkt sind, und ein Wert über 80 wird oft als gut angesehen.
+ Soziale Grenzen Score
+ Dieser Wert gibt an, wie Ihr Herz Ihre Fähigkeit zu sozialen Aktivitäten beeinflusst. Höhere Werte bedeuten, dass Sie mehr tun können, während niedrigere Werte bedeuten, dass Sie durch Ihr Herz stärker eingeschränkt sind.
+ Bewertung der Lebensqualität
+ Dieser Wert gibt an, wie zufrieden Sie mit Ihren Herzsymptomen sind. Höhere Werte bedeuten, dass Sie insgesamt zufriedener sind, während niedrigere Werte bedeuten, dass Sie weniger zufrieden mit Ihrer Situation sind.
+ Symptom Häufigkeit
+ Dieser Wert gibt die Häufigkeit an, mit der Sie herzbezogene Symptome verspüren. Höhere Werte bedeuten weniger häufige Symptome und niedrigere Werte bedeuten häufigere Symptome.
+ Schwindel Score
+ Es ist wichtig, Ihren Schwindel im Auge zu behalten, denn Schwindel kann eine Nebenwirkung Ihres Herzens oder Ihrer Herzmedikamente sein.
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index ae6cc12fb..fdf154c3f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -26,7 +26,7 @@
Physical
Social
Quality
- Specific
+ Symptoms
Dizziness
No medication recommendations
Current Dose:
@@ -108,4 +108,17 @@
Invitation Code
Onboarding
Contact
+ Understanding Your Symptoms
+ Overall Score
+ This score shows how your heart failure affects you overall. You can score 0 to 100. A higher score means you are doing better. Over 80 is often considered doing well. A goal of heart medicines is to improve this score over time or keep it from decreasing.
+ Physical Limits Score
+ This represents how your heart affects your ability to do activity. Higher scores mean you are less limited, and over 80 is often considered doing well.
+ Social Limits Score
+ This score represents how your heart affects your ability to do social activities. Higher scores mean you are able to do more, while lower scores mean you are more limited by your heart.
+ Quality of Life Score
+ This score represents how content you are with your heart symptoms. Higher scores mean you are overall more content, while lower scores mean you are less satisfied with how you are doing.
+ Symptom Frequency
+ This represents the frequency you are experiencing heart-related symptoms. Higher scores mean less frequent symptoms and lower scores mean more frequent symptoms.
+ Dizziness Score
+ Your dizziness is important to keep track of because dizziness can be a side effect of your heart or your heart medicines.
diff --git a/app/src/test/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsUiStateMapperTest.kt b/app/src/test/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsUiStateMapperTest.kt
index 941ac5424..b43e16521 100644
--- a/app/src/test/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsUiStateMapperTest.kt
+++ b/app/src/test/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsUiStateMapperTest.kt
@@ -1,6 +1,8 @@
package edu.stanford.bdh.engagehf.health.symptoms
import com.google.common.truth.Truth.assertThat
+import edu.stanford.bdh.engagehf.R
+import edu.stanford.spezi.core.design.component.StringResource
import edu.stanford.spezi.core.utils.LocaleProvider
import io.mockk.every
import io.mockk.mockk
@@ -125,6 +127,61 @@ class SymptomsUiStateMapperTest {
assertThat(successStateOverall.data.chartData[0].xValues.size).isEqualTo(0)
}
+ @Test
+ fun `mapSymptomsUiState when different symptomTypes returns correct selectedSymptomTypeText`() {
+ // Given
+ val symptomScores = listOf(
+ createSymptomScore(),
+ )
+
+ // When
+ val resultOverall =
+ symptomsUiStateMapper.mapSymptomsUiState(SymptomType.OVERALL, symptomScores)
+ val resultPhysical =
+ symptomsUiStateMapper.mapSymptomsUiState(SymptomType.PHYSICAL_LIMITS, symptomScores)
+ val resultSocial =
+ symptomsUiStateMapper.mapSymptomsUiState(SymptomType.SOCIAL_LIMITS, symptomScores)
+ val resultQuality =
+ symptomsUiStateMapper.mapSymptomsUiState(SymptomType.QUALITY_OF_LIFE, symptomScores)
+ val resultSpecific =
+ symptomsUiStateMapper.mapSymptomsUiState(SymptomType.SYMPTOMS_FREQUENCY, symptomScores)
+ val resultDizziness =
+ symptomsUiStateMapper.mapSymptomsUiState(SymptomType.DIZZINESS, symptomScores)
+
+ // Then
+ assertThat(resultOverall).isInstanceOf(SymptomsUiState.Success::class.java)
+ assertThat(resultPhysical).isInstanceOf(SymptomsUiState.Success::class.java)
+ assertThat(resultSocial).isInstanceOf(SymptomsUiState.Success::class.java)
+ assertThat(resultQuality).isInstanceOf(SymptomsUiState.Success::class.java)
+ assertThat(resultSpecific).isInstanceOf(SymptomsUiState.Success::class.java)
+ assertThat(resultDizziness).isInstanceOf(SymptomsUiState.Success::class.java)
+ val successStateOverall = resultOverall as SymptomsUiState.Success
+ val successStatePhysical = resultPhysical as SymptomsUiState.Success
+ val successStateSocial = resultSocial as SymptomsUiState.Success
+ val successStateQuality = resultQuality as SymptomsUiState.Success
+ val successStateSpecific = resultSpecific as SymptomsUiState.Success
+ val successStateDizziness = resultDizziness as SymptomsUiState.Success
+ assertThat(successStateOverall.data.headerData.selectedSymptomTypeText).isEqualTo(
+ StringResource(R.string.symptom_type_overall)
+ )
+ assertThat(successStatePhysical.data.headerData.selectedSymptomTypeText).isEqualTo(
+ StringResource(R.string.symptom_type_physical)
+ )
+
+ assertThat(successStateSocial.data.headerData.selectedSymptomTypeText).isEqualTo(
+ StringResource(R.string.symptom_type_social)
+ )
+ assertThat(successStateQuality.data.headerData.selectedSymptomTypeText).isEqualTo(
+ StringResource(R.string.symptom_type_quality)
+ )
+ assertThat(successStateSpecific.data.headerData.selectedSymptomTypeText).isEqualTo(
+ StringResource(R.string.symptom_type_specific)
+ )
+ assertThat(successStateDizziness.data.headerData.selectedSymptomTypeText).isEqualTo(
+ StringResource(R.string.symptom_type_dizziness)
+ )
+ }
+
private fun createSymptomScore(
year: Int = 2024,
month: Int = 8,
diff --git a/app/src/test/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsViewModelTest.kt b/app/src/test/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsViewModelTest.kt
index 716c82e9e..df576d5d4 100644
--- a/app/src/test/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsViewModelTest.kt
+++ b/app/src/test/kotlin/edu/stanford/bdh/engagehf/health/symptoms/SymptomsViewModelTest.kt
@@ -1,11 +1,15 @@
package edu.stanford.bdh.engagehf.health.symptoms
import com.google.common.truth.Truth.assertThat
+import edu.stanford.bdh.engagehf.R
+import edu.stanford.bdh.engagehf.bluetooth.component.AppScreenEvents
import edu.stanford.bdh.engagehf.health.HealthRepository
+import edu.stanford.spezi.core.design.component.StringResource
import edu.stanford.spezi.core.testing.CoroutineTestRule
import io.mockk.coEvery
import io.mockk.every
import io.mockk.mockk
+import io.mockk.verify
import kotlinx.coroutines.flow.flowOf
import org.junit.Before
import org.junit.Rule
@@ -21,6 +25,7 @@ class SymptomsViewModelTest {
private val symptomsUiStateMapper: SymptomsUiStateMapper = mockk()
private val symptomScores = getSymptomScores()
private val successState = SymptomsUiState.Success(getSymptomsUiData())
+ private val appScreenEvents: AppScreenEvents = mockk(relaxed = true)
private lateinit var viewModel: SymptomsViewModel
@@ -99,6 +104,18 @@ class SymptomsViewModelTest {
assertThat(uiState).isEqualTo(newState)
}
+ @Test
+ fun `it should handle SymptomsDescriptionBottomSheet correctly`() {
+ // given
+ createViewModel()
+
+ // when
+ viewModel.onAction(SymptomsViewModel.Action.Info)
+
+ // then
+ verify { appScreenEvents.emit(AppScreenEvents.Event.SymptomsDescriptionBottomSheet) }
+ }
+
private fun getSymptomScores() = listOf(
SymptomScore(
overallScore = 80.0,
@@ -117,10 +134,15 @@ class SymptomsViewModelTest {
formattedDate = "",
formattedValue = "",
selectedSymptomType = SymptomType.SYMPTOMS_FREQUENCY,
+ selectedSymptomTypeText = StringResource(R.string.symptom_type_overall),
)
)
private fun createViewModel() {
- viewModel = SymptomsViewModel(symptomsUiStateMapper, healthRepository)
+ viewModel = SymptomsViewModel(
+ symptomsUiStateMapper = symptomsUiStateMapper,
+ healthRepository = healthRepository,
+ appScreenEvents = appScreenEvents,
+ )
}
}
diff --git a/app/src/test/kotlin/edu/stanford/bdh/engagehf/navigation/screens/AppScreenViewModelTest.kt b/app/src/test/kotlin/edu/stanford/bdh/engagehf/navigation/screens/AppScreenViewModelTest.kt
index 4f905e41a..9b2092c05 100644
--- a/app/src/test/kotlin/edu/stanford/bdh/engagehf/navigation/screens/AppScreenViewModelTest.kt
+++ b/app/src/test/kotlin/edu/stanford/bdh/engagehf/navigation/screens/AppScreenViewModelTest.kt
@@ -268,4 +268,18 @@ class AppScreenViewModelTest {
val updatedUiState = viewModel.uiState.value
assertThat(updatedUiState.bottomSheetContent).isEqualTo(BottomSheetContent.HEART_RATE_DESCRIPTION_INFO)
}
+
+ @Test
+ fun `given SymptomsDescriptionBottomSheet is received then uiState should be updated`() =
+ runTestUnconfined {
+ // Given
+ val event = AppScreenEvents.Event.SymptomsDescriptionBottomSheet
+
+ // When
+ appScreenEventsFlow.emit(event)
+
+ // Then
+ val updatedUiState = viewModel.uiState.value
+ assertThat(updatedUiState.bottomSheetContent).isEqualTo(BottomSheetContent.SYMPTOMS_DESCRIPTION_INFO)
+ }
}