Merge branch 'master' into faiz_dev

# Conflicts:
#	lib/core/api/api_client.dart
#	lib/core/app_assets.dart
#	lib/core/utils/date_util.dart
#	lib/features/emergency_services/emergency_services_repo.dart
#	lib/features/emergency_services/emergency_services_view_model.dart
#	lib/presentation/emergency_services/emergency_services_page.dart
#	lib/widgets/common_bottom_sheet.dart
pull/98/head
faizatflutter 2 weeks ago
commit 8ddfdeeac4

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 543 KiB

@ -0,0 +1,5 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.49411 2.85661C9.06887 2.71829 8.56575 2.71849 7.82926 2.71878L5.20973 2.7188C4.36011 2.71878 3.66581 2.71877 3.11767 2.79255C2.5447 2.86967 2.04795 3.03656 1.65143 3.43352C1.25491 3.83049 1.0882 4.32779 1.01117 4.90139C0.93747 5.45014 0.937484 6.14521 0.9375 6.99576V10.0798C0.937484 10.9303 0.93747 11.6254 1.01117 12.1741C1.0882 12.7477 1.25491 13.245 1.65143 13.642C1.76583 13.7565 1.89283 13.8531 2.02893 13.9345C2.22063 14.0492 2.31647 14.1065 2.39389 14.059C2.47131 14.0115 2.46224 13.8786 2.44411 13.6127C2.43973 13.5484 2.4375 13.4836 2.4375 13.4181C2.4375 11.8631 3.6967 10.6025 5.25 10.6025C6.8033 10.6025 8.0625 11.8631 8.0625 13.4181C8.0625 13.5947 8.04626 13.7675 8.01519 13.9351C7.97875 14.1317 7.96053 14.23 8.00499 14.2841C8.04945 14.3381 8.14092 14.3389 8.32387 14.3406C8.77449 14.3448 9.22551 14.3448 9.67614 14.3406C9.85908 14.3389 9.95055 14.3381 9.99501 14.2841C10.0395 14.23 10.0213 14.1317 9.98481 13.9351C9.95374 13.7675 9.9375 13.5947 9.9375 13.4181C9.9375 11.8631 11.1967 10.6025 12.75 10.6025C14.3033 10.6025 15.5625 11.8631 15.5625 13.4181C15.5625 13.4835 15.5603 13.5484 15.5559 13.6127C15.5378 13.8786 15.5287 14.0115 15.6061 14.059C15.6835 14.1065 15.7794 14.0492 15.9711 13.9345C16.1072 13.8531 16.2342 13.7565 16.3486 13.642C16.7451 13.245 16.9118 12.7477 16.9888 12.1741C17.0625 11.6254 17.0625 10.9303 17.0625 10.0798V8.55433C17.0654 8.4286 17.0367 8.30042 16.9729 8.18177L15.9988 6.37069C15.7544 5.91626 15.5451 5.52708 15.3388 5.22173C15.1184 4.89536 14.8689 4.61351 14.5195 4.40455C14.17 4.19558 13.8038 4.10932 13.4123 4.06973C13.046 4.0327 12.6044 4.03272 12.0889 4.03274L11.2524 4.03274C11.1353 4.03274 11.0767 4.03274 11.0295 4.00933C10.9823 3.98592 10.9424 3.93349 10.8626 3.82864C10.5202 3.37853 10.0455 3.03597 9.49411 2.85661ZM11.7406 5.53441C11.5945 5.53441 11.5214 5.53441 11.4773 5.57901C11.4333 5.62362 11.4342 5.69802 11.4359 5.84684C11.4377 5.99664 11.4376 6.15736 11.4375 6.33106C11.4375 6.93389 11.4444 7.20613 11.4834 7.32612C11.5761 7.61185 11.7999 7.83587 12.0853 7.92871C12.2052 7.96769 12.3728 7.97464 12.975 7.97464H14.6556C14.8798 7.97464 14.9919 7.97464 15.0355 7.90148C15.0792 7.82832 15.026 7.72952 14.9197 7.53192L14.6949 7.11386C14.429 6.61959 14.2551 6.29803 14.0963 6.06291C13.9469 5.84183 13.845 5.75037 13.7503 5.69375C13.6556 5.63714 13.5268 5.59062 13.2616 5.5638C12.9795 5.53529 12.6142 5.53441 12.0535 5.53441H11.7406ZM4.5001 5.53125C4.91431 5.53125 5.2501 5.86704 5.2501 6.28125V7.78125C5.2501 8.19546 4.91431 8.53125 4.5001 8.53125C4.08589 8.53125 3.7501 8.19546 3.7501 7.78125V6.28125C3.7501 5.86704 4.08589 5.53125 4.5001 5.53125ZM7.5001 5.53125C7.91431 5.53125 8.2501 5.86704 8.2501 6.28125V7.78125C8.2501 8.19546 7.91431 8.53125 7.5001 8.53125C7.08589 8.53125 6.7501 8.19546 6.7501 7.78125V6.28125C6.7501 5.86704 7.08589 5.53125 7.5001 5.53125Z" fill="#2E3039"/>
<path d="M5.25 11.5312C4.21447 11.5312 3.375 12.3707 3.375 13.4062C3.375 14.4418 4.21447 15.2812 5.25 15.2812C6.28553 15.2812 7.125 14.4418 7.125 13.4062C7.125 12.3707 6.28553 11.5312 5.25 11.5312Z" fill="#2E3039"/>
<path d="M12.75 11.5312C11.7145 11.5312 10.875 12.3707 10.875 13.4062C10.875 14.4418 11.7145 15.2812 12.75 15.2812C13.7855 15.2812 14.625 14.4418 14.625 13.4062C14.625 12.3707 13.7855 11.5312 12.75 11.5312Z" fill="#2E3039"/>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

@ -1,7 +1,7 @@
import Flutter
import UIKit
import FirebaseCore
import FirebaseMessaging
//import FirebaseCore
//import FirebaseMessaging
import GoogleMaps
@main
@objc class AppDelegate: FlutterAppDelegate {
@ -10,13 +10,13 @@ import GoogleMaps
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GMSServices.provideAPIKey("AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng")
FirebaseApp.configure()
// FirebaseApp.configure()
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken:Data){
Messaging.messaging().apnsToken = deviceToken
// Messaging.messaging().apnsToken = deviceToken
super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
}
}

