haroon_dev
haroon amjad 12 hours ago
parent 400e5daac0
commit f929bd9017

@ -0,0 +1,9 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="40" height="40" rx="10" fill="#2E3039"/>
<path d="M16 20C15.4477 20 15 20.4477 15 21C15 21.5523 15.4477 22 16 22H16.009C16.5613 22 17.009 21.5523 17.009 21C17.009 20.4477 16.5613 20 16.009 20H16Z" fill="white"/>
<path d="M19.9955 20C19.4432 20 18.9955 20.4477 18.9955 21C18.9955 21.5523 19.4432 22 19.9955 22H20.0045C20.5568 22 21.0045 21.5523 21.0045 21C21.0045 20.4477 20.5568 20 20.0045 20H19.9955Z" fill="white"/>
<path d="M23.991 20C23.4387 20 22.991 20.4477 22.991 21C22.991 21.5523 23.4387 22 23.991 22H24C24.5523 22 25 21.5523 25 21C25 20.4477 24.5523 20 24 20H23.991Z" fill="white"/>
<path d="M16 24C15.4477 24 15 24.4477 15 25C15 25.5523 15.4477 26 16 26H16.009C16.5613 26 17.009 25.5523 17.009 25C17.009 24.4477 16.5613 24 16.009 24H16Z" fill="white"/>
<path d="M19.9955 24C19.4432 24 18.9955 24.4477 18.9955 25C18.9955 25.5523 19.4432 26 19.9955 26H20.0045C20.5568 26 21.0045 25.5523 21.0045 25C21.0045 24.4477 20.5568 24 20.0045 24H19.9955Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.75 10C14.75 9.58579 14.4142 9.25 14 9.25C13.5858 9.25 13.25 9.58579 13.25 10V10.6348C12.4452 10.8629 11.7665 11.2336 11.2015 11.8444C10.4236 12.6853 10.0778 13.7479 9.91225 15.0795C9.74998 16.3843 9.74999 18.0565 9.75 20.19V20.81C9.74999 22.9435 9.74998 24.6157 9.91225 25.9205C10.0778 27.2521 10.4236 28.3147 11.2015 29.1556C11.9871 30.0049 12.9928 30.3901 14.2513 30.573C15.4693 30.75 17.0255 30.75 18.9892 30.75H21.0108C22.9745 30.75 24.5307 30.75 25.7487 30.573C27.0072 30.3901 28.0129 30.0049 28.7985 29.1556C29.5764 28.3147 29.9222 27.2521 30.0878 25.9205C30.25 24.6157 30.25 22.9435 30.25 20.8099V20.1901C30.25 18.0565 30.25 16.3843 30.0878 15.0795C29.9222 13.7479 29.5764 12.6853 28.7985 11.8444C28.2335 11.2336 27.5548 10.8629 26.75 10.6348V10C26.75 9.58579 26.4142 9.25 26 9.25C25.5858 9.25 25.25 9.58579 25.25 10V10.3659C24.1139 10.25 22.716 10.25 21.0108 10.25L18.9892 10.25C17.284 10.25 15.8861 10.25 14.75 10.3659V10ZM13.2786 12.2058C13.3681 12.52 13.6572 12.75 14 12.75C14.4142 12.75 14.75 12.4142 14.75 12V11.8746C15.811 11.7516 17.1824 11.75 19.05 11.75L20.95 11.75C22.8176 11.75 24.189 11.7516 25.25 11.8746V12C25.25 12.4142 25.5858 12.75 26 12.75C26.3428 12.75 26.6319 12.52 26.7214 12.2058C27.1287 12.3679 27.438 12.5826 27.6973 12.8629C28.1704 13.3744 28.4505 14.0759 28.5982 15.2564C28.5661 15.2522 28.5333 15.25 28.5 15.25L11.5 15.25C11.4667 15.25 11.4339 15.2522 11.4018 15.2564C11.5495 14.0759 11.8296 13.3744 12.3027 12.8629C12.562 12.5826 12.8713 12.3679 13.2786 12.2058ZM11.2901 16.7202C11.2506 17.6832 11.25 18.8363 11.25 20.2432V20.7568C11.25 22.9551 11.2514 24.5339 11.4008 25.7354C11.5482 26.9208 11.8285 27.6244 12.3027 28.1371C12.7692 28.6414 13.3973 28.9331 14.467 29.0886C15.5648 29.2481 17.0119 29.25 19.05 29.25H20.95C22.9881 29.25 24.4352 29.2481 25.533 29.0886C26.6027 28.9331 27.2308 28.6414 27.6973 28.1371C28.1715 27.6244 28.4518 26.9208 28.5992 25.7354C28.7486 24.5339 28.75 22.9551 28.75 20.7568V20.2432C28.75 18.8363 28.7494 17.6832 28.7099 16.7202C28.6433 16.7396 28.5728 16.75 28.5 16.75L11.5 16.75C11.4272 16.75 11.3567 16.7396 11.2901 16.7202Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

