Merge branch 'master' into faiz_dev

# Conflicts:
#	lib/routes/app_routes.dart
#	lib/theme/colors.dart
pull/135/head
faizatflutter 2 weeks ago
commit f8fdd7570e

@ -0,0 +1,7 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.462872 10.1666C0.228367 10.108 0.111115 10.0787 0.0468218 9.98619C-0.0174712 9.8937 -0.00458142 9.77798 0.0211982 9.54656C0.619456 4.17595 5.17435 0 10.7046 0C16.2349 0 20.7898 4.176 21.388 9.54665C21.4138 9.77807 21.4267 9.89379 21.3624 9.98628C21.2981 10.0788 21.1808 10.1081 20.9463 10.1667L16.5365 11.2692C16.3156 11.3244 16.2052 11.352 16.1187 11.3202C16.0321 11.2885 15.9488 11.1726 15.7824 10.9408C15.5865 10.6681 15.3355 10.4575 15.0448 10.3067C14.5775 10.0644 14.0546 10.0002 13.5871 10.0002H7.82242C7.35432 10.0002 6.83087 10.0645 6.3633 10.3073C6.07298 10.458 5.82232 10.6685 5.62668 10.9408C5.46023 11.1725 5.37701 11.2884 5.29044 11.3201C5.20386 11.3519 5.09347 11.3243 4.87268 11.2691L0.462872 10.1666ZM5.67426 7.21967C6.13506 6.75887 6.76003 6.5 7.4117 6.5H8.70459C9.1188 6.5 9.45459 6.83579 9.45459 7.25C9.45459 7.66421 9.1188 8 8.70459 8H7.4117C7.15786 8 6.91441 8.10084 6.73492 8.28033C6.44203 8.57322 5.96715 8.57322 5.67426 8.28033C5.38137 7.98744 5.38137 7.51256 5.67426 7.21967ZM11.9546 7.25C11.9546 6.83579 12.2904 6.5 12.7046 6.5H13.9975C14.6491 6.5 15.2741 6.75887 15.7349 7.21967C16.0278 7.51256 16.0278 7.98744 15.7349 8.28033C15.442 8.57322 14.9672 8.57322 14.6743 8.28033C14.4948 8.10084 14.2513 8 13.9975 8H12.7046C12.2904 8 11.9546 7.66421 11.9546 7.25Z" fill="white"/>
<path d="M0.0837141 12.4212C0.0267055 12.0559 -0.00179879 11.8733 0.117089 11.7647C0.235976 11.6561 0.422465 11.7027 0.795442 11.7959L4.52364 12.728C4.76706 12.7888 4.88877 12.8193 4.95293 12.9082C5.01708 12.9972 5.00713 13.1275 4.98722 13.3883C4.9545 13.8168 4.94652 14.2577 4.96329 14.6923C4.97667 15.0388 4.98336 15.2121 4.88525 15.3055C4.78714 15.399 4.62125 15.3844 4.28947 15.3554L1.20555 15.0852C1.031 15.0699 0.943724 15.0622 0.875524 15.0115C0.807325 14.9608 0.776105 14.8824 0.713667 14.7256C0.422134 13.9936 0.208718 13.222 0.0837141 12.4212Z" fill="white"/>
<path d="M2.94493 16.749C2.40172 16.7002 2.13012 16.6758 2.03715 16.8534C1.94417 17.0309 2.11204 17.232 2.44777 17.6343C4.4197 19.9968 7.3866 21.5 10.7046 21.5C14.0226 21.5 16.9895 19.9968 18.9614 17.6343C19.2971 17.2321 19.465 17.031 19.372 16.8534C19.279 16.6759 19.0074 16.7002 18.4642 16.749L16.4748 16.9275C16.2986 16.9434 16.2105 16.9513 16.1473 16.993C16.0842 17.0348 16.033 17.1302 15.9308 17.3211C15.7212 17.7122 15.4152 18.0015 15.0448 18.1936C14.5775 18.436 14.0546 18.5002 13.5871 18.5002H7.82241C7.35508 18.5002 6.83229 18.436 6.36514 18.1938C5.99468 18.0017 5.68855 17.7124 5.47892 17.3211C5.37667 17.1303 5.32555 17.0349 5.26236 16.9931C5.19916 16.9513 5.11106 16.9434 4.93485 16.9276L2.94493 16.749Z" fill="white"/>
<path d="M20.6955 14.7257C20.6331 14.8824 20.6018 14.9608 20.5336 15.0115C20.4654 15.0623 20.3782 15.0699 20.2036 15.0852L17.1201 15.3554C16.7883 15.3844 16.6225 15.399 16.5244 15.3055C16.4263 15.2121 16.4329 15.0388 16.4463 14.6923C16.463 14.2578 16.455 13.8169 16.4222 13.3884C16.4023 13.1276 16.3923 12.9972 16.4564 12.9083C16.5206 12.8193 16.6423 12.7889 16.8858 12.728L20.6137 11.796C20.9867 11.7028 21.1732 11.6562 21.2921 11.7648C21.411 11.8734 21.3825 12.056 21.3255 12.4213C21.2004 13.2221 20.987 13.9937 20.6955 14.7257Z" fill="white"/>
<path d="M6.73398 12.051C6.80458 11.8189 6.91733 11.7098 7.05454 11.6385C7.22042 11.5524 7.47075 11.5002 7.82242 11.5002H13.5871C13.9382 11.5002 14.1884 11.5523 14.3542 11.6383C14.4914 11.7095 14.604 11.8184 14.6746 12.0497C15.0482 13.274 15.0482 15.2264 14.6746 16.4506C14.604 16.6819 14.4914 16.7909 14.3542 16.8621C14.1884 16.9481 13.9382 17.0002 13.5871 17.0002H7.82241C7.47147 17.0002 7.22139 16.9481 7.05557 16.8621C6.91833 16.791 6.80577 16.6821 6.73521 16.451C6.36164 15.2274 6.36134 13.2759 6.73398 12.051Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

@ -876,5 +876,6 @@
"endDate": "تاريخ الانتهاء",
"walkin": "زيارة بدون موعد",
"laserClinic": "عيادة الليزر",
"continueString": "يكمل"
"continueString": "يكمل",
"covid_info": "تجري مستشفيات د. سليمان الحبيب فحص فيروس كورونا المستجد وتصدر شهادات السفر على مدار الساعة، طوال أيام الأسبوع، وبسرعة ودقة عالية. يمكن للراغبين في الاستفادة من هذه الخدمة زيارة أحد فروع مستشفيات د. سليمان الحبيب وإجراء فحص كورونا خلال بضع دقائق والحصول على النتائج خلال عدة ساعات خدمة فحص فيروس كورونا Covid 19 بتقنية PCR للكشف عن الفيروس وفقاً لأعلى المعايير العالمية وبأحدث أجهزة RT-PCR عالية الدقة (GeneXpert الأمريكي وغيره)، وهي طرق معتمدة من قبل هيئة الغذاء والدواء وكذلك من قبل المركز السعودي للوقاية من الأمراض المُعدية"
}

@ -872,6 +872,6 @@
"searchClinic": "Search Clinic",
"walkin": "Walk In",
"continueString": "Continue",
"laserClinic": "Laser Clinic"
"laserClinic": "Laser Clinic",
"covid_info" :"Dr. Sulaiman Al Habib hospitals are conducting a test for the emerging corona virus and issuing travel certificates 24/7 in a short time and with high accuracy. Those wishing to benefit from this service can visit one of Dr. Sulaiman Al Habib branches to conduct a corona test within few minutes, and obtain the result within several hours. Corona Virus Covid 19 testing service with PCR technology to detect the virus according to the highest international standards and with the latest high-precision RT-PCR devices (American GeneXpert and others), That is approved by the Food and Drug Authority as well as by the Saudi Center for Infectious Diseases Prevention."
}

@ -334,6 +334,8 @@ var GET_PATIENT_SHARE_FOR_WALKIN_APPOINTMENT = 'Services/Doctors.svc/REST/GetChe
var CAN_PAY_FOR_FOR_WALKIN_APPOINTMENT = 'Services/Doctors.svc/REST/CanPayForWalkinAppointment';
var GET_APPOINTMENT_NEAREST_GATE = 'Services/OUTPs.svc/REST/getGateByProjectIDandClinicID';
//URL to get medicine and pharmacies list
var CHANNEL = 3;
var GENERAL_ID = 'Cs2020@2016\$2958';

@ -282,6 +282,8 @@ class AppAssets {
static const String pregnancyDayAccordion = '$svgBasePath/pregnancy_test_day_accordion.svg';
static const String pregnancyDueDateAccordion = '$svgBasePath/due_date_accordion.svg';
static const String covid19icon = '$svgBasePath/covid_19.svg';
// PNGS //
static const String hmgLogo = '$pngBasePath/hmg_logo.png';
static const String liveCareService = '$pngBasePath/livecare_service.png';
@ -307,6 +309,9 @@ class AppAssets {
static const String fullBodyFront = '$pngBasePath/full_body_front.png';
static const String fullBodyBack = '$pngBasePath/full_body_back.png';
}
class AppAnimations {
@ -327,4 +332,6 @@ class AppAnimations {
static const String ambulance = '$lottieBasePath/ambulance.json';
static const String ambulanceAlert = '$lottieBasePath/ambulance_alert.json';
static const String rrtAmbulance = '$lottieBasePath/rrt_ambulance.json';
}

@ -1,6 +1,7 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_repo.dart';
import 'package:hmg_patient_app_new/features/blood_donation/models/blood_group_list_model.dart';
import 'package:hmg_patient_app_new/features/blood_donation/models/blood_group_response_model.dart';
@ -31,7 +32,7 @@ class BloodDonationViewModel extends ChangeNotifier {
List<BloodGroupListModel> genderList = [
BloodGroupListModel(LocaleKeys.malE.tr(), 1),
BloodGroupListModel(LocaleKeys.female.tr(), 2),
BloodGroupListModel("Female".needTranslation.tr(), 2),
];
late CitiesModel selectedCity;

@ -5,6 +5,7 @@ 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/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/appointment_nearest_gate_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/dental_chief_complaints_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctor_profile_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctors_list_response_model.dart';
@ -102,6 +103,8 @@ abstract class BookAppointmentsRepo {
required int userAge,
Function(dynamic)? onSuccess,
Function(String)? onError});
Future<Either<Failure, GenericApiModel<AppointmentNearestGateResponseModel>>> getAppointmentNearestGate({required int projectID, required int clinicID});
}
class BookAppointmentsRepoImp implements BookAppointmentsRepo {
@ -1046,4 +1049,40 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<AppointmentNearestGateResponseModel>>> getAppointmentNearestGate({required int projectID, required int clinicID}) async {
Map<String, dynamic> mapRequest = {"ProjectID": projectID, "ClinicID": clinicID};
try {
GenericApiModel<AppointmentNearestGateResponseModel>? apiResponse;
Failure? failure;
await apiClient.post(
GET_APPOINTMENT_NEAREST_GATE,
body: mapRequest,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final nearestGateResponse = AppointmentNearestGateResponseModel.fromJson(response['getGateByProjectIDandClinicIDList'][0]);
apiResponse = GenericApiModel<AppointmentNearestGateResponseModel>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: nearestGateResponse,
);
} 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()));
}
}
}

