diff --git a/.gitattributes b/.gitattributes index bd46d170..77c2e811 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,6 +5,3 @@ # # SPDX-License-Identifier: MIT # -*.png filter=lfs diff=lfs merge=lfs -text -*.jpg filter=lfs diff=lfs merge=lfs -text -*.jpeg filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index 1f2ae578..02afef71 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,8 @@ .build/ !PAWS.xcodeproj +project.xcworkspace/ + # IDE related folders .idea diff --git a/PAWS.xcodeproj/project.pbxproj b/PAWS.xcodeproj/project.pbxproj index 698539ba..fec442d7 100644 --- a/PAWS.xcodeproj/project.pbxproj +++ b/PAWS.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 2F36AD24299D93E200B1077C /* NotificationsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F36AD23299D93E200B1077C /* NotificationsTests.swift */; }; + 2F36AD27299D989F00B1077C /* XCTestExtensions in Frameworks */ = {isa = PBXBuildFile; productRef = 2F36AD26299D989F00B1077C /* XCTestExtensions */; }; 2F49B7762980407C00BCB272 /* CardinalKit in Frameworks */ = {isa = PBXBuildFile; productRef = 2F49B7752980407B00BCB272 /* CardinalKit */; }; 2F49B7782980407C00BCB272 /* FHIR in Frameworks */ = {isa = PBXBuildFile; productRef = 2F49B7772980407C00BCB272 /* FHIR */; }; 2F49B77A2980407C00BCB272 /* HealthKitDataSource in Frameworks */ = {isa = PBXBuildFile; productRef = 2F49B7792980407C00BCB272 /* HealthKitDataSource */; }; @@ -18,21 +20,20 @@ 2F4E237E2989A2FE0013F3D9 /* OnboardingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F4E237D2989A2FE0013F3D9 /* OnboardingTests.swift */; }; 2F4E23812989C5930013F3D9 /* XCTHealthKit in Frameworks */ = {isa = PBXBuildFile; productRef = 2F4E23802989C5930013F3D9 /* XCTHealthKit */; }; 2F4E23832989D51F0013F3D9 /* PAWSAppTestingSetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F4E23822989D51F0013F3D9 /* PAWSAppTestingSetup.swift */; }; - 2F4E23852989D9130013F3D9 /* XCUIApplication+DeleteAndLaunch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F4E23842989D9130013F3D9 /* XCUIApplication+DeleteAndLaunch.swift */; }; 2F4E23872989DB360013F3D9 /* ContactsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F4E23862989DB360013F3D9 /* ContactsTests.swift */; }; 2F4E23892989DB400013F3D9 /* HealthKitUploadTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F4E23882989DB400013F3D9 /* HealthKitUploadTests.swift */; }; 2F59B93D298C628800C5107F /* PAWSContacts in Frameworks */ = {isa = PBXBuildFile; productRef = 2F59B93C298C628800C5107F /* PAWSContacts */; }; 2F59B93F298C628800C5107F /* PAWSMockDataStorageProvider in Frameworks */ = {isa = PBXBuildFile; productRef = 2F59B93E298C628800C5107F /* PAWSMockDataStorageProvider */; }; 2F59B941298C628800C5107F /* PAWSOnboardingFlow in Frameworks */ = {isa = PBXBuildFile; productRef = 2F59B940298C628800C5107F /* PAWSOnboardingFlow */; }; - 2F59B943298C628800C5107F /* PAWSSchedule in Frameworks */ = {isa = PBXBuildFile; productRef = 2F59B942298C628800C5107F /* PAWSSchedule */; }; 2F59B945298C628800C5107F /* PAWSSharedContext in Frameworks */ = {isa = PBXBuildFile; productRef = 2F59B944298C628800C5107F /* PAWSSharedContext */; }; 2F5E32BD297E05EA003432F8 /* PAWSAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F5E32BC297E05EA003432F8 /* PAWSAppDelegate.swift */; }; 2FC9759F2978E39600BA99FE /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2FC9759E2978E39600BA99FE /* Localizable.strings */; }; 2FC975A82978F11A00BA99FE /* Home.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FC975A72978F11A00BA99FE /* Home.swift */; }; + 3637947E2992F3B000B3C006 /* PAWSLandingScreen in Frameworks */ = {isa = PBXBuildFile; productRef = 3637947D2992F3B000B3C006 /* PAWSLandingScreen */; }; + 36379481299308AA00B3C006 /* PAWSNotificationScreen in Frameworks */ = {isa = PBXBuildFile; productRef = 36379480299308AA00B3C006 /* PAWSNotificationScreen */; }; 653A2551283387FE005D4D48 /* PAWS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653A2550283387FE005D4D48 /* PAWS.swift */; }; 653A255528338800005D4D48 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 653A255428338800005D4D48 /* Assets.xcassets */; }; 653A256228338800005D4D48 /* PAWSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653A256128338800005D4D48 /* PAWSTests.swift */; }; - 653A256C28338800005D4D48 /* SchedulerAndQuestionnaireTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653A256B28338800005D4D48 /* SchedulerAndQuestionnaireTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -53,10 +54,10 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 2F36AD23299D93E200B1077C /* NotificationsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsTests.swift; sourceTree = ""; }; 2F49B77329803E8F00BCB272 /* PAWSModules */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = PAWSModules; sourceTree = ""; }; 2F4E237D2989A2FE0013F3D9 /* OnboardingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingTests.swift; sourceTree = ""; }; 2F4E23822989D51F0013F3D9 /* PAWSAppTestingSetup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PAWSAppTestingSetup.swift; sourceTree = ""; }; - 2F4E23842989D9130013F3D9 /* XCUIApplication+DeleteAndLaunch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCUIApplication+DeleteAndLaunch.swift"; sourceTree = ""; }; 2F4E23862989DB360013F3D9 /* ContactsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsTests.swift; sourceTree = ""; }; 2F4E23882989DB400013F3D9 /* HealthKitUploadTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HealthKitUploadTests.swift; sourceTree = ""; }; 2F5E32BC297E05EA003432F8 /* PAWSAppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PAWSAppDelegate.swift; sourceTree = ""; }; @@ -70,7 +71,6 @@ 653A255D28338800005D4D48 /* PAWSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PAWSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 653A256128338800005D4D48 /* PAWSTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PAWSTests.swift; sourceTree = ""; }; 653A256728338800005D4D48 /* PAWSUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PAWSUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 653A256B28338800005D4D48 /* SchedulerAndQuestionnaireTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SchedulerAndQuestionnaireTests.swift; sourceTree = ""; }; 653A258928339462005D4D48 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ @@ -79,16 +79,17 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 36379481299308AA00B3C006 /* PAWSNotificationScreen in Frameworks */, 2F59B941298C628800C5107F /* PAWSOnboardingFlow in Frameworks */, 2F49B7822980419C00BCB272 /* Questionnaires in Frameworks */, 2F49B77E2980407C00BCB272 /* Scheduler in Frameworks */, + 3637947E2992F3B000B3C006 /* PAWSLandingScreen in Frameworks */, 2F59B93F298C628800C5107F /* PAWSMockDataStorageProvider in Frameworks */, 2F49B77A2980407C00BCB272 /* HealthKitDataSource in Frameworks */, 2F59B945298C628800C5107F /* PAWSSharedContext in Frameworks */, 2F49B784298041F300BCB272 /* Contact in Frameworks */, 2F49B7782980407C00BCB272 /* FHIR in Frameworks */, 2F49B7802980418400BCB272 /* Onboarding in Frameworks */, - 2F59B943298C628800C5107F /* PAWSSchedule in Frameworks */, 2F49B7762980407C00BCB272 /* CardinalKit in Frameworks */, 2F59B93D298C628800C5107F /* PAWSContacts in Frameworks */, 2F49B77C2980407C00BCB272 /* HealthKitToFHIRAdapter in Frameworks */, @@ -107,20 +108,13 @@ buildActionMask = 2147483647; files = ( 2F4E23812989C5930013F3D9 /* XCTHealthKit in Frameworks */, + 2F36AD27299D989F00B1077C /* XCTestExtensions in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 2F4E238A2989DB470013F3D9 /* Helper Extensions */ = { - isa = PBXGroup; - children = ( - 2F4E23842989D9130013F3D9 /* XCUIApplication+DeleteAndLaunch.swift */, - ); - path = "Helper Extensions"; - sourceTree = ""; - }; 2FC9759D2978E30800BA99FE /* Supporting Files */ = { isa = PBXGroup; children = ( @@ -178,10 +172,9 @@ 653A256A28338800005D4D48 /* PAWSUITests */ = { isa = PBXGroup; children = ( - 2F4E238A2989DB470013F3D9 /* Helper Extensions */, 2F4E237D2989A2FE0013F3D9 /* OnboardingTests.swift */, - 653A256B28338800005D4D48 /* SchedulerAndQuestionnaireTests.swift */, 2F4E23862989DB360013F3D9 /* ContactsTests.swift */, + 2F36AD23299D93E200B1077C /* NotificationsTests.swift */, 2F4E23882989DB400013F3D9 /* HealthKitUploadTests.swift */, ); path = PAWSUITests; @@ -201,6 +194,7 @@ isa = PBXNativeTarget; buildConfigurationList = 653A257128338800005D4D48 /* Build configuration list for PBXNativeTarget "PAWS" */; buildPhases = ( + 36BB4944299C7C00005071A3 /* ShellScript */, 653A2549283387FE005D4D48 /* Sources */, 653A254A283387FE005D4D48 /* Frameworks */, 653A254B283387FE005D4D48 /* Resources */, @@ -222,8 +216,9 @@ 2F59B93C298C628800C5107F /* PAWSContacts */, 2F59B93E298C628800C5107F /* PAWSMockDataStorageProvider */, 2F59B940298C628800C5107F /* PAWSOnboardingFlow */, - 2F59B942298C628800C5107F /* PAWSSchedule */, 2F59B944298C628800C5107F /* PAWSSharedContext */, + 3637947D2992F3B000B3C006 /* PAWSLandingScreen */, + 36379480299308AA00B3C006 /* PAWSNotificationScreen */, ); productName = TemplateApplication; productReference = 653A254D283387FE005D4D48 /* PAWS.app */; @@ -263,6 +258,7 @@ name = PAWSUITests; packageProductDependencies = ( 2F4E23802989C5930013F3D9 /* XCTHealthKit */, + 2F36AD26299D989F00B1077C /* XCTestExtensions */, ); productName = TemplateApplicationUITests; productReference = 653A256728338800005D4D48 /* PAWSUITests.xctest */; @@ -303,6 +299,7 @@ packageReferences = ( 2F49B7742980407B00BCB272 /* XCRemoteSwiftPackageReference "CardinalKit" */, 2F4E237F2989C5930013F3D9 /* XCRemoteSwiftPackageReference "XCTHealthKit" */, + 2F36AD25299D989F00B1077C /* XCRemoteSwiftPackageReference "XCTestExtensions" */, ); productRefGroup = 653A254E283387FE005D4D48 /* Products */; projectDirPath = ""; @@ -341,6 +338,26 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 36BB4944299C7C00005071A3 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\nexport PATH=\"$PATH:/opt/homebrew/bin\"\nif which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"swiftlint is not installed\"\nfi\n"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 653A2549283387FE005D4D48 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -366,10 +383,9 @@ buildActionMask = 2147483647; files = ( 2F4E23872989DB360013F3D9 /* ContactsTests.swift in Sources */, + 2F36AD24299D93E200B1077C /* NotificationsTests.swift in Sources */, 2F4E23892989DB400013F3D9 /* HealthKitUploadTests.swift in Sources */, 2F4E237E2989A2FE0013F3D9 /* OnboardingTests.swift in Sources */, - 2F4E23852989D9130013F3D9 /* XCUIApplication+DeleteAndLaunch.swift in Sources */, - 653A256C28338800005D4D48 /* SchedulerAndQuestionnaireTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -519,8 +535,8 @@ INFOPLIST_FILE = "PAWS/Supporting Files/Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = PAWS; INFOPLIST_KEY_NSCameraUsageDescription = "This message should never appear. Please adjust this when you start using camera information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; - INFOPLIST_KEY_NSHealthShareUsageDescription = "The CS342 2023 PAWS Team Application uses the step count to demonstrate CardinalKit's integration with HealthKit."; - INFOPLIST_KEY_NSHealthUpdateUsageDescription = "The CS342 2023 PAWS Team Application uses the step count to demonstrate CardinalKit's integration with HealthKit."; + INFOPLIST_KEY_NSHealthShareUsageDescription = "The PAWS Application uses the heart rate information to extract ECG data and provide it to the researchers. "; + INFOPLIST_KEY_NSHealthUpdateUsageDescription = "The PAWS Application uses the heart rate information to extract ECG data and provide it to the researchers. "; INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "This message should never appear. Please adjust this when you start using location information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "This message should never appear. Please adjust this when you start using location information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; INFOPLIST_KEY_NSMicrophoneUsageDescription = "This message should never appear. Please adjust this when you start using microphone information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; @@ -566,8 +582,8 @@ INFOPLIST_FILE = "PAWS/Supporting Files/Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = PAWS; INFOPLIST_KEY_NSCameraUsageDescription = "This message should never appear. Please adjust this when you start using camera information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; - INFOPLIST_KEY_NSHealthShareUsageDescription = "The CS342 2023 PAWS Team Application uses the step count to demonstrate CardinalKit's integration with HealthKit."; - INFOPLIST_KEY_NSHealthUpdateUsageDescription = "The CS342 2023 PAWS Team Application uses the step count to demonstrate CardinalKit's integration with HealthKit."; + INFOPLIST_KEY_NSHealthShareUsageDescription = "The PAWS Application uses the heart rate information to extract ECG data and provide it to the researchers. "; + INFOPLIST_KEY_NSHealthUpdateUsageDescription = "The PAWS Application uses the heart rate information to extract ECG data and provide it to the researchers. "; INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "This message should never appear. Please adjust this when you start using location information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "This message should never appear. Please adjust this when you start using location information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; INFOPLIST_KEY_NSMicrophoneUsageDescription = "This message should never appear. Please adjust this when you start using microphone information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; @@ -717,12 +733,20 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ + 2F36AD25299D989F00B1077C /* XCRemoteSwiftPackageReference "XCTestExtensions" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/StanfordBDHG/XCTestExtensions"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 0.3.0; + }; + }; 2F49B7742980407B00BCB272 /* XCRemoteSwiftPackageReference "CardinalKit" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/StanfordBDHG/CardinalKit"; requirement = { kind = upToNextMinorVersion; - minimumVersion = 0.2.1; + minimumVersion = 0.3.0; }; }; 2F4E237F2989C5930013F3D9 /* XCRemoteSwiftPackageReference "XCTHealthKit" */ = { @@ -730,12 +754,17 @@ repositoryURL = "https://github.com/StanfordBDHG/XCTHealthKit"; requirement = { kind = upToNextMinorVersion; - minimumVersion = 0.1.0; + minimumVersion = 0.3.1; }; }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 2F36AD26299D989F00B1077C /* XCTestExtensions */ = { + isa = XCSwiftPackageProductDependency; + package = 2F36AD25299D989F00B1077C /* XCRemoteSwiftPackageReference "XCTestExtensions" */; + productName = XCTestExtensions; + }; 2F49B7752980407B00BCB272 /* CardinalKit */ = { isa = XCSwiftPackageProductDependency; package = 2F49B7742980407B00BCB272 /* XCRemoteSwiftPackageReference "CardinalKit" */; @@ -793,14 +822,18 @@ isa = XCSwiftPackageProductDependency; productName = PAWSOnboardingFlow; }; - 2F59B942298C628800C5107F /* PAWSSchedule */ = { - isa = XCSwiftPackageProductDependency; - productName = PAWSSchedule; - }; 2F59B944298C628800C5107F /* PAWSSharedContext */ = { isa = XCSwiftPackageProductDependency; productName = PAWSSharedContext; }; + 3637947D2992F3B000B3C006 /* PAWSLandingScreen */ = { + isa = XCSwiftPackageProductDependency; + productName = PAWSLandingScreen; + }; + 36379480299308AA00B3C006 /* PAWSNotificationScreen */ = { + isa = XCSwiftPackageProductDependency; + productName = PAWSNotificationScreen; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 653A2545283387FE005D4D48 /* Project object */; diff --git a/PAWS.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/PAWS.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a6..00000000 --- a/PAWS.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/PAWS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PAWS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/PAWS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/PAWS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist.license b/PAWS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist.license deleted file mode 100644 index 9137ea9d..00000000 --- a/PAWS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist.license +++ /dev/null @@ -1,6 +0,0 @@ - -This source file is part of the CS342 2023 PAWS Team Application project - -SPDX-FileCopyrightText: 2023 Stanford University - -SPDX-License-Identifier: MIT diff --git a/PAWS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/PAWS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index bd533903..00000000 --- a/PAWS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,167 +0,0 @@ -{ - "pins" : [ - { - "identity" : "abseil-cpp-swiftpm", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/abseil-cpp-SwiftPM.git", - "state" : { - "revision" : "583de9bd60f66b40e78d08599cc92036c2e7e4e1", - "version" : "0.20220203.2" - } - }, - { - "identity" : "boringssl-swiftpm", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/boringssl-SwiftPM.git", - "state" : { - "revision" : "dd3eda2b05a3f459fc3073695ad1b28659066eab", - "version" : "0.9.1" - } - }, - { - "identity" : "cardinalkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/CardinalKit", - "state" : { - "revision" : "7d3d58de00779234bb01bebe6229a76f942b2b8e", - "version" : "0.2.1" - } - }, - { - "identity" : "fhirmodels", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/FHIRModels", - "state" : { - "revision" : "e115442fb3c5d44ffb1dc9b4e039b77fd143ad96", - "version" : "0.4.0" - } - }, - { - "identity" : "firebase-ios-sdk", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/firebase-ios-sdk", - "state" : { - "revision" : "0df86ea17d5d281415be74f2290df8431644f156", - "version" : "10.4.0" - } - }, - { - "identity" : "googleappmeasurement", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleAppMeasurement.git", - "state" : { - "revision" : "9a09ece724128e8d1e14c5133b87c0e236844ac0", - "version" : "10.4.0" - } - }, - { - "identity" : "googledatatransport", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleDataTransport.git", - "state" : { - "revision" : "f6b558e3f801f2cac336b04f615ce111fa9ddaa0", - "version" : "9.2.1" - } - }, - { - "identity" : "googleutilities", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleUtilities.git", - "state" : { - "revision" : "0543562f85620b5b7c510c6bcbef75b562a5127b", - "version" : "7.11.0" - } - }, - { - "identity" : "grpc-ios", - "kind" : "remoteSourceControl", - "location" : "https://github.com/grpc/grpc-ios.git", - "state" : { - "revision" : "8440b914756e0d26d4f4d054a1c1581daedfc5b6", - "version" : "1.44.3-grpc" - } - }, - { - "identity" : "gtm-session-fetcher", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/gtm-session-fetcher.git", - "state" : { - "revision" : "96d7cc73a71ce950723aa3c50ce4fb275ae180b8", - "version" : "3.1.0" - } - }, - { - "identity" : "healthkitonfhir", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/HealthKitOnFHIR", - "state" : { - "revision" : "1b7b7d71c30563f84d4c892421caf7f1c79ff09e", - "version" : "0.2.2" - } - }, - { - "identity" : "leveldb", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/leveldb.git", - "state" : { - "revision" : "0706abcc6b0bd9cedfbb015ba840e4a780b5159b", - "version" : "1.22.2" - } - }, - { - "identity" : "nanopb", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/nanopb.git", - "state" : { - "revision" : "819d0a2173aff699fb8c364b6fb906f7cdb1a692", - "version" : "2.30909.0" - } - }, - { - "identity" : "promises", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/promises.git", - "state" : { - "revision" : "3e4e743631e86c8c70dbc6efdc7beaa6e90fd3bb", - "version" : "2.1.1" - } - }, - { - "identity" : "researchkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/ResearchKit.git", - "state" : { - "revision" : "52a9bd8bcf2112b2f70479cd192f8c5fa9850c31", - "version" : "2.2.8" - } - }, - { - "identity" : "researchkitonfhir", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/ResearchKitOnFHIR", - "state" : { - "revision" : "efb23f31a79a0b914af6a4a3c90ef2608c95bfeb", - "version" : "0.1.5" - } - }, - { - "identity" : "swift-protobuf", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-protobuf.git", - "state" : { - "revision" : "ab3a58b7209a17d781c0d1dbb3e1ff3da306bae8", - "version" : "1.20.3" - } - }, - { - "identity" : "xcthealthkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/XCTHealthKit", - "state" : { - "revision" : "1291d29d19adb16b2301d22d1ec1bfc54819ac99", - "version" : "0.1.0" - } - } - ], - "version" : 2 -} diff --git a/PAWS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved.license b/PAWS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved.license deleted file mode 100644 index 9137ea9d..00000000 --- a/PAWS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved.license +++ /dev/null @@ -1,6 +0,0 @@ - -This source file is part of the CS342 2023 PAWS Team Application project - -SPDX-FileCopyrightText: 2023 Stanford University - -SPDX-License-Identifier: MIT diff --git a/PAWS.xcodeproj/xcshareddata/xcschemes/PAWS.xcscheme b/PAWS.xcodeproj/xcshareddata/xcschemes/PAWS.xcscheme index 7ee5ecda..c6a10ccc 100644 --- a/PAWS.xcodeproj/xcshareddata/xcschemes/PAWS.xcscheme +++ b/PAWS.xcodeproj/xcshareddata/xcschemes/PAWS.xcscheme @@ -76,6 +76,12 @@ ReferencedContainer = "container:PAWS.xcodeproj"> + + + + { + Binding( + get: { + !completedOnboardingFlow && pressedStart + }, set: { _ in } + ) + } var body: some Scene { WindowGroup { - HomeView() - .sheet(isPresented: !$completedOnboardingFlow) { + Group { + if completedOnboardingFlow { + HomeView() + } else { + LandingScreen(pressedStart: $pressedStart) + } + } + .sheet(isPresented: isSheetPresented) { OnboardingFlow() + .interactiveDismissDisabled(true) } .testingSetup() .cardinalKit(appDelegate) diff --git a/PAWS/PAWSAppDelegate.swift b/PAWS/PAWSAppDelegate.swift index 03d4ab6c..1106fe58 100644 --- a/PAWS/PAWSAppDelegate.swift +++ b/PAWS/PAWSAppDelegate.swift @@ -12,7 +12,6 @@ import HealthKit import HealthKitDataSource import HealthKitToFHIRAdapter import PAWSMockDataStorageProvider -import PAWSSchedule import Questionnaires import Scheduler import SwiftUI @@ -24,7 +23,19 @@ class PAWSAppDelegate: CardinalKitAppDelegate { if HKHealthStore.isHealthDataAvailable() { HealthKit { CollectSample( - HKQuantityType(.stepCount), + HKQuantityType(.heartRate), + deliverySetting: .anchorQuery(.afterAuthorizationAndApplicationWillLaunch) + ) + CollectSample( + HKQuantityType(.heartRateVariabilitySDNN), + deliverySetting: .anchorQuery(.afterAuthorizationAndApplicationWillLaunch) + ) + CollectSample( + HKQuantityType(.restingHeartRate), + deliverySetting: .anchorQuery(.afterAuthorizationAndApplicationWillLaunch) + ) + CollectSample( + HKQuantityType.electrocardiogramType(), deliverySetting: .anchorQuery(.afterAuthorizationAndApplicationWillLaunch) ) } adapter: { @@ -33,7 +44,6 @@ class PAWSAppDelegate: CardinalKitAppDelegate { } QuestionnaireDataSource() MockDataStorageProvider() - PAWSScheduler() } } } diff --git a/PAWS/Supporting Files/Assets.xcassets/AppIcon.appiconset/1024.png b/PAWS/Supporting Files/Assets.xcassets/AppIcon.appiconset/1024.png deleted file mode 100644 index 9dfdcaa1..00000000 --- a/PAWS/Supporting Files/Assets.xcassets/AppIcon.appiconset/1024.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7ceaf68583bb602b55d7fb2018aaa19419755fb47fd958a39233bee70b649d34 -size 122340 diff --git a/PAWS/Supporting Files/Assets.xcassets/AppIcon.appiconset/1024.png.license b/PAWS/Supporting Files/Assets.xcassets/AppIcon.appiconset/1024.png.license deleted file mode 100644 index 9137ea9d..00000000 --- a/PAWS/Supporting Files/Assets.xcassets/AppIcon.appiconset/1024.png.license +++ /dev/null @@ -1,6 +0,0 @@ - -This source file is part of the CS342 2023 PAWS Team Application project - -SPDX-FileCopyrightText: 2023 Stanford University - -SPDX-License-Identifier: MIT diff --git a/PAWS/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json b/PAWS/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json index cff1680b..5bc15b93 100644 --- a/PAWS/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/PAWS/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "1024.png", + "filename" : "paws-logo.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" diff --git a/PAWS/Supporting Files/Assets.xcassets/AppIcon.appiconset/paws-logo.png b/PAWS/Supporting Files/Assets.xcassets/AppIcon.appiconset/paws-logo.png new file mode 100644 index 00000000..b2123dd1 Binary files /dev/null and b/PAWS/Supporting Files/Assets.xcassets/AppIcon.appiconset/paws-logo.png differ diff --git a/PAWS.xcodeproj/project.xcworkspace/contents.xcworkspacedata.license b/PAWS/Supporting Files/Assets.xcassets/AppIcon.appiconset/paws-logo.png.license similarity index 100% rename from PAWS.xcodeproj/project.xcworkspace/contents.xcworkspacedata.license rename to PAWS/Supporting Files/Assets.xcassets/AppIcon.appiconset/paws-logo.png.license diff --git a/PAWS/Supporting Files/Localizable.strings b/PAWS/Supporting Files/Localizable.strings index bda6c5bc..fd4d87b4 100644 --- a/PAWS/Supporting Files/Localizable.strings +++ b/PAWS/Supporting Files/Localizable.strings @@ -7,6 +7,9 @@ // +// MARK: - Notifications +"NOTIFICATIONS_TAB_TITLE" = "Notifications"; + // MARK: - Contacts "CONTACTS_TAB_TITLE" = "Contacts"; diff --git a/PAWSModules/Package.swift b/PAWSModules/Package.swift index f60809c4..49ff460c 100644 --- a/PAWSModules/Package.swift +++ b/PAWSModules/Package.swift @@ -21,11 +21,12 @@ let package = Package( .library(name: "PAWSContacts", targets: ["PAWSContacts"]), .library(name: "PAWSMockDataStorageProvider", targets: ["PAWSMockDataStorageProvider"]), .library(name: "PAWSOnboardingFlow", targets: ["PAWSOnboardingFlow"]), - .library(name: "PAWSSchedule", targets: ["PAWSSchedule"]), - .library(name: "PAWSSharedContext", targets: ["PAWSSharedContext"]) + .library(name: "PAWSSharedContext", targets: ["PAWSSharedContext"]), + .library(name: "PAWSLandingScreen", targets: ["PAWSLandingScreen"]), + .library(name: "PAWSNotificationScreen", targets: ["PAWSNotificationScreen"]) ], dependencies: [ - .package(url: "https://github.com/StanfordBDHG/CardinalKit.git", .upToNextMinor(from: "0.2.1")) + .package(url: "https://github.com/StanfordBDHG/CardinalKit.git", .upToNextMinor(from: "0.3.0")) ], targets: [ .target( @@ -62,17 +63,13 @@ let package = Package( ] ), .target( - name: "PAWSSchedule", - dependencies: [ - .target(name: "PAWSSharedContext"), - .product(name: "FHIR", package: "CardinalKit"), - .product(name: "Questionnaires", package: "CardinalKit"), - .product(name: "Scheduler", package: "CardinalKit") - ] + name: "PAWSSharedContext" + ), + .target( + name: "PAWSLandingScreen" ), .target( - name: "PAWSSharedContext", - dependencies: [] + name: "PAWSNotificationScreen" ) ] ) diff --git a/PAWSModules/Sources/PAWSContacts/Contacts.swift b/PAWSModules/Sources/PAWSContacts/Contacts.swift index c5a5f6dc..32bc324e 100644 --- a/PAWSModules/Sources/PAWSContacts/Contacts.swift +++ b/PAWSModules/Sources/PAWSContacts/Contacts.swift @@ -16,31 +16,60 @@ public struct Contacts: View { let contacts = [ Contact( name: PersonNameComponents( - givenName: "Leland", - familyName: "Stanford" + givenName: "Scott", + familyName: "Ceresnak" ), - image: Image(systemName: "figure.wave.circle"), - title: "University Founder", - description: String(localized: "LELAND_STANFORD_BIO", bundle: .module), + image: Image(systemName: "person.circle"), + title: "Professor of Pediatrics (Cardiology)", + description: String(localized: "SCOTT_CERESNAK_BIO", bundle: .module), organization: "Stanford University", address: { let address = CNMutablePostalAddress() address.country = "USA" address.state = "CA" - address.postalCode = "94305" - address.city = "Stanford" - address.street = "450 Serra Mall" + address.postalCode = "94304" + address.city = "Palo Alto" + address.street = "725 Welch Rd" return address }(), contactOptions: [ - .call("+1 (650) 723-2300"), - .text("+1 (650) 723-2300"), - .email(addresses: ["contact@stanford.edu"]), + .email(addresses: ["ceresnak@stanford.edu"]), ContactOption( image: Image(systemName: "safari.fill"), title: "Website", action: { - if let url = URL(string: "https://stanford.edu") { + if let url = URL(string: "https://profiles.stanford.edu/intranet/scott-ceresnak?tab=bio") { + UIApplication.shared.open(url) + } + } + ) + ] + ), + Contact( + name: PersonNameComponents( + givenName: "Aydin", + familyName: "Zahedivash" + ), + image: Image(systemName: "person.circle"), + title: "Pediatric Stanford Cardiology Fellow", + description: String(localized: "AYDIN_ZAHEDIVASH_BIO", bundle: .module), + organization: "Stanford University", + address: { + let address = CNMutablePostalAddress() + address.country = "USA" + address.state = "CA" + address.postalCode = "94304" + address.city = "Palo Alto" + address.street = "725 Welch Rd" + return address + }(), + contactOptions: [ + .email(addresses: ["aydinz@stanford.edu"]), + ContactOption( + image: Image(systemName: "safari.fill"), + title: "Website", + action: { + if let url = URL(string: "https://profiles.stanford.edu/intranet/scott-ceresnak?tab=bio") { UIApplication.shared.open(url) } } diff --git a/PAWSModules/Sources/PAWSContacts/Resources/en.lproj/Localizable.strings b/PAWSModules/Sources/PAWSContacts/Resources/en.lproj/Localizable.strings index c6153b09..5d4cb079 100644 --- a/PAWSModules/Sources/PAWSContacts/Resources/en.lproj/Localizable.strings +++ b/PAWSModules/Sources/PAWSContacts/Resources/en.lproj/Localizable.strings @@ -8,5 +8,5 @@ // MARK: - Contacts "CONTACTS_NAVIGATION_TITLE" = "Contacts"; -"LELAND_STANFORD_BIO" = "Amasa Leland Stanford (March 9, 1824 – June 21, 1893) was an American industrialist and politician. [...] He and his wife Jane were also the founders of Stanford University, which they named after their late son. -[https://en.wikipedia.org/wiki/Leland_Stanford]"; +"SCOTT_CERESNAK_BIO" = "Dr. Scott R. Ceresnak is a pediatric cardiologist in Walnut Creek, California and is affiliated with multiple hospitals in the area, including California Pacific Medical Center and Stanford Health Care-Stanford Hospital. He received his medical degree from Rutgers Robert Wood Johnson Medical School and has been in practice for more than 20 years."; +"AYDIN_ZAHEDIVASH_BIO" = ""; diff --git a/PAWSModules/Sources/PAWSLandingScreen/Bundle+Image.swift b/PAWSModules/Sources/PAWSLandingScreen/Bundle+Image.swift new file mode 100644 index 00000000..2b20a775 --- /dev/null +++ b/PAWSModules/Sources/PAWSLandingScreen/Bundle+Image.swift @@ -0,0 +1,24 @@ +// +// This source file is part of the CS342 2023 Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + + +extension Bundle { + /// Loads an image from the `Bundle` and returns the content as a SwiftUI `Image`. + /// - Parameter name: The name of the image file. + /// - Returns: SwiftUI `Image` instance loaded from the `Bundle`. + public func image(fromFileNamed name: String, type: String = "jpeg") -> Image { + guard let imagePath = self.path(forResource: name, ofType: type), + let image = UIImage(contentsOfFile: imagePath) else { + return Image(systemName: "person.fill") + } + + return Image(uiImage: image) + } +} diff --git a/PAWSModules/Sources/PAWSLandingScreen/LandingScreen.swift b/PAWSModules/Sources/PAWSLandingScreen/LandingScreen.swift new file mode 100644 index 00000000..8d83667a --- /dev/null +++ b/PAWSModules/Sources/PAWSLandingScreen/LandingScreen.swift @@ -0,0 +1,67 @@ +// +// This source file is part of the CS342 2023 PAWS Team Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + + +public struct LandingScreen: View { + private let backgroundGradient = LinearGradient( + colors: [.red, .pink, .orange, .yellow], + startPoint: .leading, + endPoint: .trailing + ) + @Binding private var launchStatus: Bool + + + public var body: some View { + VStack { + backgroundGradient + .mask( + VStack { + Image(systemName: "pawprint.circle.fill") + .resizable() + .scaledToFill() + .frame(width: 200, height: 200) + .foregroundColor(.red) + Text("PAWS") + .font(.custom("GillSans-Bold", fixedSize: 30)) + Text("The Pediatric Apple Watch Study") + .font(.custom("GillSans", fixedSize: 15)) + .offset(y: 50) + } + ) + Button( + action: { + launchStatus = true + }, label: { + Text("Tap to get started") + .fontWeight(.bold) + .padding() + .foregroundColor(Color.red) + .border(backgroundGradient, width: 3) + .cornerRadius(5) + .offset(y: -30) + } + ) + } + } + + + public init(pressedStart: Binding) { + self._launchStatus = pressedStart + } +} + + +struct LandingScreen_Previews: PreviewProvider { + @State private static var pressedStart = false + + static var previews: some View { + LandingScreen(pressedStart: $pressedStart) + } +} diff --git a/PAWSModules/Sources/PAWSNotificationScreen/Notification.swift b/PAWSModules/Sources/PAWSNotificationScreen/Notification.swift new file mode 100644 index 00000000..f12baefb --- /dev/null +++ b/PAWSModules/Sources/PAWSNotificationScreen/Notification.swift @@ -0,0 +1,61 @@ +// +// This source file is part of the CS342 2023 PAWS Team Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + + +struct Notification: View { + private let backgroundGradient = LinearGradient( + colors: [.red, .pink, .yellow], + startPoint: .leading, + endPoint: .trailing + ) + + + var body: some View { + VStack(alignment: .leading) { + Text("February 8th, 2023") + .font(.title3) + .fontWeight(.bold) + .foregroundColor(.gray) + VStack(alignment: .leading) { + VStack(alignment: .leading, spacing: 8) { + Text("ECG Recording") + .font(.headline) + .padding([.leading, .trailing, .top], 20) + .fontWeight(.bold) + + Text("12:30 PM") + .font(.subheadline) + .padding([.leading, .trailing], 20) + } + + Divider() + HStack { + Text("Recording successfully uploaded") + .font(.callout) + .padding() + Image(systemName: "checkmark.circle.fill") + .foregroundColor(.green) + } + } + .frame(width: 320) + .opacity(0.9) + .border(backgroundGradient, width: 5) + .cornerRadius(10) + .shadow(radius: 10) + } + } +} + + +struct Notification_Previews: PreviewProvider { + static var previews: some View { + Notification() + } +} diff --git a/PAWSModules/Sources/PAWSNotificationScreen/NotificationScreen.swift b/PAWSModules/Sources/PAWSNotificationScreen/NotificationScreen.swift new file mode 100644 index 00000000..310a8802 --- /dev/null +++ b/PAWSModules/Sources/PAWSNotificationScreen/NotificationScreen.swift @@ -0,0 +1,37 @@ +// +// This source file is part of the CS342 2023 PAWS Team Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + + +public struct NotificationScreen: View { + public var body: some View { + ScrollView(.vertical) { + VStack(alignment: .leading) { + Text("Notifications") + .font(.title) + .fontWeight(.bold) + .padding([.top, .bottom], 20) + Notification() + Notification() + Notification() + Notification() + } + } + } + + + public init() {} +} + + +struct NotificationScreen_Previews: PreviewProvider { + static var previews: some View { + NotificationScreen() + } +} diff --git a/PAWSModules/Sources/PAWSOnboardingFlow/Consent.swift b/PAWSModules/Sources/PAWSOnboardingFlow/Consent.swift index e2369171..2e2b5a72 100644 --- a/PAWSModules/Sources/PAWSOnboardingFlow/Consent.swift +++ b/PAWSModules/Sources/PAWSOnboardingFlow/Consent.swift @@ -23,20 +23,30 @@ struct Consent: View { } var body: some View { - ConsentView( - header: { - OnboardingTitleView( - title: "CONSENT_TITLE".moduleLocalized, - subtitle: "CONSENT_SUBTITLE".moduleLocalized - ) - }, - asyncMarkdown: { - consentDocument - }, - action: { - onboardingSteps.append(.healthKitPermissions) - } - ) + VStack { + Image(systemName: "pawprint.circle.fill") + .resizable() + .scaledToFill() + .frame(width: 80, height: 80) + .foregroundColor(.red) + .offset(y: 10) + ConsentView( + header: { + OnboardingTitleView( + title: "CONSENT_TITLE".moduleLocalized, + subtitle: "CONSENT_SUBTITLE".moduleLocalized + ) + }, + + asyncMarkdown: { + consentDocument + }, + action: { + onboardingSteps.append(.healthKitPermissions) + } + ) + .offset(y: -20) + } } diff --git a/PAWSModules/Sources/PAWSOnboardingFlow/HealthKitPermissions.swift b/PAWSModules/Sources/PAWSOnboardingFlow/HealthKitPermissions.swift index 1f914fe0..3ea8e0c7 100644 --- a/PAWSModules/Sources/PAWSOnboardingFlow/HealthKitPermissions.swift +++ b/PAWSModules/Sources/PAWSOnboardingFlow/HealthKitPermissions.swift @@ -22,6 +22,12 @@ struct HealthKitPermissions: View { OnboardingView( contentView: { VStack { + Image(systemName: "pawprint.circle.fill") + .resizable() + .scaledToFill() + .frame(width: 40, height: 40) + .foregroundColor(.red) + .offset(y: 20) OnboardingTitleView( title: "HEALTHKIT_PERMISSIONS_TITLE".moduleLocalized, subtitle: "HEALTHKIT_PERMISSIONS_SUBTITLE".moduleLocalized diff --git a/PAWSModules/Sources/PAWSOnboardingFlow/InterestingModules.swift b/PAWSModules/Sources/PAWSOnboardingFlow/InterestingModules.swift index 292b4c6a..9f25b2c4 100644 --- a/PAWSModules/Sources/PAWSOnboardingFlow/InterestingModules.swift +++ b/PAWSModules/Sources/PAWSOnboardingFlow/InterestingModules.swift @@ -15,37 +15,41 @@ struct InterestingModules: View { var body: some View { - SequentialOnboardingView( - title: "INTERESTING_MODULES_TITLE".moduleLocalized, - subtitle: "INTERESTING_MODULES_SUBTITLE".moduleLocalized, - content: [ - .init( - title: "INTERESTING_MODULES_AREA1_TITLE".moduleLocalized, - description: "INTERESTING_MODULES_AREA1_DESCRIPTION".moduleLocalized - ), - .init( - title: "INTERESTING_MODULES_AREA2_TITLE".moduleLocalized, - description: "INTERESTING_MODULES_AREA2_DESCRIPTION".moduleLocalized - ), - .init( - title: "INTERESTING_MODULES_AREA3_TITLE".moduleLocalized, - description: "INTERESTING_MODULES_AREA3_DESCRIPTION".moduleLocalized - ), - .init( - title: "INTERESTING_MODULES_AREA4_TITLE".moduleLocalized, - description: "INTERESTING_MODULES_AREA4_DESCRIPTION".moduleLocalized - ) - ], - actionText: "INTERESTING_MODULES_BUTTON".moduleLocalized, - action: { - #if targetEnvironment(simulator) && (arch(i386) || arch(x86_64)) - print("PKCanvas view-related views are currently skipped on Intel-based iOS simulators due to a metal bug on the simulator.") - onboardingSteps.append(.healthKitPermissions) - #else - onboardingSteps.append(.consent) - #endif - } - ) + VStack { + Image(systemName: "pawprint.circle.fill") + .resizable() + .scaledToFill() + .frame(width: 40, height: 40) + .foregroundColor(.red) + .offset(y: 20) + SequentialOnboardingView( + title: "INTERESTING_MODULES_TITLE".moduleLocalized, + subtitle: "INTERESTING_MODULES_SUBTITLE".moduleLocalized, + content: [ + .init( + title: "INTERESTING_MODULES_AREA1_TITLE".moduleLocalized, + description: "INTERESTING_MODULES_AREA1_DESCRIPTION".moduleLocalized + ), + .init( + title: "INTERESTING_MODULES_AREA2_TITLE".moduleLocalized, + description: "INTERESTING_MODULES_AREA2_DESCRIPTION".moduleLocalized + ), + .init( + title: "INTERESTING_MODULES_AREA3_TITLE".moduleLocalized, + description: "INTERESTING_MODULES_AREA3_DESCRIPTION".moduleLocalized + ) + ], + actionText: "INTERESTING_MODULES_BUTTON".moduleLocalized, + action: { + #if targetEnvironment(simulator) && (arch(i386) || arch(x86_64)) + print("PKCanvas view-related views are currently skipped on Intel-based iOS simulators due to a metal bug on the simulator.") + onboardingSteps.append(.healthKitPermissions) + #else + onboardingSteps.append(.consent) + #endif + } + ) + } } diff --git a/PAWSModules/Sources/PAWSOnboardingFlow/OnboardingFlow.swift b/PAWSModules/Sources/PAWSOnboardingFlow/OnboardingFlow.swift index 3176c03d..20b89063 100644 --- a/PAWSModules/Sources/PAWSOnboardingFlow/OnboardingFlow.swift +++ b/PAWSModules/Sources/PAWSOnboardingFlow/OnboardingFlow.swift @@ -23,19 +23,27 @@ public struct OnboardingFlow: View { public var body: some View { - NavigationStack(path: $onboardingSteps) { - Welcome(onboardingSteps: $onboardingSteps) - .navigationDestination(for: Step.self) { onboardingStep in - switch onboardingStep { - case .interestingModules: - InterestingModules(onboardingSteps: $onboardingSteps) - case .consent: - Consent(onboardingSteps: $onboardingSteps) - case .healthKitPermissions: - HealthKitPermissions() + VStack { + NavigationStack(path: $onboardingSteps) { + Image(systemName: "pawprint.circle.fill") + .resizable() + .scaledToFill() + .frame(width: 40, height: 40) + .foregroundColor(.red) + .offset(y: 20) + Welcome(onboardingSteps: $onboardingSteps) + .navigationDestination(for: Step.self) { onboardingStep in + switch onboardingStep { + case .interestingModules: + InterestingModules(onboardingSteps: $onboardingSteps) + case .consent: + Consent(onboardingSteps: $onboardingSteps) + case .healthKitPermissions: + HealthKitPermissions() + } } - } - .navigationBarTitleDisplayMode(.inline) + .navigationBarTitleDisplayMode(.inline) + } } } diff --git a/PAWSModules/Sources/PAWSOnboardingFlow/Resources/en.lproj/ConsentDocument.md b/PAWSModules/Sources/PAWSOnboardingFlow/Resources/en.lproj/ConsentDocument.md index e5176ae2..eddfb01c 100644 --- a/PAWSModules/Sources/PAWSOnboardingFlow/Resources/en.lproj/ConsentDocument.md +++ b/PAWSModules/Sources/PAWSOnboardingFlow/Resources/en.lproj/ConsentDocument.md @@ -1 +1,3 @@ -CardinalKit can render consent documents in the markdown format: This is a *markdown* **example**. +As a patient in the **Stanford Pediatric Apple Watch Study**, you are being asked to share your heart data from your Apple Watch with the researchers to help improve diganosis for arrhythmia patients just like you. + +Please provide your name and signature to give consent. If you no longer wish to participate in the study please contact the research investigators. diff --git a/PAWSModules/Sources/PAWSOnboardingFlow/Resources/en.lproj/Localizable.strings b/PAWSModules/Sources/PAWSOnboardingFlow/Resources/en.lproj/Localizable.strings index eae9bf5c..60cde642 100644 --- a/PAWSModules/Sources/PAWSOnboardingFlow/Resources/en.lproj/Localizable.strings +++ b/PAWSModules/Sources/PAWSOnboardingFlow/Resources/en.lproj/Localizable.strings @@ -9,48 +9,51 @@ // MARK: - Onboarding // MARK: Welcome -"WELCOME_TITLE" = "CardinalKit\nPAWS Application"; -"WELCOME_SUBTITLE" = "This application demonstrates several CardinalKit features & modules."; +"WELCOME_TITLE" = "Welcome to PAWS!"; +"WELCOME_SUBTITLE" = "We are excited to have you join the Pediatric Apple Watch Study (PAWS) to improve diagnosis of arrhythmias in patients like you! -"WELCOME_AREA1_TITLE" = "The CardinalKit Framework"; -"WELCOME_AREA1_DESCRIPTION" = "The CardinalKit Framework builds the foundation of this template application."; +On this page, we'll walk through the app's main features. Next, you'll complete important onboarding information to confirm your participation in the study."; -"WELCOME_AREA2_TITLE" = "Swift Package Manager"; -"WELCOME_AREA2_DESCRIPTION" = "CardinalKit uses the Swift Package Manager to import it as a dependency."; +"WELCOME_AREA1_TITLE" = "Home Page"; +"WELCOME_AREA1_DESCRIPTION" = "On this page you'll be able to see your patient information and a summary of the ECG recordings uploaded from your Apple Watch "; -"WELCOME_AREA3_TITLE" = "CardinalKit Modules"; -"WELCOME_AREA3_DESCRIPTION" = "CardinalKit offers several modules including HealthKit integration, questionnaires, and more ..."; +"WELCOME_AREA2_TITLE" = "Notifications Page"; +"WELCOME_AREA2_DESCRIPTION" = "On this page you'll be able to check if an ECG recording from your Apple Watch was successfully uploaded to the research server. "; -"WELCOME_BUTTON" = "Learn More"; +"WELCOME_AREA3_TITLE" = "Study Information"; +"WELCOME_AREA3_DESCRIPTION" = "Learn more about the PAWS study and contact the lead researchers if you have any questions or concerns"; + +"WELCOME_BUTTON" = "Begin onboarding"; // MARK: Interesting Modules -"INTERESTING_MODULES_TITLE" = "Interesting Modules"; -"INTERESTING_MODULES_SUBTITLE" = "Here are a few CardinalKit modules that are interesting to know about ..."; +"INTERESTING_MODULES_TITLE" = "PAWS Onboarding"; +"INTERESTING_MODULES_SUBTITLE" = "You'll need to complete a few more steps +to get started..."; + +"INTERESTING_MODULES_AREA1_TITLE" = "Create an account"; +"INTERESTING_MODULES_AREA1_DESCRIPTION" = "Create an account so researchers can identify you as a patient"; -"INTERESTING_MODULES_AREA1_TITLE" = "Onboarding"; -"INTERESTING_MODULES_AREA1_DESCRIPTION" = "The onboarding module allows you to build an onboarding flow like this one."; +"INTERESTING_MODULES_AREA2_TITLE" = "Consent"; +"INTERESTING_MODULES_AREA2_DESCRIPTION" = "Give researchers consent to use your health data as part of the PAWS study"; -"INTERESTING_MODULES_AREA2_TITLE" = "FHIR"; -"INTERESTING_MODULES_AREA2_DESCRIPTION" = "The FHIR module provides a CardinalKit standard that can be used as a communication standard between modules."; +"INTERESTING_MODULES_AREA3_TITLE" = "Grant access to health data "; +"INTERESTING_MODULES_AREA3_DESCRIPTION" = "Allow the PAWS app to access the health data recorded on your Apple Watch and iPhone"; -"INTERESTING_MODULES_AREA3_TITLE" = "Contact"; -"INTERESTING_MODULES_AREA3_DESCRIPTION" = "The contact module allows you to display contact information in your application."; -"INTERESTING_MODULES_AREA4_TITLE" = "HealthKit Data Source"; -"INTERESTING_MODULES_AREA4_DESCRIPTION" = "The HealthKit data source module allows you to fetch data from HealthKit and e.g. transform it to FHIR resources."; "INTERESTING_MODULES_BUTTON" = "Next"; // MARK: Consent -"CONSENT_TITLE" = "Consent Example"; -"CONSENT_SUBTITLE" = "CardinalKit can collect consent from a user. You can provide the consent document using a markdown file."; +"CONSENT_TITLE" = "Consent Page"; +"CONSENT_SUBTITLE" = ""; "CONSENT_LOADING_ERROR" = "Please include a markdown based document named \"ConsentDocument\" in your module Bundle."; // MARK: HealthKit -"HEALTHKIT_PERMISSIONS_TITLE" = "HealthKit Access"; -"HEALTHKIT_PERMISSIONS_SUBTITLE" = "CardinalKit can access data from HealthKit using the HealthKitDataSource module."; -"HEALTHKIT_PERMISSIONS_DESCRIPTION" = "This onboarding step allows you to customize the onboarding flow to explain how the application uses the HealhtKit data and allows a user to cusomize the selection."; +"HEALTHKIT_PERMISSIONS_TITLE" = "Health Data Access"; +"HEALTHKIT_PERMISSIONS_SUBTITLE" = "PAWS requires access to your Health app data to collect ECG information including date of recording, average bpm, +reported symptoms, and any detected abnormalities. "; +"HEALTHKIT_PERMISSIONS_DESCRIPTION" = "On the next page you will be asked to grant access to the heart data from your Health app."; "HEALTHKIT_PERMISSIONS_BUTTON" = "Grant Access"; diff --git a/PAWSModules/Sources/PAWSOnboardingFlow/Welcome.swift b/PAWSModules/Sources/PAWSOnboardingFlow/Welcome.swift index ca8adba2..b1c5a623 100644 --- a/PAWSModules/Sources/PAWSOnboardingFlow/Welcome.swift +++ b/PAWSModules/Sources/PAWSOnboardingFlow/Welcome.swift @@ -20,12 +20,12 @@ struct Welcome: View { subtitle: "WELCOME_SUBTITLE".moduleLocalized, areas: [ .init( - icon: Image(systemName: "apps.iphone"), + icon: Image(systemName: "house.fill"), title: "WELCOME_AREA1_TITLE".moduleLocalized, description: "WELCOME_AREA1_DESCRIPTION".moduleLocalized ), .init( - icon: Image(systemName: "shippingbox.fill"), + icon: Image(systemName: "bell.badge"), title: "WELCOME_AREA2_TITLE".moduleLocalized, description: "WELCOME_AREA2_DESCRIPTION".moduleLocalized ), diff --git a/PAWSModules/Sources/PAWSSchedule/Bundle+Questionnaire.swift b/PAWSModules/Sources/PAWSSchedule/Bundle+Questionnaire.swift deleted file mode 100644 index 179df363..00000000 --- a/PAWSModules/Sources/PAWSSchedule/Bundle+Questionnaire.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// This source file is part of the CS342 2023 PAWS Team Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import FHIR -import Foundation - - -extension Foundation.Bundle { - func questionnaire(withName name: String) -> Questionnaire { - guard let resourceURL = self.url(forResource: name, withExtension: "json") else { - fatalError("Could not find the questionnaire \"\(name)\".json in Bundle.") - } - - do { - let resourceData = try Data(contentsOf: resourceURL) - return try JSONDecoder().decode(Questionnaire.self, from: resourceData) - } catch { - fatalError("Could not decode the FHIR questionnaire named \"\(name).json\": \(error)") - } - } -} diff --git a/PAWSModules/Sources/PAWSSchedule/EventContext.swift b/PAWSModules/Sources/PAWSSchedule/EventContext.swift deleted file mode 100644 index bfa5e247..00000000 --- a/PAWSModules/Sources/PAWSSchedule/EventContext.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// This source file is part of the CS342 2023 PAWS Team Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import Scheduler - - -struct EventContext: Comparable, Identifiable { - let event: Event - let task: Task - - - var id: Event.ID { - event.id - } - - - static func < (lhs: EventContext, rhs: EventContext) -> Bool { - lhs.event.scheduledAt < rhs.event.scheduledAt - } -} diff --git a/PAWSModules/Sources/PAWSSchedule/EventContextView.swift b/PAWSModules/Sources/PAWSSchedule/EventContextView.swift deleted file mode 100644 index c228fd0e..00000000 --- a/PAWSModules/Sources/PAWSSchedule/EventContextView.swift +++ /dev/null @@ -1,56 +0,0 @@ -// -// This source file is part of the CS342 2023 PAWS Team Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import SwiftUI - - -struct EventContextView: View { - let eventContext: EventContext - - - var body: some View { - HStack { - VStack(alignment: .leading) { - HStack { - if eventContext.event.complete { - Image(systemName: "checkmark.circle.fill") - .foregroundColor(.accentColor) - .font(.system(size: 30)) - } - VStack(alignment: .leading, spacing: 8) { - Text(eventContext.task.title) - .font(.headline) - Text(format(eventDate: eventContext.event.scheduledAt)) - .font(.subheadline) - } - } - Divider() - Text(eventContext.task.description) - .font(.callout) - if !eventContext.event.complete { - Text(eventContext.task.context.actionType) - .frame(maxWidth: .infinity, minHeight: 50) - .foregroundColor(.white) - .background(Color.accentColor) - .clipShape(RoundedRectangle(cornerRadius: 8)) - .padding(.top, 8) - } - } - } - .disabled(eventContext.event.complete) - .contentShape(Rectangle()) - } - - - private func format(eventDate: Date) -> String { - let dateFormatter = DateFormatter() - dateFormatter.dateStyle = .none - dateFormatter.timeStyle = .short - return dateFormatter.string(from: eventDate) - } -} diff --git a/PAWSModules/Sources/PAWSSchedule/PAWSScheduler.swift b/PAWSModules/Sources/PAWSSchedule/PAWSScheduler.swift deleted file mode 100644 index 818a718b..00000000 --- a/PAWSModules/Sources/PAWSSchedule/PAWSScheduler.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// This source file is part of the CS342 2023 PAWS Team Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import FHIR -import Foundation -import Scheduler - - -/// A `Scheduler` using the `FHIR` standard as well as the ``PAWSTaskContext`` to schedule and manage tasks and events in the -/// CardinalKit PAWS Applciation. -public typealias PAWSScheduler = Scheduler - - -extension PAWSScheduler { - /// Creates a default instance of the ``PAWSScheduler`` by scheduling the tasks listed below. - public convenience init() { - self.init( - tasks: [ - Task( - title: String(localized: "TASK_SOCIAL_SUPPORT_QUESTIONNAIRE_TITLE", bundle: .module), - description: String(localized: "TASK_SOCIAL_SUPPORT_QUESTIONNAIRE_DESCRIPTION", bundle: .module), - schedule: Schedule( - start: Calendar.current.startOfDay(for: Date()), - dateComponents: .init(hour: 0, minute: 30), // Every Day at 12:30 AM - end: .numberOfEvents(356) - ), - context: PAWSTaskContext.questionnaire(Bundle.module.questionnaire(withName: "SocialSupportQuestionnaire")) - ) - ] - ) - } -} diff --git a/PAWSModules/Sources/PAWSSchedule/PAWSTaskContext.swift b/PAWSModules/Sources/PAWSSchedule/PAWSTaskContext.swift deleted file mode 100644 index 98ce711d..00000000 --- a/PAWSModules/Sources/PAWSSchedule/PAWSTaskContext.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// This source file is part of the CS342 2023 PAWS Team Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import FHIR - - -/// The context attached to each task in the CS342 2023 PAWS Team Application. -/// -/// We currently only support `Questionnaire`s, more cases can be added in the future. -public enum PAWSTaskContext: Codable, Identifiable { - /// The task schould display a `Questionnaire`. - case questionnaire(Questionnaire) - - - public var id: Questionnaire.ID { - switch self { - case let .questionnaire(questionnaire): - return questionnaire.id - } - } - - var actionType: String { - switch self { - case .questionnaire: - return String(localized: "TASK_CONTEXT_ACTION_QUESTIONNAIRE", bundle: .module) - } - } -} diff --git a/PAWSModules/Sources/PAWSSchedule/Resources/en.lproj/Localizable.strings b/PAWSModules/Sources/PAWSSchedule/Resources/en.lproj/Localizable.strings deleted file mode 100644 index dd3072d8..00000000 --- a/PAWSModules/Sources/PAWSSchedule/Resources/en.lproj/Localizable.strings +++ /dev/null @@ -1,13 +0,0 @@ -// -// This source file is part of the CS342 2023 PAWS Team Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -// MARK: - Schedule -"SCHEDULE_LIST_TITLE" = "Schedule"; -"TASK_SOCIAL_SUPPORT_QUESTIONNAIRE_TITLE" = "Social Support Questionnaire"; -"TASK_SOCIAL_SUPPORT_QUESTIONNAIRE_DESCRIPTION" = "Please fill out the Social Support Questionnaire every day."; -"TASK_CONTEXT_ACTION_QUESTIONNAIRE" = "Start Questionnaire"; diff --git a/PAWSModules/Sources/PAWSSchedule/Resources/en.lproj/SocialSupportQuestionnaire.json b/PAWSModules/Sources/PAWSSchedule/Resources/en.lproj/SocialSupportQuestionnaire.json deleted file mode 100644 index 52ec9593..00000000 --- a/PAWSModules/Sources/PAWSSchedule/Resources/en.lproj/SocialSupportQuestionnaire.json +++ /dev/null @@ -1,365 +0,0 @@ -{ - "title": "Social Support", - "description": "This survey measures tangible social support plus a couple of demographic questions.", - "resourceType": "Questionnaire", - "language": "en-US", - "name": "SocialSupport", - "status": "draft", - "publisher": "RAND Corp", - "meta": { - "profile": [ - "http://cardinalkit.org/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": "Social Support" - } - ] - } - } - ], - "contact": [ - { - "name": "http://cardinalkit.orghttps://www.rand.org/health-care/surveys_tools/mos/social-support/survey-instrument.html" - } - ], - "subjectType": [ - "Patient" - ], - "url": "http://cardinalkit.org/fhir/questionnaire/32f43c8e-93e9-4c70-97a0-e716f8030073", - "id": "socialsupport", - "version": "1", - "date": "2023-01-23T00:00:00-08:00", - "purpose": "The RAND Medical Outcomes Social Support survey is a 4-item questionnaire that measures social support.", - "copyright": "RAND Corp surveys are open-source and free to use.", - "item": [ - { - "linkId": "dcea2683-9815-4505-b240-e75b502b29ef", - "type": "choice", - "text": "How often do you need someone to help you if you were confined to bed?", - "required": false, - "answerOption": [ - { - "valueCoding": { - "id": "3d6fe1b8-c64b-497c-8583-db7ddda9e94e", - "code": "1", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "None of the time" - } - }, - { - "valueCoding": { - "id": "b4081e9d-d0f1-4aea-9a15-eac4a15d1d10", - "code": "2", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "A little of the time" - } - }, - { - "valueCoding": { - "id": "e32f7952-e280-48d7-9746-c13dbb26638f", - "code": "3", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "Some of the time" - } - }, - { - "valueCoding": { - "id": "d2f6172d-9402-4cb3-870a-584a7be3a5d7", - "code": "4", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "Most of the time" - } - }, - { - "valueCoding": { - "id": "ec48001e-f03e-4a14-8a7a-9fcf34fa81d2", - "code": "5", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "All of the time" - } - } - ] - }, - { - "linkId": "ce09d701-7b93-4150-defb-51825e05ade9", - "type": "choice", - "text": "How often do you need someone to take you to the doctor if you needed it?", - "required": false, - "answerOption": [ - { - "valueCoding": { - "id": "3d6fe1b8-c64b-497c-8583-db7ddda9e94e", - "code": "1", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "None of the time" - } - }, - { - "valueCoding": { - "id": "b4081e9d-d0f1-4aea-9a15-eac4a15d1d10", - "code": "2", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "A little of the time" - } - }, - { - "valueCoding": { - "id": "e32f7952-e280-48d7-9746-c13dbb26638f", - "code": "3", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "Some of the time" - } - }, - { - "valueCoding": { - "id": "d2f6172d-9402-4cb3-870a-584a7be3a5d7", - "code": "4", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "Most of the time" - } - }, - { - "valueCoding": { - "id": "ec48001e-f03e-4a14-8a7a-9fcf34fa81d2", - "code": "5", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "All of the time" - } - } - ] - }, - { - "linkId": "58e97564-5f4d-4d4b-86d5-6429cbbc7a8e", - "type": "choice", - "text": "How often do you need someone to prepare your meals if you were unable to do it yourself?", - "required": false, - "answerOption": [ - { - "valueCoding": { - "id": "3d6fe1b8-c64b-497c-8583-db7ddda9e94e", - "code": "1", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "None of the time" - } - }, - { - "valueCoding": { - "id": "b4081e9d-d0f1-4aea-9a15-eac4a15d1d10", - "code": "2", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "A little of the time" - } - }, - { - "valueCoding": { - "id": "e32f7952-e280-48d7-9746-c13dbb26638f", - "code": "3", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "Some of the time" - } - }, - { - "valueCoding": { - "id": "d2f6172d-9402-4cb3-870a-584a7be3a5d7", - "code": "4", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "Most of the time" - } - }, - { - "valueCoding": { - "id": "ec48001e-f03e-4a14-8a7a-9fcf34fa81d2", - "code": "5", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "All of the time" - } - } - ] - }, - { - "linkId": "ad161c49-e8a6-4d31-90e8-02b2887a765f", - "type": "choice", - "text": "How often do you need someone to help with daily chores if you were sick", - "required": false, - "answerOption": [ - { - "valueCoding": { - "id": "3d6fe1b8-c64b-497c-8583-db7ddda9e94e", - "code": "1", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "None of the time" - } - }, - { - "valueCoding": { - "id": "b4081e9d-d0f1-4aea-9a15-eac4a15d1d10", - "code": "2", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "A little of the time" - } - }, - { - "valueCoding": { - "id": "e32f7952-e280-48d7-9746-c13dbb26638f", - "code": "3", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "Some of the time" - } - }, - { - "valueCoding": { - "id": "d2f6172d-9402-4cb3-870a-584a7be3a5d7", - "code": "4", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "Most of the time" - } - }, - { - "valueCoding": { - "id": "ec48001e-f03e-4a14-8a7a-9fcf34fa81d2", - "code": "5", - "system": "urn:uuid:e9ecdd47-2e8b-49b3-8780-9d0769a246aa", - "display": "All of the time" - } - } - ] - }, - { - "linkId": "ba518851-2843-4bbd-c0f7-5b5692d542e0", - "type": "integer", - "text": "What is your age?", - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/minValue", - "valueInteger": 18 - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/maxValue", - "valueInteger": 120 - }, - { - "url": "http://ehelse.no/fhir/StructureDefinition/validationtext", - "valueString": "Please enter a valid age." - } - ], - "required": false - }, - { - "linkId": "695525f3-3e89-4455-8e25-878171c596da", - "type": "choice", - "text": "What is your preferred contact method?", - "item": [ - { - "linkId": "86290b0a-017e-4193-8707-dc0c2146f0eb", - "type": "string", - "text": "What is your e-mail?", - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/regex", - "valueString": "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$" - }, - { - "url": "http://ehelse.no/fhir/StructureDefinition/validationtext", - "valueString": "Please enter a valid email" - }, - { - "url": "http://hl7.org/fhir/StructureDefinition/minLength", - "valueInteger": 1 - } - ], - "required": false, - "maxLength": 50, - "enableWhen": [ - { - "question": "695525f3-3e89-4455-8e25-878171c596da", - "operator": "=", - "answerCoding": { - "system": "urn:uuid:736ac230-812a-4f4a-edec-5156910fb6ec", - "code": "e-mail" - } - } - ] - }, - { - "linkId": "c3bea33d-4c50-4f4a-8ae4-1a52be326b19", - "type": "string", - "text": "What is your phone number? Ex. (555) 555-5555", - "required": false, - "enableWhen": [ - { - "question": "695525f3-3e89-4455-8e25-878171c596da", - "operator": "=", - "answerCoding": { - "system": "urn:uuid:736ac230-812a-4f4a-edec-5156910fb6ec", - "code": "phone-call" - } - }, - { - "question": "695525f3-3e89-4455-8e25-878171c596da", - "operator": "=", - "answerCoding": { - "system": "urn:uuid:736ac230-812a-4f4a-edec-5156910fb6ec", - "code": "text-message" - } - } - ], - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/regex", - "valueString": "(xxx) xxx-xxxxx" - }, - { - "url": "http://ehelse.no/fhir/StructureDefinition/validationtext", - "valueString": "Please enter a valid phone number." - } - ] - } - ], - "required": false, - "answerOption": [ - { - "valueCoding": { - "id": "b7a3d7a5-52b9-49b1-8b59-7a3885483f1c", - "code": "phone-call", - "system": "urn:uuid:736ac230-812a-4f4a-edec-5156910fb6ec", - "display": "Phone call" - } - }, - { - "valueCoding": { - "id": "3d42dde0-8e60-4832-bd46-bd06de28cbf2", - "code": "text-message", - "system": "urn:uuid:736ac230-812a-4f4a-edec-5156910fb6ec", - "display": "Text message" - } - }, - { - "valueCoding": { - "id": "e672cfc6-118f-4a2d-aafd-02722ff876b9", - "code": "e-mail", - "system": "urn:uuid:736ac230-812a-4f4a-edec-5156910fb6ec", - "display": "E-mail" - } - } - ] - } - ] -} diff --git a/PAWSModules/Sources/PAWSSchedule/Resources/en.lproj/SocialSupportQuestionnaire.json.license b/PAWSModules/Sources/PAWSSchedule/Resources/en.lproj/SocialSupportQuestionnaire.json.license deleted file mode 100644 index 9137ea9d..00000000 --- a/PAWSModules/Sources/PAWSSchedule/Resources/en.lproj/SocialSupportQuestionnaire.json.license +++ /dev/null @@ -1,6 +0,0 @@ - -This source file is part of the CS342 2023 PAWS Team Application project - -SPDX-FileCopyrightText: 2023 Stanford University - -SPDX-License-Identifier: MIT diff --git a/PAWSModules/Sources/PAWSSchedule/ScheduleView.swift b/PAWSModules/Sources/PAWSSchedule/ScheduleView.swift deleted file mode 100644 index dd086560..00000000 --- a/PAWSModules/Sources/PAWSSchedule/ScheduleView.swift +++ /dev/null @@ -1,124 +0,0 @@ -// -// This source file is part of the CS342 2023 PAWS Team Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - - -import Questionnaires -import Scheduler -import SwiftUI - - -public struct ScheduleView: View { - @EnvironmentObject var scheduler: PAWSScheduler - @State var eventContextsByDate: [Date: [EventContext]] = [:] - @State var presentedContext: EventContext? - - - var startOfDays: [Date] { - Array(eventContextsByDate.keys) - } - - - public 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 - } - } - } - } - } - .onChange(of: scheduler) { _ in - calculateEventContextsByDate() - } - .task { - calculateEventContextsByDate() - } - .sheet(item: $presentedContext) { presentedContext in - destination(withContext: presentedContext) - } - .navigationTitle(String(localized: "SCHEDULE_LIST_TITLE", bundle: .module)) - } - } - - - public init() {} - - - private func destination(withContext eventContext: EventContext) -> some View { - @ViewBuilder - var destination: some View { - switch eventContext.task.context { - case let .questionnaire(questionnaire): - QuestionnaireView(questionnaire: questionnaire) { _ in - _Concurrency.Task { - await eventContext.event.complete(true) - } - } - } - } - return destination - } - - - private func format(startOfDay: Date) -> String { - let dateFormatter = DateFormatter() - dateFormatter.dateStyle = .long - dateFormatter.timeStyle = .none - return dateFormatter.string(from: startOfDay) - } - - private func calculateEventContextsByDate() { - let eventContexts = scheduler.tasks.flatMap { task in - task - .events( - from: Calendar.current.startOfDay(for: .now), - to: .numberOfEventsOrEndDate(100, .now) - ) - .map { event in - EventContext(event: event, task: task) - } - } - .sorted() - - let newEventContextsByDate = Dictionary(grouping: eventContexts) { eventContext in - Calendar.current.startOfDay(for: eventContext.event.scheduledAt) - } - - if newEventContextsByDate != eventContextsByDate { - eventContextsByDate = newEventContextsByDate - } - } -} - - -struct SchedulerView_Previews: PreviewProvider { - static var previews: some View { - ScheduleView() - .environmentObject( - PAWSScheduler( - tasks: [ - Task( - title: String(localized: "TASK_SOCIAL_SUPPORT_QUESTIONNAIRE_TITLE"), - description: String(localized: "TASK_SOCIAL_SUPPORT_QUESTIONNAIRE_DESCRIPTION"), - schedule: Schedule( - start: Calendar.current.startOfDay(for: Date()), - dateComponents: .init(hour: 0, minute: 30), // Every Day at 12:30 AM - end: .numberOfEvents(356) - ), - context: PAWSTaskContext.questionnaire(Bundle.main.questionnaire(withName: "SocialSupportQuestionnaire")) - ) - ] - ) - ) - } -} diff --git a/PAWSUITests/ContactsTests.swift b/PAWSUITests/ContactsTests.swift index dc861dd8..7c207db9 100644 --- a/PAWSUITests/ContactsTests.swift +++ b/PAWSUITests/ContactsTests.swift @@ -24,36 +24,13 @@ class ContactsTests: XCTestCase { func testContacts() throws { let app = XCUIApplication() - XCTAssertTrue(app.tabBars["Tab Bar"].buttons["Contacts"].waitForExistence(timeout: 0.5)) + XCTAssertTrue(app.tabBars["Tab Bar"].buttons["Contacts"].waitForExistence(timeout: 2)) app.tabBars["Tab Bar"].buttons["Contacts"].tap() - XCTAssertTrue(app.staticTexts["Leland Stanford"].waitForExistence(timeout: 0.5)) - XCTAssertTrue(app.staticTexts["University Founder"].waitForExistence(timeout: 0.5)) - XCTAssertTrue(app.staticTexts["Stanford University"].waitForExistence(timeout: 0.5)) + XCTAssertTrue(app.staticTexts["Scott Ceresnak"].waitForExistence(timeout: 2)) - XCTAssertTrue(app.buttons["Call"].waitForExistence(timeout: 0.5)) - app.buttons["Call"].tap() - app.alerts["Call"].scrollViews.otherElements.buttons["Ok"].tap() + app.swipeUp(velocity: .fast) - XCTAssertTrue(app.buttons["Text"].waitForExistence(timeout: 0.5)) - app.buttons["Text"].tap() - app.alerts["Text"].scrollViews.otherElements.buttons["Ok"].tap() - - XCTAssertTrue(app.buttons["Email"].waitForExistence(timeout: 0.5)) - app.buttons["Email"].tap() - app.alerts["Email"].scrollViews.otherElements.buttons["Ok"].tap() - - XCTAssertTrue(app.buttons["Website"].waitForExistence(timeout: 0.5)) - app.buttons["Website"].tap() - - let safari = XCUIApplication(bundleIdentifier: "com.apple.mobilesafari") - XCTAssert(safari.wait(for: .runningForeground, timeout: 5.0)) - app.activate() - - XCTAssertTrue(app.buttons["Address, 450 Serra Mall\nStanford CA 94305\nUSA"].waitForExistence(timeout: 0.5)) - app.buttons["Address, 450 Serra Mall\nStanford CA 94305\nUSA"].tap() - - let maps = XCUIApplication(bundleIdentifier: "com.apple.Maps") - XCTAssert(maps.wait(for: .runningForeground, timeout: 5.0)) + XCTAssertTrue(app.staticTexts["Aydin Zahedivash"].waitForExistence(timeout: 2)) } } diff --git a/PAWSUITests/HealthKitUploadTests.swift b/PAWSUITests/HealthKitUploadTests.swift index 36359814..c41a4886 100644 --- a/PAWSUITests/HealthKitUploadTests.swift +++ b/PAWSUITests/HealthKitUploadTests.swift @@ -7,6 +7,7 @@ // import XCTest +import XCTestExtensions import XCTHealthKit @@ -27,41 +28,38 @@ class HealthKitUploadTests: XCTestCase { try app.conductOnboardingIfNeeded() - try navigateToMockUpload() - try assertObservationCellPresent(false) + try app.navigateToMockUpload() + try app.assertObservationCellPresent(false) - app.terminate() - - try exitAppAndOpenHealth(.steps) + try exitAppAndOpenHealth(.electrocardiograms) app.activate() - try navigateToMockUpload() - try assertObservationCellPresent(true, pressIfPresent: true) - try assertObservationCellPresent(true, pressIfPresent: false) - } - - - private func navigateToMockUpload() throws { - let app = XCUIApplication() + sleep(5) - XCTAssertTrue(app.tabBars["Tab Bar"].buttons["Mock Upload"].waitForExistence(timeout: 0.5)) - app.tabBars["Tab Bar"].buttons["Mock Upload"].tap() + try app.navigateToMockUpload() + try app.assertObservationCellPresent(true, pressIfPresent: true) + try app.assertObservationCellPresent(true, pressIfPresent: false) + } +} + +extension XCUIApplication { + fileprivate func navigateToMockUpload() throws { + XCTAssertTrue(tabBars["Tab Bar"].buttons["Mock Upload"].waitForExistence(timeout: 2)) + tabBars["Tab Bar"].buttons["Mock Upload"].tap() } - private func assertObservationCellPresent(_ shouldBePresent: Bool, pressIfPresent: Bool = true) throws { - let app = XCUIApplication() - + fileprivate func assertObservationCellPresent(_ shouldBePresent: Bool, pressIfPresent: Bool = true) throws { let observationText = "/Observation/" let predicate = NSPredicate(format: "label CONTAINS[c] %@", observationText) if shouldBePresent { - XCTAssertTrue(app.staticTexts.containing(predicate).firstMatch.waitForExistence(timeout: 0.5)) + XCTAssertTrue(staticTexts.containing(predicate).firstMatch.waitForExistence(timeout: 2)) if pressIfPresent { - app.staticTexts.containing(predicate).firstMatch.tap() + staticTexts.containing(predicate).firstMatch.tap() } } else { - XCTAssertFalse(app.staticTexts.containing(predicate).firstMatch.waitForExistence(timeout: 0.5)) + XCTAssertFalse(staticTexts.containing(predicate).firstMatch.waitForExistence(timeout: 2)) } } } diff --git a/PAWSUITests/Helper Extensions/XCUIApplication+DeleteAndLaunch.swift b/PAWSUITests/Helper Extensions/XCUIApplication+DeleteAndLaunch.swift deleted file mode 100644 index bede2864..00000000 --- a/PAWSUITests/Helper Extensions/XCUIApplication+DeleteAndLaunch.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// This source file is part of the CS342 2023 PAWS Team Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import XCTest - - -extension XCUIApplication { - func deleteAndLaunch(withSpringboardAppName appName: String) { - self.terminate() - - let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") - springboard.activate() - - if springboard.icons[appName].waitForExistence(timeout: 10.0) { - if !springboard.icons[appName].isHittable { - springboard.swipeLeft() - } - - XCTAssertTrue(springboard.icons[appName].isHittable) - springboard.icons[appName].press(forDuration: 1.5) - - XCTAssertTrue(springboard.collectionViews.buttons["Remove App"].waitForExistence(timeout: 5.0)) - springboard.collectionViews.buttons["Remove App"].tap() - XCTAssertTrue(springboard.alerts["Remove “\(appName)”?"].scrollViews.otherElements.buttons["Delete App"].waitForExistence(timeout: 5.0)) - springboard.alerts["Remove “\(appName)”?"].scrollViews.otherElements.buttons["Delete App"].tap() - XCTAssertTrue(springboard.alerts["Delete “\(appName)”?"].scrollViews.otherElements.buttons["Delete"].waitForExistence(timeout: 5.0)) - springboard.alerts["Delete “\(appName)”?"].scrollViews.otherElements.buttons["Delete"].tap() - } - - self.launch() - } -} diff --git a/PAWSUITests/NotificationsTests.swift b/PAWSUITests/NotificationsTests.swift new file mode 100644 index 00000000..fc2d9646 --- /dev/null +++ b/PAWSUITests/NotificationsTests.swift @@ -0,0 +1,34 @@ +// +// This source file is part of the CS342 2023 PAWS Team Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import XCTest + + +class NotificationsTests: XCTestCase { + override func setUpWithError() throws { + try super.setUpWithError() + + continueAfterFailure = false + + let app = XCUIApplication() + app.launchArguments = ["--skipOnboarding"] + app.launch() + } + + + func testNotifications() throws { + let app = XCUIApplication() + + XCTAssertTrue(app.tabBars["Tab Bar"].buttons["Notifications"].waitForExistence(timeout: 2)) + app.tabBars["Tab Bar"].buttons["Notifications"].tap() + + XCTAssertTrue(app.staticTexts["ECG Recording"].waitForExistence(timeout: 2)) + + app.swipeUp(velocity: .fast) + } +} diff --git a/PAWSUITests/OnboardingTests.swift b/PAWSUITests/OnboardingTests.swift index c584a5b9..bfbeb253 100644 --- a/PAWSUITests/OnboardingTests.swift +++ b/PAWSUITests/OnboardingTests.swift @@ -7,6 +7,7 @@ // import XCTest +import XCTestExtensions import XCTHealthKit @@ -28,142 +29,86 @@ class OnboardingTests: XCTestCase { try app.navigateOnboardingFlow(assertThatHealthKitConsentIsShown: true) let tabBar = app.tabBars["Tab Bar"] - XCTAssertTrue(tabBar.buttons["Schedule"].waitForExistence(timeout: 0.5)) - XCTAssertTrue(tabBar.buttons["Contacts"].waitForExistence(timeout: 0.5)) - XCTAssertTrue(tabBar.buttons["Mock Upload"].waitForExistence(timeout: 0.5)) + XCTAssertTrue(tabBar.buttons["Notifications"].waitForExistence(timeout: 2)) + XCTAssertTrue(tabBar.buttons["Contacts"].waitForExistence(timeout: 2)) + XCTAssertTrue(tabBar.buttons["Mock Upload"].waitForExistence(timeout: 2)) } } extension XCUIApplication { func conductOnboardingIfNeeded() throws { - if self.staticTexts["CardinalKit\nPAWS Application"].waitForExistence(timeout: 0.5) { + if buttons["Tap to get started"].waitForExistence(timeout: 2) { try navigateOnboardingFlow(assertThatHealthKitConsentIsShown: false) } } func navigateOnboardingFlow(assertThatHealthKitConsentIsShown: Bool = true) throws { + try navigateOnboardingGetStarted() try navigateOnboardingFlowWelcome() try navigateOnboardingFlowInterestingModules() - if staticTexts["Consent Example"].waitForExistence(timeout: 0.5) { + if staticTexts["Consent Page"].waitForExistence(timeout: 2) { try navigateOnboardingFlowConsent() } try navigateOnboardingFlowHealthKitAccess(assertThatHealthKitConsentIsShown: assertThatHealthKitConsentIsShown) } - private func navigateOnboardingFlowWelcome() throws { - XCTAssertTrue(staticTexts["CardinalKit\nPAWS Application"].waitForExistence(timeout: 0.5)) - XCTAssertTrue( - staticTexts["This application demonstrates several CardinalKit features & modules."] - .waitForExistence(timeout: 0.5) - ) - - XCTAssertTrue(staticTexts["The CardinalKit Framework"].waitForExistence(timeout: 0.5)) - XCTAssertTrue( - staticTexts["The CardinalKit Framework builds the foundation of this template application."] - .waitForExistence(timeout: 0.5) - ) - - XCTAssertTrue(staticTexts["Swift Package Manager"].waitForExistence(timeout: 0.5)) - XCTAssertTrue( - staticTexts["CardinalKit uses the Swift Package Manager to import it as a dependency."] - .waitForExistence(timeout: 0.5) - ) - - XCTAssertTrue(staticTexts["CardinalKit Modules"].waitForExistence(timeout: 0.5)) - XCTAssertTrue( - staticTexts["CardinalKit offers several modules including HealthKit integration, questionnaires, and more ..."] - .waitForExistence(timeout: 0.5) - ) - - XCTAssertTrue(buttons["Learn More"].waitForExistence(timeout: 0.5)) - buttons["Learn More"].tap() + private func navigateOnboardingGetStarted() throws { + XCTAssertTrue(buttons["Tap to get started"].waitForExistence(timeout: 2)) + buttons["Tap to get started"].tap() } - private func navigateOnboardingFlowInterestingModules() throws { - XCTAssertTrue(staticTexts["Interesting Modules"].waitForExistence(timeout: 0.5)) - XCTAssertTrue( - staticTexts["Here are a few CardinalKit modules that are interesting to know about ..."] - .waitForExistence(timeout: 0.5) - ) - - XCTAssertTrue(staticTexts["Onboarding"].waitForExistence(timeout: 0.5)) - XCTAssertTrue( - staticTexts["The onboarding module allows you to build an onboarding flow like this one."] - .waitForExistence(timeout: 0.5) - ) - XCTAssertTrue(buttons["Next"].waitForExistence(timeout: 0.5)) - buttons["Next"].tap() + private func navigateOnboardingFlowWelcome() throws { + XCTAssertTrue(staticTexts["Welcome to PAWS!"].waitForExistence(timeout: 2)) - XCTAssertTrue(staticTexts["FHIR"].waitForExistence(timeout: 0.5)) - XCTAssertTrue( - staticTexts["The FHIR module provides a CardinalKit standard that can be used as a communication standard between modules."] - .waitForExistence(timeout: 0.5) - ) - XCTAssertTrue(buttons["Next"].waitForExistence(timeout: 0.5)) - buttons["Next"].tap() + swipeUp() - XCTAssertTrue(staticTexts["Contact"].waitForExistence(timeout: 0.5)) - XCTAssertTrue( - staticTexts["The contact module allows you to display contact information in your application."] - .waitForExistence(timeout: 0.5) - ) - XCTAssertTrue(buttons["Next"].waitForExistence(timeout: 0.5)) - buttons["Next"].tap() + XCTAssertTrue(buttons["Begin onboarding"].waitForExistence(timeout: 2)) + buttons["Begin onboarding"].tap() + } + + private func navigateOnboardingFlowInterestingModules() throws { + XCTAssertTrue(staticTexts["PAWS Onboarding"].waitForExistence(timeout: 2)) - XCTAssertTrue(staticTexts["HealthKit Data Source"].waitForExistence(timeout: 0.5)) - XCTAssertTrue( - staticTexts["The HealthKit data source module allows you to fetch data from HealthKit and e.g. transform it to FHIR resources."] - .waitForExistence(timeout: 0.5) - ) + for _ in 1..<3 { + XCTAssertTrue(buttons["Next"].waitForExistence(timeout: 2)) + buttons["Next"].tap() + } - XCTAssertTrue(buttons["Next"].waitForExistence(timeout: 0.5)) + XCTAssertTrue(buttons["Next"].waitForExistence(timeout: 2)) buttons["Next"].tap() } private func navigateOnboardingFlowConsent() throws { - XCTAssertTrue(staticTexts["Consent Example"].waitForExistence(timeout: 0.5)) - XCTAssertTrue( - staticTexts["CardinalKit can collect consent from a user. You can provide the consent document using a markdown file."] - .waitForExistence(timeout: 0.5) - ) - XCTAssertTrue( - staticTexts["CardinalKit can render consent documents in the markdown format: This is a markdown example.\n"] - .waitForExistence(timeout: 0.5) - ) - - XCTAssertTrue(staticTexts["Given Name"].waitForExistence(timeout: 0.5)) + XCTAssertTrue(staticTexts["Consent Page"].waitForExistence(timeout: 2)) + + swipeUp(velocity: .fast) + + XCTAssertTrue(staticTexts["Given Name"].waitForExistence(timeout: 2)) staticTexts["Given Name"].tap() textFields["Enter your given name ..."].typeText("Leland") - XCTAssertTrue(staticTexts["Family Name"].waitForExistence(timeout: 0.5)) + XCTAssertTrue(staticTexts["Family Name"].waitForExistence(timeout: 2)) staticTexts["Family Name"].tap() textFields["Enter your family name ..."].typeText("Stanford") - staticTexts["Given Name"].swipeUp() + textFields["Enter your family name ..."].typeText("\n") + swipeUp() - XCTAssertTrue(staticTexts["Leland Stanford"].waitForExistence(timeout: 0.5)) + XCTAssertTrue(staticTexts["Leland Stanford"].waitForExistence(timeout: 2)) staticTexts["Leland Stanford"].firstMatch.swipeUp() - XCTAssertTrue(buttons["I Consent"].waitForExistence(timeout: 0.5)) + XCTAssertTrue(buttons["I Consent"].waitForExistence(timeout: 2)) buttons["I Consent"].tap() } private func navigateOnboardingFlowHealthKitAccess(assertThatHealthKitConsentIsShown: Bool = true) throws { - XCTAssertTrue(staticTexts["HealthKit Access"].waitForExistence(timeout: 0.5)) - XCTAssertTrue( - staticTexts["CardinalKit can access data from HealthKit using the HealthKitDataSource module."].waitForExistence(timeout: 0.5) - ) - XCTAssertTrue(images["heart.text.square.fill"].waitForExistence(timeout: 0.5)) - XCTAssertTrue(buttons["Grant Access"].waitForExistence(timeout: 0.5)) + XCTAssertTrue(staticTexts["Health Data Access"].waitForExistence(timeout: 2)) + + XCTAssertTrue(buttons["Grant Access"].waitForExistence(timeout: 2)) buttons["Grant Access"].tap() - if self.navigationBars["Health Access"].waitForExistence(timeout: 30) { - self.tables.staticTexts["Turn On All"].tap() - self.navigationBars["Health Access"].buttons["Allow"].tap() - } else if assertThatHealthKitConsentIsShown { - XCTFail("Did not display the HealthKit Consent Screen") - } + try handleHealthKitAuthorization() } } diff --git a/PAWSUITests/SchedulerAndQuestionnaireTests.swift b/PAWSUITests/SchedulerAndQuestionnaireTests.swift deleted file mode 100644 index 1e2437c1..00000000 --- a/PAWSUITests/SchedulerAndQuestionnaireTests.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// This source file is part of the CS342 2023 PAWS Team Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import XCTest - - -class SchedulerAndQuestionnaireTests: XCTestCase { - override func setUpWithError() throws { - try super.setUpWithError() - - continueAfterFailure = false - - let app = XCUIApplication() - app.launchArguments = ["--skipOnboarding"] - app.deleteAndLaunch(withSpringboardAppName: "PAWS") - } - - - func testSchedulerAndQuestionnaire() throws { - let app = XCUIApplication() - - XCTAssertTrue(app.tabBars["Tab Bar"].buttons["Schedule"].waitForExistence(timeout: 0.5)) - app.tabBars["Tab Bar"].buttons["Schedule"].tap() - - XCTAssertTrue(app.staticTexts["Social Support Questionnaire"].waitForExistence(timeout: 0.5)) - XCTAssertTrue(app.staticTexts["Please fill out the Social Support Questionnaire every day."].waitForExistence(timeout: 0.5)) - XCTAssertTrue(app.staticTexts["Start Questionnaire"].waitForExistence(timeout: 0.5)) - - app.staticTexts["Start Questionnaire"].tap() - - for _ in 0..<4 { - XCTAssertTrue(app.tables.staticTexts["None of the time"].waitForExistence(timeout: 0.5)) - app.tables.staticTexts["None of the time"].tap() - XCTAssertTrue(app.tables.buttons["Next"].waitForExistence(timeout: 0.5)) - app.tables.buttons["Next"].tap() - } - - XCTAssertTrue(app.textFields["Tap to answer"].waitForExistence(timeout: 0.5)) - app.textFields["Tap to answer"].tap() - app.textFields["Tap to answer"].typeText("42") - app.toolbars["Toolbar"].buttons["Done"].tap() - - XCTAssertTrue(app.buttons["Next"].waitForExistence(timeout: 0.5)) - app.buttons["Next"].tap() - - XCTAssertTrue(app.tables.staticTexts["Phone call"].waitForExistence(timeout: 0.5)) - app.tables.staticTexts["Phone call"].tap() - XCTAssertTrue(app.tables.buttons["Done"].waitForExistence(timeout: 0.5)) - app.tables.buttons["Done"].tap() - - XCTAssertTrue(!app.staticTexts["Start Questionnaire"].waitForExistence(timeout: 0.5)) - XCTAssertTrue(app.images["Selected"].waitForExistence(timeout: 0.5)) - } -}