Compare commits

...

18 Commits

Author SHA1 Message Date
aamir-csol 192d617350 family screen & widgets 1 month ago
aamir-csol e48e98d61b Merge branch 'master' into dev_aamir 1 month ago
Haroon6138 d3978de92e Merge pull request 'functionality/graph' (#54) from functionality/graph into master
Reviewed-on: #54
1 month ago
taha.alam 92c3033087 Merge remote-tracking branch 'origin/master' into functionality/graph 1 month ago
taha.alam 5151997c7f custom linear added with parameters to customize the properties of graph 1 month ago
aamir-csol e5f4da4e16 Merge branch 'master' into dev_aamir
# Conflicts:
#	lib/presentation/medical_file/medical_file_page.dart
1 month ago
aamir-csol 1125437a56 family screen & widgets 1 month ago
Haroon6138 4974121061 Merge pull request 'haroon_dev' (#53) from haroon_dev into master
Reviewed-on: #53
1 month ago
haroon amjad 836a72ec22 App directionality changes 1 month ago
haroon amjad ba2785496d Merge branch 'master' into haroon_dev 1 month ago
haroon amjad 97038f1a25 advance payment implementation done for self & other file number 1 month ago
Haroon6138 db880760c3 Merge pull request 'haroon_dev' (#52) from haroon_dev into master
Reviewed-on: #52
1 month ago
haroon amjad 3e95999bf3 Merge branch 'master' into haroon_dev 1 month ago
aamir-csol f9bfc131a8 family screen & widgets 1 month ago
Haroon Amjad 1c2564a1e2 updates 1 month ago
haroon amjad 6048b3b5f1 Advance payment module implementation contd. 1 month ago
Haroon Amjad a4854bbe4a Habib Wallet updates 1 month ago
Haroon Amjad bdde6c224d Merge branch 'master' into haroon_dev 1 month ago

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 83 KiB

@ -808,6 +808,9 @@ class ApiConsts {
static final String registerUser = 'Services/Authentication.svc/REST/PatientRegistration'; static final String registerUser = 'Services/Authentication.svc/REST/PatientRegistration';
static final String addFamilyFile = 'Services/Patients.svc/REST/ShareFamilyFileService'; static final String addFamilyFile = 'Services/Patients.svc/REST/ShareFamilyFileService';
static final String sendFamilyFileActivation = 'Services/Authentication.svc/REST/SendActivationCodeForFamilyFile';
static final String checkActivationCodeForFamily = 'Services/Authentication.svc/REST/CheckActivationCodeForFamilyFile';
// static values for Api // static values for Api
static final double appVersionID = 18.7; static final double appVersionID = 18.7;

@ -132,6 +132,7 @@ class AppAssets {
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'; static const String home_lab_result_icon = '$svgBasePath/home_lab_result_icon.svg';
static const String visa_mastercard_icon = '$svgBasePath/visa_mastercard.svg';
//bottom navigation// //bottom navigation//
static const String homeBottom = '$svgBasePath/home_bottom.svg'; static const String homeBottom = '$svgBasePath/home_bottom.svg';

@ -44,6 +44,7 @@ class AppState {
setIsAuthenticated = true; setIsAuthenticated = true;
_authenticatedRootUser = authenticatedUser; _authenticatedRootUser = authenticatedUser;
} }
} }
AuthenticatedUser? getAuthenticatedUser({bool isFamily = false}) { AuthenticatedUser? getAuthenticatedUser({bool isFamily = false}) {
@ -97,7 +98,7 @@ class AppState {
set setDeviceTypeID(v) => deviceTypeID = v; set setDeviceTypeID(v) => deviceTypeID = v;
List<VidaPlusProjectListModel> vidaPlusProjectList = []; List<VidaPlusProjectListModel> vidaPlusProjectList = [];
List<PrivilegeModel> privilegeModelList = []; List<ListPrivilege> privilegeModelList = [];
List<HMCProjectListModel> hMCProjectListModel = []; List<HMCProjectListModel> hMCProjectListModel = [];
List<ProjectDetailListModel> projectDetailListModel = []; List<ProjectDetailListModel> projectDetailListModel = [];
@ -105,7 +106,7 @@ class AppState {
vidaPlusProjectList = vidaPlusProjectListModelInput; vidaPlusProjectList = vidaPlusProjectListModelInput;
} }
setPrivilegeModelList(List<PrivilegeModel> privilegeModelListInput) { setPrivilegeModelList(List<ListPrivilege> privilegeModelListInput) {
privilegeModelList = privilegeModelListInput; privilegeModelList = privilegeModelListInput;
} }

@ -0,0 +1,14 @@
///class used to provide value for the [DynamicResultChart] to plot the values
class DataPoint {
///values that is displayed on the graph and dot is plotted on this
final double value;
///label shown on the bottom of the graph
String label;
DataPoint(
{required this.value,
required this.label,
});
}

@ -0,0 +1,21 @@
import 'dart:ui' show Color;
class ThresholdRange {
final String label;
final double value;
final Color color;
final Color lineColor;
final String? actualValue;
ThresholdRange(
{required this.label,
required this.value,
required this.color,
required this.lineColor,
this.actualValue});
@override
String toString() {
return 'ThresholdRange(label: $label, value: $value, color: ${color.value.toRadixString(16)}, lineColor: ${lineColor.value.toRadixString(16)})';
}
}

@ -9,6 +9,7 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/models/request_models/registration_payload_model.dart'; import 'package:hmg_patient_app_new/features/authentication/models/request_models/registration_payload_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/request_models/send_activation_request_model.dart'; import 'package:hmg_patient_app_new/features/authentication/models/request_models/send_activation_request_model.dart';
import 'package:hmg_patient_app_new/features/common/models/commong_authanticated_req_model.dart'; import 'package:hmg_patient_app_new/features/common/models/commong_authanticated_req_model.dart';
import 'package:hmg_patient_app_new/features/common/models/family_file_request.dart';
class RequestUtils { class RequestUtils {
static dynamic getPatientAuthenticationRequest({ static dynamic getPatientAuthenticationRequest({
@ -125,6 +126,9 @@ class RequestUtils {
required bool isForRegister, required bool isForRegister,
required bool isFileNo, required bool isFileNo,
dynamic payload, dynamic payload,
required bool isExcludedUser,
required bool isFormFamilyFile,
int? responseID,
}) { }) {
AppState _appState = getIt.get<AppState>(); AppState _appState = getIt.get<AppState>();
var request = SendActivationRequest(); var request = SendActivationRequest();
@ -156,6 +160,15 @@ class RequestUtils {
request.isRegister = false; request.isRegister = false;
} }
request.deviceTypeID = request.searchType; request.deviceTypeID = request.searchType;
if (isFormFamilyFile) {
//INFO: Only for Excluded User Family Member Addition
request.isPatientExcluded = isExcludedUser;
request.responseID = responseID;
request.status = 2;
request.familyRegionID = zipCode == CountryEnum.saudiArabia.countryCode ? 1 : 2;
}
return request; return request;
} }
@ -247,19 +260,29 @@ class RequestUtils {
}; };
} }
static dynamic getAddFamilyRequest({required String nationalIDorFile, required String mobileNo, required String countryCode, required int loginType}) { static Future<FamilyFileRequest> getAddFamilyRequest({required String nationalIDorFile, required String mobileNo, required String countryCode}) async {
var request = <String, dynamic>{}; FamilyFileRequest request = FamilyFileRequest();
int? loginType = 0; // Default to National ID
if (countryCode == CountryEnum.saudiArabia.countryCode || countryCode == '+966') {
loginType = (nationalIDorFile.length == 10) ? 1 : 2;
} else if (countryCode == CountryEnum.unitedArabEmirates.countryCode || countryCode == '+971') {
loginType = (nationalIDorFile.length == 15) ? 1 : 2;
}
if (loginType == 1) { if (loginType == 1) {
request["sharedPatientID"] = 0; request.sharedPatientId = 0;
request["sharedPatientIdentificationID"] = nationalIDorFile; request.sharedPatientIdentificationId = nationalIDorFile;
} else if (loginType == 2) { } else if (loginType == 2) {
request["sharedPatientID"] = int.parse(nationalIDorFile); request.sharedPatientId = int.parse(nationalIDorFile);
request["sharedPatientIdentificationID"] = ''; request.sharedPatientIdentificationId = '';
} }
request["searchType"] = loginType; request.searchType = loginType;
request["sharedPatientMobileNumber"] = mobileNo; request.sharedPatientMobileNumber = mobileNo;
request["zipCode"] = countryCode; request.zipCode = countryCode;
request["isRegister"] = false; request.isRegister = false;
request["patientStatus"] = 2; request.patientStatus = 2;
request.isDentalAllowedBackend = false;
return request;
} }
} }

@ -671,7 +671,7 @@ class Utils {
); );
} }
static Widget getPaymentAmountWithSymbol2(num habibWalletAmount, Color iconColor, double iconSize, {bool isSaudiCurrency = true, bool isExpanded = true}) { static Widget getPaymentAmountWithSymbol2(num habibWalletAmount, {double iconSize = 14, Color iconColor = AppColors.textColor, Color textColor = AppColors.blackColor, bool isSaudiCurrency = true, bool isExpanded = true}) {
return RichText( return RichText(
maxLines: 1, maxLines: 1,
text: TextSpan( text: TextSpan(
@ -679,11 +679,11 @@ class Utils {
WidgetSpan( WidgetSpan(
alignment: PlaceholderAlignment.baseline, alignment: PlaceholderAlignment.baseline,
baseline: TextBaseline.alphabetic, baseline: TextBaseline.alphabetic,
child: Utils.buildSvgWithAssets(icon: AppAssets.saudi_riyal_icon, width: 14.h, height: 14.h, iconColor: Colors.black.withValues(alpha: 0.31)), child: Utils.buildSvgWithAssets(icon: AppAssets.saudi_riyal_icon, width: iconSize.h, height: iconSize.h, iconColor: iconColor),
), ),
TextSpan( TextSpan(
text: " $habibWalletAmount", text: " $habibWalletAmount",
style: TextStyle(color: AppColors.blackColor, fontSize: 32.fSize, letterSpacing: -4, fontWeight: FontWeight.w600, height: 1), style: TextStyle(color: textColor, fontSize: 32.fSize, letterSpacing: -4, fontWeight: FontWeight.w600, height: 1),
), ),
], ],
), ),
@ -729,4 +729,16 @@ class Utils {
await file.writeAsBytes(bytes); await file.writeAsBytes(bytes);
return file.path; return file.path;
} }
static bool havePrivilege(int id) {
bool isHavePrivilege = false;
try {
for (var element in appState.privilegeModelList) {
if (element.id == id) isHavePrivilege = element.previlege!;
}
} catch (e) {
print(e);
}
return isHavePrivilege;
}
} }

