Design changes

pull/88/head
faizatflutter 1 week ago
parent f508d441e2
commit 8c956fc052

@ -11,23 +11,108 @@ extension ResponsiveExtension on num {
double get _screenHeight => SizeUtils.height;
/// Scale text size
/// Check if device is likely a foldable
bool get _isFoldable {
double aspectRatio = _screenWidth / _screenHeight;
// Foldable devices typically have aspect ratios close to 1:1 when unfolded
return (aspectRatio > 0.9 && aspectRatio < 1.1) && (_screenWidth > 700 || _screenHeight > 700);
}
/// Scale text size - enhanced for foldable devices
double get f {
double aspectRatio = _screenWidth / _screenHeight;
double scale = (_screenWidth < _screenHeight ? _screenWidth : _screenHeight) / figmaDesignWidth;
double clamp = (aspectRatio > 1.3 || aspectRatio < 0.77) ? 1.6 : 1.2;
// 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;
}
/// Scale horizontally (width-based)
double get w => (this * _screenWidth) / figmaDesignWidth;
/// Scale horizontally (width-based) - enhanced for foldable devices
double get w {
double baseScale = (this * _screenWidth) / figmaDesignWidth;
/// Scale vertically (height-based)
double get h => (this * _screenHeight) / figmaDesignHeight;
if (_isFoldable) {
// For foldables, use more conservative width scaling
double scale = _screenWidth / figmaDesignWidth;
scale = scale.clamp(0.8, 1.4);
return this * scale;
}
//radius
double get r => (this * _screenWidth) / figmaDesignWidth;
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
static double get screenWidth => SizeUtils.width;
@ -129,6 +214,7 @@ class SizeUtils {
}
log("longerSide: $longerSide");
log("shorterSide: $shorterSide");
log("isTablet: $isTablet");
}
}
@ -139,3 +225,9 @@ bool get isTablet => SizeUtils.deviceType == DeviceType.tablet;
bool get isMobile => SizeUtils.deviceType == DeviceType.mobile;
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 Color iconColor,
bool isDisabled = false,
double width = 24,
double height = 24,
double? width,
double? height,
}) {
final iconH = height ?? 24.h;
final iconW = width ?? 24.w;
return SvgPicture.network(
url,
colorFilter: ColorFilter.mode(
isDisabled ? iconColor.withOpacity(0.5) : iconColor,
BlendMode.srcIn,
),
width: width,
height: height,
width: iconW,
height: iconH,
);
}
@ -662,7 +664,7 @@ class Utils {
return Container(
decoration: BoxDecoration(
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),
);
@ -670,17 +672,27 @@ class Utils {
}
/// 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(
url,
width: width,
height: height,
width: iconW,
height: iconH,
fit: fit,
errorBuilder: errorBuilder??(_,__,___){
//todo change the error builder icon that it is returning
return Utils.buildSvgWithAssets(width: width,
height: height,icon: AppAssets.no_visit_icon);
},
errorBuilder: errorBuilder ??
(_, __, ___) {
//todo change the error builder icon that it is returning
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),
);
Widget toText14(
{Color? color,
bool isUnderLine = false,
bool isBold = false,
bool isCenter = false,
FontWeight? weight,
int? maxlines,
double? letterSpacing = 0,
double? height,
TextOverflow? textOverflow}) =>
Widget toText14({
Color? color,
bool isUnderLine = false,
bool isBold = false,
bool isCenter = false,
FontWeight? weight,
int? maxlines,
double? letterSpacing = 0,
double? height,
TextOverflow? textOverflow,
}) =>
Text(
this,
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/appointment_card.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/widgets/appbar/collapsing_list_view.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/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/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
import 'package:provider/provider.dart';
import '../../widgets/common_bottom_sheet.dart'
show showCommonBottomSheetWithoutHeight;
import '../../widgets/common_bottom_sheet.dart' show showCommonBottomSheetWithoutHeight;
class MyAppointmentsPage extends StatefulWidget {
const MyAppointmentsPage({super.key});
@ -86,18 +84,14 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
}
Widget getSelectedTabData(int index, MyAppointmentsViewModel myAppointmentsVM) {
return getAppointList(
myAppointmentsVM, myAppointmentsVM.filteredAppointmentList);
return getAppointList(myAppointmentsVM, myAppointmentsVM.filteredAppointmentList);
}
Widget getAppointList(MyAppointmentsViewModel myAppointmentsVM,
List<PatientAppointmentHistoryResponseModel> filteredAppointmentList) {
Widget getAppointList(MyAppointmentsViewModel myAppointmentsVM, List<PatientAppointmentHistoryResponseModel> filteredAppointmentList) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Visibility(
visible: myAppointmentsVM.availableFilters.isNotEmpty,
child: getAppointmentFilters(myAppointmentsVM)),
Visibility(visible: myAppointmentsVM.availableFilters.isNotEmpty, child: getAppointmentFilters(myAppointmentsVM)),
ListView.separated(
padding: EdgeInsets.only(top: 24.h),
shrinkWrap: true,
@ -110,14 +104,9 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
itemBuilder: (context, index) {
return myAppointmentsVM.isMyAppointmentsLoading
? 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:
PatientAppointmentHistoryResponseModel(),
patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel(),
myAppointmentsViewModel: myAppointmentsViewModel,
bookAppointmentsViewModel: bookAppointmentsViewModel,
isLoading: true,
@ -134,16 +123,10 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
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: AppointmentCard(
patientAppointmentHistoryResponseModel:
filteredAppointmentList[index],
myAppointmentsViewModel:
myAppointmentsViewModel,
patientAppointmentHistoryResponseModel: filteredAppointmentList[index],
myAppointmentsViewModel: myAppointmentsViewModel,
bookAppointmentsViewModel: bookAppointmentsViewModel,
isLoading: false,
isFromHomePage: false,
@ -154,8 +137,7 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
)
: Utils.getNoDataWidget(
context,
noDataText: "You don't have any appointments yet."
.needTranslation,
noDataText: "You don't have any appointments yet.".needTranslation,
callToActionButton: CustomButton(
text: LocaleKeys.bookAppo.tr(context: context),
onPressed: () {
@ -168,18 +150,17 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
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,
borderRadius: 12.r,
padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0),
height: 40.h,
icon: AppAssets.add_icon,
iconColor: AppColors.primaryRedColor,
).paddingSymmetrical(48.h, 0.h),
);
},
separatorBuilder: (BuildContext cxt, int index) =>
SizedBox(height: 16.h),
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
),
SizedBox(height: 24.h),
],
@ -189,45 +170,41 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
Widget getAppointmentFilters(MyAppointmentsViewModel myAppointmentsVM) {
return SizedBox(
child: Row(
children: [
Expanded(
child: ListView.separated(
separatorBuilder: (_, index) => SizedBox(
width: 8.h,
),
scrollDirection: Axis.horizontal,
itemCount: myAppointmentsVM.availableFilters.length,
itemBuilder: (_, index) => AppointmentFilters(
selectedFilter: myAppointmentsVM.selectedFilter,
item: myAppointmentsVM.availableFilters[index],
onClicked: () {
if (myAppointmentsVM.availableFilters[index] ==
AppointmentListingFilters.DATESELECTION) {
showCommonBottomSheetWithoutHeight(
title: "Set The Date Range".needTranslation,
context,
child: DateRangeSelector(
onRangeSelected: (start, end) {
// if (start != null) {
myAppointmentsVM.getSelectedDateRange(
start, end);
// }
},
),
isFullScreen: false,
isCloseButtonVisible: true,
callBackFunc: () {},
);
} else {
myAppointmentsVM.setSelectedFilter(
myAppointmentsVM.availableFilters[index]);
myAppointmentsVM.filterTheListAsPerSelection();
}
},
)),
),
],
)).paddingOnly(top: 24.h, left: 24.h, right: 24.h);
children: [
Expanded(
child: ListView.separated(
separatorBuilder: (_, index) => SizedBox(
width: 8.h,
),
scrollDirection: Axis.horizontal,
itemCount: myAppointmentsVM.availableFilters.length,
itemBuilder: (_, index) => AppointmentFilters(
selectedFilter: myAppointmentsVM.selectedFilter,
item: myAppointmentsVM.availableFilters[index],
onClicked: () {
if (myAppointmentsVM.availableFilters[index] == AppointmentListingFilters.DATESELECTION) {
showCommonBottomSheetWithoutHeight(
title: "Set The Date Range".needTranslation,
context,
child: DateRangeSelector(
onRangeSelected: (start, end) {
// if (start != null) {
myAppointmentsVM.getSelectedDateRange(start, end);
// }
},
),
isFullScreen: false,
isCloseButtonVisible: true,
callBackFunc: () {},
);
} else {
myAppointmentsVM.setSelectedFilter(myAppointmentsVM.availableFilters[index]);
myAppointmentsVM.filterTheListAsPerSelection();
}
},
)),
),
],
)).paddingOnly(top: 24.h, left: 24.h, right: 24.h);
}
}

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

