diff --git a/.gitignore b/.gitignore
index 3ada50c..79c113f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,4 +43,3 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release
-/android/
diff --git a/assets/images/svg/cancel_circle.svg b/assets/images/svg/cancel_circle.svg
new file mode 100644
index 0000000..3ceda6f
--- /dev/null
+++ b/assets/images/svg/cancel_circle.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/close_bottom_sheet_icon.svg b/assets/images/svg/close_bottom_sheet_icon.svg
new file mode 100644
index 0000000..599ce85
--- /dev/null
+++ b/assets/images/svg/close_bottom_sheet_icon.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/svg/insurance_history_icon.svg b/assets/images/svg/insurance_history_icon.svg
new file mode 100644
index 0000000..4ae2a1c
--- /dev/null
+++ b/assets/images/svg/insurance_history_icon.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/svg/prescription_reminder_icon.svg b/assets/images/svg/prescription_reminder_icon.svg
new file mode 100644
index 0000000..3a854c3
--- /dev/null
+++ b/assets/images/svg/prescription_reminder_icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/svg/update_insurance_card.svg b/assets/images/svg/update_insurance_card.svg
new file mode 100644
index 0000000..9b21aab
--- /dev/null
+++ b/assets/images/svg/update_insurance_card.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json
index 2c7ac9b..ede5e64 100644
--- a/assets/langs/ar-SA.json
+++ b/assets/langs/ar-SA.json
@@ -782,6 +782,9 @@
"resultsPending": "النتائج معلقة",
"resultsAvailable": "النتائج متاحة",
"viewReport": "عرض التقرير",
+ "checkAvailability": "التحقق من التوفر",
+ "readInstructions": "قراءة التعليمات",
+ "searchLabReport" : "ابحث عن تقرير المختبر",
"prescriptionDeliveryError": "هذه العيادة لا تدعم إعادة التعبئة والتسليم.",
"receiveOtpToast": "أين تود تلقي رمز التحقق OTP؟",
"enterPhoneNumber": "أدخل رقم الهاتف",
diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json
index d01d9f6..8ccd2c4 100644
--- a/assets/langs/en-US.json
+++ b/assets/langs/en-US.json
@@ -783,6 +783,9 @@
"resultsPending": "Results Pending",
"resultsAvailable": "Results Available",
"viewReport": "View Report",
+ "checkAvailability": "Check Availability",
+ "readInstructions": "Read Instructions",
+ "searchLabReport" : "Search Lab Report",
"prescriptionDeliveryError": "This clinic doesn't support refill",
"prepareToElevate": "Prepared to elevate your health and well-being?",
"iAcceptTermsConditions": "I Accept the Terms and Conditions",
diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart
index 5fa6f5e..6eaaff6 100644
--- a/lib/core/api_consts.dart
+++ b/lib/core/api_consts.dart
@@ -731,6 +731,14 @@ class ApiConsts {
static String baseUrl = 'https://hmgwebservices.com/'; // HIS API URL PROD
+ static String SELECT_DEVICE_IMEI = 'Services/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI';
+
+ static num VERSION_ID = 18.9;
+
+ static final String selectDeviceImei = 'Services/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI';
+ static final String sendActivationCode = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationType';
+
+
static setBackendURLs() {
switch (appEnvironmentType) {
case AppEnvironmentTypeEnum.prod:
diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart
index bd3e541..7f1b6d1 100644
--- a/lib/core/app_assets.dart
+++ b/lib/core/app_assets.dart
@@ -67,14 +67,19 @@ class AppAssets {
static const String rating_icon = '$svgBasePath/rating_icon.svg';
static const String doctor_calendar_icon = '$svgBasePath/doctor_calendar_icon.svg';
static const String prescription_remarks_icon = '$svgBasePath/prescription_remarks_icon.svg';
+ static const String prescription_reminder_icon = '$svgBasePath/prescription_reminder_icon.svg';
+ static const String insurance_history_icon = '$svgBasePath/insurance_history_icon.svg';
+ static const String cancel_circle_icon = '$svgBasePath/cancel_circle.svg';
+ static const String update_insurance_card_icon = '$svgBasePath/update_insurance_card.svg';
+ static const String close_bottom_sheet_icon = '$svgBasePath/close_bottom_sheet_icon.svg';
//bottom navigation//
-
static const String homeBottom = '$svgBasePath/home_bottom.svg';
static const String bookAppoBottom = '$svgBasePath/book_appo_bottom.svg';
static const String myFilesBottom = '$svgBasePath/my_files_bottom.svg';
static const String toDoBottom = '$svgBasePath/todo_bottom.svg';
static const String servicesBottom = '$svgBasePath/services_bottom.svg';
+ static const String closeBottomNav = '$svgBasePath/close_bottom_nav.svg';
// PNGS //
static const String hmg_logo = '$pngBasePath/hmg_logo.png';
diff --git a/lib/core/dependencies.dart b/lib/core/dependencies.dart
index 77088af..a900742 100644
--- a/lib/core/dependencies.dart
+++ b/lib/core/dependencies.dart
@@ -7,6 +7,8 @@ import 'package:hmg_patient_app_new/features/authentication/authentication_repo.
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_repo.dart';
import 'package:hmg_patient_app_new/features/common/common_repo.dart';
+import 'package:hmg_patient_app_new/features/insurance/insurance_repo.dart';
+import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/lab/lab_repo.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_repo.dart';
@@ -73,6 +75,7 @@ class AppDependencies {
getIt.registerLazySingleton(() => LabRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => RadiologyRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => PrescriptionsRepoImp(loggerService: getIt(), apiClient: getIt()));
+ getIt.registerLazySingleton(() => InsuranceRepoImp(loggerService: getIt(), apiClient: getIt()));
// ViewModels
// Global/shared VMs → LazySingleton
@@ -98,6 +101,13 @@ class AppDependencies {
),
);
+ getIt.registerLazySingleton(
+ () => InsuranceViewModel(
+ insuranceRepo: getIt(),
+ errorHandlerService: getIt(),
+ ),
+ );
+
getIt.registerLazySingleton(
() => AuthenticationViewModel(
authenticationRepo: getIt(),
diff --git a/lib/core/utils/calendar_utils.dart b/lib/core/utils/calendar_utils.dart
index 39c7a14..8786f7f 100644
--- a/lib/core/utils/calendar_utils.dart
+++ b/lib/core/utils/calendar_utils.dart
@@ -4,8 +4,6 @@ import 'dart:io';
import 'dart:ui';
import 'package:device_calendar/device_calendar.dart';
-import 'package:easy_localization/easy_localization.dart';
-import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:manage_calendar_events/manage_calendar_events.dart' as ios;
import 'package:timezone/data/latest.dart' as tzl;
@@ -137,14 +135,12 @@ class CalendarUtils {
print("catchError " + e.toString());
}).whenComplete(() {
print("whenComplete Calender ID " + eventId!);
- // Utils.showToast(LocaleKeys.appoReminderSuccess.tr());
});
} else {
await _myPlugin.createEvent(calendarId: writableCalendars.id!, event: iosCalEvent).catchError((e) {
print("catchError " + e.toString());
}).whenComplete(() {
print("whenComplete Calender ID iOS " + eventId!);
- // Utils.showToast(LocaleKeys.appoReminderSuccess.tr());
});
}
}
diff --git a/lib/core/utils/size_utils.dart b/lib/core/utils/size_utils.dart
index 0b37082..6ad1835 100644
--- a/lib/core/utils/size_utils.dart
+++ b/lib/core/utils/size_utils.dart
@@ -11,6 +11,10 @@ extension ResponsiveExtension on num {
double get h => ((this * _width) / FIGMA_DESIGN_WIDTH);
double get fSize => ((this * _width) / FIGMA_DESIGN_WIDTH);
+ static double get screenHeight => SizeUtils.height;
+
+ /// Full screen width
+ static double get screenWidth => SizeUtils.width;
}
extension FormatExtension on double {
diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart
index 4d813f0..352415b 100644
--- a/lib/extensions/string_extensions.dart
+++ b/lib/extensions/string_extensions.dart
@@ -60,15 +60,16 @@ extension EmailValidator on String {
),
);
- Widget toText12({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, int maxLine = 0}) => Text(
+ Widget toText12({Color? color, bool isUnderLine = false, bool isBold = false, FontWeight? fontWeight, bool isCenter = false, double? height, int maxLine = 0}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
maxLines: (maxLine > 0) ? maxLine : null,
style: TextStyle(
fontSize: 12.fSize,
- fontWeight: isBold ? FontWeight.bold : FontWeight.normal,
+ fontWeight: fontWeight ?? (isBold ? FontWeight.bold : FontWeight.normal),
color: color ?? AppColors.blackColor,
letterSpacing: -0.4,
+ height: height,
decorationColor: isUnderLine ? AppColors.blackColor : null,
decoration: isUnderLine ? TextDecoration.underline : null,
),
@@ -206,49 +207,45 @@ extension EmailValidator on String {
Widget toText21({Color? color, bool isBold = false, FontWeight? weight, int? maxlines}) => Text(
this,
maxLines: maxlines,
- style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 21.fSize, letterSpacing: -0.4, fontWeight: weight ?? (isBold ? FontWeight.w600 : FontWeight.normal)),
+ style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 21.fSize, letterSpacing: -0.4, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal)),
);
Widget toText22({Color? color, bool isBold = false, bool isCenter = false}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
- style: TextStyle(height: 1, color: color ?? AppColors.blackColor, fontSize: 22.fSize, letterSpacing: -0.4, fontWeight: isBold ? FontWeight.w600 : FontWeight.normal),
+ style: TextStyle(height: 1, color: color ?? AppColors.blackColor, fontSize: 22.fSize, letterSpacing: -0.4, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
Widget toText24({Color? color, bool isBold = false, bool isCenter = false}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
- style: TextStyle(height: 23 / 24, color: color ?? AppColors.blackColor, fontSize: 24.fSize, letterSpacing: -0.4, fontWeight: isBold ? FontWeight.w600 : FontWeight.normal),
+ style: TextStyle(height: 23 / 24, color: color ?? AppColors.blackColor, fontSize: 24.fSize, letterSpacing: -0.4, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
- Widget toText26({Color? color, bool isBold = false, bool isCenter = false, double height = 23/26}) => Text(
+ Widget toText26({Color? color, bool isBold = false, double? height, bool isCenter = false}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
- style: TextStyle(height: height, color: color ?? AppColors.blackColor, fontSize: 26.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.w600 : FontWeight.normal),
+ style: TextStyle(height: height ?? 23 / 26, color: color ?? AppColors.blackColor, fontSize: 26.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
- Widget toText28({Color? color, bool isBold = false, bool isCenter = false, TextScaler? textScaler}) => Text(
- this,
- textAlign: isCenter ? TextAlign.center : null,
- textScaler: textScaler,
- style: TextStyle(height: 40 / 28, color: color ?? AppColors.blackColor, fontSize: 28.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.w600 : FontWeight.normal),
- );
- Widget toText32({Color? color, bool isBold = false, bool isCenter = false}) => Text(
- this,
- textAlign: isCenter ? TextAlign.center : null,
- style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 32.fSize, letterSpacing: -0.4, fontWeight: isBold ? FontWeight.w600 : FontWeight.normal),
- );
+ Widget toText28({Color? color, bool isBold = false, double? height, bool isCenter = false}) => Text(
+ this,
+ textAlign: isCenter ? TextAlign.center : null,
+ style: TextStyle(height: height ?? 23 / 28, color: color ?? AppColors.blackColor, fontSize: 28.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
+ );
- Widget toText36({Color? color, bool isBold = false, bool isCenter = false}) => Text(
+
+
+ Widget toText32({Color? color, bool isBold = false, bool isCenter = false}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
- style: TextStyle(height: 47 / 36, color: color ?? AppColors.blackColor, fontSize: 36.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.w600 : FontWeight.normal),
+ style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 32.fSize, letterSpacing: -0.4, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
Widget toText44({Color? color, bool isBold = false}) => Text(
this,
- style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 44.fSize, letterSpacing: -0.4, fontWeight: isBold ? FontWeight.w600 : FontWeight.normal),
+ style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 44.fSize, letterSpacing: -0.4, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
Widget toSectionHeading({String upperHeading = "", String lowerHeading = ""}) {
diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart
index 36fd187..82e85ee 100644
--- a/lib/features/authentication/authentication_view_model.dart
+++ b/lib/features/authentication/authentication_view_model.dart
@@ -1,12 +1,16 @@
import 'dart:developer';
+import 'dart:convert';
+
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
+import 'package:hmg_patient_app_new/core/common_models/nationality_country_model.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/loading_utils.dart';
import 'package:hmg_patient_app_new/core/utils/request_utils.dart';
import 'package:hmg_patient_app_new/core/utils/validation_utils.dart';
+import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_repo.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_activation_code_resp_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart';
@@ -36,8 +40,13 @@ class AuthenticationViewModel extends ChangeNotifier {
_appState = appState,
_authenticationRepo = authenticationRepo;
- final TextEditingController nationalIdController = TextEditingController();
- final TextEditingController phoneNumberController = TextEditingController();
+ final TextEditingController nationalIdController = TextEditingController(), phoneNumberController = TextEditingController(), dobController = TextEditingController();
+ CountryEnum selectedCountrySignup = CountryEnum.saudiArabia;
+ MaritalStatusTypeEnum? maritalStatus;
+ GenderTypeEnum? genderType;
+ bool isTermsAccepted = false;
+ List? countriesList;
+ NationalityCountries? pickedCountryByUAEUser;
bool isDubai = false;
bool authenticated = false;
@@ -78,6 +87,52 @@ class AuthenticationViewModel extends ChangeNotifier {
}
}
+ void clearDefaults() {
+ nationalIdController.clear();
+ phoneNumberController.clear();
+ dobController.clear();
+ maritalStatus = null;
+ genderType = null;
+ isTermsAccepted = false;
+ selectedCountrySignup = CountryEnum.saudiArabia;
+ pickedCountryByUAEUser = null;
+ }
+
+ void onCountryChange(CountryEnum country) {
+ selectedCountrySignup = country;
+ notifyListeners();
+ }
+
+ void loadCountriesData({required BuildContext context}) async {
+ final String response = await DefaultAssetBundle.of(context).loadString('assets/json/countriesList.json');
+ final List data = json.decode(response);
+ countriesList = data.map((e) => NationalityCountries.fromJson(e)).toList();
+ }
+
+ void onMaritalStatusChange(String? status) {
+ maritalStatus = MaritalStatusTypeExtension.fromType(status)!;
+ notifyListeners();
+ }
+
+ void onGenderChange(String? status) {
+ genderType = GenderTypeExtension.fromType(status)!;
+ notifyListeners();
+ }
+
+ void onUAEUserCountrySelection(String? value) {
+ pickedCountryByUAEUser = countriesList!.firstWhere((element) => element.name == value);
+ notifyListeners();
+ }
+
+ void onPhoneNumberChange(String? phoneNumber) {
+ phoneNumberController.text = phoneNumber!;
+ }
+
+ void onTermAccepted() {
+ isTermsAccepted = !isTermsAccepted;
+ notifyListeners();
+ }
+
Future selectDeviceImei({required Function(dynamic data) onSuccess, Function(String)? onError}) async {
// LoadingUtils.showFullScreenLoading();
String firebaseToken = _appState.deviceToken == ""
diff --git a/lib/features/insurance/insurance_repo.dart b/lib/features/insurance/insurance_repo.dart
new file mode 100644
index 0000000..a5c624f
--- /dev/null
+++ b/lib/features/insurance/insurance_repo.dart
@@ -0,0 +1,77 @@
+import 'package:dartz/dartz.dart';
+import 'package:hmg_patient_app_new/core/api/api_client.dart';
+import 'package:hmg_patient_app_new/core/api_consts.dart';
+import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
+import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
+import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_details_response_model.dart';
+import 'package:hmg_patient_app_new/services/logger_service.dart';
+
+abstract class InsuranceRepo {
+ Future>>> getPatientInsuranceDetails({required String patientId});
+}
+
+class InsuranceRepoImp implements InsuranceRepo {
+ final ApiClient apiClient;
+ final LoggerService loggerService;
+
+ InsuranceRepoImp({required this.loggerService, required this.apiClient});
+
+ @override
+ Future>>> getPatientInsuranceDetails({required String patientId}) async {
+ final mapDevice = {
+ "isDentalAllowedBackend": false,
+ "VersionID": 50.0,
+ "Channel": 3,
+ "LanguageID": 2,
+ "IPAdress": "10.20.10.20",
+ "generalid": "Cs2020@2016\$2958",
+ "Latitude": 0.0,
+ "Longitude": 0.0,
+ "DeviceTypeID": 1,
+ "PatientType": 1,
+ "PatientTypeID": 1,
+ "TokenID": "@dm!n",
+ "PatientID": "3628599",
+ "PatientOutSA": "0",
+ "SessionID": "03478TYC02N80874CTYN04883475!?"
+ };
+
+ try {
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_PAtIENTS_INSURANCE,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus}) {
+ try {
+ final list = response['List_PatientInsuranceCard'];
+ if (list == null || list.isEmpty) {
+ throw Exception("insurance list is empty");
+ }
+
+ final labOrders = list.map((item) => PatientInsuranceDetailsResponseModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: labOrders,
+ );
+ } 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()));
+ }
+
+ throw UnimplementedError();
+ }
+}
diff --git a/lib/features/insurance/insurance_view_model.dart b/lib/features/insurance/insurance_view_model.dart
new file mode 100644
index 0000000..fac09da
--- /dev/null
+++ b/lib/features/insurance/insurance_view_model.dart
@@ -0,0 +1,50 @@
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/features/insurance/insurance_repo.dart';
+import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_details_response_model.dart';
+import 'package:hmg_patient_app_new/features/lab/lab_repo.dart';
+import 'package:hmg_patient_app_new/services/error_handler_service.dart';
+
+class InsuranceViewModel extends ChangeNotifier {
+ bool isInsuranceLoading = false;
+ bool isInsuranceHistoryLoading = false;
+
+ InsuranceRepo insuranceRepo;
+ ErrorHandlerService errorHandlerService;
+
+ List patientInsuranceList = [];
+
+ InsuranceViewModel({required this.insuranceRepo, required this.errorHandlerService});
+
+ initInsuranceProvider() {
+ patientInsuranceList.clear();
+ isInsuranceLoading = true;
+ isInsuranceHistoryLoading = true;
+ getPatientInsuranceDetails();
+ notifyListeners();
+ }
+
+ setIsInsuranceHistoryLoading(bool val) {
+ isInsuranceHistoryLoading = val;
+ notifyListeners();
+ }
+
+ Future getPatientInsuranceDetails({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await insuranceRepo.getPatientInsuranceDetails(patientId: "1231755");
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(failure: failure),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ patientInsuranceList = apiResponse.data!;
+ isInsuranceLoading = false;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+}
diff --git a/lib/features/insurance/models/resp_models/patient_insurance_details_response_model.dart b/lib/features/insurance/models/resp_models/patient_insurance_details_response_model.dart
new file mode 100644
index 0000000..b734abc
--- /dev/null
+++ b/lib/features/insurance/models/resp_models/patient_insurance_details_response_model.dart
@@ -0,0 +1,96 @@
+class PatientInsuranceDetailsResponseModel {
+ String? setupID;
+ int? projectID;
+ bool? isActive;
+ int? patientID;
+ int? companyID;
+ int? subCategoryID;
+ dynamic companyType;
+ String? patientCardID;
+ String? cardValidTo;
+ int? patientCreditLimit;
+ String? subPolicyNo;
+ String? companyName;
+ String? companyNameN;
+ String? subCategoryDesc;
+ dynamic subCategoryDescN;
+ bool? isElectronicClaim;
+ String? subCategoryValidTo;
+ dynamic groupID;
+ String? groupName;
+ dynamic groupNameN;
+ String? insurancePolicyNo;
+
+ PatientInsuranceDetailsResponseModel(
+ {this.setupID,
+ this.projectID,
+ this.isActive,
+ this.patientID,
+ this.companyID,
+ this.subCategoryID,
+ this.companyType,
+ this.patientCardID,
+ this.cardValidTo,
+ this.patientCreditLimit,
+ this.subPolicyNo,
+ this.companyName,
+ this.companyNameN,
+ this.subCategoryDesc,
+ this.subCategoryDescN,
+ this.isElectronicClaim,
+ this.subCategoryValidTo,
+ this.groupID,
+ this.groupName,
+ this.groupNameN,
+ this.insurancePolicyNo});
+
+ PatientInsuranceDetailsResponseModel.fromJson(Map json) {
+ setupID = json['SetupID'];
+ projectID = json['ProjectID'];
+ isActive = json['IsActive'];
+ patientID = json['PatientID'];
+ companyID = json['CompanyID'];
+ subCategoryID = json['SubCategoryID'];
+ companyType = json['CompanyType'];
+ patientCardID = json['PatientCardID'];
+ cardValidTo = json['CardValidTo'];
+ patientCreditLimit = json['PatientCreditLimit'];
+ subPolicyNo = json['SubPolicyNo'];
+ companyName = json['CompanyName'];
+ companyNameN = json['CompanyNameN'];
+ subCategoryDesc = json['SubCategoryDesc'];
+ subCategoryDescN = json['SubCategoryDescN'];
+ isElectronicClaim = json['IsElectronicClaim'];
+ subCategoryValidTo = json['SubCategoryValidTo'];
+ groupID = json['GroupID'];
+ groupName = json['GroupName'];
+ groupNameN = json['GroupNameN'];
+ insurancePolicyNo = json['InsurancePolicyNo'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['SetupID'] = this.setupID;
+ data['ProjectID'] = this.projectID;
+ data['IsActive'] = this.isActive;
+ data['PatientID'] = this.patientID;
+ data['CompanyID'] = this.companyID;
+ data['SubCategoryID'] = this.subCategoryID;
+ data['CompanyType'] = this.companyType;
+ data['PatientCardID'] = this.patientCardID;
+ data['CardValidTo'] = this.cardValidTo;
+ data['PatientCreditLimit'] = this.patientCreditLimit;
+ data['SubPolicyNo'] = this.subPolicyNo;
+ data['CompanyName'] = this.companyName;
+ data['CompanyNameN'] = this.companyNameN;
+ data['SubCategoryDesc'] = this.subCategoryDesc;
+ data['SubCategoryDescN'] = this.subCategoryDescN;
+ data['IsElectronicClaim'] = this.isElectronicClaim;
+ data['SubCategoryValidTo'] = this.subCategoryValidTo;
+ data['GroupID'] = this.groupID;
+ data['GroupName'] = this.groupName;
+ data['GroupNameN'] = this.groupNameN;
+ data['InsurancePolicyNo'] = this.insurancePolicyNo;
+ return data;
+ }
+}
diff --git a/lib/features/lab/lab_view_model.dart b/lib/features/lab/lab_view_model.dart
index acd87eb..94ddd87 100644
--- a/lib/features/lab/lab_view_model.dart
+++ b/lib/features/lab/lab_view_model.dart
@@ -12,6 +12,10 @@ class LabViewModel extends ChangeNotifier {
List patientLabOrders = [];
+ late List _labSuggestionsList = [];
+
+ List get labSuggestions => _labSuggestionsList;
+
LabViewModel({required this.labRepo, required this.errorHandlerService});
initLabProvider() {
@@ -34,6 +38,7 @@ class LabViewModel extends ChangeNotifier {
patientLabOrders = apiResponse.data!;
isLabOrdersLoading = false;
isLabResultsLoading = false;
+ filterSuggestions();
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
@@ -42,4 +47,15 @@ class LabViewModel extends ChangeNotifier {
},
);
}
+
+ filterSuggestions(){
+ final List labels = patientLabOrders
+ .expand((order) => order.testDetails!) // flatten testDetails
+ .map((detail) => detail.description) // pick description
+ .whereType() // remove nulls if any
+ .toList();
+ _labSuggestionsList = labels.toSet().toList(); // remove duplicates by converting to a set and back to a list
+
+ notifyListeners();
+ }
}
diff --git a/lib/features/prescriptions/models/resp_models/prescription_detail_response_model.dart b/lib/features/prescriptions/models/resp_models/prescription_detail_response_model.dart
index 3ca8396..b35cfef 100644
--- a/lib/features/prescriptions/models/resp_models/prescription_detail_response_model.dart
+++ b/lib/features/prescriptions/models/resp_models/prescription_detail_response_model.dart
@@ -32,6 +32,7 @@ class PrescriptionDetailResponseModel {
String? sKU;
num? scaleOffset;
String? startDate;
+ bool? hasReminder;
PrescriptionDetailResponseModel(
{this.address,
@@ -66,7 +67,8 @@ class PrescriptionDetailResponseModel {
this.route,
this.sKU,
this.scaleOffset,
- this.startDate});
+ this.startDate,
+ this.hasReminder = false});
PrescriptionDetailResponseModel.fromJson(Map json) {
address = json['Address'];
@@ -102,6 +104,7 @@ class PrescriptionDetailResponseModel {
sKU = json['SKU'];
scaleOffset = json['ScaleOffset'];
startDate = json['StartDate'];
+ hasReminder = false;
}
Map toJson() {
diff --git a/lib/features/prescriptions/prescriptions_view_model.dart b/lib/features/prescriptions/prescriptions_view_model.dart
index 23a818e..ff93f84 100644
--- a/lib/features/prescriptions/prescriptions_view_model.dart
+++ b/lib/features/prescriptions/prescriptions_view_model.dart
@@ -43,6 +43,14 @@ class PrescriptionsViewModel extends ChangeNotifier {
notifyListeners();
}
+ setPrescriptionItemReminder(bool value, PrescriptionDetailResponseModel item) {
+ int index = prescriptionDetailsList.indexOf(item);
+ if (index != -1) {
+ prescriptionDetailsList[index].hasReminder = value;
+ notifyListeners();
+ }
+ }
+
setIsSortByClinic(bool value) {
isSortByClinic = value;
if (isSortByClinic) {
diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart
index 0210e4c..7831616 100644
--- a/lib/generated/locale_keys.g.dart
+++ b/lib/generated/locale_keys.g.dart
@@ -802,5 +802,8 @@ abstract class LocaleKeys {
static const loginByOTP = 'loginByOTP';
static const guest = 'guest';
static const switchAccount = 'switchAccount';
+ static const checkAvailability = 'checkAvailability';
+ static const readInstructions = 'readInstructions';
+ static const searchLabReport = 'searchLabReport';
}
diff --git a/lib/main.dart b/lib/main.dart
index 29c8943..53825c8 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -9,6 +9,7 @@ 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/utils.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
+import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_view_model.dart';
@@ -84,6 +85,12 @@ void main() async {
errorHandlerService: getIt(),
),
),
+ ChangeNotifierProvider(
+ create: (_) => InsuranceViewModel(
+ insuranceRepo: getIt(),
+ errorHandlerService: getIt(),
+ ),
+ ),
ChangeNotifierProvider(
create: (_) => AuthenticationViewModel(
authenticationRepo: getIt(),
diff --git a/lib/presentation/authentication/login.dart b/lib/presentation/authentication/login.dart
index c3948a1..20a6507 100644
--- a/lib/presentation/authentication/login.dart
+++ b/lib/presentation/authentication/login.dart
@@ -160,12 +160,12 @@ class _LoginScreen extends State {
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: SingleChildScrollView(
child: GenericBottomSheet(
- countryCode: "966",
+ countryCode: authVM.selectedCountrySignup.countryCode,
initialPhoneNumber: "",
textController: phoneNumberController,
isEnableCountryDropdown: true,
- onCountryChange: (value) {},
- onChange: (String? value) {},
+ onCountryChange: authVM.onCountryChange,
+ onChange: authVM.onPhoneNumberChange,
buttons: [
Padding(
padding: EdgeInsets.only(bottom: 10.h),
diff --git a/lib/presentation/authentication/register.dart b/lib/presentation/authentication/register.dart
index a97c7ad..448b7af 100644
--- a/lib/presentation/authentication/register.dart
+++ b/lib/presentation/authentication/register.dart
@@ -9,6 +9,7 @@ import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
+import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/app_bar_widget.dart';
@@ -16,6 +17,8 @@ import 'package:hmg_patient_app_new/widgets/bottomsheet/generic_bottom_sheet.dar
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart' show CustomButton;
import 'package:hmg_patient_app_new/widgets/dropdown/country_dropdown_widget.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
+import 'package:hmg_patient_app_new/widgets/otp/otp.dart';
+import 'package:provider/provider.dart';
class RegisterNew extends StatefulWidget {
@override
@@ -23,8 +26,6 @@ class RegisterNew extends StatefulWidget {
}
class _RegisterNew extends State {
- bool isTermsAccepted = true;
-
@override
void initState() {
super.initState();
@@ -38,6 +39,8 @@ class _RegisterNew extends State {
@override
Widget build(BuildContext context) {
AppState appState = getIt.get();
+ AuthenticationViewModel authVm = context.read();
+
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
appBar: CustomAppBar(
@@ -79,30 +82,31 @@ class _RegisterNew extends State {
children: [
CustomCountryDropdown(
countryList: CountryEnum.values,
- onCountryChange: (CountryEnum? value) {},
+ onCountryChange: authVm.onCountryChange,
isRtl: Directionality.of(context) == TextDirection.LTR,
).withVerticalPadding(8.h),
Divider(height: 1.h),
TextInputWidget(
- labelText: LocaleKeys.nationalIdNumber.tr(),
- hintText: "xxxxxxxxx",
- controller: TextEditingController(),
- isEnable: true,
- prefix: null,
- isAllowRadius: true,
- isBorderAllowed: false,
- isAllowLeadingIcon: true,
- autoFocus: true,
- padding: EdgeInsets.symmetric(vertical: 8.h),
- leadingIcon: AppAssets.student_card,
- onChange: (value) {
- print(value);
- }).withVerticalPadding(8),
+ labelText: LocaleKeys.nationalIdNumber.tr(),
+ hintText: "xxxxxxxxx",
+ controller: authVm.nationalIdController,
+ isEnable: true,
+ prefix: null,
+ isAllowRadius: true,
+ isBorderAllowed: false,
+ isAllowLeadingIcon: true,
+ autoFocus: true,
+ padding: EdgeInsets.symmetric(vertical: 8.h),
+ leadingIcon: AppAssets.student_card,
+ // onChange: (value) {
+ // print(value);
+ // }
+ ).withVerticalPadding(8),
Divider(height: 1),
TextInputWidget(
labelText: LocaleKeys.dob.tr(),
hintText: "11 July, 1994",
- controller: TextEditingController(),
+ controller: authVm.dobController,
isEnable: true,
prefix: null,
isAllowRadius: true,
@@ -110,7 +114,7 @@ class _RegisterNew extends State {
isAllowLeadingIcon: true,
padding: EdgeInsets.symmetric(vertical: 8.h),
leadingIcon: AppAssets.birthday_cake,
- onChange: (value) {},
+ selectionType: SelectionTypeEnum.calendar,
).withVerticalPadding(8),
],
),
@@ -118,22 +122,25 @@ class _RegisterNew extends State {
),
SizedBox(height: 25.h),
GestureDetector(
- onTap: () {},
+ onTap: authVm.onTermAccepted,
child: Row(
children: [
- AnimatedContainer(
- duration: const Duration(milliseconds: 200),
- height: 24.h,
- width: 24.h,
- decoration: BoxDecoration(
- color: isTermsAccepted ? const Color(0xFFE92227) : Colors.transparent,
- borderRadius: BorderRadius.circular(6),
- border: Border.all(
- color: isTermsAccepted ? const Color(0xFFE92227) : Colors.grey,
- width: 2.h,
- ),
- ),
- child: isTermsAccepted ? Icon(Icons.check, size: 16.fSize, color: Colors.white) : null,
+ Selector(
+ selector: (_, viewModel) => viewModel.isTermsAccepted,
+ shouldRebuild: (previous, next) => previous != next,
+ builder: (context, isTermsAccepted, child) {
+ return AnimatedContainer(
+ duration: const Duration(milliseconds: 200),
+ height: 24.h,
+ width: 24.h,
+ decoration: BoxDecoration(
+ color: isTermsAccepted ? AppColors.primaryRedColor : Colors.transparent,
+ borderRadius: BorderRadius.circular(6),
+ border: Border.all(color: isTermsAccepted ? AppColors.primaryRedBorderColor : AppColors.greyColor, width: 2.h),
+ ),
+ child: isTermsAccepted ? Icon(Icons.check, size: 16.fSize, color: Colors.white) : null,
+ );
+ },
),
SizedBox(width: 12.h),
Expanded(
@@ -150,7 +157,7 @@ class _RegisterNew extends State {
text: "Register",
icon: AppAssets.note_edit,
onPressed: () {
- showRegisterModel(context: context);
+ showRegisterModel(context: context, authVM: authVm);
},
),
SizedBox(height: 14),
@@ -193,7 +200,7 @@ class _RegisterNew extends State {
));
}
- void showRegisterModel({required BuildContext context, TextEditingController? textController}) {
+ void showRegisterModel({required BuildContext context, required AuthenticationViewModel authVM}) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
@@ -204,18 +211,22 @@ class _RegisterNew extends State {
padding: EdgeInsets.only(bottom: MediaQuery.of(bottomSheetContext).viewInsets.bottom),
child: SingleChildScrollView(
child: GenericBottomSheet(
- countryCode: "966",
+ countryCode: authVM.selectedCountrySignup.countryCode,
initialPhoneNumber: "",
+ textController: authVM.phoneNumberController,
isEnableCountryDropdown: true,
- textController: TextEditingController(),
- onChange: (String? value) {},
+ onCountryChange: authVM.onCountryChange,
+ onChange: authVM.onPhoneNumberChange,
buttons: [
Padding(
padding: const EdgeInsets.only(bottom: 10),
child: CustomButton(
text: LocaleKeys.sendOTPSMS.tr(),
onPressed: () {
- // TODO: MOVE TO OTP SCREEN
+ Navigator.of(context).push(MaterialPageRoute(
+ builder: (BuildContext context) => OTPVerificationPage(
+ phoneNumber: '12234567',
+ )));
// if (mobileNo.isEmpty) {
// context.showBottomSheet(
diff --git a/lib/presentation/authentication/register_step2.dart b/lib/presentation/authentication/register_step2.dart
index 295dd8a..483ce5c 100644
--- a/lib/presentation/authentication/register_step2.dart
+++ b/lib/presentation/authentication/register_step2.dart
@@ -2,6 +2,7 @@ import 'dart:convert';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
+import 'package:get_it/get_it.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/common_models/nationality_country_model.dart';
@@ -11,6 +12,7 @@ import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/context_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
+import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/app_bar_widget.dart';
@@ -18,6 +20,7 @@ import 'package:hmg_patient_app_new/widgets/bottomsheet/generic_bottom_sheet.dar
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/dropdown/dropdown_widget.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
+import 'package:provider/provider.dart';
class RegisterNewStep2 extends StatefulWidget {
var nHICData;
@@ -31,30 +34,34 @@ class RegisterNewStep2 extends StatefulWidget {
class _RegisterNew extends State {
bool isFromDubai = true;
- List countriesList = [];
- AppState? appState;
- GenderTypeEnum? selectedGenderType;
- MaritalStatusTypeEnum? selectedMaritalStatusType;
- CountryEnum? selectedCountry;
+ AuthenticationViewModel? authVM;
@override
void initState() {
super.initState();
+ authVM = context.read();
+ authVM!.loadCountriesData(context: context);
// isFromDubai = widget.payload.zipCode!.contains("971") || widget.payload.zipCode!.contains("+971");
- loadCountriesList();
}
- loadCountriesList() async {
- appState = getIt.get();
- final String response = await DefaultAssetBundle.of(context).loadString('assets/json/countriesList.json');
- final List data = json.decode(response);
- countriesList = data.map((e) => NationalityCountries.fromJson(e)).toList();
+ @override
+ void dispose() {
+ super.dispose();
+ authVM!.clearDefaults();
}
+ @override
Widget build(BuildContext context) {
+ AppState appState = getIt.get();
return Scaffold(
-
- appBar: CustomAppBar(onBackPressed: () {}, onLanguageChanged: (lang) {}, hideLogoAndLang: true,),
+ appBar: CustomAppBar(
+ onBackPressed: () {
+ Navigator.of(context).pop();
+ authVM!.clearDefaults();
+ },
+ onLanguageChanged: (lang) {},
+ hideLogoAndLang: true,
+ ),
body: SingleChildScrollView(
reverse: false,
padding: EdgeInsets.only(left: 24.h, right: 24.h, top: 24.h),
@@ -69,147 +76,180 @@ class _RegisterNew extends State {
child: Column(
children: [
TextInputWidget(
- labelText: isFromDubai ? LocaleKeys.fullName.tr() : LocaleKeys.name.tr(),
- hintText: isFromDubai ? "name" ?? "" : (widget.nHICData!.firstNameEn!.toUpperCase() + " " + widget.nHICData!.lastNameEn!.toUpperCase()),
- controller: null,
- isEnable: true,
- prefix: null,
- isAllowRadius: false,
- isBorderAllowed: false,
- keyboardType: TextInputType.text,
- isAllowLeadingIcon: true,
- isReadOnly: isFromDubai ? false : true,
- leadingIcon: AppAssets.user_circle).paddingSymmetrical(0.h,16.h),
- Divider(height: 1, color: AppColors.greyColor,),
- TextInputWidget(
- labelText: LocaleKeys.nationalIdNumber.tr(),
- hintText: isFromDubai ? "widget.payload.nationalID!" : (widget.nHICData!.idNumber ?? ""),
- controller: null,
- isEnable: true,
- prefix: null,
- isAllowRadius: false,
- isBorderAllowed: false,
- isAllowLeadingIcon: true,
- isReadOnly: true,
- leadingIcon: AppAssets.student_card).paddingSymmetrical(0.h,16.h),
- Divider(height: 1, color: AppColors.greyColor,),
- isFromDubai
- ? DropdownWidget(
- labelText: LocaleKeys.gender.tr(),
- hintText: LocaleKeys.malE.tr(),
- isEnable: true,
- dropdownItems: GenderTypeEnum.values.map((e) => appState!.isArabic() ? e.typeAr : e.type).toList(),
- selectedValue: appState!.isArabic() ? selectedGenderType!.typeAr : selectedGenderType?.type,
- // selectionType: SelectionType.dropdown,
- onChange: (val) {
- if (val != null) {}
- },
- isBorderAllowed: false,
- hasSelectionCustomIcon: true,
- isAllowRadius: false,
- padding: const EdgeInsets.only(top: 8, bottom: 8, left: 0, right: 0),
- selectionCustomIcon: AppAssets.arrow_down,
- leadingIcon: AppAssets.user_full,
- ).withVerticalPadding(8)
- : TextInputWidget(
- labelText: LocaleKeys.gender.tr(),
- hintText: (widget.nHICData!.gender ?? ""),
+ labelText: isFromDubai ? LocaleKeys.fullName.tr() : LocaleKeys.name.tr(),
+ hintText: isFromDubai ? "name" ?? "" : (widget.nHICData!.firstNameEn!.toUpperCase() + " " + widget.nHICData!.lastNameEn!.toUpperCase()),
controller: null,
isEnable: true,
prefix: null,
isAllowRadius: false,
isBorderAllowed: false,
+ keyboardType: TextInputType.text,
isAllowLeadingIcon: true,
isReadOnly: isFromDubai ? false : true,
- leadingIcon: AppAssets.user_full,
-
- onChange: (value) {}).paddingSymmetrical(0.h,16.h),
- Divider(height: 1, color: AppColors.greyColor,),
- isFromDubai
- ? DropdownWidget(
- labelText: LocaleKeys.maritalStatus.tr(),
- hintText: LocaleKeys.married.tr(),
- isEnable: true,
- dropdownItems: MaritalStatusTypeEnum.values.map((e) => appState!.isArabic() ? e.typeAr : e.type).toList(),
- selectedValue: appState!.isArabic() ? selectedMaritalStatusType!.typeAr : selectedMaritalStatusType?.type,
- onChange: (val) {},
- isBorderAllowed: false,
- hasSelectionCustomIcon: true,
- isAllowRadius: false,
- padding: const EdgeInsets.only(top: 8, bottom: 8, left: 0, right: 0),
- selectionCustomIcon: AppAssets.arrow_down,
- leadingIcon: AppAssets.smart_phone,
- ).withVerticalPadding(8)
- : TextInputWidget(
- labelText: LocaleKeys.maritalStatus.tr(),
- hintText: appState!.isArabic()
- ? (MaritalStatusTypeExtension.fromValue(widget.nHICData!.maritalStatusCode)!.typeAr)
- : (MaritalStatusTypeExtension.fromValue(widget.nHICData!.maritalStatusCode)!.type),
+ leadingIcon: AppAssets.user_circle)
+ .paddingSymmetrical(0.h, 16.h),
+ Divider(height: 1, color: AppColors.greyColor),
+ TextInputWidget(
+ labelText: LocaleKeys.nationalIdNumber.tr(),
+ hintText: isFromDubai ? "widget.payload.nationalID!" : (widget.nHICData!.idNumber ?? ""),
+ controller: null,
isEnable: true,
prefix: null,
isAllowRadius: false,
isBorderAllowed: false,
isAllowLeadingIcon: true,
isReadOnly: true,
- leadingIcon: AppAssets.smart_phone,
- onChange: (value) {}).paddingSymmetrical(0.h,16.h),
- Divider(height: 1, color: AppColors.greyColor,),
+ leadingIcon: AppAssets.student_card)
+ .paddingSymmetrical(0.h, 16.h),
+ Divider(height: 1, color: AppColors.greyColor),
isFromDubai
- ? DropdownWidget(
- labelText: LocaleKeys.country.tr(),
- hintText: LocaleKeys.uae.tr(),
- isEnable: true,
- dropdownItems: countriesList.map((e) => appState!.isArabic() ? e.nameN ?? "" : e.name ?? "").toList(),
- selectedValue: appState!.isArabic() ? selectedCountry!.nameArabic ?? "" : selectedCountry?.name ?? "",
- onChange: (val) {},
- isBorderAllowed: false,
- hasSelectionCustomIcon: true,
- isAllowRadius: false,
- padding: const EdgeInsets.only(top: 8, bottom: 8, left: 0, right: 0),
- selectionCustomIcon: AppAssets.arrow_down,
- leadingIcon: AppAssets.globe,
- ).withVerticalPadding(8)
+ ? Selector(
+ selector: (_, authViewModel) => authViewModel.genderType,
+ shouldRebuild: (previous, next) => previous != next,
+ builder: (context, genderType, child) {
+ final authVM = context.read();
+ return DropdownWidget(
+ labelText: LocaleKeys.gender.tr(),
+ hintText: LocaleKeys.malE.tr(),
+ isEnable: true,
+ dropdownItems: GenderTypeEnum.values.map((e) => appState!.isArabic() ? e.typeAr : e.type).toList(),
+ selectedValue: genderType != null ? (appState!.isArabic() ? genderType!.typeAr : genderType!.type) : "",
+ onChange: authVM.onGenderChange,
+ isBorderAllowed: false,
+ hasSelectionCustomIcon: true,
+ isAllowRadius: false,
+ padding: const EdgeInsets.only(top: 8, bottom: 8, left: 0, right: 0),
+ selectionCustomIcon: AppAssets.arrow_down,
+ leadingIcon: AppAssets.user_full,
+ ).withVerticalPadding(8);
+ })
: TextInputWidget(
- labelText: LocaleKeys.nationality.tr(),
- hintText: appState!.isArabic()
- ? (countriesList.firstWhere((e) => e.id == (widget.nHICData!.nationalityCode ?? ""), orElse: () => NationalityCountries()).nameN ?? "")
- : (countriesList.firstWhere((e) => e.id == (widget.nHICData!.nationalityCode ?? ""), orElse: () => NationalityCountries()).name ?? ""),
+ labelText: LocaleKeys.gender.tr(),
+ hintText: (widget.nHICData!.gender ?? ""),
+ controller: null,
+ isEnable: true,
+ prefix: null,
+ isAllowRadius: false,
+ isBorderAllowed: false,
+ isAllowLeadingIcon: true,
+ isReadOnly: isFromDubai ? false : true,
+ leadingIcon: AppAssets.user_full,
+ onChange: (value) {})
+ .paddingSymmetrical(0.h, 16.h),
+ Divider(height: 1, color: AppColors.greyColor),
+ isFromDubai
+ ? Selector(
+ selector: (_, authViewModel) => authViewModel.maritalStatus,
+ shouldRebuild: (previous, next) => previous != next,
+ builder: (context, maritalStatus, child) {
+ final authVM = context.read(); // For onChange
+ return DropdownWidget(
+ labelText: LocaleKeys.maritalStatus.tr(),
+ hintText: LocaleKeys.married.tr(),
+ isEnable: true,
+ dropdownItems: MaritalStatusTypeEnum.values.map((e) => appState!.isArabic() ? e.typeAr : e.type).toList(),
+ selectedValue: maritalStatus != null ? (appState!.isArabic() ? maritalStatus.typeAr : maritalStatus.type) : "",
+ onChange: authVM.onMaritalStatusChange,
+ isBorderAllowed: false,
+ hasSelectionCustomIcon: true,
+ isAllowRadius: false,
+ padding: const EdgeInsets.only(top: 8, bottom: 8, left: 0, right: 0),
+ selectionCustomIcon: AppAssets.arrow_down,
+ leadingIcon: AppAssets.smart_phone,
+ ).withVerticalPadding(8);
+ },
+ )
+ : TextInputWidget(
+ labelText: LocaleKeys.maritalStatus.tr(),
+ hintText: appState!.isArabic()
+ ? (MaritalStatusTypeExtension.fromValue(widget.nHICData!.maritalStatusCode)!.typeAr)
+ : (MaritalStatusTypeExtension.fromValue(widget.nHICData!.maritalStatusCode)!.type),
+ isEnable: true,
+ prefix: null,
+ isAllowRadius: false,
+ isBorderAllowed: false,
+ isAllowLeadingIcon: true,
+ isReadOnly: true,
+ leadingIcon: AppAssets.smart_phone,
+ onChange: (value) {})
+ .paddingSymmetrical(0.h, 16.h),
+ Divider(height: 1, color: AppColors.greyColor),
+ isFromDubai
+ ? Selector? countriesList, NationalityCountries? selectedCountry, bool isArabic})>(
+ selector: (context, authViewModel) {
+ final appState = getIt.get();
+ return (countriesList: authViewModel.countriesList, selectedCountry: authViewModel.pickedCountryByUAEUser, isArabic: appState.isArabic());
+ },
+ shouldRebuild: (previous, next) => previous.countriesList != next.countriesList || previous.selectedCountry != next.selectedCountry || previous.isArabic != next.isArabic,
+ builder: (context, data, child) {
+ final authVM = context.read();
+ return DropdownWidget(
+ labelText: LocaleKeys.country.tr(),
+ hintText: LocaleKeys.uae.tr(),
+ isEnable: true,
+ dropdownItems: (data.countriesList ?? []).map((e) => data.isArabic ? e.nameN ?? "" : e.name ?? "").toList(),
+ selectedValue: data.selectedCountry != null
+ ? data.isArabic
+ ? data.selectedCountry!.nameN ?? ""
+ : data.selectedCountry!.name ?? ""
+ : "",
+ onChange: authVM.onUAEUserCountrySelection,
+ isBorderAllowed: false,
+ hasSelectionCustomIcon: true,
+ isAllowRadius: false,
+ padding: const EdgeInsets.only(top: 8, bottom: 8, left: 0, right: 0),
+ selectionCustomIcon: AppAssets.arrow_down,
+ leadingIcon: AppAssets.globe,
+ ).withVerticalPadding(8);
+ },
+ )
+ : TextInputWidget(
+ labelText: LocaleKeys.nationality.tr(),
+ hintText: appState.isArabic()
+ ? (authVM!.countriesList!.firstWhere((e) => e.id == (widget.nHICData!.nationalityCode ?? ""), orElse: () => NationalityCountries()).nameN ?? "")
+ : (authVM!.countriesList!.firstWhere((e) => e.id == (widget.nHICData!.nationalityCode ?? ""), orElse: () => NationalityCountries()).name ?? ""),
+ isEnable: true,
+ prefix: null,
+ isAllowRadius: false,
+ isBorderAllowed: false,
+ isAllowLeadingIcon: true,
+ isReadOnly: true,
+ leadingIcon: AppAssets.globe,
+ onChange: (value) {})
+ .paddingSymmetrical(0.h, 16.h),
+ Divider(
+ height: 1,
+ color: AppColors.greyColor,
+ ),
+ TextInputWidget(
+ labelText: LocaleKeys.mobileNumber.tr(),
+ hintText: ("widget.payload.mobileNo" ?? ""),
+ controller: authVM!.phoneNumberController,
isEnable: true,
prefix: null,
isAllowRadius: false,
isBorderAllowed: false,
isAllowLeadingIcon: true,
isReadOnly: true,
- leadingIcon: AppAssets.globe,
- onChange: (value) {}).paddingSymmetrical(0.h,16.h),
- Divider(height: 1, color: AppColors.greyColor,),
- TextInputWidget(
- labelText: LocaleKeys.mobileNumber.tr(),
- hintText: ("widget.payload.mobileNo" ?? ""),
- controller: null,
- isEnable: true,
- prefix: null,
- isAllowRadius: false,
- isBorderAllowed: false,
- isAllowLeadingIcon: true,
- isReadOnly: true,
- leadingIcon: AppAssets.call,
- onChange: (value) {}).paddingSymmetrical(0.h,16.h),
- Divider(height: 1, color: AppColors.greyColor,),
+ leadingIcon: AppAssets.call,
+ onChange: (value) {})
+ .paddingSymmetrical(0.h, 16.h),
+ Divider(
+ height: 1,
+ color: AppColors.greyColor,
+ ),
TextInputWidget(
- labelText: LocaleKeys.dob.tr(),
- hintText: isFromDubai ? "widget.payload.dob!" : (widget.nHICData!.dateOfBirth ?? ""),
- controller: null,
- isEnable: true,
- prefix: null,
- isBorderAllowed: false,
- isAllowLeadingIcon: true,
- isReadOnly: true,
- // : SelectionType.calendar,
- // selectedValue: widget.payload.dob != null ? Utils.formatDateToDisplay(widget.payload.dob.toString()) : null,
- // selectionCustomIcon: AppAssets.calendar,
- leadingIcon: AppAssets.birthday_cake,
- onChange: (value) {}).paddingSymmetrical(0.h,16.h),
+ labelText: LocaleKeys.dob.tr(),
+ hintText: isFromDubai ? "widget.payload.dob!" : (widget.nHICData!.dateOfBirth ?? ""),
+ controller: authVM!.dobController,
+ isEnable: true,
+ prefix: null,
+ isBorderAllowed: false,
+ isAllowLeadingIcon: true,
+ isReadOnly: true,
+ leadingIcon: AppAssets.birthday_cake,
+ selectionType: SelectionTypeEnum.calendar,
+ ).paddingSymmetrical(0.h, 16.h),
],
),
),
@@ -219,12 +259,12 @@ class _RegisterNew extends State {
children: [
Expanded(
child: CustomButton(
- text: LocaleKeys.cancel,
+ text: LocaleKeys.cancel.tr(),
icon: AppAssets.cancel,
onPressed: () {
Navigator.of(context).pop();
+ authVM!.clearDefaults();
},
- // fontFamily: context.fontFamily,
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,
diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart
index febde89..cf430e5 100644
--- a/lib/presentation/home/landing_page.dart
+++ b/lib/presentation/home/landing_page.dart
@@ -30,6 +30,7 @@ class LandingPage extends StatefulWidget {
}
class _LandingPageState extends State {
+
@override
Widget build(BuildContext context) {
AppState appState = getIt.get();
diff --git a/lib/presentation/home/navigation_screen.dart b/lib/presentation/home/navigation_screen.dart
new file mode 100644
index 0000000..152bbd2
--- /dev/null
+++ b/lib/presentation/home/navigation_screen.dart
@@ -0,0 +1,40 @@
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/presentation/home/landing_page.dart';
+import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart';
+import 'package:hmg_patient_app_new/widgets/bottom_navigation/bottom_navigation.dart';
+
+class LandingNavigation extends StatefulWidget {
+ const LandingNavigation({super.key});
+
+ @override
+ State createState() => _LandingNavigationState();
+}
+
+class _LandingNavigationState extends State {
+ int _currentIndex = 0;
+ final PageController _pageController = PageController();
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: PageView(
+ controller: _pageController,
+ physics: const NeverScrollableScrollPhysics(),
+ children: [
+ const LandingPage(),
+ MedicalFilePage(),
+ const LandingPage(),
+ const LandingPage(),
+ const LandingPage(),
+ ],
+ ),
+ bottomNavigationBar: BottomNavigation(
+ currentIndex: _currentIndex,
+ onTap: (index) {
+ setState(() => _currentIndex = index);
+ _pageController.animateToPage(index, duration: const Duration(milliseconds: 300), curve: Curves.easeInOut);
+ },
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/home/widgets/small_service_card.dart b/lib/presentation/home/widgets/small_service_card.dart
index 297ed2b..f988e18 100644
--- a/lib/presentation/home/widgets/small_service_card.dart
+++ b/lib/presentation/home/widgets/small_service_card.dart
@@ -2,6 +2,7 @@ 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/presentation/insurance/insurance_home_page.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_orders_page.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescriptions_list_page.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
@@ -78,6 +79,11 @@ class SmallServiceCard extends StatelessWidget {
);
break;
case "insurance_update":
+ Navigator.of(context).push(
+ FadePage(
+ page: InsuranceHomePage(),
+ ),
+ );
break;
default:
// Handle unknown service
diff --git a/lib/presentation/insurance/insurance_home_page.dart b/lib/presentation/insurance/insurance_home_page.dart
new file mode 100644
index 0000000..9f9271a
--- /dev/null
+++ b/lib/presentation/insurance/insurance_home_page.dart
@@ -0,0 +1,90 @@
+import 'dart:async';
+
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/core/app_assets.dart';
+import 'package:hmg_patient_app_new/core/utils/date_util.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/features/insurance/insurance_view_model.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart';
+import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
+import 'package:hmg_patient_app_new/extensions/widget_extensions.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/shimmer/movies_shimmer_widget.dart';
+import 'package:provider/provider.dart';
+
+import 'widgets/insurance_history.dart';
+
+class InsuranceHomePage extends StatefulWidget {
+ const InsuranceHomePage({super.key});
+
+ @override
+ State createState() => _InsuranceHomePageState();
+}
+
+class _InsuranceHomePageState extends State {
+ late InsuranceViewModel insuranceViewModel;
+
+ @override
+ void initState() {
+ scheduleMicrotask(() {
+ insuranceViewModel.initInsuranceProvider();
+ });
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ insuranceViewModel = Provider.of(context);
+ return Scaffold(
+ backgroundColor: AppColors.bgScaffoldColor,
+ appBar: AppBar(
+ title: LocaleKeys.insurance.tr(context: context).toText18(),
+ backgroundColor: AppColors.bgScaffoldColor,
+ ),
+ body: SingleChildScrollView(
+ child: Consumer(builder: (context, insuranceVM, child) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "${LocaleKeys.insurance.tr(context: context)} ${LocaleKeys.updateInsurance.tr(context: context)}".toText24(isBold: true),
+ CustomButton(
+ icon: AppAssets.insurance_history_icon,
+ iconColor: AppColors.primaryRedColor,
+ iconSize: 21.h,
+ text: LocaleKeys.history.tr(context: context),
+ onPressed: () {
+ insuranceVM.setIsInsuranceHistoryLoading(true);
+ showCommonBottomSheet(context,
+ child: InsuranceHistory(), callBackFunc: () {}, title: "", height: ResponsiveExtension.screenHeight * 0.5, isCloseButtonVisible: false, isFullScreen: false);
+ },
+ backgroundColor: AppColors.primaryRedColor.withOpacity(0.1),
+ borderColor: AppColors.primaryRedColor.withOpacity(0.0),
+ textColor: AppColors.primaryRedColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w600,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ ),
+ ],
+ ).paddingSymmetrical(24.h, 24.h),
+ insuranceVM.isInsuranceLoading
+ ? const MoviesShimmerWidget().paddingSymmetrical(24.h, 0)
+ : PatientInsuranceCard(
+ insuranceCardDetailsModel: insuranceVM.patientInsuranceList.first,
+ isInsuranceExpired: DateTime.now().isAfter(DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo))),
+ ],
+ );
+ }),
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/insurance/widgets/insurance_history.dart b/lib/presentation/insurance/widgets/insurance_history.dart
new file mode 100644
index 0000000..0708c7c
--- /dev/null
+++ b/lib/presentation/insurance/widgets/insurance_history.dart
@@ -0,0 +1,39 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/core/app_assets.dart';
+import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
+import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
+import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
+import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
+import 'package:provider/provider.dart';
+
+class InsuranceHistory extends StatelessWidget {
+ InsuranceHistory({super.key});
+
+ late InsuranceViewModel insuranceViewModel;
+
+ @override
+ Widget build(BuildContext context) {
+ insuranceViewModel = Provider.of(context);
+ return Consumer(builder: (context, insuranceVM, child) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ LocaleKeys.history.tr(context: context).toText24(isBold: true),
+ Utils.buildSvgWithAssets(icon: AppAssets.close_bottom_sheet_icon).onPress(() {
+ Navigator.of(context).pop();
+ }),
+ ],
+ ).paddingSymmetrical(24.h, 24.h),
+ insuranceVM.isInsuranceHistoryLoading ? const MoviesShimmerWidget().paddingSymmetrical(24.h, 24.h) : Container()
+ ],
+ );
+ });
+ }
+}
diff --git a/lib/presentation/insurance/widgets/patient_insurance_card.dart b/lib/presentation/insurance/widgets/patient_insurance_card.dart
new file mode 100644
index 0000000..2701233
--- /dev/null
+++ b/lib/presentation/insurance/widgets/patient_insurance_card.dart
@@ -0,0 +1,133 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:hmg_patient_app_new/core/app_assets.dart';
+import 'package:hmg_patient_app_new/core/utils/date_util.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/insurance/insurance_view_model.dart';
+import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_details_response_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/buttons/custom_button.dart';
+import 'package:provider/provider.dart';
+
+class PatientInsuranceCard extends StatelessWidget {
+ PatientInsuranceCard({super.key, required this.insuranceCardDetailsModel, required this.isInsuranceExpired});
+
+ PatientInsuranceDetailsResponseModel insuranceCardDetailsModel;
+ bool isInsuranceExpired = false;
+
+ late InsuranceViewModel insuranceViewModel;
+
+ @override
+ Widget build(BuildContext context) {
+ insuranceViewModel = Provider.of(context);
+ return Container(
+ width: double.infinity,
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Haroon Amjad".toText18(isBold: true),
+ "Policy: ${insuranceCardDetailsModel.insurancePolicyNo}".toText12(isBold: true, color: AppColors.lightGrayColor),
+ ],
+ ),
+ CustomButton(
+ icon: isInsuranceExpired ? AppAssets.cancel_circle_icon : AppAssets.insurance_active_icon,
+ iconColor: isInsuranceExpired ? AppColors.primaryRedColor : AppColors.successColor,
+ iconSize: 13.h,
+ text: isInsuranceExpired ? "Insurance Expired" : "Insurance Active",
+ onPressed: () {},
+ backgroundColor: isInsuranceExpired ? AppColors.primaryRedColor.withOpacity(0.15) : AppColors.successColor.withOpacity(0.15),
+ borderColor: isInsuranceExpired ? AppColors.primaryRedColor.withOpacity(0.01) : AppColors.successColor.withOpacity(0.01),
+ textColor: isInsuranceExpired ? AppColors.primaryRedColor : AppColors.successColor,
+ fontSize: 10,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 30.h,
+ ),
+ ],
+ ),
+ SizedBox(height: 12.h),
+ insuranceCardDetailsModel.groupName!.toText12(isBold: true),
+ insuranceCardDetailsModel.companyName!.toText12(isBold: true),
+ SizedBox(height: 8.h),
+ Wrap(
+ direction: Axis.horizontal,
+ spacing: 6.h,
+ runSpacing: 6.h,
+ children: [
+ Row(
+ children: [
+ CustomButton(
+ icon: AppAssets.doctor_calendar_icon,
+ iconColor: AppColors.blackColor,
+ iconSize: 13.h,
+ text: "${LocaleKeys.expiryDate.tr(context: context)} ${DateUtil.formatDateToDate(DateUtil.convertStringToDate(insuranceCardDetailsModel.cardValidTo), false)}",
+ onPressed: () {},
+ backgroundColor: AppColors.greyColor,
+ borderColor: AppColors.greyColor,
+ textColor: AppColors.blackColor,
+ fontSize: 10,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 30.h,
+ ),
+ ],
+ ),
+ Row(
+ children: [
+ CustomButton(
+ text: "Patient Card ID: ${insuranceCardDetailsModel.patientCardID}",
+ onPressed: () {},
+ backgroundColor: AppColors.greyColor,
+ borderColor: AppColors.greyColor,
+ textColor: AppColors.blackColor,
+ fontSize: 10,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 30.h,
+ ),
+ ],
+ ),
+ ],
+ ),
+ SizedBox(height: 10.h),
+ isInsuranceExpired
+ ? CustomButton(
+ icon: AppAssets.update_insurance_card_icon,
+ iconColor: AppColors.successColor,
+ iconSize: 15.h,
+ text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}",
+ onPressed: () {},
+ backgroundColor: AppColors.bgGreenColor.withOpacity(0.20),
+ borderColor: AppColors.bgGreenColor.withOpacity(0.0),
+ textColor: AppColors.bgGreenColor,
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 40.h,
+ )
+ : Container(),
+ ],
+ ),
+ ),
+ ).paddingSymmetrical(24.h, 0.h);
+ }
+}
diff --git a/lib/presentation/lab/lab_orders_page.dart b/lib/presentation/lab/lab_orders_page.dart
index 8a0ce26..1581ac3 100644
--- a/lib/presentation/lab/lab_orders_page.dart
+++ b/lib/presentation/lab/lab_orders_page.dart
@@ -9,10 +9,13 @@ import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
+import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
+import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
+import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
import 'package:provider/provider.dart';
@@ -25,7 +28,7 @@ class LabOrdersPage extends StatefulWidget {
class _LabOrdersPageState extends State {
late LabViewModel labProvider;
-
+ List?> labSuggestions = [];
int? expandedIndex;
@override
@@ -57,7 +60,17 @@ class _LabOrdersPageState extends State {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
LocaleKeys.labResults.tr(context: context).toText24(isBold: true),
- Utils.buildSvgWithAssets(icon: AppAssets.search_icon),
+ Utils.buildSvgWithAssets(icon: AppAssets.search_icon).onPress(() {
+ if(model.isLabOrdersLoading){
+ return;
+ }else {
+
+ showCommonBottomSheet(context, child: SearchLabResultsContent(labSuggestionsList: model.labSuggestions),
+ callBackFunc: () {},
+ title: LocaleKeys.searchLabReport.tr(),
+ height: ResponsiveExtension.screenHeight,
+ isCloseButtonVisible: true);
+ } }),
],
),
SizedBox(height: 16.h),
@@ -262,4 +275,13 @@ class _LabOrdersPageState extends State {
return "";
}
}
+ getLabSuggestions(LabViewModel model) {
+ if(model.patientLabOrders.isEmpty){
+ return [];
+ }
+ return model.patientLabOrders.map((m) => m.testDetails).toList();
+
+
+ }
+
}
diff --git a/lib/presentation/lab/search_lab_report.dart b/lib/presentation/lab/search_lab_report.dart
new file mode 100644
index 0000000..d513b35
--- /dev/null
+++ b/lib/presentation/lab/search_lab_report.dart
@@ -0,0 +1,155 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/core/app_assets.dart';
+import 'package:hmg_patient_app_new/core/app_export.dart';
+import 'package:hmg_patient_app_new/extensions/string_extensions.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/buttons/custom_button.dart';
+import 'package:hmg_patient_app_new/widgets/input_widget.dart';
+import 'package:sizer/sizer.dart';
+
+class SearchLabResultsContent extends StatefulWidget {
+ final List labSuggestionsList;
+
+ const SearchLabResultsContent({super.key, required this.labSuggestionsList});
+
+ @override
+ State createState() => _SearchLabResultsContentState();
+}
+
+class _SearchLabResultsContentState extends State {
+ TextEditingController searchEditingController = TextEditingController();
+ List filteredSuggestions = [];
+
+ @override
+ void initState() {
+ super.initState();
+ filteredSuggestions = List.from(widget.labSuggestionsList);
+
+ // Listen for changes in the search field
+ searchEditingController.addListener(() {
+ filterSuggestions();
+ });
+ }
+
+ @override
+ void dispose() {
+ searchEditingController.dispose();
+ super.dispose();
+ }
+
+ void filterSuggestions() {
+ final query = searchEditingController.text.toLowerCase();
+
+ if (query.isEmpty) {
+ setState(() {
+ filteredSuggestions = List.from(widget.labSuggestionsList);
+ });
+ } else {
+ setState(() {
+ filteredSuggestions = widget.labSuggestionsList
+ .where((suggestion) => suggestion.toLowerCase().contains(query))
+ .toList();
+ });
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ TextInputWidget(
+ labelText: "Search lab results",
+ hintText: "Type test name",
+ controller: searchEditingController,
+ isEnable: true,
+ prefix: null,
+ autoFocus: true,
+ isBorderAllowed: false,
+ padding: EdgeInsets.symmetric(
+ vertical: ResponsiveExtension(10).h,
+ horizontal: ResponsiveExtension(15).h,
+ ),
+ ),
+ SizedBox(height: ResponsiveExtension(20).h),
+ if (filteredSuggestions.isNotEmpty) ...[
+ "Suggestions".toText16(isBold: true),
+ const SizedBox(height: 12),
+ ],
+ ],
+ ),
+ ),
+ Expanded(
+ child: SingleChildScrollView(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: Wrap(
+ alignment: WrapAlignment.start,
+ spacing: 10,
+ runSpacing: 10,
+ children: filteredSuggestions
+ .map((label) => SuggestionChip(
+ label: label,
+ onTap: () {
+ searchEditingController.text = label;
+ },
+ ))
+ .toList(),
+ ),
+ ),
+ ),
+ Container(
+ color: Colors.white,
+ padding: EdgeInsets.all(ResponsiveExtension(20).h),
+ child: CustomButton(
+ text: LocaleKeys.search.tr(),
+ icon: AppAssets.search_icon,
+ iconColor: Colors.white,
+ onPressed: () => Navigator.pop(context, searchEditingController.text),
+ ),
+ ),
+ ],
+ );
+ }
+}
+
+class SuggestionChip extends StatelessWidget {
+ final String label;
+ final bool isSelected;
+ final VoidCallback? onTap;
+
+ const SuggestionChip({
+ super.key,
+ required this.label,
+ this.isSelected = false,
+ this.onTap,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return GestureDetector(
+ onTap: onTap,
+ child: Container(
+ padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
+ decoration: BoxDecoration(
+ color: isSelected ? AppColors.primaryRedColor : AppColors.whiteColor,
+ borderRadius: BorderRadius.circular(8),
+ border: Border.all(
+ color: AppColors.greyColor,
+ width: 1,
+ ),
+ ),
+ child: label.toText12(
+ color: isSelected ? Colors.white : Colors.black87,
+ fontWeight: FontWeight.w500,
+ ),
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart
index 9b2265c..4bb5cdb 100644
--- a/lib/presentation/medical_file/medical_file_page.dart
+++ b/lib/presentation/medical_file/medical_file_page.dart
@@ -1,20 +1,28 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
+import 'package:hmg_patient_app_new/core/utils/date_util.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/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/widgets/medical_file_card.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
+import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
+import 'package:provider/provider.dart';
class MedicalFilePage extends StatelessWidget {
- const MedicalFilePage({super.key});
+ MedicalFilePage({super.key});
+
+ late InsuranceViewModel insuranceViewModel;
@override
Widget build(BuildContext context) {
+ insuranceViewModel = Provider.of(context);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
appBar: AppBar(
@@ -161,101 +169,13 @@ class MedicalFilePage extends StatelessWidget {
),
SizedBox(height: 16.h),
//Insurance Tab Data
- Container(
- // height: 150.h,
- width: double.infinity,
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
- color: AppColors.whiteColor,
- borderRadius: 24,
- ),
- child: Padding(
- padding: EdgeInsets.all(16.h),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- "Haroon Amjad".toText18(isBold: true),
- "Policy: 223123345".toText12(isBold: true, color: AppColors.lightGrayColor),
- ],
- ),
- CustomButton(
- icon: AppAssets.cross_circle,
- iconColor: AppColors.primaryRedColor,
- iconSize: 13.h,
- text: "Insurance Expired",
- onPressed: () {},
- backgroundColor: AppColors.primaryRedColor.withOpacity(0.1),
- borderColor: AppColors.primaryRedColor.withOpacity(0.0),
- textColor: AppColors.primaryRedColor,
- fontSize: 10,
- fontWeight: FontWeight.w500,
- borderRadius: 12,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- ],
- ),
- SizedBox(height: 12.h),
- "NCCI".toText12(isBold: true),
- "NC_Dr Sulaiman Al Habib Medical Group".toText12(isBold: true),
- SizedBox(height: 8.h),
- Row(
- children: [
- CustomButton(
- icon: AppAssets.cross_circle,
- iconColor: AppColors.primaryRedColor,
- iconSize: 13.h,
- text: "Expiry: 18 Mar, 2025",
- onPressed: () {},
- backgroundColor: AppColors.primaryRedColor.withOpacity(0.1),
- borderColor: AppColors.primaryRedColor.withOpacity(0.0),
- textColor: AppColors.primaryRedColor,
- fontSize: 10,
- fontWeight: FontWeight.w500,
- borderRadius: 12,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- SizedBox(width: 5.h),
- CustomButton(
- text: "Patient Card ID: 3628599",
- onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 10,
- fontWeight: FontWeight.normal,
- borderRadius: 12,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- ],
- ),
- SizedBox(height: 10.h),
- CustomButton(
- icon: AppAssets.cross_circle,
- iconColor: AppColors.primaryRedColor,
- iconSize: 13.h,
- text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}",
- onPressed: () {},
- backgroundColor: AppColors.bgGreenColor.withOpacity(0.20),
- borderColor: AppColors.bgGreenColor.withOpacity(0.0),
- textColor: AppColors.bgGreenColor,
- fontSize: 14,
- fontWeight: FontWeight.w500,
- borderRadius: 12,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 40.h,
- ),
- ],
- ),
- ),
- ),
+ Consumer(builder: (context, insuranceVM, child) {
+ return insuranceVM.isInsuranceLoading
+ ? const MoviesShimmerWidget()
+ : PatientInsuranceCard(
+ insuranceCardDetailsModel: insuranceVM.patientInsuranceList.first,
+ isInsuranceExpired: DateTime.now().isBefore(DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo)));
+ }),
SizedBox(height: 10.h),
GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, crossAxisSpacing: 13, mainAxisSpacing: 13),
diff --git a/lib/presentation/prescriptions/prescription_detail_page.dart b/lib/presentation/prescriptions/prescription_detail_page.dart
index 0231c67..65dc550 100644
--- a/lib/presentation/prescriptions/prescription_detail_page.dart
+++ b/lib/presentation/prescriptions/prescription_detail_page.dart
@@ -29,6 +29,8 @@ class PrescriptionDetailPage extends StatefulWidget {
class _PrescriptionDetailPageState extends State {
late PrescriptionsViewModel prescriptionsViewModel;
+ bool _isSwitched = false; // Initial state of the switch
+
@override
void initState() {
scheduleMicrotask(() {
@@ -46,267 +48,353 @@ class _PrescriptionDetailPageState extends State {
title: LocaleKeys.prescriptions.tr(context: context).toText18(),
backgroundColor: AppColors.bgScaffoldColor,
),
- body: SingleChildScrollView(
- child: Consumer(builder: (context, prescriptionVM, child) {
- return Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- LocaleKeys.prescriptions.tr(context: context).toText24(isBold: true).paddingSymmetrical(24.h, 0.h),
- SizedBox(height: 24.h),
- Container(
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
- color: AppColors.whiteColor,
- borderRadius: 20.h,
- hasShadow: true,
- ),
- child: Padding(
- padding: EdgeInsets.all(16.h),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- Image.network(
- widget.prescriptionsResponseModel.doctorImageURL!,
- width: 24.h,
- height: 24.h,
- fit: BoxFit.fill,
- ).circle(100),
- SizedBox(width: 8.h),
- Expanded(child: widget.prescriptionsResponseModel.doctorName!.toText16(isBold: true)),
- ],
- ),
- SizedBox(height: 16.h),
- Wrap(
- direction: Axis.horizontal,
- spacing: 6.h,
- runSpacing: 6.h,
- children: [
- Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- CustomButton(
- icon: AppAssets.doctor_calendar_icon,
- iconColor: AppColors.textColor,
- iconSize: 13.h,
- text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(widget.prescriptionsResponseModel.appointmentDate), false),
- onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 12,
- fontWeight: FontWeight.w500,
- borderRadius: 8,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- ],
- ),
- Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- CustomButton(
- text: widget.prescriptionsResponseModel.clinicDescription!,
- onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 12,
- fontWeight: FontWeight.w500,
- borderRadius: 8,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- ],
- ),
- Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- CustomButton(
- icon: AppAssets.rating_icon,
- iconColor: AppColors.ratingColorYellow,
- iconSize: 13.h,
- text: "Rating: ${widget.prescriptionsResponseModel.decimalDoctorRate}",
- onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 12,
- fontWeight: FontWeight.w500,
- borderRadius: 8,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- ],
- ),
- Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- CustomButton(
- text: widget.prescriptionsResponseModel.name!,
- onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 12,
- fontWeight: FontWeight.w500,
- borderRadius: 8,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- ],
- ),
- ],
+ body: Column(
+ children: [
+ Expanded(
+ child: SingleChildScrollView(
+ child: Consumer(builder: (context, prescriptionVM, child) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ LocaleKeys.prescriptions.tr(context: context).toText24(isBold: true).paddingSymmetrical(24.h, 0.h),
+ SizedBox(height: 24.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.h,
+ hasShadow: true,
),
- ],
- ),
- ),
- ).paddingSymmetrical(24.h, 0.h),
- SizedBox(height: 16.h),
- ListView.builder(
- shrinkWrap: true,
- physics: NeverScrollableScrollPhysics(),
- itemCount: prescriptionVM.isPrescriptionsDetailsLoading ? 5 : prescriptionVM.prescriptionDetailsList.length,
- itemBuilder: (context, index) {
- return prescriptionVM.isPrescriptionsDetailsLoading
- ? const MoviesShimmerWidget()
- : AnimationConfiguration.staggeredList(
- position: index,
- duration: const Duration(milliseconds: 500),
- child: SlideAnimation(
- verticalOffset: 100.0,
- child: FadeInAnimation(
- child: AnimatedContainer(
- duration: Duration(milliseconds: 300),
- curve: Curves.easeInOut,
- margin: EdgeInsets.symmetric(vertical: 8.h),
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Image.network(
+ widget.prescriptionsResponseModel.doctorImageURL!,
+ width: 24.h,
+ height: 24.h,
+ fit: BoxFit.fill,
+ ).circle(100),
+ SizedBox(width: 8.h),
+ Expanded(child: widget.prescriptionsResponseModel.doctorName!.toText16(isBold: true)),
+ ],
+ ),
+ SizedBox(height: 16.h),
+ Wrap(
+ direction: Axis.horizontal,
+ spacing: 6.h,
+ runSpacing: 6.h,
+ children: [
+ Row(
+ mainAxisSize: MainAxisSize.min,
children: [
- Padding(
- padding: EdgeInsets.all(16.h),
- child: Container(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- mainAxisSize: MainAxisSize.min,
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- Image.network(
- prescriptionVM.prescriptionDetailsList[index].imageSRCUrl!,
- width: 60.h,
- height: 60.h,
- fit: BoxFit.fill,
- ).circle(100),
- SizedBox(width: 8.h),
- Expanded(
- child: prescriptionVM.prescriptionDetailsList[index].itemDescription!.toText16(isBold: true, maxlines: 2),
- ),
- ],
- ),
- SizedBox(height: 16.h),
- Wrap(
- direction: Axis.horizontal,
- spacing: 6.h,
- runSpacing: 6.h,
- children: [
- Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- CustomButton(
- text: "${LocaleKeys.route.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].route}",
- onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 12,
- fontWeight: FontWeight.w500,
- borderRadius: 8,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- ],
- ),
- Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- CustomButton(
- text: "${LocaleKeys.frequency.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].frequency}",
- onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 12,
- fontWeight: FontWeight.w500,
- borderRadius: 8,
- padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
- ),
- ],
- ),
- Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- CustomButton(
- text: "${LocaleKeys.dailyDoses.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].doseDailyQuantity}",
+ CustomButton(
+ icon: AppAssets.doctor_calendar_icon,
+ iconColor: AppColors.textColor,
+ iconSize: 13.h,
+ text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(widget.prescriptionsResponseModel.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: 30.h,
+ ),
+ ],
+ ),
+ Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ CustomButton(
+ text: widget.prescriptionsResponseModel.clinicDescription!,
+ 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,
+ ),
+ ],
+ ),
+ Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ CustomButton(
+ icon: AppAssets.rating_icon,
+ iconColor: AppColors.ratingColorYellow,
+ iconSize: 13.h,
+ text: "Rating: ${widget.prescriptionsResponseModel.decimalDoctorRate}",
+ 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,
+ ),
+ ],
+ ),
+ Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ CustomButton(
+ text: widget.prescriptionsResponseModel.name!,
+ 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,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ).paddingSymmetrical(24.h, 0.h),
+ SizedBox(height: 16.h),
+ ListView.builder(
+ shrinkWrap: true,
+ physics: NeverScrollableScrollPhysics(),
+ itemCount: prescriptionVM.isPrescriptionsDetailsLoading ? 5 : prescriptionVM.prescriptionDetailsList.length,
+ itemBuilder: (context, index) {
+ return prescriptionVM.isPrescriptionsDetailsLoading
+ ? const MoviesShimmerWidget()
+ : AnimationConfiguration.staggeredList(
+ position: index,
+ duration: const Duration(milliseconds: 500),
+ child: SlideAnimation(
+ verticalOffset: 100.0,
+ child: FadeInAnimation(
+ child: AnimatedContainer(
+ duration: Duration(milliseconds: 300),
+ curve: Curves.easeInOut,
+ margin: EdgeInsets.symmetric(vertical: 8.h),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedBox(height: 16.h),
+ Row(
+ mainAxisSize: MainAxisSize.min,
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ Image.network(
+ prescriptionVM.prescriptionDetailsList[index].imageThumbUrl!,
+ width: 60.h,
+ height: 60.h,
+ fit: BoxFit.fill,
+ ).circle(100),
+ SizedBox(width: 8.h),
+ Expanded(
+ child: prescriptionVM.prescriptionDetailsList[index].itemDescription!.toText16(isBold: true, maxlines: 2),
+ ),
+ ],
+ ).paddingSymmetrical(16.h, 0.h),
+ SizedBox(height: 16.h),
+ Wrap(
+ direction: Axis.horizontal,
+ spacing: 6.h,
+ runSpacing: 6.h,
+ children: [
+ Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ CustomButton(
+ text: "${LocaleKeys.route.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].route}",
+ 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,
+ ),
+ ],
+ ),
+ Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ CustomButton(
+ text: "${LocaleKeys.frequency.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].frequency}",
+ 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,
+ ),
+ ],
+ ),
+ Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ CustomButton(
+ text: "${LocaleKeys.dailyDoses.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].doseDailyQuantity}",
+ 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,
+ ),
+ ],
+ ),
+ Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ CustomButton(
+ text: "${LocaleKeys.days.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].days}",
+ 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,
+ ),
+ ],
+ ),
+ ],
+ ).paddingSymmetrical(16.h, 0.h),
+ SizedBox(height: 8.h),
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Utils.buildSvgWithAssets(icon: AppAssets.prescription_remarks_icon, width: 18.h, height: 18.h),
+ SizedBox(width: 9.h),
+ Expanded(child: "${LocaleKeys.remarks.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].remarks!}".toText10(isBold: true)),
+ ],
+ ).paddingSymmetrical(16.h, 0.h),
+ SizedBox(height: 14.h),
+ Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
+ SizedBox(height: 14.h),
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Utils.buildSvgWithAssets(icon: AppAssets.prescription_reminder_icon, width: 35.h, height: 35.h),
+ SizedBox(width: 8.h),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ LocaleKeys.setReminder.tr(context: context).toText13(isBold: true),
+ "Notify me before the consumption time".toText10(color: AppColors.textColorLight),
+ ],
+ ),
+ SizedBox(width: 12.h),
+ Switch(
+ activeColor: AppColors.successColor,
+ value: prescriptionVM.prescriptionDetailsList[index].hasReminder!,
+ onChanged: (newValue) {
+ setState(() {
+ prescriptionVM.setPrescriptionItemReminder(newValue, prescriptionVM.prescriptionDetailsList[index]);
+ });
+ },
+ ),
+ ],
+ ).paddingSymmetrical(16.h, 0.h),
+ SizedBox(height: 14.h),
+ Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
+ Row(
+ children: [
+ Expanded(
+ child: CustomButton(
+ text: LocaleKeys.checkAvailability.tr(context: context),
onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 12,
+ backgroundColor: AppColors.primaryRedColor.withOpacity(0.1),
+ borderColor: AppColors.primaryRedColor.withOpacity(0.0),
+ textColor: AppColors.primaryRedColor,
+ fontSize: 13,
fontWeight: FontWeight.w500,
- borderRadius: 8,
+ borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
+ height: 40.h,
),
- ],
- ),
- Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- CustomButton(
- text: "${LocaleKeys.days.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].days}",
+ ),
+ SizedBox(width: 16.h),
+ Expanded(
+ child: CustomButton(
+ text: LocaleKeys.readInstructions.tr(context: context),
onPressed: () {},
- backgroundColor: AppColors.greyColor,
- borderColor: AppColors.greyColor,
- textColor: AppColors.blackColor,
- fontSize: 12,
+ backgroundColor: AppColors.primaryRedColor,
+ borderColor: AppColors.primaryRedColor,
+ textColor: AppColors.whiteColor,
+ fontSize: 13,
fontWeight: FontWeight.w500,
- borderRadius: 8,
+ borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
- height: 30.h,
+ height: 40.h,
),
- ],
- ),
- ],
- ),
- SizedBox(height: 8.h),
- Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Utils.buildSvgWithAssets(icon: AppAssets.prescription_remarks_icon, width: 18.h, height: 18.h),
- SizedBox(width: 9.h),
- Expanded(child: "${LocaleKeys.remarks.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].remarks!}".toText10(isBold: true)),
- ],
- )
- ],
- ),
+ ),
+ ],
+ ).paddingSymmetrical(16.h, 16.h),
+ ],
+ )
+ ],
),
- )
- ],
+ ),
+ ),
),
- ),
- ),
- ),
- );
- },
- ).paddingSymmetrical(24.h, 0.h),
- ],
- );
- }),
+ );
+ },
+ ).paddingSymmetrical(24.h, 0.h),
+ ],
+ );
+ }),
+ ),
+ ),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24.h,
+ hasShadow: true,
+ ),
+ child: CustomButton(
+ text: widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! ? LocaleKeys.resendOrder.tr(context: context) : LocaleKeys.prescriptionDeliveryError.tr(context: context),
+ onPressed: () {},
+ backgroundColor: widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! ? AppColors.successColor : AppColors.greyF7Color,
+ borderColor: AppColors.successColor.withOpacity(0.01),
+ textColor: widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! ? AppColors.whiteColor : AppColors.textColor.withOpacity(0.35),
+ fontSize: 16,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 50.h,
+ icon: AppAssets.prescription_refill_icon,
+ iconColor: widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! ? AppColors.whiteColor : AppColors.textColor.withOpacity(0.35),
+ iconSize: 20.h,
+ ).paddingSymmetrical(24.h, 24.h),
+ ),
+ ],
),
);
}
diff --git a/lib/presentation/prescriptions/prescriptions_list_page.dart b/lib/presentation/prescriptions/prescriptions_list_page.dart
index 4aa1a1b..9574f28 100644
--- a/lib/presentation/prescriptions/prescriptions_list_page.dart
+++ b/lib/presentation/prescriptions/prescriptions_list_page.dart
@@ -196,7 +196,7 @@ class _PrescriptionsListPageState extends State {
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
- fontSize: 12,
+ fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
@@ -209,7 +209,7 @@ class _PrescriptionsListPageState extends State {
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
- fontSize: 12,
+ fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
diff --git a/lib/splashPage.dart b/lib/splashPage.dart
index 292b2ee..b852cd4 100644
--- a/lib/splashPage.dart
+++ b/lib/splashPage.dart
@@ -11,6 +11,7 @@ import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
// import 'package:hmg_patient_app_new/presentation/authantication/login.dart';
import 'package:hmg_patient_app_new/presentation/home/landing_page.dart';
+import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart';
@@ -37,7 +38,7 @@ class _SplashScreenState extends State {
LocalNotification.init(onNotificationClick: (payload) {});
Navigator.of(context).pushReplacement(
FadePage(
- page: LandingPage(),
+ page: LandingNavigation(),
// page: LoginScreen(),
),
);
diff --git a/lib/theme/colors.dart b/lib/theme/colors.dart
index 166783d..5cb9ced 100644
--- a/lib/theme/colors.dart
+++ b/lib/theme/colors.dart
@@ -28,6 +28,7 @@ class AppColors {
static const Color bgRedLightColor = Color(0xFFFEE9EA);
static const Color bgGreenColor = Color(0xFF18C273);
static const Color textColor = Color(0xFF2E3039);
+ static const Color textColorLight = Color(0xFF5E5E5E);
static const Color borderOnlyColor = Color(0xFF2E3039);
static const Color dividerColor = Color(0xFFD2D2D2);
static const Color warningColorYellow = Color(0xFFF4A308);
diff --git a/lib/widgets/bottom_navigation/bottom_navigation.dart b/lib/widgets/bottom_navigation/bottom_navigation.dart
index a052bc6..7f45464 100644
--- a/lib/widgets/bottom_navigation/bottom_navigation.dart
+++ b/lib/widgets/bottom_navigation/bottom_navigation.dart
@@ -1,59 +1,103 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
+import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
+import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
class BottomNavigation extends StatelessWidget {
- const BottomNavigation({super.key});
+ final int currentIndex;
+ final ValueChanged onTap;
+
+ const BottomNavigation({
+ super.key,
+ required this.currentIndex,
+ required this.onTap,
+ });
@override
Widget build(BuildContext context) {
- return Container(
- padding: const EdgeInsets.symmetric(vertical: 12),
- decoration: const BoxDecoration(
- color: Colors.white,
- border: Border(
- top: BorderSide(color: AppColors.bottomNAVBorder, width: 0.5),
- ),
-
+ final items = [
+ BottomNavItem(icon: AppAssets.homeBottom, label: LocaleKeys.home.tr()),
+ BottomNavItem(icon: AppAssets.myFilesBottom, label: LocaleKeys.myFiles.tr()),
+ BottomNavItem(
+ icon: AppAssets.bookAppoBottom,
+ label: LocaleKeys.appointment.tr(),
+ iconSize: 27,
+ isSpecial: true,
),
+ BottomNavItem(icon: AppAssets.toDoBottom, label: LocaleKeys.todoList.tr()),
+ BottomNavItem(icon: AppAssets.servicesBottom, label: LocaleKeys.services2.tr()),
+ ];
+
+ return Container(
+ decoration: _containerDecoration,
+ padding: _containerPadding,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
- children: [
- _buildNavItem(AppAssets.homeBottom, LocaleKeys.home.tr()),
- _buildNavItem(AppAssets.myFilesBottom, LocaleKeys.myFiles.tr()),
- _buildNavItem(AppAssets.bookAppoBottom, LocaleKeys.appointment.tr(), iconSize: 32),
- _buildNavItem(AppAssets.toDoBottom, LocaleKeys.todoList.tr()),
- _buildNavItem(AppAssets.servicesBottom, LocaleKeys.services2.tr()),
- ],
+ children: List.generate(
+ items.length,
+ (index) => _buildNavItem(items[index], index),
+ ),
),
);
}
- Widget _buildNavItem(String iconName, String label,{ double iconSize = 24}) {
- return Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- Container(
- padding: const EdgeInsets.all(10),
- child: Utils.buildSvgWithAssets(
- icon: iconName,
- height: iconSize,
- width: iconSize
- ),
- ),
- // const SizedBox(height: 4),
- Text(
- label,
- style: TextStyle(
- fontSize: 13,
- fontWeight: FontWeight.w500,
- color: Colors.black87,
+ Widget _buildNavItem(BottomNavItem item, int index) {
+ final bool isSelected = currentIndex == index;
+
+ return GestureDetector(
+ onTap: () => onTap(index),
+ behavior: HitTestBehavior.opaque,
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Center(
+ child: Utils.buildSvgWithAssets(
+ icon: item.icon,
+ height: item.iconSize.h,
+ width: item.iconSize.h,
+ // iconColor: isSelected ? Colors.black87 : Colors.black87,
+ ),
+ ),
+ const SizedBox(height: 10),
+ item.label.toText12(
+ fontWeight:FontWeight.w500,
+ // color: Colors.black87,
+ // textAlign: TextAlign.center,
),
- ),
- ],
+ SizedBox(height: item.isSpecial ? 5:0 )
+ ],
+
+ ),
);
}
}
+
+class BottomNavItem {
+ final String icon;
+ final String label;
+ final double iconSize;
+ final bool isSpecial;
+
+ const BottomNavItem({
+ required this.icon,
+ required this.label,
+ this.iconSize = 21,
+ this.isSpecial = false,
+ });
+}
+
+// Constants
+const EdgeInsets _containerPadding = EdgeInsets.all(15);
+const BoxDecoration _containerDecoration = BoxDecoration(
+ color: Colors.white,
+ border: Border(
+ top: BorderSide(
+ color: AppColors.bottomNAVBorder,
+ width: 0.5,
+ ),
+ ),
+);
diff --git a/lib/widgets/bottomsheet/generic_bottom_sheet.dart b/lib/widgets/bottomsheet/generic_bottom_sheet.dart
index 6ca2014..74062ef 100644
--- a/lib/widgets/bottomsheet/generic_bottom_sheet.dart
+++ b/lib/widgets/bottomsheet/generic_bottom_sheet.dart
@@ -118,13 +118,16 @@ class _GenericBottomSheetState extends State {
padding: EdgeInsets.all(8.h),
keyboardType: widget.isForEmail ? TextInputType.emailAddress : TextInputType.number,
onChange: (value) {
- widget.textController!.text = value!;
if (widget.onChange != null) {
widget.onChange!(value);
}
},
+ onCountryChange: (value) {
+ if (widget.onCountryChange != null) {
+ widget.onCountryChange!(value);
+ }
+ },
isEnable: true,
- // focusNode: widget.myFocusNode,
isReadOnly: widget.isFromSavedLogin,
prefix: widget.isForEmail ? null : widget.countryCode,
isBorderAllowed: false,
diff --git a/lib/widgets/common_bottom_sheet.dart b/lib/widgets/common_bottom_sheet.dart
new file mode 100644
index 0000000..f6039eb
--- /dev/null
+++ b/lib/widgets/common_bottom_sheet.dart
@@ -0,0 +1,88 @@
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/core/app_assets.dart';
+import 'package:hmg_patient_app_new/core/app_export.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
+import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
+import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
+
+void showCommonBottomSheet(BuildContext context,
+ {required Widget child, required VoidCallback callBackFunc, String? title, required double height, bool isCloseButtonVisible = true, bool isFullScreen = true}) {
+ showModalBottomSheet(
+ sheetAnimationStyle: AnimationStyle(
+ duration: Duration(milliseconds: 500), // Custom animation duration
+ reverseDuration: Duration(milliseconds: 300), // Custom reverse animation duration
+ ),
+ context: context,
+ isScrollControlled: true,
+ showDragHandle: false,
+ backgroundColor: AppColors.scaffoldBgColor,
+ builder: (BuildContext context) {
+ return Container(
+ height: height,
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.scaffoldBgColor, borderRadius: 24.h),
+ child: ButtonSheetContent(
+ title: title!,
+ isCloseButtonVisible: isCloseButtonVisible,
+ isFullScreen: isFullScreen,
+ child: child,
+ ),
+ );
+ }).then((value) {
+ callBackFunc();
+ });
+}
+
+class ButtonSheetContent extends StatelessWidget {
+ final Widget child;
+ final String title;
+ final bool isCloseButtonVisible;
+ final bool isFullScreen;
+
+ const ButtonSheetContent({super.key, required this.child, required this.isCloseButtonVisible, required this.title, required this.isFullScreen});
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ // SizedBox(
+ // height: 20.h,
+ // ),
+ // Center(
+ // child: Container(
+ // margin: const EdgeInsets.only(top: 18, bottom: 12),
+ // height: 4,
+ // width: 40.h,
+ // decoration: BoxDecoration(
+ // color: Colors.grey[400],
+ // borderRadius: BorderRadius.circular(2),
+ // ),
+ // ),
+ // ),
+
+ // Close button
+ isCloseButtonVisible && isFullScreen
+ ? Padding(
+ padding: EdgeInsets.symmetric(horizontal: 16),
+ child: Utils.buildSvgWithAssets(icon: AppAssets.closeBottomNav, width: 32, height: 32).onPress(() {
+ Navigator.of(context).pop();
+ }),
+ )
+ : SizedBox(),
+
+ isFullScreen
+ ? Column(
+ children: [
+ SizedBox(height: 20.h),
+ Padding(padding: EdgeInsets.symmetric(horizontal: 16.h), child: title.toText24(isBold: true)),
+ SizedBox(height: 16.h),
+ ],
+ )
+ : SizedBox(),
+
+ Expanded(child: child)
+ ],
+ );
+ }
+}
diff --git a/lib/widgets/input_widget.dart b/lib/widgets/input_widget.dart
index e34ba0c..0f520c6 100644
--- a/lib/widgets/input_widget.dart
+++ b/lib/widgets/input_widget.dart
@@ -1,11 +1,16 @@
import 'package:flutter/material.dart';
+import 'package:hijri_gregorian_calendar/hijri_gregorian_calendar.dart';
+import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
+import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/dropdown/country_dropdown_widget.dart';
+import '../core/dependencies.dart';
+
// TODO: Import AppColors if bgRedColor is defined there
// import 'package:hmg_patient_app_new/core/ui_utils/app_colors.dart';
@@ -28,11 +33,13 @@ class TextInputWidget extends StatelessWidget {
final bool isCountryDropDown;
final bool hasError;
final String? errorMessage;
+ Function(CountryEnum)? onCountryChange;
+ SelectionTypeEnum? selectionType;
// final List countryList;
// final Function(Country)? onCountryChange;
- const TextInputWidget({
+ TextInputWidget({
Key? key,
required this.labelText,
required this.hintText,
@@ -52,6 +59,8 @@ class TextInputWidget extends StatelessWidget {
this.isCountryDropDown = false,
this.hasError = false,
this.errorMessage,
+ this.onCountryChange,
+ this.selectionType,
// this.countryList = const [],
// this.onCountryChange,
}) : super(key: key);
@@ -74,30 +83,28 @@ class TextInputWidget extends StatelessWidget {
child: Row(
textDirection: Directionality.of(context),
children: [
- if (isAllowLeadingIcon && leadingIcon != null && !isCountryDropDown)
- _buildLeadingIcon(context),
- isCountryDropDown
- ? CustomCountryDropdown(
- countryList: CountryEnum.values,
- onCountryChange: (CountryEnum? value) {
-
- },
- isRtl: Directionality.of(context) == TextDirection.rtl,
- isFromBottomSheet: isCountryDropDown,
- isEnableTextField: true,
- onPhoneNumberChanged:(val){},
- textField: _buildTextField(context),
- )
- : Expanded(
- child: Column(
- mainAxisSize: MainAxisSize.min,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- _buildLabelText(),
- _buildTextField(context),
- ],
- ),
+ if (isAllowLeadingIcon && leadingIcon != null && !isCountryDropDown) _buildLeadingIcon(context),
+ isCountryDropDown
+ ? CustomCountryDropdown(
+ countryList: CountryEnum.values,
+ onCountryChange: onCountryChange,
+ isRtl: Directionality.of(context) == TextDirection.rtl,
+ isFromBottomSheet: isCountryDropDown,
+ isEnableTextField: true,
+ onPhoneNumberChanged: onChange,
+ // textField: _buildTextField(context),
+ )
+ : Expanded(
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ _buildLabelText(),
+ _buildTextField(context),
+ ],
),
+ ),
+ if (selectionType == SelectionTypeEnum.calendar) _buildTrailingIcon(context),
],
),
),
@@ -129,6 +136,38 @@ class TextInputWidget extends StatelessWidget {
child: Utils.buildSvgWithAssets(icon: leadingIcon!));
}
+ Widget _buildTrailingIcon(BuildContext context) {
+ final AppState appState = getIt.get();
+ return Container(
+ height: 40.h,
+ width: 40.h,
+ margin: EdgeInsets.zero,
+ padding: EdgeInsets.all(8.h),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 10.h, color: AppColors.whiteColor),
+ child: GestureDetector(
+ onTap: () async {
+ bool isGregorian = true;
+ final picked = await showHijriGregBottomSheet(context,
+ switcherIcon: Utils.buildSvgWithAssets(icon: AppAssets.language, width: 24.h, height: 24.h),
+ language: appState.getLanguageCode()!,
+ initialDate: DateTime.now(),
+ okWidget: Padding(padding: EdgeInsets.only(right: 8.h), child: Utils.buildSvgWithAssets(icon: AppAssets.confirm, width: 24.h, height: 24.h)),
+ cancelWidget: Padding(padding: EdgeInsets.only(right: 8.h), child: Utils.buildSvgWithAssets(icon: AppAssets.cancel, iconColor: Colors.white, width: 24.h, height: 24.h)),
+ onCalendarTypeChanged: (bool value) {
+ isGregorian = value;
+ });
+ if (picked != null && onChange != null) {
+ // if (onCalendarTypeChanged != null) {
+ // onCalendarTypeChanged.call(isGregorian);
+ // }
+ onChange!(picked.toIso8601String());
+ }
+ },
+ child: Utils.buildSvgWithAssets(icon: AppAssets.calendar),
+ ),
+ );
+ }
+
Widget _buildLabelText() {
return Text(
labelText,
@@ -155,23 +194,11 @@ class TextInputWidget extends StatelessWidget {
onChanged: onChange,
focusNode: focusNode,
autofocus: autoFocus,
- style: TextStyle(
- fontSize: 14.fSize,
- height: 21 / 14,
- fontWeight: FontWeight.w500,
- color: AppColors.textColor,
- letterSpacing: -0.2,
- ),
+ style: TextStyle(fontSize: 14.fSize, height: 21 / 14, fontWeight: FontWeight.w500, color: AppColors.textColor, letterSpacing: -0.2),
decoration: InputDecoration(
isDense: true,
hintText: hintText,
- hintStyle: TextStyle(
- fontSize: 14.fSize,
- height: 21 / 16,
- fontWeight: FontWeight.w500,
- color: Color(0xff898A8D),
- letterSpacing: -0.2,
- ),
+ hintStyle: TextStyle(fontSize: 14.fSize, height: 21 / 16, fontWeight: FontWeight.w500, color: Color(0xff898A8D), letterSpacing: -0.2),
prefixIconConstraints: BoxConstraints(minWidth: 45.h),
prefixIcon: prefix == null
? null
diff --git a/pubspec.lock b/pubspec.lock
index a6bf33b..feed2d0 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -29,10 +29,10 @@ packages:
dependency: transitive
description:
name: async
- sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
+ sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
url: "https://pub.dev"
source: hosted
- version: "2.13.0"
+ version: "2.12.0"
audio_session:
dependency: transitive
description:
@@ -1599,10 +1599,10 @@ packages:
dependency: transitive
description:
name: vm_service
- sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
+ sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
url: "https://pub.dev"
source: hosted
- version: "15.0.0"
+ version: "14.3.1"
web:
dependency: "direct main"
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index a2637f5..54ae213 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -82,7 +82,6 @@ flutter:
- assets/
- assets/fonts/
- assets/langs/
- - assets/json/
- assets/images/
- assets/images/svg/
- assets/images/png/