Compare commits
18 Commits
a79dcad221
...
192d617350
| Author | SHA1 | Date |
|---|---|---|
|
|
192d617350 | 1 month ago |
|
|
e48e98d61b | 1 month ago |
|
|
d3978de92e | 1 month ago |
|
|
92c3033087 | 1 month ago |
|
|
5151997c7f | 1 month ago |
|
|
e5f4da4e16 | 1 month ago |
|
|
1125437a56 | 1 month ago |
|
|
4974121061 | 1 month ago |
|
|
836a72ec22 | 1 month ago |
|
|
ba2785496d | 1 month ago |
|
|
97038f1a25 | 1 month ago |
|
|
db880760c3 | 1 month ago |
|
|
3e95999bf3 | 1 month ago |
|
|
f9bfc131a8 | 1 month ago |
|
|
1c2564a1e2 | 1 month ago |
|
|
6048b3b5f1 | 1 month ago |
|
|
a4854bbe4a | 1 month ago |
|
|
bdde6c224d | 1 month ago |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 83 KiB |
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
|
||||||
|
///class used to provide value for the [DynamicResultChart] to plot the values
|
||||||
|
class DataPoint {
|
||||||
|
///values that is displayed on the graph and dot is plotted on this
|
||||||
|
final double value;
|
||||||
|
///label shown on the bottom of the graph
|
||||||
|
String label;
|
||||||
|
|
||||||
|
DataPoint(
|
||||||
|
{required this.value,
|
||||||
|
required this.label,
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
import 'dart:ui' show Color;
|
||||||
|
|
||||||
|
class ThresholdRange {
|
||||||
|
final String label;
|
||||||
|
final double value;
|
||||||
|
final Color color;
|
||||||
|
final Color lineColor;
|
||||||
|
final String? actualValue;
|
||||||
|
|
||||||
|
ThresholdRange(
|
||||||
|
{required this.label,
|
||||||
|
required this.value,
|
||||||
|
required this.color,
|
||||||
|
required this.lineColor,
|
||||||
|
this.actualValue});
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ThresholdRange(label: $label, value: $value, color: ${color.value.toRadixString(16)}, lineColor: ${lineColor.value.toRadixString(16)})';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
class FamilyFileRequest {
|
||||||
|
int? sharedPatientId;
|
||||||
|
String? sharedPatientIdentificationId;
|
||||||
|
int? searchType;
|
||||||
|
String? sharedPatientMobileNumber;
|
||||||
|
String? zipCode;
|
||||||
|
bool? isRegister;
|
||||||
|
int? patientStatus;
|
||||||
|
bool? isDentalAllowedBackend;
|
||||||
|
bool? isPatientExcluded;
|
||||||
|
int? responseID;
|
||||||
|
|
||||||
|
FamilyFileRequest({
|
||||||
|
this.sharedPatientId,
|
||||||
|
this.sharedPatientIdentificationId,
|
||||||
|
this.searchType,
|
||||||
|
this.sharedPatientMobileNumber,
|
||||||
|
this.zipCode,
|
||||||
|
this.isRegister,
|
||||||
|
this.patientStatus,
|
||||||
|
this.isDentalAllowedBackend,
|
||||||
|
this.isPatientExcluded,
|
||||||
|
this.responseID,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory FamilyFileRequest.fromRawJson(String str) => FamilyFileRequest.fromJson(json.decode(str));
|
||||||
|
|
||||||
|
String toRawJson() => json.encode(toJson());
|
||||||
|
|
||||||
|
factory FamilyFileRequest.fromJson(Map<String, dynamic> json) => FamilyFileRequest(
|
||||||
|
sharedPatientId: json["sharedPatientID"],
|
||||||
|
sharedPatientIdentificationId: json["sharedPatientIdentificationID"],
|
||||||
|
searchType: json["searchType"],
|
||||||
|
sharedPatientMobileNumber: json["sharedPatientMobileNumber"],
|
||||||
|
zipCode: json["zipCode"],
|
||||||
|
isRegister: json["isRegister"],
|
||||||
|
patientStatus: json["patientStatus"],
|
||||||
|
isDentalAllowedBackend: json["isDentalAllowedBackend"],
|
||||||
|
isPatientExcluded: json["IsPatientExcluded"],
|
||||||
|
responseID: json["ReponseID"],
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
"SharedPatientID": sharedPatientId,
|
||||||
|
"SharedPatientIdentificationID": sharedPatientIdentificationId,
|
||||||
|
"SearchType": searchType,
|
||||||
|
"SharedPatientMobileNumber": sharedPatientMobileNumber,
|
||||||
|
"zipCode": zipCode,
|
||||||
|
"isRegister": isRegister,
|
||||||
|
"PatientStatus": patientStatus,
|
||||||
|
"isDentalAllowedBackend": isDentalAllowedBackend,
|
||||||
|
"IsPatientExcluded": isPatientExcluded,
|
||||||
|
"ReponseID": responseID,
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -0,0 +1,430 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:developer';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/app_assets.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/app_state.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/cache_consts.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/dependencies.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/enums.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/utils/utils.dart';
|
||||||
|
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
|
||||||
|
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
|
||||||
|
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
|
||||||
|
import 'package:hmg_patient_app_new/features/payfort/models/apple_pay_request_insert_model.dart';
|
||||||
|
import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart';
|
||||||
|
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
|
||||||
|
import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
|
||||||
|
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||||
|
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
|
||||||
|
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
|
||||||
|
import 'package:hmg_patient_app_new/widgets/in_app_browser/InAppBrowser.dart';
|
||||||
|
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class WalletPaymentConfirmPage extends StatefulWidget {
|
||||||
|
const WalletPaymentConfirmPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<WalletPaymentConfirmPage> createState() => _WalletPaymentConfirmPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _WalletPaymentConfirmPageState extends State<WalletPaymentConfirmPage> {
|
||||||
|
late PayfortViewModel payfortViewModel;
|
||||||
|
late AppState appState;
|
||||||
|
late HabibWalletViewModel habibWalletVM;
|
||||||
|
|
||||||
|
MyInAppBrowser? browser;
|
||||||
|
String selectedPaymentMethod = "";
|
||||||
|
|
||||||
|
String transID = "";
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
scheduleMicrotask(() {
|
||||||
|
payfortViewModel.initPayfortViewModel();
|
||||||
|
});
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
appState = getIt.get<AppState>();
|
||||||
|
habibWalletVM = Provider.of<HabibWalletViewModel>(context, listen: false);
|
||||||
|
payfortViewModel = Provider.of<PayfortViewModel>(context, listen: false);
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: AppColors.bgScaffoldColor,
|
||||||
|
body: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: CollapsingListView(
|
||||||
|
title: "Select Payment Method",
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SizedBox(height: 24.h),
|
||||||
|
Container(
|
||||||
|
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||||
|
color: AppColors.whiteColor,
|
||||||
|
borderRadius: 20.h,
|
||||||
|
hasShadow: false,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Image.asset(AppAssets.mada, width: 72.h, height: 25.h).toShimmer2(isShow: false),
|
||||||
|
SizedBox(height: 16.h),
|
||||||
|
"Mada".needTranslation.toText16(isBold: true).toShimmer2(isShow: false),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(width: 8.h),
|
||||||
|
const Spacer(),
|
||||||
|
Transform.flip(
|
||||||
|
flipX: appState.isArabic() ? true : false,
|
||||||
|
child: Utils.buildSvgWithAssets(
|
||||||
|
icon: AppAssets.forward_arrow_icon,
|
||||||
|
iconColor: AppColors.blackColor,
|
||||||
|
width: 18.h,
|
||||||
|
height: 13.h,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
).toShimmer2(isShow: false),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).paddingSymmetrical(16.h, 16.h),
|
||||||
|
).paddingSymmetrical(24.h, 0.h).onPress(() {
|
||||||
|
selectedPaymentMethod = "MADA";
|
||||||
|
openPaymentURL("mada");
|
||||||
|
}),
|
||||||
|
SizedBox(height: 16.h),
|
||||||
|
Container(
|
||||||
|
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||||
|
color: AppColors.whiteColor,
|
||||||
|
borderRadius: 20.h,
|
||||||
|
hasShadow: false,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Image.asset(AppAssets.visa, width: 40.h, height: 40.h),
|
||||||
|
SizedBox(width: 8.h),
|
||||||
|
Image.asset(AppAssets.Mastercard, width: 40.h, height: 40.h),
|
||||||
|
],
|
||||||
|
).toShimmer2(isShow: false),
|
||||||
|
SizedBox(height: 16.h),
|
||||||
|
"Visa or Mastercard".needTranslation.toText16(isBold: true).toShimmer2(isShow: false),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(width: 8.h),
|
||||||
|
const Spacer(),
|
||||||
|
Transform.flip(
|
||||||
|
flipX: appState.isArabic() ? true : false,
|
||||||
|
child: Utils.buildSvgWithAssets(
|
||||||
|
icon: AppAssets.forward_arrow_icon,
|
||||||
|
iconColor: AppColors.blackColor,
|
||||||
|
width: 18.h,
|
||||||
|
height: 13.h,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
).toShimmer2(isShow: false),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).paddingSymmetrical(16.h, 16.h),
|
||||||
|
).paddingSymmetrical(24.h, 0.h).onPress(() {
|
||||||
|
selectedPaymentMethod = "VISA";
|
||||||
|
openPaymentURL("visa");
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
// height: 200.h,
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||||
|
color: AppColors.whiteColor,
|
||||||
|
borderRadius: 24.h,
|
||||||
|
hasShadow: true,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SizedBox(height: 24.h),
|
||||||
|
habibWalletVM.depositorName.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
|
||||||
|
SizedBox(height: 12.h),
|
||||||
|
Wrap(
|
||||||
|
direction: Axis.horizontal,
|
||||||
|
spacing: 4.h,
|
||||||
|
runSpacing: 4.h,
|
||||||
|
children: [
|
||||||
|
AppCustomChipWidget(labelText: "${LocaleKeys.fileno.tr(context: context)}.: ${habibWalletVM.fileNumber}"),
|
||||||
|
AppCustomChipWidget(labelText: "${LocaleKeys.mobileNumber.tr(context: context)}: ${habibWalletVM.mobileNumber}"),
|
||||||
|
AppCustomChipWidget(labelText: "${habibWalletVM.selectedHospital!.name}"),
|
||||||
|
],
|
||||||
|
).paddingSymmetrical(24.h, 0.h),
|
||||||
|
SizedBox(height: 16.h),
|
||||||
|
Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h).paddingSymmetrical(24.h, 0.h),
|
||||||
|
SizedBox(height: 16.h),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
"Total amount to pay".needTranslation.toText16(isBold: true),
|
||||||
|
Utils.getPaymentAmountWithSymbol(habibWalletVM.walletRechargeAmount.toString().toText24(isBold: true), AppColors.blackColor, 15.h, isSaudiCurrency: true),
|
||||||
|
],
|
||||||
|
).paddingSymmetrical(24.h, 0.h),
|
||||||
|
SizedBox(height: 12.h),
|
||||||
|
Platform.isIOS
|
||||||
|
? Utils.buildSvgWithAssets(
|
||||||
|
icon: AppAssets.apple_pay_button,
|
||||||
|
width: 200.h,
|
||||||
|
height: 56.h,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
).paddingSymmetrical(24.h, 0.h).onPress(() {
|
||||||
|
if (Utils.havePrivilege(103)) {
|
||||||
|
startApplePay();
|
||||||
|
} else {
|
||||||
|
openPaymentURL("ApplePay");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
: SizedBox(height: 12.h),
|
||||||
|
SizedBox(height: 32.h),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
startApplePay() async {
|
||||||
|
LoaderBottomSheet.showLoader();
|
||||||
|
ApplePayInsertRequest applePayInsertRequest = ApplePayInsertRequest();
|
||||||
|
|
||||||
|
transID = Utils.getAdvancePaymentTransID(habibWalletVM.selectedHospital!.iD!, int.parse(habibWalletVM.fileNumber));
|
||||||
|
|
||||||
|
await payfortViewModel.getPayfortConfigurations(serviceId: ServiceTypeEnum.advancePayment.getIdFromServiceEnum(), projectId: habibWalletVM.selectedHospital!.iD!, integrationId: 2);
|
||||||
|
|
||||||
|
applePayInsertRequest.clientRequestID = transID;
|
||||||
|
applePayInsertRequest.clinicID = 0;
|
||||||
|
|
||||||
|
applePayInsertRequest.currency = appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED";
|
||||||
|
applePayInsertRequest.customerEmail = "CustID_${habibWalletVM.fileNumber.toString()}@HMG.com";
|
||||||
|
applePayInsertRequest.customerID = habibWalletVM.fileNumber.toString();
|
||||||
|
applePayInsertRequest.customerName = "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}";
|
||||||
|
|
||||||
|
applePayInsertRequest.deviceToken = await Utils.getStringFromPrefs(CacheConst.pushToken);
|
||||||
|
applePayInsertRequest.voipToken = await Utils.getStringFromPrefs(CacheConst.voipToken);
|
||||||
|
applePayInsertRequest.doctorID = 0;
|
||||||
|
applePayInsertRequest.projectID = habibWalletVM.selectedHospital!.iD!.toString();
|
||||||
|
applePayInsertRequest.serviceID = ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum().toString();
|
||||||
|
applePayInsertRequest.channelID = 3;
|
||||||
|
applePayInsertRequest.patientID = habibWalletVM.fileNumber.toString();
|
||||||
|
applePayInsertRequest.patientTypeID = appState.getAuthenticatedUser()!.patientType;
|
||||||
|
applePayInsertRequest.patientOutSA = appState.getAuthenticatedUser()!.outSa;
|
||||||
|
applePayInsertRequest.appointmentDate = null;
|
||||||
|
applePayInsertRequest.appointmentNo = 0;
|
||||||
|
applePayInsertRequest.orderDescription = "Advance Payment";
|
||||||
|
applePayInsertRequest.liveServiceID = "0";
|
||||||
|
applePayInsertRequest.latitude = "0.0";
|
||||||
|
applePayInsertRequest.longitude = "0.0";
|
||||||
|
applePayInsertRequest.amount = habibWalletVM.walletRechargeAmount.toString();
|
||||||
|
applePayInsertRequest.isSchedule = "0";
|
||||||
|
applePayInsertRequest.language = appState.isArabic() ? 'ar' : 'en';
|
||||||
|
applePayInsertRequest.languageID = appState.isArabic() ? 1 : 2;
|
||||||
|
applePayInsertRequest.userName = int.parse(habibWalletVM.fileNumber);
|
||||||
|
applePayInsertRequest.responseContinueURL = "http://hmg.com/Documents/success.html";
|
||||||
|
applePayInsertRequest.backClickUrl = "http://hmg.com/Documents/success.html";
|
||||||
|
applePayInsertRequest.paymentOption = "ApplePay";
|
||||||
|
|
||||||
|
applePayInsertRequest.isMobSDK = true;
|
||||||
|
applePayInsertRequest.merchantReference = transID;
|
||||||
|
applePayInsertRequest.merchantIdentifier = payfortViewModel.payfortProjectDetailsRespModel!.merchantIdentifier;
|
||||||
|
applePayInsertRequest.commandType = "PURCHASE";
|
||||||
|
applePayInsertRequest.signature = payfortViewModel.payfortProjectDetailsRespModel!.signature;
|
||||||
|
applePayInsertRequest.accessCode = payfortViewModel.payfortProjectDetailsRespModel!.accessCode;
|
||||||
|
applePayInsertRequest.shaRequestPhrase = payfortViewModel.payfortProjectDetailsRespModel!.shaRequest;
|
||||||
|
applePayInsertRequest.shaResponsePhrase = payfortViewModel.payfortProjectDetailsRespModel!.shaResponse;
|
||||||
|
applePayInsertRequest.returnURL = "";
|
||||||
|
|
||||||
|
//TODO: Need to pass dynamic params to the Apple Pay instead of static values
|
||||||
|
await payfortViewModel.applePayRequestInsert(applePayInsertRequest: applePayInsertRequest).then((value) {
|
||||||
|
payfortViewModel.paymentWithApplePay(
|
||||||
|
customerName: "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}",
|
||||||
|
// customerEmail: projectViewModel.authenticatedUserObject.user.emailAddress,
|
||||||
|
customerEmail: "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com",
|
||||||
|
orderDescription: "Appointment Payment",
|
||||||
|
orderAmount: double.parse(habibWalletVM.walletRechargeAmount.toString()),
|
||||||
|
merchantReference: transID,
|
||||||
|
merchantIdentifier: payfortViewModel.payfortProjectDetailsRespModel!.merchantIdentifier,
|
||||||
|
applePayAccessCode: payfortViewModel.payfortProjectDetailsRespModel!.accessCode,
|
||||||
|
applePayShaRequestPhrase: payfortViewModel.payfortProjectDetailsRespModel!.shaRequest,
|
||||||
|
currency: appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED",
|
||||||
|
onFailed: (failureResult) async {
|
||||||
|
log("failureResult: ${failureResult.message.toString()}");
|
||||||
|
showCommonBottomSheetWithoutHeight(
|
||||||
|
context,
|
||||||
|
child: Utils.getErrorWidget(loadingText: failureResult.message.toString()),
|
||||||
|
callBackFunc: () {},
|
||||||
|
isFullScreen: false,
|
||||||
|
isCloseButtonVisible: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onSucceeded: (successResult) async {
|
||||||
|
log("successResult: ${successResult.responseMessage.toString()}");
|
||||||
|
selectedPaymentMethod = successResult.paymentOption ?? "VISA";
|
||||||
|
checkPaymentStatus();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkPaymentStatus() async {
|
||||||
|
LoaderBottomSheet.showLoader();
|
||||||
|
await payfortViewModel.checkPaymentStatus(
|
||||||
|
transactionID: transID,
|
||||||
|
onSuccess: (apiResponse) async {
|
||||||
|
print(apiResponse.data);
|
||||||
|
if (payfortViewModel.payfortCheckPaymentStatusResponseModel!.responseMessage!.toLowerCase() == "success") {
|
||||||
|
await habibWalletVM.HISCreateAdvancePayment(
|
||||||
|
paymentMethodName: selectedPaymentMethod,
|
||||||
|
paidAmount: habibWalletVM.walletRechargeAmount,
|
||||||
|
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
|
||||||
|
patientID: habibWalletVM.fileNumber,
|
||||||
|
projectID: habibWalletVM.selectedHospital!.iD!,
|
||||||
|
depositorName: habibWalletVM.depositorName,
|
||||||
|
onSuccess: (value) async {
|
||||||
|
await habibWalletVM.addAdvanceNumberRequest(
|
||||||
|
advanceNumber: Utils.isVidaPlusProject(habibWalletVM.selectedHospital!.iD)
|
||||||
|
? value.data['OnlineCheckInAppointments'][0]['AdvanceNumber_VP'].toString()
|
||||||
|
: value.data['OnlineCheckInAppointments'][0]['AdvanceNumber'].toString(),
|
||||||
|
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
|
||||||
|
onSuccess: (value) {
|
||||||
|
LoaderBottomSheet.hideLoader();
|
||||||
|
showCommonBottomSheetWithoutHeight(
|
||||||
|
context,
|
||||||
|
child: Utils.getSuccessWidget(loadingText: "Payment Successful!".needTranslation),
|
||||||
|
callBackFunc: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
isFullScreen: false,
|
||||||
|
isCloseButtonVisible: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onError: (err) {
|
||||||
|
LoaderBottomSheet.hideLoader();
|
||||||
|
showCommonBottomSheetWithoutHeight(
|
||||||
|
context,
|
||||||
|
child: Utils.getErrorWidget(loadingText: "Payment Failed - ${err}".needTranslation),
|
||||||
|
callBackFunc: () {},
|
||||||
|
isFullScreen: false,
|
||||||
|
isCloseButtonVisible: true,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onError: (err) {});
|
||||||
|
} else {
|
||||||
|
LoaderBottomSheet.hideLoader();
|
||||||
|
showCommonBottomSheetWithoutHeight(
|
||||||
|
context,
|
||||||
|
child: Utils.getErrorWidget(loadingText: "Payment Failed! Please try again.".needTranslation),
|
||||||
|
callBackFunc: () {},
|
||||||
|
isFullScreen: false,
|
||||||
|
isCloseButtonVisible: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onBrowserLoadStart(String url) {
|
||||||
|
print("onBrowserLoadStart");
|
||||||
|
print(url);
|
||||||
|
|
||||||
|
if (selectedPaymentMethod == "tamara") {
|
||||||
|
if (Platform.isAndroid) {
|
||||||
|
Uri uri = new Uri.dataFromString(url);
|
||||||
|
// tamaraPaymentStatus = uri.queryParameters['status']!;
|
||||||
|
// tamaraOrderID = uri.queryParameters['AuthorizePaymentId']!;
|
||||||
|
} else {
|
||||||
|
Uri uri = new Uri.dataFromString(url);
|
||||||
|
// tamaraPaymentStatus = uri.queryParameters['paymentStatus']!;
|
||||||
|
// tamaraOrderID = uri.queryParameters['orderId']!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(selectedPaymentMethod != "TAMARA") {
|
||||||
|
MyInAppBrowser.successURLS.forEach((element) {
|
||||||
|
if (url.contains(element)) {
|
||||||
|
browser?.close();
|
||||||
|
MyInAppBrowser.isPaymentDone = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if(selectedPaymentMethod != "TAMARA") {
|
||||||
|
MyInAppBrowser.errorURLS.forEach((element) {
|
||||||
|
if (url.contains(element)) {
|
||||||
|
browser?.close();
|
||||||
|
MyInAppBrowser.isPaymentDone = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
onBrowserExit(bool isPaymentMade) async {
|
||||||
|
print("onBrowserExit Called!!!!");
|
||||||
|
if (selectedPaymentMethod == "TAMARA") {
|
||||||
|
// checkTamaraPaymentStatus(transID!, appo);
|
||||||
|
// if (tamaraPaymentStatus != null && tamaraPaymentStatus.toLowerCase() == "approved") {
|
||||||
|
// updateTamaraRequestStatus("success", "14", Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo), tamaraOrderID, num.parse(selectedInstallments), appo);
|
||||||
|
// } else {
|
||||||
|
// updateTamaraRequestStatus("Failed", "00", Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo), tamaraOrderID, num.parse(selectedInstallments), appo);
|
||||||
|
// }
|
||||||
|
} else {
|
||||||
|
checkPaymentStatus();
|
||||||
|
// checkPaymentStatus(appo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openPaymentURL(String paymentMethod) {
|
||||||
|
browser = MyInAppBrowser(onExitCallback: onBrowserExit, onLoadStartCallback: onBrowserLoadStart, context: context);
|
||||||
|
transID = Utils.getAdvancePaymentTransID(habibWalletVM.selectedHospital!.iD!, int.parse(habibWalletVM.fileNumber));
|
||||||
|
|
||||||
|
browser?.openPaymentBrowser(
|
||||||
|
habibWalletVM.walletRechargeAmount,
|
||||||
|
"Advance Payment",
|
||||||
|
transID,
|
||||||
|
habibWalletVM.selectedHospital!.iD!.toString(),
|
||||||
|
"CustID_${habibWalletVM.fileNumber.toString()}@HMG.com",
|
||||||
|
selectedPaymentMethod,
|
||||||
|
appState.getAuthenticatedUser()!.patientType.toString(),
|
||||||
|
habibWalletVM.depositorName,
|
||||||
|
habibWalletVM.fileNumber.toString(),
|
||||||
|
appState.getAuthenticatedUser()!,
|
||||||
|
browser!,
|
||||||
|
false,
|
||||||
|
"3",
|
||||||
|
"0",
|
||||||
|
context,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"3");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,106 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/app_assets.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/app_export.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/app_state.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/dependencies.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/utils/utils.dart';
|
||||||
|
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
|
||||||
|
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart';
|
||||||
|
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||||
|
|
||||||
|
class HospitalListItemAdvancePayment extends StatelessWidget {
|
||||||
|
final HospitalsModel hospitalModel;
|
||||||
|
final bool isLocationEnabled;
|
||||||
|
|
||||||
|
late AppState appState;
|
||||||
|
|
||||||
|
HospitalListItemAdvancePayment({super.key, required this.hospitalModel, required this.isLocationEnabled});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
appState = getIt.get<AppState>();
|
||||||
|
return DecoratedBox(
|
||||||
|
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||||
|
color: AppColors.whiteColor,
|
||||||
|
borderRadius: 20.h,
|
||||||
|
hasShadow: false,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
spacing: 8.h,
|
||||||
|
children: [hospitalName],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Transform.flip(
|
||||||
|
flipX: appState.isArabic() ? true : false,
|
||||||
|
child: Utils.buildSvgWithAssets(
|
||||||
|
icon: AppAssets.forward_arrow_icon,
|
||||||
|
iconColor: AppColors.blackColor,
|
||||||
|
width: 18,
|
||||||
|
height: 13,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).paddingSymmetrical(16.h, 16.h),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget get hospitalName => Row(
|
||||||
|
children: [
|
||||||
|
Utils.buildSvgWithAssets(
|
||||||
|
icon: (hospitalModel.isHMC == true) ? AppAssets.hmc : AppAssets.hmg,
|
||||||
|
).paddingOnly(right: 10),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
hospitalModel.name ?? "",
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 16,
|
||||||
|
color: AppColors.blackColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Widget get distanceInfo => Row(
|
||||||
|
// children: [
|
||||||
|
// Visibility(
|
||||||
|
// visible: (hospitalModel.distanceInKMs != "0"),
|
||||||
|
// child: AppCustomChipWidget(
|
||||||
|
// labelText: "${hospitalData?.distanceInKMs ?? ""} km".needTranslation,
|
||||||
|
// deleteIcon: AppAssets.location_red,
|
||||||
|
// deleteIconSize: Size(9, 12),
|
||||||
|
// backgroundColor: AppColors.secondaryLightRedColor,
|
||||||
|
// textColor: AppColors.errorColor,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// Visibility(
|
||||||
|
// visible: (hospitalData?.distanceInKMs == "0"),
|
||||||
|
// child: Row(
|
||||||
|
// children: [
|
||||||
|
// AppCustomChipWidget(
|
||||||
|
// labelText: "Distance not available".needTranslation,
|
||||||
|
// textColor: AppColors.blackColor,
|
||||||
|
// ),
|
||||||
|
// SizedBox(
|
||||||
|
// width: 8.h,
|
||||||
|
// )
|
||||||
|
// ],
|
||||||
|
// )),
|
||||||
|
// Visibility(
|
||||||
|
// visible: !isLocationEnabled,
|
||||||
|
// child: AppCustomChipWidget(
|
||||||
|
// labelText: "Location turned off".needTranslation,
|
||||||
|
// deleteIcon: AppAssets.location_unavailable,
|
||||||
|
// deleteIconSize: Size(9, 12),
|
||||||
|
// textColor: AppColors.blackColor,
|
||||||
|
// )),
|
||||||
|
// ],
|
||||||
|
// );
|
||||||
|
}
|
||||||
@ -0,0 +1,96 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart' show tr, StringTranslateExtension;
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/enums.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
|
||||||
|
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
|
||||||
|
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
|
||||||
|
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
|
||||||
|
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
|
||||||
|
import 'package:hmg_patient_app_new/features/my_appointments/appointment_via_region_viewmodel.dart';
|
||||||
|
import 'package:hmg_patient_app_new/features/my_appointments/models/facility_selection.dart';
|
||||||
|
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
|
||||||
|
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
|
||||||
|
import 'package:hmg_patient_app_new/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart';
|
||||||
|
import 'package:hmg_patient_app_new/presentation/appointments/widgets/hospital_bottom_sheet/type_selection_widget.dart';
|
||||||
|
import 'package:hmg_patient_app_new/presentation/habib_wallet/widgets/hospital_list_item.dart';
|
||||||
|
import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart';
|
||||||
|
import 'package:hmg_patient_app_new/theme/colors.dart' show AppColors;
|
||||||
|
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class SelectHospitalBottomSheet extends StatelessWidget {
|
||||||
|
late HabibWalletViewModel habibWalletVM;
|
||||||
|
final TextEditingController searchText = TextEditingController();
|
||||||
|
|
||||||
|
SelectHospitalBottomSheet({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
habibWalletVM = Provider.of<HabibWalletViewModel>(context, listen: false);
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
// Text(
|
||||||
|
// LocaleKeys.selectHospital.tr(),
|
||||||
|
// style: TextStyle(
|
||||||
|
// fontSize: 21,
|
||||||
|
// fontWeight: FontWeight.w600,
|
||||||
|
// color: AppColors.blackColor,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
Text(
|
||||||
|
"Please select the hospital you want to make an advance payment for.".needTranslation,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: AppColors.greyTextColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 16.h),
|
||||||
|
// TextInputWidget(
|
||||||
|
// labelText: LocaleKeys.search.tr(),
|
||||||
|
// hintText: "Search Hospital".tr(),
|
||||||
|
// controller: searchText,
|
||||||
|
// onChange: (value) {
|
||||||
|
// // appointmentsViewModel.filterHospitalListByString(value, regionalViewModel.selectedRegionId , regionalViewModel.selectedFacilityType ==
|
||||||
|
// // FacilitySelection.HMG.name);
|
||||||
|
// },
|
||||||
|
// isEnable: true,
|
||||||
|
// prefix: null,
|
||||||
|
// autoFocus: false,
|
||||||
|
// isBorderAllowed: false,
|
||||||
|
// keyboardType: TextInputType.text,
|
||||||
|
// isAllowLeadingIcon: true,
|
||||||
|
// selectionType: SelectionTypeEnum.search,
|
||||||
|
// padding: EdgeInsets.symmetric(
|
||||||
|
// vertical: ResponsiveExtension(10).h,
|
||||||
|
// horizontal: ResponsiveExtension(15).h,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// SizedBox(height: 24.h),
|
||||||
|
// TypeSelectionWidget(
|
||||||
|
// hmcCount: "0",
|
||||||
|
// hmgCount: "0",
|
||||||
|
// ),
|
||||||
|
// SizedBox(height: 21.h),
|
||||||
|
SizedBox(
|
||||||
|
height: MediaQuery.sizeOf(context).height * .4,
|
||||||
|
child: ListView.separated(
|
||||||
|
itemBuilder: (_, index) {
|
||||||
|
return HospitalListItemAdvancePayment(
|
||||||
|
hospitalModel: habibWalletVM.advancePaymentHospitals[index],
|
||||||
|
isLocationEnabled: false,
|
||||||
|
).onPress(() {
|
||||||
|
habibWalletVM.setSelectedHospital(habibWalletVM.advancePaymentHospitals[index]);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
separatorBuilder: (_, __) => SizedBox(
|
||||||
|
height: 16.h,
|
||||||
|
),
|
||||||
|
itemCount: habibWalletVM.advancePaymentHospitals.length),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,287 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/common_models/data_points.dart';
|
||||||
|
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
|
||||||
|
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||||
|
///
|
||||||
|
/// CustomGraph(dataPoints: sampleData, scrollDirection: Axis.horizontal,height: 200,maxY: 100, maxX:2.5,
|
||||||
|
/// leftLabelFormatter: (value){
|
||||||
|
/// Widget buildLabel(String label) {
|
||||||
|
/// return Padding(
|
||||||
|
/// padding: const EdgeInsets.only(right: 8),
|
||||||
|
/// child: Text(
|
||||||
|
/// label,
|
||||||
|
/// style: TextStyle(
|
||||||
|
/// fontSize: 8.fSize, color: AppColors.textColor,
|
||||||
|
/// fontFamily:
|
||||||
|
/// FontUtils.getFontFamilyForLanguage(false)
|
||||||
|
/// ),
|
||||||
|
/// textAlign: TextAlign.right,
|
||||||
|
/// ),
|
||||||
|
/// );
|
||||||
|
/// }
|
||||||
|
/// switch (value.toInt()) {
|
||||||
|
///
|
||||||
|
/// case 20:
|
||||||
|
/// return buildLabel("Critical Low");
|
||||||
|
/// case 40:
|
||||||
|
/// return buildLabel("Low");
|
||||||
|
/// case 60:
|
||||||
|
/// return buildLabel("Normal");
|
||||||
|
/// case 80:
|
||||||
|
/// return buildLabel("High");
|
||||||
|
/// case 100:
|
||||||
|
/// return buildLabel("Critical High");
|
||||||
|
/// }
|
||||||
|
/// return const SizedBox.shrink();
|
||||||
|
/// },
|
||||||
|
///
|
||||||
|
/// ),
|
||||||
|
class CustomGraph extends StatelessWidget {
|
||||||
|
final List<DataPoint> dataPoints;
|
||||||
|
final double? width;
|
||||||
|
final double height;
|
||||||
|
final double? maxY;
|
||||||
|
final double? maxX;
|
||||||
|
final Color spotColor;
|
||||||
|
final Color graphColor;
|
||||||
|
final Color graphShadowColor;
|
||||||
|
final Color graphGridColor;
|
||||||
|
final Color bottomLabelColor;
|
||||||
|
final double? bottomLabelSize;
|
||||||
|
final FontWeight? bottomLabelFontWeight;
|
||||||
|
|
||||||
|
///creates the left label and provide it to the chart as it will be used by other part of the application so the label will be different for every chart
|
||||||
|
final Widget Function(double value) leftLabelFormatter;
|
||||||
|
|
||||||
|
final Axis scrollDirection;
|
||||||
|
final bool showBottomTitleDates;
|
||||||
|
final bool isFullScreeGraph;
|
||||||
|
|
||||||
|
const CustomGraph({
|
||||||
|
super.key,
|
||||||
|
required this.dataPoints,
|
||||||
|
required this.leftLabelFormatter,
|
||||||
|
this.width,
|
||||||
|
required this.scrollDirection,
|
||||||
|
required this.height,
|
||||||
|
this.maxY,
|
||||||
|
this.maxX,
|
||||||
|
this.showBottomTitleDates = true,
|
||||||
|
this.isFullScreeGraph = false,
|
||||||
|
this.spotColor = AppColors.bgGreenColor,
|
||||||
|
this.graphColor = AppColors.bgGreenColor,
|
||||||
|
this.graphShadowColor = AppColors.graphGridColor,
|
||||||
|
this.graphGridColor = AppColors.graphGridColor,
|
||||||
|
this.bottomLabelColor = AppColors.textColor,
|
||||||
|
this.bottomLabelFontWeight = FontWeight.w500,
|
||||||
|
this.bottomLabelSize,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
// var maxY = 0.0;
|
||||||
|
double interval = 20;
|
||||||
|
if ((maxY ?? 0) > 10 && (maxY ?? 0) <= 20) {
|
||||||
|
interval = 2;
|
||||||
|
} else if ((maxY ?? 0) > 5 && (maxY ?? 0) <= 10) {
|
||||||
|
interval = 1;
|
||||||
|
} else if ((maxY ?? 0) >= 0 && (maxY ?? 0) <= 5) {
|
||||||
|
interval = .4;
|
||||||
|
}
|
||||||
|
return Material(
|
||||||
|
color: Colors.white,
|
||||||
|
child: SizedBox(
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0, bottom: 8),
|
||||||
|
child: LineChart(
|
||||||
|
LineChartData(
|
||||||
|
minY: 0,
|
||||||
|
maxY:
|
||||||
|
((maxY?.ceilToDouble() ?? 0.0) + interval).floorToDouble(),
|
||||||
|
// minX: dataPoints.first.labelValue - 1,
|
||||||
|
maxX: maxX,
|
||||||
|
minX: -0.2,
|
||||||
|
lineTouchData: LineTouchData(
|
||||||
|
getTouchLineEnd: (_, __) => 0,
|
||||||
|
getTouchedSpotIndicator: (barData, indicators) {
|
||||||
|
// Only show custom marker for touched spot
|
||||||
|
return indicators.map((int index) {
|
||||||
|
return TouchedSpotIndicatorData(
|
||||||
|
FlLine(color: Colors.transparent),
|
||||||
|
FlDotData(
|
||||||
|
show: true,
|
||||||
|
getDotPainter: (spot, percent, barData, idx) {
|
||||||
|
return FlDotCirclePainter(
|
||||||
|
radius: 8,
|
||||||
|
color: spotColor,
|
||||||
|
strokeWidth: 2,
|
||||||
|
strokeColor: Colors.white,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
},
|
||||||
|
enabled: true,
|
||||||
|
touchTooltipData: LineTouchTooltipData(
|
||||||
|
getTooltipColor: (_) => Colors.white,
|
||||||
|
getTooltipItems: (touchedSpots) {
|
||||||
|
if (touchedSpots.isEmpty) return [];
|
||||||
|
// Only show tooltip for the first touched spot, hide others
|
||||||
|
return touchedSpots.map((spot) {
|
||||||
|
if (spot == touchedSpots.first) {
|
||||||
|
final dataPoint = dataPoints[spot.x.toInt()];
|
||||||
|
|
||||||
|
return LineTooltipItem(
|
||||||
|
// '${dataPoint.label} ${spot.y.toStringAsFixed(2)}',
|
||||||
|
'${dataPoint.value} ',
|
||||||
|
TextStyle(
|
||||||
|
color: Colors.black,
|
||||||
|
fontSize: 12.fSize,
|
||||||
|
fontWeight: FontWeight.w500),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null; // hides the rest
|
||||||
|
}).toList();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
titlesData: FlTitlesData(
|
||||||
|
leftTitles: AxisTitles(
|
||||||
|
sideTitles: SideTitles(
|
||||||
|
showTitles: true,
|
||||||
|
reservedSize: 77,
|
||||||
|
interval: .1, // Let fl_chart handle it
|
||||||
|
getTitlesWidget: (value, _) {
|
||||||
|
return leftLabelFormatter(value);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
bottomTitles: AxisTitles(
|
||||||
|
axisNameSize: 60,
|
||||||
|
sideTitles: SideTitles(
|
||||||
|
showTitles: showBottomTitleDates,
|
||||||
|
reservedSize: 50,
|
||||||
|
getTitlesWidget: (value, _) {
|
||||||
|
if ((value.toDouble() >= 0) &&
|
||||||
|
(value.toDouble() < (maxX ?? dataPoints.length))) {
|
||||||
|
var label = dataPoints[value.toInt()].label;
|
||||||
|
|
||||||
|
return buildBottomLabel(label);
|
||||||
|
}
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
},
|
||||||
|
interval: 1, // ensures 1:1 mapping with spots
|
||||||
|
),
|
||||||
|
),
|
||||||
|
topTitles: AxisTitles(),
|
||||||
|
rightTitles: AxisTitles(),
|
||||||
|
),
|
||||||
|
borderData: FlBorderData(
|
||||||
|
show: true,
|
||||||
|
border: const Border(
|
||||||
|
bottom: BorderSide.none,
|
||||||
|
left: BorderSide(color: Colors.grey, width: .5),
|
||||||
|
right: BorderSide.none,
|
||||||
|
top: BorderSide.none,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
lineBarsData: _buildColoredLineSegments(dataPoints),
|
||||||
|
gridData: FlGridData(
|
||||||
|
show: true,
|
||||||
|
drawVerticalLine: false,
|
||||||
|
horizontalInterval: 20,
|
||||||
|
checkToShowHorizontalLine: (value) =>
|
||||||
|
value >= 0 && value <= 100,
|
||||||
|
getDrawingHorizontalLine: (value) {
|
||||||
|
return FlLine(
|
||||||
|
color: AppColors.graphGridColor,
|
||||||
|
strokeWidth: 1,
|
||||||
|
dashArray: [5, 5],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<LineChartBarData> _buildColoredLineSegments(List<DataPoint> dataPoints) {
|
||||||
|
final List<FlSpot> allSpots = dataPoints.asMap().entries.map((entry) {
|
||||||
|
return FlSpot(entry.key.toDouble(), entry.value.value);
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
var data = [
|
||||||
|
LineChartBarData(
|
||||||
|
spots: allSpots,
|
||||||
|
isCurved: true,
|
||||||
|
isStrokeCapRound: true,
|
||||||
|
isStrokeJoinRound: true,
|
||||||
|
barWidth: 4,
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [graphColor, graphColor],
|
||||||
|
begin: Alignment.centerLeft,
|
||||||
|
end: Alignment.centerRight,
|
||||||
|
),
|
||||||
|
dotData: FlDotData(
|
||||||
|
show: false,
|
||||||
|
),
|
||||||
|
belowBarData: BarAreaData(
|
||||||
|
show: true,
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [
|
||||||
|
graphShadowColor,
|
||||||
|
Colors.transparent,
|
||||||
|
],
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
end: Alignment.bottomCenter,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Widget buildLabel(String label) {
|
||||||
|
// return Padding(
|
||||||
|
// padding: const EdgeInsets.only(right: 8),
|
||||||
|
// child: Text(
|
||||||
|
// label,
|
||||||
|
// style: TextStyle(
|
||||||
|
// fontSize: leftLabelSize ?? 8.fSize, color: leftLabelColor),
|
||||||
|
// textAlign: TextAlign.right,
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
Widget buildBottomLabel(String label) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Text(
|
||||||
|
label,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: bottomLabelSize ?? 8.fSize, color: bottomLabelColor),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<DataPoint> sampleData = [
|
||||||
|
DataPoint(
|
||||||
|
value: 20,
|
||||||
|
label: 'Jan 2024',
|
||||||
|
),
|
||||||
|
DataPoint(
|
||||||
|
value: 36,
|
||||||
|
label: 'Feb 2024',
|
||||||
|
),
|
||||||
|
DataPoint(
|
||||||
|
value: 80,
|
||||||
|
label: 'This result',
|
||||||
|
),
|
||||||
|
];
|
||||||
Loading…
Reference in New Issue