Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix/UI-updates #117

Merged
merged 22 commits into from
Dec 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions ENGAGEHF/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ struct ContentView: View {
return .auth
}
guard FeatureFlags.disableFirebase
|| !(account?.details?.isIncomplete ?? true)
|| account?.details?.invitationCode != nil else {
|| (!(account?.details?.isIncomplete ?? true) && account?.details?.invitationCode != nil) else {
return .auth
}
return nil
Expand Down
6 changes: 3 additions & 3 deletions ENGAGEHF/HeartHealth/SelectionTypes/SymptomsType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ enum SymptomsType: String, CaseIterable, Identifiable, CustomStringConvertible,
case .overall: "Overall"
case .physical: "Physical"
case .social: "Social"
case .quality: "Quality"
case .specific: "Specific"
case .quality: "Quality of Life"
case .specific: "Symptoms"
case .dizziness: "Dizziness"
}
}
Expand All @@ -44,7 +44,7 @@ enum SymptomsType: String, CaseIterable, Identifiable, CustomStringConvertible,
case .physical: "Physical Limits Score"
case .social: "Social Limits Score"
case .quality: "Quality of Life Score"
case .specific: "Specific Symptoms Score"
case .specific: "Symptom Frequency Score"
case .dizziness: "Dizziness Score"
}
}
Expand Down
30 changes: 29 additions & 1 deletion ENGAGEHF/HeartHealth/Symptoms/AnyAxisContent+CustomAxes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,40 @@
}
}

// Dizziness scores range between 0 and 5, and each has a specific desired label.
@AxisContentBuilder private static var dizzinessYAxisModifierBuilder: some AxisContent {
AxisMarks(values: [0, 1, 2, 3, 4, 5]) { value in
switch value.as(Int.self) {
case 5:
AxisValueLabel("Very Severe")
case 4:
AxisValueLabel("Severe")
case 3:
AxisValueLabel("Moderate")
case 2:
AxisValueLabel("Mild")
case 1:
AxisValueLabel("Minimal")
case 0:
AxisValueLabel("None")
default:
AxisValueLabel("")

Check warning on line 44 in ENGAGEHF/HeartHealth/Symptoms/AnyAxisContent+CustomAxes.swift

View check run for this annotation

Codecov / codecov/patch

ENGAGEHF/HeartHealth/Symptoms/AnyAxisContent+CustomAxes.swift#L44

Added line #L44 was not covered by tests
}
}

AxisMarks(
values: [0, 1, 2, 3, 4, 5]
) {
AxisGridLine()
}
}

static var percentageYAxisModifier: AnyAxisContent {
AnyAxisContent(percentageYAxisModifierBuilder)
}


