my appointments implementation contd.

pull/13/head
Haroon Amjad 2 months ago
parent a0bdc34685
commit c27ba6ef09

@ -247,7 +247,7 @@
<!-- </receiver> &lt;!&ndash; Huawei Push Notifications &ndash;&gt;-->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyCiD4YqVqLNYbt8-htvFy4Wp8XSph9E3wM" />
android:value="AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng" />
<!--
Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java

@ -0,0 +1,3 @@
<svg width="15" height="14" viewBox="0 0 15 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.8115 0.745822C15.2258 2.14723 12.963 13.5442 10.6411 13.745C8.69325 13.9135 8.08629 10.0718 7.67603 8.8541C7.27114 7.65237 6.82058 7.21973 5.62874 6.82545C2.60098 5.82381 1.0871 5.32299 0.787367 4.52997C-0.00632346 2.43005 12.0052 -1.04403 13.8115 0.745822Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 394 B

@ -0,0 +1,6 @@
<svg width="343" height="51" viewBox="0 0 343 51" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect y="0.818115" width="343" height="50" rx="8" fill="black"/>
<rect y="0.818115" width="343" height="50" rx="8" stroke="black"/>
<path d="M105.44 32.8181V18.7263H110.684C113.448 18.7263 115.362 20.5818 115.362 23.3455V23.365C115.362 26.1189 113.448 28.0037 110.684 28.0037H107.628V32.8181H105.44ZM110.138 20.572H107.628V26.1677H110.138C112.042 26.1677 113.136 25.1423 113.136 23.3748V23.3552C113.136 21.5974 112.042 20.572 110.138 20.572ZM119.27 33.0037C117.219 33.0037 115.842 31.7439 115.842 29.8982V29.8787C115.842 28.0916 117.229 26.9978 119.66 26.8513L122.453 26.6853V25.9138C122.453 24.781 121.721 24.0974 120.412 24.0974C119.191 24.0974 118.439 24.6736 118.264 25.4939L118.244 25.5818H116.252L116.262 25.4744C116.408 23.7068 117.941 22.3494 120.471 22.3494C122.98 22.3494 124.572 23.6775 124.572 25.738V32.8181H122.453V31.197H122.414C121.818 32.3005 120.627 33.0037 119.27 33.0037ZM117.971 29.8494C117.971 30.7478 118.713 31.3142 119.846 31.3142C121.33 31.3142 122.453 30.3083 122.453 28.9705V28.1697L119.943 28.3259C118.674 28.4041 117.971 28.9607 117.971 29.8298V29.8494ZM127.864 36.2458C127.454 36.2458 127.015 36.197 126.761 36.1482V34.4978C126.927 34.5369 127.171 34.5759 127.454 34.5759C128.45 34.5759 128.997 34.3123 129.349 33.3162L129.525 32.8279L125.784 22.5447H128.07L130.657 30.9041H130.726L133.314 22.5447H135.54L131.712 33.2966C130.95 35.4255 129.876 36.2458 127.864 36.2458ZM142.955 32.8181L140.132 22.5447H142.242L144.117 30.6306H144.156L146.295 22.5447H148.326L150.474 30.6306H150.523L152.398 22.5447H154.488L151.675 32.8181H149.478L147.32 25.1228H147.271L145.132 32.8181H142.955ZM156.97 20.9626C156.286 20.9626 155.739 20.4158 155.739 19.7517C155.739 19.0779 156.286 18.531 156.97 18.531C157.663 18.531 158.2 19.0779 158.2 19.7517C158.2 20.4158 157.663 20.9626 156.97 20.9626ZM155.915 32.8181V22.5447H158.024V32.8181H155.915ZM163.855 33.0232C161.824 33.0232 160.848 32.1638 160.848 30.113V24.2244H159.373V22.5447H160.848V19.8689H163.006V22.5447H164.93V24.2244H163.006V29.9861C163.006 31.031 163.475 31.3435 164.363 31.3435C164.588 31.3435 164.773 31.324 164.93 31.3044V32.9353C164.686 32.9744 164.285 33.0232 163.855 33.0232ZM166.806 32.8181V18.7263H168.915V24.2341H168.964C169.511 23.0427 170.614 22.3494 172.148 22.3494C174.345 22.3494 175.79 23.99 175.79 26.4705V32.8181H173.681V26.8708C173.681 25.1716 172.821 24.156 171.337 24.156C169.882 24.156 168.915 25.2693 168.915 26.8708V32.8181H166.806Z" fill="white"/>
<path d="M193.748 20.6455C194.253 20.6455 196.061 20.6904 197.241 22.4087C197.139 22.4873 195.343 23.498 195.343 25.7666C195.343 28.3945 197.634 29.3267 197.701 29.3491C197.69 29.4053 197.33 30.6182 196.499 31.8647C195.747 32.9429 194.95 34.0322 193.748 34.0322C192.546 34.0322 192.232 33.3359 190.862 33.3359C189.503 33.3359 189.02 34.0547 187.93 34.0547C186.83 34.0547 186.055 33.0439 185.19 31.8198C184.168 30.3486 183.337 28.0913 183.337 25.9463C183.337 22.521 185.572 20.6904 187.773 20.6904C188.93 20.6904 189.907 21.4541 190.637 21.4541C191.333 21.4541 192.411 20.6455 193.748 20.6455ZM193.13 19.1968C192.535 19.9155 191.524 20.4546 190.727 20.4546C190.637 20.4546 190.547 20.4434 190.491 20.4321C190.48 20.3872 190.457 20.2412 190.457 20.1064C190.457 19.1968 190.929 18.2871 191.423 17.7144C192.063 16.9619 193.141 16.4116 194.017 16.3779C194.04 16.479 194.051 16.6025 194.051 16.7261C194.051 17.6357 193.669 18.5342 193.13 19.1968ZM202.115 17.647H208.652C211.886 17.647 214.098 19.8594 214.098 23.1274C214.098 26.3394 211.807 28.5405 208.528 28.5405H205.013V33.8525H202.115V17.647ZM205.013 20.0728V26.1372H207.877C209.943 26.1372 211.156 25.0591 211.156 23.1274C211.156 21.1396 209.977 20.0728 207.888 20.0728H205.013ZM219.535 31.8647C221.219 31.8647 222.477 30.7754 222.477 29.3491V28.3721L219.703 28.5518C218.142 28.6528 217.412 29.2144 217.412 30.2139C217.412 31.2471 218.3 31.8647 219.535 31.8647ZM218.715 34.0547C216.345 34.0547 214.65 32.6172 214.65 30.3711C214.65 28.1475 216.323 26.8672 219.31 26.6875L222.477 26.4966V25.4634C222.477 24.2617 221.669 23.5879 220.164 23.5879C218.884 23.5879 218.008 24.0371 217.749 24.8682H215.121C215.346 22.7007 217.379 21.3193 220.299 21.3193C223.454 21.3193 225.229 22.8579 225.229 25.4634V33.8525H222.545V32.168H222.354C221.669 33.3584 220.321 34.0547 218.715 34.0547ZM228.329 38.311C228.161 38.311 227.408 38.2998 227.229 38.2661V35.9863C227.386 36.02 227.801 36.0312 227.992 36.0312C229.172 36.0312 229.834 35.582 230.194 34.4478L230.34 33.9087L225.948 21.5664H229.003L231.878 31.1572H232.069L234.933 21.5664H237.875L233.439 34.2456C232.395 37.3003 231.081 38.311 228.329 38.311Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

