Merge branch 'master' into faiz_dev
# Conflicts: # lib/core/api/api_client.dart # lib/core/dependencies.dart # lib/main.dart # lib/presentation/appointments/appointment_payment_page.dartpull/94/head
commit
617b68021a
@ -0,0 +1,95 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
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/common_models/generic_api_model.dart';
|
||||
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
|
||||
import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_hmg_locations.dart';
|
||||
import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_patient_ic_projects.dart';
|
||||
import 'package:hmg_patient_app_new/services/logger_service.dart';
|
||||
|
||||
abstract class ContactUsRepo {
|
||||
Future<Either<Failure, GenericApiModel<List<GetHMGLocationsModel>>>> getHMGLocations();
|
||||
|
||||
Future<Either<Failure, GenericApiModel<List<GetPatientICProjectsModel>>>> getLiveChatProjectsList();
|
||||
}
|
||||
|
||||
class ContactUsRepoImp implements ContactUsRepo {
|
||||
final ApiClient apiClient;
|
||||
final LoggerService loggerService;
|
||||
|
||||
ContactUsRepoImp({required this.apiClient, required this.loggerService});
|
||||
|
||||
@override
|
||||
Future<Either<Failure, GenericApiModel<List<GetHMGLocationsModel>>>> getHMGLocations() async {
|
||||
Map<String, dynamic> mapDevice = {};
|
||||
|
||||
try {
|
||||
GenericApiModel<List<GetHMGLocationsModel>>? apiResponse;
|
||||
Failure? failure;
|
||||
await apiClient.post(
|
||||
GET_FINDUS_REQUEST,
|
||||
body: mapDevice,
|
||||
onFailure: (error, statusCode, {messageStatus, failureType}) {
|
||||
failure = failureType;
|
||||
},
|
||||
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
|
||||
try {
|
||||
final list = response['ListHMGLocation'];
|
||||
final hmgLocations = list.map((item) => GetHMGLocationsModel.fromJson(item as Map<String, dynamic>)).toList().cast<GetHMGLocationsModel>();
|
||||
|
||||
apiResponse = GenericApiModel<List<GetHMGLocationsModel>>(
|
||||
messageStatus: messageStatus,
|
||||
statusCode: statusCode,
|
||||
errorMessage: null,
|
||||
data: hmgLocations,
|
||||
);
|
||||
} 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<List<GetPatientICProjectsModel>>>> getLiveChatProjectsList() async {
|
||||
Map<String, dynamic> mapDevice = {};
|
||||
|
||||
try {
|
||||
GenericApiModel<List<GetPatientICProjectsModel>>? apiResponse;
|
||||
Failure? failure;
|
||||
await apiClient.post(
|
||||
GET_LIVECHAT_REQUEST,
|
||||
body: mapDevice,
|
||||
onFailure: (error, statusCode, {messageStatus, failureType}) {
|
||||
failure = failureType;
|
||||
},
|
||||
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
|
||||
try {
|
||||
final list = response['List_PatientICProjects'];
|
||||
final hmgLocations = list.map((item) => GetPatientICProjectsModel.fromJson(item as Map<String, dynamic>)).toList().cast<GetPatientICProjectsModel>();
|
||||
|
||||
apiResponse = GenericApiModel<List<GetPatientICProjectsModel>>(
|
||||
messageStatus: messageStatus,
|
||||
statusCode: statusCode,
|
||||
errorMessage: null,
|
||||
data: hmgLocations,
|
||||
);
|
||||
} 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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_state.dart';
|
||||
import 'package:hmg_patient_app_new/features/contact_us/contact_us_repo.dart';
|
||||
import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_hmg_locations.dart';
|
||||
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
|
||||
|
||||
class ContactUsViewModel extends ChangeNotifier {
|
||||
ContactUsRepo contactUsRepo;
|
||||
ErrorHandlerService errorHandlerService;
|
||||
AppState appState;
|
||||
|
||||
bool isHMGLocationsListLoading = false;
|
||||
bool isHMGHospitalsListSelected = true;
|
||||
|
||||
List<GetHMGLocationsModel> hmgHospitalsLocationsList = [];
|
||||
List<GetHMGLocationsModel> hmgPharmacyLocationsList = [];
|
||||
|
||||
ContactUsViewModel({required this.contactUsRepo, required this.errorHandlerService, required this.appState});
|
||||
|
||||
initContactUsViewModel() {
|
||||
isHMGLocationsListLoading = true;
|
||||
isHMGHospitalsListSelected = true;
|
||||
hmgHospitalsLocationsList.clear();
|
||||
hmgPharmacyLocationsList.clear();
|
||||
getHMGLocations();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
setHMGHospitalsListSelected(bool isSelected) {
|
||||
isHMGHospitalsListSelected = isSelected;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> getHMGLocations({Function(dynamic)? onSuccess, Function(String)? onError}) async {
|
||||
isHMGLocationsListLoading = true;
|
||||
hmgHospitalsLocationsList.clear();
|
||||
hmgPharmacyLocationsList.clear();
|
||||
notifyListeners();
|
||||
|
||||
final result = await contactUsRepo.getHMGLocations();
|
||||
|
||||
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) {
|
||||
// hmgLocationsList = apiResponse.data!;
|
||||
for (var location in apiResponse.data!) {
|
||||
if (location.locationType == 1) {
|
||||
hmgHospitalsLocationsList.add(location);
|
||||
} else if (location.locationType == 2) {
|
||||
hmgPharmacyLocationsList.add(location);
|
||||
}
|
||||
}
|
||||
isHMGLocationsListLoading = false;
|
||||
notifyListeners();
|
||||
if (onSuccess != null) {
|
||||
onSuccess(apiResponse);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
class GetHMGLocationsModel {
|
||||
dynamic cityID;
|
||||
String? cityName;
|
||||
dynamic cityNameN;
|
||||
dynamic distanceInKilometers;
|
||||
bool? isActive;
|
||||
String? latitude;
|
||||
int? locationID;
|
||||
String? locationName;
|
||||
dynamic locationNameN;
|
||||
dynamic locationType;
|
||||
String? longitude;
|
||||
int? pharmacyLocationID;
|
||||
String? phoneNumber;
|
||||
int? projectID;
|
||||
String? projectImageURL;
|
||||
int? setupID;
|
||||
dynamic sortOrder;
|
||||
|
||||
GetHMGLocationsModel(
|
||||
{this.cityID,
|
||||
this.cityName,
|
||||
this.cityNameN,
|
||||
this.distanceInKilometers,
|
||||
this.isActive,
|
||||
this.latitude,
|
||||
this.locationID,
|
||||
this.locationName,
|
||||
this.locationNameN,
|
||||
this.locationType,
|
||||
this.longitude,
|
||||
this.pharmacyLocationID,
|
||||
this.phoneNumber,
|
||||
this.projectID,
|
||||
this.projectImageURL,
|
||||
this.setupID,
|
||||
this.sortOrder});
|
||||
|
||||
GetHMGLocationsModel.fromJson(Map<String, dynamic> json) {
|
||||
cityID = json['CityID'];
|
||||
cityName = json['CityName'];
|
||||
cityNameN = json['CityNameN'];
|
||||
distanceInKilometers = json['DistanceInKilometers'];
|
||||
isActive = json['IsActive'];
|
||||
latitude = json['Latitude'];
|
||||
locationID = json['LocationID'];
|
||||
locationName = json['LocationName'];
|
||||
locationNameN = json['LocationNameN'];
|
||||
locationType = json['LocationType'];
|
||||
longitude = json['Longitude'];
|
||||
pharmacyLocationID = json['PharmacyLocationID'];
|
||||
phoneNumber = json['PhoneNumber'];
|
||||
projectID = json['ProjectID'];
|
||||
projectImageURL = json['ProjectImageURL'];
|
||||
setupID = json['SetupID'];
|
||||
sortOrder = json['SortOrder'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['CityID'] = this.cityID;
|
||||
data['CityName'] = this.cityName;
|
||||
data['CityNameN'] = this.cityNameN;
|
||||
data['DistanceInKilometers'] = this.distanceInKilometers;
|
||||
data['IsActive'] = this.isActive;
|
||||
data['Latitude'] = this.latitude;
|
||||
data['LocationID'] = this.locationID;
|
||||
data['LocationName'] = this.locationName;
|
||||
data['LocationNameN'] = this.locationNameN;
|
||||
data['LocationType'] = this.locationType;
|
||||
data['Longitude'] = this.longitude;
|
||||
data['PharmacyLocationID'] = this.pharmacyLocationID;
|
||||
data['PhoneNumber'] = this.phoneNumber;
|
||||
data['ProjectID'] = this.projectID;
|
||||
data['ProjectImageURL'] = this.projectImageURL;
|
||||
data['SetupID'] = this.setupID;
|
||||
data['SortOrder'] = this.sortOrder;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
|
||||
|
||||
class GetPatientICProjectsModel {
|
||||
int? id;
|
||||
String? projectName;
|
||||
String? projectNameN;
|
||||
String? value;
|
||||
dynamic languageId;
|
||||
DateTime? createdOn;
|
||||
String? createdBy;
|
||||
dynamic editedOn;
|
||||
dynamic editedBy;
|
||||
bool? isActive;
|
||||
dynamic distanceInKilometers;
|
||||
|
||||
GetPatientICProjectsModel(
|
||||
{this.id, this.projectName, this.projectNameN, this.value, this.languageId, this.createdOn, this.createdBy, this.editedOn, this.editedBy, this.distanceInKilometers, this.isActive});
|
||||
|
||||
GetPatientICProjectsModel.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
projectName = json['ProjectName'];
|
||||
projectNameN = json['ProjectNameN'];
|
||||
value = json['Value'];
|
||||
languageId = json['LanguageId'];
|
||||
createdOn = DateUtil.convertStringToDate(json['CreatedOn']);
|
||||
createdBy = json['CreatedBy'];
|
||||
editedOn = json['EditedOn'];
|
||||
editedBy = json['EditedBy'];
|
||||
isActive = json['IsActive'];
|
||||
distanceInKilometers = json['DistanceInKilometers'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['id'] = this.id;
|
||||
data['ProjectName'] = this.projectName;
|
||||
data['ProjectNameN'] = this.projectNameN;
|
||||
data['Value'] = this.value;
|
||||
data['LanguageId'] = this.languageId;
|
||||
data['CreatedOn'] = this.createdOn;
|
||||
data['CreatedBy'] = this.createdBy;
|
||||
data['EditedOn'] = this.editedOn;
|
||||
data['EditedBy'] = this.editedBy;
|
||||
data['IsActive'] = this.isActive;
|
||||
data['DistanceInKilometers'] = this.distanceInKilometers;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,108 @@
|
||||
class EROnlineCheckInPaymentDetailsResponse {
|
||||
num? cashPrice;
|
||||
num? cashPriceTax;
|
||||
num? cashPriceWithTax;
|
||||
int? companyId;
|
||||
String? companyName;
|
||||
num? companyShareWithTax;
|
||||
dynamic errCode;
|
||||
int? groupID;
|
||||
String? insurancePolicyNo;
|
||||
String? message;
|
||||
String? patientCardID;
|
||||
num? patientShare;
|
||||
num? patientShareWithTax;
|
||||
num? patientTaxAmount;
|
||||
int? policyId;
|
||||
String? policyName;
|
||||
String? procedureId;
|
||||
String? procedureName;
|
||||
dynamic setupID;
|
||||
int? statusCode;
|
||||
String? subPolicyNo;
|
||||
bool? isCash;
|
||||
bool? isEligible;
|
||||
bool? isInsured;
|
||||
|
||||
EROnlineCheckInPaymentDetailsResponse(
|
||||
{this.cashPrice,
|
||||
this.cashPriceTax,
|
||||
this.cashPriceWithTax,
|
||||
this.companyId,
|
||||
this.companyName,
|
||||
this.companyShareWithTax,
|
||||
this.errCode,
|
||||
this.groupID,
|
||||
this.insurancePolicyNo,
|
||||
this.message,
|
||||
this.patientCardID,
|
||||
this.patientShare,
|
||||
this.patientShareWithTax,
|
||||
this.patientTaxAmount,
|
||||
this.policyId,
|
||||
this.policyName,
|
||||
this.procedureId,
|
||||
this.procedureName,
|
||||
this.setupID,
|
||||
this.statusCode,
|
||||
this.subPolicyNo,
|
||||
this.isCash,
|
||||
this.isEligible,
|
||||
this.isInsured});
|
||||
|
||||
EROnlineCheckInPaymentDetailsResponse.fromJson(Map<String, dynamic> json) {
|
||||
cashPrice = json['CashPrice'];
|
||||
cashPriceTax = json['CashPriceTax'];
|
||||
cashPriceWithTax = json['CashPriceWithTax'];
|
||||
companyId = json['CompanyId'];
|
||||
companyName = json['CompanyName'];
|
||||
companyShareWithTax = json['CompanyShareWithTax'];
|
||||
errCode = json['ErrCode'];
|
||||
groupID = json['GroupID'];
|
||||
insurancePolicyNo = json['InsurancePolicyNo'];
|
||||
message = json['Message'];
|
||||
patientCardID = json['PatientCardID'];
|
||||
patientShare = json['PatientShare'];
|
||||
patientShareWithTax = json['PatientShareWithTax'];
|
||||
patientTaxAmount = json['PatientTaxAmount'];
|
||||
policyId = json['PolicyId'];
|
||||
policyName = json['PolicyName'];
|
||||
procedureId = json['ProcedureId'];
|
||||
procedureName = json['ProcedureName'];
|
||||
setupID = json['SetupID'];
|
||||
statusCode = json['StatusCode'];
|
||||
subPolicyNo = json['SubPolicyNo'];
|
||||
isCash = json['IsCash'];
|
||||
isEligible = json['IsEligible'];
|
||||
isInsured = json['IsInsured'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['CashPrice'] = this.cashPrice;
|
||||
data['CashPriceTax'] = this.cashPriceTax;
|
||||
data['CashPriceWithTax'] = this.cashPriceWithTax;
|
||||
data['CompanyId'] = this.companyId;
|
||||
data['CompanyName'] = this.companyName;
|
||||
data['CompanyShareWithTax'] = this.companyShareWithTax;
|
||||
data['ErrCode'] = this.errCode;
|
||||
data['GroupID'] = this.groupID;
|
||||
data['InsurancePolicyNo'] = this.insurancePolicyNo;
|
||||
data['Message'] = this.message;
|
||||
data['PatientCardID'] = this.patientCardID;
|
||||
data['PatientShare'] = this.patientShare;
|
||||
data['PatientShareWithTax'] = this.patientShareWithTax;
|
||||
data['PatientTaxAmount'] = this.patientTaxAmount;
|
||||
data['PolicyId'] = this.policyId;
|
||||
data['PolicyName'] = this.policyName;
|
||||
data['ProcedureId'] = this.procedureId;
|
||||
data['ProcedureName'] = this.procedureName;
|
||||
data['SetupID'] = this.setupID;
|
||||
data['StatusCode'] = this.statusCode;
|
||||
data['SubPolicyNo'] = this.subPolicyNo;
|
||||
data['IsCash'] = this.isCash;
|
||||
data['IsEligible'] = this.isEligible;
|
||||
data['IsInsured'] = this.isInsured;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
class AskDocRequestType {
|
||||
String? setupID;
|
||||
int? parameterGroup;
|
||||
int? parameterType;
|
||||
int? parameterCode;
|
||||
String? description;
|
||||
String? descriptionN;
|
||||
String? alias;
|
||||
String? aliasN;
|
||||
String? prefix;
|
||||
String? suffix;
|
||||
String? isColorCodingRequired;
|
||||
String? backColor;
|
||||
String? foreColor;
|
||||
bool? isBuiltIn;
|
||||
bool? isActive;
|
||||
int? createdBy;
|
||||
String? createdOn;
|
||||
String? editedBy;
|
||||
String? editedOn;
|
||||
String? rowVer;
|
||||
|
||||
AskDocRequestType(
|
||||
{this.setupID,
|
||||
this.parameterGroup,
|
||||
this.parameterType,
|
||||
this.parameterCode,
|
||||
this.description,
|
||||
this.descriptionN,
|
||||
this.alias,
|
||||
this.aliasN,
|
||||
this.prefix,
|
||||
this.suffix,
|
||||
this.isColorCodingRequired,
|
||||
this.backColor,
|
||||
this.foreColor,
|
||||
this.isBuiltIn,
|
||||
this.isActive,
|
||||
this.createdBy,
|
||||
this.createdOn,
|
||||
this.editedBy,
|
||||
this.editedOn,
|
||||
this.rowVer});
|
||||
|
||||
AskDocRequestType.fromJson(Map<String, dynamic> json) {
|
||||
setupID = json['SetupID'];
|
||||
parameterGroup = json['ParameterGroup'];
|
||||
parameterType = json['ParameterType'];
|
||||
parameterCode = json['ParameterCode'];
|
||||
description = json['Description'];
|
||||
descriptionN = json['DescriptionN'];
|
||||
alias = json['Alias'];
|
||||
aliasN = json['AliasN'];
|
||||
prefix = json['Prefix'];
|
||||
suffix = json['Suffix'];
|
||||
isColorCodingRequired = json['IsColorCodingRequired'];
|
||||
backColor = json['BackColor'];
|
||||
foreColor = json['ForeColor'];
|
||||
isBuiltIn = json['IsBuiltIn'];
|
||||
isActive = json['IsActive'];
|
||||
createdBy = json['CreatedBy'];
|
||||
createdOn = json['CreatedOn'];
|
||||
editedBy = json['EditedBy'];
|
||||
editedOn = json['EditedOn'];
|
||||
rowVer = json['RowVer'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['SetupID'] = this.setupID;
|
||||
data['ParameterGroup'] = this.parameterGroup;
|
||||
data['ParameterType'] = this.parameterType;
|
||||
data['ParameterCode'] = this.parameterCode;
|
||||
data['Description'] = this.description;
|
||||
data['DescriptionN'] = this.descriptionN;
|
||||
data['Alias'] = this.alias;
|
||||
data['AliasN'] = this.aliasN;
|
||||
data['Prefix'] = this.prefix;
|
||||
data['Suffix'] = this.suffix;
|
||||
data['IsColorCodingRequired'] = this.isColorCodingRequired;
|
||||
data['BackColor'] = this.backColor;
|
||||
data['ForeColor'] = this.foreColor;
|
||||
data['IsBuiltIn'] = this.isBuiltIn;
|
||||
data['IsActive'] = this.isActive;
|
||||
data['CreatedBy'] = this.createdBy;
|
||||
data['CreatedOn'] = this.createdOn;
|
||||
data['EditedBy'] = this.editedBy;
|
||||
data['EditedOn'] = this.editedOn;
|
||||
data['RowVer'] = this.rowVer;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,138 @@
|
||||
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/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/ask_doctor_request_type_response_model.dart';
|
||||
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
|
||||
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/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/common_bottom_sheet.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
|
||||
|
||||
class AskDoctorRequestTypeSelect extends StatelessWidget {
|
||||
AskDoctorRequestTypeSelect({super.key, required this.askDoctorRequestTypeList, required this.myAppointmentsViewModel, required this.patientAppointmentHistoryResponseModel});
|
||||
|
||||
final MyAppointmentsViewModel myAppointmentsViewModel;
|
||||
final PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
|
||||
List<AskDocRequestType> askDoctorRequestTypeList = [];
|
||||
int selectedParameterCodeValue = 2;
|
||||
int selectedParameterCode = 0;
|
||||
|
||||
final ValueNotifier<int> requestTypeSelectNotifier = ValueNotifier<int>(0);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24),
|
||||
child: ListView.builder(
|
||||
itemCount: askDoctorRequestTypeList.length,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
padding: EdgeInsets.only(top: 8, bottom: 8),
|
||||
shrinkWrap: true,
|
||||
itemBuilder: (context, index) {
|
||||
return ValueListenableBuilder<int>(
|
||||
valueListenable: requestTypeSelectNotifier,
|
||||
builder: (context, duration, child) {
|
||||
return Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
listTileTheme: ListTileThemeData(horizontalTitleGap: 4),
|
||||
),
|
||||
child: RadioListTile<int>(
|
||||
title: (askDoctorRequestTypeList[index].description ?? '').toText14(weight: FontWeight.w500),
|
||||
value: index,
|
||||
fillColor: WidgetStateProperty.resolveWith((states) {
|
||||
if (states.contains(WidgetState.selected)) {
|
||||
return AppColors.primaryRedColor;
|
||||
}
|
||||
return Color(0xffEEEEEE);
|
||||
}),
|
||||
contentPadding: EdgeInsets.only(left: 12.h, right: 12.h),
|
||||
groupValue: selectedParameterCode,
|
||||
onChanged: (int? newValue) {
|
||||
selectedParameterCode = newValue!;
|
||||
selectedParameterCodeValue = askDoctorRequestTypeList[index].parameterCode!;
|
||||
requestTypeSelectNotifier.value = selectedParameterCode;
|
||||
debugPrint(selectedParameterCodeValue.toString());
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: CustomButton(
|
||||
text: LocaleKeys.cancel.tr(),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
backgroundColor: AppColors.primaryRedColor,
|
||||
borderColor: AppColors.primaryRedColor,
|
||||
textColor: AppColors.whiteColor,
|
||||
icon: AppAssets.cancel,
|
||||
iconColor: AppColors.whiteColor,
|
||||
borderRadius: 12.r,
|
||||
iconSize: 14.h,
|
||||
fontSize: 14.f,
|
||||
height: 40.h,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8.h),
|
||||
Expanded(
|
||||
child: CustomButton(
|
||||
text: LocaleKeys.confirm.tr(),
|
||||
onPressed: () async {
|
||||
Navigator.pop(context);
|
||||
LoaderBottomSheet.showLoader(loadingText: "Sending Request...");
|
||||
await myAppointmentsViewModel.sendAskDocCallRequest(
|
||||
patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
|
||||
requestType: selectedParameterCodeValue.toString(),
|
||||
remarks: "",
|
||||
userMobileNumber: myAppointmentsViewModel.appState.getAuthenticatedUser()!.mobileNumber!,
|
||||
onSuccess: (val) {
|
||||
LoaderBottomSheet.hideLoader();
|
||||
showCommonBottomSheetWithoutHeight(
|
||||
context,
|
||||
child: Utils.getSuccessWidget(loadingText: "Request has been sent successfully, you will be contacted soon.".needTranslation),
|
||||
callBackFunc: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
title: "",
|
||||
isCloseButtonVisible: true,
|
||||
isDismissible: false,
|
||||
isFullScreen: false,
|
||||
);
|
||||
},
|
||||
onError: (errMessage) {
|
||||
LoaderBottomSheet.hideLoader();
|
||||
});
|
||||
},
|
||||
backgroundColor: AppColors.bgGreenColor,
|
||||
borderColor: AppColors.bgGreenColor,
|
||||
textColor: Colors.white,
|
||||
icon: AppAssets.confirm,
|
||||
iconSize: 14.h,
|
||||
borderRadius: 12.r,
|
||||
fontSize: 14.f,
|
||||
height: 40.h,
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,114 @@
|
||||
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/dependencies.dart';
|
||||
import 'package:hmg_patient_app_new/core/location_util.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/contact_us/contact_us_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/contact_us/find_us_page.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/contact_us/live_chat_page.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ContactUs extends StatelessWidget {
|
||||
ContactUs({super.key});
|
||||
|
||||
late AppState appState;
|
||||
late ContactUsViewModel contactUsViewModel;
|
||||
late LocationUtils locationUtils;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
appState = getIt.get<AppState>();
|
||||
locationUtils = getIt.get<LocationUtils>();
|
||||
locationUtils.isShowConfirmDialog = true;
|
||||
contactUsViewModel = Provider.of<ContactUsViewModel>(context);
|
||||
return Column(
|
||||
children: [
|
||||
checkInOptionCard(
|
||||
AppAssets.checkin_location_icon,
|
||||
LocaleKeys.findUs.tr(),
|
||||
"View your nearest HMG locations".needTranslation,
|
||||
).onPress(() {
|
||||
locationUtils.getCurrentLocation(onSuccess: (value) {
|
||||
contactUsViewModel.initContactUsViewModel();
|
||||
Navigator.pop(context);
|
||||
Navigator.of(context).push(
|
||||
CustomPageRoute(
|
||||
page: FindUsPage(),
|
||||
),
|
||||
);
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 16.h),
|
||||
checkInOptionCard(
|
||||
AppAssets.checkin_location_icon,
|
||||
LocaleKeys.feedback.tr(),
|
||||
"Provide your feedback on our services".needTranslation,
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
checkInOptionCard(
|
||||
AppAssets.checkin_location_icon,
|
||||
LocaleKeys.liveChat.tr(),
|
||||
"Live chat option with HMG".needTranslation,
|
||||
).onPress(() {
|
||||
locationUtils.getCurrentLocation(onSuccess: (value) {
|
||||
Navigator.pop(context);
|
||||
Navigator.of(context).push(
|
||||
CustomPageRoute(
|
||||
page: LiveChatPage(),
|
||||
),
|
||||
);
|
||||
});
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget checkInOptionCard(String icon, String title, String subTitle) {
|
||||
return Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 20.r,
|
||||
hasShadow: false,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Utils.buildSvgWithAssets(icon: icon, width: 40.h, height: 40.h, fit: BoxFit.fill),
|
||||
SizedBox(height: 16.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
title.toText16(isBold: true, color: AppColors.textColor),
|
||||
subTitle.toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
|
||||
],
|
||||
),
|
||||
),
|
||||
Transform.flip(
|
||||
flipX: appState.isArabic(),
|
||||
child: Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.forward_arrow_icon_small,
|
||||
iconColor: AppColors.blackColor,
|
||||
width: 18.h,
|
||||
height: 13.h,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
).paddingAll(16.h),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,165 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_state.dart';
|
||||
import 'package:hmg_patient_app_new/core/dependencies.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/utils.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/features/contact_us/contact_us_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/features/medical_file/models/patient_sickleave_response_model.dart';
|
||||
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/contact_us/widgets/find_us_item_card.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/medical_file/widgets/patient_sick_leave_card.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class FindUsPage extends StatelessWidget {
|
||||
FindUsPage({super.key});
|
||||
|
||||
late AppState appState;
|
||||
late ContactUsViewModel contactUsViewModel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
contactUsViewModel = Provider.of<ContactUsViewModel>(context);
|
||||
appState = getIt.get<AppState>();
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.bgScaffoldColor,
|
||||
body: CollapsingListView(
|
||||
title: LocaleKeys.location.tr(),
|
||||
child: Consumer<ContactUsViewModel>(builder: (context, contactUsVM, child) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 16.h),
|
||||
contactUsVM.isHMGLocationsListLoading
|
||||
? SizedBox.shrink()
|
||||
: CustomTabBar(
|
||||
activeTextColor: AppColors.primaryRedColor,
|
||||
activeBackgroundColor: AppColors.primaryRedColor.withValues(alpha: .1),
|
||||
tabs: [
|
||||
CustomTabBarModel(null, LocaleKeys.hmgHospitals.tr()),
|
||||
CustomTabBarModel(null, LocaleKeys.pharmaciesList.tr()),
|
||||
],
|
||||
onTabChange: (index) {
|
||||
contactUsVM.setHMGHospitalsListSelected(index == 0);
|
||||
},
|
||||
).paddingSymmetrical(24.h, 0.h),
|
||||
ListView.separated(
|
||||
padding: EdgeInsets.only(top: 16.h),
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
itemCount: contactUsVM.isHMGLocationsListLoading
|
||||
? 5
|
||||
: contactUsVM.isHMGHospitalsListSelected
|
||||
? contactUsVM.hmgHospitalsLocationsList.length
|
||||
: contactUsVM.hmgPharmacyLocationsList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return contactUsVM.isHMGLocationsListLoading
|
||||
? Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
|
||||
child: Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 20.h,
|
||||
hasShadow: true,
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(14.h),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Image.network(
|
||||
"https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
|
||||
width: 63.h,
|
||||
height: 63.h,
|
||||
fit: BoxFit.cover,
|
||||
).circle(100).toShimmer2(isShow: true),
|
||||
SizedBox(width: 16.h),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
"Dr John Smith".toText16(isBold: true).toShimmer2(isShow: true),
|
||||
SizedBox(height: 8.h),
|
||||
Wrap(
|
||||
direction: Axis.horizontal,
|
||||
spacing: 3.h,
|
||||
runSpacing: 4.h,
|
||||
children: [
|
||||
AppCustomChipWidget(labelText: "").toShimmer2(isShow: true, width: 16.h),
|
||||
AppCustomChipWidget(labelText: "").toShimmer2(isShow: true, width: 16.h),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
).paddingSymmetrical(24.h, 0.h)
|
||||
: contactUsVM.isHMGHospitalsListSelected
|
||||
// ? contactUsVM.hmgHospitalsLocationsList.isNotEmpty
|
||||
? AnimationConfiguration.staggeredList(
|
||||
position: index,
|
||||
duration: const Duration(milliseconds: 500),
|
||||
child: SlideAnimation(
|
||||
verticalOffset: 100.0,
|
||||
child: FadeInAnimation(
|
||||
child: AnimatedContainer(
|
||||
duration: Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOut,
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
|
||||
child: FindUsItemCard(
|
||||
getHMGLocationsModel: contactUsVM.hmgHospitalsLocationsList[index],
|
||||
),
|
||||
).paddingSymmetrical(24.h, 0.h),
|
||||
),
|
||||
),
|
||||
)
|
||||
: AnimationConfiguration.staggeredList(
|
||||
position: index,
|
||||
duration: const Duration(milliseconds: 500),
|
||||
child: SlideAnimation(
|
||||
verticalOffset: 100.0,
|
||||
child: FadeInAnimation(
|
||||
child: AnimatedContainer(
|
||||
duration: Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOut,
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
|
||||
child: FindUsItemCard(
|
||||
getHMGLocationsModel: contactUsVM.hmgPharmacyLocationsList[index],
|
||||
),
|
||||
).paddingSymmetrical(24.h, 0.h),
|
||||
),
|
||||
),
|
||||
);
|
||||
// : Utils.getNoDataWidget(
|
||||
// context,
|
||||
// noDataText: "No any locations yet.".needTranslation,
|
||||
// );
|
||||
},
|
||||
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
|
||||
),
|
||||
SizedBox(height: 24.h),
|
||||
// FindUsItemCard(),
|
||||
// FindUsItemCard(),
|
||||
// FindUsItemCard(),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.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/appbar/collapsing_list_view.dart';
|
||||
|
||||
class LiveChatPage extends StatelessWidget {
|
||||
const LiveChatPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.bgScaffoldColor,
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: CollapsingListView(
|
||||
title: LocaleKeys.liveChat.tr(),
|
||||
child: SingleChildScrollView(),
|
||||
),
|
||||
),
|
||||
Container()
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,106 @@
|
||||
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/dependencies.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/utils.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_hmg_locations.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/chip/app_custom_chip_widget.dart';
|
||||
import 'package:maps_launcher/maps_launcher.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class FindUsItemCard extends StatelessWidget {
|
||||
FindUsItemCard({super.key, required this.getHMGLocationsModel});
|
||||
|
||||
late AppState appState;
|
||||
GetHMGLocationsModel getHMGLocationsModel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
appState = getIt.get<AppState>();
|
||||
return DecoratedBox(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 20.r,
|
||||
hasShadow: false,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 8.h,
|
||||
children: [hospitalName, distanceInfo],
|
||||
),
|
||||
),
|
||||
],
|
||||
).paddingSymmetrical(16.h, 16.h),
|
||||
);
|
||||
}
|
||||
|
||||
Widget get hospitalName => Row(
|
||||
children: [
|
||||
Image.network(
|
||||
getHMGLocationsModel.projectImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png",
|
||||
width: 40.h,
|
||||
height: 40.h,
|
||||
fit: BoxFit.cover,
|
||||
).circle(100).toShimmer2(isShow: false).paddingOnly(right: 10),
|
||||
Expanded(
|
||||
child: Text(
|
||||
getHMGLocationsModel.locationName!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16,
|
||||
color: AppColors.blackColor,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
Widget get distanceInfo => Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
AppCustomChipWidget(
|
||||
labelText: "${getHMGLocationsModel.distanceInKilometers ?? ""} km".needTranslation,
|
||||
icon: AppAssets.location_red,
|
||||
iconColor: AppColors.primaryRedColor,
|
||||
backgroundColor: AppColors.secondaryLightRedColor,
|
||||
textColor: AppColors.errorColor,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
AppCustomChipWidget(
|
||||
labelText: "Get Directions".needTranslation,
|
||||
icon: AppAssets.directions_icon,
|
||||
iconColor: AppColors.whiteColor,
|
||||
backgroundColor: AppColors.textColor.withValues(alpha: 0.8),
|
||||
textColor: AppColors.whiteColor,
|
||||
onChipTap: () {
|
||||
MapsLauncher.launchCoordinates(double.parse(getHMGLocationsModel.latitude ?? "0.0"), double.parse(getHMGLocationsModel.longitude ?? "0.0"), getHMGLocationsModel.locationName!);
|
||||
},
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
AppCustomChipWidget(
|
||||
labelText: LocaleKeys.callNow.tr(),
|
||||
icon: AppAssets.call_fill,
|
||||
iconColor: AppColors.whiteColor,
|
||||
backgroundColor: AppColors.primaryRedColor.withValues(alpha: 1.0),
|
||||
textColor: AppColors.whiteColor,
|
||||
onChipTap: () {
|
||||
launchUrl(Uri.parse("tel://" + "${getHMGLocationsModel.phoneNumber}"));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,180 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_nfc_kit/flutter_nfc_kit.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/emergency_services/emergency_services_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/emergency_services/er_online_checkin/er_online_checkin_select_checkin_bottom_sheet.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/nfc/nfc_reader_sheet.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../call_ambulance/widgets/HospitalBottomSheetBody.dart';
|
||||
|
||||
class ErOnlineCheckinHome extends StatelessWidget {
|
||||
ErOnlineCheckinHome({super.key});
|
||||
|
||||
late EmergencyServicesViewModel emergencyServicesViewModel;
|
||||
bool _supportsNFC = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
emergencyServicesViewModel = Provider.of<EmergencyServicesViewModel>(context, listen: false);
|
||||
FlutterNfcKit.nfcAvailability.then((value) {
|
||||
_supportsNFC = (value == NFCAvailability.available);
|
||||
});
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.bgScaffoldColor,
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: CollapsingListView(
|
||||
title: "Emergency Check-In".needTranslation,
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(24.h),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Utils.buildSvgWithAssets(icon: AppAssets.immediate_service_icon, width: 58.h, height: 58.h),
|
||||
SizedBox(width: 18.h),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
"Online Check-In".needTranslation.toText18(color: AppColors.textColor, isBold: true),
|
||||
"This service lets patients to register their ER appointment prior to arrival.".needTranslation.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
CustomButton(
|
||||
text: emergencyServicesViewModel.patientHasAdvanceERBalance ? LocaleKeys.checkinOption.tr() : LocaleKeys.bookAppo.tr(),
|
||||
onPressed: () async {
|
||||
if (emergencyServicesViewModel.patientHasAdvanceERBalance) {
|
||||
Future.delayed(const Duration(milliseconds: 500), () {
|
||||
showNfcReader(context, onNcfScan: (String nfcId) {
|
||||
Future.delayed(const Duration(milliseconds: 100), () async {
|
||||
print(nfcId);
|
||||
LoaderBottomSheet.showLoader(loadingText: "Processing check-in...".needTranslation);
|
||||
await emergencyServicesViewModel.getProjectIDFromNFC(
|
||||
nfcCode: nfcId,
|
||||
onSuccess: (value) async {
|
||||
await emergencyServicesViewModel.autoGenerateInvoiceERClinic(
|
||||
projectID: value,
|
||||
onSuccess: (value) {
|
||||
LoaderBottomSheet.hideLoader();
|
||||
showCommonBottomSheetWithoutHeight(context,
|
||||
title: LocaleKeys.onlineCheckIn.tr(),
|
||||
child: Utils.getSuccessWidget(loadingText: "Your ER Online Check-In has been successfully done. Please proceed to the waiting area.".needTranslation),
|
||||
callBackFunc: () {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
CustomPageRoute(
|
||||
page: LandingNavigation(),
|
||||
),
|
||||
(r) => false);
|
||||
}, isFullScreen: false);
|
||||
},
|
||||
onError: (errMessage) {
|
||||
LoaderBottomSheet.hideLoader();
|
||||
showCommonBottomSheetWithoutHeight(
|
||||
context,
|
||||
child: Utils.getErrorWidget(loadingText: "Unexpected error occurred during check-in. Please contact support.".needTranslation),
|
||||
callBackFunc: () {},
|
||||
isFullScreen: false,
|
||||
isCloseButtonVisible: true,
|
||||
);
|
||||
});
|
||||
},
|
||||
onError: (err) {});
|
||||
});
|
||||
}, onCancel: () {});
|
||||
});
|
||||
// showCommonBottomSheetWithoutHeight(context,
|
||||
// title: LocaleKeys.onlineCheckIn.tr(),
|
||||
// child: ErOnlineCheckinSelectCheckinBottomSheet(
|
||||
// projectID: 15,
|
||||
// ),
|
||||
// callBackFunc: () {},
|
||||
// isFullScreen: false);
|
||||
} else {
|
||||
LoaderBottomSheet.showLoader(loadingText: "Fetching hospitals list...".needTranslation);
|
||||
await context.read<EmergencyServicesViewModel>().getProjects();
|
||||
LoaderBottomSheet.hideLoader();
|
||||
//Project Selection Dropdown
|
||||
showHospitalBottomSheet(context);
|
||||
}
|
||||
},
|
||||
backgroundColor: emergencyServicesViewModel.patientHasAdvanceERBalance ? AppColors.alertColor : AppColors.primaryRedColor,
|
||||
borderColor: emergencyServicesViewModel.patientHasAdvanceERBalance ? AppColors.alertColor : AppColors.primaryRedColor,
|
||||
textColor: AppColors.whiteColor,
|
||||
fontSize: 16.f,
|
||||
fontWeight: FontWeight.w500,
|
||||
borderRadius: 10.r,
|
||||
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
|
||||
height: 50.h,
|
||||
icon: emergencyServicesViewModel.patientHasAdvanceERBalance ? AppAssets.appointment_checkin_icon : AppAssets.bookAppoBottom,
|
||||
iconColor: AppColors.whiteColor,
|
||||
iconSize: 18.h,
|
||||
).paddingSymmetrical(24.h, 24.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
showHospitalBottomSheet(BuildContext context) {
|
||||
showCommonBottomSheetWithoutHeight(
|
||||
title: LocaleKeys.selectHospital.tr(),
|
||||
context,
|
||||
child: Consumer<EmergencyServicesViewModel>(
|
||||
builder: (_, vm, __) => HospitalBottomSheetBody(
|
||||
displayList: vm.displayList,
|
||||
onFacilityClicked: (value) {
|
||||
vm.setSelectedFacility(value);
|
||||
vm.getDisplayList();
|
||||
},
|
||||
onHospitalClicked: (hospital) async {
|
||||
Navigator.pop(context);
|
||||
vm.setSelectedHospital(hospital);
|
||||
LoaderBottomSheet.showLoader(loadingText: "Fetching payment information...".needTranslation);
|
||||
await vm.getPatientERPaymentInformation(onSuccess: (response) {
|
||||
LoaderBottomSheet.hideLoader();
|
||||
vm.navigateToEROnlineCheckInPaymentPage();
|
||||
});
|
||||
},
|
||||
onHospitalSearch: (value) {
|
||||
vm.searchHospitals(value ?? "");
|
||||
},
|
||||
selectedFacility: vm.selectedFacility,
|
||||
hmcCount: vm.hmcCount,
|
||||
hmgCount: vm.hmgCount,
|
||||
),
|
||||
),
|
||||
isFullScreen: false,
|
||||
isCloseButtonVisible: true,
|
||||
hasBottomPadding: false,
|
||||
backgroundColor: AppColors.bottomSheetBgColor,
|
||||
callBackFunc: () {},
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,177 @@
|
||||
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/dependencies.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/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/emergency_services/emergency_services_view_model.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/emergency_services/er_online_checkin/er_online_checkin_payment_page.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ErOnlineCheckinPaymentDetailsPage extends StatelessWidget {
|
||||
ErOnlineCheckinPaymentDetailsPage({super.key});
|
||||
|
||||
late AppState appState;
|
||||
late EmergencyServicesViewModel emergencyServicesViewModel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
appState = getIt.get<AppState>();
|
||||
emergencyServicesViewModel = Provider.of<EmergencyServicesViewModel>(context, listen: false);
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.bgScaffoldColor,
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: CollapsingListView(
|
||||
title: "Emergency Check-In".needTranslation,
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(24.h),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 20.h,
|
||||
hasShadow: true,
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(14.h),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
"ER Visit Details".needTranslation.toText18(color: AppColors.textColor, isBold: true),
|
||||
SizedBox(height: 24.h),
|
||||
Row(
|
||||
children: [
|
||||
"${appState.getAuthenticatedUser()!.firstName!} ${appState.getAuthenticatedUser()!.lastName!}".toText14(color: AppColors.textColor, isBold: true),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 12.h),
|
||||
Wrap(
|
||||
direction: Axis.horizontal,
|
||||
spacing: 6.w,
|
||||
runSpacing: 6.h,
|
||||
children: [
|
||||
AppCustomChipWidget(
|
||||
labelText: "File No.: ${appState.getAuthenticatedUser()!.patientId!.toString()}",
|
||||
labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 4.w),
|
||||
),
|
||||
AppCustomChipWidget(
|
||||
labelText: "ER Clinic".needTranslation,
|
||||
labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 4.w),
|
||||
),
|
||||
AppCustomChipWidget(
|
||||
labelText: emergencyServicesViewModel.selectedHospital!.name,
|
||||
labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 4.w),
|
||||
),
|
||||
AppCustomChipWidget(
|
||||
icon: AppAssets.calendar,
|
||||
labelText: DateUtil.formatDateToDate(DateTime.now(), false),
|
||||
labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 4.w),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 12.h),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 24.r,
|
||||
hasShadow: true,
|
||||
),
|
||||
child: SizedBox(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
"Amount before tax".needTranslation.toText18(isBold: true),
|
||||
Utils.getPaymentAmountWithSymbol(emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.patientShare.toString().toText16(isBold: true), AppColors.blackColor, 13,
|
||||
isSaudiCurrency: true),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 4.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: "".toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor)),
|
||||
"VAT 15% (${emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.patientTaxAmount})"
|
||||
.needTranslation
|
||||
.toText14(isBold: true, color: AppColors.greyTextColor, letterSpacing: -1),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 18.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 150.h,
|
||||
child: Utils.getPaymentMethods(),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Utils.getPaymentAmountWithSymbol(
|
||||
emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.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: LocaleKeys.payNow.tr(),
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
CustomPageRoute(page: ErOnlineCheckinPaymentPage()),
|
||||
);
|
||||
},
|
||||
backgroundColor: AppColors.infoColor,
|
||||
borderColor: AppColors.infoColor.withOpacity(0.01),
|
||||
textColor: AppColors.whiteColor,
|
||||
fontSize: 16.f,
|
||||
fontWeight: FontWeight.w500,
|
||||
borderRadius: 12.r,
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.w),
|
||||
height: 56.h,
|
||||
icon: AppAssets.appointment_pay_icon,
|
||||
iconColor: AppColors.whiteColor,
|
||||
iconSize: 18.h,
|
||||
).paddingSymmetrical(16.h, 24.h),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,510 @@
|
||||
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/emergency_services/emergency_services_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/insurance/insurance_home_page.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/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:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:smooth_corner/smooth_corner.dart';
|
||||
|
||||
class ErOnlineCheckinPaymentPage extends StatefulWidget {
|
||||
ErOnlineCheckinPaymentPage({super.key});
|
||||
|
||||
@override
|
||||
State<ErOnlineCheckinPaymentPage> createState() => _ErOnlineCheckinPaymentPageState();
|
||||
}
|
||||
|
||||
class _ErOnlineCheckinPaymentPageState extends State<ErOnlineCheckinPaymentPage> {
|
||||
late PayfortViewModel payfortViewModel;
|
||||
late EmergencyServicesViewModel emergencyServicesViewModel;
|
||||
|
||||
late AppState appState;
|
||||
|
||||
MyInAppBrowser? browser;
|
||||
|
||||
String selectedPaymentMethod = "";
|
||||
|
||||
String transID = "";
|
||||
|
||||
bool isShowTamara = false;
|
||||
|
||||
String tamaraPaymentStatus = "";
|
||||
|
||||
String tamaraOrderID = "";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
scheduleMicrotask(() {
|
||||
payfortViewModel.initPayfortViewModel();
|
||||
// payfortViewModel.getTamaraInstallmentsDetails().then((val) {
|
||||
// if (emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.patientShareWithTax! >= payfortViewModel.getTamaraInstallmentsDetailsResponseModel!.minLimit!.amount! &&
|
||||
// emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.patientShareWithTax! <= payfortViewModel.getTamaraInstallmentsDetailsResponseModel!.maxLimit!.amount!) {
|
||||
// setState(() {
|
||||
// isShowTamara = true;
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
appState = getIt.get<AppState>();
|
||||
payfortViewModel = Provider.of<PayfortViewModel>(context, listen: false);
|
||||
emergencyServicesViewModel = Provider.of<EmergencyServicesViewModel>(context, listen: false);
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.bgScaffoldColor,
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: CollapsingListView(
|
||||
title: "Emergency Check-In".needTranslation,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
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),
|
||||
SizedBox(height: 16.h),
|
||||
"Mada".needTranslation.toText16(isBold: true),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 8.h),
|
||||
const Spacer(),
|
||||
Transform.flip(
|
||||
flipX: appState.isArabic(),
|
||||
child: Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.forward_arrow_icon,
|
||||
iconColor: AppColors.blackColor,
|
||||
width: 40.h,
|
||||
height: 40.h,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
],
|
||||
).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: 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(),
|
||||
Transform.flip(
|
||||
flipX: appState.isArabic(),
|
||||
child: Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.forward_arrow_icon,
|
||||
iconColor: AppColors.blackColor,
|
||||
width: 40.h,
|
||||
height: 40.h,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
],
|
||||
).paddingSymmetrical(16.h, 16.h),
|
||||
).paddingSymmetrical(24.h, 0.h).onPress(() {
|
||||
selectedPaymentMethod = "VISA";
|
||||
openPaymentURL("visa");
|
||||
}),
|
||||
SizedBox(height: 16.h),
|
||||
isShowTamara
|
||||
? 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(),
|
||||
Transform.flip(
|
||||
flipX: appState.isArabic(),
|
||||
child: Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.forward_arrow_icon,
|
||||
iconColor: AppColors.blackColor,
|
||||
width: 40.h,
|
||||
height: 40.h,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
],
|
||||
).paddingSymmetrical(16.h, 16.h),
|
||||
).paddingSymmetrical(24.h, 0.h).onPress(() {
|
||||
selectedPaymentMethod = "TAMARA";
|
||||
openPaymentURL("tamara");
|
||||
})
|
||||
: SizedBox.shrink(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 24.h,
|
||||
hasShadow: false,
|
||||
),
|
||||
child: Consumer<PayfortViewModel>(builder: (context, payfortVM, child) {
|
||||
//TODO: Need to add loading state & animation for Apple Pay Configuration
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
(emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.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: () {
|
||||
Navigator.of(context).push(
|
||||
CustomPageRoute(
|
||||
page: InsuranceHomePage(),
|
||||
),
|
||||
);
|
||||
},
|
||||
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: [
|
||||
"Amount before tax".needTranslation.toText14(isBold: true),
|
||||
Utils.getPaymentAmountWithSymbol(emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.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(
|
||||
emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.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(emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.patientShareWithTax.toString().toText24(isBold: true), AppColors.blackColor, 17,
|
||||
isSaudiCurrency: true),
|
||||
],
|
||||
).paddingSymmetrical(24.h, 0.h),
|
||||
Platform.isIOS
|
||||
? Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.apple_pay_button,
|
||||
width: 200.h,
|
||||
height: 80.h,
|
||||
fit: BoxFit.contain,
|
||||
).paddingSymmetrical(24.h, 0.h).onPress(() {
|
||||
if (Utils.havePrivilege(103)) {
|
||||
startApplePay();
|
||||
} else {
|
||||
openPaymentURL("ApplePay");
|
||||
}
|
||||
})
|
||||
: SizedBox(height: 12.h),
|
||||
SizedBox(height: 12.h),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
openPaymentURL(String paymentMethod) {
|
||||
browser = MyInAppBrowser(onExitCallback: onBrowserExit, onLoadStartCallback: onBrowserLoadStart, context: context);
|
||||
transID = Utils.getAdvancePaymentTransID(
|
||||
emergencyServicesViewModel.selectedHospital!.iD,
|
||||
appState.getAuthenticatedUser()!.patientId!,
|
||||
);
|
||||
|
||||
//TODO: Need to pass dynamic params to the payment request instead of static values
|
||||
browser?.openPaymentBrowser(
|
||||
emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.patientShareWithTax!,
|
||||
"ER Online Check-In Payment",
|
||||
transID,
|
||||
emergencyServicesViewModel.selectedHospital!.iD.toString(),
|
||||
"CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com",
|
||||
selectedPaymentMethod,
|
||||
appState.getAuthenticatedUser()!.patientType.toString(),
|
||||
"${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}",
|
||||
appState.getAuthenticatedUser()!.patientId.toString(),
|
||||
appState.getAuthenticatedUser()!,
|
||||
browser!,
|
||||
false,
|
||||
"3",
|
||||
"",
|
||||
context,
|
||||
null,
|
||||
0,
|
||||
10,
|
||||
0,
|
||||
"3");
|
||||
}
|
||||
|
||||
startApplePay() async {
|
||||
// showCommonBottomSheet(context,
|
||||
// child: Utils.getLoadingWidget(), callBackFunc: (str) {}, title: "", height: ResponsiveExtension.screenHeight * 0.3, isCloseButtonVisible: false, isDismissible: false, isFullScreen: false);
|
||||
LoaderBottomSheet.showLoader();
|
||||
transID = Utils.getAdvancePaymentTransID(
|
||||
emergencyServicesViewModel.selectedHospital!.iD,
|
||||
appState.getAuthenticatedUser()!.patientId!,
|
||||
);
|
||||
|
||||
ApplePayInsertRequest applePayInsertRequest = ApplePayInsertRequest();
|
||||
|
||||
await payfortViewModel.getPayfortConfigurations(serviceId: ServiceTypeEnum.erOnlineCheckIn.getIdFromServiceEnum(), projectId: emergencyServicesViewModel.selectedHospital!.iD);
|
||||
|
||||
applePayInsertRequest.clientRequestID = transID;
|
||||
applePayInsertRequest.clinicID = 10;
|
||||
|
||||
applePayInsertRequest.currency = appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED";
|
||||
applePayInsertRequest.customerEmail = "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com";
|
||||
applePayInsertRequest.customerID = appState.getAuthenticatedUser()!.patientId.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 = emergencyServicesViewModel.selectedHospital!.iD.toString();
|
||||
applePayInsertRequest.serviceID = ServiceTypeEnum.erOnlineCheckIn.getIdFromServiceEnum().toString();
|
||||
applePayInsertRequest.channelID = 3;
|
||||
applePayInsertRequest.patientID = appState.getAuthenticatedUser()!.patientId.toString();
|
||||
applePayInsertRequest.patientTypeID = appState.getAuthenticatedUser()!.patientType;
|
||||
applePayInsertRequest.patientOutSA = appState.getAuthenticatedUser()!.outSa;
|
||||
applePayInsertRequest.appointmentDate = null;
|
||||
applePayInsertRequest.appointmentNo = 0;
|
||||
applePayInsertRequest.orderDescription = "ER Online Check-In Payment";
|
||||
applePayInsertRequest.liveServiceID = "0";
|
||||
applePayInsertRequest.latitude = "0.0";
|
||||
applePayInsertRequest.longitude = "0.0";
|
||||
applePayInsertRequest.amount = emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.patientShareWithTax!.toString();
|
||||
applePayInsertRequest.isSchedule = "0";
|
||||
applePayInsertRequest.language = appState.isArabic() ? 'ar' : 'en';
|
||||
applePayInsertRequest.languageID = appState.isArabic() ? 1 : 2;
|
||||
applePayInsertRequest.userName = appState.getAuthenticatedUser()!.patientId;
|
||||
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(emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.patientShareWithTax!.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()}");
|
||||
Navigator.of(context).pop();
|
||||
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(loadingText: "Checking payment status, Please wait...".needTranslation);
|
||||
await payfortViewModel.checkPaymentStatus(
|
||||
transactionID: transID,
|
||||
onSuccess: (apiResponse) async {
|
||||
print(apiResponse.data);
|
||||
if (payfortViewModel.payfortCheckPaymentStatusResponseModel!.responseMessage!.toLowerCase() == "success") {
|
||||
if (emergencyServicesViewModel.isERBookAppointment) {
|
||||
await emergencyServicesViewModel.ER_CreateAdvancePayment(
|
||||
paymentMethodName: selectedPaymentMethod,
|
||||
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
|
||||
onSuccess: (value) async {
|
||||
await emergencyServicesViewModel.addAdvanceNumberRequest(
|
||||
advanceNumber: value,
|
||||
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
|
||||
appointmentNo: "0",
|
||||
onSuccess: (val) {
|
||||
LoaderBottomSheet.hideLoader();
|
||||
if (emergencyServicesViewModel.isERBookAppointment) {
|
||||
showCommonBottomSheetWithoutHeight(
|
||||
context,
|
||||
child: Utils.getSuccessWidget(loadingText: "Your appointment has been booked successfully. Please perform Check-In once you arrive at the hospital.".needTranslation),
|
||||
callBackFunc: () {},
|
||||
isFullScreen: false,
|
||||
isCloseButtonVisible: true,
|
||||
);
|
||||
} else {}
|
||||
});
|
||||
});
|
||||
} else {}
|
||||
} 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 {
|
||||
checkPaymentStatus();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,169 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_nfc_kit/flutter_nfc_kit.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/common_models/privilege/ProjectDetailListModel.dart';
|
||||
import 'package:hmg_patient_app_new/core/dependencies.dart';
|
||||
import 'package:hmg_patient_app_new/core/location_util.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/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/presentation/appointments/my_appointments_page.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:barcode_scan2/barcode_scan2.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/nfc/nfc_reader_sheet.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
|
||||
|
||||
class ErOnlineCheckinSelectCheckinBottomSheet extends StatelessWidget {
|
||||
ErOnlineCheckinSelectCheckinBottomSheet({super.key, required this.projectID});
|
||||
|
||||
bool _supportsNFC = false;
|
||||
int projectID = 0;
|
||||
|
||||
late LocationUtils locationUtils;
|
||||
late AppState appState;
|
||||
ProjectDetailListModel projectDetailListModel = ProjectDetailListModel();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
appState = getIt.get<AppState>();
|
||||
FlutterNfcKit.nfcAvailability.then((value) {
|
||||
_supportsNFC = (value == NFCAvailability.available);
|
||||
});
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
checkInOptionCard(
|
||||
AppAssets.checkin_location_icon,
|
||||
"Live Location".needTranslation,
|
||||
"Verify your location to be at hospital to check in".needTranslation,
|
||||
).onPress(() {
|
||||
// locationUtils = LocationUtils(
|
||||
// isShowConfirmDialog: false,
|
||||
// navigationService: myAppointmentsViewModel.navigationService,
|
||||
// appState: myAppointmentsViewModel.appState,
|
||||
// );
|
||||
locationUtils.getCurrentLocation(onSuccess: (value) {
|
||||
projectDetailListModel = Utils.getProjectDetailObj(appState, projectID);
|
||||
double dist = Utils.distance(value.latitude, value.longitude, double.parse(projectDetailListModel.latitude!), double.parse(projectDetailListModel.longitude!)).ceilToDouble() * 1000;
|
||||
print(dist);
|
||||
if (dist <= projectDetailListModel.geofenceRadius!) {
|
||||
sendCheckInRequest(projectDetailListModel.checkInQrCode!, context);
|
||||
} else {
|
||||
showCommonBottomSheetWithoutHeight(context,
|
||||
title: "Error".needTranslation,
|
||||
child: Utils.getErrorWidget(loadingText: "Please ensure you're within the hospital location to perform online check-in.".needTranslation), callBackFunc: () {
|
||||
Navigator.of(context).pop();
|
||||
}, isFullScreen: false);
|
||||
}
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 16.h),
|
||||
checkInOptionCard(
|
||||
AppAssets.checkin_nfc_icon,
|
||||
"NFC (Near Field Communication)".needTranslation,
|
||||
"Scan your phone via NFC board to check in".needTranslation,
|
||||
).onPress(() {
|
||||
Future.delayed(const Duration(milliseconds: 500), () {
|
||||
showNfcReader(context, onNcfScan: (String nfcId) {
|
||||
Future.delayed(const Duration(milliseconds: 100), () {
|
||||
sendCheckInRequest(nfcId, context);
|
||||
});
|
||||
}, onCancel: () {});
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 16.h),
|
||||
checkInOptionCard(
|
||||
AppAssets.checkin_qr_icon,
|
||||
"QR Code".needTranslation,
|
||||
"Scan QR code with your camera to check in".needTranslation,
|
||||
).onPress(() async {
|
||||
String onlineCheckInQRCode = (await BarcodeScanner.scan().then((value) => value.rawContent));
|
||||
if (onlineCheckInQRCode != "") {
|
||||
sendCheckInRequest(onlineCheckInQRCode, context);
|
||||
} else {}
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget checkInOptionCard(String icon, String title, String subTitle) {
|
||||
return Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 20.h,
|
||||
hasShadow: false,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Utils.buildSvgWithAssets(icon: icon, width: 40.h, height: 40.h, fit: BoxFit.fill),
|
||||
SizedBox(height: 16.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
title.toText16(isBold: true, color: AppColors.textColor),
|
||||
subTitle.toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
|
||||
],
|
||||
),
|
||||
),
|
||||
Transform.flip(
|
||||
flipX: appState.isArabic(),
|
||||
child: Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.forward_arrow_icon_small,
|
||||
iconColor: AppColors.blackColor,
|
||||
width: 18.h,
|
||||
height: 13.h,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
).paddingAll(16.h),
|
||||
);
|
||||
}
|
||||
|
||||
void sendCheckInRequest(String scannedCode, BuildContext context) async {
|
||||
showCommonBottomSheet(context,
|
||||
child: Utils.getLoadingWidget(), callBackFunc: (str) {}, title: "", height: ResponsiveExtension.screenHeight * 0.3, isCloseButtonVisible: false, isDismissible: false, isFullScreen: false);
|
||||
// await myAppointmentsViewModel.sendCheckInNfcRequest(
|
||||
// patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
|
||||
// scannedCode: scannedCode,
|
||||
// checkInType: 2,
|
||||
// onSuccess: (apiResponse) {
|
||||
// Navigator.of(context).pop();
|
||||
// showCommonBottomSheetWithoutHeight(context, title: "Success".needTranslation, child: Utils.getSuccessWidget(loadingText: LocaleKeys.success.tr()), callBackFunc: () {
|
||||
// Navigator.of(context).pop();
|
||||
// Navigator.pushAndRemoveUntil(
|
||||
// context,
|
||||
// CustomPageRoute(
|
||||
// page: LandingNavigation(),
|
||||
// ),
|
||||
// (r) => false);
|
||||
// Navigator.of(context).push(
|
||||
// CustomPageRoute(page: MyAppointmentsPage()),
|
||||
// );
|
||||
// }, isFullScreen: false);
|
||||
// },
|
||||
// onError: (error) {
|
||||
// Navigator.of(context).pop();
|
||||
// showCommonBottomSheetWithoutHeight(context, title: "Error".needTranslation, child: Utils.getErrorWidget(loadingText: error), callBackFunc: () {
|
||||
// Navigator.of(context).pop();
|
||||
// }, isFullScreen: false);
|
||||
// },
|
||||
// );
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,198 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.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/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/main.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_card.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class EyeMeasurementDetailsPage extends StatelessWidget {
|
||||
EyeMeasurementDetailsPage({super.key, required this.patientAppointmentHistoryResponseModel});
|
||||
|
||||
final PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel;
|
||||
late BookAppointmentsViewModel bookAppointmentsViewModel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bookAppointmentsViewModel = Provider.of<BookAppointmentsViewModel>(context, listen: false);
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.bgScaffoldColor,
|
||||
body: CollapsingListView(
|
||||
title: LocaleKeys.eyeMeasurements.tr(),
|
||||
child: SingleChildScrollView(
|
||||
child: Consumer<MyAppointmentsViewModel>(builder: (context, myAppointmentsVM, child) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 16.h),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
|
||||
child: AppointmentCard(
|
||||
patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
|
||||
myAppointmentsViewModel: myAppointmentsVM,
|
||||
bookAppointmentsViewModel: bookAppointmentsViewModel,
|
||||
isLoading: false,
|
||||
isFromHomePage: false,
|
||||
isFromMedicalReport: true,
|
||||
isForEyeMeasurements: true,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
CustomTabBar(
|
||||
activeTextColor: AppColors.primaryRedColor,
|
||||
activeBackgroundColor: AppColors.primaryRedColor.withValues(alpha: .1),
|
||||
tabs: [
|
||||
CustomTabBarModel(null, LocaleKeys.classes.tr()),
|
||||
CustomTabBarModel(null, LocaleKeys.contactLens.tr()),
|
||||
],
|
||||
onTabChange: (index) {
|
||||
myAppointmentsVM.onEyeMeasurementsTabChanged(index);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 12.h),
|
||||
getSelectedTabContent(myAppointmentsVM),
|
||||
],
|
||||
).paddingSymmetrical(24.w, 0);
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getSelectedTabContent(MyAppointmentsViewModel myAppointmentsVM) {
|
||||
switch (myAppointmentsVM.eyeMeasurementsTabSelectedIndex) {
|
||||
case 0:
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(16.h),
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.r, hasShadow: true),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
LocaleKeys.rightEye.tr().toText14(isBold: true),
|
||||
SizedBox(height: 16.h),
|
||||
getRow(LocaleKeys.sphere.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].rightEyeSpherical}', '-'),
|
||||
getRow(LocaleKeys.cylinder.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].rightEyeCylinder}', '-'),
|
||||
getRow(LocaleKeys.axis.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].rightEyeAxis}', '-'),
|
||||
getRow(LocaleKeys.prism.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].rightEyePrism}', '-'),
|
||||
getRow(LocaleKeys.va.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].rightEyeVA}', '-'),
|
||||
getRow(LocaleKeys.remarks.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].rightEyeRemarks}', '-', isLast: true),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
Container(
|
||||
padding: EdgeInsets.all(16.h),
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.r, hasShadow: true),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
LocaleKeys.leftEye.tr().needTranslation.toText14(isBold: true),
|
||||
SizedBox(height: 16.h),
|
||||
getRow(LocaleKeys.sphere.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].leftEyeSpherical}', '-'),
|
||||
getRow(LocaleKeys.cylinder.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].leftEyeCylinder}', '-'),
|
||||
getRow(LocaleKeys.axis.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].leftEyeAxis}', '-'),
|
||||
getRow(LocaleKeys.prism.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].leftEyePrism}', '-'),
|
||||
getRow(LocaleKeys.va.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].leftEyeVA}', '-'),
|
||||
getRow(LocaleKeys.remarks.tr(), '${patientAppointmentHistoryResponseModel.listHISGetGlassPrescription![0].leftEyeRemarks}', '-', isLast: true),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24.h),
|
||||
],
|
||||
);
|
||||
case 1:
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(16.h),
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.r, hasShadow: true),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
LocaleKeys.rightEye.tr().toText14(isBold: true),
|
||||
SizedBox(height: 16.h),
|
||||
getRow(LocaleKeys.brand.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].brand}', ''),
|
||||
getRow('B.C', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].baseCurve}', ''),
|
||||
getRow(LocaleKeys.power.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].power}', ''),
|
||||
getRow(LocaleKeys.diameter.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].diameter}', ''),
|
||||
getRow('OZ', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].oZ}', ''),
|
||||
getRow('CT', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].cT}', ''),
|
||||
getRow('Blend', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].blend}', ''),
|
||||
getRow(LocaleKeys.remarks.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![0].remarks}', '', isLast: true),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
Container(
|
||||
padding: EdgeInsets.all(16.h),
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.r, hasShadow: true),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
LocaleKeys.leftEye.tr().needTranslation.toText14(isBold: true),
|
||||
SizedBox(height: 16.h),
|
||||
getRow(LocaleKeys.brand.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].brand}', ''),
|
||||
getRow('B.C', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].baseCurve}', ''),
|
||||
getRow(LocaleKeys.power.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].power}', ''),
|
||||
getRow(LocaleKeys.diameter.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].diameter}', ''),
|
||||
getRow('OZ', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].oZ}', ''),
|
||||
getRow('CT', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].cT}', ''),
|
||||
getRow('Blend', '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].blend}', ''),
|
||||
getRow(LocaleKeys.remarks.tr(), '${patientAppointmentHistoryResponseModel.listHISGetContactLensPrescription![1].remarks}', '', isLast: true),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24.h),
|
||||
],
|
||||
);
|
||||
default:
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
|
||||
Widget getRow(String title, String val1, String val2, {bool isLast = false}) => Padding(
|
||||
padding: EdgeInsets.only(left: 8.w, right: 8.w),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.all(8.h),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(flex: 2, child: title.toText11(weight: FontWeight.w500)),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
SizedBox(width: 120.w, child: (val1 == 'null' ? '-' : val1).toText10(isBold: true, textOverflow: TextOverflow.clip)),
|
||||
(val2 == 'null' ? '-' : val2).toText10(isBold: true, textOverflow: TextOverflow.ellipsis),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
isLast
|
||||
? Container(
|
||||
height: 4,
|
||||
)
|
||||
: Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 2.h)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_staggered_animations/flutter_staggered_animations.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/book_appointments/book_appointments_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
|
||||
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointment_card.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class EyeMeasurementsAppointmentsPage extends StatelessWidget {
|
||||
EyeMeasurementsAppointmentsPage({super.key});
|
||||
|
||||
late BookAppointmentsViewModel bookAppointmentsViewModel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bookAppointmentsViewModel = Provider.of<BookAppointmentsViewModel>(context, listen: false);
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.bgScaffoldColor,
|
||||
body: CollapsingListView(
|
||||
title: "Eye Measurements",
|
||||
child: SingleChildScrollView(
|
||||
child: Consumer<MyAppointmentsViewModel>(builder: (context, myAppointmentsVM, child) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 16.h),
|
||||
ListView.separated(
|
||||
scrollDirection: Axis.vertical,
|
||||
itemCount: myAppointmentsVM.isEyeMeasurementsAppointmentsLoading
|
||||
? 5
|
||||
: myAppointmentsVM.patientEyeMeasurementsAppointmentsHistoryList.isNotEmpty
|
||||
? myAppointmentsVM.patientEyeMeasurementsAppointmentsHistoryList.length
|
||||
: 1,
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
padding: EdgeInsets.only(left: 24.h, right: 24.h),
|
||||
itemBuilder: (context, index) {
|
||||
return myAppointmentsVM.isEyeMeasurementsAppointmentsLoading
|
||||
? Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
|
||||
child: AppointmentCard(
|
||||
patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel(),
|
||||
myAppointmentsViewModel: myAppointmentsVM,
|
||||
bookAppointmentsViewModel: bookAppointmentsViewModel,
|
||||
isLoading: true,
|
||||
isFromHomePage: false,
|
||||
),
|
||||
)
|
||||
: myAppointmentsVM.patientEyeMeasurementsAppointmentsHistoryList.isNotEmpty
|
||||
? AnimationConfiguration.staggeredList(
|
||||
position: index,
|
||||
duration: const Duration(milliseconds: 1000),
|
||||
child: SlideAnimation(
|
||||
verticalOffset: 100.0,
|
||||
child: FadeInAnimation(
|
||||
child: AnimatedContainer(
|
||||
duration: Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOut,
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
|
||||
child: AppointmentCard(
|
||||
patientAppointmentHistoryResponseModel: myAppointmentsVM.patientEyeMeasurementsAppointmentsHistoryList[index],
|
||||
myAppointmentsViewModel: myAppointmentsVM,
|
||||
bookAppointmentsViewModel: bookAppointmentsViewModel,
|
||||
isLoading: false,
|
||||
isFromHomePage: false,
|
||||
isForEyeMeasurements: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
: Utils.getNoDataWidget(context, noDataText: "No Ophthalmology appointments found...".needTranslation);
|
||||
},
|
||||
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
|
||||
),
|
||||
SizedBox(height: 60.h),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue