Merge branch 'dev_aamir' of http://34.17.52.180/Haroon6138/HMG_Patient_App_New into dev_sultan

# Conflicts:
#	lib/core/api_consts.dart
#	lib/presentation/medical_file/medical_file_page.dart
pull/56/head
Sultan khan 1 month ago
commit 4d52987c83

@ -0,0 +1,4 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.8333 3.99984C15.8333 3.26346 16.4303 2.6665 17.1667 2.6665H29.1667C29.903 2.6665 30.5 3.26346 30.5 3.99984C30.5 4.73622 29.903 5.33317 29.1667 5.33317L29.1667 23.3332C29.1667 26.6469 26.4804 29.3332 23.1667 29.3332C19.853 29.3332 17.1667 26.6469 17.1667 23.3332L17.1667 9.33405C17.1667 9.33376 17.1667 9.33434 17.1667 9.33405C17.1667 9.33376 17.1667 9.33259 17.1667 9.33229V5.33317C16.4303 5.33317 15.8333 4.73622 15.8333 3.99984ZM19.8333 7.99984V5.33317H26.5L26.5 13.0676C26.1378 13.317 25.8055 13.5125 25.4733 13.6324C25.0059 13.8012 24.5708 13.8095 24.0425 13.4925C22.6945 12.6837 21.4241 12.879 20.3715 13.4052C20.1897 13.4961 20.0098 13.5996 19.8333 13.7111V10.6665H22.5C23.2364 10.6665 23.8333 10.0695 23.8333 9.33317C23.8333 8.59679 23.2364 7.99984 22.5 7.99984H19.8333Z" fill="#2E3039"/>
<path d="M7.14104 12.6116C7.52794 12.2404 8.13873 12.2404 8.52562 12.6116L8.53329 12.6193C8.69353 12.7817 9.1478 13.2422 9.40228 13.5185C9.91854 14.0791 10.6087 14.8721 11.3012 15.7994C11.9917 16.7239 12.6985 17.8007 13.2361 18.9287C13.7693 20.0478 14.1667 21.2805 14.1667 22.4998C14.1667 24.7601 13.4124 26.4319 12.1558 27.5235C10.9246 28.5931 9.33325 28.9998 7.83333 28.9998C6.33342 28.9998 4.74203 28.5931 3.51084 27.5235C2.25425 26.4319 1.5 24.7601 1.5 22.4998C1.5 21.2805 1.89732 20.0478 2.4306 18.9287C2.96813 17.8007 3.67498 16.7239 4.36544 15.7994C5.05795 14.8721 5.74813 14.0791 6.26439 13.5185C6.51888 13.2422 6.97318 12.7817 7.1334 12.6193L7.14104 12.6116Z" fill="#2E3039"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -847,5 +847,8 @@
"pleaseSelectAMaritalStatus": "يرجى اختيار الحالة الاجتماعية", "pleaseSelectAMaritalStatus": "يرجى اختيار الحالة الاجتماعية",
"pleaseSelectACountry": "يرجى اختيار الدولة", "pleaseSelectACountry": "يرجى اختيار الدولة",
"pleaseEnterEmail": "يرجى إدخال البريد الإلكتروني", "pleaseEnterEmail": "يرجى إدخال البريد الإلكتروني",
"pleaseEnterAValidEmailFormat": "يرجى إدخال تنسيق بريد إلكتروني صالح" "pleaseEnterAValidEmailFormat": "يرجى إدخال تنسيق بريد إلكتروني صالح",
"selectCountry": "اختر الدولة",
"forLoginVerification": "للتحقق من تسجيل الدخول"
} }

@ -803,7 +803,6 @@
"loginByOTP": "Login By OTP", "loginByOTP": "Login By OTP",
"guest": "Guest", "guest": "Guest",
"switchAccount": "Switch Account", "switchAccount": "Switch Account",
"lastloginBy": "Last login by",
"allSet": "All Set! Now you can login with Face ID or Biometric", "allSet": "All Set! Now you can login with Face ID or Biometric",
"enableQuickLogin": "Enable Quick Login", "enableQuickLogin": "Enable Quick Login",
"enableMsg": "Enabling the quick login will verify through your existing device Face ID / Biometric", "enableMsg": "Enabling the quick login will verify through your existing device Face ID / Biometric",
@ -843,6 +842,8 @@
"pleaseSelectAMaritalStatus": "Please select a marital status", "pleaseSelectAMaritalStatus": "Please select a marital status",
"pleaseSelectACountry": "Please select a country", "pleaseSelectACountry": "Please select a country",
"pleaseEnterEmail": "Please enter email", "pleaseEnterEmail": "Please enter email",
"pleaseEnterAValidEmailFormat": "Please enter a valid email format" "pleaseEnterAValidEmailFormat": "Please enter a valid email format",
"selectCountry": "Select Country",
"forLoginVerification": "for login verification",
"lastLoginBy": "Last login by"
} }

@ -176,8 +176,8 @@ class ApiClientImp implements ApiClient {
body[_appState.isAuthenticated ? 'TokenID' : 'LogInTokenID'] = _appState.appAuthToken; body[_appState.isAuthenticated ? 'TokenID' : 'LogInTokenID'] = _appState.appAuthToken;
} }
// body['TokenID'] = "@dm!n"; body['TokenID'] = "@dm!n";
// body['PatientID'] = "4767477"; body['PatientID'] = 3628599;
} }
body.removeWhere((key, value) => value == null); body.removeWhere((key, value) => value == null);

@ -131,6 +131,7 @@ class AppAssets {
static const String smart_phone_fill = '$svgBasePath/smart_phone_fill.svg'; static const String smart_phone_fill = '$svgBasePath/smart_phone_fill.svg';
static const String touch_face_id = '$svgBasePath/touch_face_id.svg'; static const String touch_face_id = '$svgBasePath/touch_face_id.svg';
static const String minus = '$svgBasePath/minus.svg'; static const String minus = '$svgBasePath/minus.svg';
static const String home_lab_result_icon = '$svgBasePath/home_lab_result_icon.svg';
//bottom navigation// //bottom navigation//
static const String homeBottom = '$svgBasePath/home_bottom.svg'; static const String homeBottom = '$svgBasePath/home_bottom.svg';

@ -133,5 +133,10 @@ class AppState {
_userRegistrationPayload = value; _userRegistrationPayload = value;
} }
///this will be called if there is any problem in getting the user location
void resetLocation(){
userLong = 0.0;
userLong = 0.0;
}
} }

@ -158,7 +158,8 @@ class AppDependencies {
bookAppointmentsRepo: getIt(), bookAppointmentsRepo: getIt(),
errorHandlerService: getIt(), errorHandlerService: getIt(),
navigationService: getIt(), navigationService: getIt(),
myAppointmentsViewModel: getIt() myAppointmentsViewModel: getIt(),
locationUtils: getIt()
), ),
); );

