From f8d2bccd532b95990638e21d848efa0510c66e75 Mon Sep 17 00:00:00 2001
From: Catherine Zhang <137839789+czhang771@users.noreply.github.com>
Date: Fri, 1 Mar 2024 14:00:05 -0500
Subject: [PATCH] Added Onboarding Survey on Dashboard (#38)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
# Added Onboarding Survey to Dashboard
## :recycle: Current situation & Problem
Made the onboarding survey optional during onboarding process and appear
on the dashboard if not completed.
## :gear: Release Notes
- created new screen for the onboarding questionnaire that links to the
questionnaire view
- added questionnaire to dashboard if not completed
- added sliders to questionnaire format
## :books: Documentation
*Please ensure that you properly document any additions in conformance
to [Spezi Documentation
Guide](https://github.com/StanfordSpezi/.github/blob/main/DOCUMENTATIONGUIDE.md).*
Used @AppStorage to keep track of if the survey was completed and used
sheets on both the onboarding and dashboard page to display
questionnaire.
## :white_check_mark: Testing
## :pencil: Code of Conduct & Contributing Guidelines
By submitting creating this pull request, you agree to follow our [Code
of
Conduct](https://github.com/CS342/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/CS342/.github/blob/main/CONTRIBUTING.md):
- [x] I agree to follow the [Code of
Conduct](https://github.com/CS342/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/CS342/.github/blob/main/CONTRIBUTING.md).
---
PICS.xcodeproj/project.pbxproj | 62 ++++----
PICS/Onboarding/AccountQuestionnaire.swift | 73 ++++++++++
PICS/Onboarding/OnboardingFlow.swift | 2 +-
...re.swift => OnboardingQuestionnaire.swift} | 13 +-
PICS/Resources/Localizable.xcstrings | 137 +++++++++++++-----
PICS/Resources/Onboarding-Questionnaire.json | 2 +-
.../OnboardingQuestionnaireDashboard.swift | 36 +++++
PICS/Schedule/OnboardingSurveyView.swift | 75 ++++++++++
PICS/Schedule/ScheduleView.swift | 55 +++----
9 files changed, 360 insertions(+), 95 deletions(-)
create mode 100644 PICS/Onboarding/AccountQuestionnaire.swift
rename PICS/Onboarding/{Onboarding_Questionnaire.swift => OnboardingQuestionnaire.swift} (60%)
create mode 100644 PICS/Schedule/OnboardingQuestionnaireDashboard.swift
create mode 100644 PICS/Schedule/OnboardingSurveyView.swift
diff --git a/PICS.xcodeproj/project.pbxproj b/PICS.xcodeproj/project.pbxproj
index 6125653..fbb759e 100644
--- a/PICS.xcodeproj/project.pbxproj
+++ b/PICS.xcodeproj/project.pbxproj
@@ -7,8 +7,14 @@
objects = {
/* Begin PBXBuildFile section */
- 22306A2A2B7C4E8E000A8EC1 /* Onboarding_Questionnaire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22306A292B7C4E8E000A8EC1 /* Onboarding_Questionnaire.swift */; };
- 22306A2E2B8581C3000A8EC1 /* Onboarding-Questionnaire.json in Resources */ = {isa = PBXBuildFile; fileRef = 22306A2D2B8581C3000A8EC1 /* Onboarding-Questionnaire.json */; };
+ 22201EE82B9259B800E38F47 /* EQ5D5L.json in Resources */ = {isa = PBXBuildFile; fileRef = 22201EE52B9259B800E38F47 /* EQ5D5L.json */; };
+ 22201EE92B9259B800E38F47 /* PHQ-4.json in Resources */ = {isa = PBXBuildFile; fileRef = 22201EE62B9259B800E38F47 /* PHQ-4.json */; };
+ 22201EEA2B9259B800E38F47 /* Self-MNA.json in Resources */ = {isa = PBXBuildFile; fileRef = 22201EE72B9259B800E38F47 /* Self-MNA.json */; };
+ 22306A2A2B7C4E8E000A8EC1 /* OnboardingQuestionnaire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22306A292B7C4E8E000A8EC1 /* OnboardingQuestionnaire.swift */; };
+ 22306A3E2B8F0097000A8EC1 /* OnboardingSurveyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22306A3D2B8F0097000A8EC1 /* OnboardingSurveyView.swift */; };
+ 22306A412B8F20C4000A8EC1 /* AccountQuestionnaire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22306A402B8F20C4000A8EC1 /* AccountQuestionnaire.swift */; };
+ 22306A462B8FB173000A8EC1 /* OnboardingQuestionnaireDashboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22306A452B8FB173000A8EC1 /* OnboardingQuestionnaireDashboard.swift */; };
+ 22365B782B902C9100C4528E /* Onboarding-Questionnaire.json in Resources */ = {isa = PBXBuildFile; fileRef = 22365B772B902C9100C4528E /* Onboarding-Questionnaire.json */; };
226C16F02B69DF3500FBA97D /* HeightKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 226C16EF2B69DF3500FBA97D /* HeightKey.swift */; };
226C16F22B6C820C00FBA97D /* WeightKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 226C16F12B6C820B00FBA97D /* WeightKey.swift */; };
27FA29902A388E9B009CAC45 /* ModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27FA298F2A388E9B009CAC45 /* ModalView.swift */; };
@@ -70,13 +76,6 @@
653A255528338800005D4D48 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 653A255428338800005D4D48 /* Assets.xcassets */; };
653A256228338800005D4D48 /* PICSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653A256128338800005D4D48 /* PICSTests.swift */; };
741110F22B5767DF00DFC79E /* PROM-Questionnaire.json in Resources */ = {isa = PBXBuildFile; fileRef = 741110F12B5767DE00DFC79E /* PROM-Questionnaire.json */; };
- 748117182B74BC3E00801A9A /* EQ5D5L.json.license in Resources */ = {isa = PBXBuildFile; fileRef = 748117162B74BC3E00801A9A /* EQ5D5L.json.license */; };
- 74AE057F2B8FFF5200AB5287 /* EQ5D5L.json in Resources */ = {isa = PBXBuildFile; fileRef = 74AE057E2B8FFF5200AB5287 /* EQ5D5L.json */; };
- 74AE05812B90068100AB5287 /* PHQ-4.json in Resources */ = {isa = PBXBuildFile; fileRef = 74AE05802B90068100AB5287 /* PHQ-4.json */; };
- 74AE05842B90099900AB5287 /* Self-MNA.json in Resources */ = {isa = PBXBuildFile; fileRef = 74AE05832B90099900AB5287 /* Self-MNA.json */; };
- 74C593952B720781002D0274 /* (null) in Resources */ = {isa = PBXBuildFile; };
- 74C593972B720B5E002D0274 /* (null) in Resources */ = {isa = PBXBuildFile; };
- 74C5939A2B720F1B002D0274 /* (null) in Resources */ = {isa = PBXBuildFile; };
86400D192B7C4B6D009FEC10 /* ApptInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86400D182B7C4B6D009FEC10 /* ApptInfo.swift */; };
8644E6712B6C7243001218D0 /* AppointmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8644E6702B6C7243001218D0 /* AppointmentView.swift */; };
8644E67B2B6C75B1001218D0 /* MapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8644E67A2B6C75B1001218D0 /* MapView.swift */; };
@@ -117,8 +116,14 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
- 22306A292B7C4E8E000A8EC1 /* Onboarding_Questionnaire.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Onboarding_Questionnaire.swift; sourceTree = ""; };
- 22306A2D2B8581C3000A8EC1 /* Onboarding-Questionnaire.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "Onboarding-Questionnaire.json"; sourceTree = ""; };
+ 22201EE52B9259B800E38F47 /* EQ5D5L.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = EQ5D5L.json; sourceTree = ""; };
+ 22201EE62B9259B800E38F47 /* PHQ-4.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "PHQ-4.json"; sourceTree = ""; };
+ 22201EE72B9259B800E38F47 /* Self-MNA.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "Self-MNA.json"; sourceTree = ""; };
+ 22306A292B7C4E8E000A8EC1 /* OnboardingQuestionnaire.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingQuestionnaire.swift; sourceTree = ""; };
+ 22306A3D2B8F0097000A8EC1 /* OnboardingSurveyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingSurveyView.swift; sourceTree = ""; };
+ 22306A402B8F20C4000A8EC1 /* AccountQuestionnaire.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountQuestionnaire.swift; sourceTree = ""; };
+ 22306A452B8FB173000A8EC1 /* OnboardingQuestionnaireDashboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingQuestionnaireDashboard.swift; sourceTree = ""; };
+ 22365B772B902C9100C4528E /* Onboarding-Questionnaire.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "Onboarding-Questionnaire.json"; sourceTree = ""; };
226C16EF2B69DF3500FBA97D /* HeightKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeightKey.swift; sourceTree = ""; };
226C16F12B6C820B00FBA97D /* WeightKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeightKey.swift; sourceTree = ""; };
27FA298F2A388E9B009CAC45 /* ModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalView.swift; sourceTree = ""; };
@@ -165,10 +170,6 @@
653A256728338800005D4D48 /* PICSUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PICSUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
653A258928339462005D4D48 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
741110F12B5767DE00DFC79E /* PROM-Questionnaire.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "PROM-Questionnaire.json"; sourceTree = ""; };
- 748117162B74BC3E00801A9A /* EQ5D5L.json.license */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = EQ5D5L.json.license; sourceTree = ""; };
- 74AE057E2B8FFF5200AB5287 /* EQ5D5L.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = EQ5D5L.json; sourceTree = ""; };
- 74AE05802B90068100AB5287 /* PHQ-4.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "PHQ-4.json"; sourceTree = ""; };
- 74AE05832B90099900AB5287 /* Self-MNA.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "Self-MNA.json"; sourceTree = ""; };
86400D182B7C4B6D009FEC10 /* ApptInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApptInfo.swift; sourceTree = ""; };
8644E6702B6C7243001218D0 /* AppointmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppointmentView.swift; sourceTree = ""; };
8644E67A2B6C75B1001218D0 /* MapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapView.swift; sourceTree = ""; };
@@ -283,7 +284,8 @@
2FE5DCAC29EE6107004B9AB4 /* AccountOnboarding.swift */,
2FE5DC2F29EDD7CA004B9AB4 /* Consent.swift */,
2FE5DC3029EDD7CA004B9AB4 /* HealthKitPermissions.swift */,
- 22306A292B7C4E8E000A8EC1 /* Onboarding_Questionnaire.swift */,
+ 22306A292B7C4E8E000A8EC1 /* OnboardingQuestionnaire.swift */,
+ 22306A402B8F20C4000A8EC1 /* AccountQuestionnaire.swift */,
);
path = Onboarding;
sourceTree = "";
@@ -291,11 +293,10 @@
2FE5DC2D29EDD792004B9AB4 /* Resources */ = {
isa = PBXGroup;
children = (
- 74AE05832B90099900AB5287 /* Self-MNA.json */,
- 74AE05802B90068100AB5287 /* PHQ-4.json */,
- 74AE057E2B8FFF5200AB5287 /* EQ5D5L.json */,
- 22306A2D2B8581C3000A8EC1 /* Onboarding-Questionnaire.json */,
- 748117162B74BC3E00801A9A /* EQ5D5L.json.license */,
+ 22201EE52B9259B800E38F47 /* EQ5D5L.json */,
+ 22201EE62B9259B800E38F47 /* PHQ-4.json */,
+ 22201EE72B9259B800E38F47 /* Self-MNA.json */,
+ 22365B772B902C9100C4528E /* Onboarding-Questionnaire.json */,
741110F12B5767DE00DFC79E /* PROM-Questionnaire.json */,
653A255428338800005D4D48 /* Assets.xcassets */,
2FA0BFEC2ACC977500E0EF83 /* Localizable.xcstrings */,
@@ -315,6 +316,8 @@
2FE5DC4C29EDD7FA004B9AB4 /* PICSScheduler.swift */,
2FE5DC4B29EDD7FA004B9AB4 /* PICSTaskContext.swift */,
27FA298F2A388E9B009CAC45 /* ModalView.swift */,
+ 22306A3D2B8F0097000A8EC1 /* OnboardingSurveyView.swift */,
+ 22306A452B8FB173000A8EC1 /* OnboardingQuestionnaireDashboard.swift */,
);
path = Schedule;
sourceTree = "";
@@ -616,19 +619,15 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 22201EEA2B9259B800E38F47 /* Self-MNA.json in Resources */,
2FC3439229EE634B002D773C /* ConsentDocument.md in Resources */,
653A255528338800005D4D48 /* Assets.xcassets in Resources */,
- 74C5939A2B720F1B002D0274 /* (null) in Resources */,
+ 22201EE92B9259B800E38F47 /* PHQ-4.json in Resources */,
2FC3439029EE6346002D773C /* SocialSupportQuestionnaire.json in Resources */,
- 74AE057F2B8FFF5200AB5287 /* EQ5D5L.json in Resources */,
- 748117182B74BC3E00801A9A /* EQ5D5L.json.license in Resources */,
- 74C593952B720781002D0274 /* (null) in Resources */,
- 22306A2E2B8581C3000A8EC1 /* Onboarding-Questionnaire.json in Resources */,
+ 22201EE82B9259B800E38F47 /* EQ5D5L.json in Resources */,
+ 22365B782B902C9100C4528E /* Onboarding-Questionnaire.json in Resources */,
2FA0BFED2ACC977500E0EF83 /* Localizable.xcstrings in Resources */,
741110F22B5767DF00DFC79E /* PROM-Questionnaire.json in Resources */,
- 74C593972B720B5E002D0274 /* (null) in Resources */,
- 74AE05812B90068100AB5287 /* PHQ-4.json in Resources */,
- 74AE05842B90099900AB5287 /* Self-MNA.json in Resources */,
2F6025CB29BBE70F0045459E /* GoogleService-Info.plist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -680,7 +679,7 @@
86400D192B7C4B6D009FEC10 /* ApptInfo.swift in Sources */,
2F4FC8D729EE69D300BFFE26 /* MockUpload.swift in Sources */,
2FE5DC3A29EDD7CA004B9AB4 /* Welcome.swift in Sources */,
- 22306A2A2B7C4E8E000A8EC1 /* Onboarding_Questionnaire.swift in Sources */,
+ 22306A2A2B7C4E8E000A8EC1 /* OnboardingQuestionnaire.swift in Sources */,
2FE5DC3829EDD7CA004B9AB4 /* InterestingModules.swift in Sources */,
2FE5DC3529EDD7CA004B9AB4 /* Consent.swift in Sources */,
2FE5DC4529EDD7F2004B9AB4 /* Binding+Negate.swift in Sources */,
@@ -710,14 +709,17 @@
A480C7C42B6D721A00B29A07 /* HKVisualizationItem.swift in Sources */,
56F6F2A02AB441930022FE5A /* ContributionsList.swift in Sources */,
566155292AB8447C00209B80 /* Package+LicenseType.swift in Sources */,
+ 22306A412B8F20C4000A8EC1 /* AccountQuestionnaire.swift in Sources */,
5680DD392AB8983D004E6D4A /* PackageCell.swift in Sources */,
A480C7C02B6D5A3700B29A07 /* HKVisualization.swift in Sources */,
2F5E32BD297E05EA003432F8 /* PICSDelegate.swift in Sources */,
A459932C2B906C3B00A98C95 /* ResultsViz.swift in Sources */,
2FE5DC5229EDD7FA004B9AB4 /* PICSScheduler.swift in Sources */,
A9FE7AD02AA39BAB0077B045 /* AccountSheet.swift in Sources */,
+ 22306A462B8FB173000A8EC1 /* OnboardingQuestionnaireDashboard.swift in Sources */,
653A2551283387FE005D4D48 /* PICS.swift in Sources */,
2FE5DC3629EDD7CA004B9AB4 /* HealthKitPermissions.swift in Sources */,
+ 22306A3E2B8F0097000A8EC1 /* OnboardingSurveyView.swift in Sources */,
8644E6872B7204A7001218D0 /* AppointmentBlock.swift in Sources */,
5661552E2AB854C000209B80 /* PackageHelper.swift in Sources */,
27FA29902A388E9B009CAC45 /* ModalView.swift in Sources */,
diff --git a/PICS/Onboarding/AccountQuestionnaire.swift b/PICS/Onboarding/AccountQuestionnaire.swift
new file mode 100644
index 0000000..389ba1d
--- /dev/null
+++ b/PICS/Onboarding/AccountQuestionnaire.swift
@@ -0,0 +1,73 @@
+//
+// This source file is part of the PICS based on the Stanford Spezi Template Application project
+//
+// SPDX-FileCopyrightText: 2023 Stanford University
+//
+// SPDX-License-Identifier: MIT
+//
+
+import SpeziHealthKit
+import SpeziOnboarding
+import SwiftUI
+
+
+struct AccountQuestionnaire: View {
+ @Environment(OnboardingNavigationPath.self) private var onboardingNavigationPath
+ @AppStorage("isSurveyCompleted") var isSurveyCompleted = false
+ @State var isSheetPresented = false
+ @State private var showOnboardingQuestionnaire = false
+
+ var body: some View {
+ OnboardingView(
+ contentView: {
+ VStack {
+ OnboardingTitleView(
+ title: "ONBOARDING_TITLE",
+ subtitle: "ONBOARDING_SUBTITLE"
+ )
+ Spacer()
+ Image(systemName: "list.bullet.clipboard.fill")
+ .font(.system(size: 130))
+ .foregroundColor(.accentColor)
+ .accessibilityHidden(true)
+ Text("ONBOARDING_INSTRUCTION")
+ .multilineTextAlignment(.center)
+ .padding(.vertical, 15)
+ Spacer()
+ }
+ }, actionView: {
+ VStack {
+ OnboardingActionsView(
+ "Take Questionnaire",
+ action: {
+ isSheetPresented = true
+ }
+ )
+ .padding(.vertical, 16)
+ OnboardingActionsView(
+ "Skip",
+ action: {
+ onboardingNavigationPath.nextStep()
+ }
+ )
+ .sheet(isPresented: $isSheetPresented) {
+ OnboardingQuestionnaire(isSheetPresented: $isSheetPresented)
+ }
+ }
+ }
+ )
+ // .navigationBarBackButtonHidden(healthKitProcessing)
+ // Small fix as otherwise "Login" or "Sign up" is still shown in the nav bar
+ .navigationTitle(Text(verbatim: ""))
+ }
+}
+
+
+#if DEBUG
+#Preview {
+ OnboardingStack {
+ AccountQuestionnaire()
+ }
+ .previewWith(standard: PICSStandard()) {}
+}
+#endif
diff --git a/PICS/Onboarding/OnboardingFlow.swift b/PICS/Onboarding/OnboardingFlow.swift
index 4eea7ab..fe59fa6 100644
--- a/PICS/Onboarding/OnboardingFlow.swift
+++ b/PICS/Onboarding/OnboardingFlow.swift
@@ -38,7 +38,7 @@ struct OnboardingFlow: View {
if !FeatureFlags.disableFirebase {
AccountOnboarding()
}
- OnboardingQuestionnaire()
+ AccountQuestionnaire()
#if !(targetEnvironment(simulator) && (arch(i386) || arch(x86_64)))
Consent()
#endif
diff --git a/PICS/Onboarding/Onboarding_Questionnaire.swift b/PICS/Onboarding/OnboardingQuestionnaire.swift
similarity index 60%
rename from PICS/Onboarding/Onboarding_Questionnaire.swift
rename to PICS/Onboarding/OnboardingQuestionnaire.swift
index 4fe1232..8b29337 100644
--- a/PICS/Onboarding/Onboarding_Questionnaire.swift
+++ b/PICS/Onboarding/OnboardingQuestionnaire.swift
@@ -10,21 +10,30 @@ import SpeziQuestionnaire
import SwiftUI
struct OnboardingQuestionnaire: View {
@Environment(OnboardingNavigationPath.self) private var onboardingNavigationPath
+ @Environment(PICSStandard.self) private var standard
+ @AppStorage("isSurveyCompleted") var isSurveyCompleted = false
+ @Binding var isSheetPresented: Bool
+
var body: some View {
QuestionnaireView(
questionnaire: Bundle.main.questionnaire(withName: "Onboarding-Questionnaire")
) { result in
guard case let .completed(response) = result else {
+ isSheetPresented = false
+ onboardingNavigationPath.nextStep()
return // user cancelled
}
+ isSurveyCompleted = true
+ isSheetPresented = false
+ await standard.add(response: response)
onboardingNavigationPath.nextStep()
- // ... save the FHIR response to your data store
}
}
}
#Preview {
OnboardingStack {
- OnboardingQuestionnaire()
+ OnboardingQuestionnaire(isSheetPresented: .constant(true))
}
+ .previewWith(standard: PICSStandard()) {}
}
diff --git a/PICS/Resources/Localizable.xcstrings b/PICS/Resources/Localizable.xcstrings
index a39bcc9..e85e21e 100644
--- a/PICS/Resources/Localizable.xcstrings
+++ b/PICS/Resources/Localizable.xcstrings
@@ -12,39 +12,6 @@
},
"%lld kg" : {
- },
- "ASSESSMENT_TM_START_BTN" : {
- "extractionState" : "manual",
- "localizations" : {
- "en" : {
- "stringUnit" : {
- "state" : "translated",
- "value" : "Start Trail Making Assessment"
- }
- }
- }
- },
- "ASSESSMENTS_NAVIGATION_TITLE" : {
- "extractionState" : "manual",
- "localizations" : {
- "en" : {
- "stringUnit" : {
- "state" : "translated",
- "value" : "Assessments"
- }
- }
- }
- },
- "ASSESSMENTS_TAB_TITLE" : {
- "extractionState" : "manual",
- "localizations" : {
- "en" : {
- "stringUnit" : {
- "state" : "translated",
- "value" : "Assessments"
- }
- }
- }
},
"ACCOUNT_NEXT" : {
"localizations" : {
@@ -207,6 +174,39 @@
}
}
},
+ "ASSESSMENT_TM_START_BTN" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "Start Trail Making Assessment"
+ }
+ }
+ }
+ },
+ "ASSESSMENTS_NAVIGATION_TITLE" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "Assessments"
+ }
+ }
+ }
+ },
+ "ASSESSMENTS_TAB_TITLE" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "Assessments"
+ }
+ }
+ }
+ },
"CLOSE" : {
"comment" : "MARK: General",
"localizations" : {
@@ -636,6 +636,9 @@
}
}
},
+ "Key" : {
+ "extractionState" : "manual"
+ },
"LELAND_STANFORD_BIO" : {
"extractionState" : "stale",
"localizations" : {
@@ -701,13 +704,66 @@
}
}
},
- "ONBOARDING_QUESTIONNAIRE" : {
+ "Now" : {
+
+ },
+ "Onboarding Questionnaire" : {
+
+ },
+ "Onboarding Task" : {
+
+ },
+ "ONBOARDING_CAPTION" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
- "value" : "Static information on basic profile info"
+ "value" : "Please complete the Onboarding questionnaire before your first appointment."
+ }
+ }
+ }
+ },
+ "ONBOARDING_DESCRIPTION" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "Please fill out the Onboarding Questionnaire to collect some basic information before your first appointment."
+ }
+ }
+ }
+ },
+ "ONBOARDING_INSTRUCTION" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "You may skip this step during the onboarding and fill it out before your first appointment."
+ }
+ }
+ }
+ },
+ "ONBOARDING_SUBTITLE" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "Please fill out this onboarding survey to collect your basic information."
+ }
+ }
+ }
+ },
+ "ONBOARDING_TITLE" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "Onboarding Questionnaire"
}
}
}
@@ -807,6 +863,12 @@
}
}
}
+ },
+ "Skip" : {
+
+ },
+ "Start Questionnaire" : {
+
},
"STREET_ADDRESS" : {
"extractionState" : "manual",
@@ -818,6 +880,9 @@
}
}
}
+ },
+ "Take Questionnaire" : {
+
},
"TASK_CONTEXT_ACTION_QUESTIONNAIRE" : {
"localizations" : {
@@ -1050,4 +1115,4 @@
}
},
"version" : "1.0"
-}
+}
\ No newline at end of file
diff --git a/PICS/Resources/Onboarding-Questionnaire.json b/PICS/Resources/Onboarding-Questionnaire.json
index 302c689..da1ff96 100644
--- a/PICS/Resources/Onboarding-Questionnaire.json
+++ b/PICS/Resources/Onboarding-Questionnaire.json
@@ -1 +1 @@
-{"title":"Onboarding Survey","resourceType":"Questionnaire","language":"en-US","status":"draft","publisher":"Stanford Biodesign Digital Health","meta":{"profile":["http://spezi.health/fhir/StructureDefinition/sdf-Questionnaire"],"tag":[{"system":"urn:ietf:bcp:47","code":"en-US","display":"English"}]},"useContext":[{"code":{"system":"http://hl7.org/fhir/ValueSet/usage-context-type","code":"focus","display":"Clinical Focus"},"valueCodeableConcept":{"coding":[{"system":"urn:oid:2.16.578.1.12.4.1.1.8655","display":"Onboarding Survey"}]}}],"contact":[{"name":"http://spezi.health"}],"subjectType":["Patient"],"url":"http://spezi.health/fhir/questionnaire/2623b4a2-6244-4846-b23e-5262a8878b68","item":[{"linkId":"b84fded4-3be9-4e5a-8f66-1b58806765cb","type":"display","text":"In order to better assess your current physical and psychological well-being, we need to collect some basic information in different areas.","required":false},{"linkId":"10c9f106-f55e-4794-8a6f-8c19f275dfa0","type":"choice","required":true,"answerOption":[{"valueCoding":{"id":"eab8aeb9-62a2-4328-8186-556a49f9d08d","code":"male","system":"urn:uuid:ffce077a-a871-4c9e-823e-b0e498b6c75a","display":"Male"}},{"valueCoding":{"id":"6a080723-9de9-46b2-d593-20b4cbf8dcc3","code":"female","system":"urn:uuid:ffce077a-a871-4c9e-823e-b0e498b6c75a","display":"Female"}},{"valueCoding":{"id":"03c39e4e-a678-444c-ea78-b025ad8db13d","code":"other","system":"urn:uuid:ffce077a-a871-4c9e-823e-b0e498b6c75a","display":"Other"}}],"text":"Gender"},{"linkId":"f60517a5-5494-4075-b317-bc5dcec45119","type":"integer","text":"Age","required":true},{"linkId":"c88d0efe-a8d2-4cd1-8d01-858df93acdd5","type":"integer","text":"Height (cm)","required":true},{"linkId":"e6dbcba0-7a71-415b-eb7a-ab3d303557bf","type":"integer","text":"Weight (kg)","required":true},{"linkId":"3d0a62ca-52b4-4e40-8c4e-c335dd8c489d","type":"integer","text":"Need for Care (1-5)","extension":[{"url":"http://hl7.org/fhir/StructureDefinition/maxValue","valueInteger":5},{"url":"http://hl7.org/fhir/StructureDefinition/minValue","valueInteger":-2},{"url":"http://ehelse.no/fhir/StructureDefinition/validationtext","valueString":"Input must be 1-5"}],"required":true},{"linkId":"9657ae60-ab44-46c1-81b2-9caa78dc1cd1","type":"integer","text":"Degree of disability (0-100)","extension":[{"url":"http://hl7.org/fhir/StructureDefinition/minValue","valueInteger":0},{"url":"http://hl7.org/fhir/StructureDefinition/maxValue","valueInteger":100},{"url":"http://ehelse.no/fhir/StructureDefinition/validationtext","valueString":"Input must be 0-100"}],"required":true},{"linkId":"d568aaa5-8cfd-4fef-8e49-3213b053175d","type":"choice","text":"Were you able to return to your original job after the intensive care unit/serious illness?","required":true,"answerOption":[{"valueCoding":{"id":"0ea9166b-4838-4b22-acbe-17a055a95bc4","code":"yes","system":"urn:uuid:b2b6bcfe-a64f-4e3f-8d1c-cb86650e0104","display":"Yes"}},{"valueCoding":{"id":"9852e452-2440-481b-824c-ea599f0d6fb4","code":"no","system":"urn:uuid:b2b6bcfe-a64f-4e3f-8d1c-cb86650e0104","display":"No"}},{"valueCoding":{"id":"2901a9d6-53d6-417a-82bc-568d3be903f1","code":"not-applicable","system":"urn:uuid:b2b6bcfe-a64f-4e3f-8d1c-cb86650e0104","display":"Not Applicable"}},{"valueCoding":{"id":"29d13d61-7bbe-4a48-e0b3-f632f43db033","code":"i-am-retired.","system":"urn:uuid:b2b6bcfe-a64f-4e3f-8d1c-cb86650e0104","display":"I am retired."}}]},{"linkId":"a85e750e-f3dd-4fd0-8b52-409580b7273d","type":"choice","text":"Marital Status","required":true,"answerOption":[{"valueCoding":{"id":"90cbde0b-2376-41d8-8c6d-4a2da252f948","code":"single","system":"urn:uuid:1ec9af15-42ab-4ad7-8446-4ba8a42a42f4","display":"Single"}},{"valueCoding":{"id":"ad32cb57-b1aa-4a9f-8c9f-4d373a86b229","code":"married/partnership","system":"urn:uuid:1ec9af15-42ab-4ad7-8446-4ba8a42a42f4","display":"Married/Partnership"}},{"valueCoding":{"id":"1556fcde-8362-4f18-8720-91d4693e80e9","code":"divorced","system":"urn:uuid:1ec9af15-42ab-4ad7-8446-4ba8a42a42f4","display":"Divorced"}},{"valueCoding":{"id":"4eec350d-20b0-4dda-de3c-3f254a98baa1","code":"widowed","system":"urn:uuid:1ec9af15-42ab-4ad7-8446-4ba8a42a42f4","display":"Widowed"}}]},{"linkId":"078280d9-5b33-4aa6-85f4-b06f8d9fe651","type":"open-choice","text":"Current living situation","required":true,"answerOption":[{"valueCoding":{"id":"5028c5ee-c99d-45af-c752-955399eebe42","code":"living-alone","system":"urn:uuid:13f24035-c3c7-4710-96c0-7fe882ca7950","display":"Living Alone"}},{"valueCoding":{"id":"98f1f387-d4d5-4c60-8c00-a388242ddcd1","code":"living-together-with-partner","system":"urn:uuid:13f24035-c3c7-4710-96c0-7fe882ca7950","display":"Living together with partner"}},{"valueCoding":{"id":"8236a70c-e166-46f8-cc13-e366cc2485e8","code":"living-together-with-children","system":"urn:uuid:13f24035-c3c7-4710-96c0-7fe882ca7950","display":"Living together with children"}},{"valueCoding":{"id":"cb435bad-8b5d-4552-9510-d9a949676d37","code":"living-together-with-parents","system":"urn:uuid:13f24035-c3c7-4710-96c0-7fe882ca7950","display":"Living together with parents"}},{"valueCoding":{"id":"589a0a8c-af84-419d-c777-56db696b3d35","code":"other-","system":"urn:uuid:13f24035-c3c7-4710-96c0-7fe882ca7950","display":"Other "}}]},{"linkId":"e2f115c2-bf0e-4660-da7f-892ce3852bda","type":"choice","text":"What is your highest level of education?","required":true,"answerOption":[{"valueCoding":{"id":"84ca31bd-d484-4951-8084-b854156710de","code":"no-school-certificate","system":"urn:uuid:bc044025-fcd7-492e-8dc9-1b3edb4a7ad8","display":"No school certificate"}},{"valueCoding":{"id":"0923ce87-b37b-4647-d5e6-70cbc128beb9","code":"high-school-diploma","system":"urn:uuid:bc044025-fcd7-492e-8dc9-1b3edb4a7ad8","display":"High school diploma"}},{"valueCoding":{"id":"ca7f6be5-ce9e-4b9a-8b25-a57adf584881","code":"college-degree","system":"urn:uuid:bc044025-fcd7-492e-8dc9-1b3edb4a7ad8","display":"College degree"}},{"valueCoding":{"id":"838e838f-e4ad-4669-8900-18bb69fb1ad1","code":"master-degree","system":"urn:uuid:bc044025-fcd7-492e-8dc9-1b3edb4a7ad8","display":"Master degree"}},{"valueCoding":{"id":"03df41cc-af06-44e7-8215-2b1743777df3","code":"doctorate","system":"urn:uuid:bc044025-fcd7-492e-8dc9-1b3edb4a7ad8","display":"Doctorate"}}]}]}
+{"title":"Onboarding Survey","resourceType":"Questionnaire","language":"en-US","status":"draft","publisher":"Stanford Biodesign Digital Health","meta":{"profile":["http://spezi.health/fhir/StructureDefinition/sdf-Questionnaire"],"tag":[{"system":"urn:ietf:bcp:47","code":"en-US","display":"English"}]},"useContext":[{"code":{"system":"http://hl7.org/fhir/ValueSet/usage-context-type","code":"focus","display":"Clinical Focus"},"valueCodeableConcept":{"coding":[{"system":"urn:oid:2.16.578.1.12.4.1.1.8655","display":"Onboarding Survey"}]}}],"contact":[{"name":"http://spezi.health"}],"subjectType":["Patient"],"url":"http://spezi.health/fhir/questionnaire/4846c2b6-84f5-4154-8e9b-92d3a0ea101d","item":[{"linkId":"57544351-981e-4bc0-8202-81baa7a515cf","type":"display","text":"In order to better assess your current physical and psychological well-being, we need to collect some basic information in different areas. ","required":false},{"linkId":"62233356-ef0d-4e83-b90d-db2d54f75d95","type":"choice","text":"Gender","required":true,"answerOption":[{"valueCoding":{"id":"90e4af7d-fb60-4209-8b98-81b62bdb73f5","code":"male","system":"urn:uuid:f2555f86-0fb2-491b-abb0-2339f8411c5b","display":"Male"}},{"valueCoding":{"id":"c4baf7b8-9690-4b3c-8668-982b90f9220a","code":"female","system":"urn:uuid:f2555f86-0fb2-491b-abb0-2339f8411c5b","display":"Female"}},{"valueCoding":{"id":"e6dd8c90-95f7-4d8a-9503-2a542a159cb9","code":"other","system":"urn:uuid:f2555f86-0fb2-491b-abb0-2339f8411c5b","display":"Other"}}]},{"linkId":"48b5965b-b68e-4266-8e1c-1b7832be2773","type":"integer","text":"Age","required":true},{"linkId":"a6a4321a-609a-41e9-dc59-f81d6772a40a","type":"integer","text":"Height (cm)","required":true},{"linkId":"737e8c57-e3b4-4015-8787-815467cfd886","type":"integer","text":"Weight (kg)","required":true},{"linkId":"275ecc49-06b4-470d-8751-993b7cbb22d1","type":"integer","text":"Need for Care","extension":[{"url":"http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl","valueCodeableConcept":{"coding":[{"system":"http://hl7.org/fhir/questionnaire-item-control","code":"slider","display":"Slider"}]}},{"url":"http://hl7.org/fhir/StructureDefinition/minValue","valueInteger":1},{"url":"http://hl7.org/fhir/StructureDefinition/maxValue","valueInteger":5},{"url":"http://hl7.org/fhir/StructureDefinition/questionnaire-sliderStepValue","valueInteger":1}],"required":true},{"linkId":"a87c831f-c9af-4cf6-8782-009d5d250827","type":"integer","text":"Degree of Disability","extension":[{"url":"http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl","valueCodeableConcept":{"coding":[{"system":"http://hl7.org/fhir/questionnaire-item-control","code":"slider","display":"Slider"}]}},{"url":"http://hl7.org/fhir/StructureDefinition/minValue","valueInteger":0},{"url":"http://hl7.org/fhir/StructureDefinition/maxValue","valueInteger":100},{"url":"http://hl7.org/fhir/StructureDefinition/questionnaire-sliderStepValue","valueInteger":10}],"required":true},{"linkId":"4e05da2e-f11a-4120-9baa-e38039d98f4f","type":"choice","text":"Were you able to return to your original job after the intensive care unit/serious illness?","required":true,"answerOption":[{"valueCoding":{"id":"bf350307-5eda-40b0-8039-b4b347dfcd8d","code":"yes","system":"urn:uuid:2690f1cb-41d4-4c88-bf50-7a9b8edafa01","display":"Yes"}},{"valueCoding":{"id":"947c70c6-c147-437b-f493-ef553c54b866","code":"no","system":"urn:uuid:2690f1cb-41d4-4c88-bf50-7a9b8edafa01","display":"No"}},{"valueCoding":{"id":"ec6e697f-ba69-4ac3-85c5-ec1dbbc115d9","code":"not-applicable","system":"urn:uuid:2690f1cb-41d4-4c88-bf50-7a9b8edafa01","display":"Not Applicable"}},{"valueCoding":{"id":"18ea0b3e-7989-45ef-b4e4-c2351e0c73ed","code":"i-am-retired","system":"urn:uuid:2690f1cb-41d4-4c88-bf50-7a9b8edafa01","display":"I am retired"}}]},{"linkId":"1006500f-6bd3-4077-acf5-1536014cad68","type":"choice","text":"Marital Status","required":true,"answerOption":[{"valueCoding":{"id":"9fdad7db-ac20-451e-890d-d4a5dd14cadf","code":"single","system":"urn:uuid:2a72d108-bcc3-4ce2-89b9-ab7ff6fc8fb5","display":"Single"}},{"valueCoding":{"id":"bd892d60-6445-43f5-d549-fbe38f7e7ec1","code":"married/partnership","system":"urn:uuid:2a72d108-bcc3-4ce2-89b9-ab7ff6fc8fb5","display":"Married/Partnership"}},{"valueCoding":{"id":"0315e5a7-a3f2-46d3-b58e-bb2c5d3959d9","code":"divorced","system":"urn:uuid:2a72d108-bcc3-4ce2-89b9-ab7ff6fc8fb5","display":"Divorced"}},{"valueCoding":{"id":"8d5b1925-610f-4510-eb34-b521f0a6377d","code":"widowed","system":"urn:uuid:2a72d108-bcc3-4ce2-89b9-ab7ff6fc8fb5","display":"Widowed"}}]},{"linkId":"07938c2f-1784-4301-d12b-5fd5a16c1d5d","type":"choice","text":"Current living situation","required":true,"answerOption":[{"valueCoding":{"id":"15a92c88-57af-4c72-8025-4e5373269ea0","code":"living-alone","system":"urn:uuid:cb237cf9-07ed-4518-f53c-b4f695952822","display":"Living alone"}},{"valueCoding":{"id":"5b562b4f-cb92-4e6b-9e23-94bd964dd7fe","code":"living-together-with-partner","system":"urn:uuid:cb237cf9-07ed-4518-f53c-b4f695952822","display":"Living together with partner"}},{"valueCoding":{"id":"891a3878-04fa-421a-8f13-a928fab20a10","code":"living-together-with-children","system":"urn:uuid:cb237cf9-07ed-4518-f53c-b4f695952822","display":"Living together with children"}},{"valueCoding":{"id":"ae1904b0-af98-4d76-861c-f20ad91ef6ab","code":"living-together-with-parents","system":"urn:uuid:cb237cf9-07ed-4518-f53c-b4f695952822","display":"Living together with parents"}},{"valueCoding":{"id":"395e1d34-2ce0-4831-e5fe-2d37068d6dc0","code":"other-","system":"urn:uuid:cb237cf9-07ed-4518-f53c-b4f695952822","display":"Other "}}]},{"linkId":"bc384e95-37e4-45ba-8036-f64542eb6643","type":"choice","text":"What is your highest level of education?","required":true,"answerOption":[{"valueCoding":{"id":"d7127dec-b257-417a-b196-891efe184d5a","code":"no-school-certificate","system":"urn:uuid:309e68e7-bd65-4daa-cd63-c4259de23771","display":"No school certificate"}},{"valueCoding":{"id":"672cbd04-a88a-48eb-9a9c-ee4886d0b7ca","code":"high-school-diploma","system":"urn:uuid:309e68e7-bd65-4daa-cd63-c4259de23771","display":"High school diploma"}},{"valueCoding":{"id":"a331b190-e47c-4d4c-8622-d8f2aa7554d7","code":"college-degree","system":"urn:uuid:309e68e7-bd65-4daa-cd63-c4259de23771","display":"College degree"}},{"valueCoding":{"id":"86551785-fbf8-4a0e-d841-3e035b8309ee","code":"master-degree","system":"urn:uuid:309e68e7-bd65-4daa-cd63-c4259de23771","display":"Master degree"}},{"valueCoding":{"id":"7361aa77-62e4-4b7e-918b-a71e3d8c78f2","code":"doctorate","system":"urn:uuid:309e68e7-bd65-4daa-cd63-c4259de23771","display":"Doctorate"}}]}]}
\ No newline at end of file
diff --git a/PICS/Schedule/OnboardingQuestionnaireDashboard.swift b/PICS/Schedule/OnboardingQuestionnaireDashboard.swift
new file mode 100644
index 0000000..f2d3da8
--- /dev/null
+++ b/PICS/Schedule/OnboardingQuestionnaireDashboard.swift
@@ -0,0 +1,36 @@
+//
+// This source file is part of the PICS based on the Stanford Spezi Template Application project
+//
+// SPDX-FileCopyrightText: 2023 Stanford University
+//
+// SPDX-License-Identifier: MIT
+//
+import SpeziOnboarding
+import SpeziQuestionnaire
+import SwiftUI
+struct OnboardingQuestionnaireDashboard: View {
+ @Environment(PICSStandard.self) private var standard
+ @AppStorage("isSurveyCompleted") var isSurveyCompleted = false
+ @Binding var isSheetPresented: Bool
+
+ var body: some View {
+ QuestionnaireView(
+ questionnaire: Bundle.main.questionnaire(withName: "Onboarding-Questionnaire")
+ ) { result in
+ guard case let .completed(response) = result else {
+ isSheetPresented = false
+ return // user cancelled
+ }
+ isSurveyCompleted = true
+ isSheetPresented = false
+ await standard.add(response: response)
+ }
+ }
+}
+
+#Preview {
+ OnboardingStack {
+ OnboardingQuestionnaireDashboard(isSheetPresented: .constant(true))
+ }
+ .previewWith(standard: PICSStandard()) {}
+}
diff --git a/PICS/Schedule/OnboardingSurveyView.swift b/PICS/Schedule/OnboardingSurveyView.swift
new file mode 100644
index 0000000..c4ee2fe
--- /dev/null
+++ b/PICS/Schedule/OnboardingSurveyView.swift
@@ -0,0 +1,75 @@
+//
+// This source file is part of the PICS based on the Stanford Spezi Template Application project
+//
+// SPDX-FileCopyrightText: 2023 Stanford University
+//
+// SPDX-License-Identifier: MIT
+//
+import SwiftUI
+
+struct OnboardingSurveyView: View {
+ @Environment(PICSStandard.self) private var standard
+ @AppStorage("isSurveyCompleted") var isSurveyCompleted = false
+ @State var isSheetPresented = false
+
+ var body: some View {
+ HStack {
+ onboardingSurveyDetailsStack
+ }
+ .contentShape(Rectangle())
+ }
+
+ private var onboardingSurveyDetailsStack: some View {
+ VStack(alignment: .leading) {
+ HStack(alignment: .top) { // Align items to top
+ statusIcon
+ VStack(alignment: .leading) {
+ Text("Onboarding Questionnaire")
+ .font(.headline)
+ Text("Now")
+ .font(.subheadline)
+ }
+ }
+ Divider()
+ descriptionText
+ actionTypeText
+ }
+ }
+
+ private var statusIcon: some View {
+ Image(systemName: "exclamationmark.circle.fill")
+ .foregroundColor(.yellow)
+ .font(.system(size: 30))
+ .accessibilityHidden(true)
+ }
+
+ private var descriptionText: some View {
+ Text("ONBOARDING_CAPTION")
+ .font(.callout)
+ }
+
+ private var actionTypeText: some View {
+ Button(action: {
+ isSheetPresented = true
+ }) {
+ Text("Start Questionnaire")
+ .frame(maxWidth: .infinity, minHeight: 50)
+ .foregroundColor(.white)
+ .background(Color.accentColor)
+ .clipShape(RoundedRectangle(cornerRadius: 8))
+ .padding(.top, 8)
+ }
+ .sheet(isPresented: $isSheetPresented) {
+ OnboardingQuestionnaireDashboard(isSheetPresented: $isSheetPresented)
+ }
+ }
+}
+
+#if DEBUG
+struct OnboardingSurveyView_Previews: PreviewProvider {
+ static var previews: some View {
+ OnboardingSurveyView()
+ .padding()
+ }
+}
+#endif
diff --git a/PICS/Schedule/ScheduleView.swift b/PICS/Schedule/ScheduleView.swift
index ff88365..ed5f20f 100644
--- a/PICS/Schedule/ScheduleView.swift
+++ b/PICS/Schedule/ScheduleView.swift
@@ -20,42 +20,47 @@ struct ScheduleView: View {
@Binding private var presentingAccount: Bool
-
+ @AppStorage("isSurveyCompleted") var isSurveyCompleted = false
private var startOfDays: [Date] {
Array(eventContextsByDate.keys)
}
-
-
var body: some View {
NavigationStack {
- List(startOfDays, id: \.timeIntervalSinceNow) { startOfDay in
- Section(format(startOfDay: startOfDay)) {
- ForEach(eventContextsByDate[startOfDay] ?? [], id: \.event) { eventContext in
- EventContextView(eventContext: eventContext)
- .onTapGesture {
- if !eventContext.event.complete {
- presentedContext = eventContext
+ List {
+ if !isSurveyCompleted {
+ Section(header: Text("Onboarding Task")) {
+ OnboardingSurveyView()
+ }
+ }
+ ForEach(startOfDays, id: \.timeIntervalSinceNow) { startOfDay in
+ Section(format(startOfDay: startOfDay)) {
+ ForEach(eventContextsByDate[startOfDay] ?? [], id: \.event) { eventContext in
+ EventContextView(eventContext: eventContext)
+ .onTapGesture {
+ if !eventContext.event.complete {
+ presentedContext = eventContext
+ }
}
- }
+ }
}
}
}
- .onChange(of: scheduler) {
- calculateEventContextsByDate()
- }
- .task {
- calculateEventContextsByDate()
- }
- .sheet(item: $presentedContext) { presentedContext in
- destination(withContext: presentedContext)
- }
- .toolbar {
- if AccountButton.shouldDisplay {
- AccountButton(isPresented: $presentingAccount)
- }
+ .onChange(of: scheduler) {
+ calculateEventContextsByDate()
+ }
+ .task {
+ calculateEventContextsByDate()
+ }
+ .sheet(item: $presentedContext) { presentedContext in
+ destination(withContext: presentedContext)
+ }
+ .toolbar {
+ if AccountButton.shouldDisplay {
+ AccountButton(isPresented: $presentingAccount)
}
- .navigationTitle("SCHEDULE_LIST_TITLE")
+ }
+ .navigationTitle("SCHEDULE_LIST_TITLE")
}
}