Merge branch 'master' into haroon_dev

haroon_dev
haroon amjad 3 weeks ago
commit 3c81cffa75

@ -15,7 +15,6 @@ import 'package:flutter_ios_voip_kit_karmm/flutter_ios_voip_kit.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:hmg_patient_app_new/core/utils/local_notifications.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/services/cache_service.dart';
import 'package:permission_handler/permission_handler.dart';
import '../cache_consts.dart';
@ -355,7 +354,6 @@ class PushNotificationHandler {
}
onToken(String token) async {
print("Push Notification Token: " + token);
await Utils.saveStringFromPrefs(CacheConst.pushToken, token);
}
@ -370,7 +368,9 @@ class PushNotificationHandler {
Future<void> requestPermissions() async {
try {
if (Platform.isIOS) {
await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()?.requestPermissions(alert: true, badge: true, sound: true);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(alert: true, badge: true, sound: true);
} else if (Platform.isAndroid) {
Map<Permission, PermissionStatus> statuses = await [
Permission.notification,

@ -1,25 +1,41 @@
import 'dart:developer';
import 'package:flutter/material.dart'; // These are the Viewport values of your Figma Design.
// These are used in the code as a reference to create your UI Responsively.
final num FIGMA_DESIGN_WIDTH = SizeUtils.width;
final num FIGMA_DESIGN_HEIGHT = SizeUtils.height;
const num FIGMA_DESIGN_STATUS_BAR = 0;
const num figmaDesignWidth = 375; // iPhone X / 12 base width
const num figmaDesignHeight = 812; // iPhone X / 12 base height
extension ResponsiveExtension on num {
double get _width => SizeUtils.width;
double get _screenWidth => SizeUtils.width;
double get h => ((this * _width) / FIGMA_DESIGN_WIDTH);
double get _screenHeight => SizeUtils.height;
double get fSize => ((this * _width) / FIGMA_DESIGN_WIDTH);
static double get screenHeight => SizeUtils.height;
/// Scale horizontally (width-based)
double get w => (this * _screenWidth) / figmaDesignWidth;
/// Scale vertically (height-based)
double get h => (this * _screenHeight) / figmaDesignHeight;
//radius
double get r => (this * _screenWidth) / figmaDesignWidth;
/// Scale text size
double get f {
double scale = _screenWidth / figmaDesignWidth;
if (scale > 1.6) scale = 1.6; // optional clamp for tablets
return this * scale;
}
/// Full screen width
/// Optional: direct accessors for full width/height
static double get screenWidth => SizeUtils.width;
static double get screenHeight => SizeUtils.height;
}
extension FormatExtension on double {
double toDoubleValue({int fractionDigits = 2}) {
return double.parse(this.toStringAsFixed(fractionDigits));
return double.parse(toStringAsFixed(fractionDigits));
}
double isNonZero({num defaultValue = 0.0}) {
@ -36,7 +52,7 @@ typedef ResponsiveBuild = Widget Function(
);
class Sizer extends StatelessWidget {
const Sizer({Key? key, required this.builder}) : super(key: key);
const Sizer({super.key, required this.builder});
/// Builds the widget whenever the orientation changes.
final ResponsiveBuild builder;
@ -81,17 +97,46 @@ class SizeUtils {
) {
boxConstraints = constraints;
orientation = currentOrientation;
double screenWidth;
double screenHeight;
if (orientation == Orientation.portrait) {
width = boxConstraints.maxWidth.isNonZero(
defaultValue: FIGMA_DESIGN_WIDTH,
screenWidth = boxConstraints.maxWidth.isNonZero(
defaultValue: figmaDesignWidth,
);
height = boxConstraints.maxHeight.isNonZero();
screenHeight = boxConstraints.maxHeight.isNonZero();
} else {
width = boxConstraints.maxHeight.isNonZero(
defaultValue: FIGMA_DESIGN_WIDTH,
screenWidth = boxConstraints.maxHeight.isNonZero(
defaultValue: figmaDesignWidth,
);
height = boxConstraints.maxWidth.isNonZero();
screenHeight = boxConstraints.maxWidth.isNonZero();
}
deviceType = DeviceType.mobile;
width = screenWidth;
height = screenHeight;
// Fix device type detection
double longerSide = screenWidth > screenHeight ? screenWidth : screenHeight;
double shorterSide = screenWidth < screenHeight ? screenWidth : screenHeight;
if (longerSide >= 1200) {
deviceType = DeviceType.tablet;
} else if (shorterSide >= 700) {
// Use shorter side to distinguish tablets (iPads typically have 768+ width)
deviceType = DeviceType.tablet;
} else {
deviceType = DeviceType.mobile;
}
log("longerSide: $longerSide");
log("isTablet: $isTablet");
}
}
// Or create a helper method
bool get isTablet => SizeUtils.deviceType == DeviceType.tablet;
bool get isMobile => SizeUtils.deviceType == DeviceType.mobile;
bool get isDesktop => SizeUtils.deviceType == DeviceType.desktop;

@ -1,6 +1,7 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'dart:math' as dartMath;
import 'dart:typed_data';
import 'package:connectivity_plus/connectivity_plus.dart';
@ -27,8 +28,6 @@ import 'package:lottie/lottie.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:math' as dartMath;
class Utils {
static AppState appState = getIt.get<AppState>();
static NavigationService navigationService = getIt.get<NavigationService>();
@ -67,8 +66,10 @@ class Utils {
// ),
// ));
return !isAddHours
? DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US").format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.toLocal())
: DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US").format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.add(
? DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US")
.format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.toLocal())
: DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US")
.format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.add(
Duration(
hours: isAddHours ? 3 : 0,
),
@ -301,7 +302,14 @@ class Utils {
return false;
}
static Widget getNoDataWidget(BuildContext context, {double width = 124, double height = 124, String? noDataText, Widget callToActionButton = const SizedBox.shrink(), bool isSmallWidget = false}) {
static Widget getNoDataWidget(
BuildContext context, {
double width = 124,
double height = 124,
String? noDataText,
Widget callToActionButton = const SizedBox.shrink(),
bool isSmallWidget = false,
}) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
@ -309,7 +317,9 @@ class Utils {
SizedBox(height: isSmallWidget ? 0.h : 48.h),
Lottie.asset(AppAnimations.noData, repeat: false, reverse: false, frameRate: FrameRate(60), width: width.h, height: height.h, fit: BoxFit.fill),
SizedBox(height: 16.h),
(noDataText ?? LocaleKeys.noDataAvailable.tr()).toText16(weight: FontWeight.w500, color: AppColors.greyTextColor, isCenter: true).paddingSymmetrical(64.h, 0.h),
(noDataText ?? LocaleKeys.noDataAvailable.tr())
.toText16(weight: FontWeight.w500, color: AppColors.greyTextColor, isCenter: true)
.paddingSymmetrical(64.w, 0.h),
SizedBox(height: 16.h),
callToActionButton
],
@ -461,8 +471,10 @@ class Utils {
}
// Replace HTML line breaks with newlines
var withLineBreaks =
htmlString.replaceAll(RegExp(r'<br\s*\/?>', multiLine: true), '\n').replaceAll(RegExp(r'<\/p>', multiLine: true), '\n').replaceAll(RegExp(r'<divider>', multiLine: true), '\n');
var withLineBreaks = htmlString
.replaceAll(RegExp(r'<br\s*\/?>', multiLine: true), '\n')
.replaceAll(RegExp(r'<\/p>', multiLine: true), '\n')
.replaceAll(RegExp(r'<divider>', multiLine: true), '\n');
// Remove all other HTML tags
var withoutTags = withLineBreaks.replaceAll(RegExp(r'<[^>]*>'), '');
@ -540,7 +552,20 @@ class Utils {
final year = parts[0];
// Map month number to short month name (Hijri months)
const hijriMonthNames = ['Muharram', 'Safar', 'Rabi I', 'Rabi II', 'Jumada I', 'Jumada II', 'Rajab', 'Sha\'ban', 'Ramadan', 'Shawwal', 'Dhu al-Qi\'dah', 'Dhu al-Hijjah'];
const hijriMonthNames = [
'Muharram',
'Safar',
'Rabi I',
'Rabi II',
'Jumada I',
'Jumada II',
'Rajab',
'Sha\'ban',
'Ramadan',
'Shawwal',
'Dhu al-Qi\'dah',
'Dhu al-Hijjah'
];
final monthIndex = int.tryParse(parts[1]) ?? 1;
final month = hijriMonthNames[monthIndex - 1];
@ -626,18 +651,20 @@ class Utils {
required String icon,
Color? iconColor,
bool isDisabled = false,
double width = 24,
double height = 24,
double? width,
double? height,
BoxFit fit = BoxFit.cover,
double? border,
double? borderRadius,
}) {
final iconH = height ?? 24.h;
final iconW = width ?? 24.w;
return Container(
decoration: BoxDecoration(
border: border != null ? Border.all(color: AppColors.whiteColor, width: border) : null,
borderRadius: border != null ? BorderRadius.circular(borderRadius ?? 0) : null,
),
child: Image.asset(icon, width: width, height: height, fit: fit),
child: Image.asset(icon, width: iconW, height: iconH, fit: fit),
);
// return Image.asset(icon, width: width, height: height, fit: fit, );
}
@ -662,16 +689,17 @@ class Utils {
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Image.asset(AppAssets.mada, width: 25, height: 25),
Image.asset(AppAssets.tamara_en, width: 25, height: 25),
Image.asset(AppAssets.visa, width: 25, height: 25),
Image.asset(AppAssets.Mastercard, width: 25, height: 25),
Image.asset(AppAssets.apple_pay, width: 25, height: 25),
Image.asset(AppAssets.mada, width: 25.h, height: 25.h),
Image.asset(AppAssets.tamara_en, width: 25.h, height: 25.h),
Image.asset(AppAssets.visa, width: 25.h, height: 25.h),
Image.asset(AppAssets.Mastercard, width: 25.h, height: 25.h),
Image.asset(AppAssets.apple_pay, width: 25.h, height: 25.h),
],
);
}
static Widget getPaymentAmountWithSymbol(Widget paymentAmountWidget, Color iconColor, double iconSize, {bool isSaudiCurrency = true, bool isExpanded = true}) {
static Widget getPaymentAmountWithSymbol(Widget paymentAmountWidget, Color iconColor, double iconSize,
{bool isSaudiCurrency = true, bool isExpanded = true}) {
return Row(
mainAxisAlignment: isExpanded ? MainAxisAlignment.spaceBetween : MainAxisAlignment.start,
children: [
@ -701,7 +729,11 @@ class Utils {
}
static Widget getPaymentAmountWithSymbol2(num habibWalletAmount,
{double iconSize = 14, Color iconColor = AppColors.textColor, Color textColor = AppColors.blackColor, bool isSaudiCurrency = true, bool isExpanded = true}) {
{double iconSize = 14,
Color iconColor = AppColors.textColor,
Color textColor = AppColors.blackColor,
bool isSaudiCurrency = true,
bool isExpanded = true}) {
return RichText(
maxLines: 1,
text: TextSpan(
@ -713,7 +745,7 @@ class Utils {
),
TextSpan(
text: " $habibWalletAmount",
style: TextStyle(color: textColor, fontSize: 32.fSize, letterSpacing: -4, fontWeight: FontWeight.w600, height: 1),
style: TextStyle(color: textColor, fontSize: 32.f, letterSpacing: -4, fontWeight: FontWeight.w600, height: 1),
),
],
),
@ -771,5 +803,4 @@ class Utils {
}
return isHavePrivilege;
}
}

@ -4,7 +4,6 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:hmg_patient_app_new/core/common_models/nationality_country_model.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
@ -102,7 +101,8 @@ class ValidationUtils {
return regex.hasMatch(id);
}
static bool validateUaeRegistration({String? name, GenderTypeEnum? gender, NationalityCountries? country, MaritalStatusTypeEnum? maritalStatus, required Function() onOkPress}) {
static bool validateUaeRegistration(
{String? name, GenderTypeEnum? gender, NationalityCountries? country, MaritalStatusTypeEnum? maritalStatus, required Function() onOkPress}) {
if (name == null || name.isEmpty) {
_dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseEnterAValidName.tr(), onOkPressed: onOkPress);
return false;
@ -141,7 +141,8 @@ class ValidationUtils {
return true;
}
static bool isValidatedIdAndPhoneWithCountryValidation({String? nationalId, String? phoneNumber, required Function() onOkPress, CountryEnum? selectedCountry}) {
static bool isValidatedIdAndPhoneWithCountryValidation(
{String? nationalId, String? phoneNumber, required Function() onOkPress, CountryEnum? selectedCountry}) {
bool isCorrectID = true;
if (nationalId == null || nationalId.isEmpty) {
_dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseEnterAnationalID.tr(), onOkPressed: onOkPress);

@ -5,11 +5,10 @@ extension ContextUtils on BuildContext {
double get screenWidth => MediaQuery.of(this).size.width;
EdgeInsets get padding => MediaQuery.of(this).padding;
EdgeInsets get padding => MediaQuery.of(this).padding;
bool get safeInsets => padding.top > 0 || padding.bottom > 0 || padding.left > 0 || padding.right > 0;
ThemeData get theme => Theme.of(this);
TextTheme get textTheme => theme.textTheme;
@ -24,9 +23,18 @@ extension ContextUtils on BuildContext {
}
extension ShowBottomSheet on BuildContext {
Future<T?> showBottomSheet<T>({isScrollControlled = true, isDismissible = false, required Widget child, Color? backgroundColor, enableDra = false, useSafeArea = false}) {
Future<T?> showBottomSheet<T>({
isScrollControlled = true,
isDismissible = false,
required Widget child,
Color? backgroundColor,
enableDra = false,
useSafeArea = false,
BoxConstraints? constraints,
}) {
return showModalBottomSheet<T>(
context: this,
constraints: constraints,
isScrollControlled: isScrollControlled,
isDismissible: isDismissible,
enableDrag: enableDra,

@ -1,23 +1,23 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/cupertino.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/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/cupertino.dart';
import 'package:intl/intl.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:intl/intl.dart';
extension CapExtension on String {
String get toCamelCase => "${this[0].toUpperCase()}${this.substring(1)}";
String get toCamelCase => "${this[0].toUpperCase()}${substring(1)}";
String get inCaps => '${this[0].toUpperCase()}${this.substring(1)}';
String get inCaps => '${this[0].toUpperCase()}${substring(1)}';
String get allInCaps => this.toUpperCase();
String get allInCaps => toUpperCase();
String get needTranslation => this;
String get capitalizeFirstofEach => this.trim().length > 0 ? this.trim().toLowerCase().split(" ").map((str) => str.inCaps).join(" ") : "";
String get capitalizeFirstofEach => trim().isNotEmpty ? trim().toLowerCase().split(" ").map((str) => str.inCaps).join(" ") : "";
}
extension EmailValidator on String {
@ -28,7 +28,7 @@ extension EmailValidator on String {
maxLines: maxlines,
overflow: textOverflow,
style: TextStyle(
fontSize: 8.fSize,
fontSize: 8.f,
fontStyle: fontStyle ?? FontStyle.normal,
fontWeight: isBold ? FontWeight.bold : FontWeight.normal,
color: color ?? AppColors.blackColor,
@ -36,12 +36,21 @@ extension EmailValidator on String {
),
);
Widget toText10({Color? color, FontWeight? weight, bool isBold = false, bool isUnderLine = false, int? maxlines, FontStyle? fontStyle, TextOverflow? textOverflow, double letterSpacing = 0}) => Text(
Widget toText10(
{Color? color,
FontWeight? weight,
bool isBold = false,
bool isUnderLine = false,
int? maxlines,
FontStyle? fontStyle,
TextOverflow? textOverflow,
double letterSpacing = 0}) =>
Text(
this,
maxLines: maxlines,
overflow: textOverflow,
style: TextStyle(
fontSize: 10.fSize,
fontSize: 10.f,
fontStyle: fontStyle ?? FontStyle.normal,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
color: color ?? AppColors.blackColor,
@ -50,13 +59,21 @@ extension EmailValidator on String {
decorationColor: color ?? AppColors.blackColor),
);
Widget toText11({Color? color, FontWeight? weight, bool isUnderLine = false, bool isCenter = false, bool isBold = false, int maxLine = 0, double letterSpacing = 0}) => Text(
Widget toText11(
{Color? color,
FontWeight? weight,
bool isUnderLine = false,
bool isCenter = false,
bool isBold = false,
int maxLine = 0,
double letterSpacing = 0}) =>
Text(
this,
textAlign: isCenter ? TextAlign.center : null,
maxLines: (maxLine > 0) ? maxLine : null,
softWrap: true,
style: TextStyle(
fontSize: 11.fSize,
fontSize: 11.f,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
color: color ?? AppColors.blackColor,
letterSpacing: letterSpacing,
@ -65,13 +82,20 @@ extension EmailValidator on String {
);
Widget toText12(
{Color? color, bool isUnderLine = false, TextAlign textAlignment = TextAlign.start, bool isBold = false, FontWeight? fontWeight, bool isCenter = false, double? height, int maxLine = 0}) =>
{Color? color,
bool isUnderLine = false,
TextAlign textAlignment = TextAlign.start,
bool isBold = false,
FontWeight? fontWeight,
bool isCenter = false,
double? height,
int maxLine = 0}) =>
Text(
this,
textAlign: isCenter ? TextAlign.center : textAlignment,
maxLines: (maxLine > 0) ? maxLine : null,
style: TextStyle(
fontSize: 12.fSize,
fontSize: 12.f,
fontWeight: fontWeight ?? (isBold ? FontWeight.bold : FontWeight.normal),
color: color ?? AppColors.blackColor,
letterSpacing: 0,
@ -87,7 +111,7 @@ extension EmailValidator on String {
maxLines: (maxLine > 0) ? maxLine : null,
minFontSize: 8,
style: TextStyle(
fontSize: 12.fSize,
fontSize: 12.f,
fontWeight: isBold ? FontWeight.bold : FontWeight.normal,
color: color ?? AppColors.blackColor,
letterSpacing: 0,
@ -123,12 +147,20 @@ extension EmailValidator on String {
),
);
Widget toText13({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, int maxLine = 0, FontWeight? weight, double? letterSpacing = 0}) => Text(
Widget toText13(
{Color? color,
bool isUnderLine = false,
bool isBold = false,
bool isCenter = false,
int maxLine = 0,
FontWeight? weight,
double? letterSpacing = 0}) =>
Text(
this,
textAlign: isCenter ? TextAlign.center : null,
maxLines: (maxLine > 0) ? maxLine : null,
style: TextStyle(
fontSize: 13.fSize,
fontSize: 13.f,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
color: color ?? AppColors.blackColor,
letterSpacing: letterSpacing,
@ -152,20 +184,28 @@ extension EmailValidator on String {
overflow: textOverflow,
style: TextStyle(
color: color ?? AppColors.blackColor,
fontSize: 14.fSize,
fontSize: 14.f,
letterSpacing: letterSpacing,
height: height,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
decoration: isUnderLine ? TextDecoration.underline : null),
);
Widget toText15({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, FontWeight? weight, int? maxlines, double? letterSpacing = -1}) => Text(
Widget toText15(
{Color? color,
bool isUnderLine = false,
bool isBold = false,
bool isCenter = false,
FontWeight? weight,
int? maxlines,
double? letterSpacing = -1}) =>
Text(
this,
textAlign: isCenter ? TextAlign.center : null,
maxLines: maxlines,
style: TextStyle(
color: color ?? AppColors.blackColor,
fontSize: 15.fSize,
fontSize: 15.f,
letterSpacing: letterSpacing,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
decoration: isUnderLine ? TextDecoration.underline : null),
@ -189,7 +229,7 @@ extension EmailValidator on String {
textAlign: isCenter ? TextAlign.center : null,
style: TextStyle(
color: color ?? AppColors.blackColor,
fontSize: 16.fSize,
fontSize: 16.f,
letterSpacing: letterSpacing,
height: height,
overflow: textOverflow,
@ -201,7 +241,7 @@ extension EmailValidator on String {
Widget toText17({Color? color, bool isBold = false, bool isCenter = false}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 17.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 17.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
Widget toText18({Color? color, FontWeight? weight, bool isBold = false, bool isCenter = false, int? maxlines, TextOverflow? textOverflow}) => Text(
@ -209,35 +249,40 @@ extension EmailValidator on String {
textAlign: isCenter ? TextAlign.center : null,
this,
overflow: textOverflow,
style: TextStyle(fontSize: 18.fSize, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, letterSpacing: -0.4),
style: TextStyle(
fontSize: 18.f, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, letterSpacing: -0.4),
);
Widget toText19({Color? color, bool isBold = false}) => Text(
this,
style: TextStyle(fontSize: 19.fSize, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, color: color ?? AppColors.blackColor, letterSpacing: -0.4),
style: TextStyle(fontSize: 19.f, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, color: color ?? AppColors.blackColor, letterSpacing: -0.4),
);
Widget toText20({Color? color, FontWeight? weight, bool isBold = false}) => Text(
this,
style: TextStyle(fontSize: 20.fSize, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, letterSpacing: -0.4),
style: TextStyle(
fontSize: 20.f, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, letterSpacing: -0.4),
);
Widget toText21({Color? color, bool isBold = false, FontWeight? weight, int? maxlines}) => Text(
this,
maxLines: maxlines,
style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 21.fSize, letterSpacing: -1, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal)),
style: TextStyle(
color: color ?? AppColors.blackColor, fontSize: 21.f, letterSpacing: -1, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal)),
);
Widget toText22({Color? color, bool isBold = false, bool isCenter = false}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
style: TextStyle(height: 1, color: color ?? AppColors.blackColor, fontSize: 22.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
style: TextStyle(
height: 1, color: color ?? AppColors.blackColor, fontSize: 22.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
Widget toText24({Color? color, bool isBold = false, bool isCenter = false}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
style: TextStyle(height: 23 / 24, color: color ?? AppColors.blackColor, fontSize: 24.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
style: TextStyle(
height: 23 / 24, color: color ?? AppColors.blackColor, fontSize: 24.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
Widget toText26({Color? color, bool isBold = false, double? height, bool isCenter = false, FontWeight? weight, double? letterSpacing}) => Text(
@ -246,7 +291,7 @@ extension EmailValidator on String {
style: TextStyle(
height: height ?? 23 / 26,
color: color ?? AppColors.blackColor,
fontSize: 26.fSize,
fontSize: 26.f,
letterSpacing: letterSpacing ?? -1,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal)),
);
@ -254,18 +299,25 @@ extension EmailValidator on String {
Widget toText28({Color? color, bool isBold = false, double? height, bool isCenter = false}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
style: TextStyle(height: height ?? 23 / 28, color: color ?? AppColors.blackColor, fontSize: 28.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
style: TextStyle(
height: height ?? 23 / 28,
color: color ?? AppColors.blackColor,
fontSize: 28.f,
letterSpacing: -1,
fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
Widget toText32({Color? color, bool isBold = false, bool isCenter = false}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 32.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
style: TextStyle(
height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 32.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
Widget toText44({Color? color, bool isBold = false}) => Text(
this,
style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 44.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
style: TextStyle(
height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 44.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
Widget toSectionHeading({String upperHeading = "", String lowerHeading = ""}) {
@ -301,12 +353,14 @@ extension EmailValidator on String {
}
bool isValidEmail() {
return RegExp(r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$').hasMatch(this);
return RegExp(
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$')
.hasMatch(this);
}
String toFormattedDate() {
String date = this.split("T")[0];
String time = this.split("T")[1];
String date = split("T")[0];
String time = split("T")[1];
var dates = date.split("-");
return "${dates[2]} ${getMonth(int.parse(dates[1]))} ${dates[0]} ${DateFormat('hh:mm a').format(DateFormat('hh:mm:ss').parse(time))}";
}

@ -1,10 +1,8 @@
import 'dart:async';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/animation.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:get_it/get_it.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
@ -19,16 +17,16 @@ import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/services/cache_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/app_bar_widget.dart';
import 'package:sms_otp_auto_verify/sms_otp_auto_verify.dart';
import 'package:provider/provider.dart';
import 'package:sms_otp_auto_verify/sms_otp_auto_verify.dart';
typedef OnDone = void Function(String text);
class ProvidedPinBoxTextAnimation {
static AnimatedSwitcherTransitionBuilder scalingTransition = (child, animation) {
return ScaleTransition(
child: child,
scale: animation,
child: child,
);
};
@ -65,7 +63,7 @@ class OTPWidget extends StatefulWidget {
final EdgeInsets pinBoxOuterPadding;
const OTPWidget({
Key? key,
super.key,
this.maxLength = 4,
this.controller,
this.pinBoxWidth = 70.0,
@ -87,7 +85,7 @@ class OTPWidget extends StatefulWidget {
this.pinBoxBorderWidth = 2.0,
this.pinBoxRadius = 0,
this.hideDefaultKeyboard = false,
}) : super(key: key);
});
@override
State<StatefulWidget> createState() {
@ -430,7 +428,8 @@ class OTPVerificationScreen extends StatefulWidget {
final Function(String phoneNumber) onResendOTPPressed;
final bool isFormFamilyFile;
const OTPVerificationScreen({super.key, required this.phoneNumber, required this.checkActivationCode, required this.onResendOTPPressed, required this.isFormFamilyFile});
const OTPVerificationScreen(
{super.key, required this.phoneNumber, required this.checkActivationCode, required this.onResendOTPPressed, required this.isFormFamilyFile});
@override
State<OTPVerificationScreen> createState() => _OTPVerificationScreenState();
@ -555,7 +554,8 @@ class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
LocaleKeys.weHaveSendOTP.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
_getMaskedPhoneNumber().toText15(color: AppColors.inputLabelTextColor, isBold: true),
LocaleKeys.via.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
(widget.isFormFamilyFile ? LoginTypeEnum.sms.displayName : authVM.loginTypeEnum.displayName).toText15(color: AppColors.inputLabelTextColor, isBold: true, letterSpacing: -0.4),
(widget.isFormFamilyFile ? LoginTypeEnum.sms.displayName : authVM.loginTypeEnum.displayName)
.toText15(color: AppColors.inputLabelTextColor, isBold: true, letterSpacing: -0.4),
appState.getUserRegistrationPayload.isRegister != null && appState.getUserRegistrationPayload.isRegister == true
? LocaleKeys.forRegistrationVerification.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4)
: LocaleKeys.forLoginVerification.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
@ -568,7 +568,7 @@ class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
maxLength: _otpLength,
controller: _otpController,
pinBoxWidth: 70.h,
pinBoxHeight: 100,
pinBoxHeight: 100.h,
pinBoxRadius: 16,
pinBoxBorderWidth: 0,
pinBoxOuterPadding: EdgeInsets.symmetric(horizontal: 4.h),
@ -578,7 +578,7 @@ class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
autoFocus: true,
onTextChanged: _onOtpChanged,
pinTextStyle: TextStyle(
fontSize: 40.fSize,
fontSize: 40.f,
fontWeight: FontWeight.bold,
color: AppColors.whiteColor,
),

@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/get_tamara_installments_details_response_model.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/appointemnet_filters.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/get_tamara_installments_details_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_appointment_share_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_repo.dart';
@ -29,8 +29,8 @@ class MyAppointmentsViewModel extends ChangeNotifier {
List<AppointmentListingFilters> availableFilters = [];
List<AppointmentListingFilters>? selectedFilter = [];
bool isDateFilterSelected = false;
DateTime? start =null;
DateTime? end =null;
DateTime? start = null;
DateTime? end = null;
List<PatientAppointmentHistoryResponseModel> patientAppointmentsHistoryList = [];
List<PatientAppointmentHistoryResponseModel> filteredAppointmentList = [];
@ -171,40 +171,36 @@ class MyAppointmentsViewModel extends ChangeNotifier {
getFiltersForSelectedAppointmentList(filteredAppointmentList);
}
void getFiltersForSelectedAppointmentList(
List<PatientAppointmentHistoryResponseModel> filteredAppointmentList) {
void getFiltersForSelectedAppointmentList(List<PatientAppointmentHistoryResponseModel> filteredAppointmentList) {
availableFilters.clear();
if (filteredAppointmentList.isEmpty == true) return;
availableFilters.add(AppointmentListingFilters.DATESELECTION);
if (filteredAppointmentList
.any((element) => element.isLiveCareAppointment == true)) {
if (filteredAppointmentList.any((element) => element.isLiveCareAppointment == true)) {
availableFilters.add(AppointmentListingFilters.LIVECARE);
}
if (filteredAppointmentList
.any((element) => element.isLiveCareAppointment == false)) {
if (filteredAppointmentList.any((element) => element.isLiveCareAppointment == false)) {
availableFilters.add(AppointmentListingFilters.WALKIN);
}
if (filteredAppointmentList
.any((element) => AppointmentType.isArrived(element) == true)) {
if (filteredAppointmentList.any((element) => AppointmentType.isArrived(element) == true)) {
availableFilters.add(AppointmentListingFilters.ARRIVED);
}
if (filteredAppointmentList
.any((element) => AppointmentType.isBooked(element) == true)) {
if (filteredAppointmentList.any((element) => AppointmentType.isBooked(element) == true)) {
availableFilters.add(AppointmentListingFilters.BOOKED);
}
if (filteredAppointmentList
.any((element) => AppointmentType.isConfirmed(element) == true)) {
if (filteredAppointmentList.any((element) => AppointmentType.isConfirmed(element) == true)) {
availableFilters.add(AppointmentListingFilters.CONFIRMED);
}
notifyListeners();
}
Future<void> getPatientShareAppointment(int projectID, int clinicID, String appointmentNo, bool isLiveCareAppointment, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.getPatientShareAppointment(projectID: projectID, clinicID: clinicID, appointmentNo: appointmentNo, isLiveCareAppointment: isLiveCareAppointment);
Future<void> getPatientShareAppointment(int projectID, int clinicID, String appointmentNo, bool isLiveCareAppointment,
{Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.getPatientShareAppointment(
projectID: projectID, clinicID: clinicID, appointmentNo: appointmentNo, isLiveCareAppointment: isLiveCareAppointment);
result.fold(
(failure) async {
@ -230,8 +226,13 @@ class MyAppointmentsViewModel extends ChangeNotifier {
}
Future<void> addAdvanceNumberRequest(
{required String advanceNumber, required String paymentReference, required String appointmentNo, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.addAdvanceNumberRequest(advanceNumber: advanceNumber, paymentReference: paymentReference, appointmentNo: appointmentNo);
{required String advanceNumber,
required String paymentReference,
required String appointmentNo,
Function(dynamic)? onSuccess,
Function(String)? onError}) async {
final result =
await myAppointmentsRepo.addAdvanceNumberRequest(advanceNumber: advanceNumber, paymentReference: paymentReference, appointmentNo: appointmentNo);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
@ -249,8 +250,14 @@ class MyAppointmentsViewModel extends ChangeNotifier {
}
Future<void> generateAppointmentQR(
{required int clinicID, required int projectID, required String appointmentNo, required int isFollowUp, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.generateAppointmentQR(clinicID: clinicID, projectID: projectID, appointmentNo: appointmentNo, isFollowUp: isFollowUp);
{required int clinicID,
required int projectID,
required String appointmentNo,
required int isFollowUp,
Function(dynamic)? onSuccess,
Function(String)? onError}) async {
final result =
await myAppointmentsRepo.generateAppointmentQR(clinicID: clinicID, projectID: projectID, appointmentNo: appointmentNo, isFollowUp: isFollowUp);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
@ -267,7 +274,8 @@ class MyAppointmentsViewModel extends ChangeNotifier {
);
}
Future<void> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
Future<void> cancelAppointment(
{required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel);
result.fold(
@ -286,7 +294,8 @@ class MyAppointmentsViewModel extends ChangeNotifier {
);
}
Future<void> confirmAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
Future<void> confirmAppointment(
{required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.confirmAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel);
result.fold(
@ -347,7 +356,8 @@ class MyAppointmentsViewModel extends ChangeNotifier {
required int checkInType,
Function(dynamic)? onSuccess,
Function(String)? onError}) async {
final result = await myAppointmentsRepo.sendCheckInNfcRequest(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel, scannedCode: scannedCode, checkInType: checkInType);
final result = await myAppointmentsRepo.sendCheckInNfcRequest(
patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel, scannedCode: scannedCode, checkInType: checkInType);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
@ -393,8 +403,12 @@ class MyAppointmentsViewModel extends ChangeNotifier {
}
Future<void> insertLiveCareVIDARequest(
{required clientRequestID, required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.insertLiveCareVIDARequest(clientRequestID: clientRequestID, patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel);
{required clientRequestID,
required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel,
Function(dynamic)? onSuccess,
Function(String)? onError}) async {
final result = await myAppointmentsRepo.insertLiveCareVIDARequest(
clientRequestID: clientRequestID, patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
@ -441,7 +455,7 @@ class MyAppointmentsViewModel extends ChangeNotifier {
return;
}
selectedFilter?.add(availableFilter) ;
selectedFilter?.add(availableFilter);
notifyListeners();
}
@ -461,14 +475,14 @@ class MyAppointmentsViewModel extends ChangeNotifier {
if (start == null && end == null) {
isDateFilterSelected = false;
filteredAppointmentList.clear();
sourceList.forEach((element) {
for (var element in sourceList) {
if (isUnderFilter(element)) {
filteredAppointmentList.add(element);
}
});
}
} else {
filteredAppointmentList.clear();
sourceList.forEach((element) {
for (var element in sourceList) {
try {
var dateTime = DateUtil.convertStringToDate(element.appointmentDate).provideDateOnly();
@ -479,14 +493,14 @@ class MyAppointmentsViewModel extends ChangeNotifier {
}
}
} else if (start != null && end != null) {
if ((dateTime.isAfter(start)) && ((dateTime.isBefore(end))||((dateTime.isAtSameMomentAs(end))))) {
if ((dateTime.isAfter(start)) && ((dateTime.isBefore(end)) || ((dateTime.isAtSameMomentAs(end))))) {
if (isUnderFilter(element)) {
filteredAppointmentList.add(element);
}
}
}
} catch (e) {}
});
}
}
notifyListeners();
}
@ -496,27 +510,24 @@ class MyAppointmentsViewModel extends ChangeNotifier {
}
bool isUnderFilter(PatientAppointmentHistoryResponseModel element) {
bool isUnderTheFilter = false;
if (selectedFilter == null || selectedFilter!.isEmpty) return true;
int count = 0;
for (var filter in selectedFilter ?? []) {
switch (filter) {
case AppointmentListingFilters.WALKIN:
if (element.isLiveCareAppointment == false) return true;
case AppointmentListingFilters.BOOKED:
if (AppointmentType.isBooked(element))return true;
if (AppointmentType.isBooked(element)) return true;
case AppointmentListingFilters.CONFIRMED:
if (AppointmentType.isConfirmed(element))return true;
if (AppointmentType.isConfirmed(element)) return true;
case AppointmentListingFilters.ARRIVED:
if (AppointmentType.isArrived(element))return true;
if (AppointmentType.isArrived(element)) return true;
case AppointmentListingFilters.LIVECARE:
if (element.isLiveCareAppointment == true) return true;
case AppointmentListingFilters.DATESELECTION:
}
}
return false;

@ -2,7 +2,7 @@
// ignore_for_file: constant_identifier_names
abstract class LocaleKeys {
abstract class LocaleKeys {
static const english = 'english';
static const arabic = 'arabic';
static const login = 'login';
@ -876,5 +876,4 @@ abstract class LocaleKeys {
static const walkin = 'walkin';
static const laserClinic = 'laserClinic';
static const continueString = 'continueString';
}

@ -174,4 +174,4 @@ class MyApp extends StatelessWidget {
);
}
}
// flutter pub run easy_localization:generate -S assets/langs -f keys -o locale_keys.g.dart
// flutter pub run easy_localization:generate -S assets/langs -f keys -o locale_keys.g.dart

@ -1,7 +1,6 @@
import 'dart:async';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
@ -22,16 +21,15 @@ import 'package:hmg_patient_app_new/presentation/appointments/appointment_paymen
import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_doctor_card.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_detail_page.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescriptions_list_page.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/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
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/shimmer/movies_shimmer_widget.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:maps_launcher/maps_launcher.dart';
import 'package:provider/provider.dart';
@ -170,15 +168,19 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
child: CustomButton(
text: "Get Directions".needTranslation,
onPressed: () {
MapsLauncher.launchCoordinates(double.parse(widget.patientAppointmentHistoryResponseModel.latitude!),
double.parse(widget.patientAppointmentHistoryResponseModel.longitude!), widget.patientAppointmentHistoryResponseModel.projectName);
MapsLauncher.launchCoordinates(
double.parse(widget.patientAppointmentHistoryResponseModel.latitude!),
double.parse(widget.patientAppointmentHistoryResponseModel.longitude!),
widget.patientAppointmentHistoryResponseModel.projectName);
},
backgroundColor: AppColors.textColor.withOpacity(0.8),
borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
borderColor:
AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction)
.withOpacity(0.01),
textColor: AppColors.whiteColor,
fontSize: 14,
fontSize: 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12.h,
borderRadius: 12.r,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
icon: AppAssets.directions_icon,
@ -235,7 +237,8 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
"Lab & Radiology".needTranslation.toText18(isBold: true),
SizedBox(height: 16.h),
GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 13.h, mainAxisSpacing: 13.h, childAspectRatio: 7 / 6),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, crossAxisSpacing: 13.h, mainAxisSpacing: 13.h, childAspectRatio: 7 / 6),
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
children: [
@ -296,13 +299,17 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
children: [
Column(
children: [
SizedBox(width: 150.h, child: prescriptionVM.prescriptionDetailsList[index].itemDescription!.toText12(isBold: true, maxLine: 1)),
SizedBox(
width: 150.h,
child: prescriptionVM.prescriptionDetailsList[index].itemDescription!
.toText12(isBold: true, maxLine: 1)),
SizedBox(
width: 150.h,
child:
"Prescribed By: ${widget.patientAppointmentHistoryResponseModel.doctorTitle} ${widget.patientAppointmentHistoryResponseModel.doctorNameObj}"
.needTranslation
.toText10(weight: FontWeight.w500, color: AppColors.greyTextColor, letterSpacing: -0.4),
.toText10(
weight: FontWeight.w500, color: AppColors.greyTextColor, letterSpacing: -0.4),
),
],
),
@ -415,7 +422,8 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Amount before tax".needTranslation.toText18(isBold: true),
Utils.getPaymentAmountWithSymbol(widget.patientAppointmentHistoryResponseModel.patientShare!.toString().toText16(isBold: true), AppColors.blackColor, 13,
Utils.getPaymentAmountWithSymbol(
widget.patientAppointmentHistoryResponseModel.patientShare!.toString().toText16(isBold: true), AppColors.blackColor, 13,
isSaudiCurrency: true),
],
),
@ -423,8 +431,12 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(child: LocaleKeys.upcomingPaymentNow.tr(context: context).toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor)),
"VAT 15%(${widget.patientAppointmentHistoryResponseModel.patientTaxAmount})".needTranslation.toText14(isBold: true, color: AppColors.greyTextColor, letterSpacing: -2),
Expanded(
child:
LocaleKeys.upcomingPaymentNow.tr(context: context).toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor)),
"VAT 15%(${widget.patientAppointmentHistoryResponseModel.patientTaxAmount})"
.needTranslation
.toText14(isBold: true, color: AppColors.greyTextColor, letterSpacing: -2),
],
),
SizedBox(height: 18.h),
@ -438,7 +450,10 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Utils.getPaymentAmountWithSymbol(widget.patientAppointmentHistoryResponseModel.patientShareWithTax!.toString().toText24(isBold: true), AppColors.blackColor, 17,
Utils.getPaymentAmountWithSymbol(
widget.patientAppointmentHistoryResponseModel.patientShareWithTax!.toString().toText24(isBold: true),
AppColors.blackColor,
17,
isSaudiCurrency: true),
],
),
@ -543,9 +558,15 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
LoaderBottomSheet.hideLoader();
myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true);
myAppointmentsViewModel.getPatientAppointments(true, false);
showCommonBottomSheet(context, child: Utils.getSuccessWidget(loadingText: "Appointment Confirmed Successfully".needTranslation), callBackFunc: (str) {
showCommonBottomSheet(context, child: Utils.getSuccessWidget(loadingText: "Appointment Confirmed Successfully".needTranslation),
callBackFunc: (str) {
Navigator.of(context).pop();
}, title: "", height: ResponsiveExtension.screenHeight * 0.3, isCloseButtonVisible: true, isDismissible: false, isFullScreen: false,
},
title: "",
height: ResponsiveExtension.screenHeight * 0.3,
isCloseButtonVisible: true,
isDismissible: false,
isFullScreen: false,
isSuccessDialog: true);
});
// LoaderBottomSheet.hideLoader();

@ -188,7 +188,6 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
Widget getAppointmentFilters(MyAppointmentsViewModel myAppointmentsVM) {
return SizedBox(
height: 56.h,
child: Row(
children: [
Expanded(

@ -1,5 +1,3 @@
import 'dart:developer';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
@ -94,6 +92,7 @@ class LoginScreenState extends State<LoginScreen> {
),
SizedBox(height: 16.h), // Adjusted to sizer unit (approx 16px)
CustomButton(
height: 50.h,
text: LocaleKeys.login.tr(),
icon: AppAssets.login1,
iconColor: Colors.white,
@ -117,7 +116,7 @@ class LoginScreenState extends State<LoginScreen> {
text: TextSpan(
style: context.dynamicTextStyle(
color: Colors.black,
fontSize: 14.fSize, // Adjusted to sizer unit
fontSize: 14.f, // Adjusted to sizer unit
height: 26 / 16, // This height is a ratio, may need re-evaluation
fontWeight: FontWeight.w500,
),
@ -128,7 +127,7 @@ class LoginScreenState extends State<LoginScreen> {
text: LocaleKeys.registernow.tr(),
style: context.dynamicTextStyle(
color: AppColors.primaryRedColor,
fontSize: 14.fSize, // Adjusted to sizer unit
fontSize: 14.f, // Adjusted to sizer unit
height: 26 / 16, // Ratio
fontWeight: FontWeight.w500),
recognizer: TapGestureRecognizer()
@ -142,6 +141,7 @@ class LoginScreenState extends State<LoginScreen> {
),
).withVerticalPadding(2), // Adjusted to sizer unit
),
SizedBox(height: 20.h), // Adjusted to sizer unit (approx 14px)
],
),
),
@ -160,6 +160,7 @@ class LoginScreenState extends State<LoginScreen> {
isScrollControlled: true,
isDismissible: false,
useSafeArea: true,
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width),
backgroundColor: AppColors.transparent,
child: StatefulBuilder(builder: (BuildContext context, StateSetter setModalState) {
return Padding(

@ -1,7 +1,7 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.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/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -17,11 +17,10 @@ class QuickLogin extends StatefulWidget {
const QuickLogin({super.key, required this.onPressed, this.isDone = false});
@override
_QuickLogin createState() => _QuickLogin();
QuickLoginState createState() => QuickLoginState();
}
class _QuickLogin extends State<QuickLogin> {
class QuickLoginState extends State<QuickLogin> {
@override
Widget build(BuildContext context) {
NavigationService navigationService = getIt.get<NavigationService>();
@ -40,99 +39,95 @@ class _QuickLogin extends State<QuickLogin> {
children: [
widget.isDone
? Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
InkWell(
onTap: () {
navigationService.pop();
},
child: Utils.buildSvgWithAssets(icon: AppAssets.cross_circle)),
],
),
Utils.showLottie(context: context, assetPath: AppAnimations.checkmark, width: 120, height: 120, repeat: true),
LocaleKeys.allSet.tr().toText16(textAlign:
TextAlign.center, weight: FontWeight.w500)
// Text(
// ' TranslationBase.of(context).allSet',
// textAlign: TextAlign.center,
// style: context.dynamicTextStyle(
// fontSize: 16,
// fontWeight: FontWeight.w500,
// color: Colors.black,
// ),
// ),
],
)
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
InkWell(
onTap: () {
navigationService.pop();
},
child: Utils.buildSvgWithAssets(icon: AppAssets.cross_circle)),
],
),
Utils.showLottie(context: context, assetPath: AppAnimations.checkmark, width: 120, height: 120, repeat: true),
LocaleKeys.allSet.tr().toText16(textAlign: TextAlign.center, weight: FontWeight.w500)
// Text(
// ' TranslationBase.of(context).allSet',
// textAlign: TextAlign.center,
// style: context.dynamicTextStyle(
// fontSize: 16,
// fontWeight: FontWeight.w500,
// color: Colors.black,
// ),
// ),
],
)
: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.asset(
AppAssets.lockIcon,
height: 101,
),
const SizedBox(height: 10),
LocaleKeys.enableQuickLogin.tr().toText26(isBold: true),
// Text(
// ' TranslationBase.of(context).enableQuickLogin',
// style: context.dynamicTextStyle(
// fontSize: 26,
// fontWeight: FontWeight.bold,
// color: Colors.black,
// ),
// ),
const SizedBox(height: 5),
LocaleKeys.enableQuickLogin.tr().toText16(color: AppColors.quickLoginColor),
// Description
// Text(
// 'TranslationBase.of(context).enableMsg',
// style: context.dynamicTextStyle(
// fontSize: 16,
// color: Color(0xFF666666),
// height: 1.5,
// ),
//),
const SizedBox(height: 24),
// Buttons
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Expanded(
child: CustomButton(
text:LocaleKeys.enableQuickLogin.tr(),
onPressed: () {
widget.onPressed();
},
backgroundColor: Color(0xffED1C2B),
borderColor: Color(0xffED1C2B),
textColor: Colors.white,
icon:AppAssets.apple_finder,
)),
],
),
SizedBox(
height: 16,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Expanded(
child: CustomButton(
text: LocaleKeys.notNow.tr(),
onPressed: () {
Navigator.pop(context, "true");
},
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Colors.red,
// icon: "assets/images/svg/apple-finder.svg",
)),
],
),
],
)
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.asset(AppAssets.lockIcon, height: 100),
SizedBox(height: 10.h),
LocaleKeys.enableQuickLogin.tr().toText26(isBold: true),
// Text(
// ' TranslationBase.of(context).enableQuickLogin',
// style: context.dynamicTextStyle(
// fontSize: 26,
// fontWeight: FontWeight.bold,
// color: Colors.black,
// ),
// ),
SizedBox(height: 5.h),
LocaleKeys.enableQuickLogin.tr().toText16(color: AppColors.quickLoginColor),
// Description
// Text(
// 'TranslationBase.of(context).enableMsg',
// style: context.dynamicTextStyle(
// fontSize: 16,
// color: Color(0xFF666666),
// height: 1.5,
// ),
//),
const SizedBox(height: 24),
// Buttons
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Expanded(
child: CustomButton(
text: LocaleKeys.enableQuickLogin.tr(),
onPressed: () {
widget.onPressed();
},
backgroundColor: Color(0xffED1C2B),
borderColor: Color(0xffED1C2B),
textColor: Colors.white,
icon: AppAssets.apple_finder,
)),
],
),
SizedBox(
height: 16,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Expanded(
child: CustomButton(
text: LocaleKeys.notNow.tr(),
onPressed: () {
Navigator.pop(context, "true");
},
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Colors.red,
// icon: "assets/images/svg/apple-finder.svg",
)),
],
),
],
)
],
),
);

@ -11,7 +11,6 @@ import 'package:hmg_patient_app_new/core/utils/validation_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/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/authentication/widgets/otp_verification_screen.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/appbar/app_bar_widget.dart';
@ -79,7 +78,8 @@ class _RegisterNew extends State<RegisterNew> {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Utils.showLottie(context: context, assetPath: 'assets/animations/lottie/register.json', width: 200.h, height: 200.h, fit: BoxFit.cover, repeat: true),
Utils.showLottie(
context: context, assetPath: 'assets/animations/lottie/register.json', width: 200.h, height: 200.h, fit: BoxFit.cover, repeat: true),
SizedBox(height: 16.h),
LocaleKeys.prepareToElevate.tr().toText32(isBold: true),
SizedBox(height: 24.h),
@ -149,7 +149,7 @@ class _RegisterNew extends State<RegisterNew> {
borderRadius: BorderRadius.circular(6),
border: Border.all(color: isTermsAccepted ? AppColors.primaryRedBorderColor : AppColors.greyColor, width: 2.h),
),
child: isTermsAccepted ? Icon(Icons.check, size: 16.fSize, color: Colors.white) : null,
child: isTermsAccepted ? Icon(Icons.check, size: 16.f, color: Colors.white) : null,
);
},
),
@ -158,7 +158,7 @@ class _RegisterNew extends State<RegisterNew> {
children: [
Text(
LocaleKeys.iAcceptThe.tr(),
style: context.dynamicTextStyle(fontSize: 14.fSize, fontWeight: FontWeight.w500, color: Color(0xFF2E3039)),
style: context.dynamicTextStyle(fontSize: 14.f, fontWeight: FontWeight.w500, color: Color(0xFF2E3039)),
),
GestureDetector(
onTap: () {
@ -168,7 +168,7 @@ class _RegisterNew extends State<RegisterNew> {
child: Text(
LocaleKeys.termsConditoins.tr(),
style: context.dynamicTextStyle(
fontSize: 14.fSize,
fontSize: 14.f,
fontWeight: FontWeight.w500,
color: AppColors.primaryRedColor,
decoration: TextDecoration.underline,
@ -216,7 +216,7 @@ class _RegisterNew extends State<RegisterNew> {
text: TextSpan(
style: context.dynamicTextStyle(
color: Colors.black,
fontSize: 16.fSize,
fontSize: 16.f,
height: 26 / 16,
fontWeight: FontWeight.w500,
),
@ -227,7 +227,7 @@ class _RegisterNew extends State<RegisterNew> {
text: LocaleKeys.loginNow.tr(),
style: context.dynamicTextStyle(
color: AppColors.primaryRedColor,
fontSize: 16.fSize,
fontSize: 16.f,
height: 26 / 16,
fontWeight: FontWeight.w500,
),

@ -62,7 +62,7 @@ class DoctorsFilters extends StatelessWidget{
style:TextStyle(
fontFamily: 'Poppins',
fontWeight: FontWeight.w600,
fontSize: 27.fSize,
fontSize: 27.f,
color: AppColors.textColor,
letterSpacing: -1
)
@ -72,7 +72,7 @@ class DoctorsFilters extends StatelessWidget{
style:TextStyle(
fontFamily: 'Poppins',
fontWeight: FontWeight.w500,
fontSize: 14.fSize,
fontSize: 14.f,
color: AppColors.errorColor
)
).onPress((){
@ -202,7 +202,7 @@ class DoctorsFilters extends StatelessWidget{
style:TextStyle(
fontFamily: 'Poppins',
fontWeight: FontWeight.w600,
fontSize: 16.fSize,
fontSize: 16.f,
color: AppColors.textColor,
letterSpacing:-1
)

@ -39,7 +39,7 @@ class LaserAppointment extends StatelessWidget {
Text(
LocaleKeys.totalMinutes.tr(),
style: TextStyle(
fontSize: 12.fSize,
fontSize: 12.f,
fontWeight: FontWeight.w600,
color: AppColors.textColor,
letterSpacing: -0.48,
@ -48,7 +48,7 @@ class LaserAppointment extends StatelessWidget {
Text(
"$duration / 90".tr(),
style: TextStyle(
fontSize: 16.fSize,
fontSize: 16.f,
fontWeight: FontWeight.bold,
color: AppColors.textColor,
letterSpacing: -0.64,

@ -111,7 +111,7 @@ class BodyPartsListing extends StatelessWidget {
.read<BookAppointmentsViewModel>()
.getLaserProcedureNameWRTLanguage(parts[index]),
style: TextStyle(
fontSize: 12.fSize,
fontSize: 12.f,
fontWeight: FontWeight.w600,
color: Color(0xff2B353E),
letterSpacing: -0.48,

@ -278,7 +278,7 @@ class _ImmediateLiveCarePendingRequestPageState extends State<ImmediateLiveCareP
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 20.fSize,
fontSize: 20.f,
),
),
),

@ -15,8 +15,8 @@ import 'package:hmg_patient_app_new/features/book_appointments/models/resp_model
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/doctor_profile_page.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/doctor_card.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.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/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
@ -132,14 +132,18 @@ class _SelectDoctorPageState extends State<SelectDoctorPage> {
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
decoration:
RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
child: DoctorCard(
doctorsListResponseModel: bookAppointmentsVM.isLiveCareSchedule ? bookAppointmentsVM.liveCareDoctorsList[index] : bookAppointmentsVM.doctorsList[index],
doctorsListResponseModel: bookAppointmentsVM.isLiveCareSchedule
? bookAppointmentsVM.liveCareDoctorsList[index]
: bookAppointmentsVM.doctorsList[index],
isLoading: false,
bookAppointmentsViewModel: bookAppointmentsViewModel,
).onPress(() async {
bookAppointmentsVM
.setSelectedDoctor(bookAppointmentsVM.isLiveCareSchedule ? bookAppointmentsVM.liveCareDoctorsList[index] : bookAppointmentsVM.doctorsList[index]);
bookAppointmentsVM.setSelectedDoctor(bookAppointmentsVM.isLiveCareSchedule
? bookAppointmentsVM.liveCareDoctorsList[index]
: bookAppointmentsVM.doctorsList[index]);
// bookAppointmentsVM.setSelectedDoctor(DoctorsListResponseModel());
LoaderBottomSheet.showLoader();
await bookAppointmentsVM.getDoctorProfile(onSuccess: (dynamic respData) {

@ -99,11 +99,11 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
headerStyle: CalendarHeaderStyle(
backgroundColor: AppColors.scaffoldBgColor,
textAlign: TextAlign.start,
textStyle: TextStyle(fontSize: 18.fSize, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.primaryRedColor, fontFamily: "Poppins"),
textStyle: TextStyle(fontSize: 18.f, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.primaryRedColor, fontFamily: "Poppins"),
),
viewHeaderStyle: ViewHeaderStyle(
backgroundColor: AppColors.scaffoldBgColor,
dayTextStyle: TextStyle(fontSize: 14.fSize, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.textColor),
dayTextStyle: TextStyle(fontSize: 14.f, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.textColor),
),
view: CalendarView.month,
todayHighlightColor: Colors.transparent,
@ -131,7 +131,7 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
showTrailingAndLeadingDates: false,
appointmentDisplayCount: 1,
monthCellStyle: MonthCellStyle(
textStyle: TextStyle(fontSize: 19.fSize),
textStyle: TextStyle(fontSize: 19.f),
),
),
onTap: (CalendarTapDetails details) {

@ -19,7 +19,6 @@ import 'package:hmg_patient_app_new/features/book_appointments/book_appointments
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_view_model.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_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/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
@ -37,17 +36,12 @@ import 'package:hmg_patient_app_new/presentation/home/widgets/welcome_widget.dar
import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart';
import 'package:hmg_patient_app_new/presentation/profile_settings/profile_settings.dart';
import 'package:hmg_patient_app_new/services/cache_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.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/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:lottie/lottie.dart';
import 'package:provider/provider.dart';
class LandingPage extends StatefulWidget {
@ -139,7 +133,7 @@ class _LandingPageState extends State<LandingPage> {
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Color(0xffED1C2B),
fontSize: 14,
fontSize: 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10.h, 0, 10.h, 0),
@ -149,7 +143,7 @@ class _LandingPageState extends State<LandingPage> {
mainAxisSize: MainAxisSize.min,
spacing: 12.h,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.bell, height: 20, width: 20).onPress(() {
Utils.buildSvgWithAssets(icon: AppAssets.bell, height: 18.h, width: 18.h).onPress(() {
Navigator.of(context).push(
CustomPageRoute(
page: MedicalFilePage(),
@ -157,7 +151,7 @@ class _LandingPageState extends State<LandingPage> {
),
);
}),
Utils.buildSvgWithAssets(icon: AppAssets.search_icon, height: 20, width: 20).onPress(() {
Utils.buildSvgWithAssets(icon: AppAssets.search_icon, height: 18.h, width: 18.h).onPress(() {
Navigator.of(context).push(
CustomPageRoute(
page: MedicalFilePage(),
@ -165,7 +159,7 @@ class _LandingPageState extends State<LandingPage> {
),
);
}),
Utils.buildSvgWithAssets(icon: AppAssets.contact_icon, height: 20, width: 20).onPress(() {
Utils.buildSvgWithAssets(icon: AppAssets.contact_icon, height: 18.h, width: 18.h).onPress(() {
Navigator.of(context).push(
CustomPageRoute(
page: MedicalFilePage(),
@ -216,7 +210,8 @@ class _LandingPageState extends State<LandingPage> {
: myAppointmentsVM.patientAppointmentsHistoryList.isNotEmpty
? myAppointmentsVM.patientAppointmentsHistoryList.length == 1
? Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
decoration:
RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
child: AppointmentCard(
patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList.first,
myAppointmentsViewModel: myAppointmentsViewModel,
@ -245,7 +240,8 @@ class _LandingPageState extends State<LandingPage> {
),
itemBuilder: (BuildContext context, int index) {
return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
decoration: RoundedRectangleBorder()
.toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
child: AppointmentCard(
patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index],
myAppointmentsViewModel: myAppointmentsViewModel,
@ -258,7 +254,8 @@ class _LandingPageState extends State<LandingPage> {
)
: Container(
width: double.infinity,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24, hasShadow: true),
decoration:
RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24, hasShadow: true),
child: Padding(
padding: EdgeInsets.all(12.h),
child: Column(
@ -279,11 +276,9 @@ class _LandingPageState extends State<LandingPage> {
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Color(0xffED1C2B),
fontSize: 14,
fontSize: 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40,
padding: EdgeInsets.fromLTRB(10.h, 0, 10.h, 0),
icon: AppAssets.add_icon,
iconColor: AppColors.primaryRedColor,
),
@ -406,7 +401,7 @@ class _LandingPageState extends State<LandingPage> {
),
);
},
separatorBuilder: (BuildContext cxt, int index) => 0.width,
separatorBuilder: (BuildContext cxt, int index) => 10.width,
),
),
],
@ -513,6 +508,7 @@ class _LandingPageState extends State<LandingPage> {
context,
title: "",
isCloseButtonVisible: false,
child: StatefulBuilder(builder: (context, setState) {
return QuickLogin(
isDone: isDone,

@ -99,18 +99,17 @@ class PatientInsuranceCardUpdateCard extends StatelessWidget {
CustomButton(
icon: AppAssets.insurance_active_icon,
iconColor: AppColors.whiteColor,
iconSize: 20.h,
iconSize: 20.w,
text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}",
onPressed: () {},
backgroundColor: insuranceViewModel.patientInsuranceUpdateResponseModel != null ? AppColors.successColor : AppColors.lightGrayBGColor,
borderColor: AppColors.successColor.withOpacity(0.01),
textColor: AppColors.whiteColor,
fontSize: 16,
fontSize: 16.f,
fontWeight: FontWeight.w500,
borderRadius: 12,
borderRadius: 12.r,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 56.h,
).paddingSymmetrical(24.h, 0.h),
).paddingSymmetrical(24.w, 0.h),
],
);
}

@ -55,7 +55,7 @@ class LabOrderResultItem extends StatelessWidget {
child: Text(
"${tests?.resultValue} ${tests?.uOM}",
style: TextStyle(
fontSize: 24.fSize,
fontSize: 24.f,
fontWeight: FontWeight.w600,
fontFamily: 'Poppins',
color: context.read<LabViewModel>().getColor(
@ -75,7 +75,7 @@ class LabOrderResultItem extends StatelessWidget {
child: Text(
"(Reference range ${tests?.referanceRange})".needTranslation,
style: TextStyle(
fontSize: 12.fSize,
fontSize: 12.f,
fontWeight: FontWeight.w500,
fontFamily: 'Poppins',
color: AppColors.greyTextColor,

@ -94,7 +94,7 @@ class LabResultDetails extends StatelessWidget {
"${recentLabResult.resultValue} ${recentLabResult.uOM}" ??
"",
style: TextStyle(
fontSize: 24.fSize,
fontSize: 24.f,
fontWeight: FontWeight.w600,
fontFamily: 'Poppins',
color: context.read<LabViewModel>().getColor(
@ -115,7 +115,7 @@ class LabResultDetails extends StatelessWidget {
child: Text(
"(Reference range ${recentLabResult.referanceRange})".needTranslation,
style: TextStyle(
fontSize: 12.fSize,
fontSize: 12.f,
fontWeight: FontWeight.w500,
fontFamily: 'Poppins',
color: AppColors.greyTextColor,
@ -252,7 +252,7 @@ class LabResultDetails extends StatelessWidget {
style: TextStyle(
fontWeight: FontWeight.w600,
fontFamily: 'Poppins',
fontSize: 8.fSize,
fontSize: 8.f,
color: AppColors.textColor,
),
);
@ -264,7 +264,7 @@ class LabResultDetails extends StatelessWidget {
child: Text(
label,
style: TextStyle(
fontSize: 8.fSize,
fontSize: 8.f,
fontFamily: 'Poppins',
fontWeight: FontWeight.w600,
color: AppColors.labelTextColor),

@ -24,7 +24,7 @@ class LabHistoryItem extends StatelessWidget{
Text(
dayNameAndDate,
style: TextStyle(
fontSize: 14.fSize,
fontSize: 14.f,
fontWeight: FontWeight.w500,
fontFamily: 'Poppins',
color: AppColors.labelTextColor
@ -33,7 +33,7 @@ class LabHistoryItem extends StatelessWidget{
Text(
result,
style: TextStyle(
fontSize: 18.fSize,
fontSize: 18.f,
fontWeight: FontWeight.w600,
fontFamily: 'Poppins',
color: AppColors.textColor

@ -8,6 +8,7 @@ import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_config.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';
@ -34,19 +35,19 @@ import 'package:hmg_patient_app_new/presentation/insurance/widgets/insurance_upd
import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_orders_page.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart';
import 'package:hmg_patient_app_new/presentation/my_family/my_family.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/presentation/radiology/radiology_orders_page.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/presentation/medical_report/medical_reports_page.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/patient_sickleaves_list_page.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/vaccine_list_page.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/widgets/lab_rad_card.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/widgets/medical_file_card.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/widgets/patient_sick_leave_card.dart';
import 'package:hmg_patient_app_new/presentation/medical_report/medical_reports_page.dart';
import 'package:hmg_patient_app_new/presentation/my_family/my_family.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescriptions_list_page.dart';
import 'package:hmg_patient_app_new/presentation/radiology/radiology_orders_page.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.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/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';
@ -61,7 +62,7 @@ import '../prescriptions/prescription_detail_page.dart';
import 'widgets/medical_file_appointment_card.dart';
class MedicalFilePage extends StatefulWidget {
MedicalFilePage({super.key});
const MedicalFilePage({super.key});
@override
State<MedicalFilePage> createState() => _MedicalFilePageState();
@ -104,15 +105,35 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
title: "Medical File".needTranslation,
trailing: Row(
children: [
Wrap(spacing: -15, children: [
Utils.buildImgWithAssets(icon: AppAssets.babyGirlImg, width: 32.h, height: 32.h, border: 1.5.h, borderRadius: 50.h),
Utils.buildImgWithAssets(icon: AppAssets.femaleImg, width: 32.h, height: 32.h, border: 1.5.h, borderRadius: 50.h),
Utils.buildImgWithAssets(icon: AppAssets.male_img, width: 32.h, height: 32.h, border: 1.5.h, borderRadius: 50.h),
]),
Wrap(
children: [
Utils.buildImgWithAssets(
icon: AppAssets.babyGirlImg,
height: 32.h,
border: 1.5,
fit: BoxFit.contain,
borderRadius: 50.r,
),
Utils.buildImgWithAssets(
icon: AppAssets.femaleImg,
height: 32.h,
border: 1.5,
borderRadius: 50.r,
fit: BoxFit.contain,
),
Utils.buildImgWithAssets(
icon: AppAssets.male_img,
height: 32.h,
border: 1.5,
borderRadius: 50.r,
fit: BoxFit.contain,
),
],
),
SizedBox(width: 4.h),
Utils.buildSvgWithAssets(icon: AppAssets.arrow_down)
Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, height: 22.h, width: 22.w)
],
).onPress(() {
).withHorizontalPadding(24.w).onPress(() {
DialogService dialogService = getIt.get<DialogService>();
dialogService.showFamilyBottomSheetWithoutH(
label: "Who do you want to book for?".needTranslation,
@ -140,21 +161,21 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
isAllowLeadingIcon: true,
padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 8.h),
leadingIcon: AppAssets.student_card,
).paddingSymmetrical(24.h, 0.0),
).paddingSymmetrical(24.w, 0.0),
SizedBox(height: 16.h),
Container(
width: double.infinity,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.r),
child: Padding(
padding: EdgeInsets.all(16.h),
padding: EdgeInsets.all(16.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.asset(appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg, width: 56.h, height: 56.h),
SizedBox(width: 8.h),
Image.asset(appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg, width: 56.w, height: 56.h),
SizedBox(width: 8.w),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -163,12 +184,13 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
SizedBox(height: 4.h),
Wrap(
direction: Axis.horizontal,
spacing: 4.h,
runSpacing: 4.h,
spacing: 4.w,
runSpacing: 6.w,
children: [
AppCustomChipWidget(
icon: AppAssets.file_icon,
labelText: "${LocaleKeys.fileNo.tr(context: context)}: ${appState.getAuthenticatedUser()!.patientId}",
labelPadding: EdgeInsetsDirectional.only(end: 6.w),
onChipTap: () {
navigationService.pushPage(
page: FamilyMedicalScreen(
@ -181,6 +203,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
icon: AppAssets.checkmark_icon,
labelText: LocaleKeys.verified.tr(context: context),
iconColor: AppColors.successColor,
labelPadding: EdgeInsetsDirectional.only(end: 6.w),
),
],
),
@ -203,7 +226,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
icon: AppAssets.blood_icon,
labelText: "Blood: ${appState.getUserBloodGroup}",
iconColor: AppColors.primaryRedColor,
labelPadding: EdgeInsetsDirectional.only(start: -4.h, end: 8.h),
labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 8.w),
),
Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) {
return AppCustomChipWidget(
@ -211,9 +234,10 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
labelText: insuranceVM.isInsuranceExpired ? "Insurance Expired".needTranslation : "Insurance Active".needTranslation,
iconColor: insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor : AppColors.successColor,
textColor: insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor : AppColors.successColor,
iconSize: 12,
backgroundColor: insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor.withOpacity(0.1) : AppColors.successColor.withOpacity(0.1),
labelPadding: EdgeInsetsDirectional.only(start: -4.h, end: 8.h),
iconSize: 12.w,
backgroundColor:
insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor.withOpacity(0.1) : AppColors.successColor.withOpacity(0.1),
labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 8.w),
);
}),
],
@ -221,7 +245,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
],
),
),
).paddingSymmetrical(24.h, 0.0),
).paddingSymmetrical(24.w, 0.0),
SizedBox(height: 16.h),
Consumer<MedicalFileViewModel>(builder: (context, medicalFileVM, child) {
return Column(
@ -238,7 +262,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
onTabChange: (index) {
medicalFileVM.onTabChanged(index);
},
).paddingSymmetrical(24.h, 0.0),
).paddingSymmetrical(24.w, 0.0),
SizedBox(height: 24.h),
getSelectedTabData(medicalFileVM.selectedTabIndex),
],
@ -309,93 +333,89 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
],
),
],
).paddingSymmetrical(24.h, 0.h).onPress(() {
).paddingSymmetrical(24.w, 0.h).onPress(() {
Navigator.of(context).push(
CustomPageRoute(
page: MyAppointmentsPage(),
),
);
}),
SizedBox(height: 16.h),
Consumer<MyAppointmentsViewModel>(builder: (context, myAppointmentsVM, child) {
return SizedBox(
height: myAppointmentsVM.patientAppointmentsHistoryList.isNotEmpty ? 200.h : 175.h,
child: ListView.separated(
scrollDirection: Axis.horizontal,
padding: EdgeInsets.only(top: 16.h, left: 24.h, right: 24.h, bottom: 0.h),
shrinkWrap: true,
itemCount: myAppointmentsVM.isMyAppointmentsLoading ? 5 : (myAppointmentsVM.patientAppointmentsHistoryList.isNotEmpty ? myAppointmentsVM.patientAppointmentsHistoryList.length : 1),
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 500),
child: SlideAnimation(
horizontalOffset: 100.0,
child: FadeInAnimation(
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
child: myAppointmentsVM.isMyAppointmentsLoading
? MedicalFileAppointmentCard(
patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel(),
myAppointmentsViewModel: myAppointmentsVM,
onRescheduleTap: () {},
onAskDoctorTap: () {},
)
: myAppointmentsVM.patientAppointmentsHistoryList.isNotEmpty
? MedicalFileAppointmentCard(
patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index],
myAppointmentsViewModel: myAppointmentsViewModel,
onRescheduleTap: () {
openDoctorScheduleCalendar(myAppointmentsVM.patientAppointmentsHistoryList[index]);
},
onAskDoctorTap: () {},
)
: Container(
width: MediaQuery.of(context).size.width - 48.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24, hasShadow: true),
child: Padding(
padding: EdgeInsets.all(12.h),
child: Column(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.home_calendar_icon, width: 32.h, height: 32.h),
SizedBox(height: 12.h),
"You do not have any appointments. Please book an appointment".needTranslation.toText12(isCenter: true),
SizedBox(height: 12.h),
CustomButton(
text: LocaleKeys.bookAppo.tr(context: context),
onPressed: () {
Navigator.of(context).push(
CustomPageRoute(
page: BookAppointmentPage(),
),
);
},
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Color(0xffED1C2B),
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40,
icon: AppAssets.add_icon,
iconColor: AppColors.primaryRedColor,
),
],
),
),
child: myAppointmentsVM.isMyAppointmentsLoading
? MedicalFileAppointmentCard(
patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel(),
myAppointmentsViewModel: myAppointmentsVM,
onRescheduleTap: () {},
onAskDoctorTap: () {},
)
: myAppointmentsVM.patientAppointmentsHistoryList.isEmpty
? Container(
padding: EdgeInsets.all(12.w),
width: MediaQuery.of(context).size.width,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.r, hasShadow: true),
child: Column(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.home_calendar_icon, width: 32.h, height: 32.h),
SizedBox(height: 12.h),
"You do not have any appointments. Please book an appointment".needTranslation.toText12(isCenter: true),
SizedBox(height: 12.h),
CustomButton(
text: LocaleKeys.bookAppo.tr(context: context),
onPressed: () {
Navigator.of(context).push(
CustomPageRoute(
page: BookAppointmentPage(),
),
);
},
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Color(0xffED1C2B),
fontSize: 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0),
height: 40.h,
icon: AppAssets.add_icon,
iconColor: AppColors.primaryRedColor,
),
],
),
)
: ListView.separated(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: myAppointmentsVM.patientAppointmentsHistoryList.length,
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 500),
child: SlideAnimation(
horizontalOffset: 100.0,
child: FadeInAnimation(
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
child: MedicalFileAppointmentCard(
patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index],
myAppointmentsViewModel: myAppointmentsViewModel,
onRescheduleTap: () {
openDoctorScheduleCalendar(myAppointmentsVM.patientAppointmentsHistoryList[index]);
},
onAskDoctorTap: () {},
)),
),
),
);
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 12.h),
),
),
),
);
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 12.h),
),
);
).paddingSymmetrical(24.w, 0);
}),
SizedBox(height: 24.h),
"Lab & Radiology".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
"Lab & Radiology".needTranslation.toText18(isBold: true).paddingSymmetrical(24.w, 0.h),
SizedBox(height: 16.h),
Row(
children: [
@ -431,27 +451,27 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
}),
),
],
).paddingSymmetrical(24.h, 0.h),
).paddingSymmetrical(24.w, 0.h),
SizedBox(height: 24.h),
"Active Medications & Prescriptions".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
"Active Medications & Prescriptions".needTranslation.toText18(isBold: true).paddingSymmetrical(24.w, 0.h),
SizedBox(height: 16.h),
Consumer<PrescriptionsViewModel>(builder: (context, prescriptionVM, child) {
return prescriptionVM.isPrescriptionsOrdersLoading
? const MoviesShimmerWidget().paddingSymmetrical(24.h, 0.h)
? const MoviesShimmerWidget().paddingSymmetrical(24.w, 0.h)
: prescriptionVM.patientPrescriptionOrders.isNotEmpty
? Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: Colors.white,
borderRadius: 20.h,
borderRadius: 12.r,
),
child: Padding(
padding: EdgeInsets.all(16.h),
padding: EdgeInsets.all(16.w),
child: Column(
children: [
ListView.separated(
itemCount: prescriptionVM.patientPrescriptionOrders.length,
shrinkWrap: true,
padding: const EdgeInsets.only(left: 0, right: 8),
padding: EdgeInsets.only(left: 0, right: 8.w),
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList(
@ -464,11 +484,11 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
children: [
Image.network(
prescriptionVM.patientPrescriptionOrders[index].doctorImageURL!,
width: 40.h,
width: 40.w,
height: 40.h,
fit: BoxFit.cover,
).circle(100),
SizedBox(width: 16.h),
).circle(100.r),
SizedBox(width: 16.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -477,13 +497,16 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
SizedBox(height: 4.h),
Wrap(
direction: Axis.horizontal,
spacing: 3.h,
runSpacing: 4.h,
spacing: 3.w,
runSpacing: 4.w,
children: [
AppCustomChipWidget(labelText: prescriptionVM.patientPrescriptionOrders[index].clinicDescription!),
AppCustomChipWidget(
icon: AppAssets.doctor_calendar_icon,
labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(prescriptionVM.patientPrescriptionOrders[index].appointmentDate), false),
labelText: DateUtil.formatDateToDate(
DateUtil.convertStringToDate(prescriptionVM.patientPrescriptionOrders[index].appointmentDate),
false,
),
),
],
),
@ -494,7 +517,11 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon_small, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor)),
icon: AppAssets.forward_arrow_icon_small,
width: 15.w,
height: 15.h,
fit: BoxFit.contain,
iconColor: AppColors.textColor)),
],
).onPress(() {
prescriptionVM.setPrescriptionsDetailsLoading();
@ -510,9 +537,9 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
),
SizedBox(height: 16.h),
SizedBox(height: 24.h),
const Divider(color: AppColors.dividerColor),
SizedBox(height: 16.h),
SizedBox(height: 24.h),
Row(
children: [
Expanded(
@ -528,16 +555,16 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,
fontSize: 12,
fontSize: 12.f,
fontWeight: FontWeight.w500,
borderRadius: 12.h,
height: 40.h,
borderRadius: 12.r,
height: 56.h,
icon: AppAssets.requests,
iconColor: AppColors.primaryRedColor,
iconSize: 16.h,
iconSize: 16.w,
),
),
SizedBox(width: 10.h),
SizedBox(width: 10.w),
Expanded(
child: CustomButton(
text: "All Medications".needTranslation,
@ -545,10 +572,10 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,
fontSize: 12,
fontSize: 12.f,
fontWeight: FontWeight.w500,
borderRadius: 12.h,
height: 40.h,
height: 56.h,
icon: AppAssets.all_medications_icon,
iconColor: AppColors.primaryRedColor,
iconSize: 16.h,
@ -559,15 +586,21 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
],
),
),
).paddingSymmetrical(24.h, 0.h)
).paddingSymmetrical(24.w, 0.h)
: Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Utils.getNoDataWidget(context, noDataText: "You don't have any prescriptions yet.".needTranslation, isSmallWidget: true, width: 62, height: 62))
.paddingSymmetrical(24.h, 0.h);
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 12.r,
hasShadow: false,
),
child: Utils.getNoDataWidget(
context,
noDataText: "You don't have any prescriptions yet.".needTranslation,
isSmallWidget: true,
width: 62.w,
height: 62.h,
),
).paddingSymmetrical(24.w, 0.h);
}),
SizedBox(height: 24.h),
//My Doctor Section
@ -578,7 +611,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
Row(
children: [
LocaleKeys.viewAll.tr().toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
SizedBox(width: 2.h),
SizedBox(width: 2.w),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
],
).onPress(() {
@ -590,58 +623,63 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
);
}),
],
).paddingSymmetrical(24.h, 0.h),
).paddingSymmetrical(24.w, 0.h),
SizedBox(height: 16.h),
Consumer<MyAppointmentsViewModel>(builder: (context, myAppointmentsVM, child) {
return SizedBox(
height: 120.h,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: myAppointmentsVM.isPatientMyDoctorsLoading
? 5
: myAppointmentsVM.patientMyDoctorsList.isNotEmpty
? myAppointmentsVM.patientMyDoctorsList.length
: 1,
shrinkWrap: true,
padding: EdgeInsets.only(left: 24.h, right: 24.h),
itemBuilder: (context, index) {
return myAppointmentsVM.isPatientMyDoctorsLoading
? SizedBox(
width: 80.h,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.network(
"https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
width: 64.h,
height: 64.h,
fit: BoxFit.cover,
).circle(100).toShimmer2(isShow: true, radius: 50.h),
SizedBox(height: 8.h),
Expanded(
child: ("Dr. John Smith Smith Smith").toString().toText12(fontWeight: FontWeight.w500, isCenter: true, maxLine: 2).toShimmer2(isShow: true),
),
],
),
)
: myAppointmentsVM.patientMyDoctorsList.isNotEmpty
? AnimationConfiguration.staggeredList(
return myAppointmentsVM.isPatientMyDoctorsLoading
? Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.network(
"https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
width: 64.w,
height: 64.h,
fit: BoxFit.cover,
).circle(100).toShimmer2(isShow: true, radius: 50.r),
SizedBox(height: 8.h),
("Dr. John Smith Smith Smith").toString().toText12(fontWeight: FontWeight.w500, isCenter: true, maxLine: 2).toShimmer2(isShow: true),
],
)
: myAppointmentsVM.patientMyDoctorsList.isEmpty
? Container(
width: SizeConfig.screenWidth,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 12.r,
hasShadow: false,
),
child: Utils.getNoDataWidget(
context,
noDataText: "You don't have any completed visits yet".needTranslation,
isSmallWidget: true,
width: 62.w,
height: 62.h,
),
).paddingSymmetrical(24.w, 0.h)
: SizedBox(
height: 200.h,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: myAppointmentsVM.patientMyDoctorsList.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 1000),
child: SlideAnimation(
horizontalOffset: 100.0,
child: FadeInAnimation(
child: SizedBox(
width: 80.h,
// width: 80.w,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.network(
myAppointmentsVM.patientMyDoctorsList[index].doctorImageURL!,
width: 64.h,
width: 64.w,
height: 64.h,
fit: BoxFit.cover,
).circle(100).toShimmer2(isShow: false, radius: 50.h),
).circle(100).toShimmer2(isShow: false, radius: 50.r),
SizedBox(height: 8.h),
Expanded(
child: (myAppointmentsVM.patientMyDoctorsList[index].doctorName)
@ -678,29 +716,21 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
}),
),
),
)
: Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Utils.getNoDataWidget(context, noDataText: "You don't have any completed visits yet.".needTranslation, isSmallWidget: true, width: 62, height: 62),
).paddingSymmetrical(24.h, 0.h);
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 8.h),
),
);
);
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 8.h),
),
);
}),
SizedBox(height: 24.h),
"Others".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
"Others".needTranslation.toText18(isBold: true).paddingSymmetrical(24.w, 0.h),
SizedBox(height: 16.h),
GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 16,
mainAxisSpacing: 16,
mainAxisExtent: 130,
crossAxisSpacing: 16.h,
mainAxisSpacing: 16.w,
mainAxisExtent: 130.h,
),
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
@ -712,15 +742,15 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.eye_result_icon,
isLargeText: true,
iconSize: 36.h,
iconSize: 36.w,
),
MedicalFileCard(
label: "Allergy Info".needTranslation,
label: "Allergy Info".needTranslation,
textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.allergy_info_icon,
isLargeText: true,
iconSize: 36.h,
iconSize: 36.w,
),
MedicalFileCard(
label: "Vaccine Info".needTranslation,
@ -728,7 +758,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.vaccine_info_icon,
isLargeText: true,
iconSize: 36.h,
iconSize: 36.w,
).onPress(() {
Navigator.of(context).push(
CustomPageRoute(
@ -737,7 +767,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
);
}),
],
).paddingSymmetrical(24.h, 0.0),
).paddingSymmetrical(24.w, 0.0),
SizedBox(height: 24.h),
],
);
@ -752,7 +782,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
labOrder: null,
index: index,
isLoading: true,
).paddingSymmetrical(24.h, 0.0)
).paddingSymmetrical(24.w, 0.0)
: insuranceVM.patientInsuranceList.isNotEmpty
? PatientInsuranceCard(
insuranceCardDetailsModel: insuranceVM.patientInsuranceList.first,
@ -763,15 +793,15 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
: Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
borderRadius: 12.r,
hasShadow: false,
),
child: Utils.getNoDataWidget(
context,
noDataText: "You don't have insurance registered with HMG.".needTranslation,
isSmallWidget: true,
width: 62,
height: 62,
width: 62.w,
height: 62.h,
callToActionButton: CustomButton(
icon: AppAssets.update_insurance_card_icon,
iconColor: AppColors.successColor,
@ -781,53 +811,51 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
insuranceViewModel.setIsInsuranceUpdateDetailsLoading(true);
insuranceViewModel.getPatientInsuranceDetailsForUpdate(
appState.getAuthenticatedUser()!.patientId.toString(), appState.getAuthenticatedUser()!.patientIdentificationNo.toString());
showCommonBottomSheetWithoutHeight(context, child: PatientInsuranceCardUpdateCard(), callBackFunc: () {}, title: "", isCloseButtonVisible: false, isFullScreen: false);
showCommonBottomSheetWithoutHeight(context,
child: PatientInsuranceCardUpdateCard(), callBackFunc: () {}, title: "", isCloseButtonVisible: false, isFullScreen: false);
},
backgroundColor: AppColors.bgGreenColor.withOpacity(0.20),
borderColor: AppColors.bgGreenColor.withOpacity(0.0),
textColor: AppColors.bgGreenColor,
fontSize: 14,
fontSize: 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
).paddingOnly(left: 12.h, right: 12.h, bottom: 12.h),
borderRadius: 12.r,
padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0),
height: 56.h,
).paddingOnly(left: 12.w, right: 12.w, bottom: 12.h),
),
).paddingSymmetrical(24.h, 0.h);
).paddingSymmetrical(24.w, 0.h);
}),
SizedBox(height: 10.h),
GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 16,
mainAxisSpacing: 16,
mainAxisExtent: 140,
crossAxisSpacing: 16.h,
mainAxisSpacing: 16.w,
mainAxisExtent: 150.h,
),
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.only(top: 12),
padding: EdgeInsets.only(top: 12.h),
shrinkWrap: true,
children: [
MedicalFileCard(
label: "Update Insurance".needTranslation,
textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.eye_result_icon,
isLargeText: true,
iconSize: 36.h)
.onPress(() {
Navigator.of(context).push(
CustomPageRoute(
page: InsuranceHomePage(),
),
);
label: "Update Insurance".needTranslation,
textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.eye_result_icon,
isLargeText: true,
iconSize: 36.w,
).onPress(() {
Navigator.of(context).push(CustomPageRoute(page: InsuranceHomePage()));
}),
MedicalFileCard(
label: "${LocaleKeys.insurance.tr(context: context)} ${LocaleKeys.approvals.tr(context: context)}",
textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.eye_result_icon,
isLargeText: true,
iconSize: 36.h).onPress(() {
label: "${LocaleKeys.insurance.tr(context: context)} ${LocaleKeys.approvals.tr(context: context)}",
textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.eye_result_icon,
isLargeText: true,
iconSize: 36.w,
).onPress(() {
Navigator.of(context).push(
CustomPageRoute(
page: InsuranceApprovalsPage(),
@ -835,21 +863,21 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
);
}),
MedicalFileCard(
label: "My Invoices List".needTranslation,
label: "My Invoices List".needTranslation,
textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.eye_result_icon,
isLargeText: true,
iconSize: 36.h),
iconSize: 36.w),
MedicalFileCard(
label: "Ancillary Orders List".needTranslation,
textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.eye_result_icon,
isLargeText: true,
iconSize: 36.h),
iconSize: 36.w),
],
).paddingSymmetrical(24.h, 0.0),
).paddingSymmetrical(24.w, 0.0),
SizedBox(height: 16.h),
],
);
@ -862,34 +890,34 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
? PatientSickLeaveCard(
patientSickLeavesResponseModel: PatientSickLeavesResponseModel(),
isLoading: true,
).paddingSymmetrical(24.h, 0.0)
).paddingSymmetrical(24.w, 0.0)
: medicalFileVM.patientSickLeaveList.isNotEmpty
? PatientSickLeaveCard(
patientSickLeavesResponseModel: medicalFileVM.patientSickLeaveList.first,
isLoading: false,
).paddingSymmetrical(24.h, 0.0)
).paddingSymmetrical(24.w, 0.0)
: Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
borderRadius: 12.r,
hasShadow: false,
),
child: Utils.getNoDataWidget(
context,
noDataText: "You don't have any sick leaves yet.".needTranslation,
isSmallWidget: true,
width: 62,
height: 62,
width: 62.w,
height: 62.h,
),
).paddingSymmetrical(24.h, 0.h);
).paddingSymmetrical(24.w, 0.h);
}),
SizedBox(height: 16.h),
GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 16,
mainAxisSpacing: 16,
mainAxisExtent: 140,
crossAxisSpacing: 16.h,
mainAxisSpacing: 16.w,
mainAxisExtent: 140.h,
),
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
@ -934,7 +962,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
);
}),
],
).paddingSymmetrical(24.h, 0.0),
).paddingSymmetrical(24.w, 0.0),
SizedBox(height: 24.h),
],
);
@ -944,9 +972,4 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
return Container();
}
}
getMember() {
// AuthanticationViewModel authanticationViewModel = getIt.get<AuthanticationViewModel>();
// RequestUtils.getAddFamilyRequest(nationalIDorFile: nationalIDorFile, mobileNo: mobileNo, countryCode: countryCode, loginType: loginType);
}
}

@ -9,18 +9,25 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
class LabRadCard extends StatelessWidget {
LabRadCard({super.key, required this.icon, required this.labelText, required this.labOrderTests, required this.isLoading});
const LabRadCard({
super.key,
required this.icon,
required this.labelText,
required this.labOrderTests,
required this.isLoading,
});
String icon;
String labelText;
List<String> labOrderTests = [];
bool isLoading;
final String icon;
final String labelText;
final List<String> labOrderTests;
final bool isLoading;
@override
Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: false),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.r, hasShadow: false),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -28,12 +35,12 @@ class LabRadCard extends StatelessWidget {
children: [
Utils.buildSvgWithAssets(
icon: icon,
width: 40.h,
width: 40.w,
height: 40.h,
fit: BoxFit.contain,
).toShimmer2(isShow: false, radius: 12.h),
SizedBox(width: 8.h),
labelText.toText13(isBold: true).toShimmer2(isShow: false, radius: 6.h, height: 32.h),
).toShimmer2(isShow: false, radius: 12.r),
SizedBox(width: 8.w),
Flexible(child: labelText.toText14(isBold: true).toShimmer2(isShow: false, radius: 6.r, height: 32.h)),
],
),
SizedBox(height: 16.h),
@ -43,13 +50,19 @@ class LabRadCard extends StatelessWidget {
padding: EdgeInsets.zero,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (cxt, index) {
return labOrderTests[index].toText12(isBold: true, maxLine: 1).toShimmer2(isShow: false, radius: 6.h, height: 24.h, width: 120.h).toShimmer2(isShow: isLoading);
itemBuilder: (cxt, index) {
return labOrderTests[index]
.toText12(isBold: true, maxLine: 1)
.toShimmer2(isShow: false, radius: 6.r, height: 24.h, width: 120.w)
.toShimmer2(isShow: isLoading);
},
separatorBuilder: (cxt, index) => SizedBox(height: 8.h),
itemCount: 3,
)
: "You don't have any records yet".needTranslation.toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor, isCenter: true),
: "You don't have any records yet".needTranslation.toText13(
color: AppColors.greyTextColor,
isCenter: true,
),
SizedBox(height: 16.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -57,13 +70,14 @@ class LabRadCard extends StatelessWidget {
SizedBox.shrink(),
Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon_small, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor)
.toShimmer2(isShow: false, radius: 12.h),
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon_small, width: 15.w, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor)
.toShimmer2(isShow: false, radius: 12.r),
),
],
)
],
).paddingAll(16.h),
).paddingAll(16.w),
);
}
}

@ -17,16 +17,20 @@ 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';
class MedicalFileAppointmentCard extends StatelessWidget {
MedicalFileAppointmentCard({super.key, required this.patientAppointmentHistoryResponseModel, required this.myAppointmentsViewModel, required this.onRescheduleTap, required this.onAskDoctorTap});
final PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
final MyAppointmentsViewModel myAppointmentsViewModel;
final Function onRescheduleTap;
final Function onAskDoctorTap;
PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
MyAppointmentsViewModel myAppointmentsViewModel;
late Function onRescheduleTap;
late Function onAskDoctorTap;
const MedicalFileAppointmentCard({
super.key,
required this.patientAppointmentHistoryResponseModel,
required this.myAppointmentsViewModel,
required this.onRescheduleTap,
required this.onAskDoctorTap,
});
@override
Widget build(BuildContext context) {
@ -36,19 +40,21 @@ class MedicalFileAppointmentCard extends StatelessWidget {
children: [
AppCustomChipWidget(
richText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)
.toText12(color: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.textColor : AppColors.primaryRedColor, fontWeight: FontWeight.w500)
.paddingOnly(left: 8.h),
.toText12(
color: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.textColor : AppColors.primaryRedColor,
fontWeight: FontWeight.w500)
.paddingOnly(left: 8.w),
icon: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppAssets.appointment_calendar_icon : AppAssets.alarm_clock_icon,
iconColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.textColor : AppColors.primaryRedColor,
iconSize: 16.h,
iconSize: 16.w,
backgroundColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.greyColor : AppColors.secondaryLightRedColor,
textColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.textColor : AppColors.primaryRedColor,
padding: EdgeInsets.only(top: 12.h, bottom: 12.h, left: 8.h, right: 8.h),
padding: EdgeInsets.only(top: 12.h, bottom: 12.h, left: 8.w, right: 8.w),
).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
width: 200.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true),
width: 200.w,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -56,16 +62,18 @@ class MedicalFileAppointmentCard extends StatelessWidget {
children: [
Image.network(
patientAppointmentHistoryResponseModel.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
width: 25.h,
width: 25.w,
height: 27.h,
fit: BoxFit.fill,
).circle(100).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
SizedBox(width: 8.h),
SizedBox(width: 8.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(patientAppointmentHistoryResponseModel.doctorNameObj ?? "").toText14(isBold: true, maxlines: 1).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
(patientAppointmentHistoryResponseModel.doctorNameObj ?? "")
.toText14(isBold: true, maxlines: 1)
.toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
(patientAppointmentHistoryResponseModel.clinicName ?? "")
.toText12(maxLine: 1, fontWeight: FontWeight.w500, color: AppColors.greyTextColor)
.toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
@ -78,7 +86,7 @@ class MedicalFileAppointmentCard extends StatelessWidget {
Row(
children: [
myAppointmentsViewModel.isMyAppointmentsLoading
? Container().toShimmer2(isShow: true, height: 40.h, width: 100.h, radius: 12.h)
? Container().toShimmer2(isShow: true, height: 40.h, width: 100.w, radius: 12.r)
: Expanded(
flex: 6,
child: AppointmentType.isArrived(patientAppointmentHistoryResponseModel)
@ -95,37 +103,38 @@ class MedicalFileAppointmentCard extends StatelessWidget {
// widget.myAppointmentsViewModel.getPatientAppointments(true, false);
});
},
backgroundColor: AppointmentType.getNextActionButtonColor(patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.15),
backgroundColor:
AppointmentType.getNextActionButtonColor(patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.15),
borderColor: AppointmentType.getNextActionButtonColor(patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
textColor: AppointmentType.getNextActionTextColor(patientAppointmentHistoryResponseModel.nextAction),
fontSize: 14,
fontSize: 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
icon: AppointmentType.getNextActionIcon(patientAppointmentHistoryResponseModel.nextAction),
iconColor: AppointmentType.getNextActionTextColor(patientAppointmentHistoryResponseModel.nextAction),
iconSize: 14.h,
).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
),
SizedBox(width: 8.h),
SizedBox(width: 8.w),
Expanded(
flex: 2,
child: Container(
height: 40.h,
width: 40.h,
width: 40.w,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.textColor,
borderRadius: 10.h,
borderRadius: 10.r,
),
child: Padding(
padding: EdgeInsets.all(10.h),
padding: EdgeInsets.all(10.w),
child: Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(
iconColor: AppColors.whiteColor,
icon: AppAssets.forward_arrow_icon_small,
width: 40.h,
width: 40.w,
height: 40.h,
fit: BoxFit.contain,
),
@ -147,7 +156,7 @@ class MedicalFileAppointmentCard extends StatelessWidget {
],
),
],
).paddingAll(16.h),
).paddingAll(16.w),
),
],
);
@ -163,8 +172,8 @@ class MedicalFileAppointmentCard extends StatelessWidget {
textColor: AppColors.primaryRedColor,
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
icon: AppAssets.ask_doctor_icon,
iconColor: AppColors.primaryRedColor,
@ -178,10 +187,10 @@ class MedicalFileAppointmentCard extends StatelessWidget {
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 14,
fontSize: 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
icon: AppAssets.rebook_appointment_icon,
iconColor: AppColors.blackColor,

@ -9,32 +9,34 @@ class MedicalFileCard extends StatelessWidget {
final Color textColor;
final Color backgroundColor;
final String svgIcon;
final num iconSize;
bool isLargeText;
final double? iconSize;
final bool isLargeText;
MedicalFileCard({
const MedicalFileCard({
super.key,
required this.label,
required this.textColor,
required this.backgroundColor,
this.svgIcon = "",
this.iconSize = 30,
this.isLargeText = false
this.iconSize,
this.isLargeText = false,
});
@override
Widget build(BuildContext context) {
final iconS = iconSize ?? 30.w;
return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: backgroundColor,
borderRadius: 20,
borderRadius: 12.r,
),
child: Padding(
padding: EdgeInsets.all(12.h),
padding: EdgeInsets.all(12.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Utils.buildSvgWithAssets(icon: svgIcon, width: iconSize.h, height: iconSize.h, fit: BoxFit.contain),
Utils.buildSvgWithAssets(icon: svgIcon, width: iconS, height: iconS, fit: BoxFit.contain),
SizedBox(height: 12.h),
isLargeText ? label.toText13(color: textColor, isBold: true, maxLine: 2) : label.toText11(color: textColor, isBold: true, maxLine: 2),
],

@ -73,9 +73,8 @@ class _FamilyMedicalScreenState extends State<FamilyMedicalScreen> {
});
},
icon: AppAssets.add_icon,
height: 56.h,
fontSize: 16,
borderRadius: 12.h,
fontSize: 16.f,
borderRadius: 12.r,
fontWeight: FontWeight.w500))
: SizedBox(),
child: Column(

@ -4,7 +4,6 @@ import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.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/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/presentation/home/navigation_screen.dart';
@ -82,16 +81,18 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
duration: const Duration(milliseconds: 250),
height: 6.h,
width: selectedIndex == 0 ? 18.h : 6.h,
decoration: BoxDecoration(color: selectedIndex == 0 ? AppColors.textColor : AppColors.inputLabelTextColor, borderRadius: BorderRadius.circular(30)),
decoration:
BoxDecoration(color: selectedIndex == 0 ? AppColors.textColor : AppColors.inputLabelTextColor, borderRadius: BorderRadius.circular(30)),
),
AnimatedContainer(
duration: const Duration(milliseconds: 250),
height: 6.h,
width: selectedIndex == 1 ? 18.h : 6.h,
decoration: BoxDecoration(color: selectedIndex == 1 ? AppColors.textColor : AppColors.inputLabelTextColor, borderRadius: BorderRadius.circular(30)),
decoration:
BoxDecoration(color: selectedIndex == 1 ? AppColors.textColor : AppColors.inputLabelTextColor, borderRadius: BorderRadius.circular(30)),
),
],
).paddingOnly(left: 24, right: 24),
).paddingOnly(left: 24.h, right: 24.h),
Row(
children: [
AnimatedSwitcher(
@ -103,23 +104,21 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
onPressed: () => goToHomePage(),
width: 86.h,
height: 56.h,
borderRadius: 12.h,
backgroundColor: Color(0xffFEE9EA),
textColor: AppColors.primaryRedColor,
borderWidth: 0,
borderColor: Colors.transparent,
).paddingOnly(left: 24)
).paddingOnly(left: 24.h)
: const SizedBox.shrink(),
),
const Spacer(),
AnimatedContainer(
duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut,
width: selectedIndex == 0 ? 86 : MediaQuery.of(context).size.width - 48,
margin: EdgeInsets.only(left: 24, right: 24),
width: selectedIndex == 0 ? 86.h : MediaQuery.of(context).size.width - 48.h,
margin: EdgeInsets.only(left: 24.h, right: 24.h),
decoration: BoxDecoration(
color: AppColors.primaryRedColor,
borderRadius: BorderRadius.circular(12),
borderRadius: BorderRadius.circular(12.r),
),
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 250),
@ -130,7 +129,6 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
iconSize: 32.h,
width: 86.h,
height: 56.h,
borderRadius: 12.h,
text: "".needTranslation,
backgroundColor: Colors.transparent,
onPressed: () {
@ -139,9 +137,8 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
: CustomButton(
text: "Get Started".needTranslation,
fontWeight: FontWeight.w500,
fontSize: 16.h,
fontSize: 16.f,
height: 56.h,
borderRadius: 16.h,
textOverflow: TextOverflow.ellipsis,
backgroundColor: Colors.transparent,
onPressed: () => goToHomePage(),
@ -166,18 +163,23 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
alignment: Alignment.bottomCenter,
child: Transform.flip(
flipX: getIt.get<AppState>().isArabic() ? true : false,
child: Lottie.asset(icon, repeat: true, reverse: false, frameRate: FrameRate(60), width: MediaQuery.sizeOf(context).width - 50, height: MediaQuery.sizeOf(context).width - 50)))
child: Lottie.asset(icon,
repeat: true,
reverse: false,
frameRate: FrameRate(60),
width: MediaQuery.sizeOf(context).width - 50,
height: MediaQuery.sizeOf(context).width - 50)))
.expanded,
// 12.height,
Text(
heading,
style: TextStyle(fontSize: 36.h, fontWeight: FontWeight.w600, color: AppColors.textColor, letterSpacing: -0.4, height: 1),
style: TextStyle(fontSize: 36.f, fontWeight: FontWeight.w600, color: AppColors.textColor, letterSpacing: -0.4, height: 1),
),
Text(
body,
style: TextStyle(fontSize: 16.h, fontWeight: FontWeight.w500, color: AppColors.greyTextColor, letterSpacing: 0, height: 26 / 16),
style: TextStyle(fontSize: 16.f, fontWeight: FontWeight.w500, color: AppColors.greyTextColor, letterSpacing: 0, height: 26 / 16),
),
],
).paddingOnly(left: 24, right: 24);
).paddingOnly(left: 24.h, right: 24.h);
}
}

@ -1,16 +1,12 @@
import 'dart:convert';
import 'dart:developer';
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/app_state.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.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';
@ -24,14 +20,13 @@ import 'package:hmg_patient_app_new/generated/locale_keys.g.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/services/dialog_service.dart';
import 'package:hmg_patient_app_new/widgets/appbar/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/appbar/collapsing_list_view.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';
import '../../core/dependencies.dart' show getIt;
@ -66,7 +61,7 @@ class _ProfileSettingsState extends State<ProfileSettings> {
logout: () {},
isClose: true,
child: SingleChildScrollView(
padding: EdgeInsets.only(top: 24, bottom: 24),
padding: EdgeInsets.only(top: 24.h, bottom: 24.h),
physics: NeverScrollableScrollPhysics(),
child: Consumer2<ProfileSettingsViewModel, MedicalFileViewModel>(
builder: (context, profileVm, medicalVm, child) {
@ -77,14 +72,14 @@ class _ProfileSettingsState extends State<ProfileSettings> {
itemCount: medicalVm.patientFamilyFiles.length,
layout: SwiperLayout.STACK,
loop: true,
itemWidth: MediaQuery.of(context).size.width - 42,
itemWidth: SizeUtils.width - 42.w,
indicatorLayout: PageIndicatorLayout.COLOR,
axisDirection: AxisDirection.right,
controller: _controller,
itemHeight: 200.h,
pagination: const SwiperPagination(
itemHeight: 220.h,
pagination: SwiperPagination(
alignment: Alignment.bottomCenter,
margin: EdgeInsets.only(top: 210 + 8 + 24),
margin: EdgeInsets.only(top: (210.h + 8.h + 24.h)),
builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor),
),
itemBuilder: (BuildContext context, int index) {
@ -102,20 +97,20 @@ class _ProfileSettingsState extends State<ProfileSettings> {
onFamilySwitchPress: (FamilyFileResponseModelLists profile) {
medicalVm.switchFamilyFiles(responseID: profile.responseId, patientID: profile.patientId, phoneNumber: profile.mobileNumber);
},
).paddingOnly(right: 16);
).paddingOnly(right: 16.w);
},
),
GridView(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 9, mainAxisSpacing: 9),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 9.w, mainAxisSpacing: 9.h),
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(24),
padding: EdgeInsets.only(left: 24.w, right: 24.w, bottom: 24.w, top: 10.w),
shrinkWrap: true,
children: [
Container(
padding: EdgeInsets.all(16),
padding: EdgeInsets.all(16.w),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
borderRadius: 20.r,
hasShadow: true,
),
child: Column(
@ -123,10 +118,10 @@ class _ProfileSettingsState extends State<ProfileSettings> {
spacing: 4.h,
children: [
Row(
spacing: 8.h,
spacing: 8.w,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.wallet, width: 40.h, height: 40.h),
Utils.buildSvgWithAssets(icon: AppAssets.wallet, width: 40.w, height: 40.h),
"Habib Wallet".needTranslation.toText14(weight: FontWeight.w600, maxlines: 2).expanded,
Utils.buildSvgWithAssets(icon: AppAssets.arrow_forward),
],
@ -134,7 +129,7 @@ class _ProfileSettingsState extends State<ProfileSettings> {
Spacer(),
Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) {
return Utils.getPaymentAmountWithSymbol2(habibWalletVM.habibWalletAmount, isExpanded: false)
.toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 24.h);
.toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.r, width: 80.w, height: 24.h);
}),
CustomButton(
height: 40.h,
@ -143,12 +138,12 @@ class _ProfileSettingsState extends State<ProfileSettings> {
iconColor: AppColors.infoColor,
textColor: AppColors.infoColor,
text: "Recharge".needTranslation,
borderWidth: 0.h,
borderWidth: 0.w,
fontWeight: FontWeight.w500,
borderColor: Colors.transparent,
backgroundColor: Color(0xff45A2F8).withValues(alpha: 0.08),
padding: EdgeInsets.all(8.h),
fontSize: 14,
padding: EdgeInsets.all(8.w),
fontSize: 14.f,
onPressed: () {
Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage()));
},
@ -160,15 +155,19 @@ class _ProfileSettingsState extends State<ProfileSettings> {
)
],
),
"Quick Actions".needTranslation.toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24, right: 24),
"Quick Actions"
.needTranslation
.toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1)
.paddingOnly(left: 24.w, right: 24.w),
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),
margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h, bottom: 24.h),
padding: EdgeInsets.only(top: 4.h, bottom: 4.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true),
child: Column(
children: [
actionItem(AppAssets.language_change, "Language".needTranslation, () {
showCommonBottomSheetWithoutHeight(context, title: "Application Language".needTranslation, child: AppLanguageChange(), callBackFunc: () {}, isFullScreen: false);
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, () {}),
@ -179,11 +178,14 @@ class _ProfileSettingsState extends State<ProfileSettings> {
],
),
),
"Personal Information".needTranslation.toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24, right: 24),
"Personal Information"
.needTranslation
.toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1)
.paddingOnly(left: 24.w, right: 24.w),
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),
margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h, bottom: 24.h),
padding: EdgeInsets.only(top: 4.h, bottom: 4.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true),
child: Column(
children: [
actionItem(AppAssets.email_transparent, "Update Email Address".needTranslation, () {}),
@ -196,11 +198,14 @@ class _ProfileSettingsState extends State<ProfileSettings> {
],
),
),
"Help & Support".needTranslation.toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24, right: 24),
"Help & Support"
.needTranslation
.toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1)
.paddingOnly(left: 24.w, right: 24.w),
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),
margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h),
padding: EdgeInsets.only(top: 4.h, bottom: 4.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true),
child: Column(
children: [
actionItem(AppAssets.call_fill, "Contact Us".needTranslation, () {}, trailingLabel: "9200666666"),
@ -215,7 +220,7 @@ class _ProfileSettingsState extends State<ProfileSettings> {
],
),
),
CustomButton(icon: AppAssets.minus, text: "Deactivate account".needTranslation, onPressed: () {}).paddingAll(24),
CustomButton(icon: AppAssets.minus, text: "Deactivate account".needTranslation, onPressed: () {}).paddingAll(24.w),
],
);
},
@ -226,18 +231,19 @@ class _ProfileSettingsState extends State<ProfileSettings> {
Widget actionItem(String icon, String label, VoidCallback onPress, {String trailingLabel = "", bool? switchValue, bool isExternalLink = false}) {
return SizedBox(
height: 56,
height: 56.h,
child: Row(
spacing: 8.h,
spacing: 8.w,
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),
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,
activeThumbColor: AppColors.successColor,
activeTrackColor: AppColors.successColor.withValues(alpha: .15),
)
: Transform.scale(
@ -245,18 +251,22 @@ class _ProfileSettingsState extends State<ProfileSettings> {
child: Utils.buildSvgWithAssets(icon: isExternalLink ? AppAssets.externalLink : AppAssets.arrow_forward),
)
],
).paddingOnly(left: 16, right: 16).onPress(onPress),
).paddingOnly(left: 16.w, right: 16.w).onPress(onPress),
);
}
}
class FamilyCardWidget extends StatelessWidget {
late AppState appState;
final Function() onAddFamilyMemberPress;
final Function(FamilyFileResponseModelLists member) onFamilySwitchPress;
final FamilyFileResponseModelLists profile;
FamilyCardWidget({super.key, required this.onAddFamilyMemberPress, required this.profile, required this.onFamilySwitchPress(FamilyFileResponseModelLists member)});
const FamilyCardWidget({
super.key,
required this.onAddFamilyMemberPress,
required this.profile,
required this.onFamilySwitchPress(FamilyFileResponseModelLists member),
});
@override
Widget build(BuildContext context) {
@ -265,7 +275,7 @@ class FamilyCardWidget extends StatelessWidget {
final isParentUser = appState.getAuthenticatedUser()?.isParentUser ?? false;
final canSwitch = isParentUser || (!isParentUser && profile.responseId == appState.getSuperUserID);
return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.r, hasShadow: true),
child: Column(
children: [
Column(
@ -274,37 +284,38 @@ class FamilyCardWidget extends StatelessWidget {
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8.h,
//
children: [
Image.asset(profile.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg, width: 56.h, height: 56.h),
Image.asset(profile.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg, width: 56.w, height: 56.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 0.h,
mainAxisSize: MainAxisSize.min,
children: [
"${profile.patientName}".toText18(isBold: true, weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1),
AppCustomChipWidget(
icon: AppAssets.file_icon,
labelText: "${LocaleKeys.fileNo.tr(context: context)}: ${profile.responseId}",
iconSize: 12,
iconSize: 12.w,
),
],
).expanded,
Icon(Icons.qr_code, size: 56)
Icon(Icons.qr_code, size: 56.h)
],
),
SizedBox(height: 4.h),
SizedBox(
child: Wrap(
alignment: WrapAlignment.start,
spacing: 4.h,
spacing: 4.w,
runSpacing: 4.h,
children: [
AppCustomChipWidget(labelText: "${profile.age} Years Old".needTranslation),
AppCustomChipWidget(
labelText: "${profile.age} Years Old".needTranslation,
),
isActive && appState.getAuthenticatedUser()!.bloodGroup != null
? AppCustomChipWidget(
icon: AppAssets.blood_icon,
labelPadding: EdgeInsetsDirectional.only(start: -6.h, end: 8.h),
labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 8.w),
labelText: "Blood: ${appState.getAuthenticatedUser()!.bloodGroup ?? ""}",
iconColor: AppColors.primaryRedColor)
: SizedBox(),
@ -351,9 +362,9 @@ class FamilyCardWidget extends StatelessWidget {
icon: icon,
labelText: labelText,
iconColor: iconColor,
iconSize: 12,
iconSize: 12.w,
backgroundColor: backgroundColor,
labelPadding: EdgeInsetsDirectional.only(start: -6.h, end: 8.h),
labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 8.w),
// padding: EdgeInsets.zero,
).toShimmer2(isShow: isLoading);
},
@ -362,7 +373,7 @@ class FamilyCardWidget extends StatelessWidget {
),
),
],
).paddingOnly(top: 16.h, right: 16.h, left: 16.h, bottom: 12.h).expanded,
).paddingOnly(top: 16.h, right: 16.w, left: 16.w, bottom: 12.h),
1.divider,
_buildActionButton(appState),
],
@ -393,9 +404,9 @@ class FamilyCardWidget extends StatelessWidget {
borderColor: canSwitch ? AppColors.secondaryLightRedColor : AppColors.primaryRedColor,
textColor: canSwitch ? AppColors.primaryRedColor : AppColors.whiteColor,
iconColor: canSwitch ? AppColors.primaryRedColor : AppColors.whiteColor,
height: 40.h,
fontSize: 14,
).paddingOnly(top: 12, right: 16, left: 16, bottom: 16);
height: 56.h,
fontSize: 14.f,
).paddingOnly(top: 12.h, right: 16.w, left: 16.w, bottom: 16.h);
}
Widget _buildNonParentUserButton(int? superUserId) {
@ -410,8 +421,8 @@ class FamilyCardWidget extends StatelessWidget {
iconColor: canSwitchBack ? AppColors.whiteColor : AppColors.greyTextColor,
onPressed: canSwitchBack ? () => onFamilySwitchPress(profile) : () {},
height: 40.h,
fontSize: 14,
).paddingOnly(top: 12, right: 16, left: 16, bottom: 16);
fontSize: 14.f,
).paddingOnly(top: 12.h, right: 16.w, left: 16.w, bottom: 16.h);
}
// //TODO: Add family file switch logic here