@ -1,12 +1,23 @@
import 'dart:io'; import 'dart:io';
import 'dart:ui';
import 'package:geolocator/geolocator.dart'; import 'package:geolocator/geolocator.dart';
import 'package:gms_check/gms_check.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart'; import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:huawei_location/huawei_location.dart' as HmsLocation
show
FusedLocationProviderClient,
Location,
LocationSettingsRequest,
LocationRequest;
import 'package:location/location.dart'
show Location, PermissionStatus, LocationData;
import 'package:permission_handler/permission_handler.dart'
show Permission, PermissionListActions, PermissionStatusGetters;
class LocationUtils { class LocationUtils {
NavigationService navigationService; NavigationService navigationService;
@ -16,6 +27,7 @@ class LocationUtils {
bool isShowLocationTimeoutDialog; bool isShowLocationTimeoutDialog;
bool isHuawei; bool isHuawei;
final GeolocatorPlatform _geolocatorPlatform = GeolocatorPlatform.instance; final GeolocatorPlatform _geolocatorPlatform = GeolocatorPlatform.instance;
Future<bool?>? isGMSDevice;
LocationUtils({ LocationUtils({
required this.isShowConfirmDialog, required this.isShowConfirmDialog,
@ -23,49 +35,62 @@ class LocationUtils {
required this.appState, required this.appState,
this.isHuawei = false, this.isHuawei = false,
this.isShowLocationTimeoutDialog = true, this.isShowLocationTimeoutDialog = true,
}); }) {
isGMSDevice = GmsCheck().checkGmsAvailability();
void getCurrentLocation({Function(LatLng)? callBack}) async { }
Geolocator.isLocationServiceEnabled().then((value) async {
if (value) {
await Geolocator.checkPermission().then((permission) async {
if (permission == LocationPermission.always || permission == LocationPermission.whileInUse) {
Geolocator.getLastKnownPosition().then((value) {
setLocation(value);
if (callBack != null) callBack(LatLng(value?.latitude ?? 24.7101433, value?.longitude ?? 46.6757709));
}).catchError((err) {
if (isShowConfirmDialog && isShowLocationTimeoutDialog) {}
});
}
if (permission == LocationPermission.denied || permission == LocationPermission.deniedForever) { void getLocation(
if (Platform.isAndroid) { {Function(LatLng)? onSuccess, VoidCallback? onFailure}) async {
// Utils.showPermissionConsentDialog(context, TranslationBase.of(context).locationPermissionDialog, () async { if (Platform.isIOS) {
final hasPermission = await _handlePermission(); getCurrentLocation(onFailure: onFailure, onSuccess: onSuccess);
if (hasPermission) { return;
// Geolocator.getCurrentPosition(locationSettings: LocationSettings(accuracy: LocationAccuracy.medium, timeLimit: Duration(seconds: 5))).then((value) { }
Geolocator.getLastKnownPosition().then((value) {
setLocation(value); if (await isGMSDevice ?? true) {
if (callBack != null) callBack(LatLng(value?.latitude ?? 24.7101433, value?.longitude ?? 46.6757709)); getCurrentLocation(onFailure: onFailure, onSuccess: onSuccess);
}); return;
} else { }
// if (isShowConfirmDialog) showErrorLocationDialog(false, failureCallBack: () {});
} getHMSLocation(onFailure: onFailure, onSuccess: onSuccess);
// }); }
} else {
if (await Permission.location.request().isGranted) { void getCurrentLocation(
getCurrentLocation(callBack: callBack); {Function(LatLng)? onSuccess, VoidCallback? onFailure}) async {
} else { var location = Location();
setZeroLocation();
if (isShowConfirmDialog) showErrorLocationDialog(false, failureCallBack: () {}); bool isLocationEnabled = await location.serviceEnabled();
} //if the location service is not enabled, ask the user to enable it
} if (!isLocationEnabled) {
} isLocationEnabled = await location.requestService();
}).catchError((err) {}); if (!isLocationEnabled) {
} else { appState.resetLocation();
if (isShowConfirmDialog) showErrorLocationDialog(false, failureCallBack: () {}); onFailure?.call();
return;
}
}
LocationPermission permissionGranted = await Geolocator.checkPermission();
if (permissionGranted == LocationPermission.denied) {
permissionGranted = await Geolocator.requestPermission();
if (permissionGranted != LocationPermission.whileInUse &&
permissionGranted != LocationPermission.always) {
appState.resetLocation();
onFailure?.call();
return;
} }
}).catchError((err) {}); }
Position? currentLocation = await Geolocator.getLastKnownPosition();
if(currentLocation?.latitude == null || currentLocation?.longitude == null){
currentLocation = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.low);
}
LatLng locationData = LatLng(
currentLocation?.latitude ?? 0.0, currentLocation?.longitude ?? 0.0);
saveLatLngToAppState(locationData);
onSuccess?.call(locationData);
} }
Future<bool> checkIfGPSIsEnabled() async { Future<bool> checkIfGPSIsEnabled() async {
@ -166,4 +191,75 @@ class LocationUtils {
].request(); ].request();
return (result[Permission.location]!.isGranted || result[Permission.locationAlways]!.isGranted); return (result[Permission.location]!.isGranted || result[Permission.locationAlways]!.isGranted);
} }
void saveLatLngToAppState(LatLng locationData) {
appState.userLat = locationData.latitude;
appState.userLong = locationData.longitude;
}
void getHMSLocation(
{VoidCallback? onFailure, Function(LatLng p1)? onSuccess}) async {
try {
var location = Location();
HmsLocation.FusedLocationProviderClient locationService =
HmsLocation.FusedLocationProviderClient()..initFusedLocationService();
bool isLocationEnabled = await Geolocator.isLocationServiceEnabled();
//if the location service is not enabled, ask the user to enable it
if (!isLocationEnabled) {
HmsLocation.LocationRequest locationRequest =
HmsLocation.LocationRequest()
..priority = HmsLocation.LocationRequest.PRIORITY_HIGH_ACCURACY;
HmsLocation.LocationSettingsRequest request =
HmsLocation.LocationSettingsRequest(
alwaysShow: true,
needBle: false,
requests: [locationRequest],
);
await locationService.checkLocationSettings(request);
}
LocationPermission permissionGranted = await Geolocator.checkPermission();
if (permissionGranted == LocationPermission.denied) {
permissionGranted = await Geolocator.requestPermission();
if (permissionGranted != LocationPermission.whileInUse &&
permissionGranted != LocationPermission.always) {
appState.resetLocation();
onFailure?.call();
return;
}
}
HmsLocation.Location data = await locationService.getLastLocation();
if (data.latitude == null || data.longitude == null) {
appState.resetLocation();
HmsLocation.LocationRequest request = HmsLocation.LocationRequest()
..priority = HmsLocation.LocationRequest.PRIORITY_HIGH_ACCURACY
..interval = 1000 // 1 second
..numUpdates = 1;
locationService.requestLocationUpdates(request);
locationService.onLocationData?.listen((location) {
data = location;
if (data.latitude == null || data.longitude == null) {
appState.resetLocation();
onFailure?.call();
return;
}
var locationData =
LatLng(data.latitude ?? 0.0, data.longitude ?? 0.0);
saveLatLngToAppState(locationData);
onSuccess?.call(locationData);
});
} else {
var locationData = LatLng(data.latitude ?? 0.0, data.longitude ?? 0.0);
saveLatLngToAppState(locationData);
onSuccess?.call(locationData);
}
} catch (e) {
appState.resetLocation();
onFailure?.call();
}
}
} }

@ -346,9 +346,9 @@ class Utils {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Lottie.asset(AppAnimations.warningAnimation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill), Lottie.asset(AppAnimations.warningAnimation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 128.h, height: 128.h, fit: BoxFit.fill),
SizedBox(height: 8.h), SizedBox(height: 8.h),
(loadingText ?? LocaleKeys.loadingText.tr()).toText14(color: AppColors.blackColor), (loadingText ?? LocaleKeys.loadingText.tr()).toText14(color: AppColors.blackColor, letterSpacing: 0),
SizedBox(height: 16.h), SizedBox(height: 16.h),
isShowActionButtons isShowActionButtons
? Row( ? Row(
@ -361,11 +361,11 @@ class Utils {
onCancelTap(); onCancelTap();
} }
}, },
backgroundColor: AppColors.secondaryLightRedColor, backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.secondaryLightRedColor, borderColor: AppColors.primaryRedColor,
textColor: AppColors.primaryRedColor, textColor: AppColors.whiteColor,
icon: AppAssets.cancel, icon: AppAssets.cancel,
iconColor: AppColors.primaryRedColor, iconColor: AppColors.whiteColor,
), ),
), ),
SizedBox(width: 8.h), SizedBox(width: 8.h),
@ -652,6 +652,7 @@ class Utils {
static Widget getPaymentAmountWithSymbol2(num habibWalletAmount, Color iconColor, double iconSize, {bool isSaudiCurrency = true, bool isExpanded = true}) { static Widget getPaymentAmountWithSymbol2(num habibWalletAmount, Color iconColor, double iconSize, {bool isSaudiCurrency = true, bool isExpanded = true}) {
return RichText( return RichText(
maxLines: 1,
text: TextSpan( text: TextSpan(
children: [ children: [
WidgetSpan( WidgetSpan(

@ -30,12 +30,11 @@ extension EmailValidator on String {
fontStyle: fontStyle ?? FontStyle.normal, fontStyle: fontStyle ?? FontStyle.normal,
fontWeight: isBold ? FontWeight.bold : FontWeight.normal, fontWeight: isBold ? FontWeight.bold : FontWeight.normal,
color: color ?? AppColors.blackColor, color: color ?? AppColors.blackColor,
letterSpacing: -1, letterSpacing: 0,
), ),
); );
Widget toText10({Color? color, FontWeight? weight, bool isBold = false, bool isUnderLine = false, int? maxlines, FontStyle? fontStyle, TextOverflow? textOverflow, double letterSpacing = -1}) => Widget toText10({Color? color, FontWeight? weight, bool isBold = false, bool isUnderLine = false, int? maxlines, FontStyle? fontStyle, TextOverflow? textOverflow, double letterSpacing = 0}) => Text(
Text(
this, this,
maxLines: maxlines, maxLines: maxlines,
overflow: textOverflow, overflow: textOverflow,
@ -49,7 +48,7 @@ extension EmailValidator on String {
decorationColor: color ?? AppColors.blackColor), decorationColor: color ?? AppColors.blackColor),
); );
Widget toText11({Color? color, FontWeight? weight, bool isUnderLine = false, bool isCenter = false, bool isBold = false, int maxLine = 0, double letterSpacing = -1}) => Text( Widget toText11({Color? color, FontWeight? weight, bool isUnderLine = false, bool isCenter = false, bool isBold = false, int maxLine = 0, double letterSpacing = 0}) => Text(
this, this,
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? TextAlign.center : null,
maxLines: (maxLine > 0) ? maxLine : null, maxLines: (maxLine > 0) ? maxLine : null,
@ -71,7 +70,7 @@ extension EmailValidator on String {
fontSize: 12.fSize, fontSize: 12.fSize,
fontWeight: fontWeight ?? (isBold ? FontWeight.bold : FontWeight.normal), fontWeight: fontWeight ?? (isBold ? FontWeight.bold : FontWeight.normal),
color: color ?? AppColors.blackColor, color: color ?? AppColors.blackColor,
letterSpacing: -1, letterSpacing: 0,
height: height, height: height,
decorationColor: isUnderLine ? AppColors.blackColor : null, decorationColor: isUnderLine ? AppColors.blackColor : null,
decoration: isUnderLine ? TextDecoration.underline : null, decoration: isUnderLine ? TextDecoration.underline : null,
@ -87,7 +86,7 @@ extension EmailValidator on String {
fontSize: 12.fSize, fontSize: 12.fSize,
fontWeight: isBold ? FontWeight.bold : FontWeight.normal, fontWeight: isBold ? FontWeight.bold : FontWeight.normal,
color: color ?? AppColors.blackColor, color: color ?? AppColors.blackColor,
letterSpacing: -1, letterSpacing: 0,
decoration: isUnderLine ? TextDecoration.underline : null, decoration: isUnderLine ? TextDecoration.underline : null,
), ),
); );
@ -120,7 +119,7 @@ extension EmailValidator on String {
), ),
); );
Widget toText13({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, int maxLine = 0, FontWeight? weight, double? letterSpacing = -1}) => Text( Widget toText13({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, int maxLine = 0, FontWeight? weight, double? letterSpacing = 0}) => Text(
this, this,
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? TextAlign.center : null,
maxLines: (maxLine > 0) ? maxLine : null, maxLines: (maxLine > 0) ? maxLine : null,
@ -139,7 +138,7 @@ extension EmailValidator on String {
bool isCenter = false, bool isCenter = false,
FontWeight? weight, FontWeight? weight,
int? maxlines, int? maxlines,
double? letterSpacing = -1, double? letterSpacing = 0,
double? height, double? height,
TextOverflow? textOverflow}) => TextOverflow? textOverflow}) =>
Text( Text(

@ -150,13 +150,14 @@ extension SmoothContainerExtension on ShapeBorder {
bool isDisabled = false, bool isDisabled = false,
Color? backgroundColor, Color? backgroundColor,
BorderSide? side, BorderSide? side,
BorderRadius? customBorder,
bool hasShadow = false, bool hasShadow = false,
}) { }) {
final bgColor = backgroundColor ?? color; final bgColor = backgroundColor ?? color;
return ShapeDecoration( return ShapeDecoration(
color: isDisabled ? bgColor.withOpacity(0.5) : bgColor, color: isDisabled ? bgColor.withOpacity(0.5) : bgColor,
shape: SmoothRectangleBorder( shape: SmoothRectangleBorder(
borderRadius: BorderRadius.circular(borderRadius ?? 0), borderRadius: customBorder ?? BorderRadius.circular(borderRadius ?? 0),
smoothness: 1, smoothness: 1,
side: side ?? BorderSide.none, side: side ?? BorderSide.none,
), ),

@ -59,8 +59,7 @@ class AuthenticationViewModel extends ChangeNotifier {
required NavigationService navigationService, required NavigationService navigationService,
required CacheService cacheService, required CacheService cacheService,
required LocalAuthService localAuthService, required LocalAuthService localAuthService,
}) }) : _navigationService = navigationService,
: _navigationService = navigationService,
_dialogService = dialogService, _dialogService = dialogService,
_errorHandlerService = errorHandlerService, _errorHandlerService = errorHandlerService,
_appState = appState, _appState = appState,
@ -205,13 +204,13 @@ class AuthenticationViewModel extends ChangeNotifier {
final result = await _authenticationRepo.selectDeviceByImei(firebaseToken: firebaseToken); final result = await _authenticationRepo.selectDeviceByImei(firebaseToken: firebaseToken);
result.fold( result.fold(
(failure) async { (failure) async {
// LoadingUtils.hideFullScreenLoader(); // LoadingUtils.hideFullScreenLoader();
// await _errorHandlerService.handleError(failure: failure); // await _errorHandlerService.handleError(failure: failure);
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
_navigationService.pushPage(page: LoginScreen()); _navigationService.pushPage(page: LoginScreen());
}, },
(apiResponse) { (apiResponse) {
// LoadingUtils.hideFullScreenLoader(); // LoadingUtils.hideFullScreenLoader();
log("apiResponse: ${apiResponse.data.toString()}"); log("apiResponse: ${apiResponse.data.toString()}");
log("messageStatus: ${apiResponse.messageStatus.toString()}"); log("messageStatus: ${apiResponse.messageStatus.toString()}");
@ -301,8 +300,7 @@ class AuthenticationViewModel extends ChangeNotifier {
final result = await _authenticationRepo.checkPatientAuthentication(checkPatientAuthenticationReq: checkPatientAuthenticationReq); final result = await _authenticationRepo.checkPatientAuthentication(checkPatientAuthenticationReq: checkPatientAuthenticationReq);
result.fold( result.fold(
(failure) async => (failure) async => await _errorHandlerService.handleError(
await _errorHandlerService.handleError(
failure: failure, failure: failure,
onUnHandledFailure: (failure) async { onUnHandledFailure: (failure) async {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
@ -316,7 +314,7 @@ class AuthenticationViewModel extends ChangeNotifier {
_navigationService.pop(); _navigationService.pop();
}); });
}), }),
(apiResponse) async { (apiResponse) async {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty", onOkPressed: () {}); await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty", onOkPressed: () {});
@ -359,8 +357,8 @@ class AuthenticationViewModel extends ChangeNotifier {
patientOutSA: isForRegister patientOutSA: isForRegister
? isPatientOutsideSA(request: payload) ? isPatientOutsideSA(request: payload)
: selectedCountrySignup.countryCode == CountryEnum.saudiArabia : selectedCountrySignup.countryCode == CountryEnum.saudiArabia
? false ? false
: true, : true,
payload: payload, payload: payload,
); );
@ -374,8 +372,8 @@ class AuthenticationViewModel extends ChangeNotifier {
final resultEither = await _authenticationRepo.sendActivationCodeRepo(sendActivationCodeReq: request, isRegister: checkIsUserComingForRegister(request: payload), languageID: 'er'); final resultEither = await _authenticationRepo.sendActivationCodeRepo(sendActivationCodeReq: request, isRegister: checkIsUserComingForRegister(request: payload), languageID: 'er');
resultEither.fold( resultEither.fold(
(failure) async => await _errorHandlerService.handleError(failure: failure), (failure) async => await _errorHandlerService.handleError(failure: failure),
(apiResponse) async { (apiResponse) async {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
await _dialogService.showCommonBottomSheetWithoutH( await _dialogService.showCommonBottomSheetWithoutH(
@ -409,27 +407,27 @@ class AuthenticationViewModel extends ChangeNotifier {
bool isForRegister = (_appState.getUserRegistrationPayload.healthId != null || _appState.getUserRegistrationPayload.patientOutSa == true || _appState.getUserRegistrationPayload.patientOutSa == 1); bool isForRegister = (_appState.getUserRegistrationPayload.healthId != null || _appState.getUserRegistrationPayload.patientOutSa == true || _appState.getUserRegistrationPayload.patientOutSa == 1);
final request = RequestUtils.getCommonRequestWelcome( final request = RequestUtils.getCommonRequestWelcome(
phoneNumber: phoneNumberController.text, phoneNumber: phoneNumberController.text,
otpTypeEnum: otpTypeEnum, otpTypeEnum: otpTypeEnum,
deviceToken: _appState.deviceToken, deviceToken: _appState.deviceToken,
// patientOutSA: _appState.getUserRegistrationPayload.projectOutSa == 1 ? true : false, // patientOutSA: _appState.getUserRegistrationPayload.projectOutSa == 1 ? true : false,
patientOutSA: isForRegister patientOutSA: isForRegister
? _appState.getUserRegistrationPayload.projectOutSa == true ? _appState.getUserRegistrationPayload.projectOutSa == true
? true ? true
: false : false
: _appState.getSelectDeviceByImeiRespModelElement != null : _appState.getSelectDeviceByImeiRespModelElement != null
? _appState.getSelectDeviceByImeiRespModelElement!.outSa! ? _appState.getSelectDeviceByImeiRespModelElement!.outSa!
: selectedCountrySignup == CountryEnum.saudiArabia : selectedCountrySignup == CountryEnum.saudiArabia
? false ? false
: true, : true,
loginTokenID: _appState.appAuthToken, loginTokenID: _appState.appAuthToken,
registeredData: isForRegister ? _appState.getUserRegistrationPayload : null, registeredData: isForRegister ? _appState.getUserRegistrationPayload : null,
nationIdText: nationalIdController.text, nationIdText: nationalIdController.text,
countryCode: _appState.getSelectDeviceByImeiRespModelElement != null && _appState.getSelectDeviceByImeiRespModelElement!.outSa == true countryCode: _appState.getSelectDeviceByImeiRespModelElement != null && _appState.getSelectDeviceByImeiRespModelElement!.outSa == true
? CountryEnum.unitedArabEmirates.countryCode ? CountryEnum.unitedArabEmirates.countryCode
: selectedCountrySignup.countryCode, : selectedCountrySignup.countryCode,
//TODO: Error Here IN Zip Code. //TODO: Error Here IN Zip Code.
loginType: loginTypeEnum.toInt) loginType: loginTypeEnum.toInt)
.toJson(); .toJson();
LoaderBottomSheet.showLoader(); LoaderBottomSheet.showLoader();
if (isForRegister) { if (isForRegister) {
@ -445,8 +443,7 @@ class AuthenticationViewModel extends ChangeNotifier {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
resultEither.fold( resultEither.fold(
(failure) async => (failure) async => await _errorHandlerService.handleError(
await _errorHandlerService.handleError(
failure: failure, failure: failure,
onUnHandledFailure: (failure) async { onUnHandledFailure: (failure) async {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
@ -454,9 +451,6 @@ class AuthenticationViewModel extends ChangeNotifier {
message: failure.message, message: failure.message,
label: LocaleKeys.notice.tr(), label: LocaleKeys.notice.tr(),
onOkPressed: () { onOkPressed: () {
_navigationService.pushAndReplace(AppRoutes.register);
},
onCancelPressed: () {
_navigationService.pop(); _navigationService.pop();
}); });
}), (apiResponse) { }), (apiResponse) {
@ -473,8 +467,7 @@ class AuthenticationViewModel extends ChangeNotifier {
final resultEither = await _authenticationRepo.checkActivationCodeRepo(newRequest: CheckActivationCodeRegisterReq.fromJson(request), activationCode: activationCode, isRegister: false); final resultEither = await _authenticationRepo.checkActivationCodeRepo(newRequest: CheckActivationCodeRegisterReq.fromJson(request), activationCode: activationCode, isRegister: false);
resultEither.fold( resultEither.fold(
(failure) async => (failure) async => await _errorHandlerService.handleError(
await _errorHandlerService.handleError(
failure: failure, failure: failure,
onUnHandledFailure: (failure) async { onUnHandledFailure: (failure) async {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
@ -658,15 +651,15 @@ class AuthenticationViewModel extends ChangeNotifier {
bool isOutSidePatient = selectedCountrySignup.countryCode == CountryEnum.unitedArabEmirates.countryCode ? true : false; bool isOutSidePatient = selectedCountrySignup.countryCode == CountryEnum.unitedArabEmirates.countryCode ? true : false;
LoaderBottomSheet.showLoader(); LoaderBottomSheet.showLoader();
final request = await RequestUtils.getPatientAuthenticationRequest( final request = await RequestUtils.getPatientAuthenticationRequest(
phoneNumber: phoneNumberController.text, phoneNumber: phoneNumberController.text,
nationId: nationalIdController.text, nationId: nationalIdController.text,
patientOutSA: isOutSidePatient, patientOutSA: isOutSidePatient,
otpTypeEnum: otpTypeEnum, otpTypeEnum: otpTypeEnum,
isForRegister: true, isForRegister: true,
patientId: 0, patientId: 0,
zipCode: selectedCountrySignup.countryCode, zipCode: selectedCountrySignup.countryCode,
calenderType: calenderType, calenderType: calenderType,
dob: dob) dob: dob)
.toJson(); .toJson();
var nRequest = Map<String, dynamic>.from(request); var nRequest = Map<String, dynamic>.from(request);
@ -802,22 +795,22 @@ class AuthenticationViewModel extends ChangeNotifier {
Future<void> insertPatientIMEIData(int loginType) async { Future<void> insertPatientIMEIData(int loginType) async {
final resultEither = await _authenticationRepo.insertPatientIMEIData( final resultEither = await _authenticationRepo.insertPatientIMEIData(
patientIMEIDataRequest: PatientInsertDeviceImei( patientIMEIDataRequest: PatientInsertDeviceImei(
imei: _appState.deviceToken, imei: _appState.deviceToken,
deviceTypeId: _appState.getDeviceTypeID(), deviceTypeId: _appState.getDeviceTypeID(),
patientId: _appState.getAuthenticatedUser()!.patientId!, patientId: _appState.getAuthenticatedUser()!.patientId!,
patientIdentificationNo: _appState.getAuthenticatedUser()!.patientIdentificationNo!, patientIdentificationNo: _appState.getAuthenticatedUser()!.patientIdentificationNo!,
identificationNo: _appState.getAuthenticatedUser()!.patientIdentificationNo!, identificationNo: _appState.getAuthenticatedUser()!.patientIdentificationNo!,
firstName: _appState.getAuthenticatedUser()!.firstName!, firstName: _appState.getAuthenticatedUser()!.firstName!,
lastName: _appState.getAuthenticatedUser()!.lastName!, lastName: _appState.getAuthenticatedUser()!.lastName!,
patientTypeId: _appState.getAuthenticatedUser()!.patientType, patientTypeId: _appState.getAuthenticatedUser()!.patientType,
mobileNo: _appState.getAuthenticatedUser()!.mobileNumber!, mobileNo: _appState.getAuthenticatedUser()!.mobileNumber!,
logInTypeId: loginType, logInTypeId: loginType,
patientOutSa: _appState.getAuthenticatedUser()!.outSa!, patientOutSa: _appState.getAuthenticatedUser()!.outSa!,
outSa: _appState.getAuthenticatedUser()!.outSa == 1 ? true : false, outSa: _appState.getAuthenticatedUser()!.outSa == 1 ? true : false,
biometricEnabled: loginType == 1 || loginType == 2 ? false : true, biometricEnabled: loginType == 1 || loginType == 2 ? false : true,
firstNameN: _appState.getAuthenticatedUser()!.firstNameN, firstNameN: _appState.getAuthenticatedUser()!.firstNameN,
lastNameN: _appState.getAuthenticatedUser()!.lastNameN, lastNameN: _appState.getAuthenticatedUser()!.lastNameN,
).toJson()); ).toJson());
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async { resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
if (apiResponse.messageStatus == 1) { if (apiResponse.messageStatus == 1) {
log("Insert IMEI Success"); log("Insert IMEI Success");
@ -831,20 +824,20 @@ class AuthenticationViewModel extends ChangeNotifier {
Future<void> insertPatientDeviceData(int loginType) async { Future<void> insertPatientDeviceData(int loginType) async {
final resultEither = await _authenticationRepo.insertPatientDeviceData( final resultEither = await _authenticationRepo.insertPatientDeviceData(
patientDeviceDataRequest: InsertPatientMobileDeviceInfo( patientDeviceDataRequest: InsertPatientMobileDeviceInfo(
deviceToken: _appState.deviceToken, deviceToken: _appState.deviceToken,
deviceTypeId: _appState.getDeviceTypeID(), deviceTypeId: _appState.getDeviceTypeID(),
patientId: _appState.getAuthenticatedUser()!.patientId!, patientId: _appState.getAuthenticatedUser()!.patientId!,
patientTypeId: _appState.getAuthenticatedUser()!.patientType, patientTypeId: _appState.getAuthenticatedUser()!.patientType,
patientOutSa: _appState.getAuthenticatedUser()!.outSa!, patientOutSa: _appState.getAuthenticatedUser()!.outSa!,
loginType: loginType, loginType: loginType,
languageId: _appState.getLanguageID(), languageId: _appState.getLanguageID(),
latitude: _appState.userLat, latitude: _appState.userLat,
longitude: _appState.userLong, longitude: _appState.userLong,
voipToken: "", voipToken: "",
deviceType: _appState.deviceTypeID, deviceType: _appState.deviceTypeID,
patientMobileNumber: _appState.getAuthenticatedUser()!.mobileNumber, patientMobileNumber: _appState.getAuthenticatedUser()!.mobileNumber,
nationalId: _appState.getAuthenticatedUser()!.patientIdentificationNo, nationalId: _appState.getAuthenticatedUser()!.patientIdentificationNo,
gender: _appState.getAuthenticatedUser()!.gender) gender: _appState.getAuthenticatedUser()!.gender)
.toJson()); .toJson());
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async { resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
if (apiResponse.messageStatus == 1) { if (apiResponse.messageStatus == 1) {
@ -858,18 +851,18 @@ class AuthenticationViewModel extends ChangeNotifier {
Future<void> getPatientDeviceData(int loginType) async { Future<void> getPatientDeviceData(int loginType) async {
final resultEither = await _authenticationRepo.getPatientDeviceData( final resultEither = await _authenticationRepo.getPatientDeviceData(
patientDeviceDataRequest: GetUserMobileDeviceData( patientDeviceDataRequest: GetUserMobileDeviceData(
deviceToken: _appState.deviceToken, deviceToken: _appState.deviceToken,
deviceTypeId: _appState.getDeviceTypeID(), deviceTypeId: _appState.getDeviceTypeID(),
patientId: _appState.getSelectDeviceByImeiRespModelElement!.patientId!, patientId: _appState.getSelectDeviceByImeiRespModelElement!.patientId!,
patientType: _appState.getSelectDeviceByImeiRespModelElement!.patientType, patientType: _appState.getSelectDeviceByImeiRespModelElement!.patientType,
patientOutSa: _appState.getSelectDeviceByImeiRespModelElement!.outSa == true ? 1 : 0, patientOutSa: _appState.getSelectDeviceByImeiRespModelElement!.outSa == true ? 1 : 0,
loginType: loginType, loginType: loginType,
languageId: _appState.getLanguageID(), languageId: _appState.getLanguageID(),
latitude: _appState.userLat, latitude: _appState.userLat,
longitude: _appState.userLong, longitude: _appState.userLong,
mobileNo: _appState.getSelectDeviceByImeiRespModelElement!.mobile!, mobileNo: _appState.getSelectDeviceByImeiRespModelElement!.mobile!,
patientMobileNumber: int.parse(_appState.getSelectDeviceByImeiRespModelElement!.mobile!), patientMobileNumber: int.parse(_appState.getSelectDeviceByImeiRespModelElement!.mobile!),
nationalId: _appState.getSelectDeviceByImeiRespModelElement!.identificationNo) nationalId: _appState.getSelectDeviceByImeiRespModelElement!.identificationNo)
.toJson()); .toJson());
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async { resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
if (apiResponse.messageStatus == 1) { if (apiResponse.messageStatus == 1) {
@ -885,11 +878,15 @@ class AuthenticationViewModel extends ChangeNotifier {
message: apiResponse.errorMessage ?? "", message: apiResponse.errorMessage ?? "",
label: LocaleKeys.notice.tr(), label: LocaleKeys.notice.tr(),
onOkPressed: () { onOkPressed: () {
_dialogService.showPhoneNumberPickerSheet(label:"Where would you like to receive OTP?", message:"Please select from the below options to receive OTP.", onSMSPress: () { _dialogService.showPhoneNumberPickerSheet(
checkUserAuthentication(otpTypeEnum: OTPTypeEnum.sms); label: "Where would you like to receive OTP?",
}, onWhatsappPress: () { message: "Please select from the below options to receive OTP.",
checkUserAuthentication(otpTypeEnum: OTPTypeEnum.whatsapp); onSMSPress: () {
}); checkUserAuthentication(otpTypeEnum: OTPTypeEnum.sms);
},
onWhatsappPress: () {
checkUserAuthentication(otpTypeEnum: OTPTypeEnum.whatsapp);
});
}, },
onCancelPressed: () { onCancelPressed: () {
_navigationService.pop(); _navigationService.pop();
@ -914,8 +911,8 @@ class AuthenticationViewModel extends ChangeNotifier {
List<ProjectDetailListModel> projectDetailListModel = []; List<ProjectDetailListModel> projectDetailListModel = [];
resultEither.fold( resultEither.fold(
(failure) async => await _errorHandlerService.handleError(failure: failure), (failure) async => await _errorHandlerService.handleError(failure: failure),
(apiResponse) async { (apiResponse) async {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty"); await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty");
} else { } else {

@ -533,6 +533,7 @@ class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
AuthenticationViewModel authVM = context.read<AuthenticationViewModel>(); AuthenticationViewModel authVM = context.read<AuthenticationViewModel>();
AppState appState = getIt<AppState>();
return Scaffold( return Scaffold(
backgroundColor: AppColors.scaffoldBgColor, backgroundColor: AppColors.scaffoldBgColor,
appBar: CustomAppBar( appBar: CustomAppBar(
@ -552,14 +553,16 @@ class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
LocaleKeys.otpVerification.tr().toText24(isBold: true), LocaleKeys.otpVerification.tr().toText24(isBold: true),
SizedBox(height: 20.h), SizedBox(height: 20.h),
Wrap( Wrap(
spacing: 4.h, spacing: 2.h,
runSpacing: 8.0, runSpacing: 2.h,
children: [ children: [
LocaleKeys.weHaveSendOTP.tr().toText16(color: AppColors.inputLabelTextColor), LocaleKeys.weHaveSendOTP.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
_getMaskedPhoneNumber().toText16(color: AppColors.inputLabelTextColor, isBold: true), _getMaskedPhoneNumber().toText15(color: AppColors.inputLabelTextColor, isBold: true),
LocaleKeys.via.tr().toText16(color: AppColors.inputLabelTextColor), LocaleKeys.via.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
authVM.loginTypeEnum.displayName.toText16(color: AppColors.inputLabelTextColor), authVM.loginTypeEnum.displayName.toText15(color: AppColors.inputLabelTextColor, isBold: true, letterSpacing: -0.4),
LocaleKeys.forRegistrationVerification.tr().toText16(color: AppColors.inputLabelTextColor), appState.getUserRegistrationPayload.isRegister != null && appState.getUserRegistrationPayload.isRegister == true
? LocaleKeys.forRegistrationVerification.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4)
: LocaleKeys.forLoginVerification.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
], ],
), ),

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart'; import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/location_util.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/doctor_response_mapper.dart'; import 'package:hmg_patient_app_new/core/utils/doctor_response_mapper.dart';
import 'package:hmg_patient_app_new/core/utils/loading_utils.dart'; import 'package:hmg_patient_app_new/core/utils/loading_utils.dart';
@ -24,6 +25,7 @@ import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:location/location.dart' show Location; import 'package:location/location.dart' show Location;
@ -37,6 +39,8 @@ class BookAppointmentsViewModel extends ChangeNotifier {
int initialSlotDuration = 0; int initialSlotDuration = 0;
LocationUtils locationUtils;
List<GetClinicsListResponseModel> clinicsList = []; List<GetClinicsListResponseModel> clinicsList = [];
List<GetClinicsListResponseModel> _filteredClinicsList = []; List<GetClinicsListResponseModel> _filteredClinicsList = [];
@ -74,7 +78,9 @@ class BookAppointmentsViewModel extends ChangeNotifier {
bool shouldLoadSpecificClinic = false; bool shouldLoadSpecificClinic = false;
String? currentlySelectedHospitalFromRegionFlow; String? currentlySelectedHospitalFromRegionFlow;
BookAppointmentsViewModel({required this.bookAppointmentsRepo, required this.errorHandlerService, required this.navigationService, required this.myAppointmentsViewModel}); BookAppointmentsViewModel({required this.bookAppointmentsRepo, required this.errorHandlerService, required this.navigationService, required this.myAppointmentsViewModel, required this.locationUtils}) {;
initBookAppointmentViewModel();
}
void initializeFilteredList() { void initializeFilteredList() {
_filteredClinicsList = List.from(clinicsList); _filteredClinicsList = List.from(clinicsList);
@ -97,6 +103,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
isDoctorProfileLoading = true; isDoctorProfileLoading = true;
clinicsList.clear(); clinicsList.clear();
doctorsList.clear(); doctorsList.clear();
// getLocation();
notifyListeners(); notifyListeners();
} }
@ -378,7 +385,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
LoadingUtils.hideFullScreenLoader(); LoadingUtils.hideFullScreenLoader();
Navigator.pushAndRemoveUntil( Navigator.pushAndRemoveUntil(
navigationService.navigatorKey.currentContext!, navigationService.navigatorKey.currentContext!,
FadePage( CustomPageRoute(
page: LandingNavigation(), page: LandingNavigation(),
), ),
(r) => false); (r) => false);
@ -408,10 +415,10 @@ class BookAppointmentsViewModel extends ChangeNotifier {
Future<void> getRegionMappedProjectList() async { Future<void> getRegionMappedProjectList() async {
//todo handle the case in the location is switch on //todo handle the case in the location is switch on
if(hospitalList != null && hospitalList!.registeredDoctorMap != null && hospitalList!.registeredDoctorMap!.isNotEmpty){ // if(hospitalList != null && hospitalList!.registeredDoctorMap != null && hospitalList!.registeredDoctorMap!.isNotEmpty){
filteredHospitalList = hospitalList; // filteredHospitalList = hospitalList;
return; // return;
} // }
isRegionListLoading = true; isRegionListLoading = true;
notifyListeners(); notifyListeners();
final result = await bookAppointmentsRepo.getProjectList(); final result = await bookAppointmentsRepo.getProjectList();
@ -429,10 +436,8 @@ class BookAppointmentsViewModel extends ChangeNotifier {
lat: _appState.userLat, lat: _appState.userLat,
lng: _appState.userLong, lng: _appState.userLong,
); );
var lat = await Utils.getNumFromPrefs(CacheConst.userLat);
var lng = await Utils.getNumFromPrefs(CacheConst.userLong); var isLocationEnabled = (_appState.userLat != 0) && (_appState.userLong != 0);
var isLocationEnabled = (lat != 0) && (lng != 0);
hospitalList = hospitalList =
await DoctorMapper.sortList(isLocationEnabled, hospitalList!); await DoctorMapper.sortList(isLocationEnabled, hospitalList!);
@ -480,15 +485,15 @@ class BookAppointmentsViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
Future<bool> isLocationEnabled() async{ bool isLocationEnabled() {
return await Location().serviceEnabled(); return _appState.userLong != 0.0 && _appState.userLong != 0.0;
} }
bool getLocationStatus() { // bool getLocationStatus() {
bool isLocationAvaiable = false; // bool isLocationAvaiable = false;
isLocationEnabled().then((value) => isLocationAvaiable = value); // isLocationEnabled().then((value) => isLocationAvaiable = value);
return isLocationAvaiable; // return isLocationAvaiable;
} // }
void setLoadSpecificClinic(bool status) { void setLoadSpecificClinic(bool status) {
shouldLoadSpecificClinic = status; shouldLoadSpecificClinic = status;
@ -518,4 +523,9 @@ class BookAppointmentsViewModel extends ChangeNotifier {
void resetFilterList(){ void resetFilterList(){
filteredHospitalList = hospitalList; filteredHospitalList = hospitalList;
} }
void getLocation(){
locationUtils.getLocation();
}
} }

@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart' show ChangeNotifier;
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/select_clinic_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/select_clinic_page.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
enum AppointmentViaRegionState { enum AppointmentViaRegionState {
@ -39,7 +40,7 @@ class AppointmentViaRegionViewmodel extends ChangeNotifier {
void handleLastStep(){ void handleLastStep(){
navigationService.pop(); navigationService.pop();
navigationService.push(FadePage( navigationService.push(CustomPageRoute(
page: SelectClinicPage(), page: SelectClinicPage(),
),); ),);
} }

@ -79,6 +79,11 @@ class MyAppointmentsViewModel extends ChangeNotifier {
} }
Future<void> getPatientAppointments(bool isActiveAppointment, bool isArrivedAppointments, {Function(dynamic)? onSuccess, Function(String)? onError}) async { Future<void> getPatientAppointments(bool isActiveAppointment, bool isArrivedAppointments, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
patientAppointmentsHistoryList.clear();
patientUpcomingAppointmentsHistoryList.clear();
patientArrivedAppointmentsHistoryList.clear();
final result = await myAppointmentsRepo.getPatientAppointments(isActiveAppointment: isActiveAppointment, isArrivedAppointments: isArrivedAppointments); final result = await myAppointmentsRepo.getPatientAppointments(isActiveAppointment: isActiveAppointment, isArrivedAppointments: isArrivedAppointments);
final resultArrived = await myAppointmentsRepo.getPatientAppointments(isActiveAppointment: false, isArrivedAppointments: true); final resultArrived = await myAppointmentsRepo.getPatientAppointments(isActiveAppointment: false, isArrivedAppointments: true);

@ -99,6 +99,7 @@ class PayfortViewModel extends ChangeNotifier {
String? applePayShaType, String? applePayShaType,
String? applePayShaRequestPhrase, String? applePayShaRequestPhrase,
}) async { }) async {
var sdkTokenResponse;
try { try {
String? deviceId = await _payfort.getDeviceId(); String? deviceId = await _payfort.getDeviceId();
@ -125,6 +126,7 @@ class PayfortViewModel extends ChangeNotifier {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) { } else if (apiResponse.messageStatus == 1) {
// payfortProjectDetailsRespModel = apiResponse.data!; // payfortProjectDetailsRespModel = apiResponse.data!;
sdkTokenResponse = apiResponse.data;
isApplePayConfigurationLoading = false; isApplePayConfigurationLoading = false;
notifyListeners(); notifyListeners();
} }
@ -133,7 +135,7 @@ class PayfortViewModel extends ChangeNotifier {
} catch (e) { } catch (e) {
print("Error here: ${e.toString()}"); print("Error here: ${e.toString()}");
} }
return null; return sdkTokenResponse;
} }
Future<void> paymentWithApplePay({ Future<void> paymentWithApplePay({

@ -1,3 +1,5 @@
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
class PatientRadiologyResponseModel { class PatientRadiologyResponseModel {
String? setupID; String? setupID;
int? projectID; int? projectID;
@ -6,7 +8,7 @@ class PatientRadiologyResponseModel {
int? invoiceNo; int? invoiceNo;
int? doctorID; int? doctorID;
int? clinicID; int? clinicID;
String? orderDate; DateTime? orderDate;
String? reportData; String? reportData;
String? imageURL; String? imageURL;
String? procedureID; String? procedureID;
@ -120,7 +122,7 @@ class PatientRadiologyResponseModel {
invoiceNo = json['InvoiceNo']; invoiceNo = json['InvoiceNo'];
doctorID = json['DoctorID']; doctorID = json['DoctorID'];
clinicID = json['ClinicID']; clinicID = json['ClinicID'];
orderDate = json['OrderDate']; orderDate = DateUtil.convertStringToDate(json['OrderDate']);
reportData = json['ReportData']; reportData = json['ReportData'];
imageURL = json['ImageURL']; imageURL = json['ImageURL'];
procedureID = json['ProcedureID']; procedureID = json['ProcedureID'];

@ -3,11 +3,17 @@ import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart'; import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart'; import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart'; import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/radiology/models/resp_models/patient_radiology_response_model.dart'; import 'package:hmg_patient_app_new/features/radiology/models/resp_models/patient_radiology_response_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class RadiologyRepo { abstract class RadiologyRepo {
Future<Either<Failure, GenericApiModel<List<PatientRadiologyResponseModel>>>> getPatientRadiologyOrders({required String patientId}); Future<Either<Failure, GenericApiModel<List<PatientRadiologyResponseModel>>>> getPatientRadiologyOrders({required String patientId});
Future<Either<Failure, GenericApiModel<String>>> getRadiologyImage({required PatientRadiologyResponseModel patientRadiologyResponseModel});
Future<Either<Failure, GenericApiModel<String>>> getRadiologyReportPDF({required PatientRadiologyResponseModel patientRadiologyResponseModel, required AuthenticatedUser authenticatedUser});
} }
class RadiologyRepoImp implements RadiologyRepo { class RadiologyRepoImp implements RadiologyRepo {
@ -58,4 +64,99 @@ class RadiologyRepoImp implements RadiologyRepo {
return Left(UnknownFailure(e.toString())); return Left(UnknownFailure(e.toString()));
} }
} }
@override
Future<Either<Failure, GenericApiModel<String>>> getRadiologyImage({required PatientRadiologyResponseModel patientRadiologyResponseModel}) async {
Map<String, dynamic> mapDevice = {
"InvoiceNo": Utils.isVidaPlusProject(patientRadiologyResponseModel.projectID!) ? "0" : patientRadiologyResponseModel.invoiceNo,
"InvoiceNo_VP": Utils.isVidaPlusProject(patientRadiologyResponseModel.projectID!) ? patientRadiologyResponseModel.invoiceNo : "0",
"LineItemNo": patientRadiologyResponseModel.invoiceLineItemNo,
"ProjectID": patientRadiologyResponseModel.projectID!,
"InvoiceType": patientRadiologyResponseModel.invoiceType!,
"ExamId": patientRadiologyResponseModel.examId ?? "",
};
try {
GenericApiModel<String>? apiResponse;
Failure? failure;
await apiClient.post(
GET_RAD_IMAGE_URL,
body: mapDevice,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<String>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: response["Data"],
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<String>>> getRadiologyReportPDF({required PatientRadiologyResponseModel patientRadiologyResponseModel, required AuthenticatedUser authenticatedUser}) async {
Map<String, dynamic> mapDevice = {
"InvoiceNo": Utils.isVidaPlusProject(patientRadiologyResponseModel.projectID!) ? 0 : patientRadiologyResponseModel.invoiceNo,
"InvoiceNo_VP": Utils.isVidaPlusProject(patientRadiologyResponseModel.projectID!) ? patientRadiologyResponseModel.invoiceNo : 0,
"LineItemNo": patientRadiologyResponseModel.invoiceLineItemNo,
"InvoiceLineItemNo": patientRadiologyResponseModel.invoiceLineItemNo,
"ProjectID": patientRadiologyResponseModel.projectID!,
"InvoiceType": patientRadiologyResponseModel.invoiceType!,
"SetupID": patientRadiologyResponseModel.setupID!,
// "ExamId": patientRadiologyResponseModel.examId ?? "",
"IsDownload": true,
'ClinicName': patientRadiologyResponseModel.clinicDescription,
'DateofBirth': authenticatedUser.dateofBirth,
'DoctorName': patientRadiologyResponseModel.doctorName,
'OrderDate': '${patientRadiologyResponseModel.orderDate!.year}-${patientRadiologyResponseModel.orderDate!.month}-${patientRadiologyResponseModel.orderDate!.day}',
'PatientIditificationNum': authenticatedUser.patientIdentificationNo,
'PatientMobileNumber': authenticatedUser.mobileNumber,
'PatientName': "${authenticatedUser.firstName!} ${authenticatedUser.lastName!}",
'ProjectName': patientRadiologyResponseModel.projectName,
'RadResult': patientRadiologyResponseModel.reportData,
"To": authenticatedUser.emailAddress
};
try {
GenericApiModel<String>? apiResponse;
Failure? failure;
await apiClient.post(
SEND_RAD_REPORT_EMAIL,
body: mapDevice,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<String>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: response["Base64Data"],
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
} }

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_repo.dart'; import 'package:hmg_patient_app_new/features/radiology/radiology_repo.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart';
@ -6,17 +7,23 @@ import 'models/resp_models/patient_radiology_response_model.dart';
class RadiologyViewModel extends ChangeNotifier { class RadiologyViewModel extends ChangeNotifier {
bool isRadiologyOrdersLoading = false; bool isRadiologyOrdersLoading = false;
bool isRadiologyPDFReportLoading = false;
RadiologyRepo radiologyRepo; RadiologyRepo radiologyRepo;
ErrorHandlerService errorHandlerService; ErrorHandlerService errorHandlerService;
List<PatientRadiologyResponseModel> patientRadiologyOrders = []; List<PatientRadiologyResponseModel> patientRadiologyOrders = [];
String radiologyImageURL = "";
String patientRadiologyReportPDFBase64 = "";
RadiologyViewModel({required this.radiologyRepo, required this.errorHandlerService}); RadiologyViewModel({required this.radiologyRepo, required this.errorHandlerService});
initRadiologyProvider() { initRadiologyProvider() {
patientRadiologyOrders.clear(); patientRadiologyOrders.clear();
isRadiologyOrdersLoading = true; isRadiologyOrdersLoading = true;
isRadiologyPDFReportLoading = true;
radiologyImageURL = "";
getPatientRadiologyOrders(); getPatientRadiologyOrders();
notifyListeners(); notifyListeners();
} }
@ -40,4 +47,50 @@ class RadiologyViewModel extends ChangeNotifier {
}, },
); );
} }
Future<void> getRadiologyImage({required PatientRadiologyResponseModel patientRadiologyResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await radiologyRepo.getRadiologyImage(patientRadiologyResponseModel: patientRadiologyResponseModel);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
radiologyImageURL = apiResponse.data!;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> getRadiologyPDF(
{required PatientRadiologyResponseModel patientRadiologyResponseModel, required AuthenticatedUser authenticatedUser, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await radiologyRepo.getRadiologyReportPDF(patientRadiologyResponseModel: patientRadiologyResponseModel, authenticatedUser: authenticatedUser);
result.fold(
(failure) async => await errorHandlerService.handleError(
failure: failure,
onOkPressed: () {
onError!(failure.message);
},
),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
onError!(apiResponse.errorMessage!);
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
patientRadiologyReportPDFBase64 = apiResponse.data!;
isRadiologyPDFReportLoading = false;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
} }

@ -846,5 +846,7 @@ abstract class LocaleKeys {
static const pleaseSelectACountry = 'pleaseSelectACountry'; static const pleaseSelectACountry = 'pleaseSelectACountry';
static const pleaseEnterEmail = 'pleaseEnterEmail'; static const pleaseEnterEmail = 'pleaseEnterEmail';
static const pleaseEnterAValidEmailFormat = 'pleaseEnterAValidEmailFormat'; static const pleaseEnterAValidEmailFormat = 'pleaseEnterAValidEmailFormat';
static const selectCountry = 'selectCountry';
static const forLoginVerification = 'forLoginVerification';
} }

@ -132,6 +132,7 @@ void main() async {
errorHandlerService: getIt(), errorHandlerService: getIt(),
navigationService: getIt(), navigationService: getIt(),
myAppointmentsViewModel: getIt(), myAppointmentsViewModel: getIt(),
locationUtils: getIt(),
), ),
), ),
ChangeNotifierProvider<AuthenticationViewModel>( ChangeNotifierProvider<AuthenticationViewModel>(

@ -28,6 +28,7 @@ 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/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart'; import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:maps_launcher/maps_launcher.dart'; import 'package:maps_launcher/maps_launcher.dart';
@ -72,7 +73,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
Expanded( Expanded(
child: CollapsingListView( child: CollapsingListView(
title: "Appointment Details".needTranslation, title: "Appointment Details".needTranslation,
report: () {}, report: AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel) ? () {} : null,
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -331,7 +332,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
).onPress(() { ).onPress(() {
prescriptionVM.setPrescriptionsDetailsLoading(); prescriptionVM.setPrescriptionsDetailsLoading();
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: PrescriptionDetailPage(prescriptionsResponseModel: getPrescriptionRequestModel()), page: PrescriptionDetailPage(prescriptionsResponseModel: getPrescriptionRequestModel()),
), ),
); );
@ -364,7 +365,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
onPressed: () { onPressed: () {
Navigator.of(context) Navigator.of(context)
.push( .push(
FadePage( CustomPageRoute(
page: PrescriptionsListPage(), page: PrescriptionsListPage(),
), ),
) )
@ -425,8 +426,8 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
LocaleKeys.upcomingPaymentNow.tr(context: context).toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor), Expanded(child: LocaleKeys.upcomingPaymentNow.tr(context: context).toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor)),
"VAT 15%(${widget.patientAppointmentHistoryResponseModel.patientTaxAmount})".needTranslation.toText14(isBold: true, color: AppColors.greyTextColor), "VAT 15%(${widget.patientAppointmentHistoryResponseModel.patientTaxAmount})".needTranslation.toText14(isBold: true, color: AppColors.greyTextColor, letterSpacing: -2),
], ],
), ),
SizedBox(height: 18.h), SizedBox(height: 18.h),
@ -560,7 +561,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
case 20: case 20:
myAppointmentsViewModel.setIsPatientAppointmentShareLoading(true); myAppointmentsViewModel.setIsPatientAppointmentShareLoading(true);
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: AppointmentPaymentPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel), page: AppointmentPaymentPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
), ),
); );

@ -27,6 +27,7 @@ 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/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/in_app_browser/InAppBrowser.dart'; import 'package:hmg_patient_app_new/widgets/in_app_browser/InAppBrowser.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart'; import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -79,118 +80,116 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
child: CollapsingListView( child: CollapsingListView(
title: "Appointment Payment".needTranslation, title: "Appointment Payment".needTranslation,
child: SingleChildScrollView( child: SingleChildScrollView(
child: myAppointmentsVM.isAppointmentPatientShareLoading child: Column(
? const MoviesShimmerWidget().paddingAll(24.h) crossAxisAlignment: CrossAxisAlignment.start,
: Column( children: [
crossAxisAlignment: CrossAxisAlignment.start, SizedBox(height: 24.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [ children: [
SizedBox(height: 24.h), Column(
Container( crossAxisAlignment: CrossAxisAlignment.start,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( children: [
color: AppColors.whiteColor, Image.asset(AppAssets.mada, width: 72.h, height: 25.h).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
borderRadius: 20.h, SizedBox(height: 16.h),
hasShadow: false, "Mada".needTranslation.toText16(isBold: true).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
), ],
child: Row( ),
mainAxisSize: MainAxisSize.max, SizedBox(width: 8.h),
children: [ const Spacer(),
Column( Utils.buildSvgWithAssets(
crossAxisAlignment: CrossAxisAlignment.start, icon: AppAssets.forward_arrow_icon,
children: [ iconColor: AppColors.blackColor,
Image.asset(AppAssets.mada, width: 72.h, height: 25.h), width: 18.h,
SizedBox(height: 16.h), height: 13.h,
"Mada".needTranslation.toText16(isBold: true), fit: BoxFit.contain,
], ).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
), ],
SizedBox(width: 8.h), ).paddingSymmetrical(16.h, 16.h),
const Spacer(), ).paddingSymmetrical(24.h, 0.h).onPress(() {
Utils.buildSvgWithAssets( selectedPaymentMethod = "MADA";
icon: AppAssets.forward_arrow_icon, openPaymentURL("mada");
iconColor: AppColors.blackColor, }),
width: 18.h, SizedBox(height: 16.h),
height: 13.h, Container(
fit: BoxFit.contain, decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
), color: AppColors.whiteColor,
], borderRadius: 20.h,
).paddingSymmetrical(16.h, 16.h), hasShadow: false,
).paddingSymmetrical(24.h, 0.h).onPress(() { ),
selectedPaymentMethod = "MADA"; child: Row(
openPaymentURL("mada"); mainAxisSize: MainAxisSize.max,
}), children: [
SizedBox(height: 16.h), Column(
Container( crossAxisAlignment: CrossAxisAlignment.start,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( children: [
color: AppColors.whiteColor, Row(
borderRadius: 20.h, children: [
hasShadow: false, Image.asset(AppAssets.visa, width: 50.h, height: 50.h),
), SizedBox(width: 8.h),
child: Row( Image.asset(AppAssets.Mastercard, width: 40.h, height: 40.h),
mainAxisSize: MainAxisSize.max, ],
children: [ ).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
Column( SizedBox(height: 16.h),
crossAxisAlignment: CrossAxisAlignment.start, "Visa or Mastercard".needTranslation.toText16(isBold: true).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
children: [ ],
Row( ),
children: [ SizedBox(width: 8.h),
Image.asset(AppAssets.visa, width: 50.h, height: 50.h), const Spacer(),
SizedBox(width: 8.h), Utils.buildSvgWithAssets(
Image.asset(AppAssets.Mastercard, width: 40.h, height: 40.h), icon: AppAssets.forward_arrow_icon,
], iconColor: AppColors.blackColor,
), width: 18.h,
SizedBox(height: 16.h), height: 13.h,
"Visa or Mastercard".needTranslation.toText16(isBold: true), fit: BoxFit.contain,
], ).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
),
SizedBox(width: 8.h),
const Spacer(),
Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 18.h,
height: 13.h,
fit: BoxFit.contain,
),
],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "VISA";
openPaymentURL("visa");
}),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.asset(AppAssets.tamara_en, width: 72.h, height: 25.h),
SizedBox(height: 16.h),
"Tamara".needTranslation.toText16(isBold: true),
],
),
SizedBox(width: 8.h),
const Spacer(),
Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 18.h,
height: 13.h,
fit: BoxFit.contain,
),
],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "TAMARA";
openPaymentURL("tamara");
}),
], ],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "VISA";
openPaymentURL("visa");
}),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
), ),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.asset(AppAssets.tamara_en, width: 72.h, height: 25.h).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
SizedBox(height: 16.h),
"Tamara".needTranslation.toText16(isBold: true).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
],
),
SizedBox(width: 8.h),
const Spacer(),
Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 18.h,
height: 13.h,
fit: BoxFit.contain,
).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "TAMARA";
openPaymentURL("tamara");
}),
],
),
), ),
), ),
), ),
@ -204,81 +203,79 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
), ),
child: Consumer<PayfortViewModel>(builder: (context, payfortVM, child) { child: Consumer<PayfortViewModel>(builder: (context, payfortVM, child) {
//TODO: Need to add loading state & animation for Apple Pay Configuration //TODO: Need to add loading state & animation for Apple Pay Configuration
return payfortVM.isApplePayConfigurationLoading return Column(
? const MoviesShimmerWidget().paddingAll(16.h) crossAxisAlignment: CrossAxisAlignment.start,
: Column( children: [
crossAxisAlignment: CrossAxisAlignment.start, (myAppointmentsVM.patientAppointmentShareResponseModel!.isCash ?? true)
children: [ ? Container(
(myAppointmentsVM.patientAppointmentShareResponseModel!.isCash ?? true) height: 50.h,
? Container( decoration: ShapeDecoration(
height: 50.h, color: AppColors.secondaryLightRedBorderColor,
decoration: ShapeDecoration( shape: SmoothRectangleBorder(
color: AppColors.secondaryLightRedBorderColor, borderRadius: BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24)),
shape: SmoothRectangleBorder( smoothness: 1,
borderRadius: BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24)), ),
smoothness: 1, ),
), child: Row(
), mainAxisAlignment: MainAxisAlignment.spaceBetween,
child: Row( children: [
mainAxisAlignment: MainAxisAlignment.spaceBetween, "Insurance expired or inactive".needTranslation.toText14(color: AppColors.primaryRedColor, weight: FontWeight.w500).paddingSymmetrical(24.h, 0.h),
children: [ CustomButton(
"Insurance expired or inactive".needTranslation.toText14(color: AppColors.primaryRedColor, weight: FontWeight.w500).paddingSymmetrical(24.h, 0.h), text: LocaleKeys.updateInsurance.tr(context: context),
CustomButton( onPressed: () {
text: LocaleKeys.updateInsurance.tr(context: context), Navigator.of(context).push(
onPressed: () { CustomPageRoute(
Navigator.of(context).push( page: InsuranceHomePage(),
FadePage( ),
page: InsuranceHomePage(), );
), },
); backgroundColor: AppColors.primaryRedColor,
}, borderColor: AppColors.secondaryLightRedBorderColor,
backgroundColor: AppColors.primaryRedColor, textColor: AppColors.whiteColor,
borderColor: AppColors.secondaryLightRedBorderColor, fontSize: 10,
textColor: AppColors.whiteColor, fontWeight: FontWeight.w500,
fontSize: 10, borderRadius: 8,
fontWeight: FontWeight.w500, padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
borderRadius: 8, height: 30.h,
padding: EdgeInsets.fromLTRB(15, 0, 15, 0), ).paddingSymmetrical(24.h, 0.h),
height: 30.h, ],
).paddingSymmetrical(24.h, 0.h), ),
], )
), : const SizedBox(),
) SizedBox(height: 24.h),
: const SizedBox(), "Total amount to pay".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 24.h), SizedBox(height: 17.h),
"Total amount to pay".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h), Row(
SizedBox(height: 17.h), mainAxisAlignment: MainAxisAlignment.spaceBetween,
Row( children: [
mainAxisAlignment: MainAxisAlignment.spaceBetween, "Total amount to pay".needTranslation.toText14(isBold: true),
children: [ Utils.getPaymentAmountWithSymbol(myAppointmentsVM.patientAppointmentShareResponseModel!.patientShare!.toString().toText16(isBold: true), AppColors.blackColor, 13,
"Total amount to pay".needTranslation.toText14(isBold: true), isSaudiCurrency: true),
Utils.getPaymentAmountWithSymbol(myAppointmentsVM.patientAppointmentShareResponseModel!.patientShare!.toString().toText16(isBold: true), AppColors.blackColor, 13, ],
isSaudiCurrency: true), ).paddingSymmetrical(24.h, 0.h),
], Row(
).paddingSymmetrical(24.h, 0.h), mainAxisAlignment: MainAxisAlignment.spaceBetween,
Row( children: [
mainAxisAlignment: MainAxisAlignment.spaceBetween, "VAT 15%".needTranslation.toText14(isBold: true, color: AppColors.greyTextColor),
children: [ Utils.getPaymentAmountWithSymbol(
"VAT 15%".needTranslation.toText14(isBold: true, color: AppColors.greyTextColor), myAppointmentsVM.patientAppointmentShareResponseModel!.patientTaxAmount!.toString().toText14(isBold: true, color: AppColors.greyTextColor),
Utils.getPaymentAmountWithSymbol( AppColors.greyTextColor,
myAppointmentsVM.patientAppointmentShareResponseModel!.patientTaxAmount!.toString().toText14(isBold: true, color: AppColors.greyTextColor), 13,
AppColors.greyTextColor, isSaudiCurrency: true),
13, ],
isSaudiCurrency: true), ).paddingSymmetrical(24.h, 0.h),
], SizedBox(height: 17.h),
).paddingSymmetrical(24.h, 0.h), Row(
SizedBox(height: 17.h), mainAxisAlignment: MainAxisAlignment.spaceBetween,
Row( children: [
mainAxisAlignment: MainAxisAlignment.spaceBetween, "".needTranslation.toText14(isBold: true),
children: [ Utils.getPaymentAmountWithSymbol(myAppointmentsVM.patientAppointmentShareResponseModel!.patientShareWithTax!.toString().toText24(isBold: true), AppColors.blackColor, 17,
"".needTranslation.toText14(isBold: true), isSaudiCurrency: true),
Utils.getPaymentAmountWithSymbol( ],
myAppointmentsVM.patientAppointmentShareResponseModel!.patientShareWithTax!.toString().toText24(isBold: true), AppColors.blackColor, 17, ).paddingSymmetrical(24.h, 0.h),
isSaudiCurrency: true), //TODO: Add Apple Pay Privileges
], Platform.isIOS
).paddingSymmetrical(24.h, 0.h), ? Utils.buildSvgWithAssets(
//TODO: Add Apple Pay Privileges
Utils.buildSvgWithAssets(
icon: AppAssets.apple_pay_button, icon: AppAssets.apple_pay_button,
width: 200.h, width: 200.h,
height: 80.h, height: 80.h,
@ -286,10 +283,11 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
).paddingSymmetrical(24.h, 0.h).onPress(() { ).paddingSymmetrical(24.h, 0.h).onPress(() {
// payfortVM.setIsApplePayConfigurationLoading(true); // payfortVM.setIsApplePayConfigurationLoading(true);
startApplePay(); startApplePay();
}), })
SizedBox(height: 12.h), : SizedBox(height: 12.h),
], SizedBox(height: 12.h),
); ],
);
}), }),
), ),
], ],
@ -389,12 +387,12 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
Navigator.of(context).pop(); Navigator.of(context).pop();
Navigator.pushAndRemoveUntil( Navigator.pushAndRemoveUntil(
context, context,
FadePage( CustomPageRoute(
page: LandingNavigation(), page: LandingNavigation(),
), ),
(r) => false); (r) => false);
Navigator.of(context).push( Navigator.of(context).push(
FadePage(page: MyAppointmentsPage()), CustomPageRoute(page: MyAppointmentsPage()),
); );
}); });
}); });
@ -528,6 +526,7 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
onSucceeded: (successResult) async { onSucceeded: (successResult) async {
Navigator.of(context).pop(); Navigator.of(context).pop();
log("successResult: ${successResult.responseMessage.toString()}"); log("successResult: ${successResult.responseMessage.toString()}");
selectedPaymentMethod = successResult.paymentOption ?? "VISA";
checkPaymentStatus(); checkPaymentStatus();
}, },
// projectId: appo.projectID, // projectId: appo.projectID,

@ -6,6 +6,7 @@ import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.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/lab/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
@ -53,7 +54,6 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
CustomTabBarModel(null, "Completed".needTranslation), CustomTabBarModel(null, "Completed".needTranslation),
], ],
onTabChange: (index) { onTabChange: (index) {
print(index);
myAppointmentsViewModel.onTabChange(index); myAppointmentsViewModel.onTabChange(index);
}, },
).paddingSymmetrical(24.h, 0.h), ).paddingSymmetrical(24.h, 0.h),
@ -86,7 +86,15 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
: 1, : 1,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return myAppointmentsVM.isMyAppointmentsLoading return myAppointmentsVM.isMyAppointmentsLoading
? const MoviesShimmerWidget().paddingSymmetrical(24.h, 0.h) ? Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
child: AppointmentCard(
patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel(),
myAppointmentsViewModel: myAppointmentsViewModel,
isLoading: true,
isFromHomePage: false,
),
).paddingSymmetrical(24.h, 0.h)
: myAppointmentsVM.patientAppointmentsHistoryList.isNotEmpty : myAppointmentsVM.patientAppointmentsHistoryList.isNotEmpty
? AnimationConfiguration.staggeredList( ? AnimationConfiguration.staggeredList(
position: index, position: index,
@ -101,6 +109,8 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
child: AppointmentCard( child: AppointmentCard(
patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index], patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index],
myAppointmentsViewModel: myAppointmentsViewModel, myAppointmentsViewModel: myAppointmentsViewModel,
isLoading: false,
isFromHomePage: false,
), ),
).paddingSymmetrical(24.h, 0.h), ).paddingSymmetrical(24.h, 0.h),
), ),

@ -16,14 +16,16 @@ import 'package:hmg_patient_app_new/presentation/appointments/appointment_detail
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/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:smooth_corner/smooth_corner.dart';
class AppointmentCard extends StatefulWidget { class AppointmentCard extends StatefulWidget {
AppointmentCard({super.key, required this.patientAppointmentHistoryResponseModel, required this.myAppointmentsViewModel}); AppointmentCard({super.key, required this.patientAppointmentHistoryResponseModel, required this.myAppointmentsViewModel, this.isLoading = false, this.isFromHomePage = false});
PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel; PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
MyAppointmentsViewModel myAppointmentsViewModel; MyAppointmentsViewModel myAppointmentsViewModel;
bool isLoading;
bool isFromHomePage;
@override @override
State<AppointmentCard> createState() => _AppointmentCardState(); State<AppointmentCard> createState() => _AppointmentCardState();
@ -37,7 +39,7 @@ class _AppointmentCardState extends State<AppointmentCard> {
onTap: () { onTap: () {
Navigator.of(context) Navigator.of(context)
.push( .push(
FadePage( CustomPageRoute(
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel), page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
), ),
) )
@ -65,9 +67,11 @@ class _AppointmentCardState extends State<AppointmentCard> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
CustomButton( CustomButton(
text: appState.isArabic() text: widget.isLoading
? widget.patientAppointmentHistoryResponseModel.isInOutPatientDescriptionN! ? "OutPatient"
: widget.patientAppointmentHistoryResponseModel.isInOutPatientDescription!, : appState.isArabic()
? widget.patientAppointmentHistoryResponseModel.isInOutPatientDescriptionN!
: widget.patientAppointmentHistoryResponseModel.isInOutPatientDescription!,
onPressed: () {}, onPressed: () {},
backgroundColor: AppColors.primaryRedColor.withOpacity(0.1), backgroundColor: AppColors.primaryRedColor.withOpacity(0.1),
borderColor: AppColors.primaryRedColor.withOpacity(0.0), borderColor: AppColors.primaryRedColor.withOpacity(0.0),
@ -84,7 +88,7 @@ class _AppointmentCardState extends State<AppointmentCard> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
CustomButton( CustomButton(
text: AppointmentType.getAppointmentStatusType(widget.patientAppointmentHistoryResponseModel.patientStatusType!), text: widget.isLoading ? "Booked" : AppointmentType.getAppointmentStatusType(widget.patientAppointmentHistoryResponseModel.patientStatusType!),
onPressed: () {}, onPressed: () {},
backgroundColor: AppColors.successColor.withOpacity(0.1), backgroundColor: AppColors.successColor.withOpacity(0.1),
borderColor: AppColors.successColor.withOpacity(0.0), borderColor: AppColors.successColor.withOpacity(0.0),
@ -98,11 +102,11 @@ class _AppointmentCardState extends State<AppointmentCard> {
], ],
), ),
], ],
), ).toShimmer2(isShow: widget.isLoading),
), ),
// TODO: Implement the logic to enable/disable the switch based on reminder status // TODO: Implement the logic to enable/disable the switch based on reminder status
AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel) AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel)
? SizedBox() ? SizedBox().toShimmer2(isShow: widget.isLoading)
: Switch( : Switch(
activeColor: AppColors.successColor, activeColor: AppColors.successColor,
activeTrackColor: AppColors.successColor.withValues(alpha: .15), activeTrackColor: AppColors.successColor.withValues(alpha: .15),
@ -114,13 +118,13 @@ class _AppointmentCardState extends State<AppointmentCard> {
return const Icon(Icons.close); // Icon when switch is OFF return const Icon(Icons.close); // Icon when switch is OFF
}, },
), ),
value: widget.patientAppointmentHistoryResponseModel.hasReminder!, value: widget.isLoading ? false : widget.patientAppointmentHistoryResponseModel.hasReminder!,
onChanged: (newValue) { onChanged: (newValue) {
setState(() { setState(() {
widget.myAppointmentsViewModel.setAppointmentReminder(newValue, widget.patientAppointmentHistoryResponseModel); widget.myAppointmentsViewModel.setAppointmentReminder(newValue, widget.patientAppointmentHistoryResponseModel);
}); });
}, },
), ).toShimmer2(isShow: widget.isLoading),
], ],
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@ -128,30 +132,38 @@ class _AppointmentCardState extends State<AppointmentCard> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Image.network( Image.network(
widget.patientAppointmentHistoryResponseModel.doctorImageURL!, widget.isLoading ? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png" : widget.patientAppointmentHistoryResponseModel.doctorImageURL!,
width: 63.h, width: 63.h,
height: 63.h, height: 63.h,
fit: BoxFit.fill, fit: BoxFit.fill,
).circle(100), ).circle(100).toShimmer2(isShow: widget.isLoading),
SizedBox(width: 16.h), SizedBox(width: 16.h),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
widget.patientAppointmentHistoryResponseModel.doctorNameObj!.toText16(isBold: true), (widget.isLoading ? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png" : widget.patientAppointmentHistoryResponseModel.doctorNameObj!)
.toText16(isBold: true)
.toShimmer2(isShow: widget.isLoading),
SizedBox(height: 8.h),
Wrap( Wrap(
direction: Axis.horizontal, direction: Axis.horizontal,
spacing: 3.h, spacing: 3.h,
runSpacing: 4.h, runSpacing: 4.h,
children: [ children: [
AppCustomChipWidget(labelText: widget.patientAppointmentHistoryResponseModel.clinicName!), widget.isFromHomePage ? SizedBox.shrink() : AppCustomChipWidget(labelText: widget.isLoading ? "Cardiology" : widget.patientAppointmentHistoryResponseModel.clinicName!).toShimmer2(isShow: widget.isLoading),
AppCustomChipWidget(labelText: widget.patientAppointmentHistoryResponseModel.projectName!), widget.isFromHomePage ? SizedBox.shrink() : AppCustomChipWidget(labelText: widget.isLoading ? "Olaya" : widget.patientAppointmentHistoryResponseModel.projectName!).toShimmer2(isShow: widget.isLoading),
AppCustomChipWidget( AppCustomChipWidget(
icon: AppAssets.appointment_calendar_icon, icon: AppAssets.appointment_calendar_icon,
labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(widget.patientAppointmentHistoryResponseModel.appointmentDate), false)), labelText:
widget.isLoading ? "Cardiology" : DateUtil.formatDateToDate(DateUtil.convertStringToDate(widget.patientAppointmentHistoryResponseModel.appointmentDate), false))
.toShimmer2(isShow: widget.isLoading),
AppCustomChipWidget( AppCustomChipWidget(
icon: AppAssets.appointment_time_icon, icon: AppAssets.appointment_time_icon,
labelText: DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(widget.patientAppointmentHistoryResponseModel.appointmentDate), false)), labelText: widget.isLoading
? "Cardiology"
: DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(widget.patientAppointmentHistoryResponseModel.appointmentDate), false))
.toShimmer2(isShow: widget.isLoading),
], ],
), ),
], ],
@ -165,12 +177,12 @@ class _AppointmentCardState extends State<AppointmentCard> {
Expanded( Expanded(
flex: 6, flex: 6,
child: AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel) child: AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel)
? getArrivedAppointmentButton() ? getArrivedAppointmentButton().toShimmer2(isShow: widget.isLoading)
: CustomButton( : CustomButton(
text: AppointmentType.getNextActionText(widget.patientAppointmentHistoryResponseModel.nextAction), text: AppointmentType.getNextActionText(widget.patientAppointmentHistoryResponseModel.nextAction),
onPressed: () { onPressed: () {
Navigator.of(context) Navigator.of(context)
.push(FadePage( .push(CustomPageRoute(
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel), page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
)) ))
.then((val) { .then((val) {
@ -188,8 +200,8 @@ class _AppointmentCardState extends State<AppointmentCard> {
height: 40.h, height: 40.h,
icon: AppointmentType.getNextActionIcon(widget.patientAppointmentHistoryResponseModel.nextAction), icon: AppointmentType.getNextActionIcon(widget.patientAppointmentHistoryResponseModel.nextAction),
iconColor: AppointmentType.getNextActionTextColor(widget.patientAppointmentHistoryResponseModel.nextAction), iconColor: AppointmentType.getNextActionTextColor(widget.patientAppointmentHistoryResponseModel.nextAction),
iconSize: 14.h, iconSize: 15.h,
), ).toShimmer2(isShow: widget.isLoading),
), ),
SizedBox(width: 8.h), SizedBox(width: 8.h),
Expanded( Expanded(
@ -210,10 +222,10 @@ class _AppointmentCardState extends State<AppointmentCard> {
fit: BoxFit.contain, fit: BoxFit.contain,
), ),
), ),
).onPress(() { ).toShimmer2(isShow: widget.isLoading).onPress(() {
Navigator.of(context) Navigator.of(context)
.push( .push(
FadePage( CustomPageRoute(
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel), page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
), ),
) )

@ -19,6 +19,7 @@ import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:barcode_scan2/barcode_scan2.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/nfc/nfc_reader_sheet.dart'; import 'package:hmg_patient_app_new/widgets/nfc/nfc_reader_sheet.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
class AppointmentCheckinBottomSheet extends StatelessWidget { class AppointmentCheckinBottomSheet extends StatelessWidget {
@ -51,7 +52,7 @@ class AppointmentCheckinBottomSheet extends StatelessWidget {
// navigationService: myAppointmentsViewModel.navigationService, // navigationService: myAppointmentsViewModel.navigationService,
// appState: myAppointmentsViewModel.appState, // appState: myAppointmentsViewModel.appState,
// ); // );
locationUtils.getCurrentLocation(callBack: (value) { locationUtils.getCurrentLocation(onSuccess: (value) {
projectDetailListModel = Utils.getProjectDetailObj(_appState, patientAppointmentHistoryResponseModel.projectID); projectDetailListModel = Utils.getProjectDetailObj(_appState, patientAppointmentHistoryResponseModel.projectID);
double dist = Utils.distance(value.latitude, value.longitude, double.parse(projectDetailListModel.latitude!), double.parse(projectDetailListModel.longitude!)).ceilToDouble() * 1000; double dist = Utils.distance(value.latitude, value.longitude, double.parse(projectDetailListModel.latitude!), double.parse(projectDetailListModel.longitude!)).ceilToDouble() * 1000;
print(dist); print(dist);
@ -110,12 +111,14 @@ class AppointmentCheckinBottomSheet extends StatelessWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Column( Expanded(
crossAxisAlignment: CrossAxisAlignment.start, child: Column(
children: [ crossAxisAlignment: CrossAxisAlignment.start,
title.toText16(isBold: true, color: AppColors.textColor), children: [
subTitle.toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor), title.toText16(isBold: true, color: AppColors.textColor),
], subTitle.toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
],
),
), ),
Utils.buildSvgWithAssets( Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon, icon: AppAssets.forward_arrow_icon,
@ -144,12 +147,12 @@ class AppointmentCheckinBottomSheet extends StatelessWidget {
Navigator.of(context).pop(); Navigator.of(context).pop();
Navigator.pushAndRemoveUntil( Navigator.pushAndRemoveUntil(
context, context,
FadePage( CustomPageRoute(
page: LandingNavigation(), page: LandingNavigation(),
), ),
(r) => false); (r) => false);
Navigator.of(context).push( Navigator.of(context).push(
FadePage(page: MyAppointmentsPage()), CustomPageRoute(page: MyAppointmentsPage()),
); );
}, isFullScreen: false); }, isFullScreen: false);
}, },

@ -93,7 +93,7 @@ class HospitalBottomSheetBody extends StatelessWidget {
?.hmcDoctorList?[index]; ?.hmcDoctorList?[index];
return HospitalListItem( return HospitalListItem(
hospitalData: hospital, hospitalData: hospital,
isLocationEnabled: appointmentsViewModel.getLocationStatus(), isLocationEnabled: appointmentsViewModel.isLocationEnabled(),
).onPress(() { ).onPress(() {
regionalViewModel.setHospitalModel(hospital); regionalViewModel.setHospitalModel(hospital);
regionalViewModel.setBottomSheetState(AppointmentViaRegionState.CLINIC_SELECTION); regionalViewModel.setBottomSheetState(AppointmentViaRegionState.CLINIC_SELECTION);

@ -43,9 +43,11 @@ class _RegisterNew extends State<RegisterNewStep2> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>(); AppState appState = getIt.get<AppState>();
var name = appState.getLanguageCode() == "en" var name = authVM!.isUserFromUAE()
? ("${appState.getNHICUserData.firstNameEn!.toUpperCase()} ${appState.getNHICUserData.lastNameEn!.toUpperCase()}") ? ""
: ("${appState.getNHICUserData.firstNameAr!.toUpperCase()} ${appState.getNHICUserData.lastNameAr!.toUpperCase()}"); : appState.getLanguageCode() == "en"
? ("${appState.getNHICUserData.firstNameEn!.toUpperCase()} ${appState.getNHICUserData.lastNameEn!.toUpperCase()}")
: ("${appState.getNHICUserData.firstNameAr!.toUpperCase()} ${appState.getNHICUserData.lastNameAr!.toUpperCase()}");
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
appBar: CustomAppBar( appBar: CustomAppBar(
@ -57,262 +59,273 @@ class _RegisterNew extends State<RegisterNewStep2> {
onLanguageChanged: (lang) {}, onLanguageChanged: (lang) {},
hideLogoAndLang: true, hideLogoAndLang: true,
), ),
body: SingleChildScrollView( body: GestureDetector(
reverse: false, onTap: () {
padding: EdgeInsets.only(left: 24.h, right: 24.h, top: 0.h), FocusScope.of(context).unfocus();
child: Column( },
crossAxisAlignment: CrossAxisAlignment.start, behavior: HitTestBehavior.translucent, // Ensures taps on empty space are detected
children: <Widget>[ child: SizedBox(
LocaleKeys.personalDetailsVerification.tr().toText26(color: AppColors.textColor, weight: FontWeight.w600, letterSpacing: -2), width: double.infinity,
SizedBox(height: 24.h), height: double.infinity,
Directionality( child: SingleChildScrollView(
textDirection: Directionality.of(context), reverse: false,
child: Container( padding: EdgeInsets.only(left: 24.h, right: 24.h, top: 0.h),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(24)), child: Column(
padding: EdgeInsets.only(left: 16.h, right: 16.h), crossAxisAlignment: CrossAxisAlignment.start,
child: Column( children: <Widget>[
LocaleKeys.personalDetailsVerification.tr().toText26(color: AppColors.textColor, weight: FontWeight.w600, letterSpacing: -2),
SizedBox(height: 24.h),
Container(
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(24)),
padding: EdgeInsets.only(left: 16.h, right: 16.h),
child: Column(
children: [
TextInputWidget(
labelText: authVM!.isUserFromUAE() ? LocaleKeys.fullName.tr() : LocaleKeys.name.tr(),
hintText: authVM!.isUserFromUAE() ? LocaleKeys.enterNameHere.tr() : (name),
controller: authVM!.isUserFromUAE() ? authVM!.nameController : null,
isEnable: true,
prefix: null,
isAllowRadius: false,
isBorderAllowed: false,
keyboardType: TextInputType.text,
// textInputAction: TextInputAction.done,
onSubmitted: (value) {
FocusScope.of(context).unfocus();
},
isAllowLeadingIcon: true,
isReadOnly: authVM!.isUserFromUAE() ? false : true,
leadingIcon: AppAssets.user_circle,
labelColor: AppColors.textColor,
).paddingSymmetrical(0.h, 16.h),
Divider(height: 1, color: AppColors.greyColor),
TextInputWidget(
labelText: LocaleKeys.nationalIdNumber.tr(),
hintText: authVM!.isUserFromUAE() ? appState.getUserRegistrationPayload.patientIdentificationId.toString() : (appState.getNHICUserData.idNumber ?? ""),
controller: null,
isEnable: true,
prefix: null,
isAllowRadius: false,
isBorderAllowed: false,
isAllowLeadingIcon: true,
isReadOnly: true,
labelColor: AppColors.textColor,
leadingIcon: AppAssets.student_card)
.paddingSymmetrical(0.h, 16.h),
Divider(height: 1, color: AppColors.greyColor),
authVM!.isUserFromUAE()
? Selector<AuthenticationViewModel, GenderTypeEnum?>(
selector: (_, authViewModel) => authViewModel.genderType,
shouldRebuild: (previous, next) => previous != next,
builder: (context, genderType, child) {
final authVM = context.read<AuthenticationViewModel>();
return DropdownWidget(
labelText: LocaleKeys.gender.tr(),
hintText: LocaleKeys.malE.tr(),
isEnable: true,
dropdownItems: GenderTypeEnum.values.map((e) => appState.isArabic() ? e.typeAr : e.type).toList(),
selectedValue: genderType != null ? (appState.isArabic() ? genderType.typeAr : genderType.type) : "",
onChange: authVM.onGenderChange,
isBorderAllowed: false,
hasSelectionCustomIcon: true,
isAllowRadius: false,
labelColor: AppColors.textColor,
padding: const EdgeInsets.only(top: 8, bottom: 8, left: 0, right: 0),
selectionCustomIcon: AppAssets.arrow_down,
leadingIcon: AppAssets.user_full,
).withVerticalPadding(8);
})
: TextInputWidget(
labelText: LocaleKeys.gender.tr(),
hintText: (appState.getNHICUserData.gender ?? ""),
controller: null,
isEnable: true,
prefix: null,
isAllowRadius: false,
isBorderAllowed: false,
isAllowLeadingIcon: true,
isReadOnly: authVM!.isUserFromUAE() ? false : true,
leadingIcon: AppAssets.user_full,
labelColor: AppColors.textColor,
onChange: (value) {})
.paddingSymmetrical(0.h, 16.h),
Divider(height: 1, color: AppColors.greyColor),
authVM!.isUserFromUAE()
? Selector<AuthenticationViewModel, MaritalStatusTypeEnum?>(
selector: (_, authViewModel) => authViewModel.maritalStatus,
shouldRebuild: (previous, next) => previous != next,
builder: (context, maritalStatus, child) {
final authVM = context.read<AuthenticationViewModel>(); // For onChange
return DropdownWidget(
labelText: LocaleKeys.maritalStatus.tr(),
hintText: LocaleKeys.married.tr(),
isEnable: true,
dropdownItems: MaritalStatusTypeEnum.values.map((e) => appState.isArabic() ? e.typeAr : e.type).toList(),
selectedValue: maritalStatus != null ? (appState.isArabic() ? maritalStatus.typeAr : maritalStatus.type) : "",
onChange: authVM.onMaritalStatusChange,
isBorderAllowed: false,
hasSelectionCustomIcon: true,
isAllowRadius: false,
labelColor: AppColors.textColor,
padding: const EdgeInsets.only(top: 8, bottom: 8, left: 0, right: 0),
selectionCustomIcon: AppAssets.arrow_down,
leadingIcon: AppAssets.smart_phone,
).withVerticalPadding(8);
},
)
: TextInputWidget(
labelText: LocaleKeys.maritalStatus.tr(),
hintText: appState.isArabic()
? (MaritalStatusTypeExtension.fromValue(appState.getNHICUserData.maritalStatusCode)!.typeAr)
: (MaritalStatusTypeExtension.fromValue(appState.getNHICUserData.maritalStatusCode)!.type),
isEnable: true,
prefix: null,
isAllowRadius: false,
isBorderAllowed: false,
isAllowLeadingIcon: true,
isReadOnly: true,
labelColor: AppColors.textColor,
leadingIcon: AppAssets.smart_phone,
onChange: (value) {})
.paddingSymmetrical(0.h, 16.h),
Divider(height: 1, color: AppColors.greyColor),
authVM!.isUserFromUAE()
? Selector<AuthenticationViewModel, ({List<NationalityCountries>? countriesList, NationalityCountries? selectedCountry, bool isArabic})>(
selector: (context, authViewModel) {
final appState = getIt.get<AppState>();
return (
countriesList: authViewModel.countriesList,
selectedCountry: authViewModel.pickedCountryByUAEUser,
isArabic: appState.isArabic(),
);
},
shouldRebuild: (previous, next) => previous.countriesList != next.countriesList || previous.selectedCountry != next.selectedCountry || previous.isArabic != next.isArabic,
builder: (context, data, child) {
final authVM = context.read<AuthenticationViewModel>();
return DropdownWidget(
labelText: LocaleKeys.country.tr(),
hintText: LocaleKeys.uae.tr(),
isEnable: true,
dropdownItems: (data.countriesList ?? []).map((e) => data.isArabic ? e.nameN ?? "" : e.name ?? "").toList(),
selectedValue: data.selectedCountry != null
? data.isArabic
? data.selectedCountry!.nameN ?? ""
: data.selectedCountry!.name ?? ""
: "",
onChange: authVM.onUAEUserCountrySelection,
isBorderAllowed: false,
hasSelectionCustomIcon: true,
labelColor: AppColors.textColor,
isAllowRadius: false,
padding: const EdgeInsets.only(top: 8, bottom: 8, left: 0, right: 0),
selectionCustomIcon: AppAssets.arrow_down,
leadingIcon: AppAssets.globe,
).withVerticalPadding(8);
},
)
: TextInputWidget(
labelText: LocaleKeys.nationality.tr(),
hintText: appState.isArabic()
? (authVM!.countriesList!.firstWhere((e) => e.id == (appState.getNHICUserData.nationalityCode ?? ""), orElse: () => NationalityCountries()).nameN ?? "")
: (authVM!.countriesList!.firstWhere((e) => e.id == (appState.getNHICUserData.nationalityCode ?? ""), orElse: () => NationalityCountries()).name ?? ""),
isEnable: true,
prefix: null,
isAllowRadius: false,
isBorderAllowed: false,
isAllowLeadingIcon: true,
isReadOnly: true,
labelColor: AppColors.textColor,
leadingIcon: AppAssets.globe,
onChange: (value) {})
.paddingSymmetrical(0.h, 16.h),
Divider(
height: 1,
color: AppColors.greyColor,
),
TextInputWidget(
labelText: LocaleKeys.mobileNumber.tr(),
hintText: (appState.getUserRegistrationPayload.patientMobileNumber.toString() ?? ""),
controller: null,
isEnable: false,
prefix: null,
isAllowRadius: false,
isBorderAllowed: false,
isAllowLeadingIcon: true,
labelColor: AppColors.textColor,
isReadOnly: true,
leadingIcon: AppAssets.call)
.paddingSymmetrical(0.h, 16.h),
Divider(
height: 1,
color: AppColors.greyColor,
),
TextInputWidget(
labelText: LocaleKeys.dob.tr(),
hintText: authVM!.isUserFromUAE() ? appState.getUserRegistrationPayload.dob! : appState.getNHICUserData.dateOfBirth ?? "",
controller: authVM!.isUserFromUAE() ? authVM!.dobController : null,
isEnable: false,
prefix: null,
isBorderAllowed: false,
isAllowLeadingIcon: true,
isReadOnly: true,
labelColor: AppColors.textColor,
leadingIcon: AppAssets.birthday_cake,
selectionType: null,
).paddingSymmetrical(0.h, 16.h),
],
),
),
SizedBox(height: 50.h),
Row(
children: [ children: [
TextInputWidget( Expanded(
labelText: authVM!.isUserFromUAE() ? LocaleKeys.fullName.tr() : LocaleKeys.name.tr(), child: CustomButton(
hintText: authVM!.isUserFromUAE() ? LocaleKeys.enterNameHere.tr() : (name), text: LocaleKeys.cancel.tr(),
controller: authVM!.isUserFromUAE() ? authVM!.nameController : null, icon: AppAssets.cancel,
isEnable: true, onPressed: () {
prefix: null, Navigator.of(context).pop();
isAllowRadius: false, // authVM!.clearDefaultInputValues();
isBorderAllowed: false, },
keyboardType: TextInputType.text, backgroundColor: AppColors.secondaryLightRedColor,
isAllowLeadingIcon: true, borderColor: AppColors.secondaryLightRedColor,
isReadOnly: authVM!.isUserFromUAE() ? false : true, textColor: AppColors.primaryRedColor,
leadingIcon: AppAssets.user_circle, iconColor: AppColors.primaryRedColor,
labelColor: AppColors.textColor, ),
).paddingSymmetrical(0.h, 16.h),
Divider(height: 1, color: AppColors.greyColor),
TextInputWidget(
labelText: LocaleKeys.nationalIdNumber.tr(),
hintText: authVM!.isUserFromUAE() ? appState.getUserRegistrationPayload.patientIdentificationId.toString() : (appState.getNHICUserData.idNumber ?? ""),
controller: null,
isEnable: true,
prefix: null,
isAllowRadius: false,
isBorderAllowed: false,
isAllowLeadingIcon: true,
isReadOnly: true,
labelColor: AppColors.textColor,
leadingIcon: AppAssets.student_card)
.paddingSymmetrical(0.h, 16.h),
Divider(height: 1, color: AppColors.greyColor),
authVM!.isUserFromUAE()
? Selector<AuthenticationViewModel, GenderTypeEnum?>(
selector: (_, authViewModel) => authViewModel.genderType,
shouldRebuild: (previous, next) => previous != next,
builder: (context, genderType, child) {
final authVM = context.read<AuthenticationViewModel>();
return DropdownWidget(
labelText: LocaleKeys.gender.tr(),
hintText: LocaleKeys.malE.tr(),
isEnable: true,
dropdownItems: GenderTypeEnum.values.map((e) => appState.isArabic() ? e.typeAr : e.type).toList(),
selectedValue: genderType != null ? (appState.isArabic() ? genderType.typeAr : genderType.type) : "",
onChange: authVM.onGenderChange,
isBorderAllowed: false,
hasSelectionCustomIcon: true,
isAllowRadius: false,
labelColor: AppColors.textColor,
padding: const EdgeInsets.only(top: 8, bottom: 8, left: 0, right: 0),
selectionCustomIcon: AppAssets.arrow_down,
leadingIcon: AppAssets.user_full,
).withVerticalPadding(8);
})
: TextInputWidget(
labelText: LocaleKeys.gender.tr(),
hintText: (appState.getNHICUserData.gender ?? ""),
controller: null,
isEnable: true,
prefix: null,
isAllowRadius: false,
isBorderAllowed: false,
isAllowLeadingIcon: true,
isReadOnly: authVM!.isUserFromUAE() ? false : true,
leadingIcon: AppAssets.user_full,
labelColor: AppColors.textColor,
onChange: (value) {})
.paddingSymmetrical(0.h, 16.h),
Divider(height: 1, color: AppColors.greyColor),
authVM!.isUserFromUAE()
? Selector<AuthenticationViewModel, MaritalStatusTypeEnum?>(
selector: (_, authViewModel) => authViewModel.maritalStatus,
shouldRebuild: (previous, next) => previous != next,
builder: (context, maritalStatus, child) {
final authVM = context.read<AuthenticationViewModel>(); // For onChange
return DropdownWidget(
labelText: LocaleKeys.maritalStatus.tr(),
hintText: LocaleKeys.married.tr(),
isEnable: true,
dropdownItems: MaritalStatusTypeEnum.values.map((e) => appState.isArabic() ? e.typeAr : e.type).toList(),
selectedValue: maritalStatus != null ? (appState.isArabic() ? maritalStatus.typeAr : maritalStatus.type) : "",
onChange: authVM.onMaritalStatusChange,
isBorderAllowed: false,
hasSelectionCustomIcon: true,
isAllowRadius: false,
labelColor: AppColors.textColor,
padding: const EdgeInsets.only(top: 8, bottom: 8, left: 0, right: 0),
selectionCustomIcon: AppAssets.arrow_down,
leadingIcon: AppAssets.smart_phone,
).withVerticalPadding(8);
},
)
: TextInputWidget(
labelText: LocaleKeys.maritalStatus.tr(),
hintText: appState.isArabic()
? (MaritalStatusTypeExtension.fromValue(appState.getNHICUserData.maritalStatusCode)!.typeAr)
: (MaritalStatusTypeExtension.fromValue(appState.getNHICUserData.maritalStatusCode)!.type),
isEnable: true,
prefix: null,
isAllowRadius: false,
isBorderAllowed: false,
isAllowLeadingIcon: true,
isReadOnly: true,
labelColor: AppColors.textColor,
leadingIcon: AppAssets.smart_phone,
onChange: (value) {})
.paddingSymmetrical(0.h, 16.h),
Divider(height: 1, color: AppColors.greyColor),
authVM!.isUserFromUAE()
? Selector<AuthenticationViewModel, ({List<NationalityCountries>? countriesList, NationalityCountries? selectedCountry, bool isArabic})>(
selector: (context, authViewModel) {
final appState = getIt.get<AppState>();
return (
countriesList: authViewModel.countriesList,
selectedCountry: authViewModel.pickedCountryByUAEUser,
isArabic: appState.isArabic(),
);
},
shouldRebuild: (previous, next) => previous.countriesList != next.countriesList || previous.selectedCountry != next.selectedCountry || previous.isArabic != next.isArabic,
builder: (context, data, child) {
final authVM = context.read<AuthenticationViewModel>();
return DropdownWidget(
labelText: LocaleKeys.country.tr(),
hintText: LocaleKeys.uae.tr(),
isEnable: true,
dropdownItems: (data.countriesList ?? []).map((e) => data.isArabic ? e.nameN ?? "" : e.name ?? "").toList(),
selectedValue: data.selectedCountry != null
? data.isArabic
? data.selectedCountry!.nameN ?? ""
: data.selectedCountry!.name ?? ""
: "",
onChange: authVM.onUAEUserCountrySelection,
isBorderAllowed: false,
hasSelectionCustomIcon: true,
labelColor: AppColors.textColor,
isAllowRadius: false,
padding: const EdgeInsets.only(top: 8, bottom: 8, left: 0, right: 0),
selectionCustomIcon: AppAssets.arrow_down,
leadingIcon: AppAssets.globe,
).withVerticalPadding(8);
},
)
: TextInputWidget(
labelText: LocaleKeys.nationality.tr(),
hintText: appState.isArabic()
? (authVM!.countriesList!.firstWhere((e) => e.id == (appState.getNHICUserData.nationalityCode ?? ""), orElse: () => NationalityCountries()).nameN ?? "")
: (authVM!.countriesList!.firstWhere((e) => e.id == (appState.getNHICUserData.nationalityCode ?? ""), orElse: () => NationalityCountries()).name ?? ""),
isEnable: true,
prefix: null,
isAllowRadius: false,
isBorderAllowed: false,
isAllowLeadingIcon: true,
isReadOnly: true,
labelColor: AppColors.textColor,
leadingIcon: AppAssets.globe,
onChange: (value) {})
.paddingSymmetrical(0.h, 16.h),
Divider(
height: 1,
color: AppColors.greyColor,
), ),
TextInputWidget( SizedBox(
labelText: LocaleKeys.mobileNumber.tr(), width: 16,
hintText: (appState.getUserRegistrationPayload.patientMobileNumber.toString() ?? ""),
controller: null,
isEnable: false,
prefix: null,
isAllowRadius: false,
isBorderAllowed: false,
isAllowLeadingIcon: true,
labelColor: AppColors.textColor,
isReadOnly: true,
leadingIcon: AppAssets.call)
.paddingSymmetrical(0.h, 16.h),
Divider(
height: 1,
color: AppColors.greyColor,
), ),
TextInputWidget( Expanded(
labelText: LocaleKeys.dob.tr(), child: CustomButton(
hintText: authVM!.isUserFromUAE() ? appState.getUserRegistrationPayload.dob! : appState.getNHICUserData.dateOfBirth ?? "", backgroundColor: AppColors.primaryRedColor,
controller: authVM!.isUserFromUAE() ? authVM!.dobController : null, borderColor: AppColors.primaryRedColor,
isEnable: false, textColor: AppColors.whiteColor,
prefix: null, text: LocaleKeys.confirm.tr(),
isBorderAllowed: false, icon: AppAssets.confirm,
isAllowLeadingIcon: true, iconColor: AppColors.whiteColor,
isReadOnly: true, onPressed: () {
labelColor: AppColors.textColor, if (appState.getUserRegistrationPayload.zipCode != CountryEnum.saudiArabia.countryCode) {
leadingIcon: AppAssets.birthday_cake, if (ValidationUtils.validateUaeRegistration(
selectionType: null, name: authVM!.nameController.text,
).paddingSymmetrical(0.h, 16.h), gender: authVM!.genderType,
country: authVM!.pickedCountryByUAEUser,
maritalStatus: authVM!.maritalStatus,
onOkPress: () {
Navigator.of(context).pop();
})) {
showModel(context: context);
}
} else {
showModel(context: context);
}
},
),
)
], ],
), ),
),
),
SizedBox(height: 50.h),
Row(
children: [
Expanded(
child: CustomButton(
text: LocaleKeys.cancel.tr(),
icon: AppAssets.cancel,
onPressed: () {
Navigator.of(context).pop();
// authVM!.clearDefaultInputValues();
},
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,
iconColor: AppColors.primaryRedColor,
),
),
SizedBox(
width: 16,
),
Expanded(
child: CustomButton(
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
text: LocaleKeys.confirm.tr(),
icon: AppAssets.confirm,
iconColor: AppColors.whiteColor,
onPressed: () {
if (appState.getUserRegistrationPayload.zipCode != CountryEnum.saudiArabia.countryCode) {
if (ValidationUtils.validateUaeRegistration(
name: authVM!.nameController.text,
gender: authVM!.genderType,
country: authVM!.pickedCountryByUAEUser,
maritalStatus: authVM!.maritalStatus,
onOkPress: () {
Navigator.of(context).pop();
})) {
showModel(context: context);
}
} else {
showModel(context: context);
}
},
),
)
], ],
), ),
], ),
), ),
), ),
); );

@ -65,14 +65,16 @@ class _SavedLogin extends State<SavedLogin> {
body: SafeArea( body: SafeArea(
child: Padding( child: Padding(
padding: EdgeInsets.symmetric(horizontal: 24.h), padding: EdgeInsets.symmetric(horizontal: 24.h),
child: Column( child: appState.getSelectDeviceByImeiRespModelElement != null ? Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
const Spacer(flex: 2), const Spacer(flex: 2),
// Welcome back text // Welcome back text
LocaleKeys.welcomeBack.tr().toText16(color: AppColors.inputLabelTextColor), LocaleKeys.welcomeBack.tr().toText16(color: AppColors.inputLabelTextColor),
SizedBox(height: 16.h), SizedBox(height: 16.h),
appState.getSelectDeviceByImeiRespModelElement!.name!.toCamelCase.toText26(isBold: true, height: 26 / 36, color: AppColors.textColor), appState.getSelectDeviceByImeiRespModelElement != null
? appState.getSelectDeviceByImeiRespModelElement!.name!.toCamelCase.toText26(isBold: true, height: 26 / 36, color: AppColors.textColor)
: SizedBox(),
SizedBox(height: 24.h), SizedBox(height: 24.h),
Container( Container(
padding: EdgeInsets.all(16.h), padding: EdgeInsets.all(16.h),
@ -89,15 +91,22 @@ class _SavedLogin extends State<SavedLogin> {
// Last login info // Last login info
("${LocaleKeys.lastLoginBy.tr()} ${loginType.displayName}").toText14(isBold: true, color: AppColors.greyTextColor, letterSpacing: -1), ("${LocaleKeys.lastLoginBy.tr()} ${loginType.displayName}").toText14(isBold: true, color: AppColors.greyTextColor, letterSpacing: -1),
(appState.getSelectDeviceByImeiRespModelElement!.createdOn != null appState.getSelectDeviceByImeiRespModelElement != null
? DateUtil.getFormattedDate(DateUtil.convertStringToDate(appState.getSelectDeviceByImeiRespModelElement!.createdOn!), "d MMMM, y 'at' HH:mm") ? (appState.getSelectDeviceByImeiRespModelElement!.createdOn != null
: '--') ? DateUtil.getFormattedDate(DateUtil.convertStringToDate(appState.getSelectDeviceByImeiRespModelElement!.createdOn!), "d MMMM, y 'at' HH:mm")
.toText16(isBold: true, color: AppColors.textColor), : '--')
.toText16(isBold: true, color: AppColors.textColor)
: SizedBox(),
Container( appState.getSelectDeviceByImeiRespModelElement != null
margin: EdgeInsets.all(16.h), ? Container(
child: Utils.buildSvgWithAssets( margin: EdgeInsets.all(16.h),
icon: getTypeIcons(appState.getSelectDeviceByImeiRespModelElement!.logInType!), height: 54, width: 54, iconColor: loginType.toInt == 4 ? null : AppColors.primaryRedColor)), child: Utils.buildSvgWithAssets(
icon: getTypeIcons(appState.getSelectDeviceByImeiRespModelElement!.logInType!),
height: 54,
width: 54,
iconColor: loginType.toInt == 4 ? null : AppColors.primaryRedColor))
: SizedBox(),
// Face ID login button // Face ID login button
SizedBox( SizedBox(
height: 45, height: 45,
@ -110,8 +119,8 @@ class _SavedLogin extends State<SavedLogin> {
authVm.checkUserAuthentication(otpTypeEnum: loginType == LoginTypeEnum.sms ? OTPTypeEnum.sms : OTPTypeEnum.whatsapp); authVm.checkUserAuthentication(otpTypeEnum: loginType == LoginTypeEnum.sms ? OTPTypeEnum.sms : OTPTypeEnum.whatsapp);
} }
}, },
backgroundColor: Color(0xffED1C2B), backgroundColor: AppColors.primaryRedColor,
borderColor: Color(0xffFEE9EA), borderColor: AppColors.primaryRedColor,
textColor: Colors.white, textColor: Colors.white,
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -297,7 +306,7 @@ class _SavedLogin extends State<SavedLogin> {
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
], ],
), ) : SizedBox.shrink(),
), ),
), ),
); );

@ -14,15 +14,14 @@ import 'package:hmg_patient_app_new/features/my_appointments/appointment_via_reg
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/faculity_selection/facility_type_selection_widget.dart'; import 'package:hmg_patient_app_new/presentation/appointments/widgets/faculity_selection/facility_type_selection_widget.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/region_bottomsheet/region_list_widget.dart' import 'package:hmg_patient_app_new/presentation/appointments/widgets/region_bottomsheet/region_list_widget.dart' show RegionBottomSheetBody;
show RegionBottomSheetBody;
import 'package:hmg_patient_app_new/presentation/book_appointment/search_doctor_by_name.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/search_doctor_by_name.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/select_clinic_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/select_clinic_page.dart';
import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart' import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart' show showCommonBottomSheetWithoutHeight;
show showCommonBottomSheetWithoutHeight;
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/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -44,6 +43,7 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
void initState() { void initState() {
scheduleMicrotask(() { scheduleMicrotask(() {
bookAppointmentsViewModel.initBookAppointmentViewModel(); bookAppointmentsViewModel.initBookAppointmentViewModel();
bookAppointmentsViewModel.getLocation();
}); });
super.initState(); super.initState();
} }
@ -52,13 +52,12 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
bookAppointmentsViewModel = Provider.of<BookAppointmentsViewModel>(context, listen: false); bookAppointmentsViewModel = Provider.of<BookAppointmentsViewModel>(context, listen: false);
appState = getIt.get<AppState>(); appState = getIt.get<AppState>();
regionalViewModel = regionalViewModel = Provider.of<AppointmentViaRegionViewmodel>(context, listen: true);
Provider.of<AppointmentViaRegionViewmodel>(context, listen: true);
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
body: CollapsingListView( body: CollapsingListView(
title: LocaleKeys.bookAppo.tr(context: context), title: LocaleKeys.bookAppo.tr(context: context),
isLeading: false, isLeading: Navigator.canPop(context),
child: SingleChildScrollView( child: SingleChildScrollView(
child: Consumer<BookAppointmentsViewModel>(builder: (context, bookAppointmentsVM, child) { child: Consumer<BookAppointmentsViewModel>(builder: (context, bookAppointmentsVM, child) {
return Column( return Column(
@ -125,7 +124,7 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
bookAppointmentsViewModel.setLoadSpecificClinic(false); bookAppointmentsViewModel.setLoadSpecificClinic(false);
bookAppointmentsViewModel.setProjectID(null); bookAppointmentsViewModel.setProjectID(null);
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: SelectClinicPage(), page: SelectClinicPage(),
), ),
); );
@ -154,7 +153,7 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
).onPress(() { ).onPress(() {
bookAppointmentsViewModel.setIsDoctorSearchByNameStarted(false); bookAppointmentsViewModel.setIsDoctorSearchByNameStarted(false);
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: SearchDoctorByName(), page: SearchDoctorByName(),
), ),
); );
@ -198,24 +197,21 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
void openRegionListBottomSheet(BuildContext context) { void openRegionListBottomSheet(BuildContext context) {
regionalViewModel.flush(); regionalViewModel.flush();
// AppointmentViaRegionViewmodel? viewmodel = null; // AppointmentViaRegionViewmodel? viewmodel = null;
showCommonBottomSheetWithoutHeight(context, showCommonBottomSheetWithoutHeight(context, title: "", titleWidget: Consumer<AppointmentViaRegionViewmodel>(builder: (_, data, __) => getTitle(data)), isDismissible: false,
title: "",
titleWidget: Consumer<AppointmentViaRegionViewmodel>(
builder: (_, data, __) => getTitle(data)),
isDismissible: false,
child: Consumer<AppointmentViaRegionViewmodel>(builder: (_, data, __) { child: Consumer<AppointmentViaRegionViewmodel>(builder: (_, data, __) {
return getRegionalSelectionWidget(data); return getRegionalSelectionWidget(data);
}), callBackFunc: () { }), callBackFunc: () {});
});
} }
Widget getRegionalSelectionWidget(AppointmentViaRegionViewmodel data) { Widget getRegionalSelectionWidget(AppointmentViaRegionViewmodel data) {
if (data.bottomSheetState == AppointmentViaRegionState.REGION_SELECTION) { if (data.bottomSheetState == AppointmentViaRegionState.REGION_SELECTION) {
return RegionBottomSheetBody(); return RegionBottomSheetBody();
} }
if(data.bottomSheetState == AppointmentViaRegionState.TYPE_SELECTION){ if (data.bottomSheetState == AppointmentViaRegionState.TYPE_SELECTION) {
bookAppointmentsViewModel.resetFilterList(); bookAppointmentsViewModel.resetFilterList();
return FacilityTypeSelectionWidget(selectedRegion: data.selectedRegionId??"",); return FacilityTypeSelectionWidget(
selectedRegion: data.selectedRegionId ?? "",
);
} }
if (data.bottomSheetState == AppointmentViaRegionState.HOSPITAL_SELECTION) { if (data.bottomSheetState == AppointmentViaRegionState.HOSPITAL_SELECTION) {
return HospitalBottomSheetBody(); return HospitalBottomSheetBody();
@ -225,9 +221,7 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
bookAppointmentsViewModel.setIsClinicsListLoading(true); bookAppointmentsViewModel.setIsClinicsListLoading(true);
bookAppointmentsViewModel.setLoadSpecificClinic(true); bookAppointmentsViewModel.setLoadSpecificClinic(true);
bookAppointmentsViewModel.setProjectID(regionalViewModel.selectedHospital?.hospitalList.first?.mainProjectID.toString()); bookAppointmentsViewModel.setProjectID(regionalViewModel.selectedHospital?.hospitalList.first?.mainProjectID.toString());
} else {
}
else {
SizedBox.shrink(); SizedBox.shrink();
} }
return SizedBox.shrink(); return SizedBox.shrink();
@ -237,9 +231,7 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
if (data.selectedRegionId == null) { if (data.selectedRegionId == null) {
return LocaleKeys.selectRegion.tr().toText20(weight: FontWeight.w600); return LocaleKeys.selectRegion.tr().toText20(weight: FontWeight.w600);
} else { } else {
return Utils.buildSvgWithAssets( return Utils.buildSvgWithAssets(icon: AppAssets.arrow_back, iconColor: Color(0xff2B353E)).onPress(() {
icon: AppAssets.arrow_back, iconColor: Color(0xff2B353E))
.onPress(() {
data.handleBackPress(); data.handleBackPress();
}); });
} }

@ -16,6 +16,7 @@ import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.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/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -214,7 +215,7 @@ class _ReviewAppointmentPageState extends State<ReviewAppointmentPage> {
LoadingUtils.hideFullScreenLoader(); LoadingUtils.hideFullScreenLoader();
Navigator.pushAndRemoveUntil( Navigator.pushAndRemoveUntil(
context, context,
FadePage( CustomPageRoute(
page: LandingNavigation(), page: LandingNavigation(),
), ),
(r) => false); (r) => false);

@ -18,6 +18,7 @@ import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart'; import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -122,7 +123,7 @@ class _SearchDoctorByNameState extends State<SearchDoctorByName> {
await bookAppointmentsVM.getDoctorProfile(onSuccess: (dynamic respData) { await bookAppointmentsVM.getDoctorProfile(onSuccess: (dynamic respData) {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: DoctorProfilePage(), page: DoctorProfilePage(),
), ),
); );

@ -19,6 +19,7 @@ import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/clinic
import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart'; import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -141,13 +142,13 @@ class _SelectClinicPageState extends State<SelectClinicPage> {
bookAppointmentsViewModel.setIsDoctorsListLoading(true); bookAppointmentsViewModel.setIsDoctorsListLoading(true);
if (clinic.isLiveCareClinicAndOnline ?? false) { if (clinic.isLiveCareClinicAndOnline ?? false) {
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: SelectLivecareClinicPage(), page: SelectLivecareClinicPage(),
), ),
); );
} else { } else {
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: SelectDoctorPage(), page: SelectDoctorPage(),
), ),
); );

@ -20,6 +20,7 @@ import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart'; import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -124,7 +125,7 @@ class _SelectDoctorPageState extends State<SelectDoctorPage> {
await bookAppointmentsVM.getDoctorProfile(onSuccess: (dynamic respData) { await bookAppointmentsVM.getDoctorProfile(onSuccess: (dynamic respData) {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: DoctorProfilePage(), page: DoctorProfilePage(),
), ),
); );

@ -10,6 +10,7 @@ import 'package:hmg_patient_app_new/presentation/book_appointment/select_doctor_
import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.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/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
class SelectLivecareClinicPage extends StatelessWidget { class SelectLivecareClinicPage extends StatelessWidget {
@ -122,7 +123,7 @@ class SelectLivecareClinicPage extends StatelessWidget {
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: SelectDoctorPage(), page: SelectDoctorPage(),
), ),
); );

@ -19,6 +19,7 @@ import 'package:hmg_patient_app_new/presentation/home/navigation_screen.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/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:lottie/lottie.dart'; import 'package:lottie/lottie.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -106,7 +107,7 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
), ),
view: CalendarView.month, view: CalendarView.month,
todayHighlightColor: Colors.transparent, todayHighlightColor: Colors.transparent,
todayTextStyle: TextStyle(color: AppColors.textColor), todayTextStyle: TextStyle(color: AppColors.textColor, fontWeight: FontWeight.bold),
selectionDecoration: ShapeDecoration( selectionDecoration: ShapeDecoration(
color: AppColors.transparent, color: AppColors.transparent,
shape: SmoothRectangleBorder( shape: SmoothRectangleBorder(
@ -151,8 +152,8 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
child: Wrap( child: Wrap(
direction: Axis.horizontal, direction: Axis.horizontal,
alignment: WrapAlignment.start, alignment: WrapAlignment.start,
spacing: 8.h, spacing: 6.h,
runSpacing: 8.h, runSpacing: 6.h,
children: List.generate( children: List.generate(
dayEvents.length, // Generate a large number of items to ensure scrolling dayEvents.length, // Generate a large number of items to ensure scrolling
(index) => TimeSlotChip( (index) => TimeSlotChip(
@ -177,7 +178,7 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
bookAppointmentsViewModel.setSelectedAppointmentDateTime(selectedDate, selectedTime); bookAppointmentsViewModel.setSelectedAppointmentDateTime(selectedDate, selectedTime);
Navigator.of(context).pop(); Navigator.of(context).pop();
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: ReviewAppointmentPage(), page: ReviewAppointmentPage(),
), ),
); );
@ -216,7 +217,7 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
Navigator.of(context).pop(); Navigator.of(context).pop();
Navigator.pushAndRemoveUntil( Navigator.pushAndRemoveUntil(
context, context,
FadePage( CustomPageRoute(
page: LandingNavigation(), page: LandingNavigation(),
), ),
(r) => false); (r) => false);
@ -320,7 +321,7 @@ class TimeSlotChip extends StatelessWidget {
return GestureDetector( return GestureDetector(
onTap: onTap, onTap: onTap,
child: Container( child: Container(
padding: EdgeInsets.symmetric(horizontal: 18.h, vertical: 8.h), padding: EdgeInsets.symmetric(horizontal: 14.h, vertical: 8.h),
decoration: ShapeDecoration( decoration: ShapeDecoration(
color: AppColors.whiteColor, color: AppColors.whiteColor,
shape: SmoothRectangleBorder( shape: SmoothRectangleBorder(

@ -13,6 +13,7 @@ import 'package:hmg_patient_app_new/presentation/habib_wallet/recharge_wallet_pa
import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.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/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -84,7 +85,7 @@ class _HabibWalletState extends State<HabibWalletPage> {
text: "Recharge".needTranslation, text: "Recharge".needTranslation,
onPressed: () { onPressed: () {
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: RechargeWalletPage(), page: RechargeWalletPage(),
), ),
); );

@ -80,7 +80,7 @@ class LandingPageData {
), ),
ServiceCardData( ServiceCardData(
serviceName: "lab_results", serviceName: "lab_results",
icon: AppAssets.lab_result_icon, icon: AppAssets.home_lab_result_icon,
title: "My Lab", title: "My Lab",
subtitle: "Results", subtitle: "Results",
backgroundColor: AppColors.whiteColor, backgroundColor: AppColors.whiteColor,
@ -90,7 +90,7 @@ class LandingPageData {
), ),
ServiceCardData( ServiceCardData(
serviceName: "radiology_results", serviceName: "radiology_results",
icon: AppAssets.lab_result_icon, icon: AppAssets.home_lab_result_icon,
title: "My Radiology", title: "My Radiology",
subtitle: "Results", subtitle: "Results",
backgroundColor: AppColors.whiteColor, backgroundColor: AppColors.whiteColor,

@ -3,6 +3,7 @@ import 'dart:async';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:flutter_swiper_view/flutter_swiper_view.dart';
import 'package:get_it/get_it.dart'; import 'package:get_it/get_it.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/app_state.dart';
@ -15,9 +16,12 @@ 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/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart'; import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart'; import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/my_appointments_page.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_card.dart';
import 'package:hmg_patient_app_new/presentation/authentication/quick_login.dart'; import 'package:hmg_patient_app_new/presentation/authentication/quick_login.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/presentation/home/data/landing_page_data.dart'; import 'package:hmg_patient_app_new/presentation/home/data/landing_page_data.dart';
@ -34,6 +38,7 @@ import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart' show CustomTabBar; import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart' show CustomTabBar;
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/routes/spring_page_route_builder.dart'; import 'package:hmg_patient_app_new/widgets/routes/spring_page_route_builder.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -55,6 +60,8 @@ class _LandingPageState extends State<LandingPage> {
late PrescriptionsViewModel prescriptionsViewModel; late PrescriptionsViewModel prescriptionsViewModel;
final CacheService cacheService = GetIt.instance<CacheService>(); final CacheService cacheService = GetIt.instance<CacheService>();
final SwiperController _controller = SwiperController();
@override @override
void initState() { void initState() {
authVM = context.read<AuthenticationViewModel>(); authVM = context.read<AuthenticationViewModel>();
@ -87,7 +94,7 @@ class _LandingPageState extends State<LandingPage> {
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
body: SingleChildScrollView( body: SingleChildScrollView(
padding: EdgeInsets.only(top: kToolbarHeight + 12.h, bottom: 24), padding: EdgeInsets.only(top: kToolbarHeight + 0.h, bottom: 24),
child: Column( child: Column(
spacing: 16.h, spacing: 16.h,
children: [ children: [
@ -123,7 +130,7 @@ class _LandingPageState extends State<LandingPage> {
children: [ children: [
Utils.buildSvgWithAssets(icon: AppAssets.bell, height: 20, width: 20).onPress(() { Utils.buildSvgWithAssets(icon: AppAssets.bell, height: 20, width: 20).onPress(() {
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: MedicalFilePage(), page: MedicalFilePage(),
// page: LoginScreen(), // page: LoginScreen(),
), ),
@ -131,7 +138,7 @@ class _LandingPageState extends State<LandingPage> {
}), }),
Utils.buildSvgWithAssets(icon: AppAssets.search_icon, height: 20, width: 20).onPress(() { Utils.buildSvgWithAssets(icon: AppAssets.search_icon, height: 20, width: 20).onPress(() {
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: MedicalFilePage(), page: MedicalFilePage(),
// page: LoginScreen(), // page: LoginScreen(),
), ),
@ -139,7 +146,7 @@ class _LandingPageState extends State<LandingPage> {
}), }),
Utils.buildSvgWithAssets(icon: AppAssets.contact_icon, height: 20, width: 20).onPress(() { Utils.buildSvgWithAssets(icon: AppAssets.contact_icon, height: 20, width: 20).onPress(() {
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: MedicalFilePage(), page: MedicalFilePage(),
// page: LoginScreen(), // page: LoginScreen(),
), ),
@ -152,44 +159,115 @@ class _LandingPageState extends State<LandingPage> {
appState.isAuthenticated appState.isAuthenticated
? Column( ? Column(
children: [ children: [
Container( SizedBox(height: 12.h),
width: double.infinity, Row(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( mainAxisAlignment: MainAxisAlignment.spaceBetween,
color: AppColors.whiteColor, children: [
borderRadius: 24, "Appointments & Visits".toText16(isBold: true),
), Row(
child: Padding(
padding: EdgeInsets.all(12.h),
child: Column(
children: [ children: [
Utils.buildSvgWithAssets(icon: AppAssets.home_calendar_icon, width: 32.h, height: 32.h), LocaleKeys.viewAll.tr(context: context).toText12(color: AppColors.primaryRedColor),
SizedBox(height: 12.h), SizedBox(width: 2.h),
"You do not have any upcoming appointment. Please book an appointment".toText12(isCenter: true), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
SizedBox(height: 12.h),
CustomButton(
text: LocaleKeys.bookAppo.tr(context: context),
onPressed: () {
Navigator.of(context).push(
FadePage(
page: BookAppointmentPage(),
),
);
},
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Color(0xffED1C2B),
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40,
icon: AppAssets.add_icon,
iconColor: AppColors.primaryRedColor,
),
], ],
), ),
), ],
).paddingSymmetrical(24.h, 0.h), ).paddingSymmetrical(24.h, 0.h).onPress(() {
Navigator.of(context).push(
CustomPageRoute(
page: MyAppointmentsPage(),
),
);
}),
SizedBox(height: 12.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,
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,
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 - 72,
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),
child: AppointmentCard(
patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index],
myAppointmentsViewModel: myAppointmentsViewModel,
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(),
),
);
},
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Color(0xffED1C2B),
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40,
icon: AppAssets.add_icon,
iconColor: AppColors.primaryRedColor,
),
],
),
),
).paddingSymmetrical(24.h, 0.h);
}),
SizedBox(height: 12.h), SizedBox(height: 12.h),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -205,7 +283,7 @@ class _LandingPageState extends State<LandingPage> {
], ],
).paddingSymmetrical(24.h, 0.h).onPress(() { ).paddingSymmetrical(24.h, 0.h).onPress(() {
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: MedicalFilePage(), page: MedicalFilePage(),
), ),
); );

@ -8,6 +8,7 @@ import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_mode
import 'package:hmg_patient_app_new/presentation/habib_wallet/habib_wallet_page.dart'; import 'package:hmg_patient_app_new/presentation/habib_wallet/habib_wallet_page.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/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -98,7 +99,7 @@ class HabibWalletCard extends StatelessWidget {
], ],
).onPress(() { ).onPress(() {
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: HabibWalletPage(), page: HabibWalletPage(),
), ),
); );

@ -7,6 +7,7 @@ import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.d
import 'package:hmg_patient_app_new/presentation/lab/lab_orders_page.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_orders_page.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/patient_sickleaves_list_page.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/patient_sickleaves_list_page.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescriptions_list_page.dart'; import 'package:hmg_patient_app_new/presentation/prescriptions/prescriptions_list_page.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import '../../../core/utils/utils.dart'; import '../../../core/utils/utils.dart';
@ -61,28 +62,28 @@ class SmallServiceCard extends StatelessWidget {
switch (serviceName) { switch (serviceName) {
case "lab_results": case "lab_results":
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: LabOrdersPage(), page: LabOrdersPage(),
), ),
); );
break; break;
case "radiology_results": case "radiology_results":
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: RadiologyOrdersPage(), page: RadiologyOrdersPage(),
), ),
); );
break; break;
case "prescriptions": case "prescriptions":
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: PrescriptionsListPage(), page: PrescriptionsListPage(),
), ),
); );
break; break;
case "insurance_update": case "insurance_update":
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: InsuranceHomePage(), page: InsuranceHomePage(),
), ),
); );
@ -90,7 +91,7 @@ class SmallServiceCard extends StatelessWidget {
case "my_doctors": case "my_doctors":
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: MyDoctorsPage(), page: MyDoctorsPage(),
), ),
); );
@ -98,7 +99,7 @@ class SmallServiceCard extends StatelessWidget {
case "sick_leaves": case "sick_leaves":
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: PatientSickleavesListPage(), page: PatientSickleavesListPage(),
), ),
); );

@ -37,8 +37,9 @@ class WelcomeWidget extends StatelessWidget {
Row( Row(
spacing: 4.h, spacing: 4.h,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [ children: [
name.toText16(weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1, height: 1).expanded, Flexible(child: name.toText16(weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1, height: 1)),
const Icon(Icons.keyboard_arrow_down, size: 20, color: Colors.black), const Icon(Icons.keyboard_arrow_down, size: 20, color: Colors.black),
], ],
), ),

@ -42,6 +42,7 @@ import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart'; import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/my_family/my_family_sheet.dart'; import 'package:hmg_patient_app_new/widgets/my_family/my_family_sheet.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart'; import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -72,7 +73,6 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
insuranceViewModel.initInsuranceProvider(); insuranceViewModel.initInsuranceProvider();
medicalFileViewModel.setIsPatientSickLeaveListLoading(true); medicalFileViewModel.setIsPatientSickLeaveListLoading(true);
medicalFileViewModel.getPatientSickLeaveList(); medicalFileViewModel.getPatientSickLeaveList();
medicalFileViewModel.getFamilyFiles();
medicalFileViewModel.onTabChanged(0); medicalFileViewModel.onTabChanged(0);
} }
}); });
@ -324,7 +324,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
], ],
).paddingSymmetrical(24.h, 0.h).onPress(() { ).paddingSymmetrical(24.h, 0.h).onPress(() {
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: MyAppointmentsPage(), page: MyAppointmentsPage(),
), ),
); );
@ -425,8 +425,8 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
children: [ children: [
Image.network( Image.network(
prescriptionVM.patientPrescriptionOrders[index].doctorImageURL!, prescriptionVM.patientPrescriptionOrders[index].doctorImageURL!,
width: 63.h, width: 40.h,
height: 63.h, height: 40.h,
fit: BoxFit.fill, fit: BoxFit.fill,
).circle(100), ).circle(100),
SizedBox(width: 16.h), SizedBox(width: 16.h),
@ -451,13 +451,13 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
], ],
), ),
), ),
SizedBox(width: 40.h), // SizedBox(width: 40.h),
Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor), Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor),
], ],
).onPress(() { ).onPress(() {
prescriptionVM.setPrescriptionsDetailsLoading(); prescriptionVM.setPrescriptionsDetailsLoading();
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: PrescriptionDetailPage(prescriptionsResponseModel: prescriptionVM.patientPrescriptionOrders[index]), page: PrescriptionDetailPage(prescriptionsResponseModel: prescriptionVM.patientPrescriptionOrders[index]),
), ),
); );
@ -478,7 +478,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
text: "All Prescriptions".needTranslation, text: "All Prescriptions".needTranslation,
onPressed: () { onPressed: () {
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: PrescriptionsListPage(), page: PrescriptionsListPage(),
), ),
); );
@ -536,7 +536,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
myAppointmentsViewModel.setIsPatientMyDoctorsLoading(true); myAppointmentsViewModel.setIsPatientMyDoctorsLoading(true);
myAppointmentsViewModel.getPatientMyDoctors(); myAppointmentsViewModel.getPatientMyDoctors();
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: MyDoctorsPage(), page: MyDoctorsPage(),
), ),
); );
@ -641,7 +641,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
iconSize: 40.h, iconSize: 40.h,
).onPress(() { ).onPress(() {
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: VaccineListPage(), page: VaccineListPage(),
), ),
); );
@ -683,7 +683,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
iconSize: 36.h) iconSize: 36.h)
.onPress(() { .onPress(() {
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: InsuranceHomePage(), page: InsuranceHomePage(),
), ),
); );
@ -757,7 +757,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
medicalFileViewModel.setIsPatientMedicalReportsLoading(true); medicalFileViewModel.setIsPatientMedicalReportsLoading(true);
medicalFileViewModel.getPatientMedicalReportList(); medicalFileViewModel.getPatientMedicalReportList();
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: MedicalReportsPage(), page: MedicalReportsPage(),
), ),
); );
@ -771,7 +771,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
iconSize: 40.h, iconSize: 40.h,
).onPress(() { ).onPress(() {
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: PatientSickleavesListPage(), page: PatientSickleavesListPage(),
), ),
); );