@ -14,6 +14,7 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_repo.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/LaserCategoryType.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/free_slot.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/appointment_nearest_gate_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/dental_chief_complaints_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctor_profile_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctors_list_response_model.dart';
@ -44,6 +45,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
bool isDoctorsListLoading = false;
bool isDoctorProfileLoading = false;
bool isDoctorSearchByNameStarted = false;
bool isAppointmentNearestGateLoading = false;
bool isLiveCareSchedule = false;
bool isGetDocForHealthCal = false;
@ -66,6 +68,11 @@ class BookAppointmentsViewModel extends ChangeNotifier {
List<DoctorsListResponseModel> doctorsList = [];
List<DoctorsListResponseModel> filteredDoctorList = [];
// Grouped doctors lists
List<List<DoctorsListResponseModel>> doctorsListByClinic = [];
List<List<DoctorsListResponseModel>> doctorsListByHospital = [];
List<List<DoctorsListResponseModel>> doctorsListGrouped = [];
List<DoctorsListResponseModel> liveCareDoctorsList = [];
List<PatientDentalPlanEstimationResponseModel> patientDentalPlanEstimationList = [];
@ -127,6 +134,8 @@ class BookAppointmentsViewModel extends ChangeNotifier {
PatientAppointmentShareResponseModel? patientWalkInAppointmentShareResponseModel;
AppointmentNearestGateResponseModel? appointmentNearestGateResponseModel;
///variables for laser clinic
List<LaserCategoryType> femaleLaserCategory = [
LaserCategoryType(1, 'bodyString'),
@ -151,14 +160,28 @@ class BookAppointmentsViewModel extends ChangeNotifier {
setIsSortByClinic(bool value) {
isSortByClinic = value;
if (isSortByClinic) {
doctorsList.sort((a, b) => a.clinicName!.compareTo(b.clinicName!));
} else {
doctorsList.sort((a, b) => a.projectName!.compareTo(b.projectName!));
}
doctorsListGrouped = isSortByClinic ? doctorsListByClinic : doctorsListByHospital;
notifyListeners();
}
// Group doctors by clinic and hospital
void _groupDoctorsList() {
final clinicMap = <String, List<DoctorsListResponseModel>>{};
final hospitalMap = <String, List<DoctorsListResponseModel>>{};
for (var doctor in doctorsList) {
final clinicKey = (doctor.clinicName ?? 'Unknown').trim();
clinicMap.putIfAbsent(clinicKey, () => []).add(doctor);
final hospitalKey = (doctor.projectName ?? 'Unknown').trim();
hospitalMap.putIfAbsent(hospitalKey, () => []).add(doctor);
}
doctorsListByClinic = clinicMap.values.toList();
doctorsListByHospital = hospitalMap.values.toList();
doctorsListGrouped = isSortByClinic ? doctorsListByClinic : doctorsListByHospital;
}
BookAppointmentsViewModel(
{required this.bookAppointmentsRepo,
required this.errorHandlerService,
@ -419,6 +442,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
initializeFilteredList();
clearSearchFilters();
getFiltersFromDoctorList();
_groupDoctorsList();
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
@ -450,6 +474,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
initializeFilteredList();
clearSearchFilters();
getFiltersFromDoctorList();
_groupDoctorsList();
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
@ -1117,6 +1142,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
// initializeFilteredList();
// clearSearchFilters();
// getFiltersFromDoctorList();
_groupDoctorsList();
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
@ -1321,4 +1347,32 @@ class BookAppointmentsViewModel extends ChangeNotifier {
},
);
}
Future<void> getAppointmentNearestGate({required int projectID, required int clinicID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
isAppointmentNearestGateLoading = true;
notifyListeners();
final result = await bookAppointmentsRepo.getAppointmentNearestGate(projectID: projectID, clinicID: clinicID);
result.fold(
(failure) async {
if (onError != null) {
onError(failure.message);
}
},
(apiResponse) {
if (apiResponse.messageStatus == 2) {
onError!(apiResponse.errorMessage!);
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
appointmentNearestGateResponseModel = apiResponse.data!;
isAppointmentNearestGateLoading = false;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
}

@ -0,0 +1,64 @@
class AppointmentNearestGateResponseModel {
String? clinicDescription;
String? clinicDescriptionN;
int? clinicID;
String? clinicLocation;
String? clinicLocationN;
int? gender;
int? iD;
String? nearestGateNumber;
String? nearestGateNumberN;
int? projectID;
String? projectName;
String? projectNameN;
int? rowID;
AppointmentNearestGateResponseModel(
{this.clinicDescription,
this.clinicDescriptionN,
this.clinicID,
this.clinicLocation,
this.clinicLocationN,
this.gender,
this.iD,
this.nearestGateNumber,
this.nearestGateNumberN,
this.projectID,
this.projectName,
this.projectNameN,
this.rowID});
AppointmentNearestGateResponseModel.fromJson(Map<String, dynamic> json) {
clinicDescription = json['ClinicDescription'];
clinicDescriptionN = json['ClinicDescriptionN'];
clinicID = json['ClinicID'];
clinicLocation = json['ClinicLocation'];
clinicLocationN = json['ClinicLocationN'];
gender = json['Gender'];
iD = json['ID'];
nearestGateNumber = json['NearestGateNumber'];
nearestGateNumberN = json['NearestGateNumberN'];
projectID = json['ProjectID'];
projectName = json['ProjectName'];
projectNameN = json['ProjectNameN'];
rowID = json['RowID'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data['ClinicDescription'] = clinicDescription;
data['ClinicDescriptionN'] = clinicDescriptionN;
data['ClinicID'] = clinicID;
data['ClinicLocation'] = clinicLocation;
data['ClinicLocationN'] = clinicLocationN;
data['Gender'] = gender;
data['ID'] = iD;
data['NearestGateNumber'] = nearestGateNumber;
data['NearestGateNumberN'] = nearestGateNumberN;
data['ProjectID'] = projectID;
data['ProjectName'] = projectName;
data['ProjectNameN'] = projectNameN;
data['RowID'] = rowID;
return data;
}
}

@ -1,3 +1,5 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
@ -18,6 +20,7 @@ import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'models/req_models/check_activation_e_referral_req_model.dart';
import 'models/resq_models/relationship_type_resp_mode.dart';
import 'models/ui_models/covid_questionnare_model.dart';
class HmgServicesViewModel extends ChangeNotifier {
final HmgServicesRepo hmgServicesRepo;
@ -60,6 +63,8 @@ class HmgServicesViewModel extends ChangeNotifier {
Future<void> getOrdersList() async {}
// HHC multiple services selection
List<GetCMCServicesResponseModel> selectedHhcServices = [];
@ -766,4 +771,16 @@ class HmgServicesViewModel extends ChangeNotifier {
},
);
}
List<CovidQuestionnaireModel> getQuestionsFromJson() {
final String questionsJson = '''[ { "id": 1, "questionEN": "Is the test intended for travel?", "questionAR": "هل تجري التحليل بغرض السفر؟", "ans": 2 }, { "id": 2, "questionEN": "Coming from outside KSA within last 2 weeks?", "questionAR": "هل قدمت من خارج المملكة خلال الأسبوعين الماضيين؟", "ans": 2 }, { "id": 3, "questionEN": "Do you currently have fever?", "questionAR": "هل تعاني حاليا من حرارة؟", "ans": 2 }, { "id": 4, "questionEN": "Did you have fever in last 2 weeks?", "questionAR": "هل عانيت من حرارة في الأسبوعين الماضيين؟", "ans": 2 }, { "id": 5, "questionEN": "Do you have a sore throat?", "questionAR": "هل لديك التهاب في الحلق؟", "ans": 2 }, { "id": 6, "questionEN": "Do you have a runny nose?", "questionAR": "هل لديك سيلان بالأنف؟" }, { "id": 7, "questionEN": "Do you have a cough?", "questionAR": "هل لديك سعال؟", "ans": 2 }, { "id": 8, "questionEN": "Do you have shortness of breath?", "questionAR": "هل تعاني من ضيق في التنفس؟", "ans": 2 }, { "id": 9, "questionEN": "Do you have nausea?", "questionAR": "هل تعاني من غثيان؟", "ans": 2 }, { "id": 10, "questionEN": "Do you have vomiting?", "questionAR": "هل تعاني من القيء؟", "ans": 2 }, { "id": 11, "questionEN": "Do you have a headache?", "questionAR": "هل تعاني من صداع في الرأس؟", "ans": 2 }, { "id": 12, "questionEN": "Do you have muscle pain?", "questionAR": "هل تعانين من آلام عضلية؟", "ans": 2 }, { "id": 13, "questionEN": "Do you have joint pain?", "questionAR": "هل تعاني من آلام المفاصل؟", "ans": 2 }, { "id": 14, "questionEN": "Do you have diarrhea?", "questionAR": "هل لديك اسهال؟", "ans": 2 } ]''';
try {
final parsed = json.decode(questionsJson) as List<dynamic>;
return parsed
.map((e) => CovidQuestionnaireModel.fromJson(Map<String, dynamic>.from(e)))
.toList();
} catch (_) {
return <CovidQuestionnaireModel>[];
}
}
}

@ -0,0 +1,33 @@
import 'dart:convert';
class CovidQuestionnaireModel {
int? id;
String? questionEn;
String? questionAr;
int? ans;
CovidQuestionnaireModel({
this.id,
this.questionEn,
this.questionAr,
this.ans,
});
factory CovidQuestionnaireModel.fromRawJson(String str) => CovidQuestionnaireModel.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory CovidQuestionnaireModel.fromJson(Map<String, dynamic> json) => CovidQuestionnaireModel(
id: json["id"],
questionEn: json["questionEN"],
questionAr: json["questionAR"],
ans: json["ans"],
);
Map<String, dynamic> toJson() => {
"id": id,
"questionEN": questionEn,
"questionAR": questionAr,
"ans": ans,
};
}

@ -2,7 +2,7 @@
// ignore_for_file: constant_identifier_names
abstract class LocaleKeys {
abstract class LocaleKeys {
static const english = 'english';
static const arabic = 'arabic';
static const login = 'login';
@ -189,7 +189,6 @@ abstract class LocaleKeys {
static const firstName = 'firstName';
static const middleName = 'middleName';
static const lastName = 'lastName';
static const female = 'female';
static const preferredLanguage = 'preferredLanguage';
static const locationsRegister = 'locationsRegister';
static const ksa = 'ksa';
@ -801,7 +800,7 @@ abstract class LocaleKeys {
static const fullName = 'fullName';
static const married = 'married';
static const uae = 'uae';
static const malE = 'male';
static const malE = 'malE';
static const loginBy = 'loginBy';
static const loginByOTP = 'loginByOTP';
static const guest = 'guest';
@ -876,4 +875,6 @@ abstract class LocaleKeys {
static const walkin = 'walkin';
static const laserClinic = 'laserClinic';
static const continueString = 'continueString';
static const covid_info = 'covid_info';
}

@ -4,6 +4,8 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/api_consts.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/calender_utils_new.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
@ -31,6 +33,7 @@ import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_deta
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
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';
@ -132,10 +135,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
},
onCancelTap: () async {
myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true);
var isEventAddedOrRemoved = await CalenderUtilsNew.instance.checkAndRemove( id:"${widget.patientAppointmentHistoryResponseModel.appointmentNo}", );
setState(() {
myAppointmentsViewModel.setAppointmentReminder(isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel);
});
LoaderBottomSheet.showLoader(loadingText: "Cancelling Appointment, Please Wait...".needTranslation);
await myAppointmentsViewModel.cancelAppointment(
patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
@ -155,6 +155,10 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
isFullScreen: false,
);
});
var isEventAddedOrRemoved = await CalenderUtilsNew.instance.checkAndRemove( id:"${widget.patientAppointmentHistoryResponseModel.appointmentNo}", );
setState(() {
myAppointmentsViewModel.setAppointmentReminder(isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel);
});
},
onRescheduleTap: () async {
openDoctorScheduleCalendar();
@ -164,90 +168,105 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
!AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel)
? Column(
children: [
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.r,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
"Appointment Status".needTranslation.toText16(isBold: true),
],
),
SizedBox(height: 4.h),
(!AppointmentType.isConfirmed(widget.patientAppointmentHistoryResponseModel)
? "Not Confirmed".needTranslation.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500)
: "Confirmed".needTranslation.toText12(color: AppColors.successColor, fontWeight: FontWeight.w500)),
SizedBox(height: 16.h),
//TODO Add countdown timer in case of LiveCare Appointment
widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false
? Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.livecare_clinic_icon, width: 40.h, height: 40.h),
SizedBox(width: 12.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"The doctor will call you once the appointment time approaches."
.needTranslation
.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
],
Consumer<BookAppointmentsViewModel>(builder: (context, bookAppointmentsVM, child) {
return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.r,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
"Appointment Status".needTranslation.toText16(isBold: true),
],
),
SizedBox(height: 4.h),
(!AppointmentType.isConfirmed(widget.patientAppointmentHistoryResponseModel)
? "Not Confirmed".needTranslation.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500)
: "Confirmed".needTranslation.toText12(color: AppColors.successColor, fontWeight: FontWeight.w500)),
SizedBox(height: 16.h),
//TODO Add countdown timer in case of LiveCare Appointment
widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false
? Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.livecare_clinic_icon, width: 40.h, height: 40.h),
SizedBox(width: 12.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"The doctor will call you once the appointment time approaches."
.needTranslation
.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
],
),
),
),
],
)
: Stack(
children: [
ClipRRect(
clipBehavior: Clip.hardEdge,
borderRadius: BorderRadius.circular(24.r),
// Todo: what is this???? Api Key??? 😲
child: Image.network(
"https://maps.googleapis.com/maps/api/staticmap?center=${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&zoom=14&size=350x165&maptype=roadmap&markers=color:red%7C${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&key=${ApiKeyConstants.googleMapsApiKey}",
fit: BoxFit.contain,
],
)
: Stack(
children: [
ClipRRect(
clipBehavior: Clip.hardEdge,
borderRadius: BorderRadius.circular(24.r),
// Todo: what is this???? Api Key??? 😲
child: Image.network(
"https://maps.googleapis.com/maps/api/staticmap?center=${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&zoom=14&size=350x165&maptype=roadmap&markers=color:red%7C${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&key=${ApiKeyConstants.googleMapsApiKey}",
fit: BoxFit.contain,
),
),
),
Positioned(
bottom: 0,
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.785,
child: CustomButton(
text: "Get Directions".needTranslation,
onPressed: () {
MapsLauncher.launchCoordinates(
double.parse(widget.patientAppointmentHistoryResponseModel.latitude!),
double.parse(widget.patientAppointmentHistoryResponseModel.longitude!),
widget.patientAppointmentHistoryResponseModel.projectName);
},
backgroundColor: AppColors.textColor.withValues(alpha: 0.8),
borderColor: AppointmentType.getNextActionButtonColor(
widget.patientAppointmentHistoryResponseModel.nextAction)
.withValues(alpha: 0.01),
textColor: AppColors.whiteColor,
fontSize: 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
icon: AppAssets.directions_icon,
iconColor: AppColors.whiteColor,
iconSize: 14.h,
).paddingAll(12.h),
Positioned(
bottom: 0,
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.785,
child: CustomButton(
text: "Get Directions".needTranslation,
onPressed: () {
MapsLauncher.launchCoordinates(double.parse(widget.patientAppointmentHistoryResponseModel.latitude!),
double.parse(widget.patientAppointmentHistoryResponseModel.longitude!), widget.patientAppointmentHistoryResponseModel.projectName);
},
backgroundColor: AppColors.textColor.withValues(alpha: 0.8),
borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withValues(alpha: 0.01),
textColor: AppColors.whiteColor,
fontSize: 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
icon: AppAssets.directions_icon,
iconColor: AppColors.whiteColor,
iconSize: 14.h,
).paddingAll(12.h),
),
),
),
],
),
],
],
),
SizedBox(height: 8.h),
Wrap(
direction: Axis.horizontal,
spacing: 8.w,
runSpacing: 8.h,
children: [
AppCustomChipWidget(
labelText: bookAppointmentsVM.isAppointmentNearestGateLoading
? "Floor: Ground Floor"
: "Floor: ${getIt.get<AppState>().isArabic() ? bookAppointmentsViewModel.appointmentNearestGateResponseModel!.clinicLocationN : bookAppointmentsViewModel.appointmentNearestGateResponseModel!.clinicLocation}",
).toShimmer2(isShow: bookAppointmentsVM.isAppointmentNearestGateLoading),
AppCustomChipWidget(
labelText:
"Nearest Gate: ${getIt.get<AppState>().isArabic() ? bookAppointmentsVM.appointmentNearestGateResponseModel!.nearestGateNumberN : bookAppointmentsVM.appointmentNearestGateResponseModel!.nearestGateNumber}")
.toShimmer2(isShow: bookAppointmentsVM.isAppointmentNearestGateLoading),
],
),
],
),
),
),
),
);
}),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(

@ -22,6 +22,7 @@ import 'package:hmg_patient_app_new/presentation/book_appointment/book_appointme
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
import 'package:hmg_patient_app_new/widgets/date_range_selector/date_range_calender.dart';
import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart';
@ -187,18 +188,9 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CustomButton(
text: "${myAppointmentsVM.patientAppointmentsViewList[index].patientDoctorAppointmentList!.length} Appointments",
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
AppCustomChipWidget(
labelText:
"${myAppointmentsVM.patientAppointmentsViewList[index].patientDoctorAppointmentList!.length} Appointments"),
Icon(isExpanded ? Icons.expand_less : Icons.expand_more),
],
),
@ -224,7 +216,7 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
child: isExpanded
? Container(
key: ValueKey<int>(index),
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h),
padding: EdgeInsets.symmetric(horizontal: 0.w, vertical: 0.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -232,63 +224,6 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
Image.network(
appointment.doctorImageURL!,
width: 24.h,
height: 24.h,
fit: BoxFit.fill,
).circle(100),
SizedBox(width: 8.h),
Expanded(child: appointment.doctorNameObj!.toText14(weight: FontWeight.w500)),
],
),
SizedBox(height: 8.h),
Row(
children: [
CustomButton(
text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(appointment.appointmentDate), false),
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 24.h,
),
SizedBox(width: 8.h),
CustomButton(
text: myAppointmentsVM.isAppointmentsSortByClinic ? appointment.projectName! : appointment.clinicName!,
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 24.h,
),
SizedBox(width: 8.h),
CustomButton(
text: appointment.statusDesc ?? "",
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 24.h,
),
],
),
SizedBox(height: 8.h),
AppointmentCard(
patientAppointmentHistoryResponseModel: appointment,
myAppointmentsViewModel: myAppointmentsViewModel,
@ -296,9 +231,9 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
isLoading: false,
isFromHomePage: false,
),
SizedBox(height: 12.h),
Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
SizedBox(height: 12.h),
SizedBox(height: 8.h),
Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h).paddingSymmetrical(16.w, 0.h),
SizedBox(height: 8.h),
],
);
}),

