diff --git a/assets/images/svg/small_livecare_icon.svg b/assets/images/svg/small_livecare_icon.svg
new file mode 100644
index 0000000..a496914
--- /dev/null
+++ b/assets/images/svg/small_livecare_icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/walkin_appointment_icon.svg b/assets/images/svg/walkin_appointment_icon.svg
new file mode 100644
index 0000000..ceafb38
--- /dev/null
+++ b/assets/images/svg/walkin_appointment_icon.svg
@@ -0,0 +1,4 @@
+
diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart
index 83fb842..f7ca57d 100644
--- a/lib/core/app_assets.dart
+++ b/lib/core/app_assets.dart
@@ -133,6 +133,8 @@ class AppAssets {
static const String minus = '$svgBasePath/minus.svg';
static const String home_lab_result_icon = '$svgBasePath/home_lab_result_icon.svg';
static const String visa_mastercard_icon = '$svgBasePath/visa_mastercard.svg';
+ static const String small_livecare_icon = '$svgBasePath/small_livecare_icon.svg';
+ static const String walkin_appointment_icon = '$svgBasePath/walkin_appointment_icon.svg';
//bottom navigation//
static const String homeBottom = '$svgBasePath/home_bottom.svg';
diff --git a/lib/features/book_appointments/book_appointments_repo.dart b/lib/features/book_appointments/book_appointments_repo.dart
index c3cc9cf..5e99585 100644
--- a/lib/features/book_appointments/book_appointments_repo.dart
+++ b/lib/features/book_appointments/book_appointments_repo.dart
@@ -53,6 +53,19 @@ abstract class BookAppointmentsRepo {
Future>> getLiveCareDoctorFreeSlots(int clinicID, int serviceID, int projectID, int doctorId, bool isBookingForLiveCare,
{Function(dynamic)? onSuccess, Function(String)? onError});
+
+ Future>> insertSpecificAppointmentForLiveCare(
+ {required int docID,
+ required int clinicID,
+ required int projectID,
+ required String selectedTime,
+ required String selectedDate,
+ required int initialSlotDuration,
+ required int genderID,
+ required int userAge,
+ required int serviceID,
+ Function(dynamic)? onSuccess,
+ Function(String)? onError});
}
class BookAppointmentsRepoImp implements BookAppointmentsRepo {
@@ -580,4 +593,68 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo {
return Left(UnknownFailure(e.toString()));
}
}
+
+ @override
+ Future> insertSpecificAppointmentForLiveCare(
+ {required int docID,
+ required int clinicID,
+ required int projectID,
+ required String selectedTime,
+ required String selectedDate,
+ required int initialSlotDuration,
+ required int genderID,
+ required int userAge,
+ required int serviceID,
+ Function(dynamic)? onSuccess,
+ Function(String)? onError}) async {
+ Map mapDevice = {
+ "IsForLiveCare": true,
+ "ProjectID": projectID,
+ "ClinicID": clinicID,
+ "DoctorID": docID,
+ "ServiceID": serviceID,
+ "StartTime": selectedTime,
+ "SelectedTime": selectedTime,
+ "EndTime": selectedTime,
+ "InitialSlotDuration": initialSlotDuration,
+ "StrAppointmentDate": selectedDate,
+ "IsVirtual": false,
+ "BookedBy": 102,
+ "VisitType": 1,
+ "VisitFor": 1,
+ "GenderID": genderID,
+ "Age": userAge
+ };
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ INSERT_LIVECARE_SCHEDULE_APPOINTMENT,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final appointmentNo = response['AppointmentNo'];
+
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: response["ErrorEndUserMessage"],
+ data: response,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
}
diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart
index e8d02b9..c42a20d 100644
--- a/lib/features/book_appointments/book_appointments_view_model.dart
+++ b/lib/features/book_appointments/book_appointments_view_model.dart
@@ -414,18 +414,9 @@ class BookAppointmentsViewModel extends ChangeNotifier {
);
}
- //TODO: Handle the cases for LiveCare Schedule, Dental & Laser Clinics
+ //TODO: Handle the cases for Dental & Laser Clinics
Future insertSpecificAppointment(
- {
- // required int docID,
- // required int clinicID,
- // required int projectID,
- // required String selectedTime,
- // required String selectedDate,
- // required int initialSlotDuration,
- // required int genderID,
- // required int userAge,
- String? procedureID,
+ {String? procedureID,
num? testTypeEnum,
num? testProcedureEnum,
int? invoiceNumber,
@@ -527,6 +518,102 @@ class BookAppointmentsViewModel extends ChangeNotifier {
);
}
+ Future insertSpecificAppointmentForLiveCare({Function(dynamic p1)? onSuccess, Function(dynamic p1)? onError}) async {
+ _appState = getIt();
+ final result = await bookAppointmentsRepo.insertSpecificAppointmentForLiveCare(
+ docID: selectedDoctor.doctorID!,
+ clinicID: selectedDoctor.clinicID!,
+ projectID: selectedDoctor.projectID!,
+ serviceID: selectedLiveCareClinic.serviceID!,
+ selectedDate: selectedAppointmentDate,
+ selectedTime: selectedAppointmentTime,
+ initialSlotDuration: initialSlotDuration,
+ genderID: _appState.getAuthenticatedUser()!.gender!,
+ userAge: _appState.getAuthenticatedUser()!.age!,
+ onError: onError);
+
+ result.fold(
+ (failure) async {
+ print(failure);
+ },
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ // onError!(apiResponse);
+ LoadingUtils.hideFullScreenLoader();
+ showCommonBottomSheetWithoutHeight(
+ title: LocaleKeys.notice.tr(context: navigationService.navigatorKey.currentContext!),
+ navigationService.navigatorKey.currentContext!,
+ child: Utils.getWarningWidget(
+ loadingText: apiResponse.data["ErrorEndUserMessage"],
+ isShowActionButtons: true,
+ onCancelTap: () {
+ navigationService.pop();
+ },
+ onConfirmTap: () async {
+ navigationService.pop();
+ PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel = PatientAppointmentHistoryResponseModel(
+ appointmentNo: apiResponse.data["SameClinicApptList"][0]['AppointmentNo'],
+ clinicID: apiResponse.data["SameClinicApptList"][0]['ClinicID'],
+ projectID: apiResponse.data["SameClinicApptList"][0]['ProjectID'],
+ endDate: apiResponse.data["SameClinicApptList"][0]['EndTime'],
+ startTime: apiResponse.data["SameClinicApptList"][0]['StartTime'],
+ doctorID: apiResponse.data["SameClinicApptList"][0]['DoctorID'],
+ isLiveCareAppointment: apiResponse.data["SameClinicApptList"][0]['IsLiveCareAppointment'],
+ originalClinicID: 0,
+ originalProjectID: 0,
+ appointmentDate: apiResponse.data["SameClinicApptList"][0]['AppointmentDate'],
+ );
+
+ showCommonBottomSheet(navigationService.navigatorKey.currentContext!,
+ child: Utils.getLoadingWidget(loadingText: "Cancelling your previous appointment....".needTranslation),
+ callBackFunc: (str) {},
+ title: "",
+ height: ResponsiveExtension.screenHeight * 0.3,
+ isCloseButtonVisible: false,
+ isDismissible: false,
+ isFullScreen: false);
+ await cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel).then((val) async {
+ navigationService.pop();
+ Future.delayed(Duration(milliseconds: 50)).then((value) async {});
+ LoadingUtils.showFullScreenLoader(barrierDismissible: true, isSuccessDialog: false, loadingText: "Booking your appointment...".needTranslation);
+ await insertSpecificAppointment(
+ onError: (err) {},
+ onSuccess: (apiResp) async {
+ LoadingUtils.hideFullScreenLoader();
+ await Future.delayed(Duration(milliseconds: 50)).then((value) async {
+ LoadingUtils.showFullScreenLoader(barrierDismissible: true, isSuccessDialog: true, loadingText: LocaleKeys.appointmentSuccess.tr());
+ await Future.delayed(Duration(milliseconds: 4000)).then((value) {
+ LoadingUtils.hideFullScreenLoader();
+ Navigator.pushAndRemoveUntil(
+ navigationService.navigatorKey.currentContext!,
+ CustomPageRoute(
+ page: LandingNavigation(),
+ ),
+ (r) => false);
+ });
+ });
+ });
+ });
+ }),
+ callBackFunc: () {},
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ );
+ } else if (apiResponse.messageStatus == 1) {
+ if (apiResponse.data == null || apiResponse.data!.isEmpty) {
+ onError!("No free slots available".tr());
+ return;
+ }
+
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+
Future getRegionMappedProjectList() async {
isRegionListLoading = true;
notifyListeners();
diff --git a/lib/features/my_appointments/my_appointments_repo.dart b/lib/features/my_appointments/my_appointments_repo.dart
index e4745cb..99f7c7d 100644
--- a/lib/features/my_appointments/my_appointments_repo.dart
+++ b/lib/features/my_appointments/my_appointments_repo.dart
@@ -1,10 +1,13 @@
+import 'dart:io';
+
import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
+import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
-import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart'
- show HospitalsModel;
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart' show HospitalsModel;
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_share_response_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
@@ -12,7 +15,8 @@ import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class MyAppointmentsRepo {
Future>>> getPatientAppointments({required bool isActiveAppointment, required bool isArrivedAppointments});
- Future>> getPatientShareAppointment({required int projectID, required int clinicID, required String appointmentNo});
+ Future>> getPatientShareAppointment(
+ {required int projectID, required int clinicID, required String appointmentNo, required bool isLiveCareAppointment});
Future>> createAdvancePayment(
{required String paymentMethodName,
@@ -39,7 +43,7 @@ abstract class MyAppointmentsRepo {
Future>>> getPatientDoctorsList();
-
+ Future>> insertLiveCareVIDARequest({required clientRequestID, required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel});
}
class MyAppointmentsRepoImp implements MyAppointmentsRepo {
@@ -99,14 +103,15 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
}
@override
- Future>> getPatientShareAppointment({required int projectID, required int clinicID, required String appointmentNo}) async {
- Map mapRequest = {"ProjectID": projectID, "ClinicID": clinicID, "AppointmentNo": appointmentNo, "IsActiveAppointment": true};
+ Future>> getPatientShareAppointment(
+ {required int projectID, required int clinicID, required String appointmentNo, required bool isLiveCareAppointment}) async {
+ Map mapRequest = {"ProjectID": projectID, "ClinicID": clinicID, "AppointmentNo": appointmentNo, "IsActiveAppointment": true, "IsForLiveCare": isLiveCareAppointment};
try {
GenericApiModel? apiResponse;
Failure? failure;
await apiClient.post(
- GET_PATIENT_SHARE,
+ isLiveCareAppointment ? GET_PATIENT_SHARE_LIVECARE : GET_PATIENT_SHARE,
body: mapRequest,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
@@ -495,4 +500,50 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
return Left(UnknownFailure(e.toString()));
}
}
+
+ @override
+ Future> insertLiveCareVIDARequest({required clientRequestID, required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel}) async {
+ Map requestBody = {
+ "AppointmentNo": patientAppointmentHistoryResponseModel.appointmentNo,
+ "AppointmentDate": patientAppointmentHistoryResponseModel.appointmentDate,
+ "ClientRequestID": clientRequestID,
+ "ClinicID": patientAppointmentHistoryResponseModel.clinicID,
+ "ProjectID": patientAppointmentHistoryResponseModel.projectID,
+ "ServiceID": patientAppointmentHistoryResponseModel.serviceID,
+ "AcceptedBy": patientAppointmentHistoryResponseModel.doctorID,
+ "IsFlutter": true,
+ "DeviceToken": await Utils.getStringFromPrefs(CacheConst.pushToken),
+ "VoipToken": "", // TODO: Add VoIP Token functionality
+ "IsVoip": Platform.isIOS ? true : false
+ };
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ INSERT_VIDA_REQUEST,
+ body: requestBody,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: response,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
}
diff --git a/lib/features/my_appointments/my_appointments_view_model.dart b/lib/features/my_appointments/my_appointments_view_model.dart
index 55fafc4..1b884f7 100644
--- a/lib/features/my_appointments/my_appointments_view_model.dart
+++ b/lib/features/my_appointments/my_appointments_view_model.dart
@@ -79,7 +79,6 @@ class MyAppointmentsViewModel extends ChangeNotifier {
}
Future getPatientAppointments(bool isActiveAppointment, bool isArrivedAppointments, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
-
patientAppointmentsHistoryList.clear();
patientUpcomingAppointmentsHistoryList.clear();
patientArrivedAppointmentsHistoryList.clear();
@@ -127,8 +126,8 @@ class MyAppointmentsViewModel extends ChangeNotifier {
print('All Appointments: ${patientAppointmentsHistoryList.length}');
}
- Future getPatientShareAppointment(int projectID, int clinicID, String appointmentNo, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
- final result = await myAppointmentsRepo.getPatientShareAppointment(projectID: projectID, clinicID: clinicID, appointmentNo: appointmentNo);
+ Future getPatientShareAppointment(int projectID, int clinicID, String appointmentNo, bool isLiveCareAppointment, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await myAppointmentsRepo.getPatientShareAppointment(projectID: projectID, clinicID: clinicID, appointmentNo: appointmentNo, isLiveCareAppointment: isLiveCareAppointment);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
@@ -305,4 +304,24 @@ class MyAppointmentsViewModel extends ChangeNotifier {
},
);
}
+
+ Future insertLiveCareVIDARequest(
+ {required clientRequestID, required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await myAppointmentsRepo.insertLiveCareVIDARequest(clientRequestID: clientRequestID, patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel);
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(failure: failure),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ onError!(apiResponse.errorMessage!);
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
}
diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart
index 7a98b9d..f474104 100644
--- a/lib/presentation/appointments/appointment_details_page.dart
+++ b/lib/presentation/appointments/appointment_details_page.dart
@@ -81,29 +81,6 @@ class _AppointmentDetailsPageState extends State {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- // Row(
- // mainAxisAlignment: MainAxisAlignment.spaceBetween,
- // children: [
- // "Appointment Details".needTranslation.toText20(isBold: true),
- // if (AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel))
- // CustomButton(
- // text: "Report".needTranslation,
- // onPressed: () {},
- // backgroundColor: AppColors.secondaryLightRedColor,
- // borderColor: AppColors.secondaryLightRedColor,
- // textColor: AppColors.primaryRedColor,
- // fontSize: 14,
- // fontWeight: FontWeight.w500,
- // borderRadius: 12,
- // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- // height: 40.h,
- // iconSize: 16.h,
- // icon: AppAssets.report_icon,
- // iconColor: AppColors.primaryRedColor,
- // )
- // ],
- // ),
- // SizedBox(height: 24.h),
AppointmentDoctorCard(
patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
onAskDoctorTap: () {},
@@ -162,42 +139,60 @@ class _AppointmentDetailsPageState extends State {
? "Not Confirmed".needTranslation.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500)
: "Confirmed".needTranslation.toText12(color: AppColors.successColor, fontWeight: FontWeight.w500)),
SizedBox(height: 16.h),
- Stack(
- children: [
- ClipRRect(
- clipBehavior: Clip.hardEdge,
- borderRadius: BorderRadius.circular(24),
- child: Image.network(
- "https://maps.googleapis.com/maps/api/staticmap?center=${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&zoom=14&size=350x165&maptype=roadmap&markers=color:red%7C${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&key=AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng",
- fit: BoxFit.contain,
- ),
- ),
- Positioned(
- bottom: 0,
- child: SizedBox(
- width: MediaQuery.of(context).size.width * 0.785,
- child: CustomButton(
- text: "Get Directions".needTranslation,
- onPressed: () {
- MapsLauncher.launchCoordinates(double.parse(widget.patientAppointmentHistoryResponseModel.latitude!),
- double.parse(widget.patientAppointmentHistoryResponseModel.longitude!), widget.patientAppointmentHistoryResponseModel.projectName);
- },
- backgroundColor: AppColors.textColor.withOpacity(0.8),
- borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
- textColor: AppColors.whiteColor,
- fontSize: 14,
- fontWeight: FontWeight.w500,
- borderRadius: 12.h,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 40.h,
- icon: AppAssets.directions_icon,
- iconColor: AppColors.whiteColor,
- iconSize: 13.h,
- ).paddingAll(12.h),
+ widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false
+ ? Row(
+ children: [
+ Utils.buildSvgWithAssets(icon: AppAssets.livecare_clinic_icon, width: 58.h, height: 58.h),
+ SizedBox(width: 18.h),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "LiveCare Appointment".toText18(color: AppColors.textColor, isBold: true),
+ "The doctor will call you once the appointment time approaches."
+ .needTranslation
+ .toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
+ ],
+ ),
+ ),
+ ],
+ )
+ : Stack(
+ children: [
+ ClipRRect(
+ clipBehavior: Clip.hardEdge,
+ borderRadius: BorderRadius.circular(24),
+ child: Image.network(
+ "https://maps.googleapis.com/maps/api/staticmap?center=${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&zoom=14&size=350x165&maptype=roadmap&markers=color:red%7C${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&key=AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng",
+ fit: BoxFit.contain,
+ ),
+ ),
+ Positioned(
+ bottom: 0,
+ child: SizedBox(
+ width: MediaQuery.of(context).size.width * 0.785,
+ child: CustomButton(
+ text: "Get Directions".needTranslation,
+ onPressed: () {
+ MapsLauncher.launchCoordinates(double.parse(widget.patientAppointmentHistoryResponseModel.latitude!),
+ double.parse(widget.patientAppointmentHistoryResponseModel.longitude!), widget.patientAppointmentHistoryResponseModel.projectName);
+ },
+ backgroundColor: AppColors.textColor.withOpacity(0.8),
+ borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
+ textColor: AppColors.whiteColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12.h,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ icon: AppAssets.directions_icon,
+ iconColor: AppColors.whiteColor,
+ iconSize: 13.h,
+ ).paddingAll(12.h),
+ ),
+ ),
+ ],
),
- ),
- ],
- ),
],
),
),
diff --git a/lib/presentation/appointments/appointment_payment_page.dart b/lib/presentation/appointments/appointment_payment_page.dart
index 77d5d03..28355dc 100644
--- a/lib/presentation/appointments/appointment_payment_page.dart
+++ b/lib/presentation/appointments/appointment_payment_page.dart
@@ -27,9 +27,8 @@ 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/in_app_browser/InAppBrowser.dart';
+import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
-import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
-import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart';
import 'package:smooth_corner/smooth_corner.dart';
@@ -61,6 +60,7 @@ class _AppointmentPaymentPageState extends State {
widget.patientAppointmentHistoryResponseModel.projectID,
widget.patientAppointmentHistoryResponseModel.clinicID,
widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
+ widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false,
);
});
super.initState();
@@ -361,8 +361,7 @@ class _AppointmentPaymentPageState extends State {
}
void checkPaymentStatus() async {
- showCommonBottomSheet(context,
- child: Utils.getLoadingWidget(), callBackFunc: (str) {}, title: "", height: ResponsiveExtension.screenHeight * 0.3, isCloseButtonVisible: false, isDismissible: false, isFullScreen: false);
+ LoaderBottomSheet.showLoader();
await payfortViewModel.checkPaymentStatus(
transactionID: transID,
onSuccess: (apiResponse) async {
@@ -388,6 +387,21 @@ class _AppointmentPaymentPageState extends State {
onSuccess: (value) async {
if (widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment!) {
//TODO: Implement LiveCare Check-In API Call
+ await myAppointmentsViewModel.insertLiveCareVIDARequest(
+ clientRequestID: transID,
+ patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
+ onSuccess: (apiResponse) {
+ Future.delayed(Duration(milliseconds: 500), () {
+ LoaderBottomSheet.hideLoader();
+ Navigator.pushAndRemoveUntil(
+ context,
+ CustomPageRoute(
+ page: LandingNavigation(),
+ ),
+ (r) => false);
+ });
+ },
+ onError: (error) {});
} else {
await myAppointmentsViewModel.generateAppointmentQR(
clinicID: widget.patientAppointmentHistoryResponseModel.clinicID,
@@ -396,16 +410,16 @@ class _AppointmentPaymentPageState extends State {
isFollowUp: myAppointmentsViewModel.patientAppointmentShareResponseModel!.isFollowup!,
onSuccess: (apiResponse) {
Future.delayed(Duration(milliseconds: 500), () {
- Navigator.of(context).pop();
+ LoaderBottomSheet.hideLoader();
Navigator.pushAndRemoveUntil(
context,
CustomPageRoute(
page: LandingNavigation(),
),
(r) => false);
- Navigator.of(context).push(
- CustomPageRoute(page: MyAppointmentsPage()),
- );
+ // Navigator.of(context).push(
+ // CustomPageRoute(page: MyAppointmentsPage()),
+ // );
});
});
}
diff --git a/lib/presentation/appointments/widgets/appointment_card.dart b/lib/presentation/appointments/widgets/appointment_card.dart
index c345099..152436a 100644
--- a/lib/presentation/appointments/widgets/appointment_card.dart
+++ b/lib/presentation/appointments/widgets/appointment_card.dart
@@ -18,6 +18,7 @@ import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
+import 'package:smooth_corner/smooth_corner.dart';
class AppointmentCard extends StatefulWidget {
AppointmentCard({super.key, required this.patientAppointmentHistoryResponseModel, required this.myAppointmentsViewModel, this.isLoading = false, this.isFromHomePage = false});
@@ -63,44 +64,38 @@ class _AppointmentCardState extends State {
spacing: 6.h,
runSpacing: 6.h,
children: [
- Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- CustomButton(
- text: widget.isLoading
- ? "OutPatient"
- : appState.isArabic()
- ? widget.patientAppointmentHistoryResponseModel.isInOutPatientDescriptionN!
- : widget.patientAppointmentHistoryResponseModel.isInOutPatientDescription!,
- onPressed: () {},
- backgroundColor: AppColors.primaryRedColor.withOpacity(0.1),
- borderColor: AppColors.primaryRedColor.withOpacity(0.0),
- textColor: AppColors.primaryRedColor,
- fontSize: 10,
- fontWeight: FontWeight.w500,
- borderRadius: 8,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- ],
- ),
- Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- CustomButton(
- text: widget.isLoading ? "Booked" : AppointmentType.getAppointmentStatusType(widget.patientAppointmentHistoryResponseModel.patientStatusType!),
- onPressed: () {},
- backgroundColor: AppColors.successColor.withOpacity(0.1),
- borderColor: AppColors.successColor.withOpacity(0.0),
- textColor: AppColors.successColor,
- fontSize: 10,
- fontWeight: FontWeight.w500,
- borderRadius: 8,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- ],
- ),
+ AppCustomChipWidget(
+ icon: widget.isLoading
+ ? AppAssets.walkin_appointment_icon
+ : (!widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppAssets.walkin_appointment_icon : AppAssets.small_livecare_icon),
+ iconColor: widget.isLoading
+ ? AppColors.textColor
+ : !widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment!
+ ? AppColors.textColor
+ : AppColors.whiteColor,
+ labelText: widget.isLoading
+ ? "Walk In"
+ : widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment!
+ ? LocaleKeys.livecare.tr(context: context)
+ : "Walk In".needTranslation,
+ backgroundColor:
+ widget.isLoading ? AppColors.greyColor : (!widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.greyColor : AppColors.successColor),
+ textColor: widget.isLoading ? AppColors.textColor : (!widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.textColor : AppColors.whiteColor),
+ ).toShimmer2(isShow: widget.isLoading),
+ AppCustomChipWidget(
+ labelText: widget.isLoading
+ ? "OutPatient"
+ : appState.isArabic()
+ ? widget.patientAppointmentHistoryResponseModel.isInOutPatientDescriptionN!
+ : widget.patientAppointmentHistoryResponseModel.isInOutPatientDescription!,
+ backgroundColor: AppColors.primaryRedColor.withOpacity(0.1),
+ textColor: AppColors.primaryRedColor,
+ ).toShimmer2(isShow: widget.isLoading),
+ AppCustomChipWidget(
+ labelText: widget.isLoading ? "Booked" : AppointmentType.getAppointmentStatusType(widget.patientAppointmentHistoryResponseModel.patientStatusType!),
+ backgroundColor: AppColors.successColor.withOpacity(0.1),
+ textColor: AppColors.successColor,
+ ).toShimmer2(isShow: widget.isLoading),
],
).toShimmer2(isShow: widget.isLoading),
),
diff --git a/lib/presentation/appointments/widgets/appointment_doctor_card.dart b/lib/presentation/appointments/widgets/appointment_doctor_card.dart
index da00d88..b35305f 100644
--- a/lib/presentation/appointments/widgets/appointment_doctor_card.dart
+++ b/lib/presentation/appointments/widgets/appointment_doctor_card.dart
@@ -59,6 +59,13 @@ class AppointmentDoctorCard extends StatelessWidget {
icon: AppAssets.doctor_calendar_icon,
labelText:
"${DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)}, ${DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)}"),
+ AppCustomChipWidget(
+ icon: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppAssets.walkin_appointment_icon : AppAssets.small_livecare_icon,
+ iconColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.textColor : AppColors.whiteColor,
+ labelText: patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? LocaleKeys.livecare.tr(context: context) : "Walk In".needTranslation,
+ backgroundColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.greyColor : AppColors.successColor,
+ textColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.textColor : AppColors.whiteColor,
+ ),
AppCustomChipWidget(icon: AppAssets.rating_icon, iconColor: AppColors.ratingColorYellow, labelText: "Rating: ${patientAppointmentHistoryResponseModel.decimalDoctorRate}"),
],
),
@@ -113,29 +120,8 @@ class AppointmentDoctorCard extends StatelessWidget {
iconSize: 16.h,
);
} else {
- return Row(
- children: [
- Expanded(
- child: CustomButton(
- text: LocaleKeys.reschedule.tr(),
- onPressed: () {
- onRescheduleTap();
- },
- backgroundColor: AppColors.secondaryLightRedColor,
- borderColor: AppColors.secondaryLightRedColor,
- textColor: AppColors.primaryRedColor,
- fontSize: 14,
- fontWeight: FontWeight.w500,
- borderRadius: 12.h,
- height: 40.h,
- icon: AppAssets.appointment_calendar_icon,
- iconColor: AppColors.primaryRedColor,
- iconSize: 16.h,
- ),
- ),
- SizedBox(width: 16.h),
- Expanded(
- child: CustomButton(
+ return patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false
+ ? CustomButton(
text: LocaleKeys.cancel.tr(),
onPressed: () {
onCancelTap();
@@ -150,10 +136,48 @@ class AppointmentDoctorCard extends StatelessWidget {
icon: AppAssets.cancel,
iconColor: AppColors.whiteColor,
iconSize: 16.h,
- ),
- ),
- ],
- );
+ )
+ : Row(
+ children: [
+ Expanded(
+ child: CustomButton(
+ text: LocaleKeys.reschedule.tr(),
+ onPressed: () {
+ onRescheduleTap();
+ },
+ backgroundColor: AppColors.secondaryLightRedColor,
+ borderColor: AppColors.secondaryLightRedColor,
+ textColor: AppColors.primaryRedColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12.h,
+ height: 40.h,
+ icon: AppAssets.appointment_calendar_icon,
+ iconColor: AppColors.primaryRedColor,
+ iconSize: 16.h,
+ ),
+ ),
+ SizedBox(width: 16.h),
+ Expanded(
+ child: CustomButton(
+ text: LocaleKeys.cancel.tr(),
+ onPressed: () {
+ onCancelTap();
+ },
+ backgroundColor: AppColors.primaryRedColor,
+ borderColor: AppColors.primaryRedColor,
+ textColor: AppColors.whiteColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12.h,
+ height: 40.h,
+ icon: AppAssets.cancel,
+ iconColor: AppColors.whiteColor,
+ iconSize: 16.h,
+ ),
+ ),
+ ],
+ );
}
}
}
diff --git a/lib/presentation/book_appointment/doctor_profile_page.dart b/lib/presentation/book_appointment/doctor_profile_page.dart
index 8640c79..943bf59 100644
--- a/lib/presentation/book_appointment/doctor_profile_page.dart
+++ b/lib/presentation/book_appointment/doctor_profile_page.dart
@@ -115,29 +115,53 @@ class DoctorProfilePage extends StatelessWidget {
text: "View available appointments".needTranslation,
onPressed: () async {
LoaderBottomSheet.showLoader();
- await bookAppointmentsViewModel.getDoctorFreeSlots(
- isBookingForLiveCare: false,
- onSuccess: (dynamic respData) async {
- LoaderBottomSheet.hideLoader();
- showCommonBottomSheetWithoutHeight(
- title: "Pick a Date".needTranslation,
- context,
- child: AppointmentCalendar(),
- isFullScreen: false,
- isCloseButtonVisible: true,
- callBackFunc: () {},
- );
- },
- onError: (err) {
- LoaderBottomSheet.hideLoader();
- showCommonBottomSheetWithoutHeight(
- context,
- child: Utils.getErrorWidget(loadingText: err),
- callBackFunc: () {},
- isFullScreen: false,
- isCloseButtonVisible: true,
- );
- });
+ bookAppointmentsViewModel.isLiveCareSchedule
+ ? await bookAppointmentsViewModel.getLiveCareDoctorFreeSlots(
+ isBookingForLiveCare: true,
+ onSuccess: (dynamic respData) async {
+ LoaderBottomSheet.hideLoader();
+ showCommonBottomSheetWithoutHeight(
+ title: "Pick a Date".needTranslation,
+ context,
+ child: AppointmentCalendar(),
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ callBackFunc: () {},
+ );
+ },
+ onError: (err) {
+ LoaderBottomSheet.hideLoader();
+ showCommonBottomSheetWithoutHeight(
+ context,
+ child: Utils.getErrorWidget(loadingText: err),
+ callBackFunc: () {},
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ );
+ })
+ : await bookAppointmentsViewModel.getDoctorFreeSlots(
+ isBookingForLiveCare: false,
+ onSuccess: (dynamic respData) async {
+ LoaderBottomSheet.hideLoader();
+ showCommonBottomSheetWithoutHeight(
+ title: "Pick a Date".needTranslation,
+ context,
+ child: AppointmentCalendar(),
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ callBackFunc: () {},
+ );
+ },
+ onError: (err) {
+ LoaderBottomSheet.hideLoader();
+ showCommonBottomSheetWithoutHeight(
+ context,
+ child: Utils.getErrorWidget(loadingText: err),
+ callBackFunc: () {},
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ );
+ });
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
diff --git a/lib/presentation/book_appointment/review_appointment_page.dart b/lib/presentation/book_appointment/review_appointment_page.dart
index d3804d8..1439270 100644
--- a/lib/presentation/book_appointment/review_appointment_page.dart
+++ b/lib/presentation/book_appointment/review_appointment_page.dart
@@ -204,34 +204,46 @@ class _ReviewAppointmentPageState extends State {
void initiateBookAppointment() async {
LoadingUtils.showFullScreenLoader(barrierDismissible: true, isSuccessDialog: false, loadingText: "Booking your appointment...".needTranslation);
- await bookAppointmentsViewModel.insertSpecificAppointment(onError: (err) {
- print(err.data["ErrorEndUserMessage"]);
- LoadingUtils.hideFullScreenLoader();
- }, onSuccess: (apiResp) async {
- LoadingUtils.hideFullScreenLoader();
- await Future.delayed(Duration(milliseconds: 50)).then((value) async {
- LoadingUtils.showFullScreenLoader(barrierDismissible: true, isSuccessDialog: true, loadingText: LocaleKeys.appointmentSuccess.tr());
- await Future.delayed(Duration(milliseconds: 4000)).then((value) {
- LoadingUtils.hideFullScreenLoader();
- Navigator.pushAndRemoveUntil(
- context,
- CustomPageRoute(
- page: LandingNavigation(),
- ),
- (r) => false);
+ if (bookAppointmentsViewModel.isLiveCareSchedule) {
+ await bookAppointmentsViewModel.insertSpecificAppointmentForLiveCare(onError: (err) {
+ print(err.data["ErrorEndUserMessage"]);
+ LoadingUtils.hideFullScreenLoader();
+ }, onSuccess: (apiResp) async {
+ LoadingUtils.hideFullScreenLoader();
+ await Future.delayed(Duration(milliseconds: 50)).then((value) async {
+ LoadingUtils.showFullScreenLoader(barrierDismissible: true, isSuccessDialog: true, loadingText: LocaleKeys.appointmentSuccess.tr());
+ await Future.delayed(Duration(milliseconds: 4000)).then((value) {
+ LoadingUtils.hideFullScreenLoader();
+ bookAppointmentsViewModel.setIsLiveCareSchedule(false);
+ Navigator.pushAndRemoveUntil(
+ context,
+ CustomPageRoute(
+ page: LandingNavigation(),
+ ),
+ (r) => false);
+ });
});
});
- });
-
- // await Future.delayed(Duration(milliseconds: 4000)).then((value) async {
- // LoadingUtils.hideFullScreenLoader();
-
- // await Future.delayed(Duration(milliseconds: 50)).then((value) async {
- // LoadingUtils.showFullScreenLoader(barrierDismissible: true, isSuccessDialog: true, loadingText: LocaleKeys.appointmentSuccess.tr());
- // await Future.delayed(Duration(milliseconds: 4000)).then((value) {
- // LoadingUtils.hideFullScreenLoader();
- // });
- // });
- // });
+ } else {
+ await bookAppointmentsViewModel.insertSpecificAppointment(onError: (err) {
+ print(err.data["ErrorEndUserMessage"]);
+ LoadingUtils.hideFullScreenLoader();
+ }, onSuccess: (apiResp) async {
+ LoadingUtils.hideFullScreenLoader();
+ await Future.delayed(Duration(milliseconds: 50)).then((value) async {
+ LoadingUtils.showFullScreenLoader(barrierDismissible: true, isSuccessDialog: true, loadingText: LocaleKeys.appointmentSuccess.tr());
+ await Future.delayed(Duration(milliseconds: 4000)).then((value) {
+ LoadingUtils.hideFullScreenLoader();
+ bookAppointmentsViewModel.setIsLiveCareSchedule(false);
+ Navigator.pushAndRemoveUntil(
+ context,
+ CustomPageRoute(
+ page: LandingNavigation(),
+ ),
+ (r) => false);
+ });
+ });
+ });
+ }
}
}
diff --git a/lib/widgets/chip/app_custom_chip_widget.dart b/lib/widgets/chip/app_custom_chip_widget.dart
index a6e1817..a4db172 100644
--- a/lib/widgets/chip/app_custom_chip_widget.dart
+++ b/lib/widgets/chip/app_custom_chip_widget.dart
@@ -48,63 +48,46 @@ class AppCustomChipWidget extends StatelessWidget {
padding: EdgeInsets.all(0.0),
shape: SmoothRectangleBorder(
side: BorderSide(
- width: 0.0,
+ width: 10.0,
color: Colors.transparent, // Crucially, set color to transparent
style: BorderStyle.none,
),
- borderRadius: BorderRadius.circular(10.0), // Apply a border radius of 16.0
+ borderRadius: BorderRadius.circular(8.0), // Apply a border radius of 16.0
),
),
child: icon.isNotEmpty
? Chip(
- avatar: icon.isNotEmpty
- ? Utils.buildSvgWithAssets(
- icon: icon,
- width: iconSize.h,
- height: iconSize.h,
- iconColor: iconHasColor ? iconColor : null)
- : SizedBox.shrink(),
- label: richText ??
- labelText!.toText10(
- weight: FontWeight.w500,
- letterSpacing: -0.64,
- color: textColor),
+ avatar: icon.isNotEmpty ? Utils.buildSvgWithAssets(icon: icon, width: iconSize.h, height: iconSize.h, iconColor: iconHasColor ? iconColor : null) : SizedBox.shrink(),
+ label: richText ?? labelText!.toText10(weight: FontWeight.w500, letterSpacing: -0.64, color: textColor),
// padding: EdgeInsets.all(0.0),
padding: padding,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
- labelPadding: EdgeInsetsDirectional.only(
- start: -4.h,
- end: deleteIcon?.isNotEmpty == true ? 2.h : 8.h),
+ labelPadding: EdgeInsetsDirectional.only(start: -4.h, end: deleteIcon?.isNotEmpty == true ? 2.h : 8.h),
backgroundColor: backgroundColor,
- shape: shape,
+ shape: shape ??
+ SmoothRectangleBorder(
+ borderRadius: BorderRadius.circular(8 ?? 0),
+ smoothness: 10,
+ side: BorderSide(color: AppColors.transparent, width: 1.5),
+ ),
deleteIcon: deleteIcon?.isNotEmpty == true
- ? Utils.buildSvgWithAssets(
- icon: deleteIcon!,
- width: deleteIconSize!.width!.h,
- height: deleteIconSize!.height.h,
- iconColor: deleteIconHasColor ? deleteIconColor : null)
+ ? Utils.buildSvgWithAssets(icon: deleteIcon!, width: deleteIconSize!.width!.h, height: deleteIconSize!.height.h, iconColor: deleteIconHasColor ? deleteIconColor : null)
: null,
onDeleted: deleteIcon?.isNotEmpty == true ? () {} : null,
)
: Chip(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
- label: richText ??
- labelText!.toText10(
- weight: FontWeight.w500,
- letterSpacing: -0.64,
- color: textColor),
+ label: richText ?? labelText!.toText10(weight: FontWeight.w500, letterSpacing: -0.64, color: textColor),
padding: EdgeInsets.all(0.0),
backgroundColor: backgroundColor,
- shape: shape,
- labelPadding: EdgeInsetsDirectional.only(
- start: 8.h,
- end: deleteIcon?.isNotEmpty == true ? -2.h : 8.h),
+ shape: shape ?? SmoothRectangleBorder(
+ borderRadius: BorderRadius.circular(8 ?? 0),
+ smoothness: 10,
+ side: BorderSide(color: AppColors.transparent, width: 1.5),
+ ),
+ labelPadding: EdgeInsetsDirectional.only(start: 8.h, end: deleteIcon?.isNotEmpty == true ? -2.h : 8.h),
deleteIcon: deleteIcon?.isNotEmpty == true
- ? Utils.buildSvgWithAssets(
- icon: deleteIcon!,
- width: deleteIconSize!.width.h,
- height: deleteIconSize!.height.h,
- iconColor: deleteIconHasColor ? deleteIconColor : null)
+ ? Utils.buildSvgWithAssets(icon: deleteIcon!, width: deleteIconSize!.width.h, height: deleteIconSize!.height.h, iconColor: deleteIconHasColor ? deleteIconColor : null)
: null,
onDeleted: deleteIcon?.isNotEmpty == true ? () {} : null,
),