@ -201,6 +201,7 @@ class ApiClientImp implements ApiClient {
log("uri: ${Uri.parse(url.trim())}");
log("body: ${json.encode(body)}");
log("response.body: ${response.body}");
// log("response.body: ${response.body}");
if (statusCode < 200 || statusCode >= 400) {
onFailure('Error While Fetching data', statusCode, failureType: StatusCodeFailure("Error While Fetching data"));
logApiEndpointError(endPoint, 'Error While Fetching data', statusCode);
@ -364,7 +365,7 @@ class ApiClientImp implements ApiClient {
debugPrint("URL : $url");
// print("Body : ${json.encode(body)}");
if (await Utils.checkConnection()) {
if (await Utils.checkConnection(bypassConnectionCheck: true)) {
final response = await http.get(
Uri.parse(url.trim()),
headers: {'Content-Type': 'application/json', 'Accept': 'application/json'},

@ -173,6 +173,9 @@ class AppAssets {
static const String forward_arrow_medium = '$svgBasePath/forward_arrow_medium.svg';
static const String eReferral = '$svgBasePath/e-referral.svg';
static const String comprehensiveCheckup = '$svgBasePath/comprehensive_checkup.svg';
static const String all_payment_method = '$svgBasePath/all_payment_method.svg';
static const String ic_rrt_vehicle = '$svgBasePath/ic_rrt_vehicle.svg';
//bottom navigation//
static const String homeBottom = '$svgBasePath/home_bottom.svg';

@ -6,6 +6,8 @@ class DateUtil {
/// convert String To Date function
/// [date] String we want to convert
static DateTime convertStringToDate(String? date) {
if (date == null) return DateTime.now();
if (date.isEmpty) return DateTime.now();

@ -8,9 +8,11 @@ import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/request_model/PatientER_RC.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/request_model/RRTRequestModel.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/AmbulanceRequestOrdersModel.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/EROnlineCheckInPaymentDetailsResponse.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/RRTServiceData.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';
@ -18,7 +20,7 @@ import 'package:hmg_patient_app_new/services/logger_service.dart';
import 'models/resp_model/PatientERTransportationMethod.dart';
abstract class EmergencyServicesRepo {
Future<Either<Failure, GenericApiModel<List<RRTProceduresResponseModel>>>> getRRTProcedures();
Future<Either<Failure, GenericApiModel<List<RRTProceduresResponseModel>>>> getRRTProcedures(int languageId);
Future<Either<Failure, GenericApiModel<List<ProjectAvgERWaitingTime>>>> getNearestEr({int? id, int? projectID});
@ -48,7 +50,13 @@ abstract class EmergencyServicesRepo {
Future<Either<Failure, GenericApiModel<List<AmbulanceRequestOrdersModel>>>> getTransportationOrders({int? id});
Future<Either<Failure, GenericApiModel<bool>>> cancelOrder(int? iD, int patientId);
Future<Either<Failure, GenericApiModel<bool>>> cancelOrder(int? iD, int patientId);
Future<Either<Failure, GenericApiModel<bool>>> submitRRTRequest(RRTRequestModel request);
Future<Either<Failure, GenericApiModel<RRTServiceData>>> getRRTOrders({int? id});
Future<Either<Failure, GenericApiModel<bool>>> cancelRRTOrder(int? iD);
}
class EmergencyServicesRepoImp implements EmergencyServicesRepo {
@ -95,8 +103,8 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo {
}
@override
Future<Either<Failure, GenericApiModel<List<RRTProceduresResponseModel>>>> getRRTProcedures() async {
Map<String, dynamic> mapDevice = {"ProjectID": 15};
Future<Either<Failure, GenericApiModel<List<RRTProceduresResponseModel>>>> getRRTProcedures(int languageId) async {
Map<String, dynamic> mapDevice = {"ProjectID": 15, "languageID":1};
try {
GenericApiModel<List<RRTProceduresResponseModel>>? apiResponse;
@ -558,4 +566,120 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<bool>>> submitRRTRequest(RRTRequestModel request) async {
try {
GenericApiModel<bool>? apiResponse;
Failure? failure;
await apiClient.post(
body: request.toJson(),
ADD_RRT_ORDER_RC,
isRCService: true,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<bool>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: true,
);
} 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<Either<Failure, GenericApiModel<bool>>> cancelRRTOrder(int? iD) async{
try {
GenericApiModel<bool>? apiResponse;
Map<String, dynamic> request = {"Id": iD, "ClickButton": 14};
Failure? failure;
await apiClient.post(
body: request,
UPDATE_RRT_ORDER_RC,
isRCService: true,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<bool>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: true,
);
} 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<Either<Failure, GenericApiModel<RRTServiceData>>> getRRTOrders({int? id}) async {
try {
GenericApiModel<RRTServiceData>? apiResponse;
Failure? failure;
await apiClient.post(
body: {},
GET_ALL_RRT_ORDERS_RC,
isRCService: true,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response['response'];
RRTServiceData serviceData = RRTServiceData();
list.forEach((item) {
if (item["StatusId"] == 1 || item["StatusId"] == 2) {
// Pending
serviceData.pendingOrders.add(GetCMCAllOrdersResponseModel.fromJson(item));
}
serviceData.completedOrders.add(GetCMCAllOrdersResponseModel.fromJson(item));
});
apiResponse = GenericApiModel<RRTServiceData>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: serviceData,
);
} 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()));
}
}
}

@ -10,6 +10,12 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/emergency_services/emergency_services_repo.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/OrderDisplay.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/request_model/RRTRequestModel.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/EROnlineCheckInPaymentDetailsResponse.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/RRTServiceData.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/hospital_model.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/AmbulanceCallingPlace.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/request_model/PatientER_RC.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/AmbulanceRequestOrdersModel.dart';
@ -24,6 +30,8 @@ import 'package:hmg_patient_app_new/features/my_appointments/models/facility_sel
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/RRT/rrt_map_screen.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/requesting_services_page.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/tracking_screen.dart';
@ -65,7 +73,6 @@ class EmergencyServicesViewModel extends ChangeNotifier {
List<ProjectAvgERWaitingTime> nearestERList = [];
List<ProjectAvgERWaitingTime> nearestERFilteredList = [];
List<RRTProceduresResponseModel> RRTProceduresList = [];
List<HospitalsModel>? hospitalList;
List<HospitalsModel>? hmgHospitalList;
@ -77,7 +84,7 @@ class EmergencyServicesViewModel extends ChangeNotifier {
int hmcCount = 0;
bool pickupFromInsideTheLocation = true;
List<PatientAppointmentHistoryResponseModel>? appointments;
List<AmbulanceRequestOrdersModel>? orders = [];
List<AmbulanceRequestOrdersModel>? ambulanceOrders = [];
//ambulance selection data section
List<PatientERTransportationMethod> transportationOptions = [];
@ -85,7 +92,6 @@ class EmergencyServicesViewModel extends ChangeNotifier {
AmbulanceCallingPlace callingPlace = AmbulanceCallingPlace.FROM_HOSPITAL;
AmbulanceDirection ambulanceDirection = AmbulanceDirection.ONE_WAY;
late RRTProceduresResponseModel selectedRRTProcedure;
bool patientHasAdvanceERBalance = false;
bool isERBookAppointment = false;
@ -93,6 +99,21 @@ class EmergencyServicesViewModel extends ChangeNotifier {
BottomSheetType bottomSheetType = BottomSheetType.FIXED;
///RRT request data
List<RRTProceduresResponseModel> RRTProceduresList = [];
RRTProceduresResponseModel? selectedRRTProcedure;
bool agreedToTermsAndCondition = false;
RRTServiceData? ordersRRT;
TextEditingController rrtNotes = TextEditingController();
List allOrders = [];
List orderDisplayList = [];
bool historyLoading= false;
OrderDislpay currentlyDisplayedOrder = OrderDislpay.ALL;
setSelectedRRTProcedure(RRTProceduresResponseModel procedure) {
selectedRRTProcedure = procedure;
notifyListeners();
@ -126,10 +147,21 @@ class EmergencyServicesViewModel extends ChangeNotifier {
bool isMyAppointmentsLoading = false;
Future<void> getRRTProcedures({Function(dynamic)? onSuccess, Function(String)? onError}) async {
print("the app state is ${appState.isAuthenticated}");
if (!appState.isAuthenticated) {
dialogService.showErrorBottomSheet(
message: "You Need To Login First To Continue".needTranslation,
onOkPressed: () {
getIt<AuthenticationViewModel>().onLoginPressed();
});
return;
}
RRTProceduresList.clear();
notifyListeners();
final result = await emergencyServicesRepo.getRRTProcedures();
final result = await emergencyServicesRepo.getRRTProcedures(appState.getLanguageID());
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
@ -723,6 +755,8 @@ class EmergencyServicesViewModel extends ChangeNotifier {
LoaderBottomSheet.showLoader(loadingText: "Fetching Orders");
}
int? id = appState.getAuthenticatedUser()?.patientId;
historyLoading = true;
notifyListeners();
var response = await emergencyServicesRepo.getTransportationOrders(id: id);
if (shouldNavigateToTrackingScreen == false && showLoader) {
@ -730,6 +764,8 @@ class EmergencyServicesViewModel extends ChangeNotifier {
}
response.fold(
(failure) async {
historyLoading = false;
notifyListeners();
if (shouldNavigateToTrackingScreen) {
navServices.pushAndRemoveUntil(
CustomPageRoute(page: TrackingScreen(state: OrderTrackingState.waitingForCall)), ModalRoute.withName("/EmergencyServicesPage"));
@ -745,8 +781,12 @@ class EmergencyServicesViewModel extends ChangeNotifier {
)),
ModalRoute.withName("/EmergencyServicesPage"));
}
orders = apiResponse.data;
historyLoading = false;
ambulanceOrders = apiResponse.data;
allOrders.clear();
allOrders.addAll(ambulanceOrders??[]);
allOrders.addAll(ordersRRT?.completedOrders??[]);
changeOrderDisplayItems(OrderDislpay.ALL);
notifyListeners();
},
);
@ -835,4 +875,157 @@ class EmergencyServicesViewModel extends ChangeNotifier {
navServices.pop();
});
}
RRTRequestModel createRRTRequest(GeocodeResult? result, PlaceDetails? place, PlacePrediction? placePrediction){
AuthenticatedUser? user = appState.getAuthenticatedUser();
if (user == null) throw Exception("Authentication Required to Continue");
RRTRequestModel rrtRequestModel = new RRTRequestModel();
Procedures procedures = new Procedures();
rrtRequestModel.procedures = [];
procedures.serviceID = selectedRRTProcedure?.procedureID;
rrtRequestModel.latitude = ((result?.geometry.location.lat) ?? place?.lat);
rrtRequestModel.longitude = ((result?.geometry.location.lat) ?? place?.lat);
rrtRequestModel.additionalDetails = "";
rrtRequestModel.nationality = user.nationalityId;
rrtRequestModel.paymentAmount = selectedRRTProcedure?.patientShareWithTax;
rrtRequestModel.nearestProjectId = 0;
rrtRequestModel.patientId = user.patientId;
rrtRequestModel.patientOutSa = user.outSa;
rrtRequestModel.procedures!.add(procedures);
return rrtRequestModel;
}
///method to toggle the value for the aggremnent to the terms and conditon for the rrt
void setTermsAndConditions(bool value) {
agreedToTermsAndCondition = value;
notifyListeners();
}
FutureOr<void> submitRRTRequest(GeocodeResult? result, PlaceDetails? place, PlacePrediction? placePrediction) async {
RRTRequestModel request = createRRTRequest(result, place, placePrediction);
navServices.push(CustomPageRoute(page: RequestingServicesPage()));
var response = await emergencyServicesRepo.submitRRTRequest(request);
response.fold((failure) {
navServices.pushAndRemoveUntil(
CustomPageRoute(
page: TrackingScreen(
isRRTOrder: true,
state: OrderTrackingState.failed,
)),
ModalRoute.withName("/EmergencyServicesPage"));
}, (success) {
getRRTOrders(shouldNavigateToTrackingScreen: true);
});
}
Future<void> getRRTOrders({bool shouldNavigateToTrackingScreen = false, bool showLoader = false}) async {
if(shouldNavigateToTrackingScreen == false && showLoader ) {
LoaderBottomSheet.showLoader(loadingText: "Fetching Orders");
}
historyLoading = true;
notifyListeners();
int? id = appState.getAuthenticatedUser()?.patientId;
var response = await emergencyServicesRepo.getRRTOrders(id: id);
if(shouldNavigateToTrackingScreen == false && showLoader ) {
LoaderBottomSheet.hideLoader();}
response.fold(
(failure) async {
historyLoading = false;
notifyListeners();
if (shouldNavigateToTrackingScreen) {
navServices.pushAndRemoveUntil(CustomPageRoute(page: TrackingScreen(isRRTOrder: true,state: OrderTrackingState.waitingForCall)), ModalRoute.withName("/EmergencyServicesPage"));
}
},
(apiResponse) {
if (shouldNavigateToTrackingScreen) {
navServices.pushAndRemoveUntil(
CustomPageRoute(
page: TrackingScreen(
state: OrderTrackingState.waitingForCall,
isRRTOrder: true,
rrtOrder: apiResponse.data?.pendingOrders.first,
)),
ModalRoute.withName("/EmergencyServicesPage"));
}
historyLoading = false;
ordersRRT = apiResponse.data;
allOrders.clear();
allOrders.addAll(ambulanceOrders??[]);
allOrders.addAll(ordersRRT?.completedOrders??[]);
changeOrderDisplayItems(OrderDislpay.ALL);
notifyListeners();
},
);
}
FutureOr<void> cancelRRTOrder(int? orderID, {bool shouldPop = false}) async {
dialogService.showCommonBottomSheetWithoutH(
message: "Do you want to cancel the order".needTranslation,
onOkPressed: () async {
navServices.pop();
LoaderBottomSheet.showLoader(loadingText: "Cancelling Order".needTranslation);
var response = await emergencyServicesRepo.cancelRRTOrder(orderID);
LoaderBottomSheet.hideLoader();
response.fold((failure) => errorHandlerService.handleError(failure: failure), (success) {
getRRTOrders();
if (shouldPop) navServices.pop();
});
},
onCancelPressed: () {
navServices.pop();
});
}
void changeOrderDisplayItems(OrderDislpay currentlyDisplayedOrder){
this.currentlyDisplayedOrder = currentlyDisplayedOrder;
switch(currentlyDisplayedOrder){
case OrderDislpay.ALL:
orderDisplayList = allOrders;
break;
case OrderDislpay.RRT:
orderDisplayList = ordersRRT?.completedOrders ?? [];
break;
case OrderDislpay.AMBULANCE:
orderDisplayList = ambulanceOrders??[];
break;
}
notifyListeners();
}
void openRRT(){
print("the app state is ${appState.isAuthenticated}");
if (appState.isAuthenticated) {
if(agreedToTermsAndCondition == false){
dialogService.showErrorBottomSheet(message: "You Need To Agree To Terms And Conditions".needTranslation);
return;
}
locationUtils!.getLocation(
isShowConfirmDialog: true,
onSuccess: (position) {
updateBottomSheetState(BottomSheetType.FIXED);
navServices.push(
CustomPageRoute(
page: RrtMapScreen(), direction: AxisDirection.down),
);
});
} else{
dialogService.showErrorBottomSheet(
message: "You Need To Login First To Continue".needTranslation,
onOkPressed: () {
getIt<AuthenticationViewModel>().onLoginPressed();
});
}
}
clearRRTData(){
selectedRRTProcedure = null;
}
}

@ -0,0 +1,3 @@
enum OrderDislpay{
ALL,RRT,AMBULANCE
}

@ -0,0 +1,75 @@
class RRTRequestModel {
num? patientId;
int? patientOutSa;
bool? isOutPatient;
int? nearestProjectId;
num? longitude;
num? latitude;
String? additionalDetails;
String? nationality;
num? paymentAmount;
List<Procedures>? procedures;
RRTRequestModel(
{this.patientId,
this.patientOutSa,
this.isOutPatient,
this.nearestProjectId,
this.longitude,
this.latitude,
this.additionalDetails,
this.nationality,
this.paymentAmount,
this.procedures});
RRTRequestModel.fromJson(Map<String, dynamic> json) {
patientId = json['patientId'];
patientOutSa = json['patientOutSa'];
isOutPatient = json['isOutPatient'];
nearestProjectId = json['nearestProjectId'];
longitude = json['longitude'];
latitude = json['latitude'];
additionalDetails = json['additionalDetails'];
nationality = json['nationality'];
paymentAmount = json['paymentAmount'];
if (json['procedures'] != null) {
procedures = <Procedures>[];
json['procedures'].forEach((v) {
procedures!.add(new Procedures.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['patientId'] = this.patientId;
data['patientOutSa'] = this.patientOutSa;
data['isOutPatient'] = this.isOutPatient;
data['nearestProjectId'] = this.nearestProjectId;
data['longitude'] = this.longitude;
data['latitude'] = this.latitude;
data['additionalDetails'] = this.additionalDetails;
data['nationality'] = this.nationality;
data['paymentAmount'] = this.paymentAmount;
if (this.procedures != null) {
data['procedures'] = this.procedures!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Procedures {
String? serviceID;
Procedures({this.serviceID});
Procedures.fromJson(Map<String, dynamic> json) {
serviceID = json['ServiceID'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ServiceID'] = this.serviceID;
return data;
}
}

@ -0,0 +1,53 @@
class ServicePrice {
String? currency;
dynamic maxPrice;
dynamic maxTotalPrice;
dynamic maxVAT;
dynamic minPrice;
dynamic minTotalPrice;
dynamic minVAT;
dynamic price;
dynamic totalPrice;
dynamic vat;
ServicePrice({
this.currency,
this.maxPrice,
this.maxTotalPrice,
this.maxVAT,
this.minPrice,
this.minTotalPrice,
this.minVAT,
this.price,
this.totalPrice,
this.vat});
ServicePrice.fromJson(dynamic json) {
currency = json["Currency"];
maxPrice = json["MaxPrice"];
maxTotalPrice = json["MaxTotalPrice"];
maxVAT = json["MaxVAT"];
minPrice = json["MinPrice"];
minTotalPrice = json["MinTotalPrice"];
minVAT = json["MinVAT"];
price = json["Price"];
totalPrice = json["TotalPrice"];
vat = json["VAT"];
}
Map<String, dynamic> toJson() {
var map = <String, dynamic>{};
map["Currency"] = currency;
map["MaxPrice"] = maxPrice;
map["MaxTotalPrice"] = maxTotalPrice;
map["MaxVAT"] = maxVAT;
map["MinPrice"] = minPrice;
map["MinTotalPrice"] = minTotalPrice;
map["MinVAT"] = minVAT;
map["Price"] = price;
map["TotalPrice"] = totalPrice;
map["VAT"] = vat;
return map;
}
}

@ -0,0 +1,406 @@
class RRTServiceData {
List<GetCMCAllOrdersResponseModel> pendingOrders = [];
List<GetCMCAllOrdersResponseModel> completedOrders = [];
ServicePrice servicePrice = ServicePrice();
}
class GetCMCAllOrdersResponseModel {
int? iD;
int? patientId;
int? patientOutSa;
bool? isOutPatient;
int? projectId;
int? nearestProjectId;
dynamic longitude;
dynamic latitude;
dynamic appointmentNo;
dynamic dischargeId;
int? statusId;
int? serviceId;
int? channel;
Orderpayment? orderpayment;
dynamic orderselectedservice;
dynamic wforder;
dynamic orderapprovalobj;
String? created;
dynamic createdBy;
dynamic modified;
dynamic modifiedBy;
bool? isDeleted;
String? statusText;
int? paymentStatus;
dynamic clientRequestid;
dynamic paymentStatusText;
String? projectName;
String? nearestProjectName;
dynamic paymentAmount;
WFOrder? wFOrder;
String? serviceText;
bool? isSentForApproval;
int? exaCartOrderId;
bool? isTimer;
int? timeSeconds;
int? totalPendingSeconds;
int? timeMinute;
int? timeHour;
int? timeTotalSeconds;
int? timeTotalMinute;
int? timeTotalHour;
dynamic approvalStatus;
bool? isActive;
int? clickButton;
List<dynamic>? procedures;
dynamic pickupLocation;
dynamic dropOffLocation;
dynamic clinicName;
dynamic doctorName;
dynamic branch;
dynamic time;
dynamic notes;
GetCMCAllOrdersResponseModel(
{this.iD,
this.patientId,
this.patientOutSa,
this.isOutPatient,
this.projectId,
this.nearestProjectId,
this.longitude,
this.latitude,
this.appointmentNo,
this.dischargeId,
this.statusId,
this.serviceId,
this.channel,
this.orderpayment,
this.orderselectedservice,
this.wforder,
this.orderapprovalobj,
this.created,
this.createdBy,
this.modified,
this.modifiedBy,
this.isDeleted,
this.statusText,
this.paymentStatus,
this.clientRequestid,
this.paymentStatusText,
this.projectName,
this.nearestProjectName,
this.paymentAmount,
this.wFOrder,
this.serviceText,
this.isSentForApproval,
this.exaCartOrderId,
this.isTimer,
this.timeSeconds,
this.totalPendingSeconds,
this.timeMinute,
this.timeHour,
this.timeTotalSeconds,
this.timeTotalMinute,
this.timeTotalHour,
this.approvalStatus,
this.isActive,
this.clickButton,
this.procedures,
this.pickupLocation,
this.dropOffLocation,
this.clinicName,
this.doctorName,
this.branch,
this.time,
this.notes});
GetCMCAllOrdersResponseModel.fromJson(Map<String, dynamic> json) {
iD = json['ID'];
patientId = json['PatientId'];
patientOutSa = json['PatientOutSa'];
isOutPatient = json['IsOutPatient'];
projectId = json['ProjectId'];
nearestProjectId = json['NearestProjectId'];
longitude = json['Longitude'];
latitude = json['Latitude'];
appointmentNo = json['AppointmentNo'];
dischargeId = json['DischargeId'];
statusId = json['StatusId'];
serviceId = json['ServiceId'];
channel = json['Channel'];
orderpayment = json['orderpayment'] != null
? new Orderpayment.fromJson(json['orderpayment'])
: null;
orderselectedservice = json['orderselectedservice'];
wforder = json['wforder'];
orderapprovalobj = json['orderapprovalobj'];
created = json['Created'];
createdBy = json['CreatedBy'];
modified = json['Modified'];
modifiedBy = json['ModifiedBy'];
isDeleted = json['IsDeleted'];
statusText = json['StatusText'];
paymentStatus = json['PaymentStatus'];
clientRequestid = json['ClientRequestid'];
paymentStatusText = json['PaymentStatusText'];
projectName = json['ProjectName'];
nearestProjectName = json['NearestProjectName'];
paymentAmount = json['PaymentAmount'];
wFOrder = json['WF_order'] != null
? new WFOrder.fromJson(json['WF_order'])
: null;
serviceText = json['ServiceText'];
isSentForApproval = json['isSentForApproval'];
exaCartOrderId = json['ExaCart_OrderId'];
isTimer = json['isTimer'];
timeSeconds = json['TimeSeconds'];
totalPendingSeconds = json['TotalPendingSeconds'];
timeMinute = json['TimeMinute'];
timeHour = json['TimeHour'];
timeTotalSeconds = json['TimeTotalSeconds'];
timeTotalMinute = json['TimeTotalMinute'];
timeTotalHour = json['TimeTotalHour'];
approvalStatus = json['ApprovalStatus'];
isActive = json['isActive'];
clickButton = json['ClickButton'];
pickupLocation = json['PickupLocation'];
dropOffLocation = json['DropOffLocation'];
clinicName = json['clinicName'];
doctorName = json['DoctorName'];
branch = json['Branch'];
time = json['Time'];
notes = json['Notes'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ID'] = this.iD;
data['PatientId'] = this.patientId;
data['PatientOutSa'] = this.patientOutSa;
data['IsOutPatient'] = this.isOutPatient;
data['ProjectId'] = this.projectId;
data['NearestProjectId'] = this.nearestProjectId;
data['Longitude'] = this.longitude;
data['Latitude'] = this.latitude;
data['AppointmentNo'] = this.appointmentNo;
data['DischargeId'] = this.dischargeId;
data['StatusId'] = this.statusId;
data['ServiceId'] = this.serviceId;
data['Channel'] = this.channel;
if (this.orderpayment != null) {
data['orderpayment'] = this.orderpayment!.toJson();
}
data['orderselectedservice'] = this.orderselectedservice;
data['wforder'] = this.wforder;
data['orderapprovalobj'] = this.orderapprovalobj;
data['Created'] = this.created;
data['CreatedBy'] = this.createdBy;
data['Modified'] = this.modified;
data['ModifiedBy'] = this.modifiedBy;
data['IsDeleted'] = this.isDeleted;
data['StatusText'] = this.statusText;
data['PaymentStatus'] = this.paymentStatus;
data['ClientRequestid'] = this.clientRequestid;
data['PaymentStatusText'] = this.paymentStatusText;
data['ProjectName'] = this.projectName;
data['NearestProjectName'] = this.nearestProjectName;
data['PaymentAmount'] = this.paymentAmount;
if (this.wFOrder != null) {
data['WF_order'] = this.wFOrder!.toJson();
}
data['ServiceText'] = this.serviceText;
data['isSentForApproval'] = this.isSentForApproval;
data['ExaCart_OrderId'] = this.exaCartOrderId;
data['isTimer'] = this.isTimer;
data['TimeSeconds'] = this.timeSeconds;
data['TotalPendingSeconds'] = this.totalPendingSeconds;
data['TimeMinute'] = this.timeMinute;
data['TimeHour'] = this.timeHour;
data['TimeTotalSeconds'] = this.timeTotalSeconds;
data['TimeTotalMinute'] = this.timeTotalMinute;
data['TimeTotalHour'] = this.timeTotalHour;
data['ApprovalStatus'] = this.approvalStatus;
data['isActive'] = this.isActive;
data['ClickButton'] = this.clickButton;
data['PickupLocation'] = this.pickupLocation;
data['DropOffLocation'] = this.dropOffLocation;
data['clinicName'] = this.clinicName;
data['DoctorName'] = this.doctorName;
data['Branch'] = this.branch;
data['Time'] = this.time;
data['Notes'] = this.notes;
return data;
}
}
class Orderpayment {
int? iD;
int? orderId;
dynamic clientRequestId;
dynamic totalAmount;
int? paymentStatus;
dynamic order;
String? created;
dynamic createdBy;
dynamic modified;
dynamic modifiedBy;
bool? isDeleted;
Orderpayment(
{this.iD,
this.orderId,
this.clientRequestId,
this.totalAmount,
this.paymentStatus,
this.order,
this.created,
this.createdBy,
this.modified,
this.modifiedBy,
this.isDeleted});
Orderpayment.fromJson(Map<String, dynamic> json) {
iD = json['ID'];
orderId = json['OrderId'];
clientRequestId = json['ClientRequestId'];
totalAmount = json['TotalAmount'];
paymentStatus = json['PaymentStatus'];
order = json['Order'];
created = json['Created'];
createdBy = json['CreatedBy'];
modified = json['Modified'];
modifiedBy = json['ModifiedBy'];
isDeleted = json['IsDeleted'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ID'] = this.iD;
data['OrderId'] = this.orderId;
data['ClientRequestId'] = this.clientRequestId;
data['TotalAmount'] = this.totalAmount;
data['PaymentStatus'] = this.paymentStatus;
data['Order'] = this.order;
data['Created'] = this.created;
data['CreatedBy'] = this.createdBy;
data['Modified'] = this.modified;
data['ModifiedBy'] = this.modifiedBy;
data['IsDeleted'] = this.isDeleted;
return data;
}
}
class WFOrder {
dynamic wfButtonsDTO;
int? iD;
int? orderId;
int? previousStep;
int? nextStep;
int? serviceId;
dynamic order;
String? created;
dynamic createdBy;
dynamic modified;
dynamic modifiedBy;
bool? isDeleted;
WFOrder(
{this.wfButtonsDTO,
this.iD,
this.orderId,
this.previousStep,
this.nextStep,
this.serviceId,
this.order,
this.created,
this.createdBy,
this.modified,
this.modifiedBy,
this.isDeleted});
WFOrder.fromJson(Map<String, dynamic> json) {
wfButtonsDTO = json['wf_ButtonsDTO'];
iD = json['ID'];
orderId = json['OrderId'];
previousStep = json['PreviousStep'];
nextStep = json['NextStep'];
serviceId = json['ServiceId'];
order = json['Order'];
created = json['Created'];
createdBy = json['CreatedBy'];
modified = json['Modified'];
modifiedBy = json['ModifiedBy'];
isDeleted = json['IsDeleted'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['wf_ButtonsDTO'] = this.wfButtonsDTO;
data['ID'] = this.iD;
data['OrderId'] = this.orderId;
data['PreviousStep'] = this.previousStep;
data['NextStep'] = this.nextStep;
data['ServiceId'] = this.serviceId;
data['Order'] = this.order;
data['Created'] = this.created;
data['CreatedBy'] = this.createdBy;
data['Modified'] = this.modified;
data['ModifiedBy'] = this.modifiedBy;
data['IsDeleted'] = this.isDeleted;
return data;
}
}
class ServicePrice {
String? currency;
dynamic maxPrice;
dynamic maxTotalPrice;
dynamic maxVAT;
dynamic minPrice;
dynamic minTotalPrice;
dynamic minVAT;
dynamic price;
dynamic totalPrice;
dynamic vat;
ServicePrice({
this.currency,
this.maxPrice,
this.maxTotalPrice,
this.maxVAT,
this.minPrice,
this.minTotalPrice,
this.minVAT,
this.price,
this.totalPrice,
this.vat});
ServicePrice.fromJson(dynamic json) {
currency = json["Currency"];
maxPrice = json["MaxPrice"];
maxTotalPrice = json["MaxTotalPrice"];
maxVAT = json["MaxVAT"];
minPrice = json["MinPrice"];
minTotalPrice = json["MinTotalPrice"];
minVAT = json["MinVAT"];
price = json["Price"];
totalPrice = json["TotalPrice"];
vat = json["VAT"];
}
Map<String, dynamic> toJson() {
var map = <String, dynamic>{};
map["Currency"] = currency;
map["MaxPrice"] = maxPrice;
map["MaxTotalPrice"] = maxTotalPrice;
map["MaxVAT"] = maxVAT;
map["MinPrice"] = minPrice;
map["MinTotalPrice"] = minTotalPrice;
map["MinVAT"] = minVAT;
map["Price"] = price;
map["TotalPrice"] = totalPrice;
map["VAT"] = vat;
return map;
}
}

@ -0,0 +1,636 @@
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/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/GeocodeResponse.dart';
import 'package:hmg_patient_app_new/features/location/PlaceDetails.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/presentation/appointments/widgets/appointment_doctor_card.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/widgets/AddressItem.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/widgets/HospitalBottomSheetBody.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/widgets/appointment_bottom_sheet.dart' show AppointmentBottomSheet;
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';
import 'package:hmg_patient_app_new/widgets/expandable_bottom_sheet/ExpandableBottomSheet.dart';
import 'package:hmg_patient_app_new/widgets/expandable_bottom_sheet/model/BottomSheetType.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:hmg_patient_app_new/widgets/map/HMSMap.dart';
import 'package:hmg_patient_app_new/widgets/map/map.dart';
import 'package:provider/provider.dart';
import '../../../widgets/common_bottom_sheet.dart';
class RrtMapScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: Visibility(
visible: context.watch<EmergencyServicesViewModel>().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<EmergencyServicesViewModel>()
.moveToCurrentLocation();
}),
),
),
),
bottomSheet: ExpandableBottomSheet(
bottomSheetType:
context.watch<EmergencyServicesViewModel>().bottomSheetType,
children: {
BottomSheetType.EXPANDED: ExpanedBottomSheet(context),
BottomSheetType.FIXED: FixedBottomSheet(context),
},
),
body: Stack(
children: [
if (context.read<EmergencyServicesViewModel>().isGMSAvailable )
GMSMap(
currentLocation:
context.read<EmergencyServicesViewModel>().getGMSLocation(),
onCameraMoved: (value) => context
.read<LocationViewModel>()
.handleGMSMapCameraMoved(value),
onCameraIdle:
context.read<LocationViewModel>().handleOnCameraIdle,
myLocationEnabled: true,
inputController:
context.read<EmergencyServicesViewModel>().gmsController,
showCenterMarker: true,
)
else
HMSMap(
currentLocation:
context.read<EmergencyServicesViewModel>().getHMSLocation(),
onCameraMoved: (value) => context
.read<LocationViewModel>()
.handleHMSMapCameraMoved(value),
onCameraIdle:
context.read<LocationViewModel>().handleOnCameraIdle,
myLocationEnabled: false,
inputController:
context.read<EmergencyServicesViewModel>().hmsController,
showCenterMarker: true,
),
Align(
alignment: AlignmentDirectional.topStart,
child: Utils.buildSvgWithAssets(
icon: AppAssets.closeBottomNav, width: 32.h, height: 32.h)
.onPress(() {
context
.read<EmergencyServicesViewModel>()
.flushPickupInformation();
Navigator.pop(context);
}),
).paddingOnly(top: 51.h, left: 24.h),
],
),
);
}
Widget FixedBottomSheet(BuildContext context) {
return GestureDetector(
onVerticalDragUpdate: (details){
},
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
spacing: 24.h,
children: [
inputFields(context),
SizedBox(
height: 200.h,
child: DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.scaffoldBgColor,
customBorder: BorderRadius.only(
topLeft: Radius.circular(24.h),
topRight: Radius.circular(24.h),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 24.h,
children: [
Column(
spacing: 4.h,
children: [
"Select Pickup Details".needTranslation.toText21(
weight: FontWeight.w600,
color: AppColors.textColor,
),
" Please select the details of pickup"
.needTranslation
.toText12(
fontWeight: FontWeight.w500,
color: AppColors.greyTextColor,
)
],
),
CustomButton(
text: "Select Details".needTranslation,
onPressed: () {
LocationViewModel locationViewModel = context.read<LocationViewModel>();
GeocodeResponse? response = locationViewModel.geocodeResponse;
PlaceDetails? placeDetails = locationViewModel.placeDetails;
PlacePrediction? placePrediction = locationViewModel.selectedPrediction;
context.read<EmergencyServicesViewModel>().submitRRTRequest(response?.results.first, placeDetails, placePrediction);
})
],
).paddingOnly(top: 24.h, bottom: 32.h, left: 24.h, right: 24.h),
),
),
],
),
],
),
);
}
Widget ExpanedBottomSheet(BuildContext context) {
return GestureDetector(
onVerticalDragUpdate: (details){
if(details.delta.dy>0){
context.read<EmergencyServicesViewModel>().updateBottomSheetState(BottomSheetType.FIXED);
}
},
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.scaffoldBgColor,
customBorder: BorderRadius.only(
topLeft: Radius.circular(24.h),
topRight: Radius.circular(24.h),
),
),
child: Column(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 16.h,
children: [
hospitalAndPickUpSection(context),
],
).paddingOnly(top: 24.h, bottom: 32.h,left: 24.h, right: 24.h),
bottomPriceContent(context)
],
),
),
],
),
);
}
locationsSections(BuildContext context) {
return DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.h,
),
child: Column(mainAxisSize: MainAxisSize.min, children: [
ListView.separated(
separatorBuilder: (_, __) => Column(
children: [
SizedBox(height: 16.h),
Divider(
color: AppColors.bottomNAVBorder,
height: 1,
thickness: 1,
),
SizedBox(height: 16.h),
],
),
shrinkWrap: true,
itemCount: 3,
itemBuilder: (__, index) {
if (index ==
2) // todo means the end of the list so handle as per the viewmodel
{
return CustomButton(
height: 40.h,
backgroundColor: AppColors.lightRedButtonColor,
borderColor: Colors.transparent,
text: "Add new address".needTranslation,
textColor: AppColors.primaryRedColor,
iconColor: AppColors.primaryRedColor,
onPressed: () {},
icon: AppAssets.add_icon);
} else {
return AddressItem(
isSelected: index == 0,
address:
"Flat No 301, Building No 12, Palm Spring Apartment, Sector 45, Gurugram, Haryana 122003",
title: index == 0
? "Home".needTranslation
: "Work".needTranslation,
onTap: () {},
);
}
})
]).paddingAll(16.h),
);
}
hospitalAndPickUpSection(BuildContext context) {
return DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
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: "Pick".needTranslation,
subTitle: "Inside the home".needTranslation,
leadingIcon: AppAssets.pickup_bed,
),
CustomSwitch(
value: context
.watch<EmergencyServicesViewModel>()
.pickupFromInsideTheLocation,
onChanged: (value){
context
.read<EmergencyServicesViewModel>()
.updateThePickupPlaceFromLocation(value);
},
)
],
),
Row(
children: [
hospitalAndPickUpItemContent(
title: '',
subTitle: "Have any appointment".needTranslation,
leadingIcon: AppAssets.appointment_checkin_icon,
),
CustomSwitch(
value: context
.watch<EmergencyServicesViewModel>()
.haveAnAppointment,
onChanged: (value) async {
// if (value) {
// openAppointmentList(context);
// }
await context.read<EmergencyServicesViewModel>()
.updateAppointment(value);
if (context.read<EmergencyServicesViewModel>().appointments?.isNotEmpty == true) {
openAppointmentList(context);
}
},
)
],
),
],
).paddingAll(16.h),
);
}
leadingIcon(String leadingIcon) {
return Container(
height: 40.h,
width: 40.h,
margin: EdgeInsets.only(right: 10.h),
padding: EdgeInsets.all(8.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
borderRadius: 12.h,
color: AppColors.greyColor,
),
child: Utils.buildSvgWithAssets(icon: leadingIcon),
);
}
hospitalAndPickUpItemContent({
required String title,
required String subTitle,
required String leadingIcon,
}) {
return Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
this.leadingIcon(leadingIcon),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Visibility(
visible: title.isNotEmpty,
child: Column(
children: [
title.toText12(
color: AppColors.greyTextColor,
fontWeight: FontWeight.w500,
),
SizedBox(height: 2.h),
],
),
),
subTitle.toText14(
color: AppColors.textColor,
weight: FontWeight.w500,
),
],
),
),
],
),
);
}
bottomPriceContent(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.scaffoldBgColor,
customBorder: BorderRadius.only(
topLeft: Radius.circular(24.h),
topRight: Radius.circular(24.h),
),
hasShadow: true
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 12.h,
children: [
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 4.h,
children: [
"Total amount to pay".needTranslation.toText18(
weight: FontWeight.w600,
color: AppColors.textColor,
),
Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.warning,
height: 18.h, width: 18.h),
SizedBox(width: 4.h,),
"Amount will be paid at the hospital"
.needTranslation
.toText12(
fontWeight: FontWeight.w500,
color: AppColors.greyTextColor,
),
],
)
],
),
),
Utils.getPaymentAmountWithSymbol(
(Utils.formatNumberToInternationalFormat(context
.read<EmergencyServicesViewModel>()
.getTotalPrice() ??
0))
.toText24(
fontWeight: FontWeight.w600,
color: AppColors.textColor,
letterSpacing: -2),
AppColors.blackColor,
17.h)
// Utils.getPaymentAmountWithSymbol2(context.read<EmergencyServicesViewModel>().selectedTransportOption?.priceTotal??"0", letterSpacing: -2)
],
),
CustomButton(
text: "Submit Request".needTranslation,
onPressed: () {
LocationViewModel locationViewModel = context.read<LocationViewModel>();
GeocodeResponse? response = locationViewModel.geocodeResponse;
PlaceDetails? placeDetails = locationViewModel.placeDetails;
PlacePrediction? placePrediction = locationViewModel.selectedPrediction;
context.read<EmergencyServicesViewModel>().submitAmbulanceRequest(response?.results.first, placeDetails, placePrediction);
})
],
).paddingOnly(top: 24.h, bottom: 12.h, left: 24.h, right: 24.h),
),
],
);
}
showHospitalBottomSheet(BuildContext context){
showCommonBottomSheetWithoutHeight(
title:
LocaleKeys.selectHospital.tr(),
context,
child: Consumer<EmergencyServicesViewModel>(
builder:(_,vm,__)=> HospitalBottomSheetBody(
searchText: vm.searchController,
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,
backgroundColor: AppColors.bottomSheetBgColor,
callBackFunc: () {
context.read<EmergencyServicesViewModel>().clearSearchText();
},
);
}
///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<LocationViewModel>(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 textPlaceInput(context);
}
openLocationInputBottomSheet(BuildContext context) {
context.read<LocationViewModel>().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<EmergencyServicesViewModel>()
.getSelectedHospitalName() ??
"Select 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: "Select Appointment".needTranslation,
context,
child: SizedBox(
height: MediaQuery.sizeOf(context).height * .5,
child: AppointmentBottomSheet(
list: context.read<EmergencyServicesViewModel>().appointments!,
onAppointmentSelection: (appointment) {
Navigator.pop(context);
context.read<EmergencyServicesViewModel>().setSelectedAppointment(appointment);
}),
),
isFullScreen: false,
isCloseButtonVisible: true,
hasBottomPadding: false,
backgroundColor: AppColors.bottomSheetBgColor,
callBackFunc: () {
context.read<EmergencyServicesViewModel>().checkHasAppointment();
},
);
// );
}
}

