Design fixes on Fold

faiz_dev
faizatflutter 21 hours ago
parent cb299c5bca
commit 7b1684c455

@ -1,4 +1,3 @@
import 'dart:developer';
import 'dart:math' as math; import 'dart:math' as math;
import 'package:flutter/material.dart'; // These are the Viewport values of your Figma Design. import 'package:flutter/material.dart'; // These are the Viewport values of your Figma Design.
@ -26,8 +25,14 @@ extension ResponsiveExtension on num {
/// Check if device is likely a foldable /// Check if device is likely a foldable
bool get _isFoldable { bool get _isFoldable {
double aspectRatio = _screenWidth / _screenHeight; double aspectRatio = _screenWidth / _screenHeight;
// Foldable devices typically have aspect ratios close to 1:1 when unfolded double shorterSide = _screenWidth < _screenHeight ? _screenWidth : _screenHeight;
return (aspectRatio > 0.9 && aspectRatio < 1.1) && (_screenWidth > 700 || _screenHeight > 700);
// Foldable devices (unfolded) typically have:
// - Shorter side > 600 logical pixels (to exclude regular phones)
// - Aspect ratio between 0.80 and 0.92 (almost square, like Galaxy Z Fold)
// Galaxy Z Fold 5: 1812x2176 physical, ~690x796 logical = 0.866 aspect ratio
// Regular phones: typically 375-430 width, aspect ratio 0.45-0.55
return (shorterSide > 600) && (aspectRatio > 0.80 && aspectRatio < 0.92);
} }
/// Scale text size - enhanced for foldable devices /// Scale text size - enhanced for foldable devices
@ -53,7 +58,7 @@ extension ResponsiveExtension on num {
double get w { double get w {
double baseScale = (this * _screenWidth) / figmaDesignWidth; double baseScale = (this * _screenWidth) / figmaDesignWidth;
if (_isFoldable|| isTablet ) { if (_isFoldable || isTablet) {
// For foldables, use more conservative width scaling // For foldables, use more conservative width scaling
double scale = _screenWidth / figmaDesignWidthTF; double scale = _screenWidth / figmaDesignWidthTF;
scale = scale.clamp(0.8, 1.4); scale = scale.clamp(0.8, 1.4);
@ -67,7 +72,7 @@ extension ResponsiveExtension on num {
double get h { double get h {
double baseScale = (this * _screenHeight) / figmaDesignHeight; double baseScale = (this * _screenHeight) / figmaDesignHeight;
if (_isFoldable || isTablet ) { if (_isFoldable || isTablet) {
// For foldables, use height-based scaling but with constraints // For foldables, use height-based scaling but with constraints
double scale = (_screenHeight / figmaDesignHeightTF).clamp(0.8, 1.4); double scale = (_screenHeight / figmaDesignHeightTF).clamp(0.8, 1.4);
return this * scale; return this * scale;
@ -225,10 +230,16 @@ class SizeUtils {
deviceType = DeviceType.mobile; deviceType = DeviceType.mobile;
} }
log("longerSide: $longerSide"); debugPrint("============ Device Detection ============");
log("shorterSide: $shorterSide"); debugPrint("longerSide: $longerSide");
log("isTablet: $isTablet"); debugPrint("shorterSide: $shorterSide");
log("isFoldable: $isFoldable"); debugPrint("width: $width");
debugPrint("height: $height");
debugPrint("deviceType: $deviceType");
debugPrint("isTablet: $isTablet");
debugPrint("isFoldable: $isFoldable");
debugPrint("aspectRatio: ${width / height}");
debugPrint("==========================================");
} }
} }
@ -241,6 +252,12 @@ bool get isDesktop => SizeUtils.deviceType == DeviceType.desktop;
bool get isFoldable { bool get isFoldable {
double aspectRatio = SizeUtils.width / SizeUtils.height; double aspectRatio = SizeUtils.width / SizeUtils.height;
// Foldable devices typically have aspect ratios close to 1:1 when unfolded double shorterSide = SizeUtils.width < SizeUtils.height ? SizeUtils.width : SizeUtils.height;
return (aspectRatio > 0.9 && aspectRatio < 1.1) && (SizeUtils.width > 700 || SizeUtils.height > 700);
// Foldable devices (unfolded) typically have:
// - Shorter side > 600 logical pixels (to exclude regular phones)
// - Aspect ratio between 0.80 and 0.92 (almost square, like Galaxy Z Fold)
// Galaxy Z Fold 5: 1812x2176 physical, ~690x796 logical = 0.866 aspect ratio
// Regular phones: typically 375-430 width, aspect ratio 0.45-0.55
return (shorterSide > 600) && (aspectRatio > 0.80 && aspectRatio < 0.92);
} }

@ -3,7 +3,7 @@ import 'dart:math';
import 'package:hmg_patient_app_new/core/common_models/data_points.dart'; import 'package:hmg_patient_app_new/core/common_models/data_points.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'model/Vitals.dart'; import 'model/vitals_data_model.dart';
enum Durations { enum Durations {
daily("daily"), daily("daily"),

@ -1,18 +1,17 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:health/health.dart'; import 'package:health/health.dart';
import 'package:hmg_patient_app_new/core/common_models/data_points.dart';
import 'package:hmg_patient_app_new/core/common_models/smart_watch.dart'; import 'package:hmg_patient_app_new/core/common_models/smart_watch.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/loading_utils.dart';
import 'package:hmg_patient_app_new/features/smartwatch_health_data/health_service.dart'; import 'package:hmg_patient_app_new/features/smartwatch_health_data/health_service.dart';
import 'package:hmg_patient_app_new/presentation/smartwatches/activity_detail.dart';
import 'package:hmg_patient_app_new/presentation/smartwatches/smart_watches_health_data_screen.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import '../../core/common_models/data_points.dart'; import 'health_data_transformations.dart';
import '../../core/dependencies.dart'; import 'model/vitals_data_model.dart';
import '../../presentation/smartwatches/activity_detail.dart' show ActivityDetails;
import '../../presentation/smartwatches/smart_watch_activity.dart' show SmartWatchActivity;
import '../../services/navigation_service.dart' show NavigationService;
import 'HealthDataTransformation.dart';
import 'model/Vitals.dart';
class HealthProvider with ChangeNotifier { class HealthProvider with ChangeNotifier {
final HealthService _healthService = HealthService(); final HealthService _healthService = HealthService();
@ -22,7 +21,8 @@ class HealthProvider with ChangeNotifier {
String selectedTimeRange = '7D'; String selectedTimeRange = '7D';
int selectedTabIndex = 0; int selectedTabIndex = 0;
SmartWatchTypes? selectedWatchType ; SmartWatchTypes? selectedWatchType;
String selectedWatchURL = 'assets/images/png/smartwatches/apple-watch-5.jpg'; String selectedWatchURL = 'assets/images/png/smartwatches/apple-watch-5.jpg';
HealthDataTransformation healthDataTransformation = HealthDataTransformation(); HealthDataTransformation healthDataTransformation = HealthDataTransformation();
@ -90,7 +90,7 @@ class HealthProvider with ChangeNotifier {
healthData[type] = data; healthData[type] = data;
notifyListeners(); notifyListeners();
} catch (e) { } catch (e) {
print('Error refreshing metric $type: $e'); debugPrint('Error refreshing metric $type: $e');
} }
} }
@ -129,14 +129,12 @@ class HealthProvider with ChangeNotifier {
await getVitals(); await getVitals();
// LoaderBottomSheet.hideLoader(); // LoaderBottomSheet.hideLoader();
// await Future.delayed(Duration(seconds: 5)); // await Future.delayed(Duration(seconds: 5));
getIt.get<NavigationService>().pushPage(page: SmartWatchActivity()); getIt.get<NavigationService>().pushPage(page: SmartWatchesHealthDataScreen());
print('Device initialized successfully');
} }
notifyListeners(); notifyListeners();
} }
Future<void> getVitals() async { Future<void> getVitals() async {
final result = await _healthService.getVitals(); final result = await _healthService.getVitals();
vitals = result; vitals = result;
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
@ -186,15 +184,17 @@ class HealthProvider with ChangeNotifier {
} }
selectedData = yearly = healthDataTransformation.transformVitalsToDataPoints(vitals!, Durations.yearly.value, selectedSection); selectedData = yearly = healthDataTransformation.transformVitalsToDataPoints(vitals!, Durations.yearly.value, selectedSection);
break; break;
default:
{}
;
} }
notifyListeners(); notifyListeners();
} }
void navigateToDetails(String value, {required String sectionName, required String uom}) { void navigateToDetails(String value, {required String sectionName, required String uom}) {
getIt.get<NavigationService>().pushPage(page: ActivityDetails(selectedActivity: value, sectionName:sectionName, uom: uom,)); getIt.get<NavigationService>().pushPage(
page: ActivityDetails(
selectedActivity: value,
sectionName: sectionName,
uom: uom,
));
} }
void saveSelectedSection(String value) { void saveSelectedSection(String value) {
@ -243,7 +243,6 @@ class HealthProvider with ChangeNotifier {
count++; count++;
} }
}); });
print("total count is $count and total is $total");
averageValue = count > 0 ? total / count : null; averageValue = count > 0 ? total / count : null;
notifyListeners(); notifyListeners();
} }
@ -261,7 +260,7 @@ class HealthProvider with ChangeNotifier {
String firstNonEmptyValue(List<Vitals> dataPoints) { String firstNonEmptyValue(List<Vitals> dataPoints) {
try { try {
return dataPoints.firstWhere((dp) => dp.value != null && dp.value!.trim().isNotEmpty).value; return dataPoints.firstWhere((dp) => dp.value.trim().isNotEmpty).value;
} catch (e) { } catch (e) {
return "0"; // no non-empty value found return "0"; // no non-empty value found
} }

@ -5,7 +5,7 @@ import 'dart:io';
import 'package:health/health.dart'; import 'package:health/health.dart';
import 'package:hmg_patient_app_new/core/common_models/smart_watch.dart'; import 'package:hmg_patient_app_new/core/common_models/smart_watch.dart';
import 'package:hmg_patient_app_new/features/smartwatch_health_data/model/Vitals.dart'; import 'package:hmg_patient_app_new/features/smartwatch_health_data/model/vitals_data_model.dart';
import 'package:hmg_patient_app_new/features/smartwatch_health_data/watch_connectors/create_watch_helper.dart'; import 'package:hmg_patient_app_new/features/smartwatch_health_data/watch_connectors/create_watch_helper.dart';
import 'package:hmg_patient_app_new/features/smartwatch_health_data/watch_connectors/watch_helper.dart'; import 'package:hmg_patient_app_new/features/smartwatch_health_data/watch_connectors/watch_helper.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';

@ -1,5 +1,5 @@
class Vitals { class Vitals {
String value; String value;
final String timestamp; final String timestamp;
final String unitOfMeasure; final String unitOfMeasure;
@ -16,11 +16,6 @@ class Vitals {
unitOfMeasure: map['uom'] ?? "", unitOfMeasure: map['uom'] ?? "",
); );
} }
toString(){
return "{\"value\": \"$value\", \"timeStamp\": \"$timestamp\", \"uom\": \"$unitOfMeasure\"}";
}
} }
class VitalsWRTType { class VitalsWRTType {
@ -31,15 +26,21 @@ class VitalsWRTType {
final List<Vitals> activity; final List<Vitals> activity;
final List<Vitals> bodyOxygen; final List<Vitals> bodyOxygen;
final List<Vitals> bodyTemperature; final List<Vitals> bodyTemperature;
double maxHeartRate = double.negativeInfinity; double maxHeartRate = double.negativeInfinity;
double maxSleep = double.negativeInfinity; double maxSleep = double.negativeInfinity;
double maxStep= double.negativeInfinity; double maxStep = double.negativeInfinity;
double maxActivity = double.negativeInfinity; double maxActivity = double.negativeInfinity;
double maxBloodOxygen = double.negativeInfinity; double maxBloodOxygen = double.negativeInfinity;
double maxBodyTemperature = double.negativeInfinity; double maxBodyTemperature = double.negativeInfinity;
VitalsWRTType({required this.distance, required this.bodyOxygen, required this.bodyTemperature, required this.heartRate, required this.sleep, required this.step, required this.activity}); VitalsWRTType(
{required this.distance,
required this.bodyOxygen,
required this.bodyTemperature,
required this.heartRate,
required this.sleep,
required this.step,
required this.activity});
factory VitalsWRTType.fromMap(Map<dynamic, dynamic> map) { factory VitalsWRTType.fromMap(Map<dynamic, dynamic> map) {
List<Vitals> activity = []; List<Vitals> activity = [];
@ -82,16 +83,23 @@ class VitalsWRTType {
map["distance"].forEach((element) { map["distance"].forEach((element) {
element["uom"] = "km"; element["uom"] = "km";
var data = Vitals.fromMap(element); var data = Vitals.fromMap(element);
data.value = (double.parse(data.value)/1000).toStringAsFixed(2); data.value = (double.parse(data.value) / 1000).toStringAsFixed(2);
distance.add(data); distance.add(data);
}); });
return VitalsWRTType(bodyTemperature: bodyTemperature, bodyOxygen: bodyOxygen, heartRate: heartRate, sleep: sleeps, step: steps, activity: activity, distance: distance); return VitalsWRTType(
bodyTemperature: bodyTemperature,
bodyOxygen: bodyOxygen,
heartRate: heartRate,
sleep: sleeps,
step: steps,
activity: activity,
distance: distance);
} }
Map<String, List<Vitals>> getVitals() { Map<String, List<Vitals>> getVitals() {
return { return {
"heartRate": heartRate , "heartRate": heartRate,
"sleep": sleep, "sleep": sleep,
"steps": step, "steps": step,
"activity": activity, "activity": activity,

@ -6,7 +6,7 @@ import 'package:health/health.dart';
import 'package:hmg_patient_app_new/features/smartwatch_health_data/watch_connectors/watch_helper.dart' show WatchHelper; import 'package:hmg_patient_app_new/features/smartwatch_health_data/watch_connectors/watch_helper.dart' show WatchHelper;
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import '../model/Vitals.dart'; import '../model/vitals_data_model.dart';
class HealthConnectHelper extends WatchHelper { class HealthConnectHelper extends WatchHelper {
final Health health = Health(); final Health health = Health();

@ -364,10 +364,6 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
isFullScreen: false, isFullScreen: false,
isCloseButtonVisible: true, isCloseButtonVisible: true,
); );
// var isEventAddedOrRemoved = await CalenderUtilsNew.instance.checkAndRemove( id:"${widget.patientAppointmentHistoryResponseModel.appointmentNo}", );
// setState(() {
// myAppointmentsViewModel.setAppointmentReminder(isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel);
// });
}, },
onRescheduleTap: () async { onRescheduleTap: () async {
openDoctorScheduleCalendar(); openDoctorScheduleCalendar();
@ -507,67 +503,11 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
} }
}, },
) )
// Switch(
// activeThumbColor: AppColors.successColor,
// // activeTrackColor: AppColors.successColor.withValues(alpha: .15),
// value: widget.patientAppointmentHistoryResponseModel.hasReminder!,
// onChanged: (newValue) async {
// CalenderUtilsNew calender = CalenderUtilsNew.instance;
// bool isEventAddedOrRemoved = false;
// if(newValue == true){
// DateTime startDate = DateTime.now();
// DateTime endDate = DateUtil.convertStringToDate(widget
// .patientAppointmentHistoryResponseModel.appointmentDate);
// BottomSheetUtils().showReminderBottomSheet(
// context,
// endDate,
// widget.patientAppointmentHistoryResponseModel.doctorNameObj??"",
// "${widget.patientAppointmentHistoryResponseModel.appointmentNo}"??"",
// "",
// "",
// title: "Appointment with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj}",
// description:
// "${widget.patientAppointmentHistoryResponseModel.doctorNameObj} will be having an appointment on ${widget.patientAppointmentHistoryResponseModel.appointmentDate}",
// onSuccess: () {
// setState(() {
// myAppointmentsViewModel.setAppointmentReminder(newValue, widget.patientAppointmentHistoryResponseModel);
// });
// },
// isMultiAllowed: true,
// onMultiDateSuccess: (int selectedIndex) async {
// isEventAddedOrRemoved = await calender.createOrUpdateEvent(
// title:
// "Appointment Reminder with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj} on ${DateUtil.convertStringToDate(widget.patientAppointmentHistoryResponseModel.appointmentDate)}, Appointment #${widget.patientAppointmentHistoryResponseModel.appointmentNo}",
// description:
// "Appointment Reminder with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj} in ${widget.patientAppointmentHistoryResponseModel.projectName}",
// scheduleDateTime: DateUtil.convertStringToDate(widget
// .patientAppointmentHistoryResponseModel.appointmentDate),
// eventId: "${widget.patientAppointmentHistoryResponseModel.appointmentNo}",
// location: '',
// reminderMinutes: selectedIndex
// );
// setState(() {
// myAppointmentsViewModel.setAppointmentReminder(isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel);
// });
// },
// );
// }else {
// isEventAddedOrRemoved = await calender.checkAndRemove( id:"${widget.patientAppointmentHistoryResponseModel.appointmentNo}", );
// setState(() {
// myAppointmentsViewModel.setAppointmentReminder(!isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel);
// });
// }
//
//
// },
// ),
], ],
).paddingSymmetrical(16.w, 0) ).paddingSymmetrical(16.w, 0)
], ],
), ),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
!AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel) !AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel)
? Column( ? Column(
@ -602,48 +542,6 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
SizedBox(height: 16.h), SizedBox(height: 16.h),
], ],
), ),
// ((!AppointmentType.isConfirmed(widget.patientAppointmentHistoryResponseModel) && widget.patientAppointmentHistoryResponseModel.nextAction != 10)
// ? CustomButton(
// text: LocaleKeys.confirm.tr(),
// onPressed: () async {
// LoaderBottomSheet.showLoader(loadingText: LocaleKeys.confirmingAppointmentPleaseWait.tr(context: context));
// await myAppointmentsViewModel.confirmAppointment(
// patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
// onSuccess: (apiResponse) {
// LoaderBottomSheet.hideLoader();
// myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true);
// myAppointmentsViewModel.initAppointmentsViewModel();
// // myAppointmentsViewModel.getPatientAppointments(true, false);
// showCommonBottomSheetWithoutHeight(
// title: "",
// context,
// child: Utils.getSuccessWidget(loadingText: LocaleKeys.appointmentConfirmedSuccessfully.tr(context: context)),
// callBackFunc: () {
// Navigator.pushAndRemoveUntil(
// context,
// CustomPageRoute(
// page: LandingNavigation(),
// ),
// (r) => false);
// },
// isFullScreen: false,
// isCloseButtonVisible: false,
// isAutoDismiss: true
// );
// });
// },
// backgroundColor: AppColors.successColor,
// borderColor: AppColors.successColor,
// textColor: Colors.white,
// fontSize: 14.f,
// isBold: true,
// borderRadius: 12.r,
// height: 40.h,
// icon: AppAssets.confirm_appointment_icon,
// iconColor: Colors.white,
// iconSize: 16.h,
// )
// : SizedBox.shrink())
], ],
), ),
//TODO Add countdown timer in case of LiveCare Appointment //TODO Add countdown timer in case of LiveCare Appointment
@ -748,148 +646,6 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
); );
}), }),
SizedBox(height: 16.h), SizedBox(height: 16.h),
// Container(
// decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
// color: AppColors.whiteColor,
// borderRadius: 20.r,
// hasShadow: false,
// ),
// child: Row(
// mainAxisSize: MainAxisSize.max,
// children: [
// Utils.buildSvgWithAssets(icon: AppAssets.prescription_reminder_icon, width: 35.h, height: 35.h, applyThemeColor: false),
// SizedBox(width: 8.h),
// Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// LocaleKeys.setReminder.tr(context: context).toText13(isBold: true),
// LocaleKeys.notifyMeBeforeAppointment.tr(context: context).toText11(color: AppColors.textColorLight, isBold: true),
// ],
// ),
// const Spacer(),
// BellAnimatedSwitch(
// key: _bellSwitchKey,
// initialValue: widget.patientAppointmentHistoryResponseModel.hasReminder ?? false,
// activeColor: AppColors.successColor.withOpacity(0.2),
// inactiveColor: AppColors.lightGrayBGColor,
// activeCircleColor: AppColors.successColor,
// inactiveCircleColor: AppColors.greyTextColor,
// activeIconColor: AppColors.bgGreenColor,
// inactiveIconColor: AppColors.greyTextColor,
// activeIcon: Utils.buildSvgWithAssets(icon: AppAssets.bell, iconColor: AppColors.whiteColor, width: 15.w, height: 15.h),
// inactiveIcon: Utils.buildSvgWithAssets(icon: AppAssets.bell, iconColor: AppColors.whiteColor, width: 15.w, height: 15.h),
// onChanged: (newValue) async {
// CalenderUtilsNew calender = CalenderUtilsNew.instance;
// bool isEventAddedOrRemoved = false;
// if (newValue == true) {
// DateTime startDate = DateTime.now();
// DateTime endDate = DateUtil.convertStringToDate(widget.patientAppointmentHistoryResponseModel.appointmentDate);
//
// // Show reminder bottom sheet and check if permission was granted
// bool permissionGranted = await BottomSheetUtils().showReminderBottomSheet(
// context,
// endDate,
// widget.patientAppointmentHistoryResponseModel.doctorNameObj ?? "",
// "${widget.patientAppointmentHistoryResponseModel.appointmentNo}" ?? "",
// "",
// "",
// title: "Appointment with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj}",
// description:
// "${widget.patientAppointmentHistoryResponseModel.doctorNameObj} will be having an appointment on ${widget.patientAppointmentHistoryResponseModel.appointmentDate}",
// onSuccess: () {
// setState(() {
// myAppointmentsViewModel.setAppointmentReminder(newValue, widget.patientAppointmentHistoryResponseModel);
// });
// },
// isMultiAllowed: true,
// onMultiDateSuccess: (int selectedIndex) async {
// isEventAddedOrRemoved = await calender.createOrUpdateEvent(
// title:
// "Appointment Reminder with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj} on ${DateUtil.convertStringToDate(widget.patientAppointmentHistoryResponseModel.appointmentDate)}, Appointment #${widget.patientAppointmentHistoryResponseModel.appointmentNo}",
// description:
// "Appointment Reminder with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj} in ${widget.patientAppointmentHistoryResponseModel.projectName}",
// scheduleDateTime: DateUtil.convertStringToDate(widget.patientAppointmentHistoryResponseModel.appointmentDate),
// eventId: "${widget.patientAppointmentHistoryResponseModel.appointmentNo}",
// location: '',
// reminderMinutes: selectedIndex);
// setState(() {
// myAppointmentsViewModel.setAppointmentReminder(isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel);
// });
// },
// );
//
// // If permission was not granted, revert the switch back to OFF
// if (!permissionGranted) {
// _bellSwitchKey.currentState?.setSwitchValue(false);
// }
// } else {
// isEventAddedOrRemoved = await calender.checkAndRemove(
// id: "${widget.patientAppointmentHistoryResponseModel.appointmentNo}",
// );
// setState(() {
// myAppointmentsViewModel.setAppointmentReminder(!isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel);
// });
// }
// },
// )
//
// // Switch(
// // activeThumbColor: AppColors.successColor,
// // // activeTrackColor: AppColors.successColor.withValues(alpha: .15),
// // value: widget.patientAppointmentHistoryResponseModel.hasReminder!,
// // onChanged: (newValue) async {
// // CalenderUtilsNew calender = CalenderUtilsNew.instance;
// // bool isEventAddedOrRemoved = false;
// // if(newValue == true){
// // DateTime startDate = DateTime.now();
// // DateTime endDate = DateUtil.convertStringToDate(widget
// // .patientAppointmentHistoryResponseModel.appointmentDate);
// // BottomSheetUtils().showReminderBottomSheet(
// // context,
// // endDate,
// // widget.patientAppointmentHistoryResponseModel.doctorNameObj??"",
// // "${widget.patientAppointmentHistoryResponseModel.appointmentNo}"??"",
// // "",
// // "",
// // title: "Appointment with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj}",
// // description:
// // "${widget.patientAppointmentHistoryResponseModel.doctorNameObj} will be having an appointment on ${widget.patientAppointmentHistoryResponseModel.appointmentDate}",
// // onSuccess: () {
// // setState(() {
// // myAppointmentsViewModel.setAppointmentReminder(newValue, widget.patientAppointmentHistoryResponseModel);
// // });
// // },
// // isMultiAllowed: true,
// // onMultiDateSuccess: (int selectedIndex) async {
// // isEventAddedOrRemoved = await calender.createOrUpdateEvent(
// // title:
// // "Appointment Reminder with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj} on ${DateUtil.convertStringToDate(widget.patientAppointmentHistoryResponseModel.appointmentDate)}, Appointment #${widget.patientAppointmentHistoryResponseModel.appointmentNo}",
// // description:
// // "Appointment Reminder with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj} in ${widget.patientAppointmentHistoryResponseModel.projectName}",
// // scheduleDateTime: DateUtil.convertStringToDate(widget
// // .patientAppointmentHistoryResponseModel.appointmentDate),
// // eventId: "${widget.patientAppointmentHistoryResponseModel.appointmentNo}",
// // location: '',
// // reminderMinutes: selectedIndex
// // );
// // setState(() {
// // myAppointmentsViewModel.setAppointmentReminder(isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel);
// // });
// // },
// // );
// // }else {
// // isEventAddedOrRemoved = await calender.checkAndRemove( id:"${widget.patientAppointmentHistoryResponseModel.appointmentNo}", );
// // setState(() {
// // myAppointmentsViewModel.setAppointmentReminder(!isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel);
// // });
// // }
// //
// //
// // },
// // ),
// ],
// ).paddingSymmetrical(16.h, 16.h),
// ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
], ],
) )
@ -900,7 +656,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
crossAxisCount: 3, crossAxisCount: 3,
crossAxisSpacing: 16.h, crossAxisSpacing: 16.h,
mainAxisSpacing: 16.w, mainAxisSpacing: 16.w,
mainAxisExtent: 115.h, childAspectRatio: isFoldable ? 1.2 : (isTablet ? 1.1 : 0.78),
), ),
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
@ -1093,213 +849,6 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
], ],
); );
}), }),
// Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// "Lab & Radiology".needTranslation.toText18(isBold: true),
// SizedBox(height: 16.h),
// Row(
// children: [
// Expanded(
// child: LabRadCard(
// icon: AppAssets.lab_result_icon,
// labelText: LocaleKeys.labResults.tr(context: context),
// // labOrderTests: ["Complete blood count", "Creatinine", "Blood Sugar"],
// // labOrderTests: labViewModel.isLabOrdersLoading ? [] : labViewModel.labOrderTests,
// labOrderTests: [],
// // isLoading: labViewModel.isLabOrdersLoading,
// isLoading: false,
// ).onPress(() {
// Navigator.of(context).push(
// CustomPageRoute(
// page: LabOrdersPage(),
// ),
// );
// }),
// ),
// SizedBox(width: 16.h),
// Expanded(
// child: LabRadCard(
// icon: AppAssets.radiology_icon,
// labelText: LocaleKeys.radiology.tr(context: context),
// // labOrderTests: ["Chest X-ray", "Abdominal Ultrasound", "Dental X-ray"],
// labOrderTests: [],
// isLoading: false,
// ).onPress(() {
// Navigator.of(context).push(
// CustomPageRoute(
// page: RadiologyOrdersPage(),
// ),
// );
// }),
// ),
// ],
// ),
// SizedBox(height: 16.h),
// LocaleKeys.prescriptions.tr(context: context).toText18(isBold: true),
// SizedBox(height: 16.h),
// Consumer<PrescriptionsViewModel>(builder: (context, prescriptionVM, child) {
// return prescriptionVM.isPrescriptionsDetailsLoading
// ? const MoviesShimmerWidget()
// : Container(
// decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
// color: Colors.white,
// borderRadius: 20.r,
// ),
// padding: EdgeInsets.all(16.w),
// child: Column(
// children: [
// // ListView.separated(
// // itemCount: prescriptionVM.prescriptionDetailsList.length,
// // shrinkWrap: true,
// // padding: EdgeInsets.only(right: 8.w),
// // physics: NeverScrollableScrollPhysics(),
// // itemBuilder: (context, index) {
// // return AnimationConfiguration.staggeredList(
// // position: index,
// // duration: const Duration(milliseconds: 500),
// // child: SlideAnimation(
// // verticalOffset: 100.0,
// // child: FadeInAnimation(
// // child: Row(
// // children: [
// // Utils.buildSvgWithAssets(
// // icon: AppAssets.prescription_item_icon,
// // width: 40.h,
// // height: 40.h,
// // ),
// // SizedBox(width: 8.h),
// // Row(
// // mainAxisSize: MainAxisSize.max,
// // children: [
// // Column(
// // children: [
// // prescriptionVM.prescriptionDetailsList[index].itemDescription!
// // .toText12(isBold: true, maxLine: 1),
// // "Prescribed By: ${widget.patientAppointmentHistoryResponseModel.doctorTitle} ${widget.patientAppointmentHistoryResponseModel.doctorNameObj}"
// // .needTranslation
// // .toText10(
// // weight: FontWeight.w600,
// // color: AppColors.greyTextColor,
// // letterSpacing: -0.4),
// // ],
// // ),
// // SizedBox(width: 68.w),
// // Transform.flip(
// // flipX: appState.isArabic(),
// // child: Utils.buildSvgWithAssets(
// // icon: AppAssets.forward_arrow_icon,
// // iconColor: AppColors.blackColor,
// // width: 18.w,
// // height: 13.h,
// // fit: BoxFit.contain,
// // ),
// // ),
// // ],
// // ),
// // ],
// // ),
// // ),
// // ),
// // );
// // },
// // separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
// // ).onPress(() {
// // prescriptionVM.setPrescriptionsDetailsLoading();
// // Navigator.of(context).push(
// // CustomPageRoute(
// // page: PrescriptionDetailPage(prescriptionsResponseModel: getPrescriptionRequestModel()),
// // ),
// // );
// // }),
// SizedBox(height: 16.h),
// const Divider(color: AppColors.dividerColor),
// SizedBox(height: 16.h),
// // Wrap(
// // runSpacing: 6.w,
// // children: [
// // // Expanded(
// // // child: CustomButton(
// // // text: widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! ? LocaleKeys.resendOrder.tr(context: context) : LocaleKeys.prescriptionDeliveryError.tr(context: context),
// // // onPressed: () {},
// // // backgroundColor: AppColors.secondaryLightRedColor,
// // // borderColor: AppColors.secondaryLightRedColor,
// // // textColor: AppColors.primaryRedColor,
// // // fontSize: 14,
// // // isBold: true,
// // // borderRadius: 12.h,
// // // height: 40.h,
// // // icon: AppAssets.appointment_calendar_icon,
// // // iconColor: AppColors.primaryRedColor,
// // // iconSize: 16.h,
// // // ),
// // // ),
// // // SizedBox(width: 16.h),
// // Expanded(
// // child: CustomButton(
// // text: "Refill & Delivery".needTranslation,
// // onPressed: () {
// // Navigator.of(context)
// // .push(
// // CustomPageRoute(
// // page: PrescriptionsListPage(),
// // ),
// // )
// // .then((val) {
// // prescriptionsViewModel.setPrescriptionsDetailsLoading();
// // prescriptionsViewModel.getPrescriptionDetails(getPrescriptionRequestModel());
// // });
// // },
// // backgroundColor: AppColors.secondaryLightRedColor,
// // borderColor: AppColors.secondaryLightRedColor,
// // textColor: AppColors.primaryRedColor,
// // fontSize: 14.f,
// // isBold: true,
// // borderRadius: 12.r,
// // height: 40.h,
// // icon: AppAssets.requests,
// // iconColor: AppColors.primaryRedColor,
// // iconSize: 16.h,
// // ),
// // ),
// //
// // SizedBox(width: 16.w),
// // Expanded(
// // child: CustomButton(
// // text: "All Prescriptions".needTranslation,
// // onPressed: () {
// // Navigator.of(context)
// // .push(
// // CustomPageRoute(
// // page: PrescriptionsListPage(),
// // ),
// // )
// // .then((val) {
// // prescriptionsViewModel.setPrescriptionsDetailsLoading();
// // prescriptionsViewModel.getPrescriptionDetails(getPrescriptionRequestModel());
// // });
// // },
// // backgroundColor: AppColors.secondaryLightRedColor,
// // borderColor: AppColors.secondaryLightRedColor,
// // textColor: AppColors.primaryRedColor,
// // fontSize: 14.f,
// // isBold: true,
// // borderRadius: 12.r,
// // height: 40.h,
// // icon: AppAssets.requests,
// // iconColor: AppColors.primaryRedColor,
// // iconSize: 16.h,
// // ),
// // ),
// // ],
// // ),
// ],
// ),
// );
// }),
// ],
// ),
], ],
).paddingAll(24.w), ).paddingAll(24.w),
), ),

