feedbacks in symptoms checker (faiz_dev) #331

Merged
Haroon6138 merged 2 commits from faiz_dev_symptoms_checker into master 2 weeks ago

@ -1444,7 +1444,7 @@
"suggestions": "التوصيات", "suggestions": "التوصيات",
"pleaseGoBackAndSelectOrgansFirst": "يرجى العودة واختيار الأعضاء أولاً", "pleaseGoBackAndSelectOrgansFirst": "يرجى العودة واختيار الأعضاء أولاً",
"symptomsSelector": "محدد الأعراض", "symptomsSelector": "محدد الأعراض",
"possibleSymptomsRelatedTo": "أعراض مرتبطة بـ", "possibleSymptomsRelatedTo": "الأعراض المحتملة المتعلقة بأعضاء محددة",
"suggestionAIListDescription": "هذه قائمة بالأعراض المقترحة من قبل الذكاء الاصطناعي، بناءً على المعلومات التي تم جمعها حتى الآن خلال المقابلة", "suggestionAIListDescription": "هذه قائمة بالأعراض المقترحة من قبل الذكاء الاصطناعي، بناءً على المعلومات التي تم جمعها حتى الآن خلال المقابلة",
"whyAmIBeingAskedThis": "لماذا يُطرح علي هذا السؤال؟", "whyAmIBeingAskedThis": "لماذا يُطرح علي هذا السؤال؟",
"weAreAskingThisQuestionToBetterUnderstand": "نطرح هذا السؤال لفهم {symptoms} بشكل أفضل وتحسين دقة التقييم.", "weAreAskingThisQuestionToBetterUnderstand": "نطرح هذا السؤال لفهم {symptoms} بشكل أفضل وتحسين دقة التقييم.",
@ -1856,6 +1856,7 @@
"watchUsOnYoutube": "شاهدنا على يوتيوب", "watchUsOnYoutube": "شاهدنا على يوتيوب",
"connectOnLinkedin": "تواصل معنا على لينكد إن", "connectOnLinkedin": "تواصل معنا على لينكد إن",
"riskFactorPageTitle": "اعراض تشعر بها", "riskFactorPageTitle": "اعراض تشعر بها",
"doAnyOfTheseApply": "هل ينطبق عليك أي من هذه الأمور؟",
"bloodDonationService": "التبرع \n بالدم", "bloodDonationService": "التبرع \n بالدم",
"bookAppointmentService": "حجز\nموعد", "bookAppointmentService": "حجز\nموعد",
"pinchToZoom": "اضغط للتكبير", "pinchToZoom": "اضغط للتكبير",
@ -1925,6 +1926,10 @@
"refundReason6": "تم إلغاء الإجراء السريري أو تغييره من قِبل الطبيب المحيل", "refundReason6": "تم إلغاء الإجراء السريري أو تغييره من قِبل الطبيب المحيل",
"refundReason7": "تم إلغاء إجراء وحدة الخدمة / المختبر / الأشعة أو تغييره من قِبل الطبيب المحيل", "refundReason7": "تم إلغاء إجراء وحدة الخدمة / المختبر / الأشعة أو تغييره من قِبل الطبيب المحيل",
"selectProcedures": "اختر العمليات", "selectProcedures": "اختر العمليات",
"beforeUsingSymptomsChecker": "قبل استخدام فاحص الأعراض، يرجى قراءة شروط الخدمة وتذكر:",
"symptomsCheckerNotDiagnosis": "• فاحص الأعراض ليس تشخيصًا. إنه للمعلومات الخاصة بك فقط وليس رأيًا طبيًا مؤهلاً.",
"symptomsCheckerNotEmergency": "• فاحص الأعراض ليس للطوارئ. اتصل برقم الطوارئ المحلي فورًا عند وجود حالة طوارئ صحية.",
"yourDataIsSafe": "• بياناتك آمنة. تضمن تدابير الخصوصية حماية المعلومات التي تشاركها.",
"submitEReferral": "تقديم الطلب", "submitEReferral": "تقديم الطلب",
"redeem": "استبدال", "redeem": "استبدال",
"points": "نقاط", "points": "نقاط",

@ -1436,7 +1436,7 @@
"suggestions": "Suggestions", "suggestions": "Suggestions",
"pleaseGoBackAndSelectOrgansFirst": "Please go back and select organs first", "pleaseGoBackAndSelectOrgansFirst": "Please go back and select organs first",
"symptomsSelector": "Symptoms Selector", "symptomsSelector": "Symptoms Selector",
"possibleSymptomsRelatedTo": "Possible symptoms related to", "possibleSymptomsRelatedTo": "Possible symptoms related to selected organs",
"suggestionAIListDescription": "This is a list of symptoms suggested by our AI, based on the information gathered so far during the interview", "suggestionAIListDescription": "This is a list of symptoms suggested by our AI, based on the information gathered so far during the interview",
"whyAmIBeingAskedThis": "Why am I being asked this?", "whyAmIBeingAskedThis": "Why am I being asked this?",
"weAreAskingThisQuestionToBetterUnderstand": "We are asking this question to better understand your {symptoms} and improve the accuracy of the assessment.", "weAreAskingThisQuestionToBetterUnderstand": "We are asking this question to better understand your {symptoms} and improve the accuracy of the assessment.",
@ -1848,6 +1848,7 @@
"watchUsOnYoutube": "Watch us on youtube", "watchUsOnYoutube": "Watch us on youtube",
"connectOnLinkedin": "Connect on LinkedIn", "connectOnLinkedin": "Connect on LinkedIn",
"riskFactorPageTitle": "What do you feel?", "riskFactorPageTitle": "What do you feel?",
"doAnyOfTheseApply": "Do any of these apply to you?",
"bloodDonationService": "Blood \nDonation", "bloodDonationService": "Blood \nDonation",
"bookAppointmentService": "Book\nAppointment", "bookAppointmentService": "Book\nAppointment",
"pinchToZoom": "Pinch to zoom", "pinchToZoom": "Pinch to zoom",
@ -1917,6 +1918,10 @@
"refundReason6": "Clinical procedure cancelled or changed by requesting doctor", "refundReason6": "Clinical procedure cancelled or changed by requesting doctor",
"refundReason7": "Service unit/lab/radiology procedure cancelled or changed by requesting doctor", "refundReason7": "Service unit/lab/radiology procedure cancelled or changed by requesting doctor",
"selectProcedures": "Select Procedures", "selectProcedures": "Select Procedures",
"beforeUsingSymptomsChecker": "Before using the Symptoms Checker, please read the Terms of Service and remember:",
"symptomsCheckerNotDiagnosis": "• Symptoms Checker isn't a diagnosis. It's only for your information and not a qualified medical opinion.",
"symptomsCheckerNotEmergency": "• Symptoms Checker isn't for emergencies. Call your local emergency number right away when there's a health emergency.",
"yourDataIsSafe": "• Your data is safe. Privacy measures ensure the information you share is protected.",
"redeem": "Redeem", "redeem": "Redeem",
"points": "Points", "points": "Points",
"transactions": "Transactions", "transactions": "Transactions",