@ -372,6 +372,7 @@ class AppointmentCard extends StatelessWidget {
),
);
} else {
bookAppointmentsViewModel.getAppointmentNearestGate(projectID: patientAppointmentHistoryResponseModel.projectID, clinicID: patientAppointmentHistoryResponseModel.clinicID);
Navigator.of(context)
.push(
CustomPageRoute(

@ -1,6 +1,7 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/laser_body_parts.dart';
@ -81,7 +82,7 @@ class LaserAppointment extends StatelessWidget {
activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1),
tabs: [
CustomTabBarModel(null,LocaleKeys.malE.tr()),
CustomTabBarModel(null,LocaleKeys.female.tr()),
CustomTabBarModel(null, "Female".needTranslation),
],
onTabChange: (index) {
var viewmodel = context.read<BookAppointmentsViewModel>();

@ -50,146 +50,168 @@ class _ReviewAppointmentPageState extends State<ReviewAppointmentPage> {
Expanded(
child: CollapsingListView(
title: LocaleKeys.reviewAppointment.tr(context: context),
child: SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 24.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24.h),
LocaleKeys.docInfo.tr(context: context).toText16(isBold: true),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.h,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Image.network(
bookAppointmentsViewModel.selectedDoctor.doctorImageURL!,
width: 50.h,
height: 50.h,
fit: BoxFit.cover,
).circle(100),
SizedBox(width: 8.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.49,
child:
"${bookAppointmentsViewModel.selectedDoctor.doctorTitle} ${bookAppointmentsViewModel.selectedDoctor.name}".toString().toText16(isBold: true, maxlines: 1),
),
Image.network(
bookAppointmentsViewModel.selectedDoctor.nationalityFlagURL!,
width: 20.h,
height: 15.h,
fit: BoxFit.cover,
),
],
),
SizedBox(height: 2.h),
(bookAppointmentsViewModel.selectedDoctor.speciality!.isNotEmpty ? bookAppointmentsViewModel.selectedDoctor.speciality!.first : "")
.toString()
.toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor, maxLine: 1),
],
),
],
),
SizedBox(height: 12.h),
Wrap(
direction: Axis.horizontal,
spacing: 8.h,
runSpacing: 8.h,
children: [
AppCustomChipWidget(
labelText: "${LocaleKeys.clinic.tr(context: context)}: ${bookAppointmentsViewModel.selectedDoctor.clinicName}".needTranslation,
),
AppCustomChipWidget(
labelText: "${LocaleKeys.branch.tr(context: context)} ${bookAppointmentsViewModel.selectedDoctor.projectName}".needTranslation,
),
AppCustomChipWidget(
labelText:
"${LocaleKeys.date.tr(context: context)}: ${bookAppointmentsViewModel.isWaitingAppointmentSelected ? DateUtil.formatDateToDate(DateTime.now(), false) : bookAppointmentsViewModel.selectedAppointmentDate}"
.needTranslation,
),
AppCustomChipWidget(
labelText:
"${LocaleKeys.time.tr(context: context)}: ${bookAppointmentsViewModel.isWaitingAppointmentSelected ? "Waiting Appointment".needTranslation : bookAppointmentsViewModel.selectedAppointmentTime}"
.needTranslation,
),
],
),
],
child: Consumer<BookAppointmentsViewModel>(builder: (context, bookAppointmentsVM, child) {
return SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 24.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24.h),
LocaleKeys.docInfo.tr(context: context).toText16(isBold: true),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
hasShadow: false,
),
),
),
SizedBox(height: 24.h),
LocaleKeys.patientInfo.tr(context: context).toText16(isBold: true),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.h,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Row(
children: [
Image.asset(
appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.maleImg : AppAssets.femaleImg,
width: 52.h,
height: 52.h,
),
SizedBox(width: 8.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText16(isBold: true),
SizedBox(height: 8.h),
AppCustomChipWidget(labelText: "${appState.getAuthenticatedUser()!.age} Years Old"),
],
),
],
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Image.network(
bookAppointmentsViewModel.selectedDoctor.doctorImageURL!,
width: 50.h,
height: 50.h,
fit: BoxFit.cover,
).circle(100),
SizedBox(width: 8.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.49,
child: "${bookAppointmentsViewModel.selectedDoctor.doctorTitle} ${bookAppointmentsViewModel.selectedDoctor.name}"
.toString()
.toText16(isBold: true, maxlines: 1),
),
Image.network(
bookAppointmentsViewModel.selectedDoctor.nationalityFlagURL!,
width: 20.h,
height: 15.h,
fit: BoxFit.cover,
),
],
),
SizedBox(height: 2.h),
(bookAppointmentsViewModel.selectedDoctor.speciality!.isNotEmpty ? bookAppointmentsViewModel.selectedDoctor.speciality!.first : "")
.toString()
.toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor, maxLine: 1),
],
),
],
),
SizedBox(height: 12.h),
Wrap(
direction: Axis.horizontal,
spacing: 8.h,
runSpacing: 8.h,
children: [
AppCustomChipWidget(
labelText: "${LocaleKeys.clinic.tr(context: context)}: ${bookAppointmentsViewModel.selectedDoctor.clinicName}".needTranslation,
),
AppCustomChipWidget(
labelText: "${LocaleKeys.branch.tr(context: context)} ${bookAppointmentsViewModel.selectedDoctor.projectName}".needTranslation,
),
AppCustomChipWidget(
labelText:
"${LocaleKeys.date.tr(context: context)}: ${bookAppointmentsViewModel.isWaitingAppointmentSelected ? DateUtil.formatDateToDate(DateTime.now(), false) : bookAppointmentsViewModel.selectedAppointmentDate}"
.needTranslation,
),
AppCustomChipWidget(
labelText:
"${LocaleKeys.time.tr(context: context)}: ${bookAppointmentsViewModel.isWaitingAppointmentSelected ? "Waiting Appointment".needTranslation : bookAppointmentsViewModel.selectedAppointmentTime}"
.needTranslation,
),
],
),
],
),
),
),
),
SizedBox(height: 24.h),
"Hospital Information".needTranslation.toText16(isBold: true),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 12.h,
hasShadow: false,
SizedBox(height: 24.h),
LocaleKeys.patientInfo.tr(context: context).toText16(isBold: true),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Row(
children: [
Image.asset(
appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.maleImg : AppAssets.femaleImg,
width: 52.h,
height: 52.h,
),
SizedBox(width: 8.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText16(isBold: true),
SizedBox(height: 8.h),
AppCustomChipWidget(labelText: "${appState.getAuthenticatedUser()!.age} Years Old"),
],
),
],
),
),
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Row(
children: [
bookAppointmentsViewModel.selectedDoctor.projectName!.toText16(isBold: true),
],
SizedBox(height: 24.h),
"Hospital Information".needTranslation.toText16(isBold: true),
SizedBox(height: 16.h),
Container(
width: double.infinity,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
bookAppointmentsViewModel.selectedDoctor.projectName!.toText16(isBold: true),
SizedBox(height: 8.h),
Wrap(
direction: Axis.horizontal,
spacing: 8.w,
runSpacing: 8.h,
children: [
AppCustomChipWidget(
labelText: bookAppointmentsVM.isAppointmentNearestGateLoading
? "Floor: Ground Floor"
: "Floor: ${getIt.get<AppState>().isArabic() ? bookAppointmentsViewModel.appointmentNearestGateResponseModel!.clinicLocationN : bookAppointmentsViewModel.appointmentNearestGateResponseModel!.clinicLocation}",
).toShimmer2(isShow: bookAppointmentsVM.isAppointmentNearestGateLoading),
AppCustomChipWidget(
labelText:
"Nearest Gate: ${getIt.get<AppState>().isArabic() ? bookAppointmentsVM.appointmentNearestGateResponseModel!.nearestGateNumberN : bookAppointmentsVM.appointmentNearestGateResponseModel!.nearestGateNumber}")
.toShimmer2(isShow: bookAppointmentsVM.isAppointmentNearestGateLoading),
],
),
],
),
),
),
),
],
),
),
],
),
);
}),
),
),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.h,
borderRadius: 24.r,
hasShadow: true,
),
child: CustomButton(

@ -40,8 +40,14 @@ class _SelectDoctorPageState extends State<SelectDoctorPage> {
late AppState appState;
late BookAppointmentsViewModel bookAppointmentsViewModel;
// Scroll controller to control page scrolling when a group expands
late ScrollController _scrollController;
// Map of keys for each item to allow scrolling to them
final Map<int, GlobalKey> _itemKeys = {};
@override
void initState() {
_scrollController = ScrollController();
scheduleMicrotask(() {
bookAppointmentsViewModel.setIsNearestAppointmentSelected(false);
if (bookAppointmentsViewModel.isLiveCareSchedule) {
@ -59,6 +65,12 @@ class _SelectDoctorPageState extends State<SelectDoctorPage> {
super.initState();
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
bookAppointmentsViewModel = Provider.of<BookAppointmentsViewModel>(context, listen: false);
@ -68,6 +80,7 @@ class _SelectDoctorPageState extends State<SelectDoctorPage> {
body: CollapsingListView(
title: "Choose Doctor".needTranslation,
child: SingleChildScrollView(
controller: _scrollController,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 24.h),
child: Consumer<BookAppointmentsViewModel>(builder: (context, bookAppointmentsVM, child) {
@ -174,9 +187,7 @@ class _SelectDoctorPageState extends State<SelectDoctorPage> {
physics: NeverScrollableScrollPhysics(),
itemCount: bookAppointmentsVM.isDoctorsListLoading
? 5
: (bookAppointmentsVM.isLiveCareSchedule
? (bookAppointmentsVM.liveCareDoctorsList.isNotEmpty ? bookAppointmentsVM.liveCareDoctorsList.length : 1)
: (bookAppointmentsVM.doctorsList.isNotEmpty ? bookAppointmentsVM.doctorsList.length : 1)),
: (bookAppointmentsVM.doctorsListGrouped.isNotEmpty ? bookAppointmentsVM.doctorsListGrouped.length : 1),
itemBuilder: (context, index) {
final isExpanded = expandedIndex == index;
return bookAppointmentsVM.isDoctorsListLoading
@ -185,7 +196,7 @@ class _SelectDoctorPageState extends State<SelectDoctorPage> {
isLoading: true,
bookAppointmentsViewModel: bookAppointmentsViewModel,
)
: checkIsDoctorsListEmpty()
: bookAppointmentsVM.doctorsListGrouped.isEmpty
? Utils.getNoDataWidget(context, noDataText: "No Doctor found for selected criteria...".needTranslation)
: AnimationConfiguration.staggeredList(
position: index,
@ -194,6 +205,7 @@ class _SelectDoctorPageState extends State<SelectDoctorPage> {
verticalOffset: 100.0,
child: FadeInAnimation(
child: AnimatedContainer(
key: _itemKeys.putIfAbsent(index, () => GlobalKey()),
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
@ -202,34 +214,97 @@ class _SelectDoctorPageState extends State<SelectDoctorPage> {
setState(() {
expandedIndex = isExpanded ? null : index;
});
// After rebuild, ensure the expanded item is visible
WidgetsBinding.instance.addPostFrameCallback((_) {
final key = _itemKeys[index];
if (key != null && key.currentContext != null && expandedIndex == index) {
Scrollable.ensureVisible(
key.currentContext!,
duration: Duration(milliseconds: 350),
curve: Curves.easeInOut,
alignment: 0.1,
);
}
});
},
child: DoctorCard(
doctorsListResponseModel: bookAppointmentsVM.isLiveCareSchedule ? bookAppointmentsVM.liveCareDoctorsList[index] : bookAppointmentsVM.doctorsList[index],
isLoading: false,
bookAppointmentsViewModel: bookAppointmentsViewModel,
).onPress(() async {
bookAppointmentsVM
.setSelectedDoctor(bookAppointmentsVM.isLiveCareSchedule ? bookAppointmentsVM.liveCareDoctorsList[index] : bookAppointmentsVM.doctorsList[index]);
// bookAppointmentsVM.setSelectedDoctor(DoctorsListResponseModel());
LoaderBottomSheet.showLoader();
await bookAppointmentsVM.getDoctorProfile(onSuccess: (dynamic respData) {
LoaderBottomSheet.hideLoader();
Navigator.of(context).push(
CustomPageRoute(
page: DoctorProfilePage(),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Header row with count badge and expand/collapse icon
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CustomButton(
text: "${bookAppointmentsVM.doctorsListGrouped[index].length} ${'doctors'.needTranslation}",
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
Icon(isExpanded ? Icons.expand_less : Icons.expand_more),
],
),
);
}, onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
}),
SizedBox(height: 8.h),
// Clinic/Hospital name as group title
Text(
bookAppointmentsVM.isSortByClinic
? (bookAppointmentsVM.doctorsListGrouped[index].first.clinicName ?? 'Unknown')
: (bookAppointmentsVM.doctorsListGrouped[index].first.projectName ?? 'Unknown'),
style: TextStyle(fontSize: 16.h, fontWeight: FontWeight.w600),
overflow: TextOverflow.ellipsis,
),
// Expanded content - list of doctors in this group
AnimatedSwitcher(
duration: Duration(milliseconds: 400),
child: isExpanded
? Container(
key: ValueKey<int>(index),
padding: EdgeInsets.only(top: 12.h),
child: Column(
children: bookAppointmentsVM.doctorsListGrouped[index].map<Widget>((doctor) {
return Container(
margin: EdgeInsets.only(bottom: 12.h),
child: DoctorCard(
doctorsListResponseModel: doctor,
isLoading: false,
bookAppointmentsViewModel: bookAppointmentsViewModel,
).onPress(() async {
bookAppointmentsVM.setSelectedDoctor(doctor);
LoaderBottomSheet.showLoader();
await bookAppointmentsVM.getDoctorProfile(onSuccess: (dynamic respData) {
LoaderBottomSheet.hideLoader();
Navigator.of(context).push(
CustomPageRoute(
page: DoctorProfilePage(),
),
);
}, onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
}),
);
}).toList(),
),
)
: SizedBox.shrink(),
),
],
),
),
),
),
),

@ -142,6 +142,7 @@ class WaitingAppointmentOnlineCheckinSheet extends StatelessWidget {
bookAppointmentsViewModel.waitingAppointmentProjectID,
onSuccess: (value) {
LoaderBottomSheet.hideLoader();
bookAppointmentsViewModel.getAppointmentNearestGate(projectID: bookAppointmentsViewModel.waitingAppointmentProjectID, clinicID: bookAppointmentsViewModel.waitingAppointmentDoctor!.clinicID!);
bookAppointmentsViewModel.setIsWaitingAppointmentSelected(true);
Navigator.of(context).push(
CustomPageRoute(

@ -185,6 +185,7 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
),
);
} else {
bookAppointmentsViewModel.getAppointmentNearestGate(projectID: bookAppointmentsViewModel.selectedDoctor.projectID!, clinicID: bookAppointmentsViewModel.selectedDoctor.clinicID!);
bookAppointmentsViewModel.setSelectedAppointmentDateTime(selectedDate, selectedTime);
Navigator.of(context).pop();
Navigator.of(context).push(

@ -0,0 +1,283 @@
import 'dart:async';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:provider/provider.dart';
import 'covid_19_questionnaire.dart';
class Covid19LandingPage extends StatefulWidget {
const Covid19LandingPage({super.key});
@override
State<Covid19LandingPage> createState() => _Covid19LandingPageState();
}
class _Covid19LandingPageState extends State<Covid19LandingPage> {
late HabibWalletViewModel habibWalletVM;
int? _selectedBranchIndex;
@override
void initState() {
habibWalletVM = Provider.of<HabibWalletViewModel>(context, listen: false);
scheduleMicrotask(() {
getProjectList();
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: Column(
children: [
Expanded(
child: CollapsingListView(
title: "COVID-19",
child: Padding(
padding: EdgeInsets.all(24.w),
child: SingleChildScrollView(
child: Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(20.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Get the results in Few Hours"
.toText18(
color: AppColors.textColor,
weight: FontWeight.w600,
),
SizedBox(height: 16.h),
LocaleKeys.covid_info
.tr()
.toText14(
color: AppColors.greyTextColor,
weight: FontWeight.w400,
height: 1.6,
),
],
),
),
),
),
),
),
),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
// borderRadius: 24.r,
hasShadow: true,
customBorder: BorderRadius.only(topLeft:Radius.circular(24.r) , topRight:Radius.circular(24.r))
),
child: SizedBox(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CustomButton(
text: "SelectLocation".needTranslation,
onPressed: () {
_showBranchBottomSheet(context);
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 16.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 50.h,
iconSize: 18.h,
).paddingSymmetrical(16.h, 24.w),
],
),
),
),
],
));
}
void _showBranchBottomSheet(BuildContext context, ) {
// Set first branch as selected by default
setState(() {
_selectedBranchIndex = 0;
});
showCommonBottomSheet(
context,
title: "Select Branch".needTranslation,
height: ResponsiveExtension.screenHeight * 0.651,
child: StatefulBuilder(
builder: (context, setBottomSheetState) {
return Consumer<HabibWalletViewModel>(
builder: (context, habibWalletVM, child) {
final hospitals = habibWalletVM.advancePaymentHospitals;
if (hospitals.isEmpty) {
return const Center(
child: Padding(
padding: EdgeInsets.all(16.0),
child: Text('No branches available'),
),
);
}
return Column(
children: [
Expanded(
child:Container(
margin: EdgeInsets.only(left: 16.w, right: 16.w, top: 12.h, bottom: 24.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
hasShadow: true,
customBorder: BorderRadius.only(
topLeft: Radius.circular(24.r),
topRight: Radius.circular(24.r),
),
), child: ListView.separated(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
itemBuilder: (context, index) {
final branch = hospitals[index];
final isSelected = _selectedBranchIndex == index;
return GestureDetector(
onTap: () {
setBottomSheetState(() {
_selectedBranchIndex = index;
});
setState(() {
_selectedBranchIndex = index;
});
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h),
child: Row(
children: [
// Radio button
Container(
width: 20.w,
height: 20.h,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: isSelected
? AppColors.primaryRedColor
: AppColors.greyTextColor.withValues(alpha: 0.3),
width: 2,
),
),
child: isSelected
? Center(
child: Container(
width: 10.w,
height: 10.h,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: AppColors.primaryRedColor,
),
),
)
: null,
),
SizedBox(width: 12.w),
// Branch details
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 4.h),
(branch.desciption ?? 'Unknown').toText14(
color: AppColors.textColor,
weight: FontWeight.w600,
),
],
),
),
// Location icon
],
),
),
);
},
separatorBuilder: (context, index) => SizedBox(height: 12.h),
itemCount: hospitals.length,
)),
),
// Next button
Container(
padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 16.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
hasShadow: true,
customBorder: BorderRadius.only(
topLeft: Radius.circular(24.r),
topRight: Radius.circular(24.r),
),
),
child: SafeArea(
top: false,
child: CustomButton(
text: "Next".needTranslation,
onPressed: (){
Navigator.of(context)
.push(
CustomPageRoute(
page: Covid19Questionnaire(selectedHospital: hospitals[_selectedBranchIndex!],),
),
);
},
backgroundColor: _selectedBranchIndex != null
? AppColors.primaryRedColor
: AppColors.greyTextColor.withValues(alpha: 0.3),
borderColor: _selectedBranchIndex != null
? AppColors.primaryRedColor
: AppColors.greyTextColor.withValues(alpha: 0.3),
textColor: AppColors.whiteColor,
fontSize: 16.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
height: 56.h,
),
),
),
],
);
},
);
},
),
);
}
getProjectList() async{
await habibWalletVM.getProjectsList();
}
}

@ -0,0 +1,132 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_view_model.dart';
import 'package:hmg_patient_app_new/features/hmg_services/models/ui_models/covid_questionnare_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/CustomSwitch.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:provider/provider.dart';
class Covid19Questionnaire extends StatefulWidget {
final HospitalsModel selectedHospital;
const Covid19Questionnaire({super.key, required this.selectedHospital});
@override
State<Covid19Questionnaire> createState() => _Covid19QuestionnaireState();
}
class _Covid19QuestionnaireState extends State<Covid19Questionnaire> {
late HmgServicesViewModel hmgServicesViewModel;
List<CovidQuestionnaireModel> qaList = [];
@override
void initState() {
hmgServicesViewModel = Provider.of<HmgServicesViewModel>(context, listen: false);
scheduleMicrotask(() {
setState(() {
qaList = hmgServicesViewModel.getQuestionsFromJson();
});
});
super.initState();
}
void _toggleAnswer(int index, bool value) {
setState(() {
qaList[index].ans = value ? 1 : 0;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: Column(children: [
Expanded(
child: CollapsingListView(
title: "COVID-19",
child: Padding(
padding: EdgeInsets.all(24.w),
child: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(20.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Please answer below questionnaire:".toText14(
color: AppColors.textColor,
weight: FontWeight.w500,
),
SizedBox(height: 20.h),
// Question list
ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: qaList.length,
separatorBuilder: (context, index) => SizedBox(height: 16.h),
itemBuilder: (context, index) {
final question = qaList[index];
final isAnswerYes = question.ans == 1;
return Row(
children: [
Expanded(
child: (question.questionEn ?? '').toText14(
color: AppColors.textColor,
weight: FontWeight.w400,
),
),
SizedBox(width: 12.w),
CustomSwitch(
value: isAnswerYes,
onChanged: (value) => _toggleAnswer(index, value),
),
],
);
},
),
],
),
),
),
),
),
SizedBox(height: 16.h),
// Next button
CustomButton(
text: "Next".needTranslation,
onPressed: () {
// Handle next action
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 16.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
height: 56.h,
),
],
),
),
),
),
]));
}
}