@ -1,9 +1,16 @@
import 'package:easy_localization/easy_localization.dart' show tr, StringTranslateExtension;
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/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/resp_model/rrt_procedures_response_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/radio/custom_radio_button.dart';
import 'package:provider/provider.dart';
@ -13,34 +20,250 @@ class RrtRequestTypeSelect extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<EmergencyServicesViewModel>(builder: (context, emergencyServicesVM, child) {
print("the checkbox is ${emergencyServicesVM.agreedToTermsAndCondition}");
return Column(
children: [
Container(
padding: EdgeInsets.all(16.h),
height: 200.h,
Column(
children: [
"Rapid Response Team (RRT) options".needTranslation.toText20(color: AppColors.textColor, isBold: true),
SizedBox(
height: 16.h,
),
DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: Colors.white,
borderRadius: 20.r,
),
child: OptionSelection(context)),
SizedBox(
height: 24.h,
),
termsAndCondition(context, emergencyServicesVM),
],
).paddingSymmetrical(24.w, 0.h),
bottomPriceContent(context, emergencyServicesVM)
],
);
});
}
bottomPriceContent(BuildContext context, EmergencyServicesViewModel emergencyServicesVM) {
if (emergencyServicesVM.selectedRRTProcedure == null) return SizedBox.shrink();
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.h,
),
color: AppColors.scaffoldBgColor,
customBorder: BorderRadius.only(
topLeft: Radius.circular(24.h),
topRight: Radius.circular(24.h),
),
hasShadow: true),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 12.h,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 12.h,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Total amount to pay".needTranslation.toText18(
weight: FontWeight.w600,
color: AppColors.textColor,
),
Utils.getPaymentAmountWithSymbol(
(Utils.formatNumberToInternationalFormat(context.read<EmergencyServicesViewModel>().selectedRRTProcedure?.patientShare ?? 0))
.toText24(fontWeight: FontWeight.w600, color: AppColors.textColor, letterSpacing: -2),
AppColors.blackColor,
17.h)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.warning, height: 18.h, width: 18.h),
SizedBox(
width: 4.h,
),
"Amount will be paid at the hospital".needTranslation.toText11(
color: AppColors.greyTextColor,
),
],
),
Row(
children: [
"+ VAT 15%(".needTranslation.toText12(
fontWeight: FontWeight.w500,
color: AppColors.greyTextColor,
),
"${emergencyServicesVM.selectedRRTProcedure?.patientTaxAmount})".needTranslation.toText14(
weight: FontWeight.w600,
color: AppColors.greyTextColor,
),
],
),
],
)
],
),
),
// Utils.getPaymentAmountWithSymbol2(context.read<EmergencyServicesViewModel>().selectedTransportOption?.priceTotal??"0", letterSpacing: -2)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CustomRadioOption(
value: "",
groupValue: "",
onChanged: (value) {},
text: "Home Visit Emergency",
Row(
spacing: 6.w,
children: [
Image.asset(AppAssets.mada, width: 24.h, height: 24.h),
Image.asset(AppAssets.visa, width: 24.h, height: 24.h),
Image.asset(AppAssets.Mastercard, width: 24.h, height: 24.h),
Image.asset(AppAssets.apple_pay, width: 24.h, height: 24.h),
],
),
Column(
children: [
Divider(
color: AppColors.dividerColor,
thickness: 1.h,
),
Utils.getPaymentAmountWithSymbol(
(Utils.formatNumberToInternationalFormat(context.read<EmergencyServicesViewModel>().selectedRRTProcedure?.patientShareWithTax ?? 0))
.toText24(fontWeight: FontWeight.w600, color: AppColors.textColor, letterSpacing: -2),
AppColors.blackColor,
17.h),
],
)
],
),
CustomButton(text: LocaleKeys.next.tr(), onPressed: () {
Navigator.pop(context);
emergencyServicesVM.openRRT();
})
],
),
).paddingAll(24.h),
),
SizedBox(height: 32.h),
],
);
});
}
Widget OptionSelection(BuildContext context) {
return Selector<EmergencyServicesViewModel, (List<RRTProceduresResponseModel>?, RRTProceduresResponseModel?)>(
// Select both the list and the currently selected procedure
selector: (context, viewModel) => (viewModel.RRTProceduresList, viewModel.selectedRRTProcedure),
builder: (context, data, child) {
final procedureList = data.$1;
final selectedProcedure = data.$2;
// Handle loading or empty state
if (procedureList == null || procedureList.isEmpty) {
return const SizedBox.shrink();
}
return ListView.separated(
shrinkWrap: true,
padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 16.w),
// Important for ListView inside a Column
physics: const NeverScrollableScrollPhysics(),
// If the parent is scrollable
itemCount: procedureList.length,
separatorBuilder: (_, __) => Divider(thickness: 1.h, color: AppColors.dividerColor),
itemBuilder: (_, index) {
final procedure = procedureList[index];
final indexOfSelectedItem = selectedProcedure != null ? procedureList.indexOf(selectedProcedure) : -1;
return RadioListTile<int>(
title: (procedure.procedureName ?? "").toText12(color: AppColors.textColor),
value: index,
fillColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.selected)) {
return AppColors.primaryRedColor;
}
return Color(0xffEEEEEE);
}),
contentPadding: EdgeInsets.zero,
groupValue: indexOfSelectedItem,
onChanged: (int? newValue) {
context.read<EmergencyServicesViewModel>().setSelectedRRTProcedure(procedure);
},
);
// return Row(
// children: [
// Radio<String?>(
// // Specify the type for the Radio button
// value: procedure.procedureID ?? "",
// groupValue: selectedProcedure?.procedureID,
// // Compare with the selected procedure's ID
// activeColor: AppColors.primaryRedColor,
// fillColor: MaterialStateProperty.all(AppColors.primaryRedColor),
// onChanged: (value) {
// // The onChanged of the Radio button should handle the state update
// context.read<EmergencyServicesViewModel>().setSelectedRRTProcedure(procedure);
// },
// ),
// Expanded(
// // Use Expanded to allow text to wrap if it's too long
// child: (procedure.procedureName ?? "").toText12(color: AppColors.textColor),
// )
// ],
},
);
},
);
}
termsAndCondition(
BuildContext context,
EmergencyServicesViewModel emergencyServicesVM,
) {
return Row(
children: [
Checkbox(
value: emergencyServicesVM.agreedToTermsAndCondition,
checkColor: AppColors.whiteColor,
fillColor: MaterialStateProperty.resolveWith<Color>((Set<MaterialState> states) {
print("the state is ${states}");
if (states.contains(WidgetState.selected)) {
return AppColors.errorColor;
}
return AppColors.whiteColor;
}),
onChanged: (value) {
emergencyServicesVM.setTermsAndConditions(value ?? false);
}),
Row(
children: [
LocaleKeys.agreeTo.tr().toText12(color: AppColors.textColor),
LocaleKeys.termsConditoins.tr().toText12(color: AppColors.errorColor, isUnderLine: true),
],
),
],
);
// CheckboxListTile(
// title: Row(
// children: [
// LocaleKeys.agreeTo.tr().toText12(color: AppColors.textColor),
// LocaleKeys.termsConditoins.tr().toText12(color: AppColors.errorColor, isUnderLine: true),
// ],
// ),
// value: emergencyServicesVM.agreedToTermsAndCondition,
// onChanged: (value) {
// emergencyServicesVM.setTermsAndConditions(value ?? false);
// },
// );
}
}