@ -26,40 +26,37 @@ class LargeServiceCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Padding(
return Container(
width: 150.w,
padding: EdgeInsets.symmetric(horizontal: 3.w),
child: Container(
width: 150.w,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: Colors.transparent, borderRadius: 16.r),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.asset(AppAssets.livecare_service, width: 220.w, height: 220.h, fit: BoxFit.contain),
SizedBox(height: 3.h),
Row(
children: [
Utils.buildSvgWithAssets(icon: icon, width: 24.w, height: 24.h),
title.toText14(color: AppColors.blackColor, isBold: true),
],
),
subtitle.toText11(color: AppColors.blackColor),
SizedBox(height: 10.h),
CustomButton(
width: 150.w,
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,
),
],
),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: Colors.transparent, borderRadius: 16.r),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.asset(AppAssets.livecare_service, width: 220.w, fit: BoxFit.contain),
SizedBox(height: 10.h),
Row(
children: [
Utils.buildSvgWithAssets(icon: icon, width: 24.w, height: 24.h),
Flexible(child: title.toText14(color: AppColors.blackColor, isBold: true, textOverflow: TextOverflow.clip, maxlines: 1)),
],
),
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: [
AppCustomChipWidget(
labelText: "${appState.getAuthenticatedUser()!.age} Years Old",
labelPadding: EdgeInsetsDirectional.only(start: 8.w, end: 8.w),
),
AppCustomChipWidget(
icon: AppAssets.blood_icon,
labelText: "Blood: ${appState.getUserBloodGroup}",
labelText: "Blood: ${appState.getUserBloodGroup.isEmpty ? "N/A" : appState.getUserBloodGroup.isEmpty}",
iconColor: AppColors.primaryRedColor,
labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 8.w),
labelPadding: EdgeInsetsDirectional.only(end: 8.w),
),
Consumer<InsuranceViewModel>(builder: (context, insuranceVM, child) {
return AppCustomChipWidget(
@ -237,7 +238,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
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),
labelPadding: EdgeInsetsDirectional.only(end: 8.w),
);
}),
],
@ -377,7 +378,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0),
height: 40.h,
height: isFoldable ? 50.h : 40.h,
icon: AppAssets.add_icon,
iconColor: AppColors.primaryRedColor,
),
@ -821,7 +822,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
fontWeight: FontWeight.w500,
borderRadius: 12.r,
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),
),
).paddingSymmetrical(24.w, 0.h);
@ -863,19 +864,21 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
);
}),
MedicalFileCard(
label: "My Invoices List".needTranslation,
textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.eye_result_icon,
isLargeText: true,
iconSize: 36.w),
label: "My Invoices List".needTranslation,
textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.eye_result_icon,
isLargeText: true,
iconSize: 36.w,
),
MedicalFileCard(
label: "Ancillary Orders List".needTranslation,
textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.eye_result_icon,
isLargeText: true,
iconSize: 36.w),
label: "Ancillary Orders List".needTranslation,
textColor: AppColors.blackColor,
backgroundColor: AppColors.whiteColor,
svgIcon: AppAssets.eye_result_icon,
isLargeText: true,
iconSize: 36.w,
),
],
).paddingSymmetrical(24.w, 0.0),
SizedBox(height: 16.h),

