Merge branch 'refs/heads/master' into offers_discounts

offers_discounts
Aamir Muhammad 3 days ago
commit 1d9783a5b3

@ -210,8 +210,8 @@ class ApiClientImp implements ApiClient {
body['TokenID'] = "@dm!n"; body['TokenID'] = "@dm!n";
} }
body['TokenID'] = "@dm!n"; // body['TokenID'] = "@dm!n";
// body['PatientID'] = 6424682; // body['PatientID'] = 4772993;
// body['PatientID'] = 89754444; // body['PatientID'] = 89754444;
// body['PatientTypeID'] = 1; // body['PatientTypeID'] = 1;
// body['PatientOutSA'] = 0; // body['PatientOutSA'] = 0;

@ -4,12 +4,14 @@ import 'dart:io';
import 'dart:math' as dartMath; import 'dart:math' as dartMath;
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:clarity_flutter/clarity_flutter.dart';
import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:crypto/crypto.dart' as crypto; import 'package:crypto/crypto.dart' as crypto;
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:get_it/get_it.dart';
import 'package:google_api_availability/google_api_availability.dart'; import 'package:google_api_availability/google_api_availability.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/app_state.dart';
@ -916,7 +918,8 @@ class Utils {
appState.isArabic() appState.isArabic()
? Container() ? Container()
: Utils.buildSvgWithAssets( : Utils.buildSvgWithAssets(
icon: isSaudiCurrency ? AppAssets.saudi_riyal_icon : AppAssets.uae_dirham_symbol, // icon: isSaudiCurrency ? AppAssets.saudi_riyal_icon : AppAssets.uae_dirham_symbol,
icon: (getIt.get<AppState>().getAuthenticatedUser()!.outSa == 0) ? AppAssets.saudi_riyal_icon : AppAssets.uae_dirham_symbol,
iconColor: iconColor, iconColor: iconColor,
width: iconSize.h, width: iconSize.h,
height: iconSize.h, height: iconSize.h,
@ -928,7 +931,8 @@ class Utils {
!appState.isArabic() !appState.isArabic()
? Container() ? Container()
: Utils.buildSvgWithAssets( : Utils.buildSvgWithAssets(
icon: isSaudiCurrency ? AppAssets.saudi_riyal_icon : AppAssets.uae_dirham_symbol, // icon: isSaudiCurrency ? AppAssets.saudi_riyal_icon : AppAssets.uae_dirham_symbol,
icon: (getIt.get<AppState>().getAuthenticatedUser()!.outSa == 0) ? AppAssets.saudi_riyal_icon : AppAssets.uae_dirham_symbol,
iconColor: iconColor, iconColor: iconColor,
width: iconSize.h, width: iconSize.h,
height: iconSize.h, height: iconSize.h,
@ -958,7 +962,7 @@ class Utils {
WidgetSpan( WidgetSpan(
alignment: PlaceholderAlignment.baseline, alignment: PlaceholderAlignment.baseline,
baseline: TextBaseline.alphabetic, baseline: TextBaseline.alphabetic,
child: Utils.buildSvgWithAssets(icon: AppAssets.saudi_riyal_icon, width: iconSize.h, height: iconSize.h, iconColor: resolvedIconColor), child: Utils.buildSvgWithAssets(icon: (getIt.get<AppState>().getAuthenticatedUser()!.outSa == 1) ? AppAssets.uae_dirham_symbol : AppAssets.saudi_riyal_icon, width: iconSize.h, height: iconSize.h, iconColor: resolvedIconColor),
), ),
TextSpan( TextSpan(
// text: NumberFormat.currency(locale: 'en_US', symbol: " ", decimalDigits: 0).format(habibWalletAmount), // text: NumberFormat.currency(locale: 'en_US', symbol: " ", decimalDigits: 0).format(habibWalletAmount),

@ -1127,7 +1127,9 @@ class BookAppointmentsViewModel extends ChangeNotifier {
result.fold( result.fold(
(failure) async { (failure) async {
print(failure); if(onError != null) {
onError(failure.message);
}
}, },
(apiResponse) { (apiResponse) {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {

@ -1010,7 +1010,9 @@ class MyAppointmentsViewModel extends ChangeNotifier {
} }
} }
// patientQueueDetailsList.first.callType = 1; // patientQueueDetailsList.first.callType = 1;
patientQueueDetailsList.removeWhere((element) => element.patientID == patientArrivedAppointmentsHistoryList.first.patientID); // if (patientQueueDetailsList.length > 1) {
patientQueueDetailsList.removeWhere((element) => element.patientID == patientArrivedAppointmentsHistoryList.first.patientID);
// }
} else { } else {
patientQueueDetailsList.clear(); patientQueueDetailsList.clear();
isPatientHasQueueAppointment = false; isPatientHasQueueAppointment = false;

@ -319,7 +319,7 @@ class PayfortViewModel extends ChangeNotifier {
"amount": Platform.isAndroid ? (num.parse(amount) * 100).toInt() : (num.parse(amount) * 100).toInt().toString(), "amount": Platform.isAndroid ? (num.parse(amount) * 100).toInt() : (num.parse(amount) * 100).toInt().toString(),
// "amount": "100000", // "amount": "100000",
"currency": getIt.get<AppState>().getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED", "currency": getIt.get<AppState>().getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED",
"language": "en", "language": getIt.get<AppState>().isArabic() ? "ar" : "en",
"customer_email": "CustID_$fileNumber@HMG.com", "customer_email": "CustID_$fileNumber@HMG.com",
"sdk_token": sdkTokenResponse!.sdkToken, "sdk_token": sdkTokenResponse!.sdkToken,
"customer_name": "${getIt.get<AppState>().getAuthenticatedUser()!.firstName} ${getIt.get<AppState>().getAuthenticatedUser()!.lastName}", "customer_name": "${getIt.get<AppState>().getAuthenticatedUser()!.firstName} ${getIt.get<AppState>().getAuthenticatedUser()!.lastName}",
@ -353,6 +353,11 @@ class PayfortViewModel extends ChangeNotifier {
// Process real payment rejection errors here // Process real payment rejection errors here
print("Actual Payment Failure: ${e.details.toString()}"); print("Actual Payment Failure: ${e.details.toString()}");
if (onFailed != null) {
final paymentMap = (e.details as Map).cast<String, dynamic>();
paymentMap["message"] = e.details["response_message"] ?? "Payment failed with unknown error.";
onFailed(PayFortFailureResult.fromMap(paymentMap));
}
} catch (error) { } catch (error) {
print("Generic Error: $error"); print("Generic Error: $error");
} }

@ -65,7 +65,7 @@ class PayTabsViewModel extends ChangeNotifier {
"12626"), "12626"),
alternativePaymentMethods: [], alternativePaymentMethods: [],
linkBillingNameWithCardHolderName: true, linkBillingNameWithCardHolderName: true,
simplifyApplePayValidation: false, simplifyApplePayValidation: true,
); );
paymentConfiguration.iOSThemeConfigurations = IOSThemeConfigurations( paymentConfiguration.iOSThemeConfigurations = IOSThemeConfigurations(

@ -23,10 +23,14 @@ class WeatherMonitorViewModel extends ChangeNotifier {
final List<GetCityInfoList> _cityInfoList = []; final List<GetCityInfoList> _cityInfoList = [];
bool isLoading = false; bool isLoading = false;
bool isWeatherNeedToLoad = true;
List<GetCityInfoList> get cityInfoList => _cityInfoList; List<GetCityInfoList> get cityInfoList => _cityInfoList;
Future<void> fetchCityInfoList({Function(dynamic)? onSuccess, Function(String)? onError}) async { Future<void> fetchCityInfoList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
if (!isWeatherNeedToLoad) {
return;
}
isLoading = true; isLoading = true;
notifyListeners(); notifyListeners();
_cityInfoList.clear(); _cityInfoList.clear();
@ -34,7 +38,7 @@ class WeatherMonitorViewModel extends ChangeNotifier {
// Check if location permission is already granted // Check if location permission is already granted
final isLocationEnabled = await locationUtils.isLocationPermissionEnabled(); final isLocationEnabled = await locationUtils.isLocationPermissionEnabled();
if (isLocationEnabled) { if (isLocationEnabled && getIt.get<AppState>().userLat != 0.0 && getIt.get<AppState>().userLong != 0.0) {
// Permission already granted, fetch data directly // Permission already granted, fetch data directly
isLocationAvailable = true; isLocationAvailable = true;
final result = await weatherRepo.getCityInfo(); final result = await weatherRepo.getCityInfo();
@ -61,6 +65,7 @@ class WeatherMonitorViewModel extends ChangeNotifier {
if (onSuccess != null) { if (onSuccess != null) {
onSuccess(apiResponse); onSuccess(apiResponse);
} }
isWeatherNeedToLoad = false;
} }
}, },
); );

@ -69,11 +69,13 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
widget.patientAppointmentHistoryResponseModel.clinicID, widget.patientAppointmentHistoryResponseModel.clinicID,
widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(), widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false, onSuccess: (val) { widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(), widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false, onSuccess: (val) {
myAppointmentsViewModel.getTamaraInstallmentsDetails().then((val) { myAppointmentsViewModel.getTamaraInstallmentsDetails().then((val) {
if (myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax! >= myAppointmentsViewModel.getTamaraInstallmentsDetailsResponseModel!.minLimit!.amount! && if (myAppointmentsViewModel.getTamaraInstallmentsDetailsResponseModel != null) {
myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax! <= myAppointmentsViewModel.getTamaraInstallmentsDetailsResponseModel!.maxLimit!.amount!) { if (myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax! >= myAppointmentsViewModel.getTamaraInstallmentsDetailsResponseModel!.minLimit!.amount! &&
setState(() { myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax! <= myAppointmentsViewModel.getTamaraInstallmentsDetailsResponseModel!.maxLimit!.amount!) {
isShowTamara = true; setState(() {
}); isShowTamara = true;
});
}
} }
}); });
}, onError: (err) { }, onError: (err) {

@ -26,6 +26,8 @@ class AppointmentQueuePage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
appState = getIt.get<AppState>(); appState = getIt.get<AppState>();
final currentQueue = getIt.get<MyAppointmentsViewModel>().currentPatientQueueDetails;
final currentStatus = getIt.get<MyAppointmentsViewModel>().currentQueueStatus;
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
body: Consumer<MyAppointmentsViewModel>(builder: (context, myAppointmentsVM, child) { body: Consumer<MyAppointmentsViewModel>(builder: (context, myAppointmentsVM, child) {
@ -67,7 +69,7 @@ class AppointmentQueuePage extends StatelessWidget {
labelText: myAppointmentsVM.currentQueueStatus == 0 ? LocaleKeys.inQueue.tr(context: context) : LocaleKeys.yourTurn.tr(context: context), labelText: myAppointmentsVM.currentQueueStatus == 0 ? LocaleKeys.inQueue.tr(context: context) : LocaleKeys.yourTurn.tr(context: context),
backgroundColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus).withValues(alpha: 0.20), backgroundColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus).withValues(alpha: 0.20),
textColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus), textColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus),
).toShimmer2(isShow: myAppointmentsVM.patientQueueDetailsList.isEmpty), ).toShimmer2(isShow: (currentQueue.queueNo == null || currentQueue.queueNo!.isEmpty)),
Container( Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.greyColor, color: AppColors.greyColor,
@ -88,7 +90,7 @@ class AppointmentQueuePage extends StatelessWidget {
SizedBox(height: 8.h), SizedBox(height: 8.h),
(myAppointmentsVM.currentPatientQueueDetails.queueNo ?? "IM-123") (myAppointmentsVM.currentPatientQueueDetails.queueNo ?? "IM-123")
.toText32(isBold: true) .toText32(isBold: true)
.toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading || myAppointmentsVM.patientQueueDetailsList.isEmpty), .toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading || (currentQueue.queueNo == null || currentQueue.queueNo!.isEmpty)),
SizedBox(height: 8.h), SizedBox(height: 8.h),
CustomButton( CustomButton(
text: Utils.getCardButtonText(myAppointmentsVM.currentQueueStatus, myAppointmentsVM.currentPatientQueueDetails.roomNo ?? ""), text: Utils.getCardButtonText(myAppointmentsVM.currentQueueStatus, myAppointmentsVM.currentPatientQueueDetails.roomNo ?? ""),
@ -103,7 +105,7 @@ class AppointmentQueuePage extends StatelessWidget {
height: 40.h, height: 40.h,
iconColor: AppColors.whiteColor, iconColor: AppColors.whiteColor,
iconSize: 18.h, iconSize: 18.h,
).toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading || myAppointmentsVM.patientQueueDetailsList.isEmpty), ).toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading || (currentQueue.queueNo == null || currentQueue.queueNo!.isEmpty)),
], ],
), ),
), ),

@ -10,6 +10,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/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_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/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
@ -153,9 +154,15 @@ class AppointmentCheckinBottomSheet extends StatelessWidget {
myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true); myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true);
myAppointmentsViewModel.initAppointmentsViewModel(); myAppointmentsViewModel.initAppointmentsViewModel();
myAppointmentsViewModel.getPatientAppointments(true, false); myAppointmentsViewModel.getPatientAppointments(true, false);
getIt.get<HabibWalletViewModel>().setIsWalletAmountToBeLoaded(true);
getIt.get<HabibWalletViewModel>().initHabibWalletProvider();
getIt.get<HabibWalletViewModel>().getPatientBalanceAmount();
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.success.tr(context: context), child: Utils.getSuccessWidget(loadingText: LocaleKeys.success.tr()), callBackFunc: () async { showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.success.tr(context: context), child: Utils.getSuccessWidget(loadingText: LocaleKeys.success.tr()), callBackFunc: () async {
// await myAppointmentsViewModel.getPatientAppointmentQueueDetails(); // await myAppointmentsViewModel.getPatientAppointmentQueueDetails();
Navigator.of(context).pop(); Navigator.of(context).pop();
Navigator.pushAndRemoveUntil( Navigator.pushAndRemoveUntil(
context, context,

@ -94,27 +94,29 @@ class LoginScreenState extends State<LoginScreen> {
LocaleKeys.welcomeToDrSulaiman.tr(context: context).toText32(isBold: true, color: AppColors.textColor ), LocaleKeys.welcomeToDrSulaiman.tr(context: context).toText32(isBold: true, color: AppColors.textColor ),
SizedBox(height: 32.h), SizedBox(height: 32.h),
Localizations.override(context: context, locale: Locale('en', 'US'), child: Container()), // Force English locale for this widget Localizations.override(context: context, locale: Locale('en', 'US'), child: Container()), // Force English locale for this widget
TextInputWidget( ClarityUnmask(
labelText: LocaleKeys.nationalIdFileNumber.tr(context: context), child: TextInputWidget(
hintText: "xxxxxxxxx", labelText: LocaleKeys.nationalIdFileNumber.tr(context: context),
controller: authVm.nationalIdController, hintText: "xxxxxxxxx",
focusNode: _nationalIdFocusNode, controller: authVm.nationalIdController,
keyboardType: TextInputType.number, focusNode: _nationalIdFocusNode,
isEnable: true, keyboardType: TextInputType.number,
prefix: null, isEnable: true,
autoFocus: true, prefix: null,
isAllowRadius: true, autoFocus: true,
isBorderAllowed: false, isAllowRadius: true,
isAllowLeadingIcon: true, isBorderAllowed: false,
padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 10.h), isAllowLeadingIcon: true,
leadingIcon: AppAssets.student_card, padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 10.h),
errorMessage: authVm.nationalIdError, leadingIcon: AppAssets.student_card,
hasError: authVm.nationalIdError != null, errorMessage: authVm.nationalIdError,
fontFamily: "Poppins", hasError: authVm.nationalIdError != null,
onChange: (value) { fontFamily: "Poppins",
// Clear error when user starts typing onChange: (value) {
authVm.clearNationalIdError(); // Clear error when user starts typing
}, authVm.clearNationalIdError();
},
),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
CustomButton( CustomButton(
@ -205,65 +207,67 @@ class LoginScreenState extends State<LoginScreen> {
child: SingleChildScrollView( child: SingleChildScrollView(
child: Consumer<AuthenticationViewModel>( child: Consumer<AuthenticationViewModel>(
builder: (context, authVm, child) { builder: (context, authVm, child) {
return GenericBottomSheet( return ClarityUnmask(
countryCode: authVm.selectedCountrySignup.countryCode, child: GenericBottomSheet(
initialPhoneNumber: "", countryCode: authVm.selectedCountrySignup.countryCode,
textController: phoneNumberController, initialPhoneNumber: "",
isEnableCountryDropdown: true, textController: phoneNumberController,
onCountryChange: (country) { isEnableCountryDropdown: true,
authVm.onCountryChange(country); onCountryChange: (country) {
// Clear error when country changes authVm.onCountryChange(country);
authVm.clearPhoneNumberError(); // Clear error when country changes
}, authVm.clearPhoneNumberError();
onChange: (value) { },
authVm.onPhoneNumberChange(value); onChange: (value) {
// Clear error when user starts typing authVm.onPhoneNumberChange(value);
authVm.clearPhoneNumberError(); // Clear error when user starts typing
}, authVm.clearPhoneNumberError();
phoneNumberError: authVm.phoneNumberError, },
buttons: [ phoneNumberError: authVm.phoneNumberError,
if (authVm.selectedCountrySignup != CountryEnum.others) buttons: [
if (authVm.selectedCountrySignup != CountryEnum.others)
Padding(
padding: EdgeInsets.only(bottom: 10.h),
child: CustomButton(
text: LocaleKeys.sendOTPSMS.tr(context: context),
onPressed: () async {
validatePhoneAndProceed(OTPTypeEnum.sms);
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedBorderColor,
textColor: Colors.white,
iconColor: Colors.white,
icon: AppAssets.message,
),
),
if (authVm.selectedCountrySignup != CountryEnum.others)
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 8.h),
child: LocaleKeys.oR.tr(context: context).toText16(color: AppColors.textColor),
),
],
),
Padding( Padding(
padding: EdgeInsets.only(bottom: 10.h), padding: EdgeInsets.only(bottom: 10.h, top: 10.h),
child: CustomButton( child: CustomButton(
text: LocaleKeys.sendOTPSMS.tr(context: context), text: LocaleKeys.sendOTPWHATSAPP.tr(context: context),
onPressed: () async { onPressed: () async {
validatePhoneAndProceed(OTPTypeEnum.sms); validatePhoneAndProceed(OTPTypeEnum.whatsapp);
}, },
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.whiteColor,
borderColor: AppColors.primaryRedBorderColor, borderColor: AppColors.textColor,
textColor: Colors.white, textColor: AppColors.textColor,
iconColor: Colors.white, icon: AppAssets.whatsapp,
icon: AppAssets.message, iconColor: null,
applyThemeColor: false,
), ),
), ),
if (authVm.selectedCountrySignup != CountryEnum.others) ],
Row( ),
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 8.h),
child: LocaleKeys.oR.tr(context: context).toText16(color: AppColors.textColor),
),
],
),
Padding(
padding: EdgeInsets.only(bottom: 10.h, top: 10.h),
child: CustomButton(
text: LocaleKeys.sendOTPWHATSAPP.tr(context: context),
onPressed: () async {
validatePhoneAndProceed(OTPTypeEnum.whatsapp);
},
backgroundColor: AppColors.whiteColor,
borderColor: AppColors.textColor,
textColor: AppColors.textColor,
icon: AppAssets.whatsapp,
iconColor: null,
applyThemeColor: false,
),
),
],
); );
}, },
), ),

@ -63,11 +63,13 @@ class _ImmediateLiveCarePaymentPageState extends State<ImmediateLiveCarePaymentP
scheduleMicrotask(() { scheduleMicrotask(() {
payfortViewModel.initPayfortViewModel(); payfortViewModel.initPayfortViewModel();
myAppointmentsViewModel.getTamaraInstallmentsDetails().then((val) { myAppointmentsViewModel.getTamaraInstallmentsDetails().then((val) {
if (num.parse(immediateLiveCareViewModel.liveCareImmediateAppointmentFeesList.total!) >= myAppointmentsViewModel.getTamaraInstallmentsDetailsResponseModel!.minLimit!.amount! && if (myAppointmentsViewModel.getTamaraInstallmentsDetailsResponseModel != null) {
num.parse(immediateLiveCareViewModel.liveCareImmediateAppointmentFeesList.total!) <= myAppointmentsViewModel.getTamaraInstallmentsDetailsResponseModel!.maxLimit!.amount!) { if (num.parse(immediateLiveCareViewModel.liveCareImmediateAppointmentFeesList.total!) >= myAppointmentsViewModel.getTamaraInstallmentsDetailsResponseModel!.minLimit!.amount! &&
setState(() { num.parse(immediateLiveCareViewModel.liveCareImmediateAppointmentFeesList.total!) <= myAppointmentsViewModel.getTamaraInstallmentsDetailsResponseModel!.maxLimit!.amount!) {
isShowTamara = true; setState(() {
}); isShowTamara = true;
});
}
} }
}); });
}); });

@ -432,8 +432,15 @@ class _ReviewAppointmentPageState extends State<ReviewAppointmentPage> {
if (bookAppointmentsViewModel.isLiveCareSchedule) { if (bookAppointmentsViewModel.isLiveCareSchedule) {
await bookAppointmentsViewModel.insertSpecificAppointmentForLiveCare(onError: (err) { await bookAppointmentsViewModel.insertSpecificAppointmentForLiveCare(onError: (err) {
print(err.data["ErrorEndUserMessage"]);
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
title: LocaleKeys.notice.tr(context: context),
context,
child: Utils.getErrorWidget(loadingText: err.toString()),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
}, onSuccess: (apiResp) async { }, onSuccess: (apiResp) async {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
await Future.delayed(Duration(milliseconds: 50)).then((value) async { await Future.delayed(Duration(milliseconds: 50)).then((value) async {

@ -194,7 +194,7 @@ class _WaitingAppointmentPaymentPageState extends State<WaitingAppointmentPaymen
payfortViewModel.initiatePaymentWithCard( payfortViewModel.initiatePaymentWithCard(
transactionID: transID, transactionID: transID,
fileNumber: appState.getAuthenticatedUser()!.patientId.toString(), fileNumber: appState.getAuthenticatedUser()!.patientId.toString(),
amount: myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax!.toString(), amount: bookAppointmentsViewModel.patientWalkInAppointmentShareResponseModel!.patientShareWithTax!.toString(),
onSucceeded: (paymentResult) async { onSucceeded: (paymentResult) async {
print("Payment Success Data: ${paymentResult.toString()}"); print("Payment Success Data: ${paymentResult.toString()}");
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
@ -338,7 +338,7 @@ class _WaitingAppointmentPaymentPageState extends State<WaitingAppointmentPaymen
payfortViewModel.initiatePaymentWithCard( payfortViewModel.initiatePaymentWithCard(
transactionID: transID, transactionID: transID,
fileNumber: appState.getAuthenticatedUser()!.patientId.toString(), fileNumber: appState.getAuthenticatedUser()!.patientId.toString(),
amount: myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax!.toString(), amount: bookAppointmentsViewModel.patientWalkInAppointmentShareResponseModel!.patientShareWithTax!.toString(),
onSucceeded: (paymentResult) async { onSucceeded: (paymentResult) async {
print("Payment Success Data: ${paymentResult.toString()}"); print("Payment Success Data: ${paymentResult.toString()}");
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();

@ -149,7 +149,8 @@ class _RechargeWalletPageState extends State<RechargeWalletPage> {
), ),
), ),
const Spacer(), const Spacer(),
LocaleKeys.sar.tr(context: context).toText20(color: AppColors.greyTextColor, isBold: true), ((getIt.get<AppState>().getAuthenticatedUser()!.outSa == 1) ? LocaleKeys.aed.tr(context: context) : LocaleKeys.sar.tr(context: context))
.toText20(color: AppColors.greyTextColor, isBold: true),
], ],
), ),
], ],

@ -544,7 +544,7 @@ class _ServicesPageState extends State<ServicesPage> {
return Row( return Row(
children: [ children: [
Utils.buildSvgWithAssets( Utils.buildSvgWithAssets(
icon: AppAssets.saudi_riyal_icon, icon: (getIt.get<AppState>().getAuthenticatedUser()!.outSa == 1) ? AppAssets.uae_dirham_symbol : AppAssets.saudi_riyal_icon,
iconColor: AppColors.inputLabelTextColor, iconColor: AppColors.inputLabelTextColor,
width: 24.h, width: 24.h,
height: 24.h, height: 24.h,
@ -554,7 +554,7 @@ class _ServicesPageState extends State<ServicesPage> {
NumberFormat.decimalPattern() NumberFormat.decimalPattern()
.format(habibWalletVM.habibWalletAmount) .format(habibWalletVM.habibWalletAmount)
.toString() .toString()
.toText28(isBold: true, isEnglishOnly: true) .toText28(isBold: true)
.toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 40.h), .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 40.h),
], ],
); );

@ -28,6 +28,7 @@ import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_liveca
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/appointment_rating_view_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/appointment_rating_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_queue_details_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/notifications/notifications_view_model.dart'; import 'package:hmg_patient_app_new/features/notifications/notifications_view_model.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart'; import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart';
@ -144,6 +145,8 @@ class _LandingPageState extends State<LandingPage> {
} }
if (appState.isAuthenticated) { if (appState.isAuthenticated) {
Clarity.setCustomUserId(appState.getAuthenticatedUser()!.patientId.toString());
habibWalletVM.initHabibWalletProvider(); habibWalletVM.initHabibWalletProvider();
habibWalletVM.getPatientBalanceAmount(); habibWalletVM.getPatientBalanceAmount();
habibWalletVM.getLakumAccountInformation(); habibWalletVM.getLakumAccountInformation();
@ -1110,7 +1113,7 @@ class _LandingPageState extends State<LandingPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_buildQueueHeader(currentStatus), _buildQueueHeader(currentQueue, currentStatus),
SizedBox(height: 8.h), SizedBox(height: 8.h),
_buildQueueGreeting(), _buildQueueGreeting(),
SizedBox(height: 2.h), SizedBox(height: 2.h),
@ -1119,11 +1122,11 @@ class _LandingPageState extends State<LandingPage> {
color: AppColors.textColorLight, color: AppColors.textColorLight,
), ),
SizedBox(height: 8.h), SizedBox(height: 8.h),
(currentQueue.queueNo ?? "IM-123").toText28(isBold: true).toShimmer2(isShow: myAppointmentsViewModel.patientQueueDetailsList.isEmpty), (currentQueue.queueNo ?? "IM-123").toText28(isBold: true).toShimmer2(isShow: (currentQueue.queueNo == null || currentQueue.queueNo!.isEmpty)),
SizedBox(height: 6.h), SizedBox(height: 6.h),
_buildServingNowSection(), _buildServingNowSection(),
SizedBox(height: 5.h), SizedBox(height: 5.h),
_buildQueueActionButton(currentStatus, currentQueue.roomNo ?? "").toShimmer2(isShow: myAppointmentsViewModel.patientQueueDetailsList.isEmpty), _buildQueueActionButton(currentStatus, currentQueue.roomNo ?? "").toShimmer2(isShow: (currentQueue.queueNo == null || currentQueue.queueNo!.isEmpty)),
], ],
), ),
), ),
@ -1135,7 +1138,7 @@ class _LandingPageState extends State<LandingPage> {
} }
// Queue Card: Header with status chip and icon // Queue Card: Header with status chip and icon
Widget _buildQueueHeader(int currentStatus) { Widget _buildQueueHeader(PatientInQueueList currentQueue, int currentStatus) {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -1144,7 +1147,7 @@ class _LandingPageState extends State<LandingPage> {
labelText: currentStatus == 0 ? LocaleKeys.inQueue.tr() : LocaleKeys.yourTurn.tr(), labelText: currentStatus == 0 ? LocaleKeys.inQueue.tr() : LocaleKeys.yourTurn.tr(),
backgroundColor: Utils.getCardBorderColor(currentStatus).withValues(alpha: 0.20), backgroundColor: Utils.getCardBorderColor(currentStatus).withValues(alpha: 0.20),
textColor: Utils.getCardBorderColor(currentStatus), textColor: Utils.getCardBorderColor(currentStatus),
).toShimmer2(isShow: myAppointmentsViewModel.patientQueueDetailsList.isEmpty), ).toShimmer2(isShow: (currentQueue.queueNo == null || currentQueue.queueNo!.isEmpty)),
Container( Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.greyColor, color: AppColors.greyColor,

@ -91,7 +91,7 @@ class HabibWalletCard extends StatelessWidget {
Row( Row(
children: [ children: [
Utils.buildSvgWithAssets( Utils.buildSvgWithAssets(
icon: AppAssets.saudi_riyal_icon, icon: (getIt.get<AppState>().getAuthenticatedUser()!.outSa == 1) ? AppAssets.uae_dirham_symbol : AppAssets.saudi_riyal_icon,
iconColor: AppColors.inputLabelTextColor, iconColor: AppColors.inputLabelTextColor,
width: 24.h, width: 24.h,
height: 24.h, height: 24.h,

@ -1226,10 +1226,13 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
"${LocaleKeys.sickSubtitle.tr(context: context)} ${LocaleKeys.sick2.tr(context: context)}".toText16(isBold: true), (!appState.isArabic()
? "${LocaleKeys.sick2.tr(context: context)} ${LocaleKeys.sickSubtitle.tr(context: context)}"
: "${LocaleKeys.sickSubtitle.tr(context: context)} ${LocaleKeys.sick2.tr(context: context)}")
.toText16(isBold: true),
Row( Row(
children: [ children: [
LocaleKeys.viewAll.tr(context: context).toText12(color: AppColors.primaryRedColor), LocaleKeys.viewAll.tr(context: context).toText12(color: AppColors.primaryRedColor, isBold: true),
SizedBox(width: 2.h), SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
], ],

@ -53,7 +53,9 @@ class _PatientSickleavesListPageState extends State<PatientSickleavesListPage> {
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
body: CollapsingListView( body: CollapsingListView(
title: "${LocaleKeys.sickSubtitle.tr(context: context)} ${LocaleKeys.sick2.tr(context: context)}", title: (!appState.isArabic()
? "${LocaleKeys.sick2.tr(context: context)} ${LocaleKeys.sickSubtitle.tr(context: context)}"
: "${LocaleKeys.sickSubtitle.tr(context: context)} ${LocaleKeys.sick2.tr(context: context)}"),
child: SingleChildScrollView( child: SingleChildScrollView(
child: Consumer<MedicalFileViewModel>(builder: (context, model, child) { child: Consumer<MedicalFileViewModel>(builder: (context, model, child) {
return Column( return Column(

@ -62,7 +62,7 @@ class MedicalReportCard extends StatelessWidget {
), ),
if (listReady.isNotEmpty) if (listReady.isNotEmpty)
AppCustomChipWidget( AppCustomChipWidget(
labelText: '${listRequest.length.toString().padLeft(2, '0')} ${LocaleKeys.readyToDownload.tr()}', labelText: '${listReady.length.toString().padLeft(2, '0')} ${LocaleKeys.readyToDownload.tr()}',
icon: AppAssets.sucess, icon: AppAssets.sucess,
iconColor: AppColors.successColor, iconColor: AppColors.successColor,
textColor: AppColors.successColor, textColor: AppColors.successColor,

@ -444,7 +444,7 @@ class _FamilyCardsState extends State<FamilyCards> {
// Original logic: final canSwitch = isParentUser || (!isParentUser && profile.responseId == appState.getSuperUserID); // Original logic: final canSwitch = isParentUser || (!isParentUser && profile.responseId == appState.getSuperUserID);
final canSwitch = true; // Disabled - allows all users to switch final canSwitch = true; // Disabled - allows all users to switch
return Container( return Container(
padding: EdgeInsets.symmetric(vertical: 15.h, horizontal: 15.h), padding: EdgeInsets.symmetric(vertical: 12.h, horizontal: 12.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r),
child: Opacity( child: Opacity(
opacity: isActive || profile.status == FamilyFileEnum.pending.toInt || !canSwitch ? 0.4 : 1.0, // Fade all content if active opacity: isActive || profile.status == FamilyFileEnum.pending.toInt || !canSwitch ? 0.4 : 1.0, // Fade all content if active
@ -454,8 +454,8 @@ class _FamilyCardsState extends State<FamilyCards> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
UserAvatarWidget( UserAvatarWidget(
width: 72.h, width: 70.h,
height: 70.h, height: 66.h,
gender: profile.gender, gender: profile.gender,
age: profile.age, age: profile.age,
fit: BoxFit.cover, fit: BoxFit.cover,
@ -463,7 +463,7 @@ class _FamilyCardsState extends State<FamilyCards> {
isCircular: true, isCircular: true,
isFamilyMember: true, // Prevent AppState fallback isFamilyMember: true, // Prevent AppState fallback
), ),
SizedBox(height: 8.h), SizedBox(height: 4.h),
(profile.patientName ?? "Unknown").toText14(isBold: true, isCenter: true, maxlines: 1), (profile.patientName ?? "Unknown").toText14(isBold: true, isCenter: true, maxlines: 1),
// SizedBox(height: 8.h), // SizedBox(height: 8.h),
// CustomChipWidget( // CustomChipWidget(
@ -476,14 +476,17 @@ class _FamilyCardsState extends State<FamilyCards> {
// textColor: AppColors.textColor), // textColor: AppColors.textColor),
widget.isShowDetails ? SizedBox(height: 4.h) : SizedBox(), widget.isShowDetails ? SizedBox(height: 4.h) : SizedBox(),
widget.isShowDetails widget.isShowDetails
? CustomChipWidget( ? Wrap(direction: Axis.horizontal, spacing: 4.h, runSpacing: 4.h, children: [
chipType: ChipTypeEnum.alert, AppCustomChipWidget(
backgroundColor: AppColors.lightGrayBGColor, icon: AppAssets.file_icon,
chipText: "${LocaleKeys.age.tr(context: context)}: ${profile.age ?? "N/A"} ${LocaleKeys.years.tr(context: context)}", richText: "${LocaleKeys.fileno.tr(context: context)}: ${profile.responseId}".toText10(isBold: true),
isShowBorder: false, labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w),
borderRadius: 8.h, ),
textColor: AppColors.textColor, AppCustomChipWidget(
) labelText: "${LocaleKeys.age.tr(context: context)}: ${profile.age ?? "N/A"} ${LocaleKeys.years.tr(context: context)}",
labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 6.w),
),
])
: SizedBox(), : SizedBox(),
widget.isShowDetails widget.isShowDetails
? SizedBox(height: 8.h) ? SizedBox(height: 8.h)

@ -104,6 +104,8 @@ class PrescriptionDeliveryOrderSummaryPage extends StatelessWidget {
url: "https://maps.googleapis.com/maps/api/staticmap?center=${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lat},${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lng}&zoom=15&size=350x165&maptype=roadmap&markers=color:red%7C${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lat},${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lng}&key=AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng", url: "https://maps.googleapis.com/maps/api/staticmap?center=${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lat},${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lng}&zoom=15&size=350x165&maptype=roadmap&markers=color:red%7C${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lat},${prescriptionsViewModel.locationGeocodeResponse.results.first.geometry.location.lng}&key=AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng",
iconColor: AppColors.blackBgColor, iconColor: AppColors.blackBgColor,
fit: BoxFit.contain, fit: BoxFit.contain,
width: double.infinity,
height: 165.h,
), ),
), ),
], ],

@ -417,17 +417,17 @@ class _AccessibilityPageState extends State<AccessibilityPage> {
// Price with SAR symbol // Price with SAR symbol
Row( Row(
children: [ children: [
"1234".toText24(
isBold: true,
color: AppColors.blackBgColor, // Always use base color
),
SizedBox(width: 4.w),
SvgPicture.asset( SvgPicture.asset(
AppAssets.saudi_riyal_icon, (Utils.appState.getAuthenticatedUser()!.outSa == 1) ? AppAssets.uae_dirham_symbol : AppAssets.saudi_riyal_icon,
colorFilter: ColorFilter.mode(AppColors.blackBgColor, BlendMode.srcIn), colorFilter: ColorFilter.mode(AppColors.blackBgColor, BlendMode.srcIn),
width: 16.w, width: 16.w,
height: 16.h, height: 16.h,
), ),
SizedBox(width: 4.h),
"1234".toText24(
isBold: true,
color: AppColors.blackBgColor, // Always use base color
),
], ],
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),

@ -1,5 +1,6 @@
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'package:clarity_flutter/clarity_flutter.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -405,64 +406,66 @@ class TextInputWidget extends StatelessWidget {
child: Localizations.override( child: Localizations.override(
context: context, context: context,
locale: const Locale('en', 'US'), // Force English locale for TextField locale: const Locale('en', 'US'), // Force English locale for TextField
child: TextField( child: ClarityUnmask(
hintLocales: const [Locale('en', 'US')], child: TextField(
enabled: isEnable, hintLocales: const [Locale('en', 'US')],
scrollPadding: EdgeInsets.zero, enabled: isEnable,
keyboardType: isMultiline scrollPadding: EdgeInsets.zero,
? TextInputType.multiline keyboardType: isMultiline
: (isWalletAmountInput! ? const TextInputType.numberWithOptions(decimal: true) : keyboardType), ? TextInputType.multiline
controller: controller, : (isWalletAmountInput! ? const TextInputType.numberWithOptions(decimal: true) : keyboardType),
readOnly: isReadOnly, controller: controller,
textAlignVertical: TextAlignVertical.top, readOnly: isReadOnly,
textAlign: isArabic ? TextAlign.right : TextAlign.left, textAlignVertical: TextAlignVertical.top,
textDirection: ui.TextDirection.ltr, textAlign: isArabic ? TextAlign.right : TextAlign.left,
onChanged: onChange, textDirection: ui.TextDirection.ltr,
focusNode: focusNode ?? _focusNode, onChanged: onChange,
autofocus: autoFocus, focusNode: focusNode ?? _focusNode,
textInputAction: TextInputAction.done, autofocus: autoFocus,
cursorHeight: isWalletAmountInput! ? 40.h : 20.h, textInputAction: TextInputAction.done,
maxLength: isWalletAmountInput! ? 7 : 100, cursorHeight: isWalletAmountInput! ? 40.h : 20.h,
inputFormatters: isWalletAmountInput! maxLength: isWalletAmountInput! ? 7 : 100,
? [ inputFormatters: isWalletAmountInput!
_ThousandSeparatorInputFormatter(), ? [
] _ThousandSeparatorInputFormatter(),
: null, ]
onTapOutside: (event) { : null,
FocusManager.instance.primaryFocus?.unfocus(); onTapOutside: (event) {
}, FocusManager.instance.primaryFocus?.unfocus();
onSubmitted: onSubmitted, },
minLines: isMultiline ? minLines : 1, onSubmitted: onSubmitted,
maxLines: isMultiline ? maxLines : 1, minLines: isMultiline ? minLines : 1,
style: TextStyle( maxLines: isMultiline ? maxLines : 1,
fontSize: fontS, style: TextStyle(
height: isMultiline ? 1.2 : (isWalletAmountInput! ? 1 / 4 : 0), fontSize: fontS,
fontWeight: FontWeight.w600, height: isMultiline ? 1.2 : (isWalletAmountInput! ? 1 / 4 : 0),
color: AppColors.textColor,
letterSpacing: -1,
fontFamily: fontFamily,
locale: const Locale('en', 'US'), // Force English locale for text style
),
decoration: InputDecoration(
counterText: "",
isDense: true,
hintText: hintText,
hintStyle: TextStyle(
fontFamily: isArabic ? 'CairoArabic' : 'Poppins',
fontSize: 14.f,
height: 21 / 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: hintColor != null ? AppColors.textColor : Color(0xff898A8D), color: AppColors.textColor,
letterSpacing: -0.75, letterSpacing: -1,
fontFamily: fontFamily,
locale: const Locale('en', 'US'), // Force English locale for text style
),
decoration: InputDecoration(
counterText: "",
isDense: true,
hintText: hintText,
hintStyle: TextStyle(
fontFamily: isArabic ? 'CairoArabic' : 'Poppins',
fontSize: 14.f,
height: 21 / 16,
fontWeight: FontWeight.w600,
color: hintColor != null ? AppColors.textColor : Color(0xff898A8D),
letterSpacing: -0.75,
),
prefixIconConstraints: BoxConstraints(minWidth: 30.h),
prefixIcon: prefix == null ? null : "+${prefix!}".toText14(letterSpacing: -1, color: AppColors.textColor, isBold: true),
contentPadding: EdgeInsets.only(right: isArabic ? 10.w : 0),
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
// Show red border when field has error - but we handle this in the parent Container
// The parent Container in build() already shows red border based on hasError flag
), ),
prefixIconConstraints: BoxConstraints(minWidth: 30.h),
prefixIcon: prefix == null ? null : "+${prefix!}".toText14(letterSpacing: -1, color: AppColors.textColor, isBold: true),
contentPadding: EdgeInsets.only(right: isArabic ? 10.w : 0),
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
// Show red border when field has error - but we handle this in the parent Container
// The parent Container in build() already shows red border based on hasError flag
), ),
), ),
), ),

Loading…
Cancel
Save