@ -232,7 +232,6 @@ class _OtherDetailsStepState extends State<OtherDetailsStep> {
}
void _showBranchBottomSheet(BuildContext context, ReferralFormManager formManager) {
final habibWalletVM = context.read<HabibWalletViewModel>();
showCommonBottomSheetWithoutHeight(
context,

@ -49,28 +49,41 @@ class HealthCalcualtorViewModel extends ChangeNotifier {
String? get mmolValue => _mmolValue;
// Store the original entered value and which field it was entered in
String? _originalValue;
String _originalUnit = 'mg/dL'; // which field the original value was entered in
bool _isSwapped = false; // toggle state for switch
String _activeUnit = 'mg/dL'; // current source unit
String get activeUnit => _activeUnit;
// ================== BLOOD CHOLESTEROL ==================
String? _cholMgdlValue;
String? _cholMmolValue;
String? _cholOriginalValue;
String _cholOriginalUnit = 'mg/dL';
bool _cholIsSwapped = false;
String _cholActiveUnit = 'mg/dL';
String? get cholMgdlValue => _cholMgdlValue;
String? get cholMmolValue => _cholMmolValue;
String get cholActiveUnit => _cholActiveUnit;
// ================== TRIGLYCERIDES ==================
String? _triMgdlValue;
String? _triMmolValue;
String? _triOriginalValue;
String _triOriginalUnit = 'mg/dL';
bool _triIsSwapped = false;
String _triActiveUnit = 'mg/dL';
String? get triMgdlValue => _triMgdlValue;
String? get triMmolValue => _triMmolValue;
String get triActiveUnit => _triActiveUnit;
String get triActiveUnit => _triActiveUnit;
// Generic helpers
@ -726,13 +739,10 @@ class HealthCalcualtorViewModel extends ChangeNotifier {
final DateTime firstTrimesterStart = lmp;
final DateTime firstTrimesterEnd = lmp.add(const Duration(days: 83));
final DateTime secondTrimesterStart =
firstTrimesterEnd.add(const Duration(days: 1));
final DateTime secondTrimesterEnd =
lmp.add(const Duration(days: 195));
final DateTime secondTrimesterStart = firstTrimesterEnd.add(const Duration(days: 1));
final DateTime secondTrimesterEnd = lmp.add(const Duration(days: 195));
final DateTime thirdTrimesterStart =
secondTrimesterEnd.add(const Duration(days: 1));
final DateTime thirdTrimesterStart = secondTrimesterEnd.add(const Duration(days: 1));
final DateTime thirdTrimesterEnd = dueDate;
deliveryResult = {
@ -741,7 +751,7 @@ class HealthCalcualtorViewModel extends ChangeNotifier {
// Raw DateTime (useful for logic/UI)
'lmpDateTime': lmp,
'dueDateTime': dueDate,
'dueDateDay' : _formatDateWithDayName(dueDate),
'dueDateDay': _formatDateWithDayName(dueDate),
// Trimester info
'firstTrimester': {
'start': _formatDate(firstTrimesterStart),
@ -769,7 +779,6 @@ class HealthCalcualtorViewModel extends ChangeNotifier {
notifyListeners();
}
// Blood sugar conversions
void calculateBloodSugar({required String valueText, required String unit}) {
if (valueText.trim().isEmpty) {
@ -838,8 +847,6 @@ class HealthCalcualtorViewModel extends ChangeNotifier {
'dietType': dietType
};
void onBloodSugarChanged(String value, String fromUnit) {
_activeUnit = fromUnit;
@ -855,47 +862,105 @@ class HealthCalcualtorViewModel extends ChangeNotifier {
if (fromUnit == 'mg/dL') {
_mgdlValue = value;
_mmolValue = (parsed / 18.0182).toStringAsFixed(1);
_mmolValue = (parsed / 18.0182).toStringAsFixed(3);
} else {
_mmolValue = value;
_mgdlValue = (parsed * 18.0182).toStringAsFixed(0);
_mgdlValue = (parsed * 18.0182).toStringAsFixed(3);
}
notifyListeners();
}
void switchBloodSugarValues() {
if (_activeUnit == 'mg/dL') {
final mmol = double.tryParse(_mmolValue ?? '');
if (mmol == null) return;
void onBloodSugarMgdlChanged(String value) {
_mgdlValue = value;
_originalValue = value;
_originalUnit = 'mg/dL';
_isSwapped = false;
_activeUnit = 'mg/dL';
if (value.isEmpty) {
_mmolValue = null;
_originalValue = null;
notifyListeners();
return;
}
_activeUnit = 'mmol/L';
final parsed = double.tryParse(value);
if (parsed == null) return;
// mmol stays as source
_mmolValue = mmol.toStringAsFixed(1);
_mgdlValue = (mmol * 18.0182).toStringAsFixed(0);
} else {
final mgdl = double.tryParse(_mgdlValue ?? '');
if (mgdl == null) return;
// Convert mg/dL to mmol/L
_mmolValue = (parsed / 18.0182).toStringAsFixed(3);
notifyListeners();
}
_activeUnit = 'mg/dL';
void onBloodSugarMmolChanged(String value) {
_mmolValue = value;
_originalValue = value;
_originalUnit = 'mmol/L';
_isSwapped = false;
_activeUnit = 'mmol/L';
// mg/dL stays as source
_mgdlValue = mgdl.toStringAsFixed(0);
_mmolValue = (mgdl / 18.0182).toStringAsFixed(1);
if (value.isEmpty) {
_mgdlValue = null;
_originalValue = null;
notifyListeners();
return;
}
final parsed = double.tryParse(value);
if (parsed == null) return;
// Convert mmol/L to mg/dL
_mgdlValue = (parsed * 18.0182).toStringAsFixed(3);
notifyListeners();
}
void switchBloodSugarValues() {
// Toggle between two states using the original entered value
if (_originalValue == null || _originalValue!.isEmpty) return;
final originalParsed = double.tryParse(_originalValue!);
if (originalParsed == null) return;
_isSwapped = !_isSwapped;
if (_originalUnit == 'mg/dL') {
if (_isSwapped) {
// Original was in mg/dL, now treat it as mmol/L
_mmolValue = _originalValue; // Keep original format
_mgdlValue = (originalParsed * 18.0182).toStringAsFixed(3);
} else {
// Back to original: value in mg/dL
_mgdlValue = _originalValue; // Keep original format
_mmolValue = (originalParsed / 18.0182).toStringAsFixed(3);
}
} else {
// Original was in mmol/L
if (_isSwapped) {
// Now treat it as mg/dL
_mgdlValue = _originalValue; // Keep original format
_mmolValue = (originalParsed / 18.0182).toStringAsFixed(3);
} else {
// Back to original: value in mmol/L
_mmolValue = _originalValue; // Keep original format
_mgdlValue = (originalParsed * 18.0182).toStringAsFixed(3);
}
}
notifyListeners();
}
// --- NEW: Method to clear the values ---
void clearBloodSugar() {
_mgdlValue = null;
_mmolValue = null;
_originalValue = null;
_originalUnit = 'mg/dL';
_isSwapped = false;
_activeUnit = 'mg/dL';
notifyListeners();
}
void onBloodCholesterolChanged(String value, String fromUnit) {
_cholActiveUnit = fromUnit;
@ -911,47 +976,104 @@ class HealthCalcualtorViewModel extends ChangeNotifier {
if (fromUnit == 'mg/dL') {
_cholMgdlValue = value;
_cholMmolValue = (parsed / 38.67).toStringAsFixed(2);
_cholMmolValue = (parsed / 38.67).toStringAsFixed(3);
} else {
_cholMmolValue = value;
_cholMgdlValue = (parsed * 38.67).toStringAsFixed(0);
_cholMgdlValue = (parsed * 38.67).toStringAsFixed(3);
}
notifyListeners();
}
void switchBloodCholesterolValues() {
if (_cholActiveUnit == 'mg/dL') {
final mmol = double.tryParse(_cholMmolValue ?? '');
if (mmol == null) return;
void onCholesterolMgdlChanged(String value) {
_cholMgdlValue = value;
_cholOriginalValue = value;
_cholOriginalUnit = 'mg/dL';
_cholIsSwapped = false;
_cholActiveUnit = 'mg/dL';
if (value.isEmpty) {
_cholMmolValue = null;
_cholOriginalValue = null;
notifyListeners();
return;
}
_cholActiveUnit = 'mmol/L';
final parsed = double.tryParse(value);
if (parsed == null) return;
_cholMmolValue = mmol.toStringAsFixed(2);
_cholMgdlValue = (mmol * 38.67).toStringAsFixed(0);
} else {
final mgdl = double.tryParse(_cholMgdlValue ?? '');
if (mgdl == null) return;
// Convert mg/dL to mmol/L
_cholMmolValue = (parsed / 38.67).toStringAsFixed(3);
notifyListeners();
}
_cholActiveUnit = 'mg/dL';
void onCholesterolMmolChanged(String value) {
_cholMmolValue = value;
_cholOriginalValue = value;
_cholOriginalUnit = 'mmol/L';
_cholIsSwapped = false;
_cholActiveUnit = 'mmol/L';
_cholMgdlValue = mgdl.toStringAsFixed(0);
_cholMmolValue = (mgdl / 38.67).toStringAsFixed(2);
if (value.isEmpty) {
_cholMgdlValue = null;
_cholOriginalValue = null;
notifyListeners();
return;
}
final parsed = double.tryParse(value);
if (parsed == null) return;
// Convert mmol/L to mg/dL
_cholMgdlValue = (parsed * 38.67).toStringAsFixed(3);
notifyListeners();
}
void switchBloodCholesterolValues() {
// Toggle between two states using the original entered value
if (_cholOriginalValue == null || _cholOriginalValue!.isEmpty) return;
final originalParsed = double.tryParse(_cholOriginalValue!);
if (originalParsed == null) return;
_cholIsSwapped = !_cholIsSwapped;
if (_cholOriginalUnit == 'mg/dL') {
if (_cholIsSwapped) {
// Original was in mg/dL, now treat it as mmol/L
_cholMmolValue = _cholOriginalValue; // Keep original format
_cholMgdlValue = (originalParsed * 38.67).toStringAsFixed(3);
} else {
// Back to original: value in mg/dL
_cholMgdlValue = _cholOriginalValue; // Keep original format
_cholMmolValue = (originalParsed / 38.67).toStringAsFixed(3);
}
} else {
// Original was in mmol/L
if (_cholIsSwapped) {
// Now treat it as mg/dL
_cholMgdlValue = _cholOriginalValue; // Keep original format
_cholMmolValue = (originalParsed / 38.67).toStringAsFixed(3);
} else {
// Back to original: value in mmol/L
_cholMmolValue = _cholOriginalValue; // Keep original format
_cholMgdlValue = (originalParsed * 38.67).toStringAsFixed(3);
}
}
notifyListeners();
}
void clearBloodCholesterol() {
_cholMgdlValue = null;
_cholMmolValue = null;
_cholOriginalValue = null;
_cholOriginalUnit = 'mg/dL';
_cholIsSwapped = false;
_cholActiveUnit = 'mg/dL';
notifyListeners();
}
void onTriglyceridesChanged(String value, String fromUnit) {
_triActiveUnit = fromUnit;
@ -967,30 +1089,89 @@ class HealthCalcualtorViewModel extends ChangeNotifier {
if (fromUnit == 'mg/dL') {
_triMgdlValue = value;
_triMmolValue = (parsed / 88.57).toStringAsFixed(2);
_triMmolValue = (parsed / 88.57).toStringAsFixed(3);
} else {
_triMmolValue = value;
_triMgdlValue = (parsed * 88.57).toStringAsFixed(0);
_triMgdlValue = (parsed * 88.57).toStringAsFixed(3);
}
notifyListeners();
}
void onTriglyceridesMgdlChanged(String value) {
_triMgdlValue = value;
_triOriginalValue = value;
_triOriginalUnit = 'mg/dL';
_triIsSwapped = false;
_triActiveUnit = 'mg/dL';
if (value.isEmpty) {
_triMmolValue = null;
_triOriginalValue = null;
notifyListeners();
return;
}
final parsed = double.tryParse(value);
if (parsed == null) return;
// Convert mg/dL to mmol/L
_triMmolValue = (parsed / 88.57).toStringAsFixed(3);
notifyListeners();
}
void onTriglyceridesMmolChanged(String value) {
_triMmolValue = value;
_triOriginalValue = value;
_triOriginalUnit = 'mmol/L';
_triIsSwapped = false;
_triActiveUnit = 'mmol/L';
if (value.isEmpty) {
_triMgdlValue = null;
_triOriginalValue = null;
notifyListeners();
return;
}
final parsed = double.tryParse(value);
if (parsed == null) return;
// Convert mmol/L to mg/dL
_triMgdlValue = (parsed * 88.57).toStringAsFixed(3);
notifyListeners();
}
void switchTriglyceridesValues() {
if (_triActiveUnit == 'mg/dL') {
final mmol = double.tryParse(_triMmolValue ?? '');
if (mmol == null) return;
// Toggle between two states using the original entered value
if (_triOriginalValue == null || _triOriginalValue!.isEmpty) return;
_triActiveUnit = 'mmol/L';
_triMmolValue = mmol.toStringAsFixed(2);
_triMgdlValue = (mmol * 88.57).toStringAsFixed(0);
} else {
final mgdl = double.tryParse(_triMgdlValue ?? '');
if (mgdl == null) return;
final originalParsed = double.tryParse(_triOriginalValue!);
if (originalParsed == null) return;
_triIsSwapped = !_triIsSwapped;
_triActiveUnit = 'mg/dL';
_triMgdlValue = mgdl.toStringAsFixed(0);
_triMmolValue = (mgdl / 88.57).toStringAsFixed(2);
if (_triOriginalUnit == 'mg/dL') {
if (_triIsSwapped) {
// Original was in mg/dL, now treat it as mmol/L
_triMmolValue = _triOriginalValue; // Keep original format
_triMgdlValue = (originalParsed * 88.57).toStringAsFixed(3);
} else {
// Back to original: value in mg/dL
_triMgdlValue = _triOriginalValue; // Keep original format
_triMmolValue = (originalParsed / 88.57).toStringAsFixed(3);
}
} else {
// Original was in mmol/L
if (_triIsSwapped) {
// Now treat it as mg/dL
_triMgdlValue = _triOriginalValue; // Keep original format
_triMmolValue = (originalParsed / 88.57).toStringAsFixed(3);
} else {
// Back to original: value in mmol/L
_triMmolValue = _triOriginalValue; // Keep original format
_triMgdlValue = (originalParsed * 88.57).toStringAsFixed(3);
}
}
notifyListeners();
@ -999,10 +1180,10 @@ class HealthCalcualtorViewModel extends ChangeNotifier {
void clearTriglycerides() {
_triMgdlValue = null;
_triMmolValue = null;
_triOriginalValue = null;
_triOriginalUnit = 'mg/dL';
_triIsSwapped = false;
_triActiveUnit = 'mg/dL';
notifyListeners();
}
}

@ -52,14 +52,15 @@ class _BloodCholesterolWidgetState extends State<BloodCholesterolWidget> {
final mgdlText = provider.cholMgdlValue ?? '';
final mmolText = provider.cholMmolValue ?? '';
if (_mgdlController.text != mgdlText) {
// Only update if focus is not on this field (to avoid cursor jumping)
if (!_mgdlFocus.hasFocus && _mgdlController.text != mgdlText) {
_mgdlController.text = mgdlText;
_mgdlController.selection = TextSelection.fromPosition(
TextPosition(offset: _mgdlController.text.length),
);
}
if (_mmolController.text != mmolText) {
if (!_mmolFocus.hasFocus && _mmolController.text != mmolText) {
_mmolController.text = mmolText;
_mmolController.selection = TextSelection.fromPosition(
TextPosition(offset: _mmolController.text.length),
@ -81,7 +82,7 @@ class _BloodCholesterolWidgetState extends State<BloodCholesterolWidget> {
focusNode: _mgdlFocus,
onChanged: (value) {
if (_isProgrammaticChange) return;
provider.onBloodCholesterolChanged(value, 'mg/dL');
provider.onCholesterolMgdlChanged(value);
},
).paddingOnly(top: 16.h),
Row(
@ -96,24 +97,21 @@ class _BloodCholesterolWidgetState extends State<BloodCholesterolWidget> {
width: 40.h,
height: 40.h,
).onPress(() {
// Unfocus both fields before switching
_mgdlFocus.unfocus();
_mmolFocus.unfocus();
provider.switchBloodCholesterolValues();
if (provider.cholActiveUnit == 'mg/dL') {
_mgdlFocus.requestFocus();
} else {
_mmolFocus.requestFocus();
}
}),
],
),
_buildInputField(
label: "MMOL/L",
hint: "6.7",
hint: "3.1",
controller: _mmolController,
focusNode: _mmolFocus,
onChanged: (value) {
if (_isProgrammaticChange) return;
provider.onBloodCholesterolChanged(value, 'mmol/L');
provider.onCholesterolMmolChanged(value);
},
).paddingOnly(bottom: 16.h),
const Divider(height: 1, color: Color(0xFFEEEEEE)),

@ -51,14 +51,16 @@ class _BloodSugarWidgetState extends State<BloodSugarWidget> {
_isProgrammaticChange = true;
final mgdlText = provider.mgdlValue ?? '';
final mmolText = provider.mmolValue ?? '';
if (_mgdlController.text != mgdlText) {
// Only update if focus is not on this field (to avoid cursor jumping)
if (!_mgdlFocus.hasFocus && _mgdlController.text != mgdlText) {
_mgdlController.text = mgdlText;
_mgdlController.selection = TextSelection.fromPosition(
TextPosition(offset: _mgdlController.text.length),
);
}
if (_mmolController.text != mmolText) {
if (!_mmolFocus.hasFocus && _mmolController.text != mmolText) {
_mmolController.text = mmolText;
_mmolController.selection = TextSelection.fromPosition(
TextPosition(offset: _mmolController.text.length),
@ -84,7 +86,7 @@ class _BloodSugarWidgetState extends State<BloodSugarWidget> {
focusNode: _mgdlFocus,
onChanged: (value) {
if (_isProgrammaticChange) return;
provider.onBloodSugarChanged(value, 'mg/dL');
provider.onBloodSugarMgdlChanged(value);
},
).paddingOnly(top: 16.h),
Row(
@ -99,12 +101,10 @@ class _BloodSugarWidgetState extends State<BloodSugarWidget> {
width: 40.h,
height: 40.h,
).onPress(() {
// Unfocus both fields before switching
_mgdlFocus.unfocus();
_mmolFocus.unfocus();
provider.switchBloodSugarValues();
if (provider.activeUnit == 'mg/dL') {
_mgdlFocus.requestFocus();
} else {
_mmolFocus.requestFocus();
}
}),
],
),
@ -115,8 +115,7 @@ class _BloodSugarWidgetState extends State<BloodSugarWidget> {
focusNode: _mmolFocus,
onChanged: (value) {
if (_isProgrammaticChange) return;
provider.onBloodSugarChanged(value, 'mmol/L');
provider.onBloodSugarMmolChanged(value);
},
).paddingOnly(bottom: 16.h),
const Divider(height: 1, color: Color(0xFFEEEEEE)),

@ -53,14 +53,15 @@ class _TriglyceridesWidgetState extends State<TriglyceridesWidget> {
final mgdlText = provider.triMgdlValue ?? '';
final mmolText = provider.triMmolValue ?? '';
if (_mgdlController.text != mgdlText) {
// Only update if focus is not on this field (to avoid cursor jumping)
if (!_mgdlFocus.hasFocus && _mgdlController.text != mgdlText) {
_mgdlController.text = mgdlText;
_mgdlController.selection = TextSelection.fromPosition(
TextPosition(offset: _mgdlController.text.length),
);
}
if (_mmolController.text != mmolText) {
if (!_mmolFocus.hasFocus && _mmolController.text != mmolText) {
_mmolController.text = mmolText;
_mmolController.selection = TextSelection.fromPosition(
TextPosition(offset: _mmolController.text.length),
@ -85,7 +86,7 @@ class _TriglyceridesWidgetState extends State<TriglyceridesWidget> {
focusNode: _mgdlFocus,
onChanged: (value) {
if (_isProgrammaticChange) return;
provider.onTriglyceridesChanged(value, 'mg/dL');
provider.onTriglyceridesMgdlChanged(value);
},
).paddingOnly(top: 16.h),
@ -101,13 +102,10 @@ class _TriglyceridesWidgetState extends State<TriglyceridesWidget> {
width: 40.h,
height: 40.h,
).onPress(() {
// Unfocus both fields before switching
_mgdlFocus.unfocus();
_mmolFocus.unfocus();
provider.switchTriglyceridesValues();
if (provider.triActiveUnit == 'mg/dL') {
_mgdlFocus.requestFocus();
} else {
_mmolFocus.requestFocus();
}
}),
],
),
@ -119,7 +117,7 @@ class _TriglyceridesWidgetState extends State<TriglyceridesWidget> {
focusNode: _mmolFocus,
onChanged: (value) {
if (_isProgrammaticChange) return;
provider.onTriglyceridesChanged(value, 'mmol/L');
provider.onTriglyceridesMmolChanged(value);
},
).paddingOnly(bottom: 16.h),
@ -170,7 +168,6 @@ class _TriglyceridesWidgetState extends State<TriglyceridesWidget> {
child: TextField(
controller: controller,
focusNode: focusNode,
keyboardType:
const TextInputType.numberWithOptions(decimal: true),
onChanged: onChanged,
@ -185,6 +182,7 @@ class _TriglyceridesWidgetState extends State<TriglyceridesWidget> {
style: TextStyle(
fontSize: 32.f,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
),

@ -100,6 +100,16 @@ class ServicesPage extends StatelessWidget {
LoaderBottomSheet.hideLoader();
});
}),
HmgServicesComponentModel(
11,
"Covid 19 Test".needTranslation,
"".needTranslation,
AppAssets.covid19icon,
bgColor: AppColors.covid29Color,
true,
route: AppRoutes.covid19Test,
)
// HmgServicesComponentModel(
// 3,
// "Home Health Care".needTranslation,

@ -120,9 +120,7 @@ class _AlphabetScrollPageState extends State<AlphabeticScroll> {
@override
Widget build(BuildContext context) {
return
SizedBox(
return SizedBox(
width: MediaQuery.sizeOf(context).width,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start, // Add this

File diff suppressed because one or more lines are too long

@ -51,39 +51,39 @@ class _MedicalReportsPageState extends State<MedicalReportsPage> {
children: [
SizedBox(height: 16.h),
// Status filter tabs
Row(
children: [
CustomButton(
text: LocaleKeys.byClinic.tr(context: context),
onPressed: () {
medicalFileVM.setIsMedicalReportsSortByClinic(true);
},
backgroundColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor,
borderColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2),
textColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor,
fontSize: 12,
fontWeight: FontWeight.w500,
borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
),
SizedBox(width: 8.h),
CustomButton(
text: LocaleKeys.byHospital.tr(context: context),
onPressed: () {
medicalFileVM.setIsMedicalReportsSortByClinic(false);
},
backgroundColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor,
borderColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.textColor.withValues(alpha: 0.2) : AppColors.primaryRedColor,
textColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor,
fontSize: 12,
fontWeight: FontWeight.w500,
borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
),
],
).paddingSymmetrical(24.h, 0.h),
// Row(
// children: [
// CustomButton(
// text: LocaleKeys.byClinic.tr(context: context),
// onPressed: () {
// medicalFileVM.setIsMedicalReportsSortByClinic(true);
// },
// backgroundColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor,
// borderColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2),
// textColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor,
// fontSize: 12,
// fontWeight: FontWeight.w500,
// borderRadius: 10,
// padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
// height: 40.h,
// ),
// SizedBox(width: 8.h),
// CustomButton(
// text: LocaleKeys.byHospital.tr(context: context),
// onPressed: () {
// medicalFileVM.setIsMedicalReportsSortByClinic(false);
// },
// backgroundColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor,
// borderColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.textColor.withValues(alpha: 0.2) : AppColors.primaryRedColor,
// textColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor,
// fontSize: 12,
// fontWeight: FontWeight.w500,
// borderRadius: 10,
// padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
// height: 40.h,
// ),
// ],
// ).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 20.h),
Row(
children: [

@ -26,6 +26,8 @@ import 'package:hmg_patient_app_new/presentation/water_monitor/water_consumption
import 'package:hmg_patient_app_new/presentation/water_monitor/water_monitor_settings_screen.dart';
import 'package:hmg_patient_app_new/splashPage.dart';
import '../presentation/covid19test/covid19_landing_page.dart';
class AppRoutes {
static const String initialRoute = '/initialRoute';
static const String loginScreen = '/loginScreen';
@ -42,7 +44,7 @@ class AppRoutes {
static const String bloodDonationPage = '/bloodDonationPage';
static const String smartWatches = '/smartWatches';
static const String huaweiHealthExample = '/huaweiHealthExample';
static const String covid19Test = '/covid19Test';
//appointments
static const String bookAppointmentPage = '/bookAppointmentPage';
@ -85,6 +87,8 @@ class AppRoutes {
userInfoFlowManager: (context) => UserInfoFlowManager(),
smartWatches: (context) => SmartwatchInstructionsPage(),
huaweiHealthExample: (context) => HuaweiHealthExample(),
covid19Test: (context) => Covid19LandingPage(),
//
waterConsumptionScreen: (context) => WaterConsumptionScreen(),
waterMonitorSettingsScreen: (context) => WaterMonitorSettingsScreen(),
healthCalculatorsPage: (context) => HealthCalculatorsPage(type: HealthCalConEnum.calculator),

@ -108,4 +108,5 @@ class AppColors {
// Shimmer
static const Color shimmerBaseColor = Color(0xFFE0E0E0);
static const Color shimmerHighlightColor = Color(0xFFF5F5F5);
static const Color covid29Color = Color(0xff2563EB);
}

@ -108,11 +108,11 @@ class ButtonSheetContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// SizedBox(
// height: 20.h,
// ),
SizedBox(
height: 20.h,
),
// Center(
// child: Container(
// margin: const EdgeInsets.only(top: 18, bottom: 12),
@ -127,10 +127,9 @@ class ButtonSheetContent extends StatelessWidget {
// Close button
isCloseButtonVisible && isFullScreen
? Column(children: [
SizedBox(
height: 40.h,
),
? Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: EdgeInsets.symmetric(
horizontal: 16,
@ -145,7 +144,7 @@ class ButtonSheetContent extends StatelessWidget {
isFullScreen
? Column(
children: [
SizedBox(height: 20.h),
// SizedBox(height: 20.h),
Padding(padding: EdgeInsets.symmetric(horizontal: 16.h), child: title.toText24(isBold: true)),
SizedBox(height: 16.h),
],

Loading…
Cancel
Save