From a0c606ae4f0a9727db5118450273ce9a8cfb4e8b Mon Sep 17 00:00:00 2001 From: apgupta3303 Date: Wed, 28 Feb 2024 16:31:05 -0800 Subject: [PATCH 1/8] stash --- .../xcshareddata/swiftpm/Package.resolved | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 4d8c2a2..4c73220 100644 --- a/Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -192,7 +192,7 @@ { "identity" : "spezichat", "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziChat", + "location" : "https://github.com/StanfordSpezi/SpeziChat.git", "state" : { "revision" : "eae5c15b211f18e09aa98de63ce119629320afeb", "version" : "0.1.8" @@ -230,8 +230,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordSpezi/SpeziFoundation.git", "state" : { - "revision" : "0346857e2f1d6fd4b1d950d271be6c82df97107f", - "version" : "1.0.2" + "revision" : "662f25d6010a94faf4fd996e184617fcb2bf13d4", + "version" : "1.0.3" } }, { @@ -246,7 +246,7 @@ { "identity" : "spezillm", "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziLLM", + "location" : "https://github.com/StanfordSpezi/SpeziLLM.git", "state" : { "revision" : "6892c5dfe258371b6f3287f02b8fec57a611ba70", "version" : "0.7.0" From 874b569e4d0d15474bae5cc729a9d20959b61d50 Mon Sep 17 00:00:00 2001 From: apgupta3303 Date: Wed, 28 Feb 2024 19:28:09 -0800 Subject: [PATCH 2/8] saving changes --- Intake.xcodeproj/project.pbxproj | 4 + Intake/Home.swift | 6 +- Intake/Intake.swift | 9 ++ Intake/Resources/Localizable.xcstrings | 12 +++ Intake/ScrollablePDF.swift | 131 +++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 Intake/ScrollablePDF.swift diff --git a/Intake.xcodeproj/project.pbxproj b/Intake.xcodeproj/project.pbxproj index 6528a33..988f288 100644 --- a/Intake.xcodeproj/project.pbxproj +++ b/Intake.xcodeproj/project.pbxproj @@ -88,6 +88,7 @@ 5A2B9FBC2B6C7B29005CA63F /* ReactionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A2B9FBB2B6C7B29005CA63F /* ReactionView.swift */; }; 5AEA5F212B82DDD000F1577A /* LLMAssistantView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA5F202B82DDD000F1577A /* LLMAssistantView.swift */; }; 5AEA5F2C2B8680F300F1577A /* AddAllergy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA5F2B2B8680F300F1577A /* AddAllergy.swift */; }; + 5AEA5F3B2B90081B00F1577A /* ScrollablePDF.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA5F3A2B90081B00F1577A /* ScrollablePDF.swift */; }; 637BE1D52B572B4800EA19C6 /* Questionnaire.json.license in Resources */ = {isa = PBXBuildFile; fileRef = 637BE1D42B572B4800EA19C6 /* Questionnaire.json.license */; }; 653A2551283387FE005D4D48 /* Intake.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653A2550283387FE005D4D48 /* Intake.swift */; }; 653A255528338800005D4D48 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 653A255428338800005D4D48 /* Assets.xcassets */; }; @@ -190,6 +191,7 @@ 5A2B9FBB2B6C7B29005CA63F /* ReactionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReactionView.swift; sourceTree = ""; }; 5AEA5F202B82DDD000F1577A /* LLMAssistantView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LLMAssistantView.swift; sourceTree = ""; }; 5AEA5F2B2B8680F300F1577A /* AddAllergy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAllergy.swift; sourceTree = ""; }; + 5AEA5F3A2B90081B00F1577A /* ScrollablePDF.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollablePDF.swift; sourceTree = ""; }; 637BE1D42B572B4800EA19C6 /* Questionnaire.json.license */ = {isa = PBXFileReference; lastKnownFileType = text; path = Questionnaire.json.license; sourceTree = ""; }; 653A254D283387FE005D4D48 /* Intake.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Intake.app; sourceTree = BUILT_PRODUCTS_DIR; }; 653A2550283387FE005D4D48 /* Intake.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Intake.swift; sourceTree = ""; }; @@ -479,6 +481,7 @@ 2FE5DC3D29EDD7E4004B9AB4 /* Helper */, 2FE5DC2D29EDD792004B9AB4 /* Resources */, 2FC9759D2978E30800BA99FE /* Supporting Files */, + 5AEA5F3A2B90081B00F1577A /* ScrollablePDF.swift */, ); path = Intake; sourceTree = ""; @@ -814,6 +817,7 @@ 2F5E32BD297E05EA003432F8 /* IntakeDelegate.swift in Sources */, 511827962B740192002033A0 /* SurgeryView.swift in Sources */, 2FE5DC5229EDD7FA004B9AB4 /* IntakeScheduler.swift in Sources */, + 5AEA5F3B2B90081B00F1577A /* ScrollablePDF.swift in Sources */, F42AB1E52B6383F9002E13A6 /* LLMOpenAITokenOnboarding.swift in Sources */, A9FE7AD02AA39BAB0077B045 /* AccountSheet.swift in Sources */, 653A2551283387FE005D4D48 /* Intake.swift in Sources */, diff --git a/Intake/Home.swift b/Intake/Home.swift index d1f9b07..1e6b741 100644 --- a/Intake/Home.swift +++ b/Intake/Home.swift @@ -84,10 +84,10 @@ struct HomeView: View { .navigationDestination(for: NavigationViews.self) { view in switch view { - case .chat: LLMInteraction(presentingAccount: $presentingAccount) + case .chat: MedicalHistoryView() case .allergies: AllergyList() - case .surgical: SurgeryView() - case .medical: MedicalHistoryView() + case .surgical: ScrollablePDF() + case .medical: ScrollablePDF() case .social: SocialHistoryQuestionView() case .medication: MedicationView() } diff --git a/Intake/Intake.swift b/Intake/Intake.swift index cf2a947..bb4ba58 100644 --- a/Intake/Intake.swift +++ b/Intake/Intake.swift @@ -15,11 +15,20 @@ class NavigationPathWrapper { var path = NavigationPath() } +struct PatientData { + var name: String + var birthdate: String + var age: Int + var sex: String +} + @Observable class DataStore { var allergyData: [AllergyItem] = [] var conditionData: [MedicalHistoryItem] = [] var medicationData: [MedicationItem] = [] + var generalData = PatientData(name: "", birthdate: "", age: 0, sex: "") + var chiefComplaint: String = "" } @main diff --git a/Intake/Resources/Localizable.xcstrings b/Intake/Resources/Localizable.xcstrings index 8ea9657..de71227 100644 --- a/Intake/Resources/Localizable.xcstrings +++ b/Intake/Resources/Localizable.xcstrings @@ -60,6 +60,9 @@ } } } + }, + "Active" : { + }, "Add Field" : { @@ -117,6 +120,9 @@ }, "Condition" : { + }, + "Conditions" : { + }, "CONSENT_LOADING_ERROR" : { "localizations" : { @@ -256,6 +262,9 @@ }, "How many packs do you smoke a day?" : { + }, + "Inactive" : { + }, "Integrate your Records" : { @@ -426,6 +435,9 @@ }, "Other important questions." : { + }, + "Patient Form" : { + }, "Please list conditions you have had" : { diff --git a/Intake/ScrollablePDF.swift b/Intake/ScrollablePDF.swift new file mode 100644 index 0000000..034dba4 --- /dev/null +++ b/Intake/ScrollablePDF.swift @@ -0,0 +1,131 @@ +// +// ScrollablePDF.swift +// Intake +// +// Created by Akash Gupta on 2/28/24. +// + +import Foundation +import SpeziFHIR +import SwiftUI + +struct ScrollablePDF: View { + @Environment(DataStore.self) private var data + + var body: some View { + Form { + patientInfo + chiefComplaint + ConditionSection() + surgicalHistorySection + medicationsSection + allergiesSection +// DatePicker("Last Menstrual Period", selection: $lastMenstrualPeriod, displayedComponents: .date) +// smokingHistorySection + } + .navigationTitle("Patient Form") + } + + + private var patientInfo: some View { + Group { + DetailSection(header: "Patient Information", content: ["Name: Akash Gupta", "Date of Birth: 01/08/2003", "Age: 21", "Sex: Male"]) + } + } + + private var chiefComplaint: some View { + DetailSection(header: "Chief Complaint:", content: ["I hurt my knee and it hurts a lot on the outside for the last 10 days..."]) + } + + private var surgicalHistorySection: some View { + DetailSection(header: "Past Surgical History:", content: ["Appendectomy, 2005", "Left Femur Fracture Repair, 2012"]) + } + + private var medicationsSection: some View { + DetailSection(header: "Medications:", content: ["Oxycontin 20mg, twice a day", "Lisinopril 5mg, once a day"]) + } + + private var allergiesSection: some View { + DetailSection(header: "Allergies:", content: ["Peanuts - Anaphylactic Shock", "Penicillin - Rash"]) + } + +// private var smokingHistorySection: some View { +// DetailRow(label: "Smoking History:", value: "20 pack years") +// } + + private struct ConditionSection: View { + @Environment(DataStore.self) private var data// Assuming DataStore contains 'conditionData' + + var body: some View { + Section(header: headerTitle) { + VStack(alignment: .leading) { + ForEach(data.conditionData) { item in // Removed id: \.self since items are Identifiable + HStack { + Text(item.condition) + .padding(.leading) + Spacer() + Text(item.active ? "Active" : "Inactive" ) + } + } + } + } + } + + var headerTitle: some View { // Moved this inside ConditionSection + HStack { + Text("Conditions") + Spacer() + EditButton() + } + } + } + +} + +//struct DetailRow: View { +// var label: String +// var value: String +// +// var body: some View { +// HStack { +// Text(label) +// Spacer() +// Text(value) +// } +// } +//} + +struct DetailSection: View { + var header: String + var content: [String] + + + var body: some View { + Section(header: headerTitle) { + VStack(alignment: .leading) { + ForEach(content, id: \.self) { item in + Text(item) + .padding(.leading) + } + } + } + } + + private var headerTitle: some View { + HStack { + Text(header) + Spacer() + EditButton() + } + } +} + + + + +#Preview { + ScrollablePDF() + .previewWith { + FHIRStore() + } +} From 1f3ce82517db1285000948c63524735a4e06a7e3 Mon Sep 17 00:00:00 2001 From: apgupta3303 Date: Thu, 29 Feb 2024 12:53:27 -0800 Subject: [PATCH 3/8] Adding scrollable view --- Intake.xcodeproj/project.pbxproj | 4 + Intake/Allergy Records/AllergyRecords.swift | 18 +- Intake/EditPatient.swift | 40 ++++ Intake/Elements.swift | 6 +- Intake/Home.swift | 12 +- Intake/Intake.swift | 5 +- .../Medical History/MedicalHistoryView.swift | 18 +- Intake/Resources/Localizable.xcstrings | 27 +++ Intake/ScrollablePDF.swift | 200 ++++++++++++++---- 9 files changed, 251 insertions(+), 79 deletions(-) create mode 100644 Intake/EditPatient.swift diff --git a/Intake.xcodeproj/project.pbxproj b/Intake.xcodeproj/project.pbxproj index 988f288..7d2131e 100644 --- a/Intake.xcodeproj/project.pbxproj +++ b/Intake.xcodeproj/project.pbxproj @@ -89,6 +89,7 @@ 5AEA5F212B82DDD000F1577A /* LLMAssistantView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA5F202B82DDD000F1577A /* LLMAssistantView.swift */; }; 5AEA5F2C2B8680F300F1577A /* AddAllergy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA5F2B2B8680F300F1577A /* AddAllergy.swift */; }; 5AEA5F3B2B90081B00F1577A /* ScrollablePDF.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA5F3A2B90081B00F1577A /* ScrollablePDF.swift */; }; + 5AEA5F422B90710B00F1577A /* EditPatient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA5F412B90710B00F1577A /* EditPatient.swift */; }; 637BE1D52B572B4800EA19C6 /* Questionnaire.json.license in Resources */ = {isa = PBXBuildFile; fileRef = 637BE1D42B572B4800EA19C6 /* Questionnaire.json.license */; }; 653A2551283387FE005D4D48 /* Intake.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653A2550283387FE005D4D48 /* Intake.swift */; }; 653A255528338800005D4D48 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 653A255428338800005D4D48 /* Assets.xcassets */; }; @@ -192,6 +193,7 @@ 5AEA5F202B82DDD000F1577A /* LLMAssistantView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LLMAssistantView.swift; sourceTree = ""; }; 5AEA5F2B2B8680F300F1577A /* AddAllergy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAllergy.swift; sourceTree = ""; }; 5AEA5F3A2B90081B00F1577A /* ScrollablePDF.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollablePDF.swift; sourceTree = ""; }; + 5AEA5F412B90710B00F1577A /* EditPatient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditPatient.swift; sourceTree = ""; }; 637BE1D42B572B4800EA19C6 /* Questionnaire.json.license */ = {isa = PBXFileReference; lastKnownFileType = text; path = Questionnaire.json.license; sourceTree = ""; }; 653A254D283387FE005D4D48 /* Intake.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Intake.app; sourceTree = BUILT_PRODUCTS_DIR; }; 653A2550283387FE005D4D48 /* Intake.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Intake.swift; sourceTree = ""; }; @@ -482,6 +484,7 @@ 2FE5DC2D29EDD792004B9AB4 /* Resources */, 2FC9759D2978E30800BA99FE /* Supporting Files */, 5AEA5F3A2B90081B00F1577A /* ScrollablePDF.swift */, + 5AEA5F412B90710B00F1577A /* EditPatient.swift */, ); path = Intake; sourceTree = ""; @@ -813,6 +816,7 @@ 5A2B9FBC2B6C7B29005CA63F /* ReactionView.swift in Sources */, 566155292AB8447C00209B80 /* Package+LicenseType.swift in Sources */, 5680DD392AB8983D004E6D4A /* PackageCell.swift in Sources */, + 5AEA5F422B90710B00F1577A /* EditPatient.swift in Sources */, F42AB1EC2B6DBF21002E13A6 /* SummaryView.swift in Sources */, 2F5E32BD297E05EA003432F8 /* IntakeDelegate.swift in Sources */, 511827962B740192002033A0 /* SurgeryView.swift in Sources */, diff --git a/Intake/Allergy Records/AllergyRecords.swift b/Intake/Allergy Records/AllergyRecords.swift index 163a287..aaef1df 100644 --- a/Intake/Allergy Records/AllergyRecords.swift +++ b/Intake/Allergy Records/AllergyRecords.swift @@ -58,7 +58,7 @@ struct AllergyList: View { var body: some View { VStack { allergyForm - submitButton + SubmitButton(nextView: NavigationViews.social) } .onAppear(perform: loadAllergies) .sheet(isPresented: $showingChat, content: chatSheetView) @@ -94,18 +94,6 @@ struct AllergyList: View { } } } - - private var submitButton: some View { - Button(action: submitAction) { - Text("Submit") - .foregroundColor(.white) - .padding() - .frame(maxWidth: .infinity) - .background(Color.blue) - .cornerRadius(8) - } - .padding() - } private func allergyEntryRow(index: Int) -> some View { HStack { @@ -127,10 +115,6 @@ struct AllergyList: View { } } - private func submitAction() { - navigationPath.path.append(NavigationViews.social) - } - private func addAllergyAction() { data.allergyData.append(AllergyItem(allergy: "", reaction: [])) self.selectedIndex = data.allergyData.count - 1 diff --git a/Intake/EditPatient.swift b/Intake/EditPatient.swift new file mode 100644 index 0000000..233faa3 --- /dev/null +++ b/Intake/EditPatient.swift @@ -0,0 +1,40 @@ +// +// EditPatient.swift +// Intake +// +// Created by Akash Gupta on 2/29/24. +// + +import Foundation +import SwiftUI + + +struct EditPatientView: View { + @Environment(DataStore.self) private var data + + var body: some View { + @Bindable var data = data + VStack { + Form { + Section(header: Text("Name")) { + TextField("Name", text: $data.generalData.name) + } + Section(header: Text("Date of Birth")) { + TextField("Date of Birth", text: $data.generalData.birthdate) + } + Section(header: Text("Age")) { + TextField("Age", text: $data.generalData.age) + } + Section(header: Text("Sex")) { + TextField("Sex", text: $data.generalData.sex) + } + } + SubmitButton(nextView: NavigationViews.pdfs) + } + } +} + +// +// #Preview { +// EditPatientView() +// } diff --git a/Intake/Elements.swift b/Intake/Elements.swift index da2d739..b291110 100644 --- a/Intake/Elements.swift +++ b/Intake/Elements.swift @@ -37,7 +37,11 @@ struct SubmitButton: View { Button(action: { // Save output to Firestore and navigate to next screen // Still need to save output to Firestore - navigationPath.path.append(nextView) + if reachedEnd { + navigationPath.path.append(NavigationViews.pdfs) + } else { + navigationPath.path.append(nextView) + } }) { Text("Next") .foregroundColor(.white) diff --git a/Intake/Home.swift b/Intake/Home.swift index a9558f1..c59ddd8 100644 --- a/Intake/Home.swift +++ b/Intake/Home.swift @@ -18,6 +18,8 @@ enum NavigationViews: String { case medication case chat case concern + case patient + case pdfs } struct HomeView: View { @@ -88,13 +90,15 @@ struct HomeView: View { .navigationDestination(for: NavigationViews.self) { view in switch view { - case .chat: MedicalHistoryView() + case .chat: LLMInteraction(presentingAccount: $presentingAccount) case .allergies: AllergyList() - case .surgical: ScrollablePDF() - case .medical: ScrollablePDF() - case .social: SocialHistoryQuestionView() + case .surgical: SurgeryView() + case .medical: MedicalHistoryView() + case .social: ScrollablePDF() case .medication: MedicationView() case .concern: SummaryView(chiefComplaint: $data.chiefComplaint) + case .patient: EditPatientView() + case .pdfs: ScrollablePDF() } } } diff --git a/Intake/Intake.swift b/Intake/Intake.swift index 518df51..85dcc0f 100644 --- a/Intake/Intake.swift +++ b/Intake/Intake.swift @@ -18,7 +18,7 @@ class NavigationPathWrapper { struct PatientData { var name: String var birthdate: String - var age: Int + var age: String var sex: String } @@ -29,8 +29,7 @@ class DataStore { var medicationData: [MedicationItem] = [] var surgeries: [SurgeryItem] = [] var chiefComplaint: String = "" - var generalData = PatientData(name: "", birthdate: "", age: 0, sex: "") - var chiefComplaint: String = "" + var generalData = PatientData(name: "Akash", birthdate: "01/08/2003", age: "21", sex: "Male") } @main diff --git a/Intake/Medical History/MedicalHistoryView.swift b/Intake/Medical History/MedicalHistoryView.swift index 9ffcadf..2b68545 100644 --- a/Intake/Medical History/MedicalHistoryView.swift +++ b/Intake/Medical History/MedicalHistoryView.swift @@ -31,7 +31,7 @@ struct MedicalHistoryView: View { var body: some View { VStack { medicalHistoryForm - submitButton + SubmitButton(nextView: NavigationViews.surgical) } .onAppear(perform: loadConditions) .sheet(isPresented: $showingChat, content: chatSheetView) @@ -89,20 +89,6 @@ struct MedicalHistoryView: View { .font(.caption) .foregroundColor(.gray) } - - private var submitButton: some View { - Button(action: { - navigationPath.path.append(NavigationViews.surgical) - }) { - Text("Submit") - .foregroundColor(.white) - .padding() - .frame(maxWidth: .infinity) - .background(Color.blue) - .cornerRadius(8) - } - .padding() - } private func addConditionAction() { data.conditionData.append(MedicalHistoryItem(condition: "", active: false)) @@ -169,7 +155,7 @@ struct MedicalHistoryView: View { func delete(at offsets: IndexSet) { data.conditionData.remove(atOffsets: offsets) } - } +} #Preview { MedicalHistoryView() diff --git a/Intake/Resources/Localizable.xcstrings b/Intake/Resources/Localizable.xcstrings index aee92b4..c448396 100644 --- a/Intake/Resources/Localizable.xcstrings +++ b/Intake/Resources/Localizable.xcstrings @@ -78,6 +78,9 @@ }, "Additional details: %@" : { + }, + "Age" : { + }, "AI-assisted medical intake" : { @@ -93,6 +96,9 @@ }, "Auto-fill Intake Form" : { + }, + "Chief Complaint" : { + }, "CLOSE" : { "comment" : "MARK: General", @@ -182,6 +188,12 @@ } } } + }, + "Date of Birth" : { + + }, + "Date of Birth:" : { + }, "DELETE_MEDICATION" : { @@ -197,6 +209,9 @@ }, "Download your medical records from your health system." : { + }, + "EDIT" : { + }, "END_CALENDAR" : { @@ -368,6 +383,12 @@ } } } + }, + "Name" : { + + }, + "Name:" : { + }, "Next" : { @@ -438,6 +459,9 @@ }, "Patient Form" : { + }, + "Patient Information" : { + }, "Please list conditions you have had" : { @@ -548,6 +572,9 @@ }, "SETTINGS_TITLE" : { + }, + "Sex" : { + }, "Share with provider of your choice." : { diff --git a/Intake/ScrollablePDF.swift b/Intake/ScrollablePDF.swift index 034dba4..af682b4 100644 --- a/Intake/ScrollablePDF.swift +++ b/Intake/ScrollablePDF.swift @@ -9,52 +9,41 @@ import Foundation import SpeziFHIR import SwiftUI +var reachedEnd = false + struct ScrollablePDF: View { @Environment(DataStore.self) private var data + @Environment(NavigationPathWrapper.self) private var navigationPath var body: some View { Form { - patientInfo - chiefComplaint + PatientInfo() + ChiefComplaint() ConditionSection() - surgicalHistorySection + SurgerySection() medicationsSection - allergiesSection + AllergySection() // DatePicker("Last Menstrual Period", selection: $lastMenstrualPeriod, displayedComponents: .date) // smokingHistorySection } .navigationTitle("Patient Form") - } - - - private var patientInfo: some View { - Group { - DetailSection(header: "Patient Information", content: ["Name: Akash Gupta", "Date of Birth: 01/08/2003", "Age: 21", "Sex: Male"]) - } - } - - private var chiefComplaint: some View { - DetailSection(header: "Chief Complaint:", content: ["I hurt my knee and it hurts a lot on the outside for the last 10 days..."]) - } - - private var surgicalHistorySection: some View { - DetailSection(header: "Past Surgical History:", content: ["Appendectomy, 2005", "Left Femur Fracture Repair, 2012"]) + .onAppear(perform: { + reachedEnd = true + }) } private var medicationsSection: some View { DetailSection(header: "Medications:", content: ["Oxycontin 20mg, twice a day", "Lisinopril 5mg, once a day"]) } - private var allergiesSection: some View { - DetailSection(header: "Allergies:", content: ["Peanuts - Anaphylactic Shock", "Penicillin - Rash"]) - } // private var smokingHistorySection: some View { // DetailRow(label: "Smoking History:", value: "20 pack years") // } private struct ConditionSection: View { - @Environment(DataStore.self) private var data// Assuming DataStore contains 'conditionData' + @Environment(DataStore.self) private var data + @Environment(NavigationPathWrapper.self) private var navigationPath var body: some View { Section(header: headerTitle) { @@ -75,25 +64,162 @@ struct ScrollablePDF: View { HStack { Text("Conditions") Spacer() - EditButton() + Button(action: { + navigationPath.path.append(NavigationViews.medical) + }) { + Text("EDIT") + .foregroundColor(.blue) + .padding() + .cornerRadius(10) + } + } + } + } + + private struct SurgerySection: View { + @Environment(DataStore.self) private var data + @Environment(NavigationPathWrapper.self) private var navigationPath + + var body: some View { + Section(header: headerTitle) { + VStack(alignment: .leading) { + ForEach(data.surgeries) { item in + HStack { + Text(item.surgeryName) + .padding(.leading) + Spacer() + Text(item.date ?? "") + } + } + } + } + } + + var headerTitle: some View { + HStack { + Text("Surgical History") + Spacer() + Button(action: { + navigationPath.path.append(NavigationViews.surgical) + }) { + Text("EDIT") + .foregroundColor(.blue) + .padding() + .cornerRadius(10) + } + } + } + } + + private struct AllergySection: View { + @Environment(DataStore.self) private var data + @Environment(NavigationPathWrapper.self) private var navigationPath + + var body: some View { + Section(header: headerTitle) { + VStack(alignment: .leading) { + ForEach(data.allergyData) { item in + Text(item.allergy) + .padding(.leading) + ForEach(item.reaction) { reaction in + Text(reaction.reaction) + .padding(.leading, 50) + } + } + } + } + } + + var headerTitle: some View { + HStack { + Text("Allergies") + Spacer() + Button(action: { + navigationPath.path.append(NavigationViews.allergies) + }) { + Text("EDIT") + .foregroundColor(.blue) + .padding() + .cornerRadius(10) + } } } } + private struct ChiefComplaint: View { + @Environment(DataStore.self) private var data + @Environment(NavigationPathWrapper.self) private var navigationPath + + var body: some View { + Section(header: headerTitle) { + Text(data.chiefComplaint) + } + } + + var headerTitle: some View { + HStack { + Text("Chief Complaint") + Spacer() + Button(action: { + navigationPath.path.append(NavigationViews.concern) + }) { + Text("EDIT") + .foregroundColor(.blue) + .padding() + .cornerRadius(10) + } + } + } + } + + private struct PatientInfo: View { + @Environment(DataStore.self) private var data + @Environment(NavigationPathWrapper.self) private var navigationPath + + var body: some View { + Section(header: headerTitle) { + VStack(alignment: .leading) { + HStack { + Text("Name:") + .bold() + Text(data.generalData.name) + } + HStack { + Text("Date of Birth:") + .bold() + Text(data.generalData.birthdate) + } + HStack { + Text("Age") + .bold() + Text(data.generalData.age) + } + HStack { + Text("Sex") + .bold() + Text(data.generalData.sex) + } + } + } + } + + var headerTitle: some View { + HStack { + Text("Patient Information") + Spacer() + Button(action: { + navigationPath.path.append(NavigationViews.patient) + }) { + Text("EDIT") + .foregroundColor(.blue) + .padding() + .cornerRadius(10) + } + } + } + } } -//struct DetailRow: View { -// var label: String -// var value: String -// -// var body: some View { -// HStack { -// Text(label) -// Spacer() -// Text(value) -// } -// } -//} struct DetailSection: View { var header: String @@ -121,8 +247,6 @@ struct DetailSection: View { } - - #Preview { ScrollablePDF() .previewWith { From b69721f5976682c3835096332732c5ac274bc619 Mon Sep 17 00:00:00 2001 From: apgupta3303 Date: Tue, 5 Mar 2024 17:33:51 -0800 Subject: [PATCH 4/8] adding scrollable view --- Intake.xcodeproj/project.pbxproj | 75 +- .../xcshareddata/swiftpm/Package.resolved | 383 ---------- Intake/Allergy Records/AllergyRecords.swift | 10 +- Intake/Allergy Records/ReactionPDF.swift | 59 ++ Intake/ChiefComplaint/LLMInteraction.swift | 166 ++-- Intake/EditPatient.swift | 6 + Intake/Elements.swift | 5 +- Intake/Home.swift | 11 +- Intake/Intake.swift | 9 +- .../Medical History/MedicalHistoryView.swift | 4 +- Intake/Medication View/IntakeDosage.swift | 20 + Intake/Medication View/IntakeMedication.swift | 21 + .../IntakeMedicationInstance.swift | 30 + .../IntakeMedicationViewModel.swift | 133 ++++ .../MedicationContentView.swift | 51 ++ Intake/MedicationView.swift | 102 --- Intake/Mock Data/FHIRStore+Extensions.swift | 101 +-- Intake/Resources/Localizable.xcstrings | 707 +++++++++++++++++- ..._ad134528-56a5-35fd-c37f-466ff119c625.json | 0 ...8-56a5-35fd-c37f-466ff119c625.json.license | 0 ..._5b3645de-a2d0-d016-0839-bab3757c4c58.json | 0 ...e-a2d0-d016-0839-bab3757c4c58.json.license | 0 ..._9c3df38a-d3b7-2198-3898-51f9153d023d.json | 0 ...a-d3b7-2198-3898-51f9153d023d.json.license | 0 ..._ed70a28f-30b2-acb7-658a-8b340dadd685.json | 0 ...f-30b2-acb7-658a-8b340dadd685.json.license | 0 ..._e0e1f21a-22a7-d166-7bb1-63f6bbce1a32.json | 0 ...a-22a7-d166-7bb1-63f6bbce1a32.json.license | 0 ..._d66b5418-06cb-fc8a-8c13-85685b6ac939.json | 0 ...8-06cb-fc8a-8c13-85685b6ac939.json.license | 0 Intake/ScrollablePDF.swift | 274 +++---- Intake/SocialHistory/MenstrualHistory.swift | 212 ++++++ Intake/SocialHistory/SmokingHistory.swift | 72 ++ .../SocialHistoryQuestions.swift | 280 ------- IntakeUITests/LaunchTests.swift | 1 + 35 files changed, 1641 insertions(+), 1091 deletions(-) delete mode 100644 Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 Intake/Allergy Records/ReactionPDF.swift create mode 100644 Intake/Medication View/IntakeDosage.swift create mode 100644 Intake/Medication View/IntakeMedication.swift create mode 100644 Intake/Medication View/IntakeMedicationInstance.swift create mode 100644 Intake/Medication View/IntakeMedicationViewModel.swift create mode 100644 Intake/Medication View/MedicationContentView.swift delete mode 100644 Intake/MedicationView.swift rename Intake/Resources/{Mock Patients => MockPatients}/Allen322_Ferry570_ad134528-56a5-35fd-c37f-466ff119c625.json (100%) rename Intake/Resources/{Mock Patients => MockPatients}/Allen322_Ferry570_ad134528-56a5-35fd-c37f-466ff119c625.json.license (100%) rename Intake/Resources/{Mock Patients => MockPatients}/Beatris270_Bogan287_5b3645de-a2d0-d016-0839-bab3757c4c58.json (100%) rename Intake/Resources/{Mock Patients => MockPatients}/Beatris270_Bogan287_5b3645de-a2d0-d016-0839-bab3757c4c58.json.license (100%) rename Intake/Resources/{Mock Patients => MockPatients}/Edythe31_Morar593_9c3df38a-d3b7-2198-3898-51f9153d023d.json (100%) rename Intake/Resources/{Mock Patients => MockPatients}/Edythe31_Morar593_9c3df38a-d3b7-2198-3898-51f9153d023d.json.license (100%) rename Intake/Resources/{Mock Patients => MockPatients}/Gonzalo160_Duenas839_ed70a28f-30b2-acb7-658a-8b340dadd685.json (100%) rename Intake/Resources/{Mock Patients => MockPatients}/Gonzalo160_Duenas839_ed70a28f-30b2-acb7-658a-8b340dadd685.json.license (100%) rename Intake/Resources/{Mock Patients => MockPatients}/Jacklyn830_Veum823_e0e1f21a-22a7-d166-7bb1-63f6bbce1a32.json (100%) rename Intake/Resources/{Mock Patients => MockPatients}/Jacklyn830_Veum823_e0e1f21a-22a7-d166-7bb1-63f6bbce1a32.json.license (100%) rename Intake/Resources/{Mock Patients => MockPatients}/Milton509_Ortiz186_d66b5418-06cb-fc8a-8c13-85685b6ac939.json (100%) rename Intake/Resources/{Mock Patients => MockPatients}/Milton509_Ortiz186_d66b5418-06cb-fc8a-8c13-85685b6ac939.json.license (100%) create mode 100644 Intake/SocialHistory/MenstrualHistory.swift create mode 100644 Intake/SocialHistory/SmokingHistory.swift delete mode 100644 Intake/SocialHistory/SocialHistoryQuestions.swift diff --git a/Intake.xcodeproj/project.pbxproj b/Intake.xcodeproj/project.pbxproj index 7d2131e..c391aa3 100644 --- a/Intake.xcodeproj/project.pbxproj +++ b/Intake.xcodeproj/project.pbxproj @@ -58,7 +58,12 @@ 2FF53D8B2A8725DE00042B76 /* SpeziMockWebService in Frameworks */ = {isa = PBXBuildFile; productRef = 2FF53D8A2A8725DE00042B76 /* SpeziMockWebService */; }; 2FF53D8D2A8729D600042B76 /* IntakeStandard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FF53D8C2A8729D600042B76 /* IntakeStandard.swift */; }; 511827962B740192002033A0 /* SurgeryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 511827952B740191002033A0 /* SurgeryView.swift */; }; - 511827982B7401A8002033A0 /* MedicationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 511827972B7401A8002033A0 /* MedicationView.swift */; }; + 51805C122B81853800D17109 /* IntakeMedication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51805C112B81853700D17109 /* IntakeMedication.swift */; }; + 51805C152B81857100D17109 /* IntakeMedicationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51805C142B81857100D17109 /* IntakeMedicationViewModel.swift */; }; + 51805C182B81898700D17109 /* SpeziMedication in Frameworks */ = {isa = PBXBuildFile; productRef = 51805C172B81898700D17109 /* SpeziMedication */; }; + 51805C1A2B818A1A00D17109 /* IntakeDosage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51805C192B818A1A00D17109 /* IntakeDosage.swift */; }; + 51805C1D2B818A4400D17109 /* IntakeMedicationInstance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51805C1C2B818A4400D17109 /* IntakeMedicationInstance.swift */; }; + 51A027672B82CDA300A195C8 /* MedicationContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51A027662B82CDA300A195C8 /* MedicationContentView.swift */; }; 5661551D2AB8384200209B80 /* SwiftPackageList in Frameworks */ = {isa = PBXBuildFile; productRef = 5661551C2AB8384200209B80 /* SwiftPackageList */; }; 566155292AB8447C00209B80 /* Package+LicenseType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 566155282AB8447C00209B80 /* Package+LicenseType.swift */; }; 5661552E2AB854C000209B80 /* PackageHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5661552D2AB854C000209B80 /* PackageHelper.swift */; }; @@ -90,6 +95,8 @@ 5AEA5F2C2B8680F300F1577A /* AddAllergy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA5F2B2B8680F300F1577A /* AddAllergy.swift */; }; 5AEA5F3B2B90081B00F1577A /* ScrollablePDF.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA5F3A2B90081B00F1577A /* ScrollablePDF.swift */; }; 5AEA5F422B90710B00F1577A /* EditPatient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA5F412B90710B00F1577A /* EditPatient.swift */; }; + 5AEA5F472B93034A00F1577A /* ReactionPDF.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA5F462B93034A00F1577A /* ReactionPDF.swift */; }; + 5AEA5F4A2B96F63A00F1577A /* AllergyLLMAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA5F492B96F63A00F1577A /* AllergyLLMAssistant.swift */; }; 637BE1D52B572B4800EA19C6 /* Questionnaire.json.license in Resources */ = {isa = PBXBuildFile; fileRef = 637BE1D42B572B4800EA19C6 /* Questionnaire.json.license */; }; 653A2551283387FE005D4D48 /* Intake.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653A2550283387FE005D4D48 /* Intake.swift */; }; 653A255528338800005D4D48 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 653A255428338800005D4D48 /* Assets.xcassets */; }; @@ -101,8 +108,9 @@ A9D83F962B083794000D0C78 /* SpeziFirebaseAccountStorage in Frameworks */ = {isa = PBXBuildFile; productRef = A9D83F952B083794000D0C78 /* SpeziFirebaseAccountStorage */; }; A9DFE8A92ABE551400428242 /* AccountButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9DFE8A82ABE551400428242 /* AccountButton.swift */; }; A9FE7AD02AA39BAB0077B045 /* AccountSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9FE7ACF2AA39BAB0077B045 /* AccountSheet.swift */; }; - AC2A17292B70686000F560D0 /* SocialHistoryQuestions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC2A17282B70686000F560D0 /* SocialHistoryQuestions.swift */; }; ACAA47812B571C800032D21F /* Questionnaire.json in Resources */ = {isa = PBXBuildFile; fileRef = ACAA47802B571C7F0032D21F /* Questionnaire.json */; }; + ACFFA1CE2B8FD7190006E6D4 /* SmokingHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACFFA1CD2B8FD7190006E6D4 /* SmokingHistory.swift */; }; + ACFFA1D12B8FD8BB0006E6D4 /* MenstrualHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACFFA1D02B8FD8BB0006E6D4 /* MenstrualHistory.swift */; }; F42AB1D22B6379B5002E13A6 /* SpeziLLM in Frameworks */ = {isa = PBXBuildFile; productRef = F42AB1D12B6379B5002E13A6 /* SpeziLLM */; }; F42AB1D42B6379B5002E13A6 /* SpeziLLMLocal in Frameworks */ = {isa = PBXBuildFile; productRef = F42AB1D32B6379B5002E13A6 /* SpeziLLMLocal */; }; F42AB1D62B6379B5002E13A6 /* SpeziLLMLocalDownload in Frameworks */ = {isa = PBXBuildFile; productRef = F42AB1D52B6379B5002E13A6 /* SpeziLLMLocalDownload */; }; @@ -166,7 +174,11 @@ 2FE5DCAC29EE6107004B9AB4 /* AccountOnboarding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountOnboarding.swift; sourceTree = ""; }; 2FF53D8C2A8729D600042B76 /* IntakeStandard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntakeStandard.swift; sourceTree = ""; }; 511827952B740191002033A0 /* SurgeryView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SurgeryView.swift; sourceTree = ""; }; - 511827972B7401A8002033A0 /* MedicationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MedicationView.swift; sourceTree = ""; }; + 51805C112B81853700D17109 /* IntakeMedication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntakeMedication.swift; sourceTree = ""; }; + 51805C142B81857100D17109 /* IntakeMedicationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntakeMedicationViewModel.swift; sourceTree = ""; }; + 51805C192B818A1A00D17109 /* IntakeDosage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntakeDosage.swift; sourceTree = ""; }; + 51805C1C2B818A4400D17109 /* IntakeMedicationInstance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntakeMedicationInstance.swift; sourceTree = ""; }; + 51A027662B82CDA300A195C8 /* MedicationContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MedicationContentView.swift; sourceTree = ""; }; 566155282AB8447C00209B80 /* Package+LicenseType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Package+LicenseType.swift"; sourceTree = ""; }; 5661552D2AB854C000209B80 /* PackageHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PackageHelper.swift; sourceTree = ""; }; 5680DD382AB8983D004E6D4A /* PackageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PackageCell.swift; sourceTree = ""; }; @@ -194,6 +206,8 @@ 5AEA5F2B2B8680F300F1577A /* AddAllergy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAllergy.swift; sourceTree = ""; }; 5AEA5F3A2B90081B00F1577A /* ScrollablePDF.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollablePDF.swift; sourceTree = ""; }; 5AEA5F412B90710B00F1577A /* EditPatient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditPatient.swift; sourceTree = ""; }; + 5AEA5F462B93034A00F1577A /* ReactionPDF.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionPDF.swift; sourceTree = ""; }; + 5AEA5F492B96F63A00F1577A /* AllergyLLMAssistant.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllergyLLMAssistant.swift; sourceTree = ""; }; 637BE1D42B572B4800EA19C6 /* Questionnaire.json.license */ = {isa = PBXFileReference; lastKnownFileType = text; path = Questionnaire.json.license; sourceTree = ""; }; 653A254D283387FE005D4D48 /* Intake.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Intake.app; sourceTree = BUILT_PRODUCTS_DIR; }; 653A2550283387FE005D4D48 /* Intake.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Intake.swift; sourceTree = ""; }; @@ -205,8 +219,9 @@ A9720E422ABB68CC00872D23 /* AccountSetupHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSetupHeader.swift; sourceTree = ""; }; A9DFE8A82ABE551400428242 /* AccountButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountButton.swift; sourceTree = ""; }; A9FE7ACF2AA39BAB0077B045 /* AccountSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSheet.swift; sourceTree = ""; }; - AC2A17282B70686000F560D0 /* SocialHistoryQuestions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialHistoryQuestions.swift; sourceTree = ""; }; ACAA47802B571C7F0032D21F /* Questionnaire.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Questionnaire.json; sourceTree = ""; }; + ACFFA1CD2B8FD7190006E6D4 /* SmokingHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmokingHistory.swift; sourceTree = ""; }; + ACFFA1D02B8FD8BB0006E6D4 /* MenstrualHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenstrualHistory.swift; sourceTree = ""; }; F42AB1DB2B637C8C002E13A6 /* LLMOnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LLMOnboardingView.swift; sourceTree = ""; }; F42AB1DE2B637C9C002E13A6 /* LLMInteraction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LLMInteraction.swift; sourceTree = ""; }; F42AB1E42B6383F9002E13A6 /* LLMOpenAITokenOnboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LLMOpenAITokenOnboarding.swift; sourceTree = ""; }; @@ -226,6 +241,7 @@ F42AB1D42B6379B5002E13A6 /* SpeziLLMLocal in Frameworks */, 2FB099AF2A875DF100B20952 /* FirebaseAuth in Frameworks */, 97D73D6A2AD860AD00B47FA0 /* SpeziFirebaseStorage in Frameworks */, + 51805C182B81898700D17109 /* SpeziMedication in Frameworks */, F42AB1D82B6379B5002E13A6 /* SpeziLLMOpenAI in Frameworks */, 2FE5DC6729EDD894004B9AB4 /* SpeziContact in Frameworks */, 5A0C1A1B2B69691000120506 /* SpeziFHIRHealthKit in Frameworks */, @@ -315,7 +331,7 @@ 2FE5DC2D29EDD792004B9AB4 /* Resources */ = { isa = PBXGroup; children = ( - 5A2B9F912B69E32A005CA63F /* Mock Patients */, + 5A2B9F912B69E32A005CA63F /* MockPatients */, 653A255428338800005D4D48 /* Assets.xcassets */, 2FA0BFEC2ACC977500E0EF83 /* Localizable.xcstrings */, 2FE5DC2C29EDD78E004B9AB4 /* ConsentDocument.md */, @@ -367,6 +383,18 @@ path = Surgery; sourceTree = ""; }; + 519E830A2B7C4F1600A2D92D /* Medication View */ = { + isa = PBXGroup; + children = ( + 51805C112B81853700D17109 /* IntakeMedication.swift */, + 51805C192B818A1A00D17109 /* IntakeDosage.swift */, + 51805C142B81857100D17109 /* IntakeMedicationViewModel.swift */, + 51805C1C2B818A4400D17109 /* IntakeMedicationInstance.swift */, + 51A027662B82CDA300A195C8 /* MedicationContentView.swift */, + ); + path = "Medication View"; + sourceTree = ""; + }; 56F6F29E2AB441640022FE5A /* Contributions */ = { isa = PBXGroup; children = ( @@ -405,7 +433,7 @@ path = "Mock Data"; sourceTree = ""; }; - 5A2B9F912B69E32A005CA63F /* Mock Patients */ = { + 5A2B9F912B69E32A005CA63F /* MockPatients */ = { isa = PBXGroup; children = ( 5A2B9F922B69E32A005CA63F /* Beatris270_Bogan287_5b3645de-a2d0-d016-0839-bab3757c4c58.json */, @@ -421,7 +449,7 @@ 5A2B9F9C2B69E32A005CA63F /* Edythe31_Morar593_9c3df38a-d3b7-2198-3898-51f9153d023d.json.license */, 5A2B9F9D2B69E32A005CA63F /* Milton509_Ortiz186_d66b5418-06cb-fc8a-8c13-85685b6ac939.json.license */, ); - path = "Mock Patients"; + path = MockPatients; sourceTree = ""; }; 5A2B9FB32B6AFE1F005CA63F /* Allergy Records */ = { @@ -429,7 +457,9 @@ children = ( 5A2B9FB52B6AFE5D005CA63F /* AllergyRecords.swift */, 5AEA5F2B2B8680F300F1577A /* AddAllergy.swift */, + 5AEA5F492B96F63A00F1577A /* AllergyLLMAssistant.swift */, 5A2B9FBB2B6C7B29005CA63F /* ReactionView.swift */, + 5AEA5F462B93034A00F1577A /* ReactionPDF.swift */, ); path = "Allergy Records"; sourceTree = ""; @@ -461,7 +491,7 @@ isa = PBXGroup; children = ( F4F4F8802B8C6FC5008FBEED /* Elements.swift */, - 511827972B7401A8002033A0 /* MedicationView.swift */, + 519E830A2B7C4F1600A2D92D /* Medication View */, 511827942B740191002033A0 /* Surgery */, AC2A17272B70684D00F560D0 /* SocialHistory */, 5A2B9FB32B6AFE1F005CA63F /* Allergy Records */, @@ -525,7 +555,8 @@ AC2A17272B70684D00F560D0 /* SocialHistory */ = { isa = PBXGroup; children = ( - AC2A17282B70686000F560D0 /* SocialHistoryQuestions.swift */, + ACFFA1D02B8FD8BB0006E6D4 /* MenstrualHistory.swift */, + ACFFA1CD2B8FD7190006E6D4 /* SmokingHistory.swift */, ); path = SocialHistory; sourceTree = ""; @@ -600,6 +631,7 @@ 5A0C1A182B69691000120506 /* SpeziFHIR */, 5A0C1A1A2B69691000120506 /* SpeziFHIRHealthKit */, 5A2B9F892B69E0AF005CA63F /* SpeziFHIRMockPatients */, + 51805C172B81898700D17109 /* SpeziMedication */, ); productName = Intake; productReference = 653A254D283387FE005D4D48 /* Intake.app */; @@ -696,6 +728,7 @@ 5661551B2AB8384200209B80 /* XCRemoteSwiftPackageReference "swift-package-list" */, F42AB1D02B6379B5002E13A6 /* XCRemoteSwiftPackageReference "SpeziLLM" */, 5A0C1A162B69667B00120506 /* XCRemoteSwiftPackageReference "SpeziFHIR" */, + 51805C162B81898700D17109 /* XCRemoteSwiftPackageReference "SpeziMedication" */, ); productRefGroup = 653A254E283387FE005D4D48 /* Products */; projectDirPath = ""; @@ -788,24 +821,27 @@ 2FE5DC4529EDD7F2004B9AB4 /* Binding+Negate.swift in Sources */, 2FC975A82978F11A00BA99FE /* Home.swift in Sources */, 2FE5DC4E29EDD7FA004B9AB4 /* ScheduleView.swift in Sources */, - AC2A17292B70686000F560D0 /* SocialHistoryQuestions.swift in Sources */, + 51805C1D2B818A4400D17109 /* IntakeMedicationInstance.swift in Sources */, A9DFE8A92ABE551400428242 /* AccountButton.swift in Sources */, 2FE5DC3729EDD7CA004B9AB4 /* OnboardingFlow.swift in Sources */, 2F1AC9DF2B4E840E00C24973 /* Intake.docc in Sources */, 2FF53D8D2A8729D600042B76 /* IntakeStandard.swift in Sources */, - 511827982B7401A8002033A0 /* MedicationView.swift in Sources */, 2FE5DC4729EDD7F2004B9AB4 /* CodableArray+RawRepresentable.swift in Sources */, 5A2B9FAB2B69E430005CA63F /* FHIRStore+Extensions.swift in Sources */, + 5AEA5F472B93034A00F1577A /* ReactionPDF.swift in Sources */, A9720E432ABB68CC00872D23 /* AccountSetupHeader.swift in Sources */, 5AEA5F2C2B8680F300F1577A /* AddAllergy.swift in Sources */, 2FE5DC4029EDD7EE004B9AB4 /* FeatureFlags.swift in Sources */, 2FE5DC4629EDD7F2004B9AB4 /* Bundle+Image.swift in Sources */, + ACFFA1CE2B8FD7190006E6D4 /* SmokingHistory.swift in Sources */, F42AB1DC2B637C8C002E13A6 /* LLMOnboardingView.swift in Sources */, 2FE5DC4F29EDD7FA004B9AB4 /* EventContext.swift in Sources */, 2FE5DC5029EDD7FA004B9AB4 /* EventContextView.swift in Sources */, 5A2B9F872B69E06B005CA63F /* ResourceSelection.swift in Sources */, 2F4E23832989D51F0013F3D9 /* IntakeTestingSetup.swift in Sources */, + 51805C152B81857100D17109 /* IntakeMedicationViewModel.swift in Sources */, 5A2B9F862B69E06B005CA63F /* SettingsView.swift in Sources */, + 51805C1A2B818A1A00D17109 /* IntakeDosage.swift in Sources */, F4F4F8812B8C6FC5008FBEED /* Elements.swift in Sources */, 2FE5DC5329EDD7FA004B9AB4 /* Bundle+Questionnaire.swift in Sources */, 5A2B9FB62B6AFE5D005CA63F /* AllergyRecords.swift in Sources */, @@ -816,14 +852,18 @@ 5A2B9FBC2B6C7B29005CA63F /* ReactionView.swift in Sources */, 566155292AB8447C00209B80 /* Package+LicenseType.swift in Sources */, 5680DD392AB8983D004E6D4A /* PackageCell.swift in Sources */, + ACFFA1D12B8FD8BB0006E6D4 /* MenstrualHistory.swift in Sources */, 5AEA5F422B90710B00F1577A /* EditPatient.swift in Sources */, F42AB1EC2B6DBF21002E13A6 /* SummaryView.swift in Sources */, + 5AEA5F4A2B96F63A00F1577A /* AllergyLLMAssistant.swift in Sources */, 2F5E32BD297E05EA003432F8 /* IntakeDelegate.swift in Sources */, 511827962B740192002033A0 /* SurgeryView.swift in Sources */, 2FE5DC5229EDD7FA004B9AB4 /* IntakeScheduler.swift in Sources */, 5AEA5F3B2B90081B00F1577A /* ScrollablePDF.swift in Sources */, F42AB1E52B6383F9002E13A6 /* LLMOpenAITokenOnboarding.swift in Sources */, + 51805C122B81853800D17109 /* IntakeMedication.swift in Sources */, A9FE7AD02AA39BAB0077B045 /* AccountSheet.swift in Sources */, + 51A027672B82CDA300A195C8 /* MedicationContentView.swift in Sources */, 653A2551283387FE005D4D48 /* Intake.swift in Sources */, 2FE5DC3629EDD7CA004B9AB4 /* HealthKitPermissions.swift in Sources */, 5661552E2AB854C000209B80 /* PackageHelper.swift in Sources */, @@ -1474,6 +1514,14 @@ minimumVersion = 1.0.0; }; }; + 51805C162B81898700D17109 /* XCRemoteSwiftPackageReference "SpeziMedication" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/StanfordSpezi/SpeziMedication.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.4.0; + }; + }; 5661551B2AB8384200209B80 /* XCRemoteSwiftPackageReference "swift-package-list" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/FelixHerrmann/swift-package-list"; @@ -1613,6 +1661,11 @@ package = 2FE750CA2A87240100723EAE /* XCRemoteSwiftPackageReference "SpeziMockWebService" */; productName = SpeziMockWebService; }; + 51805C172B81898700D17109 /* SpeziMedication */ = { + isa = XCSwiftPackageProductDependency; + package = 51805C162B81898700D17109 /* XCRemoteSwiftPackageReference "SpeziMedication" */; + productName = SpeziMedication; + }; 5661551C2AB8384200209B80 /* SwiftPackageList */ = { isa = XCSwiftPackageProductDependency; package = 5661551B2AB8384200209B80 /* XCRemoteSwiftPackageReference "swift-package-list" */; diff --git a/Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index 4c73220..0000000 --- a/Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,383 +0,0 @@ -{ - "pins" : [ - { - "identity" : "abseil-cpp-binary", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/abseil-cpp-binary.git", - "state" : { - "revision" : "bfc0b6f81adc06ce5121eb23f628473638d67c5c", - "version" : "1.2022062300.0" - } - }, - { - "identity" : "app-check", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/app-check.git", - "state" : { - "revision" : "3e464dad87dad2d29bb29a97836789bf0f8f67d2", - "version" : "10.18.1" - } - }, - { - "identity" : "fhirmodels", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/FHIRModels", - "state" : { - "revision" : "861afd5816a98d38f86220eab2f812d76cad84a0", - "version" : "0.5.0" - } - }, - { - "identity" : "firebase-ios-sdk", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/firebase-ios-sdk.git", - "state" : { - "revision" : "b880ec8ec927a838c51c12862c6222c30d7097d7", - "version" : "10.20.0" - } - }, - { - "identity" : "googleappmeasurement", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleAppMeasurement.git", - "state" : { - "revision" : "ceec9f28dea12b7cf3dabf18b5ed7621c88fd4aa", - "version" : "10.20.0" - } - }, - { - "identity" : "googledatatransport", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleDataTransport.git", - "state" : { - "revision" : "a732a4b47f59e4f725a2ea10f0c77e93a7131117", - "version" : "9.3.0" - } - }, - { - "identity" : "googleutilities", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleUtilities.git", - "state" : { - "revision" : "bc27fad73504f3d4af235de451f02ee22586ebd3", - "version" : "7.12.1" - } - }, - { - "identity" : "grpc-binary", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/grpc-binary.git", - "state" : { - "revision" : "a673bc2937fbe886dd1f99c401b01b6d977a9c98", - "version" : "1.49.1" - } - }, - { - "identity" : "gtm-session-fetcher", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/gtm-session-fetcher.git", - "state" : { - "revision" : "76135c9f4e1ac85459d5fec61b6f76ac47ab3a4c", - "version" : "3.3.1" - } - }, - { - "identity" : "healthkitonfhir", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/HealthKitOnFHIR.git", - "state" : { - "revision" : "825e96007d83ed83f81ee49eb3ebab29d7b7ba2f", - "version" : "0.2.5" - } - }, - { - "identity" : "interop-ios-for-google-sdks", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/interop-ios-for-google-sdks.git", - "state" : { - "revision" : "2d12673670417654f08f5f90fdd62926dc3a2648", - "version" : "100.0.0" - } - }, - { - "identity" : "leveldb", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/leveldb.git", - "state" : { - "revision" : "9d108e9112aa1d65ce508facf804674546116d9c", - "version" : "1.22.3" - } - }, - { - "identity" : "llama.cpp", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/llama.cpp", - "state" : { - "revision" : "b0611c7d3cb049822f9911878514e4706b80e2ac", - "version" : "0.1.8" - } - }, - { - "identity" : "nanopb", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/nanopb.git", - "state" : { - "revision" : "819d0a2173aff699fb8c364b6fb906f7cdb1a692", - "version" : "2.30909.0" - } - }, - { - "identity" : "openai", - "kind" : "remoteSourceControl", - "location" : "https://github.com/MacPaw/OpenAI", - "state" : { - "revision" : "35afc9a6ee127b8f22a85a31aec2036a987478af", - "version" : "0.2.6" - } - }, - { - "identity" : "promises", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/promises.git", - "state" : { - "revision" : "e70e889c0196c76d22759eb50d6a0270ca9f1d9e", - "version" : "2.3.1" - } - }, - { - "identity" : "researchkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/ResearchKit", - "state" : { - "revision" : "209164ed20592a2213c4bd69cefcb078d9de0692", - "version" : "2.2.21" - } - }, - { - "identity" : "researchkitonfhir", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/ResearchKitOnFHIR", - "state" : { - "revision" : "ea4d9691591594177e7dfbc8c246324855d73eb5", - "version" : "1.0.1" - } - }, - { - "identity" : "semaphore", - "kind" : "remoteSourceControl", - "location" : "https://github.com/groue/Semaphore.git", - "state" : { - "revision" : "f1c4a0acabeb591068dea6cffdd39660b86dec28", - "version" : "0.0.8" - } - }, - { - "identity" : "spezi", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/Spezi", - "state" : { - "revision" : "0ced3efbc2af9513c07ac913ad762c773a00a6c8", - "version" : "1.2.1" - } - }, - { - "identity" : "speziaccount", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziAccount.git", - "state" : { - "revision" : "714f01ae1e67bf9c1c0e7c07624380f9bea772b7", - "version" : "1.1.0" - } - }, - { - "identity" : "spezichat", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziChat.git", - "state" : { - "revision" : "eae5c15b211f18e09aa98de63ce119629320afeb", - "version" : "0.1.8" - } - }, - { - "identity" : "spezicontact", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziContact.git", - "state" : { - "revision" : "494b776f8c98d771e4a609a1fb706097dba4c030", - "version" : "1.0.0" - } - }, - { - "identity" : "spezifhir", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziFHIR.git", - "state" : { - "revision" : "9a171a21d7028042c30a24c661bfdfc6e363c9c3", - "version" : "0.6.0" - } - }, - { - "identity" : "spezifirebase", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziFirebase.git", - "state" : { - "revision" : "ca1edf678ec59e76c9869ee3448e6e165d9c2789", - "version" : "1.0.0" - } - }, - { - "identity" : "spezifoundation", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziFoundation.git", - "state" : { - "revision" : "662f25d6010a94faf4fd996e184617fcb2bf13d4", - "version" : "1.0.3" - } - }, - { - "identity" : "spezihealthkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziHealthKit.git", - "state" : { - "revision" : "b40695ffa4d1c9d58c5a0ee277640c2343fb5516", - "version" : "0.5.1" - } - }, - { - "identity" : "spezillm", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziLLM.git", - "state" : { - "revision" : "6892c5dfe258371b6f3287f02b8fec57a611ba70", - "version" : "0.7.0" - } - }, - { - "identity" : "spezimockwebservice", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziMockWebService.git", - "state" : { - "revision" : "b18067d3499e630bbd995ef05a296ef8fdd42528", - "version" : "1.0.0" - } - }, - { - "identity" : "spezionboarding", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziOnboarding", - "state" : { - "revision" : "91463ae190611bd14ef52b0657e8db3bf53c9ae8", - "version" : "1.1.0" - } - }, - { - "identity" : "speziquestionnaire", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziQuestionnaire.git", - "state" : { - "revision" : "fac0bb02f7027b4c09bd7afdad55eb7b47ec67f3", - "version" : "1.0.1" - } - }, - { - "identity" : "spezischeduler", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziScheduler.git", - "state" : { - "revision" : "adf793cb47dc199f8ae88f5c719f4d3ba06a4c4e", - "version" : "0.8.0" - } - }, - { - "identity" : "spezispeech", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziSpeech", - "state" : { - "revision" : "a1e1d021d8f605b5e6b23aee773115d7125a57e3", - "version" : "1.0.0" - } - }, - { - "identity" : "spezistorage", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziStorage.git", - "state" : { - "revision" : "eaed2220375c35400aa69d1f96a8d32b7e66b1c7", - "version" : "1.0.0" - } - }, - { - "identity" : "speziviews", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziViews.git", - "state" : { - "revision" : "d49f716e4a4d634604bb0dcd6d53df679b6c1358", - "version" : "1.3.0" - } - }, - { - "identity" : "swift-argument-parser", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-argument-parser", - "state" : { - "revision" : "c8ed701b513cf5177118a175d85fbbbcd707ab41", - "version" : "1.3.0" - } - }, - { - "identity" : "swift-collections", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-collections.git", - "state" : { - "revision" : "d029d9d39c87bed85b1c50adee7c41795261a192", - "version" : "1.0.6" - } - }, - { - "identity" : "swift-package-list", - "kind" : "remoteSourceControl", - "location" : "https://github.com/FelixHerrmann/swift-package-list", - "state" : { - "revision" : "412180a72b9a1f8262213c16459e3533b0385ea5", - "version" : "3.1.0" - } - }, - { - "identity" : "swift-protobuf", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-protobuf.git", - "state" : { - "revision" : "65e8f29b2d63c4e38e736b25c27b83e012159be8", - "version" : "1.25.2" - } - }, - { - "identity" : "xctestextensions", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/XCTestExtensions.git", - "state" : { - "revision" : "fb7fcee97c574b950e03b0a53874e26db27db2fe", - "version" : "0.4.8" - } - }, - { - "identity" : "xcthealthkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/XCTHealthKit.git", - "state" : { - "revision" : "6e9344a2d632b801d94fe3bbd1d891817e032103", - "version" : "0.3.5" - } - }, - { - "identity" : "xctruntimeassertions", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/XCTRuntimeAssertions", - "state" : { - "revision" : "51da3403f128b120705571ce61e0fe190f8889e6", - "version" : "1.0.1" - } - } - ], - "version" : 2 -} diff --git a/Intake/Allergy Records/AllergyRecords.swift b/Intake/Allergy Records/AllergyRecords.swift index aaef1df..9e84528 100644 --- a/Intake/Allergy Records/AllergyRecords.swift +++ b/Intake/Allergy Records/AllergyRecords.swift @@ -59,6 +59,7 @@ struct AllergyList: View { VStack { allergyForm SubmitButton(nextView: NavigationViews.social) + .padding() } .onAppear(perform: loadAllergies) .sheet(isPresented: $showingChat, content: chatSheetView) @@ -76,6 +77,9 @@ struct AllergyList: View { } .navigationBarItems(trailing: EditButton()) .navigationTitle("Allergies") + .navigationBarItems(trailing: NavigationLink(destination: AllergyLLMAssistant(presentingAccount: $presentingAccount)) { + Text("Chat") + }) } private var allergyEntries: some View { @@ -115,6 +119,10 @@ struct AllergyList: View { } } + private func submitAction() { + navigationPath.path.append(NavigationViews.menstrual) + } + private func addAllergyAction() { data.allergyData.append(AllergyItem(allergy: "", reaction: [])) self.selectedIndex = data.allergyData.count - 1 @@ -162,7 +170,7 @@ struct AllergyList: View { } } if !allergies.isEmpty { - for index in 0...(allergies.count - 1) { + for index in 0...(allergies.count - 1) where !data.allergyData.contains(where: { $0.allergy == allergies[index].string }) { data.allergyData.append( AllergyItem(allergy: allergies[index].string, reaction: allReactions[index]) ) diff --git a/Intake/Allergy Records/ReactionPDF.swift b/Intake/Allergy Records/ReactionPDF.swift new file mode 100644 index 0000000..0880972 --- /dev/null +++ b/Intake/Allergy Records/ReactionPDF.swift @@ -0,0 +1,59 @@ +// +// AddConditionView.swift +// Intake +// +// Created by Akash Gupta on 2/19/24. +// +// This source file is part of the Intake based on the Stanford Spezi Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import SpeziFHIR +import SwiftUI + + +struct ReactionPDF: View { + @State private var index: Int + @Environment(DataStore.self) private var data + @Binding private var showingReaction: Bool + var body: some View { + NavigationView { + VStack { + Form { + ForEach(data.allergyData[index].reaction) { item in + Text(item.reaction) + } + } +// .navigationTitle("Medical History") +//// .navigationTitle("\(data.allergyData[index].allergy) Reactions") +// .navigationBarItems(trailing: EditButton()) + } + .toolbar { + ToolbarItem(placement: .navigationBarLeading) { + HStack { + Text("\(data.allergyData[index].allergy) Reactions") + .lineLimit(1) // Ensure the title is single-lined + .truncationMode(.tail) + .font(.headline) // Adjust the font size if needed + } + } + } + } + } + + init(index: Int, showingReaction: Binding) { + self._index = State(initialValue: index) + self._showingReaction = showingReaction + } +} + +// #Preview { +// EditAllergyView(allergyItem: AllergyItem(allergy: "", reaction: []), showingReaction: <#T##Binding#>, allergyRecords: <#T##Binding<[AllergyItem]>#>, showingReaction: .constant(true), allergyRecords: .constant([])) +// .previewWith { +// FHIRStore() +// } +// } diff --git a/Intake/ChiefComplaint/LLMInteraction.swift b/Intake/ChiefComplaint/LLMInteraction.swift index 4fc2386..92bb2d0 100644 --- a/Intake/ChiefComplaint/LLMInteraction.swift +++ b/Intake/ChiefComplaint/LLMInteraction.swift @@ -11,12 +11,77 @@ // SPDX-License-Identifier: MIT // +import Foundation import SpeziChat +import SpeziFHIR import SpeziLLM import SpeziLLMLocal import SpeziLLMOpenAI import SwiftUI +func calculateAge(from dobString: String, with format: String = "yyyy-MM-dd") -> String { + if dobString.isEmpty { + return "" + } + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = format + + guard let birthDate = dateFormatter.date(from: dobString) else { + return "Invalid date format or date string." + } + + let ageComponents = Calendar.current.dateComponents([.year], from: birthDate, to: Date()) + if let age = ageComponents.year { + return "\(age)" + } else { + return "Could not calculate age" + } +} + +func getValue(forKey key: String, from jsonString: String) -> String? { + guard let jsonData = jsonString.data(using: .utf8) else { + print("Error: Cannot create Data from JSON string") + return nil + } + + do { + if let dictionary = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] { + if key == "name" { + if let nameArray = dictionary[key] as? [[String: Any]], !nameArray.isEmpty { + let nameDict = nameArray[0] // Accessing the first name object + if let family = nameDict["family"] as? String, + let givenArray = nameDict["given"] as? [String], + !givenArray.isEmpty { + let given = givenArray.joined(separator: " ") // Assuming there might be more than one given name + + return "\(given) \(family)" + } + } + } else { + return dictionary[key] as? String + } + } else { + print("Error: JSON is not a dictionary") + } + } catch { + print("Error: \(error.localizedDescription)") + } + + return nil +} + +func getInfo(patient: FHIRResource, field: String) -> String { + let jsonDescription = patient.jsonDescription + + if let infoValue = getValue(forKey: field, from: jsonDescription) { + print("Info found: \(infoValue)") + return infoValue + } + + print("Key \(field) not found") + return "" +} + struct LLMInteraction: View { @Observable @@ -36,11 +101,16 @@ struct LLMInteraction: View { static let name: String = "summarize_complaint" static let description: String = """ When there is enough information to give to the doctor,\ - summarize the conversation into a concise Chief Complaint. + summarize the conversation into a concise Chief Complaint.\ + Then call the summerize_complaint function. """ - - @Parameter(description: "A summary of the patient's primary concern.") var patientSummary: String - + + static let summaryDescription = """ + A summary of the patient's primary concern. Include a sentence introducing the patient's name,\ + age, and gender, if you have access to this information. + """ + @Parameter(description: summaryDescription) var patientSummary: String + let stringBox: StringBox init(stringBox: StringBox) { @@ -54,6 +124,8 @@ struct LLMInteraction: View { } } + @Environment(LLMRunner.self) var runner: LLMRunner + @Environment(FHIRStore.self) private var fhirStore @Environment(DataStore.self) private var data @Environment(NavigationPathWrapper.self) private var navigationPath @@ -62,8 +134,10 @@ struct LLMInteraction: View { @State var showOnboarding = true @State var greeting = true + @State var stringBox: StringBox = .init() - + @State var showSheet = false + var body: some View { @Bindable var data = data @@ -80,9 +154,42 @@ struct LLMInteraction: View { } .onAppear { + var fullName: String = "" + var firstName: String = "" + var dob: String = "" + var gender: String = "" + + if let patient = fhirStore.patient { + fullName = getInfo(patient: patient, field: "name").filter { !$0.isNumber } + dob = getInfo(patient: patient, field: "birthDate") + gender = getInfo(patient: patient, field: "gender") + + let age = calculateAge(from: dob) + let nameString = fullName.components(separatedBy: " ") + + if let firstNameValue = nameString.first { + firstName = firstNameValue + } else { + print("First Name is empty") + } + + let systemMessage = """ + The first name of the patient is \(String(describing: firstName)) and the patient is \(String(describing: age))\ + years old. The patient's gender is \(String(describing: gender)) Please speak with\ + the patient as you would a person of this age group, using as simple words as possible\ + if the patient is young. Address them by their first name when you ask questions. + """ + session.context.append( + systemMessage: systemMessage + ) + } + if greeting { - let assistantMessage = ChatEntity(role: .assistant, content: "Hello! What brings you to the doctor's office?") - session.context.insert(assistantMessage, at: 0) + if firstName.isEmpty { + session.context.append(assistantOutput: "Hello! What brings you to the doctor's office?") + } else { + session.context.append(assistantOutput: "Hello \(String(describing: firstName))! What brings you to the doctor's office?") + } } greeting = false } @@ -92,8 +199,8 @@ struct LLMInteraction: View { self.showSummary() } } - - init(presentingAccount: Binding) { // swiftlint:disable:this function_body_length + + init(presentingAccount: Binding) { self._presentingAccount = presentingAccount let temporaryStringBox = StringBox() self.stringBox = temporaryStringBox @@ -101,46 +208,7 @@ struct LLMInteraction: View { schema: LLMOpenAISchema( parameters: .init( modelType: .gpt3_5Turbo, - systemPrompt: """ - Pretend you are a nurse. Your job is to gather information about the medical concern of a patient.\ - Your job is to provide a summary of the patient’s chief medical complaint to the doctor so that the doctor\ - has all of the information they need to begin the appointment. Ask questions specific to the concern of the\ - patient in order to help clarify their chief complaint into a concise, specific concern. Ask the patient to\ - elaborate a little bit if you feel that they are not providing sufficient information. You should always ask about\ - severity and onset, and if relevant to the specific condition, you might specific questions about the location,\ - laterality, triggers, character, timing, description, progression, and associated symptoms unique to the complaint.\ - Ask with empathy.\ - Headache:\ - Onset: When did the headache start? Location: Where is the pain located? Duration: How long does each headache episode last?\ - Severity: On a scale of 1 to 10, how would you rate the pain? Triggers: Are there any specific triggers\ - that seem to bring on the headache? Associated Symptoms: Do you experience nausea, vomiting, sensitivity to light or sound?\ - Abdominal Pain:\ - Location: Where is the pain located abdomen? Character: How would you describe the pain (e.g., sharp, dull, cramping)?\ - Severity: On a scale of 1 to 10, how severe is the pain? Timing: Does the pain come and go, or is it constant?\ - Associated Symptoms: Any nausea, vomiting, or other changes in your bowl?\ - Fever:\ - Temperature: What is your current temperature?\ - Onset: When did the fever start?\ - Duration: How long have you had the fever?\ - Associated Symptoms: Any chills, sweating, body aches?\ - Recent Travel or Exposure: Have you traveled recently?\ - Have you been around anyone who was sick? - Rash:\ - Onset: When did the rash first appear? Location: Where is the rash located on your body? Description: How would you\ - describe the rash (e.g., raised, itchy, red)? Progression: Has the rash changed in appearance since it first appeared?\ - Associated Symptoms: Any fever, itching, pain?\ - Joint Pain:\ - Location: Which joints are affected? Onset: When did the joint pain start? Character: How would you describe the pain\ - (e.g., sharp, dull, achy)? Timing: Does the pain occur at specific times of the day or with certain activities?\ - Associated Symptoms: Any swelling, redness, stiffness?\ - Fatigue: Onset: When did you start feeling fatigued? Duration: How long have you been experiencing fatigue?\ - Severity: On a scale of 1 to 10, how would you rate your fatigue? Triggers: Is there anything that seems to\ - make your fatigue better or worse? Associated Symptoms: Any changes in appetite, sleep disturbances?\ - As you can see by the examples, you should ask questions specific to the patient's symptoms. If relevant, you should\ - ask follow-up questions to the patient's responses in order to gather more information if you feel it is needed. \ - Please use everyday layman terms and avoid using complex medical terminology.\ - Only ask one question or prompt at a time, and keep your questions brief (one to two short sentences). - """ + systemPrompt: "CHIEF_COMPLAINT_SYSTEM_PROMPT".localized().localizedString() ) ) { SummarizeFunction(stringBox: temporaryStringBox) diff --git a/Intake/EditPatient.swift b/Intake/EditPatient.swift index 233faa3..d5e5f6f 100644 --- a/Intake/EditPatient.swift +++ b/Intake/EditPatient.swift @@ -4,6 +4,12 @@ // // Created by Akash Gupta on 2/29/24. // +// This source file is part of the Intake based on the Stanford Spezi Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// import Foundation import SwiftUI diff --git a/Intake/Elements.swift b/Intake/Elements.swift index b291110..fc8e220 100644 --- a/Intake/Elements.swift +++ b/Intake/Elements.swift @@ -31,13 +31,12 @@ struct SkipButton: View { struct SubmitButton: View { @Environment(NavigationPathWrapper.self) private var navigationPath + @Environment(ReachedEndWrapper.self) private var end var nextView: NavigationViews var body: some View { Button(action: { - // Save output to Firestore and navigate to next screen - // Still need to save output to Firestore - if reachedEnd { + if end.reachedEnd { navigationPath.path.append(NavigationViews.pdfs) } else { navigationPath.path.append(nextView) diff --git a/Intake/Home.swift b/Intake/Home.swift index c59ddd8..99f594f 100644 --- a/Intake/Home.swift +++ b/Intake/Home.swift @@ -14,7 +14,8 @@ enum NavigationViews: String { case allergies case surgical case medical - case social + case menstrual + case smoking case medication case chat case concern @@ -90,12 +91,14 @@ struct HomeView: View { .navigationDestination(for: NavigationViews.self) { view in switch view { - case .chat: LLMInteraction(presentingAccount: $presentingAccount) - case .allergies: AllergyList() + case .smoking: SmokingHistoryView() +// case .chat: LLMAssistantView(presentingAccount: $presentingAccount) +// case .allergies: AllergyList() case .surgical: SurgeryView() case .medical: MedicalHistoryView() case .social: ScrollablePDF() - case .medication: MedicationView() + case .medication: MedicationContentView() + case .menstrual: SocialHistoryQuestionView() case .concern: SummaryView(chiefComplaint: $data.chiefComplaint) case .patient: EditPatientView() case .pdfs: ScrollablePDF() diff --git a/Intake/Intake.swift b/Intake/Intake.swift index 85dcc0f..759212f 100644 --- a/Intake/Intake.swift +++ b/Intake/Intake.swift @@ -26,12 +26,17 @@ struct PatientData { class DataStore { var allergyData: [AllergyItem] = [] var conditionData: [MedicalHistoryItem] = [] - var medicationData: [MedicationItem] = [] + var medicationData: Set = [] var surgeries: [SurgeryItem] = [] var chiefComplaint: String = "" var generalData = PatientData(name: "Akash", birthdate: "01/08/2003", age: "21", sex: "Male") } +@Observable +class ReachedEndWrapper { + var reachedEnd = false +} + @main struct Intake: App { @UIApplicationDelegateAdaptor(IntakeDelegate.self) var appDelegate @@ -39,6 +44,7 @@ struct Intake: App { let navigationPath = NavigationPathWrapper() let data = DataStore() + let reachedEnd = ReachedEndWrapper() var body: some Scene { WindowGroup { @@ -56,6 +62,7 @@ struct Intake: App { .spezi(appDelegate) .environment(navigationPath) .environment(data) + .environment(reachedEnd) } } } diff --git a/Intake/Medical History/MedicalHistoryView.swift b/Intake/Medical History/MedicalHistoryView.swift index 2b68545..fad2c6c 100644 --- a/Intake/Medical History/MedicalHistoryView.swift +++ b/Intake/Medical History/MedicalHistoryView.swift @@ -32,6 +32,7 @@ struct MedicalHistoryView: View { VStack { medicalHistoryForm SubmitButton(nextView: NavigationViews.surgical) + .padding() } .onAppear(perform: loadConditions) .sheet(isPresented: $showingChat, content: chatSheetView) @@ -47,9 +48,6 @@ struct MedicalHistoryView: View { } .navigationTitle("Medical History") .navigationBarItems(trailing: EditButton()) - .sheet(isPresented: $showAddSheet) { - // Your add condition sheet content here - } } private var conditionEntries: some View { diff --git a/Intake/Medication View/IntakeDosage.swift b/Intake/Medication View/IntakeDosage.swift new file mode 100644 index 0000000..8641810 --- /dev/null +++ b/Intake/Medication View/IntakeDosage.swift @@ -0,0 +1,20 @@ +// +// IntakeDosage.swift +// Intake +// +// Created by Kate Callon on 2/17/24. +// +// +// This source file is part of the Intake based on the Stanford Spezi Template Medication project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import SpeziMedication + +struct IntakeDosage: Dosage { + var localizedDescription: String +} diff --git a/Intake/Medication View/IntakeMedication.swift b/Intake/Medication View/IntakeMedication.swift new file mode 100644 index 0000000..b8ba5a1 --- /dev/null +++ b/Intake/Medication View/IntakeMedication.swift @@ -0,0 +1,21 @@ +// +// IntakeMedication.swift +// Intake +// +// Created by Kate Callon on 2/17/24. +// +// +// This source file is part of the Intake based on the Stanford Spezi Medication Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import SpeziMedication + +struct IntakeMedication: Medication, Comparable { + var localizedDescription: String + var dosages: [IntakeDosage] +} diff --git a/Intake/Medication View/IntakeMedicationInstance.swift b/Intake/Medication View/IntakeMedicationInstance.swift new file mode 100644 index 0000000..51f0140 --- /dev/null +++ b/Intake/Medication View/IntakeMedicationInstance.swift @@ -0,0 +1,30 @@ +// +// IntakeMedicationInstance.swift +// Intake +// +// Created by Kate Callon on 2/17/24. +// +// +// This source file is part of the Intake based on the Stanford Spezi Template Medication project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import SpeziMedication + +struct IntakeMedicationInstance: MedicationInstance, MedicationInstanceInitializable { + let id: UUID + let type: IntakeMedication + var dosage: IntakeDosage + var schedule: Schedule + + init(type: IntakeMedication, dosage: IntakeDosage, schedule: Schedule) { + self.id = UUID() + self.type = type + self.dosage = dosage + self.schedule = schedule + } +} diff --git a/Intake/Medication View/IntakeMedicationViewModel.swift b/Intake/Medication View/IntakeMedicationViewModel.swift new file mode 100644 index 0000000..acd28ca --- /dev/null +++ b/Intake/Medication View/IntakeMedicationViewModel.swift @@ -0,0 +1,133 @@ +// +// IntakeMedicationViewModel.swift +// Intake +// +// Created by Kate Callon on 2/17/24. +// +// +// This source file is part of the Intake based on the Stanford Spezi Template Medication project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import class ModelsR4.MedicationRequest +import Spezi +import SpeziFHIR +import SpeziMedication +import SwiftUI + +@Observable +class IntakeMedicationSettingsViewModel: Module, MedicationSettingsViewModel, CustomStringConvertible { + var medicationInstances: Set = [] + let medicationOptions: Set + + var description: String { + guard !medicationInstances.isEmpty else { + return "No Medications" + } + + return medicationInstances + .map { medicationInstance in + let scheduleDescription: String + switch medicationInstance.schedule.frequency { + case let .regularDayIntervals(dayInterval): + scheduleDescription = "RegularDayIntervals: \(dayInterval)" + case let .specificDaysOfWeek(weekdays): + scheduleDescription = "SpecificDaysOfWeek: \(weekdays)" + case .asNeeded: + scheduleDescription = "AsNeeded" + } + + return "\(medicationInstance.type.localizedDescription) - \(medicationInstance.dosage.localizedDescription) - \(scheduleDescription)" + } + .joined(separator: ", ") + } + + init(existingMedications: [FHIRResource]) { // swiftlint:disable:this function_body_length + self.medicationOptions = [ + IntakeMedication( + localizedDescription: "Hydrochlorothiazide 25 MG Oral Tablet", + dosages: [ + IntakeDosage(localizedDescription: "25 MG") + ] + ), + IntakeMedication( + localizedDescription: "Acetaminophen 160 MG Chewable Tablet", + dosages: [ + IntakeDosage(localizedDescription: "160 MG") + ] + ), + IntakeMedication( + localizedDescription: "Fexofenadine hydrochloride 30 MG Oral Tablet", + dosages: [ + IntakeDosage(localizedDescription: "30 MG") + ] + ), + IntakeMedication( + localizedDescription: "NDA020800 0.3 ML Epinephrine 1 MG/ML Auto-Injector", + dosages: [ + IntakeDosage(localizedDescription: "0.3ML / 1 MG/ML") + ] + ) + ] + + var foundMedications: [IntakeMedicationInstance] = [] + if !existingMedications.isEmpty { + for medication in existingMedications { + for option in medicationOptions where option.localizedDescription == medication.displayName { + var medSchedule: SpeziMedication.Schedule + let medRequest = medicationRequest(resource: medication) + if case .boolean(let asNeeded) = medRequest?.dosageInstruction?.first?.asNeeded { + if let asNeededbool = asNeeded.value?.bool { + if asNeededbool { + medSchedule = SpeziMedication.Schedule(frequency: .asNeeded) + } else { + let intValue: Int + let interval = medRequest?.dosageInstruction?.first?.timing?.repeat?.period?.value?.decimal + if let interval = interval { + intValue = interval.int + } else { + continue + } + medSchedule = Schedule(frequency: .regularDayIntervals(intValue)) + } + + guard let firstDosage = option.dosages.first else { + continue + } + + let intakeMedicationInstance = IntakeMedicationInstance( + type: option, + dosage: firstDosage, + schedule: medSchedule + ) + foundMedications.append(intakeMedicationInstance) + } + } + } + } + self.medicationInstances = Set(foundMedications) + } + } + func persist(medicationInstances: Set) async throws { + self.medicationInstances = medicationInstances + } + + func medicationRequest(resource: FHIRResource) -> MedicationRequest? { + guard case let .r4(resource) = resource.versionedResource, + let medicationRequest = resource as? ModelsR4.MedicationRequest else { + return nil + } + return medicationRequest + } +} + +extension Decimal { + var int: Int { + let intVal = NSDecimalNumber(decimal: self).intValue // swiftlint:disable:this legacy_objc_type + return intVal + } +} diff --git a/Intake/Medication View/MedicationContentView.swift b/Intake/Medication View/MedicationContentView.swift new file mode 100644 index 0000000..052c0fc --- /dev/null +++ b/Intake/Medication View/MedicationContentView.swift @@ -0,0 +1,51 @@ +// +// MedicationContentView.swift +// Intake +// +// Created by Kate Callon on 2/18/24. +// +// +// This source file is part of the Intake based on the Stanford Spezi Template Medication project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + +import Foundation +import SpeziFHIR +import SpeziMedication +import SwiftUI + +struct MedicationContentView: View { + @Environment(FHIRStore.self) private var fhirStore + @Environment(NavigationPathWrapper.self) private var navigationPath + @Environment(DataStore.self) private var data + @State private var presentSettings = false + + @State private var medicationSettingsViewModel: IntakeMedicationSettingsViewModel? + + var body: some View { + VStack { + if let medicationSettingsViewModel { + MedicationSettings(allowEmtpySave: true, medicationSettingsViewModel: medicationSettingsViewModel) { + data.medicationData = medicationSettingsViewModel.medicationInstances + navigationPath.path.append(NavigationViews.allergies) + } + .navigationTitle("Medication Settings") + } else { + ProgressView() + } + } + .task { + let patientMedications = fhirStore.llmMedications + self.medicationSettingsViewModel = IntakeMedicationSettingsViewModel(existingMedications: patientMedications) + } + } + + init() {} +} + +#Preview { + MedicationContentView() +} diff --git a/Intake/MedicationView.swift b/Intake/MedicationView.swift deleted file mode 100644 index 2efae8d..0000000 --- a/Intake/MedicationView.swift +++ /dev/null @@ -1,102 +0,0 @@ -// -// MedicationView.swift -// Intake -// -// Created by Kate Callon on 2/6/24. -// -// This source file is part of the Intake based on the Stanford Spezi Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import Foundation -import SpeziFHIR -import SwiftUI - -struct MedicationItem: Identifiable { - var id = UUID() - var medicationName: String -} - -struct MedicationView: View { - @Environment(FHIRStore.self) private var fhirStore - @Environment(NavigationPathWrapper.self) private var navigationPath - @State private var medications: [MedicationItem] = [] - - var body: some View { - NavigationView { // swiftlint:disable:this closure_body_length - VStack { // swiftlint:disable:this closure_body_length - List { - ForEach($medications) { $item in - HStack { - TextField("Medication", text: $item.medicationName) - Button(action: { - // Action to delete this item - if let index = medications.firstIndex(where: { $0.id == item.id }) { - medications.remove(at: index) - } - }) { - Image(systemName: "xmark.circle") - .accessibilityLabel(Text("DELETE_MEDICATION")) - } - } - } - .onDelete(perform: delete) - - Button(action: { - // Action to add new item - medications.append(MedicationItem(medicationName: "")) - }) { - HStack { - Image(systemName: "plus.circle.fill") - .accessibilityLabel(Text("ADD_MEDICATION")) - Text("Add Field") - } - } - } - .navigationBarTitleDisplayMode(.inline) - .toolbar { - ToolbarItem(placement: .principal) { - Text("Please list your current medications.") - .font(.system(size: 28)) // Choose a size that fits - .lineLimit(1) - .minimumScaleFactor(0.5) // Adjusts the font size to fit the width of the line - } - } - Button(action: { - // Save output to Firestore and navigate to next screen - // Still need to save output to Firestore - navigationPath.path.append(NavigationViews.allergies) - }) { - Text("Submit") - .foregroundColor(.white) - .padding() - .frame(maxWidth: .infinity) - .background(Color.blue) - .cornerRadius(8) - } - .padding() - } - .onAppear { - // Set a breakpoint on the next line to inspect `fhirStore.conditions` - let patientMedications = fhirStore.medications - for medication in patientMedications where !self.medications.contains(where: { $0.medicationName == medication.displayName }) { - self.medications.append(MedicationItem(medicationName: medication.displayName)) - } - } - } - } - - func delete(at offsets: IndexSet) { - medications.remove(atOffsets: offsets) - } - } - -#Preview { - MedicationView() - .previewWith { - FHIRStore() - } -} diff --git a/Intake/Mock Data/FHIRStore+Extensions.swift b/Intake/Mock Data/FHIRStore+Extensions.swift index fb90761..bf72109 100644 --- a/Intake/Mock Data/FHIRStore+Extensions.swift +++ b/Intake/Mock Data/FHIRStore+Extensions.swift @@ -63,8 +63,36 @@ extension FHIRStore { } ?? false } } + var llmMedications: [FHIRResource] { + let outpatientMedications = medications + .filter { medication in + guard let medicationRequest = medicationRequest(resource: medication), + medicationRequest.category? + .contains(where: { codableconcept in + codableconcept.text?.value?.string.lowercased() == "outpatient" + }) + ?? false else { + return false + } + + return true + } + .uniqueDisplayNames + + let activeMedications = medications + .filter { medication in + guard let medicationRequest = medicationRequest(resource: medication), + medicationRequest.status == .active else { + return false + } + + return true + } + .uniqueDisplayNames + + return outpatientMedications + activeMedications + } - private var llmMedications: [FHIRResource] { func medicationRequest(resource: FHIRResource) -> MedicationRequest? { guard case let .r4(resource) = resource.versionedResource, let medicationRequest = resource as? ModelsR4.MedicationRequest else { @@ -73,77 +101,6 @@ extension FHIRStore { return medicationRequest } - - let outpatientMedications = medications - .filter { medication in - guard let medicationRequest = medicationRequest(resource: medication), - medicationRequest.category? - .contains(where: { codableconcept in - codableconcept.text?.value?.string.lowercased() == "outpatient" - }) - ?? false else { - return false - } - - return true - } - .uniqueDisplayNames - - let activeMedications = medications - .filter { medication in - guard let medicationRequest = medicationRequest(resource: medication), - medicationRequest.status == .active else { - return false - } - - return true - } - .uniqueDisplayNames - - return outpatientMedications + activeMedications - } - -// var allResourcesFunctionCallIdentifier: [String] { -// @AppStorage(StorageKeys.resourceLimit) var resourceLimit = StorageKeys.Defaults.resourceLimit -// -// let relevantResources: [FHIRResource] -// -// if llmRelevantResources.count > resourceLimit { -// relevantResources = llmRelevantResources -// .lazy -// .filter { -// $0.date != nil -// } -// .sorted { -// $0.date ?? .distantPast < $1.date ?? .distantPast -// } -// .suffix(resourceLimit) -// } else { -// relevantResources = llmRelevantResources -// } -// -// return Array(Set(relevantResources.map { $0.functionCallIdentifier })) -// } -// -// -// func loadMockResources() { -// if FeatureFlags.testMode { -// let mockObservation = Observation( -// code: CodeableConcept(coding: [Coding(code: "1234".asFHIRStringPrimitive())]), -// id: FHIRPrimitive("1234"), -// issued: FHIRPrimitive(try? Instant(date: .now)), -// status: FHIRPrimitive(ObservationStatus.final) -// ) -// -// let mockFHIRResource = FHIRResource( -// versionedResource: .r4(mockObservation), -// displayName: "Mock Resource" -// ) -// -// removeAllResources() -// insert(resource: mockFHIRResource) -// } -// } } extension Array where Element == FHIRResource { diff --git a/Intake/Resources/Localizable.xcstrings b/Intake/Resources/Localizable.xcstrings index c448396..5cb9a1a 100644 --- a/Intake/Resources/Localizable.xcstrings +++ b/Intake/Resources/Localizable.xcstrings @@ -61,13 +61,682 @@ } } }, - "Active" : { + "Add Field" : { + + }, + "ADD_REACTION" : { + + }, + "ADD_SURGERY" : { + + }, + "Additional Details" : { + + }, + "Additional details: %@" : { + + }, + "Additional Symptoms" : { + + }, + "AI-assisted medical intake" : { + + }, + "Allergies" : { + + }, + "Allergy" : { + + }, + "Allergy Name" : { + + }, + "Auto-fill Intake Form" : { + + }, + "CHIEF_COMPLAINT_SYSTEM_PROMPT" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pretend you are a nurse. Your job is to gather information about the medical concern of a patient.\\\n Your job is to provide a summary of the patient’s chief medical complaint to the doctor so that the doctor\\\n has all of the information they need to begin the appointment. Ask questions specific to the concern of the\\\n patient in order to help clarify their chief complaint into a concise, specific concern. Ask the patient to\\\n elaborate a little bit if you feel that they are not providing sufficient information. You should always ask about\\\n severity and onset, and if relevant to the specific condition, you might specific questions about the location,\\\n laterality, triggers, character, timing, description, progression, and associated symptoms unique to the complaint. If you are able to find the answer to a question based on the patient's past responses, then do not ask the question. \\\n Ask with empathy.\\\n Headache:\\\n Onset: When did the headache start? Location: Where is the pain located? Duration: How long does each headache episode last?\\\n Severity: On a scale of 1 to 10, how would you rate the pain? Triggers: Are there any specific triggers\\\n that seem to bring on the headache? Associated Symptoms: Do you experience nausea, vomiting, sensitivity to light or sound?\\\n Abdominal Pain:\\\n Location: Where is the pain located abdomen? Character: How would you describe the pain (e.g., sharp, dull, cramping)?\\\n Severity: On a scale of 1 to 10, how severe is the pain? Timing: Does the pain come and go, or is it constant?\\\n Associated Symptoms: Any nausea, vomiting, or other changes in your bowl?\\\n Fever:\\\n Temperature: What is your current temperature?\\\n Onset: When did the fever start?\\\n Duration: How long have you had the fever?\\\n Associated Symptoms: Any chills, sweating, body aches?\\\n Recent Travel or Exposure: Have you traveled recently?\\\n Have you been around anyone who was sick?\n Rash:\\\n Onset: When did the rash first appear? Location: Where is the rash located on your body? Description: How would you\\\n describe the rash (e.g., raised, itchy, red)? Progression: Has the rash changed in appearance since it first appeared?\\\n Associated Symptoms: Any fever, itching, pain?\\\n Joint Pain:\\\n Location: Which joints are affected? Onset: When did the joint pain start? Character: How would you describe the pain\\\n (e.g., sharp, dull, achy)? Timing: Does the pain occur at specific times of the day or with certain activities?\\\n Associated Symptoms: Any swelling, redness, stiffness?\\\n Fatigue: Onset: When did you start feeling fatigued? Duration: How long have you been experiencing fatigue?\\\n Severity: On a scale of 1 to 10, how would you rate your fatigue? Triggers: Is there anything that seems to\\\n make your fatigue better or worse? Associated Symptoms: Any changes in appetite, sleep disturbances?\\\n As you can see by the examples, you should ask questions specific to the patient's symptoms. If relevant, you should\\\n ask follow-up questions to the patient's responses in order to gather more information if you feel it is needed. \\\n Please use everyday layman terms and avoid using complex medical terminology.\\\n Only ask one question or prompt at a time, and keep your questions brief (one to two short sentences).\\\n As a nurse, you should decline to answer any user inputs that are completely irrelevant to your objective of\\\n understanding your patient's chief complaint and past health history." + } + } + } + }, + "CLOSE" : { + "comment" : "MARK: General", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Close" + } + } + } + }, + "COMPLETED_TASK_LABEL %@" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Completed Task: %@" + } + } + } + }, + "Condition" : { + + }, + "CONSENT_LOADING_ERROR" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Please include a markdown based document named \"ConsentDocument\" in your module Bundle." + } + } + } + }, + "CONTACTS_NAVIGATION_TITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Contacts" + } + } + } + }, + "CONTACTS_TAB_TITLE" : { + "comment" : "MARK: - Contacts", + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Contacts" + } + } + } + }, + "CONTRIBUTIONS_LIST_DESCRIPTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The following list contains all Swift Package dependencies of the SpeziIntake." + } + } + } + }, + "CONTRIBUTIONS_LIST_FOOTER" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Please refer to the individual repository links for packages without license labels." + } + } + } + }, + "CONTRIBUTIONS_LIST_HEADER" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Packages" + } + } + } + }, + "DELETE_REACTION" : { + + }, + "DETAILS" : { + + }, + "Download your medical records from your health system." : { + + }, + "End Date: %@" : { + + }, + "END_CALENDAR" : { + + }, + "Ex: Heavy bleeding on second day, fatigue..." : { + + }, + "Ex: Smoked for 10 years, quit 5 years ago..." : { + + }, + "FHIR_RESOURCES_CHAT_CANCEL" : { + + }, + "Get Started" : { + + }, + "HEALTHKIT_PERMISSIONS_BUTTON" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Grant Access" + } + } + } + }, + "HEALTHKIT_PERMISSIONS_DESCRIPTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Intake will use your different types of your health records in order to most effectively aid you with your intake form." + } + } + } + }, + "HEALTHKIT_PERMISSIONS_SUBTITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Intake would like to access to your health records to fill out your intake form." + } + } + } + }, + "HEALTHKIT_PERMISSIONS_TITLE" : { + "comment" : "MARK: HealthKit", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "HealthKit Access" + } + } + } + }, + "Here is a summary of the Primary Concern" : { + + }, + "HOME_LOGO" : { + + }, + "How many days a year do you smoke?" : { + + }, + "How many packs do you smoke a day?" : { + + }, + "Integrate your Records" : { + + }, + "INTERESTING_MODULES_BUTTON" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Next" + } + } + } + }, + "It looks like an unexpected view was appended to the NavigationPath!" : { + + }, + "LICENSE_INFO_TITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "License Information" + } + } + } + }, + "List all your allgeries." : { + + }, + "List your current medications." : { + + }, + "Main reason(s) for visit" : { + + }, + "Medical History" : { + + }, + "Medical Intake Form" : { + + }, + "Medication Settings" : { + + }, + "Medications" : { + + }, + "Menstrual Information" : { + + }, + "Message" : { + + }, + "MOCK_ALLERGY_RECORDS_TITLE" : { + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Allergy Records" + } + } + } + }, + "MOCK_MEDICAL_HISTORY_TITLE" : { + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Medical History" + } + } + } + }, + "MOCK_MEDICATIONS_RECORDS_TITLE" : { + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Medications" + } + } + } + }, + "MOCK_SURGERY_RECORDS_TITLE" : { + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Surgery" + } + } + } + }, + "MOCK_WEB_SERVICE_TAB_TITLE" : { + "comment" : "MARK: - Mock Upload Data Storage Provider", + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Web Service" + } + } + } + }, + "Next" : { + + }, + "NOTIFICATION_PERMISSIONS_BUTTON" : { + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Allow Notifications" + } + } + } + }, + "NOTIFICATION_PERMISSIONS_DESCRIPTION" : { + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The Spezi Scheduler module enables to send out local notifications when a new event of a task is scheduled." + } + } + } + }, + "NOTIFICATION_PERMISSIONS_SUBTITLE" : { + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spezi Scheduler Notifications." + } + } + } + }, + "NOTIFICATION_PERMISSIONS_TITLE" : { + "comment" : "MARK: Notifications", + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Notifications" + } + } + } + }, + "OLIVER_AALAMI_BIO" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dr. Oliver O. Aalami is a Clinical Professor of Surgery at Stanford University and a vascular surgeon based in Palo Alto, California. He is affiliated with Stanford Health Care and the VA Palo Alto Health Care System.\nDr. Aalami is also the Director of Biodesign for Digital Health at the Stanford Byers Center for Biodesign. He co-founded Spezi (formerly CardinalKit) and is passionate about clinically validating smartphone and smartwatch sensors in patients with cardiovascular disease." + } + } + } + }, + "Other important questions." : { + + }, + "Pack years: %.2f" : { + + }, + "Please list conditions you have had" : { + + }, + "Primary Concern" : { + + }, + "PROJECT_LICENSE_DESCRIPTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "This project is licensed under the MIT License." + } + } + } + }, + "QUESTIONNAIRE_DESCRIPTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Please fill out the Questionnaire every day." + } + } + } + }, + "QUESTIONNAIRE_TITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Questionnaire" + } + } + } + }, + "Reactions" : { + + }, + "ReForm" : { + + }, + "Repository Link" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Repository Link" + } + } + } + }, + "Resource Selection" : { }, - "Add Field" : { + "Resource Settings" : { + + }, + "Review of Systems" : { + + }, + "Review summary of your medical history." : { + + }, + "Save" : { + + }, + "SCHEDULE_LIST_TITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Schedule" + } + } + } + }, + "SCHEDULE_TAB_TITLE" : { + "comment" : "MARK: - Schedule", + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Schedule" + } + } + } + }, + "Select End Date" : { + + }, + "Select Start Date" : { + + }, + "Select your last period's end date" : { + + }, + "Select your last period's start date" : { + + }, + "SETTINGS" : { + + }, + "SETTINGS_TITLE" : { + + }, + "Share with provider of your choice." : { + + }, + "Skip" : { + + }, + "Smoking History" : { + + }, + "Social History" : { + + }, + "Start" : { + + }, + "Start Date: %@" : { + + }, + "START_CALENDAR" : { + + }, + "Submit" : { + + }, + "Submit your Form" : { + + }, + "Summarize your medical history." : { + + }, + "Summarize your surgical history." : { + + }, + "Surgery" : { + + }, + "Surgery Name" : { + + }, + "Surgical History" : { + + }, + "Symptoms: %@" : { + + }, + "TASK_CONTEXT_ACTION_QUESTIONNAIRE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Start Questionnaire" + } + } + } + }, + "TASK_CONTEXT_ACTION_TEST" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Start Test" + } + } + } + }, + "TASK_LABEL %@" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Task: %@" + } + } + } + }, + "TASK_SOCIAL_SUPPORT_QUESTIONNAIRE_DESCRIPTION" : { + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Please fill out the Social Support Questionnaire every day." + } + } + } + }, + "TASK_SOCIAL_SUPPORT_QUESTIONNAIRE_TITLE" : { + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Social Support Questionnaire" + } + } + } + }, + "This application will help autocomplete your medical intake form." : { + + }, + "Together we will summarize..." : { + + }, + "Use HealthKit Resources" : { + + }, + "Welcome to ReForm" : { + + }, + "What are your current allergies?" : { + + }, + "What brings you in today? Identify your primary concern(s)." : { + + }, + "What is your surgical history?" : { + + }, + "Your Responses" : { +{ + "sourceLanguage" : "en", + "strings" : { + "*Check the box if you currently have the condition. /\n*Uncheck the box if you had the condition in the past" : { + + }, + "*Click the details to view/edit the reactions" : { + + }, + "%@ Reactions" : { + + }, + "ACCOUNT_NEXT" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Next" + } + } + } + }, + "ACCOUNT_SETUP_DESCRIPTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "You may login to your existing account. Or create a new one if you don't have one already. You will have to connect a name and email to your account. You may enter additional details such as your date of birth." + } + } + } + }, + "ACCOUNT_SIGNED_IN_DESCRIPTION" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "You are already logged in with the account shown below. Continue or change your account by logging out. You can also update your details of name, date of birth, and your preferred email." + } + } + } + }, + "ACCOUNT_SUBTITLE" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The Intake demonstrates the usage of the Firebase Account Module." + } + } + } + }, + "ACCOUNT_TITLE" : { + "comment" : "MARK: Account", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Your Account" + } + } + } + }, + "Active" : { }, - "ADD_MEDICATION" : { + "Add Field" : { }, "ADD_REACTION" : { @@ -90,6 +759,9 @@ }, "Allergy" : { + }, + "Allergy Assistant" : { + }, "Allergy Name" : { @@ -97,7 +769,7 @@ "Auto-fill Intake Form" : { }, - "Chief Complaint" : { + "Chat" : { }, "CLOSE" : { @@ -123,9 +795,6 @@ }, "Condition" : { - }, - "Conditions" : { - }, "CONSENT_LOADING_ERROR" : { "localizations" : { @@ -194,9 +863,6 @@ }, "Date of Birth:" : { - }, - "DELETE_MEDICATION" : { - }, "DELETE_REACTION" : { @@ -215,6 +881,9 @@ }, "END_CALENDAR" : { + }, + "Export to PDF" : { + }, "FHIR_RESOURCES_CHAT_CANCEL" : { @@ -319,7 +988,7 @@ "Medical Intake Form" : { }, - "Medication" : { + "Medication Settings" : { }, "Medications" : { @@ -459,15 +1128,9 @@ }, "Patient Form" : { - }, - "Patient Information" : { - }, "Please list conditions you have had" : { - }, - "Please list your current medications." : { - }, "Primary Concern" : { @@ -696,16 +1359,6 @@ }, "You can include decimal values (e.g., 0.25) for the number of packs per day." : { - }, - "Your last period was from %@ to %@" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "new", - "value" : "Your last period was from %1$@ to %2$@" - } - } - } } }, "version" : "1.0" diff --git a/Intake/Resources/Mock Patients/Allen322_Ferry570_ad134528-56a5-35fd-c37f-466ff119c625.json b/Intake/Resources/MockPatients/Allen322_Ferry570_ad134528-56a5-35fd-c37f-466ff119c625.json similarity index 100% rename from Intake/Resources/Mock Patients/Allen322_Ferry570_ad134528-56a5-35fd-c37f-466ff119c625.json rename to Intake/Resources/MockPatients/Allen322_Ferry570_ad134528-56a5-35fd-c37f-466ff119c625.json diff --git a/Intake/Resources/Mock Patients/Allen322_Ferry570_ad134528-56a5-35fd-c37f-466ff119c625.json.license b/Intake/Resources/MockPatients/Allen322_Ferry570_ad134528-56a5-35fd-c37f-466ff119c625.json.license similarity index 100% rename from Intake/Resources/Mock Patients/Allen322_Ferry570_ad134528-56a5-35fd-c37f-466ff119c625.json.license rename to Intake/Resources/MockPatients/Allen322_Ferry570_ad134528-56a5-35fd-c37f-466ff119c625.json.license diff --git a/Intake/Resources/Mock Patients/Beatris270_Bogan287_5b3645de-a2d0-d016-0839-bab3757c4c58.json b/Intake/Resources/MockPatients/Beatris270_Bogan287_5b3645de-a2d0-d016-0839-bab3757c4c58.json similarity index 100% rename from Intake/Resources/Mock Patients/Beatris270_Bogan287_5b3645de-a2d0-d016-0839-bab3757c4c58.json rename to Intake/Resources/MockPatients/Beatris270_Bogan287_5b3645de-a2d0-d016-0839-bab3757c4c58.json diff --git a/Intake/Resources/Mock Patients/Beatris270_Bogan287_5b3645de-a2d0-d016-0839-bab3757c4c58.json.license b/Intake/Resources/MockPatients/Beatris270_Bogan287_5b3645de-a2d0-d016-0839-bab3757c4c58.json.license similarity index 100% rename from Intake/Resources/Mock Patients/Beatris270_Bogan287_5b3645de-a2d0-d016-0839-bab3757c4c58.json.license rename to Intake/Resources/MockPatients/Beatris270_Bogan287_5b3645de-a2d0-d016-0839-bab3757c4c58.json.license diff --git a/Intake/Resources/Mock Patients/Edythe31_Morar593_9c3df38a-d3b7-2198-3898-51f9153d023d.json b/Intake/Resources/MockPatients/Edythe31_Morar593_9c3df38a-d3b7-2198-3898-51f9153d023d.json similarity index 100% rename from Intake/Resources/Mock Patients/Edythe31_Morar593_9c3df38a-d3b7-2198-3898-51f9153d023d.json rename to Intake/Resources/MockPatients/Edythe31_Morar593_9c3df38a-d3b7-2198-3898-51f9153d023d.json diff --git a/Intake/Resources/Mock Patients/Edythe31_Morar593_9c3df38a-d3b7-2198-3898-51f9153d023d.json.license b/Intake/Resources/MockPatients/Edythe31_Morar593_9c3df38a-d3b7-2198-3898-51f9153d023d.json.license similarity index 100% rename from Intake/Resources/Mock Patients/Edythe31_Morar593_9c3df38a-d3b7-2198-3898-51f9153d023d.json.license rename to Intake/Resources/MockPatients/Edythe31_Morar593_9c3df38a-d3b7-2198-3898-51f9153d023d.json.license diff --git a/Intake/Resources/Mock Patients/Gonzalo160_Duenas839_ed70a28f-30b2-acb7-658a-8b340dadd685.json b/Intake/Resources/MockPatients/Gonzalo160_Duenas839_ed70a28f-30b2-acb7-658a-8b340dadd685.json similarity index 100% rename from Intake/Resources/Mock Patients/Gonzalo160_Duenas839_ed70a28f-30b2-acb7-658a-8b340dadd685.json rename to Intake/Resources/MockPatients/Gonzalo160_Duenas839_ed70a28f-30b2-acb7-658a-8b340dadd685.json diff --git a/Intake/Resources/Mock Patients/Gonzalo160_Duenas839_ed70a28f-30b2-acb7-658a-8b340dadd685.json.license b/Intake/Resources/MockPatients/Gonzalo160_Duenas839_ed70a28f-30b2-acb7-658a-8b340dadd685.json.license similarity index 100% rename from Intake/Resources/Mock Patients/Gonzalo160_Duenas839_ed70a28f-30b2-acb7-658a-8b340dadd685.json.license rename to Intake/Resources/MockPatients/Gonzalo160_Duenas839_ed70a28f-30b2-acb7-658a-8b340dadd685.json.license diff --git a/Intake/Resources/Mock Patients/Jacklyn830_Veum823_e0e1f21a-22a7-d166-7bb1-63f6bbce1a32.json b/Intake/Resources/MockPatients/Jacklyn830_Veum823_e0e1f21a-22a7-d166-7bb1-63f6bbce1a32.json similarity index 100% rename from Intake/Resources/Mock Patients/Jacklyn830_Veum823_e0e1f21a-22a7-d166-7bb1-63f6bbce1a32.json rename to Intake/Resources/MockPatients/Jacklyn830_Veum823_e0e1f21a-22a7-d166-7bb1-63f6bbce1a32.json diff --git a/Intake/Resources/Mock Patients/Jacklyn830_Veum823_e0e1f21a-22a7-d166-7bb1-63f6bbce1a32.json.license b/Intake/Resources/MockPatients/Jacklyn830_Veum823_e0e1f21a-22a7-d166-7bb1-63f6bbce1a32.json.license similarity index 100% rename from Intake/Resources/Mock Patients/Jacklyn830_Veum823_e0e1f21a-22a7-d166-7bb1-63f6bbce1a32.json.license rename to Intake/Resources/MockPatients/Jacklyn830_Veum823_e0e1f21a-22a7-d166-7bb1-63f6bbce1a32.json.license diff --git a/Intake/Resources/Mock Patients/Milton509_Ortiz186_d66b5418-06cb-fc8a-8c13-85685b6ac939.json b/Intake/Resources/MockPatients/Milton509_Ortiz186_d66b5418-06cb-fc8a-8c13-85685b6ac939.json similarity index 100% rename from Intake/Resources/Mock Patients/Milton509_Ortiz186_d66b5418-06cb-fc8a-8c13-85685b6ac939.json rename to Intake/Resources/MockPatients/Milton509_Ortiz186_d66b5418-06cb-fc8a-8c13-85685b6ac939.json diff --git a/Intake/Resources/Mock Patients/Milton509_Ortiz186_d66b5418-06cb-fc8a-8c13-85685b6ac939.json.license b/Intake/Resources/MockPatients/Milton509_Ortiz186_d66b5418-06cb-fc8a-8c13-85685b6ac939.json.license similarity index 100% rename from Intake/Resources/Mock Patients/Milton509_Ortiz186_d66b5418-06cb-fc8a-8c13-85685b6ac939.json.license rename to Intake/Resources/MockPatients/Milton509_Ortiz186_d66b5418-06cb-fc8a-8c13-85685b6ac939.json.license diff --git a/Intake/ScrollablePDF.swift b/Intake/ScrollablePDF.swift index af682b4..7424a6f 100644 --- a/Intake/ScrollablePDF.swift +++ b/Intake/ScrollablePDF.swift @@ -4,74 +4,70 @@ // // Created by Akash Gupta on 2/28/24. // +// This source file is part of the Intake based on the Stanford Spezi Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// import Foundation import SpeziFHIR import SwiftUI -var reachedEnd = false -struct ScrollablePDF: View { - @Environment(DataStore.self) private var data +struct HeaderTitle: View { @Environment(NavigationPathWrapper.self) private var navigationPath + let title: String + var nextView: NavigationViews var body: some View { - Form { - PatientInfo() - ChiefComplaint() - ConditionSection() - SurgerySection() - medicationsSection - AllergySection() -// DatePicker("Last Menstrual Period", selection: $lastMenstrualPeriod, displayedComponents: .date) -// smokingHistorySection + HStack { + Text(title) + Spacer() + Button(action: { + navigationPath.path.append(nextView) + }) { + Text("EDIT") + .foregroundColor(.blue) + .padding() + .cornerRadius(10) + } } - .navigationTitle("Patient Form") - .onAppear(perform: { - reachedEnd = true - }) - } - - private var medicationsSection: some View { - DetailSection(header: "Medications:", content: ["Oxycontin 20mg, twice a day", "Lisinopril 5mg, once a day"]) } - - -// private var smokingHistorySection: some View { -// DetailRow(label: "Smoking History:", value: "20 pack years") -// } - +} + +struct ScrollablePDF: View { private struct ConditionSection: View { @Environment(DataStore.self) private var data @Environment(NavigationPathWrapper.self) private var navigationPath var body: some View { - Section(header: headerTitle) { - VStack(alignment: .leading) { - ForEach(data.conditionData) { item in // Removed id: \.self since items are Identifiable - HStack { - Text(item.condition) - .padding(.leading) - Spacer() - Text(item.active ? "Active" : "Inactive" ) - } + Section(header: HeaderTitle(title: "Conditions", nextView: NavigationViews.medical)) { + List(data.conditionData, id: \.id) { item in + HStack { + Text(item.condition) + Spacer() + Text(item.active ? "Active" : "Inactive") + .foregroundColor(.secondary) } } } } + } + + private struct ExportButton: View { + @Environment(NavigationPathWrapper.self) private var navigationPath - var headerTitle: some View { // Moved this inside ConditionSection - HStack { - Text("Conditions") - Spacer() - Button(action: { - navigationPath.path.append(NavigationViews.medical) - }) { - Text("EDIT") - .foregroundColor(.blue) - .padding() - .cornerRadius(10) - } + var body: some View { + Button(action: { + }) { + Text("Export to PDF") + .foregroundColor(.white) + .padding() + .frame(maxWidth: .infinity) + .background(Color.blue) + .cornerRadius(8) } } } @@ -81,69 +77,36 @@ struct ScrollablePDF: View { @Environment(NavigationPathWrapper.self) private var navigationPath var body: some View { - Section(header: headerTitle) { - VStack(alignment: .leading) { - ForEach(data.surgeries) { item in - HStack { - Text(item.surgeryName) - .padding(.leading) - Spacer() - Text(item.date ?? "") - } + Section(header: HeaderTitle(title: "Surgical History", nextView: NavigationViews.surgical)) { + List(data.surgeries, id: \.id) { item in + HStack { + Text(item.surgeryName) + Spacer() + Text(item.date ?? "") + .foregroundColor(.secondary) } } } } - - var headerTitle: some View { - HStack { - Text("Surgical History") - Spacer() - Button(action: { - navigationPath.path.append(NavigationViews.surgical) - }) { - Text("EDIT") - .foregroundColor(.blue) - .padding() - .cornerRadius(10) - } - } - } } - private struct AllergySection: View { + private struct MedicationSection: View { @Environment(DataStore.self) private var data @Environment(NavigationPathWrapper.self) private var navigationPath var body: some View { - Section(header: headerTitle) { + Section(header: HeaderTitle(title: "Medications", nextView: NavigationViews.medication)) { VStack(alignment: .leading) { - ForEach(data.allergyData) { item in - Text(item.allergy) - .padding(.leading) - ForEach(item.reaction) { reaction in - Text(reaction.reaction) - .padding(.leading, 50) + ForEach(Array(data.medicationData)) { item in + HStack { + Text(item.type.localizedDescription) + .padding(.leading) + Spacer() } } } } } - - var headerTitle: some View { - HStack { - Text("Allergies") - Spacer() - Button(action: { - navigationPath.path.append(NavigationViews.allergies) - }) { - Text("EDIT") - .foregroundColor(.blue) - .padding() - .cornerRadius(10) - } - } - } } private struct ChiefComplaint: View { @@ -151,105 +114,106 @@ struct ScrollablePDF: View { @Environment(NavigationPathWrapper.self) private var navigationPath var body: some View { - Section(header: headerTitle) { + Section(header: HeaderTitle(title: "Chief Complaint", nextView: NavigationViews.concern)) { Text(data.chiefComplaint) } } - - var headerTitle: some View { - HStack { - Text("Chief Complaint") - Spacer() - Button(action: { - navigationPath.path.append(NavigationViews.concern) - }) { - Text("EDIT") - .foregroundColor(.blue) - .padding() - .cornerRadius(10) - } - } - } } private struct PatientInfo: View { @Environment(DataStore.self) private var data @Environment(NavigationPathWrapper.self) private var navigationPath - var body: some View { - Section(header: headerTitle) { - VStack(alignment: .leading) { + Section(header: HeaderTitle(title: "Patient Information", nextView: NavigationViews.patient)) { + List { HStack { Text("Name:") - .bold() + Spacer() Text(data.generalData.name) + .foregroundColor(.secondary) } HStack { Text("Date of Birth:") - .bold() + Spacer() Text(data.generalData.birthdate) + .foregroundColor(.secondary) } HStack { Text("Age") - .bold() + Spacer() Text(data.generalData.age) + .foregroundColor(.secondary) } HStack { Text("Sex") - .bold() + Spacer() Text(data.generalData.sex) + .foregroundColor(.secondary) } } } } - - var headerTitle: some View { - HStack { - Text("Patient Information") - Spacer() - Button(action: { - navigationPath.path.append(NavigationViews.patient) - }) { - Text("EDIT") - .foregroundColor(.blue) - .padding() - .cornerRadius(10) + } + + private struct Allergy: View { + @Environment(DataStore.self) private var data + @State private var showingReaction = false + @State private var selectedIndex = 0 + var body: some View { + Section(header: HeaderTitle(title: "Allergy", nextView: NavigationViews.allergies)) { + List { + ForEach(0.. some View { + ReactionPDF(index: selectedIndex, showingReaction: $showingReaction) + } + + private func allergyButton(index: Int) -> some View { + Button(action: { + self.selectedIndex = index + self.showingReaction = true + }) { + HStack { + Text(data.allergyData[index].allergy) + .foregroundColor(.black) + Spacer() + Image(systemName: "chevron.right") + .foregroundColor(.gray) + .accessibilityLabel(Text("DETAILS")) } } } } - private var headerTitle: some View { - HStack { - Text(header) - Spacer() - EditButton() + + @Environment(DataStore.self) private var data + @Environment(NavigationPathWrapper.self) private var navigationPath + @Environment(ReachedEndWrapper.self) private var end + + + var body: some View { + VStack { + Form { + PatientInfo() + ChiefComplaint() + ConditionSection() + SurgerySection() + MedicationSection() + Allergy() + } + .navigationTitle("Patient Form") + .onAppear(perform: { + end.reachedEnd = true + }) + ExportButton() + .padding() } } } - -#Preview { - ScrollablePDF() - .previewWith { - FHIRStore() - } -} diff --git a/Intake/SocialHistory/MenstrualHistory.swift b/Intake/SocialHistory/MenstrualHistory.swift new file mode 100644 index 0000000..82ee93a --- /dev/null +++ b/Intake/SocialHistory/MenstrualHistory.swift @@ -0,0 +1,212 @@ +// +// MenstrualHistory.swift +// Intake +// +// Created by Zoya Garg on 2/28/24. +// +// This source file is part of the Intake based on the Stanford Spezi Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT + +import Foundation +import HealthKit +import SwiftUI + + +struct SectionHeader: View { + let title: String + let subtitle: String + + var body: some View { + VStack(alignment: .leading) { + Text(title) + .font(.title) + .multilineTextAlignment(.leading) + .padding(.bottom, 2) + + if !subtitle.isEmpty { + Text(subtitle) + .font(.subheadline) + .foregroundColor(.gray) + .multilineTextAlignment(.leading) + .padding(.bottom) + } + } + } +} + +struct SocialHistoryQuestionView: View { + struct SectionHeader: View { + let title: String + + var body: some View { + VStack(alignment: .leading) { + Text(title) + .font(.headline) + } + } + } + + private var menstrualCycleButtons: some View { + VStack { + Button(action: { + isSelectingStartDate = true + }) { + HStack { + Text("Select your last period's start date") + Spacer() // Add Spacer here for white space + Image(systemName: "calendar") + .accessibilityLabel(Text("START_CALENDAR")) + } + } + .buttonStyle(BorderlessButtonStyle()) + + Spacer().frame(height: 16) + + Button(action: { + isSelectingEndDate = true + }) { + HStack { + Text("Select your last period's end date") + Spacer() + Image(systemName: "calendar") + .accessibilityLabel(Text("END_CALENDAR")) + } + } + .buttonStyle(BorderlessButtonStyle()) + } + } + + private var menstrualCycleInformationSection: some View { + Group { + Section(header: Text("Menstrual Information").foregroundColor(.gray)) { + menstrualCycleButtons + } + + Section(header: Text("Additional Symptoms")) { + TextField("Ex: Heavy bleeding on second day, fatigue...", text: $additionalDetails) + } + if shouldDisplayResponses { + Section(header: Text("Your Responses").foregroundColor(.gray)) { + VStack(alignment: .leading) { + Text("Start Date: \(formatDate(startDate))") + Text("End Date: \(formatDate(endDate))") + if !additionalDetails.isEmpty { + Text("Symptoms: \(additionalDetails)") + } + } + } + } + } + } + + @State private var dateString: String = "" + @State private var additionalDetails: String = "" + @State private var isFemale = false + @State private var showMaleSlide = false + @State private var healthStore = HKHealthStore() + + @State private var isSelectingStartDate = false + @State private var isSelectingEndDate = false + @State private var startDate = Date() + @State private var endDate = Date() + @State private var lastPeriodDate: Date? + + @Environment(NavigationPathWrapper.self) private var navigationPath + + private var shouldDisplayResponses: Bool { + !additionalDetails.isEmpty || startDate != Date() || endDate != Date() + } + + + let numberFormatter: NumberFormatter = { + let formatter = NumberFormatter() + formatter.numberStyle = .decimal + formatter.minimum = 0 + return formatter + }() + + var body: some View { + NavigationView { // swiftlint:disable:this closure_body_length + VStack { // swiftlint:disable:this closure_body_length + Form { + menstrualCycleInformationSection + } + .navigationTitle("Social History") + .onAppear { + fetchHealthKitData() + } + .sheet(isPresented: $isSelectingStartDate, content: { + VStack { + DatePicker("Select Start Date", selection: $startDate, displayedComponents: .date) + .datePickerStyle(GraphicalDatePickerStyle()) + + Button("Save") { + lastPeriodDate = startDate + isSelectingStartDate = false + } + } + }) + .sheet(isPresented: $isSelectingEndDate, content: { + VStack { + DatePicker("Select End Date", selection: $endDate, displayedComponents: .date) + .datePickerStyle(GraphicalDatePickerStyle()) + + Button("Save") { + isSelectingEndDate = false + } + } + }) + Spacer() + Button(action: { + navigationPath.path.append(NavigationViews.smoking) + }) { + Text("Submit") + .foregroundColor(.white) + .padding() + .frame(maxWidth: .infinity) + .background(Color.blue) + .cornerRadius(8) + } + .padding() + } + } + } + + private func formatDate(_ date: Date) -> String { + let formatter = DateFormatter() + formatter.dateStyle = .medium + return formatter.string(from: date) + } + + private func fetchHealthKitData() { + let infoToRead = Set([HKObjectType.characteristicType(forIdentifier: .biologicalSex)].compactMap { $0 }) + + Task { + do { + try await healthStore.requestAuthorization(toShare: [], read: infoToRead) + + if let bioSex = try? healthStore.biologicalSex() { + DispatchQueue.main.async { + self.isFemale = getIsFemaleBiologicalSex(biologicalSex: bioSex.biologicalSex) + self.showMaleSlide = !self.isFemale + } + } + } catch { + print("HealthKit authorization failed: \(error.localizedDescription)") + } + } + } + + private func getIsFemaleBiologicalSex(biologicalSex: HKBiologicalSex) -> Bool { + switch biologicalSex { + case .female: return true + case .male: return false + case .other: return true + case .notSet: return false + @unknown default: return false + } + } +} diff --git a/Intake/SocialHistory/SmokingHistory.swift b/Intake/SocialHistory/SmokingHistory.swift new file mode 100644 index 0000000..7ba14cb --- /dev/null +++ b/Intake/SocialHistory/SmokingHistory.swift @@ -0,0 +1,72 @@ +// +// SmokingHistory.swift +// Intake +// +// Created by Zoya Garg on 2/28/24. +// +// This source file is part of the Intake based on the Stanford Spezi Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT + +import SwiftUI + + +struct SmokingHistoryView: View { + @State private var daysPerYear: String = "" + @State private var packsPerDay: String = "" + @State private var packYears: Double = 0 + @State private var additionalDetails: String = "" + + var body: some View { + NavigationView { + VStack { + Form { + Section(header: Text("Smoking History").foregroundColor(.gray)) { + TextField("How many days a year do you smoke?", text: $daysPerYear) + .keyboardType(.decimalPad) + .onChange(of: daysPerYear) { calculatePackYears() } + .padding(.bottom, 8) + + TextField("How many packs do you smoke a day?", text: $packsPerDay) + .keyboardType(.decimalPad) + .onChange(of: packsPerDay) { calculatePackYears() } + .padding(.bottom, 8) + } + + Section(header: Text("Additional Details").foregroundColor(.gray)) { + TextField("Ex: Smoked for 10 years, quit 5 years ago...", text: $additionalDetails) + } + + // This section will automatically update when values are entered + Section(header: Text("Your Responses").foregroundColor(.gray)) { + Text("Pack years: \(packYears, specifier: "%.2f")") + if !additionalDetails.isEmpty { + Text("Additional details: \(additionalDetails)") + } + } + } + .navigationTitle("Social History") + + // The Submit button can remain for explicit submission, if required + Button("Submit") { + calculatePackYears() + } + .foregroundColor(.white) + .padding() + .frame(maxWidth: .infinity) + .background(Color.blue) + .cornerRadius(8) + .padding(.horizontal) + .padding(.bottom) + } + } + } + + func calculatePackYears() { + let days = Double(daysPerYear) ?? 0 + let packs = Double(packsPerDay) ?? 0 + packYears = (days * packs) / 365 + } +} diff --git a/Intake/SocialHistory/SocialHistoryQuestions.swift b/Intake/SocialHistory/SocialHistoryQuestions.swift deleted file mode 100644 index de80e5c..0000000 --- a/Intake/SocialHistory/SocialHistoryQuestions.swift +++ /dev/null @@ -1,280 +0,0 @@ -// -// SocialHistoryQuestions.swift -// Intake -// -// Created by Zoya Garg on 2/4/24. -// -// This source file is part of the Intake based on the Stanford Spezi Template Application project -// -// SPDX-FileCopyrightText: 2023 Stanford University -// -// SPDX-License-Identifier: MIT -// - -import Foundation -import HealthKit -import SwiftUI - -struct SmokingSummaryView: View { - let startDate: Date - let endDate: Date - let additionalDetails: String - let totalPacksPerYear: Double - - var body: some View { - VStack { - Text("Thank you for completing Social History!") - .font(.title) - .multilineTextAlignment(.center) - .padding(.bottom) - - Text("Your last period was from \(formatDate(startDate)) to \(formatDate(endDate))") - .multilineTextAlignment(.center) - .padding(.bottom) - - if !additionalDetails.isEmpty { - Text("Additional details: \(additionalDetails)") - .multilineTextAlignment(.center) - .padding(.bottom) - } - - Text("Total calculated result for smoking: \(totalPacksPerYear, specifier: "%.2f") pack years") - .multilineTextAlignment(.center) - .padding(.bottom) - - Spacer() - } - .padding() - .navigationBarTitle("Summary", displayMode: .inline) // Set the navigation bar title for the summary view - } - - private func formatDate(_ date: Date) -> String { - let formatter = DateFormatter() - formatter.dateStyle = .long - return formatter.string(from: date) - } -} - -struct YesNoButtonView: View { - @State private var daysPerYear: Double? - @State private var packsPerDay: Double? - @State private var totalPacksPerYear: Double = 0 - @State private var navigateToSummary = false - - var startDate: Date - var endDate: Date - var additionalDetails: String - - let numberFormatter: NumberFormatter = { - let formatter = NumberFormatter() - formatter.numberStyle = .decimal - formatter.minimum = 0 - return formatter - }() - - var body: some View { - VStack(alignment: .leading, spacing: 16) { - Text("Do you currently smoke or have you in the past?") - .font(.title) - .foregroundColor(.blue) - - // Question 1 - TextField("How many days a year do you smoke?", value: $daysPerYear, formatter: numberFormatter) - .keyboardType(.decimalPad) - .textFieldStyle(RoundedBorderTextFieldStyle()) - .padding(.bottom, 8) - - Text("You can include decimal values (e.g., 0.25) for the number of packs per day.") - .font(.caption) - .foregroundColor(.gray) - - // Question 2 - TextField("How many packs do you smoke a day?", value: $packsPerDay, formatter: numberFormatter) - .keyboardType(.decimalPad) - .textFieldStyle(RoundedBorderTextFieldStyle()) - .padding(.bottom, 8) - - Button("Submit") { - calculateTotalPacksPerYear() - navigateToSummary = true - } - .padding() - .background(Color.blue) - .foregroundColor(.white) - .cornerRadius(10) - - // NOTE: Ask Zoya about deprecated NavigationLink -- replace with sheet? Integrate into main navigation stack? - NavigationLink( - destination: SmokingSummaryView( - startDate: startDate, - endDate: endDate, - additionalDetails: additionalDetails, - totalPacksPerYear: totalPacksPerYear - ), - isActive: $navigateToSummary - ) { - EmptyView() - } - } - .padding() - } - - func calculateTotalPacksPerYear() { - let days = daysPerYear ?? 0 - let packs = packsPerDay ?? 0 - totalPacksPerYear = days * packs - } -} - -struct SocialHistoryQuestionView: View { - struct SectionHeader: View { - let title: String - let subtitle: String - - var body: some View { - VStack(alignment: .leading) { - Text(title) - .font(.headline) - Text(subtitle) - .font(.subheadline) - .foregroundColor(.gray) - } - } - } - - private var menstrualCycleButtons: some View { - VStack { - Button(action: { - isSelectingStartDate = true - }) { - HStack { - Text("Select approx. start date.") - Spacer() // Add Spacer here for white space - Image(systemName: "calendar") - .accessibilityLabel(Text("START_CALENDAR")) - } - } - .buttonStyle(BorderlessButtonStyle()) - - Spacer().frame(height: 16) // White space between buttons - - Button(action: { - isSelectingEndDate = true - }) { - HStack { - Text("Select approx. end date.") - Spacer() - Image(systemName: "calendar") - .accessibilityLabel(Text("END_CALENDAR")) - } - } - .buttonStyle(BorderlessButtonStyle()) - } - } - - private var menstrualCycleInformationSection: some View { - Section(header: SectionHeader(title: "Menstrual Cycle Information", subtitle: "Select the dates of your last period.")) { - menstrualCycleButtons - TextField("Optional symptoms: heavy bleeding, cramps, etc.", text: $additionalDetails) - .textFieldStyle(RoundedBorderTextFieldStyle()) - } - } - - @State private var dateString: String = "" - @State private var additionalDetails: String = "" - @State private var isFemale = false - @State private var showMaleSlide = false - @State private var healthStore = HKHealthStore() - - @State private var isSelectingStartDate = false - @State private var isSelectingEndDate = false - @State private var startDate = Date() - @State private var endDate = Date() - @State private var lastPeriodDate: Date? - - @State private var daysPerYear: Double? - @State private var packsPerDay: Double? - @State private var totalPacksPerYear: Double = 0 - @State private var navigateToSummary = false - - // Passed parameters should not be within a function or closure - - let numberFormatter: NumberFormatter = { - let formatter = NumberFormatter() - formatter.numberStyle = .decimal - formatter.minimum = 0 - return formatter - }() - - var body: some View { - NavigationView { - Form { - menstrualCycleInformationSection - Section { - NavigationLink(destination: YesNoButtonView(startDate: startDate, endDate: endDate, additionalDetails: additionalDetails)) { - Text("Next: Smoking History").foregroundColor(.blue) - } - } - } - .navigationTitle("Social History") - .onAppear { - fetchHealthKitData() - } - .sheet(isPresented: $isSelectingStartDate, content: { - VStack { - DatePicker("Select Start Date", selection: $startDate, displayedComponents: .date) - .datePickerStyle(GraphicalDatePickerStyle()) - - Button("Save") { - lastPeriodDate = startDate - isSelectingStartDate = false - } - } - }) - .sheet(isPresented: $isSelectingEndDate, content: { - VStack { - DatePicker("Select End Date", selection: $endDate, displayedComponents: .date) - .datePickerStyle(GraphicalDatePickerStyle()) - - Button("Save") { - // Handle saving the end date here - isSelectingEndDate = false - } - } - }) - } - } - - private func fetchHealthKitData() { - let infoToRead = Set([HKObjectType.characteristicType(forIdentifier: .biologicalSex)].compactMap { $0 }) - - Task { - do { - try await healthStore.requestAuthorization(toShare: [], read: infoToRead) - - if let bioSex = try? healthStore.biologicalSex() { - DispatchQueue.main.async { - self.isFemale = getIsFemaleBiologicalSex(biologicalSex: bioSex.biologicalSex) - self.showMaleSlide = !self.isFemale - } - } - - // Fetch and auto-populate the last menstrual period date from HealthKit - // Update the startDate and endDate variables accordingly - - } catch { - print("HealthKit authorization failed: \(error.localizedDescription)") - } - } - } - - private func getIsFemaleBiologicalSex(biologicalSex: HKBiologicalSex) -> Bool { - switch biologicalSex { - case .female: return true - case .male: return false - case .other: return true - case .notSet: return false - @unknown default: return false - } - } -} diff --git a/IntakeUITests/LaunchTests.swift b/IntakeUITests/LaunchTests.swift index 1bdee67..9c3a73c 100644 --- a/IntakeUITests/LaunchTests.swift +++ b/IntakeUITests/LaunchTests.swift @@ -24,5 +24,6 @@ class LaunchTests: XCTestCase { func testApplicationLaunch() throws { let app = XCUIApplication() XCTAssertEqual(app.state, .runningForeground) + app.buttons["Start"].tap() } } From 42c27f3294b8f1488517af26cc75c2fee24a5a57 Mon Sep 17 00:00:00 2001 From: apgupta3303 Date: Thu, 7 Mar 2024 16:38:16 -0800 Subject: [PATCH 5/8] stash --- .../xcshareddata/swiftpm/Package.resolved | 392 ++++++++++++++++++ .../Allergy Records/AllergyLLMAssistant.swift | 117 ++++++ 2 files changed, 509 insertions(+) create mode 100644 Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 Intake/Allergy Records/AllergyLLMAssistant.swift diff --git a/Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..c4b63d8 --- /dev/null +++ b/Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,392 @@ +{ + "pins" : [ + { + "identity" : "abseil-cpp-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/abseil-cpp-binary.git", + "state" : { + "revision" : "bfc0b6f81adc06ce5121eb23f628473638d67c5c", + "version" : "1.2022062300.0" + } + }, + { + "identity" : "app-check", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/app-check.git", + "state" : { + "revision" : "3e464dad87dad2d29bb29a97836789bf0f8f67d2", + "version" : "10.18.1" + } + }, + { + "identity" : "fhirmodels", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/FHIRModels", + "state" : { + "revision" : "861afd5816a98d38f86220eab2f812d76cad84a0", + "version" : "0.5.0" + } + }, + { + "identity" : "firebase-ios-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/firebase-ios-sdk.git", + "state" : { + "revision" : "b880ec8ec927a838c51c12862c6222c30d7097d7", + "version" : "10.20.0" + } + }, + { + "identity" : "googleappmeasurement", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleAppMeasurement.git", + "state" : { + "revision" : "ceec9f28dea12b7cf3dabf18b5ed7621c88fd4aa", + "version" : "10.20.0" + } + }, + { + "identity" : "googledatatransport", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleDataTransport.git", + "state" : { + "revision" : "a732a4b47f59e4f725a2ea10f0c77e93a7131117", + "version" : "9.3.0" + } + }, + { + "identity" : "googleutilities", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleUtilities.git", + "state" : { + "revision" : "bc27fad73504f3d4af235de451f02ee22586ebd3", + "version" : "7.12.1" + } + }, + { + "identity" : "grpc-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/grpc-binary.git", + "state" : { + "revision" : "a673bc2937fbe886dd1f99c401b01b6d977a9c98", + "version" : "1.49.1" + } + }, + { + "identity" : "gtm-session-fetcher", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/gtm-session-fetcher.git", + "state" : { + "revision" : "76135c9f4e1ac85459d5fec61b6f76ac47ab3a4c", + "version" : "3.3.1" + } + }, + { + "identity" : "healthkitonfhir", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordBDHG/HealthKitOnFHIR.git", + "state" : { + "revision" : "825e96007d83ed83f81ee49eb3ebab29d7b7ba2f", + "version" : "0.2.5" + } + }, + { + "identity" : "interop-ios-for-google-sdks", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/interop-ios-for-google-sdks.git", + "state" : { + "revision" : "2d12673670417654f08f5f90fdd62926dc3a2648", + "version" : "100.0.0" + } + }, + { + "identity" : "leveldb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/leveldb.git", + "state" : { + "revision" : "9d108e9112aa1d65ce508facf804674546116d9c", + "version" : "1.22.3" + } + }, + { + "identity" : "llama.cpp", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordBDHG/llama.cpp", + "state" : { + "revision" : "b0611c7d3cb049822f9911878514e4706b80e2ac", + "version" : "0.1.8" + } + }, + { + "identity" : "nanopb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/nanopb.git", + "state" : { + "revision" : "819d0a2173aff699fb8c364b6fb906f7cdb1a692", + "version" : "2.30909.0" + } + }, + { + "identity" : "openai", + "kind" : "remoteSourceControl", + "location" : "https://github.com/MacPaw/OpenAI", + "state" : { + "revision" : "35afc9a6ee127b8f22a85a31aec2036a987478af", + "version" : "0.2.6" + } + }, + { + "identity" : "promises", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/promises.git", + "state" : { + "revision" : "e70e889c0196c76d22759eb50d6a0270ca9f1d9e", + "version" : "2.3.1" + } + }, + { + "identity" : "researchkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordBDHG/ResearchKit", + "state" : { + "revision" : "209164ed20592a2213c4bd69cefcb078d9de0692", + "version" : "2.2.21" + } + }, + { + "identity" : "researchkitonfhir", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordBDHG/ResearchKitOnFHIR", + "state" : { + "revision" : "ea4d9691591594177e7dfbc8c246324855d73eb5", + "version" : "1.0.1" + } + }, + { + "identity" : "semaphore", + "kind" : "remoteSourceControl", + "location" : "https://github.com/groue/Semaphore.git", + "state" : { + "revision" : "f1c4a0acabeb591068dea6cffdd39660b86dec28", + "version" : "0.0.8" + } + }, + { + "identity" : "spezi", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/Spezi", + "state" : { + "revision" : "0ced3efbc2af9513c07ac913ad762c773a00a6c8", + "version" : "1.2.1" + } + }, + { + "identity" : "speziaccount", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziAccount.git", + "state" : { + "revision" : "714f01ae1e67bf9c1c0e7c07624380f9bea772b7", + "version" : "1.1.0" + } + }, + { + "identity" : "spezichat", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziChat.git", + "state" : { + "revision" : "eae5c15b211f18e09aa98de63ce119629320afeb", + "version" : "0.1.8" + } + }, + { + "identity" : "spezicontact", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziContact.git", + "state" : { + "revision" : "494b776f8c98d771e4a609a1fb706097dba4c030", + "version" : "1.0.0" + } + }, + { + "identity" : "spezifhir", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziFHIR.git", + "state" : { + "revision" : "9a171a21d7028042c30a24c661bfdfc6e363c9c3", + "version" : "0.6.0" + } + }, + { + "identity" : "spezifirebase", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziFirebase.git", + "state" : { + "revision" : "ca1edf678ec59e76c9869ee3448e6e165d9c2789", + "version" : "1.0.0" + } + }, + { + "identity" : "spezifoundation", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziFoundation.git", + "state" : { + "revision" : "662f25d6010a94faf4fd996e184617fcb2bf13d4", + "version" : "1.0.3" + } + }, + { + "identity" : "spezihealthkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziHealthKit.git", + "state" : { + "revision" : "b40695ffa4d1c9d58c5a0ee277640c2343fb5516", + "version" : "0.5.1" + } + }, + { + "identity" : "spezillm", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziLLM.git", + "state" : { + "revision" : "6892c5dfe258371b6f3287f02b8fec57a611ba70", + "version" : "0.7.0" + } + }, + { + "identity" : "spezimedication", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziMedication.git", + "state" : { + "revision" : "95ca9aebbd23f3842639d6e322785a0ff3620aac", + "version" : "0.4.0" + } + }, + { + "identity" : "spezimockwebservice", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziMockWebService.git", + "state" : { + "revision" : "b18067d3499e630bbd995ef05a296ef8fdd42528", + "version" : "1.0.0" + } + }, + { + "identity" : "spezionboarding", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziOnboarding", + "state" : { + "revision" : "91463ae190611bd14ef52b0657e8db3bf53c9ae8", + "version" : "1.1.0" + } + }, + { + "identity" : "speziquestionnaire", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziQuestionnaire.git", + "state" : { + "revision" : "fac0bb02f7027b4c09bd7afdad55eb7b47ec67f3", + "version" : "1.0.1" + } + }, + { + "identity" : "spezischeduler", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziScheduler.git", + "state" : { + "revision" : "adf793cb47dc199f8ae88f5c719f4d3ba06a4c4e", + "version" : "0.8.0" + } + }, + { + "identity" : "spezispeech", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziSpeech", + "state" : { + "revision" : "a1e1d021d8f605b5e6b23aee773115d7125a57e3", + "version" : "1.0.0" + } + }, + { + "identity" : "spezistorage", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziStorage.git", + "state" : { + "revision" : "eaed2220375c35400aa69d1f96a8d32b7e66b1c7", + "version" : "1.0.0" + } + }, + { + "identity" : "speziviews", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordSpezi/SpeziViews.git", + "state" : { + "revision" : "d49f716e4a4d634604bb0dcd6d53df679b6c1358", + "version" : "1.3.0" + } + }, + { + "identity" : "swift-argument-parser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-argument-parser", + "state" : { + "revision" : "c8ed701b513cf5177118a175d85fbbbcd707ab41", + "version" : "1.3.0" + } + }, + { + "identity" : "swift-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-collections.git", + "state" : { + "revision" : "d029d9d39c87bed85b1c50adee7c41795261a192", + "version" : "1.0.6" + } + }, + { + "identity" : "swift-package-list", + "kind" : "remoteSourceControl", + "location" : "https://github.com/FelixHerrmann/swift-package-list", + "state" : { + "revision" : "412180a72b9a1f8262213c16459e3533b0385ea5", + "version" : "3.1.0" + } + }, + { + "identity" : "swift-protobuf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-protobuf.git", + "state" : { + "revision" : "65e8f29b2d63c4e38e736b25c27b83e012159be8", + "version" : "1.25.2" + } + }, + { + "identity" : "xctestextensions", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordBDHG/XCTestExtensions.git", + "state" : { + "revision" : "fb7fcee97c574b950e03b0a53874e26db27db2fe", + "version" : "0.4.8" + } + }, + { + "identity" : "xcthealthkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordBDHG/XCTHealthKit.git", + "state" : { + "revision" : "6e9344a2d632b801d94fe3bbd1d891817e032103", + "version" : "0.3.5" + } + }, + { + "identity" : "xctruntimeassertions", + "kind" : "remoteSourceControl", + "location" : "https://github.com/StanfordBDHG/XCTRuntimeAssertions", + "state" : { + "revision" : "51da3403f128b120705571ce61e0fe190f8889e6", + "version" : "1.0.1" + } + } + ], + "version" : 2 +} diff --git a/Intake/Allergy Records/AllergyLLMAssistant.swift b/Intake/Allergy Records/AllergyLLMAssistant.swift new file mode 100644 index 0000000..23a72e9 --- /dev/null +++ b/Intake/Allergy Records/AllergyLLMAssistant.swift @@ -0,0 +1,117 @@ +// +// AllergyLLMAssistant.swift +// Intake +// +// Created by Akash Gupta on 3/4/24. +// +// This source file is part of the Intake based on the Stanford Spezi Template Application project +// +// SPDX-FileCopyrightText: 2023 Stanford University +// +// SPDX-License-Identifier: MIT +// + + +import Foundation +import SpeziChat +import SpeziLLM +import SpeziLLMLocal +import SpeziLLMOpenAI +import SwiftUI + + +func getCurrentPatientAllergy(allergyList: [AllergyItem]) -> String? { + var allergyDetails = "The patient has several allergies described in the next sentences." + for allergy in allergyList { + let allergyName = allergy.allergy + if let allergyReaction = allergy.reaction.first?.reaction { + allergyDetails += "The patient has allergy \(allergyName) with the reaction \(allergyReaction).\n" + } else { + allergyDetails += "The patient has allergy \(allergyName).\n" + } + } + return allergyDetails.isEmpty ? nil : allergyDetails +} + + +struct AllergyLLMAssistant: View { + struct AddAllergy: LLMFunction { + @Environment(DataStore.self) private var data + static let name: String = "add_allergy" + static let description: String = """ + If the user wants to add an allergy that is not currently \ + in their list of allergies, help them figure out the name \ + of allergy and associated reaction and add them to the list + """ + + @Parameter(description: "This is the allergy that the user wants to add") var allergy: String + @Parameter(description: "These are the corresponding reactions that the user gets when they have allergy") var reactions: [String] + + + func execute() async throws -> String? { + var reactionsAdding: [ReactionItem] = [] + for reaction in reactions { + reactionsAdding.append(ReactionItem(reaction: reaction)) + } + data.allergyData.append(AllergyItem(allergy: allergy, reaction: reactionsAdding)) + return "We have added /(allergy)" + } + } + + @Environment(DataStore.self) private var data + @Environment(NavigationPathWrapper.self) private var navigationPath + @Binding var presentingAccount: Bool + @LLMSessionProvider var session: LLMOpenAISession + @State var showOnboarding = true + @State var greeting = true + var body: some View { + @Bindable var data = data + LLMChatView( + session: $session + ) + .navigationTitle("Allergy Assistant") + .sheet(isPresented: $showOnboarding) { + LLMOnboardingView(showOnboarding: $showOnboarding) + } + .onAppear { + if greeting { + let assistantMessage = ChatEntity(role: .assistant, content: "Do you have any questions about your allergies?") + session.context.insert(assistantMessage, at: 0) + } + greeting = false + if let currentallergy = getCurrentPatientAllergy(allergyList: data.allergyData) { + session.context.append( + systemMessage: currentallergy + ) + } + } + } + + init(presentingAccount: Binding) { + self._presentingAccount = presentingAccount + self._session = LLMSessionProvider( + schema: LLMOpenAISchema( + parameters: .init( + modelType: .gpt3_5Turbo, + systemPrompt: """ + Pretend you are a nurse. Your job is to answer information about the patient's allergies.\ + Please use everyday layman terms and avoid using complex medical terminology.\ + Only ask one question or prompt at a time, and keep your questions brief (one to two short sentences). + """ + ) + ) { + AddAllergy() + } + ) + } + } + + +//#Preview { +// LLMInteraction(presentingAccount: .constant(false)) +// .previewWith { +// LLMRunner { +// LLMOpenAIPlatform() +// } +// } +//} From 41749818a9d8ef3e96297b866b128e3356153cf7 Mon Sep 17 00:00:00 2001 From: apgupta3303 Date: Thu, 7 Mar 2024 17:01:42 -0800 Subject: [PATCH 6/8] updating localizable --- Intake/Resources/Localizable.xcstrings | 702 +------------------------ Intake/ScrollablePDF.swift | 1 - 2 files changed, 1 insertion(+), 702 deletions(-) diff --git a/Intake/Resources/Localizable.xcstrings b/Intake/Resources/Localizable.xcstrings index 3de85d6..870575e 100644 --- a/Intake/Resources/Localizable.xcstrings +++ b/Intake/Resources/Localizable.xcstrings @@ -710,708 +710,8 @@ }, "Your Responses" : { -{ - "sourceLanguage" : "en", - "strings" : { - "*Check the box if you currently have the condition. /\n*Uncheck the box if you had the condition in the past" : { - }, - "*Click the details to view/edit the reactions" : { - - }, - "%@ Reactions" : { - - }, - "ACCOUNT_NEXT" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Next" - } - } - } - }, - "ACCOUNT_SETUP_DESCRIPTION" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "You may login to your existing account. Or create a new one if you don't have one already. You will have to connect a name and email to your account. You may enter additional details such as your date of birth." - } - } - } - }, - "ACCOUNT_SIGNED_IN_DESCRIPTION" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "You are already logged in with the account shown below. Continue or change your account by logging out. You can also update your details of name, date of birth, and your preferred email." - } - } - } - }, - "ACCOUNT_SUBTITLE" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "The Intake demonstrates the usage of the Firebase Account Module." - } - } - } - }, - "ACCOUNT_TITLE" : { - "comment" : "MARK: Account", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Your Account" - } - } - } - }, - "Active" : { - - }, - "Add Field" : { - - }, - "ADD_REACTION" : { - - }, - "ADD_SURGERY" : { - - }, - "Additional Details" : { - - }, - "Additional details: %@" : { - - }, - "Age" : { - - }, - "Additional Symptoms" : { - - }, - "AI-assisted medical intake" : { - - }, - "Allergies" : { - - }, - "Allergy" : { - - }, - "Allergy Assistant" : { - - }, - "Allergy Name" : { - - }, - "Auto-fill Intake Form" : { - - }, - "Chat" : { - - }, - "CLOSE" : { - "comment" : "MARK: General", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Close" - } - } - } - }, - "COMPLETED_TASK_LABEL %@" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Completed Task: %@" - } - } - } - }, - "Condition" : { - - }, - "CONSENT_LOADING_ERROR" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Please include a markdown based document named \"ConsentDocument\" in your module Bundle." - } - } - } - }, - "CONTACTS_NAVIGATION_TITLE" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Contacts" - } - } - } - }, - "CONTACTS_TAB_TITLE" : { - "comment" : "MARK: - Contacts", - "extractionState" : "stale", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Contacts" - } - } - } - }, - "CONTRIBUTIONS_LIST_DESCRIPTION" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "The following list contains all Swift Package dependencies of the SpeziIntake." - } - } - } - }, - "CONTRIBUTIONS_LIST_FOOTER" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Please refer to the individual repository links for packages without license labels." - } - } - } - }, - "CONTRIBUTIONS_LIST_HEADER" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Packages" - } - } - } - }, - "Date of Birth" : { - - }, - "Date of Birth:" : { - - }, - "DELETE_REACTION" : { - - }, - "DETAILS" : { - - }, - "Download your medical records from your health system." : { - - }, - "End Date: %@" : { - - }, - "EDIT" : { - - }, - "END_CALENDAR" : { - - }, - "Export to PDF" : { - - }, - "Ex: Heavy bleeding on second day, fatigue..." : { - - }, - "Ex: Smoked for 10 years, quit 5 years ago..." : { - - }, - "FHIR_RESOURCES_CHAT_CANCEL" : { - - }, - "Get Started" : { - - }, - "HEALTHKIT_PERMISSIONS_BUTTON" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Grant Access" - } - } - } - }, - "HEALTHKIT_PERMISSIONS_DESCRIPTION" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Intake will use your different types of your health records in order to most effectively aid you with your intake form." - } - } - } - }, - "HEALTHKIT_PERMISSIONS_SUBTITLE" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Intake would like to access to your health records to fill out your intake form." - } - } - } - }, - "HEALTHKIT_PERMISSIONS_TITLE" : { - "comment" : "MARK: HealthKit", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "HealthKit Access" - } - } - } - }, - "Here is a summary of the Primary Concern" : { - - }, - "HOME_LOGO" : { - - }, - "How many days a year do you smoke?" : { - - }, - "How many packs do you smoke a day?" : { - - }, - "Inactive" : { - - }, - "Integrate your Records" : { - - }, - "INTERESTING_MODULES_BUTTON" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Next" - } - } - } - }, - "It looks like an unexpected view was appended to the NavigationPath!" : { - - }, - "LICENSE_INFO_TITLE" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "License Information" - } - } - } - }, - "List all your allgeries." : { - - }, - "List your current medications." : { - - }, - "Main reason(s) for visit" : { - - }, - "Medical History" : { - - }, - "Medical Intake Form" : { - - }, - "Medication Settings" : { - - }, - "Medications" : { - - }, - "Menstrual Information" : { - - }, - "Message" : { - - }, - "MOCK_ALLERGY_RECORDS_TITLE" : { - "extractionState" : "stale", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Allergy Records" - } - } - } - }, - "MOCK_MEDICAL_HISTORY_TITLE" : { - "extractionState" : "stale", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Medical History" - } - } - } - }, - "MOCK_MEDICATIONS_RECORDS_TITLE" : { - "extractionState" : "stale", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Medications" - } - } - } - }, - "MOCK_SURGERY_RECORDS_TITLE" : { - "extractionState" : "stale", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Surgery" - } - } - } - }, - "MOCK_WEB_SERVICE_TAB_TITLE" : { - "comment" : "MARK: - Mock Upload Data Storage Provider", - "extractionState" : "stale", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Web Service" - } - } - } - }, - "Name" : { - - }, - "Name:" : { - - }, - "Next" : { - - }, - "NOTIFICATION_PERMISSIONS_BUTTON" : { - "extractionState" : "stale", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Allow Notifications" - } - } - } - }, - "NOTIFICATION_PERMISSIONS_DESCRIPTION" : { - "extractionState" : "stale", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "The Spezi Scheduler module enables to send out local notifications when a new event of a task is scheduled." - } - } - } - }, - "NOTIFICATION_PERMISSIONS_SUBTITLE" : { - "extractionState" : "stale", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Spezi Scheduler Notifications." - } - } - } - }, - "NOTIFICATION_PERMISSIONS_TITLE" : { - "comment" : "MARK: Notifications", - "extractionState" : "stale", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Notifications" - } - } - } - }, - "OLIVER_AALAMI_BIO" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dr. Oliver O. Aalami is a Clinical Professor of Surgery at Stanford University and a vascular surgeon based in Palo Alto, California. He is affiliated with Stanford Health Care and the VA Palo Alto Health Care System.\nDr. Aalami is also the Director of Biodesign for Digital Health at the Stanford Byers Center for Biodesign. He co-founded Spezi (formerly CardinalKit) and is passionate about clinically validating smartphone and smartwatch sensors in patients with cardiovascular disease." - } - } - } - }, - "Other important questions." : { - - }, - "Pack years: %.2f" : { - - }, - "Patient Form" : { - - }, - "Please list conditions you have had" : { - - }, - "Primary Concern" : { - - }, - "PROJECT_LICENSE_DESCRIPTION" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "This project is licensed under the MIT License." - } - } - } - }, - "QUESTIONNAIRE_DESCRIPTION" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Please fill out the Questionnaire every day." - } - } - } - }, - "QUESTIONNAIRE_TITLE" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Questionnaire" - } - } - } - }, - "Reactions" : { - - }, - "ReForm" : { - - }, - "Repository Link" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Repository Link" - } - } - } - }, - "Resource Selection" : { - - }, - "Resource Settings" : { - - }, - "Review of Systems" : { - - }, - "Review summary of your medical history." : { - - }, - "Save" : { - - }, - "SCHEDULE_LIST_TITLE" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Schedule" - } - } - } - }, - "SCHEDULE_TAB_TITLE" : { - "comment" : "MARK: - Schedule", - "extractionState" : "stale", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Schedule" - } - } - } - }, - "Select End Date" : { - - }, - "Select Start Date" : { - - }, - "Select your last period's end date" : { - - }, - "Select your last period's start date" : { - - }, - "SETTINGS" : { - - }, - "SETTINGS_TITLE" : { - - }, - "Sex" : { - - }, - "Share with provider of your choice." : { - - }, - "Skip" : { - - }, - "Smoking History" : { - - }, - "Social History" : { - - }, - "Start" : { - - }, - "Start Date: %@" : { - - }, - "START_CALENDAR" : { - - }, - "Submit" : { - - }, - "Submit your Form" : { - - }, - "Summarize your medical history." : { - - }, - "Summarize your surgical history." : { - - }, - "Surgery" : { - - }, - "Surgery Name" : { - - }, - "Surgical History" : { - - }, - "Symptoms: %@" : { - - }, - "TASK_CONTEXT_ACTION_QUESTIONNAIRE" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Start Questionnaire" - } - } - } - }, - "TASK_CONTEXT_ACTION_TEST" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Start Test" - } - } - } - }, - "TASK_LABEL %@" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Task: %@" - } - } - } - }, - "TASK_SOCIAL_SUPPORT_QUESTIONNAIRE_DESCRIPTION" : { - "extractionState" : "stale", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Please fill out the Social Support Questionnaire every day." - } - } - } - }, - "TASK_SOCIAL_SUPPORT_QUESTIONNAIRE_TITLE" : { - "extractionState" : "stale", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Social Support Questionnaire" - } - } - } - }, - "This application will help autocomplete your medical intake form." : { - - }, - "Together we will summarize..." : { - - }, - "Use HealthKit Resources" : { - - }, - "Welcome to ReForm" : { - - }, - "What are your current allergies?" : { - - }, - "What brings you in today? Identify your primary concern(s)." : { - - }, - "What is your surgical history?" : { - - }, - "Your Responses" : { - } }, "version" : "1.0" -} \ No newline at end of file +} diff --git a/Intake/ScrollablePDF.swift b/Intake/ScrollablePDF.swift index 7424a6f..222c1b3 100644 --- a/Intake/ScrollablePDF.swift +++ b/Intake/ScrollablePDF.swift @@ -216,4 +216,3 @@ struct ScrollablePDF: View { } } } - From 8daece8ab099522dcfdaa2938891b388f6eb0286 Mon Sep 17 00:00:00 2001 From: apgupta3303 Date: Thu, 7 Mar 2024 17:17:54 -0800 Subject: [PATCH 7/8] fixing package errors --- .../xcshareddata/swiftpm/Package.resolved | 505 ++---------------- 1 file changed, 52 insertions(+), 453 deletions(-) diff --git a/Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 19e352a..273e907 100644 --- a/Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Intake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/abseil-cpp-binary.git", "state" : { - "revision" : "bfc0b6f81adc06ce5121eb23f628473638d67c5c", - "version" : "1.2022062300.0" + "revision" : "df308b8b46607675f2b9ec8e569109008f9155ce", + "version" : "1.2022062300.1" } }, { @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/firebase/firebase-ios-sdk.git", "state" : { - "revision" : "b880ec8ec927a838c51c12862c6222c30d7097d7", - "version" : "10.20.0" + "revision" : "be49849dcba96f2b5ee550d4eceb2c0fa27dade4", + "version" : "10.22.1" } }, { @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/GoogleAppMeasurement.git", "state" : { - "revision" : "ceec9f28dea12b7cf3dabf18b5ed7621c88fd4aa", - "version" : "10.20.0" + "revision" : "482cfa4e5880f0a29f66ecfd60c5a62af28bd1f0", + "version" : "10.22.1" } }, { @@ -50,8 +50,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/GoogleDataTransport.git", "state" : { - "revision" : "a732a4b47f59e4f725a2ea10f0c77e93a7131117", - "version" : "9.3.0" + "revision" : "a637d318ae7ae246b02d7305121275bc75ed5565", + "version" : "9.4.0" } }, { @@ -59,8 +59,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/GoogleUtilities.git", "state" : { - "revision" : "bc27fad73504f3d4af235de451f02ee22586ebd3", - "version" : "7.12.1" + "revision" : "26c898aed8bed13b8a63057ee26500abbbcb8d55", + "version" : "7.13.1" } }, { @@ -68,8 +68,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/grpc-binary.git", "state" : { - "revision" : "a673bc2937fbe886dd1f99c401b01b6d977a9c98", - "version" : "1.49.1" + "revision" : "ea4cb5cc0c39c732b85386263116d2e2fdbbdc61", + "version" : "1.49.2" } }, { @@ -86,8 +86,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordBDHG/HealthKitOnFHIR.git", "state" : { - "revision" : "825e96007d83ed83f81ee49eb3ebab29d7b7ba2f", - "version" : "0.2.5" + "revision" : "00d64d38a8f0d826ee9e27b6f3ce32314a29fd3e", + "version" : "0.2.6" } }, { @@ -104,8 +104,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/firebase/leveldb.git", "state" : { - "revision" : "9d108e9112aa1d65ce508facf804674546116d9c", - "version" : "1.22.3" + "revision" : "43aaef65e0c665daadf848761d560e446d350d3d", + "version" : "1.22.4" } }, { @@ -113,8 +113,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordBDHG/llama.cpp", "state" : { - "revision" : "b0611c7d3cb049822f9911878514e4706b80e2ac", - "version" : "0.1.8" + "revision" : "7bfd6d4b5bbc9fd47bd023bdbb35f96c827977f3", + "version" : "0.2.1" } }, { @@ -122,8 +122,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/firebase/nanopb.git", "state" : { - "revision" : "819d0a2173aff699fb8c364b6fb906f7cdb1a692", - "version" : "2.30909.0" + "revision" : "b7e1104502eca3a213b46303391ca4d3bc8ddec1", + "version" : "2.30910.0" } }, { @@ -140,8 +140,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/promises.git", "state" : { - "revision" : "e70e889c0196c76d22759eb50d6a0270ca9f1d9e", - "version" : "2.3.1" + "revision" : "540318ecedd63d883069ae7f1ed811a2df00b6ac", + "version" : "2.4.0" } }, { @@ -149,8 +149,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordBDHG/ResearchKit", "state" : { - "revision" : "209164ed20592a2213c4bd69cefcb078d9de0692", - "version" : "2.2.21" + "revision" : "e4afb10ec636a70e06afc4a84fb98e457818439a", + "version" : "2.2.27" } }, { @@ -158,17 +158,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordBDHG/ResearchKitOnFHIR", "state" : { - "revision" : "ea4d9691591594177e7dfbc8c246324855d73eb5", - "version" : "1.0.1" - } - }, - { - "identity" : "semaphore", - "kind" : "remoteSourceControl", - "location" : "https://github.com/groue/Semaphore.git", - "state" : { - "revision" : "f1c4a0acabeb591068dea6cffdd39660b86dec28", - "version" : "0.0.8" + "revision" : "7c2efdcb17796fc9ee686900304dbbe9dd4aaf85", + "version" : "1.1.2" } }, { @@ -185,8 +176,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordSpezi/SpeziAccount.git", "state" : { - "revision" : "714f01ae1e67bf9c1c0e7c07624380f9bea772b7", - "version" : "1.1.0" + "revision" : "a7d289ef3be54de62b25dc92e8f7ff1a0f093906", + "version" : "1.2.1" } }, { @@ -194,8 +185,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordSpezi/SpeziChat.git", "state" : { - "revision" : "eae5c15b211f18e09aa98de63ce119629320afeb", - "version" : "0.1.8" + "revision" : "2334583105224b0c04fc36989db82b000021d31d", + "version" : "0.1.9" } }, { @@ -228,10 +219,10 @@ { "identity" : "spezifoundation", "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziFoundation.git", + "location" : "https://github.com/StanfordSpezi/SpeziFoundation", "state" : { - "revision" : "662f25d6010a94faf4fd996e184617fcb2bf13d4", - "version" : "1.0.3" + "revision" : "01af5b91a54f30ddd121258e81aff2ddc2a99ff9", + "version" : "1.0.4" } }, { @@ -246,10 +237,10 @@ { "identity" : "spezillm", "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziLLM.git", + "location" : "https://github.com/StanfordSpezi/SpeziLLM", "state" : { - "revision" : "6892c5dfe258371b6f3287f02b8fec57a611ba70", - "version" : "0.7.0" + "revision" : "ca379106637c69fd0138360643d0129176a8ca6b", + "version" : "0.7.1" } }, { @@ -275,8 +266,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordSpezi/SpeziOnboarding", "state" : { - "revision" : "91463ae190611bd14ef52b0657e8db3bf53c9ae8", - "version" : "1.1.0" + "revision" : "4971a82e94996ce0c3d8ecf64fdeec874a1f20d6", + "version" : "1.1.1" } }, { @@ -284,8 +275,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordSpezi/SpeziQuestionnaire.git", "state" : { - "revision" : "fac0bb02f7027b4c09bd7afdad55eb7b47ec67f3", - "version" : "1.0.1" + "revision" : "f25580e95bfdad02383980dcb94406cf97b08ea8", + "version" : "1.0.2" } }, { @@ -293,418 +284,26 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordSpezi/SpeziScheduler.git", "state" : { - "revision" : "adf793cb47dc199f8ae88f5c719f4d3ba06a4c4e", - "version" : "0.8.0" + "revision" : "ba391084109a9a16622b07e9dcefe2ab1552d2a2", + "version" : "0.8.1" } }, { "identity" : "spezispeech", "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziSpeech", + "location" : "https://github.com/StanfordSpezi/SpeziSpeech.git", "state" : { - "revision" : "a1e1d021d8f605b5e6b23aee773115d7125a57e3", - "version" : "1.0.0" - } - }, - { - "identity" : "spezistorage", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziStorage.git", - "state" : { - "revision" : "eaed2220375c35400aa69d1f96a8d32b7e66b1c7", - "version" : "1.0.0" - } - }, - { - "identity" : "speziviews", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziViews.git", - "state" : { - "revision" : "d49f716e4a4d634604bb0dcd6d53df679b6c1358", - "version" : "1.3.0" - } - }, - { - "identity" : "swift-argument-parser", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-argument-parser", - "state" : { - "revision" : "c8ed701b513cf5177118a175d85fbbbcd707ab41", - "version" : "1.3.0" - } - }, - { - "identity" : "swift-collections", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-collections.git", - "state" : { - "revision" : "d029d9d39c87bed85b1c50adee7c41795261a192", - "version" : "1.0.6" - } - }, - { - "identity" : "swift-package-list", - "kind" : "remoteSourceControl", - "location" : "https://github.com/FelixHerrmann/swift-package-list", - "state" : { - "revision" : "412180a72b9a1f8262213c16459e3533b0385ea5", - "version" : "3.1.0" - } - }, - { - "identity" : "swift-protobuf", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-protobuf.git", - "state" : { - "revision" : "65e8f29b2d63c4e38e736b25c27b83e012159be8", - "version" : "1.25.2" - } - }, - { - "identity" : "xctestextensions", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/XCTestExtensions.git", - "state" : { - "revision" : "fb7fcee97c574b950e03b0a53874e26db27db2fe", - "version" : "0.4.8" - } - }, - { - "identity" : "xcthealthkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/XCTHealthKit.git", - "state" : { - "revision" : "6e9344a2d632b801d94fe3bbd1d891817e032103", - "version" : "0.3.5" - } - }, - { - "identity" : "xctruntimeassertions", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/XCTRuntimeAssertions", - "state" : { - "revision" : "51da3403f128b120705571ce61e0fe190f8889e6", + "revision" : "60b8cdbf6f3d58b0d75eadf30db50f88848069aa", "version" : "1.0.1" } - } - ], - "version" : 2 -} -{ - "pins" : [ - { - "identity" : "abseil-cpp-binary", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/abseil-cpp-binary.git", - "state" : { - "revision" : "bfc0b6f81adc06ce5121eb23f628473638d67c5c", - "version" : "1.2022062300.0" - } - }, - { - "identity" : "app-check", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/app-check.git", - "state" : { - "revision" : "3e464dad87dad2d29bb29a97836789bf0f8f67d2", - "version" : "10.18.1" - } - }, - { - "identity" : "fhirmodels", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/FHIRModels", - "state" : { - "revision" : "861afd5816a98d38f86220eab2f812d76cad84a0", - "version" : "0.5.0" - } - }, - { - "identity" : "firebase-ios-sdk", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/firebase-ios-sdk.git", - "state" : { - "revision" : "b880ec8ec927a838c51c12862c6222c30d7097d7", - "version" : "10.20.0" - } - }, - { - "identity" : "googleappmeasurement", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleAppMeasurement.git", - "state" : { - "revision" : "ceec9f28dea12b7cf3dabf18b5ed7621c88fd4aa", - "version" : "10.20.0" - } - }, - { - "identity" : "googledatatransport", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleDataTransport.git", - "state" : { - "revision" : "a732a4b47f59e4f725a2ea10f0c77e93a7131117", - "version" : "9.3.0" - } - }, - { - "identity" : "googleutilities", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleUtilities.git", - "state" : { - "revision" : "bc27fad73504f3d4af235de451f02ee22586ebd3", - "version" : "7.12.1" - } - }, - { - "identity" : "grpc-binary", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/grpc-binary.git", - "state" : { - "revision" : "a673bc2937fbe886dd1f99c401b01b6d977a9c98", - "version" : "1.49.1" - } - }, - { - "identity" : "gtm-session-fetcher", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/gtm-session-fetcher.git", - "state" : { - "revision" : "76135c9f4e1ac85459d5fec61b6f76ac47ab3a4c", - "version" : "3.3.1" - } - }, - { - "identity" : "healthkitonfhir", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/HealthKitOnFHIR.git", - "state" : { - "revision" : "825e96007d83ed83f81ee49eb3ebab29d7b7ba2f", - "version" : "0.2.5" - } - }, - { - "identity" : "interop-ios-for-google-sdks", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/interop-ios-for-google-sdks.git", - "state" : { - "revision" : "2d12673670417654f08f5f90fdd62926dc3a2648", - "version" : "100.0.0" - } - }, - { - "identity" : "leveldb", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/leveldb.git", - "state" : { - "revision" : "9d108e9112aa1d65ce508facf804674546116d9c", - "version" : "1.22.3" - } - }, - { - "identity" : "llama.cpp", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/llama.cpp", - "state" : { - "revision" : "b0611c7d3cb049822f9911878514e4706b80e2ac", - "version" : "0.1.8" - } - }, - { - "identity" : "nanopb", - "kind" : "remoteSourceControl", - "location" : "https://github.com/firebase/nanopb.git", - "state" : { - "revision" : "819d0a2173aff699fb8c364b6fb906f7cdb1a692", - "version" : "2.30909.0" - } - }, - { - "identity" : "openai", - "kind" : "remoteSourceControl", - "location" : "https://github.com/MacPaw/OpenAI", - "state" : { - "revision" : "35afc9a6ee127b8f22a85a31aec2036a987478af", - "version" : "0.2.6" - } - }, - { - "identity" : "promises", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/promises.git", - "state" : { - "revision" : "e70e889c0196c76d22759eb50d6a0270ca9f1d9e", - "version" : "2.3.1" - } - }, - { - "identity" : "researchkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/ResearchKit", - "state" : { - "revision" : "209164ed20592a2213c4bd69cefcb078d9de0692", - "version" : "2.2.21" - } - }, - { - "identity" : "researchkitonfhir", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordBDHG/ResearchKitOnFHIR", - "state" : { - "revision" : "ea4d9691591594177e7dfbc8c246324855d73eb5", - "version" : "1.0.1" - } - }, - { - "identity" : "semaphore", - "kind" : "remoteSourceControl", - "location" : "https://github.com/groue/Semaphore.git", - "state" : { - "revision" : "f1c4a0acabeb591068dea6cffdd39660b86dec28", - "version" : "0.0.8" - } - }, - { - "identity" : "spezi", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/Spezi", - "state" : { - "revision" : "0ced3efbc2af9513c07ac913ad762c773a00a6c8", - "version" : "1.2.1" - } - }, - { - "identity" : "speziaccount", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziAccount.git", - "state" : { - "revision" : "714f01ae1e67bf9c1c0e7c07624380f9bea772b7", - "version" : "1.1.0" - } - }, - { - "identity" : "spezichat", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziChat", - "state" : { - "revision" : "eae5c15b211f18e09aa98de63ce119629320afeb", - "version" : "0.1.8" - } - }, - { - "identity" : "spezicontact", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziContact.git", - "state" : { - "revision" : "494b776f8c98d771e4a609a1fb706097dba4c030", - "version" : "1.0.0" - } - }, - { - "identity" : "spezifhir", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziFHIR.git", - "state" : { - "revision" : "9a171a21d7028042c30a24c661bfdfc6e363c9c3", - "version" : "0.6.0" - } - }, - { - "identity" : "spezifirebase", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziFirebase.git", - "state" : { - "revision" : "ca1edf678ec59e76c9869ee3448e6e165d9c2789", - "version" : "1.0.0" - } - }, - { - "identity" : "spezifoundation", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziFoundation.git", - "state" : { - "revision" : "662f25d6010a94faf4fd996e184617fcb2bf13d4", - "version" : "1.0.3" - } - }, - { - "identity" : "spezihealthkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziHealthKit.git", - "state" : { - "revision" : "b40695ffa4d1c9d58c5a0ee277640c2343fb5516", - "version" : "0.5.1" - } - }, - { - "identity" : "spezillm", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziLLM.git", - "state" : { - "revision" : "6892c5dfe258371b6f3287f02b8fec57a611ba70", - "version" : "0.7.0" - } - }, - { - "identity" : "spezimedication", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziMedication.git", - "state" : { - "revision" : "95ca9aebbd23f3842639d6e322785a0ff3620aac", - "version" : "0.4.0" - } - }, - { - "identity" : "spezimockwebservice", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziMockWebService.git", - "state" : { - "revision" : "b18067d3499e630bbd995ef05a296ef8fdd42528", - "version" : "1.0.0" - } - }, - { - "identity" : "spezionboarding", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziOnboarding", - "state" : { - "revision" : "91463ae190611bd14ef52b0657e8db3bf53c9ae8", - "version" : "1.1.0" - } - }, - { - "identity" : "speziquestionnaire", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziQuestionnaire.git", - "state" : { - "revision" : "fac0bb02f7027b4c09bd7afdad55eb7b47ec67f3", - "version" : "1.0.1" - } - }, - { - "identity" : "spezischeduler", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziScheduler.git", - "state" : { - "revision" : "adf793cb47dc199f8ae88f5c719f4d3ba06a4c4e", - "version" : "0.8.0" - } - }, - { - "identity" : "spezispeech", - "kind" : "remoteSourceControl", - "location" : "https://github.com/StanfordSpezi/SpeziSpeech", - "state" : { - "revision" : "a1e1d021d8f605b5e6b23aee773115d7125a57e3", - "version" : "1.0.0" - } }, { "identity" : "spezistorage", "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordSpezi/SpeziStorage.git", "state" : { - "revision" : "eaed2220375c35400aa69d1f96a8d32b7e66b1c7", - "version" : "1.0.0" + "revision" : "b958df9b31f24800388a7bfc28f457ce7b82556c", + "version" : "1.0.2" } }, { @@ -712,8 +311,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordSpezi/SpeziViews.git", "state" : { - "revision" : "d49f716e4a4d634604bb0dcd6d53df679b6c1358", - "version" : "1.3.0" + "revision" : "4d2a724d97c8f19ac7de7aa2c046b1cb3ef7b279", + "version" : "1.3.1" } }, { @@ -730,8 +329,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-collections.git", "state" : { - "revision" : "d029d9d39c87bed85b1c50adee7c41795261a192", - "version" : "1.0.6" + "revision" : "94cf62b3ba8d4bed62680a282d4c25f9c63c2efb", + "version" : "1.1.0" } }, { @@ -757,8 +356,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/StanfordBDHG/XCTestExtensions.git", "state" : { - "revision" : "fb7fcee97c574b950e03b0a53874e26db27db2fe", - "version" : "0.4.8" + "revision" : "1fe9b8e76aeb7a132af37bfa0892160c9b662dcc", + "version" : "0.4.10" } }, { From fca7f0e7ac7a59cb269d3caade74ff6001d7296f Mon Sep 17 00:00:00 2001 From: apgupta3303 Date: Thu, 7 Mar 2024 17:31:05 -0800 Subject: [PATCH 8/8] linting --- Intake/Allergy Records/AllergyRecords.swift | 2 +- Intake/Home.swift | 1 - Intake/Intake.swift | 1 + Intake/Resources/Localizable.xcstrings | 50 ++++++++++++++++----- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/Intake/Allergy Records/AllergyRecords.swift b/Intake/Allergy Records/AllergyRecords.swift index 88c4e13..2526036 100644 --- a/Intake/Allergy Records/AllergyRecords.swift +++ b/Intake/Allergy Records/AllergyRecords.swift @@ -62,7 +62,7 @@ struct AllergyList: View { var body: some View { VStack { allergyForm - SubmitButton(nextView: NavigationViews.social) + SubmitButton(nextView: NavigationViews.menstrual) .padding() } .onAppear(perform: loadAllergies) diff --git a/Intake/Home.swift b/Intake/Home.swift index 31ee720..d21988e 100644 --- a/Intake/Home.swift +++ b/Intake/Home.swift @@ -97,7 +97,6 @@ struct HomeView: View { case .allergies: AllergyList() case .surgical: SurgeryView() case .medical: MedicalHistoryView() - case .social: ScrollablePDF() case .medication: MedicationContentView() case .menstrual: SocialHistoryQuestionView() case .concern: SummaryView(chiefComplaint: $data.chiefComplaint) diff --git a/Intake/Intake.swift b/Intake/Intake.swift index f83d2c1..8ffd86c 100644 --- a/Intake/Intake.swift +++ b/Intake/Intake.swift @@ -28,6 +28,7 @@ class DataStore { var conditionData: [MedicalHistoryItem] = [] var medicationData: Set = [] var surgeries: [SurgeryItem] = [] + var surgeriesLoaded = false var chiefComplaint: String = "" var generalData = PatientData(name: "Akash", birthdate: "01/08/2003", age: "21", sex: "Male") } diff --git a/Intake/Resources/Localizable.xcstrings b/Intake/Resources/Localizable.xcstrings index 870575e..dbe3a7b 100644 --- a/Intake/Resources/Localizable.xcstrings +++ b/Intake/Resources/Localizable.xcstrings @@ -63,6 +63,9 @@ } } } + }, + "Active" : { + }, "Add Field" : { @@ -81,6 +84,9 @@ }, "Additional Symptoms" : { + }, + "Age" : { + }, "AI-assisted medical intake" : { @@ -199,6 +205,12 @@ } } } + }, + "Date of Birth" : { + + }, + "Date of Birth:" : { + }, "DELETE_REACTION" : { @@ -209,11 +221,14 @@ "Download your medical records from your health system." : { }, - "End Date: %@" : { + "EDIT" : { }, "Edit Surgery" : { + }, + "End Date: %@" : { + }, "END_CALENDAR" : { @@ -223,6 +238,9 @@ }, "Ex: Smoked for 10 years, quit 5 years ago..." : { + }, + "Export to PDF" : { + }, "FHIR_RESOURCES_CHAT_CANCEL" : { @@ -282,6 +300,9 @@ }, "How many packs do you smoke a day?" : { + }, + "Inactive" : { + }, "Integrate your Records" : { @@ -400,6 +421,12 @@ } } } + }, + "Name" : { + + }, + "Name:" : { + }, "New Surgery" : { @@ -467,6 +494,9 @@ }, "Pack years: %.2f" : { + }, + "Patient Form" : { + }, "Performed" : { @@ -583,6 +613,9 @@ }, "SETTINGS_TITLE" : { + }, + "Sex" : { + }, "Share with provider of your choice." : { @@ -619,15 +652,9 @@ }, "Summarize your surgical history." : { - }, - "Surgery" : { - }, "Surgery Assistant" : { - }, - "Surgery Name" : { - }, "Surgical History" : { @@ -705,13 +732,12 @@ "What brings you in today? Identify your primary concern(s)." : { }, - - "What is your surgical history?" : { + "Your Responses" : { }, - "Your Responses" : { - + "YYYY-MM-DD" : { + } }, "version" : "1.0" -} +} \ No newline at end of file