You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
HMG_Patient_App/lib/uitl/utils.dart

1450 lines
51 KiB
Dart

import 'dart:convert';
import 'dart:core';
import 'dart:io';
import 'dart:typed_data';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:badges/badges.dart' as badge_import;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:crypto/crypto.dart' as crypto;
import 'package:hmg_patient_app/analytics/google-analytics.dart';
import 'package:hmg_patient_app/config/config.dart';
import 'package:hmg_patient_app/config/shared_pref_kay.dart';
import 'package:hmg_patient_app/core/model/privilege/ProjectDetailListModel.dart';
import 'package:hmg_patient_app/core/service/client/base_app_client.dart';
import 'package:hmg_patient_app/core/viewModels/project_view_model.dart';
import 'package:hmg_patient_app/extensions/string_extensions.dart';
import 'package:hmg_patient_app/models/Authentication/authenticated_user.dart';
import 'package:hmg_patient_app/new_ui/new_ext.dart';
import 'package:hmg_patient_app/pages/AlHabibMedicalService/ancillary-orders/ancillaryOrders.dart';
import 'package:hmg_patient_app/pages/MyAppointments/MyAppointments.dart';
import 'package:hmg_patient_app/pages/insurance/insurance_approval_screen.dart';
import 'package:hmg_patient_app/pages/insurance/insurance_card_screen.dart';
import 'package:hmg_patient_app/pages/insurance/insurance_update_screen.dart';
import 'package:hmg_patient_app/pages/landing/landing_page_pharmcy.dart';
import 'package:hmg_patient_app/pages/medical/active_medications/ActiveMedicationsPage.dart';
import 'package:hmg_patient_app/pages/medical/allergies_page.dart';
import 'package:hmg_patient_app/pages/medical/ask_doctor/ask_doctor_home_page.dart';
import 'package:hmg_patient_app/pages/medical/balance/my_balance_page.dart';
import 'package:hmg_patient_app/pages/medical/dental_instructions_page.dart';
import 'package:hmg_patient_app/pages/medical/doctor/doctor_home_page.dart';
import 'package:hmg_patient_app/pages/medical/eye/EyeMeasurementsPage.dart';
import 'package:hmg_patient_app/pages/medical/labs/labs_home_page.dart';
import 'package:hmg_patient_app/pages/medical/my_invoices/my_invoice_page.dart';
import 'package:hmg_patient_app/pages/medical/my_trackers/my_trackers.dart';
import 'package:hmg_patient_app/pages/medical/patient_sick_leave_page.dart';
import 'package:hmg_patient_app/pages/medical/prescriptions/prescriptions_home_page.dart';
import 'package:hmg_patient_app/pages/medical/radiology/radiology_home_page.dart';
import 'package:hmg_patient_app/pages/medical/reports/monthly_reports.dart';
import 'package:hmg_patient_app/pages/medical/reports/report_home_page.dart';
import 'package:hmg_patient_app/pages/medical/smart_watch_health_data/smart_watch_instructions.dart';
import 'package:hmg_patient_app/pages/medical/vital_sign/vital_sign_details_screen.dart';
import 'package:hmg_patient_app/pages/vaccine/my_vaccines_screen.dart';
import 'package:hmg_patient_app/theme/colors.dart';
import 'package:hmg_patient_app/uitl/translations_delegate_base.dart';
import 'package:hmg_patient_app/uitl/utils_new.dart';
import 'package:hmg_patient_app/widgets/data_display/medical/medical_profile_item.dart';
import 'package:hmg_patient_app/widgets/dialogs/alert_dialog.dart';
import 'package:hmg_patient_app/widgets/dialogs/covid_consent_dialog.dart';
import 'package:hmg_patient_app/widgets/transitions/fade_page.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_api_availability/google_api_availability.dart';
import 'package:lottie/lottie.dart';
import 'dart:math' show asin, cos, pi, pow, sin, sqrt;
// import 'package:flutter_hms_gms_availability/flutter_hms_gms_availability.dart';
import 'package:provider/provider.dart';
import 'package:smooth_corner/smooth_corner.dart';
import 'package:url_launcher/url_launcher.dart';
import '../Constants.dart';
import '../locator.dart';
import '../new_ui/exception_widget/ExceptionBottomSheet.dart';
import '../new_ui/otp/otp_validation_bootmsheet_widget.dart';
import 'app_shared_preferences.dart';
import 'app_toast.dart';
import 'gif_loader_dialog_utils.dart';
import 'navigation_service.dart';
AppSharedPreferences sharedPref = new AppSharedPreferences();
enum OTPType { sms, whatsapp }
enum Country { saudiArabia, unitedArabEmirates }
enum SelectionType { dropdown, calendar }
enum GenderType { male, female }
enum MaritalStatusType { single, married, divorced, widowed }
class Utils {
static int? onOtpBtnPressed(OTPType type, String? phoneNumber, BuildContext context) {
if (phoneNumber == null || phoneNumber.isEmpty) {
context.showBottomSheet(
child: ExceptionBottomSheet(
message: TranslationBase.of(context).pleaseEnterMobile,
onOkPressed: () {
Navigator.of(context).pop();
},
));
return null;
} else if (!Utils.validateMobileNumber(phoneNumber)) {
context.showBottomSheet(
child: ExceptionBottomSheet(
message: TranslationBase.of(context).pleaseEnterValidMobile,
showCancel: false,
onOkPressed: () {
Navigator.of(context).pop();
},
),
);
return null;
}
return type == OTPType.sms ? 1 : 4;
}
static bool validateIqama(String iqamaNumber) {
String cleanedIqama = iqamaNumber.replaceAll(RegExp(r'[^0-9]'), '');
if (cleanedIqama.length != 10) {
return false;
}
int firstDigit = int.parse(cleanedIqama[0]);
if (firstDigit != 2 && firstDigit != 1) {
return false;
}
int sum = 0;
for (int i = 0; i < 10; i++) {
int digit = int.parse(cleanedIqama[i]);
int weight = (i % 2 == 0) ? 2 : 1; // Alternate weights: 2, 1, 2, 1...
int product = digit * weight;
sum += (product > 9) ? product - 9 : product; // Sum digits if product > 9
}
return sum % 10 == 0;
}
static bool validateUaeNationalId(String id) {
// Must be exactly 15 digits
final regex = RegExp(r'^784\d{4}\d{7}\d{1}$');
return regex.hasMatch(id);
}
static bool validateMobileNumber(String number) {
final regex = RegExp(r'^(05\d{8}|5\d{8})$');
return regex.hasMatch(number);
}
static void changeAppLanguage({required BuildContext context}) {
sharedPref.setBool(IS_ROBOT_INIT, false);
sharedPref.remove(CLINICS_LIST);
if (context.read<ProjectViewModel>().isArabic) {
context.read<ProjectViewModel>().changeLanguage('en');
locator<GAnalytics>().hamburgerMenu.logMenuItemClick('change language to english');
} else {
context.read<ProjectViewModel>().changeLanguage('ar');
locator<GAnalytics>().hamburgerMenu.logMenuItemClick('change language to arabic');
}
}
static String formatDateToDisplay(String isoDateString) {
try {
final dateTime = DateTime.parse(isoDateString);
final day = dateTime.day.toString().padLeft(2, '0');
final year = dateTime.year.toString();
// Map month number to short month name
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
final month = monthNames[dateTime.month - 1];
return '$day $month, $year';
return '$day $month, $year';
} catch (e) {
print("Error formatting date: $e");
return "";
}
}
static String formatHijriDateToDisplay(String hijriDateString) {
try {
// Assuming hijriDateString is in the format yyyy-MM-dd
final datePart = hijriDateString.split("T").first;
final parts = datePart.split('-');
if (parts.length != 3) return "";
final day = parts[2].padLeft(2, '0');
final year = parts[0];
// Map month number to short month name (Hijri months)
const hijriMonthNames = ['Muharram', 'Safar', 'Rabi I', 'Rabi II', 'Jumada I', 'Jumada II', 'Rajab', 'Sha\'ban', 'Ramadan', 'Shawwal', 'Dhu al-Qi\'dah', 'Dhu al-Hijjah'];
final monthIndex = int.tryParse(parts[1]) ?? 1;
final month = hijriMonthNames[monthIndex - 1];
return '$day $month, $year';
} catch (e) {
print("Error formatting hijri date: $e");
return "";
}
}
static String formatDateToUsage(String isoDateString) {
try {
final dateTime = DateTime.parse(isoDateString);
final day = dateTime.day.toString().padLeft(2, '0');
final month = dateTime.month.toString().padLeft(2, '0');
final year = dateTime.year.toString();
return '$day-$month-$year';
} catch (e) {
print("Error formatting date: $e");
return "";
}
}
static Widget showLottie({
required BuildContext context,
String assetPath = 'assets/icons/no_property.json',
double? height,
double? width,
BoxFit fit = BoxFit.cover,
Alignment alignment = Alignment.center,
bool repeat = false,
bool animate = true,
void Function(LottieComposition)? onLoaded,
}) {
return Lottie.asset(assetPath,
height: height ?? MediaQuery.of(context).size.height * 0.26,
width: width ?? MediaQuery.of(context).size.width,
fit: fit,
alignment: alignment,
repeat: repeat,
animate: animate,
onLoaded: onLoaded);
}
static var navigationProjectsList = [
{
"Desciption": "Sahafa Hospital",
"DesciptionN": "مستشفى الصحافة",
"ID": 130,
"LegalName": "Sahafa Hospital",
"LegalNameN": "مستشفى الصحافة",
"Name": "Sahafa Hospital",
"NameN": "مستشفى الصحافة",
"PhoneNumber": "+966115222222",
"SetupID": "013311",
"DistanceInKilometers": 0,
"HasVida3": false,
"IsActive": true,
"IsHmg": true,
"IsVidaPlus": false,
"Latitude": "24.8113774",
"Longitude": "46.6239813",
"MainProjectID": 130,
"ProjectOutSA": false,
"UsingInDoctorApp": false
}
];
///show custom Error Toast
/// [message] to show for user
static showErrorToast([String? message, BuildContext? context]) {
String localMsg = generateContactAdminMessage();
if (message != null) {
localMsg = message.toString();
}
AppToast.showErrorToast(message: localMsg, localContext: context);
}
/// Check The Internet Connection
// static Future<bool> checkConnection({bool bypassConnectionCheck = false}) async {
// if (bypassConnectionCheck) return true;
// //return true;
// ConnectivityResult connectivityResult = await (Connectivity().checkConnectivity());
// if ((connectivityResult == ConnectivityResult.mobile) || (connectivityResult == ConnectivityResult.wifi)) {
// return true;
// } else {
// return false;
// }
// }
static Future<bool> checkConnection({bool bypassConnectionCheck = false}) async {
if (bypassConnectionCheck) return true;
List<ConnectivityResult> connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult.contains(ConnectivityResult.mobile) || connectivityResult.contains(ConnectivityResult.wifi)) {
return true;
} else {
return false;
}
}
/// generate Contact Admin Message
static generateContactAdminMessage([err]) {
String localMsg = 'Something wrong happened, please contact the admin';
if (err != null) {
localMsg = localMsg + '\n \n' + err.toString();
}
return localMsg;
}
/// hides the keyboard if its already open
static hideKeyboard(BuildContext context) {
FocusScope.of(context).unfocus();
}
static showPermissionConsentDialog(BuildContext context, String message, VoidCallback? onTap, {VoidCallback? onConsentDeclined}) {
showDialog(
context: context,
builder: (cxt) => CovidConsentDialog(
okTitle: TranslationBase.of(context).acceptLbl,
title: TranslationBase.of(context).covidConsentHeader,
message: message,
onTap: onTap!,
onConsentDeclined: onConsentDeclined!,
));
}
bool isSAUDIIDValid(String id, type) {
if (type == 1) {
if (id == null) {
return false;
}
try {
id = id.toString();
id = id.trim();
var returnValue = int.parse(id);
var sum = 0;
if (returnValue > 0) {
var type = int.parse(id[0]);
if (id.length != 10) {
return false;
}
if (type != 2 && type != 1) {
return false;
}
for (var i = 0; i < 10; i++) {
if (i % 2 == 0) {
var a = id[i];
var x = int.parse(a) * 2;
var b = x.toString();
if (b.length == 1) {
b = "0" + b;
}
sum += int.parse(b[0]) + int.parse(b[1]);
} else {
sum += int.parse(id[i]);
}
}
return sum % 10 == 0;
}
} catch (err) {}
return false;
} else {
return true;
}
}
static String getAppointmentTransID(int projectID, int clinicID, int appoNo, {bool isAddMilliseconds = true}) {
String currentMillis = DateTime.now().millisecondsSinceEpoch.toString();
return projectID.toString() + '-' + clinicID.toString() + '-' + appoNo.toString() + (isAddMilliseconds ? '-' + currentMillis.substring(currentMillis.length - 5, currentMillis.length) : "");
}
static String getAdvancePaymentTransID(int projectID, int fileNumber) {
return projectID.toString() + '-' + fileNumber.toString() + '-' + DateTime.now().millisecondsSinceEpoch.toString();
}
bool validateIDBox(String value, int type) {
String pattern = loginIDPattern(type); // Get the pattern based on type
RegExp regex = RegExp(pattern);
return regex.hasMatch(value);
}
String loginIDPattern(int loginType) {
var length = loginType == 1 ? 10 : 1;
return "([0-9]{" + length.toString() + "}\$)";
}
static showProgressDialog(context, [String message = "Loading..."]) async {
// pr = ProgressDialog(context,
// type: ProgressDialogType.Normal, isDismissible: false, showLogs: false);
// pr.style(
// message: message,
// borderRadius: 10.0,
// backgroundColor: Colors.white,
// elevation: 10.0,
// insetAnimCurve: Curves.easeInOut,
// progress: 0.0,
// maxProgress: 100.0,
// progressTextStyle: TextStyle(
// color: Colors.black, fontSize: 13.0, fontWeight: FontWeight.w400),
// messageTextStyle: TextStyle(
// color: Colors.black, fontSize: 19.0, fontWeight: FontWeight.w600));
// if (!pr.isShowing()) {
// await pr.show();
// } else {
// await pr.hide();
// await pr.show();
// }
}
static hideProgressDialog() async {
// if (pr.isShowing()) {
// await pr.hide();
// }
}
static getPhoneNumberWithoutZero(String number) {
String newNumber = "";
if (number.startsWith('0')) {
newNumber = number.substring(1);
} else {
newNumber = number;
}
return newNumber;
}
static Uint8List dataFromBase64String(String base64String) {
return base64Decode(base64String);
}
static validEmail(email) {
return RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(email);
}
static List<Widget> myMedicalList({ProjectViewModel? projectViewModel, BuildContext? context, bool? isLogin, count, Function? onWeCareClick}) {
List<Widget> medical = [];
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(5) ? Navigator.push(context, FadePage(page: MyAppointments())) : null,
child: isLogin!
? Stack(children: [
Container(
width: double.infinity,
height: double.infinity,
child: MedicalProfileItem(
title: TranslationBase.of(context!).myAppointments,
imagePath: 'appointment_list.svg',
subTitle: TranslationBase.of(context).myAppointmentsList,
hasBadge: true,
isEnable: projectViewModel!.havePrivilege(5)),
),
projectViewModel.isArabic
? !projectViewModel.user.isFamily
? Positioned(
left: 8,
top: 4,
child: badge_import.Badge(
badgeAnimation: badge_import.BadgeAnimation.fade(toAnimate: false),
badgeStyle: badge_import.BadgeStyle(
elevation: 0,
shape: badge_import.BadgeShape.circle,
badgeColor: secondaryColor!.withOpacity(1.0),
borderRadius: BorderRadius.circular(8),
),
position: badge_import.BadgePosition.topEnd(),
badgeContent: Container(
padding: EdgeInsets.all(2.0),
child: Text(count.toString(), style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 12.0)),
),
),
)
: Container()
: !projectViewModel.user!.isFamily
? Positioned(
right: 8,
top: 4,
child: badge_import.Badge(
position: badge_import.BadgePosition.topEnd(),
badgeAnimation: badge_import.BadgeAnimation.fade(toAnimate: false),
badgeStyle: badge_import.BadgeStyle(
elevation: 0,
shape: badge_import.BadgeShape.circle,
badgeColor: secondaryColor!.withOpacity(1.0),
borderRadius: BorderRadius.circular(8),
),
badgeContent: Container(
padding: EdgeInsets.all(2.0),
child: Text(count.toString(), style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 12.0)),
),
),
)
: Container(),
])
: MedicalProfileItem(
title: TranslationBase.of(context!).myAppointments,
imagePath: 'appointment_list.svg',
subTitle: TranslationBase.of(context!).myAppointmentsList,
hasBadge: true,
isEnable: projectViewModel!.havePrivilege(5),
),
));
if (projectViewModel.havePrivilege(10)) {
medical.add(InkWell(
onTap: () => Navigator.push(context, FadePage(page: LabsHomePage())),
child: MedicalProfileItem(
title: TranslationBase.of(context).lab,
imagePath: 'lab_result.svg',
subTitle: TranslationBase.of(context).labSubtitle,
),
));
}
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(7) ? Navigator.push(context, FadePage(page: RadiologyHomePage())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).radiology,
imagePath: 'radiology.svg',
subTitle: TranslationBase.of(context).radiologySubtitle,
isEnable: projectViewModel.havePrivilege(7),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(12) ? Navigator.push(context, FadePage(page: HomePrescriptionsPage())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).medicines,
imagePath: 'medicine_prescription.svg',
subTitle: TranslationBase.of(context).medicinesSubtitle,
isEnable: projectViewModel.havePrivilege(12),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(25)
? Navigator.push(
context,
FadePage(page: VitalSignDetailsScreen()),
)
: null,
child: MedicalProfileItem(
title: TranslationBase.of(context).vitalSigns,
imagePath: 'vital_signs.svg',
subTitle: TranslationBase.of(context).vitalSignsSubtitle,
isEnable: projectViewModel.havePrivilege(25),
),
));
medical.add(InkWell(
onTap: () {
if (projectViewModel.havePrivilege(48)) Navigator.push(context, FadePage(page: ActiveMedicationsPage()));
},
child: MedicalProfileItem(
title: TranslationBase.of(context).myMedical,
imagePath: 'active_medication.svg',
subTitle: TranslationBase.of(context).myMedicalSubtitle,
isEnable: projectViewModel.havePrivilege(48),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(6)
? Navigator.push(
context,
FadePage(
page: DoctorHomePage(),
),
)
: null,
child:
MedicalProfileItem(title: TranslationBase.of(context).myDoctor, imagePath: 'my_doc.svg', subTitle: TranslationBase.of(context).myDoctorSubtitle, isEnable: projectViewModel.havePrivilege(6)),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(14) ? Navigator.push(context, FadePage(page: MyInvoices())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).invoicesList,
imagePath: 'invoice_list.svg',
subTitle: TranslationBase.of(context).myInvoice,
isEnable: projectViewModel.havePrivilege(14),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(85) ? Navigator.push(context, FadePage(page: AnicllaryOrders())) : null,
// onTap: () => Navigator.push(context, FadePage(page: AnicllaryOrders())),
child: MedicalProfileItem(
title: TranslationBase.of(context).anicllaryOrders,
imagePath: 'ancillary.svg',
isPngImage: false,
subTitle: TranslationBase.of(context).myInvoice,
isEnable: projectViewModel.havePrivilege(85),
),
));
medical.add(InkWell(
onTap: () => onWeCareClick!(),
child: MedicalProfileItem(
title: TranslationBase.of(context).wecare,
imagePath: 'assets/images/new-design/virtual_tour_icon.png',
isPngImage: true,
subTitle: TranslationBase.of(context).service,
isEnable: projectViewModel.havePrivilege(105),
),
));
medical.add(InkWell(
onTap: () {
Navigator.push(context, FadePage(page: DentalInstructionsPage()));
},
child: MedicalProfileItem(
title: TranslationBase.of(context).myinstructions,
imagePath: 'medical_instructions.svg',
isPngImage: false,
subTitle: TranslationBase.of(context).service,
isEnable: projectViewModel.havePrivilege(106),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(14) ? Navigator.push(context, FadePage(page: EyeMeasurementsPage())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).eye,
imagePath: 'eye_measurement.svg',
subTitle: TranslationBase.of(context).eyeSubtitle,
isEnable: projectViewModel.havePrivilege(14),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(22)
? Navigator.push(
context,
FadePage(
page: InsuranceCard(
appointmentNo: 0,
)))
: null,
child: MedicalProfileItem(
title: TranslationBase.of(context).insurance,
imagePath: 'insurance_card.svg',
subTitle: TranslationBase.of(context).insuranceSubtitle,
isEnable: projectViewModel.havePrivilege(22),
),
));
medical.add(InkWell(
onTap: () {
Navigator.push(context, FadePage(page: InsuranceUpdate()));
},
child: MedicalProfileItem(
title: TranslationBase.of(context).updateInsurance,
imagePath: 'insurance_card.svg',
subTitle: TranslationBase.of(context).updateInsuranceSubtitle,
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(18)
? Navigator.push(
context,
FadePage(
page: InsuranceApproval(
appointmentNo: 0,
)))
: null,
child: MedicalProfileItem(
title: TranslationBase.of(context).insuranceApproval,
imagePath: 'insurance_approval.svg',
subTitle: TranslationBase.of(context).insuranceApprovalSubtitle,
isEnable: projectViewModel.havePrivilege(18),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(23) ? Navigator.push(context, FadePage(page: AllergiesPage())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).allergies,
imagePath: 'allergies_diagnosed.svg',
subTitle: TranslationBase.of(context).allergiesSubtitle,
isEnable: projectViewModel.havePrivilege(23),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(26) ? Navigator.push(context, FadePage(page: MyVaccines())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).myVaccines,
imagePath: 'vaccine_list.svg',
subTitle: TranslationBase.of(context).myVaccinesSubtitle,
isEnable: projectViewModel.havePrivilege(26),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(20) ? Navigator.push(context, FadePage(page: HomeReportPage())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).medical,
imagePath: 'medical_report.svg',
subTitle: TranslationBase.of(context).medicalSubtitle,
isEnable: projectViewModel.havePrivilege(20),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(19) ? Navigator.push(context, FadePage(page: MonthlyReportsPage())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).monthly,
imagePath: 'monthly_report.svg',
subTitle: TranslationBase.of(context).monthlySubtitle,
isEnable: projectViewModel.havePrivilege(19),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(16) ? Navigator.push(context, FadePage(page: PatientSickLeavePage())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).sick,
imagePath: 'sick_leave.svg',
subTitle: TranslationBase.of(context).sickSubtitle,
isEnable: projectViewModel.havePrivilege(16),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(47) ? Navigator.push(context, FadePage(page: MyBalancePage())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).myBalance,
imagePath: 'balance_credit.svg',
subTitle: TranslationBase.of(context).myBalanceSubtitle,
isEnable: projectViewModel.havePrivilege(47),
),
));
// medical.add(MedicalProfileItem(
// title: TranslationBase.of(context).patientCall,
// imagePath: 'medical_history_icon.png',
// subTitle: TranslationBase.of(context).patientCallSubtitle,
// isEnable: projectViewModel.havePrivilege(61),
// ));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(24) ? Navigator.push(context, FadePage(page: MyTrackers())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).myTrackers,
imagePath: 'tracker.svg',
subTitle: TranslationBase.of(context).myTrackersSubtitle,
isEnable: projectViewModel.havePrivilege(24),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(30) ? Navigator.push(context, FadePage(page: SmartWatchInstructions())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).smartWatchesSubtitle,
imagePath: 'smart_watch.svg',
subTitle: TranslationBase.of(context).smartWatches,
isEnable: projectViewModel.havePrivilege(30),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(28) ? Navigator.push(context, FadePage(page: AskDoctorHomPage())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).askYourSubtitle, imagePath: 'ask_doctor.svg', subTitle: TranslationBase.of(context).askYour, isEnable: projectViewModel.havePrivilege(28)),
));
if (projectViewModel.havePrivilege(32) || true) {
medical.add(InkWell(
onTap: () {
if (Platform.isAndroid) {
showPermissionConsentDialog(context, TranslationBase.of(context).wifiPermission, () {
connectWifi(projectViewModel, context);
});
} else {
connectWifi(projectViewModel, context);
}
},
child: MedicalProfileItem(
title: TranslationBase.of(context).internet,
imagePath: 'internet_connection.svg',
subTitle: TranslationBase.of(context).internetSubtitle,
),
));
}
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(40) ? launch('whatsapp://send?phone=18885521858&text=') : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).chatbot,
imagePath: 'chatbot.svg',
subTitle: TranslationBase.of(context).chatbotSubtitle,
isEnable: projectViewModel.havePrivilege(40),
),
));
return medical;
}
static getPatientWifiCredentials(String patientID, Function(String username, String password) successCallback) {
final body = <String, dynamic>{"PatientID": patientID};
locator<BaseAppClient>().post(WIFI_CREDENTIALS, body: body, onSuccess: (dynamic response, int statusCode) {
print(response);
var data = response["Hmg_SMS_Get_By_ProjectID_And_PatientIDList"];
if (data is List && data.first != null) {
final username = data.first['UserName'];
final password = data.first['Password'];
if (username != null && password != null && username.isNotEmpty && password.isNotEmpty) {
successCallback(username, password);
}
}
}, onFailure: (String error, int statusCode) {
print(error);
}, bypassConnectionCheck: true);
}
static connectWifi(ProjectViewModel projectViewModel, BuildContext context) {
final String GUEST_SSID = "HMG-MobileApp";
final String PATIENT_SSID = "GUEST-POC";
userData().then((userData_) {
if (projectViewModel.isLogin && userData_ != null || true) {
String patientID = userData_.patientID.toString();
GifLoaderDialogUtils.showMyDialog(context);
// projectViewModel.platformBridge().connectHMGInternetWifi(patientID).then((value) => {GifLoaderDialogUtils.hideDialog(context)}).catchError((err) {
// print(err.toString());
// });
projectViewModel.platformBridge().connectHMGGuestWifi(GUEST_SSID).then((value) async {
if (value == 0) {
GifLoaderDialogUtils.hideDialog(context);
} else {
getPatientWifiCredentials(patientID, (username, password) async {
final result = await projectViewModel.platformBridge().connectHMGInternetWifi(PATIENT_SSID, username, password).catchError((err) => print(err.toString()));
GifLoaderDialogUtils.hideDialog(context);
if (result == 1) {
// Success
}
});
}
}).catchError((e) {
GifLoaderDialogUtils.hideDialog(context);
});
} else {
AlertDialogBox(
context: context,
confirmMessage: "Please login with your account first to use this feature",
okText: "OK",
okFunction: () {
AlertDialogBox.closeAlertDialog(context);
}).showAlertDialog(context);
}
});
}
static List<Widget> myMedicalListHomePage({ProjectViewModel? projectViewModel, BuildContext? context, bool? isLogin, count}) {
List<Widget> medical = [];
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(5) ? Navigator.push(context!, FadePage(page: MyAppointments())) : null,
child: isLogin!
? Stack(children: [
MedicalProfileItem(
title: TranslationBase.of(context!).myAppointments,
imagePath: 'appointment_list.svg',
subTitle: TranslationBase.of(context!).myAppointmentsList,
hasBadge: true,
isEnable: projectViewModel!.havePrivilege(5)),
projectViewModel.isArabic!
? !projectViewModel.isLoginChild
? Positioned(
left: 8,
top: 4,
child: badge_import.Badge(
position: badge_import.BadgePosition.topEnd(),
badgeAnimation: badge_import.BadgeAnimation.fade(toAnimate: false),
badgeStyle: badge_import.BadgeStyle(
elevation: 0,
shape: badge_import.BadgeShape.circle,
badgeColor: secondaryColor!.withOpacity(1.0),
borderRadius: BorderRadius.circular(8),
),
badgeContent: Container(
padding: EdgeInsets.all(2.0),
child: Text(count.toString(), style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 12.0)),
),
),
)
: Container()
: !projectViewModel.isLoginChild
? Positioned(
right: 8,
top: 4,
child: badge_import.Badge(
badgeAnimation: badge_import.BadgeAnimation.fade(toAnimate: false),
badgeStyle: badge_import.BadgeStyle(
elevation: 0,
shape: badge_import.BadgeShape.circle,
badgeColor: secondaryColor!.withOpacity(1.0),
borderRadius: BorderRadius.circular(8),
),
position: badge_import.BadgePosition.topEnd(),
badgeContent: Container(
padding: EdgeInsets.all(2.0),
child: Text(count.toString(), style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 12.0)),
),
),
)
: Container(),
])
: MedicalProfileItem(
title: TranslationBase.of(context!).myAppointments,
imagePath: 'appointment_list.svg',
subTitle: TranslationBase.of(context!).myAppointmentsList,
hasBadge: true,
isEnable: projectViewModel!.havePrivilege(5),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(10) ? Navigator.push(context, FadePage(page: LabsHomePage())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).lab,
imagePath: 'lab_result.svg',
subTitle: TranslationBase.of(context).labSubtitle,
isEnable: projectViewModel.havePrivilege(10),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(7) ? Navigator.push(context, FadePage(page: RadiologyHomePage())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).radiology,
imagePath: 'radiology.svg',
subTitle: TranslationBase.of(context).radiologySubtitle,
isEnable: projectViewModel.havePrivilege(7),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(12) ? Navigator.push(context, FadePage(page: HomePrescriptionsPage())) : null,
child: MedicalProfileItem(
title: TranslationBase.of(context).medicines,
imagePath: 'medicine_prescription.svg',
subTitle: TranslationBase.of(context).medicinesSubtitle,
isEnable: projectViewModel.havePrivilege(12),
),
));
medical.add(InkWell(
onTap: () => projectViewModel.havePrivilege(6)
? Navigator.push(
context,
FadePage(
page: DoctorHomePage(),
),
)
: null,
child:
MedicalProfileItem(title: TranslationBase.of(context).myDoctor, imagePath: 'my_doc.svg', subTitle: TranslationBase.of(context).myDoctorSubtitle, isEnable: projectViewModel.havePrivilege(6)),
));
return medical;
}
static Widget loadNetworkImage({required String url, BoxFit fitting = BoxFit.cover}) {
return CachedNetworkImage(
placeholderFadeInDuration: Duration(milliseconds: 250),
fit: fitting,
imageUrl: url,
placeholder: (context, url) => Container(child: Center(child: CircularProgressIndicator())),
errorWidget: (context, url, error) {
return Icon(
Icons.error,
color: Colors.red,
size: 50,
);
});
}
static bool route(Route route, {required Type equalsTo}) {
if ((route is FadePage)) {
return route.page.runtimeType == equalsTo;
}
return route.runtimeType == equalsTo;
}
static navigateToCartPage() {
Navigator.pushAndRemoveUntil(locator<NavigationService>()!.navigatorKey!.currentContext!, MaterialPageRoute(builder: (context) => LandingPagePharmacy(currentTab: 3)), (Route<dynamic> r) => false);
}
static Widget tableColumnTitle(String text, {bool showDivider = true}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: 6),
Text(
text,
maxLines: 1,
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.48, height: 18 / 12),
),
SizedBox(height: 5),
if (showDivider)
Divider(
height: 1,
color: Color(0xff2E303A),
thickness: 1,
)
],
);
}
static Widget tableColumnValue(String text, {bool isLast = false, bool isCapitable = true, bool isHighLow = false, bool isCurrency = false, required ProjectViewModel mProjectViewModel}) {
ProjectViewModel projectViewModel = mProjectViewModel ?? Provider.of(AppGlobal.context);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: 12),
Row(
children: [
Expanded(
child: Text(
isCapitable && !projectViewModel.isArabic ? text.toLowerCase().capitalizeFirstofEach : text,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: isHighLow ? CustomColors.accentColor : Color(0xff575757), letterSpacing: -0.4, height: 16 / 10),
),
),
isCurrency ? getSaudiRiyalSymbol() : Container(),
],
),
SizedBox(height: 12),
if (!isLast)
Divider(
height: 1,
color: Color(0xffEFEFEF),
thickness: 1,
)
],
);
}
static Widget tableColumnValueWithFlowChart(String text, String flowChartText, {bool isLast = false, bool isCapitable = true, ProjectViewModel? mProjectViewModel}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: 12),
Text(
text,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff575757), letterSpacing: -0.4, height: 16 / 10),
),
SizedBox(height: 8),
AutoSizeText(
flowChartText,
maxLines: 1,
minFontSize: 6,
style: TextStyle(decoration: TextDecoration.underline, fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xffD02127), letterSpacing: -0.48, height: 18 / 12),
),
SizedBox(height: 12),
if (!isLast)
Divider(
height: 1,
color: Color(0xffEFEFEF),
thickness: 1,
)
],
);
}
static Future<bool> isGoogleServicesAvailable() async {
GooglePlayServicesAvailability availability = await GoogleApiAvailability.instance.checkGooglePlayServicesAvailability();
String status = availability.toString().split('.').last;
if (status == "success") {
return true;
}
return false;
}
static double distance(double lat1, double lon1, double lat2, double lon2) {
const r = 6372.8; // Earth radius in kilometers
final dLat = _toRadians(lat2 - lat1);
final dLon = _toRadians(lon2 - lon1);
final lat1Radians = _toRadians(lat1);
final lat2Radians = _toRadians(lat2);
final a = _haversin(dLat) + cos(lat1Radians) * cos(lat2Radians) * _haversin(dLon);
final c = 2 * asin(sqrt(a));
return r * c;
}
static double _toRadians(double degrees) => degrees * pi / 180;
static num _haversin(double radians) => pow(sin(radians / 2), 2);
static Widget tableColumnValueWithUnderLine(String text, {bool isLast = false, bool isCapitable = true}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: 14),
AutoSizeText(
isCapitable ? text.toLowerCase().capitalizeFirstofEach : text,
maxLines: 1,
minFontSize: 6,
style: TextStyle(decoration: TextDecoration.underline, fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xffD02127), letterSpacing: -0.48, height: 18 / 12),
),
SizedBox(height: 10),
if (!isLast)
Divider(
height: 1,
color: Color(0xffEFEFEF),
thickness: 1,
)
],
);
}
static String generateMd5Hash(String input) {
return crypto.md5.convert(utf8.encode(input)).toString();
}
static bool isVidaPlusProject(ProjectViewModel projectViewModel, int projectID) {
bool isVidaPlus = false;
projectViewModel.vidaPlusProjectList.forEach((element) {
if (element.projectID == projectID) {
isVidaPlus = true;
}
});
return isVidaPlus;
}
static bool isHMCProject(ProjectViewModel projectViewModel, int projectID) {
bool isHMCProject = false;
projectViewModel.hMCProjectListModel.forEach((element) {
if (element.projectID == projectID) {
isHMCProject = true;
}
});
return isHMCProject;
}
static ProjectDetailListModel getProjectDetailObj(ProjectViewModel projectViewModel, int projectID) {
ProjectDetailListModel projectDetailListModel = ProjectDetailListModel();
projectViewModel.projectDetailListModel.forEach((element) {
if (element.projectID == projectID) {
projectDetailListModel = element;
}
});
return projectDetailListModel;
}
static Widget getSaudiRiyalSymbol({double fontSize = 16}) {
return Text(" SAR ", style: TextStyle(fontFamily: "SaudiRiyal", fontSize: fontSize));
}
//static String generateSignature() {}
}
Widget applyShadow({Color color = Colors.grey, double shadowOpacity = 0.5, double spreadRadius = 2, double blurRadius = 7, Offset offset = const Offset(2, 2), required Widget child}) {
return Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: color.withOpacity(shadowOpacity),
spreadRadius: spreadRadius,
blurRadius: blurRadius,
offset: offset, // changes position of shadow
),
],
),
child: child,
);
}
Future<AuthenticatedUser> userData() async {
var userData = AuthenticatedUser.fromJson(await AppSharedPreferences().getObject(MAIN_USER));
return userData;
}
// extension function that use in iterations(list.. etc) to iterate items and get index and item it self
extension IndexedIterable<E> on Iterable<E> {
Iterable<T> mapIndexed<T>(T Function(E e, int i) f) {
var i = 0;
return map((e) => f(e, i++));
}
}
openAppStore({String? androidPackageName, String? iOSAppID, bool isHuawei = false}) async {
if (Platform.isAndroid) {
assert(!(androidPackageName == null), "Should have valid value in androidPackageName parameter");
if (isHuawei) {
launchUrl(Uri.parse("appmarket://details?id=com.ejada.hmg"));
} else {
launchUrl(Uri.parse("market://details?id=com.ejada.hmg"));
}
} else if (Platform.isIOS) {
assert((iOSAppID == null), "Should have valid value in iOSAppID parameter");
launchUrl(Uri.parse("https://itunes.apple.com/kr/app/apple-store/$iOSAppID)"));
}
}
String labelFrom({required String className}) {
RegExp exp = RegExp(r'(?<=[a-z])[A-Z]');
String result = className.replaceAllMapped(exp, (m) {
var str = m.group(0);
if (str != null) {
return ('_' + str);
}
return "";
});
if (result.isEmpty) return className;
result = result.replaceAll("_", " ");
return result;
}
extension StringExtension on String {
String capitalize() {
return this.splitMapJoin(RegExp(r'\w+'), onMatch: (m) => '${m.group(0)}'.substring(0, 1).toUpperCase() + '${m.group(0)}'.substring(1).toLowerCase(), onNonMatch: (n) => ' ');
}
}
extension TextToRichTextWithIcon on Text {
RichText toRichTextWithIcon() {
// Create the base TextSpan with the text data and style from the Text widget
return RichText(
text: TextSpan(
style: this.style, // Inherit the text style
children: [
WidgetSpan(
child: Text(" SAR ", style: TextStyle(fontFamily: "SaudiRiyal")),
),
TextSpan(
text: this.data, // Add the original text
style: this.style, // Inherit the text style
),
],
),
);
}
}
extension WidgetPaddingExtensions on Widget {
Widget withHorizontalPadding([double padding = 16.0]) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: padding),
child: this,
);
}
Widget withVerticalPadding([double padding = 16.0]) {
return Padding(
padding: EdgeInsets.symmetric(vertical: padding),
child: this,
);
}
}
extension CountryExtension on Country {
String get displayName {
switch (this) {
case Country.saudiArabia:
return "Kingdom Of Saudi Arabia";
case Country.unitedArabEmirates:
return "United Arab Emirates";
}
}
String get nameArabic {
switch (this) {
case Country.saudiArabia:
return "المملكة العربية السعودية";
case Country.unitedArabEmirates:
return "الإمارات العربية المتحدة";
}
}
String get iconPath {
switch (this) {
case Country.saudiArabia:
return "assets/images/svg/ksa.svg";
case Country.unitedArabEmirates:
return "assets/images/svg/uae.svg";
}
}
String get countryCode {
switch (this) {
case Country.saudiArabia:
return "966";
case Country.unitedArabEmirates:
return "971";
}
}
static Country fromDisplayName(String name) {
switch (name) {
case "Kingdom Of Saudi Arabia":
case "المملكة العربية السعودية":
return Country.saudiArabia;
case "United Arab Emirates":
case "الإمارات العربية المتحدة":
return Country.unitedArabEmirates;
default:
throw Exception("Invalid country name");
}
}
}
extension FontFamilyExtension on BuildContext {
String get fontFamily {
final language = read<ProjectViewModel>().currentLanguage;
return language == 'ar' ? 'Cairo' : 'Poppins';
}
}
extension SelectedLanguageExtension on BuildContext {
String get selectedLanguage {
final language = read<ProjectViewModel>().currentLanguage;
return language;
}
double getLottieScaledWidth(double value) => MediaQuery.of(this).size.width * (value / MediaQuery.of(this).size.width);
double getLottieScaledHeight(double value) => MediaQuery.of(this).size.height * (value / MediaQuery.of(this).size.height);
}
extension GenderTypeExtension on GenderType {
String get value => this == GenderType.male ? "M" : "F";
String get type => this == GenderType.male ? "Male" : "Female";
String get typeAr => this == GenderType.male ? "ذكر" : "أنثى";
static GenderType? fromValue(String? value) {
switch (value) {
case "M":
return GenderType.male;
case "F":
return GenderType.female;
default:
return null;
}
}
static GenderType? fromType(String? type) {
switch (type) {
case "Male":
return GenderType.male;
case "Female":
return GenderType.female;
default:
return null;
}
}
}
extension MaritalStatusTypeExtension on MaritalStatusType {
String get value {
switch (this) {
case MaritalStatusType.single:
return "U";
case MaritalStatusType.married:
return "M";
case MaritalStatusType.divorced:
return "D";
case MaritalStatusType.widowed:
return "W";
}
}
String get type {
switch (this) {
case MaritalStatusType.single:
return "Single";
case MaritalStatusType.married:
return "Married";
case MaritalStatusType.divorced:
return "Divorced";
case MaritalStatusType.widowed:
return "Widowed";
}
}
String get typeAr {
switch (this) {
case MaritalStatusType.single:
return "أعزب";
case MaritalStatusType.married:
return "متزوج";
case MaritalStatusType.divorced:
return "مطلق";
case MaritalStatusType.widowed:
return "أرمل";
}
}
static MaritalStatusType? fromValue(String? value) {
switch (value) {
case "U":
return MaritalStatusType.single;
case "M":
return MaritalStatusType.married;
case "D":
return MaritalStatusType.divorced;
case "W":
return MaritalStatusType.widowed;
default:
return null;
}
}
static MaritalStatusType? fromType(String? type) {
switch (type) {
case "Single":
return MaritalStatusType.single;
case "Married":
return MaritalStatusType.married;
case "Divorced":
return MaritalStatusType.divorced;
case "Widowed":
return MaritalStatusType.widowed;
default:
return null;
}
}
}
/*
userBoard.asMap().map((i, element) => MapEntry(i, Stack(
GestureDetector(onTap: () {
setState(() {
// print("element=${element.toString()}");
// print("element=${userBoard[i].toString()}");
});
}),
))).values.toList();
*/
extension SmoothContainerExtension on ShapeBorder {
ShapeDecoration toSmoothCornerDecoration({
Color color = Colors.transparent,
double? borderRadius,
bool isDisabled = false,
Color? backgroundColor,
BorderSide? side,
}) {
final bgColor = backgroundColor ?? color;
return ShapeDecoration(
color: isDisabled ? bgColor.withOpacity(0.5) : bgColor,
shape: SmoothRectangleBorder(
borderRadius: BorderRadius.circular(borderRadius ?? 0),
smoothness: 1,
side: side ?? BorderSide.none,
),
);
}
}