UI/UX updates

haroon_dev
haroon amjad 3 days ago
parent f42fbe19ae
commit c00fe3e10c

@ -1968,5 +1968,6 @@
"notAvailable": "غير متاح",
"hide": "إخفاء",
"viewPatientQR": "عرض رمز الاستجابة السريعة للمريض",
"patientQR": "رمز الاستجابة السريعة للمريض"
"patientQR": "رمز الاستجابة السريعة للمريض",
"forText": "عن"
}

@ -1958,7 +1958,8 @@
"notAvailable": "Not Available",
"hide": "Hide",
"viewPatientQR": "View Patient QR Code",
"patientQR": "Patient QR Code"
"patientQR": "Patient QR Code",
"forText": "For"
}

@ -210,8 +210,8 @@ class ApiClientImp implements ApiClient {
body['TokenID'] = "@dm!n";
}
// body['TokenID'] = "@dm!n";
// body['PatientID'] = 2122445;
body['TokenID'] = "@dm!n";
// body['PatientID'] = 5421804;
// body['PatientID'] = 53320;
// body['PatientTypeID'] = 1;
// body['PatientOutSA'] = 0;

@ -5,7 +5,7 @@ import 'package:hmg_patient_app_new/core/enums.dart';
class ApiConsts {
static const maxSmallScreen = 660;
static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.uat;
static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod;
// static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT

@ -50,8 +50,8 @@ class AppState {
bool isPayfortHostedPageEnabled = true;
void setIsPaytabsEnabled(bool value) {
// isPaytabsEnabled = value;
isPaytabsEnabled = true;
isPaytabsEnabled = value;
// isPaytabsEnabled = true;
}
void setIsPayfortHostedPageEnabled(bool value) {

@ -420,14 +420,14 @@ class BookAppointmentsViewModel extends ChangeNotifier {
setIsNearestAppointmentSelected(bool isNearestAppointmentSelected) {
this.isNearestAppointmentSelected = isNearestAppointmentSelected;
if (isNearestAppointmentSelected) {
for (var group in doctorsListGrouped) {
group.sort((a, b) {
var aSlot = a.nearestFreeSlot;
var bSlot = b.nearestFreeSlot;
if (aSlot == null || bSlot == null) return 0;
return DateUtil.convertStringToDate(aSlot).compareTo(DateUtil.convertStringToDate(bSlot));
});
}
// for (var group in doctorsListGrouped) {
// group.sort((a, b) {
// var aSlot = a.nearestFreeSlot;
// var bSlot = b.nearestFreeSlot;
// if (aSlot == null || bSlot == null) return 0;
// return DateUtil.convertStringToDate(aSlot).compareTo(DateUtil.convertStringToDate(bSlot));
// });
// }
} else {
// for (var group in doctorsListGrouped) {
// group.sort((a, b) {

@ -1950,5 +1950,6 @@ abstract class LocaleKeys {
static const hide = 'hide';
static const viewPatientQR = 'viewPatientQR';
static const patientQR = 'patientQR';
static const forText = 'forText';
}

@ -16,6 +16,7 @@ import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/region_bottomsheet/region_list_item.dart' show RegionListItem;
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:lottie/lottie.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
@ -117,6 +118,14 @@ class _RegionBottomSheetBodyState extends State<RegionBottomSheetBody> {
height: MediaQuery.of(context).size.height * 0.5,
child: Column(
children: [
// AppCustomChipWidget(
// richText: Row(
// children: [
// "${appState.getAuthenticatedUser()!.age} ".toText10(color: AppColors.blackColor, isBold: true),
// LocaleKeys.yearsOld.tr(context: context).toText10(color: AppColors.blackColor, isBold: true),
// ],
// ),
// ),
// Consumer<AppointmentViaRegionViewmodel>(
// builder: (context, regionVM, _) {
// return Padding(

@ -1202,7 +1202,9 @@ class _SelectClinicPageState extends State<SelectClinicPage> {
getTitle(AppointmentViaRegionViewmodel data) {
if (data.selectedRegionId == null) {
return LocaleKeys.selectRegion.tr(context: context).toText20(isBold: true);
return Expanded(
child: "${LocaleKeys.selectRegion.tr(context: context)} ${LocaleKeys.forText.tr(context: context)} '${bookAppointmentsViewModel.selectedClinic.clinicDescription}'".toText20(isBold: true),
);
} else {
return Transform.flip(
flipX: data.isArabic ? true : false,

@ -57,7 +57,8 @@ class _SelectDoctorPageState extends State<SelectDoctorPage> {
} else if (bookAppointmentsViewModel.isGetDocForHealthCal) {
bookAppointmentsViewModel.getDoctorsListByHealthCal();
} else {
bookAppointmentsViewModel.getDoctorsList();
bookAppointmentsViewModel.setIsNearestAppointmentSelected(true);
bookAppointmentsViewModel.getDoctorsList(isNearest: true);
}
}
});

@ -95,7 +95,9 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
// ),
SizedBox(
height: MediaQuery.of(context).size.height * 0.45,
child: Directionality(
child: Stack(
children: [
Directionality(
textDirection: isArabic ? ui.TextDirection.rtl : ui.TextDirection.ltr,
child: Localizations.override(
context: context,
@ -104,11 +106,12 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
child: SfCalendar(
controller: _calendarController,
minDate: DateTime.now(),
showNavigationArrow: true,
// headerHeight: 60.h,
initialDisplayDate: DateUtil.convertStringToDate(bookAppointmentsViewModel.freeSlotsResponse[0]),
showNavigationArrow: false,
headerHeight: 60.h,
headerStyle: CalendarHeaderStyle(
backgroundColor: AppColors.transparent,
textAlign: isArabic ? TextAlign.end : TextAlign.start,
// textAlign: isArabic ? TextAlign.end : TextAlign.start,
textStyle: TextStyle(fontSize: 18.f, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.primaryRedColor),
),
viewHeaderStyle: ViewHeaderStyle(
@ -152,6 +155,56 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
),
),
),
),
// Custom Navigation Arrows
Positioned(
top: 0,
right: isArabic ? null : 0,
left: isArabic ? 0 : null,
child: SizedBox(
height: 60.h,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
// Previous Month Arrow
GestureDetector(
onTap: () {
setState(() {
_calendarController.backward!();
});
},
child: Container(
padding: EdgeInsets.all(8.h),
child: Icon(
// isArabic ? Icons.arrow_forward_ios : Icons.arrow_back_ios,
Icons.arrow_back_ios,
size: 24.h,
color: AppColors.primaryRedColor,
),
),
),
// Next Month Arrow
GestureDetector(
onTap: () {
setState(() {
_calendarController.forward!();
});
},
child: Container(
padding: EdgeInsets.all(8.h),
child: Icon(
// isArabic ? Icons.arrow_back_ios : Icons.arrow_forward_ios,
Icons.arrow_forward_ios,
size: 24.h,
color: AppColors.primaryRedColor,
),
),
),
],
),
),
),
],
),
),
SizedBox(height: 10.h),
@ -164,7 +217,7 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
? ClarityUnmask(
child: ConstrainedBox(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.15,
maxHeight: MediaQuery.of(context).size.height * 0.25,
minHeight: 0,
),
child: Directionality(

@ -253,8 +253,8 @@ class _LandingPageState extends State<LandingPage> {
padding: EdgeInsets.only(
top: (appState.isAuthenticated && !insuranceVM.isInsuranceLoading && insuranceVM.isInsuranceExpired && insuranceVM.isInsuranceExpiryBannerShown)
? (MediaQuery.paddingOf(context).top + 70.h)
: kToolbarHeight + 0.h,
bottom: 24),
: kToolbarHeight + 16.h,
bottom: 24.h),
child: Column(
spacing: 16.h,
children: [

@ -128,7 +128,9 @@ class LargeServiceCard extends StatelessWidget {
),
],
),
);
).onPress(() {
handleOnTap();
});
}
void handleOnTap() {
@ -275,7 +277,9 @@ class FadedLargeServiceCard extends StatelessWidget {
),
],
),
);
).onPress(() {
handleOnTap();
});
}
void handleOnTap() {

@ -41,9 +41,13 @@ class WelcomeWidget extends StatelessWidget {
borderRadius: BorderRadius.circular(30),
child: Row(
mainAxisSize: MainAxisSize.min,
spacing: 8.h,
// spacing: 8.h,
children: [
Icon(Icons.menu, color: AppColors.textColor).onPress(() {
SizedBox(
height: 40.h,
width: 20.w,
child: Icon(Icons.menu, color: AppColors.textColor),
).onPress(() {
getIt.get<ProfileSettingsViewModel>().getProfileSettings();
Navigator.of(context).push(
CustomPageRoute(
@ -92,7 +96,7 @@ class WelcomeWidget extends StatelessWidget {
],
),
],
).expanded,
).paddingOnly(left: 8.h, right: 8.h).expanded,
],
),
),

@ -6,7 +6,7 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
class CustomButton extends StatelessWidget {
class CustomButton extends StatefulWidget {
final String text;
final String? icon;
final VoidCallback? onPressed;
@ -54,25 +54,61 @@ class CustomButton extends StatelessWidget {
this.applyThemeColor = true,
});
@override
State<CustomButton> createState() => _CustomButtonState();
}
class _CustomButtonState extends State<CustomButton> with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> _scaleAnimation;
@override
void initState() {
super.initState();
_animationController = AnimationController(
duration: const Duration(milliseconds: 80),
vsync: this,
);
_scaleAnimation = Tween<double>(begin: 1.0, end: 0.95).animate(
CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
Future<void> _playTapAnimation() async {
if (!widget.isDisabled && widget.onPressed != null) {
await _animationController.forward();
_animationController.reverse();
}
}
@override
Widget build(BuildContext context) {
final radius = borderRadius ?? (12.r);
final iconS = iconSize ?? (24.h);
final fontS = fontSize ?? (16.f);
final isButtonDisabled = isDisabled || onPressed == null;
final radius = widget.borderRadius ?? (12.r);
final iconS = widget.iconSize ?? (24.h);
final fontS = widget.fontSize ?? (16.f);
final isButtonDisabled = widget.isDisabled || widget.onPressed == null;
return Semantics(
button: true,
enabled: !isButtonDisabled,
label: text,
hint: isButtonDisabled ? 'Button is disabled' : 'Tap to $text',
label: widget.text,
hint: isButtonDisabled ? 'Button is disabled' : 'Tap to ${widget.text}',
child: GestureDetector(
onTap: isButtonDisabled
? null
: () {
: () async {
// Play tap animation and wait for it to complete
await _playTapAnimation();
// Log button tap to Clarity before executing callback
try {
Clarity.setCustomTag('button_text', text.length > 100 ? text.substring(0, 100) : text);
Clarity.setCustomTag('button_text', widget.text.length > 100 ? widget.text.substring(0, 100) : widget.text);
Clarity.setCustomTag('button_action', 'tap');
Clarity.setCustomTag('button_disabled', 'false');
Clarity.sendCustomEvent('button_tapped');
@ -81,67 +117,73 @@ class CustomButton extends StatelessWidget {
}
// Execute the actual button callback
onPressed?.call();
widget.onPressed?.call();
},
child: AnimatedBuilder(
animation: _scaleAnimation,
builder: (context, child) => Transform.scale(
scale: _scaleAnimation.value,
child: child,
),
child: Container(
height: height == null
height: widget.height == null
? 56.h
: (isFoldable || isTablet)
? height! + 10.h
: height,
width: width,
padding: padding,
? widget.height! + 10.h
: widget.height,
width: widget.width,
padding: widget.padding,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: isButtonDisabled ? AppColors.inputLabelTextColor.withValues(alpha: 0.3) : backgroundColor,
color: isButtonDisabled ? AppColors.inputLabelTextColor.withValues(alpha: 0.3) : widget.backgroundColor,
borderRadius: radius,
customBorder: BorderRadius.circular(radius),
side: borderSide ?? BorderSide(width: borderWidth.h, color: isButtonDisabled ? Colors.transparent : borderColor)),
side: widget.borderSide ?? BorderSide(width: widget.borderWidth.h, color: isButtonDisabled ? Colors.transparent : widget.borderColor)),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (icon != null)
if (widget.icon != null)
Padding(
padding: text.isNotEmpty ? EdgeInsets.only(right: 6.w, left: 6.w) : EdgeInsets.zero,
padding: widget.text.isNotEmpty ? EdgeInsets.only(right: 6.w, left: 6.w) : EdgeInsets.zero,
child: Utils.buildSvgWithAssets(
icon: icon!,
iconColor: isButtonDisabled ? AppColors.greyTextColor : iconColor,
icon: widget.icon!,
iconColor: isButtonDisabled ? AppColors.greyTextColor : widget.iconColor,
isDisabled: isButtonDisabled,
width: iconS,
height: iconS,
applyThemeColor: applyThemeColor),
applyThemeColor: widget.applyThemeColor),
),
if (text.isNotEmpty && icon != null)
if (widget.text.isNotEmpty && widget.icon != null)
Flexible(
child: Text(
text,
overflow: textOverflow ?? TextOverflow.ellipsis,
widget.text,
overflow: widget.textOverflow ?? TextOverflow.ellipsis,
maxLines: 1,
textAlign: TextAlign.center,
style: context.dynamicTextStyle(
fontSize: fontS,
color: isButtonDisabled ? AppColors.greyTextColor : textColor,
color: isButtonDisabled ? AppColors.greyTextColor : widget.textColor,
letterSpacing: 0,
fontWeight: isBold ? FontWeight.w700 : fontWeight,
fontWeight: widget.isBold ? FontWeight.w700 : widget.fontWeight,
),
),
),
if (text.isNotEmpty && icon == null)
if (widget.text.isNotEmpty && widget.icon == null)
Text(
text,
overflow: textOverflow ?? TextOverflow.ellipsis,
widget.text,
overflow: widget.textOverflow ?? TextOverflow.ellipsis,
maxLines: 1,
textAlign: TextAlign.center,
style: context.dynamicTextStyle(
fontSize: fontS,
color: isButtonDisabled ? AppColors.greyTextColor : textColor,
color: isButtonDisabled ? AppColors.greyTextColor : widget.textColor,
letterSpacing: 0,
fontWeight: isBold ? FontWeight.w700 : fontWeight,
fontWeight: widget.isBold ? FontWeight.w700 : widget.fontWeight,
),
),
],
),
)),
);
));
}
}

Loading…
Cancel
Save