@ -1,3 +1,5 @@
import 'dart:ui' as ui;
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';
@ -17,8 +19,6 @@ import 'package:hmg_patient_app_new/theme/colors.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/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'dart:ui' as ui;
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
@ -67,8 +67,8 @@ class AppointmentDoctorCard extends StatelessWidget {
Transform.translate( Transform.translate(
offset: Offset(0.0, -20.h), offset: Offset(0.0, -20.h),
child: Container( child: Container(
width: 40.w, width: 50.h,
height: 40.h, height: 50.h,
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColors.whiteColor, color: AppColors.whiteColor,
shape: BoxShape.circle, // Makes the container circular shape: BoxShape.circle, // Makes the container circular
@ -80,9 +80,10 @@ class AppointmentDoctorCard extends StatelessWidget {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.w, height: 15.h, iconColor: AppColors.ratingColorYellow), Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.h, height: 15.h, iconColor: AppColors.ratingColorYellow),
SizedBox(height: 2.h), SizedBox(height: 2.h),
"${patientAppointmentHistoryResponseModel.decimalDoctorRate ?? 0.0}".toText11(isBold: true, color: AppColors.textColor, isEnglishOnly: true), "${patientAppointmentHistoryResponseModel.decimalDoctorRate ?? 0.0}"
.toText11(isBold: true, color: AppColors.textColor, isEnglishOnly: true),
], ],
), ),
).circle(100), ).circle(100),
@ -97,9 +98,14 @@ class AppointmentDoctorCard extends StatelessWidget {
children: [ children: [
Row( Row(
children: [ children: [
patientAppointmentHistoryResponseModel.doctorNameObj!.toText16(isBold: true, isEnglishOnly: !Utils.isArabicText(patientAppointmentHistoryResponseModel.doctorNameObj ?? "")), patientAppointmentHistoryResponseModel.doctorNameObj!.toText16(
isBold: true,
isEnglishOnly: !Utils.isArabicText(patientAppointmentHistoryResponseModel.doctorNameObj ?? ""),
textOverflow: TextOverflow.ellipsis,
),
SizedBox(width: 12.w), SizedBox(width: 12.w),
(patientAppointmentHistoryResponseModel.doctorNationalityFlagURL != null && patientAppointmentHistoryResponseModel.doctorNationalityFlagURL!.isNotEmpty) (patientAppointmentHistoryResponseModel.doctorNationalityFlagURL != null &&
patientAppointmentHistoryResponseModel.doctorNationalityFlagURL!.isNotEmpty)
? Image.network( ? Image.network(
patientAppointmentHistoryResponseModel.doctorNationalityFlagURL ?? "https://hmgwebservices.com/Images/flag/SAU.png", patientAppointmentHistoryResponseModel.doctorNationalityFlagURL ?? "https://hmgwebservices.com/Images/flag/SAU.png",
width: 20.h, width: 20.h,
@ -130,19 +136,25 @@ class AppointmentDoctorCard extends StatelessWidget {
child: AppCustomChipWidget( child: AppCustomChipWidget(
labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 6.w), labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 6.w),
icon: AppAssets.doctor_calendar_icon, icon: AppAssets.doctor_calendar_icon,
richText: "${DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)} ${DateUtil.formatDateToTimeLang( richText:
"${DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)} ${DateUtil.formatDateToTimeLang(
DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate),
false, false,
)}" )}"
.toText10(isBold: true), .toText10(isBold: true),
), ),
), ),
AppCustomChipWidget( AppCustomChipWidget(
labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 6.w), labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 6.w),
icon: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppAssets.walkin_appointment_icon : AppAssets.small_livecare_icon, icon: !patientAppointmentHistoryResponseModel.isLiveCareAppointment!
? AppAssets.walkin_appointment_icon
: AppAssets.small_livecare_icon,
iconColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.textColor : Colors.white, iconColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.textColor : Colors.white,
labelText: patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? LocaleKeys.livecare.tr(context: context) : LocaleKeys.walkin.tr(context: context), labelText: patientAppointmentHistoryResponseModel.isLiveCareAppointment!
backgroundColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.greyColor : AppColors.successColor, ? LocaleKeys.livecare.tr(context: context)
: LocaleKeys.walkin.tr(context: context),
backgroundColor:
!patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.greyColor : AppColors.successColor,
textColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.textColor : Colors.white, textColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.textColor : Colors.white,
), ),
], ],
@ -150,10 +162,12 @@ class AppointmentDoctorCard extends StatelessWidget {
], ],
), ),
), ),
patientAppointmentHistoryResponseModel.isLiveCareAppointment! ||
patientAppointmentHistoryResponseModel.isLiveCareAppointment! || patientAppointmentHistoryResponseModel.isClinicReBookingAllowed! ==false || patientAppointmentHistoryResponseModel.isActiveDoctor! == false patientAppointmentHistoryResponseModel.isClinicReBookingAllowed! == false ||
patientAppointmentHistoryResponseModel.isActiveDoctor! == false
? SizedBox.shrink() ? SizedBox.shrink()
: Utils.buildSvgWithAssets(icon: AppAssets.doctor_profile_icon, width: 20.h, height: 20.h, fit: BoxFit.scaleDown).onPress(() async { : Utils.buildSvgWithAssets(icon: AppAssets.doctor_profile_icon, width: 20.h, height: 20.h, fit: BoxFit.scaleDown)
.onPress(() async {
DoctorsListResponseModel selectedDoctor = DoctorsListResponseModel(); DoctorsListResponseModel selectedDoctor = DoctorsListResponseModel();
selectedDoctor.doctorID = patientAppointmentHistoryResponseModel.doctorID; selectedDoctor.doctorID = patientAppointmentHistoryResponseModel.doctorID;
selectedDoctor.doctorImageURL = patientAppointmentHistoryResponseModel.doctorImageURL; selectedDoctor.doctorImageURL = patientAppointmentHistoryResponseModel.doctorImageURL;
@ -197,8 +211,7 @@ class AppointmentDoctorCard extends StatelessWidget {
AppointmentType.isArrived(patientAppointmentHistoryResponseModel), AppointmentType.isArrived(patientAppointmentHistoryResponseModel),
), ),
), ),
if (timerWidget != null) if (timerWidget != null) timerWidget ?? SizedBox()
timerWidget ?? SizedBox()
], ],
), ),
), ),