@ -48,6 +48,7 @@
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
478CFA932E638C8E0064F3D7 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
478CFA952E6E20A60064F3D7 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7595037DD52211B91157B0F3 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
@ -129,6 +130,7 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
478CFA952E6E20A60064F3D7 /* Runner.entitlements */,
478CFA932E638C8E0064F3D7 /* GoogleService-Info.plist */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
@ -450,8 +452,9 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = ZB3P5B74MA;
DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
@ -632,8 +635,9 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = ZB3P5B74MA;
DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
@ -657,8 +661,9 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = ZB3P5B74MA;
DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;

@ -165,6 +165,9 @@ class ApiClientImp implements ApiClient {
body['LogInTokenID'] = _appState.appLoginTokenID;
}
body['TokenID'] = "@dm!n";
body['PatientID'] = "3628599";
body.removeWhere((key, value) => value == null);
log("body: ${json.encode(body)}");
log("uri: ${Uri.parse(url.trim())}");

@ -82,6 +82,8 @@ class AppAssets {
static const String appointment_checkin_icon = '$svgBasePath/appointment_checkin_icon.svg';
static const String ask_doctor_icon = '$svgBasePath/ask_doctor_icon.svg';
static const String uae_dirham_symbol = '$svgBasePath/uae_dirham_symbol.svg';
static const String directions_icon = '$svgBasePath/directions_icon.svg';
static const String apple_pay_button = '$svgBasePath/pay_with_apple_pay.svg';
//bottom navigation//
static const String homeBottom = '$svgBasePath/home_bottom.svg';

@ -526,4 +526,13 @@ class Utils {
static String generateMd5Hash(String input) {
return crypto.md5.convert(utf8.encode(input)).toString();
}
static String getAppointmentTransID(int projectID, int clinicID, int appoNo, {bool isAddMilliseconds = true}) {
String currentMillis = DateTime.now().millisecondsSinceEpoch.toString();
return '$projectID-$clinicID-$appoNo${isAddMilliseconds ? '-${currentMillis.substring(currentMillis.length - 5, currentMillis.length)}' : ""}';
}
static String getAdvancePaymentTransID(int projectID, int fileNumber) {
return '$projectID-$fileNumber-${DateTime.now().millisecondsSinceEpoch}';
}
}

@ -0,0 +1,253 @@
class PatientAppointmentShareResponseModel {
dynamic advanceNumber;
dynamic advanceNumberVP;
String? appointmentDate;
int? appointmentNo;
dynamic cardNumber;
dynamic cardType;
int? cashPrice;
int? cashPriceTax;
int? cashPriceWithTax;
int? clinicID;
String? clinicName;
int? companyId;
String? companyName;
int? companyShareWithTax;
int? doctorID;
String? doctorImageURL;
String? doctorNameObj;
List<String>? doctorSpeciality;
dynamic errCode;
int? groupID;
bool? iSAllowOnlineCheckedIN;
String? insurancePolicyNo;
bool? isAppointmentPackaged;
bool? isCash;
bool? isEligible;
bool? isExcludedForOnlineCheckin;
int? isFollowup;
bool? isInsured;
bool? isLiveCareAppointment;
bool? isOnlineCheckedIN;
String? message;
int? nextAction;
dynamic orderId;
String? patientCardID;
int? patientID;
num? patientShare;
num? patientShareWithTax;
int? patientStatusType;
num? patientTaxAmount;
String? patientType;
int? paymentAmount;
String? paymentDate;
dynamic paymentMethodName;
dynamic paymentReferenceNumber;
int? policyId;
String? policyName;
String? procedureName;
int? projectID;
String? projectName;
dynamic rRN;
int? serviceID;
dynamic setupID;
int? sourceType;
String? startTime;
int? status;
int? statusCode;
dynamic statusDesc;
String? subPolicyNo;
int? tax;
int? userID;
PatientAppointmentShareResponseModel({
this.advanceNumber,
this.advanceNumberVP,
this.appointmentDate,
this.appointmentNo,
this.cardNumber,
this.cardType,
this.cashPrice,
this.cashPriceTax,
this.cashPriceWithTax,
this.clinicID,
this.clinicName,
this.companyId,
this.companyName,
this.companyShareWithTax,
this.doctorID,
this.doctorImageURL,
this.doctorNameObj,
this.doctorSpeciality,
this.errCode,
this.groupID,
this.iSAllowOnlineCheckedIN,
this.insurancePolicyNo,
this.isAppointmentPackaged,
this.isCash,
this.isEligible,
this.isExcludedForOnlineCheckin,
this.isFollowup,
this.isInsured,
this.isLiveCareAppointment,
this.isOnlineCheckedIN,
this.message,
this.nextAction,
this.orderId,
this.patientCardID,
this.patientID,
this.patientShare,
this.patientShareWithTax,
this.patientStatusType,
this.patientTaxAmount,
this.patientType,
this.paymentAmount,
this.paymentDate,
this.paymentMethodName,
this.paymentReferenceNumber,
this.policyId,
this.policyName,
this.procedureName,
this.projectID,
this.projectName,
this.rRN,
this.serviceID,
this.setupID,
this.sourceType,
this.startTime,
this.status,
this.statusCode,
this.statusDesc,
this.subPolicyNo,
this.tax,
this.userID,
});
PatientAppointmentShareResponseModel.fromJson(Map<String, dynamic> json) {
advanceNumber = json['AdvanceNumber'];
advanceNumberVP = json['AdvanceNumber_VP'];
appointmentDate = json['AppointmentDate'];
appointmentNo = json['AppointmentNo'];
cardNumber = json['CardNumber'];
cardType = json['CardType'];
cashPrice = json['CashPrice'];
cashPriceTax = json['CashPriceTax'];
cashPriceWithTax = json['CashPriceWithTax'];
clinicID = json['ClinicID'];
clinicName = json['ClinicName'];
companyId = json['CompanyId'];
companyName = json['CompanyName'];
companyShareWithTax = json['CompanyShareWithTax'];
doctorID = json['DoctorID'];
doctorImageURL = json['DoctorImageURL'];
doctorNameObj = json['DoctorNameObj'];
doctorSpeciality = json['DoctorSpeciality'].cast<String>();
errCode = json['ErrCode'];
groupID = json['GroupID'];
iSAllowOnlineCheckedIN = json['ISAllowOnlineCheckedIN'];
insurancePolicyNo = json['InsurancePolicyNo'];
isAppointmentPackaged = json['IsAppointmentPackaged'];
isCash = json['IsCash'];
isEligible = json['IsEligible'];
isExcludedForOnlineCheckin = json['IsExcludedForOnlineCheckin'];
isFollowup = json['IsFollowup'];
isInsured = json['IsInsured'];
isLiveCareAppointment = json['IsLiveCareAppointment'];
isOnlineCheckedIN = json['IsOnlineCheckedIN'];
message = json['Message'];
nextAction = json['NextAction'];
orderId = json['OrderId'];
patientCardID = json['PatientCardID'];
patientID = json['PatientID'];
patientShare = json['PatientShare'];
patientShareWithTax = json['PatientShareWithTax'];
patientStatusType = json['PatientStatusType'];
patientTaxAmount = json['PatientTaxAmount'];
patientType = json['PatientType'];
paymentAmount = json['PaymentAmount'];
paymentDate = json['PaymentDate'];
paymentMethodName = json['PaymentMethodName'];
paymentReferenceNumber = json['PaymentReferenceNumber'];
policyId = json['PolicyId'];
policyName = json['PolicyName'];
procedureName = json['ProcedureName'];
projectID = json['ProjectID'];
projectName = json['ProjectName'];
rRN = json['RRN'];
serviceID = json['ServiceID'];
setupID = json['SetupID'];
sourceType = json['SourceType'];
startTime = json['StartTime'];
status = json['Status'];
statusCode = json['StatusCode'];
statusDesc = json['StatusDesc'];
subPolicyNo = json['SubPolicyNo'];
tax = json['Tax'];
userID = json['UserID'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['AdvanceNumber'] = this.advanceNumber;
data['AdvanceNumber_VP'] = this.advanceNumberVP;
data['AppointmentDate'] = this.appointmentDate;
data['AppointmentNo'] = this.appointmentNo;
data['CardNumber'] = this.cardNumber;
data['CardType'] = this.cardType;
data['CashPrice'] = this.cashPrice;
data['CashPriceTax'] = this.cashPriceTax;
data['CashPriceWithTax'] = this.cashPriceWithTax;
data['ClinicID'] = this.clinicID;
data['ClinicName'] = this.clinicName;
data['CompanyId'] = this.companyId;
data['CompanyName'] = this.companyName;
data['CompanyShareWithTax'] = this.companyShareWithTax;
data['DoctorID'] = this.doctorID;
data['DoctorImageURL'] = this.doctorImageURL;
data['DoctorNameObj'] = this.doctorNameObj;
data['DoctorSpeciality'] = this.doctorSpeciality;
data['ErrCode'] = this.errCode;
data['GroupID'] = this.groupID;
data['ISAllowOnlineCheckedIN'] = this.iSAllowOnlineCheckedIN;
data['InsurancePolicyNo'] = this.insurancePolicyNo;
data['IsAppointmentPackaged'] = this.isAppointmentPackaged;
data['IsCash'] = this.isCash;
data['IsEligible'] = this.isEligible;
data['IsExcludedForOnlineCheckin'] = this.isExcludedForOnlineCheckin;
data['IsFollowup'] = this.isFollowup;
data['IsInsured'] = this.isInsured;
data['IsLiveCareAppointment'] = this.isLiveCareAppointment;
data['IsOnlineCheckedIN'] = this.isOnlineCheckedIN;
data['Message'] = this.message;
data['NextAction'] = this.nextAction;
data['OrderId'] = this.orderId;
data['PatientCardID'] = this.patientCardID;
data['PatientID'] = this.patientID;
data['PatientShare'] = this.patientShare;
data['PatientShareWithTax'] = this.patientShareWithTax;
data['PatientStatusType'] = this.patientStatusType;
data['PatientTaxAmount'] = this.patientTaxAmount;
data['PatientType'] = this.patientType;
data['PaymentAmount'] = this.paymentAmount;
data['PaymentDate'] = this.paymentDate;
data['PaymentMethodName'] = this.paymentMethodName;
data['PaymentReferenceNumber'] = this.paymentReferenceNumber;
data['PolicyId'] = this.policyId;
data['PolicyName'] = this.policyName;
data['ProcedureName'] = this.procedureName;
data['ProjectID'] = this.projectID;
data['ProjectName'] = this.projectName;
data['RRN'] = this.rRN;
data['ServiceID'] = this.serviceID;
data['SetupID'] = this.setupID;
data['SourceType'] = this.sourceType;
data['StartTime'] = this.startTime;
data['Status'] = this.status;
data['StatusCode'] = this.statusCode;
data['StatusDesc'] = this.statusDesc;
data['SubPolicyNo'] = this.subPolicyNo;
data['Tax'] = this.tax;
data['UserID'] = this.userID;
return data;
}
}

@ -4,11 +4,15 @@ 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/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_share_response_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class MyAppointmentsRepo {
Future<Either<Failure, GenericApiModel<List<PatientAppointmentHistoryResponseModel>>>> getPatientAppointments(
{required String patientId, required bool isActiveAppointment, required bool isArrivedAppointments});
Future<Either<Failure, GenericApiModel<PatientAppointmentShareResponseModel>>> getPatientShareAppointment(
{required String patientId, required int projectID, required int clinicID, required String appointmentNo});
}
class MyAppointmentsRepoImp implements MyAppointmentsRepo {
@ -22,23 +26,12 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
{required String patientId, required bool isActiveAppointment, required bool isArrivedAppointments}) async {
final mapDevice = {
"IsActiveAppointment": isActiveAppointment,
"VersionID": 19.0,
"Channel": 3,
"IPAdress": "10.20.10.20",
"generalid": "Cs2020@2016\$2958",
"SessionID": "HdXmi80U6ocW3ZOdT8EpfDDke1ncXyEfIaDLJJjihvA",
"isDentalAllowedBackend": false,
"DeviceTypeID": 1,
"PatientID": patientId,
"PatientTypeID": 1,
"IsComingFromCOC": false,
"PatientType": 1,
"LanguageID": 2,
"isForUpcomming": false,
"IsForArrived": isArrivedAppointments,
"Latitude": 0.0,
"Longitude": 0.0,
"TokenID": "@dm!n",
"PatientOutSA": 0
};
@ -78,4 +71,62 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<PatientAppointmentShareResponseModel>>> getPatientShareAppointment(
{required String patientId, required int projectID, required int clinicID, required String appointmentNo}) async {
final mapRequest = {
"ProjectID": projectID,
"ClinicID": clinicID,
"AppointmentNo": appointmentNo,
"IsActiveAppointment": true,
"PatientOutSA": 0,
"isDentalAllowedBackend": false,
"PatientID": patientId,
"PatientTypeID": 1,
"PatientType": 1,
};
try {
GenericApiModel<PatientAppointmentShareResponseModel>? apiResponse;
Failure? failure;
await apiClient.post(
GET_PATIENT_SHARE,
body: mapRequest,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response['OnlineCheckInAppointments'];
if (list == null || list.isEmpty) {
throw Exception("patient share list is empty");
}
final patientShareObj = PatientAppointmentShareResponseModel.fromJson(list[0]);
patientShareObj.isCash = response["IsCash"];
// patientShareObj.isCash = false;
patientShareObj.isEligible = response["IsEligible"];
patientShareObj.isInsured = response["IsInsured"];
apiResponse = GenericApiModel<PatientAppointmentShareResponseModel>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: patientShareObj,
);
} 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()));
}
throw UnimplementedError();
}
}

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_share_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_repo.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
@ -10,8 +11,10 @@ class MyAppointmentsViewModel extends ChangeNotifier {
ErrorHandlerService errorHandlerService;
bool isMyAppointmentsLoading = false;
bool isAppointmentPatientShareLoading = false;
List<PatientAppointmentHistoryResponseModel> patientAppointmentsHistoryList = [];
PatientAppointmentShareResponseModel? patientAppointmentShareResponseModel;
MyAppointmentsViewModel({required this.myAppointmentsRepo, required this.errorHandlerService});
@ -23,6 +26,7 @@ class MyAppointmentsViewModel extends ChangeNotifier {
initAppointmentsViewModel() {
patientAppointmentsHistoryList.clear();
isMyAppointmentsLoading = true;
isAppointmentPatientShareLoading = true;
notifyListeners();
}
@ -31,6 +35,11 @@ class MyAppointmentsViewModel extends ChangeNotifier {
notifyListeners();
}
setIsPatientAppointmentShareLoading(bool val) {
isAppointmentPatientShareLoading = val;
notifyListeners();
}
setAppointmentReminder(bool value, PatientAppointmentHistoryResponseModel item) {
int index = patientAppointmentsHistoryList.indexOf(item);
if (index != -1) {
@ -58,4 +67,24 @@ class MyAppointmentsViewModel extends ChangeNotifier {
},
);
}
Future<void> getPatientShareAppointment(int projectID, int clinicID, String appointmentNo, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.getPatientShareAppointment(patientId: "3628599", projectID: projectID, clinicID: clinicID, appointmentNo: appointmentNo);
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) {
patientAppointmentShareResponseModel = apiResponse.data!;
isAppointmentPatientShareLoading = false;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
}

@ -1,3 +1,4 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
@ -11,9 +12,12 @@ import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/utils/appointment_type.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/appointment_payment_page.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_doctor_card.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/transitions/fade_page.dart';
import 'package:maps_launcher/maps_launcher.dart';
import 'package:provider/provider.dart';
class AppointmentDetailsPage extends StatefulWidget {
@ -30,7 +34,6 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
@override
Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
myAppointmentsViewModel = Provider.of<MyAppointmentsViewModel>(context);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
@ -60,12 +63,13 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
),
SizedBox(height: 16.h),
if (!AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel))
Column(
children: [
Container(
height: 200.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: true,
hasShadow: false,
),
child: Padding(
padding: EdgeInsets.all(16.h),
@ -82,10 +86,82 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
? "Not Confirmed".needTranslation.toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500)
: "Confirmed".needTranslation.toText12(color: AppColors.successColor, fontWeight: FontWeight.w500)),
SizedBox(height: 16.h),
Stack(
children: [
ClipRRect(
clipBehavior: Clip.hardEdge,
borderRadius: BorderRadius.circular(24),
child: Image.network(
"https://maps.googleapis.com/maps/api/staticmap?center=${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&zoom=14&size=350x165&maptype=roadmap&markers=color:red%7C${widget.patientAppointmentHistoryResponseModel.latitude},${widget.patientAppointmentHistoryResponseModel.longitude}&key=AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng",
fit: BoxFit.contain,
),
),
Positioned(
bottom: 0,
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.785,
child: CustomButton(
text: "Get Directions".needTranslation,
onPressed: () {
MapsLauncher.launchCoordinates(double.parse(widget.patientAppointmentHistoryResponseModel.latitude!),
double.parse(widget.patientAppointmentHistoryResponseModel.longitude!), widget.patientAppointmentHistoryResponseModel.projectName);
},
backgroundColor: AppColors.textColor.withOpacity(0.8),
borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
textColor: AppColors.whiteColor,
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12.h,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
icon: AppAssets.directions_icon,
iconColor: AppColors.whiteColor,
iconSize: 13.h,
).paddingAll(12.h),
),
),
],
),
],
),
),
),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.prescription_reminder_icon, width: 35.h, height: 35.h),
SizedBox(width: 8.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.setReminder.tr(context: context).toText13(isBold: true),
"Notify me before the appointment".needTranslation.toText11(color: AppColors.textColorLight, weight: FontWeight.w500),
],
),
const Spacer(),
Switch(
activeColor: AppColors.successColor,
activeTrackColor: AppColors.successColor.withValues(alpha: .15),
value: widget.patientAppointmentHistoryResponseModel.hasReminder!,
onChanged: (newValue) {
setState(() {
myAppointmentsViewModel.setAppointmentReminder(newValue, widget.patientAppointmentHistoryResponseModel);
});
},
),
],
).paddingSymmetrical(16.h, 16.h),
),
SizedBox(height: 16.h),
],
),
],
).paddingSymmetrical(24.h, 24.h),
),
@ -112,11 +188,43 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
isSaudiCurrency: true),
],
),
SizedBox(height: 4.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
LocaleKeys.upcomingPaymentNow.tr(context: context).toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
"VAT 15%(${widget.patientAppointmentHistoryResponseModel.patientTaxAmount})".needTranslation.toText14(isBold: true, color: AppColors.greyTextColor),
],
).paddingSymmetrical(24.h, 24.h),
),
SizedBox(height: 18.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: 150.h,
child: Utils.getPaymentMethods(),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Utils.getPaymentAmountWithSymbol(widget.patientAppointmentHistoryResponseModel.patientShareWithTax!.toString().toText24(isBold: true), AppColors.blackColor, 17,
isSaudiCurrency: true),
],
),
],
)
],
).paddingOnly(left: 16.h, top: 24.h, right: 16.h, bottom: 0.h),
CustomButton(
text: AppointmentType.getNextActionText(widget.patientAppointmentHistoryResponseModel.nextAction),
onPressed: () {},
onPressed: () {
myAppointmentsViewModel.setIsPatientAppointmentShareLoading(true);
Navigator.of(context).push(
FadePage(
page: AppointmentPaymentPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
),
);
},
backgroundColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction),
borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
textColor: AppColors.whiteColor,
@ -128,7 +236,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
icon: AppointmentType.getNextActionIcon(widget.patientAppointmentHistoryResponseModel.nextAction),
iconColor: AppColors.whiteColor,
iconSize: 18.h,
).paddingSymmetrical(24.h, 24.h),
).paddingSymmetrical(16.h, 24.h),
],
),
),

