* 'master' of http://34.17.182.140/Haroon6138/HMG_Patient_App_New:
  Updates
  radiology ai lab analysis & lab ai analysis api end points updates.
  Updates
  updates
  updates

# Conflicts:
#	lib/presentation/symptoms_checker/widgets/selected_organs_section.dart
pull/219/head
Sultan khan 18 hours ago
commit 6d647d75be

File diff suppressed because one or more lines are too long

@ -1249,7 +1249,7 @@
"quickLinks": "روابط سريعة", "quickLinks": "روابط سريعة",
"viewMedicalFileLandingPage": "عرض الملف الطبي", "viewMedicalFileLandingPage": "عرض الملف الطبي",
"immediateLiveCareRequest": "طلب لايف كير فوري", "immediateLiveCareRequest": "طلب لايف كير فوري",
"yourTurnIsAfterPatients": "دورك بعد {count} مريض.", "yourTurnIsAfterPatients": "دورك بعد {count} مريض. يرجى الانتظار حتى يحين دورك، وسيناديك الطبيب قريباً.",
"dontHaveHHCOrders": "ليس لديك أي أوامر رعاية صحية منزلية حتى الآن.", "dontHaveHHCOrders": "ليس لديك أي أوامر رعاية صحية منزلية حتى الآن.",
"hhcOrders": "أوامر الرعاية الصحية المنزلية", "hhcOrders": "أوامر الرعاية الصحية المنزلية",
"requestedServices": "الخدمات المطلوبة", "requestedServices": "الخدمات المطلوبة",
@ -1578,7 +1578,7 @@
"noFreeSlot": "لا توجد مواعيد متاحة في التاريخ المحدد. يرجى اختيار تاريخ آخر أو إعادة المحاولة لاحقاً.", "noFreeSlot": "لا توجد مواعيد متاحة في التاريخ المحدد. يرجى اختيار تاريخ آخر أو إعادة المحاولة لاحقاً.",
"noThanksIKnowTheClinic": "لا، شكراً. أنا أعرف العيادة.", "noThanksIKnowTheClinic": "لا، شكراً. أنا أعرف العيادة.",
"unableToSendOTP": "تعذر إرسال رمز التحقق لمرة واحدة", "unableToSendOTP": "تعذر إرسال رمز التحقق لمرة واحدة",
"loadingAIAnalysis": "جارٍ تحليل نتائج المختبر، يرجى التحلي بالصبر والسماح للذكاء الاصطناعي بالقيام بالمهمة، قد يستغرق هذا بعض الوقت.", "loadingAIAnalysis": "نقوم بتحليل نتائجك، يرجى التحلي بالصبر والسماح للذكاء الاصطناعي بالقيام بالمهمة، قد يستغرق هذا بعض الوقت.",
"symptoms": "أعراض", "symptoms": "أعراض",
"insuranceInActive": "التأمين غير نشط", "insuranceInActive": "التأمين غير نشط",
"insuranceInActiveContactSupport": "لديك تأمين ساري المفعول، ولكنه غير مُفعّل حاليًا في مجموعة حبيب الطبية. يُرجى التواصل مع خدمة عملاء مجموعة حبيب الطبية.", "insuranceInActiveContactSupport": "لديك تأمين ساري المفعول، ولكنه غير مُفعّل حاليًا في مجموعة حبيب الطبية. يُرجى التواصل مع خدمة عملاء مجموعة حبيب الطبية.",
@ -1689,5 +1689,7 @@
"openGallery": "افتح المعرض", "openGallery": "افتح المعرض",
"openFiles": "فتح الملفات", "openFiles": "فتح الملفات",
"generateAiAnalysisRadResult": "بإنشاء تحليل الذكاء الاصطناعي لهذا التقرير", "generateAiAnalysisRadResult": "بإنشاء تحليل الذكاء الاصطناعي لهذا التقرير",
"grantLocationPermission": "يرجى منح إذن الوصول إلى الموقع من إعدادات التطبيق للحصول على نتائج أفضل." "grantLocationPermission": "يرجى منح إذن الوصول إلى الموقع من إعدادات التطبيق للحصول على نتائج أفضل.",
"NoBookedAppointments": "لا توجد مواعيد محجوزة",
"aiDisclaimerRad": "سيتم مشاركة بيانات نتائج الأشعة الخاصة بك بشكل آمن مع محلل الذكاء الاصطناعي لدينا لتحليلها. يساعد هذا في توفير رؤى صحية مخصصة. هل ترغب في المتابعة؟"
} }

@ -1572,7 +1572,7 @@
"contextDependent": "Context Dependent", "contextDependent": "Context Dependent",
"calculatedValue": "Calculated Value", "calculatedValue": "Calculated Value",
"calculationFormula": "Calculation Formula", "calculationFormula": "Calculation Formula",
"loadingAIAnalysis": "Analysing your lab results, Please be patient and let the AI do the magic, This might take some time.", "loadingAIAnalysis": "Analysing your results, Please be patient and let the AI do the magic, This might take some time.",
"symptoms": "Symptoms", "symptoms": "Symptoms",
"insuranceInActive": "Insurance Inactive", "insuranceInActive": "Insurance Inactive",
"insuranceInActiveContactSupport": "You have a valid insurance but it is currently inactive in HMG. Please contact HMG customer support to activate it.", "insuranceInActiveContactSupport": "You have a valid insurance but it is currently inactive in HMG. Please contact HMG customer support to activate it.",
@ -1681,5 +1681,7 @@
"openGallery": "Open Gallery", "openGallery": "Open Gallery",
"openFiles": "Open Files", "openFiles": "Open Files",
"generateAiAnalysisRadResult": "Generate AI analysis for this result", "generateAiAnalysisRadResult": "Generate AI analysis for this result",
"grantLocationPermission": "Please grant location permission from app settings to see better results." "grantLocationPermission": "Please grant location permission from app settings to see better results.",
"NoBookedAppointments": "No Booked Appointments",
"aiDisclaimerRad": "Your radiology result data will be securely shared with our AI Analyzer for analysis. This helps provide personalized health insights. Do you want to proceed?"
} }

@ -415,4 +415,6 @@ class AppAnimations {
static const String ambulance = '$lottieBasePath/ambulance.json'; static const String ambulance = '$lottieBasePath/ambulance.json';
static const String ambulanceAlert = '$lottieBasePath/ambulance_alert.json'; static const String ambulanceAlert = '$lottieBasePath/ambulance_alert.json';
static const String rrtAmbulance = '$lottieBasePath/rrt_ambulance.json'; static const String rrtAmbulance = '$lottieBasePath/rrt_ambulance.json';
static const String hourGlass = '$lottieBasePath/HourGlass.json';
} }