@ -17,12 +17,9 @@ abstract class AuthenticationRepo {
Future<Either<Failure, GenericApiModel<dynamic>>> checkPatientAuthentication({required dynamic checkPatientAuthenticationReq}); Future<Either<Failure, GenericApiModel<dynamic>>> checkPatientAuthentication({required dynamic checkPatientAuthenticationReq});
Future<Either<Failure, GenericApiModel<dynamic>>> sendActivationCodeRepo({required dynamic sendActivationCodeReq, String? languageID, bool isRegister = false}); Future<Either<Failure, GenericApiModel<dynamic>>> sendActivationCodeRepo({required dynamic sendActivationCodeReq, String? languageID, bool isRegister = false, bool isFormFamilyFile = false});
Future<Either<Failure, GenericApiModel<dynamic>>> checkActivationCodeRepo( Future<Either<Failure, GenericApiModel<dynamic>>> checkActivationCodeRepo({required dynamic newRequest, required String? activationCode, required bool isRegister, bool isExcludedUser = false});
{required dynamic newRequest, // could be CheckActivationCodeReq or CheckActivationCodeRegisterReq
required String? activationCode,
required bool isRegister});
Future<Either<Failure, GenericApiModel<dynamic>>> checkIfUserAgreed({required dynamic commonAuthanticatedRequest}); Future<Either<Failure, GenericApiModel<dynamic>>> checkIfUserAgreed({required dynamic commonAuthanticatedRequest});
@ -134,6 +131,7 @@ class AuthenticationRepoImp implements AuthenticationRepo {
required dynamic sendActivationCodeReq, required dynamic sendActivationCodeReq,
String? languageID, String? languageID,
bool isRegister = false, bool isRegister = false,
bool isFormFamilyFile = false,
}) async { }) async {
int isOutKsa = (sendActivationCodeReq.zipCode == '966' || sendActivationCodeReq.zipCode == '+966') ? 0 : 1; int isOutKsa = (sendActivationCodeReq.zipCode == '966' || sendActivationCodeReq.zipCode == '+966') ? 0 : 1;
sendActivationCodeReq.patientOutSA = isOutKsa; sendActivationCodeReq.patientOutSA = isOutKsa;
@ -144,7 +142,11 @@ class AuthenticationRepoImp implements AuthenticationRepo {
Failure? failure; Failure? failure;
await apiClient.post( await apiClient.post(
isRegister ? ApiConsts.sendActivationCodeRegister : ApiConsts.sendActivationCode, isFormFamilyFile
? ApiConsts.sendFamilyFileActivation
: isRegister
? ApiConsts.sendActivationCodeRegister
: ApiConsts.sendActivationCode,
body: sendActivationCodeReq.toJson(), body: sendActivationCodeReq.toJson(),
onFailure: (error, statusCode, {messageStatus, failureType}) { onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType; failure = failureType;
@ -176,6 +178,7 @@ class AuthenticationRepoImp implements AuthenticationRepo {
required dynamic newRequest, // could be CheckActivationCodeReq or CheckActivationCodeRegisterReq required dynamic newRequest, // could be CheckActivationCodeReq or CheckActivationCodeRegisterReq
required String? activationCode, required String? activationCode,
required bool isRegister, required bool isRegister,
bool isExcludedUser = false,
}) async { }) async {
if (isRegister) { if (isRegister) {
newRequest["activationCode"] = activationCode ?? "0000"; newRequest["activationCode"] = activationCode ?? "0000";
@ -189,7 +192,11 @@ class AuthenticationRepoImp implements AuthenticationRepo {
newRequest.isRegister = false; newRequest.isRegister = false;
} }
final endpoint = isRegister ? ApiConsts.checkActivationCodeRegister : ApiConsts.checkActivationCode; final endpoint = isExcludedUser
? ApiConsts.checkActivationCodeForFamily
: isRegister
? ApiConsts.checkActivationCodeRegister
: ApiConsts.checkActivationCode;
try { try {
GenericApiModel<dynamic>? apiResponse; GenericApiModel<dynamic>? apiResponse;

@ -13,6 +13,7 @@ import 'package:hmg_patient_app_new/core/common_models/privilege/HMCProjectListM
import 'package:hmg_patient_app_new/core/common_models/privilege/PrivilegeModel.dart'; import 'package:hmg_patient_app_new/core/common_models/privilege/PrivilegeModel.dart';
import 'package:hmg_patient_app_new/core/common_models/privilege/ProjectDetailListModel.dart'; import 'package:hmg_patient_app_new/core/common_models/privilege/ProjectDetailListModel.dart';
import 'package:hmg_patient_app_new/core/common_models/privilege/VidaPlusProjectListModel.dart'; import 'package:hmg_patient_app_new/core/common_models/privilege/VidaPlusProjectListModel.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/loading_utils.dart'; import 'package:hmg_patient_app_new/core/utils/loading_utils.dart';
import 'package:hmg_patient_app_new/core/utils/request_utils.dart'; import 'package:hmg_patient_app_new/core/utils/request_utils.dart';
@ -23,9 +24,11 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_repo.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_repo.dart';
import 'package:hmg_patient_app_new/features/authentication/models/request_models/check_activation_code_register_request_model.dart'; import 'package:hmg_patient_app_new/features/authentication/models/request_models/check_activation_code_register_request_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/request_models/registration_payload_model.dart'; import 'package:hmg_patient_app_new/features/authentication/models/request_models/registration_payload_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_activation_code_resp_model.dart'; import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_activation_code_resp_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_user_staus_nhic_response_model.dart'; import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_user_staus_nhic_response_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart'; import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_repo.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/authentication/login.dart'; import 'package:hmg_patient_app_new/presentation/authentication/login.dart';
import 'package:hmg_patient_app_new/presentation/authentication/saved_login_screen.dart'; import 'package:hmg_patient_app_new/presentation/authentication/saved_login_screen.dart';
@ -344,23 +347,33 @@ class AuthenticationViewModel extends ChangeNotifier {
} }
Future<void> sendActivationCode( Future<void> sendActivationCode(
{required OTPTypeEnum otpTypeEnum, required String nationalIdOrFileNumber, required String phoneNumber, required bool isForRegister, dynamic payload, bool isComingFromResendOTP = false}) async { {required OTPTypeEnum otpTypeEnum,
required String nationalIdOrFileNumber,
required String phoneNumber,
required bool isForRegister,
dynamic payload,
bool isComingFromResendOTP = false,
bool isExcludedUser = false,
bool isFormFamilyFile = false,
int? responseID}) async {
var request = RequestUtils.getCommonRequestSendActivationCode( var request = RequestUtils.getCommonRequestSendActivationCode(
otpTypeEnum: otpTypeEnum, otpTypeEnum: otpTypeEnum,
mobileNumber: phoneNumber, mobileNumber: phoneNumber,
selectedLoginType: otpTypeEnum.toInt(), selectedLoginType: otpTypeEnum.toInt(),
zipCode: selectedCountrySignup.countryCode, zipCode: selectedCountrySignup.countryCode,
nationalId: int.parse(nationalIdOrFileNumber), nationalId: int.parse(nationalIdOrFileNumber),
isFileNo: isForRegister ? isPatientHasFile(request: payload) : false, isFileNo: isForRegister ? isPatientHasFile(request: payload) : false,
patientId: 0, patientId: 0,
isForRegister: isForRegister, isForRegister: isForRegister,
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,
); isExcludedUser: isExcludedUser,
isFormFamilyFile: isFormFamilyFile,
responseID: responseID);
// TODO: GET APP SMS SIGNATURE HERE // TODO: GET APP SMS SIGNATURE HERE
request.sMSSignature = await getSignature(); request.sMSSignature = await getSignature();
@ -369,7 +382,8 @@ class AuthenticationViewModel extends ChangeNotifier {
_appState.setUserRegistrationPayload = RegistrationDataModelPayload.fromJson(payload); _appState.setUserRegistrationPayload = RegistrationDataModelPayload.fromJson(payload);
} }
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', isFormFamilyFile: isFormFamilyFile);
resultEither.fold( resultEither.fold(
(failure) async => await _errorHandlerService.handleError(failure: failure), (failure) async => await _errorHandlerService.handleError(failure: failure),
@ -384,7 +398,10 @@ class AuthenticationViewModel extends ChangeNotifier {
} else { } else {
if (apiResponse.data != null && apiResponse.data['isSMSSent'] == true) { if (apiResponse.data != null && apiResponse.data['isSMSSent'] == true) {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
if (!isComingFromResendOTP) navigateToOTPScreen(otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumber, isComingFromRegister: checkIsUserComingForRegister(request: payload), payload: payload); if (!isComingFromResendOTP) {
navigateToOTPScreen(
otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumber, isComingFromRegister: checkIsUserComingForRegister(request: payload), payload: payload, isExcludedUser: isExcludedUser);
}
} else { } else {
// TODO: Handle isSMSSent false // TODO: Handle isSMSSent false
// navigateToOTPScreen(otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumber); // navigateToOTPScreen(otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumber);
@ -403,7 +420,13 @@ class AuthenticationViewModel extends ChangeNotifier {
} }
Future<void> checkActivationCode( Future<void> checkActivationCode(
{required String? activationCode, required OTPTypeEnum otpTypeEnum, required Function(String? message) onWrongActivationCode, Function()? onResendActivation}) async { {required String? activationCode,
required OTPTypeEnum otpTypeEnum,
required Function(String? message) onWrongActivationCode,
Function()? onResendActivation,
bool isExcludedUser = false,
dynamic requestID,
dynamic responseID}) async {
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(
@ -429,6 +452,13 @@ class AuthenticationViewModel extends ChangeNotifier {
//TODO: Error Here IN Zip Code. //TODO: Error Here IN Zip Code.
loginType: loginTypeEnum.toInt) loginType: loginTypeEnum.toInt)
.toJson(); .toJson();
if (isExcludedUser) {
request['PatientShareRequestID'] = requestID;
request['ResponseID'] = responseID;
request['Status'] = 3;
}
LoaderBottomSheet.showLoader(); LoaderBottomSheet.showLoader();
if (isForRegister) { if (isForRegister) {
if (_appState.getUserRegistrationPayload.patientOutSa == 0) request['DOB'] = _appState.getUserRegistrationPayload.dob; if (_appState.getUserRegistrationPayload.patientOutSa == 0) request['DOB'] = _appState.getUserRegistrationPayload.dob;
@ -464,7 +494,8 @@ class AuthenticationViewModel extends ChangeNotifier {
} }
}); });
} else { } else {
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, isExcludedUser: isExcludedUser);
resultEither.fold( resultEither.fold(
(failure) async => await _errorHandlerService.handleError( (failure) async => await _errorHandlerService.handleError(
@ -497,6 +528,7 @@ class AuthenticationViewModel extends ChangeNotifier {
} else { } else {
if (activation.list != null && activation.list!.isNotEmpty) { if (activation.list != null && activation.list!.isNotEmpty) {
_appState.setAuthenticatedUser(activation.list!.first); _appState.setAuthenticatedUser(activation.list!.first);
_appState.setPrivilegeModelList(activation.list!.first.listPrivilege!);
} }
_appState.setUserBloodGroup = (activation.patientBlodType ?? ""); _appState.setUserBloodGroup = (activation.patientBlodType ?? "");
_appState.setAppAuthToken = activation.authenticationTokenId; _appState.setAppAuthToken = activation.authenticationTokenId;
@ -573,12 +605,13 @@ class AuthenticationViewModel extends ChangeNotifier {
_navigationService.pushAndReplace(AppRoutes.landingScreen); _navigationService.pushAndReplace(AppRoutes.landingScreen);
} }
Future<void> navigateToOTPScreen({required OTPTypeEnum otpTypeEnum, required String phoneNumber, required bool isComingFromRegister, dynamic payload}) async { Future<void> navigateToOTPScreen({required OTPTypeEnum otpTypeEnum, required String phoneNumber, required bool isComingFromRegister, dynamic payload, bool isExcludedUser = false}) async {
_navigationService.pushToOtpScreen( _navigationService.pushToOtpScreen(
phoneNumber: phoneNumber, phoneNumber: phoneNumber,
checkActivationCode: (int activationCode) async { checkActivationCode: (int activationCode) async {
await checkActivationCode( await checkActivationCode(
activationCode: activationCode.toString(), activationCode: activationCode.toString(),
isExcludedUser: isExcludedUser,
otpTypeEnum: otpTypeEnum, otpTypeEnum: otpTypeEnum,
onWrongActivationCode: (String? value) { onWrongActivationCode: (String? value) {
onWrongActivationCode(message: value); onWrongActivationCode(message: value);
@ -905,7 +938,7 @@ class AuthenticationViewModel extends ChangeNotifier {
Future<void> getServicePrivilege() async { Future<void> getServicePrivilege() async {
final resultEither = await _authenticationRepo.getServicePrivilege(); final resultEither = await _authenticationRepo.getServicePrivilege();
List<PrivilegeModel> privilegeModelList = []; List<ListPrivilege> privilegeModelList = [];
List<VidaPlusProjectListModel> vidaPlusProjectListModel = []; List<VidaPlusProjectListModel> vidaPlusProjectListModel = [];
List<HMCProjectListModel> hMCProjectListModel = []; List<HMCProjectListModel> hMCProjectListModel = [];
List<ProjectDetailListModel> projectDetailListModel = []; List<ProjectDetailListModel> projectDetailListModel = [];
@ -917,9 +950,9 @@ class AuthenticationViewModel extends ChangeNotifier {
await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty"); await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty");
} else { } else {
apiResponse.data["ServicePrivilegeList"].forEach((v) { apiResponse.data["ServicePrivilegeList"].forEach((v) {
privilegeModelList.add(PrivilegeModel.fromJson(v)); privilegeModelList.add(ListPrivilege.fromJson(v));
}); });
_appState.setPrivilegeModelList(privilegeModelList); _appState.setPrivilegeModelList(privilegeModelList.cast<ListPrivilege>());
apiResponse.data["ProjectListVidaPlus"].forEach((v) { apiResponse.data["ProjectListVidaPlus"].forEach((v) {
vidaPlusProjectListModel.add(VidaPlusProjectListModel.fromJson(v)); vidaPlusProjectListModel.add(VidaPlusProjectListModel.fromJson(v));

@ -613,35 +613,3 @@ class ListElement {
"status": listStatus, "status": listStatus,
}; };
} }
class ListPrivilege {
int? id;
String? serviceName;
bool? previlege;
dynamic region;
ListPrivilege({
this.id,
this.serviceName,
this.previlege,
this.region,
});
factory ListPrivilege.fromRawJson(String str) => ListPrivilege.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory ListPrivilege.fromJson(Map<String, dynamic> json) => ListPrivilege(
id: json["ID"],
serviceName: json["ServiceName"],
previlege: json["Previlege"],
region: json["Region"],
);
Map<String, dynamic> toJson() => {
"ID": id,
"ServiceName": serviceName,
"Previlege": previlege,
"Region": region,
};
}

@ -42,11 +42,9 @@ abstract class BookAppointmentsRepo {
Function(dynamic)? onSuccess, Function(dynamic)? onSuccess,
Function(String)? onError}); Function(String)? onError});
Future<Either<Failure, GenericApiModel<List<HospitalsModel>>>> Future<Either<Failure, GenericApiModel<List<HospitalsModel>>>> getProjectList();
getProjectList();
Future<Either<Failure, GenericApiModel<List<GetClinicsListResponseModel>>>> getClinicsWithRespectToClinicId(String projectID); Future<Either<Failure, GenericApiModel<List<GetClinicsListResponseModel>>>> getClinicsWithRespectToClinicId(String projectID);
} }
class BookAppointmentsRepoImp implements BookAppointmentsRepo { class BookAppointmentsRepoImp implements BookAppointmentsRepo {
@ -371,8 +369,7 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo {
} }
@override @override
Future<Either<Failure, GenericApiModel<List<HospitalsModel>>>> Future<Either<Failure, GenericApiModel<List<HospitalsModel>>>> getProjectList() async {
getProjectList() async {
Map<String, dynamic> request = {}; Map<String, dynamic> request = {};
try { try {
@ -388,11 +385,7 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo {
try { try {
final list = response['ListProject']; final list = response['ListProject'];
final appointmentsList = list final appointmentsList = list.map((item) => HospitalsModel.fromJson(item as Map<String, dynamic>)).toList().cast<HospitalsModel>();
.map((item) =>
HospitalsModel.fromJson(item as Map<String, dynamic>))
.toList()
.cast<HospitalsModel>();
apiResponse = GenericApiModel<List<HospitalsModel>>( apiResponse = GenericApiModel<List<HospitalsModel>>(
messageStatus: messageStatus, messageStatus: messageStatus,

@ -0,0 +1,57 @@
import 'dart:convert';
class FamilyFileRequest {
int? sharedPatientId;
String? sharedPatientIdentificationId;
int? searchType;
String? sharedPatientMobileNumber;
String? zipCode;
bool? isRegister;
int? patientStatus;
bool? isDentalAllowedBackend;
bool? isPatientExcluded;
int? responseID;
FamilyFileRequest({
this.sharedPatientId,
this.sharedPatientIdentificationId,
this.searchType,
this.sharedPatientMobileNumber,
this.zipCode,
this.isRegister,
this.patientStatus,
this.isDentalAllowedBackend,
this.isPatientExcluded,
this.responseID,
});
factory FamilyFileRequest.fromRawJson(String str) => FamilyFileRequest.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory FamilyFileRequest.fromJson(Map<String, dynamic> json) => FamilyFileRequest(
sharedPatientId: json["sharedPatientID"],
sharedPatientIdentificationId: json["sharedPatientIdentificationID"],
searchType: json["searchType"],
sharedPatientMobileNumber: json["sharedPatientMobileNumber"],
zipCode: json["zipCode"],
isRegister: json["isRegister"],
patientStatus: json["patientStatus"],
isDentalAllowedBackend: json["isDentalAllowedBackend"],
isPatientExcluded: json["IsPatientExcluded"],
responseID: json["ReponseID"],
);
Map<String, dynamic> toJson() => {
"SharedPatientID": sharedPatientId,
"SharedPatientIdentificationID": sharedPatientIdentificationId,
"SearchType": searchType,
"SharedPatientMobileNumber": sharedPatientMobileNumber,
"zipCode": zipCode,
"isRegister": isRegister,
"PatientStatus": patientStatus,
"isDentalAllowedBackend": isDentalAllowedBackend,
"IsPatientExcluded": isPatientExcluded,
"ReponseID": responseID,
};
}

@ -3,10 +3,20 @@ 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/features/my_appointments/models/resp_models/hospital_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class HabibWalletRepo { abstract class HabibWalletRepo {
Future<Either<Failure, GenericApiModel<dynamic>>> getPatientBalanceAmount(); Future<Either<Failure, GenericApiModel<dynamic>>> getPatientBalanceAmount();
Future<Either<Failure, GenericApiModel<List<HospitalsModel>>>> getProjectList();
Future<Either<Failure, GenericApiModel<dynamic>>> HISCreateAdvancePayment(
{required String paymentMethodName, required num paidAmount, required String paymentReference, required String patientID, required int projectID, required String depositorName});
Future<Either<Failure, GenericApiModel<dynamic>>> addAdvanceNumberRequest({required String advanceNumber, required String paymentReference});
Future<Either<Failure, GenericApiModel<dynamic>>> getPatientInfoByPatientID({required String patientID});
} }
class HabibWalletRepoImp implements HabibWalletRepo { class HabibWalletRepoImp implements HabibWalletRepo {
@ -55,4 +65,165 @@ class HabibWalletRepoImp implements HabibWalletRepo {
return Left(UnknownFailure(e.toString())); return Left(UnknownFailure(e.toString()));
} }
} }
@override
Future<Either<Failure, GenericApiModel<List<HospitalsModel>>>> getProjectList() async {
Map<String, dynamic> request = {"IsOnlineCheckIn": true, "IsAdvancePayment": true};
try {
GenericApiModel<List<HospitalsModel>>? apiResponse;
Failure? failure;
await apiClient.post(
GET_PROJECT_LIST,
body: request,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response['ListProject'];
final appointmentsList = list.map((item) => HospitalsModel.fromJson(item as Map<String, dynamic>)).toList().cast<HospitalsModel>();
apiResponse = GenericApiModel<List<HospitalsModel>>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: appointmentsList,
);
} 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>> HISCreateAdvancePayment(
{required String paymentMethodName, required num paidAmount, required String paymentReference, required String patientID, required int projectID, required String depositorName}) async {
Map<String, dynamic> request = {
"CustName": depositorName,
"CustID": patientID,
"SetupID": "010266",
"ProjectID": projectID,
"PatientID": patientID,
"AccountID": patientID,
"PaymentAmount": paidAmount,
"NationalityID": null,
"DepositorName": depositorName,
"CreatedBy": 3,
"PaymentMethodName": paymentMethodName,
"PaymentReference": paymentReference,
"PaymentMethod": paymentMethodName,
"IsAncillaryOrder": false
};
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
HIS_CREATE_ADVANCE_PAYMENT,
body: request,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: errorMessage,
data: response,
);
} 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>> addAdvanceNumberRequest({required String advanceNumber, required String paymentReference}) async {
Map<String, dynamic> requestBody = {
"AdvanceNumber": advanceNumber,
"AdvanceNumber_VP": advanceNumber,
"PaymentReferenceNumber": paymentReference,
"AppointmentID": 0,
};
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
ADD_ADVANCE_NUMBER_REQUEST,
body: requestBody,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: response,
);
} 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>> getPatientInfoByPatientID({required String patientID}) async {
Map<String, dynamic> requestBody = {"SearchPatientID": patientID};
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
GET_PATIENT_INFO_BY_ID,
body: requestBody,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: response,
);
} 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,23 +1,94 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_repo.dart'; import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_repo.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart';
class HabibWalletViewModel extends ChangeNotifier { class HabibWalletViewModel extends ChangeNotifier {
bool isWalletAmountLoading = false; bool isWalletAmountLoading = false;
num habibWalletAmount = 0; num habibWalletAmount = 0;
num walletRechargeAmount = 0;
bool isBottomSheetContentLoading = false;
bool isSearchedFileNumberDataShown = false;
int currentIndex = 0;
List<HospitalsModel> advancePaymentHospitals = [];
HospitalsModel? selectedHospital;
HabibWalletRepo habibWalletRepo; HabibWalletRepo habibWalletRepo;
ErrorHandlerService errorHandlerService; ErrorHandlerService errorHandlerService;
String fileNumber = '';
String depositorName = '';
String mobileNumber = '';
num selectedRechargeType = 1;
HabibWalletViewModel({required this.habibWalletRepo, required this.errorHandlerService}); HabibWalletViewModel({required this.habibWalletRepo, required this.errorHandlerService});
initHabibWalletProvider() { initHabibWalletProvider() {
isWalletAmountLoading = true; isWalletAmountLoading = true;
isBottomSheetContentLoading = false;
habibWalletAmount = 0; habibWalletAmount = 0;
walletRechargeAmount = 0;
selectedRechargeType = 1;
advancePaymentHospitals.clear();
selectedHospital = null;
fileNumber = '';
depositorName = '';
mobileNumber = '';
notifyListeners();
}
setSelectedRechargeType(num type) {
selectedRechargeType = type;
notifyListeners(); notifyListeners();
} }
setSelectedHospital(HospitalsModel hospital) {
selectedHospital = hospital;
notifyListeners();
}
setWalletRechargeAmount(num amount) {
walletRechargeAmount = amount;
notifyListeners();
}
setDepositorDetails(String fileNum, String depositor, String mobile) {
fileNumber = fileNum;
depositorName = depositor;
mobileNumber = mobile;
notifyListeners();
}
setCurrentIndex(int index) {
currentIndex = index;
notifyListeners();
}
String getSelectedRechargeTypeValue() {
switch (selectedRechargeType) {
case 1:
return LocaleKeys.myAccount.tr();
case 2:
return LocaleKeys.family.tr();
case 3:
return LocaleKeys.otherAccount.tr();
default:
return LocaleKeys.myAccount.tr();
}
}
Future<void> getPatientBalanceAmount({Function(dynamic)? onSuccess, Function(String)? onError}) async { Future<void> getPatientBalanceAmount({Function(dynamic)? onSuccess, Function(String)? onError}) async {
isWalletAmountLoading = true;
notifyListeners();
final result = await habibWalletRepo.getPatientBalanceAmount(); final result = await habibWalletRepo.getPatientBalanceAmount();
result.fold( result.fold(
@ -36,4 +107,92 @@ class HabibWalletViewModel extends ChangeNotifier {
}, },
); );
} }
Future<void> getProjectsList() async {
advancePaymentHospitals.clear();
notifyListeners();
final result = await habibWalletRepo.getProjectList();
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) async {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
advancePaymentHospitals = apiResponse.data!;
notifyListeners();
}
},
);
}
Future<void> HISCreateAdvancePayment(
{required String paymentMethodName,
required num paidAmount,
required String paymentReference,
required String patientID,
required int projectID,
required String depositorName,
Function(dynamic)? onSuccess,
Function(String)? onError}) async {
final result = await habibWalletRepo.HISCreateAdvancePayment(
paymentMethodName: paymentMethodName, paidAmount: paidAmount, paymentReference: paymentReference, patientID: patientID, projectID: projectID, depositorName: depositorName);
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) {
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> addAdvanceNumberRequest({required String advanceNumber, required String paymentReference, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await habibWalletRepo.addAdvanceNumberRequest(advanceNumber: advanceNumber, paymentReference: paymentReference);
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) {
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> getPatientInfoByPatientID({required String patientID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
isBottomSheetContentLoading = true;
notifyListeners();
final result = await habibWalletRepo.getPatientInfoByPatientID(patientID: patientID);
result.fold(
(failure) async {
isBottomSheetContentLoading = false;
notifyListeners();
await errorHandlerService.handleError(failure: failure);
},
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
isBottomSheetContentLoading = false;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
} }

@ -26,7 +26,7 @@ abstract class MedicalFileRepo {
Future<Either<Failure, GenericApiModel<List<FamilyFileResponseModelLists>>>> getPatientFamilyFiles(); Future<Either<Failure, GenericApiModel<List<FamilyFileResponseModelLists>>>> getPatientFamilyFiles();
Future<Either<Failure, GenericApiModel<List<dynamic>>>> addFamilyFile({required dynamic request}); Future<Either<Failure, GenericApiModel<dynamic>>> addFamilyFile({required dynamic request});
} }
class MedicalFileRepoImp implements MedicalFileRepo { class MedicalFileRepoImp implements MedicalFileRepo {
@ -313,9 +313,9 @@ class MedicalFileRepoImp implements MedicalFileRepo {
} }
@override @override
Future<Either<Failure, GenericApiModel<List<dynamic>>>> addFamilyFile({dynamic request}) async { Future<Either<Failure, GenericApiModel<dynamic>>> addFamilyFile({dynamic request}) async {
try { try {
GenericApiModel<List<dynamic>>? apiResponse; GenericApiModel<dynamic>? apiResponse;
Failure? failure; Failure? failure;
await apiClient.post( await apiClient.post(
ApiConsts.addFamilyFile, ApiConsts.addFamilyFile,
@ -325,17 +325,12 @@ class MedicalFileRepoImp implements MedicalFileRepo {
}, },
onSuccess: (response, statusCode, {messageStatus, errorMessage}) { onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try { try {
print(response); apiResponse = GenericApiModel<dynamic>(
// final list = response['GetAllSharedRecordsByStatusList']; messageStatus: messageStatus,
// statusCode: statusCode,
// final familyLists = list.map((item) => FamilyFileResponseModelLists.fromJson(item as Map<String, dynamic>)).toList().cast<FamilyFileResponseModelLists>(); errorMessage: errorMessage,
// data: response["ShareFamilyFileObj"] ?? null,
// apiResponse = GenericApiModel<List<FamilyFileResponseModelLists>>( );
// messageStatus: messageStatus,
// statusCode: statusCode,
// errorMessage: null,
// data: familyLists,
// );
} catch (e) { } catch (e) {
failure = DataParsingFailure(e.toString()); failure = DataParsingFailure(e.toString());
} }

@ -1,8 +1,14 @@
import 'dart:convert';
import 'package:flutter/material.dart'; 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/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/request_utils.dart'; import 'package:hmg_patient_app_new/core/utils/request_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart'; import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/common/models/family_file_request.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_repo.dart'; import 'package:hmg_patient_app_new/features/medical_file/medical_file_repo.dart';
import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart'; import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/models/patient_medical_response_model.dart'; import 'package:hmg_patient_app_new/features/medical_file/models/patient_medical_response_model.dart';
@ -10,6 +16,7 @@ import 'package:hmg_patient_app_new/features/medical_file/models/patient_sicklea
import 'package:hmg_patient_app_new/features/medical_file/models/patient_vaccine_response_model.dart'; import 'package:hmg_patient_app_new/features/medical_file/models/patient_vaccine_response_model.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/dialog_service.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';
class MedicalFileViewModel extends ChangeNotifier { class MedicalFileViewModel extends ChangeNotifier {
int selectedTabIndex = 0; int selectedTabIndex = 0;
@ -293,9 +300,36 @@ class MedicalFileViewModel extends ChangeNotifier {
); );
} }
Future<void> addFamilyFile() async { Future<void> addFamilyFile({required OTPTypeEnum otpTypeEnum, required bool isExcludedUser}) async {
final resultEither = await medicalFileRepo.addFamilyFile(request: {}); AuthenticationViewModel authVM = getIt.get<AuthenticationViewModel>();
resultEither.fold((failure) async => await errorHandlerService.handleError(failure: failure), (apiResponse) async {}); NavigationService navigationService = getIt.get<NavigationService>();
FamilyFileRequest request =
await RequestUtils.getAddFamilyRequest(nationalIDorFile: authVM.nationalIdController.text, mobileNo: authVM.phoneNumberController.text, countryCode: authVM.selectedCountrySignup.countryCode);
final resultEither = await medicalFileRepo.addFamilyFile(request: request.toJson());
resultEither.fold((failure) async => await errorHandlerService.handleError(failure: failure), (apiResponse) async {
if (apiResponse != null && apiResponse.data != null) {
request.isPatientExcluded = apiResponse.data["IsPatientExcluded"];
request.responseID = apiResponse.data["ReponseID"];
_dialogService.showExceptionBottomSheet(
message: apiResponse.data['Message'],
onOkPressed: () {
print("=================== On Press Ok ==================");
authVM.sendActivationCode(
otpTypeEnum: otpTypeEnum,
nationalIdOrFileNumber: request.sharedPatientIdentificationId!,
phoneNumber: request.sharedPatientMobileNumber!,
isForRegister: false,
isExcludedUser: apiResponse.data['IsPatientExcluded'],
responseID: apiResponse.data["ReponseID"],
isFormFamilyFile: true);
// insertFamilyData(payload: apiResponse.data![0]['ShareFamilyFileObj'], isExcludedPatient: apiResponse.data![0]['ShareFamilyFileObj']['IsPatientExcluded']);
},
onCancelPressed: () {
navigationService.pop();
});
}
});
} }
} }

@ -7,6 +7,7 @@ import 'package:hmg_patient_app_new/features/payfort/models/payfort_project_deta
import 'package:hmg_patient_app_new/features/payfort/models/sdk_token_response_model.dart'; import 'package:hmg_patient_app_new/features/payfort/models/sdk_token_response_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_repo.dart'; import 'package:hmg_patient_app_new/features/payfort/payfort_repo.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/widgets/loader/bottomsheet_loader.dart';
import 'package:network_info_plus/network_info_plus.dart'; import 'package:network_info_plus/network_info_plus.dart';
class PayfortViewModel extends ChangeNotifier { class PayfortViewModel extends ChangeNotifier {
@ -183,6 +184,7 @@ class PayfortViewModel extends ChangeNotifier {
isApplePayConfigurationLoading = false; isApplePayConfigurationLoading = false;
notifyListeners(); notifyListeners();
LoaderBottomSheet.hideLoader();
_payfort.callPayFortForApplePay( _payfort.callPayFortForApplePay(
request: request, request: request,

@ -5,6 +5,7 @@ import 'package:flutter/cupertino.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: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/utils/size_utils.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/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -34,6 +35,7 @@ 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';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../core/dependencies.dart';
import '../medical_file/widgets/medical_file_card.dart'; import '../medical_file/widgets/medical_file_card.dart';
class AppointmentDetailsPage extends StatefulWidget { class AppointmentDetailsPage extends StatefulWidget {
@ -63,6 +65,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
myAppointmentsViewModel = Provider.of<MyAppointmentsViewModel>(context, listen: false); myAppointmentsViewModel = Provider.of<MyAppointmentsViewModel>(context, listen: false);
prescriptionsViewModel = Provider.of<PrescriptionsViewModel>(context, listen: false); prescriptionsViewModel = Provider.of<PrescriptionsViewModel>(context, listen: false);
bookAppointmentsViewModel = Provider.of<BookAppointmentsViewModel>(context, listen: false); bookAppointmentsViewModel = Provider.of<BookAppointmentsViewModel>(context, listen: false);
@ -313,12 +316,15 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
], ],
), ),
SizedBox(width: 68.h), SizedBox(width: 68.h),
Utils.buildSvgWithAssets( Transform.flip(
icon: AppAssets.forward_arrow_icon, flipX: appState.isArabic() ? true : false,
iconColor: AppColors.blackColor, child: Utils.buildSvgWithAssets(
width: 18.h, icon: AppAssets.forward_arrow_icon,
height: 13.h, iconColor: AppColors.blackColor,
fit: BoxFit.contain, width: 18.h,
height: 13.h,
fit: BoxFit.contain,
),
), ),
], ],
), ),

@ -103,13 +103,16 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
), ),
SizedBox(width: 8.h), SizedBox(width: 8.h),
const Spacer(), const Spacer(),
Utils.buildSvgWithAssets( Transform.flip(
icon: AppAssets.forward_arrow_icon, flipX: appState.isArabic() ? true : false,
iconColor: AppColors.blackColor, child: Utils.buildSvgWithAssets(
width: 18.h, icon: AppAssets.forward_arrow_icon,
height: 13.h, iconColor: AppColors.blackColor,
fit: BoxFit.contain, width: 18.h,
).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading), height: 13.h,
fit: BoxFit.contain,
).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
),
], ],
).paddingSymmetrical(16.h, 16.h), ).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() { ).paddingSymmetrical(24.h, 0.h).onPress(() {
@ -142,13 +145,16 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
), ),
SizedBox(width: 8.h), SizedBox(width: 8.h),
const Spacer(), const Spacer(),
Utils.buildSvgWithAssets( Transform.flip(
icon: AppAssets.forward_arrow_icon, flipX: appState.isArabic() ? true : false,
iconColor: AppColors.blackColor, child: Utils.buildSvgWithAssets(
width: 18.h, icon: AppAssets.forward_arrow_icon,
height: 13.h, iconColor: AppColors.blackColor,
fit: BoxFit.contain, width: 18.h,
).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading), height: 13.h,
fit: BoxFit.contain,
).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
),
], ],
).paddingSymmetrical(16.h, 16.h), ).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() { ).paddingSymmetrical(24.h, 0.h).onPress(() {
@ -175,13 +181,16 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
), ),
SizedBox(width: 8.h), SizedBox(width: 8.h),
const Spacer(), const Spacer(),
Utils.buildSvgWithAssets( Transform.flip(
icon: AppAssets.forward_arrow_icon, flipX: appState.isArabic() ? true : false,
iconColor: AppColors.blackColor, child: Utils.buildSvgWithAssets(
width: 18.h, icon: AppAssets.forward_arrow_icon,
height: 13.h, iconColor: AppColors.blackColor,
fit: BoxFit.contain, width: 18.h,
).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading), height: 13.h,
fit: BoxFit.contain,
).toShimmer2(isShow: myAppointmentsVM.isAppointmentPatientShareLoading),
),
], ],
).paddingSymmetrical(16.h, 16.h), ).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() { ).paddingSymmetrical(24.h, 0.h).onPress(() {
@ -273,7 +282,6 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
isSaudiCurrency: true), isSaudiCurrency: true),
], ],
).paddingSymmetrical(24.h, 0.h), ).paddingSymmetrical(24.h, 0.h),
//TODO: Add Apple Pay Privileges
Platform.isIOS Platform.isIOS
? Utils.buildSvgWithAssets( ? Utils.buildSvgWithAssets(
icon: AppAssets.apple_pay_button, icon: AppAssets.apple_pay_button,
@ -282,7 +290,11 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
fit: BoxFit.contain, fit: BoxFit.contain,
).paddingSymmetrical(24.h, 0.h).onPress(() { ).paddingSymmetrical(24.h, 0.h).onPress(() {
// payfortVM.setIsApplePayConfigurationLoading(true); // payfortVM.setIsApplePayConfigurationLoading(true);
startApplePay(); if (Utils.havePrivilege(103)) {
startApplePay();
} else {
openPaymentURL(selectedPaymentMethod);
}
}) })
: SizedBox(height: 12.h), : SizedBox(height: 12.h),
SizedBox(height: 12.h), SizedBox(height: 12.h),
@ -363,8 +375,8 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(), appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
payedAmount: payfortViewModel.payfortCheckPaymentStatusResponseModel!.amount!, payedAmount: payfortViewModel.payfortCheckPaymentStatusResponseModel!.amount!,
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!, paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
patientID: "4767477", patientID: appState.getAuthenticatedUser()!.patientId.toString(),
patientType: 1, patientType: appState.getAuthenticatedUser()!.patientType!,
onSuccess: (value) async { onSuccess: (value) async {
print(value); print(value);
await myAppointmentsViewModel.addAdvanceNumberRequest( await myAppointmentsViewModel.addAdvanceNumberRequest(

@ -2,6 +2,8 @@ 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: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/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.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/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -21,6 +23,7 @@ class MyDoctorsPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
myAppointmentsViewModel = Provider.of<MyAppointmentsViewModel>(context, listen: false); myAppointmentsViewModel = Provider.of<MyAppointmentsViewModel>(context, listen: false);
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
@ -136,7 +139,9 @@ class MyDoctorsPage extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
"".toText16(), "".toText16(),
Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor), Transform.flip(
flipX: appState.isArabic() ? true : false,
child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor)),
], ],
), ),
], ],

@ -151,8 +151,12 @@ class _AppointmentCardState extends State<AppointmentCard> {
spacing: 3.h, spacing: 3.h,
runSpacing: 4.h, runSpacing: 4.h,
children: [ children: [
widget.isFromHomePage ? SizedBox.shrink() : AppCustomChipWidget(labelText: widget.isLoading ? "Cardiology" : widget.patientAppointmentHistoryResponseModel.clinicName!).toShimmer2(isShow: widget.isLoading), widget.isFromHomePage
widget.isFromHomePage ? SizedBox.shrink() : AppCustomChipWidget(labelText: widget.isLoading ? "Olaya" : widget.patientAppointmentHistoryResponseModel.projectName!).toShimmer2(isShow: widget.isLoading), ? SizedBox.shrink()
: AppCustomChipWidget(labelText: widget.isLoading ? "Cardiology" : widget.patientAppointmentHistoryResponseModel.clinicName!).toShimmer2(isShow: widget.isLoading),
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: labelText:
@ -215,11 +219,15 @@ class _AppointmentCardState extends State<AppointmentCard> {
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(10.h), padding: EdgeInsets.all(10.h),
child: Utils.buildSvgWithAssets( child: Transform.flip(
icon: AppAssets.forward_arrow_icon, flipX: appState.isArabic() ? true : false,
width: 10.h, child: Utils.buildSvgWithAssets(
height: 10.h, icon: AppAssets.forward_arrow_icon,
fit: BoxFit.contain, iconColor: AppColors.whiteColor,
width: 10.h,
height: 10.h,
fit: BoxFit.contain,
),
), ),
), ),
).toShimmer2(isShow: widget.isLoading).onPress(() { ).toShimmer2(isShow: widget.isLoading).onPress(() {

@ -31,11 +31,12 @@ class AppointmentCheckinBottomSheet extends StatelessWidget {
bool _supportsNFC = false; bool _supportsNFC = false;
late LocationUtils locationUtils; late LocationUtils locationUtils;
late AppState appState;
ProjectDetailListModel projectDetailListModel = ProjectDetailListModel(); ProjectDetailListModel projectDetailListModel = ProjectDetailListModel();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
AppState _appState = getIt.get<AppState>(); appState = getIt.get<AppState>();
FlutterNfcKit.nfcAvailability.then((value) { FlutterNfcKit.nfcAvailability.then((value) {
_supportsNFC = (value == NFCAvailability.available); _supportsNFC = (value == NFCAvailability.available);
}); });
@ -53,7 +54,7 @@ class AppointmentCheckinBottomSheet extends StatelessWidget {
// appState: myAppointmentsViewModel.appState, // appState: myAppointmentsViewModel.appState,
// ); // );
locationUtils.getCurrentLocation(onSuccess: (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);
if (dist <= projectDetailListModel.geofenceRadius!) { if (dist <= projectDetailListModel.geofenceRadius!) {
@ -120,12 +121,15 @@ class AppointmentCheckinBottomSheet extends StatelessWidget {
], ],
), ),
), ),
Utils.buildSvgWithAssets( Transform.flip(
icon: AppAssets.forward_arrow_icon, flipX: appState.isArabic() ? true : false,
iconColor: AppColors.blackColor, child: Utils.buildSvgWithAssets(
width: 18.h, icon: AppAssets.forward_arrow_icon,
height: 13.h, iconColor: AppColors.blackColor,
fit: BoxFit.contain, width: 18.h,
height: 13.h,
fit: BoxFit.contain,
),
), ),
], ],
), ),

@ -1,5 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.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/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.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/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -21,6 +23,7 @@ class FacilitySelectionItem extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
return Container( return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor, color: AppColors.whiteColor,
@ -42,12 +45,15 @@ class FacilitySelectionItem extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
info, info,
Utils.buildSvgWithAssets( Transform.flip(
icon: AppAssets.forward_arrow_icon, flipX: appState.isArabic() ? true : false,
iconColor: AppColors.blackColor, child: Utils.buildSvgWithAssets(
width: 18, icon: AppAssets.forward_arrow_icon,
height: 13, iconColor: AppColors.blackColor,
fit: BoxFit.contain, width: 18,
height: 13,
fit: BoxFit.contain,
),
), ),
], ],
) )

@ -17,8 +17,7 @@ class HospitalListItem extends StatelessWidget {
late AppState appState; late AppState appState;
HospitalListItem( HospitalListItem({super.key, required this.hospitalData, required this.isLocationEnabled});
{super.key, required this.hospitalData, required this.isLocationEnabled});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -39,12 +38,15 @@ class HospitalListItem extends StatelessWidget {
children: [hospitalName, distanceInfo], children: [hospitalName, distanceInfo],
), ),
), ),
Utils.buildSvgWithAssets( Transform.flip(
icon: AppAssets.forward_arrow_icon, flipX: appState.isArabic() ? true : false,
iconColor: AppColors.blackColor, child: Utils.buildSvgWithAssets(
width: 18, icon: AppAssets.forward_arrow_icon,
height: 13, iconColor: AppColors.blackColor,
fit: BoxFit.contain, width: 18,
height: 13,
fit: BoxFit.contain,
),
), ),
], ],
).paddingSymmetrical(16.h, 16.h), ).paddingSymmetrical(16.h, 16.h),
@ -70,24 +72,17 @@ class HospitalListItem extends StatelessWidget {
); );
Widget get distanceInfo => Row( Widget get distanceInfo => Row(
children: [ children: [
Visibility( Visibility(
visible: (hospitalData?.distanceInKMs != "0"), visible: (hospitalData?.distanceInKMs != "0"),
child: child: AppCustomChipWidget(
labelText: "${hospitalData?.distanceInKMs ?? ""} km".needTranslation,
deleteIcon: AppAssets.location_red,
AppCustomChipWidget( deleteIconSize: Size(9, 12),
labelText: backgroundColor: AppColors.secondaryLightRedColor,
"${hospitalData?.distanceInKMs ?? ""} km".needTranslation, textColor: AppColors.errorColor,
deleteIcon: AppAssets.location_red, ),
deleteIconSize: Size(9, 12), ),
backgroundColor: AppColors.secondaryLightRedColor,
textColor: AppColors.errorColor,
),
),
Visibility( Visibility(
visible: (hospitalData?.distanceInKMs == "0"), visible: (hospitalData?.distanceInKMs == "0"),
child: Row( child: Row(
@ -96,8 +91,9 @@ class HospitalListItem extends StatelessWidget {
labelText: "Distance not available".needTranslation, labelText: "Distance not available".needTranslation,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
), ),
SizedBox(width: 8.h,) SizedBox(
width: 8.h,
)
], ],
)), )),
Visibility( Visibility(

@ -1,6 +1,8 @@
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: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/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.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/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -15,15 +17,11 @@ class RegionListItem extends StatelessWidget {
final String hmgCount; final String hmgCount;
final String subTitle; final String subTitle;
const RegionListItem( const RegionListItem({super.key, required this.title, required this.subTitle, required this.hmcCount, required this.hmgCount});
{super.key,
required this.title,
required this.subTitle,
required this.hmcCount,
required this.hmgCount});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
return Container( return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor, color: AppColors.whiteColor,
@ -40,18 +38,19 @@ class RegionListItem extends StatelessWidget {
Row( Row(
spacing: 8.h, spacing: 8.h,
children: [ children: [
placesCountItem( placesCountItem(AppAssets.hmg, hmgCount, " ${LocaleKeys.hospital.tr()}"),
AppAssets.hmg, hmgCount, " ${LocaleKeys.hospital.tr()}"), placesCountItem(AppAssets.hmc, hmcCount, " ${LocaleKeys.medicalCenters.tr()}"),
placesCountItem(AppAssets.hmc, hmcCount,
" ${LocaleKeys.medicalCenters.tr()}"),
], ],
), ),
Utils.buildSvgWithAssets( Transform.flip(
icon: AppAssets.forward_arrow_icon, flipX: appState.isArabic() ? true : false,
iconColor: AppColors.blackColor, child: Utils.buildSvgWithAssets(
width: 18, icon: AppAssets.forward_arrow_icon,
height: 13, iconColor: AppColors.blackColor,
fit: BoxFit.contain, width: 18,
height: 13,
fit: BoxFit.contain,
),
), ),
], ],
) )
@ -66,24 +65,14 @@ class RegionListItem extends StatelessWidget {
icon: svgPath, icon: svgPath,
iconHasColor: false, iconHasColor: false,
richText: RichText( richText: RichText(
text: TextSpan( text: TextSpan(
text: count, text: count,
style: TextStyle( style: TextStyle(fontSize: 12.h, fontWeight: FontWeight.w700, color: AppColors.blackColor),
fontSize: 12.h, children: [TextSpan(text: title, style: TextStyle(fontSize: 12.h, fontWeight: FontWeight.w500, color: AppColors.blackColor))])),
fontWeight: FontWeight.w700,
color: AppColors.blackColor),
children: [
TextSpan(
text: title,
style: TextStyle(
fontSize: 12.h,
fontWeight: FontWeight.w500,
color: AppColors.blackColor))
])),
); );
} }
Widget get header => Column( Widget get header => Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [

@ -117,7 +117,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
), ),
], ],
), ),
Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h), Transform.flip(
flipX: appState.isArabic() ? true : false, child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h)),
], ],
).onPress(() { ).onPress(() {
bookAppointmentsViewModel.setIsClinicsListLoading(true); bookAppointmentsViewModel.setIsClinicsListLoading(true);
@ -148,7 +149,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
), ),
], ],
), ),
Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h), Transform.flip(
flipX: appState.isArabic() ? true : false, child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h)),
], ],
).onPress(() { ).onPress(() {
bookAppointmentsViewModel.setIsDoctorSearchByNameStarted(false); bookAppointmentsViewModel.setIsDoctorSearchByNameStarted(false);
@ -177,7 +179,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
), ),
], ],
), ),
Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h), Transform.flip(
flipX: appState.isArabic() ? true : false, child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h)),
], ],
).onPress(() { ).onPress(() {
openRegionListBottomSheet(context); openRegionListBottomSheet(context);

@ -1,5 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.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/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.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/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -15,6 +17,7 @@ class ClinicCard extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
return Container( return Container(
padding: EdgeInsets.all(16.h), padding: EdgeInsets.all(16.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
@ -33,7 +36,9 @@ class ClinicCard extends StatelessWidget {
SizedBox(height: 16.h), SizedBox(height: 16.h),
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Expanded(child: (isLoading ? "Cardiology" : clinicsListResponseModel.clinicDescription!).toText16(isBold: true).toShimmer2(isShow: isLoading)), Expanded(child: (isLoading ? "Cardiology" : clinicsListResponseModel.clinicDescription!).toText16(isBold: true).toShimmer2(isShow: isLoading)),
Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor).toShimmer2(isShow: isLoading), Transform.flip(
flipX: appState.isArabic() ? true : false,
child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor).toShimmer2(isShow: isLoading)),
]), ]),
], ],
), ),

