From afe169d2d9f883ce6bd077c0fc0c45b5c59bab93 Mon Sep 17 00:00:00 2001 From: Sultan khan Date: Wed, 31 Dec 2025 17:17:46 +0300 Subject: [PATCH] silent login fix --- .../authentication/authentication_repo.dart | 8 +- .../hmg_services/hmg_services_repo.dart | 54 +++ .../hmg_services/hmg_services_view_model.dart | 39 +++ .../resq_models/vital_sign_respo_model.dart | 259 +++++++++++++++ .../covid19test/covid_19_questionnaire.dart | 2 +- .../hmg_services/services_page.dart | 28 +- .../vital_sign/vital_sign_page.dart | 308 ++++++++++++++++++ lib/routes/app_routes.dart | 5 +- 8 files changed, 688 insertions(+), 15 deletions(-) create mode 100644 lib/features/hmg_services/models/resq_models/vital_sign_respo_model.dart create mode 100644 lib/presentation/vital_sign/vital_sign_page.dart diff --git a/lib/features/authentication/authentication_repo.dart b/lib/features/authentication/authentication_repo.dart index 4a1517c..9b09c43 100644 --- a/lib/features/authentication/authentication_repo.dart +++ b/lib/features/authentication/authentication_repo.dart @@ -260,10 +260,10 @@ class AuthenticationRepoImp implements AuthenticationRepo { newRequest.forRegisteration = newRequest.isRegister ?? false; newRequest.isRegister = false; //silent login case removed token and login token - // if(newRequest.logInTokenID.isEmpty && newRequest.isSilentLogin == true && (newRequest.loginType==1 || newRequest.loginType==4)) { - // newRequest.logInTokenID = null; - // newRequest.deviceToken = null; - // } + if(newRequest.logInTokenID.isEmpty && newRequest.isSilentLogin == true && (newRequest.loginType==1 || newRequest.loginType==4)) { + newRequest.logInTokenID = null; + newRequest.deviceToken = null; + } } diff --git a/lib/features/hmg_services/hmg_services_repo.dart b/lib/features/hmg_services/hmg_services_repo.dart index 851ac93..37a813d 100644 --- a/lib/features/hmg_services/hmg_services_repo.dart +++ b/lib/features/hmg_services/hmg_services_repo.dart @@ -21,6 +21,7 @@ import 'models/resq_models/covid_get_test_proceedure_resp.dart'; import 'models/resq_models/get_covid_payment_info_resp.dart'; import 'models/resq_models/relationship_type_resp_mode.dart'; import 'models/resq_models/search_e_referral_resp_model.dart'; +import 'models/resq_models/vital_sign_respo_model.dart'; abstract class HmgServicesRepo { Future>>> getAllComprehensiveCheckupOrders(); @@ -65,6 +66,8 @@ abstract class HmgServicesRepo { Future>>> getCovidTestProcedures(); Future>> getCovidPaymentInfo(String procedureID, int projectID); + + Future>>> getPatientVitalSign(); } class HmgServicesRepoImp implements HmgServicesRepo { @@ -913,5 +916,56 @@ class HmgServicesRepoImp implements HmgServicesRepo { } } + @override + Future>>> getPatientVitalSign() async { + Map requestBody = {}; + + try { + GenericApiModel>? apiResponse; + Failure? failure; + + await apiClient.post( + GET_PATIENT_VITAL_SIGN, + body: requestBody, + onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + loggerService.logError("Patient Vital Sign API Failed: $error, Status: $statusCode"); + }, + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + try { + List vitalSignList = []; + + if (response['PatientVitalSignList'] != null && response['PatientVitalSignList'] is List) { + final vitalSignsList = response['PatientVitalSignList'] as List; + + for (var vitalSignJson in vitalSignsList) { + if (vitalSignJson is Map) { + vitalSignList.add(VitalSignResModel.fromJson(vitalSignJson)); + } + } + } + + apiResponse = GenericApiModel>( + messageStatus: messageStatus, + statusCode: statusCode, + errorMessage: errorMessage, + data: vitalSignList, + ); + } catch (e) { + loggerService.logError("Error parsing Patient Vital Sign: ${e.toString()}"); + failure = DataParsingFailure(e.toString()); + } + }, + ); + + if (failure != null) return Left(failure!); + if (apiResponse == null) return Left(ServerFailure("Unknown error")); + return Right(apiResponse!); + } catch (e) { + log("Unknown error in getPatientVitalSign: ${e.toString()}"); + return Left(UnknownFailure(e.toString())); + } + } + } diff --git a/lib/features/hmg_services/hmg_services_view_model.dart b/lib/features/hmg_services/hmg_services_view_model.dart index d702cab..b620c6d 100644 --- a/lib/features/hmg_services/hmg_services_view_model.dart +++ b/lib/features/hmg_services/hmg_services_view_model.dart @@ -15,6 +15,7 @@ import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get_cmc_all_orders_resp_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get_cmc_services_resp_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/search_e_referral_resp_model.dart'; +import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/vital_sign_respo_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; @@ -37,6 +38,7 @@ class HmgServicesViewModel extends ChangeNotifier { bool isCmcServicesLoading = false; bool isUpdatingOrder = false; bool isHospitalListLoading = false; + bool isVitalSignLoading = false; // HHC specific loading states bool isHhcOrdersLoading = false; @@ -47,6 +49,7 @@ class HmgServicesViewModel extends ChangeNotifier { List hospitalsList = []; List filteredHospitalsList = []; HospitalsModel? selectedHospital; + List vitalSignList = []; // HHC specific lists List hhcOrdersList = []; @@ -857,4 +860,40 @@ class HmgServicesViewModel extends ChangeNotifier { }, ); } + + Future getPatientVitalSign({ + Function(dynamic)? onSuccess, + Function(String)? onError, + }) async { + isVitalSignLoading = true; + notifyListeners(); + + final result = await hmgServicesRepo.getPatientVitalSign(); + + result.fold( + (failure) async { + isVitalSignLoading = false; + notifyListeners(); + await errorHandlerService.handleError(failure: failure); + if (onError != null) { + onError(failure.toString()); + } + }, + (apiResponse) { + isVitalSignLoading = false; + if (apiResponse.messageStatus == 1) { + vitalSignList = apiResponse.data ?? []; + notifyListeners(); + if (onSuccess != null) { + onSuccess(apiResponse); + } + } else { + notifyListeners(); + if (onError != null) { + onError(apiResponse.errorMessage ?? 'Unknown error'); + } + } + }, + ); + } } diff --git a/lib/features/hmg_services/models/resq_models/vital_sign_respo_model.dart b/lib/features/hmg_services/models/resq_models/vital_sign_respo_model.dart new file mode 100644 index 0000000..bc93f59 --- /dev/null +++ b/lib/features/hmg_services/models/resq_models/vital_sign_respo_model.dart @@ -0,0 +1,259 @@ +import 'package:hmg_patient_app_new/core/utils/date_util.dart'; + +class VitalSignResModel { + var transNo; + var projectID; + var weightKg; + var heightCm; + var temperatureCelcius; + var pulseBeatPerMinute; + var respirationBeatPerMinute; + var bloodPressureLower; + var bloodPressureHigher; + var sAO2; + var fIO2; + var painScore; + var bodyMassIndex; + var headCircumCm; + var leanBodyWeightLbs; + var idealBodyWeightLbs; + var temperatureCelciusMethod; + var pulseRhythm; + var respirationPattern; + var bloodPressureCuffLocation; + var bloodPressureCuffSize; + var bloodPressurePatientPosition; + var painLocation; + var painDuration; + var painCharacter; + var painFrequency; + bool? isPainManagementDone; + var status; + bool? isVitalsRequired; + var patientID; + var createdOn; + var doctorID; + var clinicID; + var triageCategory; + var gCScore; + var lineItemNo; + DateTime? vitalSignDate; + var actualTimeTaken; + var sugarLevel; + var fBS; + var rBS; + var observationType; + var heartRate; + var muscleTone; + var reflexIrritability; + var bodyColor; + var isFirstAssessment; + var dateofBirth; + var timeOfBirth; + var bloodPressure; + var bloodPressureCuffLocationDesc; + var bloodPressureCuffSizeDesc; + var bloodPressurePatientPositionDesc; + var clinicName; + var doctorImageURL; + var doctorName; + var painScoreDesc; + var pulseRhythmDesc; + var respirationPatternDesc; + var temperatureCelciusMethodDesc; + var time; + + VitalSignResModel( + {this.transNo, + this.projectID, + this.weightKg, + this.heightCm, + this.temperatureCelcius, + this.pulseBeatPerMinute, + this.respirationBeatPerMinute, + this.bloodPressureLower, + this.bloodPressureHigher, + this.sAO2, + this.fIO2, + this.painScore, + this.bodyMassIndex, + this.headCircumCm, + this.leanBodyWeightLbs, + this.idealBodyWeightLbs, + this.temperatureCelciusMethod, + this.pulseRhythm, + this.respirationPattern, + this.bloodPressureCuffLocation, + this.bloodPressureCuffSize, + this.bloodPressurePatientPosition, + this.painLocation, + this.painDuration, + this.painCharacter, + this.painFrequency, + this.isPainManagementDone, + this.status, + this.isVitalsRequired, + this.patientID, + this.createdOn, + this.doctorID, + this.clinicID, + this.triageCategory, + this.gCScore, + this.lineItemNo, + this.vitalSignDate, + this.actualTimeTaken, + this.sugarLevel, + this.fBS, + this.rBS, + this.observationType, + this.heartRate, + this.muscleTone, + this.reflexIrritability, + this.bodyColor, + this.isFirstAssessment, + this.dateofBirth, + this.timeOfBirth, + this.bloodPressure, + this.bloodPressureCuffLocationDesc, + this.bloodPressureCuffSizeDesc, + this.bloodPressurePatientPositionDesc, + this.clinicName, + this.doctorImageURL, + this.doctorName, + this.painScoreDesc, + this.pulseRhythmDesc, + this.respirationPatternDesc, + this.temperatureCelciusMethodDesc, + this.time}); + + VitalSignResModel.fromJson(Map json) { + transNo = json['TransNo']; + projectID = json['ProjectID']; + weightKg = json['WeightKg']; + heightCm = json['HeightCm']; + temperatureCelcius = json['TemperatureCelcius']; + pulseBeatPerMinute = json['PulseBeatPerMinute']; + respirationBeatPerMinute = json['RespirationBeatPerMinute']; + bloodPressureLower = json['BloodPressureLower']; + bloodPressureHigher = json['BloodPressureHigher']; + sAO2 = json['SAO2']; + fIO2 = json['FIO2']; + painScore = json['PainScore']; + bodyMassIndex = json['BodyMassIndex']; + headCircumCm = json['HeadCircumCm']; + leanBodyWeightLbs = json['LeanBodyWeightLbs']; + idealBodyWeightLbs = json['IdealBodyWeightLbs']; + temperatureCelciusMethod = json['TemperatureCelciusMethod']; + pulseRhythm = json['PulseRhythm']; + respirationPattern = json['RespirationPattern']; + bloodPressureCuffLocation = json['BloodPressureCuffLocation']; + bloodPressureCuffSize = json['BloodPressureCuffSize']; + bloodPressurePatientPosition = json['BloodPressurePatientPosition']; + painLocation = json['PainLocation']; + painDuration = json['PainDuration']; + painCharacter = json['PainCharacter']; + painFrequency = json['PainFrequency']; + isPainManagementDone = json['IsPainManagementDone']; + status = json['Status']; + isVitalsRequired = json['IsVitalsRequired']; + patientID = json['PatientID']; + createdOn = json['CreatedOn']; + doctorID = json['DoctorID']; + clinicID = json['ClinicID']; + triageCategory = json['TriageCategory']; + gCScore = json['GCScore']; + lineItemNo = json['LineItemNo']; + vitalSignDate = DateUtil.convertStringToDate(json['CreatedOn']); + actualTimeTaken = json['ActualTimeTaken']; + sugarLevel = json['SugarLevel']; + fBS = json['FBS']; + rBS = json['RBS']; + observationType = json['ObservationType']; + heartRate = json['HeartRate']; + muscleTone = json['MuscleTone']; + reflexIrritability = json['ReflexIrritability']; + bodyColor = json['BodyColor']; + isFirstAssessment = json['IsFirstAssessment']; + dateofBirth = json['DateofBirth']; + timeOfBirth = json['TimeOfBirth']; + bloodPressure = json['BloodPressure']; + bloodPressureCuffLocationDesc = json['BloodPressureCuffLocationDesc']; + bloodPressureCuffSizeDesc = json['BloodPressureCuffSizeDesc']; + bloodPressurePatientPositionDesc = json['BloodPressurePatientPositionDesc']; + clinicName = json['ClinicName']; + doctorImageURL = json['DoctorImageURL']; + doctorName = json['DoctorName']; + painScoreDesc = json['PainScoreDesc']; + pulseRhythmDesc = json['PulseRhythmDesc']; + respirationPatternDesc = json['RespirationPatternDesc']; + temperatureCelciusMethodDesc = json['TemperatureCelciusMethodDesc']; + time = json['Time']; + } + + Map toJson() { + final Map data = new Map(); + data['TransNo'] = this.transNo; + data['ProjectID'] = this.projectID; + data['WeightKg'] = this.weightKg; + data['HeightCm'] = this.heightCm; + data['TemperatureCelcius'] = this.temperatureCelcius; + data['PulseBeatPerMinute'] = this.pulseBeatPerMinute; + data['RespirationBeatPerMinute'] = this.respirationBeatPerMinute; + data['BloodPressureLower'] = this.bloodPressureLower; + data['BloodPressureHigher'] = this.bloodPressureHigher; + data['SAO2'] = this.sAO2; + data['FIO2'] = this.fIO2; + data['PainScore'] = this.painScore; + data['BodyMassIndex'] = this.bodyMassIndex; + data['HeadCircumCm'] = this.headCircumCm; + data['LeanBodyWeightLbs'] = this.leanBodyWeightLbs; + data['IdealBodyWeightLbs'] = this.idealBodyWeightLbs; + data['TemperatureCelciusMethod'] = this.temperatureCelciusMethod; + data['PulseRhythm'] = this.pulseRhythm; + data['RespirationPattern'] = this.respirationPattern; + data['BloodPressureCuffLocation'] = this.bloodPressureCuffLocation; + data['BloodPressureCuffSize'] = this.bloodPressureCuffSize; + data['BloodPressurePatientPosition'] = this.bloodPressurePatientPosition; + data['PainLocation'] = this.painLocation; + data['PainDuration'] = this.painDuration; + data['PainCharacter'] = this.painCharacter; + data['PainFrequency'] = this.painFrequency; + data['IsPainManagementDone'] = this.isPainManagementDone; + data['Status'] = this.status; + data['IsVitalsRequired'] = this.isVitalsRequired; + data['PatientID'] = this.patientID; + data['CreatedOn'] = this.createdOn; + data['DoctorID'] = this.doctorID; + data['ClinicID'] = this.clinicID; + data['TriageCategory'] = this.triageCategory; + data['GCScore'] = this.gCScore; + data['LineItemNo'] = this.lineItemNo; + data['VitalSignDate'] = this.vitalSignDate; + data['ActualTimeTaken'] = this.actualTimeTaken; + data['SugarLevel'] = this.sugarLevel; + data['FBS'] = this.fBS; + data['RBS'] = this.rBS; + data['ObservationType'] = this.observationType; + data['HeartRate'] = this.heartRate; + data['MuscleTone'] = this.muscleTone; + data['ReflexIrritability'] = this.reflexIrritability; + data['BodyColor'] = this.bodyColor; + data['IsFirstAssessment'] = this.isFirstAssessment; + data['DateofBirth'] = this.dateofBirth; + data['TimeOfBirth'] = this.timeOfBirth; + data['BloodPressure'] = this.bloodPressure; + data['BloodPressureCuffLocationDesc'] = this.bloodPressureCuffLocationDesc; + data['BloodPressureCuffSizeDesc'] = this.bloodPressureCuffSizeDesc; + data['BloodPressurePatientPositionDesc'] = + this.bloodPressurePatientPositionDesc; + data['ClinicName'] = this.clinicName; + data['DoctorImageURL'] = this.doctorImageURL; + data['DoctorName'] = this.doctorName; + data['PainScoreDesc'] = this.painScoreDesc; + data['PulseRhythmDesc'] = this.pulseRhythmDesc; + data['RespirationPatternDesc'] = this.respirationPatternDesc; + data['TemperatureCelciusMethodDesc'] = this.temperatureCelciusMethodDesc; + data['Time'] = this.time; + return data; + } +} diff --git a/lib/presentation/covid19test/covid_19_questionnaire.dart b/lib/presentation/covid19test/covid_19_questionnaire.dart index b9ac008..8608d80 100644 --- a/lib/presentation/covid19test/covid_19_questionnaire.dart +++ b/lib/presentation/covid19test/covid_19_questionnaire.dart @@ -102,7 +102,7 @@ class _Covid19QuestionnaireState extends State { separatorBuilder: (context, index) => SizedBox(height: 16.h), itemBuilder: (context, index) { final question = qaList[index]; - final isAnswerYes = question.ans == 1; + final isAnswerYes = question.ans == 1; return Row( children: [ diff --git a/lib/presentation/hmg_services/services_page.dart b/lib/presentation/hmg_services/services_page.dart index bf0b7f5..217a384 100644 --- a/lib/presentation/hmg_services/services_page.dart +++ b/lib/presentation/hmg_services/services_page.dart @@ -100,15 +100,25 @@ class ServicesPage extends StatelessWidget { LoaderBottomSheet.hideLoader(); }); }), - HmgServicesComponentModel( - 11, - "Covid 19 Test".needTranslation, - "".needTranslation, - AppAssets.covid19icon, - bgColor: AppColors.covid29Color, - true, - route: AppRoutes.covid19Test, - ) + // HmgServicesComponentModel( + // 11, + // "Covid 19 Test".needTranslation, + // "".needTranslation, + // AppAssets.covid19icon, + // bgColor: AppColors.covid29Color, + // true, + // route: AppRoutes.covid19Test, + // ), + + // HmgServicesComponentModel( + // 11, + // "Vital Sign".needTranslation, + // "".needTranslation, + // AppAssets.covid19icon, + // bgColor: AppColors.covid29Color, + // true, + // route: AppRoutes.vitalSign, + // ) // HmgServicesComponentModel( // 3, diff --git a/lib/presentation/vital_sign/vital_sign_page.dart b/lib/presentation/vital_sign/vital_sign_page.dart new file mode 100644 index 0000000..858e801 --- /dev/null +++ b/lib/presentation/vital_sign/vital_sign_page.dart @@ -0,0 +1,308 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:hmg_patient_app_new/core/app_assets.dart'; +import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; +import 'package:hmg_patient_app_new/core/utils/utils.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/features/hmg_services/hmg_services_view_model.dart'; +import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/vital_sign_respo_model.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/chip/app_custom_chip_widget.dart'; +import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; +import 'package:provider/provider.dart'; + +class VitalSignPage extends StatefulWidget { + const VitalSignPage({super.key}); + + @override + State createState() => _VitalSignPageState(); +} + +class _VitalSignPageState extends State { + @override + void initState() { + super.initState(); + final HmgServicesViewModel hmgServicesViewModel = context.read(); + + scheduleMicrotask(() async { + LoaderBottomSheet.showLoader(loadingText: 'Loading Vital Signs...'); + await hmgServicesViewModel.getPatientVitalSign( + onSuccess: (_) { + LoaderBottomSheet.hideLoader(); + }, + onError: (_) { + LoaderBottomSheet.hideLoader(); + }, + ); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColors.bgScaffoldColor, + body: CollapsingListView( + title: 'Vital Signs', + child: Consumer( + builder: (context, viewModel, child) { + + // Get the latest vital sign data (first item in the list) + VitalSignResModel? latestVitalSign = viewModel.vitalSignList.isNotEmpty + ? viewModel.vitalSignList.first + : null; + + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 16.h), + + // Main content with body image + Padding( + padding: EdgeInsets.symmetric(horizontal: 24.h), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Left side - Vital Sign Cards + Expanded( + child: Column( + children: [ + // BMI Card + _buildVitalSignCard( + icon: AppAssets.activity, + iconColor: AppColors.successColor, + iconBgColor: AppColors.successColor.withValues(alpha: 0.1), + label: 'BMI', + value: latestVitalSign?.bodyMassIndex?.toString() ?? '--', + unit: '', + chipText: _getBMIStatus(latestVitalSign?.bodyMassIndex), + chipBgColor: AppColors.successColor.withValues(alpha: 0.1), + chipTextColor: AppColors.successColor, + ), + SizedBox(height: 16.h), + + // Height Card + _buildVitalSignCard( + icon: AppAssets.height, + iconColor: AppColors.infoColor, + iconBgColor: AppColors.infoColor.withValues(alpha: 0.1), + label: 'Height', + value: latestVitalSign?.heightCm?.toString() ?? '--', + unit: 'cm', + ), + SizedBox(height: 16.h), + + // Weight Card + _buildVitalSignCard( + icon: AppAssets.weight, + iconColor: AppColors.successColor, + iconBgColor: AppColors.successColor.withValues(alpha: 0.1), + label: 'Weight', + value: latestVitalSign?.weightKg?.toString() ?? '--', + unit: 'kg', + chipText: 'Normal', + chipBgColor: AppColors.successColor.withValues(alpha: 0.1), + chipTextColor: AppColors.successColor, + ), + SizedBox(height: 16.h), + + // Blood Pressure Card + _buildVitalSignCard( + icon: AppAssets.activity, + iconColor: AppColors.warningColor, + iconBgColor: AppColors.warningColor.withValues(alpha: 0.1), + label: 'Blood Pressure', + value: latestVitalSign != null && + latestVitalSign.bloodPressureHigher != null && + latestVitalSign.bloodPressureLower != null + ? '${latestVitalSign.bloodPressureHigher}/${latestVitalSign.bloodPressureLower}' + : '--', + unit: '', + ), + SizedBox(height: 16.h), + + // Temperature Card + _buildVitalSignCard( + icon: AppAssets.activity, + iconColor: AppColors.errorColor, + iconBgColor: AppColors.errorColor.withValues(alpha: 0.1), + label: 'Temperature', + value: latestVitalSign?.temperatureCelcius?.toString() ?? '--', + unit: '°C', + ), + ], + ), + ), + + SizedBox(width: 16.h), + + // Right side - Body Image and Heart Rate + Respiratory Rate + Expanded( + child: Column( + children: [ + // Body anatomy image + Container( + height: 280.h, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 20.h, + hasShadow: true, + ), + child: Center( + child: Image.asset( + AppAssets.fullBodyFront, + height: 260.h, + fit: BoxFit.contain, + ), + ), + ), + SizedBox(height: 16.h), + + // Heart Rate Card + _buildVitalSignCard( + icon: AppAssets.heart, + iconColor: AppColors.errorColor, + iconBgColor: AppColors.errorColor.withValues(alpha: 0.1), + label: 'Heart Rate', + value: latestVitalSign?.heartRate?.toString() ?? + latestVitalSign?.pulseBeatPerMinute?.toString() ?? '--', + unit: 'bpm', + chipText: 'Normal', + chipBgColor: AppColors.successColor.withValues(alpha: 0.1), + chipTextColor: AppColors.successColor, + ), + SizedBox(height: 16.h), + + // Respiratory rate Card + _buildVitalSignCard( + icon: AppAssets.activity, + iconColor: AppColors.successColor, + iconBgColor: AppColors.successColor.withValues(alpha: 0.1), + label: 'Respiratory rate', + value: latestVitalSign?.respirationBeatPerMinute?.toString() ?? '--', + unit: 'bpm', + chipText: 'Normal', + chipBgColor: AppColors.successColor.withValues(alpha: 0.1), + chipTextColor: AppColors.successColor, + ), + ], + ), + ), + ], + ), + ), + + SizedBox(height: 60.h), + ], + ), + ); + }, + ), + ), + ); + } + + String? _getBMIStatus(dynamic bmi) { + if (bmi == null) return null; + double bmiValue = double.tryParse(bmi.toString()) ?? 0; + if (bmiValue < 18.5) return 'Underweight'; + if (bmiValue < 25) return 'Normal'; + if (bmiValue < 30) return 'Overweight'; + return 'Obese'; + } + + Widget _buildVitalSignCard({ + required String icon, + required Color iconColor, + required Color iconBgColor, + required String label, + required String value, + required String unit, + String? chipText, + Color? chipBgColor, + Color? chipTextColor, + }) { + return Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 20.h, + hasShadow: true, + ), + child: Padding( + padding: EdgeInsets.all(12.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + // Icon with background + Container( + padding: EdgeInsets.all(8.h), + decoration: BoxDecoration( + color: iconBgColor, + borderRadius: BorderRadius.circular(12.r), + ), + child: Utils.buildSvgWithAssets( + icon: icon, + width: 16.w, + height: 16.h, + iconColor: iconColor, + fit: BoxFit.contain, + ), + ), + SizedBox(width: 8.w), + Expanded( + child: label.toText10( + color: AppColors.textColorLight, + weight: FontWeight.w500, + ), + ), + // Forward arrow + Utils.buildSvgWithAssets( + icon: AppAssets.arrow_forward, + width: 16.w, + height: 16.h, + iconColor: AppColors.textColorLight, + fit: BoxFit.contain, + ), + ], + ), + SizedBox(height: 12.h), + + // Value + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + value.toText18( + isBold: true, + color: AppColors.textColor, + ), + if (unit.isNotEmpty) ...[ + SizedBox(width: 4.w), + unit.toText12( + color: AppColors.textColorLight, + ), + ], + ], + ), + + // Chip if available + if (chipText != null) ...[ + SizedBox(height: 8.h), + AppCustomChipWidget( + labelText: chipText, + backgroundColor: chipBgColor, + textColor: chipTextColor, + padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h), + ), + ], + ], + ), + ), + ); + } +} + diff --git a/lib/routes/app_routes.dart b/lib/routes/app_routes.dart index f0acd5b..78045b5 100644 --- a/lib/routes/app_routes.dart +++ b/lib/routes/app_routes.dart @@ -22,6 +22,7 @@ import 'package:hmg_patient_app_new/presentation/symptoms_checker/triage_screen. import 'package:hmg_patient_app_new/presentation/symptoms_checker/user_info_selection.dart'; import 'package:hmg_patient_app_new/presentation/symptoms_checker/user_info_selection/user_info_flow_manager.dart'; import 'package:hmg_patient_app_new/presentation/tele_consultation/zoom/call_screen.dart'; +import 'package:hmg_patient_app_new/presentation/vital_sign/vital_sign_page.dart'; import 'package:hmg_patient_app_new/presentation/water_monitor/water_consumption_screen.dart'; import 'package:hmg_patient_app_new/presentation/water_monitor/water_monitor_settings_screen.dart'; import 'package:hmg_patient_app_new/splashPage.dart'; @@ -45,6 +46,7 @@ class AppRoutes { static const String smartWatches = '/smartWatches'; static const String huaweiHealthExample = '/huaweiHealthExample'; static const String covid19Test = '/covid19Test'; + static const String vitalSign = '/vitalSign'; //appointments static const String bookAppointmentPage = '/bookAppointmentPage'; @@ -92,6 +94,7 @@ class AppRoutes { waterConsumptionScreen: (context) => WaterConsumptionScreen(), waterMonitorSettingsScreen: (context) => WaterMonitorSettingsScreen(), healthCalculatorsPage: (context) => HealthCalculatorsPage(type: HealthCalConEnum.calculator), - healthConvertersPage: (context) => HealthCalculatorsPage(type: HealthCalConEnum.converter) + healthConvertersPage: (context) => HealthCalculatorsPage(type: HealthCalConEnum.converter), + vitalSign: (context) => VitalSignPage() }; }