@ -105,20 +105,14 @@ class TriageQuestion {
factory TriageQuestion.fromJson(Map<String, dynamic> json) { factory TriageQuestion.fromJson(Map<String, dynamic> json) {
// TESTING: Add dummy instructions to every question for testing UI // TESTING: Add dummy instructions to every question for testing UI
final dummyInstructions = [
"Clean the thermometer using soap and cold water.",
"For rectal insertion, apply a small amount of petroleum jelly to the end of the thermometer.",
"Insert the silver tip into the anus or mouth.",
"Hold the thermometer in place for 2 minutes, or as long as recommended by the manufacturer.",
];
final dummyExplication = "The most accurate measurement is rectal temperature. You can also measure the temperature under the armpit or use contactless thermometers. However, using the contact thermometer is more accurate. Follow the thermometer manufacturer's instructions. A temperature above 37°C or 98.6°F is classified as a fever.";
return TriageQuestion( return TriageQuestion(
type: json['type'], type: json['type'],
text: json['text'], text: json['text'],
explication: json['explication'] ?? dummyExplication, // Use dummy if null explication: json['explication'],
instruction: json['instruction'] != null ? List<String>.from(json['instruction']) : dummyInstructions, // Use dummy if null // Use dummy if null
instruction: json['instruction'] != null ? List<String>.from(json['instruction']) : [],
// Use dummy if null
items: json['items'] != null ? (json['items'] as List).map((item) => TriageQuestionItem.fromJson(item)).toList() : null, items: json['items'] != null ? (json['items'] as List).map((item) => TriageQuestionItem.fromJson(item)).toList() : null,
); );
} }

@ -2,7 +2,7 @@
// ignore_for_file: constant_identifier_names // ignore_for_file: constant_identifier_names
abstract class LocaleKeys { abstract class LocaleKeys {
static const english = 'english'; static const english = 'english';
static const arabic = 'arabic'; static const arabic = 'arabic';
static const login = 'login'; static const login = 'login';
@ -1808,6 +1808,7 @@ abstract class LocaleKeys {
static const watchUsOnYoutube = 'watchUsOnYoutube'; static const watchUsOnYoutube = 'watchUsOnYoutube';
static const connectOnLinkedin = 'connectOnLinkedin'; static const connectOnLinkedin = 'connectOnLinkedin';
static const riskFactorPageTitle = 'riskFactorPageTitle'; static const riskFactorPageTitle = 'riskFactorPageTitle';
static const doAnyOfTheseApply = 'doAnyOfTheseApply';
static const bloodDonationService = 'bloodDonationService'; static const bloodDonationService = 'bloodDonationService';
static const bookAppointmentService = 'bookAppointmentService'; static const bookAppointmentService = 'bookAppointmentService';
static const pinchToZoom = 'pinchToZoom'; static const pinchToZoom = 'pinchToZoom';
@ -1883,5 +1884,4 @@ abstract class LocaleKeys {
static const advanceNumber = 'advanceNumber'; static const advanceNumber = 'advanceNumber';
static const amountOnly = 'amountOnly'; static const amountOnly = 'amountOnly';
static const invoiceHistory = 'invoiceHistory'; static const invoiceHistory = 'invoiceHistory';
} }

@ -1847,6 +1847,7 @@ abstract class LocaleKeys {
static const watchUsOnYoutube = 'watchUsOnYoutube'; static const watchUsOnYoutube = 'watchUsOnYoutube';
static const connectOnLinkedin = 'connectOnLinkedin'; static const connectOnLinkedin = 'connectOnLinkedin';
static const riskFactorPageTitle = 'riskFactorPageTitle'; static const riskFactorPageTitle = 'riskFactorPageTitle';
static const doAnyOfTheseApply = 'doAnyOfTheseApply';
static const bloodDonationService = 'bloodDonationService'; static const bloodDonationService = 'bloodDonationService';
static const bookAppointmentService = 'bookAppointmentService'; static const bookAppointmentService = 'bookAppointmentService';
static const pinchToZoom = 'pinchToZoom'; static const pinchToZoom = 'pinchToZoom';
@ -1898,6 +1899,10 @@ abstract class LocaleKeys {
static const noProceduresAvailableForRefund = 'noProceduresAvailableForRefund'; static const noProceduresAvailableForRefund = 'noProceduresAvailableForRefund';
static const selectAll = 'selectAll'; static const selectAll = 'selectAll';
static const selectRefundMethod = 'selectRefundMethod'; static const selectRefundMethod = 'selectRefundMethod';
static const beforeUsingSymptomsChecker = 'beforeUsingSymptomsChecker';
static const symptomsCheckerNotDiagnosis = 'symptomsCheckerNotDiagnosis';
static const symptomsCheckerNotEmergency = 'symptomsCheckerNotEmergency';
static const yourDataIsSafe = 'yourDataIsSafe';
static const hmgWallet = 'hmgWallet'; static const hmgWallet = 'hmgWallet';
static const bankTransfer = 'bankTransfer'; static const bankTransfer = 'bankTransfer';
static const selectRefundReason = 'selectRefundReason'; static const selectRefundReason = 'selectRefundReason';

@ -71,16 +71,21 @@ class _OrganSelectorPageState extends State<OrganSelectorPage> {
); );
return; return;
} }
// If user is not authenticated, navigate to user consent screen
if (!_appState.isAuthenticated) {
context.navigateWithName(AppRoutes.userConsentScreen);
return;
}
// User is authenticated, proceed with API call
LoaderBottomSheet.showLoader( LoaderBottomSheet.showLoader(
loadingText: LocaleKeys.pleaseWait.tr(context: context), loadingText: LocaleKeys.pleaseWait.tr(context: context),
); );
// Get fileNo if user is logged in // Get fileNo from authenticated user
String? fileNo; final user = _appState.getAuthenticatedUser();
if (_appState.isAuthenticated) { String? fileNo = user?.patientId.toString();
final user = _appState.getAuthenticatedUser();
fileNo = user?.patientId.toString();
}
await viewModel.getSymptomsUserDetails( await viewModel.getSymptomsUserDetails(
userName: ApiConsts.symptomsCheckerUsername, userName: ApiConsts.symptomsCheckerUsername,

@ -1,5 +1,3 @@
import 'dart:developer';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
@ -31,7 +29,6 @@ import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:shimmer/shimmer.dart';
class PossibleConditionsPage extends StatefulWidget { class PossibleConditionsPage extends StatefulWidget {
const PossibleConditionsPage({super.key}); const PossibleConditionsPage({super.key});
@ -91,25 +88,81 @@ class _PossibleConditionsPageState extends State<PossibleConditionsPage> {
} }
Widget _buildLoadingShimmer() { Widget _buildLoadingShimmer() {
return ListView.separated( return Column(
shrinkWrap: true, crossAxisAlignment: CrossAxisAlignment.start,
physics: const NeverScrollableScrollPhysics(), children: [
padding: EdgeInsets.all(16.w), // Triage Level Card Shimmer
itemCount: 10,
separatorBuilder: (_, __) => SizedBox(height: 12.h), // Condition Cards Shimmer
itemBuilder: (context, index) { ...List.generate(5, (index) {
return Shimmer.fromColors( return Container(
baseColor: Colors.grey[300]!, width: double.infinity,
highlightColor: Colors.grey[100]!, margin: EdgeInsets.only(left: 24.w, right: 24.w, bottom: 16.h),
child: Container( padding: EdgeInsets.all(20.w),
height: 80.h,
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColors.whiteColor, color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(10.r), borderRadius: BorderRadius.circular(24.r),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.08),
blurRadius: 10.r,
offset: Offset(0, 2.h),
),
],
), ),
), child: Column(
); crossAxisAlignment: CrossAxisAlignment.start,
}, children: [
// Condition name shimmer
Container(
height: 20.h,
width: 220.w,
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(8.r),
),
).toShimmer2(isShow: true, radius: 8.r),
SizedBox(height: 8.h),
Container(
height: 20.h,
width: 200.w,
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(8.r),
),
).toShimmer2(isShow: true, radius: 8.r),
SizedBox(height: 8.h),
// Probability percentage shimmer
Container(
height: 16.h,
width: 100.w,
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(8.r),
),
).toShimmer2(isShow: true, radius: 8.r),
SizedBox(height: 30.h),
// Action buttons shimmer
Row(
children: [
Expanded(
child: Container(
height: 40.h,
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(12.r),
),
).toShimmer2(isShow: true, radius: 12.r),
),
],
),
],
),
);
}),
],
); );
} }
@ -323,7 +376,10 @@ class _PossibleConditionsPageState extends State<PossibleConditionsPage> {
trailing: _buildTrailingSection(context), trailing: _buildTrailingSection(context),
child: Consumer<SymptomsCheckerViewModel>( child: Consumer<SymptomsCheckerViewModel>(
builder: (context, symptomsCheckerViewModel, child) { builder: (context, symptomsCheckerViewModel, child) {
if (symptomsCheckerViewModel.isPossibleConditionsLoading || symptomsCheckerViewModel.isTriageDiagnosisLoading) { // Show shimmer while loading triage level or conditions
if (symptomsCheckerViewModel.isPossibleConditionsLoading ||
symptomsCheckerViewModel.isTriageDiagnosisLoading ||
symptomsCheckerViewModel.isTriageLevelLoading) {
return _buildLoadingShimmer(); return _buildLoadingShimmer();
} }
// Get conditions directly from ViewModel // Get conditions directly from ViewModel
@ -350,9 +406,7 @@ class _PossibleConditionsPageState extends State<PossibleConditionsPage> {
// Show error if no clinic details available // Show error if no clinic details available
final dialogService = getIt<DialogService>(); final dialogService = getIt<DialogService>();
dialogService.showErrorBottomSheet( dialogService.showErrorBottomSheet(
message: appState.isArabic() message: appState.isArabic() ? "لا توجد تفاصيل عيادة متاحة" : "No clinic details available",
? "لا توجد تفاصيل عيادة متاحة"
: "No clinic details available",
); );
return; return;
} }
@ -451,13 +505,12 @@ class _PossibleConditionsPageState extends State<PossibleConditionsPage> {
var id = ""; var id = "";
if (data.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER) { if (data.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER) {
// Check if hospitalList is not empty before accessing first // Check if hospitalList is not empty before accessing first
if (regionalViewModel.selectedHospital?.hospitalList != null && if (regionalViewModel.selectedHospital?.hospitalList != null && regionalViewModel.selectedHospital!.hospitalList.isNotEmpty) {
regionalViewModel.selectedHospital!.hospitalList.isNotEmpty) {
id = regionalViewModel.selectedHospital!.hospitalList.first.iD?.toString() ?? ""; id = regionalViewModel.selectedHospital!.hospitalList.first.iD?.toString() ?? "";
} }
} else { } else {
// Check if patientDoctorAppointmentList is not empty before accessing first // Check if patientDoctorAppointmentList is not empty before accessing first
if (regionalViewModel.selectedHospital?.patientDoctorAppointmentList != null && if (regionalViewModel.selectedHospital?.patientDoctorAppointmentList != null &&
regionalViewModel.selectedHospital!.patientDoctorAppointmentList!.isNotEmpty) { regionalViewModel.selectedHospital!.patientDoctorAppointmentList!.isNotEmpty) {
id = regionalViewModel.selectedHospital!.patientDoctorAppointmentList!.first.projectID?.toString() ?? ""; id = regionalViewModel.selectedHospital!.patientDoctorAppointmentList!.first.projectID?.toString() ?? "";
} }

@ -1,5 +1,4 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart'; import 'package:hmg_patient_app_new/core/app_export.dart';
@ -121,12 +120,11 @@ class _RiskFactorsScreenState extends State<RiskFactorsScreen> {
child: RichText( child: RichText(
text: TextSpan( text: TextSpan(
style: TextStyle( style: TextStyle(
height: 1.3, height: 1.3,
fontSize: 13.f, fontSize: 13.f,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: AppColors.greyInfoTextColor, color: AppColors.greyInfoTextColor,
fontFamily: isArabic ? 'CairoArabic' : 'Poppins' fontFamily: isArabic ? 'CairoArabic' : 'Poppins'),
),
children: [ children: [
TextSpan( TextSpan(
text: LocaleKeys.aboveYouSeeCommonRiskFactors.tr(context: context), text: LocaleKeys.aboveYouSeeCommonRiskFactors.tr(context: context),
@ -223,7 +221,7 @@ class _RiskFactorsScreenState extends State<RiskFactorsScreen> {
children: [ children: [
Expanded( Expanded(
child: CollapsingListView( child: CollapsingListView(
title: LocaleKeys.riskFactorPageTitle.tr(context: context), title: LocaleKeys.doAnyOfTheseApply.tr(context: context),
leadingCallback: () => context.pop(), leadingCallback: () => context.pop(),
child: viewModel.isRiskFactorsLoading child: viewModel.isRiskFactorsLoading
? _buildLoadingShimmer() ? _buildLoadingShimmer()

@ -200,7 +200,7 @@ class _SuggestionsScreenState extends State<SuggestionsScreen> {
children: [ children: [
Expanded( Expanded(
child: CollapsingListView( child: CollapsingListView(
title: LocaleKeys.symptomsCheckSuggestions.tr() , title: LocaleKeys.riskFactorPageTitle.tr() ,
leadingCallback: () => context.pop(), leadingCallback: () => context.pop(),
child: viewModel.isSuggestionsLoading child: viewModel.isSuggestionsLoading
? _buildLoadingShimmer() ? _buildLoadingShimmer()

@ -225,7 +225,7 @@ class _SymptomsSelectorPageState extends State<SymptomsSelectorPage> {
children: [ children: [
Expanded( Expanded(
child: Text( child: Text(
'${LocaleKeys.possibleSymptomsRelatedTo.tr(context: context)} "$organName"', LocaleKeys.possibleSymptomsRelatedTo.tr(context: context),
style: TextStyle(fontSize: 18.f, fontWeight: FontWeight.w600, color: AppColors.textColor), style: TextStyle(fontSize: 18.f, fontWeight: FontWeight.w600, color: AppColors.textColor),
), ),
), ),

@ -82,7 +82,7 @@ class _TriagePageState extends State<TriagePage> {
// Case 3: Probability >= 70% OR // Case 3: Probability >= 70% OR
// Case 4: 30 or more questions answered // Case 4: 30 or more questions answered
// if (viewModel.shouldStopTriage || highestProbability >= 70.0 || viewModel.triageQuestionCount >= 30) { // if (viewModel.shouldStopTriage || highestProbability >= 70.0 || viewModel.triageQuestionCount >= 30) {
if (highestProbability >= 70.0 || viewModel.triageQuestionCount >= 30 || viewModel.shouldStopTriage) { if (highestProbability >= 70.0 || viewModel.triageQuestionCount >= 4 || viewModel.shouldStopTriage) {
// Navigate to results/possible conditions screen // Navigate to results/possible conditions screen
context.navigateWithName(AppRoutes.possibleConditionsPage); context.navigateWithName(AppRoutes.possibleConditionsPage);
return; return;
@ -346,7 +346,7 @@ class _TriagePageState extends State<TriagePage> {
final hasInstructions = instructions.isNotEmpty; final hasInstructions = instructions.isNotEmpty;
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
title: LocaleKeys.howTo.tr(context: context), title: LocaleKeys.information.tr(context: context),
context, context,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,

@ -8,16 +8,14 @@ import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart'; import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:provider/provider.dart';
// Before using the checkup, please read the Terms of Service and remember:
//
// Checkup isn't a diagnosis. It's only for your information and not a qualified medical opinion.
// Checkup isn't for emergencies. Call your local emergency number right away when there's a health emergency.
// Your data is safe. Privacy measures ensure the information you share is protected.
class UserConsentScreen extends StatefulWidget { class UserConsentScreen extends StatefulWidget {
const UserConsentScreen({super.key}); const UserConsentScreen({super.key});
@ -43,6 +41,35 @@ class _UserConsentScreenState extends State<UserConsentScreen> {
bool get _canProceed => _isTermsAccepted && _isPrivacyAccepted; bool get _canProceed => _isTermsAccepted && _isPrivacyAccepted;
void _onNextPressed() async {
final viewModel = context.read<SymptomsCheckerViewModel>();
final appState = getIt.get<AppState>();
LoaderBottomSheet.showLoader(
loadingText: LocaleKeys.pleaseWait.tr(context: context),
);
// For non-authenticated users, fileNo is null
String? fileNo;
if (appState.isAuthenticated) {
final user = appState.getAuthenticatedUser();
fileNo = user?.patientId.toString();
}
await viewModel.getSymptomsUserDetails(
userName: ApiConsts.symptomsCheckerUsername,
password: ApiConsts.symptomsCheckerPassword,
fileNo: fileNo,
onSuccess: () {
LoaderBottomSheet.hideLoader();
context.navigateWithName(AppRoutes.symptomsSelectorPage);
},
onError: (String error) {
LoaderBottomSheet.hideLoader();
},
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -55,14 +82,14 @@ class _UserConsentScreenState extends State<UserConsentScreen> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
"Before using the checkup, please read the Terms of Service and remember:".toText14(), LocaleKeys.beforeUsingSymptomsChecker.tr(context: context).toText14(),
SizedBox(height: 44.h), SizedBox(height: 30.h),
"• Checkup isn't a diagnosis. It's only for your information and not a qualified medical opinion.".toText14(), LocaleKeys.symptomsCheckerNotDiagnosis.tr(context: context).toText14(),
SizedBox(height: 12.h), SizedBox(height: 12.h),
"• Checkup isn't for emergencies. Call your local emergency number right away when there's a health emergency.".toText14(), LocaleKeys.symptomsCheckerNotEmergency.tr(context: context).toText14(),
SizedBox(height: 12.h), SizedBox(height: 12.h),
"• Your data is safe. Privacy measures ensure the information you share is protected.".toText14(), LocaleKeys.yourDataIsSafe.tr(context: context).toText14(),
SizedBox(height: 24.h), SizedBox(height: 30.h),
GestureDetector( GestureDetector(
onTap: _onTermsAndConditionsAgreed, onTap: _onTermsAndConditionsAgreed,
child: Container( child: Container(
@ -110,7 +137,7 @@ class _UserConsentScreenState extends State<UserConsentScreen> {
style: TextStyle( style: TextStyle(
fontSize: 16.f, fontSize: 16.f,
fontFamily: getIt.get<AppState>().isArabic() ? 'CairoArabic' : 'Poppins', fontFamily: getIt.get<AppState>().isArabic() ? 'CairoArabic' : 'Poppins',
fontWeight: FontWeight.w500, fontWeight: FontWeight.w600,
color: AppColors.primaryRedColor, color: AppColors.primaryRedColor,
decoration: TextDecoration.underline, decoration: TextDecoration.underline,
decorationColor: AppColors.primaryRedColor, decorationColor: AppColors.primaryRedColor,
@ -176,8 +203,9 @@ class _UserConsentScreenState extends State<UserConsentScreen> {
style: TextStyle( style: TextStyle(
fontSize: 16.f, fontSize: 16.f,
fontFamily: getIt.get<AppState>().isArabic() ? 'CairoArabic' : 'Poppins', fontFamily: getIt.get<AppState>().isArabic() ? 'CairoArabic' : 'Poppins',
fontWeight: FontWeight.w500, fontWeight: FontWeight.w600,
color: AppColors.primaryRedColor, color: AppColors.primaryRedColor,
decoration: TextDecoration.underline,
decorationColor: AppColors.primaryRedColor, decorationColor: AppColors.primaryRedColor,
), ),
), ),
@ -213,7 +241,7 @@ class _UserConsentScreenState extends State<UserConsentScreen> {
Expanded( Expanded(
child: CustomButton( child: CustomButton(
text: LocaleKeys.next.tr(context: context), text: LocaleKeys.next.tr(context: context),
onPressed: _canProceed ? () => context.navigateWithName(AppRoutes.userInfoSelection) : null, onPressed: _canProceed ? _onNextPressed : null,
isDisabled: !_canProceed, isDisabled: !_canProceed,
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor, borderColor: AppColors.primaryRedColor,

@ -71,8 +71,8 @@ dependencies:
firebase_analytics: ^11.5.1 firebase_analytics: ^11.5.1
firebase_crashlytics: ^4.3.8 firebase_crashlytics: ^4.3.8
jiffy: ^6.4.3 jiffy: ^6.4.3
# hijri_gregorian_calendar: # hijri_gregorian_calendar:
# path: /Users/aamir/StudioProjects/hijri_gregorian_calendar # path: /Users/aamir/StudioProjects/hijri_gregorian_calendar
sms_otp_auto_verify: ^2.2.0 sms_otp_auto_verify: ^2.2.0
web: any web: any
flutter_staggered_animations: ^1.1.1 flutter_staggered_animations: ^1.1.1
@ -89,7 +89,7 @@ dependencies:
path: package/flutter_swiper_view path: package/flutter_swiper_view
flutter_callkit_incoming: ^3.0.0 flutter_callkit_incoming: ^3.0.0
in_app_update: ^4.2.5 in_app_update: ^4.2.5
# device_preview: ^1.3.1 # device_preview: ^1.3.1
image_picker_android: ^0.8.13+16 image_picker_android: ^0.8.13+16
image_picker_platform_interface: ^2.10.0 image_picker_platform_interface: ^2.10.0

Loading…
Cancel
Save