@ -92,7 +92,7 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
// ], // ],
// ), // ),
SizedBox( SizedBox(
height: 350.h, height: MediaQuery.of(context).size.height * 0.45,
child: Directionality( child: Directionality(
textDirection: isArabic ? ui.TextDirection.rtl : ui.TextDirection.ltr, textDirection: isArabic ? ui.TextDirection.rtl : ui.TextDirection.ltr,
child: Localizations.override( child: Localizations.override(
@ -102,7 +102,7 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
controller: _calendarController, controller: _calendarController,
minDate: DateTime.now(), minDate: DateTime.now(),
showNavigationArrow: true, showNavigationArrow: true,
headerHeight: 60.h, // headerHeight: 60.h,
headerStyle: CalendarHeaderStyle( headerStyle: CalendarHeaderStyle(
backgroundColor: AppColors.transparent, backgroundColor: AppColors.transparent,
textAlign: isArabic ? TextAlign.end : TextAlign.start, textAlign: isArabic ? TextAlign.end : TextAlign.start,
@ -157,8 +157,11 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
), ),
//TODO: Add Next Day Span here //TODO: Add Next Day Span here
dayEvents.isNotEmpty dayEvents.isNotEmpty
? SizedBox( ? ConstrainedBox(
height: 100.h, constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.15,
minHeight: 0,
),
child: Directionality( child: Directionality(
textDirection: isArabic ? ui.TextDirection.rtl : ui.TextDirection.ltr, textDirection: isArabic ? ui.TextDirection.rtl : ui.TextDirection.ltr,
child: SingleChildScrollView( child: SingleChildScrollView(
@ -169,7 +172,7 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
spacing: 6.h, spacing: 6.h,
runSpacing: 6.h, runSpacing: 6.h,
children: List.generate( children: List.generate(
dayEvents.length, // Generate a large number of items to ensure scrolling dayEvents.length,
(index) => TimeSlotChip( (index) => TimeSlotChip(
label: dayEvents[index].isoTime!, label: dayEvents[index].isoTime!,
isSelected: index == selectedButtonIndex, isSelected: index == selectedButtonIndex,
@ -204,7 +207,8 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
), ),
); );
} else { } else {
bookAppointmentsViewModel.getAppointmentNearestGate(projectID: bookAppointmentsViewModel.selectedDoctor.projectID!, clinicID: bookAppointmentsViewModel.selectedDoctor.clinicID!); bookAppointmentsViewModel.getAppointmentNearestGate(
projectID: bookAppointmentsViewModel.selectedDoctor.projectID!, clinicID: bookAppointmentsViewModel.selectedDoctor.clinicID!);
bookAppointmentsViewModel.setSelectedAppointmentDateTime(selectedDate, selectedTime, selectedDateDisplay); bookAppointmentsViewModel.setSelectedAppointmentDateTime(selectedDate, selectedTime, selectedDateDisplay);
Navigator.of(context).pop(); Navigator.of(context).pop();
Navigator.of(context).push( Navigator.of(context).push(
@ -221,7 +225,8 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Lottie.asset(AppAnimations.errorAnimation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill), Lottie.asset(AppAnimations.errorAnimation,
repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
SizedBox(height: 8.h), SizedBox(height: 8.h),
(LocaleKeys.loginToUseService.tr(context: context)).toText16(color: AppColors.blackColor), (LocaleKeys.loginToUseService.tr(context: context)).toText16(color: AppColors.blackColor),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@ -320,7 +325,12 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
selectedButtonIndex = 0; selectedButtonIndex = 0;
List<Map<String, dynamic>> timeList = []; List<Map<String, dynamic>> timeList = [];
for (var i = 0; i < dayEvents.length; i++) { for (var i = 0; i < dayEvents.length; i++) {
Map<String, dynamic> timeSlot = {"isoTime": dayEvents[i].isoTime, "start": dayEvents[i].start.toString(), "end": dayEvents[i].end.toString(), "vidaDate": dayEvents[i].vidaDate}; Map<String, dynamic> timeSlot = {
"isoTime": dayEvents[i].isoTime,
"start": dayEvents[i].start.toString(),
"end": dayEvents[i].end.toString(),
"vidaDate": dayEvents[i].vidaDate
};
timeList.add(timeSlot); timeList.add(timeSlot);
} }
if (dayEvents.isNotEmpty) { if (dayEvents.isNotEmpty) {
@ -333,9 +343,7 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
final DateFormat formatter = DateFormat('yyyy-MM-dd', "en-US"); final DateFormat formatter = DateFormat('yyyy-MM-dd', "en-US");
final isArabic = appState.isArabic(); final isArabic = appState.isArabic();
setState(() { setState(() {
selectedDateDisplay = isArabic selectedDateDisplay = isArabic ? DateUtil.getMonthDayYearDateFormattedAr(day) : DateUtil.getMonthDayYearDateFormatted(day);
? DateUtil.getMonthDayYearDateFormattedAr(day)
: DateUtil.getMonthDayYearDateFormatted(day);
selectedNextDate = DateUtil.getWeekDayMonthDayYearDateFormatted(day.add(Duration(days: 1)), isArabic ? "ar" : "en"); selectedNextDate = DateUtil.getWeekDayMonthDayYearDateFormatted(day.add(Duration(days: 1)), isArabic ? "ar" : "en");
_calendarController.selectedDate = day; _calendarController.selectedDate = day;
openTimeSlotsPickerForDate(day, bookAppointmentsViewModel.docFreeSlots); openTimeSlotsPickerForDate(day, bookAppointmentsViewModel.docFreeSlots);

@ -1,12 +1,10 @@
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:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:get_it/get_it.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';
import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/location_util.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; 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';
@ -14,10 +12,8 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_view_model.dart'; import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_view_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/emergency_services/emergency_services_view_model.dart';
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart'; import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
import 'package:hmg_patient_app_new/features/hmg_services/models/ui_models/hmg_services_component_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/ui_models/hmg_services_component_model.dart';
import 'package:hmg_patient_app_new/features/hospital/hospital_selection_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart'; import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/features/water_monitor/water_monitor_view_model.dart'; import 'package:hmg_patient_app_new/features/water_monitor/water_monitor_view_model.dart';
import 'package:hmg_patient_app_new/features/weather/weather_view_model.dart'; import 'package:hmg_patient_app_new/features/weather/weather_view_model.dart';
@ -29,13 +25,11 @@ import 'package:hmg_patient_app_new/presentation/emergency_services/emergency_se
import 'package:hmg_patient_app_new/presentation/habib_wallet/habib_wallet_page.dart'; import 'package:hmg_patient_app_new/presentation/habib_wallet/habib_wallet_page.dart';
import 'package:hmg_patient_app_new/presentation/habib_wallet/recharge_wallet_page.dart'; import 'package:hmg_patient_app_new/presentation/habib_wallet/recharge_wallet_page.dart';
import 'package:hmg_patient_app_new/presentation/hmg_services/services_view.dart'; import 'package:hmg_patient_app_new/presentation/hmg_services/services_view.dart';
import 'package:hmg_patient_app_new/presentation/hmg_services/widgets/weather_widget.dart';
import 'package:hmg_patient_app_new/presentation/home/data/landing_page_data.dart'; import 'package:hmg_patient_app_new/presentation/home/data/landing_page_data.dart';
import 'package:hmg_patient_app_new/presentation/home/service_info_page.dart'; import 'package:hmg_patient_app_new/presentation/home/service_info_page.dart';
import 'package:hmg_patient_app_new/presentation/home/widgets/large_service_card.dart'; import 'package:hmg_patient_app_new/presentation/home/widgets/large_service_card.dart';
import 'package:hmg_patient_app_new/presentation/hmg_services/widgets/weather_widget.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart';
import 'package:hmg_patient_app_new/presentation/my_family/my_family.dart'; import 'package:hmg_patient_app_new/presentation/my_family/my_family.dart';
import 'package:hmg_patient_app_new/presentation/parking/paking_page.dart';
import 'package:hmg_patient_app_new/presentation/servicesPriceList/services_price_list_page.dart'; import 'package:hmg_patient_app_new/presentation/servicesPriceList/services_price_list_page.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart';
@ -49,8 +43,6 @@ import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import '../../core/dependencies.dart' show getIt; import '../../core/dependencies.dart' show getIt;
import '../../features/qr_parking/qr_parking_view_model.dart';
import '../emergency_services/call_ambulance/widgets/HospitalBottomSheetBody.dart';
class ServicesPage extends StatefulWidget { class ServicesPage extends StatefulWidget {
bool showBackIcon; bool showBackIcon;
@ -69,7 +61,14 @@ class _ServicesPageState extends State<ServicesPage> {
late WeatherMonitorViewModel weatherVM; late WeatherMonitorViewModel weatherVM;
late final List<HmgServicesComponentModel> hmgServices = [ late final List<HmgServicesComponentModel> hmgServices = [
HmgServicesComponentModel(11, LocaleKeys.emergencyServices.tr(), "", AppAssets.emergency_services_icon, bgColor: AppColors.primaryRedColor, true, route: null, onTap: () async { HmgServicesComponentModel(
11,
LocaleKeys.emergencyServices.tr(),
"",
AppAssets.emergency_services_icon,
bgColor: AppColors.primaryRedColor,
true,
route: null, onTap: () async {
// if (getIt.get<AppState>().isAuthenticated) { // if (getIt.get<AppState>().isAuthenticated) {
// getIt.get<EmergencyServicesViewModel>().flushData(); // getIt.get<EmergencyServicesViewModel>().flushData();
// getIt.get<EmergencyServicesViewModel>().getTransportationOrders( // getIt.get<EmergencyServicesViewModel>().getTransportationOrders(
@ -88,11 +87,19 @@ class _ServicesPageState extends State<ServicesPage> {
// await getIt.get<AuthenticationViewModel>().onLoginPressed(); // await getIt.get<AuthenticationViewModel>().onLoginPressed();
// } // }
}), }),
HmgServicesComponentModel(11, LocaleKeys.bookAppointmentService.tr(), "", AppAssets.appointment_calendar_icon, bgColor: AppColors.bookAppointment, true, route: null, onTap: () { HmgServicesComponentModel(
11,
LocaleKeys.bookAppointmentService.tr(),
"",
AppAssets.appointment_calendar_icon,
bgColor: AppColors.bookAppointment,
true,
route: null, onTap: () {
getIt.get<BookAppointmentsViewModel>().onTabChanged(0); getIt.get<BookAppointmentsViewModel>().onTabChanged(0);
Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push(CustomPageRoute(page: BookAppointmentPage())); Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push(CustomPageRoute(page: BookAppointmentPage()));
}), }),
HmgServicesComponentModel(5, LocaleKeys.completeCheckup.tr(), "", AppAssets.comprehensiveCheckup, bgColor: AppColors.bgGreenColor, true, route: null, onTap: () async { HmgServicesComponentModel(
5, LocaleKeys.completeCheckup.tr(), "", AppAssets.comprehensiveCheckup, bgColor: AppColors.bgGreenColor, true, route: null, onTap: () async {
if (getIt.get<AppState>().isAuthenticated) { if (getIt.get<AppState>().isAuthenticated) {
getIt.get<NavigationService>().pushPageRoute(AppRoutes.comprehensiveCheckupPage); getIt.get<NavigationService>().pushPageRoute(AppRoutes.comprehensiveCheckupPage);
} else { } else {
@ -152,7 +159,8 @@ class _ServicesPageState extends State<ServicesPage> {
// ); // );
// }, // },
// ), // ),
HmgServicesComponentModel(11, LocaleKeys.eReferralServices.tr(), "", AppAssets.eReferral, bgColor: AppColors.eReferralCardColor, true, route: null, onTap: () async { HmgServicesComponentModel(
11, LocaleKeys.eReferralServices.tr(), "", AppAssets.eReferral, bgColor: AppColors.eReferralCardColor, true, route: null, onTap: () async {
if (getIt.get<AppState>().isAuthenticated) { if (getIt.get<AppState>().isAuthenticated) {
getIt.get<NavigationService>().pushPageRoute(AppRoutes.eReferralPage); getIt.get<NavigationService>().pushPageRoute(AppRoutes.eReferralPage);
} else { } else {
@ -403,14 +411,13 @@ class _ServicesPageState extends State<ServicesPage> {
}, },
), ),
HmgServicesComponentModel( HmgServicesComponentModel(
103, 103,
LocaleKeys.watchUsOnYoutube.tr(), LocaleKeys.watchUsOnYoutube.tr(),
"", "",
AppAssets.youtube, AppAssets.youtube,
bgColor: AppColors.whiteColor, bgColor: AppColors.whiteColor,
true, true,
onTap:()=> launchUrl(Uri.parse("https://www.youtube.com/c/DrsulaimanAlhabibHospitals")) onTap: () => launchUrl(Uri.parse("https://www.youtube.com/c/DrsulaimanAlhabibHospitals"))),
),
HmgServicesComponentModel( HmgServicesComponentModel(
104, 104,
LocaleKeys.connectOnLinkedin.tr(), LocaleKeys.connectOnLinkedin.tr(),
@ -418,9 +425,8 @@ class _ServicesPageState extends State<ServicesPage> {
AppAssets.linkedin, AppAssets.linkedin,
bgColor: AppColors.whiteColor, bgColor: AppColors.whiteColor,
true, true,
onTap:()=> launchUrl(Uri.parse("https://www.linkedin.com/company/drsulaiman-alhabib-medical-group")), onTap: () => launchUrl(Uri.parse("https://www.linkedin.com/company/drsulaiman-alhabib-medical-group")),
), ),
]; ];
@override @override
@ -431,8 +437,6 @@ class _ServicesPageState extends State<ServicesPage> {
weatherVM.initiateFetchWeather(); weatherVM.initiateFetchWeather();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
bloodDonationViewModel = Provider.of<BloodDonationViewModel>(context); bloodDonationViewModel = Provider.of<BloodDonationViewModel>(context);
@ -451,456 +455,393 @@ class _ServicesPageState extends State<ServicesPage> {
children: [ children: [
const WeatherWidget(), const WeatherWidget(),
SizedBox(height: 16.h), SizedBox(height: 16.h),
LocaleKeys.medicalAndCareServices.tr().toText18(isBold: true).paddingSymmetrical(24.w, 0), LocaleKeys.medicalAndCareServices.tr().toText18(isBold: true).paddingSymmetrical(24.w, 0),
SizedBox(height: 16.h), SizedBox(height: 16.h),
GridView.builder( GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: (isFoldable || isTablet) ? 6 : 4, // 4 icons per row crossAxisCount: (isFoldable || isTablet) ? 5 : 4, // 4 icons per row
crossAxisSpacing: 21.w, ),
mainAxisSpacing: 18.h, physics: NeverScrollableScrollPhysics(),
childAspectRatio: 80 / 94),
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: hmgServices.length,
padding: EdgeInsets.zero,
itemBuilder: (BuildContext context, int index) {
return ServiceGridViewItem(hmgServices[index], index, false, isHealthToolIcon: false);
},
).paddingSymmetrical(24.w, 0),
SizedBox(height: 24.h),
LocaleKeys.hmgServices.tr().toText18(isBold: true).paddingSymmetrical(24.w, 0),
SizedBox(height: 16.h),
SizedBox(
height: 350.h,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: LandingPageData.getServiceCardsList.length,
shrinkWrap: true, shrinkWrap: true,
padding: EdgeInsets.symmetric(horizontal: 24.w), itemCount: hmgServices.length,
itemBuilder: (context, index) { padding: EdgeInsets.zero,
return AnimationConfiguration.staggeredList( itemBuilder: (BuildContext context, int index) {
position: index, return ServiceGridViewItem(hmgServices[index], index, false, isHealthToolIcon: false);
duration: const Duration(milliseconds: 1000), },
child: SlideAnimation( ).paddingSymmetrical(24.w, 0),
horizontalOffset: 100.0, SizedBox(height: 24.h),
child: FadeInAnimation( LocaleKeys.hmgServices.tr().toText18(isBold: true).paddingSymmetrical(24.w, 0),
child: LargeServiceCard( SizedBox(height: 16.h),
serviceCardData: LandingPageData.getServiceCardsList[index], ConstrainedBox(
image: LandingPageData.getServiceCardsList[index].icon, constraints: BoxConstraints(
title: LandingPageData.getServiceCardsList[index].title, minHeight: 320.h,
subtitle: LandingPageData.getServiceCardsList[index].subtitle, maxHeight: isFoldable ? 400.h : (isTablet ? 360.h : 340.h),
icon: LandingPageData.getServiceCardsList[index].largeCardIcon, ),
isPNG: LandingPageData.getServiceCardsList[index].isPNG, child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: LandingPageData.getServiceCardsList.length,
shrinkWrap: true,
padding: EdgeInsets.symmetric(horizontal: 24.w),
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 1000),
child: SlideAnimation(
horizontalOffset: 100.0,
child: FadeInAnimation(
child: LargeServiceCard(
serviceCardData: LandingPageData.getServiceCardsList[index],
image: LandingPageData.getServiceCardsList[index].icon,
title: LandingPageData.getServiceCardsList[index].title,
subtitle: LandingPageData.getServiceCardsList[index].subtitle,
icon: LandingPageData.getServiceCardsList[index].largeCardIcon,
isPNG: LandingPageData.getServiceCardsList[index].isPNG,
),
), ),
), ),
), );
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 16.w),
),
),
SizedBox(height: 24.h),
getIt.get<AppState>().isAuthenticated
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.personalServices.tr().toText18(isBold: true).paddingSymmetrical(24.w, 0),
SizedBox(height: 16.h),
Row(
children: [
Expanded(
child: Container(
height: 183.h,
width: 183.h,
padding: EdgeInsets.all(16.w),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.r,
hasShadow: false,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
spacing: 8.w,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.wallet, width: 40.w, height: 40.h, applyThemeColor: false),
LocaleKeys.habibWallet.tr().toText14(isBold: true, maxlines: 2).expanded,
Utils.buildSvgWithAssets(
icon: getIt.get<AppState>().isArabic() ? AppAssets.arrow_back : AppAssets.arrow_forward),
],
),
Spacer(),
getIt.get<AppState>().isAuthenticated
? Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) {
return Utils.getPaymentAmountWithSymbol2(
num.parse(NumberFormat.decimalPattern().format(habibWalletVM.habibWalletAmount)),
isExpanded: false,
letterSpacing: -1)
.toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.r, width: 80.w, height: 24.h);
})
: LocaleKeys.loginToViewWalletBalance.tr().toText12(isBold: true, maxLine: 2),
Spacer(),
getIt.get<AppState>().isAuthenticated
? CustomButton(
height: 40.h,
icon: AppAssets.recharge_icon,
iconSize: 24.w,
iconColor: AppColors.infoColor,
textColor: AppColors.infoColor,
text: LocaleKeys.recharge.tr(),
borderWidth: 0.w,
isBold: true,
borderColor: Colors.transparent,
backgroundColor: Color(0xff45A2F8).withValues(alpha: 0.08),
padding: EdgeInsets.all(8.w),
fontSize: 14.f,
onPressed: () {
Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage()));
},
)
: SizedBox.shrink(),
],
).onPress(() async {
if (getIt.get<AppState>().isAuthenticated) {
Navigator.of(context).push(CustomPageRoute(page: HabibWalletPage()));
} else {
await getIt.get<AuthenticationViewModel>().onLoginPressed();
}
}),
),
),
SizedBox(width: 16.w),
Expanded(
child: Container(
height: 183.h,
width: 183.h,
padding: EdgeInsets.all(16.w),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.r,
hasShadow: false,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
spacing: 8.w,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Utils.buildSvgWithAssets(
icon: AppAssets.services_medical_file_icon, width: 40.w, height: 40.h, applyThemeColor: false),
LocaleKeys.familyTitle.tr().toText16(isBold: true, maxlines: 2).expanded,
Utils.buildSvgWithAssets(
icon: getIt.get<AppState>().isArabic() ? AppAssets.arrow_back : AppAssets.arrow_forward),
],
),
Spacer(),
getIt.get<AppState>().isAuthenticated
? Wrap(
spacing: -12.h,
// runSpacing: 0.h,
children: [
Utils.buildImgWithAssets(
icon: AppAssets.babyGirlImg,
height: 32.h,
width: 32.w,
border: 1,
fit: BoxFit.contain,
borderRadius: 50.r,
),
Utils.buildImgWithAssets(
icon: AppAssets.femaleImg,
height: 32.h,
width: 32.w,
border: 1,
borderRadius: 50.r,
fit: BoxFit.contain,
),
Utils.buildImgWithAssets(
icon: AppAssets.maleImg,
height: 32.h,
width: 32.w,
border: 1,
borderRadius: 50.r,
fit: BoxFit.contain,
),
],
)
: LocaleKeys.loginToViewMedicalFile.tr().toText12(isBold: true, maxLine: 2),
Spacer(),
getIt.get<AppState>().isAuthenticated
? CustomButton(
height: 40.h,
icon: AppAssets.add_icon,
iconSize: 24.h,
iconColor: AppColors.primaryRedColor,
textColor: AppColors.primaryRedColor,
text: getIt.get<AppState>().isArabic() ? LocaleKeys.add.tr() : LocaleKeys.addMember.tr(),
borderWidth: 0.w,
isBold: true,
borderColor: Colors.transparent,
backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.08),
padding: EdgeInsets.all(8.w),
fontSize: 14.f,
onPressed: () {
DialogService dialogService = getIt.get<DialogService>();
medicalFileViewModel.clearAuthValues();
dialogService.showAddFamilyFileSheet(
label: LocaleKeys.addFamilyMember.tr(),
message: LocaleKeys.pleaseFillBelowFieldToAddNewFamilyMember.tr(),
onVerificationPress: () {
medicalFileViewModel.addFamilyFile(otpTypeEnum: OTPTypeEnum.sms);
});
},
)
: SizedBox.shrink(),
],
).onPress(() async {
if (getIt.get<AppState>().isAuthenticated) {
// Navigator.of(context).push(
// CustomPageRoute(
// page: MedicalFilePage(),
// ),
// );
Navigator.of(context).push(
CustomPageRoute(
direction: AxisDirection.down,
page: FamilyMedicalScreen(),
),
);
} else {
await getIt.get<AuthenticationViewModel>().onLoginPressed();
}
}),
),
),
],
).paddingSymmetrical(24.w, 0),
],
)
: SizedBox(),
SizedBox(height: 24.h),
LocaleKeys.healthTools.tr().toText18(isBold: true).paddingSymmetrical(24.w, 0),
SizedBox(height: 16.h),
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: (isFoldable || isTablet) ? 5 : 4, // 4 icons per row
mainAxisSpacing: 18.h,
),
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: hmgHealthToolServices.length,
padding: EdgeInsets.zero,
itemBuilder: (BuildContext context, int index) {
return ServiceGridViewItem(
hmgHealthToolServices[index],
index,
false,
isHealthToolIcon: true,
); );
}, },
separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 16.w), ).paddingSymmetrical(24.w, 0),
), SizedBox(height: 24.h),
), LocaleKeys.supportServices.tr().toText18(isBold: true).paddingSymmetrical(24.w, 0),
SizedBox(height: 24.h), SizedBox(height: 16.h),
getIt.get<AppState>().isAuthenticated Column(
? Column( crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, children: [
SizedBox(height: 16.h),
Row(
children: [ children: [
LocaleKeys.personalServices.tr().toText18(isBold: true).paddingSymmetrical(24.w, 0), Expanded(
SizedBox(height: 16.h), child: Container(
Row( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
children: [ color: AppColors.whiteColor,
Expanded( borderRadius: 12.h,
child: Container( hasShadow: false,
height: 183.h, ),
width: 183.h, child: Padding(
padding: EdgeInsets.all(16.w), padding: EdgeInsets.all(16.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( child: Row(
color: AppColors.whiteColor, children: [
borderRadius: 20.r, Utils.buildSvgWithAssets(
hasShadow: false, icon: AppAssets.latest_news_icon,
), width: 32.h,
child: Column( height: 32.h,
crossAxisAlignment: CrossAxisAlignment.start, fit: BoxFit.contain,
children: [ ),
Row( SizedBox(width: 8.w),
spacing: 8.w, LocaleKeys.latestNews.tr().toText14(isBold: true)
crossAxisAlignment: CrossAxisAlignment.center, ],
children: [
Utils.buildSvgWithAssets(icon: AppAssets.wallet, width: 40.w, height: 40.h, applyThemeColor: false),
LocaleKeys.habibWallet.tr().toText14(isBold: true, maxlines: 2).expanded,
Utils.buildSvgWithAssets(icon: getIt.get<AppState>().isArabic() ? AppAssets.arrow_back : AppAssets.arrow_forward),
],
),
Spacer(),
getIt.get<AppState>().isAuthenticated
? Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) {
return Utils.getPaymentAmountWithSymbol2(num.parse(NumberFormat.decimalPattern().format(habibWalletVM.habibWalletAmount)),
isExpanded: false, letterSpacing: -1)
.toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.r, width: 80.w, height: 24.h);
})
: LocaleKeys.loginToViewWalletBalance.tr().toText12(isBold: true, maxLine: 2),
Spacer(),
getIt.get<AppState>().isAuthenticated
? CustomButton(
height: 40.h,
icon: AppAssets.recharge_icon,
iconSize: 24.w,
iconColor: AppColors.infoColor,
textColor: AppColors.infoColor,
text: LocaleKeys.recharge.tr(),
borderWidth: 0.w,
isBold: true,
borderColor: Colors.transparent,
backgroundColor: Color(0xff45A2F8).withValues(alpha: 0.08),
padding: EdgeInsets.all(8.w),
fontSize: 14.f,
onPressed: () {
Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage()));
},
)
: SizedBox.shrink(),
],
).onPress(() async {
if (getIt.get<AppState>().isAuthenticated) {
Navigator.of(context).push(CustomPageRoute(page: HabibWalletPage()));
} else {
await getIt.get<AuthenticationViewModel>().onLoginPressed();
}
}),
), ),
), ),
SizedBox(width: 16.w), ).onPress(() {
Expanded( Utils.openWebView(
child: Container( url: 'https://x.com/HMG',
height: 183.h, );
width: 183.h, }),
padding: EdgeInsets.all(16.w), ),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( SizedBox(width: 16.w),
color: AppColors.whiteColor, Expanded(
borderRadius: 20.r, child: Container(
hasShadow: false, decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
), color: AppColors.whiteColor,
child: Column( borderRadius: 12.h,
crossAxisAlignment: CrossAxisAlignment.start, hasShadow: false,
children: [ ),
Row( child: Padding(
spacing: 8.w, padding: EdgeInsets.all(16.h),
crossAxisAlignment: CrossAxisAlignment.center, child: Row(
children: [ children: [
Utils.buildSvgWithAssets(icon: AppAssets.services_medical_file_icon, width: 40.w, height: 40.h, applyThemeColor: false), Utils.buildSvgWithAssets(
LocaleKeys.familyTitle.tr().toText16(isBold: true, maxlines: 2).expanded, icon: AppAssets.hmg_contact_icon,
Utils.buildSvgWithAssets(icon: getIt.get<AppState>().isArabic() ? AppAssets.arrow_back : AppAssets.arrow_forward), width: 32.h,
], height: 32.h,
), fit: BoxFit.contain,
Spacer(), ),
getIt.get<AppState>().isAuthenticated SizedBox(width: 8.w),
? Wrap( Expanded(child: LocaleKeys.hmgContact.tr().toText14(isBold: true))
spacing: -12.h, ],
// runSpacing: 0.h,
children: [
Utils.buildImgWithAssets(
icon: AppAssets.babyGirlImg,
height: 32.h,
width: 32.w,
border: 1,
fit: BoxFit.contain,
borderRadius: 50.r,
),
Utils.buildImgWithAssets(
icon: AppAssets.femaleImg,
height: 32.h,
width: 32.w,
border: 1,
borderRadius: 50.r,
fit: BoxFit.contain,
),
Utils.buildImgWithAssets(
icon: AppAssets.maleImg,
height: 32.h,
width: 32.w,
border: 1,
borderRadius: 50.r,
fit: BoxFit.contain,
),
],
)
: LocaleKeys.loginToViewMedicalFile.tr().toText12(isBold: true, maxLine: 2),
Spacer(),
getIt.get<AppState>().isAuthenticated
? CustomButton(
height: 40.h,
icon: AppAssets.add_icon,
iconSize: 24.h,
iconColor: AppColors.primaryRedColor,
textColor: AppColors.primaryRedColor,
text: getIt.get<AppState>().isArabic() ? LocaleKeys.add.tr() :LocaleKeys.addMember.tr(),
borderWidth: 0.w,
isBold: true,
borderColor: Colors.transparent,
backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.08),
padding: EdgeInsets.all(8.w),
fontSize: 14.f,
onPressed: () {
DialogService dialogService = getIt.get<DialogService>();
medicalFileViewModel.clearAuthValues();
dialogService.showAddFamilyFileSheet(
label: LocaleKeys.addFamilyMember.tr(),
message: LocaleKeys.pleaseFillBelowFieldToAddNewFamilyMember.tr(),
onVerificationPress: () {
medicalFileViewModel.addFamilyFile(otpTypeEnum: OTPTypeEnum.sms);
});
},
)
: SizedBox.shrink(),
],
).onPress(() async {
if (getIt.get<AppState>().isAuthenticated) {
// Navigator.of(context).push(
// CustomPageRoute(
// page: MedicalFilePage(),
// ),
// );
Navigator.of(context).push(
CustomPageRoute(
direction: AxisDirection.down,
page: FamilyMedicalScreen(),
),
);
} else {
await getIt.get<AuthenticationViewModel>().onLoginPressed();
}
}),
), ),
), ),
], ).onPress(() {
).paddingSymmetrical(24.w, 0), showCommonBottomSheetWithoutHeight(
context,
title: LocaleKeys.contactUs.tr(),
child: ContactUs(),
callBackFunc: () {},
isFullScreen: false,
);
}),
)
], ],
) ),
: SizedBox(), SizedBox(height: 24.h),
SizedBox(height: 24.h), LocaleKeys.hmgPolicies.tr().toText18(weight: FontWeight.bold),
LocaleKeys.healthTools.tr().toText18(isBold: true).paddingSymmetrical(24.w, 0), SizedBox(height: 16.h),
SizedBox(height: 16.h), Row(
GridView.builder( children: [
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( Expanded(
crossAxisCount: (isFoldable || isTablet) ? 6 : 4, // 4 icons per row child: Container(
crossAxisSpacing: 21.w, decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
mainAxisSpacing: 18.h, color: AppColors.whiteColor,
childAspectRatio: 80.w / 94.h, borderRadius: 12.h,
), hasShadow: false,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: hmgHealthToolServices.length,
padding: EdgeInsets.zero,
itemBuilder: (BuildContext context, int index) {
return ServiceGridViewItem(
hmgHealthToolServices[index],
index,
false,
isHealthToolIcon: true,
);
},
).paddingSymmetrical(24.w, 0),
SizedBox(height: 24.h),
LocaleKeys.supportServices.tr().toText18(isBold: true).paddingSymmetrical(24.w, 0),
SizedBox(height: 16.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Row(
// children: [
// // Expanded(
// // child: Container(
// // decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
// // color: AppColors.whiteColor,
// // borderRadius: 12.h,
// // hasShadow: false,
// // ),
// // child: Padding(
// // padding: EdgeInsets.all(16.h),
// // child: Row(
// // children: [
// // Utils.buildSvgWithAssets(
// // icon: AppAssets.virtual_tour_icon,
// // width: 32.w,
// // height: 32.h,
// // fit: BoxFit.contain,
// // ),
// // SizedBox(width: 8.w),
// // LocaleKeys.virtualTour.tr().toText14(isBold: true)
// // ],
// // ),
// // ),
// // ).onPress(() {
// // Utils.openWebView(
// // url: 'https://hmgwebservices.com/vt_mobile/html/index.html',
// // );
// // }),
// // ),
// SizedBox(width: 16.w),
// Expanded(
// child: Container(
// decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
// color: AppColors.whiteColor,
// borderRadius: 12.h,
// hasShadow: false,
// ),
// child: Padding(
// padding: EdgeInsets.all(16.h),
// child: Row(
// children: [
// Utils.buildSvgWithAssets(
// icon: AppAssets.car_parking_icon,
// width: 32.w,
// height: 32.h,
// fit: BoxFit.contain,
// ),
// SizedBox(width: 8.w),
// LocaleKeys.carParking.tr().toText14(isBold: true)
// ],
// ).onPress(() {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (_) => ChangeNotifierProvider(
// create: (_) => getIt<QrParkingViewModel>(),
// child: const ParkingPage(),
// ),
// ),
// );
// }),
// ),
// ),
// ),
// ],
// ),
SizedBox(height: 16.h),
Row(
children: [
Expanded(
child: Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 12.h,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Row(
children: [
Utils.buildSvgWithAssets(
icon: AppAssets.latest_news_icon,
width: 32.w,
height: 32.h,
fit: BoxFit.contain,
),
SizedBox(width: 8.w),
LocaleKeys.latestNews.tr().toText14(isBold: true)
],
), ),
), child: Padding(
).onPress(() { padding: EdgeInsets.all(16.h),
Utils.openWebView( child: Row(
url: 'https://x.com/HMG', children: [
); Utils.buildSvgWithAssets(
}), icon: AppAssets.privacy_terms, width: 32.w, height: 32.h, fit: BoxFit.contain, iconColor: AppColors.blackColor),
), SizedBox(width: 8.w),
SizedBox(width: 16.w), Expanded(child: LocaleKeys.termsConditoins.tr().toText14(isBold: true))
Expanded( ],
child: Container( ),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 12.h,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Row(
children: [
Utils.buildSvgWithAssets(
icon: AppAssets.hmg_contact_icon,
width: 32.w,
height: 32.h,
fit: BoxFit.contain,
),
SizedBox(width: 8.w),
Expanded(child: LocaleKeys.hmgContact.tr().toText14(isBold: true))
],
), ),
), ).onPress(() {
).onPress(() { Utils.openWebView(
showCommonBottomSheetWithoutHeight( url: 'https://hmg.com/en/Pages/Terms.aspx',
context, );
title: LocaleKeys.contactUs.tr(), }),
child: ContactUs(), ),
callBackFunc: () {}, SizedBox(width: 16.w),
isFullScreen: false, Expanded(
); child: Container(
}), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
) color: AppColors.whiteColor,
], borderRadius: 12.h,
), hasShadow: false,
SizedBox(height: 24.h),
LocaleKeys.hmgPolicies.tr().toText18(weight: FontWeight.bold),
SizedBox(height: 16.h),
Row(
children: [
Expanded(
child: Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 12.h,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.privacy_terms, width: 32.w, height: 32.h, fit: BoxFit.contain, iconColor: AppColors.blackColor),
SizedBox(width: 8.w),
Expanded(child: LocaleKeys.termsConditoins.tr().toText14(isBold: true))
],
), ),
), child: Padding(
).onPress(() { padding: EdgeInsets.all(16.h),
Utils.openWebView( child: Row(
url: 'https://hmg.com/en/Pages/Terms.aspx', children: [
); Utils.buildSvgWithAssets(
}), icon: AppAssets.privacy_terms, width: 32.w, height: 32.h, fit: BoxFit.contain, iconColor: AppColors.blackColor),
), SizedBox(width: 8.w),
SizedBox(width: 16.w), Expanded(child: LocaleKeys.privacyPolicy.tr().toText14(isBold: true))
Expanded( ],
child: Container( ),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 12.h,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.privacy_terms, width: 32.w, height: 32.h, fit: BoxFit.contain, iconColor: AppColors.blackColor),
SizedBox(width: 8.w),
Expanded(child: LocaleKeys.privacyPolicy.tr().toText14(isBold: true))
],
), ),
), ).onPress(() {
).onPress(() { Utils.openWebView(
Utils.openWebView( url: 'https://hmg.com/en/Pages/Privacy.aspx',
url: 'https://hmg.com/en/Pages/Privacy.aspx', );
); }),
}), )
) ],
], )
) ],
], ).paddingSymmetrical(24.w, 0),
).paddingSymmetrical(24.w, 0),
SizedBox(height: 16.h), SizedBox(height: 16.h),
GridView.builder( GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: (isFoldable || isTablet) ? 6 : 4, // 4 icons per row crossAxisCount: (isFoldable || isTablet) ? 5 : 4, // 4 icons per row
crossAxisSpacing: 21.w,
mainAxisSpacing: 18.h, mainAxisSpacing: 18.h,
childAspectRatio: 80.w / 94.h,
), ),
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
@ -915,11 +856,11 @@ class _ServicesPageState extends State<ServicesPage> {
); );
}, },
).paddingSymmetrical(24.w, 0), ).paddingSymmetrical(24.w, 0),
SizedBox(height: 24.h), SizedBox(height: 24.h),
], ],
),
), ),
), ),
),
); );
} }
} }