@ -13,6 +13,7 @@ import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/appointment_details_page.dart'; import 'package:hmg_patient_app_new/presentation/appointments/appointment_details_page.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/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
class MedicalFileAppointmentCard extends StatelessWidget { class MedicalFileAppointmentCard extends StatelessWidget {
@ -86,7 +87,7 @@ class MedicalFileAppointmentCard extends StatelessWidget {
text: AppointmentType.getNextActionText(patientAppointmentHistoryResponseModel.nextAction), text: AppointmentType.getNextActionText(patientAppointmentHistoryResponseModel.nextAction),
onPressed: () { onPressed: () {
Navigator.of(context) Navigator.of(context)
.push(FadePage( .push(CustomPageRoute(
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel), page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel),
)) ))
.then((val) { .then((val) {
@ -129,7 +130,7 @@ class MedicalFileAppointmentCard extends StatelessWidget {
).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading).onPress(() { ).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading).onPress(() {
Navigator.of(context) Navigator.of(context)
.push( .push(
FadePage( CustomPageRoute(
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel), page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel),
), ),
) )

@ -17,6 +17,7 @@ import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:open_filex/open_filex.dart'; import 'package:open_filex/open_filex.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -147,7 +148,7 @@ class PatientSickLeaveCard extends StatelessWidget {
), ),
).toShimmer2(isShow: isLoading).onPress(() { ).toShimmer2(isShow: isLoading).onPress(() {
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: PatientSickleavesListPage(), page: PatientSickleavesListPage(),
), ),
); );

@ -15,6 +15,7 @@ import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_detail_page.dart'; import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_detail_page.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/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart'; import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -258,7 +259,7 @@ class _PrescriptionsListPageState extends State<PrescriptionsListPage> {
).onPress(() { ).onPress(() {
model.setPrescriptionsDetailsLoading(); model.setPrescriptionsDetailsLoading();
Navigator.of(context).push( Navigator.of(context).push(
FadePage( CustomPageRoute(
page: PrescriptionDetailPage(prescriptionsResponseModel: prescription), page: PrescriptionDetailPage(prescriptionsResponseModel: prescription),
), ),
); );

@ -115,7 +115,7 @@ class _ProfileSettingsState extends State<ProfileSettings> {
iconSize: 24.h, iconSize: 24.h,
iconColor: AppColors.infoColor, iconColor: AppColors.infoColor,
textColor: AppColors.infoColor, textColor: AppColors.infoColor,
text: "Recharge", text: "Recharge".needTranslation,
borderWidth: 0.h, borderWidth: 0.h,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
borderColor: Colors.transparent, borderColor: Colors.transparent,

@ -12,8 +12,11 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/presentation/radiology/radiology_result_page.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/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart'; import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -49,156 +52,143 @@ class _RadiologyOrdersPageState extends State<RadiologyOrdersPage> {
child: SingleChildScrollView( child: SingleChildScrollView(
child: Consumer<RadiologyViewModel>( child: Consumer<RadiologyViewModel>(
builder: (context, model, child) { builder: (context, model, child) {
return Column( return Padding(
crossAxisAlignment: CrossAxisAlignment.start, padding: EdgeInsets.symmetric(horizontal: 24.h),
children: [ child: Column(
SizedBox(height: 16.h), crossAxisAlignment: CrossAxisAlignment.start,
// Expandable list children: [
ListView.builder( // Expandable list
shrinkWrap: true, ListView.builder(
physics: NeverScrollableScrollPhysics(), shrinkWrap: true,
itemCount: model.isRadiologyOrdersLoading ? 5 : model.patientRadiologyOrders.length, physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) { itemCount: model.isRadiologyOrdersLoading ? 5 : model.patientRadiologyOrders.length,
final isExpanded = expandedIndex == index; itemBuilder: (context, index) {
return model.isRadiologyOrdersLoading final isExpanded = expandedIndex == index;
? const MoviesShimmerWidget() return AnimationConfiguration.staggeredList(
: AnimationConfiguration.staggeredList( position: index,
position: index, duration: const Duration(milliseconds: 500),
duration: const Duration(milliseconds: 500), child: SlideAnimation(
child: SlideAnimation( verticalOffset: 100.0,
verticalOffset: 100.0, child: FadeInAnimation(
child: FadeInAnimation( child: AnimatedContainer(
child: AnimatedContainer( duration: Duration(milliseconds: 300),
duration: Duration(milliseconds: 300), curve: Curves.easeInOut,
curve: Curves.easeInOut, margin: EdgeInsets.symmetric(vertical: 8.h),
margin: EdgeInsets.symmetric(vertical: 8.h), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), child: InkWell(
child: InkWell( onTap: () {
onTap: () { setState(() {
setState(() { expandedIndex = isExpanded ? null : index;
expandedIndex = isExpanded ? null : index; });
}); },
}, child: Column(
child: Column( crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, children: [
children: [ Padding(
Padding( padding: EdgeInsets.all(16.h),
padding: EdgeInsets.all(16.h), child: Column(
child: Column( crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, children: [
AppCustomChipWidget(
labelText: LocaleKeys.resultsAvailable.tr(context: context),
backgroundColor: AppColors.successColor.withOpacity(0.15),
textColor: AppColors.successColor,
).toShimmer2(isShow: model.isRadiologyOrdersLoading, width: 100),
SizedBox(height: 8.h),
Row(
children: [ children: [
Row( Image.network(
mainAxisAlignment: MainAxisAlignment.spaceBetween, model.isRadiologyOrdersLoading
children: [ ? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png"
CustomButton( : model.patientRadiologyOrders[index].doctorImageURL!,
text: LocaleKeys.resultsAvailable.tr(context: context), width: 24.h,
onPressed: () {}, height: 24.h,
backgroundColor: AppColors.successColor.withOpacity(0.15), fit: BoxFit.fill,
borderColor: AppColors.successColor.withOpacity(0.01), ).circle(100).toShimmer2(isShow: model.isRadiologyOrdersLoading),
textColor: AppColors.successColor, SizedBox(width: 4.h),
fontSize: 10, (model.isRadiologyOrdersLoading ? "Dr John Smith" : model.patientRadiologyOrders[index].doctorName!)
fontWeight: FontWeight.w500, .toText16(isBold: true)
borderRadius: 8, .toShimmer2(isShow: model.isRadiologyOrdersLoading)
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), ],
height: 30.h, ),
), SizedBox(height: 8.h),
Icon(isExpanded ? Icons.expand_less : Icons.expand_more), Wrap(
], direction: Axis.horizontal,
), spacing: 3.h,
SizedBox(height: 8.h), runSpacing: 4.h,
Row( children: [
children: [ AppCustomChipWidget(
Image.network( icon: AppAssets.doctor_calendar_icon,
model.patientRadiologyOrders[index].doctorImageURL!, labelText: model.isRadiologyOrdersLoading ? "01 Jan 2025" : DateUtil.formatDateToDate(model.patientRadiologyOrders[index].orderDate!, false),
width: 24.h, ).toShimmer2(isShow: model.isRadiologyOrdersLoading),
height: 24.h, AppCustomChipWidget(
fit: BoxFit.fill, labelText: model.isRadiologyOrdersLoading ? "01 Jan 2025" : model.patientRadiologyOrders[index].clinicDescription!,
).circle(100), ).toShimmer2(isShow: model.isRadiologyOrdersLoading),
SizedBox(width: 4.h),
model.patientRadiologyOrders[index].doctorName!.toText16(isBold: true) // AppCustomChipWidget(labelText: "").toShimmer2(isShow: model.isRadiologyOrdersLoading, width: 16.h),
], // AppCustomChipWidget(labelText: "").toShimmer2(isShow: model.isRadiologyOrdersLoading, width: 16.h),
), ],
SizedBox(height: 8.h), ),
Row( ],
),
),
model.isRadiologyOrdersLoading
? SizedBox.shrink()
: AnimatedCrossFade(
firstChild: SizedBox.shrink(),
secondChild: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
CustomButton( Padding(
text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(model.patientRadiologyOrders[index].orderDate), false), padding: EdgeInsets.only(bottom: 8.h),
onPressed: () {}, child: '${model.patientRadiologyOrders[index].description}'.toText14(weight: FontWeight.w500),
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 12,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 24.h,
), ),
SizedBox(width: 8.h), Row(
CustomButton( mainAxisAlignment: MainAxisAlignment.spaceBetween,
text: model.patientRadiologyOrders[index].clinicDescription!, children: [
onPressed: () {}, SizedBox(),
backgroundColor: AppColors.greyColor, CustomButton(
borderColor: AppColors.greyColor, icon: AppAssets.view_report_icon,
textColor: AppColors.blackColor, iconColor: AppColors.primaryRedColor,
fontSize: 12, iconSize: 16.h,
fontWeight: FontWeight.w500, text: LocaleKeys.viewReport.tr(context: context),
borderRadius: 8, onPressed: () {
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), Navigator.of(context).push(
height: 24.h, CustomPageRoute(
page: RadiologyResultPage(patientRadiologyResponseModel: model.patientRadiologyOrders[index]),
),
);
},
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,
fontSize: 14,
fontWeight: FontWeight.bold,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
),
],
), ),
], ],
), ),
],
),
),
AnimatedCrossFade(
firstChild: SizedBox.shrink(),
secondChild: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 8.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(bottom: 8.h),
child: '${model.patientRadiologyOrders[index].description}'.toText14(weight: FontWeight.w500),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(),
CustomButton(
icon: AppAssets.view_report_icon,
iconColor: AppColors.primaryRedColor,
iconSize: 16.h,
text: LocaleKeys.viewReport.tr(context: context),
onPressed: () {},
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,
fontSize: 14,
fontWeight: FontWeight.bold,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
),
],
),
],
), ),
crossFadeState: isExpanded ? CrossFadeState.showSecond : CrossFadeState.showFirst,
duration: Duration(milliseconds: 300),
), ),
crossFadeState: isExpanded ? CrossFadeState.showSecond : CrossFadeState.showFirst, ],
duration: Duration(milliseconds: 300),
),
],
),
),
), ),
), ),
), ),
); ),
}, ),
), );
], },
),
],
),
); );
}, },
), ),

