diff --git a/app/integration_test/faq_test.dart b/app/integration_test/faq_test.dart index 159bd8bc..3b20dd5e 100644 --- a/app/integration_test/faq_test.dart +++ b/app/integration_test/faq_test.dart @@ -1,5 +1,5 @@ import 'package:app/common/module.dart'; -import 'package:app/faq/constants.dart'; +import 'package:app/faq/pages/content.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; @@ -38,8 +38,8 @@ void main() { await tester.pumpWidget(faqWidget); await tester.pumpAndSettle(); - final expectedNumberOfQuestions = faqList.keys.fold( - 0, (number, topic) => number + faqList[topic]!.length + final expectedNumberOfQuestions = faqContent.fold( + 0, (number, topic) => number + topic.questions.length ); expect( @@ -53,7 +53,9 @@ void main() { expectedNumberOfQuestions, ); - final firstQuestion = faqList[faqList.keys.first]![0]; + final BuildContext context = + tester.element(find.byType(Scaffold).first); + final firstQuestion = faqContent.first.questions.first(context); expect(find.text(firstQuestion.question), findsOneWidget); expect(find.text(firstQuestion.answer), findsNothing); diff --git a/app/lib/faq/constants.dart b/app/lib/faq/constants.dart deleted file mode 100644 index 026cc563..00000000 --- a/app/lib/faq/constants.dart +++ /dev/null @@ -1,97 +0,0 @@ -import '../common/module.dart'; - -abstract class Question { - const Question({ - required this.question, - required this.answer, - }); - - final String question; - final dynamic answer; -} - -class TextAnswerQuestion extends Question { - const TextAnswerQuestion({ - required super.question, - required String super.answer, - }); -} - -class WidgetAnswerQuestion extends Question { - const WidgetAnswerQuestion({ - required super.question, - required Widget super.answer, - }); -} - -final Map> faqList = { - 'Pharmacogenomics (PGx)': [ - TextAnswerQuestion( - question: 'What is pharmacogenomics?', - answer: - 'Pharmacogenomics (PGx) is the study of how your genes (DNA) affect your response to medications.', - ), - TextAnswerQuestion( - question: 'Why is pharmacogenomics important?', - answer: - 'Pharmacogenomics is important because it helps to predict those who will respond well to medications and those who may have side effects. With this information we can better select the right medication and dose to avoid side effects.', - ), - WidgetAnswerQuestion( - question: 'Where can I find out more about genetics in general?', - answer: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'To learn more about genetics, we recommend MedlinePlus,' - ' a service of the National Library of Medicine:' - ), - SizedBox(height: PharMeTheme.smallSpace * 0.5), - Hyperlink( - text: geneticInformationUrl.toString(), - onTap: openFurtherGeneticInformation, - ), - ], - ), - ), - TextAnswerQuestion( - question: 'Which medications are affected?', - answer: - 'Examples of affected medication classes include anti-clotting medications (like clopidogrel and warfarin), antidepressants (like sertraline, citalopram, and paroxetine), anti-cholesterol medications (like simvastatin and atorvastatin), acid reducers (like pantoprazole and omeprazole), pain killers (like codeine, tramadol, and ibuprofen), antifungals (like voriconazole), medications that suppress the immune system (like tacrolimus), and anti-cancer medications (like fluorouracil and irinotecan). You can find out whether a certain medication is affected in the Medications tab.', - ), - TextAnswerQuestion( - question: 'Will my results affect my family members?', - answer: - 'Yes, since this is a genetic test, it is possible that your results were passed down to you and your siblings from your parents and you will also pass them down to your children.', - ), - TextAnswerQuestion( - question: 'Who can I share my results with?', - answer: - 'We recommend that you share your results with your pharmacists, doctors, and close family members such as parents, siblings, and children.', - ), - ], - 'PharMe App': [ - TextAnswerQuestion( - question: 'What does PharMe do?', - answer: - 'PharMe provides user-friendly information on how your body reacts to medications based on your genes. This enables you to better understand which medications may be ineffective for you or could have potential side effects. We recommend that you share consult your health care team before making any changes to your treatments.', - ), - TextAnswerQuestion( - question: - 'Can I use PharMe\'s results without consulting a medical professional?', - answer: - 'No. Whether a medication is a good choice for you depends on a lot of other factors such as age, weight, or pre-existing conditions. We highly recommend that you talk to your health care team (e.g., pharmacist and doctors) before taking, stopping or adjusting the dose of any medication.', - ), - TextAnswerQuestion( - question: 'Where does PharMe get its data from?', - answer: - "PharMe is showing pharmacogenomic guidelines from the Clinical Pharmacogenetics Implementation Consortium (CPIC®) and the U.S. Food and Drug Administration (FDA). Our PGx experts adapted the language from the guidelines to make them more user-friendly and easier to understand; please note that this does only affect the guidelines' presentation, not affect the guidelines' statements.", - ), - ], - 'Data security': [ - TextAnswerQuestion( - question: 'How is the security of my genetic data ensured?', - answer: - 'Once securely imported from the lab, your genetic data is re-encrypted, saved and never sent anywhere else. All computation is done on your phone. When fetching data from external resources, PharMe always uses generalized requests and only personalizes information locally on your phone. No personal data is sent to third parties. This provides the highest level of security for your personal information.', - ), - ] -}; diff --git a/app/lib/faq/pages/content.dart b/app/lib/faq/pages/content.dart new file mode 100644 index 00000000..1ac572ee --- /dev/null +++ b/app/lib/faq/pages/content.dart @@ -0,0 +1,102 @@ +import '../../common/module.dart'; + +typedef FaqQuestionBuilder = FaqQuestion Function(BuildContext context); + +class FaqSection { + FaqSection({required this.title, required this.questions}); + + final String Function(BuildContext context) title; + final List questions; +} + +abstract class FaqQuestion { + const FaqQuestion({ + required this.question, + required this.answer, + }); + + final String question; + final dynamic answer; +} + +class FaqTextAnswerQuestion extends FaqQuestion { + const FaqTextAnswerQuestion({ + required super.question, + required String super.answer, + }); +} + +class FaqWidgetAnswerQuestion extends FaqQuestion { + const FaqWidgetAnswerQuestion({ + required super.question, + required Widget super.answer, + }); +} + +final faqContent = [ + FaqSection( + title: (context) => context.l10n.faq_section_title_pgx, + questions: [ + (context) => FaqTextAnswerQuestion( + question: context.l10n.faq_question_pgx_what, + answer: context.l10n.faq_answer_pgx_what, + ), + (context) => FaqTextAnswerQuestion( + question: context.l10n.faq_question_pgx_why, + answer: context.l10n.faq_answer_pgx_why, + ), + (context) => FaqWidgetAnswerQuestion( + question: context.l10n.faq_question_genetics_info, + answer: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(context.l10n.faq_answer_genetics_info), + SizedBox(height: PharMeTheme.smallSpace * 0.5), + Hyperlink( + text: geneticInformationUrl.toString(), + onTap: openFurtherGeneticInformation, + ), + ], + ), + ), + (context) => FaqTextAnswerQuestion( + question: context.l10n.faq_question_which_medications, + answer: context.l10n.faq_answer_which_medications, + ), + (context) => FaqTextAnswerQuestion( + question: context.l10n.faq_question_family, + answer: context.l10n.faq_answer_family, + ), + (context) => FaqTextAnswerQuestion( + question: context.l10n.faq_question_share, + answer: context.l10n.faq_answer_share, + ), + ], + ), + FaqSection( + title: (context) => context.l10n.faq_section_title_pharme, + questions: [ + (context) => FaqTextAnswerQuestion( + question: context.l10n.faq_question_pharme_function, + answer: context.l10n.faq_answer_pharme_function, + ), + (context) => FaqTextAnswerQuestion( + question: context.l10n.faq_question_pharme_hcp, + answer: context.l10n.faq_answer_pharme_hcp, + ), + (context) => FaqTextAnswerQuestion( + question: context.l10n.faq_question_pharme_data_source, + answer: context.l10n.faq_answer_pharme_data_source, + ), + ], + ), + FaqSection( + title: (context) => context.l10n.faq_section_title_security, + questions: [ + (context) => FaqTextAnswerQuestion( + question: context.l10n.faq_question_data_security, + answer: context.l10n.faq_answer_data_security, + ), + ], + ), +]; diff --git a/app/lib/faq/pages/faq.dart b/app/lib/faq/pages/faq.dart index a13c6871..b9fad095 100644 --- a/app/lib/faq/pages/faq.dart +++ b/app/lib/faq/pages/faq.dart @@ -1,5 +1,5 @@ import '../../common/module.dart'; -import '../constants.dart'; +import 'content.dart'; @RoutePage() class FaqPage extends StatelessWidget { @@ -17,10 +17,8 @@ class FaqPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 8), - ...faqList.keys.fold>( - [], (widgets, topic) => - [...widgets, ..._buildTopic(context, topic, faqList[topic]!)] - ), + ...faqContent.flatMap((faqSection) => + _buildTopic(context, faqSection)), ..._buildTopicHeader( context.l10n.more_page_contact_us, addSpace: true, @@ -53,18 +51,23 @@ class FaqPage extends StatelessWidget { List _buildTopic( BuildContext context, - String topicName, - List questions + FaqSection faqSection, ) { - final topicIndex = faqList.keys.toList().indexOf(topicName); + final isFirst = faqContent.indexOf(faqSection) == 0; return [ - ..._buildTopicHeader(topicName, addSpace: topicIndex != 0), - ...questions.map((question) => _buildQuestion(context, question)) + ..._buildTopicHeader(faqSection.title(context), addSpace: !isFirst), + ...faqSection.questions.map( + (questionBuilder) => _buildQuestion(context, questionBuilder) + ) ]; } - Widget _buildQuestion(BuildContext context, Question question) { + Widget _buildQuestion( + BuildContext context, + FaqQuestionBuilder questionBuilder, + ) { final key = GlobalKey(); + final question = questionBuilder(context); return _buildQuestionCard( key: key, child: Theme( @@ -85,7 +88,7 @@ class FaqPage extends StatelessWidget { right: PharMeTheme.mediumSpace, bottom: PharMeTheme.smallSpace, ), - title: question is TextAnswerQuestion + title: question is FaqTextAnswerQuestion ? Text(question.answer) : question.answer, ), diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index d58e84ee..02730550 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -42,8 +42,6 @@ "update_warning_title": "Updated guidelines", "update_warning_body": "The guidelines for interactions between genes and medications were updated. Please review your results, especially for the medications you are currently taking.", - - "faq_contact_us": "Do you have unanswered questions or feedback? Contact us", "general_continue": "Continue", "general_retry": "Retry", @@ -362,5 +360,33 @@ "contact_open_mail": "Send mail", "comprehension_intro_text": "Would you like to participate in a survey aiming to measure user comprehension of content in the app? This would help us make PharMe more understandable for everyone!", - "comprehension_survey_button_text": "Continue to survey" + "comprehension_survey_button_text": "Continue to survey", + + "faq_section_title_pgx": "Pharmacogenomics (PGx)", + "faq_question_pgx_what": "What is pharmacogenomics?", + "faq_answer_pgx_what": "Pharmacogenomics (PGx) is the study of how your genes (DNA) affect your response to medications.", + "faq_question_pgx_why": "Why is pharmacogenomics important?", + "faq_answer_pgx_why": "Pharmacogenomics is important because it helps to predict those who will respond well to medications and those who may have side effects. With this information we can better select the right medication and dose to avoid side effects.", + "faq_question_genetics_info": "Where can I find out more about genetics in general?", + "faq_answer_genetics_info": "To learn more about genetics, we recommend MedlinePlus, a service of the National Library of Medicine:", + "faq_question_which_medications": "Which medications have known gene interactions?", + "faq_answer_which_medications": "Examples of medication classes with known gene interactions include anti-clotting medications (like clopidogrel and warfarin), antidepressants (like sertraline, citalopram, and paroxetine), anti-cholesterol medications (like simvastatin and atorvastatin), acid reducers (like pantoprazole and omeprazole), pain killers (like codeine, tramadol, and ibuprofen), antifungals (like voriconazole), medications that suppress the immune system (like tacrolimus), and anti-cancer medications (like fluorouracil and irinotecan).\n\nSearch a medication in the Medications tab to find out whether it has known gene interactions according to CPIC® and FDA guidelines.", + "faq_question_family": "Will my results affect my family members?", + "faq_answer_family": "Yes, since this is a genetic test, it is possible that your results were passed down to you and your siblings from your parents and you will also pass them down to your children.", + "faq_question_share": "Who can I share my results with?", + "faq_answer_share": "We recommend that you share your results with your pharmacists, doctors, and close family members such as parents, siblings, and children.", + + "faq_section_title_pharme": "PharMe App", + "faq_question_pharme_function": "What does PharMe do?", + "faq_answer_pharme_function": "PharMe provides user-friendly information on how your body reacts to medications based on your genes. This enables you to better understand which medications may be ineffective for you or could have potential side effects. We recommend that you share consult your health care team before making any changes to your treatments.", + "faq_question_pharme_hcp": "Can I use PharMe's results without consulting a medical professional?", + "faq_answer_pharme_hcp": "No. Whether a medication is a good choice for you depends on a lot of other factors such as age, weight, or pre-existing conditions. We highly recommend that you talk to your health care team (e.g., pharmacist and doctors) before taking, stopping or adjusting the dose of any medication.", + "faq_question_pharme_data_source": "Where does PharMe get its data from?", + "faq_answer_pharme_data_source": "PharMe is showing pharmacogenomic guidelines from the Clinical Pharmacogenetics Implementation Consortium (CPIC®) and the U.S. Food and Drug Administration (FDA). Our PGx experts adapted the language from the guidelines to make them more user-friendly and easier to understand; please note that this does only affect the guidelines' presentation, not affect the guidelines' statements.", + + "faq_section_title_security": "Data security", + "faq_question_data_security": "How is the security of my genetic data ensured?", + "faq_answer_data_security": "Once securely imported from the lab, your genetic data is re-encrypted, saved and never sent anywhere else. All computation is done on your phone. When fetching data from external resources, PharMe always uses generalized requests and only personalizes information locally on your phone. No personal data is sent to third parties. This provides the highest level of security for your personal information.", + + "faq_contact_us": "Do you have unanswered questions or feedback? Contact us" }