Compare commits

...

6 Commits

@ -1,16 +1,166 @@
# hmg_patient_app_new # HMG Patient App
New HMG Patient App A comprehensive Flutter-based mobile application for HMG (Hospital Management Group) patients,
providing seamless healthcare services and patient management features.
## Getting Started ## 📱 Features
This project is a starting point for a Flutter application. - **Patient Registration & Authentication**: Secure login and registration system
- **Appointment Management**: Book, reschedule, and manage medical appointments
- **Medical Records**: Access to personal health records and medical history
- **Doctor Consultation**: Video consultations and chat with healthcare providers
- **Health Monitoring**: Track vital signs and health metrics
- **Prescription Management**: View and manage prescriptions
- **Payment Integration**: Secure payment processing for medical services
- **Multi-language Support**: Available in English and Arabic
- **Push Notifications**: Real-time updates for appointments and health reminders
- **Calendar Integration**: Sync appointments with device calendar
- **Location Services**: Find nearby hospitals and clinics
A few resources to get you started if this is your first Flutter project: ## 🚀 Getting Started
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) ### Prerequisites
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the - Flutter SDK (>=3.0.0)
[online documentation](https://docs.flutter.dev/), which offers tutorials, - Dart SDK (>=3.0.0)
samples, guidance on mobile development, and a full API reference. - Android Studio / VS Code
- Android SDK (for Android development)
- Xcode (for iOS development, macOS only)
### Installation
1. **Clone the repository:**
```bash
git clone <repository-url>
cd HMG_Patient_App_New
```
2. **Install dependencies:**
```bash
flutter pub get
```
3. **Configure Firebase:**
- Add your `google-services.json` file to `android/app/`
- Add your `GoogleService-Info.plist` file to `ios/Runner/`
4. **Run the application:**
```bash
flutter run
```
## 🏗️ Project Structure
```
lib/
├── core/ # Core utilities and constants
├── extensions/ # Dart extensions
├── features/ # Feature-based modules
├── generated/ # Generated files (localization, etc.)
├── presentation/ # UI screens and widgets
├── routes/ # App navigation and routing
├── services/ # Business logic and API services
├── theme/ # App theming and styling
├── widgets/ # Reusable UI components
├── main.dart # App entry point
└── splashPage.dart # Splash screen
assets/
├── animations/ # Lottie animations
├── fonts/ # Custom fonts (Poppins, Gess Two)
├── images/ # PNG and SVG images
├── json/ # JSON data files
└── langs/ # Localization files
```
## 🛠️ Technologies Used
- **Framework**: Flutter
- **Language**: Dart
- **State Management**: [Your state management solution]
- **Backend Services**: Firebase
- **Authentication**: Firebase Auth
- **Database**: Cloud Firestore
- **Push Notifications**: Firebase Cloud Messaging
- **Maps**: Google Maps
- **Payment**: Amazon PayFort
- **Video Calling**: Flutter Zoom Video SDK
- **Local Storage**: SQLite, Shared Preferences
## 📱 Supported Platforms
- ✅ Android (API level 21+)
- ✅ iOS (iOS 12.0+)
- ✅ Foldable devices support
- ✅ Tablet optimization
## 🌐 Localization
The app supports multiple languages:
- English (en-US)
- Arabic (ar-SA)
## 🔧 Configuration
### Environment Setup
1. **API Keys**: Configure your API keys in the appropriate configuration files
2. **Firebase**: Set up Firebase project and add configuration files
3. **Maps**: Add Google Maps API key
4. **Payment**: Configure PayFort credentials
### Build Variants
- **Debug**: Development build with debugging enabled
- **Release**: Production-ready optimized build
## 📝 Development Guidelines
### Code Style
- Follow Dart/Flutter best practices
- Use consistent naming conventions
- Implement proper error handling
- Write comprehensive documentation
### Testing
```bash
# Run unit tests
flutter test
# Run integration tests
flutter test integration_test/
```
### Building for Production
**Android:**
```bash
flutter build apk --release
# or
flutter build appbundle --release
```
**iOS:**
```bash
flutter build ios --release
```
## 🤝 Contributing
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/new-feature`)
3. Commit your changes (`git commit -am 'Add new feature'`)
4. Push to the branch (`git push origin feature/new-feature`)
5. Create a Pull Request
## 📄 License
This project is proprietary software developed for HMG Healthcare Group.
**Built with ❤️ for better healthcare accessibility**

@ -11,22 +11,109 @@ extension ResponsiveExtension on num {
double get _screenHeight => SizeUtils.height; double get _screenHeight => SizeUtils.height;
/// Scale horizontally (width-based) /// Check if device is likely a foldable
double get w => (this * _screenWidth) / figmaDesignWidth; bool get _isFoldable {
double aspectRatio = _screenWidth / _screenHeight;
/// Scale vertically (height-based) // Foldable devices typically have aspect ratios close to 1:1 when unfolded
double get h => (this * _screenHeight) / figmaDesignHeight; return (aspectRatio > 0.9 && aspectRatio < 1.1) && (_screenWidth > 700 || _screenHeight > 700);
}
//radius
double get r => (this * _screenWidth) / figmaDesignWidth;
/// Scale text size /// Scale text size - enhanced for foldable devices
double get f { double get f {
double scale = _screenWidth / figmaDesignWidth; double aspectRatio = _screenWidth / _screenHeight;
if (scale > 1.6) scale = 1.6; // optional clamp for tablets double scale = (_screenWidth < _screenHeight ? _screenWidth : _screenHeight) / figmaDesignWidth;
// Enhanced clamping for different device types
double clamp;
if (SizeUtils.deviceType == DeviceType.tablet || _isFoldable) {
// More conservative scaling for tablets and foldables
clamp = (aspectRatio > 1.5 || aspectRatio < 0.67) ? 1.4 : 1.1;
} else {
// Original logic for phones
clamp = (aspectRatio > 1.3 || aspectRatio < 0.77) ? 1.6 : 1.2;
}
if (scale > clamp) scale = clamp;
return this * scale; return this * scale;
} }
/// Scale horizontally (width-based) - enhanced for foldable devices
double get w {
double baseScale = (this * _screenWidth) / figmaDesignWidth;
if (_isFoldable) {
// For foldables, use more conservative width scaling
double scale = _screenWidth / figmaDesignWidth;
scale = scale.clamp(0.8, 1.4);
return this * scale;
}
return baseScale;
}
/// Scale vertically (height-based) - enhanced for foldable devices
double get h {
double baseScale = (this * _screenHeight) / figmaDesignHeight;
if (_isFoldable) {
// For foldables, use height-based scaling but with constraints
double scale = (_screenHeight / figmaDesignHeight).clamp(0.8, 1.4);
return this * scale;
}
return baseScale;
}
/// Radius - enhanced for foldable devices
double get r {
double baseScale = (this * _screenWidth) / figmaDesignWidth;
if (_isFoldable) {
// Use the same logic as enhanced width for foldables
double scale = _screenWidth / figmaDesignWidth;
scale = scale.clamp(0.8, 1.4);
return this * scale;
}
return baseScale;
}
// New enhanced getters (additional options)
/// Enhanced font scaling with device-specific adjustments
double get fh {
double baseScale = _screenHeight / figmaDesignHeight;
if (_isFoldable) {
// Special handling for foldable devices - use more conservative scaling
baseScale = baseScale.clamp(0.8, 1.3);
} else if (SizeUtils.deviceType == DeviceType.tablet) {
// Tablet-specific scaling
baseScale = baseScale.clamp(0.9, 1.5);
} else {
// Phone scaling
baseScale = baseScale.clamp(0.8, 1.8);
}
return this * baseScale;
}
/// Adaptive scaling - automatically chooses best scaling method
double get adaptive {
if (_isFoldable) {
return fh;
} else if (SizeUtils.deviceType == DeviceType.tablet) {
return f * 0.9; // Slightly smaller for tablets
}
return f;
}
/// Minimum size constraint (useful for touch targets)
double get minSize {
double scaled = adaptive;
return scaled < 44 ? 44 : scaled; // Minimum 44pt for accessibility
}
/// Optional: direct accessors for full width/height /// Optional: direct accessors for full width/height
static double get screenWidth => SizeUtils.width; static double get screenWidth => SizeUtils.width;
@ -91,10 +178,7 @@ class SizeUtils {
/// Device's Width /// Device's Width
static double width = 375; static double width = 375;
static void setScreenSize( static void setScreenSize(BoxConstraints constraints, Orientation currentOrientation) {
BoxConstraints constraints,
Orientation currentOrientation,
) {
boxConstraints = constraints; boxConstraints = constraints;
orientation = currentOrientation; orientation = currentOrientation;
@ -130,6 +214,7 @@ class SizeUtils {
} }
log("longerSide: $longerSide"); log("longerSide: $longerSide");
log("shorterSide: $shorterSide");
log("isTablet: $isTablet"); log("isTablet: $isTablet");
} }
} }
@ -140,3 +225,9 @@ bool get isTablet => SizeUtils.deviceType == DeviceType.tablet;
bool get isMobile => SizeUtils.deviceType == DeviceType.mobile; bool get isMobile => SizeUtils.deviceType == DeviceType.mobile;
bool get isDesktop => SizeUtils.deviceType == DeviceType.desktop; bool get isDesktop => SizeUtils.deviceType == DeviceType.desktop;
bool get isFoldable {
double aspectRatio = SizeUtils.width / SizeUtils.height;
// Foldable devices typically have aspect ratios close to 1:1 when unfolded
return (aspectRatio > 0.9 && aspectRatio < 1.1) && (SizeUtils.width > 700 || SizeUtils.height > 700);
}

@ -633,17 +633,19 @@ class Utils {
required String url, required String url,
required Color iconColor, required Color iconColor,
bool isDisabled = false, bool isDisabled = false,
double width = 24, double? width,
double height = 24, double? height,
}) { }) {
final iconH = height ?? 24.h;
final iconW = width ?? 24.w;
return SvgPicture.network( return SvgPicture.network(
url, url,
colorFilter: ColorFilter.mode( colorFilter: ColorFilter.mode(
isDisabled ? iconColor.withOpacity(0.5) : iconColor, isDisabled ? iconColor.withOpacity(0.5) : iconColor,
BlendMode.srcIn, BlendMode.srcIn,
), ),
width: width, width: iconW,
height: height, height: iconH,
); );
} }
@ -662,7 +664,7 @@ class Utils {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
border: border != null ? Border.all(color: AppColors.whiteColor, width: border) : null, border: border != null ? Border.all(color: AppColors.whiteColor, width: border) : null,
borderRadius: border != null ? BorderRadius.circular(borderRadius ?? 0) : null, borderRadius: border != null ? BorderRadius.circular(borderRadius ?? 12.r) : null,
), ),
child: Image.asset(icon, width: iconW, height: iconH, fit: fit), child: Image.asset(icon, width: iconW, height: iconH, fit: fit),
); );
@ -670,17 +672,27 @@ class Utils {
} }
/// Widget to build an SVG from network /// Widget to build an SVG from network
static Widget buildImgWithNetwork({required String url, required Color iconColor, bool isDisabled = false, double width = 24, double height = 24, BoxFit fit = BoxFit.cover, ImageErrorWidgetBuilder? errorBuilder}) { static Widget buildImgWithNetwork({
required String url,
required Color iconColor,
bool isDisabled = false,
double? width,
double? height,
BoxFit fit = BoxFit.cover,
ImageErrorWidgetBuilder? errorBuilder,
}) {
final iconH = height ?? 24.h;
final iconW = width ?? 24.w;
return Image.network( return Image.network(
url, url,
width: width, width: iconW,
height: height, height: iconH,
fit: fit, fit: fit,
errorBuilder: errorBuilder??(_,__,___){ errorBuilder: errorBuilder ??
//todo change the error builder icon that it is returning (_, __, ___) {
return Utils.buildSvgWithAssets(width: width, //todo change the error builder icon that it is returning
height: height,icon: AppAssets.no_visit_icon); return Utils.buildSvgWithAssets(width: iconW, height: iconH, icon: AppAssets.no_visit_icon);
}, },
); );
} }

@ -167,16 +167,17 @@ extension EmailValidator on String {
decoration: isUnderLine ? TextDecoration.underline : null), decoration: isUnderLine ? TextDecoration.underline : null),
); );
Widget toText14( Widget toText14({
{Color? color, Color? color,
bool isUnderLine = false, bool isUnderLine = false,
bool isBold = false, bool isBold = false,
bool isCenter = false, bool isCenter = false,
FontWeight? weight, FontWeight? weight,
int? maxlines, int? maxlines,
double? letterSpacing = 0, double? letterSpacing = 0,
double? height, double? height,
TextOverflow? textOverflow}) => TextOverflow? textOverflow,
}) =>
Text( Text(
this, this,
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? TextAlign.center : null,

@ -16,18 +16,16 @@ import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/AppointmentFilter.dart'; import 'package:hmg_patient_app_new/presentation/appointments/widgets/AppointmentFilter.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_card.dart'; import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_card.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/book_appointment_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/book_appointment_page.dart';
import 'package:hmg_patient_app_new/widgets/date_range_selector/date_range_calender.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/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/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
import 'package:hmg_patient_app_new/widgets/date_range_selector/date_range_calender.dart';
import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.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:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../widgets/common_bottom_sheet.dart' import '../../widgets/common_bottom_sheet.dart' show showCommonBottomSheetWithoutHeight;
show showCommonBottomSheetWithoutHeight;
class MyAppointmentsPage extends StatefulWidget { class MyAppointmentsPage extends StatefulWidget {
const MyAppointmentsPage({super.key}); const MyAppointmentsPage({super.key});
@ -86,18 +84,14 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
} }
Widget getSelectedTabData(int index, MyAppointmentsViewModel myAppointmentsVM) { Widget getSelectedTabData(int index, MyAppointmentsViewModel myAppointmentsVM) {
return getAppointList( return getAppointList(myAppointmentsVM, myAppointmentsVM.filteredAppointmentList);
myAppointmentsVM, myAppointmentsVM.filteredAppointmentList);
} }
Widget getAppointList(MyAppointmentsViewModel myAppointmentsVM, Widget getAppointList(MyAppointmentsViewModel myAppointmentsVM, List<PatientAppointmentHistoryResponseModel> filteredAppointmentList) {
List<PatientAppointmentHistoryResponseModel> filteredAppointmentList) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Visibility( Visibility(visible: myAppointmentsVM.availableFilters.isNotEmpty, child: getAppointmentFilters(myAppointmentsVM)),
visible: myAppointmentsVM.availableFilters.isNotEmpty,
child: getAppointmentFilters(myAppointmentsVM)),
ListView.separated( ListView.separated(
padding: EdgeInsets.only(top: 24.h), padding: EdgeInsets.only(top: 24.h),
shrinkWrap: true, shrinkWrap: true,
@ -110,14 +104,9 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
itemBuilder: (context, index) { itemBuilder: (context, index) {
return myAppointmentsVM.isMyAppointmentsLoading return myAppointmentsVM.isMyAppointmentsLoading
? Container( ? Container(
decoration: RoundedRectangleBorder() decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
.toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.h,
hasShadow: true),
child: AppointmentCard( child: AppointmentCard(
patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel(),
PatientAppointmentHistoryResponseModel(),
myAppointmentsViewModel: myAppointmentsViewModel, myAppointmentsViewModel: myAppointmentsViewModel,
bookAppointmentsViewModel: bookAppointmentsViewModel, bookAppointmentsViewModel: bookAppointmentsViewModel,
isLoading: true, isLoading: true,
@ -134,16 +123,10 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
child: AnimatedContainer( child: AnimatedContainer(
duration: Duration(milliseconds: 300), duration: Duration(milliseconds: 300),
curve: Curves.easeInOut, curve: Curves.easeInOut,
decoration: RoundedRectangleBorder() decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
.toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.h,
hasShadow: true),
child: AppointmentCard( child: AppointmentCard(
patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel: filteredAppointmentList[index],
filteredAppointmentList[index], myAppointmentsViewModel: myAppointmentsViewModel,
myAppointmentsViewModel:
myAppointmentsViewModel,
bookAppointmentsViewModel: bookAppointmentsViewModel, bookAppointmentsViewModel: bookAppointmentsViewModel,
isLoading: false, isLoading: false,
isFromHomePage: false, isFromHomePage: false,
@ -154,8 +137,7 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
) )
: Utils.getNoDataWidget( : Utils.getNoDataWidget(
context, context,
noDataText: "You don't have any appointments yet." noDataText: "You don't have any appointments yet.".needTranslation,
.needTranslation,
callToActionButton: CustomButton( callToActionButton: CustomButton(
text: LocaleKeys.bookAppo.tr(context: context), text: LocaleKeys.bookAppo.tr(context: context),
onPressed: () { onPressed: () {
@ -168,18 +150,17 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
backgroundColor: Color(0xffFEE9EA), backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA), borderColor: Color(0xffFEE9EA),
textColor: Color(0xffED1C2B), textColor: Color(0xffED1C2B),
fontSize: 14, fontSize: 14.f,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
borderRadius: 12, borderRadius: 12.r,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0),
height: 40, height: 40.h,
icon: AppAssets.add_icon, icon: AppAssets.add_icon,
iconColor: AppColors.primaryRedColor, iconColor: AppColors.primaryRedColor,
).paddingSymmetrical(48.h, 0.h), ).paddingSymmetrical(48.h, 0.h),
); );
}, },
separatorBuilder: (BuildContext cxt, int index) => separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
SizedBox(height: 16.h),
), ),
SizedBox(height: 24.h), SizedBox(height: 24.h),
], ],
@ -189,45 +170,41 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
Widget getAppointmentFilters(MyAppointmentsViewModel myAppointmentsVM) { Widget getAppointmentFilters(MyAppointmentsViewModel myAppointmentsVM) {
return SizedBox( return SizedBox(
child: Row( child: Row(
children: [ children: [
Expanded( Expanded(
child: ListView.separated( child: ListView.separated(
separatorBuilder: (_, index) => SizedBox( separatorBuilder: (_, index) => SizedBox(
width: 8.h, width: 8.h,
), ),
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemCount: myAppointmentsVM.availableFilters.length, itemCount: myAppointmentsVM.availableFilters.length,
itemBuilder: (_, index) => AppointmentFilters( itemBuilder: (_, index) => AppointmentFilters(
selectedFilter: myAppointmentsVM.selectedFilter, selectedFilter: myAppointmentsVM.selectedFilter,
item: myAppointmentsVM.availableFilters[index], item: myAppointmentsVM.availableFilters[index],
onClicked: () { onClicked: () {
if (myAppointmentsVM.availableFilters[index] == if (myAppointmentsVM.availableFilters[index] == AppointmentListingFilters.DATESELECTION) {
AppointmentListingFilters.DATESELECTION) { showCommonBottomSheetWithoutHeight(
showCommonBottomSheetWithoutHeight( title: "Set The Date Range".needTranslation,
title: "Set The Date Range".needTranslation, context,
context, child: DateRangeSelector(
child: DateRangeSelector( onRangeSelected: (start, end) {
onRangeSelected: (start, end) { // if (start != null) {
// if (start != null) { myAppointmentsVM.getSelectedDateRange(start, end);
myAppointmentsVM.getSelectedDateRange( // }
start, end); },
// } ),
}, isFullScreen: false,
), isCloseButtonVisible: true,
isFullScreen: false, callBackFunc: () {},
isCloseButtonVisible: true, );
callBackFunc: () {}, } else {
); myAppointmentsVM.setSelectedFilter(myAppointmentsVM.availableFilters[index]);
} else { myAppointmentsVM.filterTheListAsPerSelection();
myAppointmentsVM.setSelectedFilter( }
myAppointmentsVM.availableFilters[index]); },
myAppointmentsVM.filterTheListAsPerSelection(); )),
} ),
}, ],
)), )).paddingOnly(top: 24.h, left: 24.h, right: 24.h);
),
],
)).paddingOnly(top: 24.h, left: 24.h, right: 24.h);
} }
} }

@ -106,398 +106,388 @@ class _LandingPageState extends State<LandingPage> {
insuranceViewModel = Provider.of<InsuranceViewModel>(context, listen: false); insuranceViewModel = Provider.of<InsuranceViewModel>(context, listen: false);
immediateLiveCareViewModel = Provider.of<ImmediateLiveCareViewModel>(context, listen: false); immediateLiveCareViewModel = Provider.of<ImmediateLiveCareViewModel>(context, listen: false);
appState = getIt.get<AppState>(); appState = getIt.get<AppState>();
return Scaffold( return PopScope(
backgroundColor: AppColors.bgScaffoldColor, canPop: false,
body: SingleChildScrollView( child: Scaffold(
padding: EdgeInsets.only(top: kToolbarHeight + 0.h, bottom: 24), backgroundColor: AppColors.bgScaffoldColor,
child: Column( body: SingleChildScrollView(
spacing: 16.h, padding: EdgeInsets.only(top: kToolbarHeight + 0.h, bottom: 24),
children: [ child: Column(
Row( spacing: 16.h,
spacing: 8.h, children: [
mainAxisAlignment: MainAxisAlignment.spaceBetween, Row(
children: [ spacing: 8.h,
appState.isAuthenticated mainAxisAlignment: MainAxisAlignment.spaceBetween,
? WelcomeWidget( children: [
onTap: () { appState.isAuthenticated
Navigator.of(context).push(springPageRoute(ProfileSettings())); ? WelcomeWidget(
}, onTap: () {
name: ('${appState.getAuthenticatedUser()!.firstName!} ${appState.getAuthenticatedUser()!.lastName!}'), Navigator.of(context).push(springPageRoute(ProfileSettings()));
imageUrl: appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg, },
).expanded name: ('${appState.getAuthenticatedUser()!.firstName!} ${appState.getAuthenticatedUser()!.lastName!}'),
: CustomButton( imageUrl: appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg,
text: LocaleKeys.loginOrRegister.tr(context: context), ).expanded
onPressed: () async { : CustomButton(
await authVM.onLoginPressed(); text: LocaleKeys.loginOrRegister.tr(context: context),
}, onPressed: () async {
backgroundColor: Color(0xffFEE9EA), await authVM.onLoginPressed();
borderColor: Color(0xffFEE9EA), },
textColor: Color(0xffED1C2B), backgroundColor: Color(0xffFEE9EA),
fontSize: 14.f, borderColor: Color(0xffFEE9EA),
fontWeight: FontWeight.w500, textColor: Color(0xffED1C2B),
borderRadius: 12, fontSize: 14.f,
padding: EdgeInsets.fromLTRB(10.h, 0, 10.h, 0), fontWeight: FontWeight.w500,
height: 40.h, borderRadius: 12.r,
), padding: EdgeInsets.fromLTRB(10.h, 0, 10.h, 0),
Row( height: 40.h,
mainAxisSize: MainAxisSize.min,
spacing: 12.h,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.bell, height: 18.h, width: 18.h).onPress(() {
Navigator.of(context).push(
CustomPageRoute(
page: MedicalFilePage(),
// page: LoginScreen(),
),
);
}),
Utils.buildSvgWithAssets(icon: AppAssets.search_icon, height: 18.h, width: 18.h).onPress(() {
Navigator.of(context).push(
CustomPageRoute(
page: MedicalFilePage(),
// page: LoginScreen(),
),
);
}),
Utils.buildSvgWithAssets(icon: AppAssets.contact_icon, height: 18.h, width: 18.h).onPress(() {
Navigator.of(context).push(
CustomPageRoute(
page: MedicalFilePage(),
// page: LoginScreen(),
), ),
); Row(
}), mainAxisSize: MainAxisSize.min,
], spacing: 12.h,
)
],
).paddingSymmetrical(24.h, 0.h),
appState.isAuthenticated
? Column(
children: [ children: [
SizedBox(height: 12.h), Utils.buildSvgWithAssets(icon: AppAssets.bell, height: 18.h, width: 18.h).onPress(() {
Row( Navigator.of(context).push(
mainAxisAlignment: MainAxisAlignment.spaceBetween, CustomPageRoute(
children: [ page: MedicalFilePage(),
"Appointments & Visits".toText16(isBold: true), // page: LoginScreen(),
Row(
children: [
LocaleKeys.viewAll.tr(context: context).toText12(color: AppColors.primaryRedColor),
SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
],
), ),
], );
).paddingSymmetrical(24.h, 0.h).onPress(() { }),
Utils.buildSvgWithAssets(icon: AppAssets.search_icon, height: 18.h, width: 18.h).onPress(() {
Navigator.of(context).push( Navigator.of(context).push(
CustomPageRoute( CustomPageRoute(
page: MyAppointmentsPage(), page: MedicalFilePage(),
// page: LoginScreen(),
), ),
); );
}), }),
SizedBox(height: 16.h), Utils.buildSvgWithAssets(icon: AppAssets.contact_icon, height: 18.h, width: 18.h).onPress(() {
Consumer<MyAppointmentsViewModel>(builder: (context, myAppointmentsVM, child) { Navigator.of(context).push(
return myAppointmentsVM.isMyAppointmentsLoading CustomPageRoute(
? Container( page: MedicalFilePage(),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), // page: LoginScreen(),
child: AppointmentCard( ),
patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel(), );
myAppointmentsViewModel: myAppointmentsViewModel, }),
bookAppointmentsViewModel: bookAppointmentsViewModel, ],
isLoading: true, ),
isFromHomePage: true, ],
), ).paddingSymmetrical(24.h, 0.h),
).paddingSymmetrical(24.h, 0.h) appState.isAuthenticated
: myAppointmentsVM.patientAppointmentsHistoryList.isNotEmpty ? Column(
? myAppointmentsVM.patientAppointmentsHistoryList.length == 1 children: [
? Container( SizedBox(height: 12.h),
decoration: Row(
RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), mainAxisAlignment: MainAxisAlignment.spaceBetween,
child: AppointmentCard( children: [
patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList.first, "Appointments & Visits".toText16(isBold: true),
myAppointmentsViewModel: myAppointmentsViewModel, Row(
bookAppointmentsViewModel: bookAppointmentsViewModel, children: [
isLoading: false, LocaleKeys.viewAll.tr(context: context).toText12(color: AppColors.primaryRedColor),
isFromHomePage: true, SizedBox(width: 2.h),
), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
).paddingSymmetrical(24.h, 0.h) ],
: Swiper( ),
itemCount: myAppointmentsVM.isMyAppointmentsLoading ],
? 3 ).paddingSymmetrical(24.h, 0.h).onPress(() {
: myAppointmentsVM.patientAppointmentsHistoryList.length < 3 Navigator.of(context).push(CustomPageRoute(page: MyAppointmentsPage()));
? myAppointmentsVM.patientAppointmentsHistoryList.length }),
: 3, SizedBox(height: 16.h),
layout: SwiperLayout.STACK, Consumer<MyAppointmentsViewModel>(
loop: true, builder: (context, myAppointmentsVM, child) {
itemWidth: MediaQuery.of(context).size.width - 48.h, return myAppointmentsVM.isMyAppointmentsLoading
indicatorLayout: PageIndicatorLayout.COLOR, ? Container(
axisDirection: AxisDirection.right, decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
controller: _controller, color: AppColors.whiteColor,
itemHeight: 210 + 25, borderRadius: 24.r,
pagination: const SwiperPagination( hasShadow: true,
alignment: Alignment.bottomCenter, ),
margin: EdgeInsets.only(top: 210 + 8 + 24), child: AppointmentCard(
builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor), patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel(),
), myAppointmentsViewModel: myAppointmentsViewModel,
itemBuilder: (BuildContext context, int index) { bookAppointmentsViewModel: bookAppointmentsViewModel,
return Container( isLoading: true,
decoration: RoundedRectangleBorder() isFromHomePage: true,
.toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), ),
).paddingSymmetrical(24.h, 0.h)
: myAppointmentsVM.patientAppointmentsHistoryList.isNotEmpty
? myAppointmentsVM.patientAppointmentsHistoryList.length == 1
? Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
hasShadow: true,
),
child: AppointmentCard( child: AppointmentCard(
patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index], patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList.first,
myAppointmentsViewModel: myAppointmentsViewModel, myAppointmentsViewModel: myAppointmentsViewModel,
bookAppointmentsViewModel: bookAppointmentsViewModel, bookAppointmentsViewModel: bookAppointmentsViewModel,
isLoading: false, isLoading: false,
isFromHomePage: true, isFromHomePage: true,
), ),
); ).paddingSymmetrical(24.h, 0.h)
}, : Swiper(
) itemCount: myAppointmentsVM.isMyAppointmentsLoading
: Container( ? 3
width: double.infinity, : myAppointmentsVM.patientAppointmentsHistoryList.length < 3
decoration: ? myAppointmentsVM.patientAppointmentsHistoryList.length
RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24, hasShadow: true), : 3,
child: Padding( layout: SwiperLayout.STACK,
padding: EdgeInsets.all(12.h), loop: true,
child: Column( itemWidth: MediaQuery.of(context).size.width - 48.h,
children: [ indicatorLayout: PageIndicatorLayout.COLOR,
Utils.buildSvgWithAssets(icon: AppAssets.home_calendar_icon, width: 32.h, height: 32.h), axisDirection: AxisDirection.right,
SizedBox(height: 12.h), controller: _controller,
"You do not have any upcoming appointment. Please book an appointment".needTranslation.toText12(isCenter: true), itemHeight: 210 + 25,
SizedBox(height: 12.h), pagination: const SwiperPagination(
CustomButton( alignment: Alignment.bottomCenter,
text: LocaleKeys.bookAppo.tr(context: context), margin: EdgeInsets.only(top: 210 + 8 + 24),
onPressed: () { builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor),
Navigator.of(context).push( ),
CustomPageRoute( itemBuilder: (BuildContext context, int index) {
page: BookAppointmentPage(), return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
hasShadow: true,
),
child: AppointmentCard(
patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index],
myAppointmentsViewModel: myAppointmentsViewModel,
bookAppointmentsViewModel: bookAppointmentsViewModel,
isLoading: false,
isFromHomePage: true,
), ),
); );
}, },
backgroundColor: Color(0xffFEE9EA), )
borderColor: Color(0xffFEE9EA), : Container(
textColor: Color(0xffED1C2B), width: double.infinity,
fontSize: 14.f, decoration:
fontWeight: FontWeight.w500, RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true),
padding: EdgeInsets.fromLTRB(10.h, 0, 10.h, 0), child: Padding(
icon: AppAssets.add_icon, padding: EdgeInsets.all(12.h),
iconColor: AppColors.primaryRedColor, child: Column(
),
],
),
),
).paddingSymmetrical(24.h, 0.h);
}),
Consumer<ImmediateLiveCareViewModel>(builder: (context, immediateLiveCareVM, child) {
return immediateLiveCareVM.patientHasPendingLiveCareRequest
? Column(
children: [
SizedBox(height: 12.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: true,
side: BorderSide(color: AppColors.ratingColorYellow, width: 3.h),
),
width: double.infinity,
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
AppCustomChipWidget( Utils.buildSvgWithAssets(icon: AppAssets.home_calendar_icon, width: 32.h, height: 32.h),
labelText: immediateLiveCareViewModel.patientLiveCareHistoryList[0].stringCallStatus, SizedBox(height: 12.h),
backgroundColor: AppColors.warningColorYellow.withValues(alpha: 0.20), "You do not have any upcoming appointment. Please book an appointment".needTranslation.toText12(isCenter: true),
textColor: AppColors.alertColor, 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,
padding: EdgeInsets.fromLTRB(10.h, 0, 10.h, 0),
icon: AppAssets.add_icon,
iconColor: AppColors.primaryRedColor,
height: (isFoldable || isTablet) ? 56.h : 46.h,
), ),
Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h),
// Lottie.asset(AppAnimations.pending_loading_animation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 40.h, height: 40.h, fit: BoxFit.contain),
], ],
), ),
SizedBox(height: 8.h), ),
Row( ).paddingSymmetrical(24.h, 0.h);
mainAxisAlignment: MainAxisAlignment.spaceBetween, },
),
Consumer<ImmediateLiveCareViewModel>(
builder: (context, immediateLiveCareVM, child) {
return immediateLiveCareVM.patientHasPendingLiveCareRequest
? Column(
children: [
SizedBox(height: 12.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.r,
hasShadow: true,
side: BorderSide(color: AppColors.ratingColorYellow, width: 3.h),
),
width: double.infinity,
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
"You have a pending LiveCare request".needTranslation.toText12(isBold: true), Row(
Utils.buildSvgWithAssets( mainAxisAlignment: MainAxisAlignment.spaceBetween,
icon: AppAssets.forward_arrow_icon_small, children: [
iconColor: AppColors.blackColor, AppCustomChipWidget(
width: 20.h, labelText: immediateLiveCareViewModel.patientLiveCareHistoryList[0].stringCallStatus,
height: 15.h, backgroundColor: AppColors.warningColorYellow.withValues(alpha: 0.20),
fit: BoxFit.contain, textColor: AppColors.alertColor,
),
Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h),
// Lottie.asset(AppAnimations.pending_loading_animation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 40.h, height: 40.h, fit: BoxFit.contain),
],
),
SizedBox(height: 8.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"You have a pending LiveCare request".needTranslation.toText12(isBold: true),
Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon_small,
iconColor: AppColors.blackColor,
width: 20.h,
height: 15.h,
fit: BoxFit.contain,
),
],
), ),
], ],
), ),
], ),
), ).paddingSymmetrical(24.h, 0.h).onPress(() {
), Navigator.of(context).push(CustomPageRoute(page: ImmediateLiveCarePendingRequestPage()));
).paddingSymmetrical(24.h, 0.h).onPress(() { }),
Navigator.of(context).push( SizedBox(height: 12.h),
CustomPageRoute( ],
page: ImmediateLiveCarePendingRequestPage(), )
), : SizedBox(height: 12.h);
); },
}),
SizedBox(height: 12.h),
],
)
: SizedBox(height: 12.h);
}),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Quick Links".needTranslation.toText16(isBold: true),
Row(
children: [
"View medical file".needTranslation.toText12(color: AppColors.primaryRedColor),
SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
],
),
],
).paddingSymmetrical(24.h, 0.h).onPress(() {
Navigator.of(context).push(
CustomPageRoute(
page: MedicalFilePage(),
),
);
}),
SizedBox(height: 16.h),
Container(
height: 120.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24,
), ),
child: Column( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Expanded( "Quick Links".needTranslation.toText16(isBold: true),
child: ListView.separated( Row(
scrollDirection: Axis.horizontal, children: [
itemCount: LandingPageData.getLoggedInServiceCardsList.length, "View medical file".needTranslation.toText12(color: AppColors.primaryRedColor),
shrinkWrap: true, SizedBox(width: 2.h),
padding: EdgeInsets.only(left: 16.h, right: 16.h), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
itemBuilder: (context, index) { ],
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 1000),
child: SlideAnimation(
horizontalOffset: 100.0,
child: FadeInAnimation(
child: SmallServiceCard(
icon: LandingPageData.getLoggedInServiceCardsList[index].icon,
title: LandingPageData.getLoggedInServiceCardsList[index].title,
subtitle: LandingPageData.getLoggedInServiceCardsList[index].subtitle,
iconColor: LandingPageData.getLoggedInServiceCardsList[index].iconColor,
textColor: LandingPageData.getLoggedInServiceCardsList[index].textColor,
backgroundColor: LandingPageData.getLoggedInServiceCardsList[index].backgroundColor,
isBold: LandingPageData.getLoggedInServiceCardsList[index].isBold,
serviceName: LandingPageData.getLoggedInServiceCardsList[index].serviceName,
),
),
),
);
},
separatorBuilder: (BuildContext cxt, int index) => 10.width,
),
), ),
], ],
), ).paddingSymmetrical(24.h, 0.h).onPress(() {
).paddingSymmetrical(24.h, 0.h), Navigator.of(context).push(CustomPageRoute(page: MedicalFilePage()));
], }),
) SizedBox(height: 16.h),
: Container( Container(
height: 127.h, height: 120.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r),
color: AppColors.whiteColor, child: Column(
borderRadius: 24, children: [
), Expanded(
child: Column( child: ListView.separated(
children: [ scrollDirection: Axis.horizontal,
Expanded( itemCount: LandingPageData.getLoggedInServiceCardsList.length,
child: ListView.separated( shrinkWrap: true,
scrollDirection: Axis.horizontal, padding: EdgeInsets.only(left: 16.h, right: 16.h),
itemCount: LandingPageData.getNotLoggedInServiceCardsList.length, itemBuilder: (context, index) {
shrinkWrap: true, return AnimationConfiguration.staggeredList(
padding: EdgeInsets.only(left: 16.h, right: 16.h), position: index,
itemBuilder: (context, index) { duration: const Duration(milliseconds: 1000),
return AnimationConfiguration.staggeredList( child: SlideAnimation(
position: index, horizontalOffset: 100.0,
duration: const Duration(milliseconds: 1000), child: FadeInAnimation(
child: SlideAnimation( child: SmallServiceCard(
horizontalOffset: 100.0, icon: LandingPageData.getLoggedInServiceCardsList[index].icon,
child: FadeInAnimation( title: LandingPageData.getLoggedInServiceCardsList[index].title,
child: SmallServiceCard( subtitle: LandingPageData.getLoggedInServiceCardsList[index].subtitle,
serviceName: LandingPageData.getNotLoggedInServiceCardsList[index].serviceName, iconColor: LandingPageData.getLoggedInServiceCardsList[index].iconColor,
icon: LandingPageData.getNotLoggedInServiceCardsList[index].icon, textColor: LandingPageData.getLoggedInServiceCardsList[index].textColor,
title: LandingPageData.getNotLoggedInServiceCardsList[index].title, backgroundColor: LandingPageData.getLoggedInServiceCardsList[index].backgroundColor,
subtitle: LandingPageData.getNotLoggedInServiceCardsList[index].subtitle, isBold: LandingPageData.getLoggedInServiceCardsList[index].isBold,
iconColor: LandingPageData.getNotLoggedInServiceCardsList[index].iconColor, serviceName: LandingPageData.getLoggedInServiceCardsList[index].serviceName,
textColor: LandingPageData.getNotLoggedInServiceCardsList[index].textColor, ),
backgroundColor: LandingPageData.getNotLoggedInServiceCardsList[index].backgroundColor, ),
isBold: LandingPageData.getNotLoggedInServiceCardsList[index].isBold, ),
), );
), },
separatorBuilder: (BuildContext cxt, int index) => 10.width,
), ),
); ),
}, ],
separatorBuilder: (BuildContext cxt, int index) => 0.width,
), ),
), ).paddingSymmetrical(24.h, 0.h),
], ],
), )
).paddingSymmetrical(24.h, 0.h), : Container(
Row( height: 127.h,
mainAxisAlignment: MainAxisAlignment.spaceBetween, decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r),
children: [ child: Column(
"Services".toText16(isBold: true), children: [
Row( Expanded(
children: [ child: ListView.separated(
"View all services".toText12(color: AppColors.primaryRedColor), scrollDirection: Axis.horizontal,
SizedBox(width: 2.h), itemCount: LandingPageData.getNotLoggedInServiceCardsList.length,
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), shrinkWrap: true,
], padding: EdgeInsets.only(left: 16.h, right: 16.h),
), itemBuilder: (context, index) {
], return AnimationConfiguration.staggeredList(
).paddingSymmetrical(24.h, 0.h), position: index,
SizedBox( duration: const Duration(milliseconds: 1000),
height: 325.h, child: SlideAnimation(
child: Column( horizontalOffset: 100.0,
children: [ child: FadeInAnimation(
Expanded( child: SmallServiceCard(
child: ListView.separated( serviceName: LandingPageData.getNotLoggedInServiceCardsList[index].serviceName,
scrollDirection: Axis.horizontal, icon: LandingPageData.getNotLoggedInServiceCardsList[index].icon,
itemCount: LandingPageData.getServiceCardsList.length, title: LandingPageData.getNotLoggedInServiceCardsList[index].title,
shrinkWrap: true, subtitle: LandingPageData.getNotLoggedInServiceCardsList[index].subtitle,
padding: EdgeInsets.only(left: 24.h, right: 24.h), iconColor: LandingPageData.getNotLoggedInServiceCardsList[index].iconColor,
itemBuilder: (context, index) { textColor: LandingPageData.getNotLoggedInServiceCardsList[index].textColor,
return AnimationConfiguration.staggeredList( backgroundColor: LandingPageData.getNotLoggedInServiceCardsList[index].backgroundColor,
position: index, isBold: LandingPageData.getNotLoggedInServiceCardsList[index].isBold,
duration: const Duration(milliseconds: 1000), ),
child: SlideAnimation( ),
horizontalOffset: 100.0, ),
child: FadeInAnimation( );
child: LargeServiceCard( },
image: LandingPageData.getServiceCardsList[index].icon, separatorBuilder: (BuildContext cxt, int index) => 0.width,
title: LandingPageData.getServiceCardsList[index].title,
subtitle: LandingPageData.getServiceCardsList[index].subtitle,
icon: LandingPageData.getServiceCardsList[index].largeCardIcon,
),
), ),
), ),
); ],
}, ),
separatorBuilder: (BuildContext cxt, int index) => 8.width, ).paddingSymmetrical(24.h, 0.h),
), Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Services".toText16(isBold: true),
Row(
children: [
"View all services".toText12(color: AppColors.primaryRedColor),
SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
],
), ),
], ],
).paddingSymmetrical(24.h, 0.h),
SizedBox(
height: 340.h,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: LandingPageData.getServiceCardsList.length,
shrinkWrap: true,
padding: EdgeInsets.only(left: 24.w, right: 24.w),
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 1000),
child: SlideAnimation(
horizontalOffset: 100.0,
child: FadeInAnimation(
child: LargeServiceCard(
image: LandingPageData.getServiceCardsList[index].icon,
title: LandingPageData.getServiceCardsList[index].title,
subtitle: LandingPageData.getServiceCardsList[index].subtitle,
icon: LandingPageData.getServiceCardsList[index].largeCardIcon,
),
),
),
);
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 8.w),
),
), ),
), appState.isAuthenticated ? HabibWalletCard() : SizedBox(),
appState.isAuthenticated ? HabibWalletCard() : SizedBox(), ],
], ),
), ),
), ),
); );
@ -509,19 +499,21 @@ class _LandingPageState extends State<LandingPage> {
title: "", title: "",
isCloseButtonVisible: false, isCloseButtonVisible: false,
child: StatefulBuilder(builder: (context, setState) { child: StatefulBuilder(
return QuickLogin( builder: (context, setState) {
isDone: isDone, return QuickLogin(
onPressed: () { isDone: isDone,
// sharedPref.setBool(HAS_ENABLED_QUICK_LOGIN, true); onPressed: () {
authVM.loginWithFingerPrintFace(() { // sharedPref.setBool(HAS_ENABLED_QUICK_LOGIN, true);
isDone = true; authVM.loginWithFingerPrintFace(() {
cacheService.saveBool(key: CacheConst.quickLoginEnabled, value: true); isDone = true;
setState(() {}); cacheService.saveBool(key: CacheConst.quickLoginEnabled, value: true);
}); setState(() {});
}, });
); },
}), );
},
),
// height: isDone == false ? ResponsiveExtension.screenHeight * 0.5 : ResponsiveExtension.screenHeight * 0.3, // height: isDone == false ? ResponsiveExtension.screenHeight * 0.5 : ResponsiveExtension.screenHeight * 0.3,
isFullScreen: false, isFullScreen: false,
callBackFunc: () { callBackFunc: () {

@ -16,7 +16,7 @@ class LargeServiceCard extends StatelessWidget {
final String title; final String title;
final String subtitle; final String subtitle;
LargeServiceCard({ const LargeServiceCard({
super.key, super.key,
this.image = "", this.image = "",
this.icon = "", this.icon = "",
@ -26,51 +26,37 @@ class LargeServiceCard extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return Container(
padding: EdgeInsets.symmetric(horizontal: 3.h), width: 150.w,
child: Container( padding: EdgeInsets.symmetric(horizontal: 3.w),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: Colors.transparent, borderRadius: 16.r),
color: Colors.transparent, child: Column(
borderRadius: 16, mainAxisAlignment: MainAxisAlignment.start,
), crossAxisAlignment: CrossAxisAlignment.start,
child: Padding( children: [
padding: EdgeInsets.symmetric(horizontal: 0.h), Image.asset(AppAssets.livecare_service, width: 220.w, fit: BoxFit.contain),
child: Column( SizedBox(height: 10.h),
mainAxisAlignment: MainAxisAlignment.center, Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Image.asset(AppAssets.livecare_service, width: 220.h, height: 220.h, fit: BoxFit.contain), Utils.buildSvgWithAssets(icon: icon, width: 24.w, height: 24.h),
SizedBox(height: 3.h), Flexible(child: title.toText14(color: AppColors.blackColor, isBold: true, textOverflow: TextOverflow.clip, maxlines: 1)),
Row(
children: [
Utils.buildSvgWithAssets(icon: icon, width: 24.h, height: 24.h),
title.toText14(color: AppColors.blackColor, isBold: true),
],
),
SizedBox(width: 220.h, child: subtitle.toText11(color: AppColors.blackColor)),
SizedBox(height: 6.h),
SizedBox(
width: 220.h,
child: CustomButton(
text: LocaleKeys.bookNow.tr(context: context),
onPressed: () {
// Navigator.of(context).pushReplacement(
// MaterialPageRoute(builder: (BuildContext context) => LandingPage()),
// );
},
backgroundColor: AppColors.borderOnlyColor,
borderColor: AppColors.borderOnlyColor,
textColor: AppColors.whiteColor,
fontSize: 14,
fontWeight: FontWeight.bold,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
),
),
], ],
), ),
), subtitle.toText11(color: AppColors.blackColor),
SizedBox(height: 10.h),
CustomButton(
text: LocaleKeys.bookNow.tr(context: context),
onPressed: () {},
backgroundColor: AppColors.borderOnlyColor,
borderColor: AppColors.borderOnlyColor,
textColor: AppColors.whiteColor,
fontSize: 14.f,
fontWeight: FontWeight.bold,
borderRadius: 12.r,
padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0),
height: 40.h,
),
],
), ),
); );
} }

@ -221,12 +221,13 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
children: [ children: [
AppCustomChipWidget( AppCustomChipWidget(
labelText: "${appState.getAuthenticatedUser()!.age} Years Old", labelText: "${appState.getAuthenticatedUser()!.age} Years Old",
labelPadding: EdgeInsetsDirectional.only(start: 8.w, end: 8.w),
), ),
AppCustomChipWidget( AppCustomChipWidget(
icon: AppAssets.blood_icon, icon: AppAssets.blood_icon,
labelText: "Blood: ${appState.getUserBloodGroup}", labelText: "Blood: ${appState.getUserBloodGroup.isEmpty ? "N/A" : appState.getUserBloodGroup.isEmpty}",
iconColor: AppColors.primaryRedColor, iconColor: AppColors.primaryRedColor,
labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 8.w), labelPadding: EdgeInsetsDirectional.only(end: 8.w),
), ),
Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) { Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) {
return AppCustomChipWidget( return AppCustomChipWidget(
@ -237,7 +238,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
iconSize: 12.w, iconSize: 12.w,
backgroundColor: backgroundColor:
insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor.withOpacity(0.1) : AppColors.successColor.withOpacity(0.1), insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor.withOpacity(0.1) : AppColors.successColor.withOpacity(0.1),
labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 8.w), labelPadding: EdgeInsetsDirectional.only(end: 8.w),
); );
}), }),
], ],
@ -377,7 +378,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
borderRadius: 12.r, borderRadius: 12.r,
padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0), padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0),
height: 40.h, height: isFoldable ? 50.h : 40.h,
icon: AppAssets.add_icon, icon: AppAssets.add_icon,
iconColor: AppColors.primaryRedColor, iconColor: AppColors.primaryRedColor,
), ),
@ -821,7 +822,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
borderRadius: 12.r, borderRadius: 12.r,
padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0), padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0),
height: 56.h, height: isFoldable ? 50.h : 40.h,
).paddingOnly(left: 12.w, right: 12.w, bottom: 12.h), ).paddingOnly(left: 12.w, right: 12.w, bottom: 12.h),
), ),
).paddingSymmetrical(24.w, 0.h); ).paddingSymmetrical(24.w, 0.h);
@ -863,19 +864,21 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
); );
}), }),
MedicalFileCard( MedicalFileCard(
label: "My Invoices List".needTranslation, label: "My Invoices List".needTranslation,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor, backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.eye_result_icon, svgIcon: AppAssets.eye_result_icon,
isLargeText: true, isLargeText: true,
iconSize: 36.w), iconSize: 36.w,
),
MedicalFileCard( MedicalFileCard(
label: "Ancillary Orders List".needTranslation, label: "Ancillary Orders List".needTranslation,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor, backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.eye_result_icon, svgIcon: AppAssets.eye_result_icon,
isLargeText: true, isLargeText: true,
iconSize: 36.w), iconSize: 36.w,
),
], ],
).paddingSymmetrical(24.w, 0.0), ).paddingSymmetrical(24.w, 0.0),
SizedBox(height: 16.h), SizedBox(height: 16.h),

@ -53,7 +53,7 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
left: false, left: false,
right: false, right: false,
child: Column( child: Column(
spacing: 24, spacing: 24.h,
children: [ children: [
PageView( PageView(
controller: pageController, controller: pageController,
@ -75,24 +75,24 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
}, },
).expanded, ).expanded,
Row( Row(
spacing: 4.h, spacing: 4.w,
children: [ children: [
AnimatedContainer( AnimatedContainer(
duration: const Duration(milliseconds: 250), duration: const Duration(milliseconds: 250),
height: 6.h, height: 6.h,
width: selectedIndex == 0 ? 18.h : 6.h, width: selectedIndex == 0 ? 18.w : 6.w,
decoration: decoration:
BoxDecoration(color: selectedIndex == 0 ? AppColors.textColor : AppColors.inputLabelTextColor, borderRadius: BorderRadius.circular(30)), BoxDecoration(color: selectedIndex == 0 ? AppColors.textColor : AppColors.inputLabelTextColor, borderRadius: BorderRadius.circular(30.r)),
), ),
AnimatedContainer( AnimatedContainer(
duration: const Duration(milliseconds: 250), duration: const Duration(milliseconds: 250),
height: 6.h, height: 6.h,
width: selectedIndex == 1 ? 18.h : 6.h, width: selectedIndex == 1 ? 18.w : 6.w,
decoration: decoration:
BoxDecoration(color: selectedIndex == 1 ? AppColors.textColor : AppColors.inputLabelTextColor, borderRadius: BorderRadius.circular(30)), BoxDecoration(color: selectedIndex == 1 ? AppColors.textColor : AppColors.inputLabelTextColor, borderRadius: BorderRadius.circular(30.r)),
), ),
], ],
).paddingOnly(left: 24.h, right: 24.h), ).paddingOnly(left: 24.w, right: 24.w),
Row( Row(
children: [ children: [
AnimatedSwitcher( AnimatedSwitcher(
@ -102,20 +102,20 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
? CustomButton( ? CustomButton(
text: "Skip".needTranslation, text: "Skip".needTranslation,
onPressed: () => goToHomePage(), onPressed: () => goToHomePage(),
width: 86.h, width: 86.w,
height: 56.h, height: 56.h,
backgroundColor: Color(0xffFEE9EA), backgroundColor: Color(0xffFEE9EA),
textColor: AppColors.primaryRedColor, textColor: AppColors.primaryRedColor,
borderColor: Colors.transparent, borderColor: Colors.transparent,
).paddingOnly(left: 24.h) ).paddingOnly(left: 24.w)
: const SizedBox.shrink(), : const SizedBox.shrink(),
), ),
const Spacer(), const Spacer(),
AnimatedContainer( AnimatedContainer(
duration: const Duration(milliseconds: 400), duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut, curve: Curves.easeInOut,
width: selectedIndex == 0 ? 86.h : MediaQuery.of(context).size.width - 48.h, width: selectedIndex == 0 ? 86.w : MediaQuery.of(context).size.width - 48.w,
margin: EdgeInsets.only(left: 24.h, right: 24.h), margin: EdgeInsets.only(left: 24.w, right: 24.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColors.primaryRedColor, color: AppColors.primaryRedColor,
borderRadius: BorderRadius.circular(12.r), borderRadius: BorderRadius.circular(12.r),
@ -126,8 +126,8 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
child: selectedIndex == 0 child: selectedIndex == 0
? CustomButton( ? CustomButton(
icon: getIt.get<AppState>().isArabic() ? AppAssets.arrow_back : AppAssets.arrow_forward, icon: getIt.get<AppState>().isArabic() ? AppAssets.arrow_back : AppAssets.arrow_forward,
iconSize: 32.h, iconSize: 32.w,
width: 86.h, width: 86.w,
height: 56.h, height: 56.h,
text: "".needTranslation, text: "".needTranslation,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
@ -146,7 +146,7 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
), ),
), ),
], ],
), ).paddingOnly(bottom: 10.h),
], ],
), ),
), ),
@ -157,7 +157,7 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
spacing: 12, spacing: 12.h,
children: [ children: [
Align( Align(
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
@ -167,10 +167,9 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
repeat: true, repeat: true,
reverse: false, reverse: false,
frameRate: FrameRate(60), frameRate: FrameRate(60),
width: MediaQuery.sizeOf(context).width - 50, width: MediaQuery.sizeOf(context).width - 50.w,
height: MediaQuery.sizeOf(context).width - 50))) height: MediaQuery.sizeOf(context).width - 50.w)))
.expanded, .expanded,
// 12.height,
Text( Text(
heading, heading,
style: TextStyle(fontSize: 36.f, 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),
@ -180,6 +179,6 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
style: TextStyle(fontSize: 16.f, 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.h, right: 24.h); ).paddingOnly(left: 24.w, right: 24.w);
} }
} }

@ -51,6 +51,33 @@ class _ProfileSettingsState extends State<ProfileSettings> {
super.dispose(); super.dispose();
} }
double dynamicItemHeight(BuildContext context) {
final double w = SizeUtils.width;
final double h = SizeUtils.height;
double longer = w > h ? w : h;
double shorter = w < h ? w : h;
final double aspect = longer / (shorter == 0 ? 1 : shorter);
// Choose multiplier based on aspect ratio (handles near-square / foldable)
double multiplier;
if (aspect < 1.05) {
multiplier = 0.28; // nearly square / foldable -> smaller card height
} else if (aspect > 1.8) {
multiplier = 0.40; // very tall/wide -> larger height
} else {
multiplier = 0.34; // normal phones/tablets
}
// Compute and clamp using sensible bounds (uses .h extension)
final double minH = 210.h;
final double maxH = 380.h;
final double computed = (shorter * multiplier);
return computed.clamp(minH, maxH);
}
int length = 3; int length = 3;
final SwiperController _controller = SwiperController(); final SwiperController _controller = SwiperController();
@ -72,11 +99,11 @@ class _ProfileSettingsState extends State<ProfileSettings> {
itemCount: medicalVm.patientFamilyFiles.length, itemCount: medicalVm.patientFamilyFiles.length,
layout: SwiperLayout.STACK, layout: SwiperLayout.STACK,
loop: true, loop: true,
itemWidth: SizeUtils.width - 42.w, itemHeight: dynamicItemHeight(context),
itemWidth: SizeUtils.width - 30.w,
indicatorLayout: PageIndicatorLayout.COLOR, indicatorLayout: PageIndicatorLayout.COLOR,
axisDirection: AxisDirection.right, axisDirection: AxisDirection.right,
controller: _controller, controller: _controller,
itemHeight: 220.h,
pagination: SwiperPagination( pagination: SwiperPagination(
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
margin: EdgeInsets.only(top: (210.h + 8.h + 24.h)), margin: EdgeInsets.only(top: (210.h + 8.h + 24.h)),
@ -97,13 +124,14 @@ class _ProfileSettingsState extends State<ProfileSettings> {
onFamilySwitchPress: (FamilyFileResponseModelLists profile) { onFamilySwitchPress: (FamilyFileResponseModelLists profile) {
medicalVm.switchFamilyFiles(responseID: profile.responseId, patientID: profile.patientId, phoneNumber: profile.mobileNumber); medicalVm.switchFamilyFiles(responseID: profile.responseId, patientID: profile.patientId, phoneNumber: profile.mobileNumber);
}, },
).paddingOnly(right: 16.w); ).paddingOnly(right: 16.w, left: 8.w);
}, },
), ),
SizedBox(height: 5.h),
GridView( GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 9.w, mainAxisSpacing: 9.h), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: isTablet ? 3 : 2),
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
padding: EdgeInsets.only(left: 24.w, right: 24.w, bottom: 24.w, top: 10.w), padding: EdgeInsets.only(left: 24.w, right: 24.w, bottom: 24.h),
shrinkWrap: true, shrinkWrap: true,
children: [ children: [
Container( Container(
@ -115,14 +143,14 @@ class _ProfileSettingsState extends State<ProfileSettings> {
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
spacing: 4.h, // spacing: 4.h,
children: [ children: [
Row( Row(
spacing: 8.w, spacing: 8.w,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Utils.buildSvgWithAssets(icon: AppAssets.wallet, width: 40.w, height: 40.h), Utils.buildSvgWithAssets(icon: AppAssets.wallet, width: 40.w, height: 40.h),
"Habib Wallet".needTranslation.toText14(weight: FontWeight.w600, maxlines: 2).expanded, "Habib Wallet".needTranslation.toText16(weight: FontWeight.w600, maxlines: 2).expanded,
Utils.buildSvgWithAssets(icon: AppAssets.arrow_forward), Utils.buildSvgWithAssets(icon: AppAssets.arrow_forward),
], ],
), ),
@ -131,10 +159,11 @@ class _ProfileSettingsState extends State<ProfileSettings> {
return Utils.getPaymentAmountWithSymbol2(habibWalletVM.habibWalletAmount, isExpanded: false) return Utils.getPaymentAmountWithSymbol2(habibWalletVM.habibWalletAmount, isExpanded: false)
.toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.r, width: 80.w, height: 24.h); .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.r, width: 80.w, height: 24.h);
}), }),
Spacer(),
CustomButton( CustomButton(
height: 40.h, height: 40.h,
icon: AppAssets.recharge_icon, icon: AppAssets.recharge_icon,
iconSize: 24.h, iconSize: 22.w,
iconColor: AppColors.infoColor, iconColor: AppColors.infoColor,
textColor: AppColors.infoColor, textColor: AppColors.infoColor,
text: "Recharge".needTranslation, text: "Recharge".needTranslation,
@ -152,7 +181,7 @@ class _ProfileSettingsState extends State<ProfileSettings> {
).onPress(() { ).onPress(() {
Navigator.of(context).push(CustomPageRoute(page: HabibWalletPage())); Navigator.of(context).push(CustomPageRoute(page: HabibWalletPage()));
}), }),
) ),
], ],
), ),
"Quick Actions" "Quick Actions"
@ -220,7 +249,12 @@ class _ProfileSettingsState extends State<ProfileSettings> {
], ],
), ),
), ),
CustomButton(icon: AppAssets.minus, text: "Deactivate account".needTranslation, onPressed: () {}).paddingAll(24.w), CustomButton(
height: 56.h,
icon: AppAssets.minus,
text: "Deactivate account".needTranslation,
onPressed: () {},
).paddingAll(24.w),
], ],
); );
}, },
@ -275,7 +309,11 @@ class FamilyCardWidget extends StatelessWidget {
final isParentUser = appState.getAuthenticatedUser()?.isParentUser ?? false; final isParentUser = appState.getAuthenticatedUser()?.isParentUser ?? false;
final canSwitch = isParentUser || (!isParentUser && profile.responseId == appState.getSuperUserID); final canSwitch = isParentUser || (!isParentUser && profile.responseId == appState.getSuperUserID);
return Container( return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.r, hasShadow: true), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.r,
hasShadow: true,
),
child: Column( child: Column(
children: [ children: [
Column( Column(
@ -284,7 +322,6 @@ class FamilyCardWidget extends StatelessWidget {
children: [ children: [
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
//
children: [ children: [
Image.asset(profile.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg, width: 56.w, height: 56.h), Image.asset(profile.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg, width: 56.w, height: 56.h),
Column( Column(
@ -404,7 +441,7 @@ class FamilyCardWidget extends StatelessWidget {
borderColor: canSwitch ? AppColors.secondaryLightRedColor : AppColors.primaryRedColor, borderColor: canSwitch ? AppColors.secondaryLightRedColor : AppColors.primaryRedColor,
textColor: canSwitch ? AppColors.primaryRedColor : AppColors.whiteColor, textColor: canSwitch ? AppColors.primaryRedColor : AppColors.whiteColor,
iconColor: canSwitch ? AppColors.primaryRedColor : AppColors.whiteColor, iconColor: canSwitch ? AppColors.primaryRedColor : AppColors.whiteColor,
height: 56.h, height: isFoldable ? 50.h : 40.h,
fontSize: 14.f, fontSize: 14.f,
).paddingOnly(top: 12.h, right: 16.w, left: 16.w, bottom: 16.h); ).paddingOnly(top: 12.h, right: 16.w, left: 16.w, bottom: 16.h);
} }
@ -420,7 +457,7 @@ class FamilyCardWidget extends StatelessWidget {
textColor: canSwitchBack ? AppColors.whiteColor : AppColors.greyTextColor, textColor: canSwitchBack ? AppColors.whiteColor : AppColors.greyTextColor,
iconColor: canSwitchBack ? AppColors.whiteColor : AppColors.greyTextColor, iconColor: canSwitchBack ? AppColors.whiteColor : AppColors.greyTextColor,
onPressed: canSwitchBack ? () => onFamilySwitchPress(profile) : () {}, onPressed: canSwitchBack ? () => onFamilySwitchPress(profile) : () {},
height: 40.h, height: isFoldable ? 50.h : 40.h,
fontSize: 14.f, fontSize: 14.f,
).paddingOnly(top: 12.h, right: 16.w, left: 16.w, bottom: 16.h); ).paddingOnly(top: 12.h, right: 16.w, left: 16.w, bottom: 16.h);
} }

@ -56,7 +56,7 @@ class CustomButton extends StatelessWidget {
return GestureDetector( return GestureDetector(
onTap: isDisabled ? null : onPressed, onTap: isDisabled ? null : onPressed,
child: Container( child: Container(
height: height ?? (50.h), height: height ?? (56.h),
width: width, width: width,
padding: padding, padding: padding,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(

@ -88,7 +88,7 @@ class CustomTabBarState extends State<CustomTabBar> {
bool isSelected = selectedIndex == currentIndex; bool isSelected = selectedIndex == currentIndex;
return Container( return Container(
height: 54.h, height: 54.h,
padding: EdgeInsets.only(top: 4.h, bottom: 4.h, left: 16.w, right: 16.w), padding: EdgeInsets.only(top: 4.h, bottom: 4.h, left: 14.w, right: 14.w),
alignment: Alignment.center, alignment: Alignment.center,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: isSelected ? widget.activeBackgroundColor : widget.inActiveBackgroundColor, color: isSelected ? widget.activeBackgroundColor : widget.inActiveBackgroundColor,

Loading…
Cancel
Save