@ -0,0 +1,248 @@
import 'dart:async';
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/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/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.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/shimmer/movies_shimmer_widget.dart';
import 'package:provider/provider.dart';
import 'package:smooth_corner/smooth_corner.dart';
class AppointmentPaymentPage extends StatefulWidget {
AppointmentPaymentPage({super.key, required this.patientAppointmentHistoryResponseModel});
PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
@override
State<AppointmentPaymentPage> createState() => _AppointmentPaymentPageState();
}
class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
late MyAppointmentsViewModel myAppointmentsViewModel;
@override
void initState() {
scheduleMicrotask(() {
myAppointmentsViewModel.getPatientShareAppointment(
widget.patientAppointmentHistoryResponseModel.projectID,
widget.patientAppointmentHistoryResponseModel.clinicID,
widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
);
});
super.initState();
}
@override
Widget build(BuildContext context) {
myAppointmentsViewModel = Provider.of<MyAppointmentsViewModel>(context);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
appBar: AppBar(
title: "Appointment Payment".needTranslation.toText18(),
backgroundColor: AppColors.bgScaffoldColor,
),
body: Consumer<MyAppointmentsViewModel>(builder: (context, myAppointmentsVM, child) {
return myAppointmentsVM.isAppointmentPatientShareLoading
? const MoviesShimmerWidget().paddingAll(24.h)
: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Appointment Payment".needTranslation.toText24(isBold: true).paddingSymmetrical(24.h, 0.h),
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),
SizedBox(height: 16.h),
"Mada".needTranslation.toText16(isBold: true),
],
),
SizedBox(width: 8.h),
const Spacer(),
Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 18.h,
height: 13.h,
fit: BoxFit.contain,
),
],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h),
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: 50.h, height: 50.h),
SizedBox(width: 8.h),
Image.asset(AppAssets.Mastercard, width: 40.h, height: 40.h),
],
),
SizedBox(height: 16.h),
"Visa or Mastercard".needTranslation.toText16(isBold: true),
],
),
SizedBox(width: 8.h),
const Spacer(),
Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 18.h,
height: 13.h,
fit: BoxFit.contain,
),
],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.asset(AppAssets.tamara_en, width: 72.h, height: 25.h),
SizedBox(height: 16.h),
"Tamara".needTranslation.toText16(isBold: true),
],
),
SizedBox(width: 8.h),
const Spacer(),
Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 18.h,
height: 13.h,
fit: BoxFit.contain,
),
],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h),
],
),
),
),
Container(
// height: 200.h,
// width: double.infinity,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.h,
hasShadow: false,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(myAppointmentsVM.patientAppointmentShareResponseModel!.isCash ?? true)
? Container(
height: 50.h,
decoration: ShapeDecoration(
color: AppColors.secondaryLightRedBorderColor,
shape: SmoothRectangleBorder(
borderRadius: BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24)),
smoothness: 1,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Insurance expired or inactive".needTranslation.toText14(color: AppColors.primaryRedColor, weight: FontWeight.w500).paddingSymmetrical(24.h, 0.h),
CustomButton(
text: LocaleKeys.updateInsurance.tr(context: context),
onPressed: () {},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.secondaryLightRedBorderColor,
textColor: AppColors.whiteColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
height: 30.h,
).paddingSymmetrical(24.h, 0.h),
],
),
)
: const SizedBox(),
SizedBox(height: 24.h),
"Total amount to pay".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 17.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Total amount to pay".needTranslation.toText14(isBold: true),
Utils.getPaymentAmountWithSymbol(myAppointmentsVM.patientAppointmentShareResponseModel!.patientShare!.toString().toText16(isBold: true), AppColors.blackColor, 13,
isSaudiCurrency: true),
],
).paddingSymmetrical(24.h, 0.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"VAT 15%".needTranslation.toText14(isBold: true, color: AppColors.greyTextColor),
Utils.getPaymentAmountWithSymbol(
myAppointmentsVM.patientAppointmentShareResponseModel!.patientTaxAmount!.toString().toText14(isBold: true, color: AppColors.greyTextColor), AppColors.greyTextColor, 13,
isSaudiCurrency: true),
],
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 17.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"".needTranslation.toText14(isBold: true),
Utils.getPaymentAmountWithSymbol(myAppointmentsVM.patientAppointmentShareResponseModel!.patientShareWithTax!.toString().toText24(isBold: true), AppColors.blackColor, 17,
isSaudiCurrency: true),
],
).paddingSymmetrical(24.h, 0.h),
Utils.buildSvgWithAssets(
icon: AppAssets.apple_pay_button,
width: 200.h,
height: 80.h,
fit: BoxFit.contain,
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 12.h),
],
),
),
],
);
}),
);
}
}

@ -70,6 +70,7 @@ dependencies:
web: any
flutter_staggered_animations: ^1.1.1
smooth_corner: ^1.1.1
maps_launcher: ^3.0.0+1
dev_dependencies:
flutter_test:

Loading…
Cancel
Save