Merge pull request 'dev_sultan' (#233) from dev_sultan into master

Reviewed-on: #233
master
khansultan1 21 hours ago
commit ef021c1fa0

Binary file not shown.

After

Width:  |  Height:  |  Size: 573 KiB

@ -83,6 +83,8 @@
"bookSuccessConfirmMore2412": "ستكون عملية الدفع عبر الإنترنت متاحة قبل 24 ساعة <20><>ن الموعد.",
"upcomingPaymentPending": "سيتم تفعيل الدفع عبر الإنترنت قبل 24 ساعة من موعد الموعد",
"upcomingPaymentNow": "ادفع عبر الإنترنت الآن لتجنب الانتظار الطويل",
"timeUntilAppointment": "الوقت المتبقي حتى الموعد",
"appointmentTimePassed": "انتهى وقت الموعد",
"upcomingQR": "استخدم رمز الاستجابة السريعة لتسجيل الوصول في المستشفى",
"upcomingVirtual": "هذا موعد افتراضي، يرجى الالتزام بالتعليمات لتجربة سلسة.",
"upcomingLivecare": "هذا موعد لايف كير",
@ -307,6 +309,7 @@
"vitalSignObese": "بدين",
"vitalSignOverweight": "زيادة الوزن",
"vitalSignUnderweight": "نقص الوزن",
"vitalSignSkinny": "نحيف جداً",
"myMedical": "نشط",
"myMedicalSubtitle": "الأدوية",
"myDoctor": "أطبائي",
@ -1456,6 +1459,8 @@
"setTimerOfReminder": "ضبط مؤقت التذكير",
"youHaveAppointmentWithDr": "لديك موعد مع د. ",
"hours": "ساعات",
"minutes": "دقائق",
"seconds": "ثواني",
"secs": "ثواني",
"noAllergiesDataFound": "لم يتم العثور على بيانات الحساسية...",
"heartRateDescription": "معدل ضربات قلبك يشير إلى عدد المرات التي ينبض فيها قلبك في الدقيقة",

@ -306,6 +306,7 @@
"vitalSignObese": "Obese",
"vitalSignOverweight": "Overweight",
"vitalSignUnderweight": "Underweight",
"vitalSignSkinny": "Underweight",
"myMedical": "Active",
"myMedicalSubtitle": "Medications",
"myDoctor": "My Doctors",
@ -1448,6 +1449,8 @@
"setTimerOfReminder": "Set the timer of reminder",
"youHaveAppointmentWithDr": "You have appointment with Dr. ",
"hours": "Hours",
"minutes": "Minutes",
"seconds": "Seconds",
"secs": "Secs",
"noAllergiesDataFound": "No allergies data found...",
"heartRateDescription": "Your heart rate indicates how many times your heart beats per minute",

@ -4,7 +4,7 @@ import 'package:hmg_patient_app_new/core/enums.dart';
class ApiConsts {
static const maxSmallScreen = 660;
static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod;
static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.preProd;
// static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT

@ -400,6 +400,7 @@ class AppAssets {
static const String fullBodyFrontFemale = '$pngBasePath/full_body_front_female.png';
static const String fullBodyBackFemale = '$pngBasePath/full_body_back_female.png';
static const String bmiFullBody = '$pngBasePath/bmi_image_1.png';
static const String bmiFullBodyFemale = '$pngBasePath/female_bmi.png';
static const String defaultMEP = '$pngBasePath/default_MEP.png';
}

@ -183,7 +183,7 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo {
@override
Future<Either<Failure, GenericApiModel<List<HospitalsModel>>>> getProjectList() async {
Map<String, dynamic> request = {'IsOnlineCheckIn': true, 'IsAdvancePayment': false, 'IsForER': true};
Map<String, dynamic> request = {"IsEROnlineCheckIn":true,'IsOnlineCheckIn': false, 'IsAdvancePayment': false, 'IsForER': true};
try {
GenericApiModel<List<HospitalsModel>>? apiResponse;

@ -11,6 +11,7 @@ enum VitalSignStatus {
obese,
overweight,
underweight,
skinny,
}
/// UI-only helper model for Vital Sign cards.
@ -34,8 +35,9 @@ class VitalSignUiModel {
///
/// Rules:
/// - Height is always blue.
/// - High, Obese, Overweight => red scheme.
/// - Low, Underweight => yellow scheme.
/// - High, Obese => red scheme.
/// - Overweight => orange scheme.
/// - Low, Underweight, Skinny => yellow scheme.
/// - Otherwise => green scheme (Normal).
static VitalSignUiModel scheme({required VitalSignStatus? status, required String label}) {
final l = label.toLowerCase();
@ -50,10 +52,8 @@ class VitalSignUiModel {
);
}
// High, Obese, Overweight => red scheme (health concerns)
if (status == VitalSignStatus.high ||
status == VitalSignStatus.obese ||
status == VitalSignStatus.overweight) {
// High, Obese => red scheme (health concerns)
if (status == VitalSignStatus.high || status == VitalSignStatus.obese) {
return VitalSignUiModel(
iconBg: AppColors.chipSecondaryLightRedColor,
iconFg: AppColors.primaryRedColor,
@ -62,8 +62,20 @@ class VitalSignUiModel {
);
}
// Low, Underweight => yellow scheme (warning)
if (status == VitalSignStatus.low || status == VitalSignStatus.underweight) {
// Overweight => orange scheme (warning)
if (status == VitalSignStatus.overweight) {
return VitalSignUiModel(
iconBg: AppColors.warningColorYellow.withValues(alpha: 0.12),
iconFg: AppColors.warningColorYellow,
chipBg: AppColors.warningColorYellow.withValues(alpha: 0.12),
chipFg: AppColors.warningColorYellow,
);
}
// Low, Underweight, Skinny => yellow scheme (warning)
if (status == VitalSignStatus.low ||
status == VitalSignStatus.underweight ||
status == VitalSignStatus.skinny) {
final Color yellowBg = AppColors.highAndLow.withValues(alpha: 0.12);
return VitalSignUiModel(
iconBg: yellowBg,
@ -98,6 +110,8 @@ class VitalSignUiModel {
return LocaleKeys.vitalSignOverweight.tr();
case VitalSignStatus.underweight:
return LocaleKeys.vitalSignUnderweight.tr();
case VitalSignStatus.skinny:
return LocaleKeys.vitalSignSkinny.tr();
}
}
@ -131,22 +145,30 @@ class VitalSignUiModel {
return null;
}
// BMI >= 25 (Overweight or Obese) => High
if (bmiResult >= 25) {
return VitalSignStatus.high;
// BMI >= 30 (Obese) => Red
if (bmiResult >= 30) {
return VitalSignStatus.obese;
}
// BMI >= 25 (Overweight) => Orange
else if (bmiResult >= 25) {
return VitalSignStatus.overweight;
}
// BMI >= 18.5 and < 25 => Normal
// BMI >= 18.5 (Normal) => Green
else if (bmiResult >= 18.5) {
return VitalSignStatus.normal;
}
// BMI < 18.5 (Underweight) => Low
// BMI >= 16 (Underweight) => Yellow
else if (bmiResult >= 16) {
return VitalSignStatus.underweight;
}
// BMI < 16 (Skinny/Severely underweight) => Yellow
else {
return VitalSignStatus.low;
return VitalSignStatus.skinny;
}
}
/// Weight status based on BMI with detailed classification
/// Returns: Obese, Overweight, Normal, Underweight
/// Returns: Obese, Overweight, Normal, Underweight, Skinny
static VitalSignStatus? weightStatus(dynamic bmi) {
// Return null if BMI is not available or is 0
final double bmiResult = double.tryParse(bmi.toString()) ?? 0;
@ -155,15 +177,26 @@ class VitalSignUiModel {
return null;
}
// BMI >= 30 (Obese) => Red
if (bmiResult >= 30) {
return VitalSignStatus.obese;
} else if (bmiResult >= 25) {
}
// BMI >= 25 (Overweight) => Orange
else if (bmiResult >= 25) {
return VitalSignStatus.overweight;
} else if (bmiResult >= 18.5) {
}
// BMI >= 18.5 (Normal) => Green
else if (bmiResult >= 18.5) {
return VitalSignStatus.normal;
} else {
}
// BMI >= 16 (Underweight) => Yellow
else if (bmiResult >= 16) {
return VitalSignStatus.underweight;
}
// BMI < 16 (Skinny/Severely underweight) => Yellow
else {
return VitalSignStatus.skinny;
}
}
}

@ -191,6 +191,7 @@ class InsuranceViewModel extends ChangeNotifier {
notifyListeners();
},
(apiResponse) {
patientInsuranceApprovalsList =[];
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {

@ -75,6 +75,7 @@ class PatientAppointmentHistoryResponseModel {
num? patientShareWithTax;
num? patientTaxAmount;
String? doctorNationalityFlagURL;
bool? isClinicReBookingAllowed;
PatientAppointmentHistoryResponseModel({
this.setupID,
@ -152,6 +153,7 @@ class PatientAppointmentHistoryResponseModel {
this.patientShareWithTax,
this.patientTaxAmount,
this.doctorNationalityFlagURL,
this.isClinicReBookingAllowed,
});
PatientAppointmentHistoryResponseModel.fromJson(Map<String, dynamic> json) {
@ -241,6 +243,7 @@ class PatientAppointmentHistoryResponseModel {
patientShareWithTax = json['PatientShareWithTax'];
patientTaxAmount = json['PatientTaxAmount'];
doctorNationalityFlagURL = json['DoctorNationalityFlagURL'];
isClinicReBookingAllowed = json['IsClinicReBookingAllowed'];
}
Map<String, dynamic> toJson() {
@ -313,6 +316,7 @@ class PatientAppointmentHistoryResponseModel {
data['RemaniningHoursTocanPay'] = this.remaniningHoursTocanPay;
data['SMSButtonVisable'] = this.sMSButtonVisable;
data['ServiceID'] = this.serviceID;
data['IsClinicReBookingAllowed'] = this.isClinicReBookingAllowed;
return data;
}
}

@ -52,6 +52,8 @@ class MyInvoicesViewModel extends ChangeNotifier {
notifyListeners();
},
(apiResponse) {
_originalInvoicesList =[];
allInvoicesList =[];
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {

@ -322,6 +322,7 @@ class CodegenLoader extends AssetLoader{
"vitalSignObese": "بدين",
"vitalSignOverweight": "زيادة الوزن",
"vitalSignUnderweight": "نقص الوزن",
"vitalSignSkinny": "نحيف جداً",
"myMedical": "نشط",
"myMedicalSubtitle": "الأدوية",
"myDoctor": "أطبائي",
@ -1465,6 +1466,8 @@ class CodegenLoader extends AssetLoader{
"setTimerOfReminder": "ضبط مؤقت التذكير",
"youHaveAppointmentWithDr": "لديك موعد مع د. ",
"hours": "ساعات",
"minutes": "دقائق",
"seconds": "ثواني",
"secs": "ثواني",
"noAllergiesDataFound": "لم يتم العثور على بيانات الحساسية...",
"heartRateDescription": "معدل ضربات قلبك يشير إلى عدد المرات التي ينبض فيها قلبك في الدقيقة",
@ -2034,6 +2037,7 @@ static const Map<String,dynamic> _en_US = {
"vitalSignObese": "Obese",
"vitalSignOverweight": "Overweight",
"vitalSignUnderweight": "Underweight",
"vitalSignSkinny": "Underweight",
"myMedical": "Active",
"myMedicalSubtitle": "Medications",
"myDoctor": "My Doctors",
@ -3174,6 +3178,8 @@ static const Map<String,dynamic> _en_US = {
"setTimerOfReminder": "Set the timer of reminder",
"youHaveAppointmentWithDr": "You have appointment with Dr. ",
"hours": "Hours",
"minutes": "Minutes",
"seconds": "Seconds",
"secs": "Secs",
"noAllergiesDataFound": "No allergies data found...",
"heartRateDescription": "Your heart rate indicates how many times your heart beats per minute",

@ -87,6 +87,8 @@ abstract class LocaleKeys {
static const bookSuccessConfirmMore2412 = 'bookSuccessConfirmMore2412';
static const upcomingPaymentPending = 'upcomingPaymentPending';
static const upcomingPaymentNow = 'upcomingPaymentNow';
static const timeUntilAppointment = 'timeUntilAppointment';
static const appointmentTimePassed = 'appointmentTimePassed';
static const upcomingQR = 'upcomingQR';
static const upcomingVirtual = 'upcomingVirtual';
static const upcomingLivecare = 'upcomingLivecare';
@ -308,6 +310,7 @@ abstract class LocaleKeys {
static const vitalSignObese = 'vitalSignObese';
static const vitalSignOverweight = 'vitalSignOverweight';
static const vitalSignUnderweight = 'vitalSignUnderweight';
static const vitalSignSkinny = 'vitalSignSkinny';
static const myMedical = 'myMedical';
static const myMedicalSubtitle = 'myMedicalSubtitle';
static const myDoctor = 'myDoctor';
@ -1451,6 +1454,8 @@ abstract class LocaleKeys {
static const setTimerOfReminder = 'setTimerOfReminder';
static const youHaveAppointmentWithDr = 'youHaveAppointmentWithDr';
static const hours = 'hours';
static const minutes = 'minutes';
static const seconds = 'seconds';
static const secs = 'secs';
static const noAllergiesDataFound = 'noAllergiesDataFound';
static const heartRateDescription = 'heartRateDescription';

@ -74,6 +74,12 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
bool isAppointmentWithin4Hours = false;
// Countdown timer variables
Timer? _countdownTimer;
Duration? _timeRemaining;
String _countdownText = "";
Function(void Function())? _modalSetState; // Callback for modal state updates
@override
void initState() {
scheduleMicrotask(() async {
@ -92,9 +98,114 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
}
}
});
// Initialize countdown timer for payment
if (widget.patientAppointmentHistoryResponseModel.nextAction == 15 ||
widget.patientAppointmentHistoryResponseModel.nextAction == 20) {
_startCountdownTimer();
}
super.initState();
}
void _startCountdownTimer() {
final appointmentDate = DateUtil.convertStringToDate(widget.patientAppointmentHistoryResponseModel.appointmentDate);
_updateTimeRemaining();
_countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (mounted) {
_updateTimeRemaining();
} else {
timer.cancel();
}
});
}
void _updateTimeRemaining() {
final appointmentDate = DateUtil.convertStringToDate(widget.patientAppointmentHistoryResponseModel.appointmentDate);
final now = DateTime.now();
final difference = appointmentDate.difference(now);
if (difference.isNegative) {
if (mounted) {
setState(() {
_timeRemaining = Duration.zero;
_countdownText = LocaleKeys.appointmentTimePassed.tr(context: context);
});
}
// Also update modal if callback is available
_modalSetState?.call(() {
_timeRemaining = Duration.zero;
_countdownText = LocaleKeys.appointmentTimePassed.tr(context: context);
});
_countdownTimer?.cancel();
} else {
if (mounted) {
setState(() {
_timeRemaining = difference;
_countdownText = _formatDuration(difference);
});
}
// Also update modal if callback is available
_modalSetState?.call(() {
_timeRemaining = difference;
_countdownText = _formatDuration(difference);
});
}
}
String _formatDuration(Duration duration) {
final days = duration.inDays;
final hours = duration.inHours.remainder(24);
final minutes = duration.inMinutes.remainder(60);
final seconds = duration.inSeconds.remainder(60);
// Format: DD : HH : MM : SS
return '${days.toString().padLeft(2, '0')} : ${hours.toString().padLeft(2, '0')} : ${minutes.toString().padLeft(2, '0')} : ${seconds.toString().padLeft(2, '0')}';
}
@override
void dispose() {
_countdownTimer?.cancel();
super.dispose();
}
// Helper method to build each time unit (number + label)
Widget _buildTimeUnit(String value, String label) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
alignment: Alignment.center,
child: value.toText32(
isBold: true,
color: AppColors.blackColor,
isEnglishOnly: true,
),
),
SizedBox(height: 4.h),
Container(
alignment: Alignment.center,
child: label.toText12(
color: AppColors.greyTextColor,
),
),
],
);
}
// Helper method to build time separator (:)
Widget _buildTimeSeparator() {
return Padding(
padding: EdgeInsets.only(bottom: 16.h, left: 6.w, right: 6.w),
child: ':'.toText32(
isBold: true,
color: AppColors.blackColor,
),
);
}
@override
Widget build(BuildContext context) {
myAppointmentsViewModel = Provider.of<MyAppointmentsViewModel>(context, listen: false);
@ -934,6 +1045,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
? (!(widget.patientAppointmentHistoryResponseModel.isActiveDoctor ?? true) ||
widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment! ||
widget.patientAppointmentHistoryResponseModel.isExecludeDoctor! ||
widget.patientAppointmentHistoryResponseModel.isClinicReBookingAllowed == false ||
!Utils.isClinicAllowedForRebook(widget.patientAppointmentHistoryResponseModel.clinicID))
? SizedBox.shrink()
: CustomButton(
@ -1126,14 +1238,86 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
});
// LoaderBottomSheet.hideLoader();
case 15:
getIt.get<DialogService>().showCommonBottomSheetWithoutH(
message: LocaleKeys.upcomingPaymentPending.tr(context: context),
label: LocaleKeys.notice.tr(),
onOkPressed: () {},
okLabel: "confirm",
cancelLabel: LocaleKeys.acknowledged.tr(context: context),
isConfirmButton: true,
);
// Ensure timer is running before showing modal
if (_countdownTimer == null || !_countdownTimer!.isActive) {
_startCountdownTimer();
}
showCommonBottomSheetWithoutHeight(
context,
title: LocaleKeys.notice.tr(),
child: StatefulBuilder(
builder: (context, setModalState) {
// Store the modal setState callback
_modalSetState = setModalState;
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// Message text
LocaleKeys.upcomingPaymentPending.tr(context: context).toText14(
color: AppColors.textColor,
isCenter: true,
),
SizedBox(height: 24.h),
// Countdown Timer - DD : HH : MM : SS format with labels
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Days
_buildTimeUnit(
_timeRemaining != null ? _timeRemaining!.inDays.toString().padLeft(2, '0') : '00',
LocaleKeys.days.tr(context: context),
),
_buildTimeSeparator(),
// Hours
_buildTimeUnit(
_timeRemaining != null ? _timeRemaining!.inHours.remainder(24).toString().padLeft(2, '0') : '00',
LocaleKeys.hours.tr(context: context),
),
_buildTimeSeparator(),
// Minutes
_buildTimeUnit(
_timeRemaining != null ? _timeRemaining!.inMinutes.remainder(60).toString().padLeft(2, '0') : '00',
LocaleKeys.minutes.tr(context: context),
),
_buildTimeSeparator(),
// Seconds
_buildTimeUnit(
_timeRemaining != null ? _timeRemaining!.inSeconds.remainder(60).toString().padLeft(2, '0') : '00',
LocaleKeys.seconds.tr(context: context),
),
],
),
SizedBox(height: 24.h),
// Green Acknowledge button with checkmark icon
CustomButton(
text: LocaleKeys.acknowledged.tr(context: context),
onPressed: () {
_modalSetState = null; // Clear callback when closing
Navigator.of(context).pop();
},
backgroundColor: AppColors.successColor,
borderColor: AppColors.successColor,
textColor: Colors.white,
fontSize: 16.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
height: 50.h,
icon: AppAssets.checkmark_icon,
iconColor: Colors.white,
),
],
);
},
),
callBackFunc: () {
_modalSetState = null; // Clear callback when closing
},
isFullScreen: false,
isCloseButtonVisible: true,
);
case 20:
myAppointmentsViewModel.setIsPatientAppointmentShareLoading(true);
Navigator.of(context).push(

@ -392,58 +392,62 @@ class AppointmentCard extends StatelessWidget {
}
}
return (patientAppointmentHistoryResponseModel.isActiveDoctor ?? true)
? Row(
children: [
Expanded(
flex: 6,
child: (AppointmentType.isArrived(patientAppointmentHistoryResponseModel)
? _getArrivedButton(context)
: CustomButton(
text: AppointmentType.getNextActionText(patientAppointmentHistoryResponseModel.nextAction),
onPressed: () => _goToDetails(context),
backgroundColor: AppointmentType.getNextActionButtonColor(patientAppointmentHistoryResponseModel.nextAction).withValues(alpha: 0.15),
borderColor: AppointmentType.getNextActionButtonColor(patientAppointmentHistoryResponseModel.nextAction).withValues(alpha: 0.01),
textColor: AppointmentType.getNextActionTextColor(patientAppointmentHistoryResponseModel.nextAction),
fontSize: (isFoldable || isTablet) ? 12.f : 14.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
icon: AppointmentType.getNextActionIcon(patientAppointmentHistoryResponseModel.nextAction),
iconColor: AppointmentType.getNextActionTextColor(patientAppointmentHistoryResponseModel.nextAction),
iconSize: 15.h,
))
.toShimmer2(isShow: isLoading),
),
SizedBox(width: 8.h),
Expanded(
flex: 1,
child: Container(
height: (isFoldable || isTablet) ? 50.h : 40.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.transparent,
borderRadius: 10.h,
side: BorderSide(
color: AppColors.textColor,
width: 1.2,
),
),
child: Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.textColor,
width: 24.w,
height: 24.h,
fit: BoxFit.contain,
),
),
).toShimmer2(isShow: isLoading).onPress(() {
_goToDetails(context);
}),
),
],
)
? (AppointmentType.isArrived(patientAppointmentHistoryResponseModel) &&
patientAppointmentHistoryResponseModel.isClinicReBookingAllowed == false)
? // Show only View Details button without arrow when rebooking not allowed
_getArrivedButton(context)
: Row(
children: [
Expanded(
flex: 6,
child: (AppointmentType.isArrived(patientAppointmentHistoryResponseModel)
? _getArrivedButton(context)
: CustomButton(
text: AppointmentType.getNextActionText(patientAppointmentHistoryResponseModel.nextAction),
onPressed: () => _goToDetails(context),
backgroundColor: AppointmentType.getNextActionButtonColor(patientAppointmentHistoryResponseModel.nextAction).withValues(alpha: 0.15),
borderColor: AppointmentType.getNextActionButtonColor(patientAppointmentHistoryResponseModel.nextAction).withValues(alpha: 0.01),
textColor: AppointmentType.getNextActionTextColor(patientAppointmentHistoryResponseModel.nextAction),
fontSize: (isFoldable || isTablet) ? 12.f : 14.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
icon: AppointmentType.getNextActionIcon(patientAppointmentHistoryResponseModel.nextAction),
iconColor: AppointmentType.getNextActionTextColor(patientAppointmentHistoryResponseModel.nextAction),
iconSize: 15.h,
))
.toShimmer2(isShow: isLoading),
),
SizedBox(width: 8.h),
Expanded(
flex: 1,
child: Container(
height: (isFoldable || isTablet) ? 50.h : 40.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.transparent,
borderRadius: 10.h,
side: BorderSide(
color: AppColors.textColor,
width: 1.2,
),
),
child: Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.textColor,
width: 24.w,
height: 24.h,
fit: BoxFit.contain,
),
),
).toShimmer2(isShow: isLoading).onPress(() {
_goToDetails(context);
}),
),
],
)
: CustomButton(
text: LocaleKeys.viewDetails.tr(context: context),
onPressed: () {
@ -475,54 +479,22 @@ class AppointmentCard extends StatelessWidget {
}
Widget _getArrivedButton(BuildContext context) {
// final isRecent = DateTime.now().difference(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate)).inDays <= 15;
//
// if (isRecent) {
// return CustomButton(
// text: LocaleKeys.askDoctor.tr(context: context),
// onPressed: () async {
// LoaderBottomSheet.showLoader(loadingText: LocaleKeys.checkingDoctorAvailability.tr(context: context));
// await myAppointmentsViewModel.isDoctorAvailable(
// projectID: patientAppointmentHistoryResponseModel.projectID,
// doctorId: patientAppointmentHistoryResponseModel.doctorID,
// clinicId: patientAppointmentHistoryResponseModel.clinicID,
// onSuccess: (value) async {
// if (value) {
// await myAppointmentsViewModel.getAskDoctorRequestTypes(onSuccess: (val) {
// LoaderBottomSheet.hideLoader();
// showCommonBottomSheetWithoutHeight(
// context,
// title: LocaleKeys.askDoctor.tr(context: context),
// child: AskDoctorRequestTypeSelect(
// askDoctorRequestTypeList: myAppointmentsViewModel.askDoctorRequestTypeList,
// myAppointmentsViewModel: myAppointmentsViewModel,
// patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
// ),
// callBackFunc: () {},
// isFullScreen: false,
// isCloseButtonVisible: true,
// );
// });
// } else {
// print("Doctor is not available");
// }
// });
// },
// backgroundColor: AppColors.secondaryLightRedColor,
// borderColor: AppColors.secondaryLightRedColor,
// textColor: AppColors.primaryRedColor,
// fontSize: (isFoldable || isTablet) ? 12.f : 14.f,
// fontWeight: FontWeight.w600,
// borderRadius: 12.r,
// padding: EdgeInsets.symmetric(horizontal: 10.w),
// // height: isTablet || isFoldable ? 46.h : 40.h,
// height: 40.h,
// icon: AppAssets.ask_doctor_icon,
// iconColor: AppColors.primaryRedColor,
// iconSize: 16.h,
// );
// }
if (patientAppointmentHistoryResponseModel.isClinicReBookingAllowed == false) {
return CustomButton(
text: LocaleKeys.viewDetails.tr(context: context),
onPressed: () => _goToDetails(context),
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,
fontSize: (isFoldable || isTablet) ? 12.f : 14.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
);
}
// Show Rebook button
return CustomButton(
borderSide: BorderSide(
color: AppColors.textColor,

@ -80,7 +80,7 @@ class _TriagePageState extends State<TriagePage> {
}
// Case 2: Should stop flag is true OR Case 3: Probability >= 70% OR Case 4: 7 or more questions answered
if (viewModel.shouldStopTriage || highestProbability >= 70.0 || viewModel.triageQuestionCount >= 7) {
if (viewModel.shouldStopTriage || highestProbability >= 70.0 || viewModel.triageQuestionCount >= 15) {
// Navigate to results/possible conditions screen
context.navigateWithName(AppRoutes.possibleConditionsPage);
return;

@ -236,7 +236,9 @@ class _VitalSignPageState extends State<VitalSignPage> {
fit: StackFit.expand,
children: [
Image.asset(
AppAssets.bmiFullBody,
getIt.get<AppState>().getAuthenticatedUser()?.gender == 1
? AppAssets.bmiFullBody
: AppAssets.bmiFullBodyFemale,
fit: BoxFit.cover,
alignment: Alignment.topCenter,
),

Loading…
Cancel
Save