File diff suppressed because it is too large Load Diff

@ -43,83 +43,87 @@ class LargeServiceCard extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
height: 350.h,
width: 230.w, width: 230.w,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.transparent, borderRadius: 24.r), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
child: Stack( color: AppColors.whiteColor,
borderRadius: 24.r,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [ children: [
ClipRRect( ClipRRect(
borderRadius: BorderRadius.circular(24.r), borderRadius: BorderRadius.only(
topLeft: Radius.circular(24.r),
topRight: Radius.circular(24.r),
),
child: Image.asset( child: Image.asset(
serviceCardData.largeCardIcon, serviceCardData.largeCardIcon,
fit: BoxFit.cover, fit: BoxFit.cover,
width: double.infinity,
height: isFoldable ? 190.h : (isTablet ? 200.h : 180.h),
), ),
), ),
Positioned( Container(
bottom: 0.0, // Positions the child 0 logical pixels from the bottom padding: EdgeInsets.all(16.w),
left: 0.0, child: Column(
right: 0.0, mainAxisSize: MainAxisSize.min,
child: Container( children: [
height: 180.h, Row(
padding: EdgeInsets.only(bottom: 16.h, top: 16.h), crossAxisAlignment: CrossAxisAlignment.start,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( children: [
color: AppColors.whiteColor, isPNG
customBorder: BorderRadius.only( ? Image.asset(serviceCardData.icon, width: 35.h, height: 35.h)
bottomLeft: Radius.circular(24.r), : Container(
bottomRight: Radius.circular(24.r), height: 48.h,
), width: 48.h,
), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
child: Column( color: serviceCardData.backgroundColor!,
children: [ borderRadius: 12.r,
Row( hasShadow: false,
crossAxisAlignment: CrossAxisAlignment.start, ),
children: [ child: Padding(
isPNG ? Image.asset(serviceCardData.icon, width: 35.h, height: 35.h) : Container( padding: EdgeInsets.all(12.h),
height: 48.h, child: Utils.buildSvgWithAssets(
width: 48.h, icon: serviceCardData.icon,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( iconColor: serviceCardData.iconColor,
color: serviceCardData.backgroundColor!, fit: BoxFit.contain,
borderRadius: 12.r, applyThemeColor: false,
hasShadow: false, ),
), ),
child: Padding(
padding: EdgeInsets.all(12.h),
child: Utils.buildSvgWithAssets(
icon: serviceCardData.icon,
iconColor: serviceCardData.iconColor,
fit: BoxFit.contain,
applyThemeColor: false,
), ),
), SizedBox(width: 12.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
serviceCardData.title.tr(context: context).toText14(
isBold: true,
color: AppColors.textColor,
maxlines: 1,
textOverflow: TextOverflow.ellipsis,
),
serviceCardData.subtitle.tr(context: context).toText12(isBold: true, color: AppColors.textColorLight, maxLine: 2),
],
), ),
SizedBox(width: 12.w), ),
Expanded( ],
child: Column( ),
crossAxisAlignment: CrossAxisAlignment.start, SizedBox(height: 24.h),
children: [ CustomButton(
serviceCardData.title.tr(context: context).toText14(isBold: true, color: AppColors.textColor), text: serviceCardData.isBold ? LocaleKeys.visitPharmacyOnline.tr(context: context) : LocaleKeys.bookNow.tr(context: context),
serviceCardData.subtitle.tr(context: context).toText12(isBold: true, color: AppColors.textColorLight, maxLine: 2), onPressed: () {
], handleOnTap();
), },
), padding: EdgeInsets.zero,
], backgroundColor: serviceCardData.isBold ? AppColors.successLightColor.withValues(alpha: 0.2) : AppColors.bgRedLightColor,
).paddingSymmetrical(8.w, 0.h).expanded, borderColor: serviceCardData.isBold ? AppColors.successLightColor.withValues(alpha: 0.01) : AppColors.bgRedLightColor,
CustomButton( textColor: serviceCardData.isBold ? AppColors.successColor : AppColors.primaryRedColor,
text: serviceCardData.isBold ? LocaleKeys.visitPharmacyOnline.tr(context: context) : LocaleKeys.bookNow.tr(context: context), fontSize: 14.f,
onPressed: () { fontWeight: FontWeight.w600,
handleOnTap(); borderRadius: 10.r,
}, height: 40.h,
padding: EdgeInsets.zero, ),
backgroundColor: serviceCardData.isBold ? AppColors.successLightColor.withValues(alpha: 0.2) : AppColors.bgRedLightColor, ],
borderColor: serviceCardData.isBold ? AppColors.successLightColor.withValues(alpha: 0.01) : AppColors.bgRedLightColor,
textColor: serviceCardData.isBold ? AppColors.successColor : AppColors.primaryRedColor,
fontSize: 14.f,
fontWeight: FontWeight.w600,
borderRadius: 10.r,
height: 40.h,
).paddingSymmetrical(16.w, 0.h),
],
),
), ),
), ),
], ],
@ -229,27 +233,25 @@ class FadedLargeServiceCard extends StatelessWidget {
Row( Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
isPNG ? Image.asset(serviceCardData.icon, width: 32.h, height: 32.h).circle(100.h) : Container( isPNG
height: 32.h, ? Image.asset(serviceCardData.icon, width: 32.h, height: 32.h).circle(100.h)
width: 32.h, : Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( height: 32.h,
color: serviceCardData.backgroundColor!, width: 32.h,
borderRadius: 30.r, decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
hasShadow: false, color: serviceCardData.backgroundColor!,
), borderRadius: 30.r,
child: Padding( hasShadow: false,
padding: EdgeInsets.all(8.h), ),
child: Transform.flip( child: Padding(
flipX: getIt.get<AppState>().isArabic(), padding: EdgeInsets.all(8.h),
child: Utils.buildSvgWithAssets( child: Transform.flip(
icon: serviceCardData.icon, flipX: getIt.get<AppState>().isArabic(),
iconColor: serviceCardData.iconColor, child: Utils.buildSvgWithAssets(
fit: BoxFit.contain, icon: serviceCardData.icon, iconColor: serviceCardData.iconColor, fit: BoxFit.contain, applyThemeColor: false),
applyThemeColor: false ),
),
), ),
),
),
),
SizedBox(width: 12.w), SizedBox(width: 12.w),
serviceCardData.title.tr(context: context).toText18(isBold: true, color: AppColors.textColor).expanded, serviceCardData.title.tr(context: context).toText18(isBold: true, color: AppColors.textColor).expanded,
], ],