@ -22,9 +22,13 @@ abstract class DialogService {
Future<void> showCommonBottomSheetWithoutH({String? label, required String message, required Function() onOkPressed, Function()? onCancelPressed});
Future<void> showFamilyBottomSheetWithoutH(
{String? label, required String message, required Function(FamilyFileResponseModelLists response) onSwitchPress, required List<FamilyFileResponseModelLists> profiles});
{String? label,
required String message,
required Function(FamilyFileResponseModelLists response) onSwitchPress,
required List<FamilyFileResponseModelLists> profiles});
Future<void> showFamilyBottomSheetWithoutHWithChild({String? label, required String message, Widget? child, required Function() onOkPressed, Function()? onCancelPressed});
Future<void> showFamilyBottomSheetWithoutHWithChild(
{String? label, required String message, Widget? child, required Function() onOkPressed, Function()? onCancelPressed});
Future<void> showPhoneNumberPickerSheet({String? label, String? message, required Function() onSMSPress, required Function() onWhatsappPress});
@ -49,6 +53,7 @@ class DialogServiceImp implements DialogService {
await showModalBottomSheet(
context: context,
isScrollControlled: false,
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
@ -80,6 +85,7 @@ class DialogServiceImp implements DialogService {
await showModalBottomSheet(
context: context,
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width),
isScrollControlled: false,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
@ -101,13 +107,20 @@ class DialogServiceImp implements DialogService {
Future<void> showCommonBottomSheetWithoutH({String? label, required String message, required Function() onOkPressed, Function()? onCancelPressed}) async {
final context = navigationService.navigatorKey.currentContext;
if (context == null) return;
showCommonBottomSheetWithoutHeight(context,
title: label ?? "", child: exceptionBottomSheetWidget(context: context, message: message, onOkPressed: onOkPressed, onCancelPressed: onCancelPressed), callBackFunc: () {});
showCommonBottomSheetWithoutHeight(
context,
title: label ?? "",
child: exceptionBottomSheetWidget(context: context, message: message, onOkPressed: onOkPressed, onCancelPressed: onCancelPressed),
callBackFunc: () {},
);
}
@override
Future<void> showFamilyBottomSheetWithoutH(
{String? label, required String message, required Function(FamilyFileResponseModelLists response) onSwitchPress, required List<FamilyFileResponseModelLists> profiles}) async {
{String? label,
required String message,
required Function(FamilyFileResponseModelLists response) onSwitchPress,
required List<FamilyFileResponseModelLists> profiles}) async {
final context = navigationService.navigatorKey.currentContext;
if (context == null) return;
showCommonBottomSheetWithoutHeight(context,
@ -124,7 +137,8 @@ class DialogServiceImp implements DialogService {
}
@override
Future<void> showFamilyBottomSheetWithoutHWithChild({String? label, required String message, Widget? child, required Function() onOkPressed, Function()? onCancelPressed}) async {
Future<void> showFamilyBottomSheetWithoutHWithChild(
{String? label, required String message, Widget? child, required Function() onOkPressed, Function()? onCancelPressed}) async {
final context = navigationService.navigatorKey.currentContext;
if (context == null) return;
showCommonBottomSheetWithoutHeight(
@ -140,7 +154,9 @@ class DialogServiceImp implements DialogService {
final context = navigationService.navigatorKey.currentContext;
if (context == null) return;
showCommonBottomSheetWithoutHeight(context,
title: label ?? "", child: showPhoneNumberPickerWidget(context: context, message: message, onSMSPress: onSMSPress, onWhatsappPress: onWhatsappPress), callBackFunc: () {});
title: label ?? "",
child: showPhoneNumberPickerWidget(context: context, message: message, onSMSPress: onSMSPress, onWhatsappPress: onWhatsappPress),
callBackFunc: () {});
}
@override
@ -178,7 +194,7 @@ Widget exceptionBottomSheetWidget({required BuildContext context, required Strin
iconColor: AppColors.primaryRedColor,
),
),
SizedBox(width: 5.h),
SizedBox(width: 10.h),
Expanded(
child: CustomButton(
text: LocaleKeys.confirm.tr(),

@ -3,7 +3,6 @@ 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/widget_extensions.dart';
import 'package:hmg_patient_app_new/widgets/language_switcher.dart';
import '../../generated/locale_keys.g.dart';
@ -11,14 +10,14 @@ import '../../generated/locale_keys.g.dart';
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
final VoidCallback onBackPressed;
final ValueChanged<String> onLanguageChanged;
bool hideLogoAndLang;
final bool hideLogoAndLang;
CustomAppBar({
Key? key,
const CustomAppBar({
super.key,
required this.onBackPressed,
required this.onLanguageChanged,
this.hideLogoAndLang = false,
}) : super(key: key);
});
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
@ -42,9 +41,17 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
child: context.locale.languageCode == "ar"
? RotatedBox(
quarterTurns: 90,
child: Utils.buildSvgWithAssets(icon: AppAssets.arrow_back, width: 32.h, height: 32.h),
child: Utils.buildSvgWithAssets(
icon: AppAssets.arrow_back,
width: 32.h,
height: 32.h,
),
)
: Utils.buildSvgWithAssets(icon: AppAssets.arrow_back, width: 32.h, height: 32.h),
: Utils.buildSvgWithAssets(
icon: AppAssets.arrow_back,
width: 32.h,
height: 32.h,
),
),
),
),
@ -53,6 +60,7 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
if (!hideLogoAndLang)
Utils.buildSvgWithAssets(
icon: AppAssets.habiblogo,
height: 24.h,
),
if (!hideLogoAndLang)

@ -1,6 +1,5 @@
import 'dart:ui';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
@ -9,9 +8,8 @@ import 'package:hmg_patient_app_new/core/app_state.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/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';
import '../../core/dependencies.dart';
class CollapsingListView extends StatelessWidget {
@ -28,8 +26,21 @@ class CollapsingListView extends StatelessWidget {
bool isClose;
bool isLeading;
CollapsingListView(
{required this.title, this.child, this.search, this.isClose = false, this.bottomChild, this.report, this.logout, this.history, this.instructions, this.requests, this.isLeading = true, this.trailing});
CollapsingListView({
super.key,
required this.title,
this.child,
this.search,
this.isClose = false,
this.bottomChild,
this.report,
this.logout,
this.history,
this.instructions,
this.requests,
this.isLeading = true,
this.trailing,
});
@override
Widget build(BuildContext context) {
@ -43,7 +54,7 @@ class CollapsingListView extends StatelessWidget {
SliverAppBar(
automaticallyImplyLeading: false,
pinned: true,
expandedHeight: 100,
expandedHeight: 100.h,
stretch: true,
systemOverlayStyle: SystemUiOverlayStyle(statusBarBrightness: Brightness.light),
surfaceTintColor: Colors.transparent,
@ -61,7 +72,7 @@ class CollapsingListView extends StatelessWidget {
: SizedBox.shrink(),
flexibleSpace: LayoutBuilder(
builder: (context, constraints) {
final double maxHeight = 100;
final double maxHeight = 100.h;
final double minHeight = kToolbarHeight;
double t = (constraints.maxHeight - minHeight) / (maxHeight - minHeight);
t = t - 1;
@ -81,7 +92,8 @@ class CollapsingListView extends StatelessWidget {
t,
)!,
child: Padding(
padding: EdgeInsets.only(left: appState.isArabic() ? 0 : leftPadding, right: appState.isArabic() ? leftPadding : 0, bottom: bottomPadding),
padding: EdgeInsets.only(
left: appState.isArabic() ? 0 : leftPadding, right: appState.isArabic() ? leftPadding : 0, bottom: bottomPadding),
child: Row(
spacing: 4.h,
children: [
@ -89,7 +101,7 @@ class CollapsingListView extends StatelessWidget {
title,
maxLines: 1,
style: TextStyle(
fontSize: (27 - (5 * (2 - t))).fSize,
fontSize: (27 - (5 * (2 - t))).f,
fontWeight: FontWeight.lerp(
FontWeight.w300,
FontWeight.w600,
@ -100,9 +112,12 @@ class CollapsingListView extends StatelessWidget {
).expanded,
if (logout != null) actionButton(context, t, title: "Logout".needTranslation, icon: AppAssets.logout).onPress(logout!),
if (report != null) actionButton(context, t, title: "Report".needTranslation, icon: AppAssets.report_icon).onPress(report!),
if (history != null) actionButton(context, t, title: "History".needTranslation, icon: AppAssets.insurance_history_icon).onPress(history!),
if (instructions != null) actionButton(context, t, title: "Instructions".needTranslation, icon: AppAssets.requests).onPress(instructions!),
if (requests != null) actionButton(context, t, title: "Requests".needTranslation, icon: AppAssets.insurance_history_icon).onPress(requests!),
if (history != null)
actionButton(context, t, title: "History".needTranslation, icon: AppAssets.insurance_history_icon).onPress(history!),
if (instructions != null)
actionButton(context, t, title: "Instructions".needTranslation, icon: AppAssets.requests).onPress(instructions!),
if (requests != null)
actionButton(context, t, title: "Requests".needTranslation, icon: AppAssets.insurance_history_icon).onPress(requests!),
if (search != null) Utils.buildSvgWithAssets(icon: AppAssets.search_icon).onPress(search!).paddingOnly(right: 24),
if (trailing != null) trailing!,
],
@ -131,12 +146,12 @@ class CollapsingListView extends StatelessWidget {
return AnimatedSize(
duration: Duration(milliseconds: 150),
child: Container(
height: 40,
padding: EdgeInsets.all(8),
margin: EdgeInsets.only(right: 24),
height: 40.h,
padding: EdgeInsets.all(8.w),
margin: EdgeInsets.only(right: 24.w),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.secondaryLightRedColor,
borderRadius: 12,
borderRadius: 12.r,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
@ -151,7 +166,7 @@ class CollapsingListView extends StatelessWidget {
style: context.dynamicTextStyle(
color: AppColors.primaryRedColor,
letterSpacing: -0.4,
fontSize: (14 - (2 * (1 - t))).fSize,
fontSize: (14 - (2 * (1 - t))).f,
fontWeight: FontWeight.lerp(
FontWeight.w300,
FontWeight.w500,

@ -18,7 +18,15 @@ class ExceptionBottomSheet extends StatelessWidget {
final Function() onOkPressed;
final Function()? onCancelPressed;
const ExceptionBottomSheet({super.key, this.title, required this.message, this.showOKButton = true, this.showCancel = false, required this.onOkPressed, this.onCancelPressed});
const ExceptionBottomSheet({
super.key,
this.title,
required this.message,
this.showOKButton = true,
this.showCancel = false,
required this.onOkPressed,
this.onCancelPressed,
});
@override
Widget build(BuildContext context) {
@ -50,7 +58,10 @@ class ExceptionBottomSheet extends StatelessWidget {
onTap: () {
Navigator.of(context).pop();
},
child: Utils.buildSvgWithAssets(icon: AppAssets.cross_circle),
child: Utils.buildSvgWithAssets(
icon: AppAssets.cross_circle,
height: 24.h,
),
)
],
),
@ -63,6 +74,7 @@ class ExceptionBottomSheet extends StatelessWidget {
children: [
Expanded(
child: CustomButton(
height: 56.h,
text: LocaleKeys.cancel.tr(),
onPressed: onCancelPressed != null
? onCancelPressed!
@ -79,6 +91,7 @@ class ExceptionBottomSheet extends StatelessWidget {
SizedBox(width: 5.h),
Expanded(
child: CustomButton(
height: 56.h,
text: showCancel ? LocaleKeys.confirm.tr() : LocaleKeys.ok.tr(),
onPressed: onOkPressed,
backgroundColor: AppColors.bgGreenColor,
@ -93,6 +106,7 @@ class ExceptionBottomSheet extends StatelessWidget {
Padding(
padding: EdgeInsets.only(bottom: 10.h),
child: CustomButton(
height: 56.h,
text: LocaleKeys.ok.tr(),
onPressed: onOkPressed,
backgroundColor: AppColors.primaryRedColor,

@ -13,20 +13,20 @@ import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
class GenericBottomSheet extends StatefulWidget {
String? countryCode;
String? initialPhoneNumber;
final String? countryCode;
final String? initialPhoneNumber;
final List<Widget> buttons;
TextEditingController? textController;
final TextEditingController? textController;
final bool isForEmail;
Function(CountryEnum)? onCountryChange;
final Function(CountryEnum)? onCountryChange;
final bool isEnableCountryDropdown;
final bool isFromSavedLogin;
Function(String?)? onChange;
final Function(String?)? onChange;
final bool autoFocus;
// FocusNode myFocusNode;
GenericBottomSheet({
const GenericBottomSheet({
super.key,
this.countryCode = "",
this.initialPhoneNumber = "",
@ -42,10 +42,10 @@ class GenericBottomSheet extends StatefulWidget {
});
@override
_GenericBottomSheetState createState() => _GenericBottomSheetState();
GenericBottomSheetState createState() => GenericBottomSheetState();
}
class _GenericBottomSheetState extends State<GenericBottomSheet> {
class GenericBottomSheetState extends State<GenericBottomSheet> {
late FocusNode _textFieldFocusNode;
@override
@ -85,8 +85,11 @@ class _GenericBottomSheetState extends State<GenericBottomSheet> {
textDirection: Directionality.of(context),
child: Container(
padding: EdgeInsets.all(24.h),
decoration: RoundedRectangleBorder()
.toSmoothCornerDecoration(color: AppColors.bgScaffoldColor, borderRadius: 16, customBorder: BorderRadius.only(topLeft: Radius.circular(16), topRight: Radius.circular(16))),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.bgScaffoldColor,
borderRadius: 16.r,
customBorder: BorderRadius.only(topLeft: Radius.circular(16.r), topRight: Radius.circular(16.r)),
),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
@ -112,7 +115,10 @@ class _GenericBottomSheetState extends State<GenericBottomSheet> {
},
child: Padding(
padding: EdgeInsets.only(top: 10.h),
child: Utils.buildSvgWithAssets(icon: AppAssets.cross_circle),
child: Utils.buildSvgWithAssets(
icon: AppAssets.cross_circle,
height: 24.h,
),
),
),
],
@ -152,7 +158,7 @@ class _GenericBottomSheetState extends State<GenericBottomSheet> {
prefix: widget.isForEmail ? null : widget.countryCode,
isBorderAllowed: false,
isAllowLeadingIcon: true,
fontSize: 13.h,
fontSize: 13,
isCountryDropDown: widget.isEnableCountryDropdown,
leadingIcon: widget.isForEmail ? AppAssets.email : AppAssets.smart_phone,
)

@ -6,71 +6,73 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
class CustomButton extends StatelessWidget {
final String text;
String? icon;
final String? icon;
final VoidCallback onPressed;
final Color backgroundColor;
final Color borderColor;
final Color textColor;
final double borderRadius;
final double? borderRadius;
final double borderWidth;
final EdgeInsetsGeometry padding;
final double fontSize;
final double? fontSize;
final String? fontFamily;
final FontWeight fontWeight;
final bool isDisabled;
final Color? iconColor;
final double height;
final double? height;
final double? width;
final double iconSize;
final double? iconSize;
final TextOverflow? textOverflow;
final BorderSide? borderSide;
CustomButton(
{Key? key,
required this.text,
required this.onPressed,
this.backgroundColor = const Color(0xFFED1C2B),
this.borderColor = const Color(0xFFED1C2B),
this.textColor = Colors.white,
this.borderRadius = 12,
this.borderWidth = 2,
this.padding = const EdgeInsets.fromLTRB(8, 10, 8, 10),
this.fontSize = 16,
this.fontFamily,
this.fontWeight = FontWeight.w500,
this.isDisabled = false,
this.icon,
this.iconColor = Colors.white,
this.height = 56,
this.width,
this.iconSize = 24,
this.textOverflow,
this.borderSide})
: super(key: key);
const CustomButton({
super.key,
required this.text,
required this.onPressed,
this.backgroundColor = const Color(0xFFED1C2B),
this.borderColor = const Color(0xFFED1C2B),
this.textColor = Colors.white,
this.borderRadius,
this.borderWidth = 2,
this.padding = const EdgeInsets.fromLTRB(8, 10, 8, 10),
this.fontSize,
this.fontFamily,
this.fontWeight = FontWeight.w500,
this.isDisabled = false,
this.icon,
this.iconColor = Colors.white,
this.height,
this.width,
this.iconSize,
this.textOverflow,
this.borderSide,
});
@override
Widget build(BuildContext context) {
final radius = borderRadius ?? (12.r);
final iconS = iconSize ?? (24.h);
final fontS = fontSize ?? (16.f);
return GestureDetector(
onTap: isDisabled ? null : onPressed,
child: Container(
height: height,
height: height ?? (50.h),
width: width,
padding: padding,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: isDisabled ? backgroundColor.withOpacity(.5) : backgroundColor,
borderRadius: borderRadius,
customBorder: BorderRadius.circular(borderRadius),
side: borderSide ?? BorderSide(width: borderWidth.h, color: isDisabled ? Colors.transparent : borderColor)),
borderRadius: radius,
customBorder: BorderRadius.circular(radius),
side: borderSide ?? BorderSide(width: borderWidth.h, color: isDisabled ? borderColor.withValues(alpha: 0.5) : borderColor)),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (icon != null)
Padding(
padding: text.isNotEmpty ?EdgeInsets.only(right: 8.h, left: 8.h): EdgeInsets.zero,
child: Utils.buildSvgWithAssets(icon: icon!, iconColor: iconColor, isDisabled: isDisabled, width: iconSize, height: iconSize),
padding: text.isNotEmpty ? EdgeInsets.only(right: 8.h, left: 8.h) : EdgeInsets.zero,
child: Utils.buildSvgWithAssets(icon: icon!, iconColor: iconColor, isDisabled: isDisabled, width: iconS, height: iconS),
),
Visibility(
visible: text.isNotEmpty,
child: Padding(
@ -79,7 +81,7 @@ class CustomButton extends StatelessWidget {
text,
overflow: textOverflow,
style: context.dynamicTextStyle(
fontSize: fontSize.fSize,
fontSize: fontS,
color: isDisabled ? textColor.withOpacity(0.5) : textColor,
letterSpacing: 0,
fontWeight: fontWeight,

@ -81,7 +81,7 @@ class DefaultButton extends StatelessWidget {
text,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: fontSize ?? 18.fSize,
fontSize: fontSize ?? 18.f,
fontWeight: FontWeight.w600,
color: textColor,
letterSpacing: -0.48,
@ -94,7 +94,7 @@ class DefaultButton extends StatelessWidget {
text,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: fontSize ?? 18.fSize,
fontSize: fontSize ?? 18.f,
fontWeight: FontWeight.w600,
color: textColor,
letterSpacing: -0.48,

@ -1,26 +1,24 @@
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';
import 'package:smooth_corner/smooth_corner.dart';
class AppCustomChipWidget extends StatelessWidget {
AppCustomChipWidget({
const AppCustomChipWidget({
super.key,
this.labelText,
this.textColor = AppColors.textColor,
this.backgroundColor = AppColors.greyColor,
this.iconSize = 12,
this.iconSize,
this.icon = "",
this.iconColor = AppColors.textColor,
this.richText,
this.iconHasColor = true,
this.shape,
this.deleteIcon,
this.deleteIconSize = const Size(12, 12),
this.deleteIconSize,
this.deleteIconColor = AppColors.textColor,
this.deleteIconHasColor = false,
this.padding = EdgeInsets.zero,
@ -32,7 +30,7 @@ class AppCustomChipWidget extends StatelessWidget {
final Widget? richText;
final Color? textColor;
final Color? backgroundColor;
final num iconSize;
final double? iconSize;
final String icon;
final String? deleteIcon;
final Size? deleteIconSize;
@ -47,56 +45,66 @@ class AppCustomChipWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final iconS = iconSize ?? 12.w;
return GestureDetector(
onTap: onChipTap,
child: ChipTheme(
data: ChipThemeData(
padding: EdgeInsets.all(0.0),
shape: SmoothRectangleBorder(
side: BorderSide(
width: 10.0,
color: Colors.transparent, // Crucially, set color to transparent
style: BorderStyle.none,
child: SizedBox(
child: ChipTheme(
data: ChipThemeData(
padding: EdgeInsets.zero,
shape: SmoothRectangleBorder(
side: BorderSide(
width: 10.w,
color: Colors.transparent, // Crucially, set color to transparent
style: BorderStyle.none,
),
borderRadius: BorderRadius.circular(8.r), // Apply a border radius of 16.0
),
borderRadius: BorderRadius.circular(8.h), // Apply a border radius of 16.0
),
child: icon.isNotEmpty
? Chip(
avatar: icon.isNotEmpty
? Utils.buildSvgWithAssets(icon: icon, width: iconS, height: iconS, iconColor: iconHasColor ? iconColor : null, fit: BoxFit.contain)
: SizedBox.shrink(),
label: richText ?? labelText!.toText10(weight: FontWeight.w500, letterSpacing: 0, color: textColor),
padding: padding,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
labelPadding: labelPadding ?? EdgeInsetsDirectional.only(start: 2.w, end: deleteIcon?.isNotEmpty == true ? 2.w : 8.w),
backgroundColor: backgroundColor,
shape: shape ??
SmoothRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
smoothness: 10,
side: BorderSide(color: AppColors.transparent, width: 1.5),
),
deleteIcon: deleteIcon?.isNotEmpty == true
? Utils.buildSvgWithAssets(
icon: deleteIcon!,
width: iconS,
height: iconS,
iconColor: deleteIconHasColor ? deleteIconColor : null,
)
: null,
onDeleted: deleteIcon?.isNotEmpty == true ? () {} : null,
)
: Chip(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
label: richText ?? labelText!.toText10(weight: FontWeight.w500, letterSpacing: 0, color: textColor),
padding: EdgeInsets.zero,
backgroundColor: backgroundColor,
shape: shape ??
SmoothRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
smoothness: 10,
side: BorderSide(color: AppColors.transparent, width: 1.5),
),
labelPadding: labelPadding ?? EdgeInsetsDirectional.only(start: 2.w, end: deleteIcon?.isNotEmpty == true ? 2.w : 8.w),
deleteIcon: deleteIcon?.isNotEmpty == true
? Utils.buildSvgWithAssets(icon: deleteIcon!, width: iconS, height: iconS, iconColor: deleteIconHasColor ? deleteIconColor : null)
: null,
onDeleted: deleteIcon?.isNotEmpty == true ? () {} : null,
),
),
child: icon.isNotEmpty
? Chip(
avatar: icon.isNotEmpty ? Utils.buildSvgWithAssets(icon: icon, width: iconSize.h, height: iconSize.h, iconColor: iconHasColor ? iconColor : null, fit: BoxFit.contain) : SizedBox.shrink(),
label: richText ?? labelText!.toText10(weight: FontWeight.w500, letterSpacing: 0, color: textColor),
padding: padding,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
labelPadding: labelPadding ?? EdgeInsetsDirectional.only(start: 0.h, end: deleteIcon?.isNotEmpty == true ? 2.h : 8.h),
backgroundColor: backgroundColor,
shape: shape ??
SmoothRectangleBorder(
borderRadius: BorderRadius.circular(8 ?? 0),
smoothness: 10,
side: BorderSide(color: AppColors.transparent, width: 1.5),
),
deleteIcon: deleteIcon?.isNotEmpty == true
? Utils.buildSvgWithAssets(icon: deleteIcon!, width: deleteIconSize!.width!.h, height: deleteIconSize!.height.h, iconColor: deleteIconHasColor ? deleteIconColor : null)
: null,
onDeleted: deleteIcon?.isNotEmpty == true ? () {} : null,
)
: Chip(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
label: richText ?? labelText!.toText10(weight: FontWeight.w500, letterSpacing: 0, color: textColor),
padding: EdgeInsets.all(0.0),
backgroundColor: backgroundColor,
shape: shape ??
SmoothRectangleBorder(
borderRadius: BorderRadius.circular(8 ?? 0),
smoothness: 10,
side: BorderSide(color: AppColors.transparent, width: 1.5),
),
labelPadding: EdgeInsetsDirectional.only(start: 8.h, end: deleteIcon?.isNotEmpty == true ? -2.h : 8.h),
deleteIcon: deleteIcon?.isNotEmpty == true
? Utils.buildSvgWithAssets(icon: deleteIcon!, width: deleteIconSize!.width.h, height: deleteIconSize!.height.h, iconColor: deleteIconHasColor ? deleteIconColor : null)
: null,
onDeleted: deleteIcon?.isNotEmpty == true ? () {} : null,
),
),
);
}

@ -122,6 +122,9 @@ void showCommonBottomSheetWithoutHeight(
duration: Duration(milliseconds: 500),
reverseDuration: Duration(milliseconds: 300),
),
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width, // Full width
),
context: context,
isScrollControlled: true,
showDragHandle: false,

@ -1,5 +1,4 @@
import 'package:flutter/material.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';
@ -23,23 +22,21 @@ class CustomTabBar extends StatefulWidget {
final Color inActiveBackgroundColor;
final Function(int)? onTabChange;
CustomTabBar(
{Key? key,
required this.tabs,
this.activeTextColor = const Color(0xff2E3039),
this.inActiveTextColor = const Color(0xff898A8D),
this.activeBackgroundColor = const Color(0x142E3039),
this.inActiveBackgroundColor = Colors.white,
this.onTabChange})
: super(key: key);
const CustomTabBar({
super.key,
required this.tabs,
this.activeTextColor = const Color(0xff2E3039),
this.inActiveTextColor = const Color(0xff898A8D),
this.activeBackgroundColor = const Color(0x142E3039),
this.inActiveBackgroundColor = Colors.white,
this.onTabChange,
});
@override
_CustomTabBarState createState() {
return _CustomTabBarState();
}
CustomTabBarState createState() => CustomTabBarState();
}
class _CustomTabBarState extends State<CustomTabBar> {
class CustomTabBarState extends State<CustomTabBar> {
int selectedIndex = 0;
@override
@ -65,44 +62,53 @@ class _CustomTabBarState extends State<CustomTabBar> {
scrollDirection: Axis.horizontal,
padding: EdgeInsets.zero,
physics: const BouncingScrollPhysics(),
itemBuilder: (cxt, index) => myTab(widget.tabs[index], index),
itemBuilder: (cxt, index) => myTab(widget.tabs[index], index).expanded,
separatorBuilder: (cxt, index) => 4.width,
itemCount: widget.tabs.length,
);
} else {
parentWidget = Row(
spacing: 4,
mainAxisAlignment: MainAxisAlignment.center,
spacing: 4.w,
children: [for (int i = 0; i < widget.tabs.length; i++) myTab(widget.tabs[i], i).expanded],
);
}
return Container(
height: 62.h,
padding: EdgeInsets.all(4),
padding: EdgeInsets.all(4.w),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 11,
borderRadius: 12.r,
),
child: parentWidget);
child: Center(child: parentWidget));
}
Widget myTab(CustomTabBarModel tabBar, int currentIndex) {
bool isSelected = selectedIndex == currentIndex;
return Container(
height: 54.h,
padding: EdgeInsets.only(top: 4, bottom: 4, left: 16, right: 16),
padding: EdgeInsets.only(top: 4.h, bottom: 4.h, left: 16.w, right: 16.w),
alignment: Alignment.center,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: isSelected ? widget.activeBackgroundColor : widget.inActiveBackgroundColor,
borderRadius: 12,
borderRadius: 12.r,
),
child: Row(
mainAxisSize: MainAxisSize.min,
spacing: 4,
spacing: 4.w,
children: [
if (tabBar.image != null) Utils.buildSvgWithAssets(icon: tabBar.image!, height: 18, width: 18, iconColor: isSelected ? widget.activeTextColor : widget.inActiveTextColor),
tabBar.title
.toText13(weight: isSelected ? FontWeight.w600 : FontWeight.w500, color: isSelected ? widget.activeTextColor : widget.inActiveTextColor, letterSpacing: isSelected ? -0.3 : -0.1),
if (tabBar.image != null)
Utils.buildSvgWithAssets(
icon: tabBar.image!,
height: 18.h,
width: 18.w,
iconColor: isSelected ? widget.activeTextColor : widget.inActiveTextColor,
),
tabBar.title.toText13(
weight: isSelected ? FontWeight.w600 : FontWeight.w500,
color: isSelected ? widget.activeTextColor : widget.inActiveTextColor,
letterSpacing: isSelected ? -0.3 : -0.1),
],
)).onPress(() {
setState(() {

@ -99,7 +99,7 @@ class _DateRangeSelectorState extends State<DateRangeSelector> {
backgroundColor: Colors.white,
textAlign: TextAlign.start,
textStyle: TextStyle(
fontSize: 18.fSize,
fontSize: 18.f,
fontWeight: FontWeight.w600,
letterSpacing: -0.46,
color: AppColors.primaryRedColor,
@ -110,7 +110,7 @@ class _DateRangeSelectorState extends State<DateRangeSelector> {
viewHeaderStyle: DateRangePickerViewHeaderStyle(
backgroundColor: Colors.white,
textStyle: TextStyle(
fontSize: 14.fSize,
fontSize: 14.f,
fontWeight: FontWeight.w600,
letterSpacing: -0.46,
color: AppColors.textColor,
@ -129,7 +129,7 @@ class _DateRangeSelectorState extends State<DateRangeSelector> {
todayHighlightColor: Colors.transparent,
monthCellStyle: DateRangePickerMonthCellStyle(
textStyle: TextStyle(
fontSize: 12.fSize,
fontSize: 12.f,
color: AppColors.textColor,
),
todayTextStyle: TextStyle(

@ -16,27 +16,27 @@ class CustomCountryDropdown extends StatefulWidget {
final Function(String)? onPhoneNumberChanged;
final bool isFromBottomSheet;
final bool isEnableTextField;
Widget? textField;
final Widget? textField;
CustomCountryDropdown({
Key? key,
const CustomCountryDropdown({
super.key,
required this.countryList,
this.onCountryChange,
this.onPhoneNumberChanged,
this.isFromBottomSheet = false,
this.isEnableTextField = false,
this.textField,
}) : super(key: key);
});
@override
_CustomCountryDropdownState createState() => _CustomCountryDropdownState();
CustomCountryDropdownState createState() => CustomCountryDropdownState();
}
class _CustomCountryDropdownState extends State<CustomCountryDropdown> {
class CustomCountryDropdownState extends State<CustomCountryDropdown> {
CountryEnum? selectedCountry;
late OverlayEntry _overlayEntry;
bool _isDropdownOpen = false;
FocusNode textFocusNode = new FocusNode();
FocusNode textFocusNode = FocusNode();
@override
void initState() {
@ -61,87 +61,78 @@ class _CustomCountryDropdownState extends State<CustomCountryDropdown> {
@override
Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
return Container(
height: 40.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 10.h),
child: Row(
children: [
return Row(
children: [
GestureDetector(
onTap: () {
if (_isDropdownOpen) {
_closeDropdown();
} else {
_openDropdown();
}
},
child: Row(
children: [
Utils.buildSvgWithAssets(icon: selectedCountry != null ? selectedCountry!.iconPath : AppAssets.ksa, width: 40.h, height: 40.h),
SizedBox(width: 8.h),
Utils.buildSvgWithAssets(icon: _isDropdownOpen ? AppAssets.dropdow_icon : AppAssets.dropdow_icon),
],
),
),
SizedBox(width: 4.h),
if (widget.isFromBottomSheet)
GestureDetector(
onTap: () {
if (_isDropdownOpen) {
_closeDropdown();
} else {
_openDropdown();
if (widget.isEnableTextField && textFocusNode.canRequestFocus) {
FocusScope.of(context).requestFocus(textFocusNode);
}
},
child: Row(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Utils.buildSvgWithAssets(icon: selectedCountry != null ? selectedCountry!.iconPath : AppAssets.ksa, width: 40.h, height: 40.h),
SizedBox(width: 8.h),
Utils.buildSvgWithAssets(icon: _isDropdownOpen ? AppAssets.dropdow_icon : AppAssets.dropdow_icon),
],
),
),
SizedBox(width: 4.h),
if (widget.isFromBottomSheet)
GestureDetector(
onTap: () {
if (widget.isEnableTextField && textFocusNode.canRequestFocus) {
FocusScope.of(context).requestFocus(textFocusNode);
}
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
children: [
Text(
LocaleKeys.phoneNumber.tr(),
style: TextStyle(fontSize: 12.fSize, height: 1.2.h, fontWeight: FontWeight.w500, letterSpacing: -1),
),
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
selectedCountry!.countryCode,
style: TextStyle(fontSize: 12.fSize, fontWeight: FontWeight.w600, letterSpacing: -0.4, height: 1.5),
),
SizedBox(width: 4.h),
if (widget.isEnableTextField)
SizedBox(
height: 20.h,
width: 200.h,
child: Align(
alignment: Alignment.centerLeft,
child: TextField(
focusNode: textFocusNode,
style: TextStyle(fontSize: 12.fSize, fontWeight: FontWeight.w600, letterSpacing: -0.4, height: 1.5),
decoration: InputDecoration(hintText: "", isDense: true, border: InputBorder.none, contentPadding: EdgeInsets.zero),
keyboardType: TextInputType.phone,
onChanged: widget.onPhoneNumberChanged,
),
Text(
LocaleKeys.phoneNumber.tr(),
style: TextStyle(fontSize: 12.f, height: 1.5, fontWeight: FontWeight.w500, letterSpacing: -1),
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
selectedCountry!.countryCode,
style: TextStyle(fontSize: 12.f, fontWeight: FontWeight.w600, letterSpacing: -0.4, height: 1.5),
),
SizedBox(width: 4.h),
if (widget.isEnableTextField)
SizedBox(
height: 20.h,
width: 200.h,
child: Align(
alignment: Alignment.centerLeft,
child: TextField(
focusNode: textFocusNode,
style: TextStyle(fontSize: 12.f, fontWeight: FontWeight.w600, letterSpacing: -0.4, height: 1.5),
decoration: InputDecoration(hintText: "", isDense: true, border: InputBorder.none, contentPadding: EdgeInsets.zero),
keyboardType: TextInputType.phone,
onChanged: widget.onPhoneNumberChanged,
),
),
],
)
],
),
),
if (!widget.isFromBottomSheet)
Text(
selectedCountry != null
? appState.getLanguageCode() == "ar"
? selectedCountry!.nameArabic
: selectedCountry!.displayName
: LocaleKeys.selectCountry.tr(),
style: TextStyle(fontSize: 14.fSize, height: 21 / 14, fontWeight: FontWeight.w500, letterSpacing: -0.2),
),
],
)
],
),
],
),
),
if (!widget.isFromBottomSheet)
Text(
selectedCountry != null
? appState.getLanguageCode() == "ar"
? selectedCountry!.nameArabic
: selectedCountry!.displayName
: LocaleKeys.selectCountry.tr(),
style: TextStyle(fontSize: 14.f, height: 21 / 14, fontWeight: FontWeight.w500, letterSpacing: -0.2),
),
],
);
}
@ -202,7 +193,7 @@ class _CustomCountryDropdownState extends State<CustomCountryDropdown> {
if (!widget.isFromBottomSheet) SizedBox(width: 12.h),
if (!widget.isFromBottomSheet)
Text(appState.getLanguageCode() == "ar" ? country.nameArabic : country.displayName,
style: TextStyle(fontSize: 14.fSize, height: 21 / 14, fontWeight: FontWeight.w500, letterSpacing: -0.2)),
style: TextStyle(fontSize: 14.f, height: 21 / 14, fontWeight: FontWeight.w500, letterSpacing: -0.2)),
],
),
)),

@ -81,7 +81,7 @@ class DropdownWidget extends StatelessWidget {
return Text(
labelText,
style: TextStyle(
fontSize: 12.fSize,
fontSize: 12.f,
fontWeight: FontWeight.w500,
color: labelColor ?? Color(0xff898A8D),
letterSpacing: -0.2,
@ -111,7 +111,7 @@ class DropdownWidget extends StatelessWidget {
child: Text(
e,
style: TextStyle(
fontSize: 14.fSize,
fontSize: 14.f,
height: 21 / 14,
fontWeight: FontWeight.w500,
letterSpacing: -0.2,
@ -142,7 +142,7 @@ class DropdownWidget extends StatelessWidget {
textAlign: TextAlign.left,
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 14.fSize,
fontSize: 14.f,
height: 21 / 14,
fontWeight: FontWeight.w500,
color: (selectedValue != null && selectedValue!.isNotEmpty) ? const Color(0xff2E3039) : const Color(0xffB0B0B0),

@ -145,7 +145,7 @@ class CustomGraph extends StatelessWidget {
'${dataPoint.actualValue} ${dataPoint.unitOfMeasurement??""} - ${dataPoint.displayTime}',
TextStyle(
color: Colors.black,
fontSize: 12.fSize,
fontSize: 12.f,
fontWeight: FontWeight.w500),
);
}

@ -9,7 +9,6 @@ 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';
import 'package:hmg_patient_app_new/widgets/dropdown/country_dropdown_widget.dart';
import 'package:keyboard_actions/keyboard_actions.dart';
import '../core/dependencies.dart';
@ -36,9 +35,9 @@ class TextInputWidget extends StatelessWidget {
final bool isCountryDropDown;
final bool hasError;
final String? errorMessage;
Function(CountryEnum)? onCountryChange;
final Function(CountryEnum)? onCountryChange;
final SelectionTypeEnum? selectionType;
final num? fontSize;
final double? fontSize;
final bool? isWalletAmountInput;
final Widget? suffix;
final Color? labelColor;
@ -70,7 +69,7 @@ class TextInputWidget extends StatelessWidget {
this.errorMessage,
this.onCountryChange,
this.selectionType,
this.fontSize = 14,
this.fontSize,
this.isWalletAmountInput = false,
this.suffix,
this.labelColor,
@ -118,7 +117,7 @@ class TextInputWidget extends StatelessWidget {
alignment: Alignment.center,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: Colors.white,
borderRadius: isAllowRadius ? 20.h : null,
borderRadius: isAllowRadius ? (12.r) : null,
side: isBorderAllowed ? BorderSide(color: hasError ? errorColor : const Color(0xffefefef), width: 1) : null,
),
child: Row(
@ -151,7 +150,7 @@ class TextInputWidget extends StatelessWidget {
],
),
),
(suffix!= null )?suffix!:SizedBox.shrink()
(suffix != null) ? suffix! : SizedBox.shrink()
],
),
),
@ -167,7 +166,7 @@ class TextInputWidget extends StatelessWidget {
errorMessage!,
style: TextStyle(
color: errorColor,
fontSize: 12.fSize,
fontSize: 12.f,
),
),
),
@ -182,7 +181,7 @@ class TextInputWidget extends StatelessWidget {
margin: EdgeInsets.only(right: 10.h),
padding: EdgeInsets.all(8.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
borderRadius: 12.h,
borderRadius: 12.r,
color: AppColors.greyColor,
),
child: Utils.buildSvgWithAssets(icon: leadingIcon!));
@ -195,7 +194,7 @@ class TextInputWidget extends StatelessWidget {
width: 40.h,
margin: EdgeInsets.zero,
padding: EdgeInsets.all(8.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 10.h, color: AppColors.whiteColor),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 12.r, color: AppColors.whiteColor),
child: GestureDetector(
onTap: () async {
bool isGregorian = true;
@ -206,7 +205,9 @@ class TextInputWidget extends StatelessWidget {
initialDate: DateTime.now(),
fontFamily: appState.getLanguageCode() == "ar" ? "GESSTwo" : "Poppins",
okWidget: Padding(padding: EdgeInsets.only(right: 8.h), child: Utils.buildSvgWithAssets(icon: AppAssets.confirm, width: 24.h, height: 24.h)),
cancelWidget: Padding(padding: EdgeInsets.only(right: 8.h), child: Utils.buildSvgWithAssets(icon: AppAssets.cancel, iconColor: Colors.white, width: 24.h, height: 24.h)),
cancelWidget: Padding(
padding: EdgeInsets.only(right: 8.h),
child: Utils.buildSvgWithAssets(icon: AppAssets.cancel, iconColor: Colors.white, width: 24.h, height: 24.h)),
onCalendarTypeChanged: (bool value) {
isGregorian = value;
});
@ -226,7 +227,7 @@ class TextInputWidget extends StatelessWidget {
return Text(
labelText,
style: TextStyle(
fontSize: 12.fSize,
fontSize: 12.f,
fontWeight: FontWeight.w500,
color: labelColor ?? AppColors.inputLabelTextColor,
letterSpacing: -0,
@ -235,6 +236,7 @@ class TextInputWidget extends StatelessWidget {
}
Widget _buildTextField(BuildContext context) {
double fontS = fontSize ?? 14.f;
return TextField(
enabled: isEnable,
scrollPadding: EdgeInsets.zero,
@ -253,11 +255,11 @@ class TextInputWidget extends StatelessWidget {
FocusManager.instance.primaryFocus?.unfocus();
},
onSubmitted: onSubmitted,
style: TextStyle(fontSize: fontSize!.fSize, height: isWalletAmountInput! ? 1 / 4 : 0, fontWeight: FontWeight.w500, color: AppColors.textColor, letterSpacing: -1),
style: TextStyle(fontSize: fontS, height: isWalletAmountInput! ? 1 / 4 : 0, fontWeight: FontWeight.w500, color: AppColors.textColor, letterSpacing: -1),
decoration: InputDecoration(
isDense: true,
hintText: hintText,
hintStyle: TextStyle(fontSize: 14.fSize, height: 21 / 16, fontWeight: FontWeight.w500, color: AppColors.textColor, letterSpacing: -0.75),
hintStyle: TextStyle(fontSize: 14.f, height: 21 / 16, fontWeight: FontWeight.w500, color: Color(0xff898A8D), letterSpacing: -0.75),
prefixIconConstraints: BoxConstraints(minWidth: 30.h),
prefixIcon: prefix == null ? null : "+${prefix!}".toText14(letterSpacing: -1, color: AppColors.textColor, weight: FontWeight.w500),
contentPadding: EdgeInsets.zero,
@ -269,13 +271,12 @@ class TextInputWidget extends StatelessWidget {
}
_buildTrailingIconForSearch(BuildContext context) {
final AppState appState = getIt.get<AppState>();
return Container(
height: 40.h,
width: 40.h,
margin: EdgeInsets.zero,
padding: EdgeInsets.all(8.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 10.h, color: AppColors.whiteColor),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 12.r, color: AppColors.whiteColor),
child: Utils.buildSvgWithAssets(icon: AppAssets.search_icon),
);
}

@ -35,7 +35,6 @@ class _LanguageSelectorState extends State<LanguageSelector> {
return InkWell(
onTap: () {
final newLanguage = widget.currentLanguage == 'ar' ? 'en' : 'ar';
print(newLanguage);
widget.onLanguageChanged(newLanguage);
},
child: Utils.buildSvgWithAssets(icon: AppAssets.globe_black));
@ -43,7 +42,7 @@ class _LanguageSelectorState extends State<LanguageSelector> {
return Stack(clipBehavior: Clip.none, children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
borderRadius: BorderRadius.circular((12.r)),
color: AppColors.secondaryLightRedColor,
),
child: InkWell(
@ -53,7 +52,7 @@ class _LanguageSelectorState extends State<LanguageSelector> {
},
child: Container(
padding: EdgeInsets.all(8.h),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(12)),
decoration: BoxDecoration(borderRadius: BorderRadius.circular((12.r))),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
@ -63,7 +62,7 @@ class _LanguageSelectorState extends State<LanguageSelector> {
currentLangData['name']?.toUpperCase() ?? 'EN',
style: context.dynamicTextStyle(
fontWeight: FontWeight.w500,
fontSize: 14.fSize,
fontSize: 14.f,
color: AppColors.primaryRedColor,
letterSpacing: 0.1,
isLanguageSwitcher: true,

@ -15,14 +15,16 @@ class LoaderBottomSheet {
_isVisible = true;
final context = _navService.navigatorKey.currentContext!;
showModalBottomSheet(
context: _navService.navigatorKey.currentContext!,
context: context,
isDismissible: (ApiConsts.appEnvironmentType == AppEnvironmentTypeEnum.uat || kDebugMode) ? true : false,
enableDrag: false,
constraints: BoxConstraints(minWidth: MediaQuery.of(context).size.width),
backgroundColor: Colors.transparent,
builder: (_) {
return Container(
height: MediaQuery.of(_navService.navigatorKey.currentContext!).size.height * 0.3,
height: MediaQuery.of(context).size.height * 0.3,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),

@ -67,7 +67,6 @@ dependencies:
jiffy: ^6.4.3
hijri_gregorian_calendar: ^0.1.1
sms_otp_auto_verify: ^2.2.0
web: any
flutter_staggered_animations: ^1.1.1
smooth_corner: ^1.1.1

Loading…
Cancel
Save