diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart index d34a44c..152cd54 100644 --- a/lib/core/utils/utils.dart +++ b/lib/core/utils/utils.dart @@ -650,6 +650,24 @@ class Utils { ); } + static Widget getPaymentAmountWithSymbol2(num habibWalletAmount, Color iconColor, double iconSize, {bool isSaudiCurrency = true, bool isExpanded = true}) { + return RichText( + text: TextSpan( + children: [ + WidgetSpan( + alignment: PlaceholderAlignment.baseline, + baseline: TextBaseline.alphabetic, + child: Utils.buildSvgWithAssets(icon: AppAssets.saudi_riyal_icon, width: 14.h, height: 14.h, iconColor: Colors.black.withValues(alpha: 0.31)), + ), + TextSpan( + text: " $habibWalletAmount", + style: TextStyle(color: AppColors.blackColor, fontSize: 32.fSize, letterSpacing: -4, fontWeight: FontWeight.w600, height: 1), + ), + ], + ), + ); + } + static Future isGoogleServicesAvailable() async { GooglePlayServicesAvailability availability = await GoogleApiAvailability.instance.checkGooglePlayServicesAvailability(); String status = availability.toString().split('.').last; diff --git a/lib/presentation/habib_wallet/habib_wallet_page.dart b/lib/presentation/habib_wallet/habib_wallet_page.dart index 1d24d05..1be3e12 100644 --- a/lib/presentation/habib_wallet/habib_wallet_page.dart +++ b/lib/presentation/habib_wallet/habib_wallet_page.dart @@ -51,6 +51,7 @@ class _HabibWalletState extends State { children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -58,7 +59,7 @@ class _HabibWalletState extends State { "${_appState.getAuthenticatedUser()!.firstName!} ${_appState.getAuthenticatedUser()!.lastName!}".toText19(isBold: true, color: AppColors.whiteColor), "MRN: ${_appState.getAuthenticatedUser()!.patientId!}".toText14(weight: FontWeight.w500, color: AppColors.greyTextColor), ], - ), + ).expanded, Utils.buildSvgWithAssets(icon: AppAssets.habiblogo, width: 24.h, height: 24.h), ], ), diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index 41e1483..a68bd83 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -34,6 +34,7 @@ import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart' show CustomTabBar; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; +import 'package:hmg_patient_app_new/widgets/routes/spring_page_route_builder.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:provider/provider.dart'; @@ -96,11 +97,7 @@ class _LandingPageState extends State { appState.isAuthenticated ? WelcomeWidget( onTap: () { - Navigator.of(context).push( - FadePage( - page: ProfileSettings(), - ), - ); + Navigator.of(context).push(springPageRoute(ProfileSettings())); }, name: ('${appState.getAuthenticatedUser()!.firstName!} ${appState.getAuthenticatedUser()!.lastName!}'), imageUrl: appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg, diff --git a/lib/presentation/lab/collapsing_list_view.dart b/lib/presentation/lab/collapsing_list_view.dart index f84872d..8f63f76 100644 --- a/lib/presentation/lab/collapsing_list_view.dart +++ b/lib/presentation/lab/collapsing_list_view.dart @@ -41,11 +41,14 @@ class CollapsingListView extends StatelessWidget { systemOverlayStyle: SystemUiOverlayStyle(statusBarBrightness: Brightness.light), surfaceTintColor: Colors.transparent, backgroundColor: AppColors.bgScaffoldColor, - leading: isLeading ? IconButton( - icon: Utils.buildSvgWithAssets(icon: isClose ? AppAssets.closeBottomNav : AppAssets.arrow_back, width: 32.h, height: 32.h), - padding: EdgeInsets.only(left: 12), - onPressed: () => Navigator.pop(context), - ) : SizedBox.shrink(), + leading: isLeading + ? IconButton( + icon: Utils.buildSvgWithAssets(icon: isClose ? AppAssets.closeBottomNav : AppAssets.arrow_back, width: 32.h, height: 32.h), + padding: EdgeInsets.only(left: 12), + onPressed: () => Navigator.pop(context), + highlightColor: Colors.transparent, + ) + : SizedBox.shrink(), flexibleSpace: LayoutBuilder( builder: (context, constraints) { final double maxHeight = 100; diff --git a/lib/presentation/profile_settings/profile_settings.dart b/lib/presentation/profile_settings/profile_settings.dart index 190fe03..bc99774 100644 --- a/lib/presentation/profile_settings/profile_settings.dart +++ b/lib/presentation/profile_settings/profile_settings.dart @@ -6,6 +6,7 @@ import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/int_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; +import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart'; import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart'; import 'package:hmg_patient_app_new/presentation/habib_wallet/habib_wallet_page.dart'; import 'package:hmg_patient_app_new/presentation/habib_wallet/recharge_wallet_page.dart'; @@ -13,6 +14,7 @@ import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; +import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:provider/provider.dart'; @@ -100,19 +102,10 @@ class _ProfileSettingsState extends State { ], ), Spacer(), - RichText( - text: TextSpan( - children: [ - WidgetSpan( - child: Utils.buildSvgWithAssets(icon: AppAssets.saudi_riyal_icon, width: 14.h, height: 14.h, iconColor: Colors.black.withValues(alpha: 0.31)), - ), - TextSpan( - text: " 247", - style: TextStyle(color: AppColors.blackColor, fontSize: 32.fSize, letterSpacing: -4, fontWeight: FontWeight.w600), - ), - ], - ), - ), + Consumer(builder: (context, habibWalletVM, child) { + return Utils.getPaymentAmountWithSymbol2(habibWalletVM.habibWalletAmount, AppColors.whiteColor, 13.h, isExpanded: false) + .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 24.h); + }), CustomButton( height: 40.h, icon: AppAssets.recharge_icon, @@ -127,12 +120,12 @@ class _ProfileSettingsState extends State { padding: EdgeInsets.all(8.h), fontSize: 14, onPressed: () { - Navigator.of(context).push(FadePage(page: RechargeWalletPage())); + Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage())); }, ), ], ).onPress(() { - Navigator.of(context).push(FadePage(page: HabibWalletPage())); + Navigator.of(context).push(CustomPageRoute(page: HabibWalletPage())); }), ) ], diff --git a/lib/widgets/routes/custom_page_route.dart b/lib/widgets/routes/custom_page_route.dart new file mode 100644 index 0000000..49ebc98 --- /dev/null +++ b/lib/widgets/routes/custom_page_route.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/physics.dart'; + +/// Reusable spring route +class CustomPageRoute extends PageRouteBuilder { + final Widget page; + final AxisDirection direction; + + CustomPageRoute({required this.page, this.direction = AxisDirection.right}) + : super( + transitionDuration: const Duration(milliseconds: 1000), + pageBuilder: (_, __, ___) => page, + transitionsBuilder: (context, animation, secondaryAnimation, child) { + final spring = SpringDescription(mass: 1, stiffness: 100, damping: 15); + + // Drive animation with spring + final curvedAnimation = animation.drive( + Tween(begin: 0.0, end: 1.0).chain(CurveTween(curve: _SpringCurve(spring))), + ); + + // Choose offset based on direction + Offset beginOffset; + switch (direction) { + case AxisDirection.left: + beginOffset = const Offset(-1.0, 0.0); + break; + case AxisDirection.right: + beginOffset = const Offset(1.0, 0.0); + break; + case AxisDirection.up: + beginOffset = const Offset(0.0, -1.0); + break; + case AxisDirection.down: + beginOffset = const Offset(0.0, 1.0); + break; + } + + final offsetAnimation = Tween(begin: beginOffset, end: Offset.zero).animate(curvedAnimation); + + return SlideTransition( + position: offsetAnimation, + child: child, + ); + }, + ); +} + +/// Custom spring curve +class _SpringCurve extends Curve { + final SpringDescription spring; + + _SpringCurve(this.spring); + + @override + double transform(double t) { + final sim = SpringSimulation(spring, 0, 1, 0); + return sim.x(t * 1.5); // scaled time + } +} diff --git a/lib/widgets/routes/spring_page_route_builder.dart b/lib/widgets/routes/spring_page_route_builder.dart new file mode 100644 index 0000000..61611e1 --- /dev/null +++ b/lib/widgets/routes/spring_page_route_builder.dart @@ -0,0 +1,38 @@ +import 'package:flutter/physics.dart'; +import 'package:flutter/widgets.dart'; + +PageRouteBuilder springPageRoute(Widget page) { + return PageRouteBuilder( + pageBuilder: (_, __, ___) => page, + transitionDuration: const Duration(milliseconds: 1000), + transitionsBuilder: (context, animation, secondaryAnimation, child) { + final spring = SpringDescription(mass: 1, stiffness: 100, damping: 15); + + final curvedAnimation = animation.drive( + Tween(begin: 0.0, end: 1.0).chain(CurveTween(curve: _SpringCurve(spring))), + ); + + final offsetAnimation = Tween( + begin: const Offset(-1.0, 0.0), // slide from left + end: Offset.zero, + ).animate(curvedAnimation); + + return SlideTransition( + position: offsetAnimation, + child: child, + ); + }, + ); +} + +class _SpringCurve extends Curve { + final SpringDescription spring; + + _SpringCurve(this.spring); + + @override + double transform(double t) { + final sim = SpringSimulation(spring, 0, 1, 0); + return sim.x(t * 1.5); // scale time so it completes properly + } +}