File diff suppressed because it is too large Load Diff

@ -152,7 +152,7 @@ class _MedicalFileAppointmentCardState extends State<MedicalFileAppointmentCard>
backgroundColor: backgroundColor:
AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel) ? AppColors.greyColor : AppColors.secondaryLightRedColor, AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel) ? AppColors.greyColor : AppColors.secondaryLightRedColor,
textColor: AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel) ? AppColors.textColor : AppColors.primaryRedColor, textColor: AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel) ? AppColors.textColor : AppColors.primaryRedColor,
padding: EdgeInsets.only(top: 12.h, bottom: 12.h, left: 8.w, right: 8.w), padding: EdgeInsets.only(top: 12.h, left: 8.w, right: 8.w, bottom: 8.h),
).toShimmer2(isShow: widget.myAppointmentsViewModel.isMyAppointmentsLoading), ).toShimmer2(isShow: widget.myAppointmentsViewModel.isMyAppointmentsLoading),
SizedBox(height: 16.h), SizedBox(height: 16.h),
IntrinsicWidth( IntrinsicWidth(
@ -166,10 +166,10 @@ class _MedicalFileAppointmentCardState extends State<MedicalFileAppointmentCard>
Image.network( Image.network(
widget.patientAppointmentHistoryResponseModel.doctorImageURL ?? widget.patientAppointmentHistoryResponseModel.doctorImageURL ??
"https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
width: 25.w, width: 30.h,
height: 27.h, height: 30.h,
fit: BoxFit.fill, fit: BoxFit.fill,
).circle(100).toShimmer2(isShow: widget.myAppointmentsViewModel.isMyAppointmentsLoading), ).circle(100.r).toShimmer2(isShow: widget.myAppointmentsViewModel.isMyAppointmentsLoading),
SizedBox(width: 8.w), SizedBox(width: 8.w),
Expanded( Expanded(
child: Column( child: Column(
@ -190,138 +190,7 @@ class _MedicalFileAppointmentCardState extends State<MedicalFileAppointmentCard>
], ],
), ),
SizedBox(height: 8.h), SizedBox(height: 8.h),
// Check if doctor is active - if not, show only View Details button _buildAppointmentActionButton(context, appState),
(widget.patientAppointmentHistoryResponseModel.isActiveDoctor ?? true)
? // Doctor is active - check rebooking logic
(AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel) &&
widget.patientAppointmentHistoryResponseModel.isClinicReBookingAllowed == false)
? // Show only the button without arrow when rebooking not allowed
widget.myAppointmentsViewModel.isMyAppointmentsLoading
? Container().toShimmer2(isShow: true, height: 40.h, width: 100.w, radius: 12.r)
: AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel)
? getArrivedAppointmentButton(context).toShimmer2(isShow: widget.myAppointmentsViewModel.isMyAppointmentsLoading)
: CustomButton(
text: AppointmentType.getNextActionText(widget.patientAppointmentHistoryResponseModel.nextAction),
onPressed: () {
handleAppointmentNextAction(widget.patientAppointmentHistoryResponseModel.nextAction, context);
},
backgroundColor:
AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction)
.withValues(alpha: 0.15),
borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction)
.withValues(alpha: 0.01),
textColor: AppointmentType.getNextActionTextColor(widget.patientAppointmentHistoryResponseModel.nextAction),
fontSize: 14.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
icon: AppointmentType.getNextActionIcon(widget.patientAppointmentHistoryResponseModel.nextAction),
iconColor: AppointmentType.getNextActionTextColor(widget.patientAppointmentHistoryResponseModel.nextAction),
iconSize: 14.h,
).toShimmer2(isShow: widget.myAppointmentsViewModel.isMyAppointmentsLoading)
: // Normal flow - show button with arrow
Row(
children: [
widget.myAppointmentsViewModel.isMyAppointmentsLoading
? Container().toShimmer2(isShow: true, height: 40.h, width: 100.w, radius: 12.r)
: Expanded(
flex: 7,
child: AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel)
? getArrivedAppointmentButton(context)
.toShimmer2(isShow: widget.myAppointmentsViewModel.isMyAppointmentsLoading)
: CustomButton(
text: AppointmentType.getNextActionText(widget.patientAppointmentHistoryResponseModel.nextAction),
onPressed: () {
handleAppointmentNextAction(widget.patientAppointmentHistoryResponseModel.nextAction, context);
},
backgroundColor:
AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction)
.withValues(alpha: 0.15),
borderColor:
AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction)
.withValues(alpha: 0.01),
textColor:
AppointmentType.getNextActionTextColor(widget.patientAppointmentHistoryResponseModel.nextAction),
fontSize: 14.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
icon: AppointmentType.getNextActionIcon(widget.patientAppointmentHistoryResponseModel.nextAction),
iconColor:
AppointmentType.getNextActionTextColor(widget.patientAppointmentHistoryResponseModel.nextAction),
iconSize: 14.h,
).toShimmer2(isShow: widget.myAppointmentsViewModel.isMyAppointmentsLoading),
),
SizedBox(width: 8.w),
((((widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false) ||
(widget.patientAppointmentHistoryResponseModel.isExecludeDoctor ?? false) ||
!Utils.isClinicAllowedForRebook(widget.patientAppointmentHistoryResponseModel.clinicID ?? 0))) &&
AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel))
? SizedBox.shrink()
: Expanded(
flex: 2,
child: Container(
height: 40.h,
width: 40.w,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.textColor,
borderRadius: 10.r,
),
child: Padding(
padding: EdgeInsets.all(10.w),
child: Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(
iconColor: AppColors.whiteColor,
icon: AppAssets.forward_arrow_icon_small,
width: 40.w,
height: 40.h,
fit: BoxFit.contain,
),
),
),
).toShimmer2(isShow: widget.myAppointmentsViewModel.isMyAppointmentsLoading).onPress(() {
Navigator.of(context)
.push(
CustomPageRoute(
page: AppointmentDetailsPage(
patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
),
)
.then((val) {
// widget.myAppointmentsViewModel.initAppointmentsViewModel();
// widget.myAppointmentsViewModel.getPatientAppointments(true, false);
});
}),
),
],
)
: // Doctor is not active - show only View Details button
CustomButton(
text: LocaleKeys.viewDetails.tr(context: context),
onPressed: () {
Navigator.of(context)
.push(
CustomPageRoute(
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
),
)
.then((_) {
widget.myAppointmentsViewModel.initAppointmentsViewModel();
widget.myAppointmentsViewModel.getPatientAppointments(true, false);
});
},
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,
).toShimmer2(isShow: widget.myAppointmentsViewModel.isMyAppointmentsLoading),
], ],
).paddingAll(16.w), ).paddingAll(16.w),
), ),
@ -330,6 +199,170 @@ class _MedicalFileAppointmentCardState extends State<MedicalFileAppointmentCard>
); );
} }
/// Builds the appropriate action button based on appointment state and doctor status
Widget _buildAppointmentActionButton(BuildContext context, AppState appState) {
final isLoading = widget.myAppointmentsViewModel.isMyAppointmentsLoading;
final appointment = widget.patientAppointmentHistoryResponseModel;
final isDoctorActive = appointment.isActiveDoctor ?? true;
// If doctor is not active, show only View Details button
if (!isDoctorActive) {
return _buildViewDetailsButton(context);
}
// Doctor is active - check rebooking logic
final isArrived = AppointmentType.isArrived(appointment);
final isRebookingNotAllowed = appointment.isClinicReBookingAllowed == false;
// If arrived and rebooking not allowed, show button without arrow
if (isArrived && isRebookingNotAllowed) {
return _buildSingleButton(context, isLoading);
}
// Normal flow - show button with arrow
return _buildButtonWithArrow(context, appState, isLoading);
}
/// Builds a single button without arrow (for no rebooking scenarios)
Widget _buildSingleButton(BuildContext context, bool isLoading) {
if (isLoading) {
return Container().toShimmer2(isShow: true, height: 40.h, width: 100.w, radius: 12.r);
}
final isArrived = AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel);
if (isArrived) {
return getArrivedAppointmentButton(context).toShimmer2(isShow: isLoading);
}
return _buildNextActionButton(context, isLoading);
}
/// Builds the next action button (Pay Now, Confirm, etc.)
Widget _buildNextActionButton(BuildContext context, bool isLoading) {
final appointment = widget.patientAppointmentHistoryResponseModel;
return CustomButton(
text: AppointmentType.getNextActionText(appointment.nextAction),
onPressed: () {
handleAppointmentNextAction(appointment.nextAction, context);
},
backgroundColor: AppointmentType.getNextActionButtonColor(appointment.nextAction).withValues(alpha: 0.15),
borderColor: AppointmentType.getNextActionButtonColor(appointment.nextAction).withValues(alpha: 0.01),
textColor: AppointmentType.getNextActionTextColor(appointment.nextAction),
fontSize: 14.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
icon: AppointmentType.getNextActionIcon(appointment.nextAction),
iconColor: AppointmentType.getNextActionTextColor(appointment.nextAction),
iconSize: 14.h,
).toShimmer2(isShow: isLoading);
}
/// Builds button with arrow (normal flow with navigation arrow)
Widget _buildButtonWithArrow(BuildContext context, AppState appState, bool isLoading) {
return Row(
children: [
_buildMainActionButton(context, isLoading),
SizedBox(width: 8.w),
_buildNavigationArrow(context, appState, isLoading),
],
);
}
/// Builds the main action button in the row (left side)
Widget _buildMainActionButton(BuildContext context, bool isLoading) {
if (isLoading) {
return Container().toShimmer2(isShow: true, height: 40.h, width: 100.w, radius: 12.r);
}
final isArrived = AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel);
return Expanded(
flex: 7,
child: isArrived ? getArrivedAppointmentButton(context).toShimmer2(isShow: isLoading) : _buildNextActionButton(context, isLoading),
);
}
/// Builds the navigation arrow button (right side)
Widget _buildNavigationArrow(BuildContext context, AppState appState, bool isLoading) {
final appointment = widget.patientAppointmentHistoryResponseModel;
final isArrived = AppointmentType.isArrived(appointment);
// Check if arrow should be hidden
final shouldHideArrow = (appointment.isLiveCareAppointment ?? false) ||
(appointment.isExecludeDoctor ?? false) ||
!Utils.isClinicAllowedForRebook(appointment.clinicID ?? 0);
if (shouldHideArrow && isArrived) {
return SizedBox.shrink();
}
return Expanded(
flex: 2,
child: Container(
height: 40.h,
width: 40.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.textColor,
borderRadius: 10.r,
),
child: Padding(
padding: EdgeInsets.all(10.w),
child: Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(
iconColor: AppColors.whiteColor,
icon: AppAssets.forward_arrow_icon_small,
width: 40.h,
height: 40.h,
fit: BoxFit.contain,
),
),
),
).toShimmer2(isShow: isLoading).onPress(() {
Navigator.of(context)
.push(
CustomPageRoute(
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: appointment),
),
)
.then((val) {
// Can refresh appointments here if needed
});
}),
);
}
/// Builds the View Details button (for inactive doctors)
Widget _buildViewDetailsButton(BuildContext context) {
return CustomButton(
text: LocaleKeys.viewDetails.tr(context: context),
onPressed: () {
Navigator.of(context)
.push(
CustomPageRoute(
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
),
)
.then((_) {
widget.myAppointmentsViewModel.initAppointmentsViewModel();
widget.myAppointmentsViewModel.getPatientAppointments(true, false);
});
},
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: isFoldable ? 36.h : 40.h,
).toShimmer2(isShow: widget.myAppointmentsViewModel.isMyAppointmentsLoading);
}
Widget getArrivedAppointmentButton(BuildContext context) { Widget getArrivedAppointmentButton(BuildContext context) {
// Check if rebooking is not allowed - show View Details button // Check if rebooking is not allowed - show View Details button
if (widget.patientAppointmentHistoryResponseModel.isClinicReBookingAllowed == false) { if (widget.patientAppointmentHistoryResponseModel.isClinicReBookingAllowed == false) {

@ -30,11 +30,7 @@ class MedicalFileCard extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final iconS = iconSize ?? 30.w; final iconS = iconSize ?? 30.w;
return Container( return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: backgroundColor, borderRadius: 20.r, hasShadow: false),
color: backgroundColor,
borderRadius: 20.r,
hasShadow: false
),
padding: EdgeInsets.all(12.w), padding: EdgeInsets.all(12.w),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -64,5 +60,3 @@ class MedicalFileCard extends StatelessWidget {
); );
} }
} }

