Offers And Discounts Complete

offers_discounts
Aamir Muhammad 1 month ago
parent ea124325f0
commit 024fa602e6

@ -465,6 +465,9 @@ class OffersAndDiscountsViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
/// Check if search has text (for showing/hiding clear button)
bool get hasSearchText => searchQuery.isNotEmpty;
/// Get unique categories from the offers list /// Get unique categories from the offers list
List<Category> getUniqueCategories() { List<Category> getUniqueCategories() {
if (offersList.isEmpty) return []; if (offersList.isEmpty) return [];

@ -146,6 +146,9 @@ class _LandingPageState extends State<LandingPage> {
await authVM.handleNewImeiRegistration(isNavigate: false); await authVM.handleNewImeiRegistration(isNavigate: false);
} }
// Load offers and discounts for all users (authenticated or not)
offersAndDiscountsViewModel.initOffersAndDiscounts();
if (appState.isAuthenticated) { if (appState.isAuthenticated) {
Clarity.setCustomUserId(appState.getAuthenticatedUser()!.patientId.toString()); Clarity.setCustomUserId(appState.getAuthenticatedUser()!.patientId.toString());
@ -161,7 +164,6 @@ class _LandingPageState extends State<LandingPage> {
// myAppointmentsViewModel.getPatientAppointmentQueueDetails(); // myAppointmentsViewModel.getPatientAppointmentQueueDetails();
notificationsViewModel.initNotificationsViewModel(); notificationsViewModel.initNotificationsViewModel();
insuranceViewModel.initInsuranceProvider(); insuranceViewModel.initInsuranceProvider();
offersAndDiscountsViewModel.initOffersAndDiscounts();
if (!appState.isRatedVisible) { if (!appState.isRatedVisible) {
appointmentRatingViewModel.getLastRatingAppointment( appointmentRatingViewModel.getLastRatingAppointment(
@ -212,13 +214,17 @@ class _LandingPageState extends State<LandingPage> {
RefreshIndicator( RefreshIndicator(
color: AppColors.primaryRedColor, color: AppColors.primaryRedColor,
onRefresh: () async { onRefresh: () async {
// Refresh Offers and Discounts for all users
offersAndDiscountsViewModel.setIsoffersListLoading(true);
offersAndDiscountsViewModel.initOffersAndDiscounts(forceRefresh: true);
if (appState.isAuthenticated) { if (appState.isAuthenticated) {
// Refresh Appointments Data // Refresh Appointments Data
myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true); myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true);
myAppointmentsViewModel.initAppointmentsViewModel(); myAppointmentsViewModel.initAppointmentsViewModel();
myAppointmentsViewModel.getPatientAppointments(true, false); myAppointmentsViewModel.getPatientAppointments(true, false);
// Refresh Appointments Data // Refresh Wallet Data
habibWalletVM.initHabibWalletProvider(); habibWalletVM.initHabibWalletProvider();
habibWalletVM.getPatientBalanceAmount(); habibWalletVM.getPatientBalanceAmount();
habibWalletVM.getLakumAccountInformation(); habibWalletVM.getLakumAccountInformation();
@ -230,8 +236,6 @@ class _LandingPageState extends State<LandingPage> {
// Refresh Immediate LiveCare Data // Refresh Immediate LiveCare Data
immediateLiveCareViewModel.initImmediateLiveCare(); immediateLiveCareViewModel.initImmediateLiveCare();
immediateLiveCareViewModel.getPatientLiveCareHistory(); immediateLiveCareViewModel.getPatientLiveCareHistory();
offersAndDiscountsViewModel.setIsoffersListLoading(true);
offersAndDiscountsViewModel.initOffersAndDiscounts(forceRefresh: true);
// appointmentRatingViewModel.getLastRatingAppointment( // appointmentRatingViewModel.getLastRatingAppointment(
// onSuccess: (response) { // onSuccess: (response) {
@ -406,54 +410,7 @@ class _LandingPageState extends State<LandingPage> {
}), }),
], ],
).paddingSymmetrical(24.h, 0.h), ).paddingSymmetrical(24.h, 0.h),
!appState.isAuthenticated
? Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Row(
children: [
Utils.buildSvgWithAssets(
width: 50.w,
height: 60.h,
icon: AppAssets.symptomCheckerIcon,
fit: BoxFit.contain,
),
SizedBox(width: 12.w),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.howAreYouFeelingToday.tr(context: context).toText14(isBold: true),
LocaleKeys.checkYourSymptomsWithScale.tr(context: context).toText12(isBold: true),
SizedBox(height: 14.h),
CustomButton(
text: LocaleKeys.checkYourSymptoms.tr(context: context),
onPressed: () async {
context.navigateWithName(AppRoutes.userInfoSelection);
},
padding: EdgeInsetsGeometry.zero,
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: Colors.white,
fontSize: 14.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
height: 40.h,
),
],
).expanded
],
),
),
).paddingSymmetrical(24.w, 0.h)
: SizedBox.shrink(),
// Offers And Discounts Carousel - Auto-scrolling from right to left
//appState.isAuthenticated &&
appState.isEnabledOffersAndDiscountsCarousel appState.isEnabledOffersAndDiscountsCarousel
? Consumer<OffersAndDiscountsViewModel>( ? Consumer<OffersAndDiscountsViewModel>(
builder: (context, offersVM, child) { builder: (context, offersVM, child) {
@ -506,45 +463,6 @@ class _LandingPageState extends State<LandingPage> {
separatorBuilder: (context, index) => SizedBox(width: 12.w), separatorBuilder: (context, index) => SizedBox(width: 12.w),
), ),
).paddingSymmetrical(24.h, 0.h); ).paddingSymmetrical(24.h, 0.h);
/////////
////////////
// return Column(
// children: [
// SizedBox(height: 12.h),
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// ("${LocaleKeys.offers.tr(context: context)} & ${LocaleKeys.discount.tr(context: context)}").toText16(isBold: true),
// Row(
// children: [
// LocaleKeys.viewAll.tr(context: context).toText14(color: AppColors.primaryRedColor, isBold: true),
// SizedBox(width: 2.h),
// Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 14.h),
// ],
// ),
// ],
// ).paddingSymmetrical(24.h, 0.h).onPress(() {
// Navigator.of(context).push(CustomPageRoute(page: OffersAndDiscountsPage()));
// }),
// SizedBox(height: 16.h),
// Container(
// height: 150.h,
// decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
// color: AppColors.whiteColor,
// borderRadius: 16.r,
// hasShadow: false,
// ),
// child: Center(
// child: CircularProgressIndicator(
// valueColor: AlwaysStoppedAnimation<Color>(AppColors.primaryRedColor),
// ),
// ),
// ).paddingSymmetrical(24.h, 0.h),
// SizedBox(height: 18.h),
// ],
// );
} }
// Show offers if available // Show offers if available
@ -568,8 +486,7 @@ class _LandingPageState extends State<LandingPage> {
Navigator.of(context).push(CustomPageRoute(page: OffersAndDiscountsPage())); Navigator.of(context).push(CustomPageRoute(page: OffersAndDiscountsPage()));
}), }),
SizedBox(height: 16.h), SizedBox(height: 16.h),
OffersAndDiscountsCarousel().paddingSymmetrical(24.h, 0.h), OffersAndDiscountsCarousel().paddingOnly(left: 24.w),
SizedBox(height: 18.h),
], ],
); );
} }
@ -580,10 +497,58 @@ class _LandingPageState extends State<LandingPage> {
) )
: SizedBox.shrink(), : SizedBox.shrink(),
!appState.isAuthenticated
? Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Row(
children: [
Utils.buildSvgWithAssets(
width: 50.w,
height: 60.h,
icon: AppAssets.symptomCheckerIcon,
fit: BoxFit.contain,
),
SizedBox(width: 12.w),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.howAreYouFeelingToday.tr(context: context).toText14(isBold: true),
LocaleKeys.checkYourSymptomsWithScale.tr(context: context).toText12(isBold: true),
SizedBox(height: 14.h),
CustomButton(
text: LocaleKeys.checkYourSymptoms.tr(context: context),
onPressed: () async {
context.navigateWithName(AppRoutes.userInfoSelection);
},
padding: EdgeInsetsGeometry.zero,
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: Colors.white,
fontSize: 14.f,
fontWeight: FontWeight.w600,
borderRadius: 12.r,
height: 40.h,
),
],
).expanded
],
),
),
).paddingSymmetrical(24.w, 0.h)
: SizedBox.shrink(),
// Offers And Discounts Carousel - Auto-scrolling from right to left
//appState.isAuthenticated &&
appState.isAuthenticated appState.isAuthenticated
? Column( ? Column(
children: [ children: [
SizedBox(height: 12.h),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [

@ -12,9 +12,11 @@ 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/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/offers_and_discounts/offers_and_discounts_view_model.dart'; import 'package:hmg_patient_app_new/features/offers_and_discounts/offers_and_discounts_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';
import 'package:hmg_patient_app_new/presentation/offers_and_discounts/offers_and_discount_payment_page.dart'; import 'package:hmg_patient_app_new/presentation/offers_and_discounts/offers_and_discount_payment_page.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@ -117,12 +119,20 @@ class _OffersAndDiscountsDetailedPageState extends State<OffersAndDiscountsDetai
viewModel = Provider.of<OffersAndDiscountsViewModel>(context, listen: false); viewModel = Provider.of<OffersAndDiscountsViewModel>(context, listen: false);
return CollapsingListView( return CollapsingListView(
title: "${LocaleKeys.offerAndPackageDetails.tr(context: context)}", title: LocaleKeys.offerAndPackageDetails.tr(context: context),
bottomChild: CustomButton( bottomChild: CustomButton(
text: LocaleKeys.buyNow.tr(context: context), text: LocaleKeys.buyNow.tr(context: context),
icon: AppAssets.shoppingCart, icon: AppAssets.shoppingCart,
iconColor: AppColors.whiteColor, iconColor: AppColors.whiteColor,
onPressed: () async { onPressed: () async {
if (!appState.isAuthenticated) {
getIt<DialogService>().showErrorBottomSheet(
message: LocaleKeys.loginToUseService.tr(),
onOkPressed: () {
Navigator.of(context).pop();
getIt<AuthenticationViewModel>().onLoginPressed();
});
} else {
// Ensure patient is authenticated (will re-authenticate if needed) // Ensure patient is authenticated (will re-authenticate if needed)
final isAuthenticated = await viewModel.ensureAuthenticated( final isAuthenticated = await viewModel.ensureAuthenticated(
onSuccess: () { onSuccess: () {
@ -148,6 +158,7 @@ class _OffersAndDiscountsDetailedPageState extends State<OffersAndDiscountsDetai
page: OffersAndDiscountPaymentPage(), page: OffersAndDiscountPaymentPage(),
), ),
); );
}
}, },
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor, borderColor: AppColors.primaryRedColor,
@ -287,8 +298,12 @@ class _OffersAndDiscountsDetailedPageState extends State<OffersAndDiscountsDetai
textDirection: appState.isArabic() ? ui.TextDirection.rtl : ui.TextDirection.ltr, textDirection: appState.isArabic() ? ui.TextDirection.rtl : ui.TextDirection.ltr,
children: [ children: [
"${LocaleKeys.price.tr(context: context)}: ".toText18(isBold: true, weight: FontWeight.w700), "${LocaleKeys.price.tr(context: context)}: ".toText18(isBold: true, weight: FontWeight.w700),
if (!appState.isAuthenticated) ...[
Utils.buildSvgWithAssets(icon: AppAssets.saudi_riyal_icon)
] else ...[
Utils.getPaymentAmountWithSymbol(((offer.listPrice).toStringAsFixed(2)).toText14(isBold: true, color: AppColors.greyTextColor), AppColors.greyTextColor, 13, Utils.getPaymentAmountWithSymbol(((offer.listPrice).toStringAsFixed(2)).toText14(isBold: true, color: AppColors.greyTextColor), AppColors.greyTextColor, 13,
isSaudiCurrency: offer.currency == "SAR") isSaudiCurrency: offer.currency == "SAR")
]
], ],
), ),

@ -12,12 +12,14 @@ 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/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/offers_and_discounts/offers_and_discounts_view_model.dart'; import 'package:hmg_patient_app_new/features/offers_and_discounts/offers_and_discounts_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';
import 'package:hmg_patient_app_new/presentation/offers_and_discounts/offers_and_discount_payment_page.dart'; import 'package:hmg_patient_app_new/presentation/offers_and_discounts/offers_and_discount_payment_page.dart';
import 'package:hmg_patient_app_new/presentation/offers_and_discounts/offers_and_discounts_detailed_page.dart'; import 'package:hmg_patient_app_new/presentation/offers_and_discounts/offers_and_discounts_detailed_page.dart';
import 'package:hmg_patient_app_new/presentation/offers_and_discounts/offers_and_discounts_history_page.dart'; import 'package:hmg_patient_app_new/presentation/offers_and_discounts/offers_and_discounts_history_page.dart';
import 'package:hmg_patient_app_new/presentation/offers_and_discounts/widgets/offers_and_discount_type_selection_widget.dart'; import 'package:hmg_patient_app_new/presentation/offers_and_discounts/widgets/offers_and_discount_type_selection_widget.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@ -41,11 +43,13 @@ class _OffersAndDiscountsPageState extends State<OffersAndDiscountsPage> {
late OffersAndDiscountsViewModel offersAndDiscountsViewModel; late OffersAndDiscountsViewModel offersAndDiscountsViewModel;
late AppState appState; late AppState appState;
final TextEditingController _searchController = TextEditingController(); final TextEditingController _searchController = TextEditingController();
FocusNode textFocusNode = FocusNode();
@override @override
void initState() { void initState() {
super.initState(); super.initState();
appState = getIt.get<AppState>(); appState = getIt.get<AppState>();
scheduleMicrotask(() async { scheduleMicrotask(() async {
offersAndDiscountsViewModel = Provider.of<OffersAndDiscountsViewModel>(context, listen: false); offersAndDiscountsViewModel = Provider.of<OffersAndDiscountsViewModel>(context, listen: false);
@ -63,7 +67,7 @@ class _OffersAndDiscountsPageState extends State<OffersAndDiscountsPage> {
onError: (error) { onError: (error) {
// Hide loader on error // Hide loader on error
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
print("POMS Authentication failed: $error"); print("POMS POMS Authentication failed: $error");
// Authentication failed, but user can still browse offers // Authentication failed, but user can still browse offers
}, },
); );
@ -166,9 +170,18 @@ class _OffersAndDiscountsPageState extends State<OffersAndDiscountsPage> {
return CollapsingListView( return CollapsingListView(
title: LocaleKeys.offerAndPackages.tr(context: context), title: LocaleKeys.offerAndPackages.tr(context: context),
history: () { history: () {
if (!appState.isAuthenticated) {
getIt<DialogService>().showErrorBottomSheet(
message: LocaleKeys.loginToUseService.tr(),
onOkPressed: () {
Navigator.of(context).pop();
getIt<AuthenticationViewModel>().onLoginPressed();
});
} else {
Navigator.of(context).push( Navigator.of(context).push(
CustomPageRoute(page: OffersAndDiscountsHistoryPage()), CustomPageRoute(page: OffersAndDiscountsHistoryPage()),
); );
}
}, },
child: SingleChildScrollView( child: SingleChildScrollView(
child: Consumer<OffersAndDiscountsViewModel>(builder: (context, offersAndDiscountVM, child) { child: Consumer<OffersAndDiscountsViewModel>(builder: (context, offersAndDiscountVM, child) {
@ -180,18 +193,29 @@ class _OffersAndDiscountsPageState extends State<OffersAndDiscountsPage> {
TextInputWidget( TextInputWidget(
labelText: LocaleKeys.search.tr(context: context), labelText: LocaleKeys.search.tr(context: context),
hintText: LocaleKeys.typeAnyOffer.tr(), hintText: LocaleKeys.typeAnyOffer.tr(),
hintColor: AppColors.textColor,
controller: _searchController, controller: _searchController,
onChange: (value) { leadingIcon: AppAssets.search_icon,
offersAndDiscountVM.setSearchQuery(value!);
},
isEnable: true, isEnable: true,
prefix: null, prefix: null,
isAllowLeadingIcon: true,
autoFocus: false, autoFocus: false,
isBorderAllowed: false, isBorderAllowed: false,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
isAllowLeadingIcon: true, focusNode: textFocusNode,
selectionType: SelectionTypeEnum.search, suffix: _searchController.text.isNotEmpty
? GestureDetector(
onTap: () {
_searchController.clear();
// bookAppointmentsViewModel.filterClinics("");
offersAndDiscountVM.setSearchQuery("");
textFocusNode.unfocus();
},
child: Utils.buildSvgWithAssets(icon: AppAssets.close_bottom_sheet_icon, width: 20.h, height: 20.h, fit: BoxFit.scaleDown),
)
: null,
onChange: (value) {
offersAndDiscountVM.setSearchQuery(value!);
},
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
vertical: ResponsiveExtension(10).h, vertical: ResponsiveExtension(10).h,
horizontal: ResponsiveExtension(15).h, horizontal: ResponsiveExtension(15).h,
@ -342,6 +366,14 @@ class _OffersAndDiscountsPageState extends State<OffersAndDiscountsPage> {
icon: AppAssets.shoppingCart, icon: AppAssets.shoppingCart,
iconColor: AppColors.whiteColor, iconColor: AppColors.whiteColor,
onPressed: () async { onPressed: () async {
if (!appState.isAuthenticated) {
getIt<DialogService>().showErrorBottomSheet(
message: LocaleKeys.loginToUseService.tr(),
onOkPressed: () {
Navigator.of(context).pop();
getIt<AuthenticationViewModel>().onLoginPressed();
});
} else {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.pleaseWait.tr(context: context)); LoaderBottomSheet.showLoader(loadingText: LocaleKeys.pleaseWait.tr(context: context));
// Ensure patient is authenticated (will re-authenticate if needed) // Ensure patient is authenticated (will re-authenticate if needed)
@ -385,6 +417,7 @@ class _OffersAndDiscountsPageState extends State<OffersAndDiscountsPage> {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
}, },
); );
}
}, },
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor, borderColor: AppColors.primaryRedColor,

@ -48,6 +48,8 @@ class TextInputWidget extends StatelessWidget {
final Color? labelColor; final Color? labelColor;
final Function(String)? onSubmitted; final Function(String)? onSubmitted;
final String? btnTitle; final String? btnTitle;
final bool showSearchClear;
final VoidCallback? onClear;
// new multiline options // new multiline options
final bool isMultiline; final bool isMultiline;
@ -102,6 +104,8 @@ class TextInputWidget extends StatelessWidget {
// this.countryList = const [], // this.countryList = const [],
// this.onCountryChange, // this.onCountryChange,
this.btnTitle, this.btnTitle,
this.showSearchClear = false,
this.onClear,
}); });
final FocusNode _focusNode = FocusNode(); final FocusNode _focusNode = FocusNode();
@ -253,7 +257,10 @@ class TextInputWidget extends StatelessWidget {
context, context,
child: DateRangeSelector( child: DateRangeSelector(
onRangeSelected: (DateTime? start, DateTime? end) { onRangeSelected: (DateTime? start, DateTime? end) {
var picked = start.toString().split(" ").first; var picked = start
.toString()
.split(" ")
.first;
if (picked != null && onChange != null) { if (picked != null && onChange != null) {
onChange!(picked.toString()); onChange!(picked.toString());
} }
@ -521,6 +528,23 @@ class TextInputWidget extends StatelessWidget {
} }
_buildTrailingIconForSearch(BuildContext context) { _buildTrailingIconForSearch(BuildContext context) {
if (showSearchClear) {
return GestureDetector(
onTap: () {
if (onClear != null) {
onClear!();
}
},
child: Container(
height: 40.h,
width: 40.h,
margin: EdgeInsets.zero,
padding: EdgeInsets.all(8.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 12.r, color: AppColors.whiteColor),
child: Utils.buildSvgWithAssets(icon: AppAssets.cross_circle),
),
);
} else {
return Container( return Container(
height: 40.h, height: 40.h,
width: 40.h, width: 40.h,
@ -530,14 +554,13 @@ class TextInputWidget extends StatelessWidget {
child: Utils.buildSvgWithAssets(icon: AppAssets.search_icon), child: Utils.buildSvgWithAssets(icon: AppAssets.search_icon),
); );
} }
}
} }
class _ThousandSeparatorInputFormatter extends TextInputFormatter { class _ThousandSeparatorInputFormatter extends TextInputFormatter {
@override @override
TextEditingValue formatEditUpdate( TextEditingValue formatEditUpdate(TextEditingValue oldValue,
TextEditingValue oldValue, TextEditingValue newValue,) {
TextEditingValue newValue,
) {
// Remove all commas to get the raw number // Remove all commas to get the raw number
String newText = newValue.text.replaceAll(',', ''); String newText = newValue.text.replaceAll(',', '');
@ -570,7 +593,11 @@ class _ThousandSeparatorInputFormatter extends TextInputFormatter {
count = 0; count = 0;
} }
} }
integerPart = buffer.toString().split('').reversed.join(); integerPart = buffer
.toString()
.split('')
.reversed
.join();
} }
final formatted = '$integerPart$decimalPart'; final formatted = '$integerPart$decimalPart';
@ -578,9 +605,13 @@ class _ThousandSeparatorInputFormatter extends TextInputFormatter {
// Calculate new cursor position // Calculate new cursor position
int cursorOffset = newValue.selection.baseOffset; int cursorOffset = newValue.selection.baseOffset;
// Count commas before cursor in the new formatted string // Count commas before cursor in the new formatted string
int commasInNew = ','.allMatches(formatted.substring(0, cursorOffset.clamp(0, formatted.length))).length; int commasInNew = ','
.allMatches(formatted.substring(0, cursorOffset.clamp(0, formatted.length)))
.length;
// Count commas before cursor in the old value // Count commas before cursor in the old value
int commasInOld = ','.allMatches(oldValue.text.substring(0, oldValue.selection.baseOffset.clamp(0, oldValue.text.length))).length; int commasInOld = ','
.allMatches(oldValue.text.substring(0, oldValue.selection.baseOffset.clamp(0, oldValue.text.length)))
.length;
int newCursorPos = cursorOffset + (commasInNew - commasInOld); int newCursorPos = cursorOffset + (commasInNew - commasInOld);
newCursorPos = newCursorPos.clamp(0, formatted.length); newCursorPos = newCursorPos.clamp(0, formatted.length);

Loading…
Cancel
Save