@ -53,7 +53,7 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
left: false,
right: false,
child: Column(
spacing: 24,
spacing: 24.h,
children: [
PageView(
controller: pageController,
@ -75,24 +75,24 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
},
).expanded,
Row(
spacing: 4.h,
spacing: 4.w,
children: [
AnimatedContainer(
duration: const Duration(milliseconds: 250),
height: 6.h,
width: selectedIndex == 0 ? 18.h : 6.h,
width: selectedIndex == 0 ? 18.w : 6.w,
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(
duration: const Duration(milliseconds: 250),
height: 6.h,
width: selectedIndex == 1 ? 18.h : 6.h,
width: selectedIndex == 1 ? 18.w : 6.w,
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(
children: [
AnimatedSwitcher(
@ -102,20 +102,20 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
? CustomButton(
text: "Skip".needTranslation,
onPressed: () => goToHomePage(),
width: 86.h,
width: 86.w,
height: 56.h,
backgroundColor: Color(0xffFEE9EA),
textColor: AppColors.primaryRedColor,
borderColor: Colors.transparent,
).paddingOnly(left: 24.h)
).paddingOnly(left: 24.w)
: const SizedBox.shrink(),
),
const Spacer(),
AnimatedContainer(
duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut,
width: selectedIndex == 0 ? 86.h : MediaQuery.of(context).size.width - 48.h,
margin: EdgeInsets.only(left: 24.h, right: 24.h),
width: selectedIndex == 0 ? 86.w : MediaQuery.of(context).size.width - 48.w,
margin: EdgeInsets.only(left: 24.w, right: 24.w),
decoration: BoxDecoration(
color: AppColors.primaryRedColor,
borderRadius: BorderRadius.circular(12.r),
@ -126,8 +126,8 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
child: selectedIndex == 0
? CustomButton(
icon: getIt.get<AppState>().isArabic() ? AppAssets.arrow_back : AppAssets.arrow_forward,
iconSize: 32.h,
width: 86.h,
iconSize: 32.w,
width: 86.w,
height: 56.h,
text: "".needTranslation,
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(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 12,
spacing: 12.h,
children: [
Align(
alignment: Alignment.bottomCenter,
@ -167,10 +167,9 @@ class _OnboardingScreenState extends State<OnboardingScreen> {
repeat: true,
reverse: false,
frameRate: FrameRate(60),
width: MediaQuery.sizeOf(context).width - 50,
height: MediaQuery.sizeOf(context).width - 50)))
width: MediaQuery.sizeOf(context).width - 50.w,
height: MediaQuery.sizeOf(context).width - 50.w)))
.expanded,
// 12.height,
Text(
heading,
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),
),
],
).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();
}
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;
final SwiperController _controller = SwiperController();
@ -72,11 +99,11 @@ class _ProfileSettingsState extends State<ProfileSettings> {
itemCount: medicalVm.patientFamilyFiles.length,
layout: SwiperLayout.STACK,
loop: true,
itemWidth: SizeUtils.width - 42.w,
itemHeight: dynamicItemHeight(context),
itemWidth: SizeUtils.width - 30.w,
indicatorLayout: PageIndicatorLayout.COLOR,
axisDirection: AxisDirection.right,
controller: _controller,
itemHeight: 220.h,
pagination: SwiperPagination(
alignment: Alignment.bottomCenter,
margin: EdgeInsets.only(top: (210.h + 8.h + 24.h)),
@ -97,13 +124,14 @@ class _ProfileSettingsState extends State<ProfileSettings> {
onFamilySwitchPress: (FamilyFileResponseModelLists profile) {
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(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 9.w, mainAxisSpacing: 9.h),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: isTablet ? 3 : 2),
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,
children: [
Container(
@ -115,14 +143,14 @@ class _ProfileSettingsState extends State<ProfileSettings> {
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 4.h,
// spacing: 4.h,
children: [
Row(
spacing: 8.w,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
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),
],
),
@ -131,10 +159,11 @@ class _ProfileSettingsState extends State<ProfileSettings> {
return Utils.getPaymentAmountWithSymbol2(habibWalletVM.habibWalletAmount, isExpanded: false)
.toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.r, width: 80.w, height: 24.h);
}),
Spacer(),
CustomButton(
height: 40.h,
icon: AppAssets.recharge_icon,
iconSize: 24.h,
iconSize: 22.w,
iconColor: AppColors.infoColor,
textColor: AppColors.infoColor,
text: "Recharge".needTranslation,
@ -152,7 +181,7 @@ class _ProfileSettingsState extends State<ProfileSettings> {
).onPress(() {
Navigator.of(context).push(CustomPageRoute(page: HabibWalletPage()));
}),
)
),
],
),
"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 canSwitch = isParentUser || (!isParentUser && profile.responseId == appState.getSuperUserID);
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(
children: [
Column(
@ -284,7 +322,6 @@ class FamilyCardWidget extends StatelessWidget {
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
//
children: [
Image.asset(profile.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg, width: 56.w, height: 56.h),
Column(
@ -404,7 +441,7 @@ class FamilyCardWidget extends StatelessWidget {
borderColor: canSwitch ? AppColors.secondaryLightRedColor : AppColors.primaryRedColor,
textColor: canSwitch ? AppColors.primaryRedColor : AppColors.whiteColor,
iconColor: canSwitch ? AppColors.primaryRedColor : AppColors.whiteColor,
height: 56.h,
height: isFoldable ? 50.h : 40.h,
fontSize: 14.f,
).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,
iconColor: canSwitchBack ? AppColors.whiteColor : AppColors.greyTextColor,
onPressed: canSwitchBack ? () => onFamilySwitchPress(profile) : () {},
height: 40.h,
height: isFoldable ? 50.h : 40.h,
fontSize: 14.f,
).paddingOnly(top: 12.h, right: 16.w, left: 16.w, bottom: 16.h);
}

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

@ -88,7 +88,7 @@ class CustomTabBarState extends State<CustomTabBar> {
bool isSelected = selectedIndex == currentIndex;
return Container(
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,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: isSelected ? widget.activeBackgroundColor : widget.inActiveBackgroundColor,

Loading…
Cancel
Save