pull/208/head
haroon amjad 2 days ago
parent f7446d0d41
commit 4959392f74

@ -92,7 +92,7 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_CALENDAR" /> <uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" /> <uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" tools:node="remove"/>
<uses-permission android:name="android.permission.VIDEO_CAPTURE" /> <uses-permission android:name="android.permission.VIDEO_CAPTURE" />
<uses-permission android:name="android.permission.AUDIO_CAPTURE" /> <uses-permission android:name="android.permission.AUDIO_CAPTURE" />

@ -566,6 +566,8 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
final appointmentsList = (list as List).map((item) => GetFavoriteDoctorsListModel.fromJson(item as Map<String, dynamic>)).toList().cast<GetFavoriteDoctorsListModel>(); final appointmentsList = (list as List).map((item) => GetFavoriteDoctorsListModel.fromJson(item as Map<String, dynamic>)).toList().cast<GetFavoriteDoctorsListModel>();
appointmentsList.removeWhere((element) => element.isActive == false);
apiResponse = GenericApiModel<List<GetFavoriteDoctorsListModel>>( apiResponse = GenericApiModel<List<GetFavoriteDoctorsListModel>>(
messageStatus: messageStatus, messageStatus: messageStatus,
statusCode: statusCode, statusCode: statusCode,

@ -15,7 +15,7 @@ class NotificationsViewModel extends ChangeNotifier {
List<NotificationResponseModel> notificationsList = []; List<NotificationResponseModel> notificationsList = [];
int currentPage = 0; int currentPage = 0;
int pagingSize = 15; int pagingSize = 50;
int notificationStatusID = 2; // Default to status 2 (e.g., unread) int notificationStatusID = 2; // Default to status 2 (e.g., unread)
NotificationsViewModel({ NotificationsViewModel({

@ -258,7 +258,8 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
CustomPageRoute( CustomPageRoute(
page: InsuranceHomePage(), page: InsuranceHomePage(),
), ),
); )
.then((val) {});
}, },
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.secondaryLightRedBorderColor, borderColor: AppColors.secondaryLightRedBorderColor,

@ -1,5 +1,6 @@
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_export.dart'; import 'package:hmg_patient_app_new/core/app_export.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';
@ -8,7 +9,9 @@ import 'package:hmg_patient_app_new/features/book_appointments/models/laser_body
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/laser_body_parts.dart'; import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/laser_body_parts.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:smooth_corner/smooth_corner.dart';
class BodyPartsListing extends StatelessWidget { class BodyPartsListing extends StatelessWidget {
final List<LaserBodyPart> parts; final List<LaserBodyPart> parts;
@ -49,11 +52,7 @@ class BodyPartsListing extends StatelessWidget {
Visibility( Visibility(
visible: !isLoading, visible: !isLoading,
child: GridView.builder( child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 75 / 107, crossAxisSpacing: 4.h, mainAxisSpacing: 21.h),
crossAxisCount: 3,
childAspectRatio: 85 / 107,
crossAxisSpacing: 4.h,
mainAxisSpacing: 21.h),
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
itemCount: parts.length, itemCount: parts.length,
@ -73,7 +72,7 @@ class BodyPartsListing extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
AspectRatio( AspectRatio(
aspectRatio: 130 / 120, aspectRatio: 150 / 140,
child: FittedBox( child: FittedBox(
fit: BoxFit.fitWidth, fit: BoxFit.fitWidth,
child: Stack( child: Stack(
@ -112,14 +111,41 @@ class BodyPartsListing extends StatelessWidget {
child: Center( child: Center(
child: Column( child: Column(
children: [ children: [
context.read<BookAppointmentsViewModel>().getLaserProcedureNameWRTLanguage(parts[index]).toText12(isBold: true, color: AppColors.textColor, isCenter: true, maxLine: 2), context.read<BookAppointmentsViewModel>().getLaserProcedureNameWRTLanguage(parts[index]).toText12(isBold: true, color: AppColors.textColor, isCenter: true, maxLine: 1),
Row( SizedBox(height: 4.h),
mainAxisAlignment: MainAxisAlignment.center, AppCustomChipWidget(
children: [ backgroundColor: _isSelected ? AppColors.chipSecondaryLightRedColor : AppColors.whiteColor,
"${LocaleKeys.mins.tr()}: ".toText12(isBold: true, color: AppColors.textColor, isCenter: true, maxLine: 2), textColor: _isSelected ? AppColors.chipPrimaryRedBorderColor : AppColors.blackColor,
parts[index].timeDuration!.toText12(isBold: true, color: AppColors.textColor, isCenter: true, maxLine: 2), // labelText: "${parts[index].timeDuration!} ${LocaleKeys.mins.tr()}",
], richText: "${parts[index].timeDuration!} ${LocaleKeys.mins.tr()}".toText12(
), fontWeight: FontWeight.w500,
color: _isSelected ? AppColors.chipPrimaryRedBorderColor : AppColors.blackColor,
),
icon: AppAssets.waiting_time_clock,
iconHasColor: true,
iconColor: _isSelected ? AppColors.chipPrimaryRedBorderColor : AppColors.blackColor,
iconSize: 16,
labelPadding: EdgeInsetsDirectional.only(start: 8.w, end: 8.w),
padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 8.w),
deleteIconSize: Size(18.w, 18.h),
shape: SmoothRectangleBorder(
borderRadius: BorderRadius.circular(10.r),
smoothness: 10,
side: BorderSide(color: _isSelected ? AppColors.chipPrimaryRedBorderColor : AppColors.borderGrayColor, width: 1),
)),
// AppCustomChipWidget(
// labelText: "${parts[index].timeDuration!} ${LocaleKeys.mins.tr()}",
// backgroundColor: AppColors.whiteColor,
// // textColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus),
// ),
// Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// "${LocaleKeys.mins.tr()}: ".toText12(isBold: true, color: AppColors.textColor, isCenter: true, maxLine: 2),
// parts[index].timeDuration!.toText12(isBold: true, color: AppColors.textColor, isCenter: true, maxLine: 2),
// ],
// ),
], ],
), ),
), ),

@ -171,7 +171,22 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
CustomPageRoute( CustomPageRoute(
page: InsuranceHomePage(), page: InsuranceHomePage(),
), ),
); )
.then((val) async {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingFeesPleaseWait.tr());
await immediateLiveCareVM.getLiveCareImmediateAppointmentFees(onSuccess: (val) {
LoaderBottomSheet.hideLoader();
}, onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
});
}, },
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.secondaryLightRedBorderColor, borderColor: AppColors.secondaryLightRedBorderColor,
@ -343,15 +358,17 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
bool cameraGranted = statuses[Permission.camera]?.isGranted ?? false; bool cameraGranted = statuses[Permission.camera]?.isGranted ?? false;
bool micGranted = statuses[Permission.microphone]?.isGranted ?? false; bool micGranted = statuses[Permission.microphone]?.isGranted ?? false;
bool notifGranted = statuses[Permission.notification]?.isGranted ?? false; bool notifGranted = statuses[Permission.notification]?.isGranted ?? false;
bool alertWindowGranted = Platform.isAndroid ? (statuses[Permission.systemAlertWindow]?.isGranted ?? false) : true;
// If all required permissions are already granted // If all required permissions are already granted
if (cameraGranted && micGranted && notifGranted) return true; if (cameraGranted && micGranted && notifGranted && alertWindowGranted) return true;
// Collect only the missing permissions // Collect only the missing permissions
final missing = <Permission>[]; final missing = <Permission>[];
if (!cameraGranted) missing.add(Permission.camera); if (!cameraGranted) missing.add(Permission.camera);
if (!micGranted) missing.add(Permission.microphone); if (!micGranted) missing.add(Permission.microphone);
if (!notifGranted) missing.add(Permission.notification); if (!notifGranted) missing.add(Permission.notification);
if (Platform.isAndroid && !alertWindowGranted) missing.add(Permission.systemAlertWindow);
// If any of the missing permissions are permanently denied/restricted -> open settings (single dialog) // If any of the missing permissions are permanently denied/restricted -> open settings (single dialog)
final permanent = missing.where((p) => (statuses[p]?.isPermanentlyDenied ?? false) || (statuses[p]?.isRestricted ?? false)).toList(); final permanent = missing.where((p) => (statuses[p]?.isPermanentlyDenied ?? false) || (statuses[p]?.isRestricted ?? false)).toList();
@ -392,6 +409,7 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
cameraGranted = newStatuses[Permission.camera]?.isGranted ?? cameraGranted; cameraGranted = newStatuses[Permission.camera]?.isGranted ?? cameraGranted;
micGranted = newStatuses[Permission.microphone]?.isGranted ?? micGranted; micGranted = newStatuses[Permission.microphone]?.isGranted ?? micGranted;
notifGranted = newStatuses[Permission.notification]?.isGranted ?? notifGranted; notifGranted = newStatuses[Permission.notification]?.isGranted ?? notifGranted;
alertWindowGranted = newStatuses[Permission.systemAlertWindow]?.isGranted ?? alertWindowGranted;
// If any requested permission is now permanently denied -> open settings // If any requested permission is now permanently denied -> open settings
final newlyPermanent = missing.where((p) => (newStatuses[p]?.isPermanentlyDenied ?? false) || (newStatuses[p]?.isRestricted ?? false)).toList(); final newlyPermanent = missing.where((p) => (newStatuses[p]?.isPermanentlyDenied ?? false) || (newStatuses[p]?.isRestricted ?? false)).toList();
@ -407,7 +425,7 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
return false; return false;
} }
return cameraGranted && micGranted && notifGranted; return cameraGranted && micGranted && notifGranted && alertWindowGranted;
} }
// Future<bool> askVideoCallPermission() async { // Future<bool> askVideoCallPermission() async {

@ -199,6 +199,7 @@ class _LandingPageState extends State<LandingPage> {
Navigator.of(context).push( Navigator.of(context).push(
CustomPageRoute( CustomPageRoute(
direction: AxisDirection.down,
page: FamilyMedicalScreen(), page: FamilyMedicalScreen(),
), ),
); );

@ -45,6 +45,7 @@ class WelcomeWidget extends StatelessWidget {
getIt.get<ProfileSettingsViewModel>().getProfileSettings(); getIt.get<ProfileSettingsViewModel>().getProfileSettings();
Navigator.of(context).push( Navigator.of(context).push(
CustomPageRoute( CustomPageRoute(
direction: getIt.get<AppState>().isArabic() ? AxisDirection.right : AxisDirection.left,
page: ProfileSettings(), page: ProfileSettings(),
), ),
); );

@ -12,6 +12,7 @@ import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart';
import 'package:hmg_patient_app_new/services/dialog_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/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';
@ -121,17 +122,27 @@ class PatientInsuranceCardUpdateCard extends StatelessWidget {
insuranceCardImage: "", insuranceCardImage: "",
onSuccess: (val) { onSuccess: (val) {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight( getIt.get<DialogService>().showCommonBottomSheetWithoutH(
title: LocaleKeys.success.tr(context: context), message: LocaleKeys.insuranceRequestSubmittedSuccessfully.tr(context: context),
context, label: LocaleKeys.notice.tr(),
child: Utils.getSuccessWidget(loadingText: LocaleKeys.insuranceRequestSubmittedSuccessfully.tr(context: context)), onOkPressed: () {
callBackFunc: () { Navigator.pop(context);
Navigator.pop(context); },
}, okLabel: "confirm",
isFullScreen: false, cancelLabel: LocaleKeys.acknowledged.tr(context: context),
isCloseButtonVisible: false, isConfirmButton: true,
isAutoDismiss: true );
); // showCommonBottomSheetWithoutHeight(
// title: LocaleKeys.success.tr(context: context),
// context,
// child: Utils.getSuccessWidget(loadingText: LocaleKeys.insuranceRequestSubmittedSuccessfully.tr(context: context)),
// callBackFunc: () {
// Navigator.pop(context);
// },
// isFullScreen: false,
// isCloseButtonVisible: false,
// isAutoDismiss: true
// );
// Future.delayed(Duration(milliseconds: 2000)).then((value) async { // Future.delayed(Duration(milliseconds: 2000)).then((value) async {
// Navigator.pop(context); // Navigator.pop(context);
// }); // });

@ -43,6 +43,7 @@ class _FamilyMedicalScreenState extends State<FamilyMedicalScreen> {
AppState appState = getIt.get<AppState>(); AppState appState = getIt.get<AppState>();
return CollapsingListView( return CollapsingListView(
isClose: true,
title: LocaleKeys.familyTitle.tr(context: context), title: LocaleKeys.familyTitle.tr(context: context),
bottomChild: appState.getAuthenticatedUser()!.isParentUser! bottomChild: appState.getAuthenticatedUser()!.isParentUser!
? Container( ? Container(

@ -216,18 +216,18 @@ class _NotificationsListPageState extends State<NotificationsListPage> {
}).paddingSymmetrical(16.w, 0.h), }).paddingSymmetrical(16.w, 0.h),
).paddingSymmetrical(24.w, 0.h), ).paddingSymmetrical(24.w, 0.h),
SizedBox(height: 16.h), SizedBox(height: 16.h),
SizedBox( // SizedBox(
key: _bottomKey, // key: _bottomKey,
child: "Show more notifications".toText16( // child: "Show more notifications".toText16(
color: AppColors.primaryRedColor, // color: AppColors.primaryRedColor,
isBold: true, // isBold: true,
isUnderLine: true // isUnderLine: true
), // ),
).onPress(() async { // ).onPress(() async {
await notificationsVM.loadMoreNotifications(); // await notificationsVM.loadMoreNotifications();
_scrollToBottom(); // _scrollToBottom();
}), // }),
SizedBox(height: 24.h), SizedBox(height: 24.h),
], ],
); );
}), }),

@ -11,7 +11,6 @@ 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/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/features/radiology/models/resp_models/patient_radiology_response_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart';
import 'package:hmg_patient_app_new/presentation/radiology/radiology_result_page.dart'; import 'package:hmg_patient_app_new/presentation/radiology/radiology_result_page.dart';

@ -158,28 +158,64 @@ class _RadiologyResultPageState extends State<RadiologyResultPage> {
borderRadius: 24.h, borderRadius: 24.h,
hasShadow: true, hasShadow: true,
), ),
child: widget.patientRadiologyResponseModel.dIAPACSURL != "" ? CustomButton( child: Column(
text: LocaleKeys.openRad.tr(context: context), children: [
onPressed: () async { SizedBox(height: 24.h),
if (radiologyViewModel.radiologyImageURL.isNotEmpty) { widget.patientRadiologyResponseModel.dIAPACSURL != ""
Uri uri = Uri.parse(radiologyViewModel.radiologyImageURL); ? CustomButton(
launchUrl(uri, mode: LaunchMode.platformDefault, webOnlyWindowName: ""); text: LocaleKeys.openRad.tr(context: context),
} else { onPressed: () async {
Utils.showToast("Radiology image not available"); if (radiologyViewModel.radiologyImageURL.isNotEmpty) {
} Uri uri = Uri.parse(radiologyViewModel.radiologyImageURL);
}, launchUrl(uri, mode: LaunchMode.platformDefault, webOnlyWindowName: "");
backgroundColor: AppColors.primaryRedColor, } else {
borderColor: AppColors.primaryRedColor, Utils.showToast("Radiology image not available");
textColor: Colors.white, }
fontSize: 16, },
fontWeight: FontWeight.w500, backgroundColor: AppColors.primaryRedColor,
borderRadius: 12, borderColor: AppColors.primaryRedColor,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), textColor: Colors.white,
height: 45.h, fontSize: 16,
icon: AppAssets.imageIcon, fontWeight: FontWeight.w500,
iconColor: Colors.white, borderRadius: 12,
iconSize: 20.h, padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
).paddingSymmetrical(24.h, 24.h) : SizedBox.shrink(), height: 56.h,
icon: AppAssets.imageIcon,
iconColor: Colors.white,
iconSize: 20.h,
).paddingSymmetrical(24.h, 0.h)
: SizedBox.shrink(),
Container(
height: 56.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.r),
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
stops: [0.236, 1.0], // 53.6% and 100%
colors: [
Color(0xFF8A38F5), // Transparent
Color(0xFFE20BBB), // Solid #F8F8F8
],
),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(right: 4.w, left: 4.w),
child: Utils.buildSvgWithAssets(icon: AppAssets.aiOverView, width: 16.h, height: 16.h, iconColor: Colors.white),
),
LocaleKeys.generateAiAnalysisResult.tr(context: context).toText16(isBold: true, color: Colors.white)
],
),
).paddingSymmetrical(24.h, 12.h).onPress(() {
// Need to implement the Radiology AI analysis result generation functionality here
Utils.showToast("Radiology AI analysis result generation functionality is not implemented yet");
}),
],
),
), ),
], ],
), ),

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
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/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
@ -29,6 +30,7 @@ class LiveCarePermissionService {
Permission.camera, Permission.camera,
Permission.microphone, Permission.microphone,
Permission.notification, Permission.notification,
if (Platform.isAndroid) Permission.systemAlertWindow,
]; ];
try { try {
@ -87,6 +89,7 @@ class LiveCarePermissionService {
if (permission == Permission.camera) return 'Camera'; if (permission == Permission.camera) return 'Camera';
if (permission == Permission.microphone) return 'Microphone'; if (permission == Permission.microphone) return 'Microphone';
if (permission == Permission.notification) return 'Notifications'; if (permission == Permission.notification) return 'Notifications';
if (permission == Permission.systemAlertWindow) return 'Display over other apps';
return permission.toString(); return permission.toString();
} }
} }

Loading…
Cancel
Save