@ -14,7 +14,7 @@ import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
import 'package:hmg_patient_app_new/widgets/graph/CustomBarGraph.dart'; import 'package:hmg_patient_app_new/widgets/graph/CustomBarGraph.dart';
import 'package:intl/intl.dart' show DateFormat; import 'package:intl/intl.dart' show DateFormat;
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:hmg_patient_app_new/features/smartwatch_health_data/HealthDataTransformation.dart' as durations; import 'package:hmg_patient_app_new/features/smartwatch_health_data/health_data_transformations.dart' as durations;
import 'package:dartz/dartz.dart' show Tuple2; import 'package:dartz/dartz.dart' show Tuple2;
import '../../core/utils/date_util.dart'; import '../../core/utils/date_util.dart';

File diff suppressed because it is too large Load Diff

@ -1,252 +0,0 @@
import 'package:flutter/material.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/dependencies.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/smartwatch_health_data/health_provider.dart';
import 'package:hmg_patient_app_new/presentation/smartwatches/activity_detail.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:provider/provider.dart';
import 'package:hmg_patient_app_new/features/smartwatch_health_data/HealthDataTransformation.dart' as durations;
import '../../core/utils/date_util.dart' show DateUtil;
class SmartWatchActivity extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: CollapsingListView(
title: "All Health Data".needTranslation,
child: Column(
spacing: 16.h,
children: [
resultItem(
leadingIcon: AppAssets.watchActivity,
title: "Activity Calories".needTranslation,
description: "Activity rings give you a quick visual reference of how active you are each day. ".needTranslation,
trailingIcon: AppAssets.watchActivityTrailing,
result: context.read<HealthProvider>().sumOfNonEmptyData(context.read<HealthProvider>().vitals?.activity??[]),
unitsOfMeasure: "Kcal"
).onPress((){
// Map<String, List<Vitals>> getVitals() {
// return {
// "heartRate": heartRate ,
// "sleep": sleep,
// "steps": step,
// "activity": activity,
// "bodyOxygen": bodyOxygen,
// "bodyTemperature": bodyTemperature,
// };
// }
context.read<HealthProvider>().setDurations(durations.Durations.daily);
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("activity");
context.read<HealthProvider>().saveSelectedSection("activity");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("activity", sectionName:"Activity Calories", uom: "Kcal");
}),
resultItem(
leadingIcon: AppAssets.watchSteps,
title: "Steps".needTranslation,
description: "Step count is the number of steps you take throughout the day.".needTranslation,
trailingIcon: AppAssets.watchStepsTrailing,
result: context.read<HealthProvider>().sumOfNonEmptyData(context.read<HealthProvider>().vitals?.step??[]),
unitsOfMeasure: "Steps"
).onPress((){
// Map<String, List<Vitals>> getVitals() {
// return {
// "heartRate": heartRate ,
// "sleep": sleep,
// "steps": step,
// "activity": activity,
// "bodyOxygen": bodyOxygen,
// "bodyTemperature": bodyTemperature,
// };
// }
context.read<HealthProvider>().setDurations(durations.Durations.daily);
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("steps");
context.read<HealthProvider>().saveSelectedSection("steps");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("steps", sectionName: "Steps", uom: "Steps");
}),
resultItem(
leadingIcon: AppAssets.watchSteps,
title: "Distance Covered".needTranslation,
description: "Step count is the distance you take throughout the day.".needTranslation,
trailingIcon: AppAssets.watchStepsTrailing,
result: context.read<HealthProvider>().sumOfNonEmptyData(context.read<HealthProvider>().vitals?.distance??[]),
unitsOfMeasure: "Km"
).onPress((){
// Map<String, List<Vitals>> getVitals() {
// return {
// "heartRate": heartRate ,
// "sleep": sleep,
// "steps": step,
// "activity": activity,
// "bodyOxygen": bodyOxygen,
// "bodyTemperature": bodyTemperature,
// };
// }
context.read<HealthProvider>().setDurations(durations.Durations.daily);
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("distance");
context.read<HealthProvider>().saveSelectedSection("distance");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("distance", sectionName: "Distance Covered", uom: "km");
}),
resultItem(
leadingIcon: AppAssets.watchSleep,
title: "Sleep Score".needTranslation,
description: "This will keep track of how much hours you sleep in a day".needTranslation,
trailingIcon: AppAssets.watchSleepTrailing,
result: DateUtil.millisToHourMin(int.parse(context.read<HealthProvider>().firstNonEmptyValue(context.read<HealthProvider>().vitals?.sleep??[]))).split(" ")[0],
unitsOfMeasure: "hr",
resultSecondValue: DateUtil.millisToHourMin(int.parse(context.read<HealthProvider>().firstNonEmptyValue(context.read<HealthProvider>().vitals?.sleep??[]))).split(" ")[2],
unitOfSecondMeasure: "min"
).onPress((){
// Map<String, List<Vitals>> getVitals() {
// return {
// "heartRate": heartRate ,
// "sleep": sleep,
// "steps": step,
// "activity": activity,
// "bodyOxygen": bodyOxygen,
// "bodyTemperature": bodyTemperature,
// };
// }
context.read<HealthProvider>().setDurations(durations.Durations.daily);
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("sleep");
context.read<HealthProvider>().saveSelectedSection("sleep");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("sleep", sectionName:"Sleep Score",uom:"");
}),
resultItem(
leadingIcon: AppAssets.watchWeight,
title: "Blood Oxygen".needTranslation,
description: "This will calculate your Blood Oxygen to keep track and update history".needTranslation,
trailingIcon: AppAssets.watchWeightTrailing,
result: context.read<HealthProvider>().firstNonEmptyValue(context.read<HealthProvider>().vitals?.bodyOxygen??[], ),
unitsOfMeasure: "%"
).onPress((){
// Map<String, List<Vitals>> getVitals() {
// return {
// "heartRate": heartRate ,
// "sleep": sleep,
// "steps": step,
// "activity": activity,
// "bodyOxygen": bodyOxygen,
// "bodyTemperature": bodyTemperature,
// };
// }
context.read<HealthProvider>().setDurations(durations.Durations.daily);
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("bodyOxygen");
context.read<HealthProvider>().saveSelectedSection("bodyOxygen");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("bodyOxygen", uom: "%", sectionName:"Blood Oxygen" );
}),
resultItem(
leadingIcon: AppAssets.watchWeight,
title: "Body temperature".needTranslation,
description: "This will calculate your Body temprerature to keep track and update history".needTranslation,
trailingIcon: AppAssets.watchWeightTrailing,
result: context.read<HealthProvider>().firstNonEmptyValue(context.read<HealthProvider>().vitals?.bodyTemperature??[]),
unitsOfMeasure: "C"
).onPress((){
// Map<String, List<Vitals>> getVitals() {
// return {
// "heartRate": heartRate ,
// "sleep": sleep,
// "steps": step,
// "activity": activity,
// "bodyOxygen": bodyOxygen,
// "bodyTemperature": bodyTemperature,
// };
// }
context.read<HealthProvider>().setDurations(durations.Durations.daily);
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("bodyTemperature");
context.read<HealthProvider>().saveSelectedSection("bodyTemperature");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("bodyTemperature" , sectionName: "Body temperature".capitalizeFirstofEach, uom: "C");
}),
],
).paddingSymmetrical(24.w, 24.h),
));
}
Widget resultItem({
required String leadingIcon,
required String title,
required String description,
required String trailingIcon,
required String result,
required String unitsOfMeasure,
String? resultSecondValue,
String? unitOfSecondMeasure
}) {
return DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.h),
child: Row(
spacing: 16.w,
children: [
Expanded(
child:Column(
spacing: 8.h,
children: [
Row(
spacing: 8.w,
children: [
Utils.buildSvgWithAssets(icon: leadingIcon, height: 16.h, width: 14.w),
title.toText16( weight: FontWeight.w600, color: AppColors.textColor),
],
),
description.toText12(isBold: true, color: AppColors.greyTextColor),
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
spacing: 2.h,
children: [
result.toText21(isBold: true, color: AppColors.textColor),
unitsOfMeasure.toText10(isBold: true, color:AppColors.greyTextColor ),
if(resultSecondValue != null)
Visibility(
visible: resultSecondValue != null ,
child: Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
spacing: 2.h,
children: [
SizedBox(width: 2.w,),
resultSecondValue.toText21(isBold: true, color: AppColors.textColor),
unitOfSecondMeasure!.toText10(isBold: true, color:AppColors.greyTextColor )
],
),
)
],
),
],
) ,
),
Utils.buildSvgWithAssets(icon: trailingIcon, width: 72.w, height: 72.h),
],
).paddingSymmetrical(16.w, 16.h)
);
}
}

