diff --git a/assets/images/svg/pin_location.svg b/assets/images/svg/pin_location.svg
new file mode 100644
index 00000000..1a8012d5
--- /dev/null
+++ b/assets/images/svg/pin_location.svg
@@ -0,0 +1,4 @@
+
diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart
index 61cf2997..a64110d8 100644
--- a/lib/core/app_assets.dart
+++ b/lib/core/app_assets.dart
@@ -25,6 +25,7 @@ class AppAssets {
static const String download = '$svgBasePath/download.svg';
static const String language = '$svgBasePath/language.svg';
static const String location = '$svgBasePath/location.svg';
+ static const String pin_location = '$svgBasePath/pin_location.svg';
static const String whatsapp = '$svgBasePath/whatsapp.svg';
static const String card_user = '$svgBasePath/card_user.svg';
static const String habiblogo = '$svgBasePath/habiblogo.svg';
diff --git a/lib/core/dependencies.dart b/lib/core/dependencies.dart
index a82a9adb..42e9ea88 100644
--- a/lib/core/dependencies.dart
+++ b/lib/core/dependencies.dart
@@ -19,6 +19,8 @@ import 'package:hmg_patient_app_new/features/insurance/insurance_repo.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/lab/lab_repo.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
+import 'package:hmg_patient_app_new/features/location/location_repo.dart';
+import 'package:hmg_patient_app_new/features/location/location_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_repo.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/appointment_via_region_viewmodel.dart';
@@ -103,6 +105,8 @@ class AppDependencies {
getIt.registerLazySingleton(() => MedicalFileRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => ImmediateLiveCareRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => EmergencyServicesRepoImp(loggerService: getIt(), apiClient: getIt()));
+ getIt.registerLazySingleton(
+ () => LocationRepoImpl(apiClient: getIt()));
// ViewModels
// Global/shared VMs → LazySingleton
@@ -199,6 +203,15 @@ class AppDependencies {
emergencyServicesRepo: getIt(),
appState: getIt(),
errorHandlerService: getIt(),
+ appointmentRepo: getIt(),
+ dialogService: getIt()
+ ),
+ );
+
+ getIt.registerLazySingleton(
+ () => LocationViewModel(
+ locationRepo: getIt(),
+ errorHandlerService: getIt(),
),
);
diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart
index 491aa493..d890d36f 100644
--- a/lib/core/utils/utils.dart
+++ b/lib/core/utils/utils.dart
@@ -18,6 +18,8 @@ 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/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.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/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
@@ -742,10 +744,14 @@ class Utils {
static Widget getPaymentAmountWithSymbol2(num habibWalletAmount,
{double iconSize = 14,
- Color iconColor = AppColors.textColor,
+ double? fontSize,
+ double? letterSpacing,
+ FontWeight? fontWeight,
+ Color iconColor = AppColors.textColor,
Color textColor = AppColors.blackColor,
bool isSaudiCurrency = true,
- bool isExpanded = true}) {
+ bool isExpanded = true,
+ }) {
return RichText(
maxLines: 1,
text: TextSpan(
@@ -756,8 +762,13 @@ class Utils {
child: Utils.buildSvgWithAssets(icon: AppAssets.saudi_riyal_icon, width: iconSize.h, height: iconSize.h, iconColor: iconColor),
),
TextSpan(
- text: " $habibWalletAmount",
- style: TextStyle(color: textColor, fontSize: 32.f, letterSpacing: -4, fontWeight: FontWeight.w600, height: 1),
+ text: NumberFormat.currency(locale: 'en_US', symbol: " ", decimalDigits: 0).format(habibWalletAmount),
+ style: TextStyle(
+ color: textColor,
+ fontSize: fontSize ?? 32.f,
+ letterSpacing: letterSpacing??-4,
+ fontWeight: fontWeight ?? FontWeight.w600,
+ height: 1),
),
],
),
@@ -815,4 +826,34 @@ class Utils {
}
return isHavePrivilege;
}
+
+ ///method to be used to get the text as per the langauge of the application
+ static String getTextWRTCurrentLanguage(
+ String? englishText, String? arabicText) {
+ String? text = appState.isArabic() ? arabicText : englishText;
+ return text ?? '';
+ }
+
+
+ static String formatNumberToInternationalFormat(num number, {String? currencySymbol, int decimalDigit = 0}){
+ return NumberFormat.currency(
+ locale: 'en_US',
+ symbol: currencySymbol??"",
+ decimalDigits: decimalDigit)
+ .format(number);
+ }
+
+
+ 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);
+ }
+
}
diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart
index 041e8b7e..1a6d1ccf 100644
--- a/lib/extensions/string_extensions.dart
+++ b/lib/extensions/string_extensions.dart
@@ -279,11 +279,11 @@ extension EmailValidator on String {
height: 1, color: color ?? AppColors.blackColor, fontSize: 22.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
- Widget toText24({Color? color, bool isBold = false, bool isCenter = false, FontWeight? fontWeight}) => Text(
+ Widget toText24({Color? color, bool isBold = false, bool isCenter = false, FontWeight? fontWeight, double? letterSpacing}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
style: TextStyle(
- height: 23 / 24, color: color ?? AppColors.blackColor, fontSize: 24.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
+ height: 23 / 24, color: color ?? AppColors.blackColor, fontSize: 24.f, letterSpacing: letterSpacing??-1, fontWeight: isBold ? FontWeight.bold : fontWeight??FontWeight.normal),
);
Widget toText26({Color? color, bool isBold = false, double? height, bool isCenter = false, FontWeight? weight, double? letterSpacing}) => Text(
diff --git a/lib/features/emergency_services/emergency_services_repo.dart b/lib/features/emergency_services/emergency_services_repo.dart
index 089e7ada..a9bebd57 100644
--- a/lib/features/emergency_services/emergency_services_repo.dart
+++ b/lib/features/emergency_services/emergency_services_repo.dart
@@ -3,14 +3,22 @@ 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/emergency_services/model/resp_model/ProjectAvgERWaitingTime.dart';
-import 'package:hmg_patient_app_new/features/emergency_services/models/resp_models/rrt_procedures_response_model.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/ProjectAvgERWaitingTime.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/rrt_procedures_response_model.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
+import 'models/resp_model/PatientERTransportationMethod.dart';
+
abstract class EmergencyServicesRepo {
Future>>> getRRTProcedures();
Future>>> getNearestEr({int? id, int? projectID});
+
+ Future>>> getTransportationMethods({int? id});
+
+ Future>>> getProjectList();
+
}
class EmergencyServicesRepoImp implements EmergencyServicesRepo {
@@ -91,4 +99,79 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo {
return Left(UnknownFailure(e.toString()));
}
}
+
+ @override
+ Future>>> getTransportationMethods({int? id}) async {
+ Map mapDevice = {};
+
+ try {
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.get(
+ "$GET_ALL_TRANSPORTATIONS_RC?patientID=$id",
+ isRCService: true,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['response']['transportationservices'];
+ final proceduresList = list.map((item) => PatientERTransportationMethod.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: proceduresList,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>>> getProjectList() async {
+ Map request = {};
+
+ try {
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_PROJECT_LIST,
+ body: request,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['ListProject'];
+
+ final appointmentsList = list.map((item) => HospitalsModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: appointmentsList,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
}
diff --git a/lib/features/emergency_services/emergency_services_view_model.dart b/lib/features/emergency_services/emergency_services_view_model.dart
index 77e58239..742678ae 100644
--- a/lib/features/emergency_services/emergency_services_view_model.dart
+++ b/lib/features/emergency_services/emergency_services_view_model.dart
@@ -5,31 +5,73 @@ import 'package:google_maps_flutter/google_maps_flutter.dart' as GMSMapServices;
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/location_util.dart';
+import 'package:hmg_patient_app_new/core/utils/doctor_response_mapper.dart';
+import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/emergency_services/emergency_services_repo.dart';
-import 'package:hmg_patient_app_new/features/emergency_services/model/resp_model/ProjectAvgERWaitingTime.dart';
-import 'package:hmg_patient_app_new/features/emergency_services/models/resp_models/rrt_procedures_response_model.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/AmbulanceCallingPlace.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/PatientERTransportationMethod.dart'
+ show PatientERTransportationMethod;
+import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/ProjectAvgERWaitingTime.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/rrt_procedures_response_model.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/facility_selection.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_repo.dart';
+import 'package:hmg_patient_app_new/presentation/authentication/login.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/call_ambulance_page.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/nearest_er_page.dart';
+import 'package:hmg_patient_app_new/routes/app_routes.dart' show AppRoutes;
+import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/expandable_bottom_sheet/model/BottomSheetType.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:huawei_map/huawei_map.dart' as HMSCameraServices;
import 'package:url_launcher/url_launcher.dart';
+import '../location/GeocodeResponse.dart';
+import 'models/ambulance_direction.dart';
+
class EmergencyServicesViewModel extends ChangeNotifier {
EmergencyServicesRepo emergencyServicesRepo;
+ MyAppointmentsRepo appointmentRepo;
ErrorHandlerService errorHandlerService;
+ DialogService dialogService;
+
+ Completer? gmsController;
+ Completer? hmsController;
final NavigationService navServices;
final LocationUtils? locationUtils;
final AppState appState;
+
+ //loading variables
bool isERListLoading = false;
+ bool isTransportationOptionsLoading = false;
+
List nearestERList = [];
List nearestERFilteredList = [];
List RRTProceduresList = [];
+ List? hospitalList;
+ List? hmgHospitalList;
+ List? hmcHospitalList;
+ List? displayList;
+ HospitalsModel? selectedHospital;
+ FacilitySelection selectedFacility = FacilitySelection.ALL;
+ int hmgCount = 0;
+ int hmcCount = 0;
+ bool pickupFromInsideTheLocation = true;
+
+ //ambulance selection data section
+ List transportationOptions = [];
+ PatientERTransportationMethod? selectedTransportOption;
+ AmbulanceCallingPlace callingPlace = AmbulanceCallingPlace.FROM_HOSPITAL;
+ AmbulanceDirection ambulanceDirection = AmbulanceDirection.ONE_WAY;
+
late RRTProceduresResponseModel selectedRRTProcedure;
BottomSheetType bottomSheetType = BottomSheetType.FIXED;
@@ -45,6 +87,8 @@ class EmergencyServicesViewModel extends ChangeNotifier {
required this.navServices,
required this.locationUtils,
required this.appState,
+ required this.appointmentRepo,
+ required this.dialogService,
});
get isGMSAvailable
@@ -52,6 +96,13 @@ class EmergencyServicesViewModel extends ChangeNotifier {
return appState.isGMSAvailable;
}
+ bool get isArabic => appState.isArabic();
+
+ bool haveAnAppointment = false;
+
+ PatientAppointmentHistoryResponseModel? appointment;
+
+ bool isMyAppointmentsLoading = false;
Future getRRTProcedures({Function(dynamic)? onSuccess, Function(String)? onError}) async {
RRTProceduresList.clear();
@@ -168,17 +219,32 @@ class EmergencyServicesViewModel extends ChangeNotifier {
}
void navigateTOAmbulancePage() {
- locationUtils!.getLocation(
- isShowConfirmDialog: true,
- onSuccess: (position) {
- updateBottomSheetState(BottomSheetType.FIXED);
- navServices.push(
- CustomPageRoute(
- page: CallAmbulancePage(), direction: AxisDirection.down
- ),
- );
-
- });
+ placeValueInController();
+ getProjects();
+ flushData();
+ selectedFacility = FacilitySelection.ALL;
+
+ print("the app state is ${appState.isAuthenticated}");
+ if (appState.isAuthenticated) {
+ locationUtils!.getLocation(
+ isShowConfirmDialog: true,
+ onSuccess: (position) {
+ updateBottomSheetState(BottomSheetType.FIXED);
+ navServices.push(
+ CustomPageRoute(
+ page: CallAmbulancePage(), direction: AxisDirection.down),
+ );
+ });
+ } else {
+ dialogService.showErrorBottomSheet(
+ message: "You Need To Login First To Continue".needTranslation,
+ onOkPressed: () {
+ navServices.pop();
+ navServices.pushAndReplace(
+ AppRoutes.loginScreen
+ );
+ });
+ }
}
void updateBottomSheetState(BottomSheetType sheetType) {
@@ -187,8 +253,229 @@ class EmergencyServicesViewModel extends ChangeNotifier {
}
void setIsGMSAvailable(bool value) {
+ notifyListeners();
+ }
+
+ Future getTransportationOption() async {
+ //handle the cache if the data is present then dont fetch it in the authenticated lifecycle
+
+ print("the app state is ${appState.isAuthenticated}");
+ if (appState.isAuthenticated == false) {
+ dialogService.showErrorBottomSheet(
+ message: "You Need To Login First To Continue".needTranslation,
+ onOkPressed: () {
+ navServices.pop();
+ print("inside the ok button");
+ navServices.pushAndReplace(
+ AppRoutes.loginScreen
+ );
+ });
+ return;
+ }
+
+ if (transportationOptions.isNotEmpty) return;
+
+ int? id = appState.getAuthenticatedUser()?.patientId;
+ LoaderBottomSheet.showLoader(
+ loadingText: "Getting Ambulance Transport Option".needTranslation);
+
+ notifyListeners();
+ var response = await emergencyServicesRepo.getTransportationMethods(id: id);
+
+ response.fold(
+ (failure) async {
+ LoaderBottomSheet.hideLoader();
+ },
+ (apiResponse) {
+ transportationOptions = apiResponse.data!;
+ LoaderBottomSheet.hideLoader();
+ notifyListeners();
+ },
+ );
+ }
+
+ Future getTransportationMethods() async {
+ int? id = appState.getAuthenticatedUser()?.patientId;
+ LoaderBottomSheet.showLoader(
+ loadingText: "Getting Ambulance Transport Option".needTranslation);
+
+ notifyListeners();
+ var response =
+ await emergencyServicesRepo.getTransportationMethods(id: 4767477);
+
+ response.fold(
+ (failure) async {
+ LoaderBottomSheet.hideLoader();
+ },
+ (apiResponse) {
+ transportationOptions = apiResponse.data!;
+ LoaderBottomSheet.hideLoader();
+ notifyListeners();
+ },
+ );
+ }
+
+ void setTransportationOption(PatientERTransportationMethod item) {
+ selectedTransportOption = item;
+ }
+
+ void updateCallingPlace(AmbulanceCallingPlace? value) {
+ callingPlace = value!;
+ notifyListeners();
+ }
+
+ void updateDirection(AmbulanceDirection? value) {
+ ambulanceDirection = value!;
+ notifyListeners();
+ }
+
+ void placeValueInController() {
+ if (isGMSAvailable) {
+ gmsController = Completer();
+ } else {
+ hmsController = Completer();
+ }
+ }
+
+ void moveController(Location location) {
+ if (isGMSAvailable) {
+ gmsController?.future.then((controller) {
+ controller.animateCamera(
+ GMSMapServices.CameraUpdate.newCameraPosition(
+ GMSMapServices.CameraPosition(
+ target: GMSMapServices.LatLng(location.lat, location.lng),
+ zoom: 18,
+ ),
+ ),
+ );
+ });
+ } else {
+ hmsController?.future.then((controller) {
+ controller.animateCamera(
+ HMSCameraServices.CameraUpdate.newCameraPosition(
+ HMSCameraServices.CameraPosition(
+ target: HMSCameraServices.LatLng(location.lat, location.lng),
+ zoom: 18,
+ ),
+ ),
+ );
+ });
+ }
+ }
+
+ void moveToCurrentLocation() {
+ moveController(Location(lat: appState.userLat, lng: appState.userLong));
+ }
+ FutureOr getProjects() async {
+ // if (hospitalList.isNotEmpty) return;
+ var response = await emergencyServicesRepo.getProjectList();
+
+ response.fold(
+ (failure) async {},
+ (apiResponse) async {
+ List? data = apiResponse.data;
+ if (data == null) return;
+ hospitalList = data;
+ hmgHospitalList = data.where((e) => e.isHMC == false).toList();
+ hmcHospitalList = data.where((e) => e.isHMC == true).toList();
+ hmgCount = hmgHospitalList?.length ?? 0;
+ hmcCount = hmcHospitalList?.length ?? 0;
+ notifyListeners();
+ },
+ );
+ }
+
+ setSelectedFacility(FacilitySelection selection) {
+ selectedFacility = selection;
notifyListeners();
+ }
+ searchHospitals(String query) {
+ if (query.isEmpty) {
+ getDisplayList();
+ return;
+ }
+ List? sourceList;
+ switch (selectedFacility) {
+ case FacilitySelection.ALL:
+ sourceList = hospitalList;
+ break;
+ case FacilitySelection.HMG:
+ sourceList = hmgHospitalList;
+ break;
+ case FacilitySelection.HMC:
+ sourceList = hmcHospitalList;
+ break;
+ }
+ displayList = sourceList
+ ?.where((hospital) =>
+ hospital.name != null &&
+ hospital.name!.toLowerCase().contains(query.toLowerCase()))
+ .toList();
+ notifyListeners();
+ }
+
+ getDisplayList() {
+ switch (selectedFacility) {
+ case FacilitySelection.ALL:
+ displayList = hospitalList;
+ break;
+ case FacilitySelection.HMG:
+ displayList = hmgHospitalList;
+ break;
+ case FacilitySelection.HMC:
+ displayList = hmcHospitalList;
+ break;
+ }
+ notifyListeners();
+ }
+
+
+ void setSelectedHospital(HospitalsModel? hospital) {
+ selectedHospital = hospital;
+ notifyListeners();
+ }
+
+ String? getSelectedHospitalName() {
+ return selectedHospital?.getName(isArabic);
+ }
+
+ void updateThePickupPlaceFromLocation(bool value) {
+ pickupFromInsideTheLocation = value;
+ notifyListeners();
+ }
+
+ void flushData() {
+ selectedHospital = null;
+ displayList = hospitalList;
+ selectedFacility = FacilitySelection.ALL;
+ pickupFromInsideTheLocation = false;
+ notifyListeners();
+ }
+
+ void flushPickupInformation() {
+ ambulanceDirection = AmbulanceDirection.ONE_WAY;
+ callingPlace = AmbulanceCallingPlace.FROM_HOSPITAL;
+ notifyListeners();
+ }
+
+ num getTotalPrice() {
+ print("the ambulance direction is $ambulanceDirection");
+ switch (ambulanceDirection) {
+ case AmbulanceDirection.ONE_WAY:
+ return selectedTransportOption?.priceTotal ?? 0;
+ case AmbulanceDirection.TWO_WAY:
+ return (selectedTransportOption?.priceTotal ?? 0) * 2;
+ }
+ }
+
+ Future updateAppointment(bool value) async {
+ haveAnAppointment = value;
+ if (value) {
+ await appointmentRepo.getPatientAppointments(
+ isActiveAppointment: true, isArrivedAppointments: false);
+ }
+ notifyListeners();
}
}
diff --git a/lib/features/emergency_services/models/AmbulanceCallingPlace.dart b/lib/features/emergency_services/models/AmbulanceCallingPlace.dart
new file mode 100644
index 00000000..cf648f7c
--- /dev/null
+++ b/lib/features/emergency_services/models/AmbulanceCallingPlace.dart
@@ -0,0 +1,4 @@
+enum AmbulanceCallingPlace{
+ FROM_HOSPITAL,
+ TO_HOSPITAL
+}
\ No newline at end of file
diff --git a/lib/features/emergency_services/models/ambulance_direction.dart b/lib/features/emergency_services/models/ambulance_direction.dart
new file mode 100644
index 00000000..d3019214
--- /dev/null
+++ b/lib/features/emergency_services/models/ambulance_direction.dart
@@ -0,0 +1,3 @@
+enum AmbulanceDirection{
+ ONE_WAY, TWO_WAY
+}
\ No newline at end of file
diff --git a/lib/features/emergency_services/models/request_model/PatientER_RC.dart b/lib/features/emergency_services/models/request_model/PatientER_RC.dart
new file mode 100644
index 00000000..8cb3876d
--- /dev/null
+++ b/lib/features/emergency_services/models/request_model/PatientER_RC.dart
@@ -0,0 +1,205 @@
+
+import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/PatientERTransportationMethod.dart' show PatientERTransportationMethod;
+
+class PatientER_RC {
+ double? versionID;
+ int? channel;
+ int? languageID;
+ String? iPAdress;
+ String? generalid;
+ bool? patientOutSA;
+ String? sessionID;
+ bool? isDentalAllowedBackend;
+ int? deviceTypeID;
+ int? patientID;
+ String? tokenID;
+ int? patientTypeID;
+ int? patientType;
+ int? orderServiceID;
+ String? patientIdentificationID;
+ dynamic patientOutSa;
+ int? projectID;
+ int? lineItemNo;
+ TransportationDetails? transportationDetails;
+ PatientERTransportationMethod? patientERTransportationMethod;
+
+ PatientER_RC(
+ {this.versionID,
+ this.channel,
+ this.languageID,
+ this.iPAdress,
+ this.generalid,
+ this.patientOutSA,
+ this.sessionID,
+ this.isDentalAllowedBackend,
+ this.deviceTypeID,
+ this.patientID,
+ this.tokenID,
+ this.patientTypeID,
+ this.patientType,
+ this.orderServiceID,
+ this.patientIdentificationID,
+ this.patientOutSa,
+ this.projectID,
+ this.lineItemNo,
+ this.transportationDetails});
+
+ PatientER_RC.fromJson(Map json) {
+ versionID = json['VersionID'];
+ channel = json['Channel'];
+ languageID = json['LanguageID'];
+ iPAdress = json['IPAdress'];
+ generalid = json['generalid'];
+ patientOutSA = json['PatientOutSA'];
+ sessionID = json['SessionID'];
+ isDentalAllowedBackend = json['isDentalAllowedBackend'];
+ deviceTypeID = json['DeviceTypeID'];
+ patientID = json['PatientID'];
+ tokenID = json['TokenID'];
+ patientTypeID = json['PatientTypeID'];
+ patientType = json['PatientType'];
+ orderServiceID = json['OrderServiceID'];
+ patientIdentificationID = json['PatientIdentificationID'];
+ patientOutSa = json['patientOutSa'];
+ projectID = json['projectID'];
+ lineItemNo = json['lineItemNo'];
+ transportationDetails = json['transportationDetails'] != null
+ ? new TransportationDetails.fromJson(json['transportationDetails'])
+ : null;
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['VersionID'] = this.versionID;
+ data['Channel'] = this.channel;
+ data['LanguageID'] = this.languageID;
+ data['IPAdress'] = this.iPAdress;
+ data['generalid'] = this.generalid;
+ data['PatientOutSA'] = this.patientOutSA;
+ data['SessionID'] = this.sessionID;
+ data['isDentalAllowedBackend'] = this.isDentalAllowedBackend;
+ data['DeviceTypeID'] = this.deviceTypeID;
+ data['PatientID'] = this.patientID;
+ data['TokenID'] = this.tokenID;
+ data['PatientTypeID'] = this.patientTypeID;
+ data['PatientType'] = this.patientType;
+ data['OrderServiceID'] = this.orderServiceID;
+ data['PatientIdentificationID'] = this.patientIdentificationID;
+ data['patientOutSa'] = this.patientOutSa;
+ data['projectID'] = this.projectID;
+ data['lineItemNo'] = this.lineItemNo;
+ if (this.transportationDetails != null) {
+ data['transportationDetails'] = this.transportationDetails!.toJson();
+ }
+ return data;
+ }
+}
+
+class TransportationDetails {
+ int? direction;
+ int? haveAppointment;
+ int? tripType;
+ int? pickupUrgency;
+ int? pickupSpot;
+ String? pickupDateTime;
+ String? transportationType;
+ int? ambulate;
+ String? ambulateTitle;
+ String? notes;
+ int? requesterFileNo;
+ String? requesterMobileNo;
+ bool? requesterIsOutSA;
+ String? pickupLocationName;
+ String? dropoffLocationName;
+ String? pickupLatitude;
+ String? pickupLongitude;
+ String? dropoffLatitude;
+ String? dropoffLongitude;
+ String? appointmentNo;
+ String? appointmentClinicName;
+ String? appointmentDoctorName;
+ String? appointmentBranch;
+ String? appointmentTime;
+
+ TransportationDetails(
+ {this.direction,
+ this.haveAppointment,
+ this.tripType,
+ this.pickupUrgency,
+ this.pickupSpot,
+ this.pickupDateTime,
+ this.transportationType,
+ this.ambulate,
+ this.ambulateTitle,
+ this.notes,
+ this.requesterFileNo,
+ this.requesterMobileNo,
+ this.requesterIsOutSA,
+ this.pickupLocationName,
+ this.dropoffLocationName,
+ this.pickupLatitude,
+ this.pickupLongitude,
+ this.dropoffLatitude,
+ this.dropoffLongitude,
+ this.appointmentNo,
+ this.appointmentClinicName,
+ this.appointmentDoctorName,
+ this.appointmentBranch,
+ this.appointmentTime});
+
+ TransportationDetails.fromJson(Map json) {
+ direction = json['direction'];
+ haveAppointment = json['haveAppointment'];
+ tripType = json['tripType'];
+ pickupUrgency = json['pickupUrgency'];
+ pickupSpot = json['pickupSpot'];
+ pickupDateTime = json['pickupDateTime'];
+ transportationType = json['transportationType'];
+ ambulate = json['ambulate'];
+ ambulateTitle = "";
+ notes = json['notes'];
+ requesterFileNo = json['requesterFileNo'];
+ requesterMobileNo = json['requesterMobileNo'];
+ requesterIsOutSA = json['requesterIsOutSA'];
+ pickupLocationName = json['pickupLocationName'];
+ dropoffLocationName = json['dropoffLocationName'];
+ pickupLatitude = json['pickup_Latitude'];
+ pickupLongitude = json['pickup_Longitude'];
+ dropoffLatitude = json['dropoff_Latitude'];
+ dropoffLongitude = json['dropoff_Longitude'];
+ appointmentNo = json['appointmentNo'];
+ appointmentClinicName = json['appointmentClinicName'];
+ appointmentDoctorName = json['appointmentDoctorName'];
+ appointmentBranch = json['appointmentBranch'];
+ appointmentTime = json['appointmentTime'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['direction'] = this.direction;
+ data['haveAppointment'] = this.haveAppointment;
+ data['tripType'] = this.tripType;
+ data['pickupUrgency'] = this.pickupUrgency;
+ data['pickupSpot'] = this.pickupSpot;
+ data['pickupDateTime'] = this.pickupDateTime;
+ data['transportationType'] = this.transportationType;
+ data['ambulate'] = this.ambulate;
+ data['ambulateTitle'] = this.ambulateTitle;
+ data['notes'] = this.notes;
+ data['requesterFileNo'] = this.requesterFileNo;
+ data['requesterMobileNo'] = this.requesterMobileNo;
+ data['requesterIsOutSA'] = this.requesterIsOutSA;
+ data['pickupLocationName'] = this.pickupLocationName;
+ data['dropoffLocationName'] = this.dropoffLocationName;
+ data['pickup_Latitude'] = this.pickupLatitude;
+ data['pickup_Longitude'] = this.pickupLongitude;
+ data['dropoff_Latitude'] = this.dropoffLatitude;
+ data['dropoff_Longitude'] = this.dropoffLongitude;
+ data['appointmentNo'] = this.appointmentNo;
+ data['appointmentClinicName'] = this.appointmentClinicName;
+ data['appointmentDoctorName'] = this.appointmentDoctorName;
+ data['appointmentBranch'] = this.appointmentBranch;
+ data['appointmentTime'] = this.appointmentTime;
+ return data;
+ }
+}
diff --git a/lib/features/emergency_services/models/resp_model/PatientERTransportationMethod.dart b/lib/features/emergency_services/models/resp_model/PatientERTransportationMethod.dart
new file mode 100644
index 00000000..e4e6c7d7
--- /dev/null
+++ b/lib/features/emergency_services/models/resp_model/PatientERTransportationMethod.dart
@@ -0,0 +1,56 @@
+class PatientERTransportationMethod {
+ int? iD;
+ String? serviceID;
+ int? orderServiceID;
+ String? text;
+ String? textN;
+ dynamic price;
+ dynamic priceVAT;
+ dynamic priceTotal;
+ bool? isEnabled;
+ int? orderId;
+ int? quantity;
+
+ PatientERTransportationMethod(
+ {this.iD,
+ this.serviceID,
+ this.orderServiceID,
+ this.text,
+ this.textN,
+ this.price,
+ this.priceVAT,
+ this.priceTotal,
+ this.isEnabled,
+ this.orderId,
+ this.quantity});
+
+ PatientERTransportationMethod.fromJson(Map json) {
+ iD = json['ID'];
+ serviceID = json['ServiceID'];
+ orderServiceID = json['OrderServiceID'];
+ text = json['Text'];
+ textN = json['TextN'];
+ price = json['Price'];
+ priceVAT = json['PriceVAT'];
+ priceTotal = json['PriceTotal'];
+ isEnabled = json['IsEnabled'];
+ orderId = json['OrderId'];
+ quantity = json['Quantity'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['ID'] = this.iD;
+ data['ServiceID'] = this.serviceID;
+ data['OrderServiceID'] = this.orderServiceID;
+ data['Text'] = this.text;
+ data['TextN'] = this.textN;
+ data['Price'] = this.price;
+ data['PriceVAT'] = this.priceVAT;
+ data['PriceTotal'] = this.priceTotal;
+ data['IsEnabled'] = this.isEnabled;
+ data['OrderId'] = this.orderId;
+ data['Quantity'] = this.quantity;
+ return data;
+ }
+}
\ No newline at end of file
diff --git a/lib/features/emergency_services/model/resp_model/ProjectAvgERWaitingTime.dart b/lib/features/emergency_services/models/resp_model/ProjectAvgERWaitingTime.dart
similarity index 100%
rename from lib/features/emergency_services/model/resp_model/ProjectAvgERWaitingTime.dart
rename to lib/features/emergency_services/models/resp_model/ProjectAvgERWaitingTime.dart
diff --git a/lib/features/emergency_services/models/resp_models/rrt_procedures_response_model.dart b/lib/features/emergency_services/models/resp_model/rrt_procedures_response_model.dart
similarity index 100%
rename from lib/features/emergency_services/models/resp_models/rrt_procedures_response_model.dart
rename to lib/features/emergency_services/models/resp_model/rrt_procedures_response_model.dart
diff --git a/lib/features/location/GeocodeResponse.dart b/lib/features/location/GeocodeResponse.dart
new file mode 100644
index 00000000..3e911aa3
--- /dev/null
+++ b/lib/features/location/GeocodeResponse.dart
@@ -0,0 +1,80 @@
+class GeocodeResponse {
+ final List results;
+ final String status;
+
+ GeocodeResponse({
+ required this.results,
+ required this.status,
+ });
+
+ factory GeocodeResponse.fromJson(Map json) {
+ final resultsList = (json['results'] as List? ?? [])
+ .map((e) => GeocodeResult.fromJson(e as Map))
+ .toList();
+
+ return GeocodeResponse(
+ results: resultsList,
+ status: json['status'] ?? '',
+ );
+ }
+ @override
+ String toString() {
+ return 'GeocodeResponse(status: $status, results: [${results.map((r) => r.toString()).join(', ')}])';
+ }
+}
+
+class GeocodeResult {
+ final String formattedAddress;
+ final Geometry geometry;
+ final String placeId;
+
+ GeocodeResult({
+ required this.formattedAddress,
+ required this.geometry,
+ required this.placeId,
+ });
+
+ factory GeocodeResult.fromJson(Map json) {
+ return GeocodeResult(
+ formattedAddress: json['formatted_address'] ?? '',
+ geometry: Geometry.fromJson(json['geometry']),
+ placeId: json['place_id'] ?? '',
+ );
+ }
+ @override
+ String toString() {
+ return 'GeocodeResult(formattedAddress: $formattedAddress, placeId: $placeId, geometry: ${geometry.toString()})';
+ }
+}
+
+class Geometry {
+ final Location location;
+
+ Geometry({required this.location});
+
+ factory Geometry.fromJson(Map json) {
+ return Geometry(
+ location: Location.fromJson(json['location']),
+ );
+ }
+
+ @override
+ String toString() => 'Geometry(location: ${location.toString()})';
+}
+
+class Location {
+ final double lat;
+ final double lng;
+
+ Location({required this.lat, required this.lng});
+
+ factory Location.fromJson(Map json) {
+ return Location(
+ lat: (json['lat'] as num).toDouble(),
+ lng: (json['lng'] as num).toDouble(),
+ );
+ }
+
+ @override
+ String toString() => 'Location(lat: $lat, lng: $lng)';
+}
\ No newline at end of file
diff --git a/lib/features/location/PlaceDetails.dart b/lib/features/location/PlaceDetails.dart
new file mode 100644
index 00000000..82846ea0
--- /dev/null
+++ b/lib/features/location/PlaceDetails.dart
@@ -0,0 +1,14 @@
+class PlaceDetails {
+ final double lat;
+ final double lng;
+
+ PlaceDetails({required this.lat, required this.lng});
+
+ factory PlaceDetails.fromJson(Map json) {
+ final loc = json['result']['geometry']['location'];
+ return PlaceDetails(
+ lat: (loc['lat'] as num).toDouble(),
+ lng: (loc['lng'] as num).toDouble(),
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/features/location/PlacePrediction.dart b/lib/features/location/PlacePrediction.dart
new file mode 100644
index 00000000..ea681538
--- /dev/null
+++ b/lib/features/location/PlacePrediction.dart
@@ -0,0 +1,11 @@
+class PlacePrediction {
+ final String description;
+ final String placeID;
+ PlacePrediction({required this.description, required this.placeID});
+ factory PlacePrediction.fromJson(Map json) {
+ return PlacePrediction(
+ description: json['description'] ?? '',
+ placeID: json['place_id'] ?? '',
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/features/location/location_repo.dart b/lib/features/location/location_repo.dart
new file mode 100644
index 00000000..46c97ac3
--- /dev/null
+++ b/lib/features/location/location_repo.dart
@@ -0,0 +1,153 @@
+import 'package:dartz/dartz.dart';
+import 'package:hmg_patient_app_new/core/api/api_client.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/location/GeocodeResponse.dart';
+import 'package:hmg_patient_app_new/features/location/PlaceDetails.dart';
+
+import '../../core/api_consts.dart';
+import 'PlacePrediction.dart';
+
+abstract class LocationRepo {
+ Future>>>
+ getPlacePredictionsAsInput(String input);
+
+ Future>>
+ getPlaceDetailsOfSelectedPrediction(String placeId);
+
+ Future>>
+ getGeoCodeFromLatLng(double lat, double lng);
+}
+
+class LocationRepoImpl implements LocationRepo {
+ final ApiClient apiClient;
+
+ LocationRepoImpl({required this.apiClient});
+
+ @override
+ Future>>> getPlacePredictionsAsInput(
+ String input) async {
+ final url = Uri.parse(
+ 'https://maps.googleapis.com/maps/api/place/autocomplete/json?input=$input®ion=SA&key=$GOOGLE_API_KEY',
+ );
+
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+
+ try {
+ await apiClient.get(
+ url.toString(),
+ isExternal: true,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['predictions'];
+ final predictionsList = list
+ .map((item) =>
+ PlacePrediction.fromJson(item as Map))
+ .toList()
+ .cast();
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: predictionsList,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> getGeoCodeFromLatLng(double lat, double lng) async {
+ final url = Uri.parse(
+ 'https://maps.googleapis.com/maps/api/geocode/json?latlng=$lat,$lng&key=$GOOGLE_API_KEY',
+ );
+
+
+ GenericApiModel? apiResponse;
+ Failure? failure;
+
+ try {
+ await apiClient.get(
+ url.toString(),
+ isExternal: true,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final predictionsList = GeocodeResponse.fromJson(response);
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: predictionsList,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> getPlaceDetailsOfSelectedPrediction(String placeId) async {
+
+
+ final url = Uri.parse(
+ 'https://maps.googleapis.com/maps/api/place/details/json'
+ '?place_id=$placeId&fields=geometry&key=$GOOGLE_API_KEY',
+ );
+
+ GenericApiModel? apiResponse;
+ Failure? failure;
+
+ try {
+ await apiClient.get(
+ url.toString(),
+ isExternal: true,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final predictionsList = PlaceDetails.fromJson(response);
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: predictionsList,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+}
diff --git a/lib/features/location/location_view_model.dart b/lib/features/location/location_view_model.dart
new file mode 100644
index 00000000..e7cd6853
--- /dev/null
+++ b/lib/features/location/location_view_model.dart
@@ -0,0 +1,120 @@
+import 'dart:async';
+
+import 'package:flutter/foundation.dart' show ChangeNotifier;
+import 'package:flutter/material.dart';
+import 'package:google_maps_flutter_platform_interface/src/types/camera.dart';
+import 'package:hmg_patient_app_new/features/location/GeocodeResponse.dart';
+import 'package:hmg_patient_app_new/features/location/PlaceDetails.dart';
+import 'package:hmg_patient_app_new/features/location/location_repo.dart';
+import 'package:hmg_patient_app_new/services/error_handler_service.dart';
+import 'package:huawei_map/huawei_map.dart' as HMSCameraServices;
+import 'package:google_maps_flutter/google_maps_flutter.dart' as GMSMapServices;
+
+
+
+import 'PlacePrediction.dart';
+
+class LocationViewModel extends ChangeNotifier {
+ final LocationRepo locationRepo;
+ final ErrorHandlerService errorHandlerService;
+
+ LocationViewModel({required this.locationRepo, required this.errorHandlerService});
+
+ List predictions = [];
+ PlacePrediction? selectedPrediction;
+ bool isPredictionLoading = false;
+ GeocodeResponse? geocodeResponse;
+ PlaceDetails? placeDetails;
+
+ Location? mapCapturedLocation;
+
+
+
+
+
+ FutureOr getPlacesPrediction(String input) async {
+ predictions = [];
+ isPredictionLoading= true;
+ final result = await locationRepo.getPlacePredictionsAsInput(input);
+ result.fold(
+ (failure) {
+ errorHandlerService.handleError(failure: failure);
+ },
+ (apiModel) {
+ predictions = apiModel.data??[];
+ },
+ );
+ isPredictionLoading = false;
+ notifyListeners();
+ }
+
+ FutureOr getPlaceEncodedData(double? lat, double? lng) async {
+ geocodeResponse = null;
+ final result = await locationRepo.getGeoCodeFromLatLng(lat!, lng!);
+ result.fold(
+ (failure) {
+ errorHandlerService.handleError(failure: failure);
+ },
+ (apiModel) {
+ print("Geocode Response: ${apiModel.data}");
+ geocodeResponse = apiModel.data;
+ },
+ );
+ notifyListeners();
+ }
+
+ FutureOr getPlaceDetails(String placeID) async {
+ placeDetails = null;
+ final result = await locationRepo.getPlaceDetailsOfSelectedPrediction(placeID);
+ result.fold(
+ (failure) {
+ errorHandlerService.handleError(failure: failure);
+ },
+ (apiModel) {
+ placeDetails = apiModel.data;
+ },
+ );
+ notifyListeners();
+ }
+
+ handleGMSMapCameraMoved(GMSMapServices.CameraPosition value) {
+ mapCapturedLocation = Location(lat: value.target.latitude, lng: value.target.longitude);
+
+ }
+
+ handleHMSMapCameraMoved(HMSCameraServices.CameraPosition value) {
+ mapCapturedLocation = Location(lat: value.target.lat, lng: value.target.lng);
+ }
+
+ handleOnCameraIdle(){
+ if(mapCapturedLocation != null) {
+ getPlaceEncodedData(mapCapturedLocation!.lat, mapCapturedLocation!.lng);
+ }
+ }
+
+ void updateSearchQuery(String? value) {
+ if(value == null || value.isEmpty){
+ predictions = [];
+ return;
+ }
+
+ getPlacesPrediction(value);
+ }
+
+ void flushSearchPredictions() {
+ predictions = [];
+ mapCapturedLocation= null;
+ placeDetails= null;
+ geocodeResponse= null;
+ selectedPrediction= null;
+
+ notifyListeners();
+ }
+
+ FutureOr selectPlacePrediction(PlacePrediction placePrediction) async{
+ selectedPrediction= placePrediction;
+ await getPlaceDetails(placePrediction.placeID);
+ }
+
+
+}
\ No newline at end of file
diff --git a/lib/features/my_appointments/models/resp_models/hospital_model.dart b/lib/features/my_appointments/models/resp_models/hospital_model.dart
index 342fcea6..9a211d04 100644
--- a/lib/features/my_appointments/models/resp_models/hospital_model.dart
+++ b/lib/features/my_appointments/models/resp_models/hospital_model.dart
@@ -101,4 +101,6 @@ class HospitalsModel {
data['UsingInDoctorApp'] = this.usingInDoctorApp;
return data;
}
+
+
}
diff --git a/lib/main.dart b/lib/main.dart
index 259ce3b5..6426244b 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -17,6 +17,7 @@ import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_liveca
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/lab/history/lab_history_viewmodel.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
+import 'package:hmg_patient_app_new/features/location/location_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/appointment_via_region_viewmodel.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
@@ -129,6 +130,8 @@ void main() async {
),
ChangeNotifierProvider(
create: (_) => getIt.get(),
+ ),ChangeNotifierProvider(
+ create: (_) => getIt.get(),
)
], child: MyApp()),
),
diff --git a/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart b/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart
index 31dc74ec..65d779e8 100644
--- a/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart
+++ b/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart
@@ -72,6 +72,7 @@ class HospitalListItem extends StatelessWidget {
);
Widget get distanceInfo => Row(
+ spacing: 4.w,
children: [
Visibility(
visible: (hospitalData?.distanceInKMs != "0"),
@@ -91,9 +92,9 @@ class HospitalListItem extends StatelessWidget {
labelText: "Distance not available".needTranslation,
textColor: AppColors.blackColor,
),
- SizedBox(
- width: 8.h,
- )
+ // SizedBox(
+ // width: 8.h,
+ // )
],
)),
Visibility(
diff --git a/lib/presentation/emergency_services/call_ambulance/call_ambulance_page.dart b/lib/presentation/emergency_services/call_ambulance/call_ambulance_page.dart
index eb36f92f..f39aaf29 100644
--- a/lib/presentation/emergency_services/call_ambulance/call_ambulance_page.dart
+++ b/lib/presentation/emergency_services/call_ambulance/call_ambulance_page.dart
@@ -8,10 +8,14 @@ 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/emergency_services/emergency_services_view_model.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/AmbulanceCallingPlace.dart';
+import 'package:hmg_patient_app_new/features/location/location_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/requesting_services_page.dart' show RequestingServicesPage;
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/tracking_screen.dart' show TrackingScreen;
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/widgets/HospitalBottomSheetBody.dart';
+import 'package:hmg_patient_app_new/presentation/emergency_services/widgets/location_input_bottom_sheet.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/CustomSwitch.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@@ -30,13 +34,37 @@ class CallAmbulancePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
- bottomSheet: ExpandableBottomSheet(
- bottomSheetType:
- context.watch().bottomSheetType,
- children: {
- BottomSheetType.EXPANDED: ExpanedBottomSheet(context),
- BottomSheetType.FIXED: FixedBottomSheet(context),
- },
+ floatingActionButton: Visibility(
+ visible: context.watch().bottomSheetType ==
+ BottomSheetType.FIXED,
+ child: Padding(
+ padding: EdgeInsetsDirectional.only(end: 8.h, bottom: 68.h),
+ child: DecoratedBox(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor, borderRadius: 12.h),
+ child: Utils.buildSvgWithAssets(
+ icon: AppAssets.locate_me, width: 24.h, height: 24.h)
+ .paddingAll(12.h)
+ .onPress(() {
+ context
+ .read()
+ .moveToCurrentLocation();
+ }),
+ ),
+ ),
+ ),
+ bottomSheet: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ ExpandableBottomSheet(
+ bottomSheetType:
+ context.watch().bottomSheetType,
+ children: {
+ BottomSheetType.EXPANDED: ExpanedBottomSheet(context),
+ BottomSheetType.FIXED: FixedBottomSheet(context),
+ },
+ ),
+ ],
),
body: Stack(
children: [
@@ -46,22 +74,40 @@ class CallAmbulancePage extends StatelessWidget {
currentLocation:
context.read().getGMSLocation(),
onCameraMoved: (value) => context
- .read()
- .handleGMSMapCameraMoved(value))
+ .read()
+ .handleGMSMapCameraMoved(value),
+ onCameraIdle:
+ context.read().handleOnCameraIdle,
+ myLocationEnabled: true,
+ inputController:
+ context.read().gmsController,
+ showCenterMarker: true,
+ )
else
HMSMap(
currentLocation:
context.read().getHMSLocation(),
onCameraMoved: (value) => context
- .read()
- .handleHMSMapCameraMoved(value)),
+ .read()
+ .handleHMSMapCameraMoved(value),
+ onCameraIdle:
+ context.read().handleOnCameraIdle,
+ myLocationEnabled: false,
+ inputController:
+ context.read().hmsController,
+ showCenterMarker: true,
+ ),
Align(
alignment: AlignmentDirectional.topStart,
child: Utils.buildSvgWithAssets(
- icon: AppAssets.closeBottomNav, width: 32.h, height: 32.h),
- ).paddingOnly(top: 51.h, left: 24.h).onPress((){
- Navigator.pop(context);
- })
+ icon: AppAssets.closeBottomNav, width: 32.h, height: 32.h)
+ .onPress(() {
+ context
+ .read()
+ .flushPickupInformation();
+ Navigator.pop(context);
+ }),
+ ).paddingOnly(top: 51.h, left: 24.h),
],
),
);
@@ -70,7 +116,6 @@ class CallAmbulancePage extends StatelessWidget {
Widget FixedBottomSheet(BuildContext context) {
return GestureDetector(
onVerticalDragUpdate: (details){
- print("the delta is ${details.delta.dy}");
if(details.delta.dy<0){
@@ -81,22 +126,24 @@ class CallAmbulancePage extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.end,
- children: [
- Padding(
-
- padding: EdgeInsetsDirectional.only(end:24.h, bottom: 24.h),
- child: DecoratedBox(
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
- color: AppColors.whiteColor, borderRadius: 12.h),
- child: Utils.buildSvgWithAssets(
- icon: AppAssets.locate_me, width: 24.h, height: 24.h)
- .paddingAll(12.h),
- ),
- ),
- ],
- ),
+ // Row(
+ // mainAxisAlignment: MainAxisAlignment.end,
+ // children: [
+ // Padding(
+ //
+ // padding: EdgeInsetsDirectional.only(end:24.h, bottom: 24.h),
+ // child: DecoratedBox(
+ // decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ // color: AppColors.whiteColor, borderRadius: 12.h),
+ // child: Utils.buildSvgWithAssets(
+ // icon: AppAssets.locate_me, width: 24.h, height: 24.h)
+ // .paddingAll(12.h).onPress((){
+ // context.read().moveToCurrentLocation();
+ // }),
+ // ),
+ // ),
+ // ],
+ // ),
// PositionedDirectional(
// end: 1,
// child: Padding(
@@ -116,25 +163,7 @@ class CallAmbulancePage extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
spacing: 24.h,
children: [
- TextInputWidget(
- labelText: "Enter Pickup Location Manually".needTranslation,
- hintText: "Enter Pickup Location".needTranslation,
- leadingIcon: AppAssets.location_pickup,
- isAllowLeadingIcon: true,
- isEnable: false,
- prefix: null,
- autoFocus: false,
- isBorderAllowed: false,
- keyboardType: TextInputType.text,
- padding: EdgeInsets.symmetric(
- vertical: ResponsiveExtension(10).h,
- horizontal: ResponsiveExtension(15).h,
- ),
- ).onPress(() {
- context
- .read()
- .updateBottomSheetState(BottomSheetType.EXPANDED);
- }).paddingOnly(right: 24.h, left: 24.h),
+ inputFields(context),
SizedBox(
height: 200.h,
child: DecoratedBox(
@@ -152,11 +181,11 @@ class CallAmbulancePage extends StatelessWidget {
Column(
spacing: 4.h,
children: [
- "Select Pickup Location".needTranslation.toText21(
+ "Select Pickup Details".needTranslation.toText21(
weight: FontWeight.w600,
color: AppColors.textColor,
),
- " Please select the location of pickup"
+ " Please select the details of pickup"
.needTranslation
.toText12(
fontWeight: FontWeight.w500,
@@ -165,7 +194,7 @@ class CallAmbulancePage extends StatelessWidget {
],
),
CustomButton(
- text: "Select Location".needTranslation,
+ text: "Select Details".needTranslation,
onPressed: () {
context
.read()
@@ -207,11 +236,11 @@ class CallAmbulancePage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 16.h,
children: [
- "Select Pickup Location".needTranslation.toText21(
- weight: FontWeight.w600,
- color: AppColors.textColor,
- ),
- locationsSections(context),
+ // "Select Pickup Location".needTranslation.toText21(
+ // weight: FontWeight.w600,
+ // color: AppColors.textColor,
+ // ),
+ // locationsSections(context),
hospitalAndPickUpSection(context),
],
@@ -281,44 +310,72 @@ class CallAmbulancePage extends StatelessWidget {
return DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
- borderRadius: 24.h,
+ borderRadius: 24.r,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
+ spacing: 16.h,
children: [
+ // Row(
+ // children: [
+ // hospitalAndPickUpItemContent(
+ // title: "Select Hospital".needTranslation,
+ // subTitle: "hospital".needTranslation,
+ // leadingIcon: AppAssets.hospital,
+ // ),
+ // Utils.buildSvgWithAssets(icon: AppAssets.down_cheveron,
+ // width: 24.h, height: 24.h)
+ // .paddingAll(16.h)
+ // ],
+ // ).onPress((){
+ // showHospitalBottomSheet(context);
+ // }),
+ // SizedBox(height: 16.h),
+ // Divider(
+ // color: AppColors.bottomNAVBorder,
+ // height: 1,
+ // thickness: 1,
+ // ),
+ // SizedBox(height: 16.h),
+
Row(
children: [
hospitalAndPickUpItemContent(
- title: "Select Hospital".needTranslation,
- subTitle: "hospital".needTranslation,
- leadingIcon: AppAssets.hospital,
+ title: "Pick".needTranslation,
+ subTitle: "Inside the home".needTranslation,
+ leadingIcon: AppAssets.pickup_bed,
),
- Utils.buildSvgWithAssets(icon: AppAssets.down_cheveron,
- width: 24.h, height: 24.h)
- .paddingAll(16.h)
+ CustomSwitch(
+ value: context
+ .watch()
+ .pickupFromInsideTheLocation,
+ onChanged: (value){
+ context
+ .read()
+ .updateThePickupPlaceFromLocation(value);
+ },
+ )
],
- ).onPress((){
- showHospitalBottomSheet(context);
- }),
- SizedBox(height: 16.h),
- Divider(
- color: AppColors.bottomNAVBorder,
- height: 1,
- thickness: 1,
),
- SizedBox(height: 16.h),
Row(
children: [
hospitalAndPickUpItemContent(
- title: "Pick".needTranslation,
- subTitle: "Inside the home".needTranslation,
- leadingIcon: AppAssets.pickup_bed,
+ title: '',
+ subTitle: "Have any appointment".needTranslation,
+ leadingIcon: AppAssets.appointment_checkin_icon,
),
CustomSwitch(
- value: context.watch().isGMSAvailable,
- onChanged: (value){
- context.read().setIsGMSAvailable( value);
+ value: context
+ .watch()
+ .haveAnAppointment,
+ onChanged: (value) {
+ if (value) {
+ openAppointmentList(context);
+ }
+ context
+ .read()
+ .updateAppointment(value);
},
)
],
@@ -354,13 +411,22 @@ class CallAmbulancePage extends StatelessWidget {
this.leadingIcon(leadingIcon),
Expanded(
child: Column(
+ mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.center,
children: [
- title.toText12(
- color: AppColors.greyTextColor,
- fontWeight: FontWeight.w500,
+ Visibility(
+ visible: title.isNotEmpty,
+ child: Column(
+ children: [
+ title.toText12(
+ color: AppColors.greyTextColor,
+ fontWeight: FontWeight.w500,
+ ),
+ SizedBox(height: 2.h),
+ ],
+ ),
),
- SizedBox(height: 2.h),
subTitle.toText14(
color: AppColors.textColor,
weight: FontWeight.w500,
@@ -418,15 +484,24 @@ class CallAmbulancePage extends StatelessWidget {
],
),
),
- "\$250".toText24(
- fontWeight: FontWeight.w600,
- color: AppColors.textColor,
- )
- ],
- ),
- CustomButton(
- text: "Submit Request".needTranslation,
- onPressed: () {
+ Utils.getPaymentAmountWithSymbol(
+ (Utils.formatNumberToInternationalFormat(context
+ .read()
+ .getTotalPrice() ??
+ 0))
+ .toText24(
+ fontWeight: FontWeight.w600,
+ color: AppColors.textColor,
+ letterSpacing: -2),
+ AppColors.blackColor,
+ 17.h)
+
+ // Utils.getPaymentAmountWithSymbol2(context.read().selectedTransportOption?.priceTotal??"0", letterSpacing: -2)
+ ],
+ ),
+ CustomButton(
+ text: "Submit Request".needTranslation,
+ onPressed: () {
Navigator.push(context, CustomPageRoute(page: RequestingServicesPage()));
})
],
@@ -441,7 +516,26 @@ class CallAmbulancePage extends StatelessWidget {
title:
LocaleKeys.selectHospital.tr(),
context,
- child: HospitalBottomSheetBody(),
+ child: Consumer(
+ builder:(_,vm,__)=> HospitalBottomSheetBody(
+ displayList: vm.displayList,
+ onFacilityClicked: (value) {
+ vm.setSelectedFacility(value);
+ vm.getDisplayList();
+ },
+ onHospitalClicked: (hospital) {
+ Navigator.pop(context);
+ vm.setSelectedHospital(hospital);
+ },
+ onHospitalSearch: (value) {
+ vm.searchHospitals(value ?? "");
+ },
+ selectedFacility:
+ vm.selectedFacility,
+ hmcCount: vm.hmcCount,
+ hmgCount: vm.hmgCount,
+ ),
+ ),
isFullScreen: false,
isCloseButtonVisible: true,
hasBottomPadding: false,
@@ -449,4 +543,124 @@ class CallAmbulancePage extends StatelessWidget {
callBackFunc: () {},
);
}
+
+ ///it will show the places field first and then hospital field
+ PlaceFirstThanHospitalField(BuildContext context) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ spacing: 16.h,
+ children: [
+ textPlaceInput(context),
+ hospitalField(context),
+ ],
+ ).paddingOnly(right: 24.h, left: 24.h);
+ }
+
+ HospitalFieldFirstThanPlaces(BuildContext context) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ spacing: 16.h,
+ children: [hospitalField(context), textPlaceInput(context)],
+ ).paddingOnly(right: 24.h, left: 24.h);
+ }
+
+ textPlaceInput(context) {
+ return Consumer(builder: (_, vm, __) {
+ print(
+ "the data is ${vm.geocodeResponse?.results.first.formattedAddress ?? vm.selectedPrediction?.description}");
+ return SizedBox(
+ width: MediaQuery.sizeOf(context).width,
+ child: TextInputWidget(
+ labelText: "Enter Pickup Location Manually".needTranslation,
+ hintText: "Enter Pickup Location".needTranslation,
+ controller: TextEditingController(
+ text: vm.geocodeResponse?.results.first.formattedAddress ??
+ vm.selectedPrediction?.description,
+ ),
+ leadingIcon: AppAssets.location_pickup,
+ isAllowLeadingIcon: true,
+ isEnable: false,
+ prefix: null,
+ autoFocus: false,
+ isBorderAllowed: false,
+ keyboardType: TextInputType.text,
+ padding: EdgeInsets.symmetric(
+ vertical: ResponsiveExtension(10).h,
+ horizontal: ResponsiveExtension(15).h,
+ ),
+ ).onPress(() {
+ openLocationInputBottomSheet(context);
+ }),
+ );
+ });
+ }
+
+ ///decide which field to show first based on the selected calling place
+ inputFields(BuildContext context) {
+ return context.read().callingPlace ==
+ AmbulanceCallingPlace.FROM_HOSPITAL
+ ? HospitalFieldFirstThanPlaces(context)
+ : PlaceFirstThanHospitalField(context);
+ }
+
+ openLocationInputBottomSheet(BuildContext context) {
+ context.read().flushSearchPredictions();
+ showCommonBottomSheetWithoutHeight(
+ title: "".needTranslation,
+ context,
+ child: SizedBox(
+ height: MediaQuery.sizeOf(context).height * .8,
+ child: LocationInputBottomSheet(),
+ ),
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ hasBottomPadding: false,
+ backgroundColor: AppColors.bottomSheetBgColor,
+ callBackFunc: () {},
+ );
+ }
+
+ hospitalField(BuildContext context) {
+ return DecoratedBox(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor, borderRadius: 12.h),
+ child: Row(
+ children: [
+ hospitalAndPickUpItemContent(
+ title: "Select Hospital".needTranslation,
+ subTitle: context
+ .read()
+ .getSelectedHospitalName() ??
+ "hospital".needTranslation,
+ leadingIcon: AppAssets.hospital,
+ ),
+ Utils.buildSvgWithAssets(
+ icon: AppAssets.down_cheveron, width: 24.h, height: 24.h)
+ .paddingAll(16.h)
+ ],
+ ).onPress(() {
+ print("the item is clicked");
+ showHospitalBottomSheet(context);
+ }).paddingSymmetrical(
+ 10.w,
+ 12.h,
+ ),
+ );
+ }
+
+ void openAppointmentList(BuildContext context) {
+ // showCommonBottomSheetWithoutHeight(
+ // title: "".needTranslation,
+ // context,
+ // child: SizedBox(
+ // height: MediaQuery.sizeOf(context).height * .6,
+ // child: AppointmentBottomSheet(),
+ // ),
+ // isFullScreen: false,
+ // isCloseButtonVisible: true,
+ // hasBottomPadding: false,
+ // backgroundColor: AppColors.bottomSheetBgColor,
+ // callBackFunc: () {},
+ // );
+ }
}
diff --git a/lib/presentation/emergency_services/call_ambulance/tracking_screen.dart b/lib/presentation/emergency_services/call_ambulance/tracking_screen.dart
index 9df05586..c0f31e16 100644
--- a/lib/presentation/emergency_services/call_ambulance/tracking_screen.dart
+++ b/lib/presentation/emergency_services/call_ambulance/tracking_screen.dart
@@ -203,11 +203,17 @@ class TrackingScreen extends StatelessWidget {
if (context.read().isGMSAvailable || Platform.isIOS) {
return GMSMap(
myLocationEnabled: false,
+ onCameraIdle: (){
+
+ },
currentLocation: context.read().getGMSLocation(),
onCameraMoved: (value) => context.read().handleGMSMapCameraMoved(value));
} else {
return HMSMap(
myLocationEnabled: false,
+ onCameraIdle: (){
+
+ },
currentLocation: context.read().getHMSLocation(),
onCameraMoved: (value) => context.read().handleHMSMapCameraMoved(value));
}
diff --git a/lib/presentation/emergency_services/call_ambulance/widgets/HospitalBottomSheetBody.dart b/lib/presentation/emergency_services/call_ambulance/widgets/HospitalBottomSheetBody.dart
index c594888f..14ea705e 100644
--- a/lib/presentation/emergency_services/call_ambulance/widgets/HospitalBottomSheetBody.dart
+++ b/lib/presentation/emergency_services/call_ambulance/widgets/HospitalBottomSheetBody.dart
@@ -2,12 +2,17 @@ import 'package:easy_localization/easy_localization.dart'
show tr, StringTranslateExtension;
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
+import 'package:hmg_patient_app_new/core/utils/debouncer.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/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/my_appointments/appointment_via_region_viewmodel.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/facility_selection.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart' show HospitalsModel;
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/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart';
@@ -20,8 +25,20 @@ import 'package:provider/provider.dart';
class HospitalBottomSheetBody extends StatelessWidget {
final TextEditingController searchText = TextEditingController();
+ final Debouncer debouncer = Debouncer(milliseconds: 500);
- HospitalBottomSheetBody({super.key});
+
+ final int hmcCount;
+ final int hmgCount;
+ final List? displayList;
+ final FacilitySelection selectedFacility;
+ final Function(FacilitySelection) onFacilityClicked;
+ final Function(HospitalsModel) onHospitalClicked;
+ final Function(String) onHospitalSearch;
+
+
+
+ HospitalBottomSheetBody({super.key, required this.hmcCount, required this.hmgCount, this.displayList, required this.selectedFacility, required this.onFacilityClicked, required this.onHospitalClicked, required this.onHospitalSearch});
@override
Widget build(BuildContext context) {
@@ -29,13 +46,14 @@ class HospitalBottomSheetBody extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
-
TextInputWidget(
labelText: LocaleKeys.search.tr(),
hintText: LocaleKeys.searchHospital.tr(),
controller: searchText,
onChange: (value) {
-
+ debouncer.run((){
+ onHospitalSearch(value??"");
+ });
},
isEnable: true,
prefix: null,
@@ -51,10 +69,11 @@ class HospitalBottomSheetBody extends StatelessWidget {
),
SizedBox(height: 24.h),
TypeSelectionWidget(
- hmcCount: "0",
- hmgCount: "0",
+ selectedFacility:selectedFacility ,
+ hmcCount: hmcCount.toString(),
+ hmgCount: hmgCount.toString(),
onitemClicked: (selectedValue){
-
+ onFacilityClicked(selectedValue);
},
),
SizedBox(height: 21.h),
@@ -63,17 +82,17 @@ class HospitalBottomSheetBody extends StatelessWidget {
child: ListView.separated(
itemBuilder: (_, index)
{
- var hospital = null;
+ var hospital = displayList?[index];
return HospitalListItem(
- hospitalData: hospital,
- isLocationEnabled: false,
+ hospitalData: Utils.convertToPatientDoctorAppointmentList(hospital),
+ isLocationEnabled: true,
).onPress(() {
-
+ onHospitalClicked(hospital!);
});},
separatorBuilder: (_, __) => SizedBox(
height: 16.h,
),
- itemCount: 0,
+ itemCount: displayList?.length ?? 0,
))
],
);
diff --git a/lib/presentation/emergency_services/call_ambulance/widgets/ambulance_option_selection_bottomsheet.dart b/lib/presentation/emergency_services/call_ambulance/widgets/ambulance_option_selection_bottomsheet.dart
index 564bd640..de20d1aa 100644
--- a/lib/presentation/emergency_services/call_ambulance/widgets/ambulance_option_selection_bottomsheet.dart
+++ b/lib/presentation/emergency_services/call_ambulance/widgets/ambulance_option_selection_bottomsheet.dart
@@ -1,10 +1,14 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart' show AppAssets;
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart' show Utils;
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/emergency_services/emergency_services_view_model.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/PatientERTransportationMethod.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/widgets/transport_option_Item.dart' show TransportOptionItem;
import 'package:hmg_patient_app_new/theme/colors.dart';
+import 'package:provider/provider.dart';
class AmbulanceOptionSelectionBottomSheet extends StatelessWidget {
final Function onTap;
@@ -12,40 +16,36 @@ class AmbulanceOptionSelectionBottomSheet extends StatelessWidget {
const AmbulanceOptionSelectionBottomSheet({super.key, required this.onTap});
@override
Widget build(BuildContext context) {
- return Column(
- spacing: 16.h,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
+ return Selector>(
+ selector: (_, model) => model.transportationOptions,
+ builder: (_, data, __) => Column(
+ spacing: 16.h,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Expanded(
+ child: ListView.separated(
+ separatorBuilder: (_,__)=> SizedBox(
+ height: 16.h,
+ ),
+ itemCount: data.length??0,
+ itemBuilder: (_, index) => TransportOptionItem(
+ title: Utils.getTextWRTCurrentLanguage(data[index].text, data[index].textN),
+ subTitle: "",
+ firstIcon: AppAssets.location_pickup,
+ middleIcon: AppAssets.to_arrow,
+ lastIcon: AppAssets.hospital,
+ price: data[index].priceTotal.toString(),
+ onTap: () {
+ onTap();
+ context.read().setTransportationOption(data[index]);
+ },
+ ),
+ ),
+ ),
- TransportOptionItem(
- title: "Home to Hospital (One Way)",
- subTitle: "Pickup from home location to hospital",
- firstIcon: AppAssets.location_pickup,
- middleIcon:AppAssets.to_arrow,
- lastIcon: AppAssets.hospital,
- price: "150 AED",
- onTap: (){onTap();},
- ),
- TransportOptionItem(
- title: "Hospital to Home (One Way)",
- subTitle: "Pickup from hospital to home",
- lastIcon: AppAssets.location_pickup,
- middleIcon:AppAssets.to_arrow,
- firstIcon: AppAssets.hospital,
- price: "150 AED",
- onTap: (){onTap();},
- ),
- TransportOptionItem(
- title: "Home to Hospital (Two Way)",
- subTitle: "Pick from home to hospital then drop off to home",
- firstIcon: AppAssets.location_pickup,
- middleIcon:AppAssets.dual_arrow,
- lastIcon: AppAssets.hospital,
- price: "150 AED",
- onTap: (){onTap();},
- ),
- SizedBox(height: 16.h,)
- ],
+ ],
+ ),
);
}
}
diff --git a/lib/presentation/emergency_services/call_ambulance/widgets/appointment_bottom_sheet.dart b/lib/presentation/emergency_services/call_ambulance/widgets/appointment_bottom_sheet.dart
new file mode 100644
index 00000000..8616fc33
--- /dev/null
+++ b/lib/presentation/emergency_services/call_ambulance/widgets/appointment_bottom_sheet.dart
@@ -0,0 +1,92 @@
+// import 'package:flutter/cupertino.dart';
+// import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
+// import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
+// import 'package:hmg_patient_app_new/features/emergency_services/emergency_services_view_model.dart';
+// import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
+// import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_card.dart';
+// import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/doctor_card.dart';
+// import 'package:hmg_patient_app_new/theme/colors.dart';
+// import 'package:provider/provider.dart';
+//
+// class AppointmentBottomSheet extends StatelessWidget{
+// @override
+// Widget build(BuildContext context) {
+// // TODO: implement build
+// throw UnimplementedError();
+// }
+//
+// Widget getAppointList(EmergencyServicesViewModel viewmodel, List filteredAppointmentList) {
+// return Column(
+// crossAxisAlignment: CrossAxisAlignment.start,
+// children: [
+// ListView.separated(
+// padding: EdgeInsets.only(top: 24.h),
+// shrinkWrap: true,
+// physics: NeverScrollableScrollPhysics(),
+// itemCount: viewmodel.isMyAppointmentsLoading
+// ? 5
+// : filteredAppointmentList.isNotEmpty
+// ? filteredAppointmentList.length
+// : 1,
+// itemBuilder: (context, index) {
+// return viewmodel.isMyAppointmentsLoading
+// ? Container(
+// decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
+// child: DoctorCard(doctorsListResponseModel: doctorsListResponseModel, isLoading: viewmodel.isMyAppointmentsLoading, bookAppointmentsViewModel: bookAppointmentsViewModel),
+// ).paddingSymmetrical(24.h, 0.h)
+// : filteredAppointmentList.isNotEmpty
+// ? AnimationConfiguration.staggeredList(
+// position: index,
+// duration: const Duration(milliseconds: 500),
+// child: SlideAnimation(
+// verticalOffset: 100.0,
+// child: FadeInAnimation(
+// child: AnimatedContainer(
+// duration: Duration(milliseconds: 300),
+// curve: Curves.easeInOut,
+// decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
+// child: AppointmentCard(
+// patientAppointmentHistoryResponseModel: filteredAppointmentList[index],
+// myAppointmentsViewModel: myAppointmentsViewModel,
+// bookAppointmentsViewModel: bookAppointmentsViewModel,
+// isLoading: false,
+// isFromHomePage: false,
+// ),
+// ).paddingSymmetrical(24.h, 0.h),
+// ),
+// ),
+// )
+// : Utils.getNoDataWidget(
+// context,
+// noDataText: "You don't have any appointments yet.".needTranslation,
+// callToActionButton: CustomButton(
+// text: LocaleKeys.bookAppo.tr(context: context),
+// onPressed: () {
+// Navigator.of(context).push(
+// CustomPageRoute(
+// page: BookAppointmentPage(),
+// ),
+// );
+// },
+// backgroundColor: Color(0xffFEE9EA),
+// borderColor: Color(0xffFEE9EA),
+// textColor: Color(0xffED1C2B),
+// fontSize: 14.f,
+// fontWeight: FontWeight.w500,
+// borderRadius: 12.r,
+// padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0),
+// height: 40.h,
+// icon: AppAssets.add_icon,
+// iconColor: AppColors.primaryRedColor,
+// ).paddingSymmetrical(48.h, 0.h),
+// );
+// },
+// separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
+// ),
+// SizedBox(height: 24.h),
+// ],
+// );
+// }
+//
+//
+// }
\ No newline at end of file
diff --git a/lib/presentation/emergency_services/call_ambulance/widgets/pickup_location.dart b/lib/presentation/emergency_services/call_ambulance/widgets/pickup_location.dart
new file mode 100644
index 00000000..5d073d4b
--- /dev/null
+++ b/lib/presentation/emergency_services/call_ambulance/widgets/pickup_location.dart
@@ -0,0 +1,172 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.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/widget_extensions.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/emergency_services_view_model.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/AmbulanceCallingPlace.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/ambulance_direction.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
+import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
+import 'package:provider/provider.dart';
+
+import '../../../../generated/locale_keys.g.dart' show LocaleKeys;
+
+class PickupLocation extends StatelessWidget {
+ final VoidCallback onTap;
+ const PickupLocation({super.key, required this.onTap});
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Select Pickup Direction"
+ .needTranslation
+ .toText24(color: AppColors.textColor,isBold: true),
+ SizedBox(
+ height: 16.h,
+ ),
+ "Select Direction"
+ .needTranslation
+ .toText14(color: AppColors.textColor, weight: FontWeight.w600),
+ SizedBox(
+ height: 12.h,
+ ),
+ Selector(
+ selector: (context, viewModel) => viewModel.callingPlace,
+ builder: (context, value, _) {
+ return Column(
+ spacing: 12.h,
+ children: [
+ RadioGroup(
+ groupValue: value,
+ onChanged: (value) {
+ context
+ .read()
+ .updateCallingPlace(value);
+ },
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ spacing: 24.h,
+ children: [
+ Row(
+ children: [
+ Radio(
+ value: AmbulanceCallingPlace.TO_HOSPITAL,
+ groupValue: value,
+ activeColor: AppColors.primaryRedColor,
+
+ fillColor: MaterialStateProperty.all(AppColors.primaryRedColor),
+ ),
+ "To Hospital"
+ .needTranslation
+ .toText12(color: AppColors.textColor)
+ ],
+ ).onPress((){
+ context
+ .read()
+ .updateCallingPlace(AmbulanceCallingPlace.TO_HOSPITAL);
+ }),
+ Row(
+ children: [
+ Radio(
+ value: AmbulanceCallingPlace.FROM_HOSPITAL,
+ activeColor: AppColors.primaryRedColor,
+
+ fillColor: MaterialStateProperty.all(AppColors.primaryRedColor),
+ ),
+ "From Hospital"
+ .needTranslation
+ .toText12(color: AppColors.textColor)
+ ],
+ ).onPress((){
+ context
+ .read()
+ .updateCallingPlace(AmbulanceCallingPlace.FROM_HOSPITAL);
+ }),
+ ],
+ ),
+ ),
+ Visibility(
+ visible: value == AmbulanceCallingPlace.TO_HOSPITAL,
+ child: Selector(
+ selector: (context, viewModel) =>
+ viewModel.ambulanceDirection,
+ builder: (context, directionValue, _) {
+ return Column(
+ spacing: 12.h,
+ children: [
+ "Select Way"
+ .needTranslation
+ .toText14(color: AppColors.textColor, weight: FontWeight.w600),
+ RadioGroup(
+ groupValue: directionValue,
+ onChanged: (value) {
+ context
+ .read()
+ .updateDirection(value);
+ },
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ spacing: 24.h,
+ children: [
+ Row(
+ children: [
+ Radio(
+ value: AmbulanceDirection.ONE_WAY,
+ activeColor: AppColors.primaryRedColor,
+
+ fillColor: MaterialStateProperty.all(AppColors.primaryRedColor),
+ ),
+ "One Way"
+ .needTranslation
+ .toText12(color: AppColors.textColor)
+ ],
+ ).onPress((){
+ context
+ .read()
+ .updateDirection(AmbulanceDirection.ONE_WAY);
+ }),
+ Row(
+ children: [
+ Radio(
+ value: AmbulanceDirection.TWO_WAY,
+ // activeColor: AppColors.primaryRedColor,
+
+ fillColor: MaterialStateProperty.all(AppColors.primaryRedColor),
+ ),
+ "Two Way"
+ .needTranslation
+ .toText12(color: AppColors.textColor)
+ ],
+ ).onPress((){
+ context
+ .read()
+ .updateDirection(AmbulanceDirection.TWO_WAY);
+ }),
+ ],
+ ),
+ ),
+ ],
+ );
+ }),
+ )
+ ],
+ );
+ }),
+ SizedBox(
+ height: 16.h,
+ ),
+ CustomButton(
+ text: LocaleKeys.confirm.tr(context: context),
+ onPressed: onTap,
+ backgroundColor: AppColors.primaryRedColor,
+ borderColor: AppColors.primaryRedColor,
+ textColor: AppColors.whiteColor,
+ iconColor: AppColors.whiteColor,
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/presentation/emergency_services/call_ambulance/widgets/transport_option_Item.dart b/lib/presentation/emergency_services/call_ambulance/widgets/transport_option_Item.dart
index 25118241..9a959ebb 100644
--- a/lib/presentation/emergency_services/call_ambulance/widgets/transport_option_Item.dart
+++ b/lib/presentation/emergency_services/call_ambulance/widgets/transport_option_Item.dart
@@ -48,7 +48,6 @@ class TransportOptionItem extends StatelessWidget {
titleSection() {
return Row(
-
children: [
Expanded(
child: Column(
@@ -56,8 +55,8 @@ class TransportOptionItem extends StatelessWidget {
children: [
title.toText16(
color: AppColors.textColor, weight: FontWeight.w600),
- subTitle.toText12(
- color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
+ // subTitle.toText12(
+ // color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
],
),
),
@@ -69,18 +68,23 @@ class TransportOptionItem extends StatelessWidget {
headerSection() {
return Row(
+ mainAxisAlignment: MainAxisAlignment.end,
children: [
- Expanded(
- child: Row(
- children: [
- buildIcon(firstIcon),
- Utils.buildSvgWithAssets(
- icon: middleIcon, width: 24.h, height: 24.h).paddingAll(8.h),
- buildIcon(lastIcon)
- ],
- ),
+ // Expanded(
+ // child: Row(
+ // children: [
+ // buildIcon(firstIcon),
+ // Utils.buildSvgWithAssets(
+ // icon: middleIcon, width: 24.h, height: 24.h).paddingAll(8.h),
+ // buildIcon(lastIcon)
+ // ],
+ // ),
+ // ),
+ Utils.getPaymentAmountWithSymbol2(
+ num.tryParse(price) ?? 0.0,
+ fontSize: 18.f,
+ letterSpacing:-2
),
- price.toText18(color: AppColors.textColor, weight: FontWeight.w600)
],
);
}
diff --git a/lib/presentation/emergency_services/call_ambulance/widgets/type_selection_widget.dart b/lib/presentation/emergency_services/call_ambulance/widgets/type_selection_widget.dart
index c1ab8a84..d2e9b211 100644
--- a/lib/presentation/emergency_services/call_ambulance/widgets/type_selection_widget.dart
+++ b/lib/presentation/emergency_services/call_ambulance/widgets/type_selection_widget.dart
@@ -12,10 +12,15 @@ import 'package:provider/provider.dart' show Consumer;
class TypeSelectionWidget extends StatelessWidget {
final String hmcCount;
final String hmgCount;
- final Function(String) onitemClicked;
+ final FacilitySelection selectedFacility;
+ final Function(FacilitySelection) onitemClicked;
const TypeSelectionWidget(
- {super.key, required this.hmcCount, required this.hmgCount, required this.onitemClicked});
+ {super.key,
+ required this.hmcCount,
+ required this.hmgCount,
+ required this.onitemClicked,
+ required this.selectedFacility});
@override
Widget build(BuildContext context) {
@@ -28,51 +33,69 @@ class TypeSelectionWidget extends StatelessWidget {
labelText: "All Facilities".needTranslation,
shape: RoundedRectangleBorder(
side: BorderSide(
- color: AppColors.errorColor
- ,
+ color: selectedFacility == FacilitySelection.ALL
+ ? AppColors.errorColor
+ : AppColors.chipBorderColorOpacity20,
width: 1,
),
borderRadius: BorderRadius.circular(10)),
backgroundColor:
- AppColors.secondaryLightRedColor
- ,
- textColor: AppColors.errorColor
+ selectedFacility == FacilitySelection.ALL
+ ?AppColors.secondaryLightRedColor: AppColors.whiteColor,
+ textColor: selectedFacility == FacilitySelection.ALL
+ ? AppColors.errorColor:AppColors.blackColor
,
).onPress((){
- onitemClicked(FacilitySelection.ALL.name);
- }),
- AppCustomChipWidget(
- icon: AppAssets.hmg,
- iconHasColor: false,
- labelText: "Hospitals".needTranslation,
- shape: RoundedRectangleBorder(
- side: BorderSide(
- color: AppColors.chipBorderColorOpacity20,
- width: 1,
- ),
- borderRadius: BorderRadius.circular(10)),
- backgroundColor:
- AppColors.whiteColor,
- textColor: AppColors.blackColor,
- ).onPress((){
- onitemClicked(FacilitySelection.HMG.name);
- }),
- AppCustomChipWidget(
- icon: AppAssets.hmc,
- iconHasColor: false,
- labelText: "Medical Centers".needTranslation,
- shape: RoundedRectangleBorder(
- side: BorderSide(
- color:AppColors.chipBorderColorOpacity20,
- width: 1,
- ),
- borderRadius: BorderRadius.circular(10)),
- backgroundColor:
- AppColors.whiteColor,
- textColor: AppColors.blackColor,
- ).onPress((){
- onitemClicked(FacilitySelection.HMC.name);
+ onitemClicked(FacilitySelection.ALL);
}),
+ Visibility(
+ visible: hmgCount != "0",
+ child: AppCustomChipWidget(
+ icon: AppAssets.hmg,
+ iconHasColor: false,
+ labelText: "Hospitals".needTranslation,
+ shape: RoundedRectangleBorder(
+ side: BorderSide(
+ color: selectedFacility == FacilitySelection.HMG
+ ? AppColors.errorColor
+ : AppColors.chipBorderColorOpacity20,
+ width: 1,
+ ),
+ borderRadius: BorderRadius.circular(10)),
+ backgroundColor:
+ selectedFacility == FacilitySelection.HMG
+ ?AppColors.secondaryLightRedColor: AppColors.whiteColor,
+ textColor: selectedFacility == FacilitySelection.HMG
+ ? AppColors.errorColor
+ : AppColors.blackColor,
+ ).onPress((){
+ onitemClicked(FacilitySelection.HMG);
+ }),
+ ),
+ Visibility(
+ visible: hmcCount != "0",
+ child: AppCustomChipWidget(
+ icon: AppAssets.hmc,
+ iconHasColor: false,
+ labelText: "Medical Centers".needTranslation,
+ shape: RoundedRectangleBorder(
+ side: BorderSide(
+ color: selectedFacility == FacilitySelection.HMC
+ ? AppColors.errorColor
+ : AppColors.chipBorderColorOpacity20,
+ width: 1,
+ ),
+ borderRadius: BorderRadius.circular(10)),
+ backgroundColor:
+ selectedFacility == FacilitySelection.HMC
+ ?AppColors.secondaryLightRedColor: AppColors.whiteColor,
+ textColor: selectedFacility == FacilitySelection.HMC
+ ? AppColors.errorColor
+ : AppColors.blackColor,
+ ).onPress((){
+ onitemClicked(FacilitySelection.HMC);
+ }),
+ ),
],
);
}
diff --git a/lib/presentation/emergency_services/emergency_services_page.dart b/lib/presentation/emergency_services/emergency_services_page.dart
index ddea6fd1..5bd0afe2 100644
--- a/lib/presentation/emergency_services/emergency_services_page.dart
+++ b/lib/presentation/emergency_services/emergency_services_page.dart
@@ -8,10 +8,12 @@ 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/emergency_services/emergency_services_view_model.dart';
+import 'package:hmg_patient_app_new/features/location/location_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/RRT/rrt_request_type_select.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/call_ambulance_page.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/widgets/ambulance_option_selection_bottomsheet.dart';
+import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/widgets/pickup_location.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/nearest_er_page.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
@@ -114,23 +116,8 @@ class EmergencyServicesPage extends StatelessWidget {
onPressed: () async {
//
Navigator.of(context).pop();
- showCommonBottomSheetWithoutHeight(
- title:
- "Transport Options".needTranslation,
- context,
- child: AmbulanceOptionSelectionBottomSheet(
- onTap: () {
- Navigator.of(context).pop();
- context
- .read()
- .navigateTOAmbulancePage();
- }),
- isFullScreen: false,
- isCloseButtonVisible: true,
- hasBottomPadding: false,
- backgroundColor: AppColors.bottomSheetBgColor,
- callBackFunc: () {},
- );
+ await emergencyServicesViewModel.getTransportationOption();
+ openTranportationSelectionBottomSheet(context);
},
backgroundColor: AppColors.whiteColor,
borderColor: AppColors.whiteColor,
@@ -276,4 +263,68 @@ class EmergencyServicesPage extends StatelessWidget {
),
);
}
+
+ openPickupDetailsBottomSheet(BuildContext context){
+ showCommonBottomSheetWithoutHeight(
+ onCloseClicked: (){
+ context
+ .read()
+ .flushPickupInformation();
+ },
+ titleWidget: Transform.flip(
+ flipX: emergencyServicesViewModel.isArabic ? true : false,
+ child: Utils.buildSvgWithAssets(
+ icon: AppAssets.arrow_back,
+ iconColor: Color(0xff2B353E),
+ fit: BoxFit.contain,
+ ),
+ ).onPress(() {
+ context
+ .read()
+ .flushPickupInformation();
+ Navigator.pop(context);
+ openTranportationSelectionBottomSheet(context);
+ }),
+ context,
+ child: PickupLocation(
+ onTap: () {
+ Navigator.of(context).pop();
+ context.read().flushSearchPredictions();
+ context
+ .read()
+ .navigateTOAmbulancePage();
+ }),
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ hasBottomPadding: false,
+
+ backgroundColor: AppColors.bottomSheetBgColor,
+ callBackFunc: () {},
+ );
+ }
+
+ void openTranportationSelectionBottomSheet(BuildContext context) {
+ if(emergencyServicesViewModel.transportationOptions.isNotEmpty) {
+ showCommonBottomSheetWithoutHeight(
+ title: "Transport Options".needTranslation,
+ context,
+ child: SizedBox(
+ height: 400.h,
+ child: AmbulanceOptionSelectionBottomSheet(
+ onTap: () {
+ Navigator.of(context).pop();
+ openPickupDetailsBottomSheet(context);
+ // context
+ // .read()
+ // .navigateTOAmbulancePage();
+ }),
+ ),
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ hasBottomPadding: false,
+ backgroundColor: AppColors.bottomSheetBgColor,
+ callBackFunc: () {},
+ );
+ }
+ }
}
diff --git a/lib/presentation/emergency_services/nearest_er_page.dart b/lib/presentation/emergency_services/nearest_er_page.dart
index 8138f577..13373f1c 100644
--- a/lib/presentation/emergency_services/nearest_er_page.dart
+++ b/lib/presentation/emergency_services/nearest_er_page.dart
@@ -7,7 +7,7 @@ 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/emergency_services/emergency_services_view_model.dart';
-import 'package:hmg_patient_app_new/features/emergency_services/model/resp_model/ProjectAvgERWaitingTime.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/ProjectAvgERWaitingTime.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/widgets/nearestERItem.dart' show NearestERItem;
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
diff --git a/lib/presentation/emergency_services/widgets/location_input_bottom_sheet.dart b/lib/presentation/emergency_services/widgets/location_input_bottom_sheet.dart
new file mode 100644
index 00000000..559a0a5d
--- /dev/null
+++ b/lib/presentation/emergency_services/widgets/location_input_bottom_sheet.dart
@@ -0,0 +1,118 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'
+ show AnimationConfiguration, SlideAnimation, FadeInAnimation;
+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/enums.dart';
+import 'package:hmg_patient_app_new/core/utils/debouncer.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/emergency_services/emergency_services_view_model.dart';
+import 'package:hmg_patient_app_new/features/location/GeocodeResponse.dart';
+import 'package:hmg_patient_app_new/features/location/PlacePrediction.dart';
+import 'package:hmg_patient_app_new/features/location/location_view_model.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/widgets/input_widget.dart';
+import 'package:provider/provider.dart';
+
+import '../../../theme/colors.dart';
+import '../../appointments/widgets/hospital_bottom_sheet/type_selection_widget.dart';
+
+class LocationInputBottomSheet extends StatelessWidget {
+ final Debouncer debouncer = Debouncer(milliseconds: 500);
+
+ LocationInputBottomSheet({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ TextInputWidget(
+ labelText: LocaleKeys.search.tr(),
+ hintText: "Search Location".needTranslation,
+ controller: TextEditingController(),
+ onChange: (value){
+ debouncer.run(() {
+ context.read().updateSearchQuery(value);
+ });
+ },
+ isEnable: true,
+ prefix: null,
+ autoFocus: false,
+ isBorderAllowed: false,
+ keyboardType: TextInputType.text,
+ isAllowLeadingIcon: true,
+ selectionType: SelectionTypeEnum.search,
+ padding: EdgeInsets.symmetric(
+ vertical: 10.h,
+ horizontal: 15.h,
+ ),
+ ),
+ SizedBox(height: 24.h),
+ Selector>(
+ selector: (_, vm) => vm.predictions ?? [],
+ builder: (context, predictions, _) {
+ if (predictions.isEmpty) return SizedBox.shrink();
+ return Expanded(
+ child: ListView.separated(
+ separatorBuilder: (_,__)=>SizedBox(height: 16.h,),
+ itemCount: predictions.length,
+ itemBuilder: (_, index) {
+ final prediction = predictions[index];
+
+ return AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 500),
+ child: SlideAnimation(
+ verticalOffset: 100.0,
+ child: FadeInAnimation(
+ child: AnimatedContainer(
+ duration: Duration(milliseconds: 300),
+ curve: Curves.easeInOut,
+ decoration: RoundedRectangleBorder()
+ .toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24.h,
+ hasShadow: true),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Expanded(
+ child: prediction.description.toText14(
+ color: AppColors.textColor,
+ weight: FontWeight.w500),
+ ),
+
+ Utils.buildSvgWithAssets(
+ icon: AppAssets.forward_arrow_icon_small,
+ iconColor: AppColors.blackColor,
+ width: 20.h,
+ height: 15.h,
+ fit: BoxFit.contain,
+ ),
+ ],
+ ).paddingAll(24.h),),
+ ),
+ ),
+ ).onPress(() async {
+ await context.read().selectPlacePrediction(prediction);
+ Navigator.of(context).pop();
+ var location = context.read().placeDetails;
+ if(location != null) {
+ context.read().moveController(
+ Location(lat: location.lat, lng: location.lng));
+ }
+ });
+
+ },
+ ),
+ );
+ },
+ )
+ ],
+ );
+ }
+}
diff --git a/lib/presentation/emergency_services/widgets/nearestERItem.dart b/lib/presentation/emergency_services/widgets/nearestERItem.dart
index 3dc2aa1f..bbce56a4 100644
--- a/lib/presentation/emergency_services/widgets/nearestERItem.dart
+++ b/lib/presentation/emergency_services/widgets/nearestERItem.dart
@@ -5,7 +5,7 @@ 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/emergency_services/emergency_services_view_model.dart';
-import 'package:hmg_patient_app_new/features/emergency_services/model/resp_model/ProjectAvgERWaitingTime.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/ProjectAvgERWaitingTime.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/chip/app_custom_chip_widget.dart';
diff --git a/lib/services/dialog_service.dart b/lib/services/dialog_service.dart
index 9f1f503f..cf8918c9 100644
--- a/lib/services/dialog_service.dart
+++ b/lib/services/dialog_service.dart
@@ -62,16 +62,20 @@ class DialogServiceImp implements DialogService {
message: message,
showCancel: onCancelPressed != null ? true : false,
onOkPressed: () {
+ print('ok button is pressed');
if (onOkPressed != null) {
+ print('onOkPressed is not null');
onOkPressed();
+ }else {
+ Navigator.pop(context);
}
- context.pop();
},
onCancelPressed: () {
if (onCancelPressed != null) {
onCancelPressed();
+ }else {
+ Navigator.pop(context);
}
- context.pop();
},
),
);
diff --git a/lib/theme/colors.dart b/lib/theme/colors.dart
index ce2f87c1..6ccf8b16 100644
--- a/lib/theme/colors.dart
+++ b/lib/theme/colors.dart
@@ -63,6 +63,8 @@ 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);
diff --git a/lib/widgets/CustomSwitch.dart b/lib/widgets/CustomSwitch.dart
index 8e3364b5..784e446c 100644
--- a/lib/widgets/CustomSwitch.dart
+++ b/lib/widgets/CustomSwitch.dart
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
class CustomSwitch extends StatefulWidget {
final bool value;
@@ -17,21 +18,21 @@ class _CustomSwitchState extends State {
return GestureDetector(
onTap: () => widget.onChanged(!widget.value),
child: Container(
- width: 48.h,
+ width: 48.w,
height: 30.h,
decoration: BoxDecoration(
- color: widget.value ? Color(0xFFE6F7F0) : Color(0xFFE6F7F0),
+ color: AppColors.switchBackgroundColor ,
borderRadius: BorderRadius.circular(18),
),
child: AnimatedAlign(
- duration: Duration(milliseconds: 200),
+ duration: Duration(milliseconds: 300),
alignment: widget.value ? Alignment.centerRight : Alignment.centerLeft,
child: Container(
- margin: EdgeInsets.all(4),
- width: 28,
- height: 28,
+ margin: EdgeInsets.all(2.h),
+ width: 28.w,
+ height: 28.h,
decoration: BoxDecoration(
- color: Color(0xFF5FCB89),
+ color: AppColors.thumbColor,
shape: BoxShape.circle,
),
),
diff --git a/lib/widgets/common_bottom_sheet.dart b/lib/widgets/common_bottom_sheet.dart
index 4d0dcf12..3aaefe75 100644
--- a/lib/widgets/common_bottom_sheet.dart
+++ b/lib/widgets/common_bottom_sheet.dart
@@ -116,6 +116,7 @@ void showCommonBottomSheetWithoutHeight(
bool useSafeArea = false,
bool hasBottomPadding = true,
Color backgroundColor = AppColors.bottomSheetBgColor,
+ VoidCallback? onCloseClicked
}) {
showModalBottomSheet(
sheetAnimationStyle: AnimationStyle(
@@ -170,6 +171,7 @@ void showCommonBottomSheetWithoutHeight(
icon: AppAssets.close_bottom_sheet_icon,
iconColor: Color(0xff2B353E),
).onPress(() {
+ onCloseClicked?.call();
Navigator.of(context).pop();
}),
],
diff --git a/lib/widgets/input_widget.dart b/lib/widgets/input_widget.dart
index 2dcd32f9..d943731c 100644
--- a/lib/widgets/input_widget.dart
+++ b/lib/widgets/input_widget.dart
@@ -113,7 +113,7 @@ class TextInputWidget extends StatelessWidget {
children: [
Container(
padding: padding,
- height: 58.h,
+ height: 64.h,
alignment: Alignment.center,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: Colors.white,
diff --git a/lib/widgets/map/HMSMap.dart b/lib/widgets/map/HMSMap.dart
index 852af41f..f655479c 100644
--- a/lib/widgets/map/HMSMap.dart
+++ b/lib/widgets/map/HMSMap.dart
@@ -1,41 +1,63 @@
import 'dart:async';
import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/core/app_assets.dart';
+import 'package:hmg_patient_app_new/core/app_export.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:huawei_map/huawei_map.dart' ;
class HMSMap extends StatefulWidget{
final CameraPosition currentLocation;
final Function(CameraPosition) onCameraMoved;
+ final VoidCallback onCameraIdle;
final MapType mapType;
final bool compassEnabled;
final bool myLocationEnabled;
+ final bool showCenterMarker;
+ final Completer? inputController;
- HMSMap({super.key, required this.currentLocation ,required this.onCameraMoved, this.mapType = MapType.normal,this.compassEnabled = false, this.myLocationEnabled = true});
+ HMSMap({super.key, required this.currentLocation ,required this.onCameraMoved,required this.onCameraIdle,
+ this.mapType = MapType.normal,this.compassEnabled = false,this.showCenterMarker = false,
+ this.myLocationEnabled = true, this.inputController});
@override
State createState() => _HMSMapState();
}
class _HMSMapState extends State {
- final Completer _controller = Completer();
+ Completer? controller;
@override
void initState() {
HuaweiMapInitializer.initializeMap();
+ controller = widget.inputController ?? Completer();
super.initState();
}
// @override
@override
Widget build(BuildContext context) =>
- HuaweiMap(
- mapType: widget.mapType,
- zoomControlsEnabled: false,
- myLocationEnabled: widget.myLocationEnabled,
- compassEnabled: widget.compassEnabled,
- initialCameraPosition: widget.currentLocation,
- onCameraMove: (value) => widget.onCameraMoved(value),
- onMapCreated: (HuaweiMapController controller) {
- _controller.complete(controller);
- },
- );
+ Stack(
+ children: [
+ HuaweiMap(
+ mapType: widget.mapType,
+ zoomControlsEnabled: false,
+ myLocationEnabled: widget.myLocationEnabled,
+ myLocationButtonEnabled: false,
+ compassEnabled: widget.compassEnabled,
+ onCameraIdle:()=> widget.onCameraIdle(),
+ initialCameraPosition: widget.currentLocation,
+ onCameraMove: (value) => widget.onCameraMoved(value),
+ onMapCreated: (HuaweiMapController controller) {
+ this.controller?.complete(controller);
+ },
+ ),
+ Visibility(
+ visible: widget.showCenterMarker,
+ child: Align(
+ alignment: Alignment.center,
+ child: Utils.buildSvgWithAssets(icon: AppAssets.pin_location, width: 24.w, height: 36.h),
+ ),
+ )
+ ],
+ );
}
\ No newline at end of file
diff --git a/lib/widgets/map/map.dart b/lib/widgets/map/map.dart
index cd068385..0c67f1b6 100644
--- a/lib/widgets/map/map.dart
+++ b/lib/widgets/map/map.dart
@@ -2,31 +2,52 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.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';
class GMSMap extends StatelessWidget{
- final Completer _controller = Completer();
+ Completer? controller;
final CameraPosition currentLocation;
final Function(CameraPosition) onCameraMoved;
+ final VoidCallback onCameraIdle;
final MapType mapType;
final bool compassEnabled;
final bool myLocationEnabled;
+ final bool showCenterMarker;
- GMSMap({super.key, required this.currentLocation ,required this.onCameraMoved, this.mapType = MapType.normal,this.compassEnabled = false, this.myLocationEnabled = true});
+ GMSMap({super.key, required this.currentLocation ,required this.onCameraMoved,required this.onCameraIdle,
+ this.mapType = MapType.normal,this.compassEnabled = false,this.showCenterMarker = false,
+ this.myLocationEnabled = true,Completer? inputController}){
+ controller = inputController ?? Completer();
+ }
@override
Widget build(BuildContext context) {
- return GoogleMap(
- mapType: mapType,
- zoomControlsEnabled: false,
- myLocationEnabled: myLocationEnabled,
- compassEnabled: compassEnabled,
- initialCameraPosition: currentLocation,
- onCameraMove: (value) => onCameraMoved(value),
- onMapCreated: (GoogleMapController controller) {
-
- _controller.complete(controller);
- },
+ return Stack(
+ children: [
+ GoogleMap(
+ mapType: mapType,
+ zoomControlsEnabled: false,
+ myLocationEnabled: myLocationEnabled,
+ myLocationButtonEnabled: false,
+ compassEnabled: compassEnabled,
+ initialCameraPosition: currentLocation,
+ onCameraMove: (value) => onCameraMoved(value),
+ onCameraIdle: ()=>onCameraIdle(),
+ onMapCreated: (GoogleMapController controller) {
+ this.controller?.complete(controller);
+ },
+ ),
+ Visibility(
+ visible: showCenterMarker,
+ child: Align(
+ alignment: Alignment.center,
+ child: Utils.buildSvgWithAssets(icon: AppAssets.pin_location, width: 24.w, height: 36.h),
+ ),
+ )
+ ],
);
}
}
\ No newline at end of file