@ -8,6 +8,7 @@ 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/AmbulanceRequestOrdersModel.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/RRTServiceData.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@ -22,11 +23,13 @@ import 'package:url_launcher/url_launcher.dart' show launchUrl;
class TrackingScreen extends StatelessWidget {
OrderTrackingState? state ;
final bool isRRTOrder;
final AmbulanceRequestOrdersModel? order;
final GetCMCAllOrdersResponseModel? rrtOrder;
TrackingScreen({super.key, OrderTrackingState? state, this.order}){
TrackingScreen({super.key, OrderTrackingState? state, this.order, this.isRRTOrder = false, this.rrtOrder}){
if(state == null){
switch (order?.statusId) {
switch (order?.statusId ?? rrtOrder?.statusId) {
case 1: //pending
case 2: //processing
this.state = OrderTrackingState.waitingForCall;
@ -70,7 +73,7 @@ class TrackingScreen extends StatelessWidget {
animationSection(),
Column(
spacing: 16.h,
children: [orderStatus(context), orderTrackingId(), contactSection()],
children: [orderStatus(context), orderTrackingId(context), contactSection()],
).paddingAll(16.h),
],
))),
@ -328,11 +331,12 @@ class TrackingScreen extends StatelessWidget {
}
}
orderTrackingId() {
orderTrackingId(BuildContext context) {
if(state == OrderTrackingState.failed){
return SizedBox.shrink();
}
return Container(
width: MediaQuery.sizeOf(context).width-32.h,
padding: EdgeInsets.all(16.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
@ -344,20 +348,10 @@ class TrackingScreen extends StatelessWidget {
spacing: 8.h,
children: [
Visibility(visible:order != null ,child: "Req ID: ${order?.iD}".toText16(color: AppColors.textColor, weight: FontWeight.w600)),
Row(
spacing: 8.h,
children: [
Flexible(child:
chip(order?.pickupLocation??"", AppAssets.location_pickup, AppColors.blackBgColor),
),
Flexible(child:
chip(order?.dropOffLocation??"", AppAssets.hospital, AppColors.blackBgColor),
Visibility(visible:(order != null || rrtOrder != null) ,child: "Req ID: ${order?.iD?? rrtOrder?.iD}".toText16(color: AppColors.textColor, weight: FontWeight.w600)),
if(order != null) ambulanceOrderData()
// else rrtOrderData()
)
],
),
],
),
);
@ -456,6 +450,44 @@ class TrackingScreen extends StatelessWidget {
openCancelOrderBottomSheet(BuildContext context){
context.read<EmergencyServicesViewModel>().cancelOrder(order, shouldPop: true);
if(isRRTOrder){
context.read<EmergencyServicesViewModel>().cancelRRTOrder(rrtOrder?.iD??-1, shouldPop: true);
return;
}else {
context.read<EmergencyServicesViewModel>().cancelOrder(order, shouldPop: true);
return;
}
}
Widget ambulanceOrderData() {
return Row(
spacing: 8.h,
children: [
Flexible(child:
chip(order?.pickupLocation??"", AppAssets.location_pickup, AppColors.blackBgColor),
),
Flexible(child:
chip(order?.dropOffLocation??"", AppAssets.hospital, AppColors.blackBgColor),
)
],
);
}
// Widget rrtOrderData() {
// return Row(
// spacing: 8.h,
// children: [
// Flexible(child:
// chip(rrtOrder?.pickupLocation??"", AppAssets.location_pickup, AppColors.blackBgColor),
//
// ),
// // Flexible(child:
// // chip(rrtOrder?.??"", AppAssets.hospital, AppColors.blackBgColor),
// //
// // )
// ],
// );
// }
}

@ -6,6 +6,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/models/OrderDisplay.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';
@ -35,7 +36,8 @@ class EmergencyServicesPage extends StatelessWidget {
return CollapsingListView(
title: LocaleKeys.emergencyServices.tr(),
requests: () {
Navigator.of(context).push(CustomPageRoute(page: ErHistoryListing(), direction: AxisDirection.up));
emergencyServicesViewModel.changeOrderDisplayItems(OrderDislpay.ALL);
Navigator.of(context).push(CustomPageRoute(page: ErHistoryListing(), direction: AxisDirection.up));
},
child: Padding(
padding: EdgeInsets.all(24.h),
@ -198,23 +200,7 @@ class EmergencyServicesPage extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"".toText14(),
Utils.buildSvgWithAssets(
icon: AppAssets.cancel_circle_icon,
iconColor: AppColors.whiteColor,
width: 24.h,
height: 24.h,
fit: BoxFit.contain,
).onPress(() {
Navigator.of(context).pop();
}),
],
),
Lottie.asset(AppAnimations.ambulance_alert,
repeat: false, reverse: false, frameRate: FrameRate(60), width: 120.h, height: 120.h, fit: BoxFit.contain),
Lottie.asset(AppAnimations.ambulance_alert, repeat: false, reverse: false, frameRate: FrameRate(60), width: 120.h, height: 120.h, fit: BoxFit.contain),
SizedBox(height: 8.h),
LocaleKeys.confirm.tr().toText28(color: AppColors.whiteColor, isBold: true),
SizedBox(height: 8.h),
@ -228,10 +214,23 @@ class EmergencyServicesPage extends StatelessWidget {
Navigator.of(context).pop();
LoaderBottomSheet.showLoader();
emergencyServicesViewModel.clearRRTData();
await emergencyServicesViewModel.getRRTProcedures(onSuccess: (val) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
title: "Rapid Response Team (RRT)".needTranslation,
padding: EdgeInsets.only(top: 24.h),
titleWidget: Transform.flip(
flipX: emergencyServicesViewModel.isArabic,
child: Utils.buildSvgWithAssets(
icon: AppAssets.arrow_back,
iconColor: Color(0xff2B353E),
fit: BoxFit.contain,
),
).onPress(() {
Navigator.pop(context);
}),
// title: "Rapid Response Team (RRT)".needTranslation,
context,
child: RrtRequestTypeSelect(),
isFullScreen: false,
@ -359,8 +358,8 @@ class EmergencyServicesPage extends StatelessWidget {
onCloseClicked: () {
context.read<EmergencyServicesViewModel>().flushPickupInformation();
},
titleWidget: Transform.flip(
flipX: emergencyServicesViewModel.isArabic ? true : false,
titleWidget: Transform.flip(
flipX: emergencyServicesViewModel.isArabic,
child: Utils.buildSvgWithAssets(
icon: AppAssets.arrow_back,
iconColor: Color(0xff2B353E),

@ -1,13 +1,20 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart' show AppAssets;
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/emergency_services/emergency_services_view_model.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/OrderDisplay.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/AmbulanceRequestOrdersModel.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/RRTServiceData.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/history/widget/ambulance_history_item.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/history/widget/ambulance_history_item.dart' show AmbulanceHistoryItem;
import 'package:hmg_patient_app_new/presentation/emergency_services/history/widget/rrt_item.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:provider/provider.dart';
class ErHistoryListing extends StatelessWidget {
@ -16,30 +23,52 @@ class ErHistoryListing extends StatelessWidget {
return Scaffold(
body: Column(
children: [
Expanded(
child: CollapsingListView(
title: "History Log".needTranslation,
child: SingleChildScrollView(
physics: NeverScrollableScrollPhysics(),
child: Column(
children: [Visibility(
visible: context
.read<EmergencyServicesViewModel>()
.orders
?.isNotEmpty == true,
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: context
.read<EmergencyServicesViewModel>()
.orders
?.length ?? 0,
itemBuilder: (_, index) =>
Consumer<EmergencyServicesViewModel>( builder: (_, vm, __)=>
AmbulanceHistoryItem(order: vm.orders![index]),
)
children: [
Selector<EmergencyServicesViewModel,(List, bool)>(
selector: (context, vm) => (vm.orderDisplayList, vm.historyLoading),
builder: (context, data, _) {
return Column(
children: [
orderChips(context, data.$2),
Visibility(
visible:data.$1.isNotEmpty == true,
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount:data?.$1.length ?? 0,
itemBuilder: (_, index) {
var order = data.$1[index];
if (order is AmbulanceRequestOrdersModel) {
return AmbulanceHistoryItem(order: order).toShimmer2(isShow: data.$2);
} else {
return RRTItem(order: (order as GetCMCAllOrdersResponseModel)).toShimmer2(isShow: data.$2);
}
}),
),
Visibility(
visible: data.$1
?.isEmpty == true, child: Center(
child: Utils.getNoDataWidget(context,
noDataText: "You don't have any history"
.needTranslation),
)),
],
);
}
),
),]
]
).paddingAll(16.h)
))
@ -47,16 +76,84 @@ class ErHistoryListing extends StatelessWidget {
),
Visibility(
visible: context
.read<EmergencyServicesViewModel>()
.orders
?.isEmpty == true,
child: Utils.getNoDataWidget(context,
noDataText: "You don't have any history"
.needTranslation)),
],
),
);
}
orderChips(BuildContext context, bool isLoading) {
if (context
.read<EmergencyServicesViewModel>()
.displayList
?.isEmpty == true) {
return SizedBox.shrink();
}
return
Selector<EmergencyServicesViewModel, OrderDislpay>(
selector: (context, vm) => vm.currentlyDisplayedOrder,
builder: (context, value, __) {
return Row(
spacing: 8.h,
children: [
if(context
.read<EmergencyServicesViewModel>()
.orderDisplayList
?.isNotEmpty == true)
AppCustomChipWidget(
labelText: "All Facilities".needTranslation,
shape: RoundedRectangleBorder(
side: BorderSide(
color: value == OrderDislpay.ALL ? AppColors.errorColor : AppColors.chipBorderColorOpacity20,
width: 1,
),
borderRadius: BorderRadius.circular(10)),
backgroundColor: value == OrderDislpay.ALL ? AppColors.secondaryLightRedColor : AppColors.whiteColor,
textColor: value == OrderDislpay.ALL ? AppColors.errorColor : AppColors.blackColor,
).onPress(() {
context.read<EmergencyServicesViewModel>().changeOrderDisplayItems(OrderDislpay.ALL);
}).toShimmer2(isShow: isLoading),
if(context
.read<EmergencyServicesViewModel>()
.ambulanceOrders
?.isNotEmpty == true)
AppCustomChipWidget(
labelText: "Ambulance".needTranslation,
icon: AppAssets.ambulance,
shape: RoundedRectangleBorder(
side: BorderSide(
color: value == OrderDislpay.AMBULANCE ? AppColors.errorColor : AppColors.chipBorderColorOpacity20,
width: 1,
),
borderRadius: BorderRadius.circular(10)),
backgroundColor: value == OrderDislpay.AMBULANCE ? AppColors.secondaryLightRedColor : AppColors.whiteColor,
textColor: value == OrderDislpay.AMBULANCE ? AppColors.errorColor : AppColors.blackColor,
).toShimmer2(isShow: isLoading).onPress(() {
context.read<EmergencyServicesViewModel>().changeOrderDisplayItems(OrderDislpay.AMBULANCE);
}),
if(context
.read<EmergencyServicesViewModel>()
.ordersRRT
?.completedOrders
.isNotEmpty == true)
AppCustomChipWidget(
labelText: "Rapid Response Team".needTranslation,
icon: AppAssets.ic_rrt_vehicle,
shape: RoundedRectangleBorder(
side: BorderSide(
color: value == OrderDislpay.RRT ? AppColors.errorColor : AppColors.chipBorderColorOpacity20,
width: 1,
),
borderRadius: BorderRadius.circular(10)),
backgroundColor: value == OrderDislpay.RRT ? AppColors.secondaryLightRedColor : AppColors.whiteColor,
textColor: value == OrderDislpay.RRT ? AppColors.errorColor : AppColors.blackColor,
).toShimmer2(isShow: isLoading).onPress(() {
context.read<EmergencyServicesViewModel>().changeOrderDisplayItems(OrderDislpay.RRT);
}),
],
);
});
}
}

@ -71,7 +71,7 @@ class AmbulanceHistoryItem extends StatelessWidget {
labelText: title,
icon: iconString,
iconColor: iconColor,
iconSize: 14.h,
iconSize: 12.h,
);
}

@ -0,0 +1,76 @@
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/date_util.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/resp_model/AmbulanceRequestOrdersModel.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/RRTServiceData.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/history/widget/RequestStatus.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';
import 'package:provider/provider.dart';
import '../../../../core/utils/utils.dart';
class RRTItem extends StatelessWidget {
final GetCMCAllOrdersResponseModel order;
const RRTItem({super.key, required this.order});
@override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: Colors.white,
hasShadow: true,
customBorder: BorderRadius.all(
Radius.circular(20.h),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8.h,
children: [
RequestStatus(status: order.statusId ?? 0),
"Req ID: ${order.iD}".toText16(color: AppColors.textColor, weight: FontWeight.w600),
Row(
spacing: 4.w,
children: [
chip( Utils.getDayMonthYearDateFormatted(DateUtil.convertStringToDate(order.time)), AppAssets.calendar, AppColors.blackBgColor),
chip("Rapid Response Team(RRT)".needTranslation, AppAssets.ic_rrt_vehicle, AppColors.blackBgColor),
],
),
if (order.statusId == 1 || order.statusId == 2)
CustomButton(
text: "Cancel Request".needTranslation,
onPressed: () async {
openCancelOrderBottomSheet(context);
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: Colors.white,
icon: AppAssets.cancel,
),
],
).paddingAll(16.h),
).paddingOnly(bottom: 16.h);
}
chip(String title, String iconString, Color iconColor) {
return AppCustomChipWidget(
labelText: title,
icon: iconString,
iconColor: iconColor,
iconSize: 12.h,
);
}
openCancelOrderBottomSheet(BuildContext context) {
context.read<EmergencyServicesViewModel>().cancelRRTOrder(order.iD);
}
}

@ -110,6 +110,7 @@ class SmallServiceCard extends StatelessWidget {
case "emergency":
context.read<EmergencyServicesViewModel>().flushData();
context.read<EmergencyServicesViewModel>().getTransportationOrders(showLoader: false,);
context.read<EmergencyServicesViewModel>().getRRTOrders(showLoader: false,);
Navigator.of(context).push(
CustomPageRoute(
page: EmergencyServicesPage(),

@ -115,6 +115,7 @@ void showCommonBottomSheetWithoutHeight(
Widget? titleWidget,
bool useSafeArea = false,
bool hasBottomPadding = true,
EdgeInsets? padding,
Color backgroundColor = AppColors.bottomSheetBgColor,
VoidCallback? onCloseClicked,
}) {
@ -146,44 +147,46 @@ void showCommonBottomSheetWithoutHeight(
physics: ClampingScrollPhysics(),
child: isCloseButtonVisible
? Container(
padding: EdgeInsets.only(
left: 24,
top: 24,
right: 24,
bottom: 12,
),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.bottomSheetBgColor,
borderRadius: 24.h,
),
child: Column(
mainAxisSize: MainAxisSize.min,
padding: padding ?? const EdgeInsets.only(
left: 24,
top: 24,
right: 24,
bottom: 12,
),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.bottomSheetBgColor,
borderRadius: 24.h,
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: padding != null? EdgeInsets.symmetric(horizontal: 24.w): EdgeInsets.zero,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
titleWidget ??
Expanded(
child: title.toText20(weight: FontWeight.w600),
),
if (isCloseButtonVisible) ...[
Utils.buildSvgWithAssets(
icon: AppAssets.close_bottom_sheet_icon,
iconColor: Color(0xff2B353E),
).onPress(() {
onCloseClicked?.call();
Navigator.of(context).pop();
}),
],
],
),
SizedBox(height: 16.h),
child,
titleWidget ??
Expanded(
child: title.toText20(weight: FontWeight.w600),
),
if (isCloseButtonVisible) ...[
Utils.buildSvgWithAssets(
icon: AppAssets.close_bottom_sheet_icon,
iconColor: Color(0xff2B353E),
).onPress(() {
onCloseClicked?.call();
Navigator.of(context).pop();
}),],
],
),
)
),
SizedBox(height: 16.h),
child,
],
),
)
: child,
),
),

Loading…
Cancel
Save