@ -0,0 +1,162 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/radiology/models/resp_models/patient_radiology_response_model.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:open_filex/open_filex.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
class RadiologyResultPage extends StatefulWidget {
RadiologyResultPage({super.key, required this.patientRadiologyResponseModel});
PatientRadiologyResponseModel patientRadiologyResponseModel;
@override
State<RadiologyResultPage> createState() => _RadiologyResultPageState();
}
class _RadiologyResultPageState extends State<RadiologyResultPage> {
late RadiologyViewModel radiologyViewModel;
@override
void initState() {
scheduleMicrotask(() {
radiologyViewModel.getRadiologyImage(patientRadiologyResponseModel: widget.patientRadiologyResponseModel);
});
super.initState();
}
@override
Widget build(BuildContext context) {
radiologyViewModel = Provider.of<RadiologyViewModel>(context);
AppState _appState = getIt.get<AppState>();
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: Column(
children: [
Expanded(
child: CollapsingListView(
title: "Radiology Result".needTranslation,
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 24.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: true,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 16.h),
widget.patientRadiologyResponseModel.description!.toText16(isBold: true),
SizedBox(height: 8.h),
widget.patientRadiologyResponseModel.reportData!.trim().toText12(isBold: true, color: AppColors.textColorLight),
SizedBox(height: 16.h),
CustomButton(
text: "View Radiology Image".needTranslation,
onPressed: () async {
if (radiologyViewModel.radiologyImageURL.isNotEmpty) {
Uri uri = Uri.parse(radiologyViewModel.radiologyImageURL);
launchUrl(uri, mode: LaunchMode.platformDefault, webOnlyWindowName: "");
} else {
Utils.showToast("Radiology image not available".needTranslation);
}
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
icon: AppAssets.download,
iconColor: AppColors.whiteColor,
iconSize: 20.h,
),
SizedBox(height: 16.h),
],
).paddingSymmetrical(16.h, 0.h),
),
SizedBox(height: 24.h),
],
),
),
),
),
),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.h,
hasShadow: true,
),
child: CustomButton(
text: "Download report".needTranslation,
onPressed: () async {
LoaderBottomSheet.showLoader();
await radiologyViewModel.getRadiologyPDF(patientRadiologyResponseModel: widget.patientRadiologyResponseModel, authenticatedUser: _appState.getAuthenticatedUser()!, onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
}).then((val) async {
LoaderBottomSheet.hideLoader();
if (radiologyViewModel.patientRadiologyReportPDFBase64.isNotEmpty) {
String path = await Utils.createFileFromString(radiologyViewModel.patientRadiologyReportPDFBase64, "pdf");
try {
OpenFilex.open(path);
} catch (ex) {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: "Cannot open file".needTranslation),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
}
}
});
},
backgroundColor: AppColors.successColor,
borderColor: AppColors.successColor,
textColor: AppColors.whiteColor,
fontSize: 16,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 45.h,
icon: AppAssets.download,
iconColor: AppColors.whiteColor,
iconSize: 20.h,
).paddingSymmetrical(24.h, 24.h),
),
],
),
);
}
}