static var dizzinessYAxisModifier: AnyAxisContent {
AnyAxisContent(AxisMarks(values: .automatic(desiredCount: 5)))
AnyAxisContent(dizzinessYAxisModifierBuilder)
}
}
4 changes: 4 additions & 0 deletions ENGAGEHF/HeartHealth/Symptoms/SymptomsGraphSection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ struct SymptomsGraphSection: View {
content: {
VitalsGraph(data: graphData, options: options)
.environment(\.customChartYAxis, symptomsType == .dizziness ? .dizzinessYAxisModifier : .percentageYAxisModifier )
#if TEST
.disabled(true)
#else
.disabled(vitalsManager.symptomHistory.isEmpty)
#endif
},
header: {
SymptomsPicker(symptomsType: $symptomsType)
Expand Down
4 changes: 4 additions & 0 deletions ENGAGEHF/HeartHealth/Vitals/VitalsGraphSection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ struct VitalsGraphSection: View {
dateResolution: granularity.defaultDateUnit,
targetValue: vitalsType == .weight ? vitalsManager.latestDryWeight : nil
)
#if TEST
.disabled(true)
#else
.disabled(data.isEmpty)
#endif
},
header: {
HStack {
Expand Down
4 changes: 2 additions & 2 deletions ENGAGEHF/Managers/MedicationsManager/MedicationDetails.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ enum MedicationRecommendationType: String, Decodable, Comparable {
case .targetDoseReached: .targetReached
case .personalTargetDoseReached: .targetReached
case .improvementAvailable: .improvementAvailable
case .moreLabObservationsRequired: .improvementAvailable
case .morePatientObservationsRequired: .improvementAvailable
case .moreLabObservationsRequired: .actionRequired
case .morePatientObservationsRequired: .actionRequired
case .noActionRequired: .notStarted
case .notStarted: .notStarted
}
Expand Down
19 changes: 17 additions & 2 deletions ENGAGEHF/Managers/MedicationsManager/MedicationsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ extension MedicationsManager {
unit: "mg"
)
),
// Multi-ingredient, single schedule, at minimum dose
// Multi-ingredient, single schedule, at minimum dose, improvement available.
MedicationDetails(
id: UUID().uuidString,
title: "Sacubitril-Valsartan",
Expand All @@ -205,7 +205,8 @@ extension MedicationsManager {
unit: "mg"
)
),
// Single ingredient, below minimum dose, non-integer frequency
// Single ingredient, below minimum dose, non-integer frequency.
// Not on the med, but action required.
MedicationDetails(
id: UUID().uuidString,
title: "Spironolactone",
Expand All @@ -219,6 +220,20 @@ extension MedicationsManager {
unit: "mg"
)
),
// On the med but action required.
MedicationDetails(
id: UUID().uuidString,
title: "Dapagliflozin",
subtitle: "SGLT2i",
description: "More lab observations required for recommendations.",
videoPath: nil,
type: .moreLabObservationsRequired,
dosageInformation: DosageInformation(
currentSchedule: [DoseSchedule(frequency: 1.5, quantity: [15])],
targetSchedule: [DoseSchedule(frequency: 1.5, quantity: [25])],
unit: "mg"
)
),
// Single ingredient, single schedule, not started yet
MedicationDetails(
id: UUID().uuidString,
Expand Down
1 change: 1 addition & 0 deletions ENGAGEHF/Managers/VideoManager/VideoManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import OSLog
import Spezi
import SpeziAccount


@Observable
@MainActor
final class VideoManager: Manager {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct ColorKeyEntryView: View {


var body: some View {
HStack {
HStack(alignment: .center) {
Circle()
.fill(color)
.frame(width: 12)
Expand Down
2 changes: 1 addition & 1 deletion ENGAGEHF/Medications/ColorLegendSection/ColorLegend.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ struct ColorLegend: View {
}
},
header: {
Text("Color Key")
Text("Legend")
.padding(.horizontal, -16)
}
)
Expand Down
13 changes: 8 additions & 5 deletions ENGAGEHF/Medications/RecommendationStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,28 @@ import SwiftUI

/// Defines the color and interpretation associated with a `MedicationRecommendation` in the UI.
enum RecommendationStyle: CaseIterable {
case targetReached, improvementAvailable, notStarted
case targetReached, improvementAvailable, actionRequired, notStarted


var color: Color {
switch self {
case .targetReached: .green
case .improvementAvailable: .yellow
case .notStarted: .blue
case .actionRequired: .blue.opacity(0.6)
case .notStarted: .gray.opacity(0.6)
}
}

var localizedInterpretation: String {
switch self {
case .targetReached:
String(localized: "You're on your target dose.", comment: "Target dose reached color legend entry.")
String(localized: "You are on your target dose.", comment: "Target dose reached color legend entry.")
case .improvementAvailable:
String(localized: "On the med but may benefit from a higher dose.", comment: "Improvement available color legend entry.")
String(localized: "You are on this medication, but may benefit from a higher dose.", comment: "Improvement available color legend entry.")
case .actionRequired:
String(localized: "More information is needed to make a recommendation.", comment: "Action required color legend entry.")
case .notStarted:
String(localized: "Not on this med that may help your heart.", comment: "No action required legend entry.")
String(localized: "You are not on this medication, but it might be helpful in the future.", comment: "No action required legend entry.")
}
}
}
41 changes: 31 additions & 10 deletions ENGAGEHF/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The ENGAGE-HF demonstrates the usage of the Firebase Account Module."
"value" : "Sign in or create an account."
}
}
}
Expand Down Expand Up @@ -148,9 +148,6 @@
},
"Cancel" : {

},
"Color Key" : {

},
"Contacts" : {

Expand Down Expand Up @@ -373,6 +370,9 @@
},
"Invitation Code" : {

},
"Legend" : {

},
"LICENSE_INFO_TITLE" : {
"localizations" : {
Expand All @@ -395,6 +395,18 @@
},
"Messages" : {

},
"Mild" : {

},
"Minimal" : {

},
"Moderate" : {

},
"More information is needed to make a recommendation." : {
"comment" : "Action required color legend entry."
},
"No Contacts Available" : {

Expand All @@ -414,8 +426,8 @@
"No vitals" : {

},
"Not on this med that may help your heart." : {
"comment" : "No action required legend entry."
"None" : {

},
"Not Started" : {

Expand Down Expand Up @@ -463,9 +475,6 @@
},
"Notifications" : {

},
"On the med but may benefit from a higher dose." : {
"comment" : "Improvement available color legend entry."
},
"Organization" : {

Expand Down Expand Up @@ -526,6 +535,9 @@
},
"Series" : {

},
"Severe" : {

},
"Share Link" : {

Expand Down Expand Up @@ -689,6 +701,9 @@
}
}
}
},
"Very Severe" : {

},
"Vitals" : {

Expand Down Expand Up @@ -835,7 +850,13 @@
}
}
},
"You're on your target dose." : {
"You are not in this medication, but it might be helpful in the future." : {
"comment" : "No action required legend entry."
},
"You are on this medication, but may benefit from a higher dose." : {
"comment" : "Improvement available color legend entry."
},
"You are on your target dose." : {
"comment" : "Target dose reached color legend entry."
}
},
Expand Down
14 changes: 11 additions & 3 deletions ENGAGEHFUITests/Account/OnboardingUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,18 @@ extension XCUIApplication {
}