@ -14,7 +14,6 @@ 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/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class HabibWalletPage extends StatefulWidget { class HabibWalletPage extends StatefulWidget {
@ -25,8 +24,11 @@ class HabibWalletPage extends StatefulWidget {
} }
class _HabibWalletState extends State<HabibWalletPage> { class _HabibWalletState extends State<HabibWalletPage> {
late HabibWalletViewModel habibWalletVM;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
habibWalletVM = Provider.of<HabibWalletViewModel>(context, listen: false);
AppState _appState = getIt.get<AppState>(); AppState _appState = getIt.get<AppState>();
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
@ -66,10 +68,10 @@ class _HabibWalletState extends State<HabibWalletPage> {
), ),
Spacer(), Spacer(),
LocaleKeys.balanceAmount.tr(context: context).toText14(weight: FontWeight.w500, color: AppColors.whiteColor), LocaleKeys.balanceAmount.tr(context: context).toText14(weight: FontWeight.w500, color: AppColors.whiteColor),
SizedBox(height: 4.h),
Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) { Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) {
return Utils.getPaymentAmountWithSymbol(habibWalletVM.habibWalletAmount.toString().toText32(isBold: true, color: AppColors.whiteColor), AppColors.whiteColor, 13.h, return Utils.getPaymentAmountWithSymbol2(habibWalletVM.habibWalletAmount, textColor: AppColors.whiteColor, iconColor: AppColors.whiteColor, iconSize: 13, isExpanded: false)
isExpanded: false) .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 24.h);
.toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 40.h);
}), }),
], ],
), ),
@ -84,11 +86,15 @@ class _HabibWalletState extends State<HabibWalletPage> {
iconSize: 21.h, iconSize: 21.h,
text: "Recharge".needTranslation, text: "Recharge".needTranslation,
onPressed: () { onPressed: () {
Navigator.of(context).push( Navigator.of(context)
.push(
CustomPageRoute( CustomPageRoute(
page: RechargeWalletPage(), page: RechargeWalletPage(),
), ),
); )
.then((val) {
habibWalletVM.getPatientBalanceAmount();
});
}, },
backgroundColor: AppColors.infoColor, backgroundColor: AppColors.infoColor,
borderColor: AppColors.infoColor, borderColor: AppColors.infoColor,
@ -96,7 +102,7 @@ class _HabibWalletState extends State<HabibWalletPage> {
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
borderRadius: 12, borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h, height: 40.h,
), ),
], ],