@ -936,7 +936,7 @@
"hospitalInformation": "معلومات المستشفى",
"fetchingAppointmentShare": "جاري جلب تفاصيل الموعد...",
"bookingYourAppointment": "جاري حجز موعدك...",
"selectLiveCareClinic": "اختر عيادة لايف كير",
"selectLiveCareClinic": "عيادة لايف كير",
"checkingForExistingDentalPlan": "جاري التحقق من وجود خطة أسنان حالية، يرجى الانتظار...",
"dentalTreatmentPlan": "خطة علاج الأسنان",
"youHaveExistingTreatmentPlan": "لديك خطة علاج حالية: ",
@ -1653,5 +1653,6 @@
"oneWaySubtitle": "نقل من الموقع إلى المستشفى",
"twoWaySubtitle": "نقل من الموقع إلى المستشفى والعودة مرة أخرى",
"toHospitalSubtitle": "نقل من موقعك الحالي إلى المستشفى",
"fromHospitalSubtitle": "نقل من المستشفى إلى منزلك"
"fromHospitalSubtitle": "نقل من المستشفى إلى منزلك",
"clinicSchedule": "جدول العيادة"
}

@ -930,7 +930,7 @@
"hospitalInformation": "Hospital Information",
"fetchingAppointmentShare": "Fetching Appointment Share...",
"bookingYourAppointment": "Booking your appointment...",
"selectLiveCareClinic": "Select LiveCare Clinic",
"selectLiveCareClinic": "LiveCare Clinic",
"checkingForExistingDentalPlan": "Checking for an existing dental plan, Please wait...",
"dentalTreatmentPlan": "Dental treatment plan",
"youHaveExistingTreatmentPlan": "You have an existing treatment plan: ",
@ -1241,7 +1241,7 @@
"quickLinks": "Quick Links",
"viewMedicalFileLandingPage": "View medical file",
"immediateLiveCareRequest": "Immediate LiveCare Request",
"yourTurnIsAfterPatients": "Your turn is after {count} patients.",
"yourTurnIsAfterPatients": "Your turn is after {count} patients. Please wait for your turn, The doctor will call you shortly.",
"dontHaveHHCOrders": "You don't have any Home Health Care orders yet.",
"hhcOrders": "HHC Orders",
"requestedServices": "Requested Services",
@ -1645,5 +1645,6 @@
"oneWaySubtitle": "Pickup from location to hospital",
"twoWaySubtitle": "Round trip from location to hospital and back",
"toHospitalSubtitle": "Transfer from your current location to the hospital",
"fromHospitalSubtitle": "Transfer from the hospital back to your home"
"fromHospitalSubtitle": "Transfer from the hospital back to your home",
"clinicSchedule": "Clinic Schedule"
}

@ -199,8 +199,8 @@ class ApiClientImp implements ApiClient {
body['TokenID'] = "@dm!n";
}
// body['TokenID'] = "@dm!n";
// body['PatientID'] = 1018977;
body['TokenID'] = "@dm!n";
body['PatientID'] = 1018977;
// body['PatientTypeID'] = 1;
// body['PatientOutSA'] = 0;
// body['SessionID'] = "45786230487560q";

