diff --git a/assets/images/svg/accessibility.svg b/assets/images/svg/accessibility.svg
new file mode 100644
index 0000000..fbe3d12
--- /dev/null
+++ b/assets/images/svg/accessibility.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/svg/arrow_forward.svg b/assets/images/svg/arrow_forward.svg
new file mode 100644
index 0000000..2638c5b
--- /dev/null
+++ b/assets/images/svg/arrow_forward.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/svg/call_fill.svg b/assets/images/svg/call_fill.svg
new file mode 100644
index 0000000..25509ed
--- /dev/null
+++ b/assets/images/svg/call_fill.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/email_transparent.svg b/assets/images/svg/email_transparent.svg
new file mode 100644
index 0000000..6f45a86
--- /dev/null
+++ b/assets/images/svg/email_transparent.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/emergency.svg b/assets/images/svg/emergency.svg
new file mode 100644
index 0000000..7a5a6e3
--- /dev/null
+++ b/assets/images/svg/emergency.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/external_link.svg b/assets/images/svg/external_link.svg
new file mode 100644
index 0000000..822ebc2
--- /dev/null
+++ b/assets/images/svg/external_link.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/svg/language_change.svg b/assets/images/svg/language_change.svg
new file mode 100644
index 0000000..e84f0c3
--- /dev/null
+++ b/assets/images/svg/language_change.svg
@@ -0,0 +1,11 @@
+
diff --git a/assets/images/svg/minus.svg b/assets/images/svg/minus.svg
new file mode 100644
index 0000000..01d8ebd
--- /dev/null
+++ b/assets/images/svg/minus.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/svg/my_address.svg b/assets/images/svg/my_address.svg
new file mode 100644
index 0000000..59faec9
--- /dev/null
+++ b/assets/images/svg/my_address.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/svg/permission.svg b/assets/images/svg/permission.svg
new file mode 100644
index 0000000..00d6f5c
--- /dev/null
+++ b/assets/images/svg/permission.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/privacy_terms.svg b/assets/images/svg/privacy_terms.svg
new file mode 100644
index 0000000..ee79318
--- /dev/null
+++ b/assets/images/svg/privacy_terms.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/svg/rate.svg b/assets/images/svg/rate.svg
new file mode 100644
index 0000000..bfdaf3f
--- /dev/null
+++ b/assets/images/svg/rate.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/smart_phone_fill.svg b/assets/images/svg/smart_phone_fill.svg
new file mode 100644
index 0000000..70beb7f
--- /dev/null
+++ b/assets/images/svg/smart_phone_fill.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/touch_face_id.svg b/assets/images/svg/touch_face_id.svg
new file mode 100644
index 0000000..07808bd
--- /dev/null
+++ b/assets/images/svg/touch_face_id.svg
@@ -0,0 +1,4 @@
+
diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart
index 4a8a3da..0a414d0 100644
--- a/lib/core/app_assets.dart
+++ b/lib/core/app_assets.dart
@@ -4,6 +4,8 @@ class AppAssets {
static const String hmg = '$svgBasePath/hmg.svg';
static const String arrow_back = '$svgBasePath/arrow-back.svg';
+ static const String arrow_forward = '$svgBasePath/arrow_forward.svg';
+ static const String externalLink = '$svgBasePath/external_link.svg';
static const String calendar = '$svgBasePath/calendar.svg';
static const String hmc = '$svgBasePath/hmc.svg';
static const String ksa = '$svgBasePath/ksa.svg';
@@ -117,6 +119,18 @@ class AppAssets {
static const String free_med_delivery_icon = '$svgBasePath/free_med_delivery_icon.svg';
static const String livecare_book_icon = '$svgBasePath/livecare_book_icon.svg';
static const String doctor_profile_icon = '$svgBasePath/doctor_profile_icon.svg';
+ static const String accessibility = '$svgBasePath/accessibility.svg';
+ static const String call_fill = '$svgBasePath/call_fill.svg';
+ static const String email_transparent = '$svgBasePath/email_transparent.svg';
+ static const String emergency = '$svgBasePath/emergency.svg';
+ static const String language_change = '$svgBasePath/language_change.svg';
+ static const String my_address = '$svgBasePath/my_address.svg';
+ static const String permission = '$svgBasePath/permission.svg';
+ static const String privacy_terms = '$svgBasePath/privacy_terms.svg';
+ static const String rate = '$svgBasePath/rate.svg';
+ static const String smart_phone_fill = '$svgBasePath/smart_phone_fill.svg';
+ static const String touch_face_id = '$svgBasePath/touch_face_id.svg';
+ static const String minus = '$svgBasePath/minus.svg';
//bottom navigation//
static const String homeBottom = '$svgBasePath/home_bottom.svg';
@@ -127,6 +141,7 @@ class AppAssets {
static const String closeBottomNav = '$svgBasePath/close_bottom_nav.svg';
static const String feedback = '$svgBasePath/feedback.svg';
static const String news = '$svgBasePath/news.svg';
+
// PNGS //
static const String hmg_logo = '$pngBasePath/hmg_logo.png';
static const String livecare_service = '$pngBasePath/livecare_service.png';
@@ -148,5 +163,4 @@ class AppAnimations {
static const String loadingAnimation = '$lottieBasePath/Loader.json';
static const String errorAnimation = '$lottieBasePath/ErrorAnimation.json';
static const String warningAnimation = '$lottieBasePath/warningAnimation.json';
-
}
diff --git a/lib/core/utils/calendar_utils.dart b/lib/core/utils/calendar_utils.dart
index 979ce1b..2068db9 100644
--- a/lib/core/utils/calendar_utils.dart
+++ b/lib/core/utils/calendar_utils.dart
@@ -285,11 +285,11 @@ Future checkAndRemove(hasReminder, {bool delete = false, String itemDescri
if (calendarUtils.calendars != null) {
if (Platform.isAndroid) {
- await processEvents(calendarUtils.calendars, calendarUtils, params, delete, itemDescriptionN,hasReminder);
+ await processEvents(calendarUtils.calendars, calendarUtils, params, delete, itemDescriptionN, hasReminder);
} else {
List? iosCalendars = await _myPlugin.getCalendars();
if (iosCalendars != null) {
- await processEvents(iosCalendars.map((cal) => Calendar(id: cal.id, name: cal.name, accountName: cal.accountName)).toList(), calendarUtils, params, delete, itemDescriptionN,hasReminder);
+ await processEvents(iosCalendars.map((cal) => Calendar(id: cal.id, name: cal.name, accountName: cal.accountName)).toList(), calendarUtils, params, delete, itemDescriptionN, hasReminder);
}
}
}
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/extensions/int_extensions.dart b/lib/extensions/int_extensions.dart
index 4a2e477..80b3171 100644
--- a/lib/extensions/int_extensions.dart
+++ b/lib/extensions/int_extensions.dart
@@ -6,9 +6,7 @@ extension IntExtensions on int {
Widget get width => SizedBox(width: toDouble());
- Widget get divider => Divider(height: toDouble(), thickness: toDouble(), color: AppColors.buttonColor);
+ Widget get divider => Divider(height: toDouble(), thickness: toDouble(), color: Color(0x30D2D2D2));
Widget get makeItSquare => SizedBox(width: toDouble(), height: toDouble());
-
-
}
diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart
index 02e99f1..7140c05 100644
--- a/lib/extensions/string_extensions.dart
+++ b/lib/extensions/string_extensions.dart
@@ -132,14 +132,26 @@ extension EmailValidator on String {
decoration: isUnderLine ? TextDecoration.underline : null),
);
- Widget toText14({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, FontWeight? weight, int? maxlines, double? letterSpacing = -1}) => Text(
+ Widget toText14(
+ {Color? color,
+ bool isUnderLine = false,
+ bool isBold = false,
+ bool isCenter = false,
+ FontWeight? weight,
+ int? maxlines,
+ double? letterSpacing = -1,
+ double? height,
+ TextOverflow? textOverflow}) =>
+ Text(
this,
textAlign: isCenter ? TextAlign.center : null,
maxLines: maxlines,
+ overflow: textOverflow,
style: TextStyle(
color: color ?? AppColors.blackColor,
fontSize: 14.fSize,
letterSpacing: letterSpacing,
+ height: height,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
decoration: isUnderLine ? TextDecoration.underline : null),
);
@@ -162,8 +174,10 @@ extension EmailValidator on String {
bool isBold = false,
bool isCenter = false,
int? maxlines,
+ double? height,
TextAlign? textAlign,
FontWeight? weight,
+ TextOverflow? textOverflow,
double? letterSpacing = -0.4,
}) =>
Text(
@@ -174,6 +188,8 @@ extension EmailValidator on String {
color: color ?? AppColors.blackColor,
fontSize: 16.fSize,
letterSpacing: letterSpacing,
+ height: height,
+ overflow: textOverflow,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
decoration: isUnderLine ? TextDecoration.underline : null,
),
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 0a5ec2c..01b1490 100644
--- a/lib/presentation/home/landing_page.dart
+++ b/lib/presentation/home/landing_page.dart
@@ -36,6 +36,8 @@ 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/custom_page_route.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';
@@ -90,25 +92,24 @@ class _LandingPageState extends State {
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: SingleChildScrollView(
+ padding: EdgeInsets.only(top: kToolbarHeight + 12.h, bottom: 24),
child: Column(
+ spacing: 16.h,
children: [
- Padding(
- padding: EdgeInsets.only(top: 50.0),
- child: Row(
+ Row(
+ spacing: 8.h,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
appState.isAuthenticated
? WelcomeWidget(
onTap: () {
Navigator.of(context).push(
- FadePage(
- page: ProfileSettings(),
- ),
+ springPageRoute(ProfileSettings())
);
},
name: ('${appState.getAuthenticatedUser()!.firstName!} ${appState.getAuthenticatedUser()!.lastName!}'),
imageUrl: appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg,
- )
+ ).expanded
: CustomButton(
text: LocaleKeys.loginOrRegister.tr(context: context),
onPressed: () async {
@@ -124,37 +125,37 @@ class _LandingPageState extends State {
height: 50,
),
Row(
- children: [
- Utils.buildSvgWithAssets(icon: AppAssets.bell, height: 20, width: 20).onPress(() {
- Navigator.of(context).push(
- FadePage(
- page: MedicalFilePage(),
- // page: LoginScreen(),
- ),
- );
- }).paddingSymmetrical(8.h, 0),
- Utils.buildSvgWithAssets(icon: AppAssets.search_icon, height: 20, width: 20).onPress(() {
- Navigator.of(context).push(
- FadePage(
- page: MedicalFilePage(),
- // page: LoginScreen(),
- ),
- );
- }).paddingSymmetrical(8.h, 0),
- Utils.buildSvgWithAssets(icon: AppAssets.contact_icon, height: 20, width: 20).onPress(() {
- Navigator.of(context).push(
- FadePage(
- page: MedicalFilePage(),
- // page: LoginScreen(),
- ),
- );
- }).paddingSymmetrical(8.h, 0),
- ],
- )
- ],
- ).paddingSymmetrical(24.h, 0.h),
- ),
- SizedBox(height: 16.h),
+ mainAxisSize: MainAxisSize.min,
+ spacing: 12.h,
+ children: [
+ Utils.buildSvgWithAssets(icon: AppAssets.bell, height: 20, width: 20).onPress(() {
+ Navigator.of(context).push(
+ FadePage(
+ page: MedicalFilePage(),
+ // page: LoginScreen(),
+ ),
+ );
+ }),
+ Utils.buildSvgWithAssets(icon: AppAssets.search_icon, height: 20, width: 20).onPress(() {
+ Navigator.of(context).push(
+ FadePage(
+ page: MedicalFilePage(),
+ // page: LoginScreen(),
+ ),
+ );
+ }),
+ Utils.buildSvgWithAssets(icon: AppAssets.contact_icon, height: 20, width: 20).onPress(() {
+ Navigator.of(context).push(
+ FadePage(
+ page: MedicalFilePage(),
+ // page: LoginScreen(),
+ ),
+ );
+ }),
+ ],
+ )
+ ],
+ ).paddingSymmetrical(24.h, 0.h),
appState.isAuthenticated
? Column(
children: [
@@ -173,7 +174,7 @@ class _LandingPageState extends State {
],
).paddingSymmetrical(24.h, 0.h).onPress(() {
Navigator.of(context).push(
- FadePage(
+ CustomPageRoute(
page: MyAppointmentsPage(),
),
);
@@ -345,7 +346,6 @@ class _LandingPageState extends State {
),
),
).paddingSymmetrical(24.h, 0.h),
- SizedBox(height: 16.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -359,7 +359,6 @@ class _LandingPageState extends State {
),
],
).paddingSymmetrical(24.h, 0.h),
- SizedBox(height: 16.h),
SizedBox(
height: 325.h,
child: Column(
@@ -393,9 +392,7 @@ class _LandingPageState extends State {
],
),
),
- SizedBox(height: 16.h),
appState.isAuthenticated ? HabibWalletCard() : SizedBox(),
- SizedBox(height: 16.h),
],
),
),
diff --git a/lib/presentation/home/widgets/welcome_widget.dart b/lib/presentation/home/widgets/welcome_widget.dart
index d761a7f..4baee01 100644
--- a/lib/presentation/home/widgets/welcome_widget.dart
+++ b/lib/presentation/home/widgets/welcome_widget.dart
@@ -1,7 +1,9 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
+import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
+import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
class WelcomeWidget extends StatelessWidget {
@@ -23,32 +25,25 @@ class WelcomeWidget extends StatelessWidget {
borderRadius: BorderRadius.circular(30),
child: Row(
mainAxisSize: MainAxisSize.min,
+ spacing: 8.h,
children: [
- // Profile image
-
Image.asset(imageUrl, width: 40, height: 40),
-
- const SizedBox(width: 10),
-
- // Text column
Column(
crossAxisAlignment: CrossAxisAlignment.start,
+ spacing: 4.h,
+ mainAxisSize: MainAxisSize.min,
children: [
-
- "Welcome".toText14(color: AppColors.greyTextColor),
-
-
+ "Welcome".needTranslation.toText14(color: AppColors.greyTextColor, height: 1, weight: FontWeight.w500),
Row(
+ spacing: 4.h,
+ crossAxisAlignment: CrossAxisAlignment.center,
children: [
-
- name.toText16(isBold: true),
-
- const SizedBox(width: 4),
+ name.toText16(weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1, height: 1).expanded,
const Icon(Icons.keyboard_arrow_down, size: 20, color: Colors.black),
],
),
],
- ),
+ ).expanded,
],
),
);
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 baccbe2..832031a 100644
--- a/lib/presentation/profile_settings/profile_settings.dart
+++ b/lib/presentation/profile_settings/profile_settings.dart
@@ -1,15 +1,24 @@
+import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_swiper_view/flutter_swiper_view.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
+import 'package:hmg_patient_app_new/extensions/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';
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/app_language_change.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/common_bottom_sheet.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';
class ProfileSettings extends StatefulWidget {
@@ -70,7 +79,7 @@ class _ProfileSettingsState extends State {
},
),
GridView(
- gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, childAspectRatio: 105 / 105, crossAxisSpacing: 9, mainAxisSpacing: 9),
+ gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 9, mainAxisSpacing: 9),
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(24),
shrinkWrap: true,
@@ -83,17 +92,103 @@ class _ProfileSettingsState extends State {
hasShadow: true,
),
child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ spacing: 4.h,
children: [
Row(
+ spacing: 8.h,
+ crossAxisAlignment: CrossAxisAlignment.center,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.wallet, width: 40.h, height: 40.h),
+ "Al Habib Wallet".needTranslation.toText14(weight: FontWeight.w600, maxlines: 2).expanded,
+ Utils.buildSvgWithAssets(icon: AppAssets.arrow_forward),
],
- )
+ ),
+ Spacer(),
+ 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,
+ iconSize: 24.h,
+ iconColor: AppColors.infoColor,
+ textColor: AppColors.infoColor,
+ text: "Recharge",
+ borderWidth: 0.h,
+ fontWeight: FontWeight.w500,
+ borderColor: Colors.transparent,
+ backgroundColor: Color(0xff45A2F8).withValues(alpha: 0.08),
+ padding: EdgeInsets.all(8.h),
+ fontSize: 14,
+ onPressed: () {
+ Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage()));
+ },
+ ),
],
- ),
+ ).onPress(() {
+ Navigator.of(context).push(CustomPageRoute(page: HabibWalletPage()));
+ }),
)
],
- )
+ ),
+ "Quick Actions".needTranslation.toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24, right: 24),
+ Container(
+ margin: EdgeInsets.only(left: 24, right: 24, top: 16, bottom: 24),
+ padding: EdgeInsets.only(top: 4, bottom: 4),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
+ child: Column(
+ children: [
+ actionItem(AppAssets.language_change, "Language".needTranslation, () {
+ showCommonBottomSheetWithoutHeight(context, title: "Application Language".needTranslation, child: AppLanguageChange(), callBackFunc: () {}, isFullScreen: false);
+ }, trailingLabel: Utils.appState.isArabic() ? "العربية".needTranslation : "English".needTranslation),
+ 1.divider,
+ actionItem(AppAssets.accessibility, "Accessibility".needTranslation, () {}),
+ 1.divider,
+ actionItem(AppAssets.bell, "Notifications Settings".needTranslation, () {}),
+ 1.divider,
+ actionItem(AppAssets.touch_face_id, "Touch ID / Face ID Services".needTranslation, () {}, switchValue: true),
+ ],
+ ),
+ ),
+ "Personal Information".needTranslation.toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24, right: 24),
+ Container(
+ margin: EdgeInsets.only(left: 24, right: 24, top: 16, bottom: 24),
+ padding: EdgeInsets.only(top: 4, bottom: 4),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
+ child: Column(
+ children: [
+ actionItem(AppAssets.email_transparent, "Update Email Address".needTranslation, () {}),
+ 1.divider,
+ actionItem(AppAssets.smart_phone_fill, "Phone Number".needTranslation, () {}),
+ 1.divider,
+ actionItem(AppAssets.my_address, "My Addresses".needTranslation, () {}),
+ 1.divider,
+ actionItem(AppAssets.emergency, "Emergency Contact".needTranslation, () {}),
+ ],
+ ),
+ ),
+ "Help & Support".needTranslation.toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24, right: 24),
+ Container(
+ margin: EdgeInsets.only(left: 24, right: 24, top: 16),
+ padding: EdgeInsets.only(top: 4, bottom: 4),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
+ child: Column(
+ children: [
+ actionItem(AppAssets.call_fill, "Contact Us".needTranslation, () {}, trailingLabel: "9200666666"),
+ 1.divider,
+ actionItem(AppAssets.permission, "Permissions".needTranslation, () {}, trailingLabel: "Location, Camera"),
+ 1.divider,
+ actionItem(AppAssets.rate, "Rate Our App".needTranslation, () {}, isExternalLink: true),
+ 1.divider,
+ actionItem(AppAssets.privacy_terms, "Privacy Policy".needTranslation, () {}, isExternalLink: true),
+ 1.divider,
+ actionItem(AppAssets.privacy_terms, "Terms & Conditions".needTranslation, () {}, isExternalLink: true),
+ ],
+ ),
+ ),
+ CustomButton(icon: AppAssets.minus, text: "Deactivate account".needTranslation, onPressed: () {}).paddingAll(24),
],
);
},
@@ -101,6 +196,31 @@ class _ProfileSettingsState extends State {
),
);
}
+
+ Widget actionItem(String icon, String label, VoidCallback onPress, {String trailingLabel = "", bool? switchValue, bool isExternalLink = false}) {
+ return SizedBox(
+ height: 56,
+ child: Row(
+ spacing: 8.h,
+ children: [
+ Utils.buildSvgWithAssets(icon: icon, iconColor: AppColors.greyTextColor),
+ label.toText14(weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1).expanded,
+ if (trailingLabel.isNotEmpty) trailingLabel.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1),
+ switchValue != null
+ ? Switch(
+ value: switchValue,
+ onChanged: (value) {},
+ activeColor: AppColors.successColor,
+ activeTrackColor: AppColors.successColor.withValues(alpha: .15),
+ )
+ : Transform.scale(
+ scaleX: Utils.appState.isArabic() ? -1 : 1,
+ child: Utils.buildSvgWithAssets(icon: isExternalLink ? AppAssets.externalLink : AppAssets.arrow_forward),
+ )
+ ],
+ ).paddingOnly(left: 16, right: 16).onPress(onPress),
+ );
+ }
}
class FamilyCardWidget extends StatelessWidget {
@@ -160,12 +280,8 @@ class FamilyCardWidget extends StatelessWidget {
),
],
).paddingOnly(top: 16, right: 16, left: 16, bottom: 12).expanded,
- Divider(
- height: 1,
- thickness: 1,
- color: Color(0x30D2D2D2),
- ),
- CustomButton(icon: AppAssets.add_family, text: "Add a new family member", onPressed: () {}).paddingOnly(top: 12, right: 16, left: 16, bottom: 16),
+ 1.divider,
+ CustomButton(icon: AppAssets.add_family, text: "Add a new family member".needTranslation, onPressed: () {}).paddingOnly(top: 12, right: 16, left: 16, bottom: 16),
],
),
);
diff --git a/lib/widgets/app_language_change.dart b/lib/widgets/app_language_change.dart
new file mode 100644
index 0000000..de9cda5
--- /dev/null
+++ b/lib/widgets/app_language_change.dart
@@ -0,0 +1,87 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/core/utils/size_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/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
+import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
+
+class AppLanguageChange extends StatefulWidget {
+ AppLanguageChange({Key? key}) : super(key: key);
+
+ @override
+ _AppLanguageChangeState createState() {
+ return _AppLanguageChangeState();
+ }
+}
+
+class _AppLanguageChangeState extends State {
+ String? selectedValue;
+
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ selectedValue ??= context.locale.languageCode;
+ return Column(
+ spacing: 24.h,
+ children: [
+ Container(
+ padding: EdgeInsets.only(top: 4, bottom: 4),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
+ child: Column(
+ children: [
+ languageItem("English".needTranslation, "en"),
+ 1.divider,
+ languageItem("العربية".needTranslation, "ar"),
+ ],
+ ),
+ ),
+ CustomButton(
+ text: LocaleKeys.save.tr(),
+ onPressed: () {
+ context.setLocale(selectedValue == 'en' ? Locale('en', 'US') : Locale('ar', 'SA')).then((val) {
+ Navigator.pop(context);
+ });
+ }),
+ ],
+ );
+ }
+
+ Widget languageItem(String title, String _value) {
+ return SizedBox(
+ height: 72,
+ child: Row(
+ spacing: 8.h,
+ children: [
+ Radio(
+ value: _value,
+ groupValue: selectedValue,
+ activeColor: AppColors.errorColor,
+ onChanged: (value) {
+ setState(() {
+ selectedValue = _value;
+ });
+ },
+ materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+ ),
+ title.toText16(weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1).expanded,
+ ],
+ ).paddingOnly(left: 16, right: 16).onPress(() {
+ setState(() {
+ selectedValue = _value;
+ });
+ }),
+ );
+ }
+}
diff --git a/lib/widgets/buttons/custom_button.dart b/lib/widgets/buttons/custom_button.dart
index e1448dc..30e4e5d 100644
--- a/lib/widgets/buttons/custom_button.dart
+++ b/lib/widgets/buttons/custom_button.dart
@@ -48,6 +48,7 @@ class CustomButton extends StatelessWidget {
onTap: isDisabled ? null : onPressed,
child: Container(
height: height,
+ padding: padding,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: isDisabled ? Colors.transparent : backgroundColor,
borderRadius: borderRadius,
@@ -55,28 +56,25 @@ class CustomButton extends StatelessWidget {
width: borderWidth,
color: isDisabled ? borderColor.withOpacity(0.5) : borderColor,
)),
- child: Padding(
- padding: padding,
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.center,
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- if (icon != null)
- Padding(
- padding: const EdgeInsets.only(right: 8.0),
- child: Utils.buildSvgWithAssets(icon: icon!, iconColor: iconColor, isDisabled: isDisabled, width: iconSize, height: iconSize),
- ),
- Text(
- text,
- style: context.dynamicTextStyle(
- fontSize: fontSize.fSize,
- color: isDisabled ? textColor.withOpacity(0.5) : textColor,
- letterSpacing: -0.4,
- fontWeight: fontWeight,
- ),
+ child: Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ if (icon != null)
+ Padding(
+ padding: const EdgeInsets.only(right: 8.0),
+ child: Utils.buildSvgWithAssets(icon: icon!, iconColor: iconColor, isDisabled: isDisabled, width: iconSize, height: iconSize),
),
- ],
- ),
+ Text(
+ text,
+ style: context.dynamicTextStyle(
+ fontSize: fontSize.fSize,
+ color: isDisabled ? textColor.withOpacity(0.5) : textColor,
+ letterSpacing: -0.4,
+ fontWeight: fontWeight,
+ ),
+ ),
+ ],
),
)
diff --git a/lib/widgets/routes/custom_page_route.dart b/lib/widgets/routes/custom_page_route.dart
new file mode 100644
index 0000000..733993f
--- /dev/null
+++ b/lib/widgets/routes/custom_page_route.dart
@@ -0,0 +1,60 @@
+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: 1500),
+ reverseTransitionDuration: const Duration(milliseconds: 500),
+ 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..0533408
--- /dev/null
+++ b/lib/widgets/routes/spring_page_route_builder.dart
@@ -0,0 +1,39 @@
+import 'package:flutter/physics.dart';
+import 'package:flutter/widgets.dart';
+
+PageRouteBuilder springPageRoute(Widget page) {
+ return PageRouteBuilder(
+ pageBuilder: (_, __, ___) => page,
+ transitionDuration: const Duration(milliseconds: 1500),
+ reverseTransitionDuration: const Duration(milliseconds: 500),
+ 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
+ }
+}