@ -402,8 +402,12 @@ class BookAppointmentsViewModel extends ChangeNotifier {
refreshDoctorsList() { refreshDoctorsList() {
setIsDoctorsListLoading(true); setIsDoctorsListLoading(true);
if(selectedClinic.clinicID == 17) {
getDentalChiefComplaintDoctorsList(projectID: currentlySelectedHospitalFromRegionFlow != null ? int.parse(currentlySelectedHospitalFromRegionFlow!) : 0);
} else {
getDoctorsList(isNearest: isNearestAppointmentSelected); getDoctorsList(isNearest: isNearestAppointmentSelected);
} }
}
setIsNearestAppointmentSelected(bool isNearestAppointmentSelected) { setIsNearestAppointmentSelected(bool isNearestAppointmentSelected) {
this.isNearestAppointmentSelected = isNearestAppointmentSelected; this.isNearestAppointmentSelected = isNearestAppointmentSelected;
@ -861,8 +865,8 @@ class BookAppointmentsViewModel extends ChangeNotifier {
} }
initialSlotDuration = apiResponse.data["InitialSlotDuration"]; initialSlotDuration = apiResponse.data["InitialSlotDuration"];
freeSlotsResponse = apiResponse.data['FreeTimeSlots']; freeSlotsResponse = apiResponse.data['FreeTimeSlots'];
// isWaitingAppointmentAvailable = apiResponse.data["IsAllowToBookWaitingAppointment"]; isWaitingAppointmentAvailable = apiResponse.data["IsAllowToBookWaitingAppointment"];
isWaitingAppointmentAvailable = true; // isWaitingAppointmentAvailable = true;
freeSlotsResponse.forEach((element) { freeSlotsResponse.forEach((element) {
// date = (isLiveCareSchedule != null && isLiveCareSchedule) // date = (isLiveCareSchedule != null && isLiveCareSchedule)
@ -1044,7 +1048,8 @@ class BookAppointmentsViewModel extends ChangeNotifier {
); );
LoaderBottomSheet.showLoader( LoaderBottomSheet.showLoader(
loadingText: LocaleKeys.reschedulingAppo.tr(context: navigationService.navigatorKey.currentContext!), // loadingText: LocaleKeys.reschedulingAppo.tr(context: navigationService.navigatorKey.currentContext!),
loadingText: LocaleKeys.loadingText.tr(context: navigationService.navigatorKey.currentContext!),
); );
await cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel).then((val) async { await cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel).then((val) async {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
@ -1466,7 +1471,10 @@ class BookAppointmentsViewModel extends ChangeNotifier {
} }
Future<void> getDentalChiefComplaintDoctorsList({int projectID = 0, Function(dynamic)? onSuccess, Function(String)? onError}) async { Future<void> getDentalChiefComplaintDoctorsList({int projectID = 0, Function(dynamic)? onSuccess, Function(String)? onError}) async {
setIsNearestAppointmentSelected(false);
doctorsList.clear(); doctorsList.clear();
notifyListeners();
projectID = currentlySelectedHospitalFromRegionFlow != null ? int.parse(currentlySelectedHospitalFromRegionFlow!) : projectID; projectID = currentlySelectedHospitalFromRegionFlow != null ? int.parse(currentlySelectedHospitalFromRegionFlow!) : projectID;
final result = await bookAppointmentsRepo.getDentalChiefComplaintDoctorsList(projectID, selectedChiefComplaintID); final result = await bookAppointmentsRepo.getDentalChiefComplaintDoctorsList(projectID, selectedChiefComplaintID);
@ -1485,6 +1493,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
// clearSearchFilters(); // clearSearchFilters();
// getFiltersFromDoctorList(); // getFiltersFromDoctorList();
_groupDoctorsList(); _groupDoctorsList();
setIsNearestAppointmentSelected(isNearestAppointmentSelected);
notifyListeners(); notifyListeners();
if (onSuccess != null) { if (onSuccess != null) {
onSuccess(apiResponse); onSuccess(apiResponse);

@ -713,7 +713,7 @@ class EmergencyServicesViewModel extends ChangeNotifier {
appointments = response.data; appointments = response.data;
if (appointments?.isEmpty == true) { if (appointments?.isEmpty == true) {
haveAnAppointment = false; haveAnAppointment = false;
dialogService.showErrorBottomSheet(message: "Unable to Fetch Appointment"); dialogService.showErrorBottomSheet(message: LocaleKeys.NoBookedAppointments.tr());
} }
notifyListeners(); notifyListeners();
}); });

@ -26,9 +26,9 @@ abstract class LabRepo {
Future<Either<Failure, GenericApiModel<dynamic>>> getLabResultsByAppointmentNo({required num appointmentNo, required num projectID, required num clinicID}); Future<Either<Failure, GenericApiModel<dynamic>>> getLabResultsByAppointmentNo({required num appointmentNo, required num projectID, required num clinicID});
Future<Either<Failure, GenericApiModel<LabOrdersResponseByAi>>> getPatientAiOverViewLabOrders(var payload); Future<Either<Failure, GenericApiModel<LabOrdersResponseByAi>>> getPatientAiOverViewLabOrders({required int langId, required dynamic payload});
Future<Either<Failure, GenericApiModel<LabOrderResponseByAi>>> getPatientAiOverViewLabOrder(var payload); Future<Either<Failure, GenericApiModel<LabOrderResponseByAi>>> getPatientAiOverViewLabOrder(var payloa);
} }
class LabRepoImp implements LabRepo { class LabRepoImp implements LabRepo {
@ -358,7 +358,7 @@ class LabRepoImp implements LabRepo {
} }
@override @override
Future<Either<Failure, GenericApiModel<LabOrdersResponseByAi>>> getPatientAiOverViewLabOrders(var labOrder) async { Future<Either<Failure, GenericApiModel<LabOrdersResponseByAi>>> getPatientAiOverViewLabOrders({required int langId, required dynamic payload}) async {
try { try {
GenericApiModel<LabOrdersResponseByAi>? apiResponse; GenericApiModel<LabOrdersResponseByAi>? apiResponse;
Failure? failure; Failure? failure;
@ -372,7 +372,7 @@ class LabRepoImp implements LabRepo {
'X-API-KEY': '9d9d2ac4c1fc302299dbb0fbb1b7fea1', 'X-API-KEY': '9d9d2ac4c1fc302299dbb0fbb1b7fea1',
'accept': 'application/json', 'accept': 'application/json',
}, },
body: {"lab_results": labOrder}, body: {"lab_results": payload, "language_id": langId},
onFailure: (error, statusCode, {messageStatus, failureType}) { onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType; failure = failureType;
}, },

@ -455,12 +455,11 @@ class LabViewModel extends ChangeNotifier {
flagForLowReferenceRange = element.calculatedResultFlag; flagForLowReferenceRange = element.calculatedResultFlag;
// } // }
if(double.parse(element.referenceHigh ?? "0.0") == 0 ){ if (double.parse(element.referenceHigh ?? "0.0") == 0) {
highRefrenceValue = double.negativeInfinity; highRefrenceValue = double.negativeInfinity;
} }
if (double.parse(element.referenceLow ?? "0.0") == 0) {
if(double.parse(element.referenceLow ?? "0.0") == 0 ){
lowRefenceValue = double.negativeInfinity; lowRefenceValue = double.negativeInfinity;
} }
@ -473,18 +472,16 @@ class LabViewModel extends ChangeNotifier {
time: DateUtil.convertStringToDate(element.verifiedOnDateTime), time: DateUtil.convertStringToDate(element.verifiedOnDateTime),
referenceValue: element.calculatedResultFlag ?? "", referenceValue: element.calculatedResultFlag ?? "",
)); ));
} catch (e) {}
} catch (e) {
}
}); });
if (flagForLowReferenceRange == null && flagForHighReferenceRange == null) { if (flagForLowReferenceRange == null && flagForHighReferenceRange == null) {
highRefrenceValue = maxY; highRefrenceValue = maxY;
lowRefenceValue = minY; lowRefenceValue = minY;
} }
// //
if (lowRefenceValue != double.negativeInfinity &&minY > lowRefenceValue) { if (lowRefenceValue != double.negativeInfinity && minY > lowRefenceValue) {
minY = lowRefenceValue - getInterval(); minY = lowRefenceValue - getInterval();
}else if (highRefrenceValue != double.negativeInfinity && minY > highRefrenceValue) { } else if (highRefrenceValue != double.negativeInfinity && minY > highRefrenceValue) {
minY = highRefrenceValue - getInterval(); minY = highRefrenceValue - getInterval();
} }
@ -494,17 +491,16 @@ class LabViewModel extends ChangeNotifier {
lowTransformedReferenceValue = double.parse(transformValueInRange(lowRefenceValue, flagForLowReferenceRange ?? "").toStringAsFixed(1)); lowTransformedReferenceValue = double.parse(transformValueInRange(lowRefenceValue, flagForLowReferenceRange ?? "").toStringAsFixed(1));
this.highRefrenceValue = double.parse(highRefrenceValue.toStringAsFixed(2)); this.highRefrenceValue = double.parse(highRefrenceValue.toStringAsFixed(2));
this.lowRefenceValue = double.parse(lowRefenceValue.toStringAsFixed(2)); this.lowRefenceValue = double.parse(lowRefenceValue.toStringAsFixed(2));
if(highRefrenceValue != double.negativeInfinity &&maxY<highRefrenceValue){ if (highRefrenceValue != double.negativeInfinity && maxY < highRefrenceValue) {
maxY = highRefrenceValue+ getInterval(); maxY = highRefrenceValue + getInterval();
maxX = maxY; maxX = maxY;
}else if(lowRefenceValue != double.negativeInfinity && maxY<lowRefenceValue){ } else if (lowRefenceValue != double.negativeInfinity && maxY < lowRefenceValue) {
maxY = lowRefenceValue+ getInterval()/2; maxY = lowRefenceValue + getInterval() / 2;
maxX = maxY; maxX = maxY;
} }
// if (maxY < highRefrenceValue) { // if (maxY < highRefrenceValue) {
// minY = highRefrenceValue - getInterval(); // minY = highRefrenceValue - getInterval();
// } // }
@ -530,15 +526,16 @@ class LabViewModel extends ChangeNotifier {
bool isNumeric(String s) { bool isNumeric(String s) {
return num.tryParse(s) != null; return num.tryParse(s) != null;
} }
num getInterval() { num getInterval() {
// return .1; // return .1;
var maxX = maxY; var maxX = maxY;
if(maxX<1) return .2; if (maxX < 1) return .2;
if(maxX >=1.0 && maxX < 5.0) return .3; if (maxX >= 1.0 && maxX < 5.0) return .3;
if(maxX >=5.0 && maxX < 10.0) return 1.5; if (maxX >= 5.0 && maxX < 10.0) return 1.5;
if(maxX >=10.0 && maxX < 50.0) return 2.5; if (maxX >= 10.0 && maxX < 50.0) return 2.5;
if(maxX >=50.0 && maxX < 100.0) return 5; if (maxX >= 50.0 && maxX < 100.0) return 5;
if(maxX >=100.0 && maxX < 200.0) return 10; if (maxX >= 100.0 && maxX < 200.0) return 10;
return 15; return 15;
} }
@ -845,9 +842,7 @@ class LabViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
Future<void> getAiOverviewLabOrders({required PatientLabOrdersResponseModel labOrder, required String loadingText}) async { Future<void> getAiOverviewLabOrders({required int langId, required PatientLabOrdersResponseModel labOrder, required String loadingText}) async {
// LoadingUtils.showFullScreenLoader(loadingText: "Loading and analysing your data,\nPlease be patient and let the AI do the magic. \nPlease be patient, This might take some time.");
// LoadingUtils.showFullScreenLoader(loadingText: loadingText);
isLabAIAnalysisNeedsToBeShown = true; isLabAIAnalysisNeedsToBeShown = true;
notifyListeners(); notifyListeners();
@ -875,7 +870,8 @@ class LabViewModel extends ChangeNotifier {
} }
orderData["results"] = testResults; orderData["results"] = testResults;
results.add(orderData); results.add(orderData);
final result = await labRepo.getPatientAiOverViewLabOrders(results);
final result = await labRepo.getPatientAiOverViewLabOrders(payload: results, langId: langId);
result.fold( result.fold(
(failure) async { (failure) async {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
@ -903,7 +899,7 @@ class LabViewModel extends ChangeNotifier {
// LoadingUtils.hideFullScreenLoader(); // LoadingUtils.hideFullScreenLoader();
} }
Future<void> getAiOverviewSingleLabResult({required String langId, required LabResult recentLabResult, required String loadingText}) async { Future<void> getAiOverviewSingleLabResult({required int langId, required LabResult recentLabResult, required String loadingText}) async {
LoaderBottomSheet.showLoader( LoaderBottomSheet.showLoader(
loadingText: loadingText, loadingText: loadingText,
showCloseButton: true, showCloseButton: true,

@ -19,7 +19,7 @@ abstract class RadiologyRepo {
Future<Either<Failure, GenericApiModel<List<PatientRadiologyResponseModel>>>> getPatientRadiologyOrderByAppointment({required num appointmentNo, required num projectID}); Future<Either<Failure, GenericApiModel<List<PatientRadiologyResponseModel>>>> getPatientRadiologyOrderByAppointment({required num appointmentNo, required num projectID});
Future<Either<Failure, GenericApiModel<RadiologyAiAnalysisResponse>>> getRadiologyAiAnalysis({required String reportData}); Future<Either<Failure, GenericApiModel<RadiologyAiAnalysisResponse>>> getRadiologyAiAnalysis({required String reportData, required int langId,});
} }
class RadiologyRepoImp implements RadiologyRepo { class RadiologyRepoImp implements RadiologyRepo {
@ -223,9 +223,10 @@ class RadiologyRepoImp implements RadiologyRepo {
} }
@override @override
Future<Either<Failure, GenericApiModel<RadiologyAiAnalysisResponse>>> getRadiologyAiAnalysis({required String reportData}) async { Future<Either<Failure, GenericApiModel<RadiologyAiAnalysisResponse>>> getRadiologyAiAnalysis({required String reportData, required int langId}) async {
Map<String, dynamic> payload = { Map<String, dynamic> payload = {
"text": reportData, "text": reportData,
"language_id": langId
}; };
try { try {

@ -127,8 +127,7 @@ class RadiologyViewModel extends ChangeNotifier {
); );
} }
Future<void> getRadiologyImage( Future<void> getRadiologyImage({required PatientRadiologyResponseModel patientRadiologyResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
{required PatientRadiologyResponseModel patientRadiologyResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await radiologyRepo.getRadiologyImage(patientRadiologyResponseModel: patientRadiologyResponseModel); final result = await radiologyRepo.getRadiologyImage(patientRadiologyResponseModel: patientRadiologyResponseModel);
result.fold( result.fold(
@ -149,12 +148,8 @@ class RadiologyViewModel extends ChangeNotifier {
} }
Future<void> getRadiologyPDF( Future<void> getRadiologyPDF(
{required PatientRadiologyResponseModel patientRadiologyResponseModel, {required PatientRadiologyResponseModel patientRadiologyResponseModel, required AuthenticatedUser authenticatedUser, Function(dynamic)? onSuccess, Function(String)? onError}) async {
required AuthenticatedUser authenticatedUser, final result = await radiologyRepo.getRadiologyReportPDF(patientRadiologyResponseModel: patientRadiologyResponseModel, authenticatedUser: authenticatedUser);
Function(dynamic)? onSuccess,
Function(String)? onError}) async {
final result =
await radiologyRepo.getRadiologyReportPDF(patientRadiologyResponseModel: patientRadiologyResponseModel, authenticatedUser: authenticatedUser);
result.fold( result.fold(
(failure) async => await errorHandlerService.handleError( (failure) async => await errorHandlerService.handleError(
@ -229,7 +224,7 @@ class RadiologyViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
Future<void> getRadiologyAiAnalysis({required String reportData, required String loadingText}) async { Future<void> getRadiologyAiAnalysis({required String reportData, required String loadingText, required int langId}) async {
LoaderBottomSheet.showLoader( LoaderBottomSheet.showLoader(
loadingText: loadingText, loadingText: loadingText,
showCloseButton: true, showCloseButton: true,
@ -238,7 +233,7 @@ class RadiologyViewModel extends ChangeNotifier {
}, },
); );
final result = await radiologyRepo.getRadiologyAiAnalysis(reportData: reportData); final result = await radiologyRepo.getRadiologyAiAnalysis(reportData: reportData, langId: langId);
result.fold( result.fold(
(failure) async { (failure) async {

@ -1681,5 +1681,7 @@ abstract class LocaleKeys {
static const openFiles = 'openFiles'; static const openFiles = 'openFiles';
static const generateAiAnalysisRadResult = 'generateAiAnalysisRadResult'; static const generateAiAnalysisRadResult = 'generateAiAnalysisRadResult';
static const grantLocationPermission = 'grantLocationPermission'; static const grantLocationPermission = 'grantLocationPermission';
static const NoBookedAppointments = 'NoBookedAppointments';
static const aiDisclaimerRad = 'aiDisclaimerRad';
} }

@ -10,6 +10,7 @@ import 'package:flutter/services.dart';
import 'package:hmg_patient_app_new/core/app_state.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/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/features/ask_doctor/ask_doctor_view_model.dart'; import 'package:hmg_patient_app_new/features/ask_doctor/ask_doctor_view_model.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_view_model.dart'; import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_view_model.dart';
@ -50,6 +51,7 @@ import 'package:hmg_patient_app_new/routes/app_routes.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/app_theme.dart'; import 'package:hmg_patient_app_new/theme/app_theme.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart' show DateRangeSelectorRangeViewModel; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart' show DateRangeSelectorRangeViewModel;
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart'; import 'package:provider/single_child_widget.dart';

@ -393,8 +393,8 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
), ),
const Spacer(), const Spacer(),
Switch( Switch(
// activeThumbColor: AppColors.successColor, activeThumbColor: AppColors.successColor,
activeTrackColor: AppColors.successColor.withValues(alpha: .15), // activeTrackColor: AppColors.successColor.withValues(alpha: .15),
value: widget.patientAppointmentHistoryResponseModel.hasReminder!, value: widget.patientAppointmentHistoryResponseModel.hasReminder!,
onChanged: (newValue) async { onChanged: (newValue) async {
CalenderUtilsNew calender = CalenderUtilsNew.instance; CalenderUtilsNew calender = CalenderUtilsNew.instance;
@ -612,7 +612,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
isLocked: false, isLocked: false,
).toShimmer2() ).toShimmer2()
: MedicalFileCard( : MedicalFileCard(
label: !((myAppointmentsVM.appointmentRatedResponseModel!).isAppointmentRated ?? true) label: !((myAppointmentsVM.appointmentRatedResponseModel!).isAllowedToRate ?? false)
? LocaleKeys.ratingSubmitted.tr(context: context) ? LocaleKeys.ratingSubmitted.tr(context: context)
: LocaleKeys.doctorRatingAppointment.tr(context: context), : LocaleKeys.doctorRatingAppointment.tr(context: context),
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
@ -620,9 +620,9 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
svgIcon: AppAssets.appointmentRatingIcon, svgIcon: AppAssets.appointmentRatingIcon,
isLargeText: true, isLargeText: true,
iconSize: 36.w, iconSize: 36.w,
isLocked: !(myAppointmentsVM.appointmentRatedResponseModel!.isAppointmentRated ?? true), isLocked: !(myAppointmentsVM.appointmentRatedResponseModel!.isAllowedToRate ?? false),
).onPress(() { ).onPress(() {
if(!(myAppointmentsVM.appointmentRatedResponseModel!.isAppointmentRated ?? true)) { if ((myAppointmentsVM.appointmentRatedResponseModel!.isAllowedToRate ?? true)) {
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
context, context,
title: LocaleKeys.doctorRating.tr(context: context), title: LocaleKeys.doctorRating.tr(context: context),

@ -15,6 +15,7 @@ import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.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/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/routes/custom_page_route.dart';
import 'package:lottie/lottie.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class AppointmentQueuePage extends StatelessWidget { class AppointmentQueuePage extends StatelessWidget {
@ -39,6 +40,7 @@ class AppointmentQueuePage extends StatelessWidget {
await myAppointmentsVM.getPatientAppointmentQueueDetails(); await myAppointmentsVM.getPatientAppointmentQueueDetails();
}, },
child: SingleChildScrollView( child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Padding( child: Padding(
padding: EdgeInsets.all(24.0), padding: EdgeInsets.all(24.0),
child: Column( child: Column(
@ -59,13 +61,21 @@ class AppointmentQueuePage extends StatelessWidget {
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
AppCustomChipWidget( AppCustomChipWidget(
labelText: myAppointmentsVM.currentQueueStatus == 0 ? LocaleKeys.inQueue.tr(context: context) : LocaleKeys.yourTurn.tr(context: context), labelText: myAppointmentsVM.currentQueueStatus == 0 ? LocaleKeys.inQueue.tr(context: context) : LocaleKeys.yourTurn.tr(context: context),
backgroundColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus).withValues(alpha: 0.20), backgroundColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus).withValues(alpha: 0.20),
textColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus), textColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus),
), ),
Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h), Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.greyColor,
borderRadius: 10.h,
hasShadow: false,
),
padding: EdgeInsets.all(6.h),
child: Lottie.asset(AppAnimations.hourGlass, repeat: true, reverse: false, frameRate: FrameRate(60), width: 40.h, height: 40.h, fit: BoxFit.fill)),
], ],
).toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading), ).toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading),
SizedBox(height: 10.h), SizedBox(height: 10.h),

@ -243,6 +243,86 @@ class AppointmentCard extends StatelessWidget {
(patientAppointmentHistoryResponseModel.isExecludeDoctor ?? false) || (patientAppointmentHistoryResponseModel.isExecludeDoctor ?? false) ||
!Utils.isClinicAllowedForRebook(patientAppointmentHistoryResponseModel.clinicID ?? 0))) && !Utils.isClinicAllowedForRebook(patientAppointmentHistoryResponseModel.clinicID ?? 0))) &&
AppointmentType.isArrived(patientAppointmentHistoryResponseModel)) { AppointmentType.isArrived(patientAppointmentHistoryResponseModel)) {
if (((patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false) &&
DateTime.now().difference(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate)).inDays <= 15)) {
return Row(
children: [
Expanded(
flex: 6,
child: CustomButton(
text: LocaleKeys.askDoctor.tr(context: context),
onPressed: () async {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.checkingDoctorAvailability.tr(context: context));
await myAppointmentsViewModel.isDoctorAvailable(
projectID: patientAppointmentHistoryResponseModel.projectID,
doctorId: patientAppointmentHistoryResponseModel.doctorID,
clinicId: patientAppointmentHistoryResponseModel.clinicID,
onSuccess: (value) async {
if (value) {
await myAppointmentsViewModel.getAskDoctorRequestTypes(onSuccess: (val) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
title: LocaleKeys.askDoctor.tr(context: context),
child: AskDoctorRequestTypeSelect(
askDoctorRequestTypeList: myAppointmentsViewModel.askDoctorRequestTypeList,
myAppointmentsViewModel: myAppointmentsViewModel,
patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
} else {
print("Doctor is not available");
}
});
},
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,
fontSize: (isFoldable || isTablet) ? 12.f : 14.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
// height: isTablet || isFoldable ? 46.h : 40.h,
height: 40.h,
icon: AppAssets.ask_doctor_icon,
iconColor: AppColors.primaryRedColor,
iconSize: 16.h,
),
),
SizedBox(width: 8.h),
Expanded(
flex: 1,
child: Container(
height: (isFoldable || isTablet) ? 50.h : 40.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.textColor,
borderRadius: 10.h,
side: BorderSide(
color: AppColors.textColor,
width: 1.2,
),
),
child: Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.whiteColor,
width: 24.w,
height: 24.h,
fit: BoxFit.contain,
),
),
).toShimmer2(isShow: isLoading).onPress(() {
_goToDetails(context);
}),
),
],
);
} else {
return CustomButton( return CustomButton(
text: isFromMedicalReport ? LocaleKeys.selectAppointment.tr(context: context) : LocaleKeys.viewDetails.tr(context: context), text: isFromMedicalReport ? LocaleKeys.selectAppointment.tr(context: context) : LocaleKeys.viewDetails.tr(context: context),
onPressed: () { onPressed: () {
@ -279,6 +359,7 @@ class AppointmentCard extends StatelessWidget {
iconColor: AppColors.primaryRedColor, iconColor: AppColors.primaryRedColor,
iconSize: 16.h, iconSize: 16.h,
); );
}
} else { } else {
if (isFromMedicalReport) { if (isFromMedicalReport) {
if (isForEyeMeasurements) { if (isForEyeMeasurements) {
@ -309,7 +390,6 @@ class AppointmentCard extends StatelessWidget {
); );
} }
} }
return Row( return Row(
children: [ children: [
Expanded( Expanded(

@ -168,7 +168,7 @@ class AppointmentCheckinBottomSheet extends StatelessWidget {
// page: AppointmentQueuePage(), // page: AppointmentQueuePage(),
// ), // ),
// ); // );
}, isFullScreen: false); }, isFullScreen: false, isAutoDismiss: true, isCloseButtonVisible: false);
}, },
onError: (error) { onError: (error) {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();

@ -215,8 +215,8 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
children: [ children: [
LocaleKeys.amountBeforeTax.tr(context: context).toText14(isBold: true), LocaleKeys.amountBeforeTax.tr(context: context).toText14(isBold: true),
Utils.getPaymentAmountWithSymbol((immediateLiveCareVM.liveCareImmediateAppointmentFeesList.amount ?? "").toText16(isBold: true, isEnglishOnly: true), AppColors.blackColor, 13, Utils.getPaymentAmountWithSymbol((immediateLiveCareVM.liveCareImmediateAppointmentFeesList.amount ?? "").toText16(isBold: true, isEnglishOnly: true), AppColors.blackColor, 13,
isSaudiCurrency: immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar" || isSaudiCurrency: (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "sar").toLowerCase() == "sar" ||
immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "ريال"), (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "ريال").toLowerCase() == "ريال"),
], ],
).paddingSymmetrical(24.h, 0.h), ).paddingSymmetrical(24.h, 0.h),
Row( Row(
@ -224,9 +224,9 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
children: [ children: [
LocaleKeys.vat15.tr(context: context).toText14(isBold: true, color: AppColors.greyTextColor), LocaleKeys.vat15.tr(context: context).toText14(isBold: true, color: AppColors.greyTextColor),
Utils.getPaymentAmountWithSymbol( Utils.getPaymentAmountWithSymbol(
immediateLiveCareVM.liveCareImmediateAppointmentFeesList.tax!.toText14(isBold: true, color: AppColors.greyTextColor, isEnglishOnly: true), AppColors.greyTextColor, 13, (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.tax ?? "0.0").toText14(isBold: true, color: AppColors.greyTextColor, isEnglishOnly: true), AppColors.greyTextColor, 13,
isSaudiCurrency: (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar" || isSaudiCurrency: ((immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "sar").toLowerCase() == "sar" ||
immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "ريال")), (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "ريال").toLowerCase() == "ريال")),
], ],
).paddingSymmetrical(24.h, 0.h), ).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 17.h), SizedBox(height: 17.h),
@ -234,9 +234,9 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
SizedBox(width: 200.h, child: Utils.getPaymentMethods()), SizedBox(width: 200.h, child: Utils.getPaymentMethods()),
Utils.getPaymentAmountWithSymbol(immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total!.toText24(isBold: true, isEnglishOnly: true), AppColors.blackColor, 17, Utils.getPaymentAmountWithSymbol((immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total ?? "0.0").toText24(isBold: true, isEnglishOnly: true), AppColors.blackColor, 17,
isSaudiCurrency: (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar" || isSaudiCurrency: ((immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "sar").toLowerCase() == "sar" ||
immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "ريال")), (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "ريال").toLowerCase() == "ريال")),
], ],
).paddingSymmetrical(24.h, 0.h), ).paddingSymmetrical(24.h, 0.h),
(immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total == "0" || immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total == "0.0") (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total == "0" || immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total == "0.0")

@ -264,7 +264,7 @@ class _ImmediateLiveCarePaymentPageState extends State<ImmediateLiveCarePaymentP
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
LocaleKeys.amountBeforeTax.tr().toText14(isBold: true), LocaleKeys.amountBeforeTax.tr().toText14(isBold: true),
Utils.getPaymentAmountWithSymbol(immediateLiveCareViewModel.liveCareImmediateAppointmentFeesList.amount!.toString().toText16(isBold: true), AppColors.blackColor, 13, Utils.getPaymentAmountWithSymbol((immediateLiveCareViewModel.liveCareImmediateAppointmentFeesList.amount ?? "0.0").toString().toText16(isBold: true), AppColors.blackColor, 13,
isSaudiCurrency: true), isSaudiCurrency: true),
], ],
).paddingSymmetrical(24.h, 0.h), ).paddingSymmetrical(24.h, 0.h),
@ -273,7 +273,7 @@ class _ImmediateLiveCarePaymentPageState extends State<ImmediateLiveCarePaymentP
children: [ children: [
LocaleKeys.vat15.tr().toText14(isBold: true, color: AppColors.greyTextColor), LocaleKeys.vat15.tr().toText14(isBold: true, color: AppColors.greyTextColor),
Utils.getPaymentAmountWithSymbol( Utils.getPaymentAmountWithSymbol(
immediateLiveCareViewModel.liveCareImmediateAppointmentFeesList.tax!.toString().toText14(isBold: true, color: AppColors.greyTextColor), AppColors.greyTextColor, 13, (immediateLiveCareViewModel.liveCareImmediateAppointmentFeesList.tax ?? "0.0").toString().toText14(isBold: true, color: AppColors.greyTextColor), AppColors.greyTextColor, 13,
isSaudiCurrency: true), isSaudiCurrency: true),
], ],
).paddingSymmetrical(24.h, 0.h), ).paddingSymmetrical(24.h, 0.h),
@ -282,7 +282,7 @@ class _ImmediateLiveCarePaymentPageState extends State<ImmediateLiveCarePaymentP
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
"".toText14(isBold: true), "".toText14(isBold: true),
Utils.getPaymentAmountWithSymbol(immediateLiveCareViewModel.liveCareImmediateAppointmentFeesList.total!.toString().toText24(isBold: true), AppColors.blackColor, 17, Utils.getPaymentAmountWithSymbol((immediateLiveCareViewModel.liveCareImmediateAppointmentFeesList.total ?? "0.0").toString().toText24(isBold: true), AppColors.blackColor, 17,
isSaudiCurrency: true), isSaudiCurrency: true),
], ],
).paddingSymmetrical(24.h, 0.h), ).paddingSymmetrical(24.h, 0.h),
@ -466,7 +466,7 @@ class _ImmediateLiveCarePaymentPageState extends State<ImmediateLiveCarePaymentP
//TODO: Need to pass dynamic params to the payment request instead of static values //TODO: Need to pass dynamic params to the payment request instead of static values
browser?.openPaymentBrowser( browser?.openPaymentBrowser(
num.parse(immediateLiveCareViewModel.liveCareImmediateAppointmentFeesList.total!), num.parse(immediateLiveCareViewModel.liveCareImmediateAppointmentFeesList.total ?? "0.0"),
"LiveCare Payment", "LiveCare Payment",
transID, transID,
"12", "12",
@ -547,7 +547,7 @@ class _ImmediateLiveCarePaymentPageState extends State<ImmediateLiveCarePaymentP
// customerEmail: projectViewModel.authenticatedUserObject.user.emailAddress, // customerEmail: projectViewModel.authenticatedUserObject.user.emailAddress,
customerEmail: "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com", customerEmail: "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com",
orderDescription: "LiveCare Payment", orderDescription: "LiveCare Payment",
orderAmount: double.parse(immediateLiveCareViewModel.liveCareImmediateAppointmentFeesList.total!), orderAmount: double.parse((immediateLiveCareViewModel.liveCareImmediateAppointmentFeesList.total ?? "0.0")),
merchantReference: transID, merchantReference: transID,
merchantIdentifier: payfortViewModel.payfortProjectDetailsRespModel!.merchantIdentifier, merchantIdentifier: payfortViewModel.payfortProjectDetailsRespModel!.merchantIdentifier,
applePayAccessCode: payfortViewModel.payfortProjectDetailsRespModel!.accessCode, applePayAccessCode: payfortViewModel.payfortProjectDetailsRespModel!.accessCode,

@ -17,6 +17,7 @@ import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.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/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/countdown_timer.dart'; import 'package:hmg_patient_app_new/widgets/countdown_timer.dart';
import 'package:lottie/lottie.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
@ -97,17 +98,28 @@ class _ImmediateLiveCarePendingRequestPageState extends State<ImmediateLiveCareP
SizedBox(width: 8.w), SizedBox(width: 8.w),
AppCustomChipWidget( AppCustomChipWidget(
icon: AppAssets.appointment_calendar_icon, icon: AppAssets.appointment_calendar_icon,
labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(immediateLiveCareViewModel.patientLiveCareHistoryList[0].arrivalTime), false)), labelText: DateUtil.formatDateToDate(
DateUtil.convertStringToDate(
immediateLiveCareViewModel.patientLiveCareHistoryList.isNotEmpty ? immediateLiveCareViewModel.patientLiveCareHistoryList[0].arrivalTime : ""),
false)),
], ],
), ),
Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h), Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.greyColor,
borderRadius: 10.h,
hasShadow: false,
),
padding: EdgeInsets.all(6.h),
child: Lottie.asset(AppAnimations.hourGlass, repeat: true, reverse: false, frameRate: FrameRate(60), width: 40.h, height: 40.h, fit: BoxFit.fill)),
// Lottie.asset(AppAnimations.pending_loading_animation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 80.h, height: 80.h, fit: BoxFit.cover), // 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),
SizedBox(height: 8.h), SizedBox(height: 8.h),
LocaleKeys.yourTurnIsAfterPatients LocaleKeys.yourTurnIsAfterPatients.tr(namedArgs: {
.tr(namedArgs: {'count': (immediateLiveCareViewModel.patientLiveCareHistoryList[0].patCount ?? 0).toString()}, context: context).toText14(isBold: true), 'count': (immediateLiveCareViewModel.patientLiveCareHistoryList.isNotEmpty ? immediateLiveCareViewModel.patientLiveCareHistoryList[0].patCount ?? 0 : 0).toString()
}, context: context).toText14(isBold: true),
// "Your turn is after ${immediateLiveCareViewModel.patientLiveCareHistoryList[0].patCount} patients.".toText16(isBold: true), // "Your turn is after ${immediateLiveCareViewModel.patientLiveCareHistoryList[0].patCount} patients.".toText16(isBold: true),
SizedBox(height: 8.h), SizedBox(height: 8.h),
], ],
@ -127,7 +139,7 @@ class _ImmediateLiveCarePendingRequestPageState extends State<ImmediateLiveCareP
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
"Expected waiting time: ".toText16(isBold: true), LocaleKeys.waitingTime.tr(context: context).toText16(isBold: true),
SizedBox(height: 8.h), SizedBox(height: 8.h),
ValueListenableBuilder<Duration>( ValueListenableBuilder<Duration>(
valueListenable: immediateLiveCareVM.durationNotifier, valueListenable: immediateLiveCareVM.durationNotifier,

@ -317,7 +317,8 @@ class _ReviewAppointmentPageState extends State<ReviewAppointmentPage> {
void initiateBookAppointment() async { void initiateBookAppointment() async {
// LoadingUtils.showFullScreenLoader(barrierDismissible: true, isSuccessDialog: false, loadingText: bookAppointmentsViewModel.isPatientRescheduleAppointment ? LocaleKeys.reschedulingAppo.tr(context: context) : LocaleKeys.bookingYourAppointment.tr(context: context)); // LoadingUtils.showFullScreenLoader(barrierDismissible: true, isSuccessDialog: false, loadingText: bookAppointmentsViewModel.isPatientRescheduleAppointment ? LocaleKeys.reschedulingAppo.tr(context: context) : LocaleKeys.bookingYourAppointment.tr(context: context));
LoaderBottomSheet.showLoader(loadingText: bookAppointmentsViewModel.isPatientRescheduleAppointment ? LocaleKeys.reschedulingAppo.tr(context: context) : LocaleKeys.bookingYourAppointment.tr(context: context)); // LoaderBottomSheet.showLoader(loadingText: bookAppointmentsViewModel.isPatientRescheduleAppointment ? LocaleKeys.reschedulingAppo.tr(context: context) : LocaleKeys.bookingYourAppointment.tr(context: context));
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.loadingText.tr(context: context));
myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true); myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true);
if (bookAppointmentsViewModel.isLiveCareSchedule) { if (bookAppointmentsViewModel.isLiveCareSchedule) {

@ -1079,7 +1079,8 @@ class _SelectClinicPageState extends State<SelectClinicPage> {
// } // }
var bottomSheetType = RegionBottomSheetType.FOR_CLINIIC; var bottomSheetType = RegionBottomSheetType.FOR_CLINIIC;
if (clinic.clinicID == 17) { if (clinic.clinicID == 17) {
regionalViewModel.setBottomSheetState(AppointmentViaRegionState.HOSPITAL_SELECTION); // regionalViewModel.setBottomSheetState(AppointmentViaRegionState.HOSPITAL_SELECTION);
// bottomSheetType = RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER;
bottomSheetType = RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER; bottomSheetType = RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER;
} }
// if (clinic.clinicID == 253) { // if (clinic.clinicID == 253) {

@ -44,7 +44,7 @@ class _NearestErPageState extends State<NearestErPage> {
children: [ children: [
TextInputWidget( TextInputWidget(
labelText: LocaleKeys.search.tr(), labelText: LocaleKeys.search.tr(),
hintText: 'Type any facility name', hintText: '',
controller: searchText, controller: searchText,
onChange: (value) { onChange: (value) {
debouncer.run(() { debouncer.run(() {

@ -59,7 +59,7 @@ class NearestERItem extends StatelessWidget {
Expanded( Expanded(
child: (nearestERItem.projectName?.toText16( child: (nearestERItem.projectName?.toText16(
color: AppColors.textColor, color: AppColors.textColor,
weight: FontWeight.w600, isBold: true
) ?? ) ??
SizedBox.shrink()).toShimmer2(isShow: isLoading), SizedBox.shrink()).toShimmer2(isShow: isLoading),
), ),
@ -84,7 +84,7 @@ class NearestERItem extends StatelessWidget {
Directionality( Directionality(
textDirection: ui.TextDirection.ltr, textDirection: ui.TextDirection.ltr,
child: AppCustomChipWidget( child: AppCustomChipWidget(
labelText: "Expected waiting time: ${nearestERItem.getTime()} mins", labelText: "${LocaleKeys.waitingTime.tr(context: context)} ${nearestERItem.getTime()} ${LocaleKeys.mins.tr(context: context)}",
icon: AppAssets.waiting_time_clock, icon: AppAssets.waiting_time_clock,
iconHasColor: false, iconHasColor: false,
labelPadding: EdgeInsetsDirectional.only(start: 4.h, end: 0.h), labelPadding: EdgeInsetsDirectional.only(start: 4.h, end: 0.h),
@ -109,14 +109,14 @@ class NearestERItem extends StatelessWidget {
borderColor: AppColors.secondaryLightRedColor, borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor, textColor: AppColors.primaryRedColor,
iconColor: AppColors.primaryRedColor, iconColor: AppColors.primaryRedColor,
height: 40.h, height: 46.h,
fontSize: 14.f, fontSize: 14.f,
isBold: true, isBold: true,
).toShimmer2(isShow: isLoading), ).toShimmer2(isShow: isLoading),
), ),
SizedBox(width: 8.h), SizedBox(width: 8.h),
SizedBox( SizedBox(
height: 40.h, height: 46.h,
width: 40.h, width: 40.h,
child: CustomButton( child: CustomButton(
text: '', text: '',
@ -124,12 +124,11 @@ class NearestERItem extends StatelessWidget {
icon: AppAssets.call_fill, icon: AppAssets.call_fill,
onPressed: () { onPressed: () {
context.read<EmergencyServicesViewModel>().openDialer( nearestERItem.phonenumber??""); context.read<EmergencyServicesViewModel>().openDialer( nearestERItem.phonenumber??"");
}, },
backgroundColor: AppColors.greyColor, backgroundColor: AppColors.greyColor,
iconColor: AppColors.textColor, iconColor: AppColors.textColor,
borderColor: AppColors.greyColor, borderColor: AppColors.greyColor,
height: 40.h, height: 46.h,
).toShimmer2(isShow: isLoading), ).toShimmer2(isShow: isLoading),
), ),
], ],

@ -74,7 +74,8 @@ class _HabibWalletState extends State<HabibWalletPage> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
"${_appState.getAuthenticatedUser()!.firstName!} ${_appState.getAuthenticatedUser()!.lastName!}".toText19(isBold: true, color: Colors.white), "${_appState.getAuthenticatedUser()!.firstName!} ${_appState.getAuthenticatedUser()!.lastName!}".toText19(isBold: true, color: Colors.white),
"MRN: ${_appState.getAuthenticatedUser()!.patientId!}".toText14(isBold: true, color: AppColors.greyTextColor, isEnglishOnly: true), "${LocaleKeys.fileno.tr(context: context)}: ${_appState.getAuthenticatedUser()!.patientId!}"
.toText14(isBold: true, color: AppColors.greyTextColor, isEnglishOnly: true),
], ],
).expanded, ).expanded,
Utils.buildSvgWithAssets(icon: AppAssets.habiblogo, width: 24.h, height: 24.h, applyThemeColor: false), Utils.buildSvgWithAssets(icon: AppAssets.habiblogo, width: 24.h, height: 24.h, applyThemeColor: false),
@ -84,8 +85,15 @@ class _HabibWalletState extends State<HabibWalletPage> {
LocaleKeys.balanceAmount.tr(context: context).toText14(isBold: true, color: Colors.white), LocaleKeys.balanceAmount.tr(context: context).toText14(isBold: true, color: Colors.white),
SizedBox(height: 4.h), SizedBox(height: 4.h),
Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) { Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) {
return Utils.getPaymentAmountWithSymbol2(num.parse(NumberFormat.decimalPattern().format(habibWalletVM.habibWalletAmount)), return Utils.getPaymentAmountWithSymbol2(
textColor: Colors.white, iconColor: Colors.white, iconSize: 16, isExpanded: false) num.parse(
NumberFormat.decimalPattern().format(habibWalletVM.habibWalletAmount),
),
textColor: Colors.white,
iconColor: Colors.white,
iconSize: 16,
isExpanded: false,
letterSpacing: -1)
.toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 24.h); .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 24.h);
}), }),
], ],
@ -140,7 +148,7 @@ class _HabibWalletState extends State<HabibWalletPage> {
children: [ children: [
Expanded(child: habibWalletVM.habibWalletBalanceList[index].projectDescription!.toText16(isBold: true, color: AppColors.textColor)), Expanded(child: habibWalletVM.habibWalletBalanceList[index].projectDescription!.toText16(isBold: true, color: AppColors.textColor)),
Utils.getPaymentAmountWithSymbol2(num.parse(NumberFormat.decimalPattern().format(habibWalletVM.habibWalletBalanceList[index].patientAdvanceBalanceAmount!)), Utils.getPaymentAmountWithSymbol2(num.parse(NumberFormat.decimalPattern().format(habibWalletVM.habibWalletBalanceList[index].patientAdvanceBalanceAmount!)),
textColor: AppColors.textColor, iconColor: AppColors.textColor, iconSize: 18.h, isExpanded: false, fontSize: 28.f, fontWeight: FontWeight.w600,), textColor: AppColors.textColor, iconColor: AppColors.textColor, iconSize: 18.h, isExpanded: false, fontSize: 28.f, fontWeight: FontWeight.w600, letterSpacing: -1),
], ],
).paddingSymmetrical(0, 12.h); ).paddingSymmetrical(0, 12.h);
}, },

@ -69,6 +69,7 @@ import 'package:hmg_patient_app_new/widgets/countdown_timer.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.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/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/routes/spring_page_route_builder.dart'; import 'package:hmg_patient_app_new/widgets/routes/spring_page_route_builder.dart';
import 'package:lottie/lottie.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:smooth_corner/smooth_corner.dart'; import 'package:smooth_corner/smooth_corner.dart';
@ -264,7 +265,7 @@ class _LandingPageState extends State<LandingPage> {
borderColor: AppColors.secondaryLightRedColor, borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor, textColor: AppColors.primaryRedColor,
fontSize: 14.f, fontSize: 14.f,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w700,
borderRadius: 12.r, borderRadius: 12.r,
padding: EdgeInsets.fromLTRB(12.h, 0, 12.h, 0), padding: EdgeInsets.fromLTRB(12.h, 0, 12.h, 0),
height: 40.h, height: 40.h,
@ -484,18 +485,23 @@ class _LandingPageState extends State<LandingPage> {
) )
: SizedBox( : SizedBox(
height: 255.h + 20 + 30, // itemHeight + shadow padding (10 top + 10 bottom) + pagination dots space height: 255.h + 20 + 30, // itemHeight + shadow padding (10 top + 10 bottom) + pagination dots space
child: Swiper( child: Builder(
itemCount: myAppointmentsVM.isMyAppointmentsLoading builder: (context) {
final int swiperItemCount = myAppointmentsVM.isMyAppointmentsLoading
? 3 ? 3
: myAppointmentsVM.patientAppointmentsHistoryList.length < 3 : myAppointmentsVM.patientAppointmentsHistoryList.length < 3
? myAppointmentsVM.patientAppointmentsHistoryList.length ? myAppointmentsVM.patientAppointmentsHistoryList.length
: 3, : 3;
final bool isArabic = appState.isArabic();
return Swiper(
itemCount: swiperItemCount,
layout: SwiperLayout.STACK, layout: SwiperLayout.STACK,
loop: false, loop: false,
itemWidth: MediaQuery.of(context).size.width - 48.h, itemWidth: MediaQuery.of(context).size.width - 48.h,
indicatorLayout: PageIndicatorLayout.COLOR, indicatorLayout: PageIndicatorLayout.COLOR,
axisDirection: appState.isArabic() ? AxisDirection.right : AxisDirection.left, axisDirection: isArabic ? AxisDirection.right : AxisDirection.left,
controller: _controller, controller: _controller,
index: isArabic ? swiperItemCount - 1 : 0,
itemHeight: 255.h + 20, itemHeight: 255.h + 20,
// extra space for shadow // extra space for shadow
pagination: SwiperPagination( pagination: SwiperPagination(
@ -504,9 +510,12 @@ class _LandingPageState extends State<LandingPage> {
builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor), builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor),
), ),
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
final int actualIndex = isArabic ? (swiperItemCount - 1 - index) : index;
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 10), padding: const EdgeInsets.symmetric(vertical: 10),
child: getIndexSwiperCard(index), child: getIndexSwiperCard(actualIndex),
);
},
); );
}, },
), ),
@ -1005,17 +1014,21 @@ class _LandingPageState extends State<LandingPage> {
Widget _buildQueueHeader(int currentStatus) { Widget _buildQueueHeader(int currentStatus) {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
AppCustomChipWidget( AppCustomChipWidget(
labelText: currentStatus == 0 ? LocaleKeys.inQueue.tr() : LocaleKeys.yourTurn.tr(), labelText: currentStatus == 0 ? LocaleKeys.inQueue.tr() : LocaleKeys.yourTurn.tr(),
backgroundColor: Utils.getCardBorderColor(currentStatus).withValues(alpha: 0.20), backgroundColor: Utils.getCardBorderColor(currentStatus).withValues(alpha: 0.20),
textColor: Utils.getCardBorderColor(currentStatus), textColor: Utils.getCardBorderColor(currentStatus),
), ),
Utils.buildSvgWithAssets( Container(
icon: AppAssets.waiting_icon, decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
width: 24.h, color: AppColors.greyColor,
height: 24.h, borderRadius: 10.h,
hasShadow: false,
), ),
padding: EdgeInsets.all(6.h),
child: Lottie.asset(AppAnimations.hourGlass, repeat: true, reverse: false, frameRate: FrameRate(60), width: 40.h, height: 40.h, fit: BoxFit.fill)),
], ],
); );
} }
@ -1149,6 +1162,7 @@ class _LandingPageState extends State<LandingPage> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
AppCustomChipWidget( AppCustomChipWidget(
labelText: liveCareData.stringCallStatus, labelText: liveCareData.stringCallStatus,
@ -1163,13 +1177,42 @@ class _LandingPageState extends State<LandingPage> {
false, false,
), ),
), ),
SizedBox(width: 8.w),
AppCustomChipWidget(
richText: ValueListenableBuilder<Duration>(
valueListenable: immediateLiveCareViewModel.durationNotifier,
builder: (context, duration, child) {
final hours = duration.inHours.toString().padLeft(2, '0');
final minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0');
final seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0');
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
'$hours:$minutes:$seconds'.toText10(isBold: true),
],
);
},
),
// labelText: DateUtil.formatDateToDate(
// DateUtil.convertStringToDate(liveCareData.arrivalTime),
// false,
// ),
),
], ],
), ),
Utils.buildSvgWithAssets( Container(
icon: AppAssets.waiting_icon, decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
width: 24.h, color: AppColors.greyColor,
height: 24.h, borderRadius: 10.h,
hasShadow: false,
), ),
padding: EdgeInsets.all(6.h),
child: Lottie.asset(AppAnimations.hourGlass, repeat: true, reverse: false, frameRate: FrameRate(60), width: 40.h, height: 40.h, fit: BoxFit.fill)),
// Utils.buildSvgWithAssets(
// icon: AppAssets.waiting_icon,
// width: 24.h,
// height: 24.h,
// ),
], ],
); );
} }