@ -236,6 +236,7 @@ class AppAssets {
static const String forward_top_nav_icon = '$svgBasePath/forward_top_nav_icon.svg';
static const String back_top_nav_icon = '$svgBasePath/back_top_nav_icon.svg';
static const String bluetooth = '$svgBasePath/bluetooth.svg';
static const String calendar_filled_icon = '$svgBasePath/calendar_filled_icon.svg';
//smartwatch
static const String watchActivity = '$svgBasePath/watch_activity.svg';

@ -5,6 +5,7 @@ import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_clinic_schedule_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_clinics_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_fees_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_patient_livecare_history_response_model.dart';
@ -13,6 +14,9 @@ import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class ImmediateLiveCareRepo {
Future<Either<Failure, GenericApiModel<List<GetLiveCareClinicListResponseModel>>>> getLiveCareImmediateClinicsList(int age, int genderID, {Function(dynamic)? onSuccess, Function(String)? onError});
Future<Either<Failure, GenericApiModel<List<LiveCareClinicScheduleResponse>>>> getLiveCareImmediateClinicSchedule(int age, int genderID, int serviceID,
{Function(dynamic)? onSuccess, Function(String)? onError});
Future<Either<Failure, GenericApiModel<LiveCareImmediateAppointmentFeesList>>> getLiveCareImmediateAppointmentFees(int age, int genderID, int serviceID,
{Function(dynamic)? onSuccess, Function(String)? onError});
@ -203,4 +207,47 @@ class ImmediateLiveCareRepoImp implements ImmediateLiveCareRepo {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<List<LiveCareClinicScheduleResponse>>>> getLiveCareImmediateClinicSchedule(int age, int genderID, int serviceID,
{Function(dynamic p1)? onSuccess, Function(String p1)? onError}) async {
Map<String, dynamic> mapDevice = {
"Age": age,
"Gender": genderID,
"ServiceID": serviceID,
};
try {
GenericApiModel<List<LiveCareClinicScheduleResponse>>? apiResponse;
Failure? failure;
await apiClient.post(
GET_LIVECARE_CLINIC_TIMING,
body: mapDevice,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
// onError!(error);
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final respObject = response['PatientER_GetClinicsServiceTimingsList'];
final liveCareScheduleObj = respObject.map((item) => LiveCareClinicScheduleResponse.fromJson(item as Map<String, dynamic>)).toList().cast<LiveCareClinicScheduleResponse>();
apiResponse = GenericApiModel<List<LiveCareClinicScheduleResponse>>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: liveCareScheduleObj,
);
} 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()));
}
}
}