@ -21,6 +21,7 @@ import 'package:provider/provider.dart';
import 'core/cache_consts.dart'; import 'core/cache_consts.dart';
import 'core/utils/local_notifications.dart'; import 'core/utils/local_notifications.dart';
import 'core/utils/push_notification_handler.dart'; import 'core/utils/push_notification_handler.dart';
import 'widgets/routes/custom_page_route.dart';
class SplashPage extends StatefulWidget { class SplashPage extends StatefulWidget {
@override @override
@ -42,7 +43,7 @@ class _SplashScreenState extends State<SplashPage> {
Timer(Duration(seconds: 2, milliseconds: 500), () async { Timer(Duration(seconds: 2, milliseconds: 500), () async {
LocalNotification.init(onNotificationClick: (payload) {}); LocalNotification.init(onNotificationClick: (payload) {});
Navigator.of(context).pushReplacement( Navigator.of(context).pushReplacement(
FadePage( CustomPageRoute(
page: LandingNavigation(), page: LandingNavigation(),
// page: LoginScreen(), // page: LoginScreen(),
), ),

@ -85,7 +85,8 @@ class _GenericBottomSheetState extends State<GenericBottomSheet> {
textDirection: Directionality.of(context), textDirection: Directionality.of(context),
child: Container( child: Container(
padding: EdgeInsets.all(24.h), padding: EdgeInsets.all(24.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.bgScaffoldColor, borderRadius: 16), decoration: RoundedRectangleBorder()
.toSmoothCornerDecoration(color: AppColors.bgScaffoldColor, borderRadius: 16, customBorder: BorderRadius.only(topLeft: Radius.circular(16), topRight: Radius.circular(16))),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
@ -151,7 +152,7 @@ class _GenericBottomSheetState extends State<GenericBottomSheet> {
prefix: widget.isForEmail ? null : widget.countryCode, prefix: widget.isForEmail ? null : widget.countryCode,
isBorderAllowed: false, isBorderAllowed: false,
isAllowLeadingIcon: true, isAllowLeadingIcon: true,
fontSize: 12.h, fontSize: 13.h,
isCountryDropDown: widget.isEnableCountryDropdown, isCountryDropDown: widget.isEnableCountryDropdown,
leadingIcon: widget.isForEmail ? AppAssets.email : AppAssets.smart_phone, leadingIcon: widget.isForEmail ? AppAssets.email : AppAssets.smart_phone,
) )

@ -53,7 +53,7 @@ class CustomButton extends StatelessWidget {
color: isDisabled ? Colors.transparent : backgroundColor, color: isDisabled ? Colors.transparent : backgroundColor,
borderRadius: borderRadius, borderRadius: borderRadius,
side: BorderSide( side: BorderSide(
width: borderWidth, width: borderWidth.h,
color: isDisabled ? borderColor.withOpacity(0.5) : borderColor, color: isDisabled ? borderColor.withOpacity(0.5) : borderColor,
)), )),
child: Row( child: Row(

@ -98,30 +98,33 @@ class _CustomCountryDropdownState extends State<CustomCountryDropdown> {
children: [ children: [
Text( Text(
LocaleKeys.phoneNumber.tr(), LocaleKeys.phoneNumber.tr(),
style: TextStyle(fontSize: 12.fSize, height: 21 / 12, fontWeight: FontWeight.w500, letterSpacing: -1), style: TextStyle(fontSize: 12.fSize, height: 1.2.h, fontWeight: FontWeight.w500, letterSpacing: -1),
), ),
], ],
), ),
Row( Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Text( Text(
selectedCountry!.countryCode, selectedCountry!.countryCode,
style: TextStyle(fontSize: 12.fSize, height: 23 / 18, fontWeight: FontWeight.w600, letterSpacing: -1), style: TextStyle(fontSize: 12.fSize, fontWeight: FontWeight.w600, letterSpacing: -0.4, height: 1.5),
), ),
SizedBox(width: 4.h), SizedBox(width: 4.h),
if (widget.isEnableTextField) if (widget.isEnableTextField)
SizedBox( SizedBox(
height: 20, height: 20.h,
width: 200, width: 200.h,
// color: Colors.red, child: Align(
child: TextField( alignment: Alignment.centerLeft,
child: TextField(
focusNode: textFocusNode, focusNode: textFocusNode,
style: TextStyle(fontSize: 12.fSize, height: 23 / 18, fontWeight: FontWeight.w600, letterSpacing: -1), style: TextStyle(fontSize: 12.fSize, fontWeight: FontWeight.w600, letterSpacing: -0.4, height: 1.5),
decoration: InputDecoration(hintText: "", isDense: false, border: InputBorder.none), decoration: InputDecoration(hintText: "", isDense: true, border: InputBorder.none, contentPadding: EdgeInsets.zero),
keyboardType: TextInputType.phone, keyboardType: TextInputType.phone,
onChanged: widget.onPhoneNumberChanged), onChanged: widget.onPhoneNumberChanged,
),
),
), ),
], ],
) )
@ -134,7 +137,7 @@ class _CustomCountryDropdownState extends State<CustomCountryDropdown> {
? appState.getLanguageCode() == "ar" ? appState.getLanguageCode() == "ar"
? selectedCountry!.nameArabic ? selectedCountry!.nameArabic
: selectedCountry!.displayName : selectedCountry!.displayName
: "Select Country", : LocaleKeys.selectCountry.tr(),
style: TextStyle(fontSize: 14.fSize, height: 21 / 14, fontWeight: FontWeight.w500, letterSpacing: -0.2), style: TextStyle(fontSize: 14.fSize, height: 21 / 14, fontWeight: FontWeight.w500, letterSpacing: -0.2),
), ),
], ],

@ -122,7 +122,9 @@ class DropdownWidget extends StatelessWidget {
.toList(), .toList(),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
color: AppColors.scaffoldBgColor
); );
if (selected != null && onChange != null) { if (selected != null && onChange != null) {

@ -42,6 +42,7 @@ class TextInputWidget extends StatelessWidget {
final bool? isWalletAmountInput; final bool? isWalletAmountInput;
final Widget? suffix; final Widget? suffix;
final Color? labelColor; final Color? labelColor;
final Function(String)? onSubmitted;
// final List<Country> countryList; // final List<Country> countryList;
// final Function(Country)? onCountryChange; // final Function(Country)? onCountryChange;
@ -72,7 +73,8 @@ class TextInputWidget extends StatelessWidget {
this.fontSize = 14, this.fontSize = 14,
this.isWalletAmountInput = false, this.isWalletAmountInput = false,
this.suffix, this.suffix,
this.labelColor this.labelColor,
this.onSubmitted
// this.countryList = const [], // this.countryList = const [],
// this.onCountryChange, // this.onCountryChange,
}); });
@ -239,7 +241,8 @@ class TextInputWidget extends StatelessWidget {
onTapOutside: (event) { onTapOutside: (event) {
FocusManager.instance.primaryFocus?.unfocus(); FocusManager.instance.primaryFocus?.unfocus();
}, },
style: TextStyle(fontSize: fontSize!.fSize, height: isWalletAmountInput! ? 1 / 4 : 21 / 14, fontWeight: FontWeight.w500, color: AppColors.textColor, letterSpacing: -0.2), onSubmitted: onSubmitted,
style: TextStyle(fontSize: fontSize!.fSize, height: isWalletAmountInput! ? 1 / 4 : 0, fontWeight: FontWeight.w500, color: AppColors.textColor, letterSpacing: -1),
decoration: InputDecoration( decoration: InputDecoration(
isDense: true, isDense: true,
hintText: hintText, hintText: hintText,

@ -83,6 +83,8 @@ dependencies:
family_bottom_sheet: ^0.1.0 family_bottom_sheet: ^0.1.0
location: ^8.0.1 location: ^8.0.1
gms_check: ^1.0.4
huawei_location: ^6.14.2+301
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

Loading…
Cancel
Save