@ -1,6 +1,8 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.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';
import 'package:hmg_patient_app_new/core/utils/size_utils.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/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -76,13 +78,14 @@ class HabibWalletCard extends StatelessWidget {
// ], // ],
// ), // ),
SizedBox(height: 4.h), SizedBox(height: 4.h),
Row(
children: [
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) { Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) {
return Row( return Row(
mainAxisSize: MainAxisSize.max,
children: [
Row(
children: [ children: [
Utils.buildSvgWithAssets( Utils.buildSvgWithAssets(
icon: AppAssets.saudi_riyal_icon, icon: AppAssets.saudi_riyal_icon,
@ -98,33 +101,20 @@ class HabibWalletCard extends StatelessWidget {
.toText32(isBold: true, isEnglishOnly: true) .toText32(isBold: true, isEnglishOnly: true)
.toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 40.h), .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 40.h),
], ],
);
}),
Padding(
padding: EdgeInsets.symmetric(horizontal: 35.h),
child: Row(
children: [
LocaleKeys.viewDetails.tr(context: context).toText12(color: AppColors.primaryRedColor, isBold: true),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
],
).onPress(() {
Navigator.of(context).push(
CustomPageRoute(
page: HabibWalletPage(),
), ),
Spacer(),
Utils.getPaymentMethods(),
],
); );
}), }),
),
],
),
SizedBox(
// width: 50.h,
child: Utils.getPaymentMethods(),
),
], ],
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
CustomButton( Row(
children: [
Expanded(
flex: 6,
child: CustomButton(
height: 40.h, height: 40.h,
icon: AppAssets.recharge_icon, icon: AppAssets.recharge_icon,
iconColor: AppColors.infoColor, iconColor: AppColors.infoColor,
@ -141,15 +131,40 @@ class HabibWalletCard extends StatelessWidget {
Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage())); Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage()));
}, },
), ),
// Row( ),
// mainAxisAlignment: MainAxisAlignment.spaceBetween, SizedBox(width: 8.h),
// children: [ Expanded(
// SizedBox( flex: 1,
// width: 200.h, child: Container(
// child: Utils.getPaymentMethods(), height: (isFoldable || isTablet) ? 50.h : 40.h,
// ), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
// ], color: AppColors.textColor,
// ), borderRadius: 10.h,
side: BorderSide(
color: AppColors.textColor,
width: 1.2,
),
),
child: Transform.flip(
flipX: getIt.get<AppState>().isArabic(),
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.whiteColor,
width: 24.w,
height: 24.h,
fit: BoxFit.contain,
),
),
).onPress(() {
Navigator.of(context).push(
CustomPageRoute(
page: HabibWalletPage(),
),
);
}),
),
],
),
], ],
), ),
), ),