@ -11,6 +11,7 @@ import 'package:hmg_patient_app_new/core/enums.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/features/immediate_livecare/immediate_livecare_repo.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_clinic_schedule_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_clinics_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_fees_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_patient_livecare_history_response_model.dart';
@ -46,6 +47,8 @@ class ImmediateLiveCareViewModel extends ChangeNotifier {
List<PatientLiveCareHistory> patientLiveCareHistoryList = [];
bool patientHasPendingLiveCareRequest = false;
List<LiveCareClinicScheduleResponse> liveCareClinicScheduleList = [];
late AppState _appState;
Duration countdownDuration = Duration(minutes: 1, seconds: 0);
@ -265,6 +268,33 @@ class ImmediateLiveCareViewModel extends ChangeNotifier {
);
}
Future<void> getLiveCareImmediateClinicSchedule({int? serviceID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
liveCareClinicScheduleList.clear();
notifyListeners();
final result =
await immediateLiveCareRepo.getLiveCareImmediateClinicSchedule(_appState.getAuthenticatedUser()!.age!, _appState.getAuthenticatedUser()!.gender!, serviceID!);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
liveCareClinicScheduleList = apiResponse.data!;
// immediateLiveCareClinicsList.sort((a, b) => b.isOnline!.compareTo(a.isOnline!));
// isImmediateLiveCareClinicsLoading = false;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
void startTimer() {
timer = Timer.periodic(const Duration(seconds: 1), (_) => addTime());
notifyListeners();

@ -0,0 +1,71 @@
class LiveCareClinicScheduleResponse {
int? iD;
int? serviceID;
int? dayOfWeek;
String? dayOfWeekStr;
bool? isActive;
String? createdOn;
String? createdBy;
bool? projectOutSA;
String? dayOfWeekStrN;
List<ShiftTimings>? shiftTimings;
LiveCareClinicScheduleResponse({this.iD, this.serviceID, this.dayOfWeek, this.dayOfWeekStr, this.isActive, this.createdOn, this.createdBy, this.projectOutSA, this.dayOfWeekStrN, this.shiftTimings});
LiveCareClinicScheduleResponse.fromJson(Map<String, dynamic> json) {
iD = json['ID'];
serviceID = json['ServiceID'];
dayOfWeek = json['DayOfWeek'];
dayOfWeekStr = json['DayOfWeekStr'];
isActive = json['IsActive'];
createdOn = json['CreatedOn'];
createdBy = json['CreatedBy'];
projectOutSA = json['ProjectOutSA'];
dayOfWeekStrN = json['DayOfWeekStrN'];
if (json['ShiftTimings'] != null) {
shiftTimings = <ShiftTimings>[];
json['ShiftTimings'].forEach((v) {
shiftTimings!.add(new ShiftTimings.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ID'] = this.iD;
data['ServiceID'] = this.serviceID;
data['DayOfWeek'] = this.dayOfWeek;
data['DayOfWeekStr'] = this.dayOfWeekStr;
data['IsActive'] = this.isActive;
data['CreatedOn'] = this.createdOn;
data['CreatedBy'] = this.createdBy;
data['ProjectOutSA'] = this.projectOutSA;
data['DayOfWeekStrN'] = this.dayOfWeekStrN;
if (this.shiftTimings != null) {
data['ShiftTimings'] = this.shiftTimings!.map((v) => v.toJson()).toList();
}
return data;
}
}
class ShiftTimings {
String? endTime;
int? shiftID;
String? startTime;
ShiftTimings({this.endTime, this.shiftID, this.startTime});
ShiftTimings.fromJson(Map<String, dynamic> json) {
endTime = json['EndTime'];
shiftID = json['ShiftID'];
startTime = json['StartTime'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['EndTime'] = this.endTime;
data['ShiftID'] = this.shiftID;
data['StartTime'] = this.startTime;
return data;
}
}

@ -1646,5 +1646,6 @@ abstract class LocaleKeys {
static const twoWaySubtitle = 'twoWaySubtitle';
static const toHospitalSubtitle = 'toHospitalSubtitle';
static const fromHospitalSubtitle = 'fromHospitalSubtitle';
static const clinicSchedule = 'clinicSchedule';
}

@ -384,20 +384,20 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
}
// Show one combined retry dialog for all missing permissions
final missingNames = missing.map((p) => LiveCarePermissionService.instance.friendlyName(p)).join(' and ');
final retry = await showDialog<bool>(
context: context,
builder: (c) => AlertDialog(
title: const Text('Permissions required'),
content: Text('$missingNames permission${missing.length > 1 ? 's are' : ' is'} required to start the video call. Retry now?'),
actions: [
TextButton(onPressed: () => Navigator.of(c).pop(false), child: const Text('Cancel')),
TextButton(onPressed: () => Navigator.of(c).pop(true), child: const Text('Retry')),
],
),
);
if (retry != true) return false;
// final missingNames = missing.map((p) => LiveCarePermissionService.instance.friendlyName(p)).join(' and ');
// final retry = await showDialog<bool>(
// context: context,
// builder: (c) => AlertDialog(
// title: const Text('Permissions required'),
// content: Text('$missingNames permission${missing.length > 1 ? 's are' : ' is'} required to start the video call. Retry now?'),
// actions: [
// TextButton(onPressed: () => Navigator.of(c).pop(false), child: const Text('Cancel')),
// TextButton(onPressed: () => Navigator.of(c).pop(true), child: const Text('Retry')),
// ],
// ),
// );
//
// if (retry != true) return false;
// Request only the missing permissions
final newStatuses = <Permission, PermissionStatus>{};
@ -425,7 +425,8 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
return false;
}
return cameraGranted && micGranted && notifGranted && alertWindowGranted;
// return cameraGranted && micGranted && notifGranted && alertWindowGranted;
return cameraGranted && micGranted && notifGranted;
}
// Future<bool> askVideoCallPermission() async {

@ -82,20 +82,34 @@ class _ImmediateLiveCarePendingRequestPageState extends State<ImmediateLiveCareP
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Expected waiting time: ".toText16(isBold: true),
SizedBox(height: 8.h),
ValueListenableBuilder<Duration>(
valueListenable: immediateLiveCareVM.durationNotifier,
builder: (context, duration, child) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
LocaleKeys.immediateLiveCareRequest.tr(context: context).toText16(isBold: true),
SizedBox(height: 10.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Wrap(
children: [
buildTime(duration),
AppCustomChipWidget(
labelText: immediateLiveCareViewModel.patientLiveCareHistoryList.isNotEmpty ? immediateLiveCareViewModel.patientLiveCareHistoryList[0].stringCallStatus : "",
backgroundColor: AppColors.warningColorYellow.withValues(alpha: 0.20),
textColor: AppColors.alertColor,
),
SizedBox(width: 8.w),
AppCustomChipWidget(
icon: AppAssets.appointment_calendar_icon,
labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(immediateLiveCareViewModel.patientLiveCareHistoryList[0].arrivalTime), false)),
],
);
},
),
Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h),
// Lottie.asset(AppAnimations.pending_loading_animation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 80.h, height: 80.h, fit: BoxFit.cover),
],
),
SizedBox(height: 8.h),
SizedBox(height: 8.h),
LocaleKeys.yourTurnIsAfterPatients
.tr(namedArgs: {'count': (immediateLiveCareViewModel.patientLiveCareHistoryList[0].patCount ?? 0).toString()}, context: context).toText14(weight: FontWeight.w500),
// "Your turn is after ${immediateLiveCareViewModel.patientLiveCareHistoryList[0].patCount} patients.".toText16(isBold: true),
SizedBox(height: 8.h),
],
),
),
@ -113,31 +127,24 @@ class _ImmediateLiveCarePendingRequestPageState extends State<ImmediateLiveCareP
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
AppCustomChipWidget(
labelText: immediateLiveCareViewModel.patientLiveCareHistoryList.isNotEmpty ? immediateLiveCareViewModel.patientLiveCareHistoryList[0].stringCallStatus : "",
backgroundColor: AppColors.warningColorYellow.withValues(alpha: 0.20),
textColor: AppColors.alertColor,
),
Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h),
// Lottie.asset(AppAnimations.pending_loading_animation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 80.h, height: 80.h, fit: BoxFit.cover),
],
),
SizedBox(height: 8.h),
"Hala ${appState.getAuthenticatedUser()!.firstName}!!!".toText16(isBold: true),
SizedBox(height: 8.h),
AppCustomChipWidget(
icon: AppAssets.appointment_calendar_icon,
labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(immediateLiveCareViewModel.patientLiveCareHistoryList[0].arrivalTime), false)),
"Expected waiting time: ".toText16(isBold: true),
SizedBox(height: 8.h),
"Your turn is after ${immediateLiveCareViewModel.patientLiveCareHistoryList[0].patCount} patients.".toText16(isBold: true),
ValueListenableBuilder<Duration>(
valueListenable: immediateLiveCareVM.durationNotifier,
builder: (context, duration, child) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
buildTime(duration),
],
);
},
),
SizedBox(height: 8.h),
],
),
),
)
),
],
),
),