fileprivate func assertOnboardingComplete() {
XCTAssert(staticTexts["Home"].waitForExistence(timeout: 10))

let tabBar = tabBars["Tab Bar"]
XCTAssert(tabBar.buttons["Home"].waitForExistence(timeout: 2))

// Regression test: make sure the videos appeared correctly
XCTAssert(tabBar.buttons["Education"].waitForExistence(timeout: 2))
tabBar.buttons["Education"].tap()
XCTAssertFalse(staticTexts["No Educational Videos"].exists)

// Navigate back to home page
XCTAssert(tabBar.buttons["Home"].waitForExistence(timeout: 0.5))
tabBar.buttons["Home"].tap()

XCTAssert(staticTexts["Home"].waitForExistence(timeout: 4))
}

fileprivate func assertAccountInformation(email: String) throws {
Expand Down
14 changes: 7 additions & 7 deletions ENGAGEHFUITests/HeartHealth/HeartHealthUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -278,23 +278,23 @@ extension XCUIApplication {
}

fileprivate func testEmptySymptomScores() {
XCTAssert(buttons["Symptoms"].waitForExistence(timeout: 0.5))
buttons["Symptoms"].tap()
XCTAssert(buttons["Symptoms"].firstMatch.waitForExistence(timeout: 0.5))
buttons["Symptoms"].firstMatch.tap()

let symptomTypes = [
"Overall",
"Physical Limits",
"Social Limits",
"Quality of Life",
"Specific Symptoms",
"Symptom Frequency",
"Dizziness"
]
let symptomLabels = [
"Overall",
"Physical",
"Social",
"Quality",
"Specific",
"Quality of Life",
"Symptoms",
"Dizziness"
]

Expand All @@ -307,8 +307,8 @@ extension XCUIApplication {
XCTAssert(buttons["\(symptomTypes[idx]) Score, Symptoms Picker Chevron"].waitForExistence(timeout: 0.5))
images["Symptoms Picker Chevron"].tap()

XCTAssert(buttons["\(symptomLabels[nextIdx])"].waitForExistence(timeout: 0.5))
buttons["\(symptomLabels[nextIdx])"].tap()
XCTAssert(buttons["\(symptomLabels[nextIdx])"].firstMatch.waitForExistence(timeout: 0.5))
buttons["\(symptomLabels[nextIdx])"].firstMatch.tap()

testEmptyForSpecificType(scoreType: symptomTypes[nextIdx])
}
Expand Down
Loading