@ -1,5 +1,6 @@
import 'dart:async';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:family_bottom_sheet/family_bottom_sheet.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.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';
@ -8,12 +9,17 @@ 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/habib_wallet/habib_wallet_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/habib_wallet/wallet_payment_confirm_page.dart';
import 'package:hmg_patient_app_new/presentation/habib_wallet/widgets/select_hospital_bottom_sheet.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/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/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:provider/provider.dart';
import 'widgets/select-medical_file.dart'; import 'widgets/select-medical_file.dart';
@ -27,198 +33,222 @@ class RechargeWalletPage extends StatefulWidget {
class _RechargeWalletPageState extends State<RechargeWalletPage> { class _RechargeWalletPageState extends State<RechargeWalletPage> {
FocusNode textFocusNode = FocusNode(); FocusNode textFocusNode = FocusNode();
late HabibWalletViewModel habibWalletVM;
late AppState appState;
final TextEditingController amountTextController = TextEditingController();
@override
void initState() {
scheduleMicrotask(() {
habibWalletVM.setDepositorDetails(appState.getAuthenticatedUser()!.patientId.toString(), "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}",
appState.getAuthenticatedUser()!.mobileNumber!);
habibWalletVM.setSelectedRechargeType(0);
habibWalletVM.getProjectsList();
});
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>(); habibWalletVM = Provider.of<HabibWalletViewModel>(context, listen: false);
appState = getIt.get<AppState>();
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
body: Column( body: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded( Expanded(
child: CollapsingListView( child: CollapsingListView(
title: LocaleKeys.createAdvancedPayment.tr(context: context), title: LocaleKeys.createAdvancedPayment.tr(context: context),
child: SingleChildScrollView( child: SingleChildScrollView(
child: Padding( child: Padding(
padding: EdgeInsets.all(24.h), padding: EdgeInsets.all(24.h),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Container( Container(
height: 135.h, height: 135.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor, color: AppColors.whiteColor,
borderRadius: 24.h, borderRadius: 24.h,
hasShadow: false, hasShadow: false,
side: BorderSide(color: AppColors.textColor, width: 2.h), side: BorderSide(color: AppColors.textColor, width: 2.h),
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(16.h), padding: EdgeInsets.all(16.h),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
"Enter an amount".needTranslation.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500), //TODO: Check with hussain to show AED or SAR
Spacer(), "Enter an amount".needTranslation.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
Row( Spacer(),
crossAxisAlignment: CrossAxisAlignment.end, Row(
children: [ crossAxisAlignment: CrossAxisAlignment.end,
Utils.getPaymentAmountWithSymbol( children: [
SizedBox( Utils.getPaymentAmountWithSymbol(
width: 150.h, SizedBox(
child: TextInputWidget( width: 150.h,
labelText: "", child: TextInputWidget(
hintText: "", controller: amountTextController,
isEnable: true, labelText: "",
prefix: null, hintText: "",
isAllowRadius: true, isEnable: true,
isBorderAllowed: false, prefix: null,
isAllowLeadingIcon: true, isAllowRadius: true,
autoFocus: true, isBorderAllowed: false,
fontSize: 40, isAllowLeadingIcon: true,
padding: EdgeInsets.symmetric(horizontal: 8.h, vertical: 0.h), autoFocus: true,
focusNode: textFocusNode, fontSize: 40,
isWalletAmountInput: true, padding: EdgeInsets.symmetric(horizontal: 8.h, vertical: 0.h),
// leadingIcon: AppAssets.student_card, focusNode: textFocusNode,
isWalletAmountInput: true,
keyboardType: TextInputType.numberWithOptions(signed: false, decimal: true),
// leadingIcon: AppAssets.student_card,
),
), ),
), AppColors.textColor,
AppColors.textColor, 13.h,
13.h, isExpanded: false),
isExpanded: false), const Spacer(),
const Spacer(), "SAR".needTranslation.toText20(color: AppColors.greyTextColor, weight: FontWeight.w500),
"SAR".needTranslation.toText20(color: AppColors.greyTextColor, weight: FontWeight.w500), ],
], ),
), ],
], ),
), ),
), ),
), SizedBox(height: 24.h),
SizedBox(height: 24.h), Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) {
Container( return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor, color: AppColors.whiteColor,
borderRadius: 24.h, borderRadius: 24.h,
hasShadow: false, hasShadow: false,
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(16.h), padding: EdgeInsets.all(16.h),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Utils.buildSvgWithAssets(icon: AppAssets.my_account_icon, width: 40.h, height: 40.h), Row(
SizedBox(width: 8.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.myAccount.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500), Utils.buildSvgWithAssets(icon: AppAssets.my_account_icon, width: 40.h, height: 40.h),
"${LocaleKeys.medicalFile.tr(context: context)}: ${appState.getAuthenticatedUser()!.patientId}" SizedBox(width: 8.h),
.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500), Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(habibWalletVM.getSelectedRechargeTypeValue()).toText16(color: AppColors.textColor, weight: FontWeight.w500),
"${LocaleKeys.medicalFile.tr(context: context)}: ${habibWalletVM.fileNumber}"
.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
],
),
], ],
), ),
Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, width: 25.h, height: 25.h),
], ],
), ).onPress(() async {
Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, width: 25.h, height: 25.h), habibWalletVM.setCurrentIndex(0);
], showCommonBottomSheetWithoutHeight(context, title: "Select Medical File".needTranslation,
).onPress(() async { titleWidget: Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) {
// showCommonBottomSheetWithoutHeight(context, title: "Select Medical File".needTranslation, child: SelectMedicalFile(), callBackFunc: () {}, isFullScreen: false); return habibWalletVM.currentIndex != 0
// showCommonBottomSheetWithoutHeight(context, title: "Select Medical File".needTranslation, child: const MultiPageBottomSheet(), callBackFunc: () {}, isFullScreen: false); ? IconButton(
await FamilyModalSheet.show<void>( icon: Utils.buildSvgWithAssets(icon: AppAssets.arrow_back, width: 24.h, height: 24.h),
context: context, padding: EdgeInsets.zero,
contentBackgroundColor: AppColors.scaffoldBgColor, onPressed: () => habibWalletVM.setCurrentIndex(0),
backgroundColor: AppColors.bottomSheetBgColor, highlightColor: Colors.transparent,
mainContentPadding: EdgeInsets.all(24.h), )
isScrollControlled: true, : "Select Medical File".needTranslation.toText20(weight: FontWeight.w600);
safeAreaMinimum: EdgeInsets.zero, }), child: Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) {
useSafeArea: false, return MultiPageBottomSheet();
sheetAnimationStyle: AnimationStyle( }), callBackFunc: () {}, isFullScreen: false, isCloseButtonVisible: true);
duration: Duration(milliseconds: 500), // Custom animation duration }),
reverseDuration: Duration(milliseconds: 300), // Custom reverse animation duration SizedBox(height: 16.h),
), Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h),
builder: (ctx) { SizedBox(height: 16.h),
return const MultiPageBottomSheet();
},
// Optional configurations
);
}),
SizedBox(height: 16.h),
Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h),
SizedBox(height: 16.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Utils.buildSvgWithAssets(icon: AppAssets.select_hospital_icon, width: 40.h, height: 40.h), Row(
SizedBox(width: 8.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.hospital.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500), Utils.buildSvgWithAssets(icon: AppAssets.select_hospital_icon, width: 40.h, height: 40.h),
"Olaya".toText14(color: AppColors.greyTextColor, weight: FontWeight.w500), SizedBox(width: 8.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.hospital.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500),
SizedBox(
width: MediaQuery.of(context).size.width * 0.55,
child: (habibWalletVM.selectedHospital != null ? habibWalletVM.selectedHospital!.name : LocaleKeys.selectHospital.tr(context: context))!
.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
),
],
),
], ],
), ).onPress(() {
showCommonBottomSheetWithoutHeight(context,
title: LocaleKeys.selectHospital.tr(context: context), isDismissible: false, child: SelectHospitalBottomSheet(), callBackFunc: () {});
}),
Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, width: 25.h, height: 25.h),
], ],
), ),
Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, width: 25.h, height: 25.h), SizedBox(height: 16.h),
], Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h),
), SizedBox(height: 16.h),
SizedBox(height: 16.h),
Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h),
SizedBox(height: 16.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Utils.buildSvgWithAssets(icon: AppAssets.email_icon, width: 40.h, height: 40.h), Row(
SizedBox(width: 8.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.email.tr(context: context).toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500), Utils.buildSvgWithAssets(icon: AppAssets.email_icon, width: 40.h, height: 40.h),
"${appState.getAuthenticatedUser()!.emailAddress}".toText16(color: AppColors.textColor, weight: FontWeight.w500), SizedBox(width: 8.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.email.tr(context: context).toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
"${appState.getAuthenticatedUser()!.emailAddress}".toText16(color: AppColors.textColor, weight: FontWeight.w500),
],
),
], ],
), ),
], ],
), ),
], SizedBox(height: 16.h),
), Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h),
SizedBox(height: 16.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Utils.buildSvgWithAssets(icon: AppAssets.notes_icon, width: 40.h, height: 40.h), Row(
SizedBox(width: 8.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.notes.tr(context: context).toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500), Utils.buildSvgWithAssets(icon: AppAssets.notes_icon, width: 40.h, height: 40.h),
"Lorem Ipsum".toText16(color: AppColors.textColor, weight: FontWeight.w500), SizedBox(width: 8.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.notes.tr(context: context).toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
"Lorem Ipsum".toText16(color: AppColors.textColor, weight: FontWeight.w500),
],
),
], ],
), ),
], ],
), ),
SizedBox(height: 8.h),
], ],
), ),
SizedBox(height: 8.h), ),
], );
), }),
), ],
), ),
],
), ),
), ),
), ),
)), ),
//TODO: Handle Family member selection & Other Account Selection
Container( Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor, color: AppColors.whiteColor,
@ -227,7 +257,38 @@ class _RechargeWalletPageState extends State<RechargeWalletPage> {
), ),
child: CustomButton( child: CustomButton(
text: LocaleKeys.next.tr(context: context), text: LocaleKeys.next.tr(context: context),
onPressed: () {}, onPressed: () {
if (amountTextController.text.isEmpty) {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: "Please enter amount to continue.".needTranslation),
callBackFunc: () {
textFocusNode.requestFocus();
},
isFullScreen: false,
isCloseButtonVisible: true,
);
} else if (habibWalletVM.selectedHospital == null) {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: "Please select hospital to continue.".needTranslation),
callBackFunc: () {
textFocusNode.requestFocus();
},
isFullScreen: false,
isCloseButtonVisible: true,
);
} else {
habibWalletVM.setWalletRechargeAmount(num.parse(amountTextController.text));
// habibWalletVM.setDepositorDetails(appState.getAuthenticatedUser()!.patientId.toString(), "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}",
// appState.getAuthenticatedUser()!.mobileNumber!);
Navigator.of(context).push(
CustomPageRoute(
page: WalletPaymentConfirmPage(),
),
);
}
},
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor, borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor, textColor: AppColors.whiteColor,