@ -96,7 +96,9 @@ class _SelectImmediateLiveCareClinicPageState extends State<SelectImmediateLiveC
liveCareClinicListResponseModel: immediateLiveCareVM.immediateLiveCareClinicsList[index],
isLoading: immediateLiveCareVM.isImmediateLiveCareClinicsLoading,
).onPress(() {
onImmediateLiveCareClinicSelected(immediateLiveCareVM.immediateLiveCareClinicsList[index]);
if (immediateLiveCareVM.immediateLiveCareClinicsList[index].isOnline == 1) {
onImmediateLiveCareClinicSelected(immediateLiveCareVM.immediateLiveCareClinicsList[index]);
}
}),
),
),

@ -1,5 +1,6 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
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';
@ -10,8 +11,15 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_clinics_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/widgets/select_livecare_call_type.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/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
class LiveCareClinicCard extends StatelessWidget {
LiveCareClinicCard({super.key, required this.liveCareClinicListResponseModel, required this.isLoading, required this.immediateLiveCareViewModel});
@ -36,10 +44,13 @@ class LiveCareClinicCard extends StatelessWidget {
Utils.buildSvgWithAssets(icon: AppAssets.generic_clinic_icon, width: 24.h, height: 24.h, fit: BoxFit.contain).toShimmer2(isShow: isLoading),
AppCustomChipWidget(
icon: AppAssets.livecare_online_icon,
iconColor: AppColors.whiteColor,
richText: (liveCareClinicListResponseModel.isOnline == 1 ? LocaleKeys.online.tr(context: context) : LocaleKeys.offline.tr()).toText10(isBold: true, color: AppColors.whiteColor),
backgroundColor: liveCareClinicListResponseModel.isOnline == 1 ? AppColors.successColor : AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
iconColor: liveCareClinicListResponseModel.isOnline == 1 ? AppColors.successColor : AppColors.primaryRedColor,
richText: (liveCareClinicListResponseModel.isOnline == 1 ? LocaleKeys.online.tr(context: context) : LocaleKeys.offline.tr()).toText12(
isBold: true,
color: liveCareClinicListResponseModel.isOnline == 1 ? AppColors.successColor : AppColors.primaryRedColor,
),
backgroundColor: AppColors.transparent,
textColor: liveCareClinicListResponseModel.isOnline == 1 ? AppColors.successColor : AppColors.primaryRedColor,
),
]),
SizedBox(height: 8.h),
@ -48,12 +59,189 @@ class LiveCareClinicCard extends StatelessWidget {
child: (isLoading ? "Cardiology" : (appState.isArabic() ? liveCareClinicListResponseModel.serviceNameN : liveCareClinicListResponseModel.serviceName))!
.toText16(isBold: true)
.toShimmer2(isShow: isLoading)),
Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, width: 40.h, height: 40.h, fit: BoxFit.contain, iconColor: AppColors.textColor).toShimmer2(isShow: isLoading)),
// Transform.flip(
// flipX: appState.isArabic(),
// child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, width: 40.h, height: 40.h, fit: BoxFit.contain, iconColor: AppColors.textColor).toShimmer2(isShow: isLoading)),
]),
SizedBox(height: 8.h),
Row(
children: [
Expanded(
flex: 7,
child: CustomButton(
text: LocaleKeys.bookNow.tr(),
onPressed: () async {
onImmediateLiveCareClinicSelected(liveCareClinicListResponseModel);
},
backgroundColor: AppColors.successLightBgColor,
borderColor: AppColors.successLightBgColor,
textColor: AppColors.successColor,
borderWidth: 1.h,
fontSize: (isFoldable || isTablet) ? 12.f : 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
icon: AppAssets.bookAppoBottom,
iconColor: liveCareClinicListResponseModel.isOnline == 0 ? AppColors.textColorLight : AppColors.successColor,
iconSize: 16.h,
isDisabled: liveCareClinicListResponseModel.isOnline == 0,
),
),
SizedBox(width: 8.w),
Expanded(
flex: 1,
child: Container(
height: (isFoldable || isTablet) ? 50.h : 40.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
// color: Color(0xFFEFEFF0),
color: AppColors.transparent,
borderRadius: 10.h,
side: BorderSide(
color: AppColors.textColor,
width: 1.2,
),
),
child: Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(
icon: AppAssets.calendar,
iconColor: AppColors.textColor,
width: 5.w,
height: 5.h,
fit: BoxFit.scaleDown,
),
),
).onPress(() {
onClinicScheduleTapped(liveCareClinicListResponseModel.serviceID!);
}),
),
],
),
],
),
);
}
onClinicScheduleTapped(int serviceID) async {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.loadingText.tr());
await immediateLiveCareViewModel.getLiveCareImmediateClinicSchedule(
serviceID: serviceID,
onSuccess: (val) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(GetIt.instance<NavigationService>().navigatorKey.currentContext!,
child: ListView.separated(
shrinkWrap: true,
itemBuilder: (_, index) {
return DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8.h,
children: [
checkInOptionCard(AppAssets.calendarGrey, immediateLiveCareViewModel.liveCareClinicScheduleList[index].dayOfWeekStr!,
"${immediateLiveCareViewModel.liveCareClinicScheduleList[index].shiftTimings!.first.startTime} to ${immediateLiveCareViewModel.liveCareClinicScheduleList[index].shiftTimings!.first.endTime}"),
],
),
),
],
),
).paddingSymmetrical(0.h, 0.h).onPress(() {});
},
separatorBuilder: (_, __) => SizedBox(height: 16.h),
itemCount: immediateLiveCareViewModel.liveCareClinicScheduleList.length),
title: LocaleKeys.clinicSchedule.tr(),
isCloseButtonVisible: true,
useSafeArea: true,
isFullScreen: true);
});
}
onImmediateLiveCareClinicSelected(GetLiveCareClinicListResponseModel liveCareClinic) {
//TODO: add implementation to show clinic schedule
// if (liveCareClinic.isOnline == 1) {
showCommonBottomSheetWithoutHeight(GetIt.instance<NavigationService>().navigatorKey.currentContext!, child: SelectLiveCareCallType(immediateLiveCareViewModel: immediateLiveCareViewModel),
callBackFunc: () async {
if (immediateLiveCareViewModel.liveCareSelectedCallType != 0) {
immediateLiveCareViewModel.setImmediateLiveCareSelectedClinic(liveCareClinic);
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingFeesPleaseWait.tr());
await immediateLiveCareViewModel.getLiveCareImmediateAppointmentFees(onSuccess: (val) {
LoaderBottomSheet.hideLoader();
Navigator.of(GetIt.instance<NavigationService>().navigatorKey.currentContext!).push(
CustomPageRoute(
page: ImmediateLiveCarePaymentDetails(),
),
);
}, onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
GetIt.instance<NavigationService>().navigatorKey.currentContext!,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
}
}, title: LocaleKeys.selectLiveCareCallType.tr(), isCloseButtonVisible: true, isFullScreen: false);
}
Widget checkInOptionCard(String icon, String title, String subTitle) {
return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
title.toText16(isBold: true, color: AppColors.textColor),
SizedBox(height: 8.h),
Row(
children: [
AppCustomChipWidget(
icon: AppAssets.appointment_time_icon,
iconColor: AppColors.textColor,
labelText: subTitle.split("to").first.trim(),
),
SizedBox(width: 8.w),
Utils.buildSvgWithAssets(
icon: AppAssets.arrow_forward,
height: 24.h,
width: 24.h,
iconColor: AppColors.textColor,
),
SizedBox(width: 8.w),
AppCustomChipWidget(
icon: AppAssets.appointment_time_icon,
iconColor: AppColors.textColor,
labelText: subTitle.split("to")[1].trim(),
),
],
),
],
),
),
],
),
],
).paddingAll(16.h),
);
}
}