@ -168,15 +168,16 @@ class LabResultByClinic extends StatelessWidget {
], ],
), ),
).paddingSymmetrical(24.h, 24.h).onPress(() async { ).paddingSymmetrical(24.h, 24.h).onPress(() async {
final _dialogService = getIt.get<DialogService>(); final dialogService = getIt.get<DialogService>();
await _dialogService.showCommonBottomSheetWithoutH( final appState = getIt.get<AppState>();
await dialogService.showCommonBottomSheetWithoutH(
message: LocaleKeys.aiDisclaimer.tr(), message: LocaleKeys.aiDisclaimer.tr(),
label: LocaleKeys.consent.tr(), label: LocaleKeys.consent.tr(),
okLabel: LocaleKeys.acceptLbl.tr(), okLabel: LocaleKeys.acceptLbl.tr(),
cancelLabel: LocaleKeys.rejectView.tr(), cancelLabel: LocaleKeys.rejectView.tr(),
onOkPressed: () { onOkPressed: () {
context.pop(); context.pop();
labViewModel.getAiOverviewLabOrders(labOrder: labOrder, loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context)); labViewModel.getAiOverviewLabOrders(langId: appState.getLanguageID(), labOrder: labOrder, loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context));
}, },
onCancelPressed: () { onCancelPressed: () {
context.pop(); context.pop();

@ -197,7 +197,7 @@ class _LabResultDetailsState extends State<LabResultDetails> {
onOkPressed: () { onOkPressed: () {
context.pop(); context.pop();
labViewModel.getAiOverviewSingleLabResult( labViewModel.getAiOverviewSingleLabResult(
langId: appState.getLanguageID().toString(), recentLabResult: recentLabResult, loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context)); langId: appState.getLanguageID(), recentLabResult: recentLabResult, loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context));
}, },
onCancelPressed: () { onCancelPressed: () {
context.pop(); context.pop();

@ -185,7 +185,7 @@ class _MyInvoicesDetailsPageState extends State<MyInvoicesDetailsPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
(getIt<AppState>().isArabic() ? widget.getInvoiceDetailsResponseModel.doctorNameN ?? LocaleKeys.doctor.tr(context: context) : widget.getInvoiceDetailsResponseModel.doctorName!).toText16(isBold: true), (getIt<AppState>().isArabic() ? widget.getInvoiceDetailsResponseModel.doctorName ?? LocaleKeys.doctor.tr(context: context) : widget.getInvoiceDetailsResponseModel.doctorName!).toText16(isBold: true),
SizedBox(height: 8.h), SizedBox(height: 8.h),
Wrap( Wrap(
direction: Axis.horizontal, direction: Axis.horizontal,
@ -199,7 +199,7 @@ class _MyInvoicesDetailsPageState extends State<MyInvoicesDetailsPage> {
), ),
AppCustomChipWidget( AppCustomChipWidget(
labelText: ((getIt<AppState>().isArabic() ? widget.getInvoiceDetailsResponseModel.clinicDescriptionN : widget.getInvoiceDetailsResponseModel.clinicDescription ?? "")!.length > 15 labelText: ((getIt<AppState>().isArabic() ? widget.getInvoiceDetailsResponseModel.clinicDescriptionN : widget.getInvoiceDetailsResponseModel.clinicDescription ?? "")!.length > 15
? '${widget.getInvoiceDetailsResponseModel.clinicDescription!.substring(0, 12)}...' ? '${(getIt<AppState>().isArabic() ? widget.getInvoiceDetailsResponseModel.clinicDescriptionN : widget.getInvoiceDetailsResponseModel.clinicDescription ?? "")!.substring(0, 12)}...'
: getIt<AppState>().isArabic() ? widget.getInvoiceDetailsResponseModel.clinicDescriptionN : widget.getInvoiceDetailsResponseModel.clinicDescription ?? ""), : getIt<AppState>().isArabic() ? widget.getInvoiceDetailsResponseModel.clinicDescriptionN : widget.getInvoiceDetailsResponseModel.clinicDescription ?? ""),
labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 4.w), labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 4.w),
), ),

@ -48,6 +48,14 @@ class _RadiologyResultPageState extends State<RadiologyResultPage> {
super.initState(); super.initState();
} }
@override
void dispose() {
// Clear AI analysis data when leaving the screen
radiologyViewModel.closeRadiologyAIAnalysis();
radiologyViewModel.setIsRadiologyAIAnalysisNeedsToBeShown(true);
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
radiologyViewModel = Provider.of<RadiologyViewModel>(context, listen: false); radiologyViewModel = Provider.of<RadiologyViewModel>(context, listen: false);
@ -250,7 +258,7 @@ class _RadiologyResultPageState extends State<RadiologyResultPage> {
).paddingSymmetrical(24.h, 12.h).onPress(() async { ).paddingSymmetrical(24.h, 12.h).onPress(() async {
final _dialogService = getIt.get<DialogService>(); final _dialogService = getIt.get<DialogService>();
await _dialogService.showCommonBottomSheetWithoutH( await _dialogService.showCommonBottomSheetWithoutH(
message: LocaleKeys.aiDisclaimer.tr(), message: LocaleKeys.aiDisclaimerRad.tr(),
label: LocaleKeys.consent.tr(), label: LocaleKeys.consent.tr(),
okLabel: LocaleKeys.acceptLbl.tr(), okLabel: LocaleKeys.acceptLbl.tr(),
cancelLabel: LocaleKeys.rejectView.tr(), cancelLabel: LocaleKeys.rejectView.tr(),
@ -259,6 +267,7 @@ class _RadiologyResultPageState extends State<RadiologyResultPage> {
radiologyViewModel.getRadiologyAiAnalysis( radiologyViewModel.getRadiologyAiAnalysis(
reportData: widget.patientRadiologyResponseModel.reportData ?? "", reportData: widget.patientRadiologyResponseModel.reportData ?? "",
loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context), loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context),
langId: _appState.getLanguageID(),
); );
}, },
onCancelPressed: () { onCancelPressed: () {

@ -58,6 +58,7 @@ class _SelectedOrgansSectionState extends State<SelectedOrgansSection> {
style: TextStyle( style: TextStyle(
fontSize: 16.f, fontSize: 16.f,
// isBold: true, // isBold: true,
fontWeight: FontWeight.w600,
color: AppColors.textColor, color: AppColors.textColor,
), ),
), ),
@ -78,7 +79,7 @@ class _SelectedOrgansSectionState extends State<SelectedOrgansSection> {
style: TextStyle( style: TextStyle(
color: AppColors.whiteColor, color: AppColors.whiteColor,
fontSize: 12.f, fontSize: 12.f,
// isBold: true, fontWeight: FontWeight.w600,
), ),
), ),
), ),

@ -26,8 +26,7 @@ class AppTheme {
canvasColor: Colors.white, canvasColor: Colors.white,
highlightColor: Colors.grey[100]!.withOpacity(0.4), highlightColor: Colors.grey[100]!.withOpacity(0.4),
splashColor: Colors.transparent, splashColor: Colors.transparent,
bottomSheetTheme: BottomSheetThemeData( bottomSheetTheme: BottomSheetThemeData(backgroundColor: Colors.black.withOpacity(0)),
backgroundColor: Colors.black.withOpacity(0)),
floatingActionButtonTheme: const FloatingActionButtonThemeData(highlightElevation: 2, disabledElevation: 0, elevation: 2), floatingActionButtonTheme: const FloatingActionButtonThemeData(highlightElevation: 2, disabledElevation: 0, elevation: 2),
appBarTheme: AppBarTheme( appBarTheme: AppBarTheme(
color: const Color(0xff515A5D), color: const Color(0xff515A5D),
@ -35,7 +34,7 @@ class AppTheme {
actionsIconTheme: IconThemeData( actionsIconTheme: IconThemeData(
color: Colors.grey[800], color: Colors.grey[800],
), ),
systemOverlayStyle: SystemUiOverlayStyle.light, systemOverlayStyle: SystemUiOverlayStyle.dark,
surfaceTintColor: Colors.transparent, surfaceTintColor: Colors.transparent,
), ),
); );

@ -88,7 +88,7 @@ Widget buildDigit(String digit) {
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.black, color: Colors.black,
fontSize: 14.f, fontSize: 10.f,
), ),
), ),
), ),

