Merge pull request 'ambulance_listing_and_request' (#99) from ambulance_listing_and_request into master

Reviewed-on: #99
pull/102/head
Haroon6138 2 months ago
commit e23f2c1e48

@ -223,6 +223,7 @@ extension EmailValidator on String {
FontWeight? weight,
TextOverflow? textOverflow,
double? letterSpacing = -0.4,
Color decorationColor =AppColors.errorColor
}) =>
Text(
this,
@ -236,6 +237,7 @@ extension EmailValidator on String {
overflow: textOverflow,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
decoration: isUnderLine ? TextDecoration.underline : null,
decorationColor: decorationColor
),
);

@ -58,6 +58,7 @@ abstract class EmergencyServicesRepo {
Future<Either<Failure, GenericApiModel<RRTServiceData>>> getRRTOrders({int? id});
Future<Either<Failure, GenericApiModel<bool>>> cancelRRTOrder(int? iD);
Future<Either<Failure, GenericApiModel<String>>> getTermsAndCondition();
}
class EmergencyServicesRepoImp implements EmergencyServicesRepo {
@ -681,5 +682,40 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo {
}
}
@override
Future<Either<Failure, GenericApiModel<String>>> getTermsAndCondition() async {
try {
GenericApiModel<String>? apiResponse;
Failure? failure;
await apiClient.post(
body: {},
GET_USER_TERMS,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final agreement = response['UserAgreementContent'];
apiResponse = GenericApiModel<String>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: agreement,
);
} 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()));
}
}
}