@ -0,0 +1,430 @@
import 'dart:async';
import 'dart:developer';
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
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/cache_consts.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package: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/habib_wallet/habib_wallet_view_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/apple_pay_request_insert_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_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/chip/app_custom_chip_widget.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/loader/bottomsheet_loader.dart';
import 'package:provider/provider.dart';
class WalletPaymentConfirmPage extends StatefulWidget {
const WalletPaymentConfirmPage({super.key});
@override
State<WalletPaymentConfirmPage> createState() => _WalletPaymentConfirmPageState();
}
class _WalletPaymentConfirmPageState extends State<WalletPaymentConfirmPage> {
late PayfortViewModel payfortViewModel;
late AppState appState;
late HabibWalletViewModel habibWalletVM;
MyInAppBrowser? browser;
String selectedPaymentMethod = "";
String transID = "";
@override
void initState() {
scheduleMicrotask(() {
payfortViewModel.initPayfortViewModel();
});
super.initState();
}
@override
Widget build(BuildContext context) {
appState = getIt.get<AppState>();
habibWalletVM = Provider.of<HabibWalletViewModel>(context, listen: false);
payfortViewModel = Provider.of<PayfortViewModel>(context, listen: false);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: CollapsingListView(
title: "Select Payment Method",
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24.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.mada, width: 72.h, height: 25.h).toShimmer2(isShow: false),
SizedBox(height: 16.h),
"Mada".needTranslation.toText16(isBold: true).toShimmer2(isShow: false),
],
),
SizedBox(width: 8.h),
const Spacer(),
Transform.flip(
flipX: appState.isArabic() ? true : false,
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 18.h,
height: 13.h,
fit: BoxFit.contain,
).toShimmer2(isShow: false),
),
],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "MADA";
openPaymentURL("mada");
}),
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: [
Row(
children: [
Image.asset(AppAssets.visa, width: 40.h, height: 40.h),
SizedBox(width: 8.h),
Image.asset(AppAssets.Mastercard, width: 40.h, height: 40.h),
],
).toShimmer2(isShow: false),
SizedBox(height: 16.h),
"Visa or Mastercard".needTranslation.toText16(isBold: true).toShimmer2(isShow: false),
],
),
SizedBox(width: 8.h),
const Spacer(),
Transform.flip(
flipX: appState.isArabic() ? true : false,
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 18.h,
height: 13.h,
fit: BoxFit.contain,
).toShimmer2(isShow: false),
),
],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "VISA";
openPaymentURL("visa");
}),
],
),
),
),
),
Container(
// height: 200.h,
width: MediaQuery.of(context).size.width,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.h,
hasShadow: true,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24.h),
habibWalletVM.depositorName.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 12.h),
Wrap(
direction: Axis.horizontal,
spacing: 4.h,
runSpacing: 4.h,
children: [
AppCustomChipWidget(labelText: "${LocaleKeys.fileno.tr(context: context)}.: ${habibWalletVM.fileNumber}"),
AppCustomChipWidget(labelText: "${LocaleKeys.mobileNumber.tr(context: context)}: ${habibWalletVM.mobileNumber}"),
AppCustomChipWidget(labelText: "${habibWalletVM.selectedHospital!.name}"),
],
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 16.h),
Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 16.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Total amount to pay".needTranslation.toText16(isBold: true),
Utils.getPaymentAmountWithSymbol(habibWalletVM.walletRechargeAmount.toString().toText24(isBold: true), AppColors.blackColor, 15.h, isSaudiCurrency: true),
],
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 12.h),
Platform.isIOS
? Utils.buildSvgWithAssets(
icon: AppAssets.apple_pay_button,
width: 200.h,
height: 56.h,
fit: BoxFit.contain,
).paddingSymmetrical(24.h, 0.h).onPress(() {
if (Utils.havePrivilege(103)) {
startApplePay();
} else {
openPaymentURL("ApplePay");
}
})
: SizedBox(height: 12.h),
SizedBox(height: 32.h),
],
),
),
],
),
);
}
startApplePay() async {
LoaderBottomSheet.showLoader();
ApplePayInsertRequest applePayInsertRequest = ApplePayInsertRequest();
transID = Utils.getAdvancePaymentTransID(habibWalletVM.selectedHospital!.iD!, int.parse(habibWalletVM.fileNumber));
await payfortViewModel.getPayfortConfigurations(serviceId: ServiceTypeEnum.advancePayment.getIdFromServiceEnum(), projectId: habibWalletVM.selectedHospital!.iD!, integrationId: 2);
applePayInsertRequest.clientRequestID = transID;
applePayInsertRequest.clinicID = 0;
applePayInsertRequest.currency = appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED";
applePayInsertRequest.customerEmail = "CustID_${habibWalletVM.fileNumber.toString()}@HMG.com";
applePayInsertRequest.customerID = habibWalletVM.fileNumber.toString();
applePayInsertRequest.customerName = "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}";
applePayInsertRequest.deviceToken = await Utils.getStringFromPrefs(CacheConst.pushToken);
applePayInsertRequest.voipToken = await Utils.getStringFromPrefs(CacheConst.voipToken);
applePayInsertRequest.doctorID = 0;
applePayInsertRequest.projectID = habibWalletVM.selectedHospital!.iD!.toString();
applePayInsertRequest.serviceID = ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum().toString();
applePayInsertRequest.channelID = 3;
applePayInsertRequest.patientID = habibWalletVM.fileNumber.toString();
applePayInsertRequest.patientTypeID = appState.getAuthenticatedUser()!.patientType;
applePayInsertRequest.patientOutSA = appState.getAuthenticatedUser()!.outSa;
applePayInsertRequest.appointmentDate = null;
applePayInsertRequest.appointmentNo = 0;
applePayInsertRequest.orderDescription = "Advance Payment";
applePayInsertRequest.liveServiceID = "0";
applePayInsertRequest.latitude = "0.0";
applePayInsertRequest.longitude = "0.0";
applePayInsertRequest.amount = habibWalletVM.walletRechargeAmount.toString();
applePayInsertRequest.isSchedule = "0";
applePayInsertRequest.language = appState.isArabic() ? 'ar' : 'en';
applePayInsertRequest.languageID = appState.isArabic() ? 1 : 2;
applePayInsertRequest.userName = int.parse(habibWalletVM.fileNumber);
applePayInsertRequest.responseContinueURL = "http://hmg.com/Documents/success.html";
applePayInsertRequest.backClickUrl = "http://hmg.com/Documents/success.html";
applePayInsertRequest.paymentOption = "ApplePay";
applePayInsertRequest.isMobSDK = true;
applePayInsertRequest.merchantReference = transID;
applePayInsertRequest.merchantIdentifier = payfortViewModel.payfortProjectDetailsRespModel!.merchantIdentifier;
applePayInsertRequest.commandType = "PURCHASE";
applePayInsertRequest.signature = payfortViewModel.payfortProjectDetailsRespModel!.signature;
applePayInsertRequest.accessCode = payfortViewModel.payfortProjectDetailsRespModel!.accessCode;
applePayInsertRequest.shaRequestPhrase = payfortViewModel.payfortProjectDetailsRespModel!.shaRequest;
applePayInsertRequest.shaResponsePhrase = payfortViewModel.payfortProjectDetailsRespModel!.shaResponse;
applePayInsertRequest.returnURL = "";
//TODO: Need to pass dynamic params to the Apple Pay instead of static values
await payfortViewModel.applePayRequestInsert(applePayInsertRequest: applePayInsertRequest).then((value) {
payfortViewModel.paymentWithApplePay(
customerName: "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}",
// customerEmail: projectViewModel.authenticatedUserObject.user.emailAddress,
customerEmail: "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com",
orderDescription: "Appointment Payment",
orderAmount: double.parse(habibWalletVM.walletRechargeAmount.toString()),
merchantReference: transID,
merchantIdentifier: payfortViewModel.payfortProjectDetailsRespModel!.merchantIdentifier,
applePayAccessCode: payfortViewModel.payfortProjectDetailsRespModel!.accessCode,
applePayShaRequestPhrase: payfortViewModel.payfortProjectDetailsRespModel!.shaRequest,
currency: appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED",
onFailed: (failureResult) async {
log("failureResult: ${failureResult.message.toString()}");
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: failureResult.message.toString()),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
},
onSucceeded: (successResult) async {
log("successResult: ${successResult.responseMessage.toString()}");
selectedPaymentMethod = successResult.paymentOption ?? "VISA";
checkPaymentStatus();
},
);
});
}
void checkPaymentStatus() async {
LoaderBottomSheet.showLoader();
await payfortViewModel.checkPaymentStatus(
transactionID: transID,
onSuccess: (apiResponse) async {
print(apiResponse.data);
if (payfortViewModel.payfortCheckPaymentStatusResponseModel!.responseMessage!.toLowerCase() == "success") {
await habibWalletVM.HISCreateAdvancePayment(
paymentMethodName: selectedPaymentMethod,
paidAmount: habibWalletVM.walletRechargeAmount,
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
patientID: habibWalletVM.fileNumber,
projectID: habibWalletVM.selectedHospital!.iD!,
depositorName: habibWalletVM.depositorName,
onSuccess: (value) async {
await habibWalletVM.addAdvanceNumberRequest(
advanceNumber: Utils.isVidaPlusProject(habibWalletVM.selectedHospital!.iD)
? value.data['OnlineCheckInAppointments'][0]['AdvanceNumber_VP'].toString()
: value.data['OnlineCheckInAppointments'][0]['AdvanceNumber'].toString(),
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
onSuccess: (value) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getSuccessWidget(loadingText: "Payment Successful!".needTranslation),
callBackFunc: () {
Navigator.of(context).pop();
Navigator.of(context).pop();
},
isFullScreen: false,
isCloseButtonVisible: true,
);
},
onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: "Payment Failed - ${err}".needTranslation),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
},
onError: (err) {});
} else {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: "Payment Failed! Please try again.".needTranslation),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
}
},
);
}
onBrowserLoadStart(String url) {
print("onBrowserLoadStart");
print(url);
if (selectedPaymentMethod == "tamara") {
if (Platform.isAndroid) {
Uri uri = new Uri.dataFromString(url);
// tamaraPaymentStatus = uri.queryParameters['status']!;
// tamaraOrderID = uri.queryParameters['AuthorizePaymentId']!;
} else {
Uri uri = new Uri.dataFromString(url);
// tamaraPaymentStatus = uri.queryParameters['paymentStatus']!;
// tamaraOrderID = uri.queryParameters['orderId']!;
}
}
// if(selectedPaymentMethod != "TAMARA") {
MyInAppBrowser.successURLS.forEach((element) {
if (url.contains(element)) {
browser?.close();
MyInAppBrowser.isPaymentDone = true;
return;
}
});
// }
// if(selectedPaymentMethod != "TAMARA") {
MyInAppBrowser.errorURLS.forEach((element) {
if (url.contains(element)) {
browser?.close();
MyInAppBrowser.isPaymentDone = false;
return;
}
});
// }
}
onBrowserExit(bool isPaymentMade) async {
print("onBrowserExit Called!!!!");
if (selectedPaymentMethod == "TAMARA") {
// checkTamaraPaymentStatus(transID!, appo);
// if (tamaraPaymentStatus != null && tamaraPaymentStatus.toLowerCase() == "approved") {
// updateTamaraRequestStatus("success", "14", Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo), tamaraOrderID, num.parse(selectedInstallments), appo);
// } else {
// updateTamaraRequestStatus("Failed", "00", Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo), tamaraOrderID, num.parse(selectedInstallments), appo);
// }
} else {
checkPaymentStatus();
// checkPaymentStatus(appo);
}
}
openPaymentURL(String paymentMethod) {
browser = MyInAppBrowser(onExitCallback: onBrowserExit, onLoadStartCallback: onBrowserLoadStart, context: context);
transID = Utils.getAdvancePaymentTransID(habibWalletVM.selectedHospital!.iD!, int.parse(habibWalletVM.fileNumber));
browser?.openPaymentBrowser(
habibWalletVM.walletRechargeAmount,
"Advance Payment",
transID,
habibWalletVM.selectedHospital!.iD!.toString(),
"CustID_${habibWalletVM.fileNumber.toString()}@HMG.com",
selectedPaymentMethod,
appState.getAuthenticatedUser()!.patientType.toString(),
habibWalletVM.depositorName,
habibWalletVM.fileNumber.toString(),
appState.getAuthenticatedUser()!,
browser!,
false,
"3",
"0",
context,
"",
"",
"",
"",
"3");
}
}

@ -0,0 +1,106 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
class HospitalListItemAdvancePayment extends StatelessWidget {
final HospitalsModel hospitalModel;
final bool isLocationEnabled;
late AppState appState;
HospitalListItemAdvancePayment({super.key, required this.hospitalModel, required this.isLocationEnabled});
@override
Widget build(BuildContext context) {
appState = getIt.get<AppState>();
return DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8.h,
children: [hospitalName],
),
),
Transform.flip(
flipX: appState.isArabic() ? true : false,
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 18,
height: 13,
fit: BoxFit.contain,
),
),
],
).paddingSymmetrical(16.h, 16.h),
);
}
Widget get hospitalName => Row(
children: [
Utils.buildSvgWithAssets(
icon: (hospitalModel.isHMC == true) ? AppAssets.hmc : AppAssets.hmg,
).paddingOnly(right: 10),
Expanded(
child: Text(
hospitalModel.name ?? "",
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 16,
color: AppColors.blackColor,
),
),
)
],
);
// Widget get distanceInfo => Row(
// children: [
// Visibility(
// visible: (hospitalModel.distanceInKMs != "0"),
// child: AppCustomChipWidget(
// labelText: "${hospitalData?.distanceInKMs ?? ""} km".needTranslation,
// deleteIcon: AppAssets.location_red,
// deleteIconSize: Size(9, 12),
// backgroundColor: AppColors.secondaryLightRedColor,
// textColor: AppColors.errorColor,
// ),
// ),
// Visibility(
// visible: (hospitalData?.distanceInKMs == "0"),
// child: Row(
// children: [
// AppCustomChipWidget(
// labelText: "Distance not available".needTranslation,
// textColor: AppColors.blackColor,
// ),
// SizedBox(
// width: 8.h,
// )
// ],
// )),
// Visibility(
// visible: !isLocationEnabled,
// child: AppCustomChipWidget(
// labelText: "Location turned off".needTranslation,
// deleteIcon: AppAssets.location_unavailable,
// deleteIconSize: Size(9, 12),
// textColor: AppColors.blackColor,
// )),
// ],
// );
}

