diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart index d10434d..30f06cf 100644 --- a/lib/core/api_consts.dart +++ b/lib/core/api_consts.dart @@ -842,14 +842,9 @@ class ApiConsts { static final String allCMCOrdersRc = 'api/cmc/list'; static final String allCMCServicesRc = 'api/cmc/getallcmc'; static final String updateCMCOrder = 'api/cmc/update'; + static final String addCMCOrder = 'api/cmc/add'; static final String getHospitalsList = 'Services/Lists.svc/REST/GetProject'; - // CMC RC SERVICES - var GET_ALL_CMC_SERVICES_RC = 'api/cmc/getallcmc'; - var ADD_CMC_ORDER_RC = 'api/cmc/add'; - var GET_ALL_CMC_ORDERS_RC = 'api/cmc/list'; - var UPDATE_CMC_ORDER_RC = 'api/cmc/update'; - // ************ static values for Api **************** static final double appVersionID = 20.0; static final int appChannelId = 3; diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart index 6f1dcc6..e3b108f 100644 --- a/lib/core/utils/utils.dart +++ b/lib/core/utils/utils.dart @@ -102,8 +102,9 @@ class Utils { ? getMonthArabic(dateTime.month) + " " + dateTime.day.toString() + ", " + dateTime.year.toString() : getMonth(dateTime.month) + " " + dateTime.day.toString() + ", " + dateTime.year.toString(); } + static String getDayMonthYearDateFormatted(DateTime? dateTime) { - if(dateTime == null ) return ""; + if (dateTime == null) return ""; return appState.isArabic() ? "${dateTime.day.toString()} ${getMonthArabic(dateTime.month)}, ${dateTime.year.toString()}" : "${dateTime.day.toString()} ${getMonth(dateTime.month)}, ${dateTime.year.toString()}"; @@ -376,16 +377,21 @@ class Utils { ).center; } - static Widget getWarningWidget( - {String? loadingText, bool isShowActionButtons = false, Widget? bodyWidget, Function? onConfirmTap, Function? onCancelTap}) { + static Widget getWarningWidget({ + String? loadingText, + bool isShowActionButtons = false, + Widget? bodyWidget, + Function? onConfirmTap, + Function? onCancelTap, + }) { return Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Lottie.asset(AppAnimations.warningAnimation, - repeat: false, reverse: false, frameRate: FrameRate(60), width: 128.h, height: 128.h, fit: BoxFit.fill), + repeat: false, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill), SizedBox(height: 8.h), - (loadingText ?? LocaleKeys.loadingText.tr()).toText14(color: AppColors.blackColor, letterSpacing: 0), + (loadingText ?? LocaleKeys.loadingText.tr()).toText15(color: AppColors.blackColor, letterSpacing: 0), SizedBox(height: 16.h), bodyWidget ?? SizedBox.shrink(), SizedBox(height: 16.h), @@ -753,14 +759,15 @@ class Utils { ); } - static Widget getPaymentAmountWithSymbol2(num habibWalletAmount, - {double iconSize = 14, + static Widget getPaymentAmountWithSymbol2( + num habibWalletAmount, { + double iconSize = 14, double? fontSize, double? letterSpacing, FontWeight? fontWeight, Color iconColor = AppColors.textColor, - Color textColor = AppColors.blackColor, - bool isSaudiCurrency = true, + Color textColor = AppColors.blackColor, + bool isSaudiCurrency = true, bool isExpanded = true, }) { return RichText( @@ -777,7 +784,7 @@ class Utils { style: TextStyle( color: textColor, fontSize: fontSize ?? 32.f, - letterSpacing: letterSpacing??-4, + letterSpacing: letterSpacing ?? -4, fontWeight: fontWeight ?? FontWeight.w600, height: 1), ), @@ -839,7 +846,12 @@ class Utils { static PatientDoctorAppointmentList? convertToPatientDoctorAppointmentList(HospitalsModel? hospital) { if (hospital == null) return null; return PatientDoctorAppointmentList( - filterName: hospital.name, distanceInKMs: hospital.distanceInKilometers?.toString(), projectTopName: hospital.name, projectBottomName: hospital.name, model: hospital, isHMC: hospital.isHMC); + filterName: hospital.name, + distanceInKMs: hospital.distanceInKilometers?.toString(), + projectTopName: hospital.name, + projectBottomName: hospital.name, + model: hospital, + isHMC: hospital.isHMC); } static bool havePrivilege(int id) { @@ -853,7 +865,4 @@ class Utils { } return isHavePrivilege; } - - - } diff --git a/lib/features/hmg_services/hmg_services_repo.dart b/lib/features/hmg_services/hmg_services_repo.dart index 9264385..b9ad0a4 100644 --- a/lib/features/hmg_services/hmg_services_repo.dart +++ b/lib/features/hmg_services/hmg_services_repo.dart @@ -5,6 +5,7 @@ import 'package:hmg_patient_app_new/core/api/api_client.dart'; import 'package:hmg_patient_app_new/core/api_consts.dart'; import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart'; import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart'; +import 'package:hmg_patient_app_new/features/hmg_services/models/req_models/cmc_create_new_order_req_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/req_models/order_update_req_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get_cmc_all_orders_resp_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get_cmc_services_resp_model.dart'; @@ -19,6 +20,12 @@ abstract class HmgServicesRepo { Future>>> getAllCmcServices({required int patientID}); Future>>> getHospitalsList(); + + Future>> addCmcOrder({ + required int projectID, + required int orderServiceID, + required List services, + }); } class HmgServicesRepoImp implements HmgServicesRepo { @@ -240,4 +247,58 @@ class HmgServicesRepoImp implements HmgServicesRepo { return Left(UnknownFailure(e.toString())); } } + + @override + Future>> addCmcOrder({ + required int projectID, + required int orderServiceID, + required List services, + }) async { + try { + GenericApiModel? apiResponse; + Failure? failure; + + final requestBody = { + 'ProjectID': projectID, + 'OrderServiceID': orderServiceID, + 'procedures': services.map((service) => service.toJson()).toList(), + }; + + await apiClient.post( + ApiConsts.addCMCOrder, + isRCService: true, + body: requestBody, + onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + loggerService.logError("Add CMC Order API Failed: $error, Status: $statusCode"); + }, + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + int requestId = 0; + if (response is Map) { + requestId = response['response']; + } + try { + apiResponse = GenericApiModel( + messageStatus: messageStatus, + statusCode: statusCode, + errorMessage: errorMessage, + data: requestId, + ); + + loggerService.logInfo("CMC Order added successfully: ProjectID=$projectID, OrderServiceID=$orderServiceID"); + } catch (e) { + loggerService.logError("Error processing add CMC order response: ${e.toString()}"); + failure = DataParsingFailure(e.toString()); + } + }, + ); + + if (failure != null) return Left(failure!); + if (apiResponse == null) return Left(ServerFailure("Unknown error")); + return Right(apiResponse!); + } catch (e) { + loggerService.logError("Unknown error in addCmcOrder: ${e.toString()}"); + return Left(UnknownFailure(e.toString())); + } + } } diff --git a/lib/features/hmg_services/hmg_services_view_model.dart b/lib/features/hmg_services/hmg_services_view_model.dart index 19e7a1f..9c8003f 100644 --- a/lib/features/hmg_services/hmg_services_view_model.dart +++ b/lib/features/hmg_services/hmg_services_view_model.dart @@ -1,8 +1,7 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_repo.dart'; import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_repo.dart'; +import 'package:hmg_patient_app_new/features/hmg_services/models/req_models/cmc_create_new_order_req_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/req_models/order_update_req_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get_cmc_all_orders_resp_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get_cmc_services_resp_model.dart'; @@ -166,7 +165,6 @@ class HmgServicesViewModel extends ChangeNotifier { (apiResponse) { isHospitalListLoading = false; if (apiResponse.messageStatus == 1) { - log("apiResponse.messageStatus: ${apiResponse.data}"); hospitalsList = apiResponse.data ?? []; filteredHospitalsList = List.from(hospitalsList); notifyListeners(); @@ -224,4 +222,51 @@ class HmgServicesViewModel extends ChangeNotifier { } bool get isOrderReadyToConfirm => selectedHospitalForOrder != null && selectedServiceForOrder != null; + + Future addCmcOrder({ + required int projectID, + required int orderServiceID, + required List services, + Function(int)? onSuccess, + Function(String)? onError, + }) async { + isUpdatingOrder = true; + notifyListeners(); + + final result = await hmgServicesRepo.addCmcOrder( + projectID: projectID, + orderServiceID: orderServiceID, + services: services, + ); + + int requestId = 0; + + result.fold( + (failure) async { + isUpdatingOrder = false; + notifyListeners(); + await errorHandlerService.handleError(failure: failure); + if (onError != null) { + onError(failure.toString()); + } + }, + (apiResponse) { + isUpdatingOrder = false; + if (apiResponse.messageStatus == 1) { + requestId = apiResponse.data ?? 0; + notifyListeners(); + if (onSuccess != null) { + onSuccess(requestId); + } + } else { + notifyListeners(); + if (onError != null) { + onError(apiResponse.errorMessage ?? 'Unknown error'); + } + } + }, + ); + + return requestId; + } } diff --git a/lib/features/hmg_services/models/req_models/cmc_create_service_order_req_model.dart b/lib/features/hmg_services/models/req_models/cmc_create_service_order_req_model.dart new file mode 100644 index 0000000..af2808d --- /dev/null +++ b/lib/features/hmg_services/models/req_models/cmc_create_service_order_req_model.dart @@ -0,0 +1,41 @@ +class CmcCreateServiceOrderReqModel { + int? recordID; + String? serviceID; + String? selectedServiceName; + String? selectedServiceNameAR; + dynamic price; + dynamic vAT; + dynamic totalPrice; + + CmcCreateServiceOrderReqModel({ + this.recordID, + this.serviceID, + this.selectedServiceName, + this.selectedServiceNameAR, + this.price, + this.vAT, + this.totalPrice, + }); + + CmcCreateServiceOrderReqModel.fromJson(Map json) { + recordID = json['RecordID']; + serviceID = json['ServiceID']; + selectedServiceName = json['selectedServiceName']; + selectedServiceNameAR = json['selectedServiceNameAR']; + price = json['Price']; + vAT = json['VAT']; + totalPrice = json['TotalPrice']; + } + + Map toJson() { + final Map data = {}; + data['RecordID'] = recordID; + data['ServiceID'] = serviceID; + data['selectedServiceName'] = selectedServiceName; + data['selectedServiceNameAR'] = selectedServiceNameAR; + data['Price'] = price; + data['VAT'] = vAT; + data['TotalPrice'] = totalPrice; + return data; + } +} diff --git a/lib/presentation/comprehensive_checkup/cmc_order_detail_page.dart b/lib/presentation/comprehensive_checkup/cmc_order_detail_page.dart index 97e5e6d..6f17959 100644 --- a/lib/presentation/comprehensive_checkup/cmc_order_detail_page.dart +++ b/lib/presentation/comprehensive_checkup/cmc_order_detail_page.dart @@ -1,18 +1,25 @@ import 'dart:async'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:fluttertoast/fluttertoast.dart'; +import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; +import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; +import 'package:hmg_patient_app_new/core/utils/utils.dart'; +import 'package:hmg_patient_app_new/extensions/route_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/features/hmg_services/hmg_services_view_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/req_models/order_update_req_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get_cmc_all_orders_resp_model.dart'; -import 'package:hmg_patient_app_new/services/dialog_service.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/widgets/appbar/collapsing_list_view.dart'; -import 'package:intl/intl.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/common_bottom_sheet.dart'; +import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:provider/provider.dart'; -import 'package:shimmer/shimmer.dart'; class CmcOrderDetailPage extends StatefulWidget { const CmcOrderDetailPage({super.key}); @@ -22,8 +29,6 @@ class CmcOrderDetailPage extends StatefulWidget { } class _CmcOrderDetailPageState extends State { - bool _isLoading = false; - @override void initState() { super.initState(); @@ -54,75 +59,81 @@ class _CmcOrderDetailPageState extends State { if (dateString == null) return ''; try { final date = DateTime.parse(dateString); - return DateFormat('dd MMM yyyy').format(date); + return DateFormat('MMM dd, yyyy').format(date); } catch (e) { return dateString; } } - Future _showCancelConfirmationDialog({ - required BuildContext context, - required HmgServicesViewModel viewModel, - required GetCMCAllOrdersResponseModel order, - }) async { - final dialogService = context.read(); - - await dialogService.showCommonBottomSheetWithoutH( - label: "Confirm Cancellation".needTranslation, - message: "Are you sure you want to cancel this order?".needTranslation, - onOkPressed: () async { - Navigator.of(context).pop(); + void _showCancelConfirmationDialog({required GetCMCAllOrdersResponseModel order}) { + final HmgServicesViewModel hmgServicesViewModel = context.read(); - // Show loading state - setState(() { - _isLoading = true; - }); + return showCommonBottomSheetWithoutHeight( + title: LocaleKeys.notice.tr(context: context), + context, + child: Utils.getWarningWidget( + loadingText: "Are you sure you want to cancel this order?".needTranslation, + isShowActionButtons: true, + onCancelTap: () { + Navigator.pop(context); + }, + onConfirmTap: () async { + Navigator.pop(context); + LoaderBottomSheet.showLoader(); - final requestModel = OrderUpdateRequestModel( - presOrderID: order.iD, - rejectionReason: "", - presOrderStatus: 4, // Cancelled status - editedBy: 3, - ); + final requestModel = OrderUpdateRequestModel( + presOrderID: order.iD, + rejectionReason: "Cancelled by user", + presOrderStatus: 4, // Cancelled status + editedBy: 3, + ); - final success = await viewModel.updateCmcPresOrder( - requestModel: requestModel, - onSuccess: (_) async { - setState(() { - _isLoading = false; - }); - Fluttertoast.showToast( - msg: "Order cancelled successfully".needTranslation, - toastLength: Toast.LENGTH_SHORT, - gravity: ToastGravity.BOTTOM, - backgroundColor: Colors.green, - textColor: Colors.white, - ); - await viewModel.getAllCmcOrders(); - }, - onError: (error) { - setState(() { - _isLoading = false; - }); - Fluttertoast.showToast( - msg: error, - toastLength: Toast.LENGTH_SHORT, - gravity: ToastGravity.BOTTOM, - backgroundColor: Colors.red, - textColor: Colors.white, - ); - }, - ); + await hmgServicesViewModel.updateCmcPresOrder( + requestModel: requestModel, + onSuccess: (_) async { + LoaderBottomSheet.hideLoader(); - if (!success) { - setState(() { - _isLoading = false; - }); - } - }, - onCancelPressed: () { - Navigator.of(context).pop(); - }, + showCommonBottomSheetWithoutHeight( + context, + child: Padding( + padding: EdgeInsets.all(16.w), + child: Column( + children: [ + Utils.getSuccessWidget(loadingText: "Order has been cancelled successfully".needTranslation), + SizedBox(height: 24.h), + Row( + children: [ + Expanded( + child: CustomButton( + height: 56.h, + text: LocaleKeys.ok.tr(), + onPressed: () { + context.pop(); + context.pop(); + hmgServicesViewModel.getAllCmcOrders(); + }, + textColor: AppColors.whiteColor, + ), + ), + ], + ), + ], + ), + ), + isCloseButtonVisible: false, + isDismissible: false, + isFullScreen: false, + ); + }, + onError: (error) { + LoaderBottomSheet.hideLoader(); + }, + ); + }, + ), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, ); } @@ -130,158 +141,119 @@ class _CmcOrderDetailPageState extends State { return ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - padding: EdgeInsets.all(21.w), itemCount: 3, separatorBuilder: (_, __) => SizedBox(height: 12.h), itemBuilder: (context, index) { - return Shimmer.fromColors( - baseColor: Colors.grey[300]!, - highlightColor: Colors.grey[100]!, - child: Container( - height: 120.h, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(10.r), - ), - ), - ); + return _buildOrderCard(GetCMCAllOrdersResponseModel(), isLoading: true); }, ); } - Widget _buildOrderCard(GetCMCAllOrdersResponseModel order) { + Widget _buildOrderCard(GetCMCAllOrdersResponseModel order, {bool isLoading = false}) { final statusColor = _getStatusColor(order.statusId); final canCancel = order.statusId == 1 || order.statusId == 2; - return Container( - decoration: BoxDecoration( - color: statusColor, - borderRadius: BorderRadius.circular(10.r), - boxShadow: [ - BoxShadow( - color: const Color(0xff000000).withValues(alpha: 0.05), - blurRadius: 27, - offset: const Offset(0, -3), - ), - ], + return AnimatedContainer( + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.h, + hasShadow: true, ), - child: Container( - margin: EdgeInsets.only(left: 6.w), - padding: EdgeInsets.symmetric(vertical: 14.h, horizontal: 12.w), - decoration: BoxDecoration( - color: Colors.white, - border: Border.all(color: Colors.white, width: 1), - borderRadius: BorderRadius.only( - bottomRight: Radius.circular(10.r), - topRight: Radius.circular(10.r), - ), - ), - child: Row( + child: Padding( + padding: EdgeInsets.all(16.w), + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - order.statusText ?? '', - style: TextStyle( - fontSize: 12.f, - fontWeight: FontWeight.w600, - color: statusColor, - letterSpacing: -0.4, - height: 16 / 10, - ), - ), - SizedBox(height: 6.h), - Text( - '${"Request ID".needTranslation}: ${order.iD}', - style: TextStyle( - fontSize: 16.f, - fontWeight: FontWeight.w600, - color: const Color(0xff2E303A), - letterSpacing: -0.64, - height: 25 / 16, - ), - ), - SizedBox(height: 4.h), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "${"Hospital".needTranslation}: ", - style: TextStyle( - fontSize: 12.f, - fontWeight: FontWeight.w600, - color: const Color(0xff575757), - letterSpacing: -0.4, - height: 16 / 10, - ), - ), - Expanded( - child: Text( - order.projectName?.trim() ?? '', - style: TextStyle( - fontSize: 14.f, - fontWeight: FontWeight.w600, - color: const Color(0xff2B353E), - letterSpacing: -0.56, - ), - ), - ), - ], - ), - ], - ), - ), - Column( + // Status and Date Row + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - _formatDate(order.created), - style: TextStyle( - fontSize: 12.f, - fontWeight: FontWeight.w600, - color: const Color(0xff2B353E), - letterSpacing: -0.4, - height: 16 / 10, + Container( + padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h), + decoration: BoxDecoration( + color: statusColor.withValues(alpha: 0.1), + borderRadius: BorderRadius.circular(8.r), ), + child: (isLoading ? "Processing" : order.statusText ?? '') + .toText12( + color: statusColor, + fontWeight: FontWeight.w600, + ) + .toShimmer2(isShow: isLoading), ), - if (canCancel) ...[ - SizedBox(height: 12.h), - InkWell( - onTap: _isLoading - ? null - : () { - _showCancelConfirmationDialog( - context: context, - viewModel: context.read(), - order: order, - ); - }, - child: Container( - padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 14.w), - decoration: BoxDecoration( - color: _isLoading ? Colors.grey : const Color(0xffD02127), - border: Border.all(color: Colors.white, width: 1), - borderRadius: BorderRadius.circular(10.r), - ), - child: Text( - "Cancel".needTranslation, - style: TextStyle( - fontSize: 12.f, - fontWeight: FontWeight.w600, - color: Colors.white, - letterSpacing: -0.4, - ), + SizedBox(width: 8.w), + (isLoading ? "Jan 15, 2024" : _formatDate(order.created)) + .toText12( + color: AppColors.textColorLight, + fontWeight: FontWeight.w500, + ) + .toShimmer2(isShow: isLoading), + ], + ), + + SizedBox(height: 16.h), + + // Request ID + Row( + children: [ + if (!isLoading) ...[ + "Request ID:".needTranslation.toText14( + color: AppColors.textColorLight, + weight: FontWeight.w500, ), - ), - ), + SizedBox(width: 4.w), ], + (isLoading ? "12345" : "${order.iD ?? '-'}").toText16(isBold: true).toShimmer2(isShow: isLoading), ], ), + + SizedBox(height: 12.h), + + // Chips for Hospital, Service, and Amount + Wrap( + spacing: 6.w, + runSpacing: 6.h, + children: [ + // Hospital + if (order.projectName != null || isLoading) + AppCustomChipWidget( + icon: AppAssets.hospital, + labelText: isLoading ? "Hospital Name" : order.projectName ?? '-', + ).toShimmer2(isShow: isLoading), + + // Service + if (order.serviceText != null || isLoading) + AppCustomChipWidget( + icon: AppAssets.servicesBottom, + labelText: isLoading ? "Service Name" : order.serviceText ?? '-', + ).toShimmer2(isShow: isLoading), + ], + ), + + // Cancel Button + if (canCancel || isLoading) ...[ + SizedBox(height: 16.h), + Row( + children: [ + Expanded( + child: CustomButton( + text: "Cancel Order".needTranslation, + onPressed: isLoading ? () {} : () => _showCancelConfirmationDialog(order: order), + backgroundColor: AppColors.primaryRedColor, + borderColor: AppColors.primaryRedColor, + textColor: AppColors.whiteColor, + fontSize: 14.f, + fontWeight: FontWeight.w600, + borderRadius: 10.r, + height: 44.h, + ).toShimmer2(isShow: isLoading), + ), + ], + ), + ] ], ), ), @@ -290,20 +262,22 @@ class _CmcOrderDetailPageState extends State { Widget _buildEmptyState() { return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(Icons.inbox_outlined, size: 80.w, color: AppColors.greyColor), - SizedBox(height: 16.h), - Text( - "No orders found".needTranslation, - style: TextStyle( - fontSize: 16.f, - color: AppColors.greyTextColor, - fontWeight: FontWeight.w500, - ), + child: Padding( + padding: EdgeInsets.symmetric(vertical: 40.h), + child: Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 12.r, + hasShadow: false, ), - ], + child: Utils.getNoDataWidget( + context, + noDataText: "You don't have any CMC orders yet.".needTranslation, + isSmallWidget: true, + width: 62.w, + height: 62.h, + ), + ), ), ); } @@ -313,31 +287,44 @@ class _CmcOrderDetailPageState extends State { return CollapsingListView( title: "CMC Orders".needTranslation, isLeading: true, - child: Consumer( - builder: (context, viewModel, child) { - if (viewModel.isCmcOrdersLoading) { - return _buildLoadingShimmer(); - } + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Consumer( + builder: (context, viewModel, child) { + if (viewModel.isCmcOrdersLoading) { + return _buildLoadingShimmer(); + } - if (viewModel.cmcOrdersList.isEmpty) { - return SizedBox( - height: MediaQuery.of(context).size.height * 0.6, - child: _buildEmptyState(), - ); - } + if (viewModel.cmcOrdersList.isEmpty) { + return _buildEmptyState(); + } - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - padding: EdgeInsets.all(21.w), - itemCount: viewModel.cmcOrdersList.length, - separatorBuilder: (_, __) => SizedBox(height: 12.h), - itemBuilder: (context, index) { - final order = viewModel.cmcOrdersList.reversed.toList()[index]; - return _buildOrderCard(order); - }, - ); - }, + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: viewModel.cmcOrdersList.length, + separatorBuilder: (_, __) => SizedBox(height: 12.h), + itemBuilder: (context, index) { + final order = viewModel.cmcOrdersList.reversed.toList()[index]; + + return AnimationConfiguration.staggeredList( + position: index, + duration: const Duration(milliseconds: 500), + child: SlideAnimation( + verticalOffset: 100.0, + child: FadeInAnimation( + child: _buildOrderCard(order), + ), + ), + ); + }, + ); + }, + ), + ], + ).paddingSymmetrical(24.w, 0), ), ); } diff --git a/lib/presentation/comprehensive_checkup/cmc_selection_review_page.dart b/lib/presentation/comprehensive_checkup/cmc_selection_review_page.dart index 1186e2f..9fb8f17 100644 --- a/lib/presentation/comprehensive_checkup/cmc_selection_review_page.dart +++ b/lib/presentation/comprehensive_checkup/cmc_selection_review_page.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; @@ -8,12 +9,16 @@ 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/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_view_model.dart'; +import 'package:hmg_patient_app_new/features/hmg_services/models/req_models/cmc_create_new_order_req_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get_cmc_services_resp_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/comprehensive_checkup/widgets/cmc_hospital_selection_helper.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/buttons/custom_button.dart'; +import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; +import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:maps_launcher/maps_launcher.dart'; import 'package:provider/provider.dart'; @@ -308,7 +313,7 @@ class _CmcSelectionReviewPageState extends State { child: CustomButton( text: "Confirm".needTranslation, onPressed: () { - isLocationSelected ? _handleConfirm : null; + isLocationSelected ? _handleConfirm() : null; }, textColor: AppColors.whiteColor, backgroundColor: isLocationSelected ? AppColors.successColor : AppColors.greyColor, @@ -340,6 +345,50 @@ class _CmcSelectionReviewPageState extends State { } } + showSuccessBottomSheet(int requestId, HmgServicesViewModel hmgServicesViewModel) { + return showCommonBottomSheetWithoutHeight( + context, + child: Padding( + padding: EdgeInsets.all(16.w), + child: Column( + children: [ + Utils.getSuccessWidget(loadingText: "Your request has been successfully submitted.".needTranslation), + Row( + children: [ + "Here is your request #: ".needTranslation.toText14( + color: AppColors.textColorLight, + weight: FontWeight.w500, + ), + SizedBox(width: 4.w), + ("$requestId").toText16(isBold: true), + ], + ), + SizedBox(height: 24.h), + Row( + children: [ + Expanded( + child: CustomButton( + height: 56.h, + text: LocaleKeys.ok.tr(), + onPressed: () { + context.pop(); + context.pop(); + hmgServicesViewModel.getAllCmcOrders(); + }, + textColor: AppColors.whiteColor, + ), + ), + ], + ), + ], + ), + ), + isCloseButtonVisible: false, + isDismissible: false, + isFullScreen: false, + ); + } + void _handleConfirm() { final hmgServicesViewModel = context.read(); final selectedHospital = hmgServicesViewModel.selectedHospitalForOrder; @@ -354,27 +403,50 @@ class _CmcSelectionReviewPageState extends State { return; } - // TODO: Implement order creation API call - // Create CMC order with: - // - hmgServicesViewModel.selectedServiceForOrder (the medical checkup service) - // - hmgServicesViewModel.selectedHospitalForOrder (the chosen hospital) - // - Call hmgServicesViewModel.createCmcOrder() or similar method + final selectedService = widget.selectedService; + return showCommonBottomSheetWithoutHeight( + title: LocaleKeys.notice.tr(context: context), + context, + child: Utils.getWarningWidget( + loadingText: "Are you sure you want to submit this request?".needTranslation, + isShowActionButtons: true, + onCancelTap: () { + Navigator.pop(context); + }, + onConfirmTap: () async { + Navigator.pop(context); + LoaderBottomSheet.showLoader(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - "Order confirmed! Service: ${widget.selectedService.text}, Hospital: ${selectedHospital.name}", - ), - backgroundColor: AppColors.successColor, - ), - ); + // Create the services list + final servicesList = [ + PatientERCMCInsertServicesList( + recordID: selectedService.iD, + serviceID: selectedService.serviceID, + selectedServiceName: selectedService.text, + selectedServiceNameAR: selectedService.textN, + price: selectedService.price, + vAT: selectedService.priceVAT, + totalPrice: selectedService.priceTotal, + ), + ]; - // Navigate back after confirmation - Future.delayed(Duration(seconds: 2), () { - Navigator.of(context).pop(); - Navigator.of(context).pop(); - // Clear order selection after successful confirmation - hmgServicesViewModel.clearOrderSelection(); - }); + await hmgServicesViewModel.addCmcOrder( + projectID: selectedHospital.mainProjectID ?? 0, + orderServiceID: selectedService.orderServiceID ?? 3, + services: servicesList, + onSuccess: (requestId) { + LoaderBottomSheet.hideLoader(); + showSuccessBottomSheet(requestId, hmgServicesViewModel); + }, + onError: (err) { + LoaderBottomSheet.hideLoader(); + // showCommonBottomSheetWithoutHeight(context, child: Utils.getErrorWidget(loadingText: err), callBackFunc: () {}); + }, + ); + }), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); } } diff --git a/lib/presentation/comprehensive_checkup/comprehensive_checkup_page.dart b/lib/presentation/comprehensive_checkup/comprehensive_checkup_page.dart index 699152c..0776221 100644 --- a/lib/presentation/comprehensive_checkup/comprehensive_checkup_page.dart +++ b/lib/presentation/comprehensive_checkup/comprehensive_checkup_page.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; @@ -17,6 +18,7 @@ import 'package:hmg_patient_app_new/presentation/comprehensive_checkup/widgets/c 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/buttons/custom_button.dart'; +import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/media_viewer/full_screen_image_viewer.dart'; import 'package:hmg_patient_app_new/widgets/radio_list_tile_widget.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; @@ -69,120 +71,120 @@ class _ComprehensiveCheckupPageState extends State { if (status == 1) { // pending - statusColor = const Color(0xffCC9B14); + statusColor = AppColors.statusPendingColor; } else if (status == 2) { // processing - statusColor = const Color(0xff2E303A); + statusColor = AppColors.statusProcessingColor; } else if (status == 3) { // completed - statusColor = const Color(0xff359846); + statusColor = AppColors.statusCompletedColor; } else { // cancel / rejected - statusColor = const Color(0xffD02127); + statusColor = AppColors.statusRejectedColor; } return Container( width: double.infinity, - margin: EdgeInsets.all(16.h), - decoration: BoxDecoration( + margin: EdgeInsets.all(16.w), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor, - borderRadius: BorderRadius.circular(12.h), - boxShadow: [ - BoxShadow( - color: Color.fromARGB(13, 0, 0, 0), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ], + borderRadius: 24.h, + hasShadow: true, ), - child: Container( - padding: EdgeInsets.all(14.h), + child: Padding( + padding: EdgeInsets.all(16.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + // Status and Date Row Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - statusDisp, - style: TextStyle( - fontSize: 12.h, - fontWeight: FontWeight.w600, - color: statusColor, - letterSpacing: -0.4, - ), - ), - SizedBox(height: 6.h), - Text( - '${"Request ID".needTranslation}: ${order.iD}', - style: TextStyle( - fontSize: 16.h, - fontWeight: FontWeight.w600, - color: AppColors.blackColor, - letterSpacing: -0.64, - ), - ), - SizedBox(height: 4.h), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "${"Hospital".needTranslation}: ", - style: TextStyle( - fontSize: 12.h, - fontWeight: FontWeight.w600, - color: AppColors.greyTextColor, - letterSpacing: -0.4, - ), - ), - Expanded( - child: Text( - order.projectName ?? "", - style: TextStyle( - fontSize: 14.h, - fontWeight: FontWeight.w600, - color: const Color(0xff2B353E), - letterSpacing: -0.56, - ), - ), - ), - ], - ), - SizedBox(height: 4.h), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "${"Service Name".needTranslation}: ", - style: TextStyle( - fontSize: 12.h, - fontWeight: FontWeight.w600, - color: AppColors.greyTextColor, - letterSpacing: -0.4, - ), - ), - Expanded( - child: Text( - order.serviceText ?? "", - style: TextStyle( - fontSize: 14.h, - fontWeight: FontWeight.w600, - color: const Color(0xff2B353E), - letterSpacing: -0.56, - ), - ), - ), - ], - ), - ], + Container( + padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h), + decoration: BoxDecoration( + color: statusColor.withValues(alpha: 0.1), + borderRadius: BorderRadius.circular(8.r), + ), + child: statusDisp.toText12( + color: statusColor, + fontWeight: FontWeight.w600, ), ), + SizedBox(width: 8.w), + if (order.created != null) + DateFormat('MMM dd, yyyy').format(DateTime.parse(order.created!)).toText12( + color: AppColors.textColorLight, + fontWeight: FontWeight.w500, + ), + ], + ), + + SizedBox(height: 16.h), + + // Request ID + Row( + children: [ + "Request ID:".needTranslation.toText14(color: AppColors.textColorLight, weight: FontWeight.w500), + SizedBox(width: 4.w), + "${order.iD ?? '-'}".toText16(isBold: true), ], ), + + SizedBox(height: 12.h), + + // Chips for Hospital, Service, and Amount + Wrap( + spacing: 6.w, + runSpacing: 6.h, + children: [ + // Hospital + if (order.projectName != null) + AppCustomChipWidget( + icon: AppAssets.hospital, + labelText: order.projectName ?? '-', + ), + + // Service + if (order.serviceText != null) + AppCustomChipWidget( + icon: AppAssets.file_icon, + labelText: order.serviceText ?? '-', + ), + ], + ), + + SizedBox(height: 16.h), + + // Info message + Container( + padding: EdgeInsets.all(12.w), + decoration: BoxDecoration( + color: AppColors.infoBannerBgColor, + borderRadius: BorderRadius.circular(10.r), + border: Border.all( + color: AppColors.infoBannerBorderColor, + width: 1, + ), + ), + child: Row( + children: [ + Icon( + Icons.info_outline, + size: 20.w, + color: AppColors.infoBannerIconColor, + ), + SizedBox(width: 8.w), + Expanded( + child: "You have a pending order. Please wait for it to be processed.".needTranslation.toText12( + color: AppColors.infoBannerTextColor, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), ], ), ), @@ -315,15 +317,15 @@ class _ComprehensiveCheckupPageState extends State { return ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - padding: EdgeInsets.all(21.w), - itemCount: 3, + padding: EdgeInsets.all(16.w), + itemCount: 10, separatorBuilder: (_, __) => SizedBox(height: 12.h), itemBuilder: (context, index) { return Shimmer.fromColors( baseColor: Colors.grey[300]!, highlightColor: Colors.grey[100]!, child: Container( - height: 120.h, + height: 80.h, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10.r), diff --git a/lib/presentation/comprehensive_checkup/old_cmc_page.dart b/lib/presentation/comprehensive_checkup/old_cmc_page.dart deleted file mode 100644 index b1a6f69..0000000 --- a/lib/presentation/comprehensive_checkup/old_cmc_page.dart +++ /dev/null @@ -1,427 +0,0 @@ -// import 'dart:async'; -// -// import 'package:hmg_patient_app/core/enum/viewstate.dart'; -// import 'package:hmg_patient_app/core/model/AlHabibMedicalService/ComprehensiveMedicalCheckup/cmc_insert_pres_order_request_model.dart'; -// import 'package:hmg_patient_app/core/model/ImagesInfo.dart'; -// import 'package:hmg_patient_app/core/model/hospitals/hospitals_model.dart'; -// import 'package:hmg_patient_app/core/viewModels/AlHabibMedicalService/cmc_view_model.dart'; -// import 'package:hmg_patient_app/core/viewModels/project_view_model.dart'; -// import 'package:hmg_patient_app/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/Dialog/confirm_dialog.dart'; -// import 'package:hmg_patient_app/services/clinic_services/get_clinic_service.dart'; -// import 'package:hmg_patient_app/theme/colors.dart'; -// import 'package:hmg_patient_app/uitl/app_toast.dart'; -// import 'package:hmg_patient_app/uitl/gif_loader_dialog_utils.dart'; -// import 'package:hmg_patient_app/uitl/translations_delegate_base.dart'; -// import 'package:hmg_patient_app/uitl/utils.dart'; -// import 'package:hmg_patient_app/uitl/utils_new.dart'; -// import 'package:hmg_patient_app/widgets/buttons/defaultButton.dart'; -// import 'package:hmg_patient_app/widgets/others/app_scaffold_widget.dart'; -// import 'package:flutter/cupertino.dart'; -// import 'package:flutter/material.dart'; -// import 'package:flutter_svg/flutter_svg.dart'; -// import 'package:google_maps_flutter/google_maps_flutter.dart'; -// import 'package:maps_launcher/maps_launcher.dart'; -// import 'package:provider/provider.dart'; -// -// class NewCMCStepThreePage extends StatefulWidget { -// final CMCInsertPresOrderRequestModel cmcInsertPresOrderRequestModel; -// final CMCViewModel model; -// -// NewCMCStepThreePage( -// {Key? key, -// required this.model, -// required this.cmcInsertPresOrderRequestModel}); -// -// @override -// _NewCMCStepThreePageState createState() => _NewCMCStepThreePageState(); -// } -// -// class _NewCMCStepThreePageState extends State { -// Completer _controller = Completer(); -// -// String? projectDropdownValue; -// late List projectsList = []; -// HospitalsModel? selectedHospital; -// final GlobalKey projectDropdownKey = GlobalKey(); -// bool isLocationSelected = false; -// ProjectViewModel? projectViewModel; -// -// static CameraPosition _kGooglePlex = CameraPosition( -// target: LatLng(37.42796133580664, -122.085749655962), -// zoom: 14.4746, -// ); -// final Set markers = new Set(); -// -// @override -// void initState() { -// if (widget.cmcInsertPresOrderRequestModel.latitude != null) { -// markers.clear(); -// markers.add( -// Marker( -// markerId: MarkerId( -// widget.cmcInsertPresOrderRequestModel.latitude.hashCode -// .toString(), -// ), -// position: LatLng(widget.cmcInsertPresOrderRequestModel.latitude!, -// widget.cmcInsertPresOrderRequestModel.longitude!)), -// ); -// _kGooglePlex = CameraPosition( -// target: LatLng(widget.cmcInsertPresOrderRequestModel.latitude!, -// widget.cmcInsertPresOrderRequestModel.longitude!), -// zoom: 14.4746, -// ); -// } -// WidgetsBinding.instance.addPostFrameCallback((_) { -// // if (projectViewModel.isLogin) { -// getProjectsList(); -// // } -// }); -// super.initState(); -// } -// -// @override -// Widget build(BuildContext context) { -// projectViewModel = Provider.of(context); -// return AppScaffold( -// isShowAppBar: true, -// description: TranslationBase.of(context).infoCMC, -// imagesInfo: [ -// ImagesInfo( -// imageAr: 'https://hmgwebservices.com/Images/MobileApp/CMC/ar/0.png', -// imageEn: -// 'https://hmgwebservices.com/Images/MobileApp/CMC/en/0.png'), -// ], -// appBarTitle: TranslationBase.of(context).comprehensiveMedicalCheckup, -// showNewAppBar: true, -// showNewAppBarTitle: true, -// backgroundColor: CustomColors.appBackgroudGreyColor, -// baseViewModel: widget.model, -// body: SingleChildScrollView( -// physics: BouncingScrollPhysics(), -// child: Container( -// height: 500, -// width: double.maxFinite, -// margin: EdgeInsets.only(left: 12, right: 12), -// child: Column( -// crossAxisAlignment: CrossAxisAlignment.start, -// children: [ -// SizedBox( -// height: 12, -// ), -// Text( -// TranslationBase.of(context).orderSummary, -// style: TextStyle( -// fontSize: 16, -// fontWeight: FontWeight.bold, -// letterSpacing: -0.46, -// ), -// ), -// SizedBox( -// height: 12, -// ), -// Container( -// decoration: cardRadius(12), -// child: Container( -// padding: EdgeInsets.all(8), -// child: Column( -// crossAxisAlignment: CrossAxisAlignment.start, -// children: [ -// Container( -// width: double.infinity, -// decoration: containerRadius(Colors.white, 12), -// margin: EdgeInsets.only(top: 12), -// padding: EdgeInsets.only( -// left: 0, right: 0, top: 0, bottom: 12), -// child: Row( -// children: [ -// Flexible( -// child: Column( -// crossAxisAlignment: CrossAxisAlignment.start, -// children: [ -// Text( -// TranslationBase.of(context).selectLocation, -// style: TextStyle( -// fontSize: 11, -// letterSpacing: -0.44, -// fontWeight: FontWeight.w600, -// ), -// ), -// Container( -// height: 18, -// child: DropdownButtonHideUnderline( -// child: DropdownButton( -// key: projectDropdownKey, -// hint: new Text( -// TranslationBase.of(context) -// .selectHospital), -// value: selectedHospital, -// iconSize: 0, -// isExpanded: true, -// style: TextStyle( -// fontSize: 14, -// letterSpacing: -0.56, -// color: Colors.black), -// items: projectsList.map((item) { -// return new DropdownMenuItem< -// HospitalsModel>( -// value: item, -// child: new Text(item.name!), -// ); -// }).toList(), -// onChanged: -// (HospitalsModel? newValue) async { -// setState(() { -// selectedHospital = newValue!; -// projectDropdownValue = newValue -// .mainProjectID -// .toString(); -// isLocationSelected = true; -// widget.cmcInsertPresOrderRequestModel -// .projectID = -// newValue.mainProjectID; -// // getDoctorsList(context); -// }); -// }, -// ), -// ), -// ), -// ], -// ), -// ), -// Icon(Icons.keyboard_arrow_down), -// ], -// ), -// ), -// SizedBox( -// height: 6, -// ), -// isLocationSelected -// ? Padding( -// padding: const EdgeInsets.all(8.0), -// child: Stack( -// children: [ -// Container( -// height: 200, -// decoration: containerColorRadiusBorder( -// Colors.white, 12, Colors.grey), -// clipBehavior: Clip.antiAlias, -// child: Container( -// decoration: cardRadius(12), -// clipBehavior: Clip.antiAlias, -// margin: const EdgeInsets.all(0), -// child: Image.network( -// "https://maps.googleapis.com/maps/api/staticmap?center=" + -// selectedHospital!.latitude -// .toString() + -// "," + -// selectedHospital!.longitude -// .toString() + -// "&zoom=16&size=600x300&maptype=roadmap&markers=color:red%7C" + -// selectedHospital!.latitude -// .toString() + -// "," + -// selectedHospital!.longitude -// .toString() + -// "&key=AIzaSyCyDbWUM9d_sBUGIE8PcuShzPaqO08NSC8", -// width: double.infinity, -// height: double.infinity, -// fit: BoxFit.cover, -// ), -// ), -// ), -// Row( -// mainAxisAlignment: MainAxisAlignment.end, -// crossAxisAlignment: CrossAxisAlignment.end, -// children: [ -// InkWell( -// onTap: () { -// getDirections(); -// }, -// child: Container( -// decoration: cardRadius(1000), -// margin: EdgeInsets.all(12), -// child: Padding( -// padding: const EdgeInsets.only( -// left: 12, -// right: 12, -// top: 6, -// bottom: 6), -// child: Row( -// children: [ -// Padding( -// padding: -// const EdgeInsets.all(3.0), -// child: SvgPicture.asset( -// "assets/images/new/direction.svg", -// width: 13, -// height: 13, -// ), -// ), -// mWidth(6), -// Text( -// TranslationBase.of(context) -// .getDirections, -// style: TextStyle( -// color: Colors.black, -// fontSize: 11, -// letterSpacing: -0.44, -// fontWeight: FontWeight.w600, -// ), -// ) -// ], -// ), -// ), -// ), -// ), -// ], -// ), -// ], -// ), -// ) -// : Container(), -// SizedBox( -// height: 12, -// ), -// Text( -// TranslationBase.of(context).selectedService, -// style: TextStyle( -// fontSize: 14, -// fontWeight: FontWeight.bold, -// letterSpacing: -0.46, -// color: CustomColors.grey, -// ), -// ), -// ...List.generate( -// widget.cmcInsertPresOrderRequestModel -// .patientERCMCInsertServicesList!.length, -// (index) => Container( -// child: Column( -// crossAxisAlignment: CrossAxisAlignment.start, -// children: [ -// Text( -// projectViewModel!.isArabic -// ? widget -// .cmcInsertPresOrderRequestModel -// .patientERCMCInsertServicesList![index] -// .selectedServiceNameAR! -// : widget -// .cmcInsertPresOrderRequestModel -// .patientERCMCInsertServicesList![index] -// .selectedServiceName!, -// style: TextStyle( -// fontSize: 12, -// fontWeight: FontWeight.bold, -// letterSpacing: -0.46, -// ), -// ), -// ], -// ), -// ), -// ) -// ], -// ), -// ), -// ) -// ], -// ), -// ), -// ), -// bottomSheet: Container( -// height: MediaQuery.of(context).size.height * 0.10, -// width: double.infinity, -// color: Colors.white, -// child: Column( -// mainAxisAlignment: MainAxisAlignment.center, -// children: [ -// Container( -// width: MediaQuery.of(context).size.width * 0.9, -// child: DefaultButton( -// TranslationBase.of(context).confirm, -// !isLocationSelected -// ? null -// : () async { -// GifLoaderDialogUtils.showMyDialog(context); -// String requestId = await widget.model.insertCMCOrderRC( -// order: widget.cmcInsertPresOrderRequestModel); -// GifLoaderDialogUtils.hideDialog(context); -// if (widget.model.state != ViewState.ErrorLocal) { -// showCMCConfirmDialog( -// context, -// requestId, -// onClick: () { -// Navigator.pop(context); -// Navigator.pop(context); -// }, -// ); -// } else { -// AppToast.showErrorToast(message: widget.model.error); -// } -// }, -// color: CustomColors.green, -// disabledColor: CustomColors.grey, -// ), -// // SecondaryButton( -// // label: TranslationBase.of(context).confirm, -// // color: CustomColors.green, -// // onTap: () async { -// // if(isLocationSelected) { -// // GifLoaderDialogUtils.showMyDialog(context); -// // String requestId = await widget.model.insertCMCOrderRC(order: widget.cmcInsertPresOrderRequestModel); -// // GifLoaderDialogUtils.hideDialog(context); -// // if (widget.model.state != ViewState.ErrorLocal) { -// // showCMCConfirmDialog( -// // context, -// // requestId, -// // onClick: () { -// // Navigator.pop(context); -// // Navigator.pop(context); -// // }, -// // ); -// // } else { -// // AppToast.showErrorToast(message: widget.model.error); -// // } -// // } else { -// // Utils.showErrorToast("Please select hospital from the dropdown menu to continue"); -// // } -// // }, -// // textColor: Theme.of(context).backgroundColor), -// ), -// ], -// ), -// ), -// ); -// } -// -// getDirections() { -// if (isLocationSelected) { -// MapsLauncher.launchCoordinates(double.parse(selectedHospital!.latitude!), -// double.parse(selectedHospital!.longitude!), selectedHospital!.name); -// } else { -// Utils.showErrorToast( -// "Please select address from the dropdown menu to get directions"); -// } -// } -// -// getProjectsList() { -// int languageID = projectViewModel!.isArabic ? 1 : 2; -// ClinicListService service = new ClinicListService(); -// GifLoaderDialogUtils.showMyDialog(context); -// List projectsListLocal = []; -// service.getProjectsList(languageID, context).then((res) { -// if (res['MessageStatus'] == 1) { -// setState(() { -// res['ListProject'].forEach((v) { -// projectsListLocal.add(new HospitalsModel.fromJson(v)); -// }); -// projectsList = projectsListLocal; -// }); -// } -// GifLoaderDialogUtils.hideDialog(context); -// }).catchError((err) { -// GifLoaderDialogUtils.hideDialog(context); -// }).catchError((err) { -// GifLoaderDialogUtils.hideDialog(context); -// print(err); -// }); -// } -// } diff --git a/lib/presentation/comprehensive_checkup/old_detail_page.dart b/lib/presentation/comprehensive_checkup/old_detail_page.dart deleted file mode 100644 index 27070fe..0000000 --- a/lib/presentation/comprehensive_checkup/old_detail_page.dart +++ /dev/null @@ -1,183 +0,0 @@ -// import 'package:hmg_patient_app/core/enum/viewstate.dart'; -// import 'package:hmg_patient_app/core/model/AlHabibMedicalService/ComprehensiveMedicalCheckup/GetCMCAllOrdersResponseModel.dart'; -// import 'package:hmg_patient_app/core/model/AlHabibMedicalService/HomeHealthCare/get_hhc_all_pres_orders_response_model.dart'; -// import 'package:hmg_patient_app/core/model/AlHabibMedicalService/HomeHealthCare/update_pres_oreder_request_model.dart'; -// import 'package:hmg_patient_app/core/viewModels/AlHabibMedicalService/cmc_view_model.dart'; -// import 'package:hmg_patient_app/core/viewModels/project_view_model.dart'; -// import 'package:hmg_patient_app/uitl/app_toast.dart'; -// import 'package:hmg_patient_app/uitl/date_uitl.dart'; -// import 'package:hmg_patient_app/uitl/gif_loader_dialog_utils.dart'; -// import 'package:hmg_patient_app/uitl/translations_delegate_base.dart'; -// import 'package:hmg_patient_app/uitl/utils.dart'; -// import 'package:hmg_patient_app/uitl/utils_new.dart'; -// import 'package:hmg_patient_app/widgets/buttons/defaultButton.dart'; -// import 'package:hmg_patient_app/widgets/buttons/secondary_button.dart'; -// import 'package:hmg_patient_app/widgets/data_display/text.dart'; -// import 'package:hmg_patient_app/widgets/dialogs/ConfirmWithMessageDialog.dart'; -// import 'package:hmg_patient_app/widgets/others/app_scaffold_widget.dart'; -// import 'package:flutter/material.dart'; -// import 'package:provider/provider.dart'; -// -// import 'Dialog/confirm_cancel_order_dialog.dart'; -// -// class OrdersLogDetailsPage extends StatelessWidget { -// final CMCViewModel model; -// -// const OrdersLogDetailsPage({Key ?key, required this.model}) : super(key: key); -// -// @override -// Widget build(BuildContext context) { -// ProjectViewModel projectViewModel = Provider.of(context); -// -// void showConfirmMessage(CMCViewModel model, GetCMCAllOrdersResponseModel order) { -// showDialog( -// context: context, -// builder: (cxt) => ConfirmWithMessageDialog( -// message: TranslationBase.of(context).cancelOrderMsg, -// onTap: () { -// UpdatePresOrderRequestModel updatePresOrderRequestModel = UpdatePresOrderRequestModel(presOrderID: order.iD, rejectionReason: "", presOrderStatus: 4, editedBy: 3); -// Future.delayed(new Duration(milliseconds: 300)).then((value) async { -// GifLoaderDialogUtils.showMyDialog(context); -// await model.updateCmcPresOrder(updatePresOrderRequestModel); -// if (model.state == ViewState.ErrorLocal) { -// Utils.showErrorToast(model.error); -// GifLoaderDialogUtils.hideDialog(context); -// } else { -// AppToast.showSuccessToast(message: TranslationBase.of(context).processDoneSuccessfully); -// await model.getCmcAllPresOrders(); -// GifLoaderDialogUtils.hideDialog(context); -// } -// }); -// }, -// )); -// return; -// } -// -// return AppScaffold( -// isShowAppBar: false, -// baseViewModel: model, -// body: model.cmcAllPresOrders.length > 0 ? ListView.separated( -// padding: EdgeInsets.all(21), -// physics: BouncingScrollPhysics(), -// itemBuilder: (context, index) { -// GetCMCAllOrdersResponseModel order = model.cmcAllPresOrders.reversed.toList()[index]; -// -// int status = order.statusId!; -// String _statusDisp = order.statusText!; -// late Color _color; -// if (status == 1) { -// //pending -// _color = Color(0xffCC9B14); -// } else if (status == 2) { -// //processing -// _color = Color(0xff2E303A); -// } else if (status == 3) { -// //completed -// _color = Color(0xff359846); -// } else if (status == 4 || status == 6 || status == 7) { -// //cancel // Rejected -// _color = Color(0xffD02127); -// } -// return Container( -// decoration: BoxDecoration( -// color: _color, -// borderRadius: BorderRadius.all( -// Radius.circular(10.0), -// ), -// boxShadow: [ -// BoxShadow( -// color: Color(0xff000000).withOpacity(.05), -// blurRadius: 27, -// offset: Offset(0, -3), -// ), -// ], -// ), -// child: Container( -// margin: EdgeInsets.only(left: projectViewModel.isArabic ? 0 : 6, right: projectViewModel.isArabic ? 6 : 0), -// padding: EdgeInsets.symmetric(vertical: 14, horizontal: 12), -// decoration: BoxDecoration( -// color: Colors.white, -// border: Border.all(color: Colors.white, width: 1), -// borderRadius: BorderRadius.only( -// bottomRight: projectViewModel.isArabic ? Radius.circular(0) : Radius.circular(10.0), -// topRight: projectViewModel.isArabic ? Radius.circular(0) : Radius.circular(10.0), -// bottomLeft: projectViewModel.isArabic ? Radius.circular(10.0) : Radius.circular(0), -// topLeft: projectViewModel.isArabic ? Radius.circular(10.0) : Radius.circular(0), -// ), -// ), -// // clipBehavior: Clip.antiAlias, -// child: Row( -// crossAxisAlignment: CrossAxisAlignment.start, -// children: [ -// Expanded( -// child: Column( -// mainAxisAlignment: MainAxisAlignment.start, -// crossAxisAlignment: CrossAxisAlignment.start, -// children: [ -// Text( -// _statusDisp, -// style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: _color, letterSpacing: -0.4, height: 16 / 10), -// ), -// SizedBox(height: 6), -// Text( -// '${TranslationBase.of(context).requestID}: ${order.iD}', -// style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.64, height: 25 / 16), -// ), -// Row( -// crossAxisAlignment: CrossAxisAlignment.start, -// children: [ -// Text( -// TranslationBase.of(context).hospital + ": ", -// style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff575757), letterSpacing: -0.4, height: 16 / 10), -// ), -// Expanded( -// child: Text( -// // !projectViewModel.isArabic ? order.nearestProjectDescription.trim().toString() : order.nearestProjectDescriptionN.toString(), -// order.projectName != null ? order.projectName!.trim().toString() : "", -// style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.56), -// ), -// ), -// ], -// ) -// ], -// ), -// ), -// Column( -// mainAxisAlignment: MainAxisAlignment.spaceBetween, -// crossAxisAlignment: CrossAxisAlignment.end, -// children: [ -// Text( -// DateUtil.getDayMonthYearDateFormatted(DateTime.tryParse(order.created!)!), -// style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.4, height: 16 / 10), -// ), -// SizedBox(height: 12), -// if (order.statusId == 1 || order.statusId == 2) -// InkWell( -// onTap: () { -// showConfirmMessage(model, order); -// }, -// child: Container( -// padding: EdgeInsets.symmetric(vertical: 8, horizontal: 14), -// decoration: BoxDecoration( -// color: Color(0xffD02127), -// border: Border.all(color: Colors.white, width: 1), -// borderRadius: BorderRadius.circular(10), -// ), -// child: Text( -// TranslationBase.of(context).cancel_nocaps, -// style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Colors.white, letterSpacing: -0.4), -// ), -// ), -// ), -// ], -// ), -// ], -// ), -// ), -// ); -// }, -// separatorBuilder: (context, index) => SizedBox(height: 12), -// itemCount: model.cmcAllPresOrders.length) : getNoDataWidget(context), -// ); -// } -// } diff --git a/lib/presentation/emergency_services/emergency_services_page.dart b/lib/presentation/emergency_services/emergency_services_page.dart index 9e70b3b..d41f2eb 100644 --- a/lib/presentation/emergency_services/emergency_services_page.dart +++ b/lib/presentation/emergency_services/emergency_services_page.dart @@ -1,8 +1,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; -import 'package:hmg_patient_app_new/core/dependencies.dart'; -import 'package:hmg_patient_app_new/core/location_util.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; @@ -27,13 +25,13 @@ class EmergencyServicesPage extends StatelessWidget { EmergencyServicesPage({super.key}); late EmergencyServicesViewModel emergencyServicesViewModel; - LocationUtils? locationUtils; + + _handleConfirmationBottomSheet() {} @override Widget build(BuildContext context) { emergencyServicesViewModel = Provider.of(context, listen: false); - locationUtils = getIt.get(); - locationUtils!.isShowConfirmDialog = true; + return CollapsingListView( title: LocaleKeys.emergencyServices.tr(), requests: () { @@ -293,10 +291,7 @@ class EmergencyServicesPage extends StatelessWidget { showCommonBottomSheetWithoutHeight( context, child: Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.primaryRedColor, - borderRadius: 24.h, - ), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.primaryRedColor, borderRadius: 24.h), child: Padding( padding: EdgeInsets.all(24.h), child: Column( diff --git a/lib/theme/colors.dart b/lib/theme/colors.dart index 6ccf8b1..469704a 100644 --- a/lib/theme/colors.dart +++ b/lib/theme/colors.dart @@ -37,11 +37,10 @@ class AppColors { static const Color warningColorYellow = Color(0xFFF4A308); static const Color blackBgColor = Color(0xFF2E3039); static const blackColor = textColor; - static const Color inputLabelTextColor = Color(0xff898A8D); + static const Color inputLabelTextColor = Color(0xff898A8D); static const Color greyTextColor = Color(0xFF8F9AA3); static const Color lightGrayBGColor = Color(0x142E3039); - static const lightGreenColor = Color(0xFF0ccedde); static const textGreenColor = Color(0xFF18C273); static const Color ratingColorYellow = Color(0xFFFFAF15); @@ -57,27 +56,38 @@ class AppColors { static const Color chipPrimaryRedBorderColor = Color(0xFFED1C2B); static const Color chipSecondaryLightRedColor = Color(0xFFFEE9EA); -static const Color successLightColor = Color(0xFF18C273); -static const Color errorLightColor = Color(0xFFED1C2B); -static const Color alertLightColor = Color(0xFFD48D05); -static const Color infoLightColor = Color(0xFF0B85F7); -static const Color warningLightColor = Color(0xFFFFCC00); -static const Color greyLightColor = Color(0xFFEFEFF0); -static const Color thumbColor = Color(0xFF18C273); -static const Color switchBackgroundColor = Color(0x2618C273); + static const Color successLightColor = Color(0xFF18C273); + static const Color errorLightColor = Color(0xFFED1C2B); + static const Color alertLightColor = Color(0xFFD48D05); + static const Color infoLightColor = Color(0xFF0B85F7); + static const Color warningLightColor = Color(0xFFFFCC00); + static const Color greyLightColor = Color(0xFFEFEFF0); + static const Color thumbColor = Color(0xFF18C273); + static const Color switchBackgroundColor = Color(0x2618C273); + + static const Color bottomNAVBorder = Color(0xFFEEEEEE); -static const Color bottomNAVBorder = Color(0xFFEEEEEE); + static const Color quickLoginColor = Color(0xFF666666); -static const Color quickLoginColor = Color(0xFF666666); + static const Color tooltipTextColor = Color(0xFF414D55); + static const Color graphGridColor = Color(0x4D18C273); + static const Color criticalLowAndHigh = Color(0xFFED1C2B); + static const Color highAndLow = Color(0xFFFFAF15); + static const Color labelTextColor = Color(0xFF838383); + static const Color calenderTextColor = Color(0xFFD0D0D0); + static const Color lightGreenButtonColor = Color(0x2618C273); -static const Color tooltipTextColor = Color(0xFF414D55); -static const Color graphGridColor = Color(0x4D18C273); -static const Color criticalLowAndHigh = Color(0xFFED1C2B); -static const Color highAndLow = Color(0xFFFFAF15); -static const Color labelTextColor = Color(0xFF838383); -static const Color calenderTextColor = Color(0xFFD0D0D0); -static const Color lightGreenButtonColor = Color(0x2618C273); + static const Color lightRedButtonColor = Color(0x1AED1C2B); -static const Color lightRedButtonColor = Color(0x1AED1C2B); + // Status Colors + static const Color statusPendingColor = Color(0xffCC9B14); + static const Color statusProcessingColor = Color(0xff2E303A); + static const Color statusCompletedColor = Color(0xff359846); + static const Color statusRejectedColor = Color(0xffD02127); + // Info Banner Colors + static const Color infoBannerBgColor = Color(0xFFFFF4E6); + static const Color infoBannerBorderColor = Color(0xFFFFE5B4); + static const Color infoBannerIconColor = Color(0xFFCC9B14); + static const Color infoBannerTextColor = Color(0xFF856404); } diff --git a/lib/widgets/common_bottom_sheet.dart b/lib/widgets/common_bottom_sheet.dart index 1bbe472..8021641 100644 --- a/lib/widgets/common_bottom_sheet.dart +++ b/lib/widgets/common_bottom_sheet.dart @@ -104,18 +104,20 @@ class ButtonSheetContent extends StatelessWidget { } } -void showCommonBottomSheetWithoutHeight(BuildContext context, - {required Widget child, - VoidCallback? callBackFunc, - String title = "", - bool isCloseButtonVisible = true, - bool isFullScreen = true, - bool isDismissible = true, - Widget? titleWidget, - bool useSafeArea = false, - bool hasBottomPadding = true, - Color backgroundColor = AppColors.bottomSheetBgColor, - VoidCallback? onCloseClicked}) { +void showCommonBottomSheetWithoutHeight( + BuildContext context, { + required Widget child, + VoidCallback? callBackFunc, + String title = "", + bool isCloseButtonVisible = true, + bool isFullScreen = true, + bool isDismissible = true, + Widget? titleWidget, + bool useSafeArea = false, + bool hasBottomPadding = true, + Color backgroundColor = AppColors.bottomSheetBgColor, + VoidCallback? onCloseClicked, +}) { showModalBottomSheet( sheetAnimationStyle: AnimationStyle( duration: Duration(milliseconds: 500),