@ -0,0 +1,188 @@
import 'package:flutter/material.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/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/smartwatch_health_data/health_data_transformations.dart' as durations;
import 'package:hmg_patient_app_new/features/smartwatch_health_data/health_provider.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:provider/provider.dart';
import '../../core/utils/date_util.dart' show DateUtil;
class SmartWatchesHealthDataScreen extends StatelessWidget {
const SmartWatchesHealthDataScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: CollapsingListView(
title: "All Health Data".needTranslation,
child: Column(
spacing: 16.h,
children: [
resultItem(
leadingIcon: AppAssets.watchActivity,
title: "Activity Calories".needTranslation,
description: "Activity rings give you a quick visual reference of how active you are each day. ".needTranslation,
trailingIcon: AppAssets.watchActivityTrailing,
result: context.read<HealthProvider>().sumOfNonEmptyData(context.read<HealthProvider>().vitals?.activity ?? []),
unitsOfMeasure: "Kcal")
.onPress(() {
context.read<HealthProvider>().setDurations(durations.Durations.daily);
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("activity");
context.read<HealthProvider>().saveSelectedSection("activity");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("activity", sectionName: "Activity Calories", uom: "Kcal");
}),
resultItem(
leadingIcon: AppAssets.watchSteps,
title: "Steps".needTranslation,
description: "Step count is the number of steps you take throughout the day.".needTranslation,
trailingIcon: AppAssets.watchStepsTrailing,
result: context.read<HealthProvider>().sumOfNonEmptyData(context.read<HealthProvider>().vitals?.step ?? []),
unitsOfMeasure: "Steps")
.onPress(() {
// Map<String, List<Vitals>> getVitals() {
// return {
// "heartRate": heartRate ,
// "sleep": sleep,
// "steps": step,
// "activity": activity,
// "bodyOxygen": bodyOxygen,
// "bodyTemperature": bodyTemperature,
// };
// }
context.read<HealthProvider>().setDurations(durations.Durations.daily);
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("steps");
context.read<HealthProvider>().saveSelectedSection("steps");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("steps", sectionName: "Steps", uom: "Steps");
}),
resultItem(
leadingIcon: AppAssets.watchSteps,
title: "Distance Covered".needTranslation,
description: "Step count is the distance you take throughout the day.".needTranslation,
trailingIcon: AppAssets.watchStepsTrailing,
result: context.read<HealthProvider>().sumOfNonEmptyData(context.read<HealthProvider>().vitals?.distance ?? []),
unitsOfMeasure: "Km")
.onPress(() {
context.read<HealthProvider>().setDurations(durations.Durations.daily);
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("distance");
context.read<HealthProvider>().saveSelectedSection("distance");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("distance", sectionName: "Distance Covered", uom: "km");
}),
resultItem(
leadingIcon: AppAssets.watchSleep,
title: "Sleep Score".needTranslation,
description: "This will keep track of how much hours you sleep in a day".needTranslation,
trailingIcon: AppAssets.watchSleepTrailing,
result: DateUtil.millisToHourMin(
int.parse(context.read<HealthProvider>().firstNonEmptyValue(context.read<HealthProvider>().vitals?.sleep ?? [])))
.split(" ")[0],
unitsOfMeasure: "hr",
resultSecondValue: DateUtil.millisToHourMin(
int.parse(context.read<HealthProvider>().firstNonEmptyValue(context.read<HealthProvider>().vitals?.sleep ?? [])))
.split(" ")[2],
unitOfSecondMeasure: "min")
.onPress(() {
context.read<HealthProvider>().setDurations(durations.Durations.daily);
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("sleep");
context.read<HealthProvider>().saveSelectedSection("sleep");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("sleep", sectionName: "Sleep Score", uom: "");
}),
resultItem(
leadingIcon: AppAssets.watchWeight,
title: "Blood Oxygen".needTranslation,
description: "This will calculate your Blood Oxygen to keep track and update history".needTranslation,
trailingIcon: AppAssets.watchWeightTrailing,
result: context.read<HealthProvider>().firstNonEmptyValue(
context.read<HealthProvider>().vitals?.bodyOxygen ?? [],
),
unitsOfMeasure: "%")
.onPress(() {
context.read<HealthProvider>().setDurations(durations.Durations.daily);
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("bodyOxygen");
context.read<HealthProvider>().saveSelectedSection("bodyOxygen");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("bodyOxygen", uom: "%", sectionName: "Blood Oxygen");
}),
resultItem(
leadingIcon: AppAssets.watchWeight,
title: "Body temperature".needTranslation,
description: "This will calculate your Body temprerature to keep track and update history".needTranslation,
trailingIcon: AppAssets.watchWeightTrailing,
result: context.read<HealthProvider>().firstNonEmptyValue(context.read<HealthProvider>().vitals?.bodyTemperature ?? []),
unitsOfMeasure: "C")
.onPress(() {
context.read<HealthProvider>().setDurations(durations.Durations.daily);
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("bodyTemperature");
context.read<HealthProvider>().saveSelectedSection("bodyTemperature");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("bodyTemperature", sectionName: "Body temperature".capitalizeFirstofEach, uom: "C");
}),
],
).paddingSymmetrical(24.w, 24.h),
));
}
Widget resultItem({
required String leadingIcon,
required String title,
required String description,
required String trailingIcon,
required String result,
required String unitsOfMeasure,
String? resultSecondValue,
String? unitOfSecondMeasure,
}) {
return DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.h),
child: Row(
spacing: 16.w,
children: [
Expanded(
child: Column(
spacing: 8.h,
children: [
Row(
spacing: 8.w,
children: [
Utils.buildSvgWithAssets(icon: leadingIcon, height: 16.h, width: 14.w),
title.toText16(weight: FontWeight.w600, color: AppColors.textColor),
],
),
description.toText12(isBold: true, color: AppColors.greyTextColor),
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
spacing: 2.h,
children: [
result.toText21(isBold: true, color: AppColors.textColor),
unitsOfMeasure.toText10(isBold: true, color: AppColors.greyTextColor),
if (resultSecondValue != null)
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
spacing: 2.h,
children: [
SizedBox(width: 2.w),
resultSecondValue.toText21(isBold: true, color: AppColors.textColor),
unitOfSecondMeasure!.toText10(isBold: true, color: AppColors.greyTextColor)
],
),
],
),
],
),
),
Utils.buildSvgWithAssets(icon: trailingIcon, width: 72.w, height: 72.h),
],
).paddingSymmetrical(16.w, 16.h));
}
}