@ -210,7 +210,7 @@ class _GMSMapState extends State<GMSMap> {
Icons.location_pin, Icons.location_pin,
size: 36.h, size: 36.h,
color: AppColors.primaryRedColor, color: AppColors.primaryRedColor,
).paddingOnly(bottom: Platform.isAndroid ? 30.h : double.parse((widget.bottomPaddingHeight + 25.h).toString())), ).paddingOnly(bottom: Platform.isAndroid ? 30.h : 60.h),
), ),
// My Location button // My Location button

@ -204,31 +204,10 @@ abstract class _CustomLayoutStateBase<T extends _SubSwiper> extends State<T>
void _onPanEnd(DragEndDetails details) { void _onPanEnd(DragEndDetails details) {
if (_lockScroll) return; if (_lockScroll) return;
final bool _isReversedGesture = widget.axisDirection == AxisDirection.right;
double velocity = widget.scrollDirection == Axis.horizontal double velocity = widget.scrollDirection == Axis.horizontal
? details.velocity.pixelsPerSecond.dx ? details.velocity.pixelsPerSecond.dx
: details.velocity.pixelsPerSecond.dy; : details.velocity.pixelsPerSecond.dy;
if (_isReversedGesture) {
// Reversed: swipe right (value >= 0.75) = next, swipe left (value < 0.25) = previous
if (_animationController.value >= 0.75 || velocity > 500.0) {
if (_currentIndex >= widget.itemCount - 1 && !widget.loop) {
_move(0.5);
return;
}
_move(1.0, nextIndex: _currentIndex + 1);
} else if (_animationController.value < 0.25 || velocity < -500.0) {
if (_currentIndex <= 0 && !widget.loop) {
_move(0.5);
return;
}
_move(0.0, nextIndex: _currentIndex - 1);
} else {
_move(0.5);
}
} else {
// Default: swipe right (value >= 0.75) = previous, swipe left (value < 0.25) = next
if (_animationController.value >= 0.75 || velocity > 500.0) { if (_animationController.value >= 0.75 || velocity > 500.0) {
if (_currentIndex <= 0 && !widget.loop) { if (_currentIndex <= 0 && !widget.loop) {
return; return;
@ -243,7 +222,6 @@ abstract class _CustomLayoutStateBase<T extends _SubSwiper> extends State<T>
_move(0.5); _move(0.5);
} }
} }
}
void _onPanStart(DragStartDetails details) { void _onPanStart(DragStartDetails details) {
if (_lockScroll) return; if (_lockScroll) return;
@ -255,7 +233,6 @@ abstract class _CustomLayoutStateBase<T extends _SubSwiper> extends State<T>
void _onPanUpdate(DragUpdateDetails details) { void _onPanUpdate(DragUpdateDetails details) {
if (_lockScroll) return; if (_lockScroll) return;
double value = _currentValue + double value = _currentValue +
((widget.scrollDirection == Axis.horizontal ((widget.scrollDirection == Axis.horizontal
? details.globalPosition.dx ? details.globalPosition.dx
@ -265,18 +242,6 @@ abstract class _CustomLayoutStateBase<T extends _SubSwiper> extends State<T>
2; 2;
// no loop ? // no loop ?
if (!widget.loop) { if (!widget.loop) {
if (widget.axisDirection == AxisDirection.right) {
// Reversed bounds: block dragging left past first, right past last
if (_currentIndex <= 0) {
if (value < 0.5) {
value = 0.5;
}
} else if (_currentIndex >= widget.itemCount - 1) {
if (value > 0.5) {
value = 0.5;
}
}
} else {
if (_currentIndex >= widget.itemCount - 1) { if (_currentIndex >= widget.itemCount - 1) {
if (value < 0.5) { if (value < 0.5) {
value = 0.5; value = 0.5;
@ -287,7 +252,6 @@ abstract class _CustomLayoutStateBase<T extends _SubSwiper> extends State<T>
} }
} }
} }
}
_animationController.value = value; _animationController.value = value;
} }

Loading…
Cancel
Save