@ -2,13 +2,17 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart' as GMSMapServices;
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/location_util.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/doctor_response_mapper.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/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';
@ -34,6 +38,8 @@ import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/
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/RRT/rrt_request_type_select.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/RRT/terms_and_condition.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/er_online_checkin/er_online_checkin_home.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/er_online_checkin/er_online_checkin_payment_details_page.dart';
@ -44,6 +50,8 @@ 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/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.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/order_tracking/order_tracking_state.dart';
@ -149,6 +157,8 @@ class EmergencyServicesViewModel extends ChangeNotifier {
bool isMyAppointmentsLoading = false;
String? termsAndConditions;
Future<void> getRRTProcedures({Function(dynamic)? onSuccess, Function(String)? onError}) async {
print("the app state is ${appState.isAuthenticated}");
@ -156,6 +166,7 @@ class EmergencyServicesViewModel extends ChangeNotifier {
dialogService.showErrorBottomSheet(
message: "You Need To Login First To Continue".needTranslation,
onOkPressed: () {
navServices.pop();
getIt<AuthenticationViewModel>().onLoginPressed();
});
return;
@ -490,8 +501,6 @@ class EmergencyServicesViewModel extends ChangeNotifier {
return;
}
if (transportationOptions.isNotEmpty) return;
int? id = appState.getAuthenticatedUser()?.patientId;
LoaderBottomSheet.showLoader(
loadingText: "Getting Ambulance Transport Option".needTranslation);
@ -864,10 +873,10 @@ class EmergencyServicesViewModel extends ChangeNotifier {
Future<void> cancelOrder(AmbulanceRequestOrdersModel? order, {bool shouldPop = false}) async {
dialogService.showCommonBottomSheetWithoutH(
message: "Do you want to cancel the order".needTranslation,
message: "Do you want to cancel the request".needTranslation,
onOkPressed: () async {
navServices.pop();
LoaderBottomSheet.showLoader(loadingText: "Cancelling Order".needTranslation);
LoaderBottomSheet.showLoader(loadingText: "Cancelling request".needTranslation);
var response = await emergencyServicesRepo.cancelOrder(order?.iD, appState.getAuthenticatedUser()?.patientId ?? 0);
LoaderBottomSheet.hideLoader();
response.fold((failure) => errorHandlerService.handleError(failure: failure), (success) {
@ -973,10 +982,10 @@ class EmergencyServicesViewModel extends ChangeNotifier {
FutureOr<void> cancelRRTOrder(int? orderID, {bool shouldPop = false}) async {
dialogService.showCommonBottomSheetWithoutH(
message: "Do you want to cancel the order".needTranslation,
message: "Do you want to cancel the request".needTranslation,
onOkPressed: () async {
navServices.pop();
LoaderBottomSheet.showLoader(loadingText: "Cancelling Order".needTranslation);
LoaderBottomSheet.showLoader(loadingText: "Cancelling request".needTranslation);
var response = await emergencyServicesRepo.cancelRRTOrder(orderID);
LoaderBottomSheet.hideLoader();
response.fold((failure) => errorHandlerService.handleError(failure: failure), (success) {
@ -1009,9 +1018,35 @@ class EmergencyServicesViewModel extends ChangeNotifier {
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);
dialogService.showErrorBottomSheet(message: "You Need To Agree To Terms And Conditions".needTranslation, onOkPressed: (){
if(navServices.context == null ) return;
showCommonBottomSheetWithoutHeight(
navServices.context!,
padding: EdgeInsets.only(top: 24.h),
titleWidget: Transform.flip(
flipX: isArabic,
child: Utils.buildSvgWithAssets(
icon: AppAssets.arrow_back,
iconColor: Color(0xff2B353E),
fit: BoxFit.contain,
),
).onPress(() {
navServices.pop();
}),
// title: "Rapid Response Team (RRT)".needTranslation,
child: RrtRequestTypeSelect(),
isFullScreen: false,
isCloseButtonVisible: true,
hasBottomPadding: false,
backgroundColor: AppColors.bottomSheetBgColor,
callBackFunc: () {
navServices.pop();
},
);
});
return;
}
placeValueInController();
locationUtils!.getLocation(
isShowConfirmDialog: true,
onSuccess: (position) {
@ -1025,6 +1060,7 @@ class EmergencyServicesViewModel extends ChangeNotifier {
dialogService.showErrorBottomSheet(
message: "You Need To Login First To Continue".needTranslation,
onOkPressed: () {
navServices.pop();
getIt<AuthenticationViewModel>().onLoginPressed();
});
}
@ -1032,4 +1068,21 @@ class EmergencyServicesViewModel extends ChangeNotifier {
clearRRTData(){
selectedRRTProcedure = null;
}
FutureOr<void> getTermsAndConditions() async {
LoaderBottomSheet.showLoader(loadingText: "Fetching Terms And Conditions".needTranslation);
var response = await emergencyServicesRepo.getTermsAndCondition();
LoaderBottomSheet.hideLoader();
response.fold((failure)=>errorHandlerService.handleError(failure: failure),(success){
termsAndConditions = success.data;
print("the response terms are $termsAndConditions");
notifyListeners();
navServices.push(
CustomPageRoute(
page: TermsAndCondition(termsAndCondition:success.data??""), direction: AxisDirection.down),
);
});
}
}

@ -61,7 +61,7 @@ class RrtMapScreen extends StatelessWidget {
BottomSheetType.EXPANDED: ExpanedBottomSheet(context),
BottomSheetType.FIXED: FixedBottomSheet(context),
},
),
).paddingAll(16.h),
body: Stack(
children: [
if (context.read<EmergencyServicesViewModel>().isGMSAvailable )
@ -153,7 +153,7 @@ class RrtMapScreen extends StatelessWidget {
],
),
CustomButton(
text: "Select Details".needTranslation,
text: "Submit Request".needTranslation,
onPressed: () {
LocationViewModel locationViewModel = context.read<LocationViewModel>();
GeocodeResponse? response = locationViewModel.geocodeResponse;

@ -11,6 +11,7 @@ import 'package:hmg_patient_app_new/features/emergency_services/models/resp_mode
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/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/radio/custom_radio_button.dart';
import 'package:provider/provider.dart';
@ -186,7 +187,7 @@ class RrtRequestTypeSelect extends StatelessWidget {
final indexOfSelectedItem = selectedProcedure != null ? procedureList.indexOf(selectedProcedure) : -1;
return RadioListTile<int>(
title: (procedure.procedureName ?? "").toText12(color: AppColors.textColor),
title: (procedure.procedureName ?? "").toText16(color: AppColors.textColor, weight: FontWeight.w500),
value: index,
fillColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.selected)) {
@ -231,23 +232,32 @@ class RrtRequestTypeSelect extends StatelessWidget {
) {
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);
}),
SizedBox(
height: 18.h,
width: 18.w,
child: Checkbox(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
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(
spacing: 4.w,
children: [
LocaleKeys.agreeTo.tr().toText12(color: AppColors.textColor),
LocaleKeys.termsConditoins.tr().toText12(color: AppColors.errorColor, isUnderLine: true),
SizedBox.shrink(),
LocaleKeys.agreeTo.tr().toText16(color: AppColors.textColor, weight: FontWeight.w500),
LocaleKeys.termsConditoins.tr().toText16(color: AppColors.errorColor, isUnderLine: true, weight: FontWeight.w500).onPress(() {
emergencyServicesVM.getTermsAndConditions();
}),
],
),
],

@ -0,0 +1,33 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_widget_from_html/flutter_widget_from_html.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/emergency_services/emergency_services_view_model.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:provider/provider.dart';
class TermsAndCondition extends StatelessWidget {
final String termsAndCondition;
const TermsAndCondition({super.key, required this.termsAndCondition});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
child: CollapsingListView(
title: "Terms And Condition".needTranslation,
child:DecoratedBox(decoration:RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: true,
),child: HtmlWidget(termsAndCondition).paddingAll(16.h)).paddingAll(12.h)))]));
}
}

@ -369,9 +369,9 @@ class CallAmbulancePage extends StatelessWidget {
Row(
children: [
hospitalAndPickUpItemContent(
title: '',
title: 'Appointment',
subTitle: "Have any appointment".needTranslation,
leadingIcon: AppAssets.appointment_checkin_icon,
leadingIcon: AppAssets.appointment_calendar_icon,
),
CustomSwitch(
value: context
@ -405,7 +405,7 @@ class CallAmbulancePage extends StatelessWidget {
borderRadius: 12.h,
color: AppColors.greyColor,
),
child: Utils.buildSvgWithAssets(icon: leadingIcon),
child: Utils.buildSvgWithAssets(icon: leadingIcon, iconColor: AppColors.greyTextColor),
);
}

@ -56,7 +56,8 @@ class TrackingScreen extends StatelessWidget {
visible: state == OrderTrackingState.ended,
child: SafeArea(
child: CustomButton(
height: 56.h,
height: 40.h,
iconSize: 18.w,
backgroundColor: AppColors.bgGreenColor,
borderColor: Colors.transparent,
text: "Close".needTranslation,
@ -143,6 +144,8 @@ class TrackingScreen extends StatelessWidget {
borderColor: AppColors.primaryRedColor,
textColor: Colors.white,
icon: AppAssets.cancel,
height: 40.h,
iconSize: 18.w,
),
],
);
@ -156,6 +159,7 @@ class TrackingScreen extends StatelessWidget {
mapSection(context),
CustomButton(
height: 40.h,
iconSize: 18.w,
backgroundColor: AppColors.lightRedButtonColor,
borderColor: Colors.transparent,
text: "Share Your Live Location on Whatsapp".needTranslation,
@ -225,13 +229,13 @@ class TrackingScreen extends StatelessWidget {
width: 36.h,
child: CustomButton(
text: '',
iconSize: 16.h,
iconSize: 18.h,
icon: AppAssets.call_fill,
onPressed: () {},
backgroundColor: AppColors.lightRedButtonColor,
iconColor: AppColors.primaryRedColor,
borderColor: Colors.transparent,
height: 36.h,
height: 40.h,
),
)
],
@ -367,6 +371,7 @@ class TrackingScreen extends StatelessWidget {
}
contactSection() {
if(isRRTOrder) return SizedBox.shrink();
return Container(
padding: EdgeInsets.all(16.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
@ -381,8 +386,12 @@ class TrackingScreen extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 4.h,
children: [
"Contact Rapid Response Team (RRT)".needTranslation.toText14(color: AppColors.textColor, weight: FontWeight.w600),
"0115259555".needTranslation.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
"Contact".needTranslation.toText14(color: AppColors.textColor, weight: FontWeight.w600),
"0115259555".needTranslation.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500).onPress((){
launchUrl(
Uri.parse("tel://0115259555"),
);
}),
SizedBox(height: 8.h),
],
),

@ -29,7 +29,7 @@ class PickupLocation extends StatelessWidget {
),
"Select Direction"
.needTranslation
.toText14(color: AppColors.textColor, weight: FontWeight.w600),
.toText16(color: AppColors.textColor, weight: FontWeight.w600),
SizedBox(
height: 12.h,
),
@ -61,7 +61,7 @@ class PickupLocation extends StatelessWidget {
),
"To Hospital"
.needTranslation
.toText12(color: AppColors.textColor)
.toText14(color: AppColors.textColor, weight: FontWeight.w500)
],
).onPress((){
context
@ -78,7 +78,7 @@ class PickupLocation extends StatelessWidget {
),
"From Hospital"
.needTranslation
.toText12(color: AppColors.textColor)
.toText14(color: AppColors.textColor, weight: FontWeight.w500)
],
).onPress((){
context
@ -96,10 +96,11 @@ class PickupLocation extends StatelessWidget {
builder: (context, directionValue, _) {
return Column(
spacing: 12.h,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Select Way"
.needTranslation
.toText14(color: AppColors.textColor, weight: FontWeight.w600),
.toText16(color: AppColors.textColor, weight: FontWeight.w600),
RadioGroup<AmbulanceDirection>(
groupValue: directionValue,
onChanged: (value) {
@ -121,7 +122,7 @@ class PickupLocation extends StatelessWidget {
),
"One Way"
.needTranslation
.toText12(color: AppColors.textColor)
.toText12(color: AppColors.textColor, fontWeight: FontWeight.w500)
],
).onPress((){
context
@ -138,7 +139,7 @@ class PickupLocation extends StatelessWidget {
),
"Two Way"
.needTranslation
.toText12(color: AppColors.textColor)
.toText14(color: AppColors.textColor, weight: FontWeight.w500)
],
).onPress((){
context

@ -38,11 +38,12 @@ class ErHistoryListing extends StatelessWidget {
return Column(
children: [
orderChips(context, data.$2),
orderChips(context, data.$2, data.$1),
Visibility(
visible:data.$1.isNotEmpty == true,
child: ListView.builder(
padding: EdgeInsets.only(top:24.h ),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount:data?.$1.length ?? 0,
@ -82,25 +83,18 @@ class ErHistoryListing extends StatelessWidget {
);
}
orderChips(BuildContext context, bool isLoading) {
orderChips(BuildContext context, bool isLoading, List dataList) {
if (context
.read<EmergencyServicesViewModel>()
.displayList
?.isEmpty == true) {
if (dataList?.isEmpty == true) {
return SizedBox.shrink();
}
return
Selector<EmergencyServicesViewModel, OrderDislpay>(
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)
if(dataList?.isNotEmpty == true)
AppCustomChipWidget(
labelText: "All Facilities".needTranslation,
shape: RoundedRectangleBorder(

@ -54,8 +54,8 @@ class RequestStatus extends StatelessWidget {
switch (status) {
case 1: //pending
case 2:
return AppColors.successColor;//processing
case 3: //completed
return AppColors.successColor;//processing
case 4: //cancel
case 6:
case 7:

@ -60,6 +60,8 @@ class AmbulanceHistoryItem extends StatelessWidget {
borderColor: AppColors.primaryRedColor,
textColor: Colors.white,
icon: AppAssets.cancel,
height: 40.h,
iconSize: 18.w,
),
],
).paddingAll(16.h),

@ -55,6 +55,8 @@ class RRTItem extends StatelessWidget {
borderColor: AppColors.primaryRedColor,
textColor: Colors.white,
icon: AppAssets.cancel,
height: 40.h,
iconSize: 18.w,
),
],
).paddingAll(16.h),

@ -21,7 +21,7 @@ class _CustomSwitchState extends State<CustomSwitch> {
width: 48.w,
height: 30.h,
decoration: BoxDecoration(
color: AppColors.switchBackgroundColor ,
color: widget.value ? AppColors.switchBackgroundColor : AppColors.greyTextColor,
borderRadius: BorderRadius.circular(18),
),
child: AnimatedAlign(
@ -32,7 +32,7 @@ class _CustomSwitchState extends State<CustomSwitch> {
width: 28.w,
height: 28.h,
decoration: BoxDecoration(
color: AppColors.thumbColor,
color: widget.value? AppColors.thumbColor : AppColors.greyColor,
shape: BoxShape.circle,
),
),

@ -125,7 +125,8 @@ void showCommonBottomSheetWithoutHeight(
reverseDuration: Duration(milliseconds: 300),
),
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width, // Full width
maxWidth: MediaQuery.sizeOf(context).width//MediaQuery.of(context).size.width, // Full width
),
context: context,
isScrollControlled: true,

Loading…
Cancel
Save