@ -27,8 +27,13 @@ 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/habib_wallet/habib_wallet_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/services/dialog_service.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/input_widget.dart';
import 'package:provider/provider.dart';
class MultiPageBottomSheet extends StatefulWidget { class MultiPageBottomSheet extends StatefulWidget {
const MultiPageBottomSheet({Key? key}) : super(key: key); const MultiPageBottomSheet({Key? key}) : super(key: key);
@ -39,90 +44,154 @@ class MultiPageBottomSheet extends StatefulWidget {
class _MultiPageBottomSheetState extends State<MultiPageBottomSheet> { class _MultiPageBottomSheetState extends State<MultiPageBottomSheet> {
late AppState appState; late AppState appState;
static final DialogService _dialogService = getIt.get<DialogService>();
TextEditingController fileNumberEditingController = TextEditingController();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
appState = getIt.get<AppState>(); appState = getIt.get<AppState>();
return SizedBox( return Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) {
height: MediaQuery.of(context).size.height * 0.38, return Padding(
child: Column( padding: MediaQuery.of(context).viewInsets,
crossAxisAlignment: CrossAxisAlignment.start, child: habibWalletVM.isBottomSheetContentLoading ? Utils.getLoadingWidget() : getCurrentIndexWidget(habibWalletVM),
children: [ );
Row( });
crossAxisAlignment: CrossAxisAlignment.center, }
Widget getCurrentIndexWidget(HabibWalletViewModel habibWalletVM) {
switch (habibWalletVM.currentIndex) {
case 0:
return getSelectMedicalFileContent(habibWalletVM);
case 1:
return getOtherAccountContent(habibWalletVM);
case 2:
return getOtherAccountContent(habibWalletVM);
default:
return getSelectMedicalFileContent(habibWalletVM);
}
}
Widget getOtherAccountContent(HabibWalletViewModel habibWalletVM) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Enter File Number".needTranslation.toText20(weight: FontWeight.w600),
SizedBox(height: 12.h),
TextInputWidget(
labelText: LocaleKeys.fileNumber.tr(),
hintText: "xxxxxxxxx",
controller: fileNumberEditingController,
isEnable: true,
prefix: null,
isAllowRadius: true,
isBorderAllowed: false,
isAllowLeadingIcon: true,
autoFocus: false,
padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 8.h),
leadingIcon: AppAssets.requests,
).withVerticalPadding(8),
SizedBox(height: 12.h),
CustomButton(
text: LocaleKeys.submit.tr(),
onPressed: () async {
await habibWalletVM.getPatientInfoByPatientID(
patientID: fileNumberEditingController.text,
onSuccess: (response) async {
print(response.data["GetPatientInfoByPatientIDList"][0]["FullName"]);
await _dialogService.showCommonBottomSheetWithoutH(
message: "A file was found with name: ${response.data["GetPatientInfoByPatientIDList"][0]["FullName"]}, Would you like to recharge wallet for this file number?".needTranslation,
label: LocaleKeys.notice.tr(),
onOkPressed: () {
habibWalletVM.setSelectedRechargeType(3);
habibWalletVM.setDepositorDetails(response.data["GetPatientInfoByPatientIDList"][0]["PatientID"].toString(), response.data["GetPatientInfoByPatientIDList"][0]["FullName"],
response.data["GetPatientInfoByPatientIDList"][0]["MobileNumber"]);
Navigator.of(context).pop();
Navigator.of(context).pop();
},
onCancelPressed: () {});
},
onError: (error) {});
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedBorderColor,
textColor: AppColors.whiteColor,
),
],
);
}
Widget getSelectMedicalFileContent(HabibWalletViewModel habibWalletVM) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 16.h,
hasShadow: false,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
"Select Medical File".toText20(weight: FontWeight.w600).expanded, Column(
Utils.buildSvgWithAssets(icon: AppAssets.close_bottom_sheet_icon, iconColor: Color(0xff2B353E)).onPress(() { crossAxisAlignment: CrossAxisAlignment.start,
Navigator.of(context).pop(); children: [
}), LocaleKeys.myMedicalFile.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500),
"${LocaleKeys.fileno.tr(context: context)}: ${appState.getAuthenticatedUser()!.patientId}".toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
],
),
Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h),
], ],
).paddingAll(16.h),
).onPress(() {
Navigator.of(context).pop();
}),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 16.h,
hasShadow: false,
), ),
Container( child: Row(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( mainAxisAlignment: MainAxisAlignment.spaceBetween,
color: AppColors.whiteColor, children: [
borderRadius: 16.h, Column(
hasShadow: false, crossAxisAlignment: CrossAxisAlignment.start,
), children: [
child: Row( LocaleKeys.familyTitle.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500),
mainAxisAlignment: MainAxisAlignment.spaceBetween, "Select a medical file from your family".needTranslation.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
children: [ ],
Column( ),
crossAxisAlignment: CrossAxisAlignment.start, Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h),
children: [ ],
LocaleKeys.myMedicalFile.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500), ).paddingAll(16.h),
"${LocaleKeys.fileno.tr(context: context)}: ${appState.getAuthenticatedUser()!.patientId}".toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500), ),
], SizedBox(height: 16.h),
), Container(
Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
], color: AppColors.whiteColor,
).paddingAll(16.h), borderRadius: 16.h,
).onPress(() { hasShadow: false,
Navigator.of(context).pop();
}),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 16.h,
hasShadow: false,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.familyTitle.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500),
"Select a medical file from your family".needTranslation.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
],
),
Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h),
],
).paddingAll(16.h),
), ),
SizedBox(height: 16.h), child: Row(
Container( mainAxisAlignment: MainAxisAlignment.spaceBetween,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( children: [
color: AppColors.whiteColor, Column(
borderRadius: 16.h, crossAxisAlignment: CrossAxisAlignment.start,
hasShadow: false, children: [
), LocaleKeys.otherAccount.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500),
child: Row( "Any active medical file from HMG".toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
mainAxisAlignment: MainAxisAlignment.spaceBetween, ],
children: [ ),
Column( Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h),
crossAxisAlignment: CrossAxisAlignment.start, ],
children: [ ).paddingAll(16.h),
LocaleKeys.otherAccount.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500), ).onPress(() {
"Any active medical file from HMG".toText14(color: AppColors.greyTextColor, weight: FontWeight.w500), habibWalletVM.setCurrentIndex(2);
], }),
), ],
Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h),
],
).paddingAll(16.h),
).onPress(() {}),
],
),
); );
} }
} }

@ -0,0 +1,96 @@
import 'package:easy_localization/easy_localization.dart' show tr, StringTranslateExtension;
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/size_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/book_appointments/book_appointments_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/appointment_via_region_viewmodel.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/facility_selection.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/hospital_bottom_sheet/type_selection_widget.dart';
import 'package:hmg_patient_app_new/presentation/habib_wallet/widgets/hospital_list_item.dart';
import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/theme/colors.dart' show AppColors;
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:provider/provider.dart';
class SelectHospitalBottomSheet extends StatelessWidget {
late HabibWalletViewModel habibWalletVM;
final TextEditingController searchText = TextEditingController();
SelectHospitalBottomSheet({super.key});
@override
Widget build(BuildContext context) {
habibWalletVM = Provider.of<HabibWalletViewModel>(context, listen: false);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Text(
// LocaleKeys.selectHospital.tr(),
// style: TextStyle(
// fontSize: 21,
// fontWeight: FontWeight.w600,
// color: AppColors.blackColor,
// ),
// ),
Text(
"Please select the hospital you want to make an advance payment for.".needTranslation,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: AppColors.greyTextColor,
),
),
SizedBox(height: 16.h),
// TextInputWidget(
// labelText: LocaleKeys.search.tr(),
// hintText: "Search Hospital".tr(),
// controller: searchText,
// onChange: (value) {
// // appointmentsViewModel.filterHospitalListByString(value, regionalViewModel.selectedRegionId , regionalViewModel.selectedFacilityType ==
// // FacilitySelection.HMG.name);
// },
// isEnable: true,
// prefix: null,
// autoFocus: false,
// isBorderAllowed: false,
// keyboardType: TextInputType.text,
// isAllowLeadingIcon: true,
// selectionType: SelectionTypeEnum.search,
// padding: EdgeInsets.symmetric(
// vertical: ResponsiveExtension(10).h,
// horizontal: ResponsiveExtension(15).h,
// ),
// ),
// SizedBox(height: 24.h),
// TypeSelectionWidget(
// hmcCount: "0",
// hmgCount: "0",
// ),
// SizedBox(height: 21.h),
SizedBox(
height: MediaQuery.sizeOf(context).height * .4,
child: ListView.separated(
itemBuilder: (_, index) {
return HospitalListItemAdvancePayment(
hospitalModel: habibWalletVM.advancePaymentHospitals[index],
isLocationEnabled: false,
).onPress(() {
habibWalletVM.setSelectedHospital(habibWalletVM.advancePaymentHospitals[index]);
Navigator.of(context).pop();
});
},
separatorBuilder: (_, __) => SizedBox(
height: 16.h,
),
itemCount: habibWalletVM.advancePaymentHospitals.length),
)
],
);
}
}

@ -10,6 +10,7 @@ import 'package:hmg_patient_app_new/features/insurance/insurance_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/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/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';
@ -73,7 +74,7 @@ class InsuranceHistory extends StatelessWidget {
], ],
), ),
SizedBox(height: 8.h), SizedBox(height: 8.h),
"Haroon Amjad".toText16(weight: FontWeight.w600), // "Haroon Amjad".toText16(weight: FontWeight.w600),
SizedBox(height: 8.h), SizedBox(height: 8.h),
Row( Row(
children: [ children: [
@ -82,38 +83,11 @@ class InsuranceHistory extends StatelessWidget {
spacing: 4.h, spacing: 4.h,
runSpacing: 4.h, runSpacing: 4.h,
children: [ children: [
Row( AppCustomChipWidget(
children: [ labelText: "File No.: ${insuranceVM.patientInsuranceCardHistoryList[index].patientID}",
CustomButton(
text: "File No.: 3628599",
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
],
), ),
Row( AppCustomChipWidget(
children: [ labelText: insuranceVM.patientInsuranceCardHistoryList[index].createdOn!,
CustomButton(
text: insuranceVM.patientInsuranceCardHistoryList[index].createdOn!,
// text: "test",
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
),
],
), ),
], ],
), ),

@ -5,12 +5,14 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.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_export.dart'; import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/utils/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/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/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 '../../core/dependencies.dart';
class CollapsingListView extends StatelessWidget { class CollapsingListView extends StatelessWidget {
final String title; final String title;
@ -27,6 +29,7 @@ class CollapsingListView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
body: Column( body: Column(
@ -42,11 +45,14 @@ class CollapsingListView extends StatelessWidget {
surfaceTintColor: Colors.transparent, surfaceTintColor: Colors.transparent,
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
leading: isLeading leading: isLeading
? IconButton( ? Transform.flip(
icon: Utils.buildSvgWithAssets(icon: isClose ? AppAssets.closeBottomNav : AppAssets.arrow_back, width: 32.h, height: 32.h), flipX: appState.isArabic() ? true : false,
padding: EdgeInsets.only(left: 12), child: IconButton(
onPressed: () => Navigator.pop(context), icon: Utils.buildSvgWithAssets(icon: isClose ? AppAssets.closeBottomNav : AppAssets.arrow_back, width: 32.h, height: 32.h),
highlightColor: Colors.transparent, padding: EdgeInsets.only(left: 12),
onPressed: () => Navigator.pop(context),
highlightColor: Colors.transparent,
),
) )
: SizedBox.shrink(), : SizedBox.shrink(),
flexibleSpace: LayoutBuilder( flexibleSpace: LayoutBuilder(
@ -71,7 +77,7 @@ class CollapsingListView extends StatelessWidget {
t, t,
)!, )!,
child: Padding( child: Padding(
padding: EdgeInsets.only(left: leftPadding, bottom: bottomPadding), padding: EdgeInsets.only(left: appState.isArabic() ? 0 : leftPadding, right: appState.isArabic() ? leftPadding : 0, bottom: bottomPadding),
child: Row( child: Row(
spacing: 4.h, spacing: 4.h,
children: [ children: [

@ -6,6 +6,8 @@ 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:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_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/lab/models/resp_models/patient_lab_orders_response_model.dart'; import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_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/features/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
@ -13,6 +15,7 @@ import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart';
import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart'; import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.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/chip/custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'collapsing_list_view.dart'; import 'collapsing_list_view.dart';
@ -65,6 +68,20 @@ class _LabOrdersPageState extends State<LabOrdersPage> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SizedBox(height: 16.h),
CustomTabBar(
activeTextColor: Color(0xffED1C2B),
activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1),
tabs: [
CustomTabBarModel(null, "By Visit".needTranslation),
CustomTabBarModel(null, "By Test".needTranslation),
// CustomTabBarModel(null, "Completed".needTranslation),
],
onTabChange: (index) {
// myAppointmentsViewModel.onTabChange(index);
},
),
SizedBox(height: 16.h),
selectedFilterText!.isNotEmpty selectedFilterText!.isNotEmpty
? CustomChipWidget( ? CustomChipWidget(
chipText: selectedFilterText!, chipText: selectedFilterText!,

@ -25,6 +25,7 @@ import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_mo
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/my_appointments_page.dart';
import 'package:hmg_patient_app_new/presentation/appointments/my_doctors_page.dart'; import 'package:hmg_patient_app_new/presentation/appointments/my_doctors_page.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/book_appointment_page.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart';
import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart'; import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart';
import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart'; import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insurance_card.dart';
@ -122,6 +123,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
child: Padding( child: Padding(
padding: EdgeInsets.all(16.h), padding: EdgeInsets.all(16.h),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -133,43 +135,26 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
children: [ children: [
"${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText18(isBold: true), "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText18(isBold: true),
SizedBox(height: 4.h), SizedBox(height: 4.h),
Row( Wrap(
direction: Axis.horizontal,
spacing: 4.h,
runSpacing: 4.h,
children: [ children: [
CustomButton( AppCustomChipWidget(
icon: AppAssets.file_icon, icon: AppAssets.file_icon,
iconColor: AppColors.blackColor, labelText: "${LocaleKeys.fileNo.tr(context: context)}: ${appState.getAuthenticatedUser()!.patientId}",
iconSize: 12.h, onChipTap: () {
text: "File no: ${appState.getAuthenticatedUser()!.patientId}",
onPressed: () {
//need to remove from this call from here once the family icons will be added
// MyFamilySheet.show(context, medicalFileViewModel.patientFamilyFiles, (profile) {});
navigationService.pushPage( navigationService.pushPage(
page: FamilyMedicalScreen( page: FamilyMedicalScreen(
profiles: medicalFileViewModel.patientFamilyFiles, profiles: medicalFileViewModel.patientFamilyFiles,
onSelect: (FamilyFileResponseModelLists p1) {}, onSelect: (FamilyFileResponseModelLists p1) {},
)); ));
}, },
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.normal,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
), ),
SizedBox(width: 4.h), AppCustomChipWidget(
CustomButton( icon: AppAssets.checkmark_icon,
text: LocaleKeys.verified.tr(context: context), labelText: LocaleKeys.verified.tr(context: context),
onPressed: () {}, iconColor: AppColors.successColor,
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.normal,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
), ),
], ],
), ),
@ -180,55 +165,21 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
SizedBox(height: 16.h), SizedBox(height: 16.h),
Divider(color: AppColors.dividerColor, height: 1.h), Divider(color: AppColors.dividerColor, height: 1.h),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Row( Wrap(
direction: Axis.horizontal,
spacing: 4.h,
runSpacing: 4.h,
children: [ children: [
CustomButton( AppCustomChipWidget(
text: "${appState.getAuthenticatedUser()!.age} Years Old", labelText: "${appState.getAuthenticatedUser()!.age} Years Old",
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.normal,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
), ),
SizedBox(width: 4.h), AppCustomChipWidget(
CustomButton(
icon: AppAssets.blood_icon, icon: AppAssets.blood_icon,
labelText: "${LocaleKeys.bloodType.tr(context: context)}: ${appState.getUserBloodGroup}",
iconColor: AppColors.primaryRedColor, iconColor: AppColors.primaryRedColor,
iconSize: 13.h,
text: "Blood: ${appState.getUserBloodGroup}",
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.normal,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h,
), ),
// SizedBox(width: 4.h),
// CustomButton(
// icon: AppAssets.insurance_active_icon,
// iconColor: AppColors.successColor,
// iconSize: 13.h,
// text: "Insurance Active",
// onPressed: () {},
// backgroundColor: AppColors.bgGreenColor.withOpacity(0.20),
// borderColor: AppColors.bgGreenColor.withOpacity(0.0),
// textColor: AppColors.blackColor,
// fontSize: 10,
// fontWeight: FontWeight.normal,
// borderRadius: 12,
// padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
// height: 30.h,
// ),
], ],
), ),
SizedBox(height: 8.h),
], ],
), ),
), ),
@ -336,7 +287,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
padding: EdgeInsets.only(top: 16.h, left: 24.h, right: 24.h, bottom: 0.h), padding: EdgeInsets.only(top: 16.h, left: 24.h, right: 24.h, bottom: 0.h),
shrinkWrap: true, shrinkWrap: true,
itemCount: myAppointmentsVM.isMyAppointmentsLoading ? 5 : myAppointmentsVM.patientAppointmentsHistoryList.length, itemCount: myAppointmentsVM.isMyAppointmentsLoading ? 5 : (myAppointmentsVM.patientAppointmentsHistoryList.isNotEmpty ? myAppointmentsVM.patientAppointmentsHistoryList.length : 1),
itemBuilder: (context, index) { itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList( return AnimationConfiguration.staggeredList(
position: index, position: index,
@ -354,14 +305,50 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
onRescheduleTap: () {}, onRescheduleTap: () {},
onAskDoctorTap: () {}, onAskDoctorTap: () {},
) )
: MedicalFileAppointmentCard( : myAppointmentsVM.patientAppointmentsHistoryList.isNotEmpty
patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index], ? MedicalFileAppointmentCard(
myAppointmentsViewModel: myAppointmentsViewModel, patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index],
onRescheduleTap: () { myAppointmentsViewModel: myAppointmentsViewModel,
openDoctorScheduleCalendar(myAppointmentsVM.patientAppointmentsHistoryList[index]); onRescheduleTap: () {
}, openDoctorScheduleCalendar(myAppointmentsVM.patientAppointmentsHistoryList[index]);
onAskDoctorTap: () {}, },
), onAskDoctorTap: () {},
)
: Container(
width: MediaQuery.of(context).size.width - 48.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24, hasShadow: true),
child: Padding(
padding: EdgeInsets.all(12.h),
child: Column(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.home_calendar_icon, width: 32.h, height: 32.h),
SizedBox(height: 12.h),
"You do not have any appointments. Please book an appointment".needTranslation.toText12(isCenter: true),
SizedBox(height: 12.h),
CustomButton(
text: LocaleKeys.bookAppo.tr(context: context),
onPressed: () {
Navigator.of(context).push(
CustomPageRoute(
page: BookAppointmentPage(),
),
);
},
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Color(0xffED1C2B),
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40,
icon: AppAssets.add_icon,
iconColor: AppColors.primaryRedColor,
),
],
),
),
),
), ),
), ),
), ),
@ -452,7 +439,9 @@ 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), Transform.flip(
flipX: appState.isArabic() ? true : false,
child: 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();
@ -787,9 +776,4 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
return Container(); return Container();
} }
} }
getMember() {
// AuthanticationViewModel authanticationViewModel = getIt.get<AuthanticationViewModel>();
// RequestUtils.getAddFamilyRequest(nationalIDorFile: nationalIDorFile, mobileNo: mobileNo, countryCode: countryCode, loginType: loginType);
}
} }