@ -1006,15 +1006,33 @@ class _LandingPageState extends State<LandingPage> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.immediateLiveCareRequest.tr(context: context).toText16(isBold: true),
SizedBox(height: 10.h),
_buildLiveCareHeader(liveCareData),
SizedBox(height: 10.h),
_buildLiveCareGreeting(),
SizedBox(height: 8.h),
_buildLiveCareQueueInfo(liveCareData.patCount),
SizedBox(height: 8.h),
_buildLiveCareWaitingTime(),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.immediateLiveCareRequest.tr(context: context).toText16(isBold: true),
SizedBox(height: 10.h),
_buildLiveCareHeader(liveCareData),
SizedBox(height: 10.h),
SizedBox(height: 8.h),
_buildLiveCareQueueInfo(liveCareData.patCount),
SizedBox(height: 25.h),
],
),
CustomButton(
text: LocaleKeys.viewDetails.tr(context: context),
onPressed: () {},
backgroundColor: AppColors.warningColorYellow.withValues(alpha: 0.20),
textColor: AppColors.alertColor,
borderColor: AppColors.infoBannerBgColor,
fontSize: 12.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
iconColor: AppColors.whiteColor,
iconSize: 18.h,
),
// _buildLiveCareWaitingTime(),
],
),
),
@ -1069,10 +1087,7 @@ class _LandingPageState extends State<LandingPage> {
// LiveCare Card: Queue position info
Widget _buildLiveCareQueueInfo(int? patCount) {
return LocaleKeys.yourTurnIsAfterPatients.tr(
namedArgs: {'count': (patCount ?? 0).toString()},
context: context,
).toText14(isBold: true);
return LocaleKeys.yourTurnIsAfterPatients.tr(namedArgs: {'count': (patCount ?? 0).toString()}, context: context).toText14(weight: FontWeight.w500);
}
// LiveCare Card: Waiting time counter

Loading…
Cancel
Save