@ -1,5 +1,3 @@
import 'dart:io';
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';
@ -54,7 +52,6 @@ class SmartwatchHomePage extends StatelessWidget {
fontSize: 16.f, fontSize: 16.f,
isBold: true, isBold: true,
borderRadius: 12.r, borderRadius: 12.r,
height: 50.h, height: 50.h,
icon: AppAssets.ask_doctor_icon, icon: AppAssets.ask_doctor_icon,
iconColor: AppColors.infoColor, iconColor: AppColors.infoColor,
@ -69,11 +66,12 @@ class SmartwatchHomePage extends StatelessWidget {
child: GridView( child: GridView(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
shrinkWrap: true, shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, crossAxisCount: 2,
crossAxisSpacing: 16.h, crossAxisSpacing: 16.h,
mainAxisSpacing: 16.w, mainAxisSpacing: 16.w,
mainAxisExtent: 240.h, childAspectRatio: isFoldable ? 1.1 : (isTablet ? 1.3 : 0.7),
), ),
children: [ children: [
Container( Container(
@ -83,20 +81,24 @@ class SmartwatchHomePage extends StatelessWidget {
), ),
child: Column( child: Column(
children: [ children: [
Image.asset("assets/images/png/smartwatches/apple-watch-5.jpg", width: 136.w, height: 136.h).paddingSymmetrical(24.w, 8.h), Image.asset("assets/images/png/smartwatches/apple-watch-5.jpg", width: 136.h, height: 136.h).paddingSymmetrical(24.w, 8.h),
"Apple Watch".needTranslation.toText16(isBold: true), "Apple Watch".needTranslation.toText16(isBold: true),
CustomButton( CustomButton(
text: LocaleKeys.selectSmartWatch.tr(context: context), text: LocaleKeys.selectSmartWatch.tr(context: context),
onPressed: () { onPressed: () {
context.read<HealthProvider>().setSelectedWatchType(SmartWatchTypes.apple, "assets/images/png/smartwatches/apple-watch-5.jpg"); context
getIt.get<NavigationService>().pushPage(page: SmartwatchInstructionsPage( .read<HealthProvider>()
smartwatchDetails: SmartwatchDetails(SmartWatchTypes.apple, .setSelectedWatchType(SmartWatchTypes.apple, "assets/images/png/smartwatches/apple-watch-5.jpg");
"assets/images/png/smartwatches/apple-watch-5.jpg", getIt.get<NavigationService>().pushPage(
AppAssets.bluetooth, page: SmartwatchInstructionsPage(
LocaleKeys.applehealthapplicationshouldbeinstalledinyourphone.tr(context: context), smartwatchDetails: SmartwatchDetails(
LocaleKeys.unabletodetectapplicationinstalledpleasecomebackonceinstalled.tr(context: context), SmartWatchTypes.apple,
LocaleKeys.applewatchshouldbeconnected.tr(context: context)), "assets/images/png/smartwatches/apple-watch-5.jpg",
)); AppAssets.bluetooth,
LocaleKeys.applehealthapplicationshouldbeinstalledinyourphone.tr(context: context),
LocaleKeys.unabletodetectapplicationinstalledpleasecomebackonceinstalled.tr(context: context),
LocaleKeys.applewatchshouldbeconnected.tr(context: context)),
));
}, },
backgroundColor: AppColors.primaryRedColor.withAlpha(40), backgroundColor: AppColors.primaryRedColor.withAlpha(40),
borderColor: AppColors.primaryRedColor.withAlpha(0), borderColor: AppColors.primaryRedColor.withAlpha(0),
@ -110,26 +112,29 @@ class SmartwatchHomePage extends StatelessWidget {
), ),
), ),
Container( Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r),
color: AppColors.whiteColor,
borderRadius: 24.r,
),
child: Column( child: Column(
children: [ children: [
Image.asset("assets/images/png/smartwatches/galaxy_watch_8_classic.jpeg", fit: BoxFit.contain, width: 136.w, height: 136.h).paddingSymmetrical(24.w, 8.h), Image.asset("assets/images/png/smartwatches/galaxy_watch_8_classic.jpeg", fit: BoxFit.contain, width: 136.w, height: 136.h)
.paddingSymmetrical(24.w, 8.h),
"Samsung Watch".needTranslation.toText16(isBold: true), "Samsung Watch".needTranslation.toText16(isBold: true),
CustomButton( CustomButton(
text: LocaleKeys.selectSmartWatch.tr(context: context), text: LocaleKeys.selectSmartWatch.tr(context: context),
onPressed: () { onPressed: () {
context.read<HealthProvider>().setSelectedWatchType(SmartWatchTypes.samsung, "assets/images/png/smartwatches/galaxy_watch_8_classic.jpeg"); context
getIt.get<NavigationService>().pushPage(page: SmartwatchInstructionsPage( .read<HealthProvider>()
smartwatchDetails: SmartwatchDetails(SmartWatchTypes.samsung, .setSelectedWatchType(SmartWatchTypes.samsung, "assets/images/png/smartwatches/galaxy_watch_8_classic.jpeg");
"assets/images/png/smartwatches/galaxy_watch_8_classic.jpeg", getIt.get<NavigationService>().pushPage(
AppAssets.bluetooth, page: SmartwatchInstructionsPage(
LocaleKeys.samsunghealthapplicationshouldbeinstalledinyourphone.tr(context: context), smartwatchDetails: SmartwatchDetails(
LocaleKeys.unabletodetectapplicationinstalledpleasecomebackonceinstalled.tr(context: context), SmartWatchTypes.samsung,
LocaleKeys.samsungwatchshouldbeconnected.tr(context: context)), "assets/images/png/smartwatches/galaxy_watch_8_classic.jpeg",
)); }, AppAssets.bluetooth,
LocaleKeys.samsunghealthapplicationshouldbeinstalledinyourphone.tr(context: context),
LocaleKeys.unabletodetectapplicationinstalledpleasecomebackonceinstalled.tr(context: context),
LocaleKeys.samsungwatchshouldbeconnected.tr(context: context)),
));
},
backgroundColor: AppColors.primaryRedColor.withAlpha(40), backgroundColor: AppColors.primaryRedColor.withAlpha(40),
borderColor: AppColors.primaryRedColor.withAlpha(0), borderColor: AppColors.primaryRedColor.withAlpha(0),
textColor: AppColors.primaryRedColor, textColor: AppColors.primaryRedColor,
@ -187,7 +192,6 @@ class SmartwatchHomePage extends StatelessWidget {
CustomButton( CustomButton(
text: LocaleKeys.selectSmartWatch.tr(context: context), text: LocaleKeys.selectSmartWatch.tr(context: context),
onPressed: () { onPressed: () {
showUnavailableDialog(context); showUnavailableDialog(context);
// context.read<HealthProvider>().setSelectedWatchType(SmartWatchTypes.whoop, "assets/images/png/smartwatches/Whoop_Watch.png"); // context.read<HealthProvider>().setSelectedWatchType(SmartWatchTypes.whoop, "assets/images/png/smartwatches/Whoop_Watch.png");
// getIt.get<NavigationService>().pushPage(page: SmartwatchInstructionsPage( // getIt.get<NavigationService>().pushPage(page: SmartwatchInstructionsPage(
@ -221,18 +225,16 @@ class SmartwatchHomePage extends StatelessWidget {
} }
void showUnavailableDialog(BuildContext context) { void showUnavailableDialog(BuildContext context) {
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
title: LocaleKeys.notice.tr(context: context), title: LocaleKeys.notice.tr(context: context),
context, context,
child: Utils.getWarningWidget( child: Utils.getWarningWidget(
loadingText: LocaleKeys.featureComingSoonDescription.tr(context: context), loadingText: LocaleKeys.featureComingSoonDescription.tr(context: context),
isShowActionButtons: false, isShowActionButtons: false,
showOkButton: true, showOkButton: true,
onConfirmTap: () async { onConfirmTap: () async {
context.pop(); context.pop();
} }),
),
callBackFunc: () {}, callBackFunc: () {},
isFullScreen: false, isFullScreen: false,
isCloseButtonVisible: true, isCloseButtonVisible: true,

@ -2,13 +2,10 @@ 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';
import 'package:hmg_patient_app_new/core/common_models/smart_watch.dart'; import 'package:hmg_patient_app_new/core/common_models/smart_watch.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.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/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/smartwatches/smart_watch_activity.dart' show SmartWatchActivity;
import 'package:hmg_patient_app_new/services/navigation_service.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';
@ -26,62 +23,66 @@ class SmartwatchInstructionsPage extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
body: CollapsingListView( body: CollapsingListView(
title: "How does it work".needTranslation, title: "How does it work".needTranslation,
bottomChild: Container( bottomChild: Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor, color: AppColors.whiteColor,
borderRadius: 24.r, borderRadius: 24.r,
),
child: CustomButton(
text: LocaleKeys.getStarted.tr(context: context),
onPressed: () {
context.read<HealthProvider>().initDevice();
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 16.f,
isBold: true,
borderRadius: 12.r,
height: 50.h,
).paddingSymmetrical(24.w, 30.h),
), ),
child: Column( child: CustomButton(
mainAxisSize: MainAxisSize.max, text: LocaleKeys.getStarted.tr(context: context),
spacing: 18.h, onPressed: () {
children: [ context.read<HealthProvider>().initDevice();
Image.asset(smartwatchDetails.watchIcon, fit: BoxFit.contain, height: 280.h,width: 280.w,), },
DecoratedBox( backgroundColor: AppColors.primaryRedColor,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.h), borderColor: AppColors.primaryRedColor,
child: Column( textColor: AppColors.whiteColor,
children: [ fontSize: 16.f,
watchContentDetails( isBold: true,
title: smartwatchDetails.detailsTitle, borderRadius: 12.r,
description: smartwatchDetails.details, height: 50.h,
icon: smartwatchDetails.smallIcon, ).paddingSymmetrical(24.w, 30.h),
descriptionTextColor: AppColors.primaryRedColor
),
Divider(
color: AppColors.dividerColor,
thickness: 1.h,
).paddingOnly(top: 16.h, bottom: 16.h),
watchContentDetails(
title: smartwatchDetails.secondTitle,
description: LocaleKeys.updatetheinformation.tr(),
icon: AppAssets.bluetooth,
descriptionTextColor: AppColors.greyTextColor
),
],
).paddingSymmetrical(16.w, 16.h),
)
],
).paddingSymmetrical(24.w, 16.h),
), ),
child: Column(
mainAxisSize: MainAxisSize.max,
spacing: 18.h,
children: [
Image.asset(
smartwatchDetails.watchIcon,
fit: BoxFit.contain,
height: 280.h,
width: 280.w,
),
DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.h),
child: Column(
children: [
watchContentDetails(
title: smartwatchDetails.detailsTitle,
description: smartwatchDetails.details,
icon: smartwatchDetails.smallIcon,
descriptionTextColor: AppColors.primaryRedColor,
),
Divider(
color: AppColors.dividerColor,
thickness: 1.h,
).paddingOnly(top: 16.h, bottom: 16.h),
watchContentDetails(
title: smartwatchDetails.secondTitle,
description: LocaleKeys.updatetheinformation.tr(),
icon: AppAssets.bluetooth,
descriptionTextColor: AppColors.greyTextColor,
),
],
).paddingSymmetrical(16.w, 16.h),
)
],
).paddingSymmetrical(24.w, 16.h),
),
); );
} }
Widget watchContentDetails({required String title, required String description, required String icon, required Color descriptionTextColor}) { Widget watchContentDetails({required String title, required String description, required String icon, required Color descriptionTextColor}) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -90,9 +91,7 @@ class SmartwatchInstructionsPage extends StatelessWidget {
DecoratedBox( DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.h), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.h),
child: Utils.buildSvgWithAssets(icon: icon, width: 40.w, height: 40.h), child: Utils.buildSvgWithAssets(icon: icon, width: 40.w, height: 40.h),
), ),
title.toText16(isBold: true, color: AppColors.textColor), title.toText16(isBold: true, color: AppColors.textColor),
description.toText12(isBold: true, color: descriptionTextColor) description.toText12(isBold: true, color: descriptionTextColor)
], ],

@ -19,7 +19,6 @@ import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
import 'package:hmg_patient_app_new/presentation/home_health_care/hhc_procedures_page.dart'; import 'package:hmg_patient_app_new/presentation/home_health_care/hhc_procedures_page.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart';
import 'package:hmg_patient_app_new/presentation/servicesPriceList/services_price_list_page.dart'; import 'package:hmg_patient_app_new/presentation/servicesPriceList/services_price_list_page.dart';
import 'package:hmg_patient_app_new/presentation/smartwatches/huawei_health_example.dart';
import 'package:hmg_patient_app_new/presentation/smartwatches/smartwatch_home_page.dart'; import 'package:hmg_patient_app_new/presentation/smartwatches/smartwatch_home_page.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/organ_selector_screen.dart'; import 'package:hmg_patient_app_new/presentation/symptoms_checker/organ_selector_screen.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/possible_conditions_screen.dart'; import 'package:hmg_patient_app_new/presentation/symptoms_checker/possible_conditions_screen.dart';
@ -42,7 +41,6 @@ import '../features/monthly_reports/monthly_reports_repo.dart';
import '../features/monthly_reports/monthly_reports_view_model.dart'; import '../features/monthly_reports/monthly_reports_view_model.dart';
import '../features/qr_parking/qr_parking_view_model.dart'; import '../features/qr_parking/qr_parking_view_model.dart';
import '../presentation/parking/paking_page.dart'; import '../presentation/parking/paking_page.dart';
import '../presentation/smartwatches/smartwatch_instructions_page.dart';
import '../services/error_handler_service.dart'; import '../services/error_handler_service.dart';
class AppRoutes { class AppRoutes {

Loading…
Cancel
Save