@ -1,5 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.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/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.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/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -15,6 +17,7 @@ class LabRadCard extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
return Container( return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: false), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: false),
child: Column( child: Column(
@ -49,13 +52,11 @@ class LabRadCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
SizedBox.shrink(), SizedBox.shrink(),
Utils.buildSvgWithAssets( Transform.flip(
icon: AppAssets.forward_arrow_icon, flipX: appState.isArabic() ? true : false,
width: 15.h, child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, width: 15.h, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor)
height: 15.h, .toShimmer2(isShow: false, radius: 12.h),
fit: BoxFit.contain, ),
iconColor: AppColors.textColor
).toShimmer2(isShow: false, radius: 12.h),
], ],
) )
], ],

@ -1,6 +1,8 @@
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: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/dependencies.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/size_utils.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/core/utils/utils.dart';
@ -13,6 +15,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/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/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';
@ -27,23 +30,20 @@ class MedicalFileAppointmentCard extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
CustomButton( AppCustomChipWidget(
text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false), richText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)
onPressed: () {}, .toText12(color: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.textColor : AppColors.primaryRedColor, fontWeight: FontWeight.w500)
backgroundColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.greyColor : AppColors.secondaryLightRedColor, .paddingOnly(left: 8.h),
borderColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.greyLightColor : AppColors.secondaryLightRedColor,
textColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.textColor : AppColors.primaryRedColor,
fontSize: 12,
fontWeight: FontWeight.w500,
borderRadius: 12.h,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
icon: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppAssets.appointment_calendar_icon : AppAssets.alarm_clock_icon, icon: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppAssets.appointment_calendar_icon : AppAssets.alarm_clock_icon,
iconColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.textColor : AppColors.primaryRedColor, iconColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.textColor : AppColors.primaryRedColor,
iconSize: 16.h, iconSize: 16.h,
backgroundColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.greyColor : AppColors.secondaryLightRedColor,
textColor: AppointmentType.isArrived(patientAppointmentHistoryResponseModel) ? AppColors.textColor : AppColors.primaryRedColor,
padding: EdgeInsets.only(top: 12.h, bottom: 12.h, left: 8.h, right: 8.h),
).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading), ).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Container( Container(
@ -120,11 +120,14 @@ class MedicalFileAppointmentCard extends StatelessWidget {
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(10.h), padding: EdgeInsets.all(10.h),
child: Utils.buildSvgWithAssets( child: Transform.flip(
icon: AppAssets.forward_arrow_icon, flipX: appState.isArabic() ? true : false,
width: 10.h, child: Utils.buildSvgWithAssets(
height: 10.h, icon: AppAssets.forward_arrow_icon,
fit: BoxFit.contain, width: 10.h,
height: 10.h,
fit: BoxFit.contain,
),
), ),
), ),
).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading).onPress(() { ).toShimmer2(isShow: myAppointmentsViewModel.isMyAppointmentsLoading).onPress(() {

@ -139,11 +139,14 @@ class PatientSickLeaveCard extends StatelessWidget {
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(10.h), padding: EdgeInsets.all(10.h),
child: Utils.buildSvgWithAssets( child: Transform.flip(
icon: AppAssets.forward_arrow_icon, flipX: _appState.isArabic() ? true : false,
width: 10.h, child: Utils.buildSvgWithAssets(
height: 10.h, icon: AppAssets.forward_arrow_icon,
fit: BoxFit.contain, width: 10.h,
height: 10.h,
fit: BoxFit.contain,
),
), ),
), ),
).toShimmer2(isShow: isLoading).onPress(() { ).toShimmer2(isShow: isLoading).onPress(() {

@ -10,6 +10,7 @@ import 'package:hmg_patient_app_new/core/utils/validation_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/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/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_model.dart'; import 'package:hmg_patient_app_new/features/medical_file/models/family_file_response_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/my_family/widget/family_cards.dart'; import 'package:hmg_patient_app_new/presentation/my_family/widget/family_cards.dart';
@ -27,10 +28,10 @@ class FamilyMedicalScreen extends StatefulWidget {
final Function(FamilyFileResponseModelLists) onSelect; final Function(FamilyFileResponseModelLists) onSelect;
const FamilyMedicalScreen({ const FamilyMedicalScreen({
Key? key, super.key,
required this.profiles, required this.profiles,
required this.onSelect, required this.onSelect,
}) : super(key: key); });
@override @override
State<FamilyMedicalScreen> createState() => _FamilyMedicalScreenState(); State<FamilyMedicalScreen> createState() => _FamilyMedicalScreenState();
@ -38,6 +39,13 @@ class FamilyMedicalScreen extends StatefulWidget {
class _FamilyMedicalScreenState extends State<FamilyMedicalScreen> { class _FamilyMedicalScreenState extends State<FamilyMedicalScreen> {
List<CustomTabBarModel> tabs = [CustomTabBarModel("", LocaleKeys.medicalFile.tr()), CustomTabBarModel("", LocaleKeys.request.tr())]; List<CustomTabBarModel> tabs = [CustomTabBarModel("", LocaleKeys.medicalFile.tr()), CustomTabBarModel("", LocaleKeys.request.tr())];
MedicalFileViewModel? medicalVM;
@override
void initState() {
super.initState();
medicalVM = getIt.get<MedicalFileViewModel>();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -89,9 +97,11 @@ class _FamilyMedicalScreenState extends State<FamilyMedicalScreen> {
AuthenticationViewModel authVm = getIt.get<AuthenticationViewModel>(); AuthenticationViewModel authVm = getIt.get<AuthenticationViewModel>();
return showCommonBottomSheetWithoutHeight(context, return showCommonBottomSheetWithoutHeight(context,
title: "Add Family Member", title: "Add Family Member",
useSafeArea: true,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [ children: [
"Please fill the below field to add a new family member to your profile".toText16(color: AppColors.textColor, weight: FontWeight.w500), "Please fill the below field to add a new family member to your profile".toText16(color: AppColors.textColor, weight: FontWeight.w500),
SizedBox(height: 20.h), SizedBox(height: 20.h),
@ -104,10 +114,7 @@ class _FamilyMedicalScreenState extends State<FamilyMedicalScreen> {
countryList: CountryEnum.values, countryList: CountryEnum.values,
onCountryChange: authVm.onCountryChange, onCountryChange: authVm.onCountryChange,
).paddingOnly(top: 8.h, bottom: 16.h), ).paddingOnly(top: 8.h, bottom: 16.h),
Divider( Divider(height: 1.h, color: AppColors.spacerLineColor),
height: 1.h,
color: AppColors.spacerLineColor,
),
TextInputWidget( TextInputWidget(
labelText: LocaleKeys.nationalIdNumber.tr(), labelText: LocaleKeys.nationalIdNumber.tr(),
hintText: "xxxxxxxxx", hintText: "xxxxxxxxx",
@ -123,13 +130,10 @@ class _FamilyMedicalScreenState extends State<FamilyMedicalScreen> {
padding: EdgeInsets.symmetric(vertical: 8.h), padding: EdgeInsets.symmetric(vertical: 8.h),
leadingIcon: AppAssets.student_card, leadingIcon: AppAssets.student_card,
).paddingOnly(top: 8.h, bottom: 8.h), ).paddingOnly(top: 8.h, bottom: 8.h),
Divider( Divider(height: 1.h, color: AppColors.spacerLineColor),
height: 1.h,
color: AppColors.spacerLineColor,
),
TextInputWidget( TextInputWidget(
labelText: LocaleKeys.phoneNumber.tr(), labelText: LocaleKeys.phoneNumber.tr(),
hintText: "574345434", hintText: "",
controller: authVm.phoneNumberController, controller: authVm.phoneNumberController,
isEnable: true, isEnable: true,
prefix: authVm.selectedCountrySignup.countryCode, prefix: authVm.selectedCountrySignup.countryCode,
@ -140,35 +144,7 @@ class _FamilyMedicalScreenState extends State<FamilyMedicalScreen> {
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
padding: EdgeInsets.symmetric(vertical: 8.h), padding: EdgeInsets.symmetric(vertical: 8.h),
leadingIcon: AppAssets.smart_phone, leadingIcon: AppAssets.smart_phone,
).paddingOnly(top: 8.h, bottom: 4), ).paddingOnly(top: 8.h, bottom: 4.h),
//TextInputWidget(
// labelText: widget.isForEmail ? LocaleKeys.email.tr() : LocaleKeys.phoneNumber.tr(),
// hintText: widget.isForEmail ? "demo@gmail.com" : "5xxxxxxxx",
// controller: widget.textController!,
// focusNode: _textFieldFocusNode,
// autoFocus: widget.autoFocus,
// padding: EdgeInsets.all(8.h),
// keyboardType: widget.isForEmail ? TextInputType.emailAddress : TextInputType.number,
// onChange: (value) {
// if (widget.onChange != null) {
// widget.onChange!(value);
// }
// },
// onCountryChange: (value) {
// if (widget.onCountryChange != null) {
// widget.onCountryChange!(value);
// }
// },
// isEnable: true,
// isReadOnly: widget.isFromSavedLogin,
// prefix: widget.isForEmail ? null : widget.countryCode,
// isBorderAllowed: false,
// isAllowLeadingIcon: true,
// fontSize: 13.h,
// isCountryDropDown: widget.isEnableCountryDropdown,
// leadingIcon: widget.isForEmail ? AppAssets.email : AppAssets.smart_phone,
// )
], ],
), ),
), ),
@ -184,7 +160,10 @@ class _FamilyMedicalScreenState extends State<FamilyMedicalScreen> {
onOkPress: () { onOkPress: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
)) {} )) {
// authVm.addFamilyMember(otpTypeEnum: OTPTypeEnum.sms, isExcludedUser: true);
medicalVM?.addFamilyFile(otpTypeEnum: OTPTypeEnum.sms, isExcludedUser: true);
}
}, },
icon: AppAssets.add_icon, icon: AppAssets.add_icon,
height: 56.h, height: 56.h,

@ -4,6 +4,8 @@ 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: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/dependencies.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/size_utils.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/core/utils/utils.dart';
@ -42,6 +44,7 @@ class _PrescriptionsListPageState extends State<PrescriptionsListPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
prescriptionsViewModel = Provider.of<PrescriptionsViewModel>(context, listen: false); prescriptionsViewModel = Provider.of<PrescriptionsViewModel>(context, listen: false);
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
@ -249,11 +252,14 @@ class _PrescriptionsListPageState extends State<PrescriptionsListPage> {
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(8.h), padding: EdgeInsets.all(8.h),
child: Utils.buildSvgWithAssets( child: Transform.flip(
icon: AppAssets.forward_arrow_icon, flipX: appState.isArabic() ? true : false,
width: 10.h, child: Utils.buildSvgWithAssets(
height: 10.h, icon: AppAssets.forward_arrow_icon,
fit: BoxFit.contain, width: 10.h,
height: 10.h,
fit: BoxFit.contain,
),
), ),
), ),
).onPress(() { ).onPress(() {

@ -100,13 +100,13 @@ class _ProfileSettingsState extends State<ProfileSettings> {
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Utils.buildSvgWithAssets(icon: AppAssets.wallet, width: 40.h, height: 40.h), Utils.buildSvgWithAssets(icon: AppAssets.wallet, width: 40.h, height: 40.h),
"Al Habib Wallet".needTranslation.toText14(weight: FontWeight.w600, maxlines: 2).expanded, "Habib Wallet".needTranslation.toText14(weight: FontWeight.w600, maxlines: 2).expanded,
Utils.buildSvgWithAssets(icon: AppAssets.arrow_forward), Utils.buildSvgWithAssets(icon: AppAssets.arrow_forward),
], ],
), ),
Spacer(), Spacer(),
Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) { Consumer<HabibWalletViewModel>(builder: (context, habibWalletVM, child) {
return Utils.getPaymentAmountWithSymbol2(habibWalletVM.habibWalletAmount, AppColors.whiteColor, 13.h, isExpanded: false) return Utils.getPaymentAmountWithSymbol2(habibWalletVM.habibWalletAmount, isExpanded: false)
.toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 24.h); .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 24.h);
}), }),
CustomButton( CustomButton(

@ -73,9 +73,8 @@ class DialogServiceImp implements DialogService {
Future<void> showCommonBottomSheetWithoutH({String? label, required String message, required Function() onOkPressed, Function()? onCancelPressed}) async { Future<void> showCommonBottomSheetWithoutH({String? label, required String message, required Function() onOkPressed, Function()? onCancelPressed}) async {
final context = navigationService.navigatorKey.currentContext; final context = navigationService.navigatorKey.currentContext;
if (context == null) return; if (context == null) return;
showCommonBottomSheetWithoutHeight(context, title: label ?? "", child: exceptionBottomSheetWidget(context: context, message: message, onOkPressed: onOkPressed, onCancelPressed: onCancelPressed), showCommonBottomSheetWithoutHeight(context,
callBackFunc: () { title: label ?? "", child: exceptionBottomSheetWidget(context: context, message: message, onOkPressed: onOkPressed, onCancelPressed: onCancelPressed), callBackFunc: () {});
});
} }
@override @override

@ -66,4 +66,7 @@ static const Color greyLightColor = Color(0xFFEFEFF0);
static const Color bottomNAVBorder = Color(0xFFEEEEEE); static const Color bottomNAVBorder = Color(0xFFEEEEEE);
static const Color quickLoginColor = Color(0xFF666666); static const Color quickLoginColor = Color(0xFF666666);
static const Color tooltipTextColor = Color(0xFF414D55);
static const Color graphGridColor = Color(0x4D18C273);
} }

@ -62,16 +62,19 @@ class CustomButton extends StatelessWidget {
children: [ children: [
if (icon != null) if (icon != null)
Padding( Padding(
padding: const EdgeInsets.only(right: 8.0), padding: const EdgeInsets.only(right: 8.0, left: 8.0),
child: Utils.buildSvgWithAssets(icon: icon!, iconColor: iconColor, isDisabled: isDisabled, width: iconSize, height: iconSize), child: Utils.buildSvgWithAssets(icon: icon!, iconColor: iconColor, isDisabled: isDisabled, width: iconSize, height: iconSize),
), ),
Text( Padding(
text, padding: EdgeInsets.only(top: 2.5),
style: context.dynamicTextStyle( child: Text(
fontSize: fontSize.fSize, text,
color: isDisabled ? textColor.withOpacity(0.5) : textColor, style: context.dynamicTextStyle(
letterSpacing: -0.4, fontSize: fontSize.fSize,
fontWeight: fontWeight, color: isDisabled ? textColor.withOpacity(0.5) : textColor,
letterSpacing: -0.4,
fontWeight: fontWeight,
),
), ),
), ),
], ],

@ -23,6 +23,8 @@ class AppCustomChipWidget extends StatelessWidget {
this.deleteIconSize = const Size(12, 12), this.deleteIconSize = const Size(12, 12),
this.deleteIconColor = AppColors.textColor, this.deleteIconColor = AppColors.textColor,
this.deleteIconHasColor = false, this.deleteIconHasColor = false,
this.padding = EdgeInsets.zero,
this.onChipTap
}); });
final String? labelText; final String? labelText;
@ -38,73 +40,79 @@ class AppCustomChipWidget extends StatelessWidget {
final bool iconHasColor; final bool iconHasColor;
final bool deleteIconHasColor; final bool deleteIconHasColor;
final OutlinedBorder? shape; final OutlinedBorder? shape;
final EdgeInsets? padding;
final void Function()? onChipTap;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ChipTheme( return GestureDetector(
data: ChipThemeData( onTap: onChipTap,
padding: EdgeInsets.all(0.0), child: ChipTheme(
shape: SmoothRectangleBorder( data: ChipThemeData(
side: BorderSide( padding: EdgeInsets.all(0.0),
width: 0.0, shape: SmoothRectangleBorder(
color: Colors.transparent, // Crucially, set color to transparent side: BorderSide(
style: BorderStyle.none, width: 0.0,
color: Colors.transparent, // Crucially, set color to transparent
style: BorderStyle.none,
),
borderRadius: BorderRadius.circular(10.0), // Apply a border radius of 16.0
), ),
borderRadius: BorderRadius.circular(8.0), // Apply a border radius of 16.0
), ),
child: icon.isNotEmpty
? Chip(
avatar: icon.isNotEmpty
? Utils.buildSvgWithAssets(
icon: icon,
width: iconSize.h,
height: iconSize.h,
iconColor: iconHasColor ? iconColor : null)
: SizedBox.shrink(),
label: richText ??
labelText!.toText10(
weight: FontWeight.w500,
letterSpacing: -0.64,
color: textColor),
// padding: EdgeInsets.all(0.0),
padding: padding,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
labelPadding: EdgeInsets.only(
left: -4.h,
right: deleteIcon?.isNotEmpty == true ? 2.h : 8.h),
backgroundColor: backgroundColor,
shape: shape,
deleteIcon: deleteIcon?.isNotEmpty == true
? Utils.buildSvgWithAssets(
icon: deleteIcon!,
width: deleteIconSize!.width!.h,
height: deleteIconSize!.height.h,
iconColor: deleteIconHasColor ? deleteIconColor : null)
: null,
onDeleted: deleteIcon?.isNotEmpty == true ? () {} : null,
)
: Chip(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
label: richText ??
labelText!.toText10(
weight: FontWeight.w500,
letterSpacing: -0.64,
color: textColor),
padding: EdgeInsets.all(0.0),
backgroundColor: backgroundColor,
shape: shape,
labelPadding: EdgeInsets.only(
left: 8.h,
right: deleteIcon?.isNotEmpty == true ? -2.h : 8.h),
deleteIcon: deleteIcon?.isNotEmpty == true
? Utils.buildSvgWithAssets(
icon: deleteIcon!,
width: deleteIconSize!.width.h,
height: deleteIconSize!.height.h,
iconColor: deleteIconHasColor ? deleteIconColor : null)
: null,
onDeleted: deleteIcon?.isNotEmpty == true ? () {} : null,
),
), ),
child: icon.isNotEmpty
? Chip(
avatar: icon.isNotEmpty
? Utils.buildSvgWithAssets(
icon: icon,
width: iconSize.h,
height: iconSize.h,
iconColor: iconHasColor ? iconColor : null)
: SizedBox.shrink(),
label: richText ??
labelText!.toText10(
weight: FontWeight.w500,
letterSpacing: -0.64,
color: textColor),
padding: EdgeInsets.all(0.0),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
labelPadding: EdgeInsets.only(
left: -4.h,
right: deleteIcon?.isNotEmpty == true ? 2.h : 8.h),
backgroundColor: backgroundColor,
shape: shape,
deleteIcon: deleteIcon?.isNotEmpty == true
? Utils.buildSvgWithAssets(
icon: deleteIcon!,
width: deleteIconSize!.width!.h,
height: deleteIconSize!.height.h,
iconColor: deleteIconHasColor ? deleteIconColor : null)
: null,
onDeleted: deleteIcon?.isNotEmpty == true ? () {} : null,
)
: Chip(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
label: richText ??
labelText!.toText10(
weight: FontWeight.w500,
letterSpacing: -0.64,
color: textColor),
padding: EdgeInsets.all(0.0),
backgroundColor: backgroundColor,
shape: shape,
labelPadding: EdgeInsets.only(
left: 8.h,
right: deleteIcon?.isNotEmpty == true ? -2.h : 8.h),
deleteIcon: deleteIcon?.isNotEmpty == true
? Utils.buildSvgWithAssets(
icon: deleteIcon!,
width: deleteIconSize!.width.h,
height: deleteIconSize!.height.h,
iconColor: deleteIconHasColor ? deleteIconColor : null)
: null,
onDeleted: deleteIcon?.isNotEmpty == true ? () {} : null,
),
); );
} }
} }

@ -105,54 +105,136 @@ class ButtonSheetContent extends StatelessWidget {
} }
void showCommonBottomSheetWithoutHeight( void showCommonBottomSheetWithoutHeight(
BuildContext context, { BuildContext context, {
required Widget child, required Widget child,
required VoidCallback callBackFunc, required VoidCallback callBackFunc,
String title = "", String title = "",
bool isCloseButtonVisible = true, bool isCloseButtonVisible = true,
bool isFullScreen = true, bool isFullScreen = true,
bool isDismissible = true, bool isDismissible = true,
Widget? titleWidget, Widget? titleWidget,
}) { bool useSafeArea = false,
}) {
showModalBottomSheet<String>( showModalBottomSheet<String>(
sheetAnimationStyle: AnimationStyle( sheetAnimationStyle: AnimationStyle(
duration: Duration(milliseconds: 500), // Custom animation duration duration: Duration(milliseconds: 500),
reverseDuration: Duration(milliseconds: 300), // Custom reverse animation duration reverseDuration: Duration(milliseconds: 300),
), ),
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,
showDragHandle: false, showDragHandle: false,
isDismissible: isDismissible, isDismissible: isDismissible,
backgroundColor: AppColors.bottomSheetBgColor, backgroundColor: AppColors.bottomSheetBgColor,
builder: (BuildContext context) { useSafeArea: useSafeArea,
return SafeArea( builder: (BuildContext context) {
top: false, return SafeArea(
left: false, top: false,
right: false, left: false,
child: isCloseButtonVisible right: false,
? Container( child: Padding(
padding: EdgeInsets.only(left: 24, top: 24, right: 24, bottom: 12), padding: EdgeInsets.only(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.bottomSheetBgColor, borderRadius: 24.h), bottom: MediaQuery.of(context).viewInsets.bottom,
child: Column( ),
mainAxisSize: MainAxisSize.min, child: SingleChildScrollView(
spacing: 16.h, physics: ClampingScrollPhysics(),
child: isCloseButtonVisible
? Container(
padding: EdgeInsets.only(
left: 24,
top: 24,
right: 24,
bottom: 12,
),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.bottomSheetBgColor,
borderRadius: 24.h,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Row( titleWidget ??
mainAxisAlignment: MainAxisAlignment.spaceBetween, Expanded(
crossAxisAlignment: CrossAxisAlignment.center, child: title.toText20(weight: FontWeight.w600),
children: [ ),
titleWidget ?? Expanded(child: title.toText20(weight: FontWeight.w600)), Utils.buildSvgWithAssets(
Utils.buildSvgWithAssets(icon: AppAssets.close_bottom_sheet_icon, iconColor: Color(0xff2B353E)).onPress(() { icon: AppAssets.close_bottom_sheet_icon,
Navigator.of(context).pop(); iconColor: Color(0xff2B353E),
}), ).onPress(() {
], Navigator.of(context).pop();
), }),
child,
], ],
)) ),
: child, SizedBox(height: 16.h),
); child,
}).then((value) { ],
),
)
: child,
),
),
);
},
).then((value) {
callBackFunc(); callBackFunc();
}); });
} }
// void showCommonBottomSheetWithoutHeight(
// BuildContext context, {
// required Widget child,
// required VoidCallback callBackFunc,
// String title = "",
// bool isCloseButtonVisible = true,
// bool isFullScreen = true,
// bool isDismissible = true,
// Widget? titleWidget,
// bool useSafeArea = false,
//
// }) {
// showModalBottomSheet<String>(
// sheetAnimationStyle: AnimationStyle(
// duration: Duration(milliseconds: 500), // Custom animation duration
// reverseDuration: Duration(milliseconds: 300), // Custom reverse animation duration
// ),
// context: context,
// isScrollControlled: true,
// showDragHandle: false,
// isDismissible: isDismissible,
// backgroundColor: AppColors.bottomSheetBgColor,
// useSafeArea: useSafeArea,
// builder: (BuildContext context) {
// return SafeArea(
// top: false,
// left: false,
// right: false,
// child: isCloseButtonVisible
// ? Container(
// padding: EdgeInsets.only(left: 24, top: 24, right: 24, bottom: 12),
// decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.bottomSheetBgColor, borderRadius: 24.h),
// child: Column(
// mainAxisSize: MainAxisSize.min,
// spacing: 16.h,
// children: [
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// titleWidget ?? Expanded(child: title.toText20(weight: FontWeight.w600)),
// Utils.buildSvgWithAssets(icon: AppAssets.close_bottom_sheet_icon, iconColor: Color(0xff2B353E)).onPress(() {
// Navigator.of(context).pop();
// }),
// ],
// ),
// child,
// ],
// ))
// : child,
// );
// }).then((value) {
// callBackFunc();
// });
// }

@ -0,0 +1,287 @@
import 'package:flutter/material.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:hmg_patient_app_new/core/common_models/data_points.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
///
/// CustomGraph(dataPoints: sampleData, scrollDirection: Axis.horizontal,height: 200,maxY: 100, maxX:2.5,
/// leftLabelFormatter: (value){
/// Widget buildLabel(String label) {
/// return Padding(
/// padding: const EdgeInsets.only(right: 8),
/// child: Text(
/// label,
/// style: TextStyle(
/// fontSize: 8.fSize, color: AppColors.textColor,
/// fontFamily:
/// FontUtils.getFontFamilyForLanguage(false)
/// ),
/// textAlign: TextAlign.right,
/// ),
/// );
/// }
/// switch (value.toInt()) {
///
/// case 20:
/// return buildLabel("Critical Low");
/// case 40:
/// return buildLabel("Low");
/// case 60:
/// return buildLabel("Normal");
/// case 80:
/// return buildLabel("High");
/// case 100:
/// return buildLabel("Critical High");
/// }
/// return const SizedBox.shrink();
/// },
///
/// ),
class CustomGraph extends StatelessWidget {
final List<DataPoint> dataPoints;
final double? width;
final double height;
final double? maxY;
final double? maxX;
final Color spotColor;
final Color graphColor;
final Color graphShadowColor;
final Color graphGridColor;
final Color bottomLabelColor;
final double? bottomLabelSize;
final FontWeight? bottomLabelFontWeight;
///creates the left label and provide it to the chart as it will be used by other part of the application so the label will be different for every chart
final Widget Function(double value) leftLabelFormatter;
final Axis scrollDirection;
final bool showBottomTitleDates;
final bool isFullScreeGraph;
const CustomGraph({
super.key,
required this.dataPoints,
required this.leftLabelFormatter,
this.width,
required this.scrollDirection,
required this.height,
this.maxY,
this.maxX,
this.showBottomTitleDates = true,
this.isFullScreeGraph = false,
this.spotColor = AppColors.bgGreenColor,
this.graphColor = AppColors.bgGreenColor,
this.graphShadowColor = AppColors.graphGridColor,
this.graphGridColor = AppColors.graphGridColor,
this.bottomLabelColor = AppColors.textColor,
this.bottomLabelFontWeight = FontWeight.w500,
this.bottomLabelSize,
});
@override
Widget build(BuildContext context) {
// var maxY = 0.0;
double interval = 20;
if ((maxY ?? 0) > 10 && (maxY ?? 0) <= 20) {
interval = 2;
} else if ((maxY ?? 0) > 5 && (maxY ?? 0) <= 10) {
interval = 1;
} else if ((maxY ?? 0) >= 0 && (maxY ?? 0) <= 5) {
interval = .4;
}
return Material(
color: Colors.white,
child: SizedBox(
width: width,
height: height,
child: Padding(
padding: const EdgeInsets.only(top: 8.0, bottom: 8),
child: LineChart(
LineChartData(
minY: 0,
maxY:
((maxY?.ceilToDouble() ?? 0.0) + interval).floorToDouble(),
// minX: dataPoints.first.labelValue - 1,
maxX: maxX,
minX: -0.2,
lineTouchData: LineTouchData(
getTouchLineEnd: (_, __) => 0,
getTouchedSpotIndicator: (barData, indicators) {
// Only show custom marker for touched spot
return indicators.map((int index) {
return TouchedSpotIndicatorData(
FlLine(color: Colors.transparent),
FlDotData(
show: true,
getDotPainter: (spot, percent, barData, idx) {
return FlDotCirclePainter(
radius: 8,
color: spotColor,
strokeWidth: 2,
strokeColor: Colors.white,
);
},
),
);
}).toList();
},
enabled: true,
touchTooltipData: LineTouchTooltipData(
getTooltipColor: (_) => Colors.white,
getTooltipItems: (touchedSpots) {
if (touchedSpots.isEmpty) return [];
// Only show tooltip for the first touched spot, hide others
return touchedSpots.map((spot) {
if (spot == touchedSpots.first) {
final dataPoint = dataPoints[spot.x.toInt()];
return LineTooltipItem(
// '${dataPoint.label} ${spot.y.toStringAsFixed(2)}',
'${dataPoint.value} ',
TextStyle(
color: Colors.black,
fontSize: 12.fSize,
fontWeight: FontWeight.w500),
);
}
return null; // hides the rest
}).toList();
},
),
),
titlesData: FlTitlesData(
leftTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 77,
interval: .1, // Let fl_chart handle it
getTitlesWidget: (value, _) {
return leftLabelFormatter(value);
},
),
),
bottomTitles: AxisTitles(
axisNameSize: 60,
sideTitles: SideTitles(
showTitles: showBottomTitleDates,
reservedSize: 50,
getTitlesWidget: (value, _) {
if ((value.toDouble() >= 0) &&
(value.toDouble() < (maxX ?? dataPoints.length))) {
var label = dataPoints[value.toInt()].label;
return buildBottomLabel(label);
}
return const SizedBox.shrink();
},
interval: 1, // ensures 1:1 mapping with spots
),
),
topTitles: AxisTitles(),
rightTitles: AxisTitles(),
),
borderData: FlBorderData(
show: true,
border: const Border(
bottom: BorderSide.none,
left: BorderSide(color: Colors.grey, width: .5),
right: BorderSide.none,
top: BorderSide.none,
),
),
lineBarsData: _buildColoredLineSegments(dataPoints),
gridData: FlGridData(
show: true,
drawVerticalLine: false,
horizontalInterval: 20,
checkToShowHorizontalLine: (value) =>
value >= 0 && value <= 100,
getDrawingHorizontalLine: (value) {
return FlLine(
color: AppColors.graphGridColor,
strokeWidth: 1,
dashArray: [5, 5],
);
},
),
),
),
),
));
}
List<LineChartBarData> _buildColoredLineSegments(List<DataPoint> dataPoints) {
final List<FlSpot> allSpots = dataPoints.asMap().entries.map((entry) {
return FlSpot(entry.key.toDouble(), entry.value.value);
}).toList();
var data = [
LineChartBarData(
spots: allSpots,
isCurved: true,
isStrokeCapRound: true,
isStrokeJoinRound: true,
barWidth: 4,
gradient: LinearGradient(
colors: [graphColor, graphColor],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
dotData: FlDotData(
show: false,
),
belowBarData: BarAreaData(
show: true,
gradient: LinearGradient(
colors: [
graphShadowColor,
Colors.transparent,
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
)
];
return data;
}
// Widget buildLabel(String label) {
// return Padding(
// padding: const EdgeInsets.only(right: 8),
// child: Text(
// label,
// style: TextStyle(
// fontSize: leftLabelSize ?? 8.fSize, color: leftLabelColor),
// textAlign: TextAlign.right,
// ),
// );
// }
Widget buildBottomLabel(String label) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
label,
style: TextStyle(
fontSize: bottomLabelSize ?? 8.fSize, color: bottomLabelColor),
),
);
}
}
final List<DataPoint> sampleData = [
DataPoint(
value: 20,
label: 'Jan 2024',
),
DataPoint(
value: 36,
label: 'Feb 2024',
),
DataPoint(
value: 80,
label: 'This result',
),
];

@ -55,7 +55,7 @@ dependencies:
uuid: ^4.5.1 uuid: ^4.5.1
health: ^13.1.3 health: ^13.1.3
# health: 12.0.1 # health: 12.0.1
fl_chart: ^1.0.0 fl_chart: ^1.1.1
geolocator: ^14.0.2 geolocator: ^14.0.2
dropdown_search: ^6.0.2 dropdown_search: ^6.0.2
google_maps_flutter: ^2.12.3 google_maps_flutter: ^2.12.3
@ -80,7 +80,6 @@ dependencies:
path_provider: ^2.0.8 path_provider: ^2.0.8
open_filex: ^4.7.0 open_filex: ^4.7.0
flutter_swiper_view: ^1.1.8 flutter_swiper_view: ^1.1.8
family_bottom_sheet: ^0.1.0
location: ^8.0.1 location: ^8.0.1
gms_check: ^1.0.4 gms_check: